Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package hs.kr.entrydsm.user.domain.admin.adapter.`in`.web

import hs.kr.entrydsm.user.domain.admin.adapter.`in`.web.dto.request.AdminLoginRequest
import hs.kr.entrydsm.user.domain.admin.application.port.`in`.AdminLoginUseCase
import hs.kr.entrydsm.user.domain.admin.application.port.`in`.AdminTokenRefreshUseCase
import hs.kr.entrydsm.user.domain.admin.application.port.`in`.DeleteAllTableUseCase
import hs.kr.entrydsm.user.domain.admin.application.port.`in`.QueryAdminByUUIDUseCase
import hs.kr.entrydsm.user.global.document.admin.AdminApiDocument
import hs.kr.entrydsm.user.global.utils.token.dto.TokenResponse
import jakarta.validation.Valid
import org.springframework.web.bind.annotation.DeleteMapping
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PathVariable
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.PutMapping
import org.springframework.web.bind.annotation.RequestBody
import org.springframework.web.bind.annotation.RequestHeader
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController
import java.util.UUID

/**
* 관리자 관련 HTTP 요청을 처리하는 REST 컨트롤러 클래스입니다.
*/
@RestController
@RequestMapping("/admin")
class AdminWebAdapter(
private val adminLoginUseCase: AdminLoginUseCase,
private val adminTokenRefreshUseCase: AdminTokenRefreshUseCase,
private val deleteAllTableUseCase: DeleteAllTableUseCase,
private val queryAdminByUUIDUseCase: QueryAdminByUUIDUseCase,
) : AdminApiDocument {
/**
* 관리자 로그인을 처리합니다.
*/
@PostMapping("/auth")
override fun login(
@RequestBody @Valid
adminLoginRequest: AdminLoginRequest,
): TokenResponse = adminLoginUseCase.login(adminLoginRequest)

/**
* 관리자 토큰을 갱신합니다.
*/
@PutMapping("/auth")
override fun tokenRefresh(
@RequestHeader("X-Refresh-Token") refreshToken: String,
): TokenResponse = adminTokenRefreshUseCase.refresh(refreshToken)

/**
* 모든 테이블을 삭제합니다.
*/
@DeleteMapping("/auth")
override fun deleteAllTable() = deleteAllTableUseCase.deleteAllTables()

/**
* UUID로 관리자 정보를 조회합니다.
*/
@GetMapping("/{adminId}")
override fun findAdminById(
@PathVariable adminId: UUID,
) = queryAdminByUUIDUseCase.queryByUUID(adminId)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package hs.kr.entrydsm.user.domain.admin.adapter.`in`.web.dto.response

import java.util.UUID

/**
* 내부 시스템 간 관리자 정보 응답 데이터를 담는 DTO 클래스입니다.
*/
data class InternalAdminResponse(
val id: UUID,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package hs.kr.entrydsm.user.domain.admin.adapter.out

import hs.kr.entrydsm.user.global.base.BaseUUIDEntity
import jakarta.persistence.Column
import jakarta.persistence.Entity
import java.util.UUID

/**
* 관리자 정보를 데이터베이스에 저장하기 위한 JPA 엔티티 클래스입니다.
* 데이터베이스의 tbl_admin 테이블과 매핑됩니다.
*
* @property adminId 관리자 로그인 ID
* @property password 해시화된 비밀번호
*/
@Entity(name = "tbl_admin")
class AdminJpaEntity(
id: UUID?,
@Column(name = "admin_id", length = 15, nullable = false)
val adminId: String,
@Column(name = "password", length = 60, nullable = false)
val password: String,
) : BaseUUIDEntity(id)
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package hs.kr.entrydsm.user.domain.admin.adapter.out.mapper

import hs.kr.entrydsm.user.domain.admin.adapter.out.AdminJpaEntity
import hs.kr.entrydsm.user.domain.admin.model.Admin
import hs.kr.entrydsm.user.global.mapper.GenericMapper
import org.mapstruct.Mapper

/**
* [Admin] 도메인 모델과 [AdminJpaEntity] JPA 엔티티 간의 변환을 담당하는 MapStruct 매퍼 클래스입니다.
*/
@Mapper(componentModel = "spring")
abstract class AdminMapper : GenericMapper<AdminJpaEntity, Admin> {

/**
* 도메인 모델 [Admin]을 JPA 엔티티 [AdminJpaEntity]로 변환합니다.
*
* @param model 변환할 도메인 모델
* @return 변환된 JPA 엔티티
*/
abstract override fun toEntity(model: Admin): AdminJpaEntity

/**
* JPA 엔티티 [AdminJpaEntity]를 도메인 모델 [Admin]로 변환합니다.
*
* @param entity 변환할 JPA 엔티티 (nullable)
* @return 변환된 도메인 모델 (nullable)
*/
abstract override fun toModel(entity: AdminJpaEntity?): Admin?
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package hs.kr.entrydsm.user.domain.admin.adapter.out.persistence

import hs.kr.entrydsm.user.domain.admin.adapter.out.mapper.AdminMapper
import hs.kr.entrydsm.user.domain.admin.adapter.out.persistence.repository.AdminRepository
import hs.kr.entrydsm.user.domain.admin.application.port.out.AdminPort
import hs.kr.entrydsm.user.domain.admin.model.Admin
import org.springframework.data.repository.findByIdOrNull
import org.springframework.stereotype.Component
import java.util.UUID

/**
* 관리자 데이터의 영속성 처리를 담당하는 어댑터 클래스입니다.
*/
@Component
class AdminPersistenceAdapter(
private val adminRepository: AdminRepository,
private val adminMapper: AdminMapper,
) : AdminPort {
/**
* UUID를 이용하여 관리자 정보를 조회합니다.
*
* @param id 조회할 관리자의 UUID
* @return 조회된 관리자 정보, 존재하지 않을 경우 null
*/
override fun findById(id: UUID): Admin? {
return adminRepository.findByIdOrNull(id)?.let { adminMapper.toModel(it) }
}

/**
* 관리자 ID를 이용하여 관리자 정보를 조회합니다.
*
* @param adminId 조회할 관리자의 ID
* @return 조회된 관리자 정보, 존재하지 않을 경우 null
*/
override fun findByAdminId(adminId: String): Admin? {
return adminRepository.findByAdminId(adminId)?.let { adminMapper.toModel(it) }
}

/**
* 관리자 정보를 저장합니다.
*
* @param admin 저장할 관리자 정보
*/
override fun save(admin: Admin) {
adminRepository.save(adminMapper.toEntity(admin))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package hs.kr.entrydsm.user.domain.admin.adapter.out.persistence.repository

import hs.kr.entrydsm.user.domain.admin.adapter.out.AdminJpaEntity
import org.springframework.data.jpa.repository.JpaRepository
import java.util.UUID

/**
* 관리자 JPA 엔티티에 대한 데이터 액세스를 담당하는 리포지토리 인터페이스입니다.
*/
interface AdminRepository : JpaRepository<AdminJpaEntity, UUID> {
/**
* 관리자 ID로 관리자를 조회합니다.
*/
fun findByAdminId(adminId: String): AdminJpaEntity?
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package hs.kr.entrydsm.user.domain.admin.application.port.`in`

import hs.kr.entrydsm.user.domain.admin.model.Admin

/**
* 관리자 Facade 기능을 정의하는 UseCase 인터페이스입니다.
*/
interface AdminFacadeUseCase {
/**
* 현재 인증된 관리자의 사용자 정보를 조회합니다.
*/
fun getCurrentUser(): Admin

/**
* 관리자 ID로 사용자 정보를 조회합니다.
*/
fun getUserById(adminId: String): Admin
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package hs.kr.entrydsm.user.domain.admin.application.port.`in`

import hs.kr.entrydsm.user.domain.admin.adapter.`in`.web.dto.request.AdminLoginRequest
import hs.kr.entrydsm.user.global.utils.token.dto.TokenResponse

/**
* 관리자 로그인 유스케이스 인터페이스입니다.
* 관리자 인증 및 토큰 발급 처리를 정의합니다.
*/
interface AdminLoginUseCase {
/**
* 관리자 로그인을 처리합니다.
*
* @param request 관리자 로그인 요청 정보
* @return 생성된 인증 토큰 응답
*/
fun login(request: AdminLoginRequest): TokenResponse
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package hs.kr.entrydsm.user.domain.admin.application.port.`in`

import hs.kr.entrydsm.user.global.utils.token.dto.TokenResponse

/**
* 관리자 토큰 갱신 기능을 정의하는 UseCase 인터페이스입니다.
*/
interface AdminTokenRefreshUseCase {
/**
* 관리자 토큰을 갱신합니다.
*/
fun refresh(token: String): TokenResponse
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package hs.kr.entrydsm.user.domain.admin.application.port.`in`

/**
* 모든 테이블 삭제 기능을 정의하는 UseCase 인터페이스입니다.
*/
interface DeleteAllTableUseCase {
/**
* 모든 테이블을 삭제합니다.
*/
fun deleteAllTables()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package hs.kr.entrydsm.user.domain.admin.application.port.`in`

import hs.kr.entrydsm.user.domain.admin.adapter.`in`.web.dto.response.InternalAdminResponse
import java.util.UUID

/**
* UUID로 관리자 조회 기능을 정의하는 UseCase 인터페이스입니다.
*/
interface QueryAdminByUUIDUseCase {
/**
* UUID로 관리자 정보를 조회합니다.
*/
fun queryByUUID(adminId: UUID): InternalAdminResponse
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package hs.kr.entrydsm.user.domain.admin.application.port.out

/**
* 관리자 관련 모든 포트 인터페이스를 통합한 포트입니다.
* 관리자 데이터의 CRUD 작업을 위한 모든 인터페이스를 상속받습니다.
*/
interface AdminPort : SaveAdminPort, QueryAdminPort
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package hs.kr.entrydsm.user.domain.admin.application.port.out

import hs.kr.entrydsm.user.domain.admin.model.Admin
import java.util.UUID

/**
* 관리자 조회 작업을 위한 포트 인터페이스입니다.
* 헥사고날 아키텍처에서 도메인 계층이 인프라스트럭처 계층과 통신하기 위한 인터페이스입니다.
*/
interface QueryAdminPort {
/**
* 관리자 ID로 관리자를 조회합니다.
*
* @param adminId 조회할 관리자 ID
* @return 조회된 관리자 도메인 모델 (없으면 null)
*/
fun findByAdminId(adminId: String): Admin?

/**
* UUID로 관리자를 조회합니다.
*
* @param id 조회할 관리자 UUID
* @return 조회된 관리자 도메인 모델 (없으면 null)
*/
fun findById(id: UUID): Admin?
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package hs.kr.entrydsm.user.domain.admin.application.port.out

import hs.kr.entrydsm.user.domain.admin.model.Admin

/**
* 관리자 저장 작업을 위한 포트 인터페이스입니다.
* 헥사고날 아키텍처에서 도메인 계층이 인프라스트럭처 계층과 통신하기 위한 인터페이스입니다.
*/
interface SaveAdminPort {
/**
* 관리자 정보를 저장합니다.
*
* @param admin 저장할 관리자 도메인 모델
*/
fun save(admin: Admin)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package hs.kr.entrydsm.user.domain.admin.application.service

import hs.kr.entrydsm.user.domain.admin.application.port.`in`.AdminTokenRefreshUseCase
import hs.kr.entrydsm.user.global.security.jwt.JwtTokenProvider
import hs.kr.entrydsm.user.global.utils.token.dto.TokenResponse
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional

/**
* 관리자 토큰 갱신 비즈니스 로직을 처리하는 서비스 클래스입니다.
*/
@Service
class AdminTokenRefreshService(
private val jwtTokenProvider: JwtTokenProvider,
) : AdminTokenRefreshUseCase {
/**
* 관리자의 리프레시 토큰을 이용하여 새로운 액세스 토큰을 발급합니다.
*/
@Transactional
override fun refresh(refreshToken: String): TokenResponse = jwtTokenProvider.reIssue(refreshToken)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package hs.kr.entrydsm.user.domain.admin.application.service

import hs.kr.entrydsm.user.domain.admin.application.port.`in`.DeleteAllTableUseCase
import hs.kr.entrydsm.user.infrastructure.kafka.producer.DeleteAllTableProducer
import org.springframework.stereotype.Service

/**
* 모든 테이블 삭제 비즈니스 로직을 처리하는 서비스 클래스입니다.
*/
@Service
class DeleteAllTableService(
private val deleteAllTableProducer: DeleteAllTableProducer,
) : DeleteAllTableUseCase {
/**
* 모든 테이블을 삭제합니다.
*/
override fun deleteAllTables() = deleteAllTableProducer.send()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package hs.kr.entrydsm.user.domain.admin.application.service

import hs.kr.entrydsm.user.domain.admin.adapter.`in`.web.dto.response.InternalAdminResponse
import hs.kr.entrydsm.user.domain.admin.application.port.`in`.QueryAdminByUUIDUseCase
import hs.kr.entrydsm.user.domain.admin.application.port.out.QueryAdminPort
import hs.kr.entrydsm.user.domain.admin.exception.AdminNotFoundException
import org.springframework.stereotype.Service
import org.springframework.transaction.annotation.Transactional
import java.util.UUID

/**
* UUID로 관리자 조회 비즈니스 로직을 처리하는 서비스 클래스입니다.
*/
@Service
class QueryAdminByUUIDService(
private val queryAdminPort: QueryAdminPort,
) : QueryAdminByUUIDUseCase {
/**
* UUID를 이용하여 관리자 정보를 조회합니다.
*/
@Transactional(readOnly = true)
override fun queryByUUID(adminId: UUID): InternalAdminResponse {
val admin = queryAdminPort.findById(adminId) ?: throw AdminNotFoundException
return InternalAdminResponse(
id = admin.id!!,
)
}
}
Loading