Skip to content
Merged
14 changes: 14 additions & 0 deletions RecorDream-iOS/Projects/Core/Sources/Constants/C.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// C.swift
// RD-CoreTests
//
// Created by 정은희 on 2022/12/04.
// Copyright © 2022 RecorDream. All rights reserved.
//

public struct C {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기서는 축약어를 사용하기 보다는 AuthConstants 나 LoginConstants와 같이 어떤 정보를 상수로 묶어 두셨는지 네이밍해주시면 좋을 것 같습니다 !!

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

반영하겠습니다!

public static let KAKAO_APP_KEY = "000e1e31f022f98fbe16c76ab287abd1"
public static let accessToken = "accessToken"
public static let refreshToken = "refreshToken"
public static let nickname = "nickname"
}
14 changes: 14 additions & 0 deletions RecorDream-iOS/Projects/Core/Sources/Constants/Key.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// Key.swift
// RD-Core
//
// Created by 정은희 on 2022/12/05.
// Copyright © 2022 RecorDream. All rights reserved.
//

public enum Key: String {
case platform = "key.platform"
case userToken = "key.userToken"
case accessToken = "key.accessToken"
case nickname = "key.nickname"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
//
// UserDefaultManager.swift
// RD-Core
//
// Created by 정은희 on 2022/12/05.
// Copyright © 2022 RecorDream. All rights reserved.
//

import Foundation

public protocol UserDefaultManager {
static func set(value: Any, keyPath: Key.RawValue)
static func string(key: Key) -> String?
static func int(key: Key) -> Int?
static func remove(key: Key)
static func clearUserData()
}
Comment on lines +11 to +17
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저는 PropertyWrapper를 이용했었는데 이 방식도 좋네요!!


public class DefaultUserDefaultManager: UserDefaultManager {
public static func set(value: Any, keyPath: Key.RawValue) {
UserDefaults.standard.setValue(value, forKeyPath: keyPath)
}
public static func string(key: Key) -> String? {
return UserDefaults.standard.string(forKey: key.rawValue)
}
public static func int(key: Key) -> Int? {
return UserDefaults.standard.integer(forKey: key.rawValue)
}
public static func remove(key: Key) {
UserDefaults.standard.removeObject(forKey: key.rawValue)
}
public static func clearUserData() {
self.remove(key: .platform)
self.remove(key: .userToken)
self.remove(key: .accessToken)
self.remove(key: .nickname)
Comment on lines +33 to +36
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

casIterable을 채택해서 allcases로 지워주는 방법도 있을 것 같습니다~~! 취향 차이인 것 같아여

Comment on lines +19 to +36
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

구웃ㅎㅎㅎ !!

}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//
// DefaultAuthRepository.swift
// Data
//
// Created by 정은희 on 2022/12/04.
// Copyright © 2022 RecorDream. All rights reserved.
//

import Foundation

import Domain
import RD_Network

import RxSwift

public final class DefaultAuthRepository {

private let authService: AuthService
private let disposeBag = DisposeBag()

init(authService: AuthService) {
self.authService = authService
}
}

extension DefaultAuthRepository: AuthRepository {
public func requestAuth(request: AuthRequest) -> RxSwift.Observable<AuthEntity?> {
return Observable.create { observer in
self.authService.login(kakaoToken: request.kakaoToken, appleToken: request.appleToken, fcmToken: request.fcmToken)
.subscribe(onNext: { response in
guard let response = response else { return }
observer.onNext(.init(duplicated: response.duplicated, accessToken: response.accessToken, refreshToken: response.refreshToken))
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기서는 transform 파일에서 toDomain 메서드를 구현해줘도 좋을 것 같습니다!

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

반영하겠습니다!

}, onError: { err in
observer.onError(err)
})
.disposed(by: self.disposeBag)
return Disposables.create()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//
// AuthEntity.swift
// Domain
//
// Created by 정은희 on 2022/12/04.
// Copyright © 2022 RecorDream. All rights reserved.
//

public struct AuthEntity: Codable {
public let duplicated: Bool
public let accessToken: String
public let refreshToken: String

public init(duplicated: Bool, accessToken: String, refreshToken: String) {
self.duplicated = duplicated
self.accessToken = accessToken
self.refreshToken = refreshToken
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//
// AuthRequest.swift
// Domain
//
// Created by 정은희 on 2022/12/05.
// Copyright © 2022 RecorDream. All rights reserved.
//

import Foundation

public struct AuthRequest: Codable {
public var kakaoToken: String? = nil
public var appleToken: String? = nil
public let fcmToken: String

public init(kakaoToken: String?, appleToken: String?, fcmToken: String) {
self.kakaoToken = kakaoToken
self.appleToken = appleToken
self.fcmToken = fcmToken
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// AuthRepository.swift
// Domain
//
// Created by 정은희 on 2022/12/04.
// Copyright © 2022 RecorDream. All rights reserved.
//

import RxSwift

public protocol AuthRepository {
func requestAuth(request: AuthRequest) -> Observable<AuthEntity?>
}
49 changes: 49 additions & 0 deletions RecorDream-iOS/Projects/Domain/Sources/UseCases/AuthUseCase.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//
// AuthUseCase.swift
// Domain
//
// Created by 정은희 on 2022/12/05.
// Copyright © 2022 RecorDream. All rights reserved.
//

import Foundation

import RD_Core

import RxSwift

public protocol AuthUseCase {
func login(request: AuthRequest)

var authSuccess: PublishSubject<AuthEntity> { get set }
var authFail: PublishSubject<Error> { get set }
}

public final class DefaultAuthUseCase {
private let repository: AuthRepository
private let disposeBag = DisposeBag()

public var authSuccess = PublishSubject<AuthEntity>()
public var authFail = PublishSubject<Error>()

init(repository: AuthRepository) {
self.repository = repository
}
}

extension DefaultAuthUseCase: AuthUseCase {
public func login(request: AuthRequest) {
self.repository.requestAuth(request: request)
.filter { $0 != nil }
.subscribe(onNext: { [weak self] entity in
guard let self = self else { return }
guard let entity = entity else {
return }
DefaultUserDefaultManager.set(value: entity.accessToken, keyPath: C.accessToken)
DefaultUserDefaultManager.set(value: entity.refreshToken, keyPath: C.refreshToken)
self.authSuccess.onNext(entity)
}, onError: { err in
self.authFail.onNext(err)
}).disposed(by: disposeBag)
Comment on lines +37 to +47
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

요 부분에서 필요하다면 response가 nil로 오는 경우에 대한 처리를 할 수도 있을 것 같네요! nil인 경우에 authFail에 넥스트 이벤트를 보내줄 수 있곘네요~~

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

반영하겠습니다!

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,10 @@ public enum RDDSKitAsset {
}
public enum Images {
public static let icnMicTitle = RDDSKitImages(name: "icn_mic_title")
public static let kakaotalk = RDDSKitImages(name: "Kakaotalk")
public static let icnEdit = RDDSKitImages(name: "icn_edit")
public static let icnMypage = RDDSKitImages(name: "icn_mypage")
public static let apple = RDDSKitImages(name: "apple")
public static let backgroundBlue = RDDSKitImages(name: "background_blue")
public static let backgroundPink = RDDSKitImages(name: "background_pink")
public static let backgroundPurple = RDDSKitImages(name: "background_purple")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"images" : [
{
"filename" : "Kakaotalk.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "[email protected]",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "[email protected]",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "original"
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"images" : [
{
"filename" : "apple.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "[email protected]",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "[email protected]",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "original"
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//
// RDLoginButton.swift
// RD-DSKit
//
// Created by 정은희 on 2022/12/01.
// Copyright © 2022 RecorDream. All rights reserved.
//

import UIKit

import SnapKit

public class RDLoginButton: UIButton {
public enum PlatformType: String {
case kakao = "kakao"
case apple = "apple"
}

public let iconImageView: UIImageView = {
let iv = UIImageView()
iv.image = UIImage()
iv.contentMode = .scaleAspectFit
return iv
}()

// MARK: - Initialization
public convenience init(platform: PlatformType, title: String) {
self.init(frame: .zero)

self.setupView(at: platform, for: title)
self.setupConstraint()
}
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}

// MARK: - Extensions
extension RDLoginButton {
private func setupView(at platform: PlatformType, for title: String) {
switch platform {
case .kakao:
self.iconImageView.image = RDDSKitAsset.Images.kakaotalk.image
case .apple:
self.iconImageView.image = RDDSKitAsset.Images.apple.image
}

self.backgroundColor = .white.withAlphaComponent(0.05)
self.makeRoundedWithBorder(radius: 12, borderColor: UIColor(white: 1.0, alpha: 0.1).cgColor)
self.setTitle(title, for: .normal)
self.titleLabel?.font = RDDSKitFontFamily.Pretendard.regular.font(size: 14)
self.titleLabel?.textAlignment = .center
self.titleLabel?.textColor = .white

self.addSubview(iconImageView)
}
private func setupConstraint() {
self.iconImageView.snp.makeConstraints { make in
make.leading.equalToSuperview().offset(24)
make.centerY.equalToSuperview()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//
// AuthResponse.swift
// RD-Network
//
// Created by 정은희 on 2022/12/04.
// Copyright © 2022 RecorDream. All rights reserved.
//

import Foundation

public struct AuthResponse: Codable {
public let duplicated: Bool
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

혹시 duplicated는 어떤 정보를 나타내는 걸까요? 이미 로그인 중이라는 뜻인감..

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

현재 서버 쪽에서 하나의 API로 로그인과 회원가입을 동시에 수행하도록 구현되어 있는데요, (자세한 사항은 아래와 같음)

  • 클라에서는 공통적으로 한 번에 보내면 → 회원가입이 안 되어 있다면 회원가입 수행, 되어 있다면 로그인 수행 → 기존 유저인지의 여부를 bool 값으로 보내줌
  • 이걸 쓰지 않고 UserDefault 에 저장해둔 값의 유무로 토큰의 상태를 static하게 판별하도록 했는데(= SplashVC 68번째 줄), PR 답변 쓰면서 정리하다 보니까 어떻게 사용할 지 정리가 되네요... ㅎㅅㅎ

SplashVC TODO 주석 부분 구현할 때 해당 내용 추가하겠습니다!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

적어놓으신 내용을 바탕으로 생각해봤는데, 저도 userDefault에 저장해둔 값으로 판단하기보다는 서버에서 넘어온 값으로 판단하는게 정확할 것 같다는 생각이 듭니다 ~~! 앱에 저장된 userDefault 값이 실수로 제거될 수도 있고.. ㅇ.ㅇ... 여러 오류의 가능성이 있을 것 같다는 생각?? 네이밍도 더 명확하게 변경하는게 좋을 것 같아요 ~~

public let accessToken: String
public let refreshToken: String

enum CodingKeys: String, CodingKey {
case duplicated = "isAlreadyUser"
case accessToken, refreshToken
}
}
Loading