Implements photo review endpoint
This commit is contained in:
@@ -2,21 +2,25 @@ package net.halfbinary.scavengerhuntapi.controller
|
|||||||
|
|
||||||
import io.swagger.v3.oas.annotations.Operation
|
import io.swagger.v3.oas.annotations.Operation
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag
|
import io.swagger.v3.oas.annotations.tags.Tag
|
||||||
|
import jakarta.validation.Valid
|
||||||
import net.halfbinary.scavengerhuntapi.model.PhotoId
|
import net.halfbinary.scavengerhuntapi.model.PhotoId
|
||||||
|
import net.halfbinary.scavengerhuntapi.model.request.ReviewPhotoRequest
|
||||||
|
import net.halfbinary.scavengerhuntapi.service.PhotoService
|
||||||
import org.springframework.security.access.prepost.PreAuthorize
|
import org.springframework.security.access.prepost.PreAuthorize
|
||||||
|
import org.springframework.web.bind.annotation.PatchMapping
|
||||||
import org.springframework.web.bind.annotation.PathVariable
|
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.RequestMapping
|
||||||
import org.springframework.web.bind.annotation.RestController
|
import org.springframework.web.bind.annotation.RestController
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("admin")
|
@RequestMapping("admin")
|
||||||
class AdminController {
|
class AdminController(private val photoService: PhotoService) {
|
||||||
@PreAuthorize("hasRole('ADMIN')")
|
@PreAuthorize("hasRole('ADMIN')")
|
||||||
@Tag(name = "Admin")
|
@Tag(name = "Admin")
|
||||||
@PostMapping("/admin/photo/{photoId}")
|
@PatchMapping("/photo/{photoId}")
|
||||||
@Operation(summary = "Sets a review status for the specified photo")
|
@Operation(summary = "Sets a review status for the specified photo")
|
||||||
fun reviewPhoto(@PathVariable photoId: PhotoId) {
|
fun reviewPhoto(@PathVariable photoId: PhotoId, @Valid @RequestBody request: ReviewPhotoRequest) {
|
||||||
TODO("Set a review status for the specified photo, and update the photo record's status change timestamp")
|
photoService.updatePhotoStatus(photoId, request.status)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package net.halfbinary.scavengerhuntapi.model.request
|
||||||
|
|
||||||
|
import jakarta.validation.constraints.NotBlank
|
||||||
|
import net.halfbinary.scavengerhuntapi.model.PhotoStatus
|
||||||
|
|
||||||
|
data class ReviewPhotoRequest(
|
||||||
|
@field:NotBlank(message = "Status must not be blank")
|
||||||
|
val status: PhotoStatus
|
||||||
|
)
|
||||||
@@ -27,6 +27,8 @@ import java.io.ByteArrayInputStream
|
|||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
|
|
||||||
|
private const val PHOTO_NOT_FOUND = "Photo not found"
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
class PhotoService(
|
class PhotoService(
|
||||||
private val photoRepository: PhotoRepository,
|
private val photoRepository: PhotoRepository,
|
||||||
@@ -69,7 +71,7 @@ class PhotoService(
|
|||||||
fun getPhotoInfo(huntId: HuntId, teamId: TeamId, itemId: ItemId, photoId: PhotoId, email: String): PhotoResponse {
|
fun getPhotoInfo(huntId: HuntId, teamId: TeamId, itemId: ItemId, photoId: PhotoId, email: String): PhotoResponse {
|
||||||
val requestingHunter = hunterService.getHunterByEmail(email)
|
val requestingHunter = hunterService.getHunterByEmail(email)
|
||||||
val photoRecord = photoRepository.findByIdAndItemIdAndHuntId(photoId, itemId, huntId)
|
val photoRecord = photoRepository.findByIdAndItemIdAndHuntId(photoId, itemId, huntId)
|
||||||
?: throw NotFoundException("Photo not found")
|
?: throw NotFoundException(PHOTO_NOT_FOUND)
|
||||||
|
|
||||||
if (!requestingHunter.isAdmin) {
|
if (!requestingHunter.isAdmin) {
|
||||||
val team = try {
|
val team = try {
|
||||||
@@ -87,7 +89,7 @@ class PhotoService(
|
|||||||
fun getPhotoFile(photoId: PhotoId, email: String, version: ImageVersion = ImageVersion.LARGE): PhotoFile {
|
fun getPhotoFile(photoId: PhotoId, email: String, version: ImageVersion = ImageVersion.LARGE): PhotoFile {
|
||||||
val requestingHunter = hunterService.getHunterByEmail(email)
|
val requestingHunter = hunterService.getHunterByEmail(email)
|
||||||
val photoRecord = photoRepository.findByIdOrNull(photoId)
|
val photoRecord = photoRepository.findByIdOrNull(photoId)
|
||||||
?: throw NotFoundException("Photo not found")
|
?: throw NotFoundException(PHOTO_NOT_FOUND)
|
||||||
|
|
||||||
if (!requestingHunter.isAdmin) {
|
if (!requestingHunter.isAdmin) {
|
||||||
val submitter = hunterService.getHunterById(photoRecord.hunterId)
|
val submitter = hunterService.getHunterById(photoRecord.hunterId)
|
||||||
@@ -113,6 +115,12 @@ class PhotoService(
|
|||||||
return PhotoFile(InputStreamResource(stream), MediaType.parseMediaType(contentType))
|
return PhotoFile(InputStreamResource(stream), MediaType.parseMediaType(contentType))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun updatePhotoStatus(photoId: PhotoId, status: PhotoStatus) {
|
||||||
|
val record = photoRepository.findByIdOrNull(photoId)
|
||||||
|
?: throw NotFoundException(PHOTO_NOT_FOUND)
|
||||||
|
photoRepository.save(record.copy(status = status, statusChangeDateTime = LocalDateTime.now()))
|
||||||
|
}
|
||||||
|
|
||||||
private fun toJpeg(bytes: ByteArray): ByteArray {
|
private fun toJpeg(bytes: ByteArray): ByteArray {
|
||||||
val output = ByteArrayOutputStream()
|
val output = ByteArrayOutputStream()
|
||||||
Thumbnails.of(ByteArrayInputStream(bytes))
|
Thumbnails.of(ByteArrayInputStream(bytes))
|
||||||
|
|||||||
Reference in New Issue
Block a user