Skip to content

Commit

Permalink
Api-v0.0.3-5
Browse files Browse the repository at this point in the history
  • Loading branch information
kdomo authored Jul 7, 2023
2 parents 71186af + 07e62b6 commit 70bf8f9
Show file tree
Hide file tree
Showing 57 changed files with 929 additions and 178 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,71 +2,99 @@ package com.depromeet.whatnow.api.image.controller

import com.depromeet.whatnow.api.image.dto.ImageCommentElement
import com.depromeet.whatnow.api.image.dto.ImageUrlResponse
import com.depromeet.whatnow.api.image.dto.PromiseImageDetailResponse
import com.depromeet.whatnow.api.image.dto.PromiseImageResponse
import com.depromeet.whatnow.api.image.usecase.GetPresignedUrlUseCase
import com.depromeet.whatnow.api.image.usecase.ImageCommentReadUseCase
import com.depromeet.whatnow.api.image.usecase.ImageUploadSuccessUseCase
import com.depromeet.whatnow.common.vo.CoordinateVo
import com.depromeet.whatnow.api.image.usecase.PromiseImageDeleteUseCase
import com.depromeet.whatnow.api.image.usecase.PromiseImageReadUseCase
import com.depromeet.whatnow.config.s3.ImageFileExtension
import com.depromeet.whatnow.domains.image.domain.PromiseImageCommentType
import io.swagger.v3.oas.annotations.Operation
import io.swagger.v3.oas.annotations.security.SecurityRequirement
import io.swagger.v3.oas.annotations.tags.Tag
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.RequestBody
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
import javax.validation.Valid

@RestController
@Tag(name = "6. [이미지]")
@RequestMapping("/v1")
@RequestMapping("/v1/images")
@SecurityRequirement(name = "access-token")
class ImageController(
val getPresignedUrlUseCase: GetPresignedUrlUseCase,
val successUseCase: ImageUploadSuccessUseCase,
val imageCommentReadUseCase: ImageCommentReadUseCase,
val promiseImageReadUseCase: PromiseImageReadUseCase,
val promiseImageDeleteUseCase: PromiseImageDeleteUseCase,
) {
@Tag(name = "6-1 [약속 이미지]")
@Operation(summary = "약속 이미지 업로드 Presigned URL 발급")
@GetMapping("/images/promises/{promiseId}")
@GetMapping("/promises/{promiseId}/presigned-url")
fun getPresignedUrlOfPromise(
@PathVariable promiseId: Long,
@RequestParam fileExtension: ImageFileExtension,
): ImageUrlResponse {
return getPresignedUrlUseCase.forPromise(promiseId, fileExtension)
}

@Operation(summary = "유저 프로필 이미지 업로드 Presigned URL 발급")
@GetMapping("/images/users/me")
fun getPresignedUrlOfUser(
@RequestParam fileExtension: ImageFileExtension,
): ImageUrlResponse {
return getPresignedUrlUseCase.forUser(fileExtension)
}

@Tag(name = "6-1 [약속 이미지]")
@Operation(summary = "약속 이미지 업로드 성공 요청")
@PostMapping("/images/{imageKey}/promises/{promiseId}")
@PostMapping("/{imageKey}/promises/{promiseId}")
fun promiseUploadImageSuccess(
@PathVariable promiseId: Long,
@PathVariable imageKey: String,
@RequestParam fileExtension: ImageFileExtension,
@RequestParam promiseImageCommentType: PromiseImageCommentType,
@RequestBody @Valid
userLocation: CoordinateVo,
) {
successUseCase.promiseUploadImageSuccess(promiseId, imageKey, promiseImageCommentType, userLocation)
}

@Operation(summary = "유저 프로필 이미지 업로드 성공 요청")
@PostMapping("/images/{imageKey}/users/me")
fun userUploadImageSuccess(@PathVariable imageKey: String) {
successUseCase.userUploadImageSuccess(imageKey)
successUseCase.promiseUploadImageSuccess(promiseId, imageKey, fileExtension, promiseImageCommentType)
}

@Tag(name = "6-1 [약속 이미지]")
@Operation(summary = "이미지 코멘트를 이넘으로 확인합니다. 주의!! 스웨거 이넘 예시 값과 실제 요청했을 때 값이 달라요 실제 요청값 기준으로 해주세요")
@GetMapping("/images/comments")
@GetMapping("/comments")
fun getImageCommentType(): List<ImageCommentElement> {
return imageCommentReadUseCase.execute()
}

@Tag(name = "6-1 [약속 이미지]")
@Operation(summary = "약속 아이디를 통해 모든 이미지를 LATE, WAIT로 구분하여 가져옵니다.")
@GetMapping("/promises/{promiseId}")
fun getLateAndWaitImagesByPromiseId(@PathVariable promiseId: Long): PromiseImageResponse {
return promiseImageReadUseCase.getLateAndWaitImagesByPromiseId(promiseId)
}

@Tag(name = "6-1 [약속 이미지]")
@Operation(summary = "이미지 키를 통해 이미지를 가져옵니다.")
@GetMapping("/{imageKey}")
fun getImageByImageKey(@PathVariable imageKey: String): PromiseImageDetailResponse {
return promiseImageReadUseCase.getImageByImageKey(imageKey)
}

@Tag(name = "6-1 [약속 이미지]")
@Operation(summary = "이미지 키를 통해 약속 이미지를 삭제합니다.")
@DeleteMapping("/{imageKey}/promises/{promiseId}")
fun deletePromiseImage(@PathVariable promiseId: Long, @PathVariable imageKey: String) {
promiseImageDeleteUseCase.execute(promiseId, imageKey)
}

@Tag(name = "6-2 [유저 이미지]")
@Operation(summary = "유저 프로필 이미지 업로드 Presigned URL 발급")
@GetMapping("/users/me/presigned-url")
fun getPresignedUrlOfUser(
@RequestParam fileExtension: ImageFileExtension,
): ImageUrlResponse {
return getPresignedUrlUseCase.forUser(fileExtension)
}

@Tag(name = "6-2 [유저 이미지]")
@Operation(summary = "유저 프로필 이미지 업로드 성공 요청")
@PostMapping("/{imageKey}/users/me")
fun userUploadImageSuccess(@PathVariable imageKey: String, @RequestParam fileExtension: ImageFileExtension) {
successUseCase.userUploadImageSuccess(imageKey, fileExtension)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.depromeet.whatnow.api.image.dto

import com.depromeet.whatnow.domains.image.domain.PromiseImage
import com.depromeet.whatnow.domains.image.domain.PromiseImageCommentType

data class PromiseImageDetailResponse(
val uploadUserId: Long,
val promiseImageCommentType: PromiseImageCommentType,
) {
companion object {
fun from(promiseImage: PromiseImage): PromiseImageDetailResponse {
return PromiseImageDetailResponse(promiseImage.userId, promiseImage.promiseImageCommentType)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.depromeet.whatnow.api.image.dto

import com.depromeet.whatnow.domains.image.domain.PromiseImage

data class PromiseImageDto(
val imageKey: String,
val imageUrl: String,
val uploadUserId: Long,
) {
companion object {
fun from(promiseImage: PromiseImage): PromiseImageDto {
return PromiseImageDto(promiseImage.imageKey, promiseImage.uri, promiseImage.userId)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.depromeet.whatnow.api.image.dto

import com.depromeet.whatnow.domains.promiseuser.domain.PromiseUserType
import io.swagger.v3.oas.annotations.media.Schema

data class PromiseImageResponse(
@Schema(description = "조회한 유저의 약속 상태 (LATE=빨강, WAIT=파랑)", example = "LATE")
val promiseUserType: PromiseUserType,
@Schema(description = "약속에 참여한 유저들의 사진 목록 (LATE, WAIT로 구분. WAIT는 가장 최신 1개만 존재")
val promiseImages: MutableMap<PromiseUserType, List<PromiseImageDto>>,
)
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,19 @@ package com.depromeet.whatnow.api.image.usecase
import com.depromeet.whatnow.annotation.UseCase
import com.depromeet.whatnow.api.image.dto.ImageUrlResponse
import com.depromeet.whatnow.config.s3.ImageFileExtension
import com.depromeet.whatnow.config.s3.S3UploadPresignedUrlService
import com.depromeet.whatnow.config.s3.S3Service
import com.depromeet.whatnow.config.security.SecurityUtils

@UseCase
class GetPresignedUrlUseCase(
val presignedUrlService: S3UploadPresignedUrlService,
val s3Service: S3Service,
) {
fun forPromise(promiseId: Long, fileExtension: ImageFileExtension): ImageUrlResponse {
return ImageUrlResponse.from(presignedUrlService.forPromise(promiseId, fileExtension))
return ImageUrlResponse.from(s3Service.getPresignedUrlForPromise(promiseId, fileExtension))
}

fun forUser(fileExtension: ImageFileExtension): ImageUrlResponse {
val currentUserId = SecurityUtils.currentUserId
return ImageUrlResponse.from(presignedUrlService.forUser(currentUserId, fileExtension))
return ImageUrlResponse.from(s3Service.getPresignedUrlForUser(currentUserId, fileExtension))
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.depromeet.whatnow.api.image.usecase

import com.depromeet.whatnow.annotation.UseCase
import com.depromeet.whatnow.common.vo.CoordinateVo
import com.depromeet.whatnow.config.s3.ImageFileExtension
import com.depromeet.whatnow.config.security.SecurityUtils
import com.depromeet.whatnow.domains.image.domain.PromiseImageCommentType
import com.depromeet.whatnow.domains.image.service.ImageDomainService
Expand All @@ -13,15 +13,15 @@ class ImageUploadSuccessUseCase(
fun promiseUploadImageSuccess(
promiseId: Long,
imageKey: String,
fileExtension: ImageFileExtension,
promiseImageCommentType: PromiseImageCommentType,
userLocation: CoordinateVo,
) {
val currentUserId: Long = SecurityUtils.currentUserId
imageDomainService.promiseImageUploadSuccess(currentUserId, promiseId, imageKey, promiseImageCommentType, userLocation)
imageDomainService.promiseImageUploadSuccess(currentUserId, promiseId, imageKey, fileExtension, promiseImageCommentType)
}

fun userUploadImageSuccess(imageKey: String) {
fun userUploadImageSuccess(imageKey: String, fileExtension: ImageFileExtension) {
val currentUserId: Long = SecurityUtils.currentUserId
imageDomainService.userImageUploadSuccess(currentUserId, imageKey)
imageDomainService.userImageUploadSuccess(currentUserId, imageKey, fileExtension)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.depromeet.whatnow.api.image.usecase

import com.depromeet.whatnow.annotation.UseCase
import com.depromeet.whatnow.config.security.SecurityUtils
import com.depromeet.whatnow.domains.image.service.ImageDomainService

@UseCase
class PromiseImageDeleteUseCase(
val imageDomainService: ImageDomainService,
) {
fun execute(promiseId: Long, imageKey: String) {
val userId = SecurityUtils.currentUserId
imageDomainService.deleteForPromise(userId, promiseId, imageKey)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.depromeet.whatnow.api.image.usecase

import com.depromeet.whatnow.annotation.UseCase
import com.depromeet.whatnow.api.image.dto.PromiseImageDetailResponse
import com.depromeet.whatnow.api.image.dto.PromiseImageDto
import com.depromeet.whatnow.api.image.dto.PromiseImageResponse
import com.depromeet.whatnow.config.security.SecurityUtils
import com.depromeet.whatnow.domains.image.service.ImageDomainService
import com.depromeet.whatnow.domains.promiseuser.domain.PromiseUserType
import com.depromeet.whatnow.domains.promiseuser.service.PromiseUserDomainService

@UseCase
class PromiseImageReadUseCase(
val imageDomainService: ImageDomainService,
val promiseUserDomainService: PromiseUserDomainService,
) {

fun getLateAndWaitImagesByPromiseId(promiseId: Long): PromiseImageResponse {
var userId = SecurityUtils.currentUserId

// 사진을 조회하는 유저의 Late, Wait 상태를 조회하기 위해
val promiseUser = promiseUserDomainService.findByPromiseIdAndUserId(promiseId, userId)

val result: MutableMap<PromiseUserType, List<PromiseImageDto>> = mutableMapOf()
val promiseImages = imageDomainService.getImagesByPromiseId(promiseId)

// LATE의 사진
result[PromiseUserType.LATE] = (
promiseImages.filter { promiseImage -> promiseUserDomainService.findByPromiseIdAndUserId(promiseId, promiseImage.userId).promiseUserType == PromiseUserType.LATE }
.sortedByDescending { promiseImage -> promiseImage.createdAt }
.map { promiseImage ->
PromiseImageDto(promiseImage.imageKey, promiseImage.uri, promiseImage.userId)
}.toList()
)

// WAIT의 사진 (가장 최신 1개)
result[PromiseUserType.WAIT] = (
promiseImages.filter { promiseImage -> promiseUserDomainService.findByPromiseIdAndUserId(promiseId, promiseImage.userId).promiseUserType == PromiseUserType.WAIT }
.sortedByDescending { promiseImage -> promiseImage.createdAt }
).firstOrNull()?.let { promiseImage ->
listOf(
PromiseImageDto(promiseImage.imageKey, promiseImage.uri, promiseImage.userId),
)
} ?: listOf()

return PromiseImageResponse(promiseUser.promiseUserType!!, result)
}

fun getImagesByPromiseId(promiseId: Long): List<PromiseImageDto> {
return imageDomainService.getImagesByPromiseId(promiseId)
.map { PromiseImageDto.from(it) }
}

fun getImageByImageKey(imageKey: String): PromiseImageDetailResponse {
return imageDomainService.getImageByImageKey(imageKey)
.let { PromiseImageDetailResponse.from(it) }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.depromeet.whatnow.api.image.usecase

import com.depromeet.whatnow.annotation.UseCase
import com.depromeet.whatnow.config.security.SecurityUtils
import com.depromeet.whatnow.domains.image.service.ImageDomainService

@UseCase
class UserImageDeleteUseCase(
val imageDomainService: ImageDomainService,
) {
fun execute(imageKey: String) {
val userId = SecurityUtils.currentUserId
imageDomainService.deleteForUser(userId, imageKey)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class RequiresMainUserAspect(
val userId = SecurityUtils.currentUserId
val promiseId = joinPoint.args[0] as Long
val promise = promiseAdaptor.queryPromise(promiseId)

if (userId == promise.mainUserId) {
return joinPoint.proceed()
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@ class PromiseController(
return promiseReadUseCase.findPromiseByUserIdSeparatedType()
}

@Operation(summary = "월단위 약속 조회", description = "유저의 월간 약속 조회 (단, 예정된 약속과 지난 약속을 구분없이 조회), year-month 파라미터는 2021-01 이 형식입니다.")
@Operation(
summary = "월단위 약속 조회",
description = "유저의 월간 약속 조회 (단, 예정된 약속과 지난 약속을 구분없이 조회), year-month 파라미터는 2021-01 이 형식입니다.",
)
@GetMapping("/promises/users")
fun findPromiseByUserAndYearMonth(@RequestParam(value = "year-month") yearMonth: YearMonth): List<PromiseFindDto> {
return promiseReadUseCase.findPromiseByUserIdYearMonth(yearMonth)
Expand All @@ -60,6 +63,12 @@ class PromiseController(
return promiseReadUseCase.findPromiseActive(promiseId)
}

@Operation(summary = "promiseId 로 약속 조회", description = "promiseId 로 약속 조회")
@GetMapping("/promises/{promise-id}")
fun findByPromiseId(@PathVariable(value = "promise-id") promiseId: Long): PromiseFindDto {
return promiseReadUseCase.findByPromiseId(promiseId)
}

@Operation(summary = "약속(promise) 생성", description = "약속을 생성합니다.")
@PostMapping("/promises")
fun createPromise(@RequestBody promiseRequest: PromiseRequest): PromiseDto {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
package com.depromeet.whatnow.api.promise.dto

import com.depromeet.whatnow.common.vo.CoordinateVo
import com.depromeet.whatnow.domains.promise.domain.Promise
import java.time.LocalDateTime

data class PromiseDetailDto(
val promiseId: Long,
val address: String,
val coordinateVo: CoordinateVo,
val title: String,
val date: LocalDateTime,
val endTime: LocalDateTime,
// 유저의 마지막 위치 리스트
val promiseUsers: List<PromiseUserInfoVo>,
// TODO : 약속 기록 사진 기능 추가시 함께 추가할게요.
val promiseImageUrls: List<String>?,
val timeOverLocations: List<LocationCapture>,
// TODO : highlight 기능 추가시 함께 추가할게요. ( 최대 3개 제한 )
// val highlights: List<NotificationDto>,
// x val highlights: List<NotificationDto>,
) {
companion object {
fun of(
Expand All @@ -22,8 +26,11 @@ data class PromiseDetailDto(
timeOverLocations: List<LocationCapture>,
): PromiseDetailDto {
return PromiseDetailDto(
promiseId = promise.id!!,
address = promise.meetPlace!!.address,
coordinateVo = promise.meetPlace!!.coordinate,
title = promise.title,
date = promise.endTime,
endTime = promise.endTime,
promiseUsers = promiseUsers,
promiseImageUrls = promiseImageUrls,
timeOverLocations = timeOverLocations,
Expand Down
Loading

0 comments on commit 70bf8f9

Please sign in to comment.