From 210b58b1770788d9959681037f15fc25a794b5cd Mon Sep 17 00:00:00 2001 From: jombi Date: Mon, 13 May 2024 21:28:37 +0900 Subject: [PATCH] feat: user deletion --- .../molohala/grow/api/auth/AuthController.kt | 5 +++++ .../common/exception/GlobalExceptionCode.kt | 1 + .../auth/application/service/AuthService.kt | 1 + .../application/service/AuthServiceImpl.kt | 19 ++++++++++++------- .../application/service/InfoServiceImpl.kt | 3 +++ .../service/LanguageServiceImpl.kt | 7 +++++++ .../grow/core/member/domain/entity/Member.kt | 5 +++++ .../infra/security/MemberDetailsService.kt | 5 ++++- .../grow/infra/security/SecurityConfig.kt | 2 +- .../grow/infra/token/TokenExtractor.kt | 10 +++------- 10 files changed, 42 insertions(+), 16 deletions(-) diff --git a/grow-api/src/main/kotlin/com/molohala/grow/api/auth/AuthController.kt b/grow-api/src/main/kotlin/com/molohala/grow/api/auth/AuthController.kt index 04b980c..e1659ba 100644 --- a/grow-api/src/main/kotlin/com/molohala/grow/api/auth/AuthController.kt +++ b/grow-api/src/main/kotlin/com/molohala/grow/api/auth/AuthController.kt @@ -21,6 +21,11 @@ class AuthController( @RequestBody @Valid reissueTokenReq: ReissueTokenReq ) = ResponseData.ok("토큰 재발급 성공", authService.reissue(reissueTokenReq)) + @DeleteMapping + fun revoke() { + authService.revokeAccount() + } + @PostMapping("/test") fun test(@RequestParam("email") email: String) = ResponseData.ok("테스트 로그인 성공", authService.test(email)) diff --git a/grow-common/src/main/kotlin/com/molohala/grow/common/exception/GlobalExceptionCode.kt b/grow-common/src/main/kotlin/com/molohala/grow/common/exception/GlobalExceptionCode.kt index 32428fa..b7fbe92 100644 --- a/grow-common/src/main/kotlin/com/molohala/grow/common/exception/GlobalExceptionCode.kt +++ b/grow-common/src/main/kotlin/com/molohala/grow/common/exception/GlobalExceptionCode.kt @@ -21,6 +21,7 @@ enum class GlobalExceptionCode( INVALID_ROLE(HttpStatus.FORBIDDEN, "유효하지 않은 권한"), TOKEN_NOT_PROVIDED(HttpStatus.BAD_REQUEST, "잘못된 토큰"), TOKEN_EXPIRED(HttpStatus.UNAUTHORIZED, "만료된 토큰"), + USER_IS_DELETED(HttpStatus.GONE, "삭제된 유저"), INTERNAL_SERVER(HttpStatus.INTERNAL_SERVER_ERROR, "서버 오류"); override fun getHttpStatus(): HttpStatus { diff --git a/grow-core/src/main/kotlin/com/molohala/grow/core/auth/application/service/AuthService.kt b/grow-core/src/main/kotlin/com/molohala/grow/core/auth/application/service/AuthService.kt index 09c8c50..97f1f34 100644 --- a/grow-core/src/main/kotlin/com/molohala/grow/core/auth/application/service/AuthService.kt +++ b/grow-core/src/main/kotlin/com/molohala/grow/core/auth/application/service/AuthService.kt @@ -8,4 +8,5 @@ interface AuthService { suspend fun signIn(code: String): Token fun reissue(reissueTokenReq: ReissueTokenReq): ReissueTokenRes fun test(email: String): Token + fun revokeAccount() } \ No newline at end of file diff --git a/grow-core/src/main/kotlin/com/molohala/grow/core/auth/application/service/AuthServiceImpl.kt b/grow-core/src/main/kotlin/com/molohala/grow/core/auth/application/service/AuthServiceImpl.kt index 89f8672..8c1fbc1 100644 --- a/grow-core/src/main/kotlin/com/molohala/grow/core/auth/application/service/AuthServiceImpl.kt +++ b/grow-core/src/main/kotlin/com/molohala/grow/core/auth/application/service/AuthServiceImpl.kt @@ -1,5 +1,7 @@ package com.molohala.grow.core.auth.application.service +import com.molohala.grow.common.exception.GlobalExceptionCode +import com.molohala.grow.common.exception.custom.CustomException import com.molohala.grow.common.exception.custom.InternalServerException import com.molohala.grow.core.auth.DodamMemberClient import com.molohala.grow.core.auth.IssueJwtToken @@ -7,6 +9,7 @@ import com.molohala.grow.core.auth.application.dto.DodamUserData import com.molohala.grow.core.auth.application.dto.Token import com.molohala.grow.core.auth.application.dto.req.ReissueTokenReq import com.molohala.grow.core.auth.application.dto.res.ReissueTokenRes +import com.molohala.grow.core.member.application.MemberSessionHolder import com.molohala.grow.core.member.domain.consts.MemberRole import com.molohala.grow.core.member.domain.consts.MemberState import com.molohala.grow.core.member.domain.entity.Member @@ -21,7 +24,8 @@ import org.springframework.transaction.annotation.Transactional class AuthServiceImpl( private val dodamMemberClient: DodamMemberClient, private val issueJwtToken: IssueJwtToken, - private val memberJpaRepository: MemberJpaRepository + private val memberJpaRepository: MemberJpaRepository, + private val memberSessionHolder: MemberSessionHolder ) : AuthService { @Transactional(rollbackFor = [Exception::class]) @@ -29,12 +33,8 @@ class AuthServiceImpl( val dodamUserData: DodamUserData? = dodamMemberClient.getMemberInfo(code) dodamUserData?.let { userData -> return withContext(Dispatchers.IO) { - var member: Member? = memberJpaRepository.findByEmail(userData.email) - if (member == null) { - member = save(userData) - } else { - member.updateEmail(userData.email) - } + val member = memberJpaRepository.findByEmail(userData.email) ?: save(userData) + if (member.state == MemberState.DELETED) throw CustomException(GlobalExceptionCode.USER_IS_DELETED) issueJwtToken.issueToken(member.email, member.role) } } ?: throw InternalServerException() @@ -60,4 +60,9 @@ class AuthServiceImpl( return issueJwtToken.issueToken(email, member!!.role) } + @Transactional(rollbackFor = [Exception::class]) + override fun revokeAccount() { + memberJpaRepository.save(memberSessionHolder.current().markDelete()) + } + } \ No newline at end of file diff --git a/grow-core/src/main/kotlin/com/molohala/grow/core/info/application/service/InfoServiceImpl.kt b/grow-core/src/main/kotlin/com/molohala/grow/core/info/application/service/InfoServiceImpl.kt index 7adfff0..60b5094 100644 --- a/grow-core/src/main/kotlin/com/molohala/grow/core/info/application/service/InfoServiceImpl.kt +++ b/grow-core/src/main/kotlin/com/molohala/grow/core/info/application/service/InfoServiceImpl.kt @@ -1,5 +1,6 @@ package com.molohala.grow.core.info.application.service +import com.molohala.grow.common.exception.GlobalExceptionCode import com.molohala.grow.common.exception.custom.CustomException import com.molohala.grow.core.info.GithubInfoClient import com.molohala.grow.core.info.SolvedAcInfoClient @@ -11,6 +12,7 @@ import com.molohala.grow.core.info.application.dto.res.SolvedAcInfoRes import com.molohala.grow.core.info.exception.InfoExceptionCode import com.molohala.grow.core.member.application.MemberSessionHolder import com.molohala.grow.core.member.domain.consts.MemberJob +import com.molohala.grow.core.member.domain.consts.MemberState import com.molohala.grow.core.member.domain.consts.SocialType import com.molohala.grow.core.member.domain.entity.SocialAccount import com.molohala.grow.core.member.repository.MemberJpaRepository @@ -78,6 +80,7 @@ class InfoServiceImpl( override fun getUserInfo(userId: Long): InfoRes { val member = memberJpaRepository.findById(userId) .orElseThrow { CustomException(InfoExceptionCode.USER_NOT_FOUND) } + if (member.state == MemberState.DELETED) throw CustomException(GlobalExceptionCode.USER_IS_DELETED) val socials = socialAccountJpaRepository.findSocialAccountsByMemberId(member.id!!) // id won't be null .map { SocialAccountRes( diff --git a/grow-core/src/main/kotlin/com/molohala/grow/core/language/application/service/LanguageServiceImpl.kt b/grow-core/src/main/kotlin/com/molohala/grow/core/language/application/service/LanguageServiceImpl.kt index 4cf2c04..0a6bb26 100644 --- a/grow-core/src/main/kotlin/com/molohala/grow/core/language/application/service/LanguageServiceImpl.kt +++ b/grow-core/src/main/kotlin/com/molohala/grow/core/language/application/service/LanguageServiceImpl.kt @@ -1,6 +1,8 @@ package com.molohala.grow.core.language.application.service +import com.molohala.grow.common.exception.GlobalExceptionCode import com.molohala.grow.common.exception.custom.CustomException +import com.molohala.grow.core.info.exception.InfoExceptionCode import com.molohala.grow.core.language.domain.entity.Language import com.molohala.grow.core.language.domain.entity.MemberAndLanguage import com.molohala.grow.core.language.exception.LanguageExceptionCode @@ -8,12 +10,15 @@ import com.molohala.grow.core.language.repository.LanguageJpaRepository import com.molohala.grow.core.language.repository.MemberLanguageJpaRepository import com.molohala.grow.core.language.repository.MemberLanguageQueryRepository import com.molohala.grow.core.member.application.MemberSessionHolder +import com.molohala.grow.core.member.domain.consts.MemberState +import com.molohala.grow.core.member.repository.MemberJpaRepository import jakarta.transaction.Transactional import org.springframework.stereotype.Service @Service class LanguageServiceImpl( private val memberSessionHolder: MemberSessionHolder, + private val memberJpaRepository: MemberJpaRepository, private val languageJpaRepository: LanguageJpaRepository, private val memberLanguageJpaRepository: MemberLanguageJpaRepository, private val memberLanguageQueryRepository: MemberLanguageQueryRepository @@ -49,6 +54,8 @@ class LanguageServiceImpl( } override fun getUsingLanguagesByOther(user: Long): List { + val member = memberJpaRepository.findById(user).orElseThrow { CustomException(InfoExceptionCode.USER_NOT_FOUND) } + if (member.state == MemberState.DELETED) throw CustomException(GlobalExceptionCode.USER_IS_DELETED) return memberLanguageQueryRepository.getLanguagesByMemberId(user) } diff --git a/grow-core/src/main/kotlin/com/molohala/grow/core/member/domain/entity/Member.kt b/grow-core/src/main/kotlin/com/molohala/grow/core/member/domain/entity/Member.kt index 63b5a2d..eb3a8f2 100644 --- a/grow-core/src/main/kotlin/com/molohala/grow/core/member/domain/entity/Member.kt +++ b/grow-core/src/main/kotlin/com/molohala/grow/core/member/domain/entity/Member.kt @@ -54,4 +54,9 @@ class Member( if (bio != null) this.bio = bio if (job != null) this.job = job } + + fun markDelete(): Member { + state = MemberState.DELETED + return this + } } \ No newline at end of file diff --git a/grow-infra/src/main/kotlin/com/molohala/grow/infra/security/MemberDetailsService.kt b/grow-infra/src/main/kotlin/com/molohala/grow/infra/security/MemberDetailsService.kt index 0d4cce7..3b59c8d 100644 --- a/grow-infra/src/main/kotlin/com/molohala/grow/infra/security/MemberDetailsService.kt +++ b/grow-infra/src/main/kotlin/com/molohala/grow/infra/security/MemberDetailsService.kt @@ -1,6 +1,9 @@ package com.molohala.grow.infra.security +import com.molohala.grow.common.exception.GlobalExceptionCode +import com.molohala.grow.common.exception.custom.CustomException import com.molohala.grow.core.member.application.service.MemberService +import com.molohala.grow.core.member.domain.consts.MemberState import com.molohala.grow.core.member.domain.entity.Member import org.springframework.security.core.userdetails.UserDetails import org.springframework.security.core.userdetails.UserDetailsService @@ -13,7 +16,7 @@ class MemberDetailsService( override fun loadUserByUsername(email: String): UserDetails { val member: Member? = memberService.getByEmail(email) - + if (member?.state == MemberState.DELETED) throw CustomException(GlobalExceptionCode.USER_IS_DELETED) return MemberDetails(member) } } diff --git a/grow-infra/src/main/kotlin/com/molohala/grow/infra/security/SecurityConfig.kt b/grow-infra/src/main/kotlin/com/molohala/grow/infra/security/SecurityConfig.kt index aaea792..70881bf 100644 --- a/grow-infra/src/main/kotlin/com/molohala/grow/infra/security/SecurityConfig.kt +++ b/grow-infra/src/main/kotlin/com/molohala/grow/infra/security/SecurityConfig.kt @@ -30,7 +30,7 @@ class SecurityConfig( .addFilterBefore(tokenExceptionFilter, TokenFilter::class.java) .authorizeHttpRequests { authorize -> authorize - .requestMatchers("auth/**").permitAll() + .requestMatchers("/auth/sign-in", "/auth/reissue").permitAll() .requestMatchers("/v3/api-docs/**", "/swagger-ui/**").permitAll() .anyRequest().authenticated() } diff --git a/grow-infra/src/main/kotlin/com/molohala/grow/infra/token/TokenExtractor.kt b/grow-infra/src/main/kotlin/com/molohala/grow/infra/token/TokenExtractor.kt index 82f8cbd..f5d1549 100644 --- a/grow-infra/src/main/kotlin/com/molohala/grow/infra/token/TokenExtractor.kt +++ b/grow-infra/src/main/kotlin/com/molohala/grow/infra/token/TokenExtractor.kt @@ -3,9 +3,7 @@ package com.molohala.grow.infra.token import com.molohala.grow.common.exception.GlobalExceptionCode import com.molohala.grow.common.exception.custom.CustomException -import com.molohala.grow.core.member.application.service.MemberService -import com.molohala.grow.core.member.domain.entity.Member -import com.molohala.grow.infra.security.MemberDetails +import com.molohala.grow.infra.security.MemberDetailsService import io.jsonwebtoken.* import io.jsonwebtoken.io.Decoders import io.jsonwebtoken.security.Keys @@ -18,16 +16,14 @@ import java.util.* @Component class TokenExtractor( - private val memberService: MemberService, + private val memberDetailsService: MemberDetailsService, private val jwtProperties: JwtProperties ) { fun signingKey() = Keys.hmacShaKeyFor(Decoders.BASE64.decode(jwtProperties.secret)) fun getAuthentication(accessToken: String): Authentication { val claims = extractClaims(accessToken) - val member: Member? = memberService.getByEmail(claims.subject.toString()) - - val details = MemberDetails(member) + val details = memberDetailsService.loadUserByUsername(claims.subject.toString()) return UsernamePasswordAuthenticationToken(details, null, details.authorities) }