diff --git a/ILSANG_ADMIN_WIDGET/Provider.swift b/ILSANG_ADMIN_WIDGET/Provider.swift index 76ff7da..d93d6cb 100644 --- a/ILSANG_ADMIN_WIDGET/Provider.swift +++ b/ILSANG_ADMIN_WIDGET/Provider.swift @@ -74,7 +74,7 @@ extension Provider { } private func checkPrdServerStatus() async -> Bool { - let url = "http://43.202.229.190:9091/api/admin/quest?page=0&creatorRole=ADMIN&size=10" + let url = "http://52.79.126.243:8881/api/admin/quest?page=0&creatorRole=ADMIN&size=10" let result: Result = await Network.request(url: url) switch result { case .success: @@ -85,7 +85,7 @@ extension Provider { } private func checkDevServerStatus() async -> Bool { - let url = "http://43.202.229.190:9090/api/admin/quest?page=0&creatorRole=ADMIN&size=10" + let url = "http://52.79.126.243:8880/api/admin/quest?page=0&creatorRole=ADMIN&size=10" let result: Result = await Network.request(url: url) switch result { case .success: @@ -96,7 +96,7 @@ extension Provider { } private func getReportedChallengeCount() async -> Int { - let url = "http://43.202.229.190:9091/api/admin/report?page=0&size=10" + let url = "http://52.79.126.243:8881/api/admin/report?page=0&size=10" let result: Result = await Network.request(url: url) switch result { case .success(let res): diff --git a/MatQ_Admin.xcodeproj/project.pbxproj b/MatQ_Admin.xcodeproj/project.pbxproj index f5be24d..ab187c5 100644 --- a/MatQ_Admin.xcodeproj/project.pbxproj +++ b/MatQ_Admin.xcodeproj/project.pbxproj @@ -12,10 +12,11 @@ 601048712C652FC20028662D /* UIImage++.swift in Sources */ = {isa = PBXBuildFile; fileRef = 601048702C652FC20028662D /* UIImage++.swift */; }; 603F25702D119D4E00A088E2 /* SearchTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 603F256F2D119D4E00A088E2 /* SearchTextField.swift */; }; 603F25722D11C94B00A088E2 /* XpStat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 603F25712D11C94B00A088E2 /* XpStat.swift */; }; + 605334592D30164000599159 /* KeychainHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 605334582D30164000599159 /* KeychainHelper.swift */; }; + 6053345A2D30170100599159 /* KeychainHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 605334582D30164000599159 /* KeychainHelper.swift */; }; 60631DF52C84E63B005643B1 /* NetworkService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60DB54B02C7272E400AEDFE9 /* NetworkService.swift */; }; 60631DF62C84E647005643B1 /* NetworkError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60DA570B2B94124F00EDAF30 /* NetworkError.swift */; }; 60631DF72C84E64F005643B1 /* CommonResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60F27DEE2C45F1A900711A53 /* CommonResponse.swift */; }; - 60631DF92C8590CA005643B1 /* Alamofire in Frameworks */ = {isa = PBXBuildFile; productRef = 60631DF82C8590CA005643B1 /* Alamofire */; }; 60631DFC2C85A08C005643B1 /* HttpHeaderField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60DA57122B94152000EDAF30 /* HttpHeaderField.swift */; }; 60631DFD2C85A0CA005643B1 /* Bundle++.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60E696B42B98C583009DD235 /* Bundle++.swift */; }; 60631DFE2C85A0DC005643B1 /* PrivateToken.plist in Resources */ = {isa = PBXBuildFile; fileRef = 60E696B62B98C5AD009DD235 /* PrivateToken.plist */; }; @@ -29,6 +30,8 @@ 606329952C748E10000F4513 /* DeleteChallengeUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 606329942C748E10000F4513 /* DeleteChallengeUseCase.swift */; }; 6073BEBD2CA2B8DA00072FF9 /* PutQuestUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6073BEBC2CA2B8DA00072FF9 /* PutQuestUseCase.swift */; }; 6073BEC22CA31C3000072FF9 /* String++.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6073BEC12CA31C3000072FF9 /* String++.swift */; }; + 60856CE12D1DA9A90048747E /* AuthTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60856CE02D1DA9A90048747E /* AuthTarget.swift */; }; + 60856CE52D1DAADC0048747E /* AuthRepository.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60856CE42D1DAADC0048747E /* AuthRepository.swift */; }; 608EBF8A2C38709800B862CC /* AppInject.swift in Sources */ = {isa = PBXBuildFile; fileRef = 608EBF892C38709800B862CC /* AppInject.swift */; }; 608EBF8D2C38716100B862CC /* QuestMainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 608EBF8C2C38716100B862CC /* QuestMainView.swift */; }; 608EBF8F2C38716900B862CC /* QuestDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 608EBF8E2C38716900B862CC /* QuestDetailView.swift */; }; @@ -67,6 +70,11 @@ 6094290E2CC95DC600C8D5D6 /* GetChallengeUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60DB54D02C73C1F900AEDFE9 /* GetChallengeUseCase.swift */; }; 609429102CC95E6200C8D5D6 /* PutQuestUseCase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6073BEBC2CA2B8DA00072FF9 /* PutQuestUseCase.swift */; }; 609429122CC960C700C8D5D6 /* Alamofire in Frameworks */ = {isa = PBXBuildFile; productRef = 609429112CC960C700C8D5D6 /* Alamofire */; }; + 60A766E02D1DBA1B00928824 /* AuthModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60856CE22D1DA9C50048747E /* AuthModel.swift */; }; + 60A766E12D1DBA1C00928824 /* AuthModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60856CE22D1DA9C50048747E /* AuthModel.swift */; }; + 60A766E42D1DBB6900928824 /* Alamofire in Frameworks */ = {isa = PBXBuildFile; productRef = 60A766E32D1DBB6900928824 /* Alamofire */; }; + 60A766E52D1DBC0100928824 /* AuthModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60856CE22D1DA9C50048747E /* AuthModel.swift */; }; + 60A766E62D1DBC0C00928824 /* AuthTarget.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60856CE02D1DA9A90048747E /* AuthTarget.swift */; }; 60C0F4342CD1413700DB19AB /* QuestRepositoryInterface.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60F27DF62C46031A00711A53 /* QuestRepositoryInterface.swift */; }; 60C0F4352CD1415F00DB19AB /* UIImage++.swift in Sources */ = {isa = PBXBuildFile; fileRef = 601048702C652FC20028662D /* UIImage++.swift */; }; 60C0F4372CD1FA6500DB19AB /* DeleteChallengeUseCaseTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 60C0F4362CD1FA6500DB19AB /* DeleteChallengeUseCaseTests.swift */; }; @@ -179,12 +187,16 @@ 601048702C652FC20028662D /* UIImage++.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIImage++.swift"; sourceTree = ""; }; 603F256F2D119D4E00A088E2 /* SearchTextField.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchTextField.swift; sourceTree = ""; }; 603F25712D11C94B00A088E2 /* XpStat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XpStat.swift; sourceTree = ""; }; + 605334582D30164000599159 /* KeychainHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeychainHelper.swift; sourceTree = ""; }; 60631E042C85E4CC005643B1 /* Network.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Network.swift; sourceTree = ""; }; 60631E072C85E761005643B1 /* Provider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Provider.swift; sourceTree = ""; }; 606329922C7483E8000F4513 /* PatchChallengeUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PatchChallengeUseCase.swift; sourceTree = ""; }; 606329942C748E10000F4513 /* DeleteChallengeUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeleteChallengeUseCase.swift; sourceTree = ""; }; 6073BEBC2CA2B8DA00072FF9 /* PutQuestUseCase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PutQuestUseCase.swift; sourceTree = ""; }; 6073BEC12CA31C3000072FF9 /* String++.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String++.swift"; sourceTree = ""; }; + 60856CE02D1DA9A90048747E /* AuthTarget.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthTarget.swift; sourceTree = ""; }; + 60856CE22D1DA9C50048747E /* AuthModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthModel.swift; sourceTree = ""; }; + 60856CE42D1DAADC0048747E /* AuthRepository.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthRepository.swift; sourceTree = ""; }; 608EBF892C38709800B862CC /* AppInject.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppInject.swift; sourceTree = ""; }; 608EBF8C2C38716100B862CC /* QuestMainView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuestMainView.swift; sourceTree = ""; }; 608EBF8E2C38716900B862CC /* QuestDetailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuestDetailView.swift; sourceTree = ""; }; @@ -277,7 +289,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 60631DF92C8590CA005643B1 /* Alamofire in Frameworks */, + 60A766E42D1DBB6900928824 /* Alamofire in Frameworks */, 60ECFBCA2C8459800020E24B /* SwiftUI.framework in Frameworks */, 60ECFBC82C8459800020E24B /* WidgetKit.framework in Frameworks */, ); @@ -299,6 +311,7 @@ isa = PBXGroup; children = ( 60004FEF2C662365009AECF2 /* ImageDataTransferable.swift */, + 605334582D30164000599159 /* KeychainHelper.swift */, ); path = Helper; sourceTree = ""; @@ -382,6 +395,7 @@ 60F27DF82C46039400711A53 /* QuestRepository.swift */, 60DB54CC2C73C12600AEDFE9 /* ChallengeRepository.swift */, 60DB54B72C73788900AEDFE9 /* ImageRepository.swift */, + 60856CE42D1DAADC0048747E /* AuthRepository.swift */, ); path = Repository; sourceTree = ""; @@ -467,6 +481,7 @@ 60F27DEC2C45691F00711A53 /* QuestModel.swift */, 60DB54C62C73BC4D00AEDFE9 /* ChallengeModel.swift */, 60E696BA2B9A1BFE009DD235 /* ImageModel.swift */, + 60856CE22D1DA9C50048747E /* AuthModel.swift */, ); path = DTO; sourceTree = ""; @@ -510,6 +525,7 @@ isa = PBXGroup; children = ( 60E696BC2B9A1ED4009DD235 /* ImageTarget.swift */, + 60856CE02D1DA9A90048747E /* AuthTarget.swift */, 60F27DF02C45FADC00711A53 /* QuestTarget.swift */, 60DB54CA2C73BF5500AEDFE9 /* ChallengeTarget.swift */, ); @@ -675,7 +691,7 @@ ); name = MatQ_Admin_Extension; packageProductDependencies = ( - 60631DF82C8590CA005643B1 /* Alamofire */, + 60A766E32D1DBB6900928824 /* Alamofire */, ); productName = ILSANG_ADMIN_WIDGETExtension; productReference = 60ECFBC62C8459800020E24B /* MatQ_Admin_Extension.appex */; @@ -788,6 +804,7 @@ 6094290D2CC95D1700C8D5D6 /* ImageTarget.swift in Sources */, 6094290B2CC95D1200C8D5D6 /* ChallengeTarget.swift in Sources */, 60C0F43A2CD1FB8C00DB19AB /* MockChallengeRepository.swift in Sources */, + 60A766E62D1DBC0C00928824 /* AuthTarget.swift in Sources */, 609428E92CC9361400C8D5D6 /* Quest.swift in Sources */, 6094290E2CC95DC600C8D5D6 /* GetChallengeUseCase.swift in Sources */, 609428FC2CC9390300C8D5D6 /* Bundle++.swift in Sources */, @@ -808,6 +825,7 @@ 609428FE2CC939B700C8D5D6 /* PutQuestUseCaseTests.swift in Sources */, 609428FF2CC93A5500C8D5D6 /* Challenge.swift in Sources */, 609428EE2CC9365000C8D5D6 /* ChallengeModel.swift in Sources */, + 60A766E52D1DBC0100928824 /* AuthModel.swift in Sources */, 609428F82CC938CB00C8D5D6 /* Endpoint.swift in Sources */, 609428EB2CC9363700C8D5D6 /* ChallengeRepositoryInterface.swift in Sources */, 609429082CC95D0C00C8D5D6 /* HttpHeaderField.swift in Sources */, @@ -832,7 +850,9 @@ 60ECFBD12C8459800020E24B /* AppIntent.swift in Sources */, 60631E022C85A37A005643B1 /* Quest.swift in Sources */, 60631DFC2C85A08C005643B1 /* HttpHeaderField.swift in Sources */, + 6053345A2D30170100599159 /* KeychainHelper.swift in Sources */, 60631DF62C84E647005643B1 /* NetworkError.swift in Sources */, + 60A766E02D1DBA1B00928824 /* AuthModel.swift in Sources */, 60631DF72C84E64F005643B1 /* CommonResponse.swift in Sources */, 60631E012C85A347005643B1 /* ChallengeModel.swift in Sources */, ); @@ -852,6 +872,7 @@ 60E696B12B98958C009DD235 /* ButtonLabelComponent.swift in Sources */, 60F27DF12C45FADC00711A53 /* QuestTarget.swift in Sources */, 60DB54C72C73BC4D00AEDFE9 /* ChallengeModel.swift in Sources */, + 60856CE12D1DA9A90048747E /* AuthTarget.swift in Sources */, E5DD827B2B350A9E00A026C2 /* NavigationStackRouter.swift in Sources */, 603F25722D11C94B00A088E2 /* XpStat.swift in Sources */, 60F27DFD2C461B2B00711A53 /* DeleteQuestUseCase.swift in Sources */, @@ -861,6 +882,7 @@ 60E696AF2B97CDE2009DD235 /* DomainAssembly.swift in Sources */, 608EBF932C3872D700B862CC /* Quest.swift in Sources */, 60DA570C2B94124F00EDAF30 /* NetworkError.swift in Sources */, + 60A766E12D1DBA1C00928824 /* AuthModel.swift in Sources */, 60F27DED2C45691F00711A53 /* QuestModel.swift in Sources */, 60DB54CD2C73C12600AEDFE9 /* ChallengeRepository.swift in Sources */, 608EBF8D2C38716100B862CC /* QuestMainView.swift in Sources */, @@ -893,11 +915,13 @@ 60DB54C32C73940100AEDFE9 /* ManageDetailViewModel.swift in Sources */, 60E696BD2B9A1ED4009DD235 /* ImageTarget.swift in Sources */, 60E696BF2B9A1FC1009DD235 /* ImageDataSource.swift in Sources */, + 605334592D30164000599159 /* KeychainHelper.swift in Sources */, 608EBF992C39166F00B862CC /* TextFieldComponent.swift in Sources */, 60F27DF52C4602DD00711A53 /* GetQuestUseCase.swift in Sources */, 60DB54C52C73BBD600AEDFE9 /* ChallengeDataSource.swift in Sources */, 60DB54CF2C73C15200AEDFE9 /* ChallengeRepositoryInterface.swift in Sources */, 608EBF8A2C38709800B862CC /* AppInject.swift in Sources */, + 60856CE52D1DAADC0048747E /* AuthRepository.swift in Sources */, E5DD82762B3509F600A026C2 /* InfoComponent.swift in Sources */, E5DD825A2B34DCCA00A026C2 /* MatQ_AdminApp.swift in Sources */, 60DB54B82C73788900AEDFE9 /* ImageRepository.swift in Sources */, @@ -1185,7 +1209,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.1.7; + MARKETING_VERSION = 1.2.0; ONLY_ACTIVE_ARCH = YES; PRODUCT_BUNDLE_IDENTIFIER = "com.teamfair.MatQ-Admin"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -1229,7 +1253,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.1.7; + MARKETING_VERSION = 1.2.0; ONLY_ACTIVE_ARCH = YES; PRODUCT_BUNDLE_IDENTIFIER = "com.teamfair.MatQ-Admin"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -1305,12 +1329,12 @@ /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ - 60631DF82C8590CA005643B1 /* Alamofire */ = { + 609429112CC960C700C8D5D6 /* Alamofire */ = { isa = XCSwiftPackageProductDependency; package = E5C503992B467FFD00F47989 /* XCRemoteSwiftPackageReference "Alamofire" */; productName = Alamofire; }; - 609429112CC960C700C8D5D6 /* Alamofire */ = { + 60A766E32D1DBB6900928824 /* Alamofire */ = { isa = XCSwiftPackageProductDependency; package = E5C503992B467FFD00F47989 /* XCRemoteSwiftPackageReference "Alamofire" */; productName = Alamofire; diff --git a/MatQ_Admin.xcodeproj/project.xcworkspace/xcuserdata/leejinhee.xcuserdatad/UserInterfaceState.xcuserstate b/MatQ_Admin.xcodeproj/project.xcworkspace/xcuserdata/leejinhee.xcuserdatad/UserInterfaceState.xcuserstate index 9280ba3..9dab1c1 100644 Binary files a/MatQ_Admin.xcodeproj/project.xcworkspace/xcuserdata/leejinhee.xcuserdatad/UserInterfaceState.xcuserstate and b/MatQ_Admin.xcodeproj/project.xcworkspace/xcuserdata/leejinhee.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/MatQ_Admin.xcodeproj/xcuserdata/leejinhee.xcuserdatad/xcschemes/xcschememanagement.plist b/MatQ_Admin.xcodeproj/xcuserdata/leejinhee.xcuserdatad/xcschemes/xcschememanagement.plist index cc2ed60..4482537 100644 --- a/MatQ_Admin.xcodeproj/xcuserdata/leejinhee.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/MatQ_Admin.xcodeproj/xcuserdata/leejinhee.xcuserdatad/xcschemes/xcschememanagement.plist @@ -29,21 +29,42 @@ isShown orderHint - 3 + 4 Sample-iOS (Playground) 2.xcscheme + + isShown + + orderHint + 6 + + Sample-iOS (Playground) 3.xcscheme isShown orderHint 5 + Sample-iOS (Playground) 4.xcscheme + + isShown + + orderHint + 7 + + Sample-iOS (Playground) 5.xcscheme + + isShown + + orderHint + 8 + Sample-iOS (Playground).xcscheme isShown orderHint - 4 + 3 SuppressBuildableAutocreation diff --git a/MatQ_Admin/App/DI/DataAssembly.swift b/MatQ_Admin/App/DI/DataAssembly.swift index 7b556ac..0db6938 100644 --- a/MatQ_Admin/App/DI/DataAssembly.swift +++ b/MatQ_Admin/App/DI/DataAssembly.swift @@ -41,11 +41,20 @@ final class DataAssembly: Assembly { // MARK: - Repository + +#if DEBUG container.register(QuestRepositoryInterface.self, factory: { ( resolver: Resolver ) -> QuestRepository in return .init(questDataSource: resolver.resolve(QuestDataSourceInterface.self)!) }).inObjectScope(.container) +#else + container.register(QuestRepositoryInterface.self, factory: { ( + resolver: Resolver + ) -> MockQuestRepository in + return .init(questDataSource: resolver.resolve(QuestDataSourceInterface.self)!) + }).inObjectScope(.container) +#endif container.register(ChallengeRepositoryInterface.self, factory: { ( resolver: Resolver diff --git a/MatQ_Admin/App/Extension/Bundle++.swift b/MatQ_Admin/App/Extension/Bundle++.swift index a7e5660..6b1644b 100644 --- a/MatQ_Admin/App/Extension/Bundle++.swift +++ b/MatQ_Admin/App/Extension/Bundle++.swift @@ -7,6 +7,7 @@ import Foundation +/// Deprecated extension Bundle { var adminAuthToken: String { guard let filePath = Bundle.main.path(forResource: "PrivateToken", ofType: "plist"), diff --git a/MatQ_Admin/App/Helper/KeychainHelper.swift b/MatQ_Admin/App/Helper/KeychainHelper.swift new file mode 100644 index 0000000..c9ca0ec --- /dev/null +++ b/MatQ_Admin/App/Helper/KeychainHelper.swift @@ -0,0 +1,43 @@ +// +// KeychainHelper.swift +// MatQ_Admin +// +// Created by Lee Jinhee on 1/9/25. +// + +import Foundation +import Security + +class KeychainHelper { + static let shared = KeychainHelper() + + private init() {} + + func save(key: String, value: String) { + let data = value.data(using: .utf8)! + let query = [ + kSecClass: kSecClassGenericPassword, + kSecAttrAccount: key, + kSecValueData: data + ] as CFDictionary + + SecItemDelete(query) // 기존 데이터 제거 + SecItemAdd(query, nil) + } + + func retrieve(key: String) -> String? { + let query = [ + kSecClass: kSecClassGenericPassword, + kSecAttrAccount: key, + kSecReturnData: true, + kSecMatchLimit: kSecMatchLimitOne + ] as CFDictionary + + var result: AnyObject? + if SecItemCopyMatching(query, &result) == errSecSuccess, + let data = result as? Data { + return String(data: data, encoding: .utf8) + } + return nil + } +} diff --git a/MatQ_Admin/Data/Network/API/DTO/AuthModel.swift b/MatQ_Admin/Data/Network/API/DTO/AuthModel.swift new file mode 100644 index 0000000..007096f --- /dev/null +++ b/MatQ_Admin/Data/Network/API/DTO/AuthModel.swift @@ -0,0 +1,20 @@ +// +// AuthModel.swift +// MatQ_Admin +// +// Created by Lee Jinhee on 12/27/24. +// + +import Foundation + +struct PostAuthRequest: Encodable { + let userType: String = "ADMIN" + let accessToken: String = "accessToken" + let refreshToken: String = "refreshToken" + let email: String = "admin" + let channel: String = "KAKAO" +} + +struct PostAuthResponse: Decodable { + let authorization: String? +} diff --git a/MatQ_Admin/Data/Network/API/DTO/QuestModel.swift b/MatQ_Admin/Data/Network/API/DTO/QuestModel.swift index 599c1e6..47f3599 100644 --- a/MatQ_Admin/Data/Network/API/DTO/QuestModel.swift +++ b/MatQ_Admin/Data/Network/API/DTO/QuestModel.swift @@ -11,7 +11,7 @@ import UIKit // MARK: - 퀘스트 목록 조회 struct GetQuestRequest: Encodable { let page: Int - let size: Int = 50 + let size: Int = 60 let creatorRole: String = "ADMIN" } diff --git a/MatQ_Admin/Data/Network/API/Target/AuthTarget.swift b/MatQ_Admin/Data/Network/API/Target/AuthTarget.swift new file mode 100644 index 0000000..8b0705a --- /dev/null +++ b/MatQ_Admin/Data/Network/API/Target/AuthTarget.swift @@ -0,0 +1,37 @@ +// +// AuthTarget.swift +// MatQ_Admin +// +// Created by Lee Jinhee on 12/27/24. +// + +import Alamofire +import Foundation + +enum AuthTarget { + case login(PostAuthRequest) +} + +extension AuthTarget: TargetType { + var baseURL: String { + return URL.makeEndPoint(.open(endPoint: "")) + } + + var method: HTTPMethod { + switch self { + case .login: return .post + } + } + + var path: String? { + switch self { + case .login: return "login" + } + } + + var parameters: RequestParams { + switch self { + case .login(let request): return .body(request) + } + } +} diff --git a/MatQ_Admin/Data/Network/Base/HttpHeaderField.swift b/MatQ_Admin/Data/Network/Base/HttpHeaderField.swift index 7ef0858..a6ae092 100644 --- a/MatQ_Admin/Data/Network/Base/HttpHeaderField.swift +++ b/MatQ_Admin/Data/Network/Base/HttpHeaderField.swift @@ -16,7 +16,7 @@ enum HTTPHeaderField: String { var value: String { switch self { case .authentication: - return Bundle.main.adminAuthToken + return KeychainHelper.shared.retrieve(key: "AdminAuthToken") ?? "" case .contentType: return type.json.rawValue case .acceptType: @@ -27,4 +27,8 @@ enum HTTPHeaderField: String { enum type: String { case json = "application/json" } + + static func updateAuthToken(_ newToken: String) { + KeychainHelper.shared.save(key: "AdminAuthToken", value: newToken) + } } diff --git a/MatQ_Admin/Data/Network/Base/NetworkError.swift b/MatQ_Admin/Data/Network/Base/NetworkError.swift index 95f0fd6..1a8face 100644 --- a/MatQ_Admin/Data/Network/Base/NetworkError.swift +++ b/MatQ_Admin/Data/Network/Base/NetworkError.swift @@ -23,6 +23,7 @@ enum NetworkError: Error, Equatable { case decodingError case serverError case invalidImageData + case invalidResponse case error((Int, String, String)) // StatusCode, Status, ErrMessage case unknownError diff --git a/MatQ_Admin/Data/Repository/AuthRepository.swift b/MatQ_Admin/Data/Repository/AuthRepository.swift new file mode 100644 index 0000000..ea9da04 --- /dev/null +++ b/MatQ_Admin/Data/Repository/AuthRepository.swift @@ -0,0 +1,42 @@ +// +// AuthRepository.swift +// MatQ_Admin +// +// Created by Lee Jinhee on 12/27/24. +// + +import Alamofire +import Combine + +protocol AuthRepositoryInterface { + func postAuth(request: PostAuthRequest) -> AnyPublisher +} + +final class AuthRepository: AuthRepositoryInterface { + private let networkService: NetworkServiceInterface + + init(networkService: NetworkServiceInterface) { + self.networkService = networkService + } + + func postAuth(request: PostAuthRequest) -> AnyPublisher { + networkService.request(AuthTarget.login(request), as: Response.self) + .tryMap { response in + dump(response) + guard let token = response.data.authorization else { + throw NetworkError.invalidResponse // 에러 처리 + } + // Keychain에 토큰 저장 + // print(token) + KeychainHelper.shared.save(key: "AdminAuthToken", value: token) + } + .mapError { error -> NetworkError in + if let networkError = error as? NetworkError { + return networkError + } else { + return .unknownError + } + } + .eraseToAnyPublisher() + } +} diff --git a/MatQ_Admin/Presentation/View/Quest/QuestMainView.swift b/MatQ_Admin/Presentation/View/Quest/QuestMainView.swift index 5e7a429..a633cd5 100644 --- a/MatQ_Admin/Presentation/View/Quest/QuestMainView.swift +++ b/MatQ_Admin/Presentation/View/Quest/QuestMainView.swift @@ -21,10 +21,18 @@ struct QuestMainView: View { switch vm.viewState { case .empty: - Text("불러올 퀘스트가 없어요!") - .font(.callout) - .foregroundStyle(.textSecondary) - .frame(maxHeight: .infinity) + VStack { + Text("불러올 퀘스트가 없어요!") + .font(.callout) + .foregroundStyle(.textSecondary) + Button { + vm.getQuestList(page: 0) + } label: { + Text("재시도") + } + } + .frame(maxHeight: .infinity) + case .loading: ProgressView().frame(maxHeight: .infinity) case .loaded: @@ -42,10 +50,7 @@ struct QuestMainView: View { .padding(.bottom, 8) } .background(.bgSecondary) - .task { - vm.getQuestList(page: 0) - } - .alert(isPresented: $vm.showingErrorAlert) { + .alert(isPresented: $vm.showingAlert) { Alert(title: Text("Error"), message: Text(vm.errorMessage), dismissButton: .default(Text("OK"))) } } diff --git a/MatQ_Admin/Presentation/View/Quest/QuestMainViewModel.swift b/MatQ_Admin/Presentation/View/Quest/QuestMainViewModel.swift index e83e118..28fd82c 100644 --- a/MatQ_Admin/Presentation/View/Quest/QuestMainViewModel.swift +++ b/MatQ_Admin/Presentation/View/Quest/QuestMainViewModel.swift @@ -67,6 +67,21 @@ final class QuestMainViewModel: QuestMainViewModelInput, QuestMainViewModelOutpu self?.errorMessage = errorMessage self?.showingErrorAlert = true }.store(in: &cancellables) + + AuthRepository(networkService: NetworkService()).postAuth(request: PostAuthRequest()) + .sink(receiveCompletion: { [weak self] completion in + switch completion { + case .finished: + print("Authorization token saved successfully.") + case .failure(let error): + print("Failed with error: \(error.localizedDescription)") + } + }, receiveValue: { _ in + print("Authorization token receiveValue") + }) + .store(in: &cancellables) + + getQuestList(page: 0) } func getQuestList(page: Int) {