diff --git a/Graduating-Server/src/main/kotlin/com/bestswlkh0310/graduating/graduatingserver/api/school/SchoolService.kt b/Graduating-Server/src/main/kotlin/com/bestswlkh0310/graduating/graduatingserver/api/school/SchoolService.kt index a4fd797..3c0320e 100644 --- a/Graduating-Server/src/main/kotlin/com/bestswlkh0310/graduating/graduatingserver/api/school/SchoolService.kt +++ b/Graduating-Server/src/main/kotlin/com/bestswlkh0310/graduating/graduatingserver/api/school/SchoolService.kt @@ -4,6 +4,8 @@ import com.bestswlkh0310.graduating.graduatingserver.core.graduating.GraduatingE import com.bestswlkh0310.graduating.graduatingserver.core.school.SchoolEntity import com.bestswlkh0310.graduating.graduatingserver.core.graduating.GraduatingRepository import com.bestswlkh0310.graduating.graduatingserver.core.school.SchoolRepository +import com.bestswlkh0310.graduating.graduatingserver.global.exception.CustomException +import org.springframework.http.HttpStatus import org.springframework.stereotype.Service @Service @@ -16,6 +18,6 @@ class SchoolService( } fun getGraduating(schoolId: Long): GraduatingEntity { - return graduatingRepository.findBySchoolId(schoolId).firstOrNull()?: throw Exception("404") // TODO: Create CustomException + return graduatingRepository.findBySchoolId(schoolId).firstOrNull()?: throw CustomException(HttpStatus.NOT_FOUND, "Not found graduating school") } } \ No newline at end of file diff --git a/Graduating-Server/src/main/kotlin/com/bestswlkh0310/graduating/graduatingserver/core/user/User.kt b/Graduating-Server/src/main/kotlin/com/bestswlkh0310/graduating/graduatingserver/core/user/User.kt index f46173a..1d25b5d 100644 --- a/Graduating-Server/src/main/kotlin/com/bestswlkh0310/graduating/graduatingserver/core/user/User.kt +++ b/Graduating-Server/src/main/kotlin/com/bestswlkh0310/graduating/graduatingserver/core/user/User.kt @@ -11,7 +11,7 @@ class User( @Column(nullable = false) val username: String, - @Column(nullable = false) + @Column val nickname: String?, @Column(nullable = false) diff --git a/Graduating-Server/src/main/kotlin/com/bestswlkh0310/graduating/graduatingserver/global/exception/CustomExceptionHandler.kt b/Graduating-Server/src/main/kotlin/com/bestswlkh0310/graduating/graduatingserver/global/exception/CustomExceptionHandler.kt index d8f99ec..64ad540 100644 --- a/Graduating-Server/src/main/kotlin/com/bestswlkh0310/graduating/graduatingserver/global/exception/CustomExceptionHandler.kt +++ b/Graduating-Server/src/main/kotlin/com/bestswlkh0310/graduating/graduatingserver/global/exception/CustomExceptionHandler.kt @@ -1,6 +1,7 @@ package com.bestswlkh0310.graduating.graduatingserver.global.exception import com.bestswlkh0310.graduating.graduatingserver.global.ErrorRes +import mu.KLogger import org.springframework.http.HttpStatus import org.springframework.http.ResponseEntity import org.springframework.web.HttpRequestMethodNotSupportedException @@ -10,11 +11,13 @@ import org.springframework.web.context.request.WebRequest import org.springframework.web.servlet.resource.NoResourceFoundException @RestControllerAdvice -class CustomExceptionHandler { +class CustomExceptionHandler( + private val logger: KLogger +) { @ExceptionHandler(CustomException::class) fun handleCustomException(exception: CustomException): ResponseEntity { - exception.printStackTrace() + logger.error("CustomExceptionHandler.CustomException", exception) return createErrorResponse( status = exception.status, message = exception.message @@ -23,7 +26,7 @@ class CustomExceptionHandler { @ExceptionHandler(NoResourceFoundException::class) fun handleNoResourceFound(exception: NoResourceFoundException): ResponseEntity { - exception.printStackTrace() + logger.error("CustomExceptionHandler.NoResourceFoundException", exception) return createErrorResponse( status = HttpStatus.NOT_FOUND, message = HttpStatus.NOT_FOUND.reasonPhrase @@ -32,7 +35,7 @@ class CustomExceptionHandler { @ExceptionHandler(HttpRequestMethodNotSupportedException::class) fun handleHttpRequestMethodNotSupported(exception: HttpRequestMethodNotSupportedException): ResponseEntity { - exception.printStackTrace() + logger.error("CustomExceptionHandler.HttpRequestMethodNotSupportedException", exception) return createErrorResponse( status = HttpStatus.METHOD_NOT_ALLOWED, message = HttpStatus.METHOD_NOT_ALLOWED.reasonPhrase @@ -41,7 +44,7 @@ class CustomExceptionHandler { @ExceptionHandler(Exception::class) fun handleException(exception: Exception, webRequest: WebRequest): ResponseEntity { - exception.printStackTrace() + logger.error("CustomExceptionHandler.Exception", exception) return createErrorResponse( status = HttpStatus.INTERNAL_SERVER_ERROR, message = HttpStatus.INTERNAL_SERVER_ERROR.reasonPhrase, diff --git a/Graduating-Server/src/main/kotlin/com/bestswlkh0310/graduating/graduatingserver/global/exception/ErrorResponseSender.kt b/Graduating-Server/src/main/kotlin/com/bestswlkh0310/graduating/graduatingserver/global/exception/ErrorResponseSender.kt index bf8bdb3..8d40ad5 100644 --- a/Graduating-Server/src/main/kotlin/com/bestswlkh0310/graduating/graduatingserver/global/exception/ErrorResponseSender.kt +++ b/Graduating-Server/src/main/kotlin/com/bestswlkh0310/graduating/graduatingserver/global/exception/ErrorResponseSender.kt @@ -3,6 +3,7 @@ package com.bestswlkh0310.graduating.graduatingserver.global.exception import com.bestswlkh0310.graduating.graduatingserver.global.ErrorRes import com.fasterxml.jackson.databind.ObjectMapper import jakarta.servlet.http.HttpServletResponse +import mu.KLogger import org.springframework.http.HttpStatus import org.springframework.http.MediaType import org.springframework.stereotype.Component @@ -10,7 +11,8 @@ import java.io.IOException @Component class ErrorResponseSender( - private val objectMapper: ObjectMapper + private val objectMapper: ObjectMapper, + private val logger: KLogger ) { fun send(response: HttpServletResponse, customException: CustomException) = @@ -32,7 +34,7 @@ class ErrorResponseSender( ) ) } catch (e: IOException) { - e.printStackTrace() + logger.error("ErrorResponseSender.send", e) } } } \ No newline at end of file diff --git a/Graduating-Server/src/main/kotlin/com/bestswlkh0310/graduating/graduatingserver/global/jwt/JwtExceptionFilter.kt b/Graduating-Server/src/main/kotlin/com/bestswlkh0310/graduating/graduatingserver/global/jwt/JwtExceptionFilter.kt index 4084f7d..8d1f4b2 100644 --- a/Graduating-Server/src/main/kotlin/com/bestswlkh0310/graduating/graduatingserver/global/jwt/JwtExceptionFilter.kt +++ b/Graduating-Server/src/main/kotlin/com/bestswlkh0310/graduating/graduatingserver/global/jwt/JwtExceptionFilter.kt @@ -24,7 +24,6 @@ class JwtExceptionFilter( } catch (exception: CustomException) { sender.send(response, exception) } catch (exception: Exception) { - exception.printStackTrace() sender.send(response, status = HttpStatus.INTERNAL_SERVER_ERROR) } } diff --git a/Graduating-Server/src/main/kotlin/com/bestswlkh0310/graduating/graduatingserver/infra/neis/NeisMealHelper.kt b/Graduating-Server/src/main/kotlin/com/bestswlkh0310/graduating/graduatingserver/infra/neis/NeisMealHelper.kt index a39388d..fd8a9a8 100644 --- a/Graduating-Server/src/main/kotlin/com/bestswlkh0310/graduating/graduatingserver/infra/neis/NeisMealHelper.kt +++ b/Graduating-Server/src/main/kotlin/com/bestswlkh0310/graduating/graduatingserver/infra/neis/NeisMealHelper.kt @@ -5,6 +5,7 @@ import com.bestswlkh0310.graduating.graduatingserver.core.meal.MealEntity import com.bestswlkh0310.graduating.graduatingserver.core.school.SchoolEntity import com.bestswlkh0310.graduating.graduatingserver.core.meal.MealRepository import com.bestswlkh0310.graduating.graduatingserver.core.school.SchoolRepository +import mu.KLogger import org.springframework.beans.factory.annotation.Qualifier import org.springframework.stereotype.Component import org.springframework.web.client.RestClient @@ -16,7 +17,8 @@ class NeisMealHelper( private val neisProperties: NeisProperties, private val mealRepository: MealRepository, @Qualifier("neis") - private val restClient: RestClient + private val restClient: RestClient, + private val logger: KLogger, ) { suspend fun getMeals(school: SchoolEntity): List { @@ -54,7 +56,7 @@ class NeisMealHelper( } result.add(entity) } catch (e: Exception) { - e.printStackTrace() + logger.error("Neis Error") } } } diff --git a/Graduating-Server/src/main/kotlin/com/bestswlkh0310/graduating/graduatingserver/infra/neis/NeisScheduleHelper.kt b/Graduating-Server/src/main/kotlin/com/bestswlkh0310/graduating/graduatingserver/infra/neis/NeisScheduleHelper.kt index 4bfee05..d3fe563 100644 --- a/Graduating-Server/src/main/kotlin/com/bestswlkh0310/graduating/graduatingserver/infra/neis/NeisScheduleHelper.kt +++ b/Graduating-Server/src/main/kotlin/com/bestswlkh0310/graduating/graduatingserver/infra/neis/NeisScheduleHelper.kt @@ -5,6 +5,7 @@ import com.bestswlkh0310.graduating.graduatingserver.core.school.SchoolEntity import com.bestswlkh0310.graduating.graduatingserver.core.school.SchoolType import com.bestswlkh0310.graduating.graduatingserver.core.graduating.GraduatingRepository import com.bestswlkh0310.graduating.graduatingserver.core.school.SchoolRepository +import mu.KLogger import org.apache.commons.csv.CSVFormat import org.apache.commons.csv.CSVParser import org.springframework.beans.factory.annotation.Qualifier @@ -23,7 +24,8 @@ class NeisScheduleHelper( private val graduatingRepository: GraduatingRepository, @Qualifier("neis") private val restClient: RestClient, - private val neisProperties: NeisProperties + private val neisProperties: NeisProperties, + private val logger: KLogger ) { fun importCsv(filePath: String) { @@ -48,7 +50,7 @@ class NeisScheduleHelper( anniversary = LocalDate.parse(v[11], DateTimeFormatter.ofPattern("yyyyMMdd")), ) } catch (e: Exception) { - e.printStackTrace() + logger.error("Neis Error", e) null } }.let { @@ -99,7 +101,7 @@ class NeisScheduleHelper( println("❌ - ${school.name} - 알 수 없음 ${response?.SchoolSchedule}") } } catch (e: Exception) { - e.printStackTrace() + logger.error("Neis Error", e) } return result } diff --git a/Graduating-Server/src/main/kotlin/com/bestswlkh0310/graduating/graduatingserver/infra/oauth2/apple/AppleOAuth2Client.kt b/Graduating-Server/src/main/kotlin/com/bestswlkh0310/graduating/graduatingserver/infra/oauth2/apple/AppleOAuth2Client.kt index c4ef650..ec51887 100644 --- a/Graduating-Server/src/main/kotlin/com/bestswlkh0310/graduating/graduatingserver/infra/oauth2/apple/AppleOAuth2Client.kt +++ b/Graduating-Server/src/main/kotlin/com/bestswlkh0310/graduating/graduatingserver/infra/oauth2/apple/AppleOAuth2Client.kt @@ -73,7 +73,7 @@ class AppleOAuth2Client( val privateKeyInfo = PrivateKeyInfo.getInstance(privateKeyBytes) return converter.getPrivateKey(privateKeyInfo) } catch (e: Exception) { - throw java.lang.RuntimeException("Error converting private key from String", e) + throw CustomException(HttpStatus.INTERNAL_SERVER_ERROR, "Error converting private key from String") } } } \ No newline at end of file diff --git a/Graduating-iOS/Data/Local/Extension/UserDefaultsExt.swift b/Graduating-iOS/Data/Local/Extension/UserDefaultsExt.swift index f57471d..cf92e04 100644 --- a/Graduating-iOS/Data/Local/Extension/UserDefaultsExt.swift +++ b/Graduating-iOS/Data/Local/Extension/UserDefaultsExt.swift @@ -5,4 +5,9 @@ public extension UserDefaults { let appGroupId = "group.hhhello0507.graduating" return UserDefaults(suiteName: appGroupId) ?? .standard } + + var accessToken: String? { + get { self.string(forKey: "accessToken") } + set { self.set(newValue, forKey: "accessToken") } + } } diff --git a/Graduating-iOS/Data/Local/SignInExt.swift b/Graduating-iOS/Data/Local/SignInExt.swift new file mode 100644 index 0000000..5ee6f9b --- /dev/null +++ b/Graduating-iOS/Data/Local/SignInExt.swift @@ -0,0 +1,15 @@ +// +// SignInExt.swift +// Data +// +// Created by hhhello0507 on 10/4/24. +// + +import Foundation +import SignKit + +public extension Sign { + static var me: Sign { + Sign(store: .init(.graduating)) + } +} diff --git a/Graduating-iOS/Data/Network/AuthService.swift b/Graduating-iOS/Data/Network/AuthService.swift index 7622118..77249f0 100644 --- a/Graduating-iOS/Data/Network/AuthService.swift +++ b/Graduating-iOS/Data/Network/AuthService.swift @@ -7,18 +7,20 @@ import MyMoya import Model +import Moya +import Combine -public enum AuthEndpoint { +enum AuthEndpoint { case oauth2SignIn(OAuth2SignInReq) case refresh(RefreshReq) } extension AuthEndpoint: MyTarget { - public var host: String { "auth" } - public var route: Route { + var host: String { "auth" } + var route: Route { switch self { case .oauth2SignIn(let req): - .post("sign-in/auth2") + .post("sign-in/oauth2") .task(req.toJSONParameters()) case .refresh(let req): .post("refresh") @@ -27,4 +29,15 @@ extension AuthEndpoint: MyTarget { } } -//public e +public class AuthService { + public static let shared = AuthService() + let netRunner = DefaultNetRunner() + + public func oauth2SignIn(_ req: OAuth2SignInReq) -> AnyPublisher { + netRunner.deepDive(.oauth2SignIn(req), res: Token.self) + } + + public func refresh(_ req: RefreshReq) -> AnyPublisher { + netRunner.deepDive(.refresh(req), res: Token.self) + } +} diff --git a/Graduating-iOS/Graduating.xcodeproj/project.pbxproj b/Graduating-iOS/Graduating.xcodeproj/project.pbxproj index e427ebe..cea0388 100644 --- a/Graduating-iOS/Graduating.xcodeproj/project.pbxproj +++ b/Graduating-iOS/Graduating.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* Begin PBXBuildFile section */ 25064D392CAEFEFF00181796 /* GoogleSignIn in Frameworks */ = {isa = PBXBuildFile; productRef = 25064D382CAEFEFF00181796 /* GoogleSignIn */; }; 25064D3B2CAEFEFF00181796 /* GoogleSignInSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 25064D3A2CAEFEFF00181796 /* GoogleSignInSwift */; }; + 25064DDB2CAF862D00181796 /* SignKit in Frameworks */ = {isa = PBXBuildFile; productRef = 25064DDA2CAF862D00181796 /* SignKit */; }; 250EAE242C7DE05500D9FF5E /* CombineMoya in Frameworks */ = {isa = PBXBuildFile; productRef = 250EAE232C7DE05500D9FF5E /* CombineMoya */; }; 250EAE262C7DE05500D9FF5E /* Moya in Frameworks */ = {isa = PBXBuildFile; productRef = 250EAE252C7DE05500D9FF5E /* Moya */; }; 250FD0852C74AF100070503B /* CombineMoya in Frameworks */ = {isa = PBXBuildFile; productRef = 250FD0842C74AF100070503B /* CombineMoya */; }; @@ -182,6 +183,7 @@ 250FD0852C74AF100070503B /* CombineMoya in Frameworks */, 25064D392CAEFEFF00181796 /* GoogleSignIn in Frameworks */, 25C962D42C7B07C500EB872E /* libData.a in Frameworks */, + 25064DDB2CAF862D00181796 /* SignKit in Frameworks */, 25C962D12C7B07C000EB872E /* libModel.a in Frameworks */, 253DC2B22C7EBEAC0047C401 /* MyDesignSystem in Frameworks */, 250FD0872C74AF100070503B /* Moya in Frameworks */, @@ -298,6 +300,7 @@ 253DC2B12C7EBEAC0047C401 /* MyDesignSystem */, 25064D382CAEFEFF00181796 /* GoogleSignIn */, 25064D3A2CAEFEFF00181796 /* GoogleSignInSwift */, + 25064DDA2CAF862D00181796 /* SignKit */, ); productName = Graduating; productReference = 2560F1732C746C16007009E2 /* Graduating.app */; @@ -447,6 +450,7 @@ 25C4CCF32C74B30600DB83B3 /* XCRemoteSwiftPackageReference "Then" */, 253DC2B02C7EBEAC0047C401 /* XCRemoteSwiftPackageReference "my-ios-kit" */, 25064D372CAEFEFF00181796 /* XCRemoteSwiftPackageReference "GoogleSignIn-iOS" */, + 25064DD92CAF862D00181796 /* XCRemoteSwiftPackageReference "SignKit" */, ); productRefGroup = 2560F1742C746C16007009E2 /* Products */; projectDirPath = ""; @@ -996,6 +1000,14 @@ minimumVersion = 8.0.0; }; }; + 25064DD92CAF862D00181796 /* XCRemoteSwiftPackageReference "SignKit" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/hhhello0507/SignKit"; + requirement = { + branch = main; + kind = branch; + }; + }; 250FD0832C74AF100070503B /* XCRemoteSwiftPackageReference "Moya" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/Moya/Moya"; @@ -1041,6 +1053,11 @@ package = 25064D372CAEFEFF00181796 /* XCRemoteSwiftPackageReference "GoogleSignIn-iOS" */; productName = GoogleSignInSwift; }; + 25064DDA2CAF862D00181796 /* SignKit */ = { + isa = XCSwiftPackageProductDependency; + package = 25064DD92CAF862D00181796 /* XCRemoteSwiftPackageReference "SignKit" */; + productName = SignKit; + }; 250EAE232C7DE05500D9FF5E /* CombineMoya */ = { isa = XCSwiftPackageProductDependency; package = 250FD0832C74AF100070503B /* XCRemoteSwiftPackageReference "Moya" */; diff --git a/Graduating-iOS/Graduating.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Graduating-iOS/Graduating.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 7665438..bd97e62 100644 --- a/Graduating-iOS/Graduating.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/Graduating-iOS/Graduating.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,5 +1,5 @@ { - "originHash" : "e3c1180a8e38a74c7306c05087a0cb19db9d112d93d960a6d4f87d4ab491fe93", + "originHash" : "86ee7362d835b2c48d70dbdbd539e71a20eddc693570324381092defd335f7d8", "pins" : [ { "identity" : "alamofire", @@ -118,6 +118,15 @@ "version" : "6.7.1" } }, + { + "identity" : "signkit", + "kind" : "remoteSourceControl", + "location" : "https://github.com/hhhello0507/SignKit", + "state" : { + "branch" : "main", + "revision" : "9f1560813ea00a57462ae16074eaee3a67adc233" + } + }, { "identity" : "then", "kind" : "remoteSourceControl", diff --git a/Graduating-iOS/Graduating/Feature/Main/Profile/ProfileObservable.swift b/Graduating-iOS/Graduating/Feature/Main/Profile/ProfileObservable.swift new file mode 100644 index 0000000..c2cee28 --- /dev/null +++ b/Graduating-iOS/Graduating/Feature/Main/Profile/ProfileObservable.swift @@ -0,0 +1,37 @@ +// +// ProfileViewModel.swift +// Graduating +// +// Created by hhhello0507 on 10/4/24. +// + +import Combine +import Model +import Data +import Foundation +import SignKit + +final class ProfileObservable: ObservableObject { + enum Subject { + case signInFailure + } + var subscription = Set() + var subject = PassthroughSubject() + func signIn(code: String, platformType: PlatformType) { + AuthService.shared.oauth2SignIn( + .init(platformType: platformType, code: code) + ) + .sink { + print($0) + } receiveValue: { + Sign.me.login(id: "", password: "", accessToken: $0.accessToken, refreshToken: $0.refreshToken) + } + .store(in: &subscription) + } + + deinit { + subscription.forEach { + $0.cancel() + } + } +} diff --git a/Graduating-iOS/Graduating/Feature/Main/Profile/ProfileView.swift b/Graduating-iOS/Graduating/Feature/Main/Profile/ProfileView.swift index 6753ec7..8138211 100644 --- a/Graduating-iOS/Graduating/Feature/Main/Profile/ProfileView.swift +++ b/Graduating-iOS/Graduating/Feature/Main/Profile/ProfileView.swift @@ -3,14 +3,18 @@ import MyDesignSystem import GoogleSignIn import MyUIKitExt import Model +import Data struct ProfileView: View { @StateObject private var appleObservable = AppleObservable() + @StateObject private var observable = ProfileObservable() @EnvironmentObject private var dialog: DialogProvider @EnvironmentObject private var router: Router + @EnvironmentObject private var appState: AppState @Environment(\.openURL) private var openURL @State private var isSheetPresent: Bool = false + @AppStorage("accessToken") private var accessToken: String? var body: some View { MyTopAppBar.default( @@ -20,10 +24,16 @@ struct ProfileView: View { VStack(spacing: 0) { VStack(spacing: 8) { MyAvatar(nil, type: .larger) - Button { - isSheetPresent = true - } label: { - Text("로그인 하기") + if accessToken == nil { + Button { + isSheetPresent = true + } label: { + Text("로그인 하기") + .foreground(Colors.Label.alternative) + .myFont(.bodyR) + } + } else { + Text("-") .foreground(Colors.Label.alternative) .myFont(.bodyR) } @@ -61,7 +71,7 @@ struct ProfileView: View { VStack(spacing: 10) { AppleSignInButton { appleObservable.signIn { code in - signIn(code: code, platformType: .apple) + observable.signIn(code: code, platformType: .apple) } failureCompletion: { dialog.present( .init(title: "로그인 실패") @@ -72,6 +82,7 @@ struct ProfileView: View { guard let rootViewController = UIApplicationUtil.window?.rootViewController else { return } Task { let result = try await GIDSignIn.sharedInstance.signIn(withPresenting: rootViewController) + guard let code = result.serverAuthCode else { return } } } @@ -82,10 +93,3 @@ struct ProfileView: View { } } } - -// MARK: - Presenter -extension ProfileView { - func signIn(code: String, platformType: PlatformType) { - - } -} diff --git a/Graduating-iOS/Graduating/Feature/Observable/AppState.swift b/Graduating-iOS/Graduating/Feature/Observable/AppState.swift index bd96ab0..3e4a3bd 100644 --- a/Graduating-iOS/Graduating/Feature/Observable/AppState.swift +++ b/Graduating-iOS/Graduating/Feature/Observable/AppState.swift @@ -9,6 +9,7 @@ import Combine import Foundation import Model import Data +import SignKit final class AppState: BaseViewModel { @@ -16,12 +17,12 @@ final class AppState: BaseViewModel { case fetchedGraduating(Graduating) } + var subject = PassthroughSubject() @Published var grade: Int? = UserDefaultsType.grade.value as? Int { didSet { UserDefaultsType.grade.set(grade) } } - // json @Published var school: School? = { guard let json = UserDefaultsType.school.value as? String else { return nil @@ -45,7 +46,6 @@ final class AppState: BaseViewModel { } } @Published var graduatingFetchFailure = false - var subject = PassthroughSubject() func fetchGraduating(id: Int) { SchoolService.shared.getGraduating(id: id) diff --git a/Graduating-iOS/Model/Auth/Token.swift b/Graduating-iOS/Model/Auth/Token.swift new file mode 100644 index 0000000..a6df292 --- /dev/null +++ b/Graduating-iOS/Model/Auth/Token.swift @@ -0,0 +1,18 @@ +// +// Token.swift +// Model +// +// Created by hhhello0507 on 10/4/24. +// + +import Foundation + +public struct Token: ModelProtocol { + public let accessToken: String + public let refreshToken: String + + public init(accessToken: String, refreshToken: String) { + self.accessToken = accessToken + self.refreshToken = refreshToken + } +}