1 package de.dlr.shepard.integrationtests;
2
3 import static io.restassured.RestAssured.given;
4 import static org.assertj.core.api.Assertions.assertThat;
5
6 import de.dlr.shepard.auth.permission.io.PermissionsIO;
7 import de.dlr.shepard.auth.users.io.UserGroupIO;
8 import de.dlr.shepard.common.search.io.QueryType;
9 import de.dlr.shepard.common.search.io.ResponseBody;
10 import de.dlr.shepard.common.search.io.ResultTriple;
11 import de.dlr.shepard.common.search.io.SearchBody;
12 import de.dlr.shepard.common.search.io.SearchParams;
13 import de.dlr.shepard.common.search.io.SearchScope;
14 import de.dlr.shepard.common.util.Constants;
15 import de.dlr.shepard.common.util.TraversalRules;
16 import de.dlr.shepard.context.collection.io.CollectionIO;
17 import de.dlr.shepard.context.semantic.SemanticRepositoryType;
18 import de.dlr.shepard.context.semantic.io.SemanticAnnotationIO;
19 import de.dlr.shepard.context.semantic.io.SemanticRepositoryIO;
20 import io.quarkus.test.common.WithTestResource;
21 import io.quarkus.test.junit.QuarkusIntegrationTest;
22 import java.util.Map;
23 import org.junit.jupiter.api.BeforeAll;
24 import org.junit.jupiter.api.MethodOrderer;
25 import org.junit.jupiter.api.Order;
26 import org.junit.jupiter.api.Test;
27 import org.junit.jupiter.api.TestMethodOrder;
28
29 @QuarkusIntegrationTest
30 @WithTestResource(WireMockResource.class)
31 @TestMethodOrder(MethodOrderer.OrderAnnotation.class)
32 public class CollectionSearcherIT extends BaseTestCaseIT {
33
34 private static String collectionsURL;
35 private static CollectionIO collection1;
36 private static CollectionIO collection2;
37 private static String searchURL;
38
39 private static String repositoryURL;
40 private static SemanticRepositoryIO repository;
41 private static SemanticAnnotationIO annotation;
42 private static CollectionIO annotatedCollection;
43 private static String annotatedCollectionURL;
44
45 @BeforeAll
46 public static void setUp() {
47 collectionsURL = "/" + Constants.COLLECTIONS;
48
49 var payload1 = new CollectionIO();
50 payload1.setName("CollectionDummy");
51 payload1.setDescription("First Collection");
52 payload1.setAttributes(Map.of("a", "1", "b", "2"));
53 collection1 = given()
54 .spec(requestSpecOfDefaultUser)
55 .body(payload1)
56 .when()
57 .post(collectionsURL)
58 .then()
59 .statusCode(201)
60 .extract()
61 .as(CollectionIO.class);
62 var payload2 = new CollectionIO();
63 payload2.setName("secondCollectionDummy");
64 payload2.setDescription("Second Collection");
65 collection2 = given()
66 .spec(requestSpecOfDefaultUser)
67 .body(payload2)
68 .when()
69 .post(collectionsURL)
70 .then()
71 .statusCode(201)
72 .extract()
73 .as(CollectionIO.class);
74 searchURL = "/" + Constants.SEARCH;
75
76
77 repositoryURL = "/" + Constants.SEMANTIC_REPOSITORIES;
78 annotatedCollection = createCollection("SemanticsCollection");
79 annotatedCollectionURL = "/%s/%d/semanticAnnotations".formatted(Constants.COLLECTIONS, annotatedCollection.getId());
80 var repositoryToCreate = new SemanticRepositoryIO();
81 repositoryToCreate.setName("SemanticRepository");
82 repositoryToCreate.setType(SemanticRepositoryType.SPARQL);
83 repositoryToCreate.setEndpoint(WireMockResource.getWireMockServerURlWithPath("/sparql"));
84 repository = given()
85 .spec(requestSpecOfDefaultUser)
86 .body(repositoryToCreate)
87 .when()
88 .post(repositoryURL)
89 .then()
90 .statusCode(201)
91 .extract()
92 .as(SemanticRepositoryIO.class);
93
94 var annotationToCreate = new SemanticAnnotationIO();
95 annotationToCreate.setPropertyIRI("http://dbpedia.org/ontology/ingredient");
96 annotationToCreate.setPropertyRepositoryId(repository.getId());
97 annotationToCreate.setValueIRI("http://dbpedia.org/resource/Almond_milk");
98 annotationToCreate.setValueRepositoryId(repository.getId());
99 annotation = given()
100 .spec(requestSpecOfDefaultUser)
101 .body(annotationToCreate)
102 .when()
103 .post(annotatedCollectionURL)
104 .then()
105 .statusCode(201)
106 .extract()
107 .as(SemanticAnnotationIO.class);
108 }
109
110 @Test
111 @Order(1)
112 public void findOneOutOfTwoCollectionsTest() {
113 SearchBody searchBody = new SearchBody();
114 SearchScope searchScope = new SearchScope();
115 searchScope.setTraversalRules(new TraversalRules[] {});
116 searchBody.setScopes(new SearchScope[] { searchScope });
117 SearchParams searchParams = new SearchParams();
118 searchParams.setQueryType(QueryType.Collection);
119 String query =
120 """
121 {
122 "OR": [
123 {
124 "property": "id",
125 "value": %d,
126 "operator": "eq"
127 },
128 {
129 "property": "number",
130 "value": 123,
131 "operator": "le"
132 }
133 ]}""".formatted(collection1.getId());
134 searchParams.setQuery(query);
135 searchBody.setSearchParams(searchParams);
136 var result = given()
137 .spec(requestSpecOfDefaultUser)
138 .body(searchBody)
139 .when()
140 .post(searchURL)
141 .then()
142 .statusCode(200)
143 .extract()
144 .as(ResponseBody.class);
145 ResultTriple triple1 = new ResultTriple(collection1.getId(), null, null);
146 assertThat(result.getResultSet()).containsExactly(triple1);
147 assertThat(result.getResults()[0].getId()).isEqualTo(collection1.getId());
148 assertThat(result.getSearchParams()).isEqualTo(searchParams);
149 }
150
151 @Test
152 @Order(2)
153 public void findCollectionByAttribute() {
154 SearchBody searchBody = new SearchBody();
155 SearchScope searchScope = new SearchScope();
156 searchScope.setTraversalRules(new TraversalRules[] {});
157 searchBody.setScopes(new SearchScope[] { searchScope });
158 SearchParams searchParams = new SearchParams();
159 searchParams.setQueryType(QueryType.Collection);
160 String query =
161 """
162 {
163 "AND": [
164 {
165 "property": "id",
166 "value": %d,
167 "operator": "eq"
168 },
169 {
170 "property": "attributes.a",
171 "value": "1",
172 "operator": "eq"
173 }
174 ]
175 }""".formatted(collection1.getId());
176 searchParams.setQuery(query);
177 searchBody.setSearchParams(searchParams);
178 var result = given()
179 .spec(requestSpecOfDefaultUser)
180 .body(searchBody)
181 .when()
182 .post(searchURL)
183 .then()
184 .statusCode(200)
185 .extract()
186 .as(ResponseBody.class);
187 ResultTriple triple1 = new ResultTriple(collection1.getId(), null, null);
188 assertThat(result.getResultSet()).containsExactly(triple1);
189 assertThat(result.getResults()[0].getId()).isEqualTo(collection1.getId());
190 assertThat(result.getSearchParams()).isEqualTo(searchParams);
191 }
192
193 @Test
194 @Order(3)
195 public void neTest() {
196 SearchBody searchBody = new SearchBody();
197 SearchScope searchScope = new SearchScope();
198 searchScope.setTraversalRules(new TraversalRules[] {});
199 searchBody.setScopes(new SearchScope[] { searchScope });
200 SearchParams searchParams = new SearchParams();
201 searchParams.setQueryType(QueryType.Collection);
202 String query =
203 """
204 {
205 "property": "id",
206 "value": %d,
207 "operator": "ne"
208 }""".formatted(collection1.getId());
209 searchParams.setQuery(query);
210 searchBody.setSearchParams(searchParams);
211 var result = given()
212 .spec(requestSpecOfDefaultUser)
213 .body(searchBody)
214 .when()
215 .post(searchURL)
216 .then()
217 .statusCode(200)
218 .extract()
219 .as(ResponseBody.class);
220 ResultTriple triple1 = new ResultTriple(collection1.getId(), null, null);
221 assertThat(result.getResultSet()).doesNotContain(triple1);
222 }
223
224 @Test
225 @Order(4)
226 public void findTwoOutOfTwoCollectionsTest() {
227 SearchBody searchBody = new SearchBody();
228 SearchScope searchScope = new SearchScope();
229 searchScope.setTraversalRules(new TraversalRules[] {});
230 searchBody.setScopes(new SearchScope[] { searchScope });
231 SearchParams searchParams = new SearchParams();
232 searchParams.setQueryType(QueryType.Collection);
233 String query =
234 """
235 {
236 "OR": [
237 {
238 "property": "id",
239 "value": %d,
240 "operator": "ge"
241 },
242 {
243 "property": "id",
244 "value": %d,
245 "operator": "le"
246 }
247 ]}""".formatted(collection1.getId(), collection2.getId());
248 searchParams.setQuery(query);
249 searchBody.setSearchParams(searchParams);
250 var result = given()
251 .spec(requestSpecOfDefaultUser)
252 .body(searchBody)
253 .when()
254 .post(searchURL)
255 .then()
256 .statusCode(200)
257 .extract()
258 .as(ResponseBody.class);
259 ResultTriple triple1 = new ResultTriple(collection1.getId(), null, null);
260 ResultTriple triple2 = new ResultTriple(collection2.getId(), null, null);
261 assertThat(result.getResultSet()).contains(triple1, triple2);
262 }
263
264 @Test
265 @Order(5)
266 public void findNoCollectionTest() {
267 SearchBody searchBody = new SearchBody();
268 SearchScope searchScope = new SearchScope();
269 searchScope.setTraversalRules(new TraversalRules[] {});
270 searchBody.setScopes(new SearchScope[] { searchScope });
271 SearchParams searchParams = new SearchParams();
272 searchParams.setQueryType(QueryType.Collection);
273 String query =
274 """
275 {
276 "AND": [
277 {
278 "property": "id",
279 "value": %d,
280 "operator": "gt"
281 },
282 {
283 "property": "id",
284 "value": %d,
285 "operator": "gt"
286 }
287 ]}""".formatted(collection1.getId(), collection2.getId());
288 searchParams.setQuery(query);
289 searchBody.setSearchParams(searchParams);
290 var result = given()
291 .spec(requestSpecOfDefaultUser)
292 .body(searchBody)
293 .when()
294 .post(searchURL)
295 .then()
296 .statusCode(200)
297 .extract()
298 .as(ResponseBody.class);
299 ResultTriple triple1 = new ResultTriple(collection1.getId(), null, null);
300 ResultTriple triple2 = new ResultTriple(collection2.getId(), null, null);
301 assertThat(result.getResultSet()).doesNotContain(triple1, triple2);
302 }
303
304 @Test
305 @Order(6)
306 public void findByAndTest() {
307 SearchBody searchBody = new SearchBody();
308 SearchScope searchScope = new SearchScope();
309 searchScope.setTraversalRules(new TraversalRules[] {});
310 searchBody.setScopes(new SearchScope[] { searchScope });
311 SearchParams searchParams = new SearchParams();
312 searchParams.setQueryType(QueryType.Collection);
313 String query =
314 """
315 {
316 "AND": [
317 {
318 "property": "id",
319 "value": %d,
320 "operator": "eq"
321 },
322 {
323 "property": "name",
324 "value": "%s",
325 "operator": "eq"
326 }
327 ]}""".formatted(collection1.getId(), collection1.getName());
328 searchParams.setQuery(query);
329 searchBody.setSearchParams(searchParams);
330 var result = given()
331 .spec(requestSpecOfDefaultUser)
332 .body(searchBody)
333 .when()
334 .post(searchURL)
335 .then()
336 .statusCode(200)
337 .extract()
338 .as(ResponseBody.class);
339 ResultTriple triple1 = new ResultTriple(collection1.getId(), null, null);
340 ResultTriple triple2 = new ResultTriple(collection2.getId(), null, null);
341 assertThat(result.getResultSet()).contains(triple1);
342 assertThat(result.getResultSet()).doesNotContain(triple2);
343 }
344
345 @Test
346 @Order(7)
347 public void unauthorizedCollectionsSearchTest() {
348 SearchBody searchBody = new SearchBody();
349 SearchScope searchScope = new SearchScope();
350 searchScope.setTraversalRules(new TraversalRules[] {});
351 searchBody.setScopes(new SearchScope[] { searchScope });
352 SearchParams searchParams = new SearchParams();
353 searchParams.setQueryType(QueryType.Collection);
354 String query =
355 """
356 {
357 "OR": [
358 {
359 "property": "id",
360 "value": %d,
361 "operator": "ge"
362 },
363 {
364 "property": "id",
365 "value": %d,
366 "operator": "le"
367 }
368 ]}""".formatted(collection1.getId(), collection2.getId());
369 searchParams.setQuery(query);
370 searchBody.setSearchParams(searchParams);
371 var result = given()
372 .spec(requestSpecOfOtherUser)
373 .body(searchBody)
374 .when()
375 .post(searchURL)
376 .then()
377 .statusCode(200)
378 .extract()
379 .as(ResponseBody.class);
380 ResultTriple triple1 = new ResultTriple(collection1.getId(), null, null);
381 ResultTriple triple2 = new ResultTriple(collection2.getId(), null, null);
382 assertThat(result.getResultSet()).doesNotContain(triple1, triple2);
383 }
384
385 @Test
386 @Order(8)
387 public void authorizedCollectionsSearchTest() {
388 String permissionsURL = "/collections/" + collection1.getId() + "/permissions";
389 PermissionsIO permissions = given()
390 .spec(requestSpecOfDefaultUser)
391 .when()
392 .get(permissionsURL)
393 .then()
394 .statusCode(200)
395 .extract()
396 .as(PermissionsIO.class);
397 String[] reader = { otherUser.getUser().getUsername() };
398 permissions.setReader(reader);
399 given()
400 .spec(requestSpecOfDefaultUser)
401 .body(permissions)
402 .when()
403 .put(permissionsURL)
404 .then()
405 .statusCode(200)
406 .extract()
407 .as(PermissionsIO.class);
408 SearchBody searchBody = new SearchBody();
409 SearchScope searchScope = new SearchScope();
410 searchScope.setTraversalRules(new TraversalRules[] {});
411 searchBody.setScopes(new SearchScope[] { searchScope });
412 SearchParams searchParams = new SearchParams();
413 searchParams.setQueryType(QueryType.Collection);
414 String query =
415 """
416 {
417 "OR": [
418 {
419 "property": "id",
420 "value": %d,
421 "operator": "ge"
422 },
423 {
424 "property": "id",
425 "value": %d,
426 "operator": "le"
427 }
428 ]}""".formatted(collection1.getId(), collection2.getId());
429 searchParams.setQuery(query);
430 searchBody.setSearchParams(searchParams);
431 var result = given()
432 .spec(requestSpecOfOtherUser)
433 .body(searchBody)
434 .when()
435 .post(searchURL)
436 .then()
437 .statusCode(200)
438 .extract()
439 .as(ResponseBody.class);
440 ResultTriple triple1 = new ResultTriple(collection1.getId(), null, null);
441 ResultTriple triple2 = new ResultTriple(collection2.getId(), null, null);
442 assertThat(result.getResultSet()).contains(triple1);
443 assertThat(result.getResultSet()).doesNotContain(triple2);
444 }
445
446 @Test
447 @Order(9)
448 public void collectionsSearchTestReaderGroup() {
449 String userGroupURL = "/" + Constants.USERGROUPS;
450 UserGroupIO userGroup = new UserGroupIO();
451 userGroup.setName("userGroup");
452 userGroup.setUsernames(new String[] { otherUser.getUser().getUsername() });
453 UserGroupIO userGroupCreated = given()
454 .spec(requestSpecOfDefaultUser)
455 .body(userGroup)
456 .when()
457 .post(userGroupURL)
458 .then()
459 .statusCode(201)
460 .extract()
461 .as(UserGroupIO.class);
462
463 String permissionsURL = "/" + Constants.COLLECTIONS + "/" + collection2.getId() + "/" + Constants.PERMISSIONS;
464 PermissionsIO permissions = given()
465 .spec(requestSpecOfDefaultUser)
466 .when()
467 .get(permissionsURL)
468 .then()
469 .statusCode(200)
470 .extract()
471 .as(PermissionsIO.class);
472 long[] readerGroupIds = { userGroupCreated.getId() };
473 permissions.setReaderGroupIds(readerGroupIds);
474 given()
475 .spec(requestSpecOfDefaultUser)
476 .body(permissions)
477 .when()
478 .put(permissionsURL)
479 .then()
480 .statusCode(200)
481 .extract()
482 .as(PermissionsIO.class);
483 SearchBody searchBody = new SearchBody();
484 SearchScope searchScope = new SearchScope();
485 searchScope.setTraversalRules(new TraversalRules[] {});
486 searchBody.setScopes(new SearchScope[] { searchScope });
487 SearchParams searchParams = new SearchParams();
488 searchParams.setQueryType(QueryType.Collection);
489 String query =
490 """
491 {
492 "OR": [
493 {
494 "property": "id",
495 "value": %d,
496 "operator": "ge"
497 },
498 {
499 "property": "id",
500 "value": %d,
501 "operator": "le"
502 }
503 ]}""".formatted(collection1.getId(), collection2.getId());
504 searchParams.setQuery(query);
505 searchBody.setSearchParams(searchParams);
506 var result = given()
507 .spec(requestSpecOfOtherUser)
508 .body(searchBody)
509 .when()
510 .post(searchURL)
511 .then()
512 .statusCode(200)
513 .extract()
514 .as(ResponseBody.class);
515 ResultTriple triple1 = new ResultTriple(collection1.getId(), null, null);
516 ResultTriple triple2 = new ResultTriple(collection2.getId(), null, null);
517 assertThat(result.getResultSet()).contains(triple1);
518 assertThat(result.getResultSet()).contains(triple2);
519 }
520
521 @Test
522 @Order(10)
523 public void inTest() {
524 String userGroupURL = "/" + Constants.USERGROUPS;
525 UserGroupIO userGroup = new UserGroupIO();
526 userGroup.setName("userGroup");
527 userGroup.setUsernames(new String[] { otherUser.getUser().getUsername() });
528 UserGroupIO userGroupCreated = given()
529 .spec(requestSpecOfDefaultUser)
530 .body(userGroup)
531 .when()
532 .post(userGroupURL)
533 .then()
534 .statusCode(201)
535 .extract()
536 .as(UserGroupIO.class);
537
538 String permissionsURL = "/" + Constants.COLLECTIONS + "/" + collection2.getId() + "/" + Constants.PERMISSIONS;
539 PermissionsIO permissions = given()
540 .spec(requestSpecOfDefaultUser)
541 .when()
542 .get(permissionsURL)
543 .then()
544 .statusCode(200)
545 .extract()
546 .as(PermissionsIO.class);
547 long[] readerGroupIds = { userGroupCreated.getId() };
548 permissions.setReaderGroupIds(readerGroupIds);
549 given()
550 .spec(requestSpecOfDefaultUser)
551 .body(permissions)
552 .when()
553 .put(permissionsURL)
554 .then()
555 .statusCode(200)
556 .extract()
557 .as(PermissionsIO.class);
558 SearchBody searchBody = new SearchBody();
559 SearchScope searchScope = new SearchScope();
560 searchScope.setTraversalRules(new TraversalRules[] {});
561 searchBody.setScopes(new SearchScope[] { searchScope });
562 SearchParams searchParams = new SearchParams();
563 searchParams.setQueryType(QueryType.Collection);
564 String query =
565 """
566 {
567 "property": "id",
568 "value": [%d,%d],
569 "operator": "in"
570 }""".formatted(collection1.getId(), collection2.getId());
571 searchParams.setQuery(query);
572 searchBody.setSearchParams(searchParams);
573 var result = given()
574 .spec(requestSpecOfOtherUser)
575 .body(searchBody)
576 .when()
577 .post(searchURL)
578 .then()
579 .statusCode(200)
580 .extract()
581 .as(ResponseBody.class);
582 ResultTriple triple1 = new ResultTriple(collection1.getId(), null, null);
583 ResultTriple triple2 = new ResultTriple(collection2.getId(), null, null);
584 assertThat(result.getResultSet()).contains(triple1);
585 assertThat(result.getResultSet()).contains(triple2);
586 }
587
588 @Test
589 @Order(11)
590 public void searchCollectionsViaPropertyIRI() {
591 SearchBody searchBody = new SearchBody();
592 SearchScope searchScope = new SearchScope();
593 searchScope.setTraversalRules(new TraversalRules[] {});
594 searchBody.setScopes(new SearchScope[] { searchScope });
595 SearchParams searchParams = new SearchParams();
596 searchParams.setQueryType(QueryType.Collection);
597 String query =
598 "{\"property\": \"propertyIRI\",\"value\": \"" + annotation.getPropertyIRI() + "\",\"operator\": \"eq\"}";
599 searchParams.setQuery(query);
600 searchBody.setSearchParams(searchParams);
601 var result = given()
602 .spec(requestSpecOfDefaultUser)
603 .body(searchBody)
604 .when()
605 .post(searchURL)
606 .then()
607 .statusCode(200)
608 .extract()
609 .as(ResponseBody.class);
610 ResultTriple triple = new ResultTriple(annotatedCollection.getId(), null, null);
611 assertThat(result.getResultSet()).contains(triple);
612 }
613
614 @Test
615 @Order(12)
616 public void searchCollectionsViaValueIRI() {
617 SearchBody searchBody = new SearchBody();
618 SearchScope searchScope = new SearchScope();
619 searchScope.setTraversalRules(new TraversalRules[] {});
620 searchBody.setScopes(new SearchScope[] { searchScope });
621 SearchParams searchParams = new SearchParams();
622 searchParams.setQueryType(QueryType.Collection);
623 String query =
624 "{\"property\": \"valueIRI\",\"value\": \"" +
625 annotation.getValueIRI().substring(2, 10) +
626 "\",\"operator\": \"contains\"}";
627 searchParams.setQuery(query);
628 searchBody.setSearchParams(searchParams);
629 var result = given()
630 .spec(requestSpecOfDefaultUser)
631 .body(searchBody)
632 .when()
633 .post(searchURL)
634 .then()
635 .statusCode(200)
636 .extract()
637 .as(ResponseBody.class);
638 ResultTriple triple = new ResultTriple(annotatedCollection.getId(), null, null);
639 assertThat(result.getResultSet()).contains(triple);
640 }
641 }