Skip to content
This repository was archived by the owner on Jun 20, 2023. It is now read-only.

Fix/14396: Extending error codes #4928

Merged
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,34 @@ extension Locator {
// type: default
// comment: the endpoint for otp authorization for SRS
static func authorizeOtpSrs(
isFake: Bool
forceApiTokenHeader: Bool = false,
isFake: Bool
) -> Locator {
let fake = String(isFake ? 1 : 0)
return Locator(
endpoint: .dataDonation,
paths: ["version", "v1", "ios", "srs"],
method: .post,
defaultHeaders: [
"Content-Type": "application/x-protobuf",
"cwa-fake": fake
]
)
let forceApiHeader = String(forceApiTokenHeader ? 1 : 0)

#if !RELEASE
return Locator(
endpoint: .dataDonation,
paths: ["version", "v1", "ios", "srs"],
method: .post,
defaultHeaders: [
"Content-Type": "application/x-protobuf",
"cwa-fake": fake,
"cwa-ppac-ios-accept-api-token": forceApiHeader
]
)
#else
return Locator(
endpoint: .dataDonation,
paths: ["version", "v1", "ios", "srs"],
method: .post,
defaultHeaders: [
"Content-Type": "application/x-protobuf",
"cwa-fake": fake,
"cwa-ppac-ios-accept-api-token": forceApiHeader
]
)
#endif
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ enum OTPAuthorizationError: LocalizedError, Equatable {
case apiTokenAlreadyIssued
case apiTokenExpired
case apiTokenQuotaExceeded
case deviceBlocked
case deviceTokenInvalid
case deviceTokenRedeemed
case deviceTokenSyntaxError
Expand Down Expand Up @@ -41,6 +42,8 @@ enum OTPAuthorizationError: LocalizedError, Equatable {
return "apiTokenExpired"
case .apiTokenQuotaExceeded:
return "apiTokenQuotaExceeded"
case .deviceBlocked:
return "deviceBlocked"
case .deviceTokenInvalid:
return "deviceTokenInvalid"
case .deviceTokenRedeemed:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ struct OTPAuthorizationForSRSResource: Resource {
init(
otpSRS: String,
requestPadding: Data? = nil,
forceApiTokenHeader: Bool = false,
isFake: Bool = false,
ppacToken: PPACToken,
trustEvaluation: TrustEvaluating = DefaultTrustEvaluation(
Expand All @@ -37,7 +38,7 @@ struct OTPAuthorizationForSRSResource: Resource {
}
)

self.locator = .authorizeOtpSrs(isFake: isFake)
self.locator = .authorizeOtpSrs(forceApiTokenHeader: forceApiTokenHeader, isFake: isFake)
self.type = .default
self.receiveResource = JSONReceiveResource<OTPForSRSResponsePropertiesReceiveModel>()
self.trustEvaluation = trustEvaluation
Expand Down Expand Up @@ -65,7 +66,7 @@ struct OTPAuthorizationForSRSResource: Resource {
return .noNetworkConnection
case .unexpectedServerError(let statusCode):
switch statusCode {
case 400, 401, 403:
case 400, 401, 403, 429:
return otpAuthorizationFailureHandler(for: responseBody, statusCode: statusCode)
case 500:
Log.error("Failed to get authorized OTP - 500 status code", log: .api)
Expand All @@ -81,6 +82,7 @@ struct OTPAuthorizationForSRSResource: Resource {

// MARK: - Private

// swiftlint:disable:next cyclomatic_complexity
private func otpAuthorizationFailureHandler(for response: Data?, statusCode: Int) -> OTPAuthorizationError? {
guard let responseBody = response else {
Log.error("Failed to get authorized OTP - no 200 status code: \(statusCode)", log: .api)
Expand All @@ -106,6 +108,8 @@ struct OTPAuthorizationForSRSResource: Resource {
return .apiTokenExpired
case .API_TOKEN_QUOTA_EXCEEDED:
return .apiTokenQuotaExceeded
case .DEVICE_BLOCKED:
return .deviceBlocked
case .DEVICE_TOKEN_INVALID:
return .deviceTokenInvalid
case .DEVICE_TOKEN_REDEEMED:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ enum SurveyError: Error {

init(otpError: OTPError) {
switch otpError {
case .generalError, .invalidResponseError, .internalServerError, .otherServerError, .apiTokenExpired, .deviceTokenInvalid, .deviceTokenRedeemed, .deviceTokenSyntaxError, .noNetworkConnection, .restServiceError:
case .generalError, .invalidResponseError, .internalServerError, .otherServerError, .apiTokenExpired, .deviceBlocked, .deviceTokenInvalid, .deviceTokenRedeemed, .deviceTokenSyntaxError, .noNetworkConnection, .restServiceError:
self = .tryAgainLater(otpError.description)
case .apiTokenAlreadyIssued, .otpAlreadyUsedThisMonth:
self = .tryAgainNextMonth(otpError.description)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ class ExposureSubmissionCoordinatorModel {
}

case .failure(let srsError):
onError(.srsError(srsError))
self.handleSRSError(srsError, onError: onError)
Log.debug(srsError.description, log: .ppac)
}
}
Expand Down Expand Up @@ -489,4 +489,40 @@ class ExposureSubmissionCoordinatorModel {
// MARK: - Private

private let store: Store

private func handleSRSError(_ srsError: SRSError, onError: @escaping (ExposureSubmissionServiceError) -> Void) {
switch srsError {
case .otpError(let otpError):
switch otpError {
case .restServiceError(let serverError):
switch serverError {
case .receivedResourceError(let otpAuthorizationError):
switch otpAuthorizationError {
case .apiTokenAlreadyIssued:
onError(.srsError(.otpError(.apiTokenAlreadyIssued)))
case .apiTokenExpired:
onError(.srsError(.otpError(.apiTokenExpired)))
case .apiTokenQuotaExceeded:
onError(.srsError(.otpError(.apiTokenQuotaExceeded)))
case .deviceBlocked:
onError(.srsError(.otpError(.deviceBlocked)))
case .deviceTokenInvalid:
onError(.srsError(.otpError(.deviceTokenInvalid)))
case .deviceTokenRedeemed:
onError(.srsError(.otpError(.deviceTokenRedeemed)))
case .deviceTokenSyntaxError:
onError(.srsError(.otpError(.deviceTokenSyntaxError)))
default:
onError(.srsError(.otpError(otpError)))
}
default:
onError(.srsError(.otpError(otpError)))
}
default:
onError(.srsError(.otpError(otpError)))
}
default:
onError(.srsError(srsError))
}
}
}
67 changes: 35 additions & 32 deletions src/xcode/ENA/ENA/Source/Services/OTP/Model/OTPError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ enum OTPError: Error, Equatable, LocalizedError {
case apiTokenAlreadyIssued
case apiTokenExpired
case apiTokenQuotaExceeded
case deviceBlocked
case deviceTokenInvalid
case deviceTokenRedeemed
case deviceTokenSyntaxError
Expand All @@ -21,38 +22,40 @@ enum OTPError: Error, Equatable, LocalizedError {
case restServiceError(ServiceError<OTPAuthorizationError>)

var description: String {
switch self {
case .generalError(let error):
if let e = error?.localizedDescription {
return "generalError with underlying: \(e)"
} else {
return "generalError"
}
case .invalidResponseError:
return "invalidResponseError"
case .internalServerError:
return "internalServerError"
case .otpAlreadyUsedThisMonth:
return "otpAlreadyUsedThisMonth"
case .otherServerError:
return "otherServerError"
case .apiTokenAlreadyIssued:
return "apiTokenAlreadyIssued"
case .apiTokenExpired:
return "apiTokenExpired"
case .apiTokenQuotaExceeded:
return "apiTokenQuotaExceeded"
case .deviceTokenInvalid:
return "deviceTokenInvalid"
case .deviceTokenRedeemed:
return "deviceTokenRedeemed"
case .deviceTokenSyntaxError:
return "deviceTokenSyntaxError"
case .noNetworkConnection:
return "noNetworkConnection"
case .restServiceError:
return "restServiceError"
}
switch self {
case .generalError(let error):
if let e = error?.localizedDescription {
return "generalError with underlying: \(e)"
} else {
return "generalError"
}
case .invalidResponseError:
return "invalidResponseError"
case .internalServerError:
return "internalServerError"
case .otpAlreadyUsedThisMonth:
return "otpAlreadyUsedThisMonth"
case .otherServerError:
return "otherServerError"
case .apiTokenAlreadyIssued:
return "apiTokenAlreadyIssued"
case .apiTokenExpired:
return "apiTokenExpired"
case .apiTokenQuotaExceeded:
return "apiTokenQuotaExceeded"
case .deviceBlocked:
return "deviceBlocked"
case .deviceTokenInvalid:
return "deviceTokenInvalid"
case .deviceTokenRedeemed:
return "deviceTokenRedeemed"
case .deviceTokenSyntaxError:
return "deviceTokenSyntaxError"
case .noNetworkConnection:
return "noNetworkConnection"
case .restServiceError:
return "restServiceError"
}
}

var errorDescription: String? {
Expand Down
3 changes: 2 additions & 1 deletion src/xcode/ENA/ENA/Source/Services/OTP/OTPService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,8 @@ final class OTPService: OTPServiceProviding {
private func authorizeSRS(_ otp: String, with ppacToken: PPACToken, completion: @escaping (Result<String, OTPError>) -> Void) {
Log.info("Authorization of a new OTP SRS started.", log: .otp)
// We authorize the otp with the ppac Token at our server.
let resource = OTPAuthorizationForSRSResource(otpSRS: otp, ppacToken: ppacToken)

let resource = OTPAuthorizationForSRSResource(otpSRS: otp, forceApiTokenHeader: store.forceAPITokenAuthorization, ppacToken: ppacToken)
restServiceProvider.load(resource) { [weak self] result in
guard let self = self else {
Log.error("could not create strong self", log: .otp)
Expand Down