docs(geschichte): annotate GET /api/geschichten query parameters in OpenAPI spec (#794) #810

Merged
marcel merged 4 commits from feat/issue-794-geschichte-openapi-params into feat/issue-750-lesereisen-data-model 2026-06-12 08:44:04 +02:00
4 changed files with 47 additions and 0 deletions

View File

@@ -9,6 +9,7 @@ import org.raddatz.familienarchiv.geschichte.journeyitem.JourneyReorderDTO;
import org.raddatz.familienarchiv.security.Permission; import org.raddatz.familienarchiv.security.Permission;
import org.raddatz.familienarchiv.security.RequirePermission; import org.raddatz.familienarchiv.security.RequirePermission;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.DeleteMapping;
@@ -35,9 +36,13 @@ public class GeschichteController {
@GetMapping @GetMapping
public List<GeschichteSummary> list( public List<GeschichteSummary> list(
@Parameter(description = "Filter by status. Callers without BLOG_WRITE always receive PUBLISHED results regardless of the value passed. Callers with BLOG_WRITE requesting DRAFT receive only their own unpublished stories.")
@RequestParam(required = false) GeschichteStatus status, @RequestParam(required = false) GeschichteStatus status,
@Parameter(description = "AND-filter: story must include all supplied person IDs.")
@RequestParam(name = "personId", required = false) List<UUID> personIds, @RequestParam(name = "personId", required = false) List<UUID> personIds,
@Parameter(description = "Filter to stories containing this document.")
@RequestParam(required = false) UUID documentId, @RequestParam(required = false) UUID documentId,
@Parameter(description = "Maximum results to return. Values ≤ 0 default to 50. Clamped at 200.")
@RequestParam(required = false, defaultValue = "50") int limit) { @RequestParam(required = false, defaultValue = "50") int limit) {
return geschichteService.list( return geschichteService.list(
status, status,

View File

@@ -100,6 +100,43 @@ class GeschichteControllerTest {
verify(geschichteService).list(any(), eq(List.of(a, b)), any(), anyInt()); verify(geschichteService).list(any(), eq(List.of(a, b)), any(), anyInt());
} }
@Test
@WithMockUser(authorities = "READ_ALL")
void list_passesDocumentIdFilterToService() throws Exception {
UUID documentId = UUID.randomUUID();
when(geschichteService.list(any(), any(), eq(documentId), anyInt()))
.thenReturn(List.of());
mockMvc.perform(get("/api/geschichten").param("documentId", documentId.toString()))
.andExpect(status().isOk());
verify(geschichteService).list(any(), any(), eq(documentId), anyInt());
}
@Test
@WithMockUser(authorities = "READ_ALL")
void list_passesLimitToService() throws Exception {
when(geschichteService.list(any(), any(), any(), eq(5)))
.thenReturn(List.of());
mockMvc.perform(get("/api/geschichten").param("limit", "5"))
.andExpect(status().isOk());
verify(geschichteService).list(any(), any(), any(), eq(5));
}
@Test
@WithMockUser(authorities = "READ_ALL")
void list_passesStatusFilterToService() throws Exception {
when(geschichteService.list(eq(GeschichteStatus.PUBLISHED), any(), any(), anyInt()))
.thenReturn(List.of());
mockMvc.perform(get("/api/geschichten").param("status", "PUBLISHED"))
.andExpect(status().isOk());
verify(geschichteService).list(eq(GeschichteStatus.PUBLISHED), any(), any(), anyInt());
}
// ─── GET /api/geschichten/{id} ─────────────────────────────────────────── // ─── GET /api/geschichten/{id} ───────────────────────────────────────────
@Test @Test

View File

@@ -19,6 +19,7 @@ bun.lockb
/src/lib/paraglide/ /src/lib/paraglide/
/src/lib/paraglide_bak*/ /src/lib/paraglide_bak*/
/src/paraglide/ /src/paraglide/
/src.main/
/project.inlang/ /project.inlang/
# Test artifacts # Test artifacts

View File

@@ -3712,9 +3712,13 @@ export interface operations {
list: { list: {
parameters: { parameters: {
query?: { query?: {
/** @description Filter by status. Callers without BLOG_WRITE always receive PUBLISHED results regardless of the value passed. Callers with BLOG_WRITE requesting DRAFT receive only their own unpublished stories. */
status?: "DRAFT" | "PUBLISHED"; status?: "DRAFT" | "PUBLISHED";
/** @description AND-filter: story must include all supplied person IDs. */
personId?: string[]; personId?: string[];
/** @description Filter to stories containing this document. */
documentId?: string; documentId?: string;
/** @description Maximum results to return. Values ≤ 0 default to 50. Clamped at 200. */
limit?: number; limit?: number;
}; };
header?: never; header?: never;