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 1 commit
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
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))
}
}
}
15 changes: 15 additions & 0 deletions Projects/Data/Sources/DI/RepositoryAssembly.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import Foundation
import Swinject
import Domain

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

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

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

// swiftlint:disable function_body_length
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)!
)
}
}
// swiftlint:enable function_body_length
}
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.

45 changes: 45 additions & 0 deletions Projects/Modules/AppNetwork/Sources/Plugin/EmotingAPI.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import Foundation
import Moya

public protocol EmotingAPI: TargetType, JwtAuthorizable {
associatedtype ErrorType: Error
var domain: EmotingDomain { get }
var urlPath: String { get }
var errorMap: [Int: ErrorType]? { get }
}

public extension EmotingAPI {
var baseURL: URL {
URL(
string: "http://52.79.170.221:8080"
) ?? URL(string: "https://www.google.com")!
}

var path: String {
domain.asURLString + urlPath
}

var headers: [String: String]? {
["Content-Type": "application/json"]
}

var validationType: ValidationType {
return .successCodes
}
}

public enum EmotingDomain: String {
case auth
}

extension EmotingDomain {
var asURLString: String {
"/\(self.rawValue)"
}
}

private class BundleFinder {}

extension Foundation.Bundle {
static let module = Bundle(for: BundleFinder.self)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import Moya

public enum JwtTokenType: String {
case accessToken = "Authorization"
case none
}

public protocol JwtAuthorizable {
var jwtTokenType: JwtTokenType { get }
}
Loading