diff --git a/src/main/kotlin/com/hero/alignlab/domain/auth/application/OAuthFacade.kt b/src/main/kotlin/com/hero/alignlab/domain/auth/application/OAuthFacade.kt index c2dc7d4..4a49e25 100644 --- a/src/main/kotlin/com/hero/alignlab/domain/auth/application/OAuthFacade.kt +++ b/src/main/kotlin/com/hero/alignlab/domain/auth/application/OAuthFacade.kt @@ -1,5 +1,7 @@ package com.hero.alignlab.domain.auth.application +import com.hero.alignlab.client.kakao.KakaoInfoService +import com.hero.alignlab.client.kakao.model.request.KakaoOAuthUnlinkRequest import com.hero.alignlab.common.extension.executes import com.hero.alignlab.config.database.TransactionTemplates import com.hero.alignlab.domain.auth.model.OAuthProvider @@ -12,7 +14,9 @@ import com.hero.alignlab.domain.user.application.OAuthUserInfoService import com.hero.alignlab.domain.user.application.UserInfoService import com.hero.alignlab.domain.user.domain.OAuthUserInfo import com.hero.alignlab.domain.user.domain.UserInfo +import com.hero.alignlab.event.model.WithdrawEvent import io.github.oshai.kotlinlogging.KotlinLogging +import org.springframework.context.ApplicationEventPublisher import org.springframework.stereotype.Service import java.time.LocalDateTime @@ -23,6 +27,8 @@ class OAuthFacade( private val userInfoService: UserInfoService, private val jwtTokenService: JwtTokenService, private val txTemplates: TransactionTemplates, + private val kakaoInfoService: KakaoInfoService, + private val publisher: ApplicationEventPublisher, ) { companion object { private val TOKEN_EXPIRED_DATE = LocalDateTime.of(2024, 12, 29, 0, 0, 0) @@ -84,4 +90,26 @@ class OAuthFacade( accessToken = token ) } + + suspend fun withdraw( + provider: OAuthProvider, + accessToken: String, + oauthId: String + ) { + when (provider) { + OAuthProvider.kakao -> kakaoInfoService.unlink(accessToken, KakaoOAuthUnlinkRequest(targetId = oauthId)) + } + + val oauthUser = oAuthUserInfoService.findByProviderAndOauthId(provider.toProvider(), oauthId) + + if (oauthUser != null) { + /** 유저 정보는 즉시 삭제 */ + txTemplates.writer.executes { + oAuthUserInfoService.deleteSync(provider.toProvider(), oauthId) + userInfoService.deleteBySync(oauthUser.uid) + + publisher.publishEvent(WithdrawEvent(oauthUser.uid)) + } + } + } } diff --git a/src/main/kotlin/com/hero/alignlab/domain/auth/resource/OAuthResource.kt b/src/main/kotlin/com/hero/alignlab/domain/auth/resource/OAuthResource.kt index a22c5c0..3a4e6e2 100644 --- a/src/main/kotlin/com/hero/alignlab/domain/auth/resource/OAuthResource.kt +++ b/src/main/kotlin/com/hero/alignlab/domain/auth/resource/OAuthResource.kt @@ -2,6 +2,7 @@ package com.hero.alignlab.domain.auth.resource import com.hero.alignlab.common.extension.wrapCreated import com.hero.alignlab.common.extension.wrapOk +import com.hero.alignlab.common.extension.wrapVoid import com.hero.alignlab.domain.auth.application.OAuthFacade import com.hero.alignlab.domain.auth.model.OAuthProvider import com.hero.alignlab.domain.auth.model.request.OAuthSignInRequest @@ -40,4 +41,16 @@ class OAuthResource( @PathVariable provider: OAuthProvider, @RequestBody request: OAuthSignUpRequest, ) = oAuthFacade.signUp(provider, request).wrapCreated() + + @Operation(summary = "탈퇴하기") + @DeleteMapping("/api/v1/oauth/{provider}/withdraw") + suspend fun withdraw( + @PathVariable provider: OAuthProvider, + @RequestParam accessToken: String, + @RequestParam oauthId: String, + ) = oAuthFacade.withdraw( + provider = provider, + accessToken = accessToken, + oauthId = oauthId + ).wrapVoid() } diff --git a/src/main/kotlin/com/hero/alignlab/event/listener/WithdrawEventListener.kt b/src/main/kotlin/com/hero/alignlab/event/listener/WithdrawEventListener.kt new file mode 100644 index 0000000..5b359dd --- /dev/null +++ b/src/main/kotlin/com/hero/alignlab/event/listener/WithdrawEventListener.kt @@ -0,0 +1,33 @@ +package com.hero.alignlab.event.listener + +import com.hero.alignlab.config.database.TransactionTemplates +import com.hero.alignlab.domain.discussion.infrastructure.DiscussionCommentRepository +import com.hero.alignlab.domain.discussion.infrastructure.DiscussionRepository +import com.hero.alignlab.domain.group.infrastructure.GroupRepository +import com.hero.alignlab.domain.group.infrastructure.GroupUserRepository +import com.hero.alignlab.domain.notification.infrastructure.PoseNotificationRepository +import com.hero.alignlab.event.model.WithdrawEvent +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import org.springframework.stereotype.Component +import org.springframework.transaction.event.TransactionalEventListener + +@Component +class WithdrawEventListener( + private val txTemplates: TransactionTemplates, + private val discussionRepository: DiscussionRepository, + private val groupRepository: GroupRepository, + private val groupUserRepository: GroupUserRepository, + private val poseNotificationRepository: PoseNotificationRepository, + private val discussionCommentRepository: DiscussionCommentRepository, +) { + @TransactionalEventListener + fun handle(event: WithdrawEvent) { + CoroutineScope(Dispatchers.IO).launch { + txTemplates.writer.executeWithoutResult { + // TODO: 회원 탈퇴 로직 필요. + } + } + } +} diff --git a/src/main/kotlin/com/hero/alignlab/event/model/Event.kt b/src/main/kotlin/com/hero/alignlab/event/model/Event.kt index d322a76..fafc6be 100644 --- a/src/main/kotlin/com/hero/alignlab/event/model/Event.kt +++ b/src/main/kotlin/com/hero/alignlab/event/model/Event.kt @@ -52,3 +52,7 @@ data class SystemActionLogEvent( } } } + +data class WithdrawEvent( + val uid: Long, +) : BaseEvent()