1 package de.dlr.shepard.context.collection.endpoints;
2
3 import de.dlr.shepard.auth.permission.io.PermissionsIO;
4 import de.dlr.shepard.auth.permission.model.Permissions;
5 import de.dlr.shepard.auth.permission.model.Roles;
6 import de.dlr.shepard.auth.security.AuthenticationContext;
7 import de.dlr.shepard.common.filters.Subscribable;
8 import de.dlr.shepard.common.util.Constants;
9 import de.dlr.shepard.common.util.QueryParamHelper;
10 import de.dlr.shepard.context.collection.entities.Collection;
11 import de.dlr.shepard.context.collection.io.CollectionIO;
12 import de.dlr.shepard.context.collection.services.CollectionService;
13 import de.dlr.shepard.context.export.ExportService;
14 import jakarta.enterprise.context.RequestScoped;
15 import jakarta.inject.Inject;
16 import jakarta.validation.Valid;
17 import jakarta.validation.constraints.NotNull;
18 import jakarta.validation.constraints.PositiveOrZero;
19 import jakarta.ws.rs.Consumes;
20 import jakarta.ws.rs.DELETE;
21 import jakarta.ws.rs.GET;
22 import jakarta.ws.rs.POST;
23 import jakarta.ws.rs.PUT;
24 import jakarta.ws.rs.Path;
25 import jakarta.ws.rs.PathParam;
26 import jakarta.ws.rs.Produces;
27 import jakarta.ws.rs.QueryParam;
28 import jakarta.ws.rs.core.MediaType;
29 import jakarta.ws.rs.core.Response;
30 import jakarta.ws.rs.core.Response.Status;
31 import java.io.IOException;
32 import java.io.InputStream;
33 import java.util.ArrayList;
34 import java.util.UUID;
35 import org.eclipse.microprofile.openapi.annotations.Operation;
36 import org.eclipse.microprofile.openapi.annotations.enums.SchemaType;
37 import org.eclipse.microprofile.openapi.annotations.media.Content;
38 import org.eclipse.microprofile.openapi.annotations.media.Schema;
39 import org.eclipse.microprofile.openapi.annotations.parameters.Parameter;
40 import org.eclipse.microprofile.openapi.annotations.parameters.RequestBody;
41 import org.eclipse.microprofile.openapi.annotations.responses.APIResponse;
42 import org.eclipse.microprofile.openapi.annotations.tags.Tag;
43
44 @Path(Constants.COLLECTIONS)
45 @Produces(MediaType.APPLICATION_JSON)
46 @Consumes(MediaType.APPLICATION_JSON)
47 @RequestScoped
48 public class CollectionRest {
49
50 @Inject
51 CollectionService collectionService;
52
53 @Inject
54 ExportService exportService;
55
56 @Inject
57 AuthenticationContext authenticationContext;
58
59 @GET
60 @Tag(name = Constants.COLLECTION)
61 @Operation(description = "Get all collections")
62 @APIResponse(
63 description = "ok",
64 responseCode = "200",
65 content = @Content(schema = @Schema(type = SchemaType.ARRAY, implementation = CollectionIO.class))
66 )
67 @APIResponse(description = "not found", responseCode = "404")
68 @APIResponse(responseCode = "401", description = "not authorized")
69 @APIResponse(responseCode = "400", description = "bad request")
70 @Parameter(name = Constants.QP_NAME)
71 @Parameter(name = Constants.QP_PAGE)
72 @Parameter(name = Constants.QP_SIZE)
73 @Parameter(name = Constants.QP_ORDER_BY_ATTRIBUTE)
74 @Parameter(name = Constants.QP_ORDER_DESC)
75 public Response getAllCollections(
76 @QueryParam(Constants.QP_NAME) String name,
77 @QueryParam(Constants.QP_PAGE) @PositiveOrZero Integer page,
78 @QueryParam(Constants.QP_SIZE) @PositiveOrZero Integer size,
79 @QueryParam(Constants.QP_ORDER_BY_ATTRIBUTE) DataObjectAttributes orderBy,
80 @QueryParam(Constants.QP_ORDER_DESC) Boolean orderDesc
81 ) {
82 var params = new QueryParamHelper();
83 if (name != null) params = params.withName(name);
84 if (page != null && size != null) params = params.withPageAndSize(page, size);
85 if (orderBy != null) params = params.withOrderByAttribute(orderBy, orderDesc);
86 var collections = collectionService.getAllCollections(params);
87
88 var result = new ArrayList<CollectionIO>(collections.size());
89 for (var collection : collections) {
90 result.add(new CollectionIO(collection));
91 }
92 return Response.ok(result).build();
93 }
94
95 @GET
96 @Path("/{" + Constants.COLLECTION_ID + "}")
97 @Tag(name = Constants.COLLECTION)
98 @Operation(description = "Get collection")
99 @APIResponse(
100 description = "ok",
101 responseCode = "200",
102 content = @Content(schema = @Schema(implementation = CollectionIO.class))
103 )
104 @APIResponse(responseCode = "400", description = "bad request")
105 @APIResponse(responseCode = "401", description = "not authorized")
106 @APIResponse(responseCode = "403", description = "forbidden")
107 @APIResponse(responseCode = "404", description = "not found")
108 @Parameter(name = Constants.COLLECTION_ID)
109 @Parameter(name = Constants.VERSION_UID)
110 public Response getCollection(
111 @PathParam(Constants.COLLECTION_ID) @NotNull @PositiveOrZero Long collectionId,
112 @QueryParam(Constants.VERSION_UID) @org.hibernate.validator.constraints.UUID String versionUID
113 ) {
114
115
116 UUID versionUUID = null;
117 if (versionUID != null) {
118 versionUUID = UUID.fromString(versionUID);
119 }
120
121 Collection collection = collectionService.getCollectionWithDataObjectsAndIncomingReferences(
122 collectionId,
123 versionUUID
124 );
125 return Response.ok(new CollectionIO(collection)).build();
126 }
127
128 @PUT
129 @Path("/{" + Constants.COLLECTION_ID + "}")
130 @Subscribable
131 @Tag(name = Constants.COLLECTION)
132 @Operation(description = "Update collection")
133 @APIResponse(
134 description = "ok",
135 responseCode = "200",
136 content = @Content(schema = @Schema(implementation = CollectionIO.class))
137 )
138 @Parameter(name = Constants.COLLECTION_ID)
139 @APIResponse(responseCode = "400", description = "bad request")
140 @APIResponse(responseCode = "401", description = "not authorized")
141 @APIResponse(responseCode = "403", description = "forbidden")
142 @APIResponse(responseCode = "404", description = "not found")
143 public Response updateCollection(
144 @PathParam(Constants.COLLECTION_ID) @NotNull @PositiveOrZero Long collectionId,
145 @RequestBody(
146 required = true,
147 content = @Content(schema = @Schema(implementation = CollectionIO.class))
148 ) @Valid CollectionIO collection
149 ) {
150 Collection updatedCollection = collectionService.updateCollectionByShepardId(collectionId, collection);
151 return Response.ok(new CollectionIO(updatedCollection)).build();
152 }
153
154 @DELETE
155 @Path("/{" + Constants.COLLECTION_ID + "}")
156 @Subscribable
157 @Tag(name = Constants.COLLECTION)
158 @Operation(description = "Delete collection")
159 @APIResponse(responseCode = "400", description = "bad request")
160 @APIResponse(responseCode = "401", description = "not authorized")
161 @APIResponse(responseCode = "403", description = "forbidden")
162 @APIResponse(responseCode = "404", description = "not found")
163 @Parameter(name = Constants.COLLECTION_ID)
164 public Response deleteCollection(@PathParam(Constants.COLLECTION_ID) @NotNull @PositiveOrZero Long collectionId) {
165 collectionService.deleteCollection(collectionId);
166 return Response.status(Status.NO_CONTENT).build();
167 }
168
169 @GET
170 @Path("/{" + Constants.COLLECTION_ID + "}/" + Constants.PERMISSIONS)
171 @Tag(name = Constants.COLLECTION)
172 @Operation(description = "Get permissions")
173 @APIResponse(
174 description = "ok",
175 responseCode = "200",
176 content = @Content(schema = @Schema(implementation = PermissionsIO.class))
177 )
178 @APIResponse(responseCode = "400", description = "bad request")
179 @APIResponse(responseCode = "401", description = "not authorized")
180 @APIResponse(responseCode = "403", description = "forbidden")
181 @APIResponse(responseCode = "404", description = "not found")
182 @Parameter(name = Constants.COLLECTION_ID)
183 public Response getCollectionPermissions(
184 @PathParam(Constants.COLLECTION_ID) @NotNull @PositiveOrZero Long collectionId
185 ) {
186 Permissions permissions = collectionService.getCollectionPermissions(collectionId);
187 return Response.ok(new PermissionsIO(permissions)).build();
188 }
189
190 @PUT
191 @Path("/{" + Constants.COLLECTION_ID + "}/" + Constants.PERMISSIONS)
192 @Tag(name = Constants.COLLECTION)
193 @Operation(description = "Edit permissions")
194 @APIResponse(
195 description = "ok",
196 responseCode = "200",
197 content = @Content(schema = @Schema(implementation = PermissionsIO.class))
198 )
199 @APIResponse(responseCode = "400", description = "bad request")
200 @APIResponse(responseCode = "401", description = "not authorized")
201 @APIResponse(responseCode = "403", description = "forbidden")
202 @APIResponse(responseCode = "404", description = "not found")
203 @Parameter(name = Constants.COLLECTION_ID)
204 public Response editCollectionPermissions(
205 @PathParam(Constants.COLLECTION_ID) @NotNull @PositiveOrZero Long collectionId,
206 @RequestBody(
207 required = true,
208 content = @Content(schema = @Schema(implementation = PermissionsIO.class))
209 ) @Valid PermissionsIO newPermissions
210 ) {
211 Permissions updatedPermissions = collectionService.updateCollectionPermissions(newPermissions, collectionId);
212
213 return Response.ok(new PermissionsIO(updatedPermissions)).build();
214 }
215
216 @GET
217 @Path("/{" + Constants.COLLECTION_ID + "}/" + Constants.ROLES)
218 @Tag(name = Constants.COLLECTION)
219 @Operation(description = "Get roles")
220 @APIResponse(
221 description = "ok",
222 responseCode = "200",
223 content = @Content(schema = @Schema(implementation = Roles.class))
224 )
225 @APIResponse(responseCode = "400", description = "bad request")
226 @APIResponse(responseCode = "401", description = "not authorized")
227 @APIResponse(responseCode = "403", description = "forbidden")
228 @APIResponse(responseCode = "404", description = "not found")
229 @Parameter(name = Constants.COLLECTION_ID)
230 public Response getCollectionRoles(@PathParam(Constants.COLLECTION_ID) @NotNull @PositiveOrZero Long collectionId) {
231 Roles roles = collectionService.getCollectionRoles(collectionId);
232 return Response.ok(roles).build();
233 }
234
235 @POST
236 @Tag(name = Constants.COLLECTION)
237 @Operation(description = "Create a new collection")
238 @APIResponse(
239 description = "created",
240 responseCode = "201",
241 content = @Content(schema = @Schema(implementation = CollectionIO.class))
242 )
243 @APIResponse(responseCode = "400", description = "bad request")
244 @APIResponse(responseCode = "403", description = "forbidden")
245 @APIResponse(responseCode = "404", description = "not found")
246 public Response createCollection(
247 @RequestBody(
248 required = true,
249 content = @Content(schema = @Schema(implementation = CollectionIO.class))
250 ) @Valid CollectionIO collection
251 ) {
252 Collection newCollection = collectionService.createCollection(collection);
253 return Response.ok(new CollectionIO(newCollection)).status(Status.CREATED).build();
254 }
255
256 @GET
257 @Path("/{" + Constants.COLLECTION_ID + "}/" + Constants.EXPORT)
258 @Produces(MediaType.APPLICATION_OCTET_STREAM)
259 @Tag(name = Constants.COLLECTION)
260 @Operation(description = "Export Collection as RoCrate")
261 @APIResponse(
262 description = "ok",
263 responseCode = "200",
264 content = @Content(
265 mediaType = MediaType.APPLICATION_OCTET_STREAM,
266 schema = @Schema(type = SchemaType.STRING, format = "binary")
267 )
268 )
269 @APIResponse(responseCode = "400", description = "bad request")
270 @APIResponse(responseCode = "401", description = "not authorized")
271 @APIResponse(responseCode = "403", description = "forbidden")
272 @APIResponse(responseCode = "404", description = "not found")
273 @Parameter(name = Constants.COLLECTION_ID)
274 public Response exportCollection(@PathParam(Constants.COLLECTION_ID) @NotNull @PositiveOrZero Long collectionId)
275 throws IOException {
276 InputStream is = exportService.exportCollectionByShepardId(collectionId);
277 return Response.ok(is, MediaType.APPLICATION_OCTET_STREAM)
278 .header("Content-Disposition", "attachment; filename=\"export.zip\"")
279 .build();
280 }
281 }