Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

로그인 api 연동 #7

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion Projects/App/Sources/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@ final class AppDelegate: UIResponder, UIApplicationDelegate {

assembler = Assembler([
KeychainAssembly(),
PresentationAssembly()
PresentationAssembly(),
DataSourceAssembly(),
RepositoryAssembly(),
UseCaseAssembly()
], container: AppDelegate.container)
return true
}
Expand Down
5 changes: 5 additions & 0 deletions Projects/App/Support/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>API_BASE_URL</key>
<string>$(API_BASE_URL)</string>
<key>AppIdentifierPrefix</key>
Expand Down
3 changes: 0 additions & 3 deletions Projects/Core/Sources/JwtStore/JwtStore.swift
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
public enum KeychainType: String {
case accessToken = "ACCESS-TOKEN"
case refreshToken = "REFRESH-TOKEN"
case accessExpiresAt = "ACCESS-EXPIRED-AT"
case refreshExpiresAt = "REFRESH-EXPIRED-AT"
}

public protocol Keychain {
Expand Down
6 changes: 6 additions & 0 deletions Projects/Core/Sources/Steps/EmailLoginStep.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import RxFlow

public enum EmailLoginStep: Step {
case emailLoginisRequired
case tabIsRequired
}
47 changes: 47 additions & 0 deletions Projects/Data/Sources/Auth/DataSource/API/AuthAPI.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import Moya
import Domain
import AppNetwork

enum AuthAPI {
case login(LoginRequestQuery)
case signup(SignupRequestQuery)
}

extension AuthAPI: EmotingAPI {
typealias ErrorType = Error

var domain: EmotingDomain {
.auth
}

var urlPath: String {
switch self {
case .login:
return "/login"
case .signup:
return "/signup"
}
}

var method: Method {
return .post
}

var task: Task {
switch self {
case let .login(req):
return .requestJSONEncodable(req)

case let .signup(req):
return .requestJSONEncodable(req)
}
}

var jwtTokenType: JwtTokenType {
return .none
}

var errorMap: [Int: ErrorType]? {
return nil
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import RxSwift
import Domain
import AppNetwork

protocol RemoteAuthDataSource {
func login(req: LoginRequestQuery) -> Single<TokenDTO>
func signup(req: SignupRequestQuery) -> Completable
}

final class RemoteAuthDataSourceImpl: RemoteBaseDataSource<AuthAPI>, RemoteAuthDataSource {
func login(req: LoginRequestQuery) -> Single<TokenDTO> {
return request(.login(req))
.map(TokenDTO.self)
}

func signup(req: SignupRequestQuery) -> Completable {
return request(.signup(req))
.asCompletable()
}

}
19 changes: 19 additions & 0 deletions Projects/Data/Sources/Auth/Repository/AuthRepositoryImpl.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import RxSwift
import Domain

struct AuthRepositoryImpl: AuthRepository {
private let remoteAuthDataSource: any RemoteAuthDataSource

init(remoteAuthDataSource: any RemoteAuthDataSource) {
self.remoteAuthDataSource = remoteAuthDataSource
}

func login(req: Domain.LoginRequestQuery) -> RxSwift.Completable {
remoteAuthDataSource.login(req: req)
.asCompletable()
}

func signup(req: Domain.SignupRequestQuery) -> RxSwift.Completable {
remoteAuthDataSource.signup(req: req)
}
}
51 changes: 51 additions & 0 deletions Projects/Data/Sources/Base/BaseRemoteDataSource.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import Moya
import Domain
import AppNetwork
import Foundation
import RxSwift
import RxMoya
import Core
import Alamofire

class RemoteBaseDataSource<API: EmotingAPI> {
private let keychain: any Keychain

private let provider: MoyaProvider<API>

init(keychain: any Keychain) {
self.keychain = keychain
#if DEBUG
self.provider = MoyaProvider<API>(plugins: [JwtPlugin(keychain: keychain), MoyaLogginPlugin()])
#else
self.provider = MoyaProvider<API>(plugins: [JwtPlugin(keychain: keychain)])
#endif
}

func request(_ api: API) -> Single<Response> {
return .create { single in
var disposables: [Disposable] = []
disposables.append(
self.defaultRequest(api)
.subscribe(
onSuccess: { single(.success($0)) },
onFailure: { single(.failure($0)) }
)
)
return Disposables.create(disposables)
}
}
}

private extension RemoteBaseDataSource {
func defaultRequest(_ api: API) -> Single<Response> {
return provider.rx
.request(api)
.timeout(.seconds(120), scheduler: MainScheduler.asyncInstance)
.catch { error in
guard let code = (error as? MoyaError)?.response?.statusCode else {
return .error(error)
}
return .error(api.errorMap?[code] ?? error)
}
}
}
18 changes: 18 additions & 0 deletions Projects/Data/Sources/DI/DataSourceAssembly.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import Foundation
import Swinject
import Core
import Domain

public final class DataSourceAssembly: Assembly {
public init() {}

private let keychain = { (resolver: Resolver) in
resolver.resolve(Keychain.self)!
}

public func assemble(container: Container) {
container.register(RemoteAuthDataSource.self) { resolver in
RemoteAuthDataSourceImpl(keychain: self.keychain(resolver))
}
}
}
13 changes: 13 additions & 0 deletions Projects/Data/Sources/DI/RepositoryAssembly.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import Foundation
import Swinject
import Domain

public final class RepositoryAssembly: Assembly {
public init() {}

public func assemble(container: Container) {
container.register(AuthRepository.self) { resolver in
AuthRepositoryImpl(remoteAuthDataSource: resolver.resolve(RemoteAuthDataSource.self)!)
}
}
}
21 changes: 21 additions & 0 deletions Projects/Data/Sources/DI/UseCaseAssembly.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import Foundation
import Swinject
import Domain

public final class UseCaseAssembly: Assembly {
public init() {}

public func assemble(container: Container) {
// Auth
container.register(LoginUseCase.self) { resolver in
LoginUseCase(
authRepository: resolver.resolve(AuthRepository.self)!
)
}
container.register(SignupUseCase.self) { resolver in
SignupUseCase(
authRepository: resolver.resolve(AuthRepository.self)!
)
}
}
}
1 change: 0 additions & 1 deletion Projects/Data/Sources/TempFile.swift

This file was deleted.

11 changes: 11 additions & 0 deletions Projects/Domain/Sources/Auth/Parameter/LoginRequestQuery.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import Foundation

public struct LoginRequestQuery: Encodable {
public let email: String
public let password: String

public init(email: String, password: String) {
self.email = email
self.password = password
}
}
15 changes: 15 additions & 0 deletions Projects/Domain/Sources/Auth/Parameter/SignupRequestQuery.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import Foundation

public struct SignupRequestQuery: Encodable {
public let email: String
public let password: String
public let nickname: String
public let age: Int

public init(email: String, password: String, nickname: String, age: Int) {
self.email = email
self.password = password
self.nickname = nickname
self.age = age
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import RxSwift

public protocol AuthRepository {
func login(req: LoginRequestQuery) -> Completable
func signup(req: SignupRequestQuery) -> Completable
}
13 changes: 13 additions & 0 deletions Projects/Domain/Sources/Auth/UseCase/LoginUseCase.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import RxSwift

public struct LoginUseCase {
public init(authRepository: AuthRepository) {
self.authRepository = authRepository
}

private let authRepository: AuthRepository

public func execute(req: LoginRequestQuery) -> Completable {
return authRepository.login(req: req)
}
}
13 changes: 13 additions & 0 deletions Projects/Domain/Sources/Auth/UseCase/SignupUseCase.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import RxSwift

public struct SignupUseCase {
public init(authRepository: AuthRepository) {
self.authRepository = authRepository
}

private let authRepository: AuthRepository

public func execute(req: SignupRequestQuery) -> Completable {
return authRepository.signup(req: req)
}
}
1 change: 0 additions & 1 deletion Projects/Domain/Sources/TempFile.swift

This file was deleted.

4 changes: 2 additions & 2 deletions Projects/Flow/Sources/AgeSignupFlow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ private extension AgeSignupFlow {
}

return .one(flowContributor: .contribute(
withNextPresentable: rootViewController,
withNextStepper: rootViewController.reactor
withNextPresentable: profilSignupFlow,
withNextStepper: OneStepper(withSingleStep: ProfilSignupStep.profilSignupIsRequired)
))
}
}
2 changes: 1 addition & 1 deletion Projects/Flow/Sources/AppStepper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ public final class AppStepper: Stepper {
public init() {}

public var initialStep: Step {
return AppStep.testIsRequired
return AppStep.onboardingIsRequired
}
}
40 changes: 40 additions & 0 deletions Projects/Flow/Sources/EmailLoginFlow.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import UIKit
import RxFlow
import RxSwift
import Core
import Swinject
import Presentation

public final class EmailLoginFlow: Flow {
public let container: Container
public var root: Presentable {
return self.rootViewController
}

public let rootViewController: EmailLoginViewController

public init(container: Container) {
self.container = container
self.rootViewController = container.resolve(EmailLoginViewController.self)!
}

public func navigate(to step: Step) -> FlowContributors {
guard let step = step as? EmailLoginStep else { return .none }

switch step {
case .emailLoginisRequired:
return navigationToEmailLogin()
case .tabIsRequired:
return .end(forwardToParentFlowWithStep: OauthLoginStep.tabIsRequired)
}
}
}

private extension EmailLoginFlow {
func navigationToEmailLogin() -> FlowContributors {
return .one(flowContributor: .contribute(
withNextPresentable: rootViewController,
withNextStepper: rootViewController.reactor
))
}
}
15 changes: 7 additions & 8 deletions Projects/Flow/Sources/OauthLoginFlow.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public final class OauthLoginFlow: Flow {
case .emailSignupIsRequired:
return navigationToEmailSignup()
case .tabIsRequired:
return .end(forwardToParentFlowWithStep: OnboardingStep.tabIsRequired)
return .end(forwardToParentFlowWithStep: AppStep.tabIsRequired)
}
}
}
Expand All @@ -50,16 +50,15 @@ private extension OauthLoginFlow {
}

func navigationToEmailLogin() -> FlowContributors {
let emailLoginViewController = container.resolve(EmailLoginViewController.self)!
let emailLoginFlow = EmailLoginFlow(container: container)

self.rootViewController.pushViewController(
emailLoginViewController,
animated: true
)
Flows.use(emailLoginFlow, when: .created) { (root) in
self.rootViewController.pushViewController(root, animated: true)
}

return .one(flowContributor: .contribute(
withNextPresentable: emailLoginViewController,
withNextStepper: emailLoginViewController.reactor
withNextPresentable: emailLoginFlow,
withNextStepper: OneStepper(withSingleStep: EmailLoginStep.emailLoginisRequired)
))
}

Expand Down
Loading