-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Start hooking up login use cases
- Loading branch information
Showing
29 changed files
with
579 additions
and
427 deletions.
There are no files selected for viewing
6 changes: 6 additions & 0 deletions
6
iosApp/Modules/DI/ModuleLinker/Extensions/Error+KMMException.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,6 @@ | ||
import Foundation | ||
import shared | ||
|
||
public extension Error { | ||
var kmmException: KMMException? { (self as NSError).kotlinException as? KMMException } | ||
} |
7 changes: 7 additions & 0 deletions
7
iosApp/Modules/DI/ModuleLinker/Extensions/Notification+KMM.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,7 @@ | ||
import Foundation | ||
|
||
public extension NotificationCenter { | ||
func publisher(for name: String) -> Publisher { | ||
publisher(for: Notification.Name(name), object: nil) | ||
} | ||
} |
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 |
---|---|---|
@@ -1,19 +1,19 @@ | ||
import Foundation | ||
import Models | ||
|
||
public protocol UserManaging: ObservableObject { | ||
var currentUser: User? { get } | ||
|
||
func deleteUser() async throws | ||
func createUser(nickname: String, email: String, password: String, passwordConfirmation: String, verificationCode: String) async throws | ||
func resetPassword(email: String, password: String, confirmPassword: String, authCode: String) async throws | ||
func fetchCurrentUser() async throws | ||
func updateUserInfo(firstName: String?, lastName: String?, currentPassword: String?, newPassword: String?, confirmNewPassword: String?) async throws | ||
} | ||
|
||
public enum UserRepoError: LocalizedError { | ||
case accountExists | ||
case twoFAFailed | ||
case dataUnavailable | ||
case displayError(String) | ||
} | ||
//import Foundation | ||
//import Models | ||
// | ||
//public protocol UserManaging: ObservableObject { | ||
// var currentUser: User? { get } | ||
// | ||
// func deleteUser() async throws | ||
// func createUser(nickname: String, email: String, password: String, passwordConfirmation: String, verificationCode: String) async throws | ||
// func resetPassword(email: String, password: String, confirmPassword: String, authCode: String) async throws | ||
// func fetchCurrentUser() async throws | ||
// func updateUserInfo(firstName: String?, lastName: String?, currentPassword: String?, newPassword: String?, confirmNewPassword: String?) async throws | ||
//} | ||
// | ||
//public enum UserRepoError: LocalizedError { | ||
// case accountExists | ||
// case twoFAFailed | ||
// case dataUnavailable | ||
// case displayError(String) | ||
//} |
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
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 |
---|---|---|
@@ -1,70 +1,67 @@ | ||
import Foundation | ||
import API | ||
import KeychainSwift | ||
import FacebookLogin | ||
import GoogleSignIn | ||
import AuthenticationServices | ||
|
||
enum LoginError: Error { | ||
case facebookAccessTokenMissing | ||
} | ||
|
||
public class LoginRepo: ObservableObject { | ||
//TODO: update this with user info | ||
@Published public var userIsLoggedIn: Bool = false | ||
private let api: LoginAPI | ||
|
||
private var appleSignInID: String? | ||
|
||
//TODO: make actor | ||
// public static let shared = LoginRepo() | ||
|
||
private init(api: LoginAPI = LoginAPI()) { | ||
self.api = api | ||
api.$userIsLoggedIn.assign(to: &$userIsLoggedIn) | ||
} | ||
|
||
public func loginWithFacebook(result: LoginManagerLoginResult) async throws { | ||
do { | ||
guard let token = result.token?.tokenString else { | ||
throw LoginError.facebookAccessTokenMissing | ||
} | ||
try await api.login(method: .facebook(accessToken: token)) | ||
} catch { | ||
Task { @MainActor in | ||
FacebookLogin.LoginManager().logOut() | ||
} | ||
throw error | ||
} | ||
} | ||
|
||
public func loginWithGoogle(result: GIDSignInResult) async throws { | ||
let token = result.user.accessToken.tokenString | ||
try await api.login(method: .google(accessToken: token)) | ||
} | ||
|
||
public func login(email: String, password: String) async throws { | ||
try await api.login(method: .email(email: email, password: password)) | ||
} | ||
|
||
public func logOut() { | ||
api.logOut() | ||
FacebookLogin.LoginManager().logOut() | ||
GIDSignIn.sharedInstance.signOut() | ||
signOutOfApple() | ||
UserRepo.shared.currentUser = nil | ||
} | ||
|
||
public func requestEmailVerificationCode(for email: String) async throws { | ||
try await api.requestEmailVerificationCode(for: email) | ||
} | ||
|
||
public func loginWithApple(result: ASAuthorization) async throws { | ||
let token = String(data: (result.credential as! ASAuthorizationAppleIDCredential).identityToken!, encoding: .utf8)! | ||
try await api.login(method: .apple(idToken: token)) | ||
} | ||
|
||
private func signOutOfApple() { | ||
//TODO: | ||
} | ||
} | ||
//import Foundation | ||
//import API | ||
//import KeychainSwift | ||
//import FacebookLogin | ||
//import GoogleSignIn | ||
//import AuthenticationServices | ||
// | ||
//enum LoginError: Error { | ||
// case facebookAccessTokenMissing | ||
//} | ||
// | ||
//public class LoginRepo: ObservableObject { | ||
// //TODO: update this with user info | ||
// @Published public var userIsLoggedIn: Bool = false | ||
// private let api: LoginAPI | ||
// | ||
// private var appleSignInID: String? | ||
// | ||
// private init(api: LoginAPI = LoginAPI()) { | ||
// self.api = api | ||
// api.$userIsLoggedIn.assign(to: &$userIsLoggedIn) | ||
// } | ||
// | ||
// public func loginWithFacebook(result: LoginManagerLoginResult) async throws { | ||
// do { | ||
// guard let token = result.token?.tokenString else { | ||
// throw LoginError.facebookAccessTokenMissing | ||
// } | ||
// try await api.login(method: .facebook(accessToken: token)) | ||
// } catch { | ||
// Task { @MainActor in | ||
// FacebookLogin.LoginManager().logOut() | ||
// } | ||
// throw error | ||
// } | ||
// } | ||
// | ||
// public func loginWithGoogle(result: GIDSignInResult) async throws { | ||
// let token = result.user.accessToken.tokenString | ||
// try await api.login(method: .google(accessToken: token)) | ||
// } | ||
// | ||
// public func login(email: String, password: String) async throws { | ||
// try await api.login(method: .email(email: email, password: password)) | ||
// } | ||
// | ||
// public func logOut() { | ||
// api.logOut() | ||
// FacebookLogin.LoginManager().logOut() | ||
// GIDSignIn.sharedInstance.signOut() | ||
// signOutOfApple() | ||
// UserRepo.shared.currentUser = nil | ||
// } | ||
// | ||
// public func requestEmailVerificationCode(for email: String) async throws { | ||
// try await api.requestEmailVerificationCode(for: email) | ||
// } | ||
// | ||
// public func loginWithApple(result: ASAuthorization) async throws { | ||
// let token = String(data: (result.credential as! ASAuthorizationAppleIDCredential).identityToken!, encoding: .utf8)! | ||
// try await api.login(method: .apple(idToken: token)) | ||
// } | ||
// | ||
// private func signOutOfApple() { | ||
// //TODO: | ||
// } | ||
//} |
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 |
---|---|---|
@@ -1,86 +1,86 @@ | ||
import Foundation | ||
import API | ||
import Models | ||
import ModuleLinker | ||
import Resolver | ||
|
||
class UserRepo: UserManaging, ObservableObject { | ||
private let api = UserAPI() | ||
@Injected private var loginRepo: LoginRepo | ||
|
||
@Published public var currentUser: User? | ||
|
||
//TODO: make actor | ||
public static let shared = UserRepo() | ||
|
||
private init() {} | ||
|
||
public func deleteUser() async throws { | ||
do { | ||
try await api.delete() | ||
} catch { | ||
try handleError(error) | ||
} | ||
loginRepo.logOut() | ||
} | ||
|
||
public func createUser(nickname: String, email: String, password: String, passwordConfirmation: String, verificationCode: String) async throws { | ||
do { | ||
try await api.create(nickname: nickname, email: email, password: password, passwordConfirmation: passwordConfirmation, verificationCode: verificationCode) | ||
} catch { | ||
try handleError(error) | ||
} | ||
} | ||
|
||
public func resetPassword(email: String, password: String, confirmPassword: String, authCode: String) async throws { | ||
do { | ||
try await api.resetPassword(email: email, password: password, confirmPassword: confirmPassword, authCode: authCode) | ||
} catch { | ||
try handleError(error) | ||
} | ||
} | ||
|
||
public func fetchCurrentUser() async throws { | ||
do { | ||
currentUser = try await api.getCurrentUser() | ||
} catch { | ||
try handleError(error) | ||
} | ||
} | ||
|
||
public func updateUserInfo(firstName: String?, lastName: String?, currentPassword: String?, newPassword: String?, confirmNewPassword: String?) async throws { | ||
let updatedUser = try UpdatedUser( | ||
firstName: firstName?.nilIfEmpty, | ||
lastName: lastName?.nilIfEmpty, | ||
newPassword: newPassword?.nilIfEmpty, | ||
confirmPassword: confirmNewPassword?.nilIfEmpty, | ||
currentPassword: currentPassword?.nilIfEmpty | ||
) | ||
do { | ||
try await api.update(user: updatedUser) | ||
try await fetchCurrentUser() | ||
} catch { | ||
try handleError(error) | ||
} | ||
} | ||
|
||
private func handleError(_ error: Error) throws { | ||
if let error = error as? UserAPI.Error { | ||
switch error { | ||
case .accountExists: | ||
throw UserRepoError.accountExists | ||
case .twoFAFailed: | ||
throw UserRepoError.twoFAFailed | ||
case .unprocessableEntity(let cause): | ||
throw UserRepoError.displayError(cause) | ||
} | ||
} else if let error = error as? APIError { | ||
switch error { | ||
case .invalidResponse: | ||
throw UserRepoError.dataUnavailable | ||
case .httpError(_, let cause): | ||
throw UserRepoError.displayError(cause ?? "An unknown error occurred.") | ||
} | ||
} | ||
} | ||
} | ||
//import Foundation | ||
//import API | ||
//import Models | ||
//import ModuleLinker | ||
//import Resolver | ||
// | ||
//class UserRepo: UserManaging, ObservableObject { | ||
// private let api = UserAPI() | ||
// @Injected private var loginRepo: LoginRepo | ||
// | ||
// @Published public var currentUser: User? | ||
// | ||
// //TODO: make actor | ||
// public static let shared = UserRepo() | ||
// | ||
// private init() {} | ||
// | ||
// public func deleteUser() async throws { | ||
// do { | ||
// try await api.delete() | ||
// } catch { | ||
// try handleError(error) | ||
// } | ||
// loginRepo.logOut() | ||
// } | ||
// | ||
// public func createUser(nickname: String, email: String, password: String, passwordConfirmation: String, verificationCode: String) async throws { | ||
// do { | ||
// try await api.create(nickname: nickname, email: email, password: password, passwordConfirmation: passwordConfirmation, verificationCode: verificationCode) | ||
// } catch { | ||
// try handleError(error) | ||
// } | ||
// } | ||
// | ||
// public func resetPassword(email: String, password: String, confirmPassword: String, authCode: String) async throws { | ||
// do { | ||
// try await api.resetPassword(email: email, password: password, confirmPassword: confirmPassword, authCode: authCode) | ||
// } catch { | ||
// try handleError(error) | ||
// } | ||
// } | ||
// | ||
// public func fetchCurrentUser() async throws { | ||
// do { | ||
// currentUser = try await api.getCurrentUser() | ||
// } catch { | ||
// try handleError(error) | ||
// } | ||
// } | ||
// | ||
// public func updateUserInfo(firstName: String?, lastName: String?, currentPassword: String?, newPassword: String?, confirmNewPassword: String?) async throws { | ||
// let updatedUser = try UpdatedUser( | ||
// firstName: firstName?.nilIfEmpty, | ||
// lastName: lastName?.nilIfEmpty, | ||
// newPassword: newPassword?.nilIfEmpty, | ||
// confirmPassword: confirmNewPassword?.nilIfEmpty, | ||
// currentPassword: currentPassword?.nilIfEmpty | ||
// ) | ||
// do { | ||
// try await api.update(user: updatedUser) | ||
// try await fetchCurrentUser() | ||
// } catch { | ||
// try handleError(error) | ||
// } | ||
// } | ||
// | ||
// private func handleError(_ error: Error) throws { | ||
// if let error = error as? UserAPI.Error { | ||
// switch error { | ||
// case .accountExists: | ||
// throw UserRepoError.accountExists | ||
// case .twoFAFailed: | ||
// throw UserRepoError.twoFAFailed | ||
// case .unprocessableEntity(let cause): | ||
// throw UserRepoError.displayError(cause) | ||
// } | ||
// } else if let error = error as? APIError { | ||
// switch error { | ||
// case .invalidResponse: | ||
// throw UserRepoError.dataUnavailable | ||
// case .httpError(_, let cause): | ||
// throw UserRepoError.displayError(cause ?? "An unknown error occurred.") | ||
// } | ||
// } | ||
// } | ||
//} |
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
Oops, something went wrong.