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