Skip to content

Commit

Permalink
merge: (#25) 회원 가입 설계
Browse files Browse the repository at this point in the history
  • Loading branch information
khcho0125 authored Sep 7, 2022
2 parents 8da793b + 9517b50 commit 7b400c4
Show file tree
Hide file tree
Showing 40 changed files with 601 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package team.comit.simtong.domain.auth.spi

import team.comit.simtong.domain.auth.usecase.dto.TokenResponse
import team.comit.simtong.domain.user.model.Authority
import java.util.*

Expand All @@ -13,7 +14,6 @@ import java.util.*
**/
interface ReceiveTokenPort {

fun generateAccessToken(userId: UUID, authority: Authority): String
fun generateJsonWebToken(userId: UUID, authority: Authority): TokenResponse

fun generateRefreshToken(userId: UUID, authority: Authority): String
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package team.comit.simtong.domain.auth.usecase.dto

import java.util.Date

/**
*
* Jwt 토큰을 전송하는 TokenResponse
*
* @author Chokyunghyeon
* @date 2022/09/05
* @version 1.0.0
**/
data class TokenResponse(
val accessToken: String,

val accessTokenExp: Date,

val refreshToken: String
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package team.comit.simtong.domain.user.spi

import team.comit.simtong.domain.user.model.User
import java.util.UUID

/**
*
* User에 관한 Query를 요청하는 QueryUserPort
*
* @author Chokyunghyeon
* @date 2022/09/04
* @version 1.0.0
**/
interface QueryUserPort {

fun queryUserById(id: UUID): User

fun queryUserByEmail(email: String): User

fun queryUserByNickName(nickName: String): User

fun existsUserByEmail(email: String): Boolean

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package team.comit.simtong.domain.user.spi

import team.comit.simtong.domain.user.model.User

/**
*
* User의 저장을 요청하는 SaveUserPort
*
* @author Chokyunghyeon
* @date 2022/09/04
* @version 1.0.0
**/
interface SaveUserPort {

fun saveUser(user: User): User

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package team.comit.simtong.domain.user.usecase

import team.comit.simtong.domain.auth.spi.ReceiveTokenPort
import team.comit.simtong.domain.auth.usecase.dto.TokenResponse
import team.comit.simtong.domain.user.dto.DomainSignUpRequest
import team.comit.simtong.domain.user.policy.SignUpPolicy
import team.comit.simtong.domain.user.spi.SaveUserPort
import team.comit.simtong.global.annotation.UseCase

/**
*
* 사용자의 회원가입 기능을 담당하는 SignUpUseCase
*
* @author Chokyunghyeon
* @date 2022/09/04
* @version 1.0.0
**/
@UseCase
class SignUpUseCase(
private val receiveTokenPort: ReceiveTokenPort,
private val saveUserPort: SaveUserPort,
private val signUpPolicy: SignUpPolicy
) {

fun execute(request: DomainSignUpRequest): TokenResponse {
val user = saveUserPort.saveUser(signUpPolicy.implement(request))

return receiveTokenPort.generateJsonWebToken(
userId = user.id!!,
authority = user.authority
)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package team.comit.simtong.domain.user.dto

/**
*
* 회원 가입 정보를 전달하는 SignUpRequest
*
* @author Chokyunghyeon
* @date 2022/09/04
* @version 1.0.0
**/
data class DomainSignUpRequest(
val name: String,

val email: String,

val password: String,

val nickname: String?,

val employeeNumber: Int,

val profileImagePath: String?
)
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package team.comit.simtong.domain.user.error

import team.comit.simtong.global.error.ErrorProperty

/**
*
* User에 대해 발생하는 Error를 관리하는 UserErrorCode
*
* @author Chokyunghyeon
* @date 2022/09/04
* @version 1.0.0
**/
enum class UserErrorCode(
private val status: Int,
private val message: String
): ErrorProperty {

ALREADY_USED_EMAIL(409, "이미 사용된 이메일"),

USER_NOT_FOUND(401, "유저를 찾을 수 없음");

override fun status(): Int = status

override fun message(): String = message

}
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package team.comit.simtong.domain.user.exception

import team.comit.simtong.domain.user.error.UserErrorCode
import team.comit.simtong.global.error.BusinessException

/**
*
* Already Used Email Error를 발생시키는 UsedEmailException
*
* @author Chokyunghyeon
* @date 2022/09/04
* @version 1.0.0
**/
class UsedEmailException private constructor(): BusinessException(UserErrorCode.ALREADY_USED_EMAIL) {

companion object {
@JvmField
val EXCEPTION = UsedEmailException()
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package team.comit.simtong.domain.user.exception

import team.comit.simtong.domain.user.error.UserErrorCode
import team.comit.simtong.global.error.BusinessException

/**
*
* User Not Found Error를 발생시키는 UserNotFoundException
*
* @author Chokyunghyeon
* @date 2022/09/04
* @version 1.0.0
**/
class UserNotFoundException private constructor(): BusinessException(UserErrorCode.USER_NOT_FOUND) {

companion object {
@JvmField
val EXCEPTION = UserNotFoundException()
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package team.comit.simtong.domain.user.model

import team.comit.simtong.global.annotation.Aggregate
import java.util.UUID

/**
*
* Root Aggregate를 담당하는 User
*
* @author Chokyunghyeon
* @date 2022/09/04
* @version 1.0.0
**/
@Aggregate
data class User(
val id: UUID?,

val nickname: String,

val name: String,

val email: String,

val password: String,

val employeeNumber: Int,

val authority: Authority,

val adminCode: String?,

val profileImagePath: String
) {

companion object {
const val defaultImage = "" // TODO 기본 프로필 이미지 설정
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package team.comit.simtong.domain.user.policy

import team.comit.simtong.domain.user.dto.DomainSignUpRequest
import team.comit.simtong.domain.user.model.Authority
import team.comit.simtong.domain.user.model.User
import team.comit.simtong.domain.user.spi.CheckEmailPort
import team.comit.simtong.domain.user.spi.CheckEmployeePort
import team.comit.simtong.domain.user.spi.NickNamePort
import team.comit.simtong.domain.user.spi.SecurityPort
import team.comit.simtong.global.annotation.Policy

/**
*
* 회원 가입 정책을 관리하는 SignUpPolicy
*
* @author Chokyunghyeon
* @author kimbeomjin
* @date 2022/09/05
* @version 1.0.0
**/
@Policy
class SignUpPolicy(
private val checkEmployeePort: CheckEmployeePort,
private val checkEmailPort: CheckEmailPort,
private val randomNamePort: NickNamePort,
private val securityPort: SecurityPort
) {

fun implement(request: DomainSignUpRequest): User {

checkEmailPort.checkCertifiedEmail(request.email)
checkEmailPort.checkUsedEmail(request.email)

checkEmployeePort.checkList(request.name, request.employeeNumber)

return User(
id = null,
name = request.name,
email = request.email,
password = securityPort.encode(request.password),
nickname = request.nickname ?: randomNamePort.random(),
employeeNumber = request.employeeNumber,
authority = Authority.ROLE_COMMON,
adminCode = null,
profileImagePath = request.profileImagePath ?: User.defaultImage
)
}
}
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package team.comit.simtong.domain.user.spi

/**
*
* User의 Email 인증 정책을 관리하는 CheckEmailPort
*
* @author Chokyunghyeon
* @date 2022/09/05
* @version 1.0.0
**/
interface CheckEmailPort {

fun checkUsedEmail(email: String)

fun checkCertifiedEmail(email: String)

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package team.comit.simtong.domain.user.spi

interface CheckEmployeePort {

fun checkList(name: String, employeeNumber: Int)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package team.comit.simtong.domain.user.spi

/**
*
* User의 랜덤한 Nickname을 요청하는 RandomNamePort
*
* @author Chokyunghyeon
* @date 2022/09/05
* @version 1.0.0
**/
interface NickNamePort {

fun random(): String

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package team.comit.simtong.domain.user.spi

/**
*
* 비밀번호 암호화를 담당하는 SecurityPort
*
* @author Chokyunghyeon
* @date 2022/09/04
* @version 1.0.0
**/
interface SecurityPort {

fun compare(target: String, encryptedPassword: String): Boolean

fun encode(password: String): String

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package team.comit.simtong.global.annotation

/**
*
* 도메인의 Policy를 나타내는 어노테이션
*
* @author kimbeomjin
* @date 2022/09/07
* @version 1.0.0
**/
@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.CLASS)
annotation class Policy()
Loading

0 comments on commit 7b400c4

Please sign in to comment.