From 08d0b1730a83c077f963ae90f4cbbffc3c7ad85d Mon Sep 17 00:00:00 2001 From: aarbit Date: Mon, 18 May 2026 08:58:09 -0500 Subject: [PATCH] Adds update and delete item endpoints --- .../controller/ItemController.kt | 20 ++++++++++++++++++ .../model/request/ItemUpdateRequest.kt | 6 ++++++ .../repository/HuntItemRepository.kt | 6 +++++- .../scavengerhuntapi/service/HuntService.kt | 21 +++++++++++++++++++ 4 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 src/main/kotlin/net/halfbinary/scavengerhuntapi/model/request/ItemUpdateRequest.kt diff --git a/src/main/kotlin/net/halfbinary/scavengerhuntapi/controller/ItemController.kt b/src/main/kotlin/net/halfbinary/scavengerhuntapi/controller/ItemController.kt index 5eabe68..dbd1c2f 100644 --- a/src/main/kotlin/net/halfbinary/scavengerhuntapi/controller/ItemController.kt +++ b/src/main/kotlin/net/halfbinary/scavengerhuntapi/controller/ItemController.kt @@ -8,11 +8,14 @@ import net.halfbinary.scavengerhuntapi.model.ItemId import net.halfbinary.scavengerhuntapi.model.converter.toDomain import net.halfbinary.scavengerhuntapi.model.converter.toResponse import net.halfbinary.scavengerhuntapi.model.request.ItemRequest +import net.halfbinary.scavengerhuntapi.model.request.ItemUpdateRequest import net.halfbinary.scavengerhuntapi.model.response.ItemResponse import net.halfbinary.scavengerhuntapi.service.HuntService import org.springframework.http.ResponseEntity import org.springframework.security.access.prepost.PreAuthorize +import org.springframework.web.bind.annotation.DeleteMapping 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.PostMapping import org.springframework.web.bind.annotation.RequestBody @@ -41,4 +44,21 @@ class ItemController(private val huntService: HuntService) { return ResponseEntity.ok(huntService.addItemToHunt(huntId, body.toDomain()).toResponse()) } + @PreAuthorize("hasRole('ADMIN')") + @Tag(name = "Admin") + @PatchMapping("/{itemId}") + @Operation(summary = "Updates name and/or points for the specified Item in the specified Hunt") + fun updateItem(@PathVariable huntId: HuntId, @PathVariable itemId: ItemId, @RequestBody body: ItemUpdateRequest): ResponseEntity { + return ResponseEntity.ok(huntService.updateItem(huntId, itemId, body).toResponse()) + } + + @PreAuthorize("hasRole('ADMIN')") + @Tag(name = "Admin") + @DeleteMapping("/{itemId}") + @Operation(summary = "Deletes the specified Item from the specified Hunt") + fun deleteItem(@PathVariable huntId: HuntId, @PathVariable itemId: ItemId): ResponseEntity { + huntService.deleteItem(huntId, itemId) + return ResponseEntity.noContent().build() + } + } \ No newline at end of file diff --git a/src/main/kotlin/net/halfbinary/scavengerhuntapi/model/request/ItemUpdateRequest.kt b/src/main/kotlin/net/halfbinary/scavengerhuntapi/model/request/ItemUpdateRequest.kt new file mode 100644 index 0000000..f16b676 --- /dev/null +++ b/src/main/kotlin/net/halfbinary/scavengerhuntapi/model/request/ItemUpdateRequest.kt @@ -0,0 +1,6 @@ +package net.halfbinary.scavengerhuntapi.model.request + +data class ItemUpdateRequest( + val name: String?, + val points: Int? +) \ No newline at end of file diff --git a/src/main/kotlin/net/halfbinary/scavengerhuntapi/repository/HuntItemRepository.kt b/src/main/kotlin/net/halfbinary/scavengerhuntapi/repository/HuntItemRepository.kt index 5e0523e..10ee23b 100644 --- a/src/main/kotlin/net/halfbinary/scavengerhuntapi/repository/HuntItemRepository.kt +++ b/src/main/kotlin/net/halfbinary/scavengerhuntapi/repository/HuntItemRepository.kt @@ -1,9 +1,13 @@ package net.halfbinary.scavengerhuntapi.repository +import net.halfbinary.scavengerhuntapi.model.HuntId +import net.halfbinary.scavengerhuntapi.model.ItemId import net.halfbinary.scavengerhuntapi.model.record.HuntItemRecord import org.springframework.data.jpa.repository.JpaRepository import org.springframework.stereotype.Repository import java.util.* @Repository -interface HuntItemRepository : JpaRepository +interface HuntItemRepository : JpaRepository { + fun findByHuntIdAndItemId(huntId: HuntId, itemId: ItemId): HuntItemRecord? +} diff --git a/src/main/kotlin/net/halfbinary/scavengerhuntapi/service/HuntService.kt b/src/main/kotlin/net/halfbinary/scavengerhuntapi/service/HuntService.kt index bbe6352..d77959d 100644 --- a/src/main/kotlin/net/halfbinary/scavengerhuntapi/service/HuntService.kt +++ b/src/main/kotlin/net/halfbinary/scavengerhuntapi/service/HuntService.kt @@ -3,12 +3,14 @@ package net.halfbinary.scavengerhuntapi.service import net.halfbinary.scavengerhuntapi.error.exception.NotFoundException import net.halfbinary.scavengerhuntapi.model.HuntId import net.halfbinary.scavengerhuntapi.model.HunterId +import net.halfbinary.scavengerhuntapi.model.ItemId import net.halfbinary.scavengerhuntapi.model.converter.toDomain import net.halfbinary.scavengerhuntapi.model.converter.toRecord import net.halfbinary.scavengerhuntapi.model.domain.Hunt import net.halfbinary.scavengerhuntapi.model.domain.HuntItem import net.halfbinary.scavengerhuntapi.model.domain.Item import net.halfbinary.scavengerhuntapi.model.request.HuntStatus +import net.halfbinary.scavengerhuntapi.model.request.ItemUpdateRequest import net.halfbinary.scavengerhuntapi.repository.HuntItemRepository import net.halfbinary.scavengerhuntapi.repository.HuntRepository import net.halfbinary.scavengerhuntapi.repository.ItemRepository @@ -75,4 +77,23 @@ class HuntService( huntItemRepository.save(HuntItem(huntId = huntId, itemId = savedItem.id).toRecord()) return savedItem } + + fun updateItem(huntId: HuntId, itemId: ItemId, request: ItemUpdateRequest): Item { + huntItemRepository.findByHuntIdAndItemId(huntId, itemId) + ?: throw NotFoundException("No item with id $itemId found in hunt $huntId") + val existing = itemRepository.findByIdOrNull(itemId) + ?: throw NotFoundException("No item with id $itemId found") + val updated = existing.copy( + name = request.name ?: existing.name, + points = request.points ?: existing.points + ) + return itemRepository.save(updated).toDomain() + } + + fun deleteItem(huntId: HuntId, itemId: ItemId) { + val huntItem = huntItemRepository.findByHuntIdAndItemId(huntId, itemId) + ?: throw NotFoundException("No item with id $itemId found in hunt $huntId") + huntItemRepository.delete(huntItem) + itemRepository.deleteById(itemId) + } } \ No newline at end of file