From 3bf5fc89403b6bc744fbb2fd58279876134e910f Mon Sep 17 00:00:00 2001 From: DualFroz Date: Mon, 24 Aug 2026 18:50:58 +0200 Subject: [PATCH] feat: add resource REST endpoints --- .../slotline/resource/ResourceController.java | 67 +++++++++++++++++++ .../resource/dto/ResourceRequest.java | 16 +++++ .../resource/dto/ResourceResponse.java | 28 ++++++++ 3 files changed, 111 insertions(+) create mode 100644 src/main/java/com/slotline/resource/ResourceController.java create mode 100644 src/main/java/com/slotline/resource/dto/ResourceRequest.java create mode 100644 src/main/java/com/slotline/resource/dto/ResourceResponse.java diff --git a/src/main/java/com/slotline/resource/ResourceController.java b/src/main/java/com/slotline/resource/ResourceController.java new file mode 100644 index 0000000..5662f1d --- /dev/null +++ b/src/main/java/com/slotline/resource/ResourceController.java @@ -0,0 +1,67 @@ +package com.slotline.resource; + +import com.slotline.resource.dto.ResourceRequest; +import com.slotline.resource.dto.ResourceResponse; +import com.slotline.security.AuthenticatedUser; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import org.springframework.http.HttpStatus; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +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.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +@RestController +@RequestMapping("/api/resources") +@Tag(name = "Resources") +public class ResourceController { + + private final ResourceService resourceService; + + public ResourceController(ResourceService resourceService) { + this.resourceService = resourceService; + } + + @GetMapping + @Operation(summary = "List bookable resources in the caller's organization") + public List list(@AuthenticationPrincipal AuthenticatedUser actor) { + return resourceService.findAll(actor.organizationId()); + } + + @GetMapping("/{id}") + @Operation(summary = "Get a single resource") + public ResourceResponse get(@AuthenticationPrincipal AuthenticatedUser actor, @PathVariable Long id) { + return resourceService.findById(actor.organizationId(), id); + } + + @PostMapping + @ResponseStatus(HttpStatus.CREATED) + @Operation(summary = "Create a resource (ADMIN only)") + public ResourceResponse create(@AuthenticationPrincipal AuthenticatedUser actor, + @Valid @RequestBody ResourceRequest request) { + return resourceService.create(actor.organizationId(), request); + } + + @PutMapping("/{id}") + @Operation(summary = "Update a resource (ADMIN only)") + public ResourceResponse update(@AuthenticationPrincipal AuthenticatedUser actor, @PathVariable Long id, + @Valid @RequestBody ResourceRequest request) { + return resourceService.update(actor.organizationId(), id, request); + } + + @DeleteMapping("/{id}") + @ResponseStatus(HttpStatus.NO_CONTENT) + @Operation(summary = "Delete a resource (ADMIN only)") + public void delete(@AuthenticationPrincipal AuthenticatedUser actor, @PathVariable Long id) { + resourceService.delete(actor.organizationId(), id); + } +} diff --git a/src/main/java/com/slotline/resource/dto/ResourceRequest.java b/src/main/java/com/slotline/resource/dto/ResourceRequest.java new file mode 100644 index 0000000..30cb54e --- /dev/null +++ b/src/main/java/com/slotline/resource/dto/ResourceRequest.java @@ -0,0 +1,16 @@ +package com.slotline.resource.dto; + +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Size; + +public record ResourceRequest( + @NotBlank @Size(max = 128) String name, + @Size(max = 512) String description, + @Size(max = 64) String zoneId, + @Min(0) Integer bufferMinutes) { + + public ResourceRequest(String name, String description) { + this(name, description, null, null); + } +} diff --git a/src/main/java/com/slotline/resource/dto/ResourceResponse.java b/src/main/java/com/slotline/resource/dto/ResourceResponse.java new file mode 100644 index 0000000..dc55d53 --- /dev/null +++ b/src/main/java/com/slotline/resource/dto/ResourceResponse.java @@ -0,0 +1,28 @@ +package com.slotline.resource.dto; + +import com.slotline.resource.Resource; + +import java.time.Instant; + +public record ResourceResponse( + Long id, + Long organizationId, + Long groupId, + String name, + String description, + String zoneId, + int bufferMinutes, + Instant createdAt) { + + public static ResourceResponse from(Resource resource) { + return new ResourceResponse( + resource.getId(), + resource.getOrganizationId(), + resource.getGroupId(), + resource.getName(), + resource.getDescription(), + resource.getZoneId(), + resource.getBufferMinutes(), + resource.getCreatedAt()); + } +}