Skip to content

Commit

Permalink
Convert AuthenticationData to be a protocol
Browse files Browse the repository at this point in the history
  • Loading branch information
mohannad-hassan committed Jan 5, 2025
1 parent 8049a8b commit 3cdc724
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 27 deletions.
28 changes: 9 additions & 19 deletions Data/AuthenticationClient/Sources/AuthenticationData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,36 +22,26 @@ enum AuthenticationStateError: Error {
///
/// The abstraction is mainly for testing purposes. The API has been designed to be in conjunction
/// with the `AppAuth's OIDAuthState` class.
class AuthenticationData: NSObject, Codable {
protocol AuthenticationData: Codable {
/// Invokes subscribers when the state changes. Usually happens during refreshing tokens.
var stateChangedPublisher: AnyPublisher<Void, Never> { fatalError() }
var stateChangedPublisher: AnyPublisher<Void, Never> { get }

var isAuthorized: Bool {
fatalError()
}
var isAuthorized: Bool { get }

/// Returns fresh access token to be used for API requests.
///
/// - throws: `AuthenticationStateError.failedToRefreshTokens` if the
/// refresh operation fails for any reason.
func getFreshTokens() async throws -> String {
fatalError()
}

override init() { }

required init(from decoder: any Decoder) throws {
fatalError()
}
func getFreshTokens() async throws -> String
}

class AppAuthAuthenticationData: AuthenticationData {
final class AppAuthAuthenticationData: NSObject, AuthenticationData {
private enum CodingKeys: String, CodingKey {
case state
}

private let stateChangedSubject: PassthroughSubject<Void, Never> = .init()
override var stateChangedPublisher: AnyPublisher<Void, Never> {
var stateChangedPublisher: AnyPublisher<Void, Never> {
stateChangedSubject.eraseToAnyPublisher()
}

Expand All @@ -61,7 +51,7 @@ class AppAuthAuthenticationData: AuthenticationData {
}
}

override var isAuthorized: Bool {
var isAuthorized: Bool {
state.isAuthorized
}

Expand All @@ -88,13 +78,13 @@ class AppAuthAuthenticationData: AuthenticationData {
state.stateChangeDelegate = self
}

override func encode(to encoder: any Encoder) throws {
func encode(to encoder: any Encoder) throws {
var container: KeyedEncodingContainer<CodingKeys> = encoder.container(keyedBy: CodingKeys.self)
let data = try NSKeyedArchiver.archivedData(withRootObject: state, requiringSecureCoding: true)
try container.encode(data, forKey: .state)
}

override func getFreshTokens() async throws -> String {
func getFreshTokens() async throws -> String {
return try await withCheckedThrowingContinuation { continuation in
state.performAction { accessToken, clientID, error in
guard error == nil else {
Expand Down
18 changes: 10 additions & 8 deletions Data/AuthenticationClient/Tests/AuthenticationClientTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ final class AuthenticationClientTests: XCTestCase {
func testLoginSuccessful() async throws {
sut.set(appConfiguration: configuration)

persistance.currentState = AuthenticationData()
persistance.currentState = AutehenticationDataMock()

let state = AutehenticationDataMock()
state.accessToken = "abcd"
Expand Down Expand Up @@ -142,33 +142,35 @@ private final class OAuthCallerMock: OAuthCaller {
}
}

private final class AutehenticationDataMock: AuthenticationData {
private final class AutehenticationDataMock: Equatable, AuthenticationData {
var accessToken: String? {
didSet {
guard oldValue != nil else { return }
subject.send()
}
}

override var stateChangedPublisher: AnyPublisher<Void, Never> {
var stateChangedPublisher: AnyPublisher<Void, Never> {
subject.eraseToAnyPublisher()
}

let subject = PassthroughSubject<Void, Never>()

override init() {
super.init()
}
init() { }

required init(from decoder: any Decoder) throws {
fatalError()
}

override var isAuthorized: Bool {
func encode(to encoder: any Encoder) throws {
fatalError()
}

var isAuthorized: Bool {
accessToken != nil
}

override func getFreshTokens() async throws -> String {
func getFreshTokens() async throws -> String {
guard let token = accessToken else {
throw AuthenticationStateError.failedToRefreshTokens(nil)
}
Expand Down

0 comments on commit 3cdc724

Please sign in to comment.