diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/live/signature/AdminAdminSignatureCanRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/live/signature/AdminSignatureCanRepository.kt similarity index 93% rename from src/main/kotlin/kr/co/vividnext/sodalive/admin/live/signature/AdminAdminSignatureCanRepository.kt rename to src/main/kotlin/kr/co/vividnext/sodalive/admin/live/signature/AdminSignatureCanRepository.kt index 215e006..5f34200 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/live/signature/AdminAdminSignatureCanRepository.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/live/signature/AdminSignatureCanRepository.kt @@ -6,7 +6,7 @@ import kr.co.vividnext.sodalive.live.signature.SignatureCan import kr.co.vividnext.sodalive.member.QMember.member import org.springframework.data.jpa.repository.JpaRepository -interface AdminAdminSignatureCanRepository : JpaRepository, AdminSignatureCanQueryRepository +interface AdminSignatureCanRepository : JpaRepository, AdminSignatureCanQueryRepository interface AdminSignatureCanQueryRepository { fun getSignatureCanListTotalCount(): Int diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/admin/live/signature/AdminSignatureCanService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/admin/live/signature/AdminSignatureCanService.kt index cae253a..8834731 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/admin/live/signature/AdminSignatureCanService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/admin/live/signature/AdminSignatureCanService.kt @@ -15,7 +15,7 @@ import org.springframework.web.multipart.MultipartFile @Service class AdminSignatureCanService( - private val repository: AdminAdminSignatureCanRepository, + private val repository: AdminSignatureCanRepository, private val memberRepository: MemberRepository, private val s3Uploader: S3Uploader, diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/signature/CreatorAdminSignatureController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/signature/CreatorAdminSignatureController.kt new file mode 100644 index 0000000..5fdafa1 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/signature/CreatorAdminSignatureController.kt @@ -0,0 +1,60 @@ +package kr.co.vividnext.sodalive.creator.admin.signature + +import kr.co.vividnext.sodalive.common.ApiResponse +import kr.co.vividnext.sodalive.common.SodaException +import kr.co.vividnext.sodalive.member.Member +import org.springframework.data.domain.Pageable +import org.springframework.security.access.prepost.PreAuthorize +import org.springframework.security.core.annotation.AuthenticationPrincipal +import org.springframework.web.bind.annotation.GetMapping +import org.springframework.web.bind.annotation.PostMapping +import org.springframework.web.bind.annotation.PutMapping +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.RequestParam +import org.springframework.web.bind.annotation.RestController +import org.springframework.web.multipart.MultipartFile + +@RestController +@PreAuthorize("hasRole('CREATOR')") +@RequestMapping("/creator-admin/signature") +class CreatorAdminSignatureController(private val service: CreatorAdminSignatureService) { + @GetMapping + fun getSignatureCanList( + pageable: Pageable, + @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? + ) = run { + if (member == null) throw SodaException("로그인 정보를 확인해주세요.") + + ApiResponse.ok(data = service.getSignatureList(pageable, memberId = member.id!!)) + } + + @PostMapping + fun createSignature( + @RequestParam("can") can: Int, + @RequestParam("image") image: MultipartFile, + @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? + ) = run { + if (member == null) throw SodaException("로그인 정보를 확인해주세요.") + + ApiResponse.ok( + service.createSignature(can = can, image = image, memberId = member.id!!), + "등록되었습니다." + ) + } + + @PutMapping + fun modifySignature( + @RequestParam("id") id: Long, + @RequestParam("image", required = false) image: MultipartFile?, + @RequestParam("isActive", required = false) isActive: Boolean?, + @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? + ) = run { + if (member == null) throw SodaException("로그인 정보를 확인해주세요.") + if (image == null && isActive == null) throw SodaException("변경사항이 없습니다.") + + ApiResponse.ok( + service.modifySignature(id = id, image = image, isActive = isActive, memberId = member.id!!), + if (isActive == false) "삭제되었습니다." else "수정되었습니다." + ) + } +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/signature/CreatorAdminSignatureRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/signature/CreatorAdminSignatureRepository.kt new file mode 100644 index 0000000..4442839 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/signature/CreatorAdminSignatureRepository.kt @@ -0,0 +1,68 @@ +package kr.co.vividnext.sodalive.creator.admin.signature + +import com.querydsl.jpa.impl.JPAQueryFactory +import kr.co.vividnext.sodalive.live.signature.QSignatureCan.signatureCan +import kr.co.vividnext.sodalive.live.signature.SignatureCan +import kr.co.vividnext.sodalive.member.QMember.member +import org.springframework.data.jpa.repository.JpaRepository + +interface CreatorAdminSignatureRepository : JpaRepository, CreatorAdminSignatureQueryRepository + +interface CreatorAdminSignatureQueryRepository { + fun getSignatureListTotalCount(memberId: Long): Int + + fun getSignatureList(memberId: Long, imageHost: String, offset: Long, limit: Long): List + + fun findSignatureByIdOrNull(id: Long, memberId: Long): SignatureCan? +} + +class CreatorAdminSignatureQueryRepositoryImpl( + private val queryFactory: JPAQueryFactory +) : CreatorAdminSignatureQueryRepository { + override fun getSignatureListTotalCount(memberId: Long): Int { + return queryFactory.select(signatureCan.id) + .from(signatureCan) + .where( + signatureCan.isActive.isTrue + .and(signatureCan.creator.id.eq(memberId)) + ) + .fetch() + .size + } + + override fun getSignatureList( + memberId: Long, + imageHost: String, + offset: Long, + limit: Long + ): List { + return queryFactory.select( + QGetSignatureListItem( + signatureCan.id, + signatureCan.can, + signatureCan.image.prepend("/").prepend(imageHost), + member.nickname + ) + ) + .from(signatureCan) + .innerJoin(signatureCan.creator, member) + .where( + signatureCan.isActive.isTrue + .and(signatureCan.creator.id.eq(memberId)) + ) + .offset(offset) + .limit(limit) + .orderBy(signatureCan.id.desc()) + .fetch() + } + + override fun findSignatureByIdOrNull(id: Long, memberId: Long): SignatureCan? { + return queryFactory + .selectFrom(signatureCan) + .where( + signatureCan.id.eq(id) + .and(signatureCan.creator.id.eq(memberId)) + ) + .fetchFirst() + } +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/signature/CreatorAdminSignatureService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/signature/CreatorAdminSignatureService.kt new file mode 100644 index 0000000..f1a637e --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/signature/CreatorAdminSignatureService.kt @@ -0,0 +1,82 @@ +package kr.co.vividnext.sodalive.creator.admin.signature + +import com.amazonaws.services.s3.model.ObjectMetadata +import kr.co.vividnext.sodalive.aws.s3.S3Uploader +import kr.co.vividnext.sodalive.common.SodaException +import kr.co.vividnext.sodalive.live.signature.SignatureCan +import kr.co.vividnext.sodalive.member.MemberRepository +import kr.co.vividnext.sodalive.utils.generateFileName +import org.springframework.beans.factory.annotation.Value +import org.springframework.data.domain.Pageable +import org.springframework.stereotype.Service +import org.springframework.transaction.annotation.Transactional +import org.springframework.web.multipart.MultipartFile + +@Service +class CreatorAdminSignatureService( + private val repository: CreatorAdminSignatureRepository, + private val memberRepository: MemberRepository, + + private val s3Uploader: S3Uploader, + + @Value("\${cloud.aws.s3.bucket}") + private val bucket: String, + @Value("\${cloud.aws.cloud-front.host}") + private val imageHost: String +) { + fun getSignatureList(pageable: Pageable, memberId: Long): GetSignatureListResponse { + val totalCount = repository.getSignatureListTotalCount(memberId = memberId) + val items = repository.getSignatureList( + memberId = memberId, + imageHost = imageHost, + offset = pageable.offset, + limit = pageable.pageSize.toLong() + ) + + return GetSignatureListResponse(totalCount, items) + } + + @Transactional + fun createSignature(can: Int, image: MultipartFile, memberId: Long) { + val member = memberRepository.findCreatorByIdOrNull(memberId = memberId) + ?: throw SodaException("잘못된 접근입니다.") + + val signatureCan = SignatureCan(can = can) + signatureCan.creator = member + repository.save(signatureCan) + + val metadata = ObjectMetadata() + metadata.contentLength = image.size + val imagePath = s3Uploader.upload( + inputStream = image.inputStream, + bucket = bucket, + filePath = "signature_can/${signatureCan.id}/${generateFileName()}", + metadata = metadata + ) + + signatureCan.image = imagePath + } + + @Transactional + fun modifySignature(id: Long, image: MultipartFile?, isActive: Boolean?, memberId: Long) { + val signatureCan = repository.findSignatureByIdOrNull(id = id, memberId = memberId) + ?: throw SodaException("잘못된 요청입니다.") + + if (isActive != null) { + signatureCan.isActive = isActive + } + + if (image != null) { + val metadata = ObjectMetadata() + metadata.contentLength = image.size + val imagePath = s3Uploader.upload( + inputStream = image.inputStream, + bucket = bucket, + filePath = "signature_can/${signatureCan.id}/${generateFileName()}", + metadata = metadata + ) + + signatureCan.image = imagePath + } + } +} diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/signature/GetSignatureListResponse.kt b/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/signature/GetSignatureListResponse.kt new file mode 100644 index 0000000..95093d8 --- /dev/null +++ b/src/main/kotlin/kr/co/vividnext/sodalive/creator/admin/signature/GetSignatureListResponse.kt @@ -0,0 +1,15 @@ +package kr.co.vividnext.sodalive.creator.admin.signature + +import com.querydsl.core.annotations.QueryProjection + +data class GetSignatureListResponse( + val totalCount: Int, + val items: List +) + +data class GetSignatureListItem @QueryProjection constructor( + val id: Long, + val can: Int, + val image: String, + val nickname: String +)