크리에이터 관리자
- 시그니처 조회/등록/수정/삭제 API 추가
This commit is contained in:
		| @@ -13,13 +13,13 @@ import org.springframework.web.bind.annotation.RequestMapping | |||||||
| import org.springframework.web.bind.annotation.RestController | import org.springframework.web.bind.annotation.RestController | ||||||
|  |  | ||||||
| @RestController | @RestController | ||||||
|  | @PreAuthorize("hasRole('CREATOR')") | ||||||
| @RequestMapping("/creator-admin/member") | @RequestMapping("/creator-admin/member") | ||||||
| class CreatorAdminMemberController(private val service: CreatorAdminMemberService) { | class CreatorAdminMemberController(private val service: CreatorAdminMemberService) { | ||||||
|     @PostMapping("/login") |     @PostMapping("/login") | ||||||
|     fun login(@RequestBody loginRequest: LoginRequest) = service.login(loginRequest) |     fun login(@RequestBody loginRequest: LoginRequest) = service.login(loginRequest) | ||||||
|  |  | ||||||
|     @PostMapping("/logout") |     @PostMapping("/logout") | ||||||
|     @PreAuthorize("hasRole('CREATOR')") |  | ||||||
|     fun logout( |     fun logout( | ||||||
|         @RequestHeader("Authorization") token: String, |         @RequestHeader("Authorization") token: String, | ||||||
|         @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? |         @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : member") member: Member? | ||||||
|   | |||||||
| @@ -0,0 +1,53 @@ | |||||||
|  | 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) = ApiResponse.ok(data = service.getSignatureList(pageable)) | ||||||
|  |  | ||||||
|  |     @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 "수정되었습니다." | ||||||
|  |         ) | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,57 @@ | |||||||
|  | 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<SignatureCan, Long>, CreatorAdminSignatureQueryRepository | ||||||
|  |  | ||||||
|  | interface CreatorAdminSignatureQueryRepository { | ||||||
|  |     fun getSignatureListTotalCount(): Int | ||||||
|  |  | ||||||
|  |     fun getSignatureList(imageHost: String, offset: Long, limit: Long): List<GetSignatureListItem> | ||||||
|  |  | ||||||
|  |     fun findSignatureByIdOrNull(id: Long, memberId: Long): SignatureCan? | ||||||
|  | } | ||||||
|  |  | ||||||
|  | class CreatorAdminSignatureQueryRepositoryImpl( | ||||||
|  |     private val queryFactory: JPAQueryFactory | ||||||
|  | ) : CreatorAdminSignatureQueryRepository { | ||||||
|  |     override fun getSignatureListTotalCount(): Int { | ||||||
|  |         return queryFactory.select(signatureCan.id) | ||||||
|  |             .from(signatureCan) | ||||||
|  |             .where(signatureCan.isActive.isTrue) | ||||||
|  |             .fetch() | ||||||
|  |             .size | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     override fun getSignatureList(imageHost: String, offset: Long, limit: Long): List<GetSignatureListItem> { | ||||||
|  |         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) | ||||||
|  |             .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() | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,80 @@ | |||||||
|  | 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): GetSignatureListResponse { | ||||||
|  |         val totalCount = repository.getSignatureListTotalCount() | ||||||
|  |         val items = repository.getSignatureList( | ||||||
|  |             imageHost = imageHost, | ||||||
|  |             offset = pageable.offset, | ||||||
|  |             limit = pageable.pageSize.toLong() | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |         return GetSignatureListResponse(totalCount, items) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     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 | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -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<GetSignatureListItem> | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | data class GetSignatureListItem @QueryProjection constructor( | ||||||
|  |     val id: Long, | ||||||
|  |     val can: Int, | ||||||
|  |     val image: String, | ||||||
|  |     val nickname: String | ||||||
|  | ) | ||||||
		Reference in New Issue
	
	Block a user