-
Notifications
You must be signed in to change notification settings - Fork 305
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This code has been reviewed in other branches.
- Loading branch information
Showing
50 changed files
with
2,695 additions
and
305 deletions.
There are no files selected for viewing
242 changes: 223 additions & 19 deletions
242
Tests/TestingApps/PaywallsTester/PaywallsTester.xcodeproj/project.pbxproj
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
23 changes: 23 additions & 0 deletions
23
Tests/TestingApps/PaywallsTester/PaywallsTester/Assets.xcassets/logo.imageset/Contents.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
{ | ||
"images" : [ | ||
{ | ||
"filename" : "logo46 1.png", | ||
"idiom" : "universal", | ||
"scale" : "1x" | ||
}, | ||
{ | ||
"filename" : "logo46.png", | ||
"idiom" : "universal", | ||
"scale" : "2x" | ||
}, | ||
{ | ||
"filename" : "logo69.png", | ||
"idiom" : "universal", | ||
"scale" : "3x" | ||
} | ||
], | ||
"info" : { | ||
"author" : "xcode", | ||
"version" : 1 | ||
} | ||
} |
Binary file added
BIN
+3.25 KB
...ngApps/PaywallsTester/PaywallsTester/Assets.xcassets/logo.imageset/logo46 1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+3.25 KB
...tingApps/PaywallsTester/PaywallsTester/Assets.xcassets/logo.imageset/logo46.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+4.78 KB
...tingApps/PaywallsTester/PaywallsTester/Assets.xcassets/logo.imageset/logo69.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
59 changes: 59 additions & 0 deletions
59
Tests/TestingApps/PaywallsTester/PaywallsTester/Data/ApplicationData.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
// | ||
// ApplicationData.swift | ||
// | ||
// | ||
// Created by Nacho Soto on 12/11/23. | ||
// | ||
|
||
import Foundation | ||
|
||
import OSLog | ||
|
||
@Observable | ||
final class ApplicationData { | ||
|
||
private(set) var authenticationStatus: AuthenticationStatus = .unknown { | ||
didSet { | ||
Self.logger.info("Changed authentication: \(String(describing: self.authenticationStatus))") | ||
} | ||
} | ||
|
||
@MainActor | ||
func loadApplicationData() async throws { | ||
do { | ||
self.authenticationStatus = .signedIn(try await self.manager.loadApplicationData()) | ||
} catch ApplicationManager.Error.unauthenticated { | ||
Self.logger.warning("Received unauthentication error when loading application data") | ||
self.authenticationStatus = .signedOut | ||
} | ||
} | ||
|
||
func signOut() { | ||
self.manager.signOut() | ||
self.authenticationStatus = .signedOut | ||
} | ||
|
||
var isSignedIn: Bool { | ||
if case .signedIn = self.authenticationStatus { | ||
return true | ||
} | ||
return false | ||
} | ||
|
||
@ObservationIgnored | ||
private var manager: ApplicationManagerType = ApplicationManager() | ||
private static let logger = Logging.shared.logger(category: "ApplicationData") | ||
|
||
} | ||
|
||
extension ApplicationData { | ||
|
||
enum AuthenticationStatus: Equatable { | ||
|
||
case signedIn(DeveloperResponse) | ||
case signedOut | ||
case unknown | ||
|
||
} | ||
|
||
} |
59 changes: 59 additions & 0 deletions
59
Tests/TestingApps/PaywallsTester/PaywallsTester/Data/ApplicationManager.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
// | ||
// ApplicationManager.swift | ||
// | ||
// | ||
// Created by Nacho Soto on 12/11/23. | ||
// | ||
|
||
import Foundation | ||
|
||
|
||
public protocol ApplicationManagerType { | ||
|
||
func loadApplicationData() async throws -> DeveloperResponse | ||
func signOut() | ||
|
||
} | ||
|
||
public final class ApplicationManager: ApplicationManagerType { | ||
|
||
private var client = HTTPClient.shared | ||
|
||
public init() {} | ||
|
||
/// - Throws: ``ApplicationManager/Error`` | ||
public func loadApplicationData() async throws -> DeveloperResponse { | ||
do { | ||
return try await self.client.perform( | ||
.init(method: .get, endpoint: .me) | ||
) | ||
} catch HTTPClient.Error.errorResponse(.unauthorized, _, _, _), | ||
HTTPClient.Error.errorResponse(.forbidden, _, _, _){ | ||
throw Error.unauthenticated | ||
} catch let error as HTTPClient.Error { | ||
throw Error.requestError(error) | ||
} catch URLError.cancelled, is CancellationError { | ||
throw Error.operationCancelled | ||
} catch { | ||
throw Error.unknown(error) | ||
} | ||
} | ||
|
||
public func signOut() { | ||
self.client.removeCookies() | ||
} | ||
|
||
} | ||
|
||
// MARK: - Errors | ||
|
||
public extension ApplicationManager { | ||
|
||
enum Error: Swift.Error { | ||
case unauthenticated | ||
case requestError(HTTPClient.Error) | ||
case operationCancelled | ||
case unknown(Swift.Error) | ||
} | ||
|
||
} |
92 changes: 92 additions & 0 deletions
92
Tests/TestingApps/PaywallsTester/PaywallsTester/Data/AuthenticationActor.swift
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
// | ||
// AuthenticationActor.swift | ||
// | ||
// | ||
// Created by Nacho Soto on 12/11/23. | ||
// | ||
|
||
import Foundation | ||
|
||
public protocol AuthenticationActorType { | ||
|
||
func logIn(user: String, password: String, code: String?) async throws | ||
|
||
} | ||
|
||
public actor AuthenticationActor: AuthenticationActorType { | ||
|
||
private var client: HTTPClient = HTTPClient.shared | ||
|
||
public init() {} | ||
|
||
/// - Returns: authentication code | ||
/// - Throws: ``AuthenticationActor/Error`` | ||
public func logIn(user: String, password: String, code: String?) async throws { | ||
do { | ||
let _: LoginResponse = try await self.client.perform( | ||
.init( | ||
method: .post, | ||
endpoint: .login( | ||
user: user, | ||
password: password, | ||
code: code?.notEmptyOrWhitespaces | ||
) | ||
) | ||
) | ||
} catch HTTPClient.Error.errorResponse(_, .optCodeRequired, _, _) { | ||
throw Error.codeRequired | ||
} catch HTTPClient.Error.errorResponse(.unauthorized, _, _, _), | ||
HTTPClient.Error.errorResponse(.forbidden, _, _, _) { | ||
throw Error.invalidCredentials | ||
} catch let error as HTTPClient.Error { | ||
throw Error.requestError(error) | ||
} catch { | ||
throw Error.unknown(error) | ||
} | ||
} | ||
|
||
} | ||
|
||
// MARK: - Errors | ||
|
||
public extension AuthenticationActor { | ||
|
||
enum Error: Swift.Error { | ||
case codeRequired | ||
case invalidCredentials | ||
case requestError(HTTPClient.Error) | ||
case unknown(Swift.Error) | ||
} | ||
|
||
} | ||
|
||
extension AuthenticationActor.Error: LocalizedError { | ||
|
||
public var errorDescription: String? { | ||
switch self { | ||
case .codeRequired: | ||
return "Code required" | ||
case .invalidCredentials: | ||
return "Error" | ||
case .requestError, .unknown: | ||
return nil | ||
} | ||
} | ||
|
||
public var failureReason: String? { | ||
switch self { | ||
case .codeRequired: | ||
return "This account required 2FA" | ||
|
||
case .invalidCredentials: | ||
return "Invalid credentials" | ||
|
||
case let .requestError(error): | ||
return error.failureReason | ||
|
||
case let .unknown(error): | ||
return "Unknown error: \(error.localizedDescription)" | ||
} | ||
} | ||
|
||
} |
Oops, something went wrong.