Skip to content

Commit 96ece7c

Browse files
committed
refactor: 인증 공급자 로그아웃 책임 분리
1 parent 198c38e commit 96ece7c

7 files changed

Lines changed: 63 additions & 98 deletions

File tree

Application/Data/Sources/Protocol/AuthenticationService.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import Foundation
99

1010
public protocol AuthenticationService {
1111
func signIn() async throws -> AuthDataResponse?
12-
func signOut(_ uid: String) async throws
12+
func signOut()
1313
func deleteAuth(_ uid: String) async throws
1414
func link(uid: String) async throws -> Bool
1515
func unlink(_ uid: String) async throws

Application/Data/Sources/Repository/AuthenticationRepositoryImpl.swift

Lines changed: 9 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -64,29 +64,22 @@ final class AuthenticationRepositoryImpl: AuthenticationRepository {
6464
}
6565

6666
func signOut() async throws {
67-
guard let uid = authService.uid,
68-
let providerID = try await authService.getProviderID(),
69-
let provider = AuthProvider(rawValue: providerID)
70-
else {
67+
let providers = authService.providerIDs.compactMap { AuthProvider(rawValue: $0) }
68+
69+
do {
7170
try await authService.clearCurrentSession()
72-
widgetSnapshotUpdater.clear()
73-
return
71+
} catch {
72+
throw error.toDomain()
7473
}
7574

76-
do {
75+
for provider in providers {
7776
switch provider {
7877
case .apple:
79-
try await appleAuthService.signOut(uid)
78+
appleAuthService.signOut()
8079
case .github:
81-
try await githubAuthService.signOut(uid)
80+
githubAuthService.signOut()
8281
case .google:
83-
try await googleAuthService.signOut(uid)
84-
}
85-
} catch {
86-
if case AuthError.notAuthenticated = error.toDomain() {
87-
try await authService.clearCurrentSession()
88-
} else {
89-
throw error.toDomain()
82+
googleAuthService.signOut()
9083
}
9184
}
9285

Application/Data/Tests/Repository/AuthenticationRepositoryImplTests.swift

Lines changed: 44 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,17 +44,46 @@ struct AuthenticationRepositoryImplTests {
4444
])
4545
}
4646

47-
@Test("Apple 로그아웃은 provider 로그아웃 뒤 위젯 데이터를 정리한다")
48-
func Apple_로그아웃은_provider_로그아웃_뒤_위젯_데이터를_정리한다() async throws {
47+
@Test("로그아웃은 공통 세션 정리 후 연결된 모든 provider 세션과 위젯 데이터를 정리한다")
48+
func 로그아웃은_공통_세션_정리_후_연결된_모든_provider_세션과_위젯_데이터를_정리한다() async throws {
4949
let fixture = makeAuthenticationRepositoryFixture(
5050
uid: "user-id",
51-
providerID: "apple.com"
51+
providerIDs: ["apple.com", "github.com", "google.com"]
5252
)
5353

5454
try await fixture.repository.signOut()
5555

5656
#expect(fixture.events.values() == [
57+
"auth.clearCurrentSession",
5758
"apple.signOut",
59+
"github.signOut",
60+
"google.signOut",
61+
"widget.clear"
62+
])
63+
}
64+
65+
@Test("공통 세션 정리 실패는 provider 세션과 위젯 데이터를 정리하지 않고 오류를 전달한다")
66+
func 공통_세션_정리_실패는_provider_세션과_위젯_데이터를_정리하지_않고_오류를_전달한다() async {
67+
let fixture = makeAuthenticationRepositoryFixture(
68+
uid: "user-id",
69+
providerIDs: ["apple.com", "github.com", "google.com"],
70+
clearCurrentSessionError: AuthenticationRepositoryTestError.clearCurrentSession
71+
)
72+
73+
await #expect(throws: AuthenticationRepositoryTestError.clearCurrentSession) {
74+
try await fixture.repository.signOut()
75+
}
76+
#expect(fixture.events.values() == ["auth.clearCurrentSession"])
77+
}
78+
79+
@Test("provider 목록이 없어도 공통 세션과 위젯 데이터를 정리한다")
80+
func provider_목록이_없어도_공통_세션과_위젯_데이터를_정리한다() async throws {
81+
let fixture = makeAuthenticationRepositoryFixture(uid: "user-id")
82+
83+
try await fixture.repository.signOut()
84+
85+
#expect(fixture.events.values() == [
86+
"auth.clearCurrentSession",
5887
"widget.clear"
5988
])
6089
}
@@ -98,14 +127,16 @@ struct AuthenticationRepositoryImplTests {
98127
providerID: String? = nil,
99128
providerIDs: [String] = [],
100129
signInResult: Result<AuthDataResponse?, Error> = .success(nil),
101-
deleteCurrentUserError: Error? = nil
130+
deleteCurrentUserError: Error? = nil,
131+
clearCurrentSessionError: Error? = nil
102132
) -> AuthenticationRepositoryFixture {
103133
let events = AuthenticationRepositoryEventRecorder()
104134
let authService = AuthenticationRepositoryAuthServiceSpy(
105135
uid: uid,
106136
providerID: providerID,
107137
providerIDs: providerIDs,
108138
deleteCurrentUserError: deleteCurrentUserError,
139+
clearCurrentSessionError: clearCurrentSessionError,
109140
events: events
110141
)
111142
let appleAuthService = AuthenticationServiceSpy(
@@ -149,6 +180,7 @@ private struct AuthenticationRepositoryFixture {
149180
}
150181

151182
private enum AuthenticationRepositoryTestError: Error, Equatable {
183+
case clearCurrentSession
152184
case requiresRecentLogin
153185
}
154186

@@ -171,6 +203,7 @@ final class AuthenticationRepositoryAuthServiceSpy: AuthService {
171203
private let subject: CurrentValueSubject<Bool, Never>
172204
private let providerID: String?
173205
private let deleteCurrentUserError: Error?
206+
private let clearCurrentSessionError: Error?
174207
private let events: AuthenticationRepositoryEventRecorder
175208

176209
var uid: String?
@@ -183,13 +216,15 @@ final class AuthenticationRepositoryAuthServiceSpy: AuthService {
183216
providerIDs: [String],
184217
providerCount: Int? = nil,
185218
deleteCurrentUserError: Error? = nil,
219+
clearCurrentSessionError: Error? = nil,
186220
events: AuthenticationRepositoryEventRecorder
187221
) {
188222
self.uid = uid
189223
self.providerID = providerID
190224
self.providerIDs = providerIDs
191225
self.providerCount = providerCount ?? providerIDs.count
192226
self.deleteCurrentUserError = deleteCurrentUserError
227+
self.clearCurrentSessionError = clearCurrentSessionError
193228
self.events = events
194229
self.subject = CurrentValueSubject<Bool, Never>(uid != nil)
195230
}
@@ -223,10 +258,13 @@ final class AuthenticationRepositoryAuthServiceSpy: AuthService {
223258

224259
func clearCurrentSession() async throws {
225260
events.record("auth.clearCurrentSession")
261+
if let clearCurrentSessionError {
262+
throw clearCurrentSessionError
263+
}
226264
}
227265
}
228266

229-
actor AuthenticationServiceSpy: AuthenticationService {
267+
final class AuthenticationServiceSpy: AuthenticationService {
230268
private let provider: String
231269
private let signInResult: Result<AuthDataResponse?, Error>
232270
private let linkResult: Result<Bool, Error>
@@ -252,7 +290,7 @@ actor AuthenticationServiceSpy: AuthenticationService {
252290
return try signInResult.get()
253291
}
254292

255-
func signOut(_ uid: String) async throws {
293+
func signOut() {
256294
events.record("\(provider).signOut")
257295
}
258296

Application/Infra/Sources/Service/AuthServiceImpl.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,11 @@ final class AuthServiceImpl: AuthService {
119119
func clearCurrentSession() async throws {
120120
logger.info("Clearing current auth session")
121121

122+
if let uid {
123+
let infoRef = store.document(FirestorePath.userData(uid, document: .tokens))
124+
try? await infoRef.updateData(["fcmToken": FieldValue.delete()])
125+
}
126+
122127
do {
123128
if messaging.fcmToken != nil {
124129
try await messaging.deleteToken()

Application/Infra/Sources/Service/SocialLogin/AppleAuthenticationServiceImpl.swift

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@
77

88
import AuthenticationServices
99
import FirebaseAuth
10-
import FirebaseFirestore
11-
import FirebaseMessaging
1210
import Foundation
1311
import Core
1412
import Data
@@ -19,7 +17,6 @@ final class AppleAuthenticationServiceImpl: AuthenticationService {
1917

2018
enum Code: Int {
2119
case signIn = 1
22-
case signOut
2320
case deleteAuth
2421
case link
2522
case unlink
@@ -28,8 +25,6 @@ final class AppleAuthenticationServiceImpl: AuthenticationService {
2825

2926
private var appleSignInDelegate: AppleSignInDelegate?
3027
private var appleSignInContinuation: CheckedContinuation<ASAuthorization, Error>?
31-
private let store = FirebaseConfiguration.firestore
32-
private let messaging = Messaging.messaging()
3328
private var user: User? { Auth.auth().currentUser }
3429
private let logger = Logger(category: "AppleAuthService")
3530

@@ -65,26 +60,7 @@ final class AppleAuthenticationServiceImpl: AuthenticationService {
6560
}
6661
}
6762

68-
func signOut(_ uid: String) async throws {
69-
do {
70-
let infoRef = store.document(FirestorePath.userData(uid, document: .tokens))
71-
try? await infoRef.updateData(["fcmToken": FieldValue.delete()])
72-
73-
if messaging.fcmToken != nil {
74-
do {
75-
try await messaging.deleteToken()
76-
} catch {
77-
logger.error("Failed to delete FCM token while signing out with Apple", error: error)
78-
}
79-
}
80-
81-
try Auth.auth().signOut()
82-
} catch {
83-
logger.error("Failed to sign out with Apple", error: error)
84-
record(error, code: .signOut)
85-
throw error
86-
}
87-
}
63+
func signOut() { }
8864

8965
func deleteAuth(_ uid: String) async throws {
9066
do {

Application/Infra/Sources/Service/SocialLogin/GithubAuthenticationServiceImpl.swift

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
//
77

88
import FirebaseAuth
9-
import FirebaseFirestore
10-
import FirebaseMessaging
119
import Core
1210
import Data
1311

@@ -17,15 +15,12 @@ final class GithubAuthenticationServiceImpl: AuthenticationService {
1715

1816
enum Code: Int {
1917
case signIn = 1
20-
case signOut
2118
case deleteAuth
2219
case link
2320
case unlink
2421
}
2522
}
2623

27-
private let store = FirebaseConfiguration.firestore
28-
private let messaging = Messaging.messaging()
2924
private var user: User? { Auth.auth().currentUser }
3025
private let logger = Logger(category: "GithubAuthService")
3126

@@ -58,26 +53,7 @@ final class GithubAuthenticationServiceImpl: AuthenticationService {
5853
}
5954
}
6055

61-
func signOut(_ uid: String) async throws {
62-
do {
63-
let infoRef = store.document(FirestorePath.userData(uid, document: .tokens))
64-
try? await infoRef.updateData(["fcmToken": FieldValue.delete()])
65-
66-
if messaging.fcmToken != nil {
67-
do {
68-
try await messaging.deleteToken()
69-
} catch {
70-
logger.error("Failed to delete FCM token while signing out with GitHub", error: error)
71-
}
72-
}
73-
74-
try Auth.auth().signOut()
75-
} catch {
76-
logger.error("Failed to sign out with GitHub", error: error)
77-
record(error, code: .signOut)
78-
throw error
79-
}
80-
}
56+
func signOut() { }
8157

8258
func deleteAuth(_ uid: String) async throws {
8359
do {

Application/Infra/Sources/Service/SocialLogin/GoogleAuthenticationServiceImpl.swift

Lines changed: 2 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@
66
//
77

88
import FirebaseAuth
9-
import FirebaseFirestore
10-
import FirebaseMessaging
119
import Foundation
1210
import GoogleSignIn
1311
import Core
@@ -19,15 +17,12 @@ final class GoogleAuthenticationServiceImpl: AuthenticationService {
1917

2018
enum Code: Int {
2119
case signIn = 1
22-
case signOut
2320
case deleteAuth
2421
case link
2522
case unlink
2623
}
2724
}
2825

29-
private let store = FirebaseConfiguration.firestore
30-
private let messaging = Messaging.messaging()
3126
private var user: User? { Auth.auth().currentUser }
3227
private let logger = Logger(category: "GoogleAuthService")
3328

@@ -59,26 +54,8 @@ final class GoogleAuthenticationServiceImpl: AuthenticationService {
5954
}
6055
}
6156

62-
func signOut(_ uid: String) async throws {
63-
do {
64-
let infoRef = store.document(FirestorePath.userData(uid, document: .tokens))
65-
try? await infoRef.updateData(["fcmToken": FieldValue.delete()])
66-
67-
if messaging.fcmToken != nil {
68-
do {
69-
try await messaging.deleteToken()
70-
} catch {
71-
logger.error("Failed to delete FCM token while signing out with Google", error: error)
72-
}
73-
}
74-
75-
try Auth.auth().signOut()
76-
GIDSignIn.sharedInstance.signOut()
77-
} catch {
78-
logger.error("Failed to sign out with Google", error: error)
79-
record(error, code: .signOut)
80-
throw error
81-
}
57+
func signOut() {
58+
GIDSignIn.sharedInstance.signOut()
8259
}
8360

8461
func deleteAuth(_ uid: String) async throws {

0 commit comments

Comments
 (0)