Skip to content

Commit 74b7550

Browse files
authored
Merge pull request #228 from OMZigak/refactor/#225-RemarkProvider
[refactor] authtarget 통합
2 parents 470d850 + f9eaa39 commit 74b7550

File tree

5 files changed

+234
-2
lines changed

5 files changed

+234
-2
lines changed

KkuMulKum.xcodeproj/project.pbxproj

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@
4747
785AE1BE2C2E878600677CA0 /* FirebaseStorageCombine-Community in Frameworks */ = {isa = PBXBuildFile; productRef = 785AE1BD2C2E878600677CA0 /* FirebaseStorageCombine-Community */; };
4848
785AE1C02C2E878600677CA0 /* FirebaseVertexAI-Preview in Frameworks */ = {isa = PBXBuildFile; productRef = 785AE1BF2C2E878600677CA0 /* FirebaseVertexAI-Preview */; };
4949
785AE1D12C3B07A600677CA0 /* PrivacyInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 785AE1D02C3B07A600677CA0 /* PrivacyInfo.plist */; };
50+
789196362C492F8600FF8CDF /* AuthTargetType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 789196352C492F8600FF8CDF /* AuthTargetType.swift */; };
51+
789196382C49697B00FF8CDF /* AuthError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 789196372C49697B00FF8CDF /* AuthError.swift */; };
5052
789196342C486F6B00FF8CDF /* KeychainAccessible.swift in Sources */ = {isa = PBXBuildFile; fileRef = 789196332C486F6B00FF8CDF /* KeychainAccessible.swift */; };
5153
789873322C3D1A7B00435E96 /* LoginViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7898732F2C3D1A7B00435E96 /* LoginViewController.swift */; };
5254
789873332C3D1A7B00435E96 /* LoginViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 789873302C3D1A7B00435E96 /* LoginViewModel.swift */; };
@@ -237,6 +239,8 @@
237239
782B407E2C3E44B7008B0CA7 /* WelcomeViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomeViewModel.swift; sourceTree = "<group>"; };
238240
782B40812C3E4925008B0CA7 /* NicknameViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NicknameViewModel.swift; sourceTree = "<group>"; };
239241
785AE1D02C3B07A600677CA0 /* PrivacyInfo.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = PrivacyInfo.plist; sourceTree = "<group>"; };
242+
789196352C492F8600FF8CDF /* AuthTargetType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthTargetType.swift; sourceTree = "<group>"; };
243+
789196372C49697B00FF8CDF /* AuthError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthError.swift; sourceTree = "<group>"; };
240244
789196332C486F6B00FF8CDF /* KeychainAccessible.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainAccessible.swift; sourceTree = "<group>"; };
241245
7898732F2C3D1A7B00435E96 /* LoginViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoginViewController.swift; sourceTree = "<group>"; };
242246
789873302C3D1A7B00435E96 /* LoginViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoginViewModel.swift; sourceTree = "<group>"; };
@@ -512,6 +516,15 @@
512516
path = ViewModel;
513517
sourceTree = "<group>";
514518
};
519+
789196392C49697F00FF8CDF /* Auth */ = {
520+
isa = PBXGroup;
521+
children = (
522+
789196372C49697B00FF8CDF /* AuthError.swift */,
523+
789196352C492F8600FF8CDF /* AuthTargetType.swift */,
524+
);
525+
path = Auth;
526+
sourceTree = "<group>";
527+
};
515528
789873352C3D1B3000435E96 /* View */ = {
516529
isa = PBXGroup;
517530
children = (
@@ -1120,6 +1133,7 @@
11201133
DDE7D2BE2C470A58005A921F /* TargetType */ = {
11211134
isa = PBXGroup;
11221135
children = (
1136+
789196392C49697F00FF8CDF /* Auth */,
11231137
DDE7D2BF2C470A58005A921F /* LoginTargetType.swift */,
11241138
DDE7D2C02C470A58005A921F /* ProfileTargetType.swift */,
11251139
DDE7D2C12C470A58005A921F /* NicknameTargetType.swift */,
@@ -1700,6 +1714,7 @@
17001714
DD8626622C4606A300E4F980 /* ReadyStatusViewModel.swift in Sources */,
17011715
DD3F9DC22C481ED5008E1FF7 /* MeetingService.swift in Sources */,
17021716
DE6D4D102C3F14D80005584B /* InvitationCodePopUpView.swift in Sources */,
1717+
789196382C49697B00FF8CDF /* AuthError.swift in Sources */,
17031718
A39F2B1B2C47C206008DA5F5 /* SetReadyCompletedViewController.swift in Sources */,
17041719
DDFA50812C4693BD000A62E2 /* ProfileSetupViewController.swift in Sources */,
17051720
DD30721A2C3C011600416D9F /* AddPromiseRequestModel.swift in Sources */,
@@ -1804,6 +1819,7 @@
18041819
DD3976862C41C2AD00E2A4C4 /* HomeView.swift in Sources */,
18051820
DD8626672C4606A300E4F980 /* SetReadyInfoView.swift in Sources */,
18061821
DD41BEFC2C41D54D0095A068 /* TardyPenaltyView.swift in Sources */,
1822+
789196362C492F8600FF8CDF /* AuthTargetType.swift in Sources */,
18071823
789873322C3D1A7B00435E96 /* LoginViewController.swift in Sources */,
18081824
78BD61342C45B4A7005752FD /* AuthService.swift in Sources */,
18091825
DE32D1D22C3BF703006848DF /* LoginUserResponseModel.swift in Sources */,

KkuMulKum/Network/Service/AuthService.swift

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,26 @@
44
//
55
// Created by 이지훈 on 7/14/24.
66
//
7-
87
import Foundation
8+
import Moya
99

1010
protocol AuthServiceType {
1111
func saveAccessToken(_ token: String) -> Bool
1212
func saveRefreshToken(_ token: String) -> Bool
1313
func getAccessToken() -> String?
1414
func getRefreshToken() -> String?
1515
func clearTokens() -> Bool
16+
func performRequest<T: ResponseModelType>(
17+
_ target: AuthTargetType,
18+
completion: @escaping (
19+
Result<T, NetworkError>
20+
) -> Void
21+
)
1622
}
1723

1824
class AuthService: AuthServiceType {
1925
private var keychainService: KeychainService
26+
private let provider = MoyaProvider<AuthTargetType>()
2027

2128
init(keychainService: KeychainService = DefaultKeychainService.shared) {
2229
self.keychainService = keychainService
@@ -45,4 +52,52 @@ class AuthService: AuthServiceType {
4552
keychainService.refreshToken = nil
4653
return keychainService.accessToken == nil && keychainService.refreshToken == nil
4754
}
55+
56+
func performRequest<T: ResponseModelType>(
57+
_ target: AuthTargetType,
58+
completion: @escaping (Result<T, NetworkError>) -> Void
59+
) {
60+
provider.request(target) { result in
61+
switch result {
62+
case .success(let response):
63+
do {
64+
let decodedResponse = try JSONDecoder().decode(
65+
ResponseBodyDTO<T>.self,
66+
from: response.data
67+
)
68+
if decodedResponse.success {
69+
if let data = decodedResponse.data {
70+
completion(.success(data))
71+
} else {
72+
completion(.failure(.decodingError))
73+
}
74+
} else {
75+
let networkError = self.handleErrorResponse(decodedResponse.error)
76+
completion(.failure(networkError))
77+
}
78+
} catch {
79+
completion(.failure(.decodingError))
80+
}
81+
case .failure:
82+
completion(.failure(.networkError))
83+
}
84+
}
85+
}
86+
87+
private func handleErrorResponse(_ error: ErrorResponse?) -> NetworkError {
88+
guard let error = error else {
89+
return .unknownError("Unknown error occurred")
90+
}
91+
92+
switch error.code {
93+
case 40080:
94+
return .invalidImageFormat
95+
case 40081:
96+
return .imageSizeExceeded
97+
case 40420:
98+
return .userNotFound
99+
default:
100+
return .unknownError(error.message)
101+
}
102+
}
48103
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//
2+
// AuthError.swift
3+
// KkuMulKum
4+
//
5+
// Created by 이지훈 on 7/19/24.
6+
//
7+
8+
import Foundation
9+
10+
enum NetworkError: Error {
11+
case invalidImageFormat
12+
case imageSizeExceeded
13+
case userNotFound
14+
case decodingError
15+
case networkError
16+
case unknownError(String)
17+
18+
var message: String {
19+
switch self {
20+
case .invalidImageFormat:
21+
return "이미지 확장자는 jpg, png, webp만 가능합니다."
22+
case .imageSizeExceeded:
23+
return "이미지 사이즈는 5MB를 넘을 수 없습니다."
24+
case .userNotFound:
25+
return "유저를 찾을 수 없습니다."
26+
case .decodingError:
27+
return "데이터 디코딩 중 오류가 발생했습니다."
28+
case .networkError:
29+
return "네트워크 오류가 발생했습니다."
30+
case .unknownError(let message):
31+
return message
32+
}
33+
}
34+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
//
2+
// AuthTargetType.swift
3+
// KkuMulKum
4+
//
5+
// Created by 이지훈 on 7/18/24.
6+
//
7+
8+
import Foundation
9+
10+
import Moya
11+
12+
enum AuthTargetType {
13+
case appleLogin(identityToken: String, fcmToken: String)
14+
case kakaoLogin(accessToken: String, fcmToken: String)
15+
case refreshToken(refreshToken: String)
16+
case updateProfileImage(image: Data, fileName: String, mimeType: String)
17+
case updateName(name: String)
18+
}
19+
20+
extension AuthTargetType: TargetType {
21+
var baseURL: URL {
22+
guard let privacyInfo = Bundle.main.privacyInfo,
23+
let urlString = privacyInfo["BASE_URL"] as? String,
24+
let url = URL(string: urlString) else {
25+
fatalError("Invalid BASE_URL in PrivacyInfo.plist")
26+
}
27+
return url
28+
}
29+
30+
var path: String {
31+
switch self {
32+
case .appleLogin, .kakaoLogin:
33+
return "/api/v1/auth/signin"
34+
case .refreshToken:
35+
return "/api/v1/auth/reissue"
36+
case .updateProfileImage:
37+
return "/api/v1/users/me/image"
38+
case .updateName:
39+
return "/api/v1/users/me/name"
40+
}
41+
}
42+
43+
var method: Moya.Method {
44+
switch self {
45+
case .appleLogin, .kakaoLogin, .refreshToken:
46+
return .post
47+
case .updateProfileImage, .updateName:
48+
return .patch
49+
}
50+
}
51+
52+
var task: Task {
53+
switch self {
54+
case let .appleLogin(_, fcmToken):
55+
return .requestJSONEncodable(SocialLoginRequestModel(provider: "APPLE", fcmToken: fcmToken))
56+
case let .kakaoLogin(_, fcmToken):
57+
return .requestJSONEncodable(SocialLoginRequestModel(provider: "KAKAO", fcmToken: fcmToken))
58+
case .refreshToken:
59+
return .requestPlain
60+
case let .updateProfileImage(imageData, fileName, mimeType):
61+
let formData: [MultipartFormData] = [
62+
MultipartFormData(
63+
provider: .data(imageData),
64+
name: "image",
65+
fileName: fileName,
66+
mimeType: mimeType
67+
)
68+
]
69+
return .uploadMultipart(formData)
70+
case let .updateName(name):
71+
return .requestParameters(
72+
parameters: ["name": name],
73+
encoding: JSONEncoding.default
74+
)
75+
}
76+
}
77+
78+
var headers: [String : String]? {
79+
switch self {
80+
case .appleLogin(let identityToken, _):
81+
return ["Authorization": identityToken, "Content-Type": "application/json"]
82+
case .kakaoLogin(let accessToken, _):
83+
return ["Authorization": accessToken, "Content-Type": "application/json"]
84+
case .refreshToken(let refreshToken):
85+
return ["Authorization": refreshToken, "Content-Type": "application/json"]
86+
case .updateProfileImage:
87+
guard let token = DefaultKeychainService.shared.accessToken else {
88+
return ["Content-Type": "multipart/form-data"]
89+
}
90+
return [
91+
"Authorization": "Bearer \(token)",
92+
"Content-Type": "multipart/form-data"
93+
]
94+
case .updateName:
95+
guard let token = DefaultKeychainService.shared.accessToken else {
96+
fatalError("No access token available")
97+
}
98+
return [
99+
"Content-Type": "application/json",
100+
"Authorization": "Bearer \(token)"
101+
]
102+
}
103+
}
104+
}

KkuMulKum/Source/Onboarding/Profile/ViewModel/ProfileSetupViewModel.swift

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
// Created by 이지훈 on 7/10/24.
66
//
77

8+
89
import UIKit
910

1011
import RxSwift
@@ -25,8 +26,30 @@ class ProfileSetupViewModel {
2526
private let disposeBag = DisposeBag()
2627
private let provider = MoyaProvider<ProfileTargetType>()
2728

28-
init(nickname: String) {
29+
init(nickname: String, authService: AuthServiceType = AuthService()) {
2930
self.nickname = nickname
31+
self.authService = authService
32+
}
33+
34+
func updateProfileImage(_ image: UIImage?) {
35+
profileImage.value = image
36+
isConfirmButtonEnabled.value = image != nil
37+
}
38+
39+
func uploadProfileImage(completion: @escaping (Bool) -> Void) {
40+
print("uploadProfileImage 함수 호출됨")
41+
guard let image = profileImage.value,
42+
let imageData = image.jpegData(compressionQuality: 0.8) else {
43+
print("이미지 변환 실패")
44+
serverResponse.value = "이미지 변환 중 오류가 발생했습니다."
45+
completion(false)
46+
return
47+
}
48+
49+
print("이미지 데이터 크기: \(imageData.count) bytes")
50+
51+
let fileName = "profile_image.jpg"
52+
let mimeType = "image/jpeg"
3053

3154
updateProfileImageTrigger
3255
.withLatestFrom(profileImage)

0 commit comments

Comments
 (0)