mirror of
https://github.com/AU-COVIDSafe/mobile-ios.git
synced 2025-04-26 00:15:20 +00:00
COVIDSafe code from version 2.6 (#51)
This commit is contained in:
parent
195798ddd5
commit
4d98b6c5e4
43 changed files with 910 additions and 144 deletions
|
@ -16,10 +16,15 @@ class AuthenticationAPI: CovidSafeAuthenticatedAPI {
|
|||
return
|
||||
}
|
||||
|
||||
guard let authHeaders = try? authenticatedHeaders() else {
|
||||
completion(nil, .RequestError)
|
||||
return
|
||||
}
|
||||
|
||||
CovidNetworking.shared.session.request("\(apiHost)/issueInitialRefreshToken",
|
||||
method: .post,
|
||||
encoding: JSONEncoding.default,
|
||||
headers: authenticatedHeaders
|
||||
headers: authHeaders
|
||||
).validate().responseDecodable(of: ChallengeResponse.self) { (response) in
|
||||
switch response.result {
|
||||
case .success:
|
||||
|
@ -55,7 +60,7 @@ class AuthenticationAPI: CovidSafeAuthenticatedAPI {
|
|||
return
|
||||
}
|
||||
|
||||
let keychain = KeychainSwift()
|
||||
let keychain = KeychainSwift.shared
|
||||
|
||||
guard let token = keychain.get("JWT_TOKEN"),
|
||||
let refreshToken = keychain.get("REFRESH_TOKEN"),
|
||||
|
@ -105,7 +110,7 @@ class AuthenticationAPI: CovidSafeAuthenticatedAPI {
|
|||
}
|
||||
|
||||
static func issueTokensAPI(completion: @escaping (ChallengeResponse?, CovidSafeAPIError?) -> Void) {
|
||||
let keychain = KeychainSwift()
|
||||
let keychain = KeychainSwift.shared
|
||||
|
||||
// block api call only if refresh token exists, if it doesn't it means the app should get it for the first time
|
||||
if UserDefaults.standard.bool(forKey: "ReauthenticationNeededKey") && keychain.get("REFRESH_TOKEN") != nil {
|
||||
|
@ -132,13 +137,20 @@ class AuthenticationAPI: CovidSafeAuthenticatedAPI {
|
|||
completion(response, nil)
|
||||
}
|
||||
} else {
|
||||
let refreshTokenBeforeRefresh = keychain.get("REFRESH_TOKEN")
|
||||
AuthenticationAPI.issueJWTTokenAPI { (response, error) in
|
||||
|
||||
guard let jwt = response?.token,
|
||||
let refresh = response?.refreshToken,
|
||||
error == nil else {
|
||||
|
||||
// set corrupted
|
||||
// if the token in the system before the call is different than the one in keychain, this is a concurrency issue, the token was refresh already and that is why this failed. We should not start re-authentication
|
||||
guard refreshTokenBeforeRefresh == keychain.get("REFRESH_TOKEN") else {
|
||||
completion(response, .TokenAlreadyRefreshedError)
|
||||
return
|
||||
}
|
||||
|
||||
// set corrupted only when it has not been changed
|
||||
UserDefaults.standard.set(true, forKey: "ReauthenticationNeededKey")
|
||||
completion(response, .TokenExpiredError)
|
||||
return
|
||||
|
|
|
@ -20,11 +20,17 @@ class ChangePostcodeAPI: CovidSafeAuthenticatedAPI {
|
|||
let params = [
|
||||
"postcode": newPostcode,
|
||||
]
|
||||
|
||||
guard let authHeaders = try? authenticatedHeaders() else {
|
||||
completion(.RequestError)
|
||||
return
|
||||
}
|
||||
|
||||
CovidNetworking.shared.session.request("\(apiHost)/device",
|
||||
method: .post,
|
||||
parameters: params,
|
||||
encoding: JSONEncoding.default,
|
||||
headers: authenticatedHeaders,
|
||||
headers: authHeaders,
|
||||
interceptor: CovidRequestRetrier(retries:3)).validate().responseDecodable(of: DeviceResponse.self) { (response) in
|
||||
switch response.result {
|
||||
case .success:
|
||||
|
|
|
@ -56,6 +56,8 @@ enum CovidSafeAPIError: Error {
|
|||
case ResponseError
|
||||
case ServerError
|
||||
case TokenExpiredError
|
||||
case TokenAlreadyRefreshedError
|
||||
case MaxRegistrationError
|
||||
case UnknownError
|
||||
}
|
||||
|
||||
|
@ -63,18 +65,16 @@ class CovidSafeAuthenticatedAPI {
|
|||
|
||||
static var isBusy = false
|
||||
|
||||
static var authenticatedHeaders: HTTPHeaders {
|
||||
get {
|
||||
let keychain = KeychainSwift()
|
||||
|
||||
guard let token = keychain.get("JWT_TOKEN") else {
|
||||
return []
|
||||
}
|
||||
let headers: HTTPHeaders = [
|
||||
"Authorization": "Bearer \(token)"
|
||||
]
|
||||
return headers
|
||||
static func authenticatedHeaders() throws -> HTTPHeaders {
|
||||
let keychain = KeychainSwift.shared
|
||||
|
||||
guard let token = keychain.get("JWT_TOKEN") else {
|
||||
throw CovidSafeAPIError.RequestError
|
||||
}
|
||||
let headers: HTTPHeaders = [
|
||||
"Authorization": "Bearer \(token)"
|
||||
]
|
||||
return headers
|
||||
}
|
||||
|
||||
static func processUnauthorizedError(_ data: Data) -> CovidSafeAPIError {
|
||||
|
|
|
@ -20,8 +20,12 @@ final class CovidRequestRetrier: Alamofire.RequestInterceptor {
|
|||
|
||||
func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
|
||||
var urlRequest = urlRequest
|
||||
let keychain = KeychainSwift()
|
||||
let keychain = KeychainSwift.shared
|
||||
let refreshExists = keychain.get("REFRESH_TOKEN") != nil
|
||||
|
||||
// turn off geolock error
|
||||
UserDefaults.standard.setValue(false, forKey: showGeolockErrorKey)
|
||||
|
||||
// prevent authenticated api calls if the re-registration flow has been started
|
||||
if UserDefaults.standard.bool(forKey: "ReauthenticationNeededKey") &&
|
||||
refreshExists {
|
||||
|
@ -81,13 +85,19 @@ final class CovidRequestRetrier: Alamofire.RequestInterceptor {
|
|||
return completion(.retryWithDelay(1.0))
|
||||
}
|
||||
|
||||
if let serverHeader = response.headers.first(where: { $0.name == "Server" }),
|
||||
response.statusCode == 403 && serverHeader.value == "CloudFront" {
|
||||
UserDefaults.standard.setValue(true, forKey: showGeolockErrorKey)
|
||||
return completion(.doNotRetryWithError(error))
|
||||
}
|
||||
|
||||
if !triedRefresh &&
|
||||
(response.statusCode == 403 || response.statusCode == 401) {
|
||||
(response.statusCode == 401 || response.statusCode == 403) {
|
||||
triedRefresh = true
|
||||
retriesExecuted += 1
|
||||
AuthenticationAPI.issueTokensAPI { (response, authError) in
|
||||
// this will update the tokens automatically
|
||||
guard let respError = authError, respError == .TokenExpiredError else {
|
||||
if let respError = authError, respError == .TokenExpiredError {
|
||||
completion(.doNotRetryWithError(error))
|
||||
return
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ class GetTempIdAPI: CovidSafeAuthenticatedAPI {
|
|||
"version" : apiVersion
|
||||
]
|
||||
|
||||
guard authenticatedHeaders.count > 0 else {
|
||||
guard let authHeaders = try? authenticatedHeaders(), authHeaders.count > 0 else {
|
||||
completion(nil, nil, nil, .TokenExpiredError)
|
||||
return
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ class GetTempIdAPI: CovidSafeAuthenticatedAPI {
|
|||
CovidNetworking.shared.session.request("\(apiHost)/getTempId",
|
||||
method: .get,
|
||||
parameters: params,
|
||||
headers: authenticatedHeaders,
|
||||
headers: authHeaders,
|
||||
interceptor: CovidRequestRetrier(retries: 3)).validate().responseDecodable(of: TempIdResponse.self) { (response) in
|
||||
switch response.result {
|
||||
case .success:
|
||||
|
|
|
@ -65,7 +65,7 @@ class MessageAPI: CovidSafeAuthenticatedAPI {
|
|||
var shouldGetMessages = true
|
||||
|
||||
let calendar = NSCalendar.current
|
||||
let currentDate = calendar.startOfDay(for: Date())
|
||||
let currentDate = Date()
|
||||
|
||||
// if the current version is newer than the last version checked, allow messages call
|
||||
if let currVersionStr = Bundle.main.version, let currVersion = Int(currVersionStr), currVersion > versionChecked {
|
||||
|
@ -77,7 +77,7 @@ class MessageAPI: CovidSafeAuthenticatedAPI {
|
|||
let components = calendar.dateComponents([.hour], from: lastCheckedDate, to: currentDate)
|
||||
|
||||
if let numHours = components.hour {
|
||||
shouldGetMessages = numHours > 4
|
||||
shouldGetMessages = numHours >= 4
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -109,10 +109,15 @@ class MessageAPI: CovidSafeAuthenticatedAPI {
|
|||
|
||||
isBusy = true
|
||||
|
||||
guard let authHeaders = try? authenticatedHeaders() else {
|
||||
completion(nil, .RequestError)
|
||||
return
|
||||
}
|
||||
|
||||
CovidNetworking.shared.session.request("\(apiHost)/messages",
|
||||
method: .get,
|
||||
parameters: params,
|
||||
headers: authenticatedHeaders,
|
||||
headers: authHeaders,
|
||||
interceptor: CovidRequestRetrier(retries: 3)
|
||||
).validate().responseDecodable(of: MessageResponse.self) { (response) in
|
||||
switch response.result {
|
||||
|
@ -120,7 +125,7 @@ class MessageAPI: CovidSafeAuthenticatedAPI {
|
|||
guard let messageResponse = response.value else { return }
|
||||
|
||||
// save successful timestamp
|
||||
let minutesToDefer = Int.random(in: 0..<10)
|
||||
let minutesToDefer = Int.random(in: 0..<30)
|
||||
let calendar = NSCalendar.current
|
||||
let currentDate = Date()
|
||||
if let deferredDate = calendar.date(byAdding: .minute, value: minutesToDefer, to: currentDate) {
|
||||
|
|
|
@ -11,7 +11,7 @@ import Alamofire
|
|||
class PhoneValidationAPI {
|
||||
|
||||
static func verifyPhoneNumber(regInfo: RegistrationRequest,
|
||||
completion: @escaping (String?, Swift.Error?) -> Void) {
|
||||
completion: @escaping (String?, CovidSafeAPIError?) -> Void) {
|
||||
|
||||
guard let apiHost = PlistHelper.getvalueFromInfoPlist(withKey: "API_Host", plistName: "CovidSafe-config") else {
|
||||
return
|
||||
|
@ -33,8 +33,22 @@ class PhoneValidationAPI {
|
|||
case .success:
|
||||
guard let authResponse = response.value else { return }
|
||||
completion(authResponse.session, nil)
|
||||
case let .failure(error):
|
||||
completion(nil, error)
|
||||
case .failure(_):
|
||||
var apiError = CovidSafeAPIError.RequestError
|
||||
|
||||
if let respData = response.data {
|
||||
do {
|
||||
let errorResponse = try JSONDecoder().decode(CovidSafeErrorResponse.self, from: respData)
|
||||
if errorResponse.message == "MaxRegistrationsReached" {
|
||||
apiError = .MaxRegistrationError
|
||||
}
|
||||
} catch {
|
||||
// unable to parse response
|
||||
apiError = .ResponseError
|
||||
}
|
||||
}
|
||||
completion(nil, apiError)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,10 +24,15 @@ class RestrictionsAPI: CovidSafeAuthenticatedAPI {
|
|||
|
||||
let params = ["state": "\(forState.rawValue.lowercased())"]
|
||||
|
||||
guard let authHeaders = try? authenticatedHeaders() else {
|
||||
completion(nil, .RequestError)
|
||||
return
|
||||
}
|
||||
|
||||
CovidNetworking.shared.session.request("\(apiHost)/restrictions",
|
||||
method: .get,
|
||||
parameters: params,
|
||||
headers: authenticatedHeaders,
|
||||
headers: authHeaders,
|
||||
interceptor: CovidRequestRetrier(retries: 3)
|
||||
).validate().responseDecodable(of: StateRestriction.self) { (response) in
|
||||
switch response.result {
|
||||
|
|
|
@ -20,10 +20,15 @@ class StatisticsAPI: CovidSafeAuthenticatedAPI {
|
|||
|
||||
let parameters = ["state" : "\(forState.rawValue)"]
|
||||
|
||||
guard let authHeaders = try? authenticatedHeaders() else {
|
||||
completion(nil, .RequestError)
|
||||
return
|
||||
}
|
||||
|
||||
CovidNetworking.shared.session.request("\(apiHost)/v2/statistics",
|
||||
method: .get,
|
||||
parameters: parameters,
|
||||
headers: authenticatedHeaders,
|
||||
headers: authHeaders,
|
||||
interceptor: CovidRequestRetrier(retries: 3)
|
||||
).validate().responseDecodable(of: StatisticsResponse.self) { (response) in
|
||||
switch response.result {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue