Implements remove photo endpoint
This commit is contained in:
@@ -10,9 +10,6 @@ REST API to support a community scavenger hunt app.
|
|||||||
|
|
||||||
## TODO:
|
## TODO:
|
||||||
### User Endpoints
|
### User Endpoints
|
||||||
* upload photo for hunt item POST `/hunt/{huntId}/team/{teamId}/item/{itemId}/photo` - body: image binary
|
|
||||||
* delete photo for hunt item DELETE `/hunt/{huntId}/team/{teamId}/item/{itemId}/photo/{photoId}`
|
* delete photo for hunt item DELETE `/hunt/{huntId}/team/{teamId}/item/{itemId}/photo/{photoId}`
|
||||||
* list hunt teams with scores for hunt `GET /lead/hunt/{huntId}/team`
|
* list hunt teams with scores for hunt GET `/lead/hunt/{huntId}/team`
|
||||||
* list hunters with scores for hunt GET `/lead/hunt/{huntId}/hunter`
|
* list hunters with scores for hunt GET `/lead/hunt/{huntId}/hunter`
|
||||||
### Admin Endpoints
|
|
||||||
* approve photo for hunt item POST `/admin/hunt/{huntId}/team/{teamId}/item/{itemId}/photo/{photoId}` - body: approval status
|
|
||||||
@@ -16,6 +16,7 @@ import net.halfbinary.scavengerhuntapi.service.TeamService
|
|||||||
import org.springframework.http.ResponseEntity
|
import org.springframework.http.ResponseEntity
|
||||||
import org.springframework.security.core.Authentication
|
import org.springframework.security.core.Authentication
|
||||||
import org.springframework.web.bind.annotation.GetMapping
|
import org.springframework.web.bind.annotation.GetMapping
|
||||||
|
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.PostMapping
|
||||||
import org.springframework.web.bind.annotation.RequestBody
|
import org.springframework.web.bind.annotation.RequestBody
|
||||||
@@ -64,6 +65,16 @@ class TeamController(private val teamService: TeamService, private val photoServ
|
|||||||
TODO("Get list of photo information for the specified Team, Hunt, and Item")
|
TODO("Get list of photo information for the specified Team, Hunt, and Item")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PatchMapping("/{teamId}/item/{itemId}/photo/{photoId}")
|
||||||
|
@Operation(summary = "Mark the specified Photo as removed")
|
||||||
|
fun removePhoto(@PathVariable huntId: HuntId,
|
||||||
|
@PathVariable teamId: TeamId,
|
||||||
|
@PathVariable itemId: ItemId,
|
||||||
|
@PathVariable photoId: PhotoId,
|
||||||
|
authentication: Authentication) {
|
||||||
|
photoService.removePhoto(huntId, teamId, itemId, photoId, authentication.name)
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping("/{teamId}/item/{itemId}/photo/{photoId}")
|
@GetMapping("/{teamId}/item/{itemId}/photo/{photoId}")
|
||||||
@Operation(summary = "Get photo information for the specified Team, Hunt, Item, and Photo")
|
@Operation(summary = "Get photo information for the specified Team, Hunt, Item, and Photo")
|
||||||
fun getPhotoInfo(@PathVariable huntId: HuntId,
|
fun getPhotoInfo(@PathVariable huntId: HuntId,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package net.halfbinary.scavengerhuntapi.error
|
package net.halfbinary.scavengerhuntapi.error
|
||||||
|
|
||||||
import net.halfbinary.scavengerhuntapi.error.exception.BadFileException
|
import net.halfbinary.scavengerhuntapi.error.exception.BadFileException
|
||||||
|
import net.halfbinary.scavengerhuntapi.error.exception.ConflictException
|
||||||
import net.halfbinary.scavengerhuntapi.error.exception.ForbiddenException
|
import net.halfbinary.scavengerhuntapi.error.exception.ForbiddenException
|
||||||
import net.halfbinary.scavengerhuntapi.error.exception.InvalidEmailException
|
import net.halfbinary.scavengerhuntapi.error.exception.InvalidEmailException
|
||||||
import net.halfbinary.scavengerhuntapi.error.exception.LoginFailedException
|
import net.halfbinary.scavengerhuntapi.error.exception.LoginFailedException
|
||||||
@@ -54,6 +55,12 @@ class ExceptionHandler {
|
|||||||
return e.message
|
return e.message
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ExceptionHandler(ConflictException::class)
|
||||||
|
@ResponseStatus(HttpStatus.CONFLICT)
|
||||||
|
fun conflictException(e: ConflictException): String? {
|
||||||
|
return e.message
|
||||||
|
}
|
||||||
|
|
||||||
@ExceptionHandler(HttpMessageNotReadableException::class)
|
@ExceptionHandler(HttpMessageNotReadableException::class)
|
||||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||||
fun httpMessageNotReadableException(e: HttpMessageNotReadableException): Map<String, String?> {
|
fun httpMessageNotReadableException(e: HttpMessageNotReadableException): Map<String, String?> {
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
package net.halfbinary.scavengerhuntapi.error.exception
|
||||||
|
|
||||||
|
class ConflictException(override val message: String) : RuntimeException(message)
|
||||||
@@ -3,6 +3,7 @@ package net.halfbinary.scavengerhuntapi.service
|
|||||||
import net.coobird.thumbnailator.Thumbnails
|
import net.coobird.thumbnailator.Thumbnails
|
||||||
import net.coobird.thumbnailator.tasks.UnsupportedFormatException
|
import net.coobird.thumbnailator.tasks.UnsupportedFormatException
|
||||||
import net.halfbinary.scavengerhuntapi.error.exception.BadFileException
|
import net.halfbinary.scavengerhuntapi.error.exception.BadFileException
|
||||||
|
import net.halfbinary.scavengerhuntapi.error.exception.ConflictException
|
||||||
import net.halfbinary.scavengerhuntapi.error.exception.ForbiddenException
|
import net.halfbinary.scavengerhuntapi.error.exception.ForbiddenException
|
||||||
import net.halfbinary.scavengerhuntapi.error.exception.NotFoundException
|
import net.halfbinary.scavengerhuntapi.error.exception.NotFoundException
|
||||||
import net.halfbinary.scavengerhuntapi.model.FoundStatus
|
import net.halfbinary.scavengerhuntapi.model.FoundStatus
|
||||||
@@ -140,6 +141,22 @@ class PhotoService(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun removePhoto(huntId: HuntId, teamId: TeamId, itemId: ItemId, photoId: PhotoId, email: String) {
|
||||||
|
val photoRecord = photoRepository.findByIdAndItemIdAndHuntId(photoId, itemId, huntId)
|
||||||
|
?: throw NotFoundException(PHOTO_NOT_FOUND)
|
||||||
|
|
||||||
|
val team = try {
|
||||||
|
teamService.getTeamForHunterInHunt(huntId, email)
|
||||||
|
} catch (_: NotFoundException) {
|
||||||
|
throw ForbiddenException()
|
||||||
|
}
|
||||||
|
if (team.id != teamId) throw ForbiddenException()
|
||||||
|
|
||||||
|
if (photoRecord.status == PhotoStatus.APPROVED) throw ConflictException("Cannot remove an approved photo")
|
||||||
|
|
||||||
|
photoRepository.save(photoRecord.copy(status = PhotoStatus.REMOVED, statusChangeDateTime = LocalDateTime.now()))
|
||||||
|
}
|
||||||
|
|
||||||
fun updatePhotoStatus(photoId: PhotoId, status: PhotoStatus) {
|
fun updatePhotoStatus(photoId: PhotoId, status: PhotoStatus) {
|
||||||
val record = photoRepository.findByIdOrNull(photoId)
|
val record = photoRepository.findByIdOrNull(photoId)
|
||||||
?: throw NotFoundException(PHOTO_NOT_FOUND)
|
?: throw NotFoundException(PHOTO_NOT_FOUND)
|
||||||
|
|||||||
Reference in New Issue
Block a user