Skip to content

Commit

Permalink
Merge pull request #290 from boostcampwm2023/iOS/chore#284
Browse files Browse the repository at this point in the history
chore: 탈퇴 시 안내 문구 수정, 회원가입시 memberId UserDefaults에 저장하도록 변경
  • Loading branch information
loinsir authored Dec 11, 2023
2 parents d2b726d + be62bcd commit 4730b80
Show file tree
Hide file tree
Showing 9 changed files with 113 additions and 44 deletions.
39 changes: 31 additions & 8 deletions iOS/Layover/Layover/Network/AuthManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,53 @@
// Created by 김인환 on 11/13/23.
//


protocol AuthManagerProtocol: AnyObject {
var accessToken: String? { get set }
var refreshToken: String? { get set }
var isLoggedIn: Bool { get set }
var isLoggedIn: Bool? { get set }
var loginType: LoginType? { get set }
var memberID: Int? { get set }

func login(accessToken: String?, refreshToken: String?, memberID: Int?, loginType: LoginType?)
func logout()
}

enum LoginType: String, Codable {
case kakao
case apple
}

extension AuthManagerProtocol {
func login(accessToken: String?, refreshToken: String?, memberID: Int?, loginType: LoginType?) {
self.accessToken = accessToken
self.refreshToken = refreshToken
self.memberID = memberID
self.loginType = loginType
isLoggedIn = true
}

func logout() {
accessToken = nil
refreshToken = nil
memberID = nil
loginType = nil
isLoggedIn = false
}
}

final class AuthManager: AuthManagerProtocol {

// MARK: Properties

@KeychainStored(key: "accessToken") var accessToken: String?
@KeychainStored(key: "refreshToken") var refreshToken: String?

@UserDefaultStored(key: UserDefaultKey.isLoggedIn, defaultValue: false) var isLoggedIn: Bool
@UserDefaultStored(key: UserDefaultKey.isLoggedIn, defaultValue: false) var isLoggedIn: Bool?
@UserDefaultStored(key: UserDefaultKey.memberId, defaultValue: nil) var memberID: Int?
@UserDefaultStored(key: UserDefaultKey.loginType, defaultValue: nil) var loginType: LoginType?

static let shared = AuthManager()

private init() { }

func logout() {
accessToken = nil
refreshToken = nil
isLoggedIn = false
}
}
2 changes: 1 addition & 1 deletion iOS/Layover/Layover/SceneDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class SceneDelegate: UIResponder, UIWindowSceneDelegate {
guard let windowScene = (scene as? UIWindowScene) else { return }

let window = UIWindow(windowScene: windowScene)
let rootViewController = AuthManager.shared.isLoggedIn ? MainTabBarViewController() : LoginViewController()
let rootViewController = AuthManager.shared.isLoggedIn == true ? MainTabBarViewController() : LoginViewController()
let rootNavigationController = UINavigationController(rootViewController: rootViewController)

if rootViewController is MainTabBarViewController {
Expand Down
38 changes: 29 additions & 9 deletions iOS/Layover/Layover/Scenes/Login/LoginWorker.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,19 @@ final class LoginWorker: NSObject {

typealias Models = LoginModels

let provider: ProviderType
let loginEndPointFactory: LoginEndPointFactory
let authManager: AuthManager
private let provider: ProviderType
private let loginEndPointFactory: LoginEndPointFactory
private let userEndPointFactory: UserEndPointFactory
private let authManager: AuthManager

init(provider: ProviderType = Provider(),
loginEndPointFactory: LoginEndPointFactory = DefaultLoginEndPointFactory(),
userEndPointFactory: UserEndPointFactory = DefaultUserEndPointFactory(),
authManager: AuthManager = .shared) {
self.provider = provider
self.authManager = authManager
self.loginEndPointFactory = loginEndPointFactory
self.userEndPointFactory = userEndPointFactory
}
}

Expand Down Expand Up @@ -85,9 +88,10 @@ extension LoginWorker: LoginWorkerProtocol {
let endPoint = loginEndPointFactory.makeKakaoLoginEndPoint(with: socialToken)
let result = try await provider.request(with: endPoint, authenticationIfNeeded: false)

authManager.accessToken = result.data?.accessToken
authManager.refreshToken = result.data?.refreshToken
authManager.isLoggedIn = true
authManager.login(accessToken: result.data?.accessToken,
refreshToken: result.data?.refreshToken,
memberID: await fetchMemberId(),
loginType: .kakao)
return true
} catch {
os_log(.error, log: .data, "%@", error.localizedDescription)
Expand All @@ -113,13 +117,29 @@ extension LoginWorker: LoginWorkerProtocol {
let endPoint: EndPoint = loginEndPointFactory.makeAppleLoginEndPoint(with: identityToken)
let result: EndPoint<Response<LoginDTO>>.Response = try await provider.request(with: endPoint, authenticationIfNeeded: false)

authManager.accessToken = result.data?.accessToken
authManager.refreshToken = result.data?.refreshToken
authManager.isLoggedIn = true
authManager.login(accessToken: result.data?.accessToken,
refreshToken: result.data?.refreshToken,
memberID: await fetchMemberId(),
loginType: .apple)
return true
} catch {
os_log(.error, log: .data, "%@", error.localizedDescription)
return false
}
}

private func fetchMemberId() async -> Int? {
let endPoint = userEndPointFactory.makeUserInformationEndPoint(with: nil)
do {
let responseData = try await provider.request(with: endPoint)
guard let data = responseData.data else {
os_log(.error, log: .default, "Failed to fetch member id with error: %@", responseData.message)
return nil
}
return data.id
} catch {
os_log(.error, log: .default, "Failed to fetch member id with error: %@", error.localizedDescription)
return nil
}
}
}
1 change: 1 addition & 0 deletions iOS/Layover/Layover/Scenes/Setting/SettingInteractor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ final class SettingInteractor: SettingBusinessLogic, SettingDataStore {
func performUserWithdraw(request: SettingModels.Withdraw.Request) -> Task<Bool, Never> {
Task {
guard (await userWorker?.withdraw()) != nil else { return false }
userWorker?.logout()
await MainActor.run {
presenter?.presentUserWithdrawConfirmed(with: Models.Withdraw.Response())
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ final class SettingViewController: BaseViewController {
}()

private lazy var withdrawAlertController: UIAlertController = {
let alertController = UIAlertController(title: "회원탈퇴", message: "회원탈퇴 하시겠습니까?", preferredStyle: .alert)
let alertController = UIAlertController(title: "회원탈퇴", message: "7일 내로 재로그인시 계정이 복구됩니다.\n정말 탈퇴하시겠어요?", preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "탈퇴", style: .destructive, handler: { [weak self] _ in
self?.interactor?.performUserWithdraw(request: Models.Withdraw.Request())
}))
Expand Down
36 changes: 28 additions & 8 deletions iOS/Layover/Layover/Scenes/SignUpScene/SignUpWorker.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,18 @@ final class SignUpWorker {
// MARK: Properties

private let signUpEndPointFactory: SignUpEndPointFactory
private let userEndPointFactory: UserEndPointFactory
private let provider: ProviderType
private let authManager: AuthManagerProtocol

// MARK: Intializer

init(signUpEndPointFactory: SignUpEndPointFactory = DefaultSignUpEndPointFactory(),
userEndPointFactory: UserEndPointFactory = DefaultUserEndPointFactory(),
provider: ProviderType = Provider(),
authManager: AuthManagerProtocol = AuthManager.shared) {
self.signUpEndPointFactory = signUpEndPointFactory
self.userEndPointFactory = userEndPointFactory
self.provider = provider
self.authManager = authManager
}
Expand All @@ -47,12 +50,13 @@ extension SignUpWorker: SignUpWorkerProtocol {
return false
}

authManager.accessToken = data.accessToken
authManager.refreshToken = data.refreshToken
authManager.isLoggedIn = true
authManager.login(accessToken: data.accessToken,
refreshToken: data.refreshToken,
memberID: await fetchMemberId(),
loginType: .kakao)
return true
} catch {
os_log(.error, log: .default, "Failed to sign up with error: %@", error.localizedDescription)
os_log(.error, log: .data, "Failed to sign up with error: %@", error.localizedDescription)
return false
}
}
Expand All @@ -66,13 +70,29 @@ extension SignUpWorker: SignUpWorkerProtocol {
os_log(.error, log: .default, "Failed to sign up with error: %@", responseData.message)
return false
}
authManager.accessToken = data.accessToken
authManager.refreshToken = data.refreshToken
authManager.isLoggedIn = true
authManager.login(accessToken: data.accessToken,
refreshToken: data.refreshToken,
memberID: await fetchMemberId(),
loginType: .apple)
return true
} catch {
os_log(.error, log: .default, "Failed to sign up with error: %@", error.localizedDescription)
os_log(.error, log: .data, "Failed to sign up with error: %@", error.localizedDescription)
return false
}
}

private func fetchMemberId() async -> Int? {
let endPoint = userEndPointFactory.makeUserInformationEndPoint(with: nil)
do {
let responseData = try await provider.request(with: endPoint)
guard let data = responseData.data else {
os_log(.error, log: .data, "Failed to fetch member id with error: %@", responseData.message)
return nil
}
return data.id
} catch {
os_log(.error, log: .data, "Failed to fetch member id with error: %@", error.localizedDescription)
return nil
}
}
}
4 changes: 2 additions & 2 deletions iOS/Layover/Layover/Services/System.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ import Foundation

enum System {

@UserDefaultStored(key: UserDefaultKey.hasBeenLaunchedBefore, defaultValue: false) static var hasBeenLaunchedBefore: Bool
@UserDefaultStored(key: UserDefaultKey.hasBeenLaunchedBefore, defaultValue: false) static var hasBeenLaunchedBefore: Bool?

static func isFirstLaunch() -> Bool {
if !hasBeenLaunchedBefore {
if hasBeenLaunchedBefore == false {
hasBeenLaunchedBefore = true
return true
}
Expand Down
23 changes: 17 additions & 6 deletions iOS/Layover/Layover/Services/UserDefaults/UserDefaultStored.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,37 @@
import Foundation

@propertyWrapper
struct UserDefaultStored<T> {
struct UserDefaultStored<T: Codable> {
private let key: String
private let defaultValue: T
private let defaultValue: T?

init(key: String, defaultValue: T) {
init(key: String, defaultValue: T?) {
self.key = key
self.defaultValue = defaultValue
}

var wrappedValue: T {
var wrappedValue: T? {
get {
return UserDefaults.standard.object(forKey: key) as? T ?? defaultValue
if let savedData = UserDefaults.standard.object(forKey: key) as? Data {
let decoder = JSONDecoder()
if let loadedObject = try? decoder.decode(T.self, from: savedData) {
return loadedObject
}
}
return defaultValue
}
set {
UserDefaults.standard.set(newValue, forKey: key)
let encoder = JSONEncoder()
if let encodedObject = try? encoder.encode(newValue) {
UserDefaults.standard.set(encodedObject, forKey: key)
}
}
}
}

enum UserDefaultKey {
static let isLoggedIn = "isLoggedIn"
static let hasBeenLaunchedBefore = "hasBeenLaunchedBefore"
static let memberId = "memberId"
static let loginType = "loginType"
}
12 changes: 3 additions & 9 deletions iOS/Layover/Layover/Workers/Mocks/StubAuthManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,7 @@ final class StubAuthManager: AuthManagerProtocol {

var accessToken: String? = "Fake Access Token"
var refreshToken: String? = "Fake Refresh Token"
var isLoggedIn: Bool = true

// MARK: Methods

func logout() {
accessToken = nil
refreshToken = nil
isLoggedIn = false
}
var isLoggedIn: Bool? = true
var loginType: LoginType? = .kakao
var memberID: Int? = -1
}

0 comments on commit 4730b80

Please sign in to comment.