Skip to content

Commit

Permalink
⚡️ :: 로그인 api 연동 및 전체적인 api 설정
Browse files Browse the repository at this point in the history
  • Loading branch information
juyeong525 committed Mar 20, 2024
1 parent 560d532 commit f6332f2
Show file tree
Hide file tree
Showing 26 changed files with 517 additions and 16 deletions.
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
}
}
6 changes: 6 additions & 0 deletions Projects/Domain/Sources/Auth/Repository/AuthRepository.swift
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

0 comments on commit f6332f2

Please sign in to comment.