diff --git a/adapters/in-web/src/main/kotlin/com/pokit/user/UserController.kt b/adapters/in-web/src/main/kotlin/com/pokit/user/UserController.kt index 266771cc..d3a89eed 100644 --- a/adapters/in-web/src/main/kotlin/com/pokit/user/UserController.kt +++ b/adapters/in-web/src/main/kotlin/com/pokit/user/UserController.kt @@ -4,6 +4,7 @@ import com.pokit.auth.config.ErrorOperation import com.pokit.auth.model.PrincipalUser import com.pokit.auth.model.toDomain import com.pokit.common.wrapper.ResponseWrapper.wrapOk +import com.pokit.user.dto.request.ApiCreateFcmTokenRequest import com.pokit.user.dto.request.ApiSignUpRequest import com.pokit.user.dto.request.ApiUpdateNicknameRequest import com.pokit.user.dto.request.toDto @@ -12,6 +13,7 @@ import com.pokit.user.dto.response.InterestTypeResponse import com.pokit.user.dto.response.UserResponse import com.pokit.user.dto.response.toResponse import com.pokit.user.exception.UserErrorCode +import com.pokit.user.model.FcmToken import com.pokit.user.model.InterestType import com.pokit.user.port.`in`.UserUseCase import io.swagger.v3.oas.annotations.Operation @@ -68,4 +70,14 @@ class UserController( InterestType.values() .map { InterestTypeResponse(it.name, it.kor) } .wrapOk() + + @PostMapping("/fcm") + @Operation(summary = "fcm 토큰 저장 API") + fun createFcmToken( + @AuthenticationPrincipal user: PrincipalUser, + @RequestBody request: ApiCreateFcmTokenRequest + ): ResponseEntity { + return userUseCase.createFcmToken(user.id, request.toDto()) + .wrapOk() + } } diff --git a/adapters/in-web/src/main/kotlin/com/pokit/user/dto/request/ApiCreateFcmTokenRequest.kt b/adapters/in-web/src/main/kotlin/com/pokit/user/dto/request/ApiCreateFcmTokenRequest.kt new file mode 100644 index 00000000..4d6f27a6 --- /dev/null +++ b/adapters/in-web/src/main/kotlin/com/pokit/user/dto/request/ApiCreateFcmTokenRequest.kt @@ -0,0 +1,14 @@ +package com.pokit.user.dto.request + +import io.swagger.v3.oas.annotations.media.Schema +import jakarta.validation.constraints.NotNull + +data class ApiCreateFcmTokenRequest( + @field:Schema(description = "사용자 기기 토큰(FCM 토큰)") + @field:NotNull + val token: String +) + +internal fun ApiCreateFcmTokenRequest.toDto() = CreateFcmTokenRequest( + token = this.token +) diff --git a/adapters/out-persistence/src/main/kotlin/com/pokit/out/persistence/user/impl/FcmTokenAdapter.kt b/adapters/out-persistence/src/main/kotlin/com/pokit/out/persistence/user/impl/FcmTokenAdapter.kt new file mode 100644 index 00000000..c96fc315 --- /dev/null +++ b/adapters/out-persistence/src/main/kotlin/com/pokit/out/persistence/user/impl/FcmTokenAdapter.kt @@ -0,0 +1,18 @@ +package com.pokit.out.persistence.user.impl + +import com.pokit.out.persistence.user.persist.FcmTokenEntity +import com.pokit.out.persistence.user.persist.FcmTokenRepository +import com.pokit.out.persistence.user.persist.toDomain +import com.pokit.user.model.FcmToken +import com.pokit.user.port.out.FcmTokenPort +import org.springframework.stereotype.Repository + +@Repository +class FcmTokenAdapter( + private val fcmTokenRepository: FcmTokenRepository +) : FcmTokenPort { + override fun persist(fcmToken: FcmToken): FcmToken { + val fcmTokenEntity = FcmTokenEntity.of(fcmToken) + return fcmTokenRepository.save(fcmTokenEntity).toDomain() + } +} diff --git a/adapters/out-persistence/src/main/kotlin/com/pokit/out/persistence/user/persist/FcmTokenEntity.kt b/adapters/out-persistence/src/main/kotlin/com/pokit/out/persistence/user/persist/FcmTokenEntity.kt index dc23e66e..14da1091 100644 --- a/adapters/out-persistence/src/main/kotlin/com/pokit/out/persistence/user/persist/FcmTokenEntity.kt +++ b/adapters/out-persistence/src/main/kotlin/com/pokit/out/persistence/user/persist/FcmTokenEntity.kt @@ -15,8 +15,15 @@ class FcmTokenEntity( val userId: Long, @Column(name = "token") - val token: String + val token: String, + + @Column(name = "is_deleted") + var deleted: Boolean = false ) { + fun delete() { + this.deleted = true + } + companion object { fun of(fcmToken: FcmToken) = FcmTokenEntity( userId = fcmToken.userId, @@ -24,3 +31,8 @@ class FcmTokenEntity( ) } } + +fun FcmTokenEntity.toDomain() = FcmToken( + userId = this.userId, + token = this.token +) diff --git a/adapters/out-persistence/src/main/kotlin/com/pokit/out/persistence/user/persist/FcmTokenRepository.kt b/adapters/out-persistence/src/main/kotlin/com/pokit/out/persistence/user/persist/FcmTokenRepository.kt new file mode 100644 index 00000000..5ac9a926 --- /dev/null +++ b/adapters/out-persistence/src/main/kotlin/com/pokit/out/persistence/user/persist/FcmTokenRepository.kt @@ -0,0 +1,6 @@ +package com.pokit.out.persistence.user.persist + +import org.springframework.data.jpa.repository.JpaRepository + +interface FcmTokenRepository : JpaRepository { +} diff --git a/application/src/main/kotlin/com/pokit/user/port/in/UserUseCase.kt b/application/src/main/kotlin/com/pokit/user/port/in/UserUseCase.kt index 6f7bb7a6..879afc12 100644 --- a/application/src/main/kotlin/com/pokit/user/port/in/UserUseCase.kt +++ b/application/src/main/kotlin/com/pokit/user/port/in/UserUseCase.kt @@ -1,7 +1,9 @@ package com.pokit.user.port.`in` +import com.pokit.user.dto.request.CreateFcmTokenRequest import com.pokit.user.dto.request.SignUpRequest import com.pokit.user.dto.request.UpdateNicknameRequest +import com.pokit.user.model.FcmToken import com.pokit.user.model.User interface UserUseCase { @@ -12,4 +14,6 @@ interface UserUseCase { fun updateNickname(user: User, request: UpdateNicknameRequest): User fun fetchAllUserId(): List + + fun createFcmToken(userId: Long, request: CreateFcmTokenRequest): FcmToken } diff --git a/application/src/main/kotlin/com/pokit/user/port/out/FcmTokenPort.kt b/application/src/main/kotlin/com/pokit/user/port/out/FcmTokenPort.kt new file mode 100644 index 00000000..949d7835 --- /dev/null +++ b/application/src/main/kotlin/com/pokit/user/port/out/FcmTokenPort.kt @@ -0,0 +1,7 @@ +package com.pokit.user.port.out + +import com.pokit.user.model.FcmToken + +interface FcmTokenPort { + fun persist(fcmToken: FcmToken): FcmToken +} diff --git a/application/src/main/kotlin/com/pokit/user/port/service/UserService.kt b/application/src/main/kotlin/com/pokit/user/port/service/UserService.kt index ec56a574..3fa308da 100644 --- a/application/src/main/kotlin/com/pokit/user/port/service/UserService.kt +++ b/application/src/main/kotlin/com/pokit/user/port/service/UserService.kt @@ -8,11 +8,14 @@ import com.pokit.category.port.out.CategoryImagePort import com.pokit.category.port.out.CategoryPort import com.pokit.common.exception.ClientValidationException import com.pokit.common.exception.NotFoundCustomException +import com.pokit.user.dto.request.CreateFcmTokenRequest import com.pokit.user.dto.request.SignUpRequest import com.pokit.user.dto.request.UpdateNicknameRequest import com.pokit.user.exception.UserErrorCode +import com.pokit.user.model.FcmToken import com.pokit.user.model.User import com.pokit.user.port.`in`.UserUseCase +import com.pokit.user.port.out.FcmTokenPort import com.pokit.user.port.out.UserPort import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @@ -22,7 +25,8 @@ import org.springframework.transaction.annotation.Transactional class UserService( private val userPort: UserPort, private val categoryPort: CategoryPort, - private val categoryImagePort: CategoryImagePort + private val categoryImagePort: CategoryImagePort, + private val fcmTokenPort: FcmTokenPort ) : UserUseCase { companion object { private const val UNCATEGORIZED_IMAGE_ID = 1 @@ -75,4 +79,12 @@ class UserService( override fun fetchAllUserId() = userPort.loadAllIds() + + @Transactional + override fun createFcmToken(userId: Long, request: CreateFcmTokenRequest): FcmToken { + val user = userPort.loadById(userId) + ?: throw NotFoundCustomException(UserErrorCode.NOT_FOUND_USER) + val fcmToken = FcmToken(user.id, request.token) + return fcmTokenPort.persist(fcmToken) + } } diff --git a/domain/src/main/kotlin/com/pokit/user/dto/request/CreateFcmTokenRequest.kt b/domain/src/main/kotlin/com/pokit/user/dto/request/CreateFcmTokenRequest.kt new file mode 100644 index 00000000..ad773d7f --- /dev/null +++ b/domain/src/main/kotlin/com/pokit/user/dto/request/CreateFcmTokenRequest.kt @@ -0,0 +1,5 @@ +package com.pokit.user.dto.request + +data class CreateFcmTokenRequest( + val token: String +)