diff options
| author | Andrej Mihajlov <and@mullvad.net> | 2021-05-21 16:46:49 +0200 |
|---|---|---|
| committer | Andrej Mihajlov <and@mullvad.net> | 2021-05-21 16:46:49 +0200 |
| commit | d46c782a2c798eb4aaf3a188b6aea916f28e79a8 (patch) | |
| tree | e319c00d1baa1cc28f8bf220e99e121fc2c231fd | |
| parent | 17a399fb9e271c9adaac4323749361bcbe39bc84 (diff) | |
| parent | 7cd07fb1292210bde0cecf39dd7ccb08defe3050 (diff) | |
| download | mullvadvpn-d46c782a2c798eb4aaf3a188b6aea916f28e79a8.tar.xz mullvadvpn-d46c782a2c798eb4aaf3a188b6aea916f28e79a8.zip | |
Merge branch 'fix-rest-create-apple-payment'
| -rw-r--r-- | ios/MullvadVPN/AccountViewController.swift | 12 | ||||
| -rw-r--r-- | ios/MullvadVPN/AppStorePaymentManager.swift | 7 | ||||
| -rw-r--r-- | ios/MullvadVPN/MullvadRest.swift | 91 |
3 files changed, 80 insertions, 30 deletions
diff --git a/ios/MullvadVPN/AccountViewController.swift b/ios/MullvadVPN/AccountViewController.swift index a441e6f0d1..398d304f0a 100644 --- a/ios/MullvadVPN/AccountViewController.swift +++ b/ios/MullvadVPN/AccountViewController.swift @@ -395,13 +395,17 @@ private extension CreateApplePaymentResponse { formattedTimeAdded ?? "" ) case .restoration: - return timeAdded == 0 - ? NSLocalizedString( + switch self { + case .noTimeAdded: + return NSLocalizedString( "Your previous purchases have already been added to this account.", comment: "") - : String( + case .timeAdded: + return String( format: NSLocalizedString("%@ have been added to your account", comment: ""), - formattedTimeAdded ?? "") + self.formattedTimeAdded ?? "" + ) + } } } } diff --git a/ios/MullvadVPN/AppStorePaymentManager.swift b/ios/MullvadVPN/AppStorePaymentManager.swift index 117de36bc0..4fa043b9c5 100644 --- a/ios/MullvadVPN/AppStorePaymentManager.swift +++ b/ios/MullvadVPN/AppStorePaymentManager.swift @@ -257,11 +257,13 @@ class AppStorePaymentManager: NSObject, SKPaymentTransactionObserver { createApplePaymentOperation.addDidFinishBlockObserver { (operation, result) in switch result { case .success(let response): - self.logger.info("AppStore Receipt was processed. Time added: \(response.timeAdded), New expiry: \(response.newExpiry)") + self.logger.info("AppStore receipt was processed. Time added: \(response.timeAdded), New expiry: \(response.newExpiry)") completionHandler(.success(response)) case .failure(let error): + self.logger.error(chainedError: error, message: "Failed to upload the AppStore receipt") + completionHandler(.failure(.sendReceipt(error))) } } @@ -270,6 +272,7 @@ class AppStorePaymentManager: NSObject, SKPaymentTransactionObserver { case .failure(let error): self.logger.error(chainedError: error, message: "Failed to fetch the AppStore receipt") + completionHandler(.failure(.readReceipt(error))) } } @@ -354,8 +357,6 @@ class AppStorePaymentManager: NSObject, SKPaymentTransactionObserver { } case .failure(let error): - self.logger.error(chainedError: error, message: "Failed to upload the AppStore receipt") - self.observerList.forEach { (observer) in observer.appStorePaymentManager( self, diff --git a/ios/MullvadVPN/MullvadRest.swift b/ios/MullvadVPN/MullvadRest.swift index 4d6b6da45d..5d03a668ea 100644 --- a/ios/MullvadVPN/MullvadRest.swift +++ b/ios/MullvadVPN/MullvadRest.swift @@ -217,6 +217,10 @@ struct AnyResponseHandler<Response>: ResponseHandler { } } + init(block: @escaping (HTTPURLResponse, Data) -> Result<Response, ResponseHandlerError>) { + self.decodeResponseBlock = block + } + func decodeResponse(_ httpResponse: HTTPURLResponse, data: Data) -> Result<Response, ResponseHandlerError> { return self.decodeResponseBlock(httpResponse, data) } @@ -233,10 +237,7 @@ struct DecodingResponseHandler<Response: Decodable>: ResponseHandler { func decodeResponse(_ httpResponse: HTTPURLResponse, data: Data) -> Result<Response, ResponseHandlerError> { if httpResponse.statusCode == expectedStatus { - return Result { try MullvadRest.makeJSONDecoder().decode(Response.self, from: data) } - .mapError { (error) -> ResponseHandlerError in - return .decodeData(error) - } + return MullvadRest.decodeSuccessResponse(Response.self, from: data) } else { return .failure(.badResponse(httpResponse.statusCode)) } @@ -274,10 +275,8 @@ struct HttpCacheDecodingResponseHandler<WrappedType: Decodable>: ResponseHandler func decodeResponse(_ httpResponse: HTTPURLResponse, data: Data) -> Result<Response, ResponseHandlerError> { switch httpResponse.statusCode { case HttpStatus.ok: - return Result { try MullvadRest.makeJSONDecoder().decode(WrappedType.self, from: data) } - .mapError { (error) -> ResponseHandlerError in - return .decodeData(error) - }.map { (relays) -> Response in + return MullvadRest.decodeSuccessResponse(WrappedType.self, from: data) + .map { (relays) -> Response in let etag = httpResponse.value(forCaseInsensitiveHTTPHeaderField: HttpHeader.etag) return .newContent(etag, relays) @@ -370,7 +369,7 @@ struct RestEndpoint<Input, Response> where Input: RestPayload { switch error { case .badResponse: // Try decoding the server error response in case when unexpected response is returned - return Self.decodeErrorResponse(httpResponse: httpResponse, data: data) + return MullvadRest.decodeErrorResponse(httpResponse: httpResponse, data: data) .flatMap { (serverErrorResponse) -> Result<Response, RestError> in return .failure(.server(serverErrorResponse)) } @@ -380,15 +379,6 @@ struct RestEndpoint<Input, Response> where Input: RestPayload { } } } - - /// A private helper that parses the JSON response in case of error (Any HTTP code except 2xx) - private static func decodeErrorResponse(httpResponse: HTTPURLResponse, data: Data) -> Result<ServerErrorResponse, RestError> { - return Result { () -> ServerErrorResponse in - return try MullvadRest.makeJSONDecoder().decode(ServerErrorResponse.self, from: data) - }.mapError({ (error) -> RestError in - return .decodeErrorResponse(error) - }) - } } /// A convenience class for `RestEndpoint` that transparently provides it with the `URLSession` @@ -557,7 +547,24 @@ extension MullvadRest { endpointURL: kRestBaseURL.appendingPathComponent("create-apple-payment"), httpMethod: .post, responseHandlerFactory: { (input) in - return DecodingResponseHandler(expectedStatus: HttpStatus.created) + return AnyResponseHandler { (httpResponse, data) -> Result<CreateApplePaymentResponse, ResponseHandlerError> in + switch httpResponse.statusCode { + case HttpStatus.ok: + return MullvadRest.decodeSuccessResponse(CreateApplePaymentRawResponse.self, from: data) + .map { (response) in + return .noTimeAdded(response.newExpiry) + } + + case HttpStatus.created: + return MullvadRest.decodeSuccessResponse(CreateApplePaymentRawResponse.self, from: data) + .map { (response) in + return .timeAdded(response.timeAdded, response.newExpiry) + } + + default: + return .failure(.badResponse(httpResponse.statusCode)) + } + } } ) } @@ -589,6 +596,23 @@ extension MullvadRest { decoder.dataDecodingStrategy = .base64 return decoder } + + /// A private helper that parses the JSON response into the given `Decodable` type. + fileprivate static func decodeSuccessResponse<T: Decodable>(_ type: T.Type, from data: Data) -> Result<T, ResponseHandlerError> { + return Result { try MullvadRest.makeJSONDecoder().decode(type, from: data) } + .mapError { (error) -> ResponseHandlerError in + return .decodeData(error) + } + } + + /// A private helper that parses the JSON response in case of error (Any HTTP code except 2xx) + fileprivate static func decodeErrorResponse(httpResponse: HTTPURLResponse, data: Data) -> Result<ServerErrorResponse, RestError> { + return Result { () -> ServerErrorResponse in + return try MullvadRest.makeJSONDecoder().decode(ServerErrorResponse.self, from: data) + }.mapError({ (error) -> RestError in + return .decodeErrorResponse(error) + }) + } } @@ -740,9 +764,25 @@ struct CreateApplePaymentRequest: Encodable, RestPayload { let receiptString: Data } -struct CreateApplePaymentResponse: Decodable { - let timeAdded: Int - let newExpiry: Date +enum CreateApplePaymentResponse { + case noTimeAdded(_ expiry: Date) + case timeAdded(_ timeAdded: Int, _ newExpiry: Date) + + var newExpiry: Date { + switch self { + case .noTimeAdded(let expiry), .timeAdded(_, let expiry): + return expiry + } + } + + var timeAdded: TimeInterval { + switch self { + case .noTimeAdded: + return 0 + case .timeAdded(let timeAdded, _): + return TimeInterval(timeAdded) + } + } /// Returns a formatted string for the `timeAdded` interval, i.e "30 days" var formattedTimeAdded: String? { @@ -750,10 +790,15 @@ struct CreateApplePaymentResponse: Decodable { formatter.allowedUnits = [.day, .hour] formatter.unitsStyle = .full - return formatter.string(from: TimeInterval(timeAdded)) + return formatter.string(from: self.timeAdded) } } +fileprivate struct CreateApplePaymentRawResponse: Decodable { + let timeAdded: Int + let newExpiry: Date +} + struct ProblemReportRequest: Encodable, RestPayload { let address: String let message: String |
