Skip to content

Commit

Permalink
[feat] 카카오 연동 해제 및 잡일...
Browse files Browse the repository at this point in the history
  • Loading branch information
yeseonglee committed Nov 26, 2024
1 parent 97b8e37 commit 4354e70
Show file tree
Hide file tree
Showing 10 changed files with 224 additions and 113 deletions.
91 changes: 88 additions & 3 deletions DropDrug/Sources/APIServices/Plugins/BearerToken+Plugin.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,105 @@

import Foundation
import Moya
import SwiftyToaster

final class BearerTokenPlugin: PluginType {
private var accessToken: String? {
return SelectLoginTypeVC.keychain.get("serverAccessToken")
}

func checkAuthenticationStatus(completion: @escaping (String?) -> Void) {
guard let accessToken = SelectLoginTypeVC.keychain.get("serverAccessToken"),
let accessTokenExpiryMillis = SelectLoginTypeVC.keychain.get("accessTokenExpiresIn"),
let expiryMillis = Int64(accessTokenExpiryMillis),
let accessTokenExpiryDate = Date(milliseconds: expiryMillis) else {
print("AccessToken이 존재하지 않음.")
refreshAccessToken(completion: completion)
return
}

if Date() < accessTokenExpiryDate {
print("AccessToken 유효. 갱신 불필요.")
completion(accessToken)
} else {
print("AccessToken 만료. RefreshToken으로 갱신 시도.")
refreshAccessToken(completion: completion)
}
}

private func refreshAccessToken(completion: @escaping (String?) -> Void) {
guard let refreshToken = SelectLoginTypeVC.keychain.get("serverRefreshToken") else {
print("RefreshToken이 존재하지 않음.")
Toaster.shared.makeToast("다시 로그인해 주세요")
completion(nil)
return
}

let provider = MoyaProvider<LoginService>(plugins: [NetworkLoggerPlugin()])
provider.request(.refreshAccessToken(refreshToken: refreshToken)) { result in
switch result {
case .success(let response):
do {
let data = try response.map(RefreshTokenDto.self)
SelectLoginTypeVC.keychain.set(data.accessToken, forKey: "serverAccessToken")
SelectLoginTypeVC.keychain.set(String(data.accessTokenExpiresIn), forKey: "accessTokenExpiresIn")
SelectLoginTypeVC.keychain.delete("serverRefreshToken")
print("AccessToken 갱신 성공.")
completion(data.accessToken)
} catch {
Toaster.shared.makeToast("데이터를 불러오는데 실패했습니다.")
completion(nil)
}
case .failure(let error):
Toaster.shared.makeToast("\(error.localizedDescription)")
if let response = error.response {
print("Response Body: \(String(data: response.data, encoding: .utf8) ?? "")")
}
completion(nil)
}
}
}

func prepare(_ request: URLRequest, target: TargetType) -> URLRequest {
var request = request

let semaphore = DispatchSemaphore(value: 0) // 동기적 작업을 위해 사용
var tokenToAdd: String?

// 만약 accessToken이 있다면 Authorization 헤더에 추가합니다.
if let token = accessToken {
checkAuthenticationStatus { token in
tokenToAdd = token
semaphore.signal()
}

semaphore.wait()

if let token = tokenToAdd {
request.addValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
}

return request
}
}


//// Copyright © 2024 RT4. All rights reserved
//
//import Foundation
//import Moya
//
//final class BearerTokenPlugin: PluginType {
// private var accessToken: String? {
// return SelectLoginTypeVC.keychain.get("serverAccessToken")
// }
//
// func prepare(_ request: URLRequest, target: TargetType) -> URLRequest {
// var request = request
//
// // 만약 accessToken이 있다면 Authorization 헤더에 추가합니다.
// if let token = accessToken {
// request.addValue("Bearer \(token)", forHTTPHeaderField: "Authorization")
// }
//
// return request
// }
//}
46 changes: 23 additions & 23 deletions DropDrug/Sources/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
}
}

checkAuthenticationStatus()
// checkAuthenticationStatus()

return true
}
Expand All @@ -85,28 +85,28 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
}

private func checkAuthenticationStatus() {
guard let accessToken = SelectLoginTypeVC.keychain.get("serverAccessToken"),
let accessTokenExpiryMillis = SelectLoginTypeVC.keychain.get("accessTokenExpiresIn"),
let expiryMillis = Int64(accessTokenExpiryMillis),
let accessTokenExpiryDate = Date(milliseconds: expiryMillis) else {
//accessToken 존재 X
return
}

if Date() < accessTokenExpiryDate {
print("AccessToken 유효. 갱신 불필요.")
} else {
print("AccessToken 만료. RefreshToken으로 갱신 시도.")
self.refreshAccessToken { success in
if success {
print("refresh AccessToken successfully")
} else {
print("Failed to refresh AccessToken")
}
}
}
}
// private func checkAuthenticationStatus() {
// guard let accessToken = SelectLoginTypeVC.keychain.get("serverAccessToken"),
// let accessTokenExpiryMillis = SelectLoginTypeVC.keychain.get("accessTokenExpiresIn"),
// let expiryMillis = Int64(accessTokenExpiryMillis),
// let accessTokenExpiryDate = Date(milliseconds: expiryMillis) else {
// //accessToken 존재 X
// return
// }
//
// if Date() < accessTokenExpiryDate {
// print("AccessToken 유효. 갱신 불필요.")
// } else {
// print("AccessToken 만료. RefreshToken으로 갱신 시도.")
// self.refreshAccessToken { success in
// if success {
// print("refresh AccessToken successfully")
// } else {
// print("Failed to refresh AccessToken")
// }
// }
// }
// }
}

extension AppDelegate: UNUserNotificationCenterDelegate {
Expand Down
12 changes: 9 additions & 3 deletions DropDrug/Sources/Cells/SeoulCollectionViewCell.swift
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,14 @@ class SeoulCollectionViewCell: UICollectionViewCell {
make.centerX.equalToSuperview()
}
}
func configure(showNameLabel: Bool, showBorder: Bool) {
name.isHidden = !showNameLabel
image.layer.borderColor = showBorder ? Constants.Colors.gray300?.cgColor : UIColor.clear.cgColor
func configure(showNameLabel: Bool, showBorder: Bool, borderColor: UIColor?) {
name.isHidden = !showNameLabel
if showBorder {
image.layer.borderWidth = 4.0 // 원하는 두께 설정
image.layer.borderColor = borderColor?.cgColor ?? UIColor.clear.cgColor
} else {
image.layer.borderWidth = 0.0
image.layer.borderColor = UIColor.clear.cgColor
}
}
}
32 changes: 28 additions & 4 deletions DropDrug/Sources/Models/Auth/KakaoAuthVM.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ import KeychainSwift

class KakaoAuthVM: ObservableObject {

static let keychain = KeychainSwift()

var subscriptions = Set<AnyCancellable>()

@Published var isLoggedIn: Bool = false
Expand Down Expand Up @@ -110,10 +108,36 @@ class KakaoAuthVM: ObservableObject {
}
}

@MainActor
func unlinkKakaoAccount(completion: @escaping (Bool) -> Void) {
Task {
let success = await handleKakaoUnlink()
if success {
clearToken() // 연동 해제 성공 시 토큰 삭제
self.isLoggedIn = false
}
completion(success)
}
}

func handleKakaoUnlink() async -> Bool {
await withCheckedContinuation { continuation in
UserApi.shared.unlink { [weak self] error in
if let error = error {
print("카카오 계정 연동 해제 실패: \(error.localizedDescription)")
self?.errorMessage = "연동 해제 실패: \(error.localizedDescription)"
continuation.resume(returning: false)
} else {
print("카카오 계정 연동 해제 성공")
continuation.resume(returning: true)
}
}
}
}

// 저장된 토큰을 삭제
private func clearToken() {
//TODO: keychain kakotoken clear
UserDefaults.standard.removeObject(forKey: "kakaoToken")
SelectLoginTypeVC.keychain.clear()
oauthToken = nil
}
}
35 changes: 0 additions & 35 deletions DropDrug/Sources/Models/Auth/RegisterManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,41 +5,6 @@ import Moya
import KeychainSwift
import SwiftyToaster

extension AppDelegate {
func refreshAccessToken(completion: @escaping (Bool) -> Void) {
guard let refreshToken = SelectLoginTypeVC.keychain.get("serverRefreshToken")
else {
Toaster.shared.makeToast("리프레시 토큰을 찾을 수 없습니다")
completion(false)
return
}
provider.request(.refreshAccessToken(refreshToken: refreshToken)) { result in
print("refreshToken found")
switch result {
case .success(let response):
print(response)
do {
let data = try response.map(RefreshTokenDto.self)
SelectLoginTypeVC.keychain.set(data.accessToken, forKey: "serverAccessToken")
SelectLoginTypeVC.keychain.set(String(data.accessTokenExpiresIn), forKey: "accessTokenExpiresIn")
completion(true)
} catch {
// print("Failed to map data : \(error)")
Toaster.shared.makeToast("데이터를 불러오는데 실패했습니다.")
completion(false)
}
case .failure(let error):
Toaster.shared.makeToast("\(error.localizedDescription)")
// print("Error: \(error.localizedDescription)")
if let response = error.response {
print("Response Body: \(String(data: response.data, encoding: .utf8) ?? "")")
}
completion(false)
}
}
}
}

extension SignUpVC {
func setupSignUpDTO(_ emailString: String, _ pwString: String, name : String) -> MemberSignupRequest {
return MemberSignupRequest(email: emailString, name: name, password: pwString)
Expand Down
1 change: 1 addition & 0 deletions DropDrug/Sources/Models/MyPage/CharacterManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ extension CharacterSettingsVC {
do {
let data = try response.map(MemberInfo.self)
self.ownedChar = data.ownedChars
self.selectedChar = data.selectedChar
completion(true)
} catch {
completion(false)
Expand Down
1 change: 1 addition & 0 deletions DropDrug/Sources/Models/MyPage/MemberInfoManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ extension AccountSettingsVC {
do {
let data = try response.map(MemberInfo.self)
self.nickname = data.nickname
let hasKakaoTokens = SelectLoginTypeVC.keychain.get("KakaoAccessToken") != nil || SelectLoginTypeVC.keychain.get("KakaoRefreshToken") != nil || SelectLoginTypeVC.keychain.get("KakaoIdToken") != nil
self.userId = data.email
completion(true)
} catch {
Expand Down
29 changes: 18 additions & 11 deletions DropDrug/Sources/ViewControllers/Auth/SplashVC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import KeychainSwift

class SplashVC : UIViewController {

let provider = MoyaProvider<LoginService>(plugins: [ NetworkLoggerPlugin() ])
let tokenPlugin = BearerTokenPlugin()

private lazy var titleLabel: UILabel = {
let label = UILabel()
Expand All @@ -24,9 +24,16 @@ class SplashVC : UIViewController {
setupViews()
setConstraints()
DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {
self.checkAuthenticationStatus()
self.tokenPlugin.checkAuthenticationStatus { token in
if let token = token {
print("토큰 확인 완료: \(token)")
self.navigateToMainScreen()
} else {
print("토큰 확인 실패")
self.navigateToOnBoaringScreen()
}
}
}
print("refreshToken : \(SelectLoginTypeVC.keychain.get("serverRefreshToken"))")
}

func setupViews() {
Expand All @@ -52,12 +59,12 @@ class SplashVC : UIViewController {
}
}

private func checkAuthenticationStatus() {
if let accessToken = SelectLoginTypeVC.keychain.get("serverAccessToken") {
navigateToMainScreen()
} else {
print("토큰 없음. 로그인 화면으로 이동.")
navigateToOnBoaringScreen()
}
}
// private func checkAuthenticationStatus() {
// if let accessToken = SelectLoginTypeVC.keychain.get("serverAccessToken") {
// navigateToMainScreen()
// } else {
// print("토큰 없음. 로그인 화면으로 이동.")
// navigateToOnBoaringScreen()
// }
// }
}
Loading

0 comments on commit 4354e70

Please sign in to comment.