Skip to content

Commit 9845f87

Browse files
authored
[#251] 여러 계정을 링크한 이후 각 공급자에 대한 실질적인 회원탈퇴가 이루어지지 않는 이슈를 해결한다 (#252)
* fix: 여러 공급자가 링크된 유저인 경우 providers를 순회해서 링크를 끉도록 해결 * refactor: providerIDs가 currentUser가 nil인 경우 빈 배열을 반환하도록 개선 * refactor: uid를 클라이언트 쪽에서 보내지 않도록 개선 * refactor: FCM 토큰을 삭제하는데 실패해도 로그아웃은 되도록 개선
1 parent e2f1c9c commit 9845f87

7 files changed

Lines changed: 61 additions & 40 deletions

File tree

DevLog/Data/Repository/AuthDataRepositoryImpl.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ final class AuthDataRepositoryImpl: AuthDataRepository {
3333
}
3434

3535
func fetchAllProviders() async throws -> [AuthProvider] {
36-
let providerStrings = authService.providerIDs ?? []
36+
let providerStrings = authService.providerIDs
3737
return providerStrings.compactMap { AuthProvider(rawValue: $0) }
3838
}
3939

DevLog/Data/Repository/AuthenticationRepositoryImpl.swift

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -63,20 +63,25 @@ final class AuthenticationRepositoryImpl: AuthenticationRepository {
6363
}
6464

6565
func delete() async throws {
66-
guard let uid = authService.uid,
67-
let providerID = try await authService.getProviderID(),
68-
let provider = AuthProvider(rawValue: providerID)
69-
else {
66+
guard let uid = authService.uid else {
7067
throw AuthError.notAuthenticated
7168
}
7269

73-
switch provider {
74-
case .apple:
75-
try await appleAuthService.deleteAuth(uid)
76-
case .github:
77-
try await githubAuthService.deleteAuth(uid)
78-
case .google:
79-
try await googleAuthService.deleteAuth(uid)
70+
let providers = authService.providerIDs.compactMap { AuthProvider(rawValue: $0) }
71+
72+
for provider in providers {
73+
switch provider {
74+
case .apple:
75+
try await appleAuthService.deleteAuth(uid)
76+
case .github:
77+
try await githubAuthService.deleteAuth(uid)
78+
case .google:
79+
try await googleAuthService.deleteAuth(uid)
80+
}
8081
}
82+
83+
try await authService.deleteFirestoreUserData()
84+
try await authService.deleteCurrentUser()
85+
try await authService.clearCurrentSession()
8186
}
8287
}

DevLog/Infra/Service/AuthService.swift

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,21 @@
77

88
import FirebaseAuth
99
import FirebaseFirestore
10+
import FirebaseFunctions
11+
import FirebaseMessaging
1012

1113
final class AuthService {
1214
private let store = Firestore.firestore()
15+
private let functions = Functions.functions(region: "asia-northeast3")
16+
private let messaging = Messaging.messaging()
1317
private let logger = Logger(category: "AuthService")
1418

1519
var uid: String? {
1620
Auth.auth().currentUser?.uid
1721
}
1822

19-
var providerIDs: [String]? {
20-
Auth.auth().currentUser?.providerData.map { $0.providerID }
23+
var providerIDs: [String] {
24+
Auth.auth().currentUser?.providerData.map { $0.providerID } ?? []
2125
}
2226

2327
func getProviderID() async throws -> String? {
@@ -42,4 +46,33 @@ final class AuthService {
4246
throw error
4347
}
4448
}
49+
50+
func deleteFirestoreUserData() async throws {
51+
logger.info("Deleting Firestore user data")
52+
53+
let deleteFunction = functions.httpsCallable("deleteUserFirestoreData")
54+
_ = try await deleteFunction.call()
55+
}
56+
57+
func deleteCurrentUser() async throws {
58+
logger.info("Deleting FirebaseAuth current user")
59+
60+
guard let currentUser = Auth.auth().currentUser else {
61+
logger.warning("No current user to delete")
62+
throw AuthError.notAuthenticated
63+
}
64+
65+
try await currentUser.delete()
66+
}
67+
68+
func clearCurrentSession() async throws {
69+
logger.info("Clearing current auth session")
70+
71+
do {
72+
try await messaging.deleteToken()
73+
} catch {
74+
logger.error("Failed to delete FCM token while clearing session", error: error)
75+
}
76+
try Auth.auth().signOut()
77+
}
4578
}

DevLog/Infra/Service/SocialLogin/AppleAuthenticationService.swift

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -105,14 +105,6 @@ final class AppleAuthenticationService: AuthenticationService {
105105
let token = try await refreshAppleAccessToken()
106106

107107
try await revokeAppleAccessToken(token: token)
108-
109-
let deleteFunction = functions.httpsCallable("deleteUserFirestoreData")
110-
111-
_ = try await deleteFunction.call(["uid": uid])
112-
113-
try await user?.delete()
114-
try await messaging.deleteToken()
115-
try Auth.auth().signOut()
116108
}
117109

118110
func link(uid: String, email: String) async throws {

DevLog/Infra/Service/SocialLogin/GithubAuthenticationService.swift

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -82,14 +82,6 @@ final class GithubAuthenticationService: NSObject, AuthenticationService {
8282

8383
func deleteAuth(_ uid: String) async throws {
8484
try await revokeAccessToken()
85-
86-
let deleteFunction = functions.httpsCallable("deleteUserFirestoreData")
87-
88-
_ = try await deleteFunction.call(["uid": uid])
89-
90-
try await user?.delete()
91-
try await messaging.deleteToken()
92-
try Auth.auth().signOut()
9385
}
9486

9587
func link(uid: String, email: String) async throws {

DevLog/Infra/Service/SocialLogin/GoogleAuthenticationService.swift

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,15 +78,8 @@ final class GoogleAuthenticationService: AuthenticationService {
7878
}
7979

8080
func deleteAuth(_ uid: String) async throws {
81-
let deleteFunction = functions.httpsCallable("deleteUserFirestoreData")
82-
83-
_ = try await deleteFunction.call(["uid": uid])
84-
85-
try await user?.delete()
8681
GIDSignIn.sharedInstance.signOut()
8782
try await GIDSignIn.sharedInstance.disconnect()
88-
try await messaging.deleteToken()
89-
try Auth.auth().signOut()
9083
}
9184

9285
func link(uid: String, email: String) async throws {

Firebase/functions/src/user/delete.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
11
import { onCall, HttpsError } from "firebase-functions/v2/https";
22
import * as admin from "firebase-admin";
3+
import * as logger from "firebase-functions/logger";
34

45
export const deleteUserFirestoreData = onCall({
56
cors: true,
67
maxInstances: 10,
78
region: "asia-northeast3"
89
},
910
async (request) => {
10-
if (!request.auth) throw new HttpsError("unauthenticated", "로그인 필요");
11-
const uid = request.data.uid;
12-
if (!uid) throw new HttpsError("invalid-argument", "uid 필요");
11+
if (!request.auth?.uid) {
12+
logger.error("deleteUserFirestoreData called without authenticated uid", {
13+
auth: request.auth ?? null
14+
});
15+
throw new HttpsError("unauthenticated", "로그인 필요");
16+
}
17+
18+
const uid = request.auth.uid;
1319

1420
try {
1521
const userDocRef = admin.firestore().doc(`users/${uid}`);

0 commit comments

Comments
 (0)