From 99ba7e3a34c43877816be2e6e8227cefd946a312 Mon Sep 17 00:00:00 2001 From: Martin Weise <martin.weise@tuwien.ac.at> Date: Mon, 6 Jan 2025 19:12:41 +0100 Subject: [PATCH] Increased coverage --- .../at/tuwien/endpoints/AccessEndpoint.java | 45 +- .../tuwien/endpoints/IdentifierEndpoint.java | 139 ++-- .../at/tuwien/endpoints/ImageEndpoint.java | 7 +- .../at/tuwien/endpoints/TableEndpoint.java | 103 ++- .../at/tuwien/endpoints/UserEndpoint.java | 2 +- .../at/tuwien/endpoints/ViewEndpoint.java | 8 +- .../endpoints/AccessEndpointUnitTest.java | 168 +++-- .../endpoints/DatabaseEndpointUnitTest.java | 46 +- .../endpoints/IdentifierEndpointUnitTest.java | 600 +++++++++++++++--- .../endpoints/ImageEndpointUnitTest.java | 19 +- .../endpoints/MessageEndpointUnitTest.java | 12 +- .../endpoints/TableEndpointUnitTest.java | 238 +++++-- .../endpoints/UserEndpointUnitTest.java | 214 ++++++- .../endpoints/ViewEndpointUnitTest.java | 95 ++- .../tuwien/mvc/PrometheusEndpointMvcTest.java | 8 +- ...aCiteIdentifierServicePersistenceTest.java | 5 +- .../IdentifierServicePersistenceTest.java | 5 +- .../tuwien/service/TableServiceUnitTest.java | 21 +- .../validator/EndpointValidatorUnitTest.java | 6 +- .../at/tuwien/gateway/DataServiceGateway.java | 96 +-- .../gateway/impl/DataServiceGatewayImpl.java | 5 +- .../at/tuwien/service/IdentifierService.java | 7 +- .../java/at/tuwien/service/TableService.java | 11 +- .../impl/DataCiteIdentifierServiceImpl.java | 5 +- .../service/impl/IdentifierServiceImpl.java | 5 +- .../tuwien/service/impl/TableServiceImpl.java | 18 +- .../java/at/tuwien/test/AbstractUnitTest.java | 4 + .../main/java/at/tuwien/test/BaseTest.java | 16 +- 28 files changed, 1410 insertions(+), 498 deletions(-) diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/AccessEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/AccessEndpoint.java index 812ec7bc21..99e4d2e6b1 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/AccessEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/AccessEndpoint.java @@ -99,20 +99,20 @@ public class AccessEndpoint { log.debug("endpoint give access to database, databaseId={}, userId={}, access.type={}", databaseId, userId, data.getType()); final Database database = databaseService.findById(databaseId); - final User user = userService.findByUsername(principal.getName()); - if (!database.getOwner().equals(user)) { + final User caller = userService.findByUsername(principal.getName()); + if (!database.getOwner().getId().equals(caller.getId())) { log.error("Failed to create access: not owner"); throw new NotAllowedException("Failed to create access: not owner"); } - final User otherUser = userService.findById(userId); + final User user = userService.findById(userId); try { - accessService.find(database, otherUser); + accessService.find(database, user); log.error("Failed to create access to user with id {}: already has access", userId); throw new NotAllowedException("Failed to create access to user with id " + userId + ": already has access"); } catch (AccessNotFoundException e) { /* ignore */ } - accessService.create(database, otherUser, data.getType()); + accessService.create(database, user, data.getType()); return ResponseEntity.accepted() .build(); } @@ -159,17 +159,17 @@ public class AccessEndpoint { @NotNull Principal principal) throws NotAllowedException, DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, UserNotFoundException, AccessNotFoundException, SearchServiceException, SearchServiceConnectionException { - log.debug("endpoint modify database access, databaseId={}, userId={}, access.type={}", databaseId, userId, - data.getType()); + log.debug("endpoint modify database access, databaseId={}, userId={}, access.type={}, principal.name={}", + databaseId, userId, data.getType(), principal.getName()); final Database database = databaseService.findById(databaseId); - final User user = userService.findByUsername(principal.getName()); - if (!database.getOwner().equals(user)) { + final User caller = userService.findByUsername(principal.getName()); + if (!database.getOwner().getId().equals(caller.getId())) { log.error("Failed to update access: not owner"); throw new NotAllowedException("Failed to update access: not owner"); } - final User otherUser = userService.findById(userId); - accessService.find(database, otherUser); - accessService.update(database, otherUser, data.getType()); + final User user = userService.findById(userId); + accessService.find(database, user); + accessService.update(database, user, data.getType()); return ResponseEntity.accepted() .build(); } @@ -204,7 +204,8 @@ public class AccessEndpoint { UserNotFoundException, AccessNotFoundException, NotAllowedException { log.debug("endpoint get database access, databaseId={}, userId={}, principal.name={}", databaseId, userId, principal.getName()); - if (!userId.equals(UserUtil.getId(principal))) { + final User caller = userService.findByUsername(principal.getName()); + if (!userId.equals(caller.getId())) { if (!UserUtil.hasRole(principal, "check-foreign-database-access")) { log.error("Failed to find access: foreign user"); throw new NotAllowedException("Failed to find access: foreign user"); @@ -212,11 +213,9 @@ public class AccessEndpoint { log.trace("principal is allowed to check foreign user access"); } final Database database = databaseService.findById(databaseId); - final User otherUser = userService.findById(userId); - final DatabaseAccess access = accessService.find(database, otherUser); - final DatabaseAccessDto dto = databaseMapper.databaseAccessToDatabaseAccessDto(access); - log.trace("check access resulted in dto {}", dto); - return ResponseEntity.ok(dto); + final User user = userService.findById(userId); + final DatabaseAccess access = accessService.find(database, user); + return ResponseEntity.ok(databaseMapper.databaseAccessToDatabaseAccessDto(access)); } @DeleteMapping("/{userId}") @@ -262,14 +261,14 @@ public class AccessEndpoint { SearchServiceException, SearchServiceConnectionException { log.debug("endpoint revoke database access, databaseId={}, userId={}", databaseId, userId); final Database database = databaseService.findById(databaseId); - final User user = userService.findByUsername(principal.getName()); - if (!database.getOwner().equals(user)) { + final User caller = userService.findByUsername(principal.getName()); + if (!database.getOwner().getId().equals(caller.getId())) { log.error("Failed to revoke access: not owner"); throw new NotAllowedException("Failed to revoke access: not owner"); } - final User otherUser = userService.findById(userId); - accessService.find(database, otherUser); - accessService.delete(database, otherUser); + final User user = userService.findById(userId); + accessService.find(database, user); + accessService.delete(database, user); return ResponseEntity.accepted() .build(); } diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/IdentifierEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/IdentifierEndpoint.java index e84b7161f8..31fcd67305 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/IdentifierEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/IdentifierEndpoint.java @@ -1,6 +1,5 @@ package at.tuwien.endpoints; -import at.tuwien.api.database.query.QueryDto; import at.tuwien.api.error.ApiErrorDto; import at.tuwien.api.identifier.*; import at.tuwien.api.identifier.ld.LdDatasetDto; @@ -8,8 +7,6 @@ import at.tuwien.api.user.external.ExternalMetadataDto; import at.tuwien.config.EndpointConfig; import at.tuwien.entities.database.Database; import at.tuwien.entities.database.DatabaseAccess; -import at.tuwien.entities.database.View; -import at.tuwien.entities.database.table.Table; import at.tuwien.entities.identifier.Identifier; import at.tuwien.entities.identifier.IdentifierStatusType; import at.tuwien.entities.identifier.IdentifierType; @@ -137,8 +134,10 @@ public class IdentifierEndpoint { .toList(); log.debug("find identifier resulted in identifiers {}", resource2); return ResponseEntity.ok(resource2); + default: + log.error("accept header {} is not supported", accept); + throw new FormatNotAvailableException("Must provide either application/json or application/ld+json headers"); } - throw new FormatNotAvailableException("Must provide either application/json or application/ld+json headers"); } @GetMapping(value = "/{identifierId}", produces = {MediaType.APPLICATION_JSON_VALUE, "application/ld+json", @@ -202,56 +201,54 @@ public class IdentifierEndpoint { DataServiceException, DataServiceConnectionException, MalformedException, FormatNotAvailableException, QueryNotFoundException { log.debug("endpoint find identifier, identifierId={}, accept={}", identifierId, accept); + if (accept == null) { + accept = ""; + } final Identifier identifier = identifierService.find(identifierId); - log.info("Found persistent identifier with id {}", identifier.getId()); - log.trace("found persistent identifier {}", identifier); - if (accept != null) { - log.trace("accept header present: {}", accept); - switch (accept) { - case "application/json": - log.trace("accept header matches json"); - final IdentifierDto resource1 = metadataMapper.identifierToIdentifierDto(identifier); - log.debug("find identifier resulted in identifier {}", resource1); - return ResponseEntity.ok(resource1); - case "application/ld+json": - log.trace("accept header matches json-ld"); - final LdDatasetDto resource2 = metadataMapper.identifierToLdDatasetDto(identifier, endpointConfig.getWebsiteUrl()); - log.debug("find identifier resulted in identifier {}", resource2); - return ResponseEntity.ok(resource2); - case "text/csv": - log.trace("accept header matches csv"); - if (identifier.getType().equals(IdentifierType.DATABASE)) { - log.error("Failed to export dataset: identifier type is database"); - throw new FormatNotAvailableException("Failed to export dataset: identifier type is database"); - } - final InputStreamResource resource3; - resource3 = identifierService.exportResource(identifier); - log.debug("find identifier resulted in resource {}", resource3); - return ResponseEntity.ok(resource3); - case "text/xml": - log.trace("accept header matches xml"); - final InputStreamResource resource4 = identifierService.exportMetadata(identifier); - log.debug("find identifier resulted in resource {}", resource4); - return ResponseEntity.ok(resource4); - } - final Pattern regex = Pattern.compile("text\\/bibliography(; ?style=(apa|ieee|bibtex))?"); - final Matcher matcher = regex.matcher(accept); - if (matcher.find()) { - log.trace("accept header matches bibliography"); - final BibliographyTypeDto style; - if (matcher.group(2) != null) { - style = BibliographyTypeDto.valueOf(matcher.group(2).toUpperCase()); - log.trace("bibliography style matches {}", style); - } else { - style = BibliographyTypeDto.APA; - log.trace("no bibliography style provided, default: {}", style); + log.info("Found persistent identifier with id: {}", identifier.getId()); + switch (accept) { + case "application/json": + log.trace("accept header matches json"); + final IdentifierDto resource1 = metadataMapper.identifierToIdentifierDto(identifier); + log.debug("find identifier resulted in identifier {}", resource1); + return ResponseEntity.ok(resource1); + case "application/ld+json": + log.trace("accept header matches json-ld"); + final LdDatasetDto resource2 = metadataMapper.identifierToLdDatasetDto(identifier, endpointConfig.getWebsiteUrl()); + log.debug("find identifier resulted in identifier {}", resource2); + log.debug("find identifier resulted in identifier {}", resource2); + return ResponseEntity.ok(resource2); + case "text/csv": + log.trace("accept header matches csv"); + if (identifier.getType().equals(IdentifierType.DATABASE)) { + log.error("Failed to export dataset: identifier type is database"); + throw new FormatNotAvailableException("Failed to export dataset: identifier type is database"); } - final String resource = identifierService.exportBibliography(identifier, style); - log.debug("find identifier resulted in resource {}", resource); - return ResponseEntity.ok(resource); + final InputStreamResource resource3; + resource3 = identifierService.exportResource(identifier); + log.debug("find identifier resulted in resource {}", resource3); + return ResponseEntity.ok(resource3); + case "text/xml": + log.trace("accept header matches xml"); + final InputStreamResource resource4 = identifierService.exportMetadata(identifier); + log.debug("find identifier resulted in resource {}", resource4); + return ResponseEntity.ok(resource4); + } + final Pattern regex = Pattern.compile("text\\/bibliography(; ?style=(apa|ieee|bibtex))?"); + final Matcher matcher = regex.matcher(accept); + if (matcher.find()) { + log.trace("accept header matches bibliography"); + final BibliographyTypeDto style; + if (matcher.group(2) != null) { + style = BibliographyTypeDto.valueOf(matcher.group(2).toUpperCase()); + log.trace("bibliography style matches {}", style); + } else { + style = BibliographyTypeDto.APA; + log.trace("no bibliography style provided, default: {}", style); } - } else { - log.trace("no accept header present"); + final String resource = identifierService.exportBibliography(identifier, style); + log.debug("find identifier resulted in resource {}", resource); + return ResponseEntity.ok(resource); } final HttpHeaders headers = new HttpHeaders(); final String url = metadataMapper.identifierToLocationUrl(endpointConfig.getWebsiteUrl(), identifier); @@ -351,9 +348,9 @@ public class IdentifierEndpoint { throws SearchServiceException, DatabaseNotFoundException, SearchServiceConnectionException, MalformedException, DataServiceConnectionException, IdentifierNotFoundException, ExternalServiceException { log.debug("endpoint publish identifier, identifierId={}", identifierId); - identifierService.find(identifierId); + final Identifier identifier = identifierService.find(identifierId); return ResponseEntity.status(HttpStatus.CREATED) - .body(metadataMapper.identifierToIdentifierDto(identifierService.publish(identifierId))); + .body(metadataMapper.identifierToIdentifierDto(identifierService.publish(identifier))); } @PutMapping("/{identifierId}") @@ -405,10 +402,10 @@ public class IdentifierEndpoint { log.debug("endpoint save identifier, identifierId={}, data.id={}, principal.name={}", identifierId, data.getId(), principal.getName()); final Database database = databaseService.findById(data.getDatabaseId()); - final User user = userService.findByUsername(principal.getName()); + final User caller = userService.findByUsername(principal.getName()); final Identifier identifier = identifierService.find(identifierId); /* check owner */ - if (!identifier.getOwner().equals(user) && !UserUtil.hasRole(principal, "create-foreign-identifier")) { + if (!identifier.getOwner().getId().equals(caller.getId()) && !UserUtil.hasRole(principal, "create-foreign-identifier")) { log.error("Failed to save identifier: foreign user"); throw new NotAllowedException("Failed to save identifier: foreign user"); } @@ -418,9 +415,8 @@ public class IdentifierEndpoint { throw new MalformedException("Failed to save identifier: publication date is invalid"); } /* check access */ - DatabaseAccess access = null; try { - access = accessService.find(database, user); + final DatabaseAccess access = accessService.find(database, caller); log.trace("found access: {}", access); } catch (AccessNotFoundException e) { if (!UserUtil.hasRole(principal, "create-foreign-identifier")) { @@ -434,22 +430,12 @@ public class IdentifierEndpoint { log.error("Failed to save view identifier: only parameters database_id & view_id must be present"); throw new MalformedException("Failed to save view identifier: only parameters database_id & view_id must be present"); } - final View view = viewService.findById(database, data.getViewId()); - if (!endpointValidator.validateOnlyMineOrReadAccessOrHasRole(view.getOwner(), principal, access, "create-foreign-identifier")) { - log.error("Failed to save view identifier: insufficient access or role"); - throw new MalformedException("Failed to save view identifier: insufficient access or role"); - } } case TABLE -> { if (data.getQueryId() != null || data.getViewId() != null || data.getTableId() == null) { log.error("Failed to save table identifier: only parameters database_id & table_id must be present"); throw new MalformedException("Failed to save table identifier: only parameters database_id & table_id must be present"); } - final Table table = tableService.findById(data.getDatabaseId(), data.getTableId()); - if (!endpointValidator.validateOnlyMineOrReadAccessOrHasRole(table.getOwner(), principal, access, "create-foreign-identifier")) { - log.error("Failed to save table identifier: insufficient access or role"); - throw new MalformedException("Failed to save table identifier: insufficient access or role"); - } } case SUBSET -> { if (data.getQueryId() == null || data.getViewId() != null || data.getTableId() != null) { @@ -457,26 +443,16 @@ public class IdentifierEndpoint { throw new MalformedException("Failed to save subset identifier: only parameters database_id & query_id must be present"); } log.debug("retrieving subset from data service: data.database_id={}, data.query_id={}", data.getDatabaseId(), data.getQueryId()); - final QueryDto query = dataServiceGateway.findQuery(data.getDatabaseId(), data.getQueryId()); - final User queryCreator = userService.findById(query.getOwner().getId()); - if (!endpointValidator.validateOnlyMineOrReadAccessOrHasRole(queryCreator, principal, access, "create-foreign-identifier")) { - log.error("Failed to create subset identifier: insufficient access or role"); - throw new MalformedException("Failed to create subset identifier: insufficient access or role"); - } } case DATABASE -> { if (data.getQueryId() != null || data.getViewId() != null || data.getTableId() != null) { log.error("Failed to save database identifier: only parameters database_id must be present"); throw new MalformedException("Failed to save database identifier: only parameters database_id must be present"); } - if (!endpointValidator.validateOnlyMineOrReadAccessOrHasRole(database.getOwner(), principal, access, "create-foreign-identifier")) { - log.error("Failed to save database identifier: insufficient access or role"); - throw new MalformedException("Failed to save database identifier: insufficient access or role"); - } } } return ResponseEntity.accepted() - .body(metadataMapper.identifierToIdentifierDto(identifierService.save(database, user, data))); + .body(metadataMapper.identifierToIdentifierDto(identifierService.save(database, caller, data))); } @PostMapping @@ -525,18 +501,17 @@ public class IdentifierEndpoint { IdentifierNotFoundException, ViewNotFoundException, ExternalServiceException { log.debug("endpoint create identifier, data.databaseId={}", data.getDatabaseId()); final Database database = databaseService.findById(data.getDatabaseId()); - final User user = userService.findByUsername(principal.getName()); + final User caller = userService.findByUsername(principal.getName()); /* check access */ try { - final DatabaseAccess access = accessService.find(database, user); - log.trace("found access: {}", access.getType()); + accessService.find(database, caller); } catch (AccessNotFoundException e) { if (!UserUtil.hasRole(principal, "create-foreign-identifier")) { log.error("Failed to create identifier: insufficient role"); throw new NotAllowedException("Failed to create identifier: insufficient role"); } } - final Identifier identifier = identifierService.create(database, user, data); + final Identifier identifier = identifierService.create(database, caller, data); return ResponseEntity.status(HttpStatus.CREATED) .body(metadataMapper.identifierToIdentifierDto(identifier)); } diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ImageEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ImageEndpoint.java index 088dc2981b..2a9dd56870 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ImageEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ImageEndpoint.java @@ -31,7 +31,6 @@ import org.springframework.web.bind.annotation.*; import java.security.Principal; import java.util.List; -import java.util.stream.Collectors; @Log4j2 @RestController @@ -97,11 +96,7 @@ public class ImageEndpoint { public ResponseEntity<ImageDto> create(@Valid @RequestBody ImageCreateDto data, @NotNull Principal principal) throws ImageAlreadyExistsException, ImageInvalidException { - log.debug("endpoint create image, data={}", data); - if (data.getDefaultPort() == null) { - log.error("Failed to create image, default port is null"); - throw new ImageInvalidException("Failed to create image, default port is null"); - } + log.debug("endpoint create image, data={}, principal.name={}", data, principal.getName()); final ContainerImage image = imageService.create(data, principal); final ImageDto dto = metadataMapper.containerImageToImageDto(image); log.trace("create image resulted in image {}", dto); diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java index e04cba85ce..822581bb99 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java @@ -112,7 +112,7 @@ public class TableEndpoint { @PreAuthorize("hasAuthority('table-semantic-analyse')") @Observed(name = "dbrepo_semantic_table_analyse") @Operation(summary = "Suggest semantics", - description = "Suggests semantic concepts for a table. Requires role `table-semantic-analyse`.", + description = "Suggests semantic concepts for a table. This action can only be performed by the table owner. Requires role `table-semantic-analyse`.", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "200", @@ -125,6 +125,11 @@ public class TableEndpoint { content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "403", + description = "Not the table owner.", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), @ApiResponse(responseCode = "404", description = "Failed to find database/table in metadata database", content = {@Content( @@ -142,13 +147,19 @@ public class TableEndpoint { schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<List<EntityDto>> analyseTable(@NotNull @PathVariable("databaseId") Long databaseId, - @NotNull @PathVariable("tableId") Long tableId) - throws MalformedException, TableNotFoundException, DatabaseNotFoundException { - log.debug("endpoint analyse table semantics, databaseId={}, tableId={}", databaseId, tableId); - final Table table = tableService.findById(databaseId, tableId); - final List<EntityDto> dtos = entityService.suggestByTable(table); + @NotNull @PathVariable("tableId") Long tableId, + @NotNull Principal principal) + throws MalformedException, TableNotFoundException, DatabaseNotFoundException, NotAllowedException { + log.debug("endpoint analyse table semantics, databaseId={}, tableId={}, principal.name={}", databaseId, tableId, + principal); + final Database database = databaseService.findById(databaseId); + final Table table = tableService.findById(database, tableId); + if (!table.getOwner().getUsername().equals(principal.getName())) { + log.error("Failed to analyse table semantics: not owner"); + throw new NotAllowedException("Failed to analyse table semantics: not owner"); + } return ResponseEntity.ok() - .body(dtos); + .body(entityService.suggestByTable(table)); } @PutMapping("/{tableId}/statistic") @@ -156,18 +167,23 @@ public class TableEndpoint { @PreAuthorize("hasAuthority('update-table-statistic')") @Observed(name = "dbrepo_statistic_table_update") @Operation(summary = "Update statistics", - description = "Updates basic statistical properties (min, max, mean, median, std.dev) for numerical columns in a table with id. Requires role `update-table-statistic`.", + description = "Updates basic statistical properties (min, max, mean, median, std.dev) for numerical columns in a table with id. This action can only be performed by the table owner. Requires role `update-table-statistic`.", security = {@SecurityRequirement(name = "bearerAuth"), @SecurityRequirement(name = "basicAuth")}) @ApiResponses(value = { @ApiResponse(responseCode = "202", description = "Updated table statistics successfully"), - @ApiResponse(responseCode = "404", - description = "Failed to find database/table in metadata database", + @ApiResponse(responseCode = "400", + description = "Failed to map column statistic to known columns", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), - @ApiResponse(responseCode = "400", - description = "Failed to map column statistic to known columns", + @ApiResponse(responseCode = "403", + description = "Not the owner", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), + @ApiResponse(responseCode = "404", + description = "Failed to find database/table in metadata database", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @@ -183,11 +199,18 @@ public class TableEndpoint { schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<Void> updateStatistic(@NotNull @PathVariable("databaseId") Long databaseId, - @NotNull @PathVariable("tableId") Long tableId) - throws TableNotFoundException, DatabaseNotFoundException, SearchServiceException, + @NotNull @PathVariable("tableId") Long tableId, + @NotNull Principal principal) + throws TableNotFoundException, DatabaseNotFoundException, SearchServiceException, NotAllowedException, SearchServiceConnectionException, MalformedException, DataServiceException, DataServiceConnectionException { - log.debug("endpoint update table statistics, databaseId={}, tableId={}", databaseId, tableId); - final Table table = tableService.findById(databaseId, tableId); + log.debug("endpoint update table statistics, databaseId={}, tableId={}, principal.name={}", databaseId, tableId, + principal.getName()); + final Database database = databaseService.findById(databaseId); + final Table table = tableService.findById(database, tableId); + if (!table.getOwner().getUsername().equals(principal.getName())) { + log.error("Failed to update table statistics: not owner"); + throw new NotAllowedException("Failed to update table statistics: not owner"); + } tableService.updateStatistics(table); return ResponseEntity.accepted() .build(); @@ -232,17 +255,19 @@ public class TableEndpoint { mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), }) - public ResponseEntity<ColumnDto> update(@NotNull @PathVariable("databaseId") Long databaseId, - @NotNull @PathVariable("tableId") Long tableId, - @NotNull @PathVariable("columnId") Long columnId, - @NotNull @Valid @RequestBody ColumnSemanticsUpdateDto updateDto, - @NotNull Principal principal) throws NotAllowedException, + public ResponseEntity<ColumnDto> updateColumn(@NotNull @PathVariable("databaseId") Long databaseId, + @NotNull @PathVariable("tableId") Long tableId, + @NotNull @PathVariable("columnId") Long columnId, + @NotNull @Valid @RequestBody ColumnSemanticsUpdateDto updateDto, + @NotNull Principal principal) throws NotAllowedException, MalformedException, DataServiceException, DataServiceConnectionException, UserNotFoundException, TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, SearchServiceException, SearchServiceConnectionException, OntologyNotFoundException, SemanticEntityNotFoundException { - log.debug("endpoint update table, databaseId={}, tableId={}, columnId={}", databaseId, tableId, columnId); + log.debug("endpoint update table, databaseId={}, tableId={}, columnId={}, principal.name={}", databaseId, + tableId, columnId, principal.getName()); + final Database database = databaseService.findById(databaseId); final User user = userService.findByUsername(principal.getName()); - final Table table = tableService.findById(databaseId, tableId); + final Table table = tableService.findById(database, tableId); if (!UserUtil.hasRole(principal, "modify-foreign-table-column-semantics")) { endpointValidator.validateOnlyAccess(table.getDatabase(), principal, true); endpointValidator.validateOnlyOwnerOrWriteAll(table, user); @@ -287,10 +312,13 @@ public class TableEndpoint { }) public ResponseEntity<List<TableColumnEntityDto>> analyseTableColumn(@NotNull @PathVariable("databaseId") Long databaseId, @NotNull @PathVariable("tableId") Long tableId, - @NotNull @PathVariable("columnId") Long columnId) + @NotNull @PathVariable("columnId") Long columnId, + @NotNull Principal principal) throws MalformedException, TableNotFoundException, DatabaseNotFoundException { - log.debug("endpoint analyse table column semantics, databaseId={}, tableId={}, columnId={}", databaseId, tableId, columnId); - final Table table = tableService.findById(databaseId, tableId); + log.debug("endpoint analyse table column semantics, databaseId={}, tableId={}, columnId={}, principal.name={}", + databaseId, tableId, columnId, principal.getName()); + final Database database = databaseService.findById(databaseId); + final Table table = tableService.findById(database, tableId); TableColumn column = tableService.findColumnById(table, columnId); final List<TableColumnEntityDto> dtos = entityService.suggestByColumn(column); return ResponseEntity.ok() @@ -347,7 +375,8 @@ public class TableEndpoint { DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, UserNotFoundException, AccessNotFoundException, TableNotFoundException, TableExistsException, SearchServiceException, SearchServiceConnectionException, OntologyNotFoundException, SemanticEntityNotFoundException { - log.debug("endpoint create table, databaseId={}, data.name={}", databaseId, data.getName()); + log.debug("endpoint create table, databaseId={}, data.name={}, principal.name={}", databaseId, data.getName(), + principal.getName()); final Database database = databaseService.findById(databaseId); endpointValidator.validateOnlyAccess(database, principal, true); endpointValidator.validateColumnCreateConstraints(data); @@ -403,10 +432,11 @@ public class TableEndpoint { @NotNull Principal principal) throws NotAllowedException, DataServiceException, DataServiceConnectionException, DatabaseNotFoundException, TableNotFoundException, SearchServiceException, SearchServiceConnectionException { - log.debug("endpoint update table, databaseId={}, data.is_public={}, data.is_schema_public={}", databaseId, - data.getIsPublic(), data.getIsSchemaPublic()); - final Table table = tableService.findById(databaseId, tableId); - if (!table.getOwner().equals(principal)) { + log.debug("endpoint update table, databaseId={}, data.is_public={}, data.is_schema_public={}, principal.name={}", + databaseId, data.getIsPublic(), data.getIsSchemaPublic(), principal.getName()); + final Database database = databaseService.findById(databaseId); + final Table table = tableService.findById(database, tableId); + if (!table.getOwner().getUsername().equals(principal.getName())) { log.error("Failed to update table: not owner"); throw new NotAllowedException("Failed to update table: not owner"); } @@ -462,7 +492,8 @@ public class TableEndpoint { Principal principal) throws DataServiceException, DataServiceConnectionException, TableNotFoundException, DatabaseNotFoundException, QueueNotFoundException { log.debug("endpoint find table, databaseId={}, tableId={}", databaseId, tableId); - final Table table = tableService.findById(databaseId, tableId); + final Database database = databaseService.findById(databaseId); + final Table table = tableService.findById(database, tableId); boolean hasAccess = UserUtil.isSystem(principal); boolean isOwner = false; try { @@ -470,7 +501,7 @@ public class TableEndpoint { final User user = userService.findByUsername(principal.getName()); accessService.find(table.getDatabase(), user); hasAccess = true; - isOwner = table.getOwner().equals(user); + isOwner = table.getOwner().getId().equals(user.getId()); } } catch (UserNotFoundException | AccessNotFoundException e) { /* ignore */ @@ -537,8 +568,10 @@ public class TableEndpoint { @NotNull Principal principal) throws NotAllowedException, DataServiceException, DataServiceConnectionException, TableNotFoundException, DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException { - log.debug("endpoint delete table, databaseId={}, tableId={}", databaseId, tableId); - final Table table = tableService.findById(databaseId, tableId); + log.debug("endpoint delete table, databaseId={}, tableId={}, principal.name={}", databaseId, tableId, + principal.getName()); + final Database database = databaseService.findById(databaseId); + final Table table = tableService.findById(database, tableId); /* roles */ if (!table.getOwner().getUsername().equals(principal.getName()) && !UserUtil.hasRole(principal, "delete-foreign-table")) { log.error("Failed to delete table: not owned by current user"); diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/UserEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/UserEndpoint.java index fe2d0a343a..151169c244 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/UserEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/UserEndpoint.java @@ -205,7 +205,7 @@ public class UserEndpoint { .password(data.getPassword()) .build(); final at.tuwien.api.keycloak.UserDto user = authenticationService.findByUsername(data.getUsername()); - if (user.getAttributes().getLdapId().length != 1) { + if (user.getAttributes().getLdapId() == null || user.getAttributes().getLdapId().length != 1) { log.error("Failed to map ldap id for user with username: {}", data.getUsername()); throw new UserNotFoundException("Failed to map ldap id"); } diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java index 359c1be796..012206289e 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ViewEndpoint.java @@ -141,14 +141,14 @@ public class ViewEndpoint { UserNotFoundException, SearchServiceException, SearchServiceConnectionException { log.debug("endpoint create view, databaseId={}, data={}", databaseId, data); final Database database = databaseService.findById(databaseId); - if (!database.getOwner().equals(principal)) { + final User caller = userService.findByUsername(principal.getName()); + if (!database.getOwner().getId().equals(caller.getId())) { log.error("Failed to create view: not the database owner"); throw new NotAllowedException("Failed to create view: not the database owner"); } - final User user = userService.findByUsername(principal.getName()); log.trace("create view for database {}", database); final View view; - view = viewService.create(database, user, data); + view = viewService.create(database, caller, data); final ViewBriefDto dto = metadataMapper.viewToViewBriefDto(view); return ResponseEntity.status(HttpStatus.CREATED) .body(dto); @@ -311,7 +311,7 @@ public class ViewEndpoint { log.debug("endpoint update view, databaseId={}, viewId={}", databaseId, viewId); final Database database = databaseService.findById(databaseId); final View view = viewService.findById(database, viewId); - if (!database.getOwner().equals(principal) && !view.getOwner().equals(principal)) { + if (!database.getOwner().getUsername().equals(principal.getName()) && !view.getOwner().getUsername().equals(principal.getName())) { log.error("Failed to update view: not the database- or view owner"); throw new NotAllowedException("Failed to update view: not the database- or view owner"); } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/AccessEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/AccessEndpointUnitTest.java index 7c6061ed1e..f4a700e859 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/AccessEndpointUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/AccessEndpointUnitTest.java @@ -7,9 +7,9 @@ import at.tuwien.entities.database.DatabaseAccess; import at.tuwien.entities.user.User; import at.tuwien.exception.*; import at.tuwien.mapper.MetadataMapper; -import at.tuwien.repository.DatabaseRepository; -import at.tuwien.repository.UserRepository; import at.tuwien.service.AccessService; +import at.tuwien.service.DatabaseService; +import at.tuwien.service.UserService; import at.tuwien.test.AbstractUnitTest; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.BeforeEach; @@ -20,12 +20,14 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.test.context.support.WithAnonymousUser; import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.context.junit.jupiter.SpringExtension; import java.security.Principal; -import java.util.Optional; +import java.util.List; import java.util.UUID; import static org.junit.jupiter.api.Assertions.*; @@ -41,10 +43,10 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { private AccessService accessService; @MockBean - private DatabaseRepository databaseRepository; + private DatabaseService databaseService; @MockBean - private UserRepository userRepository; + private UserService userService; @Autowired private AccessEndpoint accessEndpoint; @@ -63,7 +65,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { - generic_create(null, null, null, null); + generic_create(null, null, null, null, null); }); } @@ -73,7 +75,37 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { - generic_create(USER_2_PRINCIPAL, USER_2, USER_4_ID, USER_4); + generic_create(USER_2_PRINCIPAL, USER_2, USER_4_ID, USER_4, null); + }); + } + + @Test + @WithMockUser(username = USER_4_USERNAME) + public void create_noRole_fails() { + + /* test */ + assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { + generic_create(USER_2_PRINCIPAL, USER_2, USER_4_ID, USER_4, null); + }); + } + + @Test + @WithMockUser(username = USER_4_USERNAME, authorities = {"create-database-access"}) + public void create_notOwner_fails() { + + /* test */ + assertThrows(NotAllowedException.class, () -> { + generic_create(USER_2_PRINCIPAL, USER_2, USER_4_ID, USER_4, null); + }); + } + + @Test + @WithMockUser(username = USER_1_USERNAME, authorities = {"create-database-access"}) + public void create_alreadyAccess_fails() { + + /* test */ + assertThrows(NotAllowedException.class, () -> { + generic_create(USER_1_PRINCIPAL, USER_1, USER_2_ID, USER_2, DATABASE_1_USER_2_READ_ACCESS); }); } @@ -88,7 +120,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { .thenReturn(DATABASE_1_USER_1_READ_ACCESS); /* test */ - generic_create(USER_1_PRINCIPAL, USER_1, USER_2_ID, USER_2); + generic_create(USER_1_PRINCIPAL, USER_1, USER_2_ID, USER_2, null); } @Test @@ -97,7 +129,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(AccessNotFoundException.class, () -> { - generic_find(DATABASE_1_ID, DATABASE_1, null, USER_2_PRINCIPAL, USER_2_ID, USER_2); + generic_find(DATABASE_1_ID, DATABASE_1, null, USER_2_PRINCIPAL, USER_2, USER_2_ID, USER_2); }); } @@ -107,7 +139,7 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { AccessNotFoundException, NotAllowedException { /* test */ - generic_find(DATABASE_1_ID, DATABASE_1, DATABASE_1_USER_1_READ_ACCESS, USER_1_PRINCIPAL, USER_1_ID, USER_1); + generic_find(DATABASE_1_ID, DATABASE_1, DATABASE_1_USER_1_READ_ACCESS, USER_1_PRINCIPAL, USER_1, USER_1_ID, USER_1); } @Test @@ -116,17 +148,20 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(NotAllowedException.class, () -> { - generic_find(DATABASE_1_ID, DATABASE_1, DATABASE_1_USER_1_READ_ACCESS, USER_1_PRINCIPAL, USER_2_ID, USER_2); + generic_find(DATABASE_1_ID, DATABASE_1, DATABASE_1_USER_1_READ_ACCESS, USER_1_PRINCIPAL, USER_1, USER_2_ID, USER_2); }); } @Test - @WithMockUser(username = USER_1_USERNAME, authorities = {"check-foreign-database-access"}) + @WithMockUser(username = USER_1_USERNAME, authorities = {"check-database-access", "check-foreign-database-access"}) public void find_hasRoleHasAccessForeign_succeeds() throws UserNotFoundException, NotAllowedException, DatabaseNotFoundException, AccessNotFoundException { + final Principal principal = new UsernamePasswordAuthenticationToken(USER_1_DETAILS, USER_1_PASSWORD, List.of( + new SimpleGrantedAuthority("check-database-access"), + new SimpleGrantedAuthority("check-foreign-database-access"))); /* test */ - generic_find(DATABASE_1_ID, DATABASE_1, DATABASE_1_USER_1_READ_ACCESS, USER_1_PRINCIPAL, USER_1_ID, USER_1); + generic_find(DATABASE_1_ID, DATABASE_1, DATABASE_1_USER_2_READ_ACCESS, principal, USER_1, USER_2_ID, USER_2); } @Test @@ -159,6 +194,16 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { }); } + @Test + @WithMockUser(username = USER_4_USERNAME, authorities = {"update-database-access"}) + public void update_notOwner_fails() { + + /* test */ + assertThrows(NotAllowedException.class, () -> { + generic_update(USER_4_PRINCIPAL, USER_4, USER_1_ID, USER_1, null); + }); + } + @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"update-database-access"}) public void update_succeeds() throws NotAllowedException, DataServiceException, DataServiceConnectionException, @@ -194,6 +239,16 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { }); } + @Test + @WithMockUser(username = USER_4_USERNAME, authorities = {"delete-database-access"}) + public void revoke_notOwner_fails() { + + /* test */ + assertThrows(NotAllowedException.class, () -> { + generic_revoke(USER_4_PRINCIPAL, USER_4, USER_1_ID, USER_1); + }); + } + @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"delete-database-access"}) public void revoke_succeeds() throws NotAllowedException, DataServiceException, DataServiceConnectionException, @@ -213,30 +268,37 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { /* ## GENERIC TEST CASES ## */ /* ################################################################################################### */ - protected void generic_create(Principal principal, User principalUser, UUID userId, User user) + protected void generic_create(Principal principal, User principalUser, UUID userId, User user, DatabaseAccess access) throws NotAllowedException, DataServiceException, DataServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, AccessNotFoundException, SearchServiceException, SearchServiceConnectionException { /* mock */ - when(databaseRepository.findById(DATABASE_1_ID)) - .thenReturn(Optional.of(DATABASE_1)); - doThrow(AccessNotFoundException.class) - .when(accessService) - .find(DATABASE_1, user); + when(databaseService.findById(DATABASE_1_ID)) + .thenReturn(DATABASE_1); + if (access != null) { + when(accessService.find(DATABASE_1, user)) + .thenReturn(access); + } else { + doThrow(AccessNotFoundException.class) + .when(accessService) + .find(DATABASE_1, user); + } if (principalUser != null) { - when(userRepository.findByUsername(principal.getName())) - .thenReturn(Optional.of(principalUser)); + when(userService.findByUsername(principal.getName())) + .thenReturn(principalUser); } else { - when(userRepository.findByUsername(anyString())) - .thenReturn(Optional.empty()); + doThrow(UserNotFoundException.class) + .when(userService) + .findByUsername(anyString()); } if (user != null) { - when(userRepository.findById(userId)) - .thenReturn(Optional.of(user)); + when(userService.findById(userId)) + .thenReturn(user); } else { - when(userRepository.findById(any(UUID.class))) - .thenReturn(Optional.empty()); + doThrow(UserNotFoundException.class) + .when(userService) + .findById(any(UUID.class)); } /* test */ @@ -246,14 +308,16 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { } protected void generic_find(Long databaseId, Database database, DatabaseAccess access, Principal principal, - UUID userId, User user) throws UserNotFoundException, DatabaseNotFoundException, - AccessNotFoundException, NotAllowedException { + User caller, UUID userId, User user) throws UserNotFoundException, + DatabaseNotFoundException, AccessNotFoundException, NotAllowedException { /* mock */ - when(databaseRepository.findById(databaseId)) - .thenReturn(Optional.of(database)); - when(userRepository.findById(userId)) - .thenReturn(Optional.of(user)); + when(userService.findByUsername(principal.getName())) + .thenReturn(caller); + when(databaseService.findById(databaseId)) + .thenReturn(database); + when(userService.findById(userId)) + .thenReturn(user); if (access != null) { log.trace("mock access {} for user with id {} for database with id {}", access.getType(), userId, databaseId); when(accessService.find(database, user)) @@ -264,10 +328,6 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { .when(accessService) .find(database, user); } - if (principal != null) { - when(userRepository.findByUsername(principal.getName())) - .thenReturn(Optional.of(user)); - } /* test */ final ResponseEntity<DatabaseAccessDto> response = accessEndpoint.find(databaseId, userId, principal); @@ -287,8 +347,8 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { SearchServiceException, SearchServiceConnectionException { /* mock */ - when(databaseRepository.findById(DATABASE_1_ID)) - .thenReturn(Optional.of(DATABASE_1)); + when(databaseService.findById(DATABASE_1_ID)) + .thenReturn(DATABASE_1); if (access != null) { log.trace("mock access {} for user with id {} for database with id {}", access.getType(), userId, DATABASE_1_ID); when(accessService.find(DATABASE_1, user)) @@ -300,18 +360,20 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { .find(DATABASE_1, user); } if (userId != null) { - when(userRepository.findById(userId)) - .thenReturn(Optional.of(user)); + when(userService.findById(userId)) + .thenReturn(user); } else { - when(userRepository.findById(any(UUID.class))) - .thenReturn(Optional.empty()); + doThrow(UserNotFoundException.class) + .when(userService) + .findById(any(UUID.class)); } if (principal != null) { - when(userRepository.findByUsername(principal.getName())) - .thenReturn(Optional.of(principalUser)); + when(userService.findByUsername(principal.getName())) + .thenReturn(principalUser); } else { - when(userRepository.findByUsername(anyString())) - .thenReturn(Optional.empty()); + doThrow(UserNotFoundException.class) + .when(userService) + .findByUsername(anyString()); } /* test */ @@ -326,14 +388,14 @@ public class AccessEndpointUnitTest extends AbstractUnitTest { SearchServiceConnectionException { /* mock */ - when(databaseRepository.findById(DATABASE_1_ID)) - .thenReturn(Optional.of(DATABASE_1)); + when(databaseService.findById(DATABASE_1_ID)) + .thenReturn(DATABASE_1); if (principal != null) { - when(userRepository.findByUsername(principal.getName())) - .thenReturn(Optional.of(principalUser)); + when(userService.findByUsername(principal.getName())) + .thenReturn(principalUser); } - when(userRepository.findById(userId)) - .thenReturn(Optional.of(user)); + when(userService.findById(userId)) + .thenReturn(user); /* test */ final ResponseEntity<?> response = accessEndpoint.revoke(DATABASE_1_ID, userId, principal); diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/DatabaseEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/DatabaseEndpointUnitTest.java index 861863a315..b788fd206b 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/DatabaseEndpointUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/DatabaseEndpointUnitTest.java @@ -386,7 +386,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_4_USERNAME) + @WithMockUser(username = USER_3_USERNAME) public void modifyImage_noRole_fails() { final DatabaseModifyImageDto request = DatabaseModifyImageDto.builder() .key("s3key_here") @@ -394,13 +394,32 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(AccessDeniedException.class, () -> { - databaseEndpoint.modifyImage(DATABASE_3_ID, request, USER_4_PRINCIPAL); + databaseEndpoint.modifyImage(DATABASE_3_ID, request, USER_3_PRINCIPAL); + }); + } + + @Test + @WithMockUser(username = USER_2_USERNAME, authorities = {"modify-database-image"}) + public void modifyImage_notOwner_fails() throws DatabaseNotFoundException, UserNotFoundException { + final DatabaseModifyImageDto request = DatabaseModifyImageDto.builder() + .key("s3key_here") + .build(); + + /* mock */ + when(databaseService.findById(DATABASE_3_ID)) + .thenReturn(DATABASE_3); + when(userService.findByUsername(USER_2_USERNAME)) + .thenReturn(USER_2); + + /* test */ + assertThrows(NotAllowedException.class, () -> { + databaseEndpoint.modifyImage(DATABASE_3_ID, request, USER_2_PRINCIPAL); }); } @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"modify-database-image"}) - public void modifyImage_hasRole_succeeds() throws NotAllowedException, UserNotFoundException, + public void modifyImage_succeeds() throws NotAllowedException, UserNotFoundException, DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException, StorageUnavailableException, StorageNotFoundException { final DatabaseModifyImageDto request = DatabaseModifyImageDto.builder() @@ -413,7 +432,26 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { when(userService.findByUsername(USER_1_USERNAME)) .thenReturn(USER_1); when(storageService.getBytes(request.getKey())) - .thenReturn(new byte[]{}); + .thenReturn(new byte[]{1, 2, 3, 4, 5}); + + /* test */ + databaseEndpoint.modifyImage(DATABASE_1_ID, request, USER_1_PRINCIPAL); + } + + @Test + @WithMockUser(username = USER_1_USERNAME, authorities = {"modify-database-image"}) + public void modifyImage_empty_succeeds() throws NotAllowedException, UserNotFoundException, + DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException, + StorageUnavailableException, StorageNotFoundException { + final DatabaseModifyImageDto request = DatabaseModifyImageDto.builder() + .key(null) + .build(); + + /* mock */ + when(databaseService.findById(DATABASE_1_ID)) + .thenReturn(DATABASE_1); + when(userService.findByUsername(USER_1_USERNAME)) + .thenReturn(USER_1); /* test */ databaseEndpoint.modifyImage(DATABASE_1_ID, request, USER_1_PRINCIPAL); diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/IdentifierEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/IdentifierEndpointUnitTest.java index ba3debd79d..243f0e9aed 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/IdentifierEndpointUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/IdentifierEndpointUnitTest.java @@ -1,6 +1,7 @@ package at.tuwien.endpoints; import at.tuwien.api.identifier.*; +import at.tuwien.api.identifier.ld.LdDatasetDto; import at.tuwien.config.EndpointConfig; import at.tuwien.entities.database.Database; import at.tuwien.entities.database.DatabaseAccess; @@ -9,25 +10,27 @@ import at.tuwien.entities.identifier.IdentifierType; import at.tuwien.entities.user.User; import at.tuwien.exception.*; import at.tuwien.gateway.DataServiceGateway; -import at.tuwien.service.AccessService; -import at.tuwien.service.DatabaseService; -import at.tuwien.service.IdentifierService; -import at.tuwien.service.UserService; +import at.tuwien.service.*; import at.tuwien.test.AbstractUnitTest; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.log4j.Log4j2; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.core.io.InputStreamResource; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.test.context.support.WithAnonymousUser; import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.context.junit.jupiter.SpringExtension; @@ -38,6 +41,7 @@ import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.security.Principal; import java.util.List; +import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; @@ -62,6 +66,12 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { @MockBean private UserService userService; + @MockBean + private ViewService viewService; + + @MockBean + private TableService tableService; + @Autowired private IdentifierEndpoint identifierEndpoint; @@ -71,11 +81,162 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { @Autowired private EndpointConfig endpointConfig; + public static Stream<Arguments> save_parameters() { + return Stream.of( + Arguments.arguments("foreign_subset", DATABASE_2_ID, DATABASE_2, null, IDENTIFIER_5, IDENTIFIER_5_SAVE_DTO, USER_1_PRINCIPAL, USER_1), + Arguments.arguments("foreign_database", DATABASE_1_ID, DATABASE_1, null, IDENTIFIER_1, IDENTIFIER_1_SAVE_DTO, USER_1_PRINCIPAL, USER_1), + Arguments.arguments("foreign_view", DATABASE_1_ID, DATABASE_1, null, IDENTIFIER_3, IDENTIFIER_3_SAVE_DTO, USER_1_PRINCIPAL, USER_1), + Arguments.arguments("foreign_table", DATABASE_1_ID, DATABASE_1, null, IDENTIFIER_4, IDENTIFIER_4_SAVE_DTO, USER_1_PRINCIPAL, USER_1) + ); + } + + public static Stream<Arguments> malformedDatabase_parameters() { + return Stream.of( + Arguments.arguments("queryId", 9999L, null, null), + Arguments.arguments("viewId", null, 9999L, null), + Arguments.arguments("tableId", null, null, 9999L) + ); + } + + public static Stream<Arguments> malformedSubset_parameters() { + return Stream.of( + Arguments.arguments("queryId", null, null, null), + Arguments.arguments("viewId", null, 9999L, null), + Arguments.arguments("tableId", null, null, 9999L) + ); + } + + public static Stream<Arguments> malformedView_parameters() { + return Stream.of( + Arguments.arguments("queryId", 9999L, null, null), + Arguments.arguments("viewId", null, null, null), + Arguments.arguments("tableId", null, null, 9999L) + ); + } + + public static Stream<Arguments> malformedTable_parameters() { + return Stream.of( + Arguments.arguments("queryId", 9999L, null, null), + Arguments.arguments("viewId", null, 9999L, null), + Arguments.arguments("tableId", null, null, null) + ); + } + + public static Stream<Arguments> findAll_filterDatabase_parameters() { + return Stream.of( + Arguments.arguments("dbid", DATABASE_1_ID, null, null, null, 4), + Arguments.arguments("qid", DATABASE_1_ID, QUERY_1_ID, null, null, 1), + Arguments.arguments("vid", DATABASE_1_ID, null, VIEW_1_ID, null, 1), + Arguments.arguments("tid", DATABASE_1_ID, null, null, TABLE_1_ID, 1) + ); + } + + public static Stream<Arguments> save_foreign_parameters() { + return Stream.of( + Arguments.arguments("view", IDENTIFIER_3, IDENTIFIER_3_SAVE_DTO), + Arguments.arguments("table", IDENTIFIER_4, IDENTIFIER_4_SAVE_DTO), + Arguments.arguments("subset", IDENTIFIER_2, IDENTIFIER_2_SAVE_DTO) + ); + } + @BeforeEach public void beforeEach() { genesis(); } + @Test + @WithAnonymousUser + public void findAll_empty_succeeds() throws FormatNotAvailableException { + + /* mock */ + when(identifierService.findAll()) + .thenReturn(List.of()); + + /* test */ + final ResponseEntity<?> response = identifierEndpoint.findAll(null, null, null, null, "application/json"); + assertEquals(HttpStatus.OK, response.getStatusCode()); + assertNotNull(response.getBody()); + final List<IdentifierBriefDto> identifiers = (List<IdentifierBriefDto>) response.getBody(); + assertNotNull(identifiers); + assertEquals(0, identifiers.size()); + } + + @ParameterizedTest + @MethodSource("findAll_filterDatabase_parameters") + @WithAnonymousUser + public void findAll_filterDatabase_succeeds(String name, Long databaseId, Long queryId, Long viewId, Long tableId, + Integer expectedSize) throws FormatNotAvailableException, + ViewNotFoundException, TableNotFoundException, DatabaseNotFoundException { + + /* mock */ + when(identifierService.findAll()) + .thenReturn(List.of(IDENTIFIER_1, IDENTIFIER_2, IDENTIFIER_3, IDENTIFIER_4, IDENTIFIER_5, IDENTIFIER_6, IDENTIFIER_7)); + if (viewId != null) { + when(viewService.findById(DATABASE_1, VIEW_1_ID)) + .thenReturn(VIEW_1); + } + if (tableId != null) { + when(tableService.findById(DATABASE_1, TABLE_1_ID)) + .thenReturn(TABLE_1); + } + + /* test */ + final ResponseEntity<?> response = identifierEndpoint.findAll(databaseId, queryId, viewId, tableId, "application/json"); + assertEquals(HttpStatus.OK, response.getStatusCode()); + assertNotNull(response.getBody()); + final List<IdentifierBriefDto> identifiers = (List<IdentifierBriefDto>) response.getBody(); + assertNotNull(identifiers); + assertEquals(expectedSize, identifiers.size()); + } + + @Test + @WithAnonymousUser + public void findAll_json_succeeds() throws FormatNotAvailableException { + + /* mock */ + when(identifierService.findAll()) + .thenReturn(List.of(IDENTIFIER_1)); + + /* test */ + final ResponseEntity<?> response = identifierEndpoint.findAll(null, null, null, null, "application/json"); + assertEquals(HttpStatus.OK, response.getStatusCode()); + assertNotNull(response.getBody()); + final List<IdentifierBriefDto> identifiers = (List<IdentifierBriefDto>) response.getBody(); + assertNotNull(identifiers); + assertEquals(1, identifiers.size()); + } + + @Test + @WithAnonymousUser + public void findAll_jsonLd_succeeds() throws FormatNotAvailableException { + + /* mock */ + when(identifierService.findAll()) + .thenReturn(List.of(IDENTIFIER_1)); + + /* test */ + final ResponseEntity<?> response = identifierEndpoint.findAll(null, null, null, null, "application/ld+json"); + assertEquals(HttpStatus.OK, response.getStatusCode()); + assertNotNull(response.getBody()); + final List<LdDatasetDto> identifiers = (List<LdDatasetDto>) response.getBody(); + assertNotNull(identifiers); + assertEquals(1, identifiers.size()); + } + + @Test + @WithAnonymousUser + public void findAll_format_fails() { + + /* mock */ + when(identifierService.findAll()) + .thenReturn(List.of(IDENTIFIER_1)); + + /* test */ + assertThrows(FormatNotAvailableException.class, () -> { + identifierEndpoint.findAll(null, null, null, null, "text/csv"); + }); + } + @Test @WithAnonymousUser public void find_json0_succeeds() throws IOException, MalformedException, DataServiceException, @@ -179,47 +340,6 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { assertEquals(inputStreamToString(compare.getInputStream()), inputStreamToString(body.getInputStream())); } - @Test - @Disabled("not testable with xml") - public void find_xml0_succeeds() throws IOException, MalformedException, DataServiceException, - DataServiceConnectionException, IdentifierNotFoundException, QueryNotFoundException, - FormatNotAvailableException { - final String accept = "text/xml"; - final InputStreamResource compare = new InputStreamResource(FileUtils.openInputStream(new File("src/test/resources/xml/metadata0.xml"))); - - /* mock */ - when(identifierService.find(IDENTIFIER_1_ID)) - .thenReturn(IDENTIFIER_1); - - /* test */ - final ResponseEntity<?> response = identifierEndpoint.find(IDENTIFIER_1_ID, accept); - assertEquals(HttpStatus.OK, response.getStatusCode()); - final InputStreamResource body = (InputStreamResource) response.getBody(); - assertNotNull(body); - assertEquals(inputStreamToString(compare.getInputStream()), inputStreamToString(body.getInputStream())); - } - - @Test - @Disabled("not testable with xml") - public void find_xml1_succeeds() throws IOException, MalformedException, DataServiceException, - DataServiceConnectionException, QueryNotFoundException, IdentifierNotFoundException, - FormatNotAvailableException { - final String accept = "text/xml"; - final InputStreamResource compare = new InputStreamResource(FileUtils.openInputStream(new File("src/test/resources/xml/metadata1.xml"))); - - /* mock */ - when(identifierService.find(IDENTIFIER_1_ID)) - .thenReturn(IDENTIFIER_1); - - /* test */ - final ResponseEntity<?> response = identifierEndpoint.find(IDENTIFIER_1_ID, accept); - assertEquals(HttpStatus.OK, response.getStatusCode()); - final InputStreamResource body = (InputStreamResource) response.getBody(); - assertNotNull(body); - assertEquals(inputStreamToString(body.getInputStream()), inputStreamToString(compare.getInputStream())); - - } - @Test @WithAnonymousUser public void find_bibliography_succeeds() throws IOException, MalformedException, DataServiceException, @@ -542,6 +662,52 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { assertEquals(compare, body); } + @Test + @WithAnonymousUser + public void find_jsonLd_succeeds() throws MalformedException, DataServiceException, DataServiceConnectionException, + QueryNotFoundException, IdentifierNotFoundException, FormatNotAvailableException { + final String accept = "application/ld+json"; + + /* mock */ + when(identifierService.find(IDENTIFIER_1_ID)) + .thenReturn(IDENTIFIER_1); + + /* test */ + final ResponseEntity<?> response = identifierEndpoint.find(IDENTIFIER_1_ID, accept); + assertEquals(HttpStatus.OK, response.getStatusCode()); + final LdDatasetDto body = (LdDatasetDto) response.getBody(); + assertNotNull(body); + } + + @Test + @WithAnonymousUser + public void find_jsonDatabase_fails() throws IdentifierNotFoundException { + final String accept = "text/csv"; + + /* mock */ + when(identifierService.find(IDENTIFIER_7_ID)) + .thenReturn(IDENTIFIER_7); + + /* test */ + assertThrows(FormatNotAvailableException.class, () -> { + identifierEndpoint.find(IDENTIFIER_7_ID, accept); + }); + } + + @Test + @WithAnonymousUser + public void find_move_succeeds() throws MalformedException, DataServiceException, DataServiceConnectionException, + QueryNotFoundException, IdentifierNotFoundException, FormatNotAvailableException { + + /* mock */ + when(identifierService.find(IDENTIFIER_1_ID)) + .thenReturn(IDENTIFIER_1); + + /* test */ + final ResponseEntity<?> response = identifierEndpoint.find(IDENTIFIER_1_ID, null); + assertEquals(HttpStatus.MOVED_PERMANENTLY, response.getStatusCode()); + } + @Test @WithAnonymousUser public void delete_anonymous_fails() { @@ -568,6 +734,117 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { this.generic_delete(); } + @Test + @WithMockUser(username = USER_2_USERNAME, authorities = {"delete-identifier"}) + public void delete_alreadyPublished_fails() throws DataServiceException, DataServiceConnectionException, + DatabaseNotFoundException, IdentifierNotFoundException, SearchServiceException, + SearchServiceConnectionException { + + /* mock */ + when(identifierService.find(IDENTIFIER_1_ID)) + .thenReturn(IDENTIFIER_1); + doNothing() + .when(identifierService) + .delete(IDENTIFIER_1); + + /* test */ + assertThrows(NotAllowedException.class, () -> { + identifierEndpoint.delete(IDENTIFIER_1_ID); + }); + } + + @Test + @WithAnonymousUser + public void publish_anonymous_fails() { + + /* test */ + assertThrows(AccessDeniedException.class, () -> { + identifierEndpoint.publish(IDENTIFIER_1_ID); + }); + } + + @Test + @WithMockUser(username = USER_1_USERNAME) + public void publish_noRole_fails() { + + /* test */ + assertThrows(AccessDeniedException.class, () -> { + identifierEndpoint.publish(IDENTIFIER_1_ID); + }); + } + + @Test + @WithMockUser(username = USER_1_USERNAME, authorities = {"publish-identifier"}) + public void publish_succeeds() throws IdentifierNotFoundException, SearchServiceException, MalformedException, + DatabaseNotFoundException, ExternalServiceException, SearchServiceConnectionException, + DataServiceConnectionException { + + /* mock */ + when(identifierService.find(IDENTIFIER_1_ID)) + .thenReturn(IDENTIFIER_1); + when(identifierService.publish(IDENTIFIER_1)) + .thenReturn(IDENTIFIER_1); + + /* test */ + final ResponseEntity<IdentifierDto> response = identifierEndpoint.publish(IDENTIFIER_1_ID); + assertEquals(HttpStatus.CREATED, response.getStatusCode()); + final IdentifierDto body = response.getBody(); + assertNotNull(body); + } + + @Test + @WithMockUser(username = USER_1_USERNAME, authorities = {"publish-identifier"}) + public void publish_searchService_fails() throws IdentifierNotFoundException, SearchServiceException, MalformedException, + DatabaseNotFoundException, ExternalServiceException, SearchServiceConnectionException, + DataServiceConnectionException { + + /* mock */ + when(identifierService.find(IDENTIFIER_1_ID)) + .thenReturn(IDENTIFIER_1); + doThrow(SearchServiceException.class) + .when(identifierService) + .publish(IDENTIFIER_1); + + /* test */ + assertThrows(SearchServiceException.class, () -> { + identifierEndpoint.publish(IDENTIFIER_1_ID); + }); + } + + @Test + @WithMockUser(username = USER_1_USERNAME, authorities = {"publish-identifier"}) + public void publish_searchServiceConnection_fails() throws IdentifierNotFoundException, SearchServiceException, + MalformedException, DatabaseNotFoundException, ExternalServiceException, SearchServiceConnectionException, + DataServiceConnectionException { + + /* mock */ + when(identifierService.find(IDENTIFIER_1_ID)) + .thenReturn(IDENTIFIER_1); + doThrow(SearchServiceConnectionException.class) + .when(identifierService) + .publish(IDENTIFIER_1); + + /* test */ + assertThrows(SearchServiceConnectionException.class, () -> { + identifierEndpoint.publish(IDENTIFIER_1_ID); + }); + } + + @Test + @WithMockUser(username = USER_1_USERNAME, authorities = {"publish-identifier"}) + public void publish_notFound_fails() throws IdentifierNotFoundException { + + /* mock */ + doThrow(IdentifierNotFoundException.class) + .when(identifierService) + .find(IDENTIFIER_1_ID); + + /* test */ + assertThrows(IdentifierNotFoundException.class, () -> { + identifierEndpoint.publish(IDENTIFIER_1_ID); + }); + } + @Test @WithAnonymousUser public void find_json_succeeds() throws MalformedException, DataServiceException, DataServiceConnectionException, @@ -627,7 +904,7 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"create-identifier"}) - public void save_hasRoleDatabase_succeeds() throws MalformedException, NotAllowedException, DataServiceException, + public void save_succeeds() throws MalformedException, NotAllowedException, DataServiceException, DataServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, AccessNotFoundException, QueryNotFoundException, IdentifierNotFoundException, ViewNotFoundException, SearchServiceException, SearchServiceConnectionException, TableNotFoundException, ExternalServiceException { @@ -638,7 +915,7 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"create-identifier"}) - public void save_hasRoleDatabaseNoAccess_fails() { + public void save_noAccess_fails() { /* test */ assertThrows(NotAllowedException.class, () -> { @@ -648,7 +925,7 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_2_USERNAME, authorities = {"create-identifier"}) - public void save_hasRoleReadAccessQuery_succeeds() throws MalformedException, NotAllowedException, + public void save_readAccessQuery_succeeds() throws MalformedException, NotAllowedException, DataServiceException, DataServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, AccessNotFoundException, QueryNotFoundException, IdentifierNotFoundException, ViewNotFoundException, SearchServiceException, SearchServiceConnectionException, TableNotFoundException, ExternalServiceException { @@ -661,11 +938,14 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { generic_save(DATABASE_2_ID, DATABASE_2, DATABASE_2_USER_1_READ_ACCESS, IDENTIFIER_5, IDENTIFIER_5_SAVE_DTO, USER_2_PRINCIPAL, USER_2); } - @Test + @ParameterizedTest + @MethodSource("malformedSubset_parameters") @WithMockUser(username = USER_1_USERNAME, authorities = {"create-identifier"}) - public void save_invalidSubset_fails() { + public void save_malformedSubset_fails(String name, Long queryId, Long viewId, Long tableId) { final IdentifierSaveDto request = IdentifierSaveDto.builder() - .queryId(null) // <-- + .queryId(queryId) + .viewId(viewId) + .tableId(tableId) .databaseId(IDENTIFIER_1_DATABASE_ID) .descriptions(List.of(IDENTIFIER_1_DESCRIPTION_1_CREATE_DTO)) .titles(List.of(IDENTIFIER_1_TITLE_1_CREATE_DTO)) @@ -683,21 +963,23 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { }); } - @Test + @ParameterizedTest + @MethodSource("malformedView_parameters") @WithMockUser(username = USER_1_USERNAME, authorities = {"create-identifier"}) - public void save_invalidDatabase_fails() { + public void save_malformedView_fails(String name, Long queryId, Long viewId, Long tableId) { final IdentifierSaveDto request = IdentifierSaveDto.builder() - .queryId(1L) // <-- + .queryId(queryId) + .viewId(viewId) + .tableId(tableId) .databaseId(IDENTIFIER_1_DATABASE_ID) .descriptions(List.of(IDENTIFIER_1_DESCRIPTION_1_CREATE_DTO)) .titles(List.of(IDENTIFIER_1_TITLE_1_CREATE_DTO)) - .relatedIdentifiers(List.of(IDENTIFIER_1_RELATED_IDENTIFIER_5_CREATE_DTO)) - .publicationDay(IDENTIFIER_1_PUBLICATION_DAY) + .relatedIdentifiers(List.of()) .publicationMonth(IDENTIFIER_1_PUBLICATION_MONTH) .publicationYear(IDENTIFIER_1_PUBLICATION_YEAR) .creators(List.of(IDENTIFIER_1_CREATOR_1_CREATE_DTO)) .publisher(IDENTIFIER_1_PUBLISHER) - .type(IdentifierTypeDto.DATABASE) + .type(IdentifierTypeDto.VIEW) .build(); /* test */ @@ -706,21 +988,48 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { }); } - @Test + @ParameterizedTest + @MethodSource("malformedTable_parameters") @WithMockUser(username = USER_1_USERNAME, authorities = {"create-identifier"}) - public void save_invalidView_fails() { + public void save_malformedTable_fails(String name, Long queryId, Long viewId, Long tableId) { final IdentifierSaveDto request = IdentifierSaveDto.builder() - .tableId(1L) // <-- - .databaseId(DATABASE_1_ID) + .queryId(queryId) + .viewId(viewId) + .tableId(tableId) + .databaseId(IDENTIFIER_1_DATABASE_ID) .descriptions(List.of(IDENTIFIER_1_DESCRIPTION_1_CREATE_DTO)) .titles(List.of(IDENTIFIER_1_TITLE_1_CREATE_DTO)) - .relatedIdentifiers(List.of(IDENTIFIER_1_RELATED_IDENTIFIER_5_CREATE_DTO)) - .publicationDay(IDENTIFIER_1_PUBLICATION_DAY) + .relatedIdentifiers(List.of()) .publicationMonth(IDENTIFIER_1_PUBLICATION_MONTH) .publicationYear(IDENTIFIER_1_PUBLICATION_YEAR) .creators(List.of(IDENTIFIER_1_CREATOR_1_CREATE_DTO)) .publisher(IDENTIFIER_1_PUBLISHER) - .type(IdentifierTypeDto.VIEW) + .type(IdentifierTypeDto.TABLE) + .build(); + + /* test */ + assertThrows(MalformedException.class, () -> { + generic_save(DATABASE_1_ID, DATABASE_1, DATABASE_1_USER_1_READ_ACCESS, IDENTIFIER_1, request, USER_1_PRINCIPAL, USER_1); + }); + } + + @ParameterizedTest + @MethodSource("malformedDatabase_parameters") + @WithMockUser(username = USER_1_USERNAME, authorities = {"create-identifier"}) + public void save_malformedDatabase_fails(String name, Long queryId, Long viewId, Long tableId) { + final IdentifierSaveDto request = IdentifierSaveDto.builder() + .queryId(queryId) + .viewId(viewId) + .tableId(tableId) + .databaseId(IDENTIFIER_1_DATABASE_ID) + .descriptions(List.of(IDENTIFIER_1_DESCRIPTION_1_CREATE_DTO)) + .titles(List.of(IDENTIFIER_1_TITLE_1_CREATE_DTO)) + .relatedIdentifiers(List.of()) + .publicationMonth(IDENTIFIER_1_PUBLICATION_MONTH) + .publicationYear(IDENTIFIER_1_PUBLICATION_YEAR) + .creators(List.of(IDENTIFIER_1_CREATOR_1_CREATE_DTO)) + .publisher(IDENTIFIER_1_PUBLISHER) + .type(IdentifierTypeDto.DATABASE) .build(); /* test */ @@ -731,42 +1040,40 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"create-identifier"}) - public void save_foreignUser_fails() { + public void save_invalidDateDay_fails() { final IdentifierSaveDto request = IdentifierSaveDto.builder() - .viewId(9999L) // <-- - .databaseId(DATABASE_1_ID) + .databaseId(IDENTIFIER_1_DATABASE_ID) .descriptions(List.of(IDENTIFIER_1_DESCRIPTION_1_CREATE_DTO)) .titles(List.of(IDENTIFIER_1_TITLE_1_CREATE_DTO)) .relatedIdentifiers(List.of(IDENTIFIER_1_RELATED_IDENTIFIER_5_CREATE_DTO)) - .publicationDay(IDENTIFIER_1_PUBLICATION_DAY) + .publicationDay(32) // <<< .publicationMonth(IDENTIFIER_1_PUBLICATION_MONTH) .publicationYear(IDENTIFIER_1_PUBLICATION_YEAR) .creators(List.of(IDENTIFIER_1_CREATOR_1_CREATE_DTO)) .publisher(IDENTIFIER_1_PUBLISHER) - .type(IdentifierTypeDto.VIEW) + .type(IdentifierTypeDto.DATABASE) .build(); /* test */ - assertThrows(NotAllowedException.class, () -> { - generic_save(DATABASE_1_ID, DATABASE_1, DATABASE_1_USER_1_READ_ACCESS, IDENTIFIER_5, request, USER_1_PRINCIPAL, USER_1); + assertThrows(MalformedException.class, () -> { + generic_save(DATABASE_1_ID, DATABASE_1, DATABASE_1_USER_1_READ_ACCESS, IDENTIFIER_1, request, USER_1_PRINCIPAL, USER_1); }); } @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"create-identifier"}) - public void save_invalidTable_fails() { + public void save_invalidDateMonth_fails() { final IdentifierSaveDto request = IdentifierSaveDto.builder() - .viewId(1L) // <-- - .databaseId(DATABASE_1_ID) + .databaseId(IDENTIFIER_1_DATABASE_ID) .descriptions(List.of(IDENTIFIER_1_DESCRIPTION_1_CREATE_DTO)) .titles(List.of(IDENTIFIER_1_TITLE_1_CREATE_DTO)) .relatedIdentifiers(List.of(IDENTIFIER_1_RELATED_IDENTIFIER_5_CREATE_DTO)) .publicationDay(IDENTIFIER_1_PUBLICATION_DAY) - .publicationMonth(IDENTIFIER_1_PUBLICATION_MONTH) + .publicationMonth(13) // <<< .publicationYear(IDENTIFIER_1_PUBLICATION_YEAR) .creators(List.of(IDENTIFIER_1_CREATOR_1_CREATE_DTO)) .publisher(IDENTIFIER_1_PUBLISHER) - .type(IdentifierTypeDto.TABLE) + .type(IdentifierTypeDto.DATABASE) .build(); /* test */ @@ -775,11 +1082,27 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { }); } + @ParameterizedTest + @MethodSource("save_foreign_parameters") + @WithMockUser(username = USER_1_USERNAME, authorities = {"create-identifier"}) + public void save_foreign_fails(String name, Identifier identifier, IdentifierSaveDto data) + throws UserNotFoundException { + + /* mock */ + when(userService.findByUsername(USER_1_USERNAME)) + .thenReturn(USER_1); + + /* test */ + assertThrows(NotAllowedException.class, () -> { + generic_save(DATABASE_1_ID, DATABASE_1, null, identifier, data, USER_1_PRINCIPAL, USER_1); + }); + } + @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"create-identifier"}) - public void save_tableNotFound_fails() { + public void save_invalidTable_fails() { final IdentifierSaveDto request = IdentifierSaveDto.builder() - .tableId(9999L) // <-- + .viewId(1L) // <-- .databaseId(DATABASE_1_ID) .descriptions(List.of(IDENTIFIER_1_DESCRIPTION_1_CREATE_DTO)) .titles(List.of(IDENTIFIER_1_TITLE_1_CREATE_DTO)) @@ -793,18 +1116,121 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { .build(); /* test */ - assertThrows(TableNotFoundException.class, () -> { + assertThrows(MalformedException.class, () -> { generic_save(DATABASE_1_ID, DATABASE_1, DATABASE_1_USER_1_READ_ACCESS, IDENTIFIER_1, request, USER_1_PRINCIPAL, USER_1); }); } + @ParameterizedTest + @MethodSource("save_parameters") + @WithMockUser(username = USER_1_USERNAME, authorities = {"create-identifier"}) + public void save_noForeign_fails(String name, Long databaseId, Database database, DatabaseAccess access, + Identifier identifier, IdentifierSaveDto data, Principal principal, User user) { + + /* test */ + assertThrows(NotAllowedException.class, () -> { + generic_save(databaseId, database, access, identifier, data, principal, user); + }); + } + + @Test + @WithAnonymousUser + public void create_anonymous_fails() { + + /* test */ + assertThrows(AccessDeniedException.class, () -> { + identifierEndpoint.create(IDENTIFIER_1_CREATE_DTO, USER_1_PRINCIPAL); + }); + } + + @Test + @WithMockUser(username = USER_1_USERNAME) + public void create_noRole_fails() { + + /* test */ + assertThrows(AccessDeniedException.class, () -> { + identifierEndpoint.create(IDENTIFIER_1_CREATE_DTO, USER_1_PRINCIPAL); + }); + } + @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"create-identifier"}) - public void save_queryForeign_fails() { + public void create_succeeds() throws DatabaseNotFoundException, UserNotFoundException, AccessNotFoundException, + SearchServiceException, MalformedException, DataServiceException, QueryNotFoundException, + ExternalServiceException, SearchServiceConnectionException, DataServiceConnectionException, + IdentifierNotFoundException, ViewNotFoundException, NotAllowedException { + + /* mock */ + when(databaseService.findById(DATABASE_1_ID)) + .thenReturn(DATABASE_1); + when(userService.findByUsername(USER_1_USERNAME)) + .thenReturn(USER_1); + when(accessService.find(DATABASE_1, USER_1)) + .thenReturn(DATABASE_1_USER_1_READ_ACCESS); + when(identifierService.create(DATABASE_1, USER_1, IDENTIFIER_1_CREATE_DTO)) + .thenReturn(IDENTIFIER_1); + + /* test */ + final ResponseEntity<IdentifierDto> response = identifierEndpoint.create(IDENTIFIER_1_CREATE_DTO, USER_1_PRINCIPAL); + assertEquals(HttpStatus.CREATED, response.getStatusCode()); + final IdentifierDto body = response.getBody(); + assertNotNull(body); + } + + @Test + @WithMockUser(username = USER_1_USERNAME, authorities = {"create-identifier"}) + public void create_noAccess_fails() throws DatabaseNotFoundException, UserNotFoundException, + AccessNotFoundException { + + /* mock */ + when(databaseService.findById(DATABASE_1_ID)) + .thenReturn(DATABASE_1); + when(userService.findByUsername(USER_1_USERNAME)) + .thenReturn(USER_1); + doThrow(AccessNotFoundException.class) + .when(accessService) + .find(DATABASE_1, USER_1); /* test */ assertThrows(NotAllowedException.class, () -> { - generic_save(DATABASE_2_ID, DATABASE_2, null, IDENTIFIER_5, IDENTIFIER_5_SAVE_DTO, USER_1_PRINCIPAL, USER_1); + identifierEndpoint.create(IDENTIFIER_1_CREATE_DTO, USER_1_PRINCIPAL); + }); + } + + @Test + @WithMockUser(username = USER_2_USERNAME, authorities = {"create-foreign-identifier"}) + public void create_hasForeign_succeeds() throws DatabaseNotFoundException, UserNotFoundException, + AccessNotFoundException, SearchServiceException, MalformedException, NotAllowedException, + DataServiceException, QueryNotFoundException, ExternalServiceException, SearchServiceConnectionException, + DataServiceConnectionException, IdentifierNotFoundException, ViewNotFoundException { + final Principal principal = new UsernamePasswordAuthenticationToken(USER_2_DETAILS, USER_2_PASSWORD, List.of( + new SimpleGrantedAuthority("create-foreign-identifier"))); + + /* mock */ + when(databaseService.findById(DATABASE_1_ID)) + .thenReturn(DATABASE_1); + when(userService.findByUsername(USER_2_USERNAME)) + .thenReturn(USER_2); + doThrow(AccessNotFoundException.class) + .when(accessService) + .find(DATABASE_1, USER_2); + + /* test */ + identifierEndpoint.create(IDENTIFIER_1_CREATE_DTO, principal); + } + + @Test + @WithMockUser(username = USER_1_USERNAME, authorities = {"create-identifier"}) + public void create_databaseNotFound_fails() throws DatabaseNotFoundException { + + /* mock */ + doThrow(DatabaseNotFoundException.class) + .when(databaseService) + .findById(DATABASE_1_ID); + + /* test */ + assertThrows(DatabaseNotFoundException.class, () -> { + identifierEndpoint.create(IDENTIFIER_1_CREATE_DTO, USER_1_PRINCIPAL); }); } @@ -820,6 +1246,14 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { SearchServiceConnectionException, TableNotFoundException, ExternalServiceException { /* mock */ + if (database != null) { + when(databaseService.findById(databaseId)) + .thenReturn(database); + } else { + doThrow(DatabaseNotFoundException.class) + .when(databaseService) + .findById(databaseId); + } if (access != null) { log.trace("mock access: {}", access); when(accessService.find(any(Database.class), any(User.class))) @@ -833,8 +1267,6 @@ public class IdentifierEndpointUnitTest extends AbstractUnitTest { if (identifier.getType().equals(IdentifierType.SUBSET)) { when(dataServiceGateway.findQuery(databaseId, QUERY_2_ID)) .thenReturn(QUERY_2_DTO); - when(userService.findById(USER_1_ID)) - .thenReturn(USER_1); } when(identifierService.find(identifier.getId())) .thenReturn(identifier); diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ImageEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ImageEndpointUnitTest.java index c5c3c24cfd..bf1b2ffa55 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ImageEndpointUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ImageEndpointUnitTest.java @@ -1,13 +1,15 @@ package at.tuwien.endpoints; -import at.tuwien.test.AbstractUnitTest; import at.tuwien.api.container.image.ImageBriefDto; import at.tuwien.api.container.image.ImageChangeDto; import at.tuwien.api.container.image.ImageCreateDto; import at.tuwien.api.container.image.ImageDto; import at.tuwien.entities.container.image.ContainerImage; -import at.tuwien.exception.*; +import at.tuwien.exception.ImageAlreadyExistsException; +import at.tuwien.exception.ImageInvalidException; +import at.tuwien.exception.ImageNotFoundException; import at.tuwien.service.impl.ImageServiceImpl; +import at.tuwien.test.AbstractUnitTest; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -120,19 +122,10 @@ public class ImageEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"create-image"}) - public void create_missingEssentialInfo_fails() { - final ImageCreateDto request = ImageCreateDto.builder() - .name(IMAGE_1_NAME) - .version(IMAGE_1_VERSION) - .defaultPort(null) - .dialect(IMAGE_1_DIALECT) - .jdbcMethod(IMAGE_1_JDBC) - .build(); + public void create_succeeds() throws ImageAlreadyExistsException, ImageInvalidException { /* test */ - assertThrows(ImageInvalidException.class, () -> { - create_generic(request, USER_1_PRINCIPAL); - }); + create_generic(IMAGE_1_CREATE_DTO, USER_1_PRINCIPAL); } @Test diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/MessageEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/MessageEndpointUnitTest.java index 59166b7200..22516074ae 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/MessageEndpointUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/MessageEndpointUnitTest.java @@ -58,11 +58,17 @@ public class MessageEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_1_USERNAME, authorities = {"list-maintenance-messages"}) - public void list_hasRole_succeeds() { + @WithAnonymousUser + public void list_onlyActive_succeeds() { + + /* mock */ + when(bannerMessageService.getActive()) + .thenReturn(List.of(BANNER_MESSAGE_1)); /* test */ - list_generic(); + final ResponseEntity<List<BannerMessageDto>> response = messageEndpoint.list(true); + assertEquals(HttpStatus.OK, response.getStatusCode()); + assertNotNull(response.getBody()); } @Test diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableEndpointUnitTest.java index 1ceb6fd75f..dcc10f61a7 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableEndpointUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/TableEndpointUnitTest.java @@ -3,6 +3,7 @@ package at.tuwien.endpoints; import at.tuwien.api.database.table.TableBriefDto; import at.tuwien.api.database.table.TableCreateDto; import at.tuwien.api.database.table.TableDto; +import at.tuwien.api.database.table.TableUpdateDto; import at.tuwien.api.database.table.columns.ColumnCreateDto; import at.tuwien.api.database.table.columns.ColumnDto; import at.tuwien.api.database.table.columns.ColumnTypeDto; @@ -29,8 +30,6 @@ import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.HttpStatus; @@ -47,7 +46,6 @@ import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; @Log4j2 -@EnableAutoConfiguration(exclude = RabbitAutoConfiguration.class) @SpringBootTest @ExtendWith(SpringExtension.class) public class TableEndpointUnitTest extends AbstractUnitTest { @@ -468,10 +466,10 @@ public class TableEndpointUnitTest extends AbstractUnitTest { .name("Some Table") .description("Some Description") .columns(List.of(ColumnCreateDto.builder() - .name("ID") - .type(ColumnTypeDto.SERIAL) - .nullAllowed(true) // <<< - .build())) + .name("ID") + .type(ColumnTypeDto.SERIAL) + .nullAllowed(true) // <<< + .build())) .constraints(ConstraintsCreateDto.builder() .uniques(List.of(List.of("ID"))) .build()) @@ -514,7 +512,8 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser public void findById_publicAnonymous_succeeds() throws DataServiceException, DataServiceConnectionException, - TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, QueueNotFoundException { + TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, QueueNotFoundException, + UserNotFoundException { /* test */ generic_findById(DATABASE_3_ID, DATABASE_3, TABLE_8_ID, TABLE_8, null, null, null); @@ -532,17 +531,19 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = "find-table") - public void findById_publicHasRoleDatabaseNotFound_succeeds() throws DataServiceException, DataServiceConnectionException, - TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, QueueNotFoundException { + public void findById_publicHasRoleDatabaseNotFound_fails() { /* test */ - generic_findById(DATABASE_3_ID, null, TABLE_8_ID, TABLE_8, USER_1_PRINCIPAL, USER_1, DATABASE_1_USER_1_READ_ACCESS); + assertThrows(DatabaseNotFoundException.class, () -> { + generic_findById(DATABASE_3_ID, null, TABLE_8_ID, TABLE_8, USER_1_PRINCIPAL, USER_1, DATABASE_1_USER_1_READ_ACCESS); + }); } @Test @WithMockUser(username = USER_1_USERNAME, authorities = "find-table") public void findById_publicHasRole_succeeds() throws DataServiceException, DataServiceConnectionException, - TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, QueueNotFoundException { + TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, QueueNotFoundException, + UserNotFoundException { /* test */ final ResponseEntity<TableDto> response = generic_findById(DATABASE_3_ID, DATABASE_3, TABLE_8_ID, TABLE_8, USER_1_PRINCIPAL, USER_1, DATABASE_1_USER_1_READ_ACCESS); @@ -554,7 +555,8 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_4_USERNAME) public void findById_publicNoRole_succeeds() throws DataServiceException, DataServiceConnectionException, - TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, QueueNotFoundException { + TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, QueueNotFoundException, + UserNotFoundException { /* test */ generic_findById(DATABASE_3_ID, DATABASE_3, TABLE_8_ID, TABLE_8, USER_1_PRINCIPAL, USER_1, null); @@ -566,7 +568,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { - analyseTable_generic(DATABASE_1_ID, TABLE_1_ID, TABLE_1); + analyseTable_generic(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, TABLE_1, null); }); } @@ -576,17 +578,17 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { - analyseTable_generic(DATABASE_1_ID, TABLE_1_ID, TABLE_1); + analyseTable_generic(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, TABLE_1, USER_4_PRINCIPAL); }); } @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"table-semantic-analyse"}) public void findAll_hasRole_succeeds() throws MalformedException, TableNotFoundException, - DatabaseNotFoundException { + DatabaseNotFoundException, NotAllowedException { /* test */ - analyseTable_generic(DATABASE_1_ID, TABLE_1_ID, TABLE_1); + analyseTable_generic(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, TABLE_1, USER_1_PRINCIPAL); } @Test @@ -595,7 +597,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { - analyseTableColumn_generic(DATABASE_1_ID, TABLE_1_ID, TABLE_1_COLUMNS.get(0).getId(), TABLE_1_COLUMNS.get(0)); + analyseTableColumn_generic(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, TABLE_1_COLUMNS.get(0).getId(), TABLE_1_COLUMNS.get(0), null); }); } @@ -605,7 +607,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { - analyseTableColumn_generic(DATABASE_1_ID, TABLE_1_ID, TABLE_1_COLUMNS.get(0).getId(), TABLE_1_COLUMNS.get(0)); + analyseTableColumn_generic(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, TABLE_1_COLUMNS.get(0).getId(), TABLE_1_COLUMNS.get(0), USER_4_PRINCIPAL); }); } @@ -615,7 +617,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { DatabaseNotFoundException { /* test */ - analyseTableColumn_generic(DATABASE_1_ID, TABLE_1_ID, TABLE_1_COLUMNS.get(0).getId(), TABLE_1_COLUMNS.get(0)); + analyseTableColumn_generic(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, TABLE_1_COLUMNS.get(0).getId(), TABLE_1_COLUMNS.get(0), USER_1_PRINCIPAL); } @Test @@ -627,7 +629,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { - generic_update(DATABASE_3_ID, DATABASE_3, TABLE_8_ID, TABLE_8, TABLE_8_COLUMNS.get(0).getId(), + generic_updateColumn(DATABASE_3_ID, DATABASE_3, TABLE_8_ID, TABLE_8, TABLE_8_COLUMNS.get(0).getId(), TABLE_8_COLUMNS.get(0), null, null, request, null); }); } @@ -641,7 +643,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(AccessNotFoundException.class, () -> { - generic_update(DATABASE_3_ID, DATABASE_3, TABLE_8_ID, TABLE_8, TABLE_8_COLUMNS.get(0).getId(), + generic_updateColumn(DATABASE_3_ID, DATABASE_3, TABLE_8_ID, TABLE_8, TABLE_8_COLUMNS.get(0).getId(), TABLE_8_COLUMNS.get(0), USER_1_PRINCIPAL, USER_1, request, null); }); } @@ -655,7 +657,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(NotAllowedException.class, () -> { - generic_update(DATABASE_3_ID, DATABASE_3, TABLE_8_ID, TABLE_8, TABLE_8_COLUMNS.get(0).getId(), + generic_updateColumn(DATABASE_3_ID, DATABASE_3, TABLE_8_ID, TABLE_8, TABLE_8_COLUMNS.get(0).getId(), TABLE_8_COLUMNS.get(0), USER_1_PRINCIPAL, USER_1, request, DATABASE_3_USER_1_READ_ACCESS); }); } @@ -671,7 +673,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { .build(); /* test */ - generic_update(DATABASE_3_ID, DATABASE_3, TABLE_8_ID, TABLE_8, TABLE_8_COLUMNS.get(0).getId(), + generic_updateColumn(DATABASE_3_ID, DATABASE_3, TABLE_8_ID, TABLE_8, TABLE_8_COLUMNS.get(0).getId(), TABLE_8_COLUMNS.get(0), USER_1_PRINCIPAL, USER_1, request, DATABASE_3_USER_1_WRITE_OWN_ACCESS); } @@ -684,7 +686,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(NotAllowedException.class, () -> { - generic_update(DATABASE_3_ID, DATABASE_3, TABLE_8_ID, TABLE_8, TABLE_8_COLUMNS.get(0).getId(), + generic_updateColumn(DATABASE_3_ID, DATABASE_3, TABLE_8_ID, TABLE_8, TABLE_8_COLUMNS.get(0).getId(), TABLE_8_COLUMNS.get(0), USER_2_PRINCIPAL, USER_2, request, DATABASE_3_USER_2_WRITE_OWN_ACCESS); }); } @@ -698,7 +700,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(TableNotFoundException.class, () -> { - generic_update(DATABASE_3_ID, DATABASE_3, TABLE_8_ID, null, TABLE_8_COLUMNS.get(0).getId(), + generic_updateColumn(DATABASE_3_ID, DATABASE_3, TABLE_8_ID, null, TABLE_8_COLUMNS.get(0).getId(), TABLE_8_COLUMNS.get(0), USER_1_PRINCIPAL, USER_1, request, DATABASE_3_USER_1_WRITE_OWN_ACCESS); }); } @@ -714,7 +716,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { .build(); /* test */ - generic_update(DATABASE_3_ID, DATABASE_3, TABLE_8_ID, TABLE_8, TABLE_8_COLUMNS.get(0).getId(), + generic_updateColumn(DATABASE_3_ID, DATABASE_3, TABLE_8_ID, TABLE_8, TABLE_8_COLUMNS.get(0).getId(), TABLE_8_COLUMNS.get(0), USER_2_PRINCIPAL, USER_2, request, DATABASE_3_USER_2_WRITE_ALL_ACCESS); } @@ -731,7 +733,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { - generic_update(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, TABLE_1, TABLE_1_COLUMNS.get(0).getId(), + generic_updateColumn(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, TABLE_1, TABLE_1_COLUMNS.get(0).getId(), TABLE_1_COLUMNS.get(0), null, null, request, null); }); } @@ -745,7 +747,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(AccessNotFoundException.class, () -> { - generic_update(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, TABLE_1, TABLE_1_COLUMNS.get(0).getId(), + generic_updateColumn(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, TABLE_1, TABLE_1_COLUMNS.get(0).getId(), TABLE_1_COLUMNS.get(0), USER_1_PRINCIPAL, USER_1, request, null); }); } @@ -759,7 +761,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(NotAllowedException.class, () -> { - generic_update(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, TABLE_1, TABLE_1_COLUMNS.get(0).getId(), + generic_updateColumn(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, TABLE_1, TABLE_1_COLUMNS.get(0).getId(), TABLE_1_COLUMNS.get(0), USER_1_PRINCIPAL, USER_1, request, DATABASE_1_USER_1_READ_ACCESS); }); } @@ -775,7 +777,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { .build(); /* test */ - generic_update(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, TABLE_1, TABLE_1_COLUMNS.get(0).getId(), + generic_updateColumn(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, TABLE_1, TABLE_1_COLUMNS.get(0).getId(), TABLE_1_COLUMNS.get(0), USER_1_PRINCIPAL, USER_1, request, DATABASE_1_USER_1_WRITE_OWN_ACCESS); } @@ -788,7 +790,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(NotAllowedException.class, () -> { - generic_update(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, TABLE_1, TABLE_1_COLUMNS.get(0).getId(), + generic_updateColumn(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, TABLE_1, TABLE_1_COLUMNS.get(0).getId(), TABLE_1_COLUMNS.get(0), USER_2_PRINCIPAL, USER_2, request, DATABASE_1_USER_2_WRITE_OWN_ACCESS); }); } @@ -802,7 +804,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { /* test */ assertThrows(TableNotFoundException.class, () -> { - generic_update(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, null, TABLE_1_COLUMNS.get(0).getId(), + generic_updateColumn(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, null, TABLE_1_COLUMNS.get(0).getId(), TABLE_1_COLUMNS.get(0), USER_2_PRINCIPAL, USER_2, request, DATABASE_1_USER_2_WRITE_ALL_ACCESS); }); } @@ -818,7 +820,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { .build(); /* test */ - generic_update(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, TABLE_1, TABLE_1_COLUMNS.get(0).getId(), + generic_updateColumn(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, TABLE_1, TABLE_1_COLUMNS.get(0).getId(), TABLE_1_COLUMNS.get(0), USER_2_PRINCIPAL, USER_2, request, DATABASE_1_USER_2_WRITE_ALL_ACCESS); } @@ -897,7 +899,8 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser public void findById_privateAnonymous_succeeds() throws DataServiceException, DataServiceConnectionException, - TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, QueueNotFoundException { + TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, QueueNotFoundException, + UserNotFoundException { /* test */ generic_findById(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, TABLE_1, null, null, null); @@ -915,17 +918,19 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = "find-table") - public void findById_privateHasRoleDatabaseNotFound_succeeds() throws DataServiceException, DataServiceConnectionException, - TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, QueueNotFoundException { + public void findById_privateHasRoleDatabaseNotFound_fails() { /* test */ - generic_findById(DATABASE_1_ID, null, TABLE_1_ID, TABLE_1, USER_1_PRINCIPAL, USER_1, DATABASE_1_USER_1_READ_ACCESS); + assertThrows(DatabaseNotFoundException.class, () -> { + generic_findById(DATABASE_1_ID, null, TABLE_1_ID, TABLE_1, USER_1_PRINCIPAL, USER_1, DATABASE_1_USER_1_READ_ACCESS); + }); } @Test @WithMockUser(username = USER_1_USERNAME, authorities = "find-table") public void findById_privateHasRole_succeeds() throws DataServiceException, DataServiceConnectionException, - TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, QueueNotFoundException { + TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, QueueNotFoundException, + UserNotFoundException { /* test */ final ResponseEntity<TableDto> response = generic_findById(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, TABLE_1, USER_1_PRINCIPAL, USER_1, DATABASE_1_USER_1_READ_ACCESS); @@ -937,7 +942,8 @@ public class TableEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_4_USERNAME) public void findById_privateNoRole_succeeds() throws DataServiceException, DataServiceConnectionException, - TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, QueueNotFoundException { + TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, QueueNotFoundException, + UserNotFoundException { /* test */ generic_findById(DATABASE_1_ID, DATABASE_1, TABLE_1_ID, TABLE_1, USER_4_PRINCIPAL, USER_4, null); @@ -998,25 +1004,83 @@ public class TableEndpointUnitTest extends AbstractUnitTest { }); } + @Test + @WithMockUser(username = USER_1_USERNAME, authorities = {"update-table"}) + public void update_succeeds() throws TableNotFoundException, SearchServiceException, NotAllowedException, + DataServiceException, DatabaseNotFoundException, SearchServiceConnectionException, + DataServiceConnectionException { + final TableUpdateDto request = TableUpdateDto.builder() + .isPublic(true) + .isSchemaPublic(true) + .description("Debug") + .build(); + + /* test */ + final ResponseEntity<TableDto> response = generic_update(request, USER_1_PRINCIPAL); + assertEquals(HttpStatus.ACCEPTED, response.getStatusCode()); + assertNotNull(response.getBody()); + } + + @Test + @WithMockUser(username = USER_2_USERNAME, authorities = {"update-table"}) + public void update_notOwner_fails() { + final TableUpdateDto request = TableUpdateDto.builder() + .isPublic(true) + .isSchemaPublic(true) + .description("Debug") + .build(); + + /* test */ + assertThrows(NotAllowedException.class, () -> { + generic_update(request, USER_2_PRINCIPAL); + }); + } + + @Test + @WithMockUser(username = USER_2_USERNAME, authorities = {"update-table-statistic"}) + public void updateStatistic_notOwner_fails() { + + /* test */ + assertThrows(NotAllowedException.class, () -> { + generic_updateStatistic(USER_2_PRINCIPAL); + }); + } + + @Test + @WithMockUser(username = USER_1_USERNAME, authorities = {"update-table-statistic"}) + public void updateStatistic_succeeds() throws TableNotFoundException, SearchServiceException, MalformedException, + NotAllowedException, DataServiceException, DatabaseNotFoundException, SearchServiceConnectionException, + DataServiceConnectionException { + + /* test */ + final ResponseEntity<Void> response = generic_updateStatistic(USER_1_PRINCIPAL); + assertEquals(HttpStatus.ACCEPTED, response.getStatusCode()); + } + /* ################################################################################################### */ /* ## GENERIC TEST CASES ## */ /* ################################################################################################### */ - public void analyseTable_generic(Long databaseId, Long tableId, Table table) throws MalformedException, - TableNotFoundException, DatabaseNotFoundException { + public void analyseTable_generic(Long databaseId, Database database, Long tableId, Table table, Principal principal) + throws MalformedException, TableNotFoundException, DatabaseNotFoundException, NotAllowedException { /* mock */ + when(databaseService.findById(databaseId)) + .thenReturn(database); + when(tableService.findById(database, tableId)) + .thenReturn(table); when(entityService.suggestByTable(table)) .thenReturn(List.of()); /* test */ - final ResponseEntity<List<EntityDto>> response = tableEndpoint.analyseTable(databaseId, tableId); + final ResponseEntity<List<EntityDto>> response = tableEndpoint.analyseTable(databaseId, tableId, principal); assertEquals(HttpStatus.OK, response.getStatusCode()); final List<EntityDto> body = response.getBody(); assertNotNull(body); } - public void analyseTableColumn_generic(Long databaseId, Long tableId, Long columnId, TableColumn tableColumn) + public void analyseTableColumn_generic(Long databaseId, Database database, Long tableId, Long columnId, + TableColumn tableColumn, Principal principal) throws MalformedException, TableNotFoundException, DatabaseNotFoundException { /* mock */ @@ -1024,7 +1088,8 @@ public class TableEndpointUnitTest extends AbstractUnitTest { .thenReturn(List.of()); /* test */ - final ResponseEntity<List<TableColumnEntityDto>> response = tableEndpoint.analyseTableColumn(databaseId, tableId, columnId); + final ResponseEntity<List<TableColumnEntityDto>> response = tableEndpoint.analyseTableColumn(databaseId, + tableId, columnId, principal); assertEquals(HttpStatus.OK, response.getStatusCode()); final List<TableColumnEntityDto> body = response.getBody(); assertNotNull(body); @@ -1095,19 +1160,9 @@ public class TableEndpointUnitTest extends AbstractUnitTest { Table table, Principal principal, User user, DatabaseAccess access) throws DataServiceException, DataServiceConnectionException, TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, - QueueNotFoundException { + QueueNotFoundException, UserNotFoundException { /* mock */ - if (table != null) { - when(tableService.findById(databaseId, tableId)) - .thenReturn(table); - when(databaseService.findById(databaseId)) - .thenReturn(database); - } else { - doThrow(TableNotFoundException.class) - .when(tableService) - .findById(databaseId, tableId); - } if (database != null) { when(databaseService.findById(databaseId)) .thenReturn(database); @@ -1116,13 +1171,19 @@ public class TableEndpointUnitTest extends AbstractUnitTest { .when(databaseService) .findById(databaseId); } - if (access != null) { - when(accessService.find(database, user)) - .thenReturn(access); + if (table != null) { + when(tableService.findById(any(Database.class), eq(tableId))) + .thenReturn(table); } else { - doThrow(AccessNotFoundException.class) - .when(accessService) - .find(database, user); + doThrow(TableNotFoundException.class) + .when(tableService) + .findById(any(Database.class), eq(tableId)); + } + if (principal != null) { + when(userService.findByUsername(principal.getName())) + .thenReturn(user); + when(accessService.find(any(Database.class), eq(user))) + .thenReturn(access); } /* test */ @@ -1134,24 +1195,29 @@ public class TableEndpointUnitTest extends AbstractUnitTest { SearchServiceException, SearchServiceConnectionException { /* mock */ - when(tableService.findById(anyLong(), anyLong())) + when(databaseService.findById(DATABASE_1_ID)) + .thenReturn(DATABASE_1); + when(tableService.findById(any(Database.class), anyLong())) .thenReturn(table); /* test */ return tableEndpoint.delete(DATABASE_1_ID, TABLE_1_ID, principal); } - protected ResponseEntity<ColumnDto> generic_update(Long databaseId, Database database, Long tableId, Table table, - Long columnId, TableColumn column, Principal principal, - User user, ColumnSemanticsUpdateDto data, DatabaseAccess access) + protected ResponseEntity<ColumnDto> generic_updateColumn(Long databaseId, Database database, Long tableId, + Table table, Long columnId, TableColumn column, + Principal principal, User user, + ColumnSemanticsUpdateDto data, DatabaseAccess access) throws DataServiceException, DataServiceConnectionException, MalformedException, NotAllowedException, UserNotFoundException, TableNotFoundException, DatabaseNotFoundException, AccessNotFoundException, SearchServiceException, SearchServiceConnectionException, OntologyNotFoundException, SemanticEntityNotFoundException { /* mock */ + when(databaseService.findById(databaseId)) + .thenReturn(database); if (table != null) { - when(tableService.findById(databaseId, tableId)) + when(tableService.findById(database, tableId)) .thenReturn(table); when(tableService.update(column, data)) .thenReturn(column); @@ -1161,7 +1227,7 @@ public class TableEndpointUnitTest extends AbstractUnitTest { .update(column, data); doThrow(TableNotFoundException.class) .when(tableService) - .findById(databaseId, tableId); + .findById(database, tableId); } if (principal != null) { log.trace("mock user {}", user); @@ -1180,6 +1246,40 @@ public class TableEndpointUnitTest extends AbstractUnitTest { } /* test */ - return tableEndpoint.update(databaseId, tableId, columnId, data, principal); + return tableEndpoint.updateColumn(databaseId, tableId, columnId, data, principal); + } + + protected ResponseEntity<TableDto> generic_update(TableUpdateDto data, Principal caller) + throws TableNotFoundException, SearchServiceException, NotAllowedException, DataServiceException, + DatabaseNotFoundException, SearchServiceConnectionException, DataServiceConnectionException { + + /* mock */ + when(databaseService.findById(DATABASE_1_ID)) + .thenReturn(DATABASE_1); + when(tableService.findById(DATABASE_1, TABLE_1_ID)) + .thenReturn(TABLE_1); + when(tableService.updateTable(any(Table.class), eq(data))) + .thenReturn(TABLE_1); + + /* test */ + return tableEndpoint.update(DATABASE_1_ID, TABLE_1_ID, data, caller); + } + + protected ResponseEntity<Void> generic_updateStatistic(Principal caller) + throws TableNotFoundException, SearchServiceException, NotAllowedException, DataServiceException, + DatabaseNotFoundException, SearchServiceConnectionException, DataServiceConnectionException, + MalformedException { + + /* mock */ + when(databaseService.findById(DATABASE_1_ID)) + .thenReturn(DATABASE_1); + when(tableService.findById(DATABASE_1, TABLE_1_ID)) + .thenReturn(TABLE_1); + doNothing() + .when(tableService) + .updateStatistics(TABLE_1); + + /* test */ + return tableEndpoint.updateStatistic(DATABASE_1_ID, TABLE_1_ID, caller); } } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/UserEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/UserEndpointUnitTest.java index da86dd9344..54cef2ca4b 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/UserEndpointUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/UserEndpointUnitTest.java @@ -1,23 +1,32 @@ package at.tuwien.endpoints; -import at.tuwien.test.AbstractUnitTest; +import at.tuwien.api.auth.LoginRequestDto; import at.tuwien.api.auth.SignupRequestDto; -import at.tuwien.api.user.*; +import at.tuwien.api.keycloak.UserAttributesDto; +import at.tuwien.api.user.UserBriefDto; +import at.tuwien.api.user.UserDto; +import at.tuwien.api.user.UserPasswordDto; +import at.tuwien.api.user.UserUpdateDto; import at.tuwien.entities.user.User; import at.tuwien.exception.*; import at.tuwien.service.AuthenticationService; +import at.tuwien.service.DatabaseService; import at.tuwien.service.UserService; +import at.tuwien.test.AbstractUnitTest; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.test.context.support.WithAnonymousUser; import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.context.junit.jupiter.SpringExtension; @@ -25,12 +34,12 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import java.security.Principal; import java.util.List; import java.util.UUID; +import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; @Log4j2 -@EnableAutoConfiguration(exclude = RabbitAutoConfiguration.class) @SpringBootTest @ExtendWith(SpringExtension.class) public class UserEndpointUnitTest extends AbstractUnitTest { @@ -41,9 +50,19 @@ public class UserEndpointUnitTest extends AbstractUnitTest { @MockBean private AuthenticationService authenticationService; + @MockBean + private DatabaseService databaseService; + @Autowired private UserEndpoint userEndpoint; + public static Stream<Arguments> getToken_parameters() { + return Stream.of( + Arguments.arguments("null", null), + Arguments.arguments("empty", new UUID[]{}) + ); + } + @BeforeEach public void beforeEach() { genesis(); @@ -142,13 +161,28 @@ public class UserEndpointUnitTest extends AbstractUnitTest { } @Test - @WithMockUser(username = USER_3_USERNAME, authorities = {"find-user"}) - public void find_hasRoleForeign_succeeds() { + @WithMockUser(username = USER_3_USERNAME, authorities = {"find-foreign-user"}) + public void find_hasRoleForeign_succeeds() throws UserNotFoundException, NotAllowedException { + final Principal principal = new UsernamePasswordAuthenticationToken(USER_3_DETAILS, USER_3_PASSWORD, List.of( + new SimpleGrantedAuthority("find-foreign-user"))); /* test */ - assertThrows(NotAllowedException.class, () -> { - find_generic(USER_2_ID, USER_2, USER_3_PRINCIPAL); - }); + find_generic(USER_2_ID, USER_2, principal); + } + + @Test + @WithMockUser(username = USER_3_USERNAME, authorities = {"system"}) + public void find_system_succeeds() throws UserNotFoundException, NotAllowedException { + final Principal principal = new UsernamePasswordAuthenticationToken(USER_3_DETAILS, USER_3_PASSWORD, List.of( + new SimpleGrantedAuthority("system"))); + + /* test */ + final ResponseEntity<UserDto> response = find_generic(USER_3_ID, USER_3, principal); + assertNotNull(response.getHeaders().get("X-Username")); + assertEquals(USER_3_USERNAME, response.getHeaders().get("X-Username").get(0)); + assertNotNull(response.getHeaders().get("X-Password")); + assertNotEquals(USER_3_PASSWORD, response.getHeaders().get("X-Password").get(0)); + assertEquals(USER_3_DATABASE_PASSWORD, response.getHeaders().get("X-Password").get(0)); } @Test @@ -252,6 +286,136 @@ public class UserEndpointUnitTest extends AbstractUnitTest { password_generic(USER_1_PRINCIPAL, request); } + @Test + @WithAnonymousUser + public void getToken_anonymous_succeeds() throws UserNotFoundException, AuthServiceException, + AuthServiceConnectionException, AccountNotSetupException, CredentialsInvalidException { + + /* test */ + getToken_generic(USER_1_LOGIN_REQUEST_DTO, USER_1_PRINCIPAL, USER_1); + } + + @Test + @WithMockUser(username = USER_1_USERNAME) + public void getToken_loggedIn_succeeds() throws UserNotFoundException, AuthServiceException, + AuthServiceConnectionException, AccountNotSetupException, CredentialsInvalidException { + + /* test */ + getToken_generic(USER_1_LOGIN_REQUEST_DTO, USER_1_PRINCIPAL, USER_1); + } + + @Test + @WithAnonymousUser + public void getToken_notExists_succeeds() throws UserNotFoundException, AuthServiceException, + AuthServiceConnectionException, AccountNotSetupException, CredentialsInvalidException { + + /* mock */ + when(authenticationService.findByUsername(USER_1_USERNAME)) + .thenReturn(USER_1_KEYCLOAK_DTO); + when(userService.create(any(SignupRequestDto.class), any(UUID.class))) + .thenReturn(USER_1); + + /* test */ + getToken_generic(USER_1_LOGIN_REQUEST_DTO, USER_1_PRINCIPAL, null); + } + + @Test + @WithAnonymousUser + public void getToken_notExists_fails() throws UserNotFoundException, AuthServiceException, + AuthServiceConnectionException, CredentialsInvalidException { + + /* mock */ + doThrow(UserNotFoundException.class) + .when(authenticationService) + .findByUsername(USER_1_USERNAME); + + /* test */ + assertThrows(UserNotFoundException.class, () -> { + getToken_generic(USER_1_LOGIN_REQUEST_DTO, USER_1_PRINCIPAL, null); + }); + } + + @ParameterizedTest + @MethodSource("getToken_parameters") + @WithAnonymousUser + public void getToken_missingLdapId_fails(String name, UUID[] ldapId) throws UserNotFoundException, AuthServiceException, + AuthServiceConnectionException, CredentialsInvalidException { + final at.tuwien.api.keycloak.UserDto mock = at.tuwien.api.keycloak.UserDto.builder() + .attributes(UserAttributesDto.builder() + .ldapId(ldapId) + .build()) + .build(); + + /* mock */ + when(authenticationService.findByUsername(USER_1_USERNAME)) + .thenReturn(mock); + + /* test */ + assertThrows(UserNotFoundException.class, () -> { + getToken_generic(USER_1_LOGIN_REQUEST_DTO, USER_1_PRINCIPAL, null); + }); + } + + @Test + @WithAnonymousUser + public void refreshToken_anonymous_succeeds() throws AuthServiceConnectionException, CredentialsInvalidException { + + /* mock */ + when(authenticationService.refreshToken(anyString())) + .thenReturn(TOKEN_DTO); + + /* test */ + final ResponseEntity<?> response = userEndpoint.refreshToken(REFRESH_TOKEN_REQUEST_DTO); + assertEquals(HttpStatus.ACCEPTED, response.getStatusCode()); + assertNotNull(response.getBody()); + } + + @Test + @WithMockUser(username = USER_1_USERNAME) + public void refreshToken_loggedIn_succeeds() throws AuthServiceConnectionException, CredentialsInvalidException { + + /* mock */ + when(authenticationService.refreshToken(anyString())) + .thenReturn(TOKEN_DTO); + + /* test */ + final ResponseEntity<?> response = userEndpoint.refreshToken(REFRESH_TOKEN_REQUEST_DTO); + assertEquals(HttpStatus.ACCEPTED, response.getStatusCode()); + assertNotNull(response.getBody()); + } + + @Test + @WithMockUser(username = USER_1_USERNAME) + public void refreshToken_authServiceConnection_fails() throws AuthServiceConnectionException, + CredentialsInvalidException { + + /* mock */ + doThrow(AuthServiceConnectionException.class) + .when(authenticationService) + .refreshToken(anyString()); + + /* test */ + assertThrows(AuthServiceConnectionException.class, () -> { + userEndpoint.refreshToken(REFRESH_TOKEN_REQUEST_DTO); + }); + } + + @Test + @WithMockUser(username = USER_1_USERNAME) + public void refreshToken_invalidCredentials_fails() throws AuthServiceConnectionException, + CredentialsInvalidException { + + /* mock */ + doThrow(CredentialsInvalidException.class) + .when(authenticationService) + .refreshToken(anyString()); + + /* test */ + assertThrows(CredentialsInvalidException.class, () -> { + userEndpoint.refreshToken(REFRESH_TOKEN_REQUEST_DTO); + }); + } + /* ################################################################################################### */ /* ## GENERIC TEST CASES ## */ /* ################################################################################################### */ @@ -300,7 +464,7 @@ public class UserEndpointUnitTest extends AbstractUnitTest { assertNotNull(body); } - protected void find_generic(UUID id, User user, Principal principal) throws NotAllowedException, + protected ResponseEntity<UserDto> find_generic(UUID id, User user, Principal principal) throws NotAllowedException, UserNotFoundException { /* mock */ @@ -318,6 +482,7 @@ public class UserEndpointUnitTest extends AbstractUnitTest { assertEquals(HttpStatus.OK, response.getStatusCode()); final UserDto body = response.getBody(); assertNotNull(body); + return response; } protected void modify_generic(UUID userId, User user, Principal principal, UserUpdateDto data) @@ -347,9 +512,36 @@ public class UserEndpointUnitTest extends AbstractUnitTest { doNothing() .when(userService) .updatePassword(USER_1, data); + when(databaseService.findAllAccess(USER_1_ID)) + .thenReturn(List.of(DATABASE_1)); + doNothing() + .when(databaseService) + .updatePassword(DATABASE_1, USER_1); /* test */ final ResponseEntity<?> response = userEndpoint.password(USER_1_ID, data, principal); assertEquals(HttpStatus.ACCEPTED, response.getStatusCode()); } + + protected void getToken_generic(LoginRequestDto request, Principal principal, User user) + throws UserNotFoundException, AuthServiceConnectionException, AccountNotSetupException, + CredentialsInvalidException, AuthServiceException { + + /* mock */ + when(authenticationService.obtainToken(any(LoginRequestDto.class))) + .thenReturn(TOKEN_DTO); + if (user != null) { + when(userService.findByUsername(principal.getName())) + .thenReturn(user); + } else { + doThrow(UserNotFoundException.class) + .when(userService) + .findByUsername(principal.getName()); + } + + /* test */ + final ResponseEntity<?> response = userEndpoint.getToken(request); + assertEquals(HttpStatus.ACCEPTED, response.getStatusCode()); + assertNotNull(response.getBody()); + } } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ViewEndpointUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ViewEndpointUnitTest.java index 7f1855b91e..ccd8b067de 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ViewEndpointUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/endpoints/ViewEndpointUnitTest.java @@ -3,6 +3,7 @@ package at.tuwien.endpoints; import at.tuwien.api.database.ViewBriefDto; import at.tuwien.api.database.ViewCreateDto; import at.tuwien.api.database.ViewDto; +import at.tuwien.api.database.ViewUpdateDto; import at.tuwien.entities.database.Database; import at.tuwien.entities.database.DatabaseAccess; import at.tuwien.entities.database.View; @@ -22,6 +23,7 @@ import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.security.access.AccessDeniedException; import org.springframework.security.test.context.support.WithAnonymousUser; import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.context.junit.jupiter.SpringExtension; @@ -99,7 +101,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { public void create_publicAnonymous_succeeds() { /* test */ - assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { + assertThrows(AccessDeniedException.class, () -> { create_generic(DATABASE_3_ID, DATABASE_3, null, null, null, null); }); } @@ -129,11 +131,21 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { public void create_publicNoRole_fails() { /* test */ - assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { + assertThrows(AccessDeniedException.class, () -> { create_generic(DATABASE_3_ID, DATABASE_3, USER_2_PRINCIPAL, USER_2_ID, USER_2, null); }); } + @Test + @WithMockUser(username = USER_1_USERNAME, authorities = {"create-database-view"}) + public void create_succeeds() throws UserNotFoundException, SearchServiceException, MalformedException, + NotAllowedException, DataServiceException, DatabaseNotFoundException, AccessNotFoundException, + SearchServiceConnectionException, DataServiceConnectionException { + + /* test */ + create_generic(DATABASE_1_ID, DATABASE_1, USER_1_PRINCIPAL, USER_1_ID, USER_1, DATABASE_1_USER_1_WRITE_ALL_ACCESS); + } + @Test @WithAnonymousUser public void find_publicAnonymous_succeeds() throws UserNotFoundException, DatabaseNotFoundException, @@ -175,7 +187,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { public void delete_publicAnonymous_fails() { /* test */ - assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { + assertThrows(AccessDeniedException.class, () -> { delete_generic(DATABASE_3_ID, DATABASE_3, VIEW_1_ID, VIEW_1, null, null, null, null); }); } @@ -195,7 +207,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { public void delete_publicNoRole_fails() { /* test */ - assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { + assertThrows(AccessDeniedException.class, () -> { delete_generic(DATABASE_3_ID, DATABASE_3, VIEW_1_ID, VIEW_1, USER_2_PRINCIPAL, USER_2_ID, USER_2, DATABASE_2_USER_1_READ_ACCESS); }); } @@ -252,10 +264,10 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void create_privateAnonymous_succeeds() { + public void create_privateAnonymous_fails() { /* test */ - assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { + assertThrows(AccessDeniedException.class, () -> { create_generic(DATABASE_1_ID, DATABASE_1, null, null, null, null); }); } @@ -285,7 +297,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { public void create_privateNoRole_fails() { /* test */ - assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { + assertThrows(AccessDeniedException.class, () -> { create_generic(DATABASE_1_ID, DATABASE_1, USER_2_PRINCIPAL, USER_2_ID, USER_2, null); }); } @@ -331,7 +343,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { public void delete_privateAnonymous_fails() { /* test */ - assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { + assertThrows(AccessDeniedException.class, () -> { delete_generic(DATABASE_1_ID, DATABASE_1, VIEW_1_ID, VIEW_1, null, null, null, null); }); } @@ -351,7 +363,7 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { public void delete_privateNoRole_fails() { /* test */ - assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> { + assertThrows(AccessDeniedException.class, () -> { delete_generic(DATABASE_1_ID, DATABASE_1, VIEW_1_ID, VIEW_1, USER_2_PRINCIPAL, USER_2_ID, USER_2, DATABASE_2_USER_1_READ_ACCESS); }); } @@ -366,6 +378,45 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { delete_generic(DATABASE_1_ID, DATABASE_1, VIEW_1_ID, VIEW_1, USER_1_PRINCIPAL, USER_1_ID, USER_1, DATABASE_1_USER_1_WRITE_ALL_ACCESS); } + @Test + @WithAnonymousUser + public void update_anonymous_succeeds() { + + /* test */ + assertThrows(AccessDeniedException.class, () -> { + update_generic(USER_1_PRINCIPAL); + }); + } + + @Test + @WithMockUser(username = USER_1_USERNAME) + public void update_noRole_fails() { + + /* test */ + assertThrows(AccessDeniedException.class, () -> { + update_generic(USER_1_PRINCIPAL); + }); + } + + @Test + @WithMockUser(username = USER_2_USERNAME, authorities = {"modify-view-visibility"}) + public void update_notOwner_fails() { + + /* test */ + assertThrows(NotAllowedException.class, () -> { + update_generic(USER_2_PRINCIPAL); + }); + } + + @Test + @WithMockUser(username = USER_1_USERNAME, authorities = {"modify-view-visibility"}) + public void update_succeeds() throws NotAllowedException, DataServiceConnectionException, DatabaseNotFoundException, + SearchServiceException, SearchServiceConnectionException, ViewNotFoundException { + + /* test */ + update_generic(USER_1_PRINCIPAL); + } + /* ################################################################################################### */ /* ## GENERIC TEST CASES ## */ /* ################################################################################################### */ @@ -419,6 +470,10 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { /* mock */ when(databaseService.findById(databaseId)) .thenReturn(database); + if (principal != null) { + when(userService.findByUsername(principal.getName())) + .thenReturn(user); + } if (access != null) { log.trace("mock access of database with id {} and user id {}", databaseId, userId); when(accessService.find(database, user)) @@ -499,4 +554,26 @@ public class ViewEndpointUnitTest extends AbstractUnitTest { assertEquals(HttpStatus.ACCEPTED, response.getStatusCode()); } + protected void update_generic(Principal principal) throws SearchServiceException, NotAllowedException, + DatabaseNotFoundException, SearchServiceConnectionException, DataServiceConnectionException, + ViewNotFoundException { + final ViewUpdateDto request = ViewUpdateDto.builder() + .isPublic(true) + .isSchemaPublic(true) + .build(); + + /* mock */ + when(databaseService.findById(DATABASE_1_ID)) + .thenReturn(DATABASE_1); + when(viewService.findById(DATABASE_1, VIEW_1_ID)) + .thenReturn(VIEW_1); + when(viewService.update(DATABASE_1, VIEW_1, request)) + .thenReturn(VIEW_1); + + /* test */ + final ResponseEntity<ViewDto> response = viewEndpoint.update(DATABASE_1_ID, VIEW_1_ID, request, principal); + assertEquals(HttpStatus.ACCEPTED, response.getStatusCode()); + assertNotNull(response.getBody()); + } + } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/PrometheusEndpointMvcTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/PrometheusEndpointMvcTest.java index 9a43b234d9..578f6276c7 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/PrometheusEndpointMvcTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mvc/PrometheusEndpointMvcTest.java @@ -535,22 +535,22 @@ public class PrometheusEndpointMvcTest extends AbstractUnitTest { /* ignore */ } try { - tableEndpoint.analyseTable(DATABASE_1_ID, TABLE_1_ID); + tableEndpoint.analyseTable(DATABASE_1_ID, TABLE_1_ID, USER_1_PRINCIPAL); } catch (Exception e) { /* ignore */ } try { - tableEndpoint.updateStatistic(DATABASE_1_ID, TABLE_1_ID); + tableEndpoint.updateStatistic(DATABASE_1_ID, TABLE_1_ID, USER_1_PRINCIPAL); } catch (Exception e) { /* ignore */ } try { - tableEndpoint.analyseTableColumn(DATABASE_1_ID, TABLE_1_ID, TABLE_1_COLUMNS.get(0).getId()); + tableEndpoint.analyseTableColumn(DATABASE_1_ID, TABLE_1_ID, TABLE_1_COLUMNS.get(0).getId(), USER_1_PRINCIPAL); } catch (Exception e) { /* ignore */ } try { - tableEndpoint.update(DATABASE_1_ID, TABLE_1_ID, TABLE_1_COLUMNS.get(3).getId(), request, USER_1_PRINCIPAL); + tableEndpoint.updateColumn(DATABASE_1_ID, TABLE_1_ID, TABLE_1_COLUMNS.get(3).getId(), request, USER_1_PRINCIPAL); } catch (Exception e) { /* ignore */ } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DataCiteIdentifierServicePersistenceTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DataCiteIdentifierServicePersistenceTest.java index 43f99276f5..182fe8e14a 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DataCiteIdentifierServicePersistenceTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DataCiteIdentifierServicePersistenceTest.java @@ -217,8 +217,7 @@ public class DataCiteIdentifierServicePersistenceTest extends AbstractUnitTest { @Test public void publish_succeeds() throws MalformedException, DataServiceConnectionException, SearchServiceException, - DatabaseNotFoundException, SearchServiceConnectionException, IdentifierNotFoundException, - ExternalServiceException { + DatabaseNotFoundException, SearchServiceConnectionException, ExternalServiceException { final ResponseEntity<DataCiteBody<DataCiteDoi>> mock = ResponseEntity.status(HttpStatus.CREATED) .body(IDENTIFIER_7_DATA_CITE); @@ -227,7 +226,7 @@ public class DataCiteIdentifierServicePersistenceTest extends AbstractUnitTest { .thenReturn(mock); /* test */ - final Identifier response = dataCiteIdentifierService.publish(IDENTIFIER_7_ID); + final Identifier response = dataCiteIdentifierService.publish(IDENTIFIER_7); assertEquals(IDENTIFIER_7_ID, response.getId()); assertEquals(IdentifierStatusType.PUBLISHED, response.getStatus()); } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/IdentifierServicePersistenceTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/IdentifierServicePersistenceTest.java index 8947e823fc..0c87dcdd69 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/IdentifierServicePersistenceTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/IdentifierServicePersistenceTest.java @@ -493,11 +493,10 @@ public class IdentifierServicePersistenceTest extends AbstractUnitTest { @Test public void publish_succeeds() throws MalformedException, DataServiceConnectionException, SearchServiceException, - DatabaseNotFoundException, SearchServiceConnectionException, IdentifierNotFoundException, - ExternalServiceException { + DatabaseNotFoundException, SearchServiceConnectionException, ExternalServiceException { /* test */ - final Identifier response = identifierService.publish(IDENTIFIER_7_ID); + final Identifier response = identifierService.publish(IDENTIFIER_7); assertEquals(IDENTIFIER_7_ID, response.getId()); assertEquals(IdentifierStatusType.PUBLISHED, response.getStatus()); } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServiceUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServiceUnitTest.java index 477d2bd17d..d975e808e3 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServiceUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/TableServiceUnitTest.java @@ -78,7 +78,7 @@ public class TableServiceUnitTest extends AbstractUnitTest { .thenReturn(Optional.of(DATABASE_3)); /* test */ - final Table response = tableService.findById(DATABASE_3_ID, TABLE_8_ID); + final Table response = tableService.findById(DATABASE_3, TABLE_8_ID); assertEquals(TABLE_8_ID, response.getId()); assertEquals(TABLE_8_NAME, response.getName()); assertEquals(TABLE_8_INTERNAL_NAME, response.getInternalName()); @@ -93,7 +93,7 @@ public class TableServiceUnitTest extends AbstractUnitTest { /* test */ assertThrows(TableNotFoundException.class, () -> { - tableService.findById(DATABASE_3_ID, TABLE_1_ID); + tableService.findById(DATABASE_3, TABLE_1_ID); }); } @@ -105,7 +105,7 @@ public class TableServiceUnitTest extends AbstractUnitTest { .thenReturn(Optional.of(DATABASE_3)); /* test */ - final Table response = tableService.findByName(DATABASE_3_ID, TABLE_8_INTERNAL_NAME); + final Table response = tableService.findByName(DATABASE_3, TABLE_8_INTERNAL_NAME); assertEquals(TABLE_8_ID, response.getId()); assertEquals(TABLE_8_NAME, response.getName()); assertEquals(TABLE_8_INTERNAL_NAME, response.getInternalName()); @@ -119,8 +119,8 @@ public class TableServiceUnitTest extends AbstractUnitTest { .thenReturn(Optional.empty()); /* test */ - assertThrows(DatabaseNotFoundException.class, () -> { - tableService.findByName(DATABASE_3_ID, TABLE_1_INTERNAL_NAME); + assertThrows(TableNotFoundException.class, () -> { + tableService.findByName(DATABASE_3, TABLE_1_INTERNAL_NAME); }); } @@ -542,16 +542,7 @@ public class TableServiceUnitTest extends AbstractUnitTest { /* test */ assertThrows(TableNotFoundException.class, () -> { - tableService.findByName(DATABASE_1_ID, "i_do_not_exist"); - }); - } - - @Test - public void findById_databaseNotFound_fails() { - - /* test */ - assertThrows(DatabaseNotFoundException.class, () -> { - tableService.findByName(99999L, TABLE_3_INTERNALNAME); + tableService.findByName(DATABASE_1, "i_do_not_exist"); }); } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/validator/EndpointValidatorUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/validator/EndpointValidatorUnitTest.java index 9444cea6e9..29718b0962 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/validator/EndpointValidatorUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/validator/EndpointValidatorUnitTest.java @@ -227,7 +227,7 @@ public class EndpointValidatorUnitTest extends AbstractUnitTest { TableNotFoundException, AccessNotFoundException { /* mock */ - when(tableService.findById(DATABASE_1_ID, TABLE_1_ID)) + when(tableService.findById(DATABASE_1, TABLE_1_ID)) .thenReturn(TABLE_1); when(accessService.find(eq(DATABASE_1), any(User.class))) .thenReturn(DATABASE_1_USER_1_READ_ACCESS); @@ -243,7 +243,7 @@ public class EndpointValidatorUnitTest extends AbstractUnitTest { DatabaseNotFoundException, AccessNotFoundException, TableNotFoundException { /* mock */ - when(tableService.findById(DATABASE_1_ID, TABLE_1_ID)) + when(tableService.findById(DATABASE_1, TABLE_1_ID)) .thenReturn(TABLE_1); when(accessService.find(eq(DATABASE_1), any(User.class))) .thenReturn(DATABASE_1_USER_1_WRITE_OWN_ACCESS); @@ -312,7 +312,7 @@ public class EndpointValidatorUnitTest extends AbstractUnitTest { TableNotFoundException, AccessNotFoundException { /* mock */ - when(tableService.findById(DATABASE_1_ID, TABLE_1_ID)) + when(tableService.findById(DATABASE_1, TABLE_1_ID)) .thenReturn(TABLE_1); when(accessService.find(DATABASE_1, USER_1)) .thenReturn(DATABASE_1_USER_1_READ_ACCESS); diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/DataServiceGateway.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/DataServiceGateway.java index 621ee53dfe..976830cebb 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/DataServiceGateway.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/DataServiceGateway.java @@ -21,57 +21,62 @@ public interface DataServiceGateway { /** * Create r/w access for a given user to a given database. + * * @param databaseId The database id. - * @param userId The user id. - * @param access The access. + * @param userId The user id. + * @param access The access. * @throws DataServiceConnectionException The connection to the data service could not be established. - * @throws DataServiceException The data service responded unexpectedly. - * @throws DatabaseNotFoundException Some of the privileged parameters of the given database were not provided by the metadata service. + * @throws DataServiceException The data service responded unexpectedly. + * @throws DatabaseNotFoundException Some of the privileged parameters of the given database were not provided by the metadata service. */ void createAccess(Long databaseId, UUID userId, AccessTypeDto access) throws DataServiceConnectionException, DataServiceException, DatabaseNotFoundException; /** * Update r/w access for a given user to a given database. + * * @param databaseId The database id. - * @param userId The user id. - * @param access The access. + * @param userId The user id. + * @param access The access. * @throws DataServiceConnectionException The connection to the data service could not be established. - * @throws DataServiceException The data service responded unexpectedly. - * @throws AccessNotFoundException Some of the privileged parameters of the given database were not provided by the metadata service. + * @throws DataServiceException The data service responded unexpectedly. + * @throws AccessNotFoundException Some of the privileged parameters of the given database were not provided by the metadata service. */ void updateAccess(Long databaseId, UUID userId, AccessTypeDto access) throws DataServiceConnectionException, DataServiceException, AccessNotFoundException; /** * Deletes access for a given user to a given database. + * * @param databaseId The database id. - * @param userId The user id. + * @param userId The user id. * @throws DataServiceConnectionException The connection to the data service could not be established. - * @throws DataServiceException The data service responded unexpectedly. - * @throws AccessNotFoundException Some of the privileged parameters of the given database were not provided by the metadata service. + * @throws DataServiceException The data service responded unexpectedly. + * @throws AccessNotFoundException Some of the privileged parameters of the given database were not provided by the metadata service. */ void deleteAccess(Long databaseId, UUID userId) throws DataServiceConnectionException, DataServiceException, AccessNotFoundException; /** * Creates a database in the data service. + * * @param data The data. * @return The created database, if successful. * @throws DataServiceConnectionException The connection to the data service could not be established. - * @throws DataServiceException The data service responded unexpectedly. - * @throws DatabaseNotFoundException Some of the privileged parameters of the given database were not provided by the metadata service. + * @throws DataServiceException The data service responded unexpectedly. + * @throws DatabaseNotFoundException Some of the privileged parameters of the given database were not provided by the metadata service. */ DatabaseDto createDatabase(CreateDatabaseDto data) throws DataServiceConnectionException, DataServiceException, DatabaseNotFoundException; /** * Updates the user password in the given database in the data service. + * * @param databaseId The database id. - * @param data The user password. + * @param data The user password. * @throws DataServiceConnectionException The connection to the data service could not be established. - * @throws DataServiceException The data service responded unexpectedly. - * @throws DatabaseNotFoundException Some of the privileged parameters of the given database were not provided by the metadata service. + * @throws DataServiceException The data service responded unexpectedly. + * @throws DatabaseNotFoundException Some of the privileged parameters of the given database were not provided by the metadata service. */ void updateDatabase(Long databaseId, UpdateUserPasswordDto data) throws DataServiceConnectionException, DataServiceException, DatabaseNotFoundException; @@ -81,102 +86,111 @@ public interface DataServiceGateway { /** * Creates a table in a given database. + * * @param databaseId The database id. - * @param data The table data. + * @param data The table data. * @throws DataServiceConnectionException The connection to the data service could not be established. - * @throws DataServiceException The data service responded unexpectedly. - * @throws DatabaseNotFoundException Some of the privileged parameters of the given database were not provided by the metadata service. - * @throws TableExistsException A table with this internal name exists already in the database. + * @throws DataServiceException The data service responded unexpectedly. + * @throws DatabaseNotFoundException Some of the privileged parameters of the given database were not provided by the metadata service. + * @throws TableExistsException A table with this internal name exists already in the database. */ void createTable(Long databaseId, TableCreateDto data) throws DataServiceConnectionException, DataServiceException, DatabaseNotFoundException, TableExistsException; /** * Deletes a given table in a given database. + * * @param databaseId The database id. - * @param tableId The table id. + * @param tableId The table id. * @throws DataServiceConnectionException The connection to the data service could not be established. - * @throws DataServiceException The data service responded unexpectedly. - * @throws TableNotFoundException The given table was not found in the database. + * @throws DataServiceException The data service responded unexpectedly. + * @throws TableNotFoundException The given table was not found in the database. */ void deleteTable(Long databaseId, Long tableId) throws DataServiceConnectionException, DataServiceException, TableNotFoundException; /** * Creates a view in the given database. + * * @param databaseId The database id. - * @param data The view data. + * @param data The view data. * @return The created view, if successful. * @throws DataServiceConnectionException The connection to the data service could not be established. - * @throws DataServiceException The data service responded unexpectedly. + * @throws DataServiceException The data service responded unexpectedly. */ ViewDto createView(Long databaseId, ViewCreateDto data) throws DataServiceConnectionException, DataServiceException; /** * Deletes a given view in the given database. + * * @param databaseId The database id. - * @param viewId The view id. + * @param viewId The view id. * @throws DataServiceConnectionException The connection to the data service could not be established. - * @throws DataServiceException The data service responded unexpectedly. - * @throws ViewNotFoundException The given view was not found in the database. + * @throws DataServiceException The data service responded unexpectedly. + * @throws ViewNotFoundException The given view was not found in the database. */ void deleteView(Long databaseId, Long viewId) throws DataServiceConnectionException, DataServiceException, ViewNotFoundException; /** * Finds a given query in a given database. + * * @param databaseId The database id. - * @param queryId The query id. + * @param queryId The query id. * @return The query, if successful. * @throws DataServiceConnectionException The connection to the data service could not be established. - * @throws DataServiceException The data service responded unexpectedly. - * @throws QueryNotFoundException The given query was not found in the query store. + * @throws DataServiceException The data service responded unexpectedly. + * @throws QueryNotFoundException The given query was not found in the query store. */ QueryDto findQuery(Long databaseId, Long queryId) throws DataServiceConnectionException, DataServiceException, QueryNotFoundException; /** * Exports a given query. + * * @param databaseId The database id. - * @param queryId The query id. + * @param queryId The query id. * @return The exported resource, if successful. * @throws DataServiceConnectionException The connection to the data service could not be established. - * @throws DataServiceException The data service responded unexpectedly. - * @throws QueryNotFoundException The given query was not found in the query store. + * @throws DataServiceException The data service responded unexpectedly. + * @throws QueryNotFoundException The given query was not found in the query store. */ ExportResourceDto exportQuery(Long databaseId, Long queryId) throws DataServiceConnectionException, DataServiceException, QueryNotFoundException; /** * Obtain table schemas from a given database. + * * @param databaseId The database id. * @return The list of tables, if successful. * @throws DataServiceConnectionException The connection to the data service could not be established. - * @throws DataServiceException The data service responded unexpectedly. - * @throws TableNotFoundException The table was not found in the database. + * @throws DataServiceException The data service responded unexpectedly. + * @throws TableNotFoundException The table was not found in the database. */ List<TableDto> getTableSchemas(Long databaseId) throws DataServiceConnectionException, DataServiceException, TableNotFoundException; /** * Obtain view schemas from a given database. + * * @param databaseId The database id. * @return The list of tables, if successful. * @throws DataServiceConnectionException The connection to the data service could not be established. - * @throws DataServiceException The data service responded unexpectedly. - * @throws ViewNotFoundException The table was not found in the database. + * @throws DataServiceException The data service responded unexpectedly. + * @throws ViewNotFoundException The table was not found in the database. */ List<ViewDto> getViewSchemas(Long databaseId) throws DataServiceConnectionException, DataServiceException, ViewNotFoundException; /** * Obtain table statistics for a given table in a given database. + * * @param databaseId The database id. - * @param tableId The table id. + * @param tableId The table id. * @return The statistic, if successful. * @throws DataServiceConnectionException The connection to the data service could not be established. - * @throws DataServiceException The data service responded unexpectedly. - * @throws TableNotFoundException The table was not found in the database. + * @throws DataServiceException The data service responded unexpectedly. + * @throws TableNotFoundException The table was not found in the database. */ TableStatisticDto getTableStatistics(Long databaseId, Long tableId) throws DataServiceConnectionException, DataServiceException, TableNotFoundException; diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/DataServiceGatewayImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/DataServiceGatewayImpl.java index 09ad1e55da..2b0cd72dda 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/DataServiceGatewayImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/gateway/impl/DataServiceGatewayImpl.java @@ -14,7 +14,10 @@ import at.tuwien.exception.*; import at.tuwien.gateway.DataServiceGateway; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.http.*; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.HttpServerErrorException; diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/IdentifierService.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/IdentifierService.java index 4d0228f410..ded8204f32 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/IdentifierService.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/IdentifierService.java @@ -87,7 +87,8 @@ public interface IdentifierService { /** * Publishes a draft identifier with DataCite. - * @param identifierId The identifier id. + * + * @param identifier The identifier. * @return The resulting identifier. * @throws SearchServiceException * @throws DatabaseNotFoundException @@ -96,9 +97,9 @@ public interface IdentifierService { * @throws DataServiceConnectionException * @throws IdentifierNotFoundException */ - Identifier publish(Long identifierId) throws SearchServiceException, DatabaseNotFoundException, + Identifier publish(Identifier identifier) throws SearchServiceException, DatabaseNotFoundException, SearchServiceConnectionException, MalformedException, DataServiceConnectionException, - IdentifierNotFoundException, ExternalServiceException; + ExternalServiceException; /** * Creates a new identifier in the metadata database for a query or database. diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/TableService.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/TableService.java index 9a5c395c72..299283e68b 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/TableService.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/TableService.java @@ -7,7 +7,6 @@ import at.tuwien.entities.database.Database; import at.tuwien.entities.database.table.Table; import at.tuwien.entities.database.table.columns.TableColumn; import at.tuwien.exception.*; -import org.springframework.transaction.annotation.Transactional; import java.security.Principal; @@ -16,20 +15,20 @@ public interface TableService { /** * Find a table in the metadata database by database and table id. * - * @param databaseId The database id. - * @param tableId The table id. + * @param database The database. + * @param tableId The table id. * @return The table, if successful. */ - Table findById(Long databaseId, Long tableId) throws TableNotFoundException, DatabaseNotFoundException; + Table findById(Database database, Long tableId) throws TableNotFoundException, DatabaseNotFoundException; /** * Find a table in the metadata database by database id and table name. * - * @param databaseId The database id. + * @param database The database. * @param internalName The table name. * @return The table, if successful. */ - Table findByName(Long databaseId, String internalName) throws TableNotFoundException, DatabaseNotFoundException; + Table findByName(Database database, String internalName) throws TableNotFoundException, DatabaseNotFoundException; /** diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/DataCiteIdentifierServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/DataCiteIdentifierServiceImpl.java index ed58148707..0151ea92f7 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/DataCiteIdentifierServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/DataCiteIdentifierServiceImpl.java @@ -70,9 +70,8 @@ public class DataCiteIdentifierServiceImpl implements IdentifierService { @Override @Transactional - public Identifier publish(Long identifierId) throws MalformedException, DataServiceConnectionException, - IdentifierNotFoundException, ExternalServiceException { - final Identifier identifier = find(identifierId); + public Identifier publish(Identifier identifier) throws MalformedException, DataServiceConnectionException, + ExternalServiceException { identifier.setStatus(IdentifierStatusType.PUBLISHED); identifier.setDoi(remoteSave(identifier, DataCiteDoiEvent.PUBLISH)); return identifierRepository.save(identifier); diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/IdentifierServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/IdentifierServiceImpl.java index 0682225e8a..8706e18bbc 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/IdentifierServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/IdentifierServiceImpl.java @@ -147,9 +147,8 @@ public class IdentifierServiceImpl implements IdentifierService { @Override @Transactional - public Identifier publish(Long identifierId) throws SearchServiceException, DatabaseNotFoundException, - SearchServiceConnectionException, IdentifierNotFoundException { - Identifier identifier = find(identifierId); + public Identifier publish(Identifier identifier) throws SearchServiceException, DatabaseNotFoundException, + SearchServiceConnectionException { /* publish identifier */ identifier.setStatus(IdentifierStatusType.PUBLISHED); identifier = identifierRepository.save(identifier); diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java index 57b546fcea..52a9a63667 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java @@ -40,7 +40,6 @@ public class TableServiceImpl implements TableService { private final EntityService entityService; private final ConceptService conceptService; private final MetadataMapper metadataMapper; - private final DatabaseService databaseService; private final DataServiceGateway dataServiceGateway; private final DatabaseRepository databaseRepository; private final SearchServiceGateway searchServiceGateway; @@ -48,15 +47,14 @@ public class TableServiceImpl implements TableService { @Autowired public TableServiceImpl(UserService userService, UnitService unitService, RabbitConfig rabbitConfig, EntityService entityService, ConceptService conceptService, MetadataMapper metadataMapper, - DatabaseService databaseService, DataServiceGateway dataServiceGateway, - DatabaseRepository databaseRepository, SearchServiceGateway searchServiceGateway) { + DataServiceGateway dataServiceGateway, DatabaseRepository databaseRepository, + SearchServiceGateway searchServiceGateway) { this.userService = userService; this.unitService = unitService; this.rabbitConfig = rabbitConfig; this.entityService = entityService; this.conceptService = conceptService; this.metadataMapper = metadataMapper; - this.databaseService = databaseService; this.dataServiceGateway = dataServiceGateway; this.databaseRepository = databaseRepository; this.searchServiceGateway = searchServiceGateway; @@ -64,10 +62,8 @@ public class TableServiceImpl implements TableService { @Override @Transactional(readOnly = true) - public Table findById(Long databaseId, Long tableId) throws TableNotFoundException, - DatabaseNotFoundException { - final Optional<Table> table = databaseService.findById(databaseId) - .getTables() + public Table findById(Database database, Long tableId) throws TableNotFoundException { + final Optional<Table> table = database.getTables() .stream() .filter(t -> t.getId().equals(tableId)) .findFirst(); @@ -80,10 +76,8 @@ public class TableServiceImpl implements TableService { @Override @Transactional(readOnly = true) - public Table findByName(Long databaseId, String internalName) throws TableNotFoundException, - DatabaseNotFoundException { - final Optional<Table> table = databaseService.findById(databaseId) - .getTables() + public Table findByName(Database database, String internalName) throws TableNotFoundException { + final Optional<Table> table = database.getTables() .stream() .filter(t -> t.getInternalName().equals(internalName)) .findFirst(); diff --git a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/AbstractUnitTest.java b/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/AbstractUnitTest.java index b0f5d3f85c..51b0e89b35 100644 --- a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/AbstractUnitTest.java +++ b/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/AbstractUnitTest.java @@ -42,6 +42,10 @@ public abstract class AbstractUnitTest extends BaseTest { TABLE_1_PRIVILEGED_DTO.setDatabase(DATABASE_1_PRIVILEGED_DTO); VIEW_1_DTO.setDatabase(DATABASE_1_DTO); DATABASE_1.setIdentifiers(new LinkedList<>(List.of(IDENTIFIER_1, IDENTIFIER_2, IDENTIFIER_3, IDENTIFIER_4))); + IDENTIFIER_1.setDatabase(DATABASE_1); + IDENTIFIER_2.setDatabase(DATABASE_1); + IDENTIFIER_3.setDatabase(DATABASE_1); + IDENTIFIER_4.setDatabase(DATABASE_1); DATABASE_1.setTables(new LinkedList<>(List.of(TABLE_1, TABLE_2, TABLE_3, TABLE_4))); DATABASE_1.setViews(new LinkedList<>(List.of(VIEW_1, VIEW_2, VIEW_3))); DATABASE_1_PRIVILEGED_DTO.setIdentifiers(new LinkedList<>(List.of(IDENTIFIER_1_DTO, IDENTIFIER_2_DTO, IDENTIFIER_3_DTO, IDENTIFIER_4_DTO))); diff --git a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java b/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java index f706dd021d..5e5b653852 100644 --- a/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java +++ b/dbrepo-metadata-service/test/src/main/java/at/tuwien/test/BaseTest.java @@ -6,6 +6,7 @@ import at.tuwien.api.amqp.ExchangeDto; import at.tuwien.api.amqp.GrantVirtualHostPermissionsDto; import at.tuwien.api.amqp.QueueDto; import at.tuwien.api.auth.LoginRequestDto; +import at.tuwien.api.auth.RefreshTokenRequestDto; import at.tuwien.api.auth.SignupRequestDto; import at.tuwien.api.container.ContainerBriefDto; import at.tuwien.api.container.ContainerDto; @@ -287,11 +288,15 @@ public abstract class BaseTest { .scope("openid") .build(); + public final static RefreshTokenRequestDto REFRESH_TOKEN_REQUEST_DTO = RefreshTokenRequestDto.builder() + .refreshToken("ey.yee.skrr") + .build(); + public final static Long CONCEPT_1_ID = 1L; public final static String CONCEPT_1_NAME = "precipitation"; public final static String CONCEPT_1_URI = "http://www.wikidata.org/entity/Q25257"; public final static String CONCEPT_1_DESCRIPTION = null; - public final static Instant CONCEPT_1_CREATED = Instant.ofEpochSecond(1701976048L) /* 2023-12-07 19:07:27 */; + public final static Instant CONCEPT_1_CREATED = Instant.ofEpochSecond(1701976048L) /* 2023-12-07 19:07:27 (UTC) */; public final static ConceptSaveDto CONCEPT_1_SAVE_DTO = ConceptSaveDto.builder() .uri(CONCEPT_1_URI) @@ -5946,6 +5951,7 @@ public abstract class BaseTest { .firstname(IDENTIFIER_1_CREATOR_1_FIRSTNAME) .lastname(IDENTIFIER_1_CREATOR_1_LASTNAME) .creatorName(IDENTIFIER_1_CREATOR_1_NAME) + .nameType(NameType.PERSONAL) .nameIdentifier(IDENTIFIER_1_CREATOR_1_ORCID) .nameIdentifierScheme(IDENTIFIER_1_CREATOR_1_IDENTIFIER_SCHEME_TYPE) .affiliation(IDENTIFIER_1_CREATOR_1_AFFILIATION) @@ -5959,6 +5965,7 @@ public abstract class BaseTest { .firstname(IDENTIFIER_1_CREATOR_1_FIRSTNAME) .lastname(IDENTIFIER_1_CREATOR_1_LASTNAME) .creatorName(IDENTIFIER_1_CREATOR_1_NAME) + .nameType(NameTypeDto.PERSONAL) .nameIdentifier(IDENTIFIER_1_CREATOR_1_ORCID) .nameIdentifierScheme(IDENTIFIER_1_CREATOR_1_IDENTIFIER_SCHEME_TYPE_DTO) .affiliation(IDENTIFIER_1_CREATOR_1_AFFILIATION) @@ -5972,6 +5979,7 @@ public abstract class BaseTest { .firstname(IDENTIFIER_1_CREATOR_1_FIRSTNAME) .lastname(IDENTIFIER_1_CREATOR_1_LASTNAME) .creatorName(IDENTIFIER_1_CREATOR_1_NAME) + .nameType(NameTypeDto.PERSONAL) .nameIdentifier(IDENTIFIER_1_CREATOR_1_ORCID) .nameIdentifierScheme(IDENTIFIER_1_CREATOR_1_IDENTIFIER_SCHEME_TYPE_DTO) .affiliation(IDENTIFIER_1_CREATOR_1_AFFILIATION) @@ -7142,7 +7150,7 @@ public abstract class BaseTest { public final static String BANNER_MESSAGE_1_MESSAGE = "Next maintenance in 7 days!"; public final static BannerMessageType BANNER_MESSAGE_1_TYPE = BannerMessageType.INFO; public final static BannerMessageTypeDto BANNER_MESSAGE_1_TYPE_DTO = BannerMessageTypeDto.INFO; - public final static Instant BANNER_MESSAGE_1_START = Instant.ofEpochSecond(1684577786L); + public final static Instant BANNER_MESSAGE_1_START = Instant.ofEpochSecond(1684577786L) /* 2022-12-23 22:00:00 (UTC) */; public final static Instant BANNER_MESSAGE_1_END = null; public final static BannerMessage BANNER_MESSAGE_1 = BannerMessage.builder() @@ -7171,8 +7179,8 @@ public abstract class BaseTest { public final static String BANNER_MESSAGE_2_MESSAGE = "No operation on Christmas 2022!"; public final static BannerMessageType BANNER_MESSAGE_2_TYPE = BannerMessageType.ERROR; public final static BannerMessageTypeDto BANNER_MESSAGE_2_TYPE_DTO = BannerMessageTypeDto.ERROR; - public final static Instant BANNER_MESSAGE_2_START = Instant.ofEpochSecond(1671836400L); - public final static Instant BANNER_MESSAGE_2_END = Instant.ofEpochSecond(1672009200L); + public final static Instant BANNER_MESSAGE_2_START = Instant.ofEpochSecond(1671836400L) /* 2022-12-23 22:00:00 (UTC) */; + public final static Instant BANNER_MESSAGE_2_END = Instant.ofEpochSecond(1672009200L) /* 2022-12-25 22:00:00 (UTC) */; public final static BannerMessage BANNER_MESSAGE_2 = BannerMessage.builder() .id(BANNER_MESSAGE_2_ID) -- GitLab