Skip to content

Commit

Permalink
#93 -탈퇴 정책 적용 및 어드민 로그인 추가 (#104)
Browse files Browse the repository at this point in the history
* feat: PersonalInfo 테이블 추가

* feat: 탈퇴 로직 변경

* feat: 탈퇴 스케줄링 설정

* refactor: Welcome 메시지 변경

* refactor: 기본 프로필 설정 및 테스트 수정

* feat: 어드민 로그인 개발

* feat: BadCredentialsException 추가 및 url 설정

* refactor: 기본 데이터 변경

* chore: config 업데이트

* test: user 테스트 수정

* refactor: 익셉션 수정

* test: 테스트 수정

* refactor: 알림 설정 request 변경

* refactor: data.sql 변경 (색상 변경)
  • Loading branch information
sectionr0 authored Aug 24, 2024
1 parent 4212914 commit 108524f
Show file tree
Hide file tree
Showing 39 changed files with 828 additions and 1,927 deletions.
22 changes: 17 additions & 5 deletions app/src/main/kotlin/com/wespot/auth/AuthController.kt
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package com.wespot.auth

import com.wespot.auth.dto.request.AdminLoginRequest
import com.wespot.auth.dto.request.AuthLoginRequest
import com.wespot.auth.dto.request.RefreshTokenRequest
import com.wespot.auth.dto.request.SignUpRequest
import com.wespot.auth.dto.response.SignUpResponse
import com.wespot.auth.dto.response.TokenAndUserDetailResponse
import com.wespot.auth.dto.response.TokenResponse
import com.wespot.auth.port.`in`.AuthUseCase
import com.wespot.auth.service.AuthService
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
Expand All @@ -17,14 +19,14 @@ import org.springframework.web.bind.annotation.RestController
@RestController
@RequestMapping("/api/v1/auth")
class AuthController(
private val authService: AuthService
private val authUseCase: AuthUseCase
) {

@PostMapping("/login")
fun signIn(
@RequestBody request: AuthLoginRequest
): Any {
val response = authService.socialAccess(request)
val response = authUseCase.socialAccess(request)

return if (response is SignUpResponse) {
ResponseEntity.status(HttpStatus.ACCEPTED)
Expand All @@ -39,7 +41,7 @@ class AuthController(
fun signUp(
@RequestBody request: SignUpRequest
): ResponseEntity<TokenAndUserDetailResponse> {
val signUp = authService.signUp(request)
val signUp = authUseCase.signUp(request)

return ResponseEntity.ok()
.body(signUp)
Expand All @@ -49,17 +51,27 @@ class AuthController(
fun reissue(
@RequestBody request: RefreshTokenRequest
): ResponseEntity<TokenResponse> {
val response = authService.reIssueToken(request)
val response = authUseCase.reIssueToken(request)

return ResponseEntity.ok()
.body(response)
}

@PostMapping("/revoke")
fun revoke(): ResponseEntity<Unit> {
authService.revoke()
authUseCase.revoke()

return ResponseEntity.noContent().build()
}

@PostMapping("/admin/login")
fun adminLogin(
@RequestBody request: AdminLoginRequest
): ResponseEntity<TokenResponse> {
val response = authUseCase.adminLogin(request)

return ResponseEntity.ok()
.body(response)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.wespot.auth.schedule

import com.wespot.message.port.`in`.SchedulerUserWithdrawalUseCase
import org.springframework.scheduling.annotation.Scheduled
import org.springframework.stereotype.Service

@Service
class UserWithdrawalScheduler(
private val schedulerUserWithdrawalUseCase: SchedulerUserWithdrawalUseCase
) {

@Scheduled(cron = "0 0 0 * * ?") // 매일 자정에 실행
fun completeUserWithdrawals() {
schedulerUserWithdrawalUseCase.completeUserWithdrawals()
}
}
21 changes: 21 additions & 0 deletions app/src/main/kotlin/com/wespot/common/GlobalExceptionHandler.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import org.springframework.http.HttpStatus
import org.springframework.http.HttpStatusCode
import org.springframework.http.ProblemDetail
import org.springframework.http.ResponseEntity
import org.springframework.security.authentication.BadCredentialsException
import org.springframework.web.bind.MethodArgumentNotValidException
import org.springframework.web.bind.annotation.ControllerAdvice
import org.springframework.web.bind.annotation.ExceptionHandler
Expand Down Expand Up @@ -88,6 +89,26 @@ class GlobalExceptionHandler(
.body(ExceptionResponse.of(ExceptionView.TOAST, problemDetail))
}

@ExceptionHandler(BadCredentialsException::class)
fun handleBadCredentialsException(
exception: BadCredentialsException,
request: HttpServletRequest
): ResponseEntity<ProblemDetail> {
notifyException(false, request, exception)
logger.warn("잘못된 자격 증명입니다.", exception)

val problemDetail = ProblemDetail.forStatusAndDetail(
HttpStatus.UNAUTHORIZED,
exception.message
).apply {
type = ReasonPhraseUtil.createErrorTypeInProblemDetail("/error", HttpStatus.UNAUTHORIZED)
instance = URI.create(request.requestURI)
}

return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
.body(problemDetail)
}

override fun handleMethodArgumentNotValid(
exception: MethodArgumentNotValidException,
headers: HttpHeaders,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class CustomUrlFilter(
private val validUrlPatterns = listOf(
"/health",
"/",
"/api/v1/auth/admin/login",
"/api/v1/auth/kakao/template",
"/api/v1/auth/reissue",
"/api/v1/auth/login",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ class SecurityConfig(
"/api/v1/schools/search",
"/api/v1/check-profanity",
"/api/v1/auth/kakao/template",
"/api/v1/auth/admin/login",
).permitAll()
.anyRequest().authenticated()
}
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/resources/config
2,076 changes: 253 additions & 1,823 deletions app/src/main/resources/data.sql

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions app/src/test/kotlin/com/wespot/auth/fixture/AuthFixture.kt
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package com.wespot.auth.fixture

import com.wespot.auth.dto.AuthData
import com.wespot.auth.dto.request.ProfileRequest
import com.wespot.auth.dto.request.SignUpRequest
import com.wespot.auth.dto.request.ConsentsRequest
import com.wespot.auth.dto.response.TokenResponse
import com.wespot.user.ConsentType
import com.wespot.user.Gender
import com.wespot.user.User
import com.wespot.user.fixture.UserFixture
Expand Down
23 changes: 15 additions & 8 deletions app/src/test/kotlin/com/wespot/auth/service/AuthServiceTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ import com.wespot.user.port.out.FCMPort
import com.wespot.user.port.out.ProfilePort
import com.wespot.user.port.out.UserConsentPort
import com.wespot.user.port.out.UserPort
import com.wespot.user.port.out.RestrictionPort
import com.wespot.auth.port.out.PersonalInfoPort

import io.kotest.assertions.throwables.shouldThrow
import io.kotest.core.spec.style.BehaviorSpec
import io.kotest.matchers.shouldBe
Expand Down Expand Up @@ -55,6 +58,8 @@ class AuthServiceTest : BehaviorSpec({
val refreshTokenService = mockk<RefreshTokenService>()
val eventPublisher = mockk<ApplicationEventPublisher>()
val fcmPort = mockk<FCMPort>()
val restrictionPort = mockk<RestrictionPort>()
val personalInfoPort = mockk<PersonalInfoPort>()

val secretKey = "testSecretKey"

Expand All @@ -74,7 +79,9 @@ class AuthServiceTest : BehaviorSpec({
refreshTokenService = refreshTokenService,
eventPublisher = eventPublisher,
fcmPort = fcmPort,
secretKey = secretKey
secretKey = secretKey,
restrictionPort = restrictionPort,
personalInfoPort = personalInfoPort
)
)

Expand Down Expand Up @@ -152,7 +159,8 @@ class AuthServiceTest : BehaviorSpec({
isVoteNotification = false,
isMarketingNotification = user.userConsent.consentValue ?: false
),
name = user.name
name = user.name,
isProfileChanged = false
)

every { userPort.findByEmail(formatSocialEmail) } returns user
Expand Down Expand Up @@ -201,7 +209,8 @@ class AuthServiceTest : BehaviorSpec({
isVoteNotification = false,
isMarketingNotification = signUpRequest.consents.marketing
),
name = user.name
name = user.name,
isProfileChanged = false
)

every { authService.checkSignUpToken(signUpRequest.signUpToken) } returns authData
Expand Down Expand Up @@ -373,6 +382,8 @@ class AuthServiceTest : BehaviorSpec({
} returns true
every { refreshTokenPort.deleteByUserId(user.id) } just Runs
every { userPort.save(any()) } returns user
UserFixture.setSecurityContextUser(user)
every { userPort.findByEmail(user.email) } returns user

`when`("사용자가 revoke를 호출할 때") {
authService.revoke()
Expand All @@ -390,17 +401,13 @@ class AuthServiceTest : BehaviorSpec({
.revoke(user.social.socialId, user.social.socialRefreshToken) shouldBe true
}

then("refreshToken을 삭제한다") {
refreshTokenPort.deleteByUserId(user.id) shouldBe Unit
}

then("사용자를 withdraw 상태로 저장한다") {
userPort.save(user.withdraw()) shouldBe user
}
}

`when`("잘못된 사용자 ID로 revoke를 호출할 때") {
every { userPort.findById(user.id) } returns null
every { userPort.findByEmail(any()) } returns null

then("CustomException Not Found가 발생해야 한다") {
shouldThrow<CustomException> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import com.wespot.auth.dto.response.KakaoTemplateResponse
import com.wespot.auth.fixture.KakaoTemplateFixture.createKakaoTemplate
import com.wespot.auth.port.out.KakaoTemplatePort
import com.wespot.auth.service.kakao.KakaoTemplateService
import com.wespot.exception.CustomException
import io.kotest.core.spec.style.BehaviorSpec
import io.kotest.matchers.shouldBe
import io.kotest.assertions.throwables.shouldThrow
Expand Down Expand Up @@ -39,8 +40,8 @@ class KakaoTemplateServiceTest : BehaviorSpec({

every { kakaoTemplatePort.getKakaoTemplate(type) } returns null

then("NoSuchElementException 발생해야 한다") {
shouldThrow<NoSuchElementException> {
then("CustomException 발생해야 한다") {
shouldThrow<CustomException> {
kakaoTemplateService.getKakaoTemplate(type)
}.message shouldBe "해당 타입에는 카카오 템플릿이 존재하지 않습니다."
}
Expand Down
2 changes: 1 addition & 1 deletion app/src/test/kotlin/com/wespot/user/domain/UserTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ class UserTest : BehaviorSpec({
`when`("탈퇴를") {
val withdrawUser = user.withdraw()
then("정상적으로 진행한다.") {
withdrawUser.name shouldBe "탈퇴한 유저입니다."
withdrawUser.withdrawalRequestAt shouldNotBe null
}
}
}
Expand Down
52 changes: 40 additions & 12 deletions app/src/test/kotlin/com/wespot/user/fixture/UserFixture.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@ package com.wespot.user.fixture

import com.wespot.auth.PrincipalDetails
import com.wespot.auth.dto.request.ProfileRequest
import com.wespot.user.ConsentType
import com.wespot.user.FCM
import com.wespot.user.Profile
import com.wespot.user.restriction.Restriction
import com.wespot.user.Role
import com.wespot.user.Setting
Expand All @@ -14,6 +11,10 @@ import com.wespot.user.User
import com.wespot.user.UserConsent
import com.wespot.user.UserIntroduction
import com.wespot.user.Gender
import com.wespot.user.Profile
import com.wespot.user.FCM
import com.wespot.user.WithdrawalStatus
import com.wespot.user.ConsentType
import com.wespot.user.RestrictionType
import com.wespot.user.dto.request.UpdateProfileRequest
import org.springframework.security.authentication.TestingAuthenticationToken
Expand Down Expand Up @@ -53,7 +54,10 @@ object UserFixture {
restriction = Restriction.createInitialState(),
createdAt = LocalDateTime.now(),
updatedAt = LocalDateTime.now(),
withdrawAt = LocalDateTime.now(),
withdrawalStatus = WithdrawalStatus.NONE,
withdrawalRequestAt = null,
withdrawalCancelAt = null,
withdrawalCompleteAt = null
)

fun createWithIdAndEmail(
Expand Down Expand Up @@ -88,7 +92,10 @@ object UserFixture {
restriction = Restriction.createInitialState(),
createdAt = LocalDateTime.now(),
updatedAt = LocalDateTime.now(),
withdrawAt = LocalDateTime.now(),
withdrawalStatus = WithdrawalStatus.NONE,
withdrawalRequestAt = null,
withdrawalCancelAt = null,
withdrawalCompleteAt = null
)

fun createSender(
Expand Down Expand Up @@ -122,7 +129,10 @@ object UserFixture {
restriction = Restriction.createInitialState(),
createdAt = LocalDateTime.now(),
updatedAt = LocalDateTime.now(),
withdrawAt = null
withdrawalStatus = WithdrawalStatus.NONE,
withdrawalRequestAt = null,
withdrawalCancelAt = null,
withdrawalCompleteAt = null
)

fun createReceiver(
Expand Down Expand Up @@ -156,7 +166,10 @@ object UserFixture {
restriction = Restriction.createInitialState(),
createdAt = LocalDateTime.now(),
updatedAt = LocalDateTime.now(),
withdrawAt = null
withdrawalStatus = WithdrawalStatus.NONE,
withdrawalRequestAt = null,
withdrawalCancelAt = null,
withdrawalCompleteAt = null
)

// SecurityContextHolder를 사용하여 테스트를 위한 User를 설정
Expand Down Expand Up @@ -212,7 +225,10 @@ object UserFixture {
),
role = Role.USER,
restriction = Restriction.createInitialState(),
withdrawAt = null,
withdrawalStatus = WithdrawalStatus.NONE,
withdrawalRequestAt = null,
withdrawalCancelAt = null,
withdrawalCompleteAt = null,
createdAt = LocalDateTime.now(),
updatedAt = LocalDateTime.now()
)
Expand Down Expand Up @@ -251,7 +267,10 @@ object UserFixture {
restriction = Restriction.createInitialState(),
createdAt = LocalDateTime.now(),
updatedAt = LocalDateTime.now(),
withdrawAt = LocalDateTime.now(),
withdrawalStatus = WithdrawalStatus.NONE,
withdrawalRequestAt = null,
withdrawalCancelAt = null,
withdrawalCompleteAt = null
)

fun createWithIdAndSchoolIdAndGradeAndClassNumber(
Expand Down Expand Up @@ -288,7 +307,10 @@ object UserFixture {
restriction = Restriction.createInitialState(),
createdAt = LocalDateTime.now(),
updatedAt = LocalDateTime.now(),
withdrawAt = LocalDateTime.now(),
withdrawalStatus = WithdrawalStatus.NONE,
withdrawalRequestAt = null,
withdrawalCancelAt = null,
withdrawalCompleteAt = null
)

fun createWithEmailAndSchoolIdAndGradeAndClassNumber(
Expand Down Expand Up @@ -325,7 +347,10 @@ object UserFixture {
restriction = Restriction.createInitialState(),
createdAt = LocalDateTime.now(),
updatedAt = LocalDateTime.now(),
withdrawAt = LocalDateTime.now(),
withdrawalStatus = WithdrawalStatus.NONE,
withdrawalRequestAt = null,
withdrawalCancelAt = null,
withdrawalCompleteAt = null
)

fun createUserWithRestrictionTypeAndRestrictDay(restrictions: List<Pair<RestrictionType, Long>>): User {
Expand Down Expand Up @@ -362,7 +387,10 @@ object UserFixture {
restriction = restriction,
createdAt = LocalDateTime.now(),
updatedAt = LocalDateTime.now(),
withdrawAt = LocalDateTime.now()
withdrawalStatus = WithdrawalStatus.NONE,
withdrawalRequestAt = null,
withdrawalCancelAt = null,
withdrawalCompleteAt = null
)
}

Expand Down
Loading

0 comments on commit 108524f

Please sign in to comment.