diff --git a/src/main/kotlin/com/seugi/api/domain/oauth/adapter/in/controller/GoogleRemoveController.kt b/src/main/kotlin/com/seugi/api/domain/oauth/adapter/in/controller/GoogleRemoveController.kt new file mode 100644 index 000000000..780711d43 --- /dev/null +++ b/src/main/kotlin/com/seugi/api/domain/oauth/adapter/in/controller/GoogleRemoveController.kt @@ -0,0 +1,22 @@ +package com.seugi.api.domain.oauth.adapter.`in`.controller + +import com.seugi.api.domain.oauth.port.`in`.GoogleRemoveUseCase +import com.seugi.api.global.common.annotation.GetAuthenticatedId +import com.seugi.api.global.response.BaseResponse +import org.springframework.web.bind.annotation.DeleteMapping +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RestController + +@RestController +@RequestMapping("/oauth/google") +class GoogleRemoveController ( + private val service: GoogleRemoveUseCase +) { + + @DeleteMapping("/remove") + fun remove(@GetAuthenticatedId userId: Long): BaseResponse { + service.remove(userId) + return BaseResponse(message = "삭제 성공 !") + } + +} \ No newline at end of file diff --git a/src/main/kotlin/com/seugi/api/domain/oauth/adapter/out/OAuthAdapter.kt b/src/main/kotlin/com/seugi/api/domain/oauth/adapter/out/OAuthAdapter.kt index 59e97b666..05a5e5e39 100644 --- a/src/main/kotlin/com/seugi/api/domain/oauth/adapter/out/OAuthAdapter.kt +++ b/src/main/kotlin/com/seugi/api/domain/oauth/adapter/out/OAuthAdapter.kt @@ -6,6 +6,7 @@ import com.seugi.api.domain.oauth.adapter.out.mapper.OAuthMapper import com.seugi.api.domain.oauth.adapter.out.repository.OAuthRepository import com.seugi.api.domain.oauth.application.exception.OAuthErrorCode import com.seugi.api.domain.oauth.application.model.OAuth +import com.seugi.api.domain.oauth.port.out.DeleteOAuthPort import com.seugi.api.domain.oauth.port.out.ExistOAuthPort import com.seugi.api.domain.oauth.port.out.LoadOAuthPort import com.seugi.api.domain.oauth.port.out.SaveOAuthPort @@ -19,7 +20,7 @@ class OAuthAdapter ( private val oAuthRepository: OAuthRepository, private val memberRepository: MemberRepository, private val oAuthMapper: OAuthMapper -): LoadOAuthPort, ExistOAuthPort, SaveOAuthPort { +): LoadOAuthPort, ExistOAuthPort, SaveOAuthPort, DeleteOAuthPort { override fun loadOAuthByMemberIdAndProvider(memberId: Long, provider: Provider): OAuth { val member = memberRepository.findByIdOrNull(memberId) @@ -51,4 +52,10 @@ class OAuthAdapter ( ) } + override fun deleteOAuth(memberId: Long, provider: Provider) { + val member = memberRepository.findByIdOrNull(memberId) + ?: throw CustomException(MemberErrorCode.MEMBER_NOT_FOUND) + + oAuthRepository.deleteByMemberAndProvider(member, provider) + } } \ No newline at end of file diff --git a/src/main/kotlin/com/seugi/api/domain/oauth/adapter/out/repository/OAuthCustomRepository.kt b/src/main/kotlin/com/seugi/api/domain/oauth/adapter/out/repository/OAuthCustomRepository.kt index 3c323753e..be4eb2a0b 100644 --- a/src/main/kotlin/com/seugi/api/domain/oauth/adapter/out/repository/OAuthCustomRepository.kt +++ b/src/main/kotlin/com/seugi/api/domain/oauth/adapter/out/repository/OAuthCustomRepository.kt @@ -9,5 +9,6 @@ interface OAuthCustomRepository { fun findByMemberAndProvider(member: MemberEntity, provider: Provider): OAuthEntity? fun findByProviderAndSub(provider: Provider, sub: String): OAuthEntity? fun existsByMemberAndProvider(member: MemberEntity, provider: Provider): Boolean + fun deleteByMemberAndProvider(member: MemberEntity, provider: Provider) } \ No newline at end of file diff --git a/src/main/kotlin/com/seugi/api/domain/oauth/adapter/out/repository/OAuthRepository.kt b/src/main/kotlin/com/seugi/api/domain/oauth/adapter/out/repository/OAuthRepository.kt index c8894c16f..d979c3b00 100644 --- a/src/main/kotlin/com/seugi/api/domain/oauth/adapter/out/repository/OAuthRepository.kt +++ b/src/main/kotlin/com/seugi/api/domain/oauth/adapter/out/repository/OAuthRepository.kt @@ -10,5 +10,6 @@ interface OAuthRepository : CrudRepository, OAuthCustomReposi override fun findByMemberAndProvider(member: MemberEntity, provider: Provider): OAuthEntity? override fun findByProviderAndSub(provider: Provider, sub: String): OAuthEntity? override fun existsByMemberAndProvider(member: MemberEntity, provider: Provider): Boolean + override fun deleteByMemberAndProvider(member: MemberEntity, provider: Provider) } \ No newline at end of file diff --git a/src/main/kotlin/com/seugi/api/domain/oauth/adapter/out/repository/OAuthRepositoryCustomImpl.kt b/src/main/kotlin/com/seugi/api/domain/oauth/adapter/out/repository/OAuthRepositoryCustomImpl.kt index de60ec1e5..0af857562 100644 --- a/src/main/kotlin/com/seugi/api/domain/oauth/adapter/out/repository/OAuthRepositoryCustomImpl.kt +++ b/src/main/kotlin/com/seugi/api/domain/oauth/adapter/out/repository/OAuthRepositoryCustomImpl.kt @@ -51,4 +51,15 @@ class OAuthRepositoryCustomImpl ( .fetchOne() != null } + override fun deleteByMemberAndProvider(member: MemberEntity, provider: Provider) { + val entity = QOAuthEntity.oAuthEntity + + jpaQueryFactory + .delete(entity) + .where( + entity.member.eq(member), + entity.provider.eq(provider) + ) + .execute() + } } \ No newline at end of file diff --git a/src/main/kotlin/com/seugi/api/domain/oauth/application/service/GoogleRefreshService.kt b/src/main/kotlin/com/seugi/api/domain/oauth/application/service/GoogleRefreshService.kt index c40e893e4..6f769dbae 100644 --- a/src/main/kotlin/com/seugi/api/domain/oauth/application/service/GoogleRefreshService.kt +++ b/src/main/kotlin/com/seugi/api/domain/oauth/application/service/GoogleRefreshService.kt @@ -1,9 +1,9 @@ package com.seugi.api.domain.oauth.application.service +import com.google.api.client.auth.oauth2.TokenResponseException import com.google.api.client.json.gson.GsonFactory import com.seugi.api.global.auth.oauth.google.GoogleProperties import com.google.api.client.googleapis.auth.oauth2.GoogleRefreshTokenRequest -import com.google.api.client.googleapis.json.GoogleJsonResponseException import com.google.api.client.http.javanet.NetHttpTransport import com.seugi.api.domain.oauth.application.exception.OAuthErrorCode import com.seugi.api.domain.oauth.application.model.OAuth @@ -32,7 +32,7 @@ class GoogleRefreshService ( oauth.accessToken = OAuthAccessToken(accessToken) saveOAuthPort.saveOAuth(oauth) - } catch (e: GoogleJsonResponseException) { + } catch (e: TokenResponseException) { throw CustomException(OAuthErrorCode.OAUTH_REFRESH_EXPIRED) } diff --git a/src/main/kotlin/com/seugi/api/domain/oauth/application/service/GoogleRemoveService.kt b/src/main/kotlin/com/seugi/api/domain/oauth/application/service/GoogleRemoveService.kt new file mode 100644 index 000000000..a23263889 --- /dev/null +++ b/src/main/kotlin/com/seugi/api/domain/oauth/application/service/GoogleRemoveService.kt @@ -0,0 +1,27 @@ +package com.seugi.api.domain.oauth.application.service + +import com.seugi.api.domain.oauth.application.exception.OAuthErrorCode +import com.seugi.api.domain.oauth.port.`in`.GoogleRemoveUseCase +import com.seugi.api.domain.oauth.port.out.DeleteOAuthPort +import com.seugi.api.domain.oauth.port.out.ExistOAuthPort +import com.seugi.api.global.auth.oauth.enums.Provider +import com.seugi.api.global.exception.CustomException +import jakarta.transaction.Transactional +import org.springframework.stereotype.Service + +@Service +class GoogleRemoveService ( + private val existOAuthPort: ExistOAuthPort, + private val deleteOAuthPort: DeleteOAuthPort +) : GoogleRemoveUseCase { + + @Transactional + override fun remove(userId: Long) { + if (!existOAuthPort.existOAuthByMemberIdAndProvider(userId, Provider.GOOGLE)) { + throw CustomException(OAuthErrorCode.OAUTH_NOT_FOUND) + } + + deleteOAuthPort.deleteOAuth(userId, Provider.GOOGLE) + } + +} \ No newline at end of file diff --git a/src/main/kotlin/com/seugi/api/domain/oauth/port/in/GoogleRemoveUseCase.kt b/src/main/kotlin/com/seugi/api/domain/oauth/port/in/GoogleRemoveUseCase.kt new file mode 100644 index 000000000..b08286ad5 --- /dev/null +++ b/src/main/kotlin/com/seugi/api/domain/oauth/port/in/GoogleRemoveUseCase.kt @@ -0,0 +1,7 @@ +package com.seugi.api.domain.oauth.port.`in` + +interface GoogleRemoveUseCase { + + fun remove(userId: Long) + +} \ No newline at end of file diff --git a/src/main/kotlin/com/seugi/api/domain/oauth/port/out/DeleteOAuthPort.kt b/src/main/kotlin/com/seugi/api/domain/oauth/port/out/DeleteOAuthPort.kt new file mode 100644 index 000000000..9e881b386 --- /dev/null +++ b/src/main/kotlin/com/seugi/api/domain/oauth/port/out/DeleteOAuthPort.kt @@ -0,0 +1,9 @@ +package com.seugi.api.domain.oauth.port.out + +import com.seugi.api.global.auth.oauth.enums.Provider + +interface DeleteOAuthPort { + + fun deleteOAuth(memberId: Long, provider: Provider) + +} \ No newline at end of file