From 59e6af4702877cca24a77d72a7aec2185e1b51f1 Mon Sep 17 00:00:00 2001 From: soohyeon Date: Mon, 2 Sep 2024 16:52:58 +0900 Subject: [PATCH 1/4] add : user --- .../org/meogo/domain/user/domain/User.kt | 29 +++++++++++++++++++ .../org/meogo/domain/user/domain/UserRole.kt | 7 +++++ .../meogo/domain/user/facade/UserFacade.kt | 21 ++++++++++++++ .../domain/user/repository/UserRepository.kt | 13 +++++++++ 4 files changed, 70 insertions(+) create mode 100644 src/main/kotlin/org/meogo/domain/user/domain/User.kt create mode 100644 src/main/kotlin/org/meogo/domain/user/domain/UserRole.kt create mode 100644 src/main/kotlin/org/meogo/domain/user/facade/UserFacade.kt create mode 100644 src/main/kotlin/org/meogo/domain/user/repository/UserRepository.kt diff --git a/src/main/kotlin/org/meogo/domain/user/domain/User.kt b/src/main/kotlin/org/meogo/domain/user/domain/User.kt new file mode 100644 index 0000000..389e9ee --- /dev/null +++ b/src/main/kotlin/org/meogo/domain/user/domain/User.kt @@ -0,0 +1,29 @@ +package org.meogo.domain.user.domain + +import org.meogo.global.base.BaseUUIDEntity +import java.util.UUID +import javax.persistence.Column +import javax.persistence.Entity +import javax.persistence.EnumType +import javax.persistence.Enumerated + +@Entity +class User( + id: UUID? = null, + + @Column(nullable = false, length = 4) + val name: String, + + @Column(name = "account_id", nullable = false, length = 15, unique = true) + val accountId: String, + + val password: String, + + @Column(name = "enrolled_school", nullable = true) + val enrolledSchool: Int? = 0, + + val profile: String? = null, + + @Enumerated(EnumType.STRING) + val role: UserRole +) : BaseUUIDEntity(id) diff --git a/src/main/kotlin/org/meogo/domain/user/domain/UserRole.kt b/src/main/kotlin/org/meogo/domain/user/domain/UserRole.kt new file mode 100644 index 0000000..e918796 --- /dev/null +++ b/src/main/kotlin/org/meogo/domain/user/domain/UserRole.kt @@ -0,0 +1,7 @@ +package org.meogo.domain.user.domain + +enum class UserRole { + MANAGER, + USER, + ADMIN +} diff --git a/src/main/kotlin/org/meogo/domain/user/facade/UserFacade.kt b/src/main/kotlin/org/meogo/domain/user/facade/UserFacade.kt new file mode 100644 index 0000000..3030f28 --- /dev/null +++ b/src/main/kotlin/org/meogo/domain/user/facade/UserFacade.kt @@ -0,0 +1,21 @@ +package org.meogo.domain.user.facade + +import org.meogo.domain.user.domain.User +import org.meogo.domain.user.exception.UserNotFoundException +import org.meogo.domain.user.repository.UserRepository +import org.springframework.security.core.context.SecurityContextHolder +import org.springframework.stereotype.Component + +@Component +class UserFacade( + private val userRepository: UserRepository +) { + + fun currentUser(): User { + val accountId = SecurityContextHolder.getContext().authentication.name + return getUserByAccountId(accountId) + } + + fun getUserByAccountId(accountId: String): User = + userRepository.findByAccountId(accountId) ?: throw UserNotFoundException +} diff --git a/src/main/kotlin/org/meogo/domain/user/repository/UserRepository.kt b/src/main/kotlin/org/meogo/domain/user/repository/UserRepository.kt new file mode 100644 index 0000000..77972e1 --- /dev/null +++ b/src/main/kotlin/org/meogo/domain/user/repository/UserRepository.kt @@ -0,0 +1,13 @@ +package org.meogo.domain.user.repository + +import org.meogo.domain.user.domain.User +import org.springframework.data.repository.Repository +import java.util.UUID + +interface UserRepository : Repository { + fun save(entity: User): User + + fun findByAccountId(accountId: String): User? + + fun existsByAccountId(accountId: String): Boolean +} From 74fb48d143221392d79654d09129ddad3465df14 Mon Sep 17 00:00:00 2001 From: soohyeon Date: Mon, 2 Sep 2024 16:53:13 +0900 Subject: [PATCH 2/4] add :: userNofFound --- .../meogo/domain/user/exception/UserNotFoundException.kt | 8 ++++++++ .../kotlin/org/meogo/global/error/exception/ErrorCode.kt | 2 ++ 2 files changed, 10 insertions(+) create mode 100644 src/main/kotlin/org/meogo/domain/user/exception/UserNotFoundException.kt diff --git a/src/main/kotlin/org/meogo/domain/user/exception/UserNotFoundException.kt b/src/main/kotlin/org/meogo/domain/user/exception/UserNotFoundException.kt new file mode 100644 index 0000000..d82df77 --- /dev/null +++ b/src/main/kotlin/org/meogo/domain/user/exception/UserNotFoundException.kt @@ -0,0 +1,8 @@ +package org.meogo.domain.user.exception + +import org.meogo.global.error.exception.ErrorCode +import org.meogo.global.error.exception.MeogoException + +object UserNotFoundException : MeogoException( + ErrorCode.USER_NOT_FOUND +) diff --git a/src/main/kotlin/org/meogo/global/error/exception/ErrorCode.kt b/src/main/kotlin/org/meogo/global/error/exception/ErrorCode.kt index 24e843b..8885fdb 100644 --- a/src/main/kotlin/org/meogo/global/error/exception/ErrorCode.kt +++ b/src/main/kotlin/org/meogo/global/error/exception/ErrorCode.kt @@ -7,6 +7,8 @@ enum class ErrorCode( INVALID_TOKEN(401, "Invalid Token"), EXPIRED_TOKEN(401, "Expired Token"), + USER_NOT_FOUND(404, "User not found"), + // Internal Server Error INTERNAL_SERVER_ERROR(500, "Internal Server Error") } From 5b2b8e5c73e75ca26474c71d0746f93f84c40867 Mon Sep 17 00:00:00 2001 From: soohyeon Date: Mon, 2 Sep 2024 17:02:31 +0900 Subject: [PATCH 3/4] modify :: tokenProvider --- .../org/meogo/global/jwt/JwtTokenProvider.kt | 41 +++++++++---------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/src/main/kotlin/org/meogo/global/jwt/JwtTokenProvider.kt b/src/main/kotlin/org/meogo/global/jwt/JwtTokenProvider.kt index 4ab1fa4..d8b82db 100644 --- a/src/main/kotlin/org/meogo/global/jwt/JwtTokenProvider.kt +++ b/src/main/kotlin/org/meogo/global/jwt/JwtTokenProvider.kt @@ -12,7 +12,6 @@ import org.meogo.global.jwt.entity.repository.RefreshTokenRepository import org.meogo.global.jwt.exception.ExpiredTokenException import org.meogo.global.jwt.exception.InvalidJwtException import org.springframework.security.authentication.UsernamePasswordAuthenticationToken -import org.springframework.security.core.userdetails.UserDetails import org.springframework.stereotype.Component import java.util.Date import javax.servlet.http.HttpServletRequest @@ -29,16 +28,17 @@ class JwtTokenProvider( } fun getToken(name: String): TokenResponse { - val accessToken: String = generateAccessToken(name, ACCESS_KEY, jwtProperties.accessExp) - val refreshToken: String = generateRefreshToken(REFRESH_KEY, jwtProperties.refreshExp) + val accessToken = generateAccessToken(name, ACCESS_KEY, jwtProperties.accessExp) + val refreshToken = generateRefreshToken(REFRESH_KEY, jwtProperties.refreshExp) refreshTokenRepository.save( RefreshToken(name, refreshToken, jwtProperties.refreshExp) ) - return TokenResponse(accessToken = accessToken, refreshToken = refreshToken) + return TokenResponse(accessToken, refreshToken) } private fun generateAccessToken(name: String, type: String, expiration: Long): String { - return Jwts.builder().signWith(SignatureAlgorithm.HS256, jwtProperties.secretKey) + return Jwts.builder() + .signWith(SignatureAlgorithm.HS256, jwtProperties.secretKey) .setSubject(name) .setHeaderParam("type", type) .setIssuedAt(Date()) @@ -47,7 +47,8 @@ class JwtTokenProvider( } private fun generateRefreshToken(type: String, ttl: Long): String { - return Jwts.builder().signWith(SignatureAlgorithm.HS256, jwtProperties.secretKey) + return Jwts.builder() + .signWith(SignatureAlgorithm.HS256, jwtProperties.secretKey) .setHeaderParam("type", type) .setIssuedAt(Date()) .setExpiration(Date(System.currentTimeMillis() + ttl * 1000)) @@ -55,40 +56,36 @@ class JwtTokenProvider( } fun resolveToken(request: HttpServletRequest): String? { - val bearer: String? = request.getHeader("Authorization") - + val bearer = request.getHeader("Authorization") return parseToken(bearer) } fun parseToken(bearerToken: String?): String? { return if (bearerToken != null && bearerToken.startsWith("Bearer ")) { - return bearerToken.replace("Bearer ", "") + bearerToken.removePrefix("Bearer ") } else { null } } fun authorization(token: String): UsernamePasswordAuthenticationToken { - return token.let { - val userDetails: UserDetails = authDetailsService.loadUserByUsername(getTokenSubject(token)) - return UsernamePasswordAuthenticationToken(userDetails, "", userDetails.authorities) - } + val userDetails = authDetailsService.loadUserByUsername(getTokenSubject(token)) + return UsernamePasswordAuthenticationToken(userDetails, "", userDetails.authorities) } - private fun getTokenSubject(subject: String): String { - return getTokenBody(subject).subject + private fun getTokenSubject(token: String): String { + return getTokenBody(token).subject } private fun getTokenBody(token: String?): Claims { return try { - Jwts.parser().setSigningKey(jwtProperties.secretKey) - .parseClaimsJws(token).body + Jwts.parser().setSigningKey(jwtProperties.secretKey).parseClaimsJws(token).body + } catch (e: ExpiredJwtException) { + throw ExpiredTokenException + } catch (e: InvalidClaimException) { + throw InvalidJwtException } catch (e: Exception) { - when (e) { - is ExpiredJwtException -> throw ExpiredTokenException - is InvalidClaimException -> throw InvalidJwtException - else -> throw InvalidJwtException - } + throw InvalidJwtException } } } From 2d623fe71b68fa6aac91cf0adffe9d5b82bff5f1 Mon Sep 17 00:00:00 2001 From: soohyeon Date: Mon, 2 Sep 2024 17:25:03 +0900 Subject: [PATCH 4/4] delete :: test --- .../org/meogo/domain/user/facade/UserFacade.kt | 7 ++++--- .../kotlin/org/meogo/MeogoBackendApplicationTests.kt | 12 ------------ 2 files changed, 4 insertions(+), 15 deletions(-) delete mode 100644 src/test/kotlin/org/meogo/MeogoBackendApplicationTests.kt diff --git a/src/main/kotlin/org/meogo/domain/user/facade/UserFacade.kt b/src/main/kotlin/org/meogo/domain/user/facade/UserFacade.kt index 3030f28..55340e2 100644 --- a/src/main/kotlin/org/meogo/domain/user/facade/UserFacade.kt +++ b/src/main/kotlin/org/meogo/domain/user/facade/UserFacade.kt @@ -11,9 +11,10 @@ class UserFacade( private val userRepository: UserRepository ) { - fun currentUser(): User { - val accountId = SecurityContextHolder.getContext().authentication.name - return getUserByAccountId(accountId) + fun currentUser(): User? { + val authentication = SecurityContextHolder.getContext().authentication + val accountId = authentication?.name + return accountId?.let { getUserByAccountId(it) } } fun getUserByAccountId(accountId: String): User = diff --git a/src/test/kotlin/org/meogo/MeogoBackendApplicationTests.kt b/src/test/kotlin/org/meogo/MeogoBackendApplicationTests.kt deleted file mode 100644 index 5bc0b2d..0000000 --- a/src/test/kotlin/org/meogo/MeogoBackendApplicationTests.kt +++ /dev/null @@ -1,12 +0,0 @@ -package org.meogo - -import org.junit.jupiter.api.Test -import org.springframework.boot.test.context.SpringBootTest - -@SpringBootTest -class MeogoBackendApplicationTests { - - @Test - fun contextLoads() { - } -}