diff --git a/dbrepo-data-service/pom.xml b/dbrepo-data-service/pom.xml index 953dcd097d664353c7b08f7d3a43f44d5df07406..884824994aff8a6e8f05bce24c44307ffe64c2b8 100644 --- a/dbrepo-data-service/pom.xml +++ b/dbrepo-data-service/pom.xml @@ -60,6 +60,8 @@ <!-- see https://github.com/apache/spark/blob/cde8e4a82e20a363861f451ebd5138efb3194ab8/pom.xml --> <hadoop.version>3.4.0</hadoop.version> <jakarta-servlet.version>5.0.0</jakarta-servlet.version> + <sonar.coverage.jacoco.xmlReportPaths>./report/target/site/jacoco-aggregate/jacoco.xml + </sonar.coverage.jacoco.xmlReportPaths> </properties> <dependencies> diff --git a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/Database.java b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/Database.java index f70fbd93a31d7566e878fd11f31945bc73689c49..a692cce3297525771471d60a28ed83c9df4b804d 100644 --- a/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/Database.java +++ b/dbrepo-metadata-service/entities/src/main/java/at/tuwien/entities/database/Database.java @@ -32,14 +32,11 @@ import static jakarta.persistence.GenerationType.IDENTITY; @UniqueConstraint(columnNames = {"cid", "internalName"}) }) @NamedQueries({ - @NamedQuery(name = "Database.findAllDesc", query = "select d from Database d order by d.created desc"), - @NamedQuery(name = "Database.findByInternalName", query = "select d from Database d where d.internalName = ?1"), - @NamedQuery(name = "Database.findAllOnlyIds", query = "select d.id from Database d order by d.created desc"), - @NamedQuery(name = "Database.findReadAccess", query = "select distinct d from Database d join DatabaseAccess a on a.hdbid = d.id and a.huserid = ?1"), - @NamedQuery(name = "Database.findWriteAccess", query = "select distinct d from Database d join DatabaseAccess a on a.hdbid = d.id and a.huserid = ?1 where a.type = 'WRITE_OWN' or a.type = 'WRITE_ALL'"), - @NamedQuery(name = "Database.findConfigureAccess", query = "select distinct d from Database d where d.ownedBy = ?1"), - @NamedQuery(name = "Database.findPublicOrMine", query = "select distinct d from Database d where d.id = ?1 and (d.isPublic = true or d.ownedBy = ?2)"), - @NamedQuery(name = "Database.findPublic", query = "select distinct d from Database d where d.isPublic = true and d.id = ?1"), + @NamedQuery(name = "Database.findAllDesc", query = "select distinct d from Database d order by d.id desc"), + @NamedQuery(name = "Database.findAllPublicDesc", query = "select distinct d from Database d where d.isPublic = true order by d.id desc"), + @NamedQuery(name = "Database.findAllPublicOrReadAccessDesc", query = "select distinct d from Database d where d.isPublic = true or exists(select a.hdbid from DatabaseAccess a where a.huserid = ?1 and a.hdbid = d.id) order by d.id desc"), + @NamedQuery(name = "Database.findAllPublicOrReadAccessByInternalNameDesc", query = "select distinct d from Database d where d.isPublic = true and d.internalName = ?2 or exists(select a.hdbid from DatabaseAccess a where a.huserid = ?1 and a.hdbid = d.id) order by d.id desc"), + @NamedQuery(name = "Database.findAllPublicByInternalNameDesc", query = "select distinct d from Database d where d.isPublic = true and d.internalName = ?1 order by d.id desc"), }) public class Database implements Serializable { diff --git a/dbrepo-metadata-service/pom.xml b/dbrepo-metadata-service/pom.xml index 42794bab0693bbf5c84f1aea2960d1e6485a0848..2803d9b5f39ddd69f34151251083c35e8a46b406 100644 --- a/dbrepo-metadata-service/pom.xml +++ b/dbrepo-metadata-service/pom.xml @@ -60,6 +60,8 @@ <aws-s3.version>2.25.23</aws-s3.version> <jackson.version>2.15.2</jackson.version> <minio.version>8.5.7</minio.version> + <sonar.coverage.jacoco.xmlReportPaths>./report/target/site/jacoco-aggregate/jacoco.xml + </sonar.coverage.jacoco.xmlReportPaths> </properties> <dependencies> diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/MetadataMapper.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/MetadataMapper.java index f63c387c9865079aca8eb8a3dedf74dcccdc3bba..61c052933a17aa3506757421a49dcd934afc5b21 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/MetadataMapper.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/mapper/MetadataMapper.java @@ -858,18 +858,7 @@ public interface MetadataMapper { LanguageType languageTypeDtoToLanguageType(LanguageTypeDto data); - default Boolean onlyIsPublicOrOwner(Boolean isPublic, User caller, User owner, User databaseOwner) { - if (isPublic) { - return true; - } - /* private schema */ - if (caller == null) { - return false; - } - return owner.equals(caller) || databaseOwner.equals(caller); - } - - default DatabaseDto customDatabaseToDatabaseDto(Database data, User caller) { + default DatabaseDto customDatabaseToDatabaseDto(Database data) { if (data == null) { return null; } @@ -899,14 +888,12 @@ public interface MetadataMapper { if (data.getTables() != null) { database.setTables(new LinkedList<>(data.getTables() .stream() - .filter(t -> onlyIsPublicOrOwner(t.getIsSchemaPublic() || t.getIsPublic(), caller, t.getOwner(), t.getDatabase().getOwner())) .map(this::tableToTableBriefDto) .toList())); } if (data.getViews() != null) { database.setViews(new LinkedList<>(data.getViews() .stream() - .filter(v -> onlyIsPublicOrOwner(v.getIsSchemaPublic() || v.getIsPublic(), caller, v.getOwner(), v.getDatabase().getOwner())) .map(this::viewToViewBriefDto) .toList())); } diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/DatabaseRepository.java b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/DatabaseRepository.java index 3b962bccbb89bad6f6ad5d765860f48df10a0fb0..3c1a79f16e59941c7b4602a0879b725e36329043 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/DatabaseRepository.java +++ b/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/repository/DatabaseRepository.java @@ -13,18 +13,12 @@ public interface DatabaseRepository extends JpaRepository<Database, Long> { List<Database> findAllDesc(); - List<Database> findReadAccess(UUID id); + List<Database> findAllPublicDesc(); - List<Database> findWriteAccess(UUID id); + List<Database> findAllPublicOrReadAccessDesc(UUID id); - List<Database> findConfigureAccess(UUID id); + List<Database> findAllPublicOrReadAccessByInternalNameDesc(UUID id, String internalName); - List<Long> findAllOnlyIds(); - - Optional<Database> findPublicOrMine(Long databaseId, UUID id); - - Optional<Database> findPublic(Long databaseId); - - Optional<Database> findByInternalName(String internalName); + List<Database> findAllPublicByInternalNameDesc(String internalName); } diff --git a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/utils/UserUtil.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/AbstractEndpoint.java similarity index 82% rename from dbrepo-metadata-service/repositories/src/main/java/at/tuwien/utils/UserUtil.java rename to dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/AbstractEndpoint.java index 4e517625ed8bc7d700c1815a8437675d17534d85..b41cc089a7f13965305aa94fd671fdc24d95f44d 100644 --- a/dbrepo-metadata-service/repositories/src/main/java/at/tuwien/utils/UserUtil.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/AbstractEndpoint.java @@ -1,4 +1,4 @@ -package at.tuwien.utils; +package at.tuwien.endpoints; import at.tuwien.api.user.UserDetailsDto; import org.springframework.security.core.Authentication; @@ -6,9 +6,9 @@ import org.springframework.security.core.Authentication; import java.security.Principal; import java.util.UUID; -public class UserUtil { +public abstract class AbstractEndpoint { - public static boolean hasRole(Principal principal, String role) { + public boolean hasRole(Principal principal, String role) { if (principal == null || role == null) { return false; } @@ -18,7 +18,7 @@ public class UserUtil { .anyMatch(a -> a.getAuthority().equals(role)); } - public static boolean isSystem(Principal principal) { + public boolean isSystem(Principal principal) { if (principal == null) { return false; } @@ -28,7 +28,7 @@ public class UserUtil { .anyMatch(a -> a.getAuthority().equals("system")); } - public static UUID getId(Principal principal) { + public UUID getId(Principal principal) { if (principal == null) { return null; } 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 99e4d2e6b11d58fa31bd58effbd849a9696c16d1..2a0bd17cbc6993c5e44e2d010c3b2f8d511c3632 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 @@ -11,7 +11,6 @@ import at.tuwien.mapper.MetadataMapper; import at.tuwien.service.AccessService; import at.tuwien.service.DatabaseService; import at.tuwien.service.UserService; -import at.tuwien.utils.UserUtil; import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.Content; @@ -35,7 +34,7 @@ import java.util.UUID; @RestController @CrossOrigin(origins = "*") @RequestMapping(path = "/api/database/{databaseId}/access") -public class AccessEndpoint { +public class AccessEndpoint extends AbstractEndpoint { private final UserService userService; private final AccessService accessService; @@ -99,8 +98,7 @@ 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 caller = userService.findByUsername(principal.getName()); - if (!database.getOwner().getId().equals(caller.getId())) { + if (!database.getOwner().getId().equals(getId(principal))) { log.error("Failed to create access: not owner"); throw new NotAllowedException("Failed to create access: not owner"); } @@ -162,8 +160,7 @@ public class AccessEndpoint { 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 caller = userService.findByUsername(principal.getName()); - if (!database.getOwner().getId().equals(caller.getId())) { + if (!database.getOwner().getId().equals(getId(principal))) { log.error("Failed to update access: not owner"); throw new NotAllowedException("Failed to update access: not owner"); } @@ -204,9 +201,8 @@ public class AccessEndpoint { UserNotFoundException, AccessNotFoundException, NotAllowedException { log.debug("endpoint get database access, databaseId={}, userId={}, principal.name={}", databaseId, userId, principal.getName()); - final User caller = userService.findByUsername(principal.getName()); - if (!userId.equals(caller.getId())) { - if (!UserUtil.hasRole(principal, "check-foreign-database-access")) { + if (!userId.equals(getId(principal))) { + if (!hasRole(principal, "check-foreign-database-access")) { log.error("Failed to find access: foreign user"); throw new NotAllowedException("Failed to find access: foreign user"); } @@ -261,8 +257,7 @@ public class AccessEndpoint { SearchServiceException, SearchServiceConnectionException { log.debug("endpoint revoke database access, databaseId={}, userId={}", databaseId, userId); final Database database = databaseService.findById(databaseId); - final User caller = userService.findByUsername(principal.getName()); - if (!database.getOwner().getId().equals(caller.getId())) { + if (!database.getOwner().getId().equals(getId(principal))) { log.error("Failed to revoke access: not owner"); throw new NotAllowedException("Failed to revoke access: not owner"); } diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ConceptEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ConceptEndpoint.java index 44a592658ea3f8a512a07cbfe261b39192e3b1e4..acf6a31ca2a583a91ba9bf9e1e4e3c544342eb65 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ConceptEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ConceptEndpoint.java @@ -14,7 +14,10 @@ import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; import java.util.List; @@ -22,7 +25,7 @@ import java.util.List; @CrossOrigin(origins = "*") @RestController @RequestMapping(path = "/api/concept") -public class ConceptEndpoint { +public class ConceptEndpoint extends AbstractEndpoint { private final ConceptService conceptService; private final MetadataMapper metadataMapper; @@ -47,13 +50,11 @@ public class ConceptEndpoint { }) public ResponseEntity<List<ConceptDto>> findAll() { log.debug("endpoint list concepts"); - final List<ConceptDto> dtos = conceptService.findAll() - .stream() - .map(metadataMapper::tableColumnConceptToConceptDto) - .toList(); - log.trace("Find all concepts resulted in dtos {}", dtos); return ResponseEntity.ok() - .body(dtos); + .body(conceptService.findAll() + .stream() + .map(metadataMapper::tableColumnConceptToConceptDto) + .toList()); } } diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ContainerEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ContainerEndpoint.java index 7995b79bf62117f2f360375af08eb93e1d80eee5..3c506cfd0a910d10bba6401eebe5467d1c97e738 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ContainerEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/ContainerEndpoint.java @@ -10,7 +10,6 @@ import at.tuwien.exception.ContainerNotFoundException; import at.tuwien.exception.ImageNotFoundException; import at.tuwien.mapper.MetadataMapper; import at.tuwien.service.ContainerService; -import at.tuwien.utils.UserUtil; import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.ArraySchema; @@ -40,7 +39,7 @@ import java.util.stream.Collectors; @CrossOrigin(origins = "*") @ControllerAdvice @RequestMapping(path = "/api/container") -public class ContainerEndpoint { +public class ContainerEndpoint extends AbstractEndpoint { private final MetadataMapper metadataMapper; private final ContainerService containerService; @@ -65,13 +64,11 @@ public class ContainerEndpoint { }) public ResponseEntity<List<ContainerBriefDto>> findAll(@RequestParam(required = false) Integer limit) { log.debug("endpoint find all containers, limit={}", limit); - final List<ContainerBriefDto> dtos = containerService.getAll(limit) - .stream() - .map(metadataMapper::containerToContainerBriefDto) - .collect(Collectors.toList()); - log.debug("find all containers resulted in {} container(s)", dtos.size()); return ResponseEntity.ok() - .body(dtos); + .body(containerService.getAll(limit) + .stream() + .map(metadataMapper::containerToContainerBriefDto) + .collect(Collectors.toList())); } @PostMapping @@ -111,11 +108,8 @@ public class ContainerEndpoint { public ResponseEntity<ContainerDto> create(@Valid @RequestBody ContainerCreateDto data) throws ImageNotFoundException, ContainerAlreadyExistsException { log.debug("endpoint create container, data={}", data); - final Container container = containerService.create(data); - final ContainerDto dto = metadataMapper.containerToContainerDto(container); - log.trace("create container resulted in container {}", dto); return ResponseEntity.status(HttpStatus.CREATED) - .body(dto); + .body(metadataMapper.containerToContainerDto(containerService.create(data))); } @GetMapping("/{containerId}") @@ -140,10 +134,8 @@ public class ContainerEndpoint { throws ContainerNotFoundException { log.debug("endpoint find container, containerId={}", containerId); final Container container = containerService.find(containerId); - final ContainerDto dto = metadataMapper.containerToContainerDto(container); - log.trace("find container resulted in container {}", dto); final HttpHeaders headers = new HttpHeaders(); - if (UserUtil.isSystem(principal)) { + if (isSystem(principal)) { log.trace("attach privileged credential information"); headers.set("X-Username", container.getPrivilegedUsername()); headers.set("X-Password", container.getPrivilegedPassword()); @@ -151,7 +143,7 @@ public class ContainerEndpoint { } return ResponseEntity.ok() .headers(headers) - .body(dto); + .body(metadataMapper.containerToContainerDto(container)); } @DeleteMapping("/{containerId}") @@ -175,10 +167,10 @@ public class ContainerEndpoint { mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), }) - public ResponseEntity<Void> delete(@NotNull @PathVariable("containerId") Long containerId) throws ContainerNotFoundException { + public ResponseEntity<Void> delete(@NotNull @PathVariable("containerId") Long containerId) + throws ContainerNotFoundException { log.debug("endpoint delete container, containerId={}", containerId); - final Container container = containerService.find(containerId); - containerService.remove(container); + containerService.remove(containerService.find(containerId)); return ResponseEntity.accepted() .build(); } diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java index 29c27074d77253c5cecd6e4ea67afb07954e3bed..f7e39c7302a5f18ae9dd97e01cce5bb501233887 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java @@ -8,8 +8,10 @@ import at.tuwien.entities.database.DatabaseAccess; import at.tuwien.entities.user.User; import at.tuwien.exception.*; import at.tuwien.mapper.MetadataMapper; -import at.tuwien.service.*; -import at.tuwien.utils.UserUtil; +import at.tuwien.service.ContainerService; +import at.tuwien.service.DatabaseService; +import at.tuwien.service.StorageService; +import at.tuwien.service.UserService; import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.headers.Header; @@ -32,29 +34,25 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.*; import java.security.Principal; -import java.util.LinkedList; import java.util.List; -import java.util.stream.Collectors; +import java.util.Optional; @Log4j2 @RestController @CrossOrigin(origins = "*") @RequestMapping(path = "/api/database") -public class DatabaseEndpoint { +public class DatabaseEndpoint extends AbstractEndpoint { private final UserService userService; - private final AccessService accessService; private final MetadataMapper databaseMapper; private final StorageService storageService; private final DatabaseService databaseService; private final ContainerService containerService; @Autowired - public DatabaseEndpoint(UserService userService, AccessService accessService, MetadataMapper databaseMapper, - StorageService storageService, DatabaseService databaseService, - ContainerService containerService) { + public DatabaseEndpoint(UserService userService, MetadataMapper databaseMapper, StorageService storageService, + DatabaseService databaseService, ContainerService containerService) { this.userService = userService; - this.accessService = accessService; this.databaseMapper = databaseMapper; this.storageService = storageService; this.databaseService = databaseService; @@ -75,28 +73,36 @@ public class DatabaseEndpoint { mediaType = "application/json", array = @ArraySchema(schema = @Schema(implementation = DatabaseDto.class)))}), }) - public ResponseEntity<List<DatabaseBriefDto>> list(@RequestParam(name = "internal_name", required = false) String internalName) { + public ResponseEntity<List<DatabaseBriefDto>> list(@RequestParam(name = "internal_name", required = false) String internalName, + Principal principal) throws UserNotFoundException, + DatabaseNotFoundException { log.debug("endpoint list databases, internalName={}", internalName); - List<DatabaseBriefDto> dtos = new LinkedList<>(); - if (internalName != null) { - try { - dtos = List.of(databaseMapper.databaseToDatabaseBriefDto(databaseService.findByInternalName(internalName))); - } catch (DatabaseNotFoundException e) { - /* ignore */ + final List<Database> databases; + if (principal != null) { + if (internalName != null) { + log.debug("filter request to contain only public databases or where user with id {} has at least read access that match internal name {}", getId(principal), internalName); + databases = databaseService.findAllPublicOrReadAccessByInternalName(getId(principal), internalName); + } else { + log.debug("filter request to contain only public databases or where user with id {} has at least read access", getId(principal)); + databases = databaseService.findAllPublicOrReadAccess(getId(principal)); } } else { - dtos = databaseService.findAll() - .stream() - .map(databaseMapper::databaseToDatabaseBriefDto) - .toList(); + if (internalName != null) { + log.debug("filter request to contain only public databases that match internal name {}", internalName); + databases = databaseService.findAllPublicByInternalName(internalName); + } else { + log.debug("filter request to contain only public databases"); + databases = databaseService.findAllPublic(); + } } - log.trace("list databases resulted in {} database(s)", dtos.size()); final HttpHeaders headers = new HttpHeaders(); - headers.set("X-Count", "" + dtos.size()); + headers.set("X-Count", "" + databases.size()); headers.set("Access-Control-Expose-Headers", "X-Count"); return ResponseEntity.status(HttpStatus.OK) .headers(headers) - .body(dtos); + .body(databases.stream() + .map(databaseMapper::databaseToDatabaseBriefDto) + .toList()); } @PostMapping @@ -150,20 +156,19 @@ public class DatabaseEndpoint { }) public ResponseEntity<DatabaseDto> create(@Valid @RequestBody DatabaseCreateDto data, @NotNull Principal principal) throws DataServiceException, - DataServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, ContainerNotFoundException, - SearchServiceException, SearchServiceConnectionException, ContainerQuotaException { + DataServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, + ContainerNotFoundException, SearchServiceException, SearchServiceConnectionException, + ContainerQuotaException { log.debug("endpoint create database, data.name={}", data.getName()); final Container container = containerService.find(data.getCid()); - final User caller = userService.findByUsername(principal.getName()); if (container.getDatabases().size() + 1 > container.getQuota()) { log.error("Failed to create database: quota of {} exceeded", container.getQuota()); throw new ContainerQuotaException("Failed to create database: quota of " + container.getQuota() + " exceeded"); } - final User user = userService.findByUsername(principal.getName()); - final Database database = databaseService.create(container, data, user); - final DatabaseDto dto = databaseMapper.customDatabaseToDatabaseDto(database, caller); + final User caller = userService.findById(getId(principal)); return ResponseEntity.status(HttpStatus.CREATED) - .body(dto); + .body(databaseMapper.customDatabaseToDatabaseDto( + databaseService.create(container, data, caller))); } @PutMapping("/{databaseId}/metadata/table") @@ -212,13 +217,12 @@ public class DatabaseEndpoint { TableNotFoundException { log.debug("endpoint refresh database metadata, databaseId={}", databaseId); final Database database = databaseService.findById(databaseId); - final User caller = userService.findByUsername(principal.getName()); - if (!database.getOwner().getId().equals(caller.getId())) { + if (!database.getOwner().getId().equals(getId(principal))) { log.error("Failed to refresh database tables metadata: not owner"); throw new NotAllowedException("Failed to refresh tables metadata: not owner"); } - final DatabaseDto dto = databaseMapper.customDatabaseToDatabaseDto(databaseService.updateTableMetadata(database), caller); - return ResponseEntity.ok(dto); + return ResponseEntity.ok(databaseMapper.customDatabaseToDatabaseDto( + databaseService.updateTableMetadata(database))); } @PutMapping("/{databaseId}/metadata/view") @@ -261,13 +265,12 @@ public class DatabaseEndpoint { SearchServiceConnectionException, NotAllowedException, QueryNotFoundException, ViewNotFoundException { log.debug("endpoint refresh database metadata, databaseId={}, principal.name={}", databaseId, principal.getName()); final Database database = databaseService.findById(databaseId); - final User caller = userService.findByUsername(principal.getName()); - if (!database.getOwner().getId().equals(caller.getId())) { + if (!database.getOwner().getId().equals(getId(principal))) { log.error("Failed to refresh database views metadata: not owner"); throw new NotAllowedException("Failed to refresh database views metadata: not owner"); } - final DatabaseDto dto = databaseMapper.customDatabaseToDatabaseDto(databaseService.updateViewMetadata(database), caller); - return ResponseEntity.ok(dto); + return ResponseEntity.ok(databaseMapper.customDatabaseToDatabaseDto( + databaseService.updateViewMetadata(database))); } @PutMapping("/{databaseId}/visibility") @@ -315,14 +318,13 @@ public class DatabaseEndpoint { NotAllowedException, SearchServiceException, SearchServiceConnectionException, UserNotFoundException { log.debug("endpoint modify database visibility, databaseId={}, data={}", databaseId, data); final Database database = databaseService.findById(databaseId); - final User caller = userService.findByUsername(principal.getName()); - if (!database.getOwner().equals(caller)) { + if (!database.getOwner().getId().equals(getId(principal))) { log.error("Failed to modify database visibility: not owner"); throw new NotAllowedException("Failed to modify database visibility: not owner"); } - final DatabaseDto dto = databaseMapper.customDatabaseToDatabaseDto(databaseService.modifyVisibility(database, data), caller); return ResponseEntity.accepted() - .body(dto); + .body(databaseMapper.customDatabaseToDatabaseDto( + databaseService.modifyVisibility(database, data))); } @PutMapping("/{databaseId}/owner") @@ -371,15 +373,14 @@ public class DatabaseEndpoint { SearchServiceException, SearchServiceConnectionException { log.debug("endpoint transfer database, databaseId={}, transferDto.id={}", databaseId, data.getId()); final Database database = databaseService.findById(databaseId); - final User caller = userService.findByUsername(principal.getName()); final User newOwner = userService.findById(data.getId()); - if (!database.getOwner().equals(caller)) { + if (!database.getOwner().getId().equals(getId(principal))) { log.error("Failed to transfer database: not owner"); throw new NotAllowedException("Failed to transfer database: not owner"); } - final DatabaseDto dto = databaseMapper.customDatabaseToDatabaseDto(databaseService.modifyOwner(database, newOwner), caller); return ResponseEntity.accepted() - .body(dto); + .body(databaseMapper.customDatabaseToDatabaseDto( + databaseService.modifyOwner(database, newOwner))); } @PutMapping("/{databaseId}/image") @@ -395,13 +396,13 @@ public class DatabaseEndpoint { content = {@Content( mediaType = "application/json", schema = @Schema(implementation = DatabaseDto.class))}), - @ApiResponse(responseCode = "404", - description = "Database or user could not be found", + @ApiResponse(responseCode = "403", + description = "Modify of image is not permitted", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), - @ApiResponse(responseCode = "403", - description = "Modify of image is not permitted", + @ApiResponse(responseCode = "404", + description = "Database could not be found", content = {@Content( mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), @@ -424,23 +425,21 @@ public class DatabaseEndpoint { public ResponseEntity<DatabaseDto> modifyImage(@NotNull @PathVariable("databaseId") Long databaseId, @Valid @RequestBody DatabaseModifyImageDto data, @NotNull Principal principal) throws NotAllowedException, - DatabaseNotFoundException, UserNotFoundException, SearchServiceException, SearchServiceConnectionException, + DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException, StorageUnavailableException, StorageNotFoundException { log.debug("endpoint modify database image, databaseId={}, data.key={}", databaseId, data.getKey()); final Database database = databaseService.findById(databaseId); - final User caller = userService.findByUsername(principal.getName()); - if (!database.getOwner().getId().equals(caller.getId())) { + if (!database.getOwner().getId().equals(getId(principal))) { log.error("Failed to update database image: not owner"); throw new NotAllowedException("Failed to update database image: not owner"); } - final DatabaseDto dto; byte[] image = null; if (data.getKey() != null) { image = storageService.getBytes(data.getKey()); } - dto = databaseMapper.customDatabaseToDatabaseDto(databaseService.modifyImage(database, image), caller); return ResponseEntity.accepted() - .body(dto); + .body(databaseMapper.customDatabaseToDatabaseDto( + databaseService.modifyImage(database, image))); } @GetMapping("/{databaseId}/image") @@ -461,10 +460,9 @@ public class DatabaseEndpoint { public ResponseEntity<byte[]> findPreviewImage(@NotNull @PathVariable("databaseId") Long databaseId) throws DatabaseNotFoundException { log.debug("endpoint get database preview image, databaseId={}", databaseId); - final Database database = databaseService.findById(databaseId); return ResponseEntity.ok() .contentType(MediaType.parseMediaType("image/webp")) - .body(database.getImage()); + .body(databaseService.findById(databaseId).getImage()); } @GetMapping("/{databaseId}") @@ -482,6 +480,11 @@ public class DatabaseEndpoint { content = {@Content( mediaType = "application/json", schema = @Schema(implementation = DatabaseDto.class))}), + @ApiResponse(responseCode = "403", + description = "Not allowed to view database", + content = {@Content( + mediaType = "application/json", + schema = @Schema(implementation = ApiErrorDto.class))}), @ApiResponse(responseCode = "404", description = "Database, user or exchange could not be found", content = {@Content( @@ -500,27 +503,50 @@ public class DatabaseEndpoint { }) public ResponseEntity<DatabaseDto> findById(@NotNull @PathVariable("databaseId") Long databaseId, Principal principal) throws DataServiceException, - DataServiceConnectionException, DatabaseNotFoundException, ExchangeNotFoundException, UserNotFoundException { + DataServiceConnectionException, DatabaseNotFoundException, ExchangeNotFoundException, UserNotFoundException, + NotAllowedException { log.debug("endpoint find database, databaseId={}", databaseId); final Database database = databaseService.findById(databaseId); - final User caller; if (principal != null) { - caller = userService.findByUsername(principal.getName()); + final Optional<DatabaseAccess> optional = database.getAccesses() + .stream() + .filter(a -> a.getUser().getId().equals(getId(principal))) + .findFirst(); + if (!database.getIsPublic() && !database.getIsSchemaPublic() && optional.isEmpty() && !isSystem(principal)) { + log.error("Failed to find database: not public and no access found"); + throw new DatabaseNotFoundException("Failed to find database: not public and no access found"); + } + /* reduce metadata */ + database.setTables(database.getTables() + .stream() + .filter(t -> t.getIsPublic() || t.getIsSchemaPublic() || optional.isPresent()) + .toList()); + database.setViews(database.getViews() + .stream() + .filter(v -> v.getIsPublic() || v.getIsSchemaPublic() || optional.isPresent()) + .toList()); + if (!database.getOwner().getId().equals(getId(principal))) { + database.setAccesses(List.of()); + } } else { - caller = null; - } - final DatabaseDto dto = databaseMapper.customDatabaseToDatabaseDto(database, caller); - if (caller != null && database.getOwner().getId().equals(caller.getId())) { - log.debug("current logged-in user is also the owner: additionally load access list"); - /* only owner sees the access rights */ - final List<DatabaseAccess> accesses = accessService.list(database); - dto.setAccesses(accesses.stream() - .map(databaseMapper::databaseAccessToDatabaseAccessDto) - .collect(Collectors.toList())); - log.debug("found {} database accesses", accesses.size()); + if (!database.getIsPublic() && !database.getIsSchemaPublic()) { + log.error("Failed to find database: not public and not authenticated"); + throw new NotAllowedException("Failed to find database: not public and not authenticated"); + } + /* reduce metadata */ + database.setTables(database.getTables() + .stream() + .filter(t -> t.getIsPublic() || t.getIsSchemaPublic()) + .toList()); + database.setViews(database.getViews() + .stream() + .filter(v -> v.getIsPublic() || v.getIsSchemaPublic()) + .toList()); + database.setAccesses(List.of()); } + final DatabaseDto dto = databaseMapper.customDatabaseToDatabaseDto(database); final HttpHeaders headers = new HttpHeaders(); - if (UserUtil.isSystem(principal)) { + if (isSystem(principal)) { headers.set("X-Username", database.getContainer().getPrivilegedUsername()); headers.set("X-Password", database.getContainer().getPrivilegedPassword()); headers.set("X-Host", database.getContainer().getHost()); 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 31fcd6730551277b4eab2a8bdced3e42afbfbcb5..2830f9714a62cb7fea0b0cf616b4bd54eff8d340 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 @@ -12,10 +12,8 @@ import at.tuwien.entities.identifier.IdentifierStatusType; import at.tuwien.entities.identifier.IdentifierType; import at.tuwien.entities.user.User; import at.tuwien.exception.*; -import at.tuwien.gateway.DataServiceGateway; import at.tuwien.mapper.MetadataMapper; import at.tuwien.service.*; -import at.tuwien.utils.UserUtil; import at.tuwien.validation.EndpointValidator; import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; @@ -29,7 +27,6 @@ import jakarta.validation.Valid; import jakarta.validation.constraints.NotNull; import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.core.io.InputStreamResource; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; @@ -48,11 +45,9 @@ import java.util.regex.Pattern; @CrossOrigin(origins = "*") @RestController @RequestMapping(path = "/api/identifier") -public class IdentifierEndpoint { +public class IdentifierEndpoint extends AbstractEndpoint { private final UserService userService; - private final ViewService viewService; - private final TableService tableService; private final AccessService accessService; private final EndpointConfig endpointConfig; private final MetadataMapper metadataMapper; @@ -60,17 +55,15 @@ public class IdentifierEndpoint { private final MetadataService metadataService; private final EndpointValidator endpointValidator; private final IdentifierService identifierService; - private final DataServiceGateway dataServiceGateway; + + private static final String CREATE_FOREIGN_IDENTIFIER_ROLE = "create-foreign-identifier"; @Autowired - public IdentifierEndpoint(UserService userService, ViewService viewService, TableService tableService, - AccessService accessService, EndpointConfig endpointConfig, MetadataMapper metadataMapper, - DatabaseService databaseService, MetadataService metadataService, - EndpointValidator endpointValidator, IdentifierService identifierService, - DataServiceGateway dataServiceGateway) { + public IdentifierEndpoint(UserService userService, AccessService accessService, EndpointConfig endpointConfig, + MetadataMapper metadataMapper, DatabaseService databaseService, + MetadataService metadataService, EndpointValidator endpointValidator, + IdentifierService identifierService) { this.userService = userService; - this.viewService = viewService; - this.tableService = tableService; this.accessService = accessService; this.endpointConfig = endpointConfig; this.metadataMapper = metadataMapper; @@ -78,7 +71,6 @@ public class IdentifierEndpoint { this.metadataService = metadataService; this.endpointValidator = endpointValidator; this.identifierService = identifierService; - this.dataServiceGateway = dataServiceGateway; } @GetMapping(produces = {MediaType.APPLICATION_JSON_VALUE, "application/ld+json"}) @@ -119,25 +111,24 @@ public class IdentifierEndpoint { return ResponseEntity.ok(List.of()); } log.trace("found persistent identifiers {}", identifiers); - switch (accept) { - case "application/json": + return switch (accept) { + case "application/json" -> { log.trace("accept header matches json"); - final List<IdentifierBriefDto> resource1 = identifiers.stream() + yield ResponseEntity.ok(identifiers.stream() .map(metadataMapper::identifierToIdentifierBriefDto) - .toList(); - log.debug("find identifier resulted in identifiers {}", resource1); - return ResponseEntity.ok(resource1); - case "application/ld+json": + .toList()); + } + case "application/ld+json" -> { log.trace("accept header matches json-ld"); - final List<LdDatasetDto> resource2 = identifiers.stream() + yield ResponseEntity.ok(identifiers.stream() .map(i -> metadataMapper.identifierToLdDatasetDto(i, endpointConfig.getWebsiteUrl())) - .toList(); - log.debug("find identifier resulted in identifiers {}", resource2); - return ResponseEntity.ok(resource2); - default: + .toList()); + } + default -> { log.error("accept header {} is not supported", accept); throw new FormatNotAvailableException("Must provide either application/json or application/ld+json headers"); - } + } + }; } @GetMapping(value = "/{identifierId}", produces = {MediaType.APPLICATION_JSON_VALUE, "application/ld+json", @@ -209,30 +200,20 @@ public class IdentifierEndpoint { 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); + return ResponseEntity.ok(metadataMapper.identifierToIdentifierDto(identifier)); 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); + return ResponseEntity.ok(metadataMapper.identifierToLdDatasetDto(identifier, endpointConfig.getWebsiteUrl())); 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); + return ResponseEntity.ok(identifierService.exportResource(identifier)); 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); + return ResponseEntity.ok(identifierService.exportMetadata(identifier)); } final Pattern regex = Pattern.compile("text\\/bibliography(; ?style=(apa|ieee|bibtex))?"); final Matcher matcher = regex.matcher(accept); @@ -348,9 +329,9 @@ public class IdentifierEndpoint { throws SearchServiceException, DatabaseNotFoundException, SearchServiceConnectionException, MalformedException, DataServiceConnectionException, IdentifierNotFoundException, ExternalServiceException { log.debug("endpoint publish identifier, identifierId={}", identifierId); - final Identifier identifier = identifierService.find(identifierId); return ResponseEntity.status(HttpStatus.CREATED) - .body(metadataMapper.identifierToIdentifierDto(identifierService.publish(identifier))); + .body(metadataMapper.identifierToIdentifierDto( + identifierService.publish(identifierService.find(identifierId)))); } @PutMapping("/{identifierId}") @@ -402,10 +383,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 caller = userService.findByUsername(principal.getName()); + final User caller = userService.findById(getId(principal)); final Identifier identifier = identifierService.find(identifierId); /* check owner */ - if (!identifier.getOwner().getId().equals(caller.getId()) && !UserUtil.hasRole(principal, "create-foreign-identifier")) { + if (!identifier.getOwner().getId().equals(getId(principal)) && !hasRole(principal, CREATE_FOREIGN_IDENTIFIER_ROLE)) { log.error("Failed to save identifier: foreign user"); throw new NotAllowedException("Failed to save identifier: foreign user"); } @@ -419,7 +400,7 @@ public class IdentifierEndpoint { final DatabaseAccess access = accessService.find(database, caller); log.trace("found access: {}", access); } catch (AccessNotFoundException e) { - if (!UserUtil.hasRole(principal, "create-foreign-identifier")) { + if (!hasRole(principal, CREATE_FOREIGN_IDENTIFIER_ROLE)) { log.error("Failed to save identifier: insufficient role"); throw new NotAllowedException("Failed to save identifier: insufficient role"); } @@ -501,12 +482,12 @@ public class IdentifierEndpoint { IdentifierNotFoundException, ViewNotFoundException, ExternalServiceException { log.debug("endpoint create identifier, data.databaseId={}", data.getDatabaseId()); final Database database = databaseService.findById(data.getDatabaseId()); - final User caller = userService.findByUsername(principal.getName()); + final User caller = userService.findById(getId(principal)); /* check access */ try { accessService.find(database, caller); } catch (AccessNotFoundException e) { - if (!UserUtil.hasRole(principal, "create-foreign-identifier")) { + if (!hasRole(principal, CREATE_FOREIGN_IDENTIFIER_ROLE)) { log.error("Failed to create identifier: insufficient role"); throw new NotAllowedException("Failed to create identifier: insufficient role"); } @@ -532,8 +513,9 @@ public class IdentifierEndpoint { mediaType = "application/json", schema = @Schema(implementation = ApiErrorDto.class))}), }) - public ResponseEntity<ExternalMetadataDto> retrieve(@NotNull @Valid @RequestParam String url) + public ResponseEntity<ExternalMetadataDto> retrieve(@NotNull @Valid @RequestParam("url") String url) throws OrcidNotFoundException, RorNotFoundException, DoiNotFoundException, IdentifierNotSupportedException { + log.debug("endpoint retrieve identifier, url={}", url); return ResponseEntity.ok(metadataService.findByUrl(url)); } 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 2a9dd568703c03932d3a2f20a57bb49b19433fbc..2aaad860a8bbb70e4d7023b00587cc0ad70b7e94 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 @@ -37,7 +37,7 @@ import java.util.List; @CrossOrigin(origins = "*") @ControllerAdvice @RequestMapping(path = "/api/image") -public class ImageEndpoint { +public class ImageEndpoint extends AbstractEndpoint { private final MetadataMapper metadataMapper; private final ImageServiceImpl imageService; @@ -97,11 +97,9 @@ public class ImageEndpoint { @NotNull Principal principal) throws ImageAlreadyExistsException, ImageInvalidException { 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); return ResponseEntity.status(HttpStatus.CREATED) - .body(dto); + .body(metadataMapper.containerImageToImageDto( + imageService.create(data, principal))); } @GetMapping("/{imageId}") @@ -122,12 +120,9 @@ public class ImageEndpoint { schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<ImageDto> findById(@NotNull @PathVariable("imageId") Long imageId) throws ImageNotFoundException { - log.debug("endpoint find image, id={}", imageId); - final ContainerImage image = imageService.find(imageId); - final ImageDto dto = metadataMapper.containerImageToImageDto(image); - log.trace("find image resulted in image {}", dto); + log.debug("endpoint find image, imageId={}", imageId); return ResponseEntity.ok() - .body(dto); + .body(metadataMapper.containerImageToImageDto(imageService.find(imageId))); } @PutMapping("/{imageId}") @@ -152,13 +147,10 @@ public class ImageEndpoint { public ResponseEntity<ImageDto> update(@NotNull @PathVariable("imageId") Long imageId, @RequestBody @Valid ImageChangeDto changeDto) throws ImageNotFoundException { - log.debug("endpoint update image, id={}, changeDto={}", imageId, changeDto); - ContainerImage image = imageService.find(imageId); - image = imageService.update(image, changeDto); - final ImageDto dto = metadataMapper.containerImageToImageDto(image); - log.trace("update image resulted in image {}", dto); + log.debug("endpoint update image, imageId={}, changeDto={}", imageId, changeDto); return ResponseEntity.accepted() - .body(dto); + .body(metadataMapper.containerImageToImageDto( + imageService.update(imageService.find(imageId), changeDto))); } @DeleteMapping("/{imageId}") @@ -179,9 +171,8 @@ public class ImageEndpoint { schema = @Schema(implementation = ApiErrorDto.class))}), }) public ResponseEntity<Void> delete(@NotNull @PathVariable("imageId") Long imageId) throws ImageNotFoundException { - log.debug("endpoint delete image, id={}", imageId); - final ContainerImage image = imageService.find(imageId); - imageService.delete(image); + log.debug("endpoint delete image, imageId={}", imageId); + imageService.delete(imageService.find(imageId)); return ResponseEntity.accepted() .build(); } diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/LicenseEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/LicenseEndpoint.java index 75998b03a5c239661a9f7b3022263a00cd0bff4d..18d5e93ca26a824f1b445e39fb82213b0f7fe649 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/LicenseEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/LicenseEndpoint.java @@ -21,7 +21,6 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.List; -import java.util.stream.Collectors; @Log4j2 @RestController @@ -52,12 +51,11 @@ public class LicenseEndpoint { }) public ResponseEntity<List<LicenseDto>> list() { log.debug("endpoint list licenses"); - final List<LicenseDto> licenses = licenseService.findAll() - .stream() - .map(metadataMapper::licenseToLicenseDto) - .toList(); return ResponseEntity.status(HttpStatus.OK) - .body(licenses); + .body(licenseService.findAll() + .stream() + .map(metadataMapper::licenseToLicenseDto) + .toList()); } } diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/MessageEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/MessageEndpoint.java index 0a1cddf5dfddbb4559cc4b608952da94b58cb901..0aeeac9401c796b82060d363a5e1ed01e6ac0e61 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/MessageEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/MessageEndpoint.java @@ -56,20 +56,15 @@ public class MessageEndpoint { }) public ResponseEntity<List<BannerMessageDto>> list(@RequestParam(required = false) Boolean active) { log.debug("endpoint list messages, active={}", active); - List<BannerMessageDto> dtos; + final List<BannerMessage> messages; if (active != null && active) { - dtos = bannerMessageService.getActive() - .stream() - .map(metadataMapper::bannerMessageToBannerMessageDto) - .toList(); + messages = bannerMessageService.getActive(); } else { - dtos = bannerMessageService.findAll() - .stream() - .map(metadataMapper::bannerMessageToBannerMessageDto) - .toList(); + messages = bannerMessageService.findAll(); } - log.info("List messages resulted in {} message(s)", dtos.size()); - return ResponseEntity.ok(dtos); + return ResponseEntity.ok(messages.stream() + .map(metadataMapper::bannerMessageToBannerMessageDto) + .toList()); } @GetMapping("/message/{messageId}") @@ -91,8 +86,8 @@ public class MessageEndpoint { public ResponseEntity<BannerMessageDto> find(@NotNull @PathVariable("messageId") Long messageId) throws MessageNotFoundException { log.debug("endpoint find one maintenance message, messageId={}", messageId); - final BannerMessageDto dto = metadataMapper.bannerMessageToBannerMessageDto(bannerMessageService.find(messageId)); - return ResponseEntity.ok(dto); + return ResponseEntity.ok(metadataMapper.bannerMessageToBannerMessageDto( + bannerMessageService.find(messageId))); } @PostMapping @@ -110,10 +105,9 @@ public class MessageEndpoint { }) public ResponseEntity<BannerMessageDto> create(@Valid @RequestBody BannerMessageCreateDto data) { log.debug("endpoint create maintenance message, data={}", data); - final BannerMessageDto dto = metadataMapper.bannerMessageToBannerMessageDto(bannerMessageService.create(data)); - log.trace("create maintenance message results in dto {}", dto); return ResponseEntity.status(HttpStatus.CREATED) - .body(dto); + .body(metadataMapper.bannerMessageToBannerMessageDto( + bannerMessageService.create(data))); } @PutMapping("/{messageId}") @@ -139,10 +133,9 @@ public class MessageEndpoint { throws MessageNotFoundException { log.debug("endpoint update maintenance message, messageId={}, data={}", messageId, data); final BannerMessage message = bannerMessageService.find(messageId); - final BannerMessageDto dto = metadataMapper.bannerMessageToBannerMessageDto(bannerMessageService.update(message, data)); - log.trace("update maintenance message results in dto {}", dto); - return ResponseEntity.status(HttpStatus.ACCEPTED) - .body(dto); + return ResponseEntity.accepted() + .body(metadataMapper.bannerMessageToBannerMessageDto( + bannerMessageService.update(message, data))); } @DeleteMapping("/{messageId}") @@ -166,7 +159,7 @@ public class MessageEndpoint { log.debug("endpoint delete maintenance message, messageId={}", messageId); final BannerMessage message = bannerMessageService.find(messageId); bannerMessageService.delete(message); - return ResponseEntity.status(HttpStatus.ACCEPTED) + return ResponseEntity.accepted() .build(); } diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/MetadataEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/MetadataEndpoint.java index fbfd40e6289ef20d20ae2ade97b08b9e47f96d96..8a36471816ee9a4d2a89e3fee2edcde59f7361ae 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/MetadataEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/MetadataEndpoint.java @@ -29,7 +29,7 @@ import java.util.List; @CrossOrigin(origins = "*") @RestController @RequestMapping(path = "/api/oai") -public class MetadataEndpoint { +public class MetadataEndpoint extends AbstractEndpoint { private final MetadataService metadataService; diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/OntologyEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/OntologyEndpoint.java index cd17c7ac0b15d014769683dadc660a426986cd9e..7bc6bc037e75501bfd7de5006150550a7a42366b 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/OntologyEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/OntologyEndpoint.java @@ -3,9 +3,11 @@ package at.tuwien.endpoints; import at.tuwien.api.error.ApiErrorDto; import at.tuwien.api.semantics.*; import at.tuwien.entities.semantics.Ontology; -import at.tuwien.exception.*; +import at.tuwien.exception.FilterBadRequestException; +import at.tuwien.exception.MalformedException; +import at.tuwien.exception.OntologyNotFoundException; +import at.tuwien.exception.UriMalformedException; import at.tuwien.mapper.MetadataMapper; -import at.tuwien.mapper.SparqlMapper; import at.tuwien.service.EntityService; import at.tuwien.service.OntologyService; import io.micrometer.observation.annotation.Observed; @@ -32,7 +34,7 @@ import java.util.List; @CrossOrigin(origins = "*") @RestController @RequestMapping(path = "/api/ontology") -public class OntologyEndpoint { +public class OntologyEndpoint extends AbstractEndpoint { private final EntityService entityService; private final MetadataMapper metadataMapper; @@ -59,11 +61,10 @@ public class OntologyEndpoint { }) public ResponseEntity<List<OntologyBriefDto>> findAll() { log.debug("endpoint find all ontologies"); - final List<OntologyBriefDto> dtos = ontologyService.findAll() + return ResponseEntity.ok(ontologyService.findAll() .stream() .map(metadataMapper::ontologyToOntologyBriefDto) - .toList(); - return ResponseEntity.ok(dtos); + .toList()); } @GetMapping("/{ontologyId}") @@ -85,8 +86,7 @@ public class OntologyEndpoint { public ResponseEntity<OntologyDto> find(@NotNull @PathVariable("ontologyId") Long ontologyId) throws OntologyNotFoundException { log.debug("endpoint find all ontologies, ontologyId={}", ontologyId); - final OntologyDto dto = metadataMapper.ontologyToOntologyDto(ontologyService.find(ontologyId)); - return ResponseEntity.ok(dto); + return ResponseEntity.ok(metadataMapper.ontologyToOntologyDto(ontologyService.find(ontologyId))); } @PostMapping @@ -104,10 +104,9 @@ public class OntologyEndpoint { }) public ResponseEntity<OntologyDto> create(@NotNull @Valid @RequestBody OntologyCreateDto data, @NotNull Principal principal) { - log.debug("endpoint create ontology, data={}", data); - final OntologyDto dto = metadataMapper.ontologyToOntologyDto(ontologyService.create(data, principal)); + log.debug("endpoint create ontology, data={}, principal.name={}", data, principal.getName()); return ResponseEntity.status(HttpStatus.CREATED) - .body(dto); + .body(metadataMapper.ontologyToOntologyDto(ontologyService.create(data, principal))); } @PutMapping("/{ontologyId}") @@ -131,11 +130,10 @@ public class OntologyEndpoint { public ResponseEntity<OntologyDto> update(@NotNull @PathVariable("ontologyId") Long ontologyId, @NotNull @Valid @RequestBody OntologyModifyDto data) throws OntologyNotFoundException { - log.debug("endpoint update ontology, data={}", data); - final Ontology ontology = ontologyService.find(ontologyId); - final OntologyDto dto = metadataMapper.ontologyToOntologyDto(ontologyService.update(ontology, data)); + log.debug("endpoint update ontology, ontologyId={}, data={}", ontologyId, data); return ResponseEntity.accepted() - .body(dto); + .body(metadataMapper.ontologyToOntologyDto( + ontologyService.update(ontologyService.find(ontologyId), data))); } @DeleteMapping("/{ontologyId}") @@ -158,8 +156,7 @@ public class OntologyEndpoint { public ResponseEntity<Void> delete(@NotNull @PathVariable("ontologyId") Long ontologyId) throws OntologyNotFoundException { log.debug("endpoint delete ontology, ontologyId={}", ontologyId); - final Ontology ontology = ontologyService.find(ontologyId); - ontologyService.delete(ontology); + ontologyService.delete(ontologyService.find(ontologyId)); return ResponseEntity.accepted() .build(); } @@ -217,15 +214,12 @@ public class OntologyEndpoint { throw new OntologyNotFoundException("Failed to find SPARQL endpoint for ontology with id " + ontology.getId()); } /* get */ - final List<EntityDto> dtos; if (uri != null) { - dtos = entityService.findByUri(uri); return ResponseEntity.ok() - .body(dtos); + .body(entityService.findByUri(uri)); } - dtos = entityService.findByLabel(ontology, label); return ResponseEntity.ok() - .body(dtos); + .body(entityService.findByLabel(ontology, label)); } } 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 822581bb991786467123b7adde5e35c1e6cde6e2..c4ad192eec938eb0d115d0bb469dd5fd0a46dff7 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 @@ -11,12 +11,9 @@ import at.tuwien.api.semantics.EntityDto; import at.tuwien.api.semantics.TableColumnEntityDto; import at.tuwien.entities.database.Database; import at.tuwien.entities.database.table.Table; -import at.tuwien.entities.database.table.columns.TableColumn; -import at.tuwien.entities.user.User; import at.tuwien.exception.*; import at.tuwien.mapper.MetadataMapper; import at.tuwien.service.*; -import at.tuwien.utils.UserUtil; import at.tuwien.validation.EndpointValidator; import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; @@ -46,7 +43,7 @@ import java.util.stream.Collectors; @CrossOrigin(origins = "*") @RestController @RequestMapping(path = "/api/database/{databaseId}/table") -public class TableEndpoint { +public class TableEndpoint extends AbstractEndpoint { private final UserService userService; private final TableService tableService; @@ -99,12 +96,10 @@ public class TableEndpoint { final Database database = databaseService.findById(databaseId); endpointValidator.validateOnlyPrivateAccess(database, principal); endpointValidator.validateOnlyPrivateHasRole(database, principal, "list-tables"); - final List<TableBriefDto> dto = database.getTables() + return ResponseEntity.ok(database.getTables() .stream() .map(metadataMapper::tableToTableBriefDto) - .collect(Collectors.toList()); - log.trace("list tables resulted in tables {}", dto); - return ResponseEntity.ok(dto); + .collect(Collectors.toList())); } @GetMapping("/{tableId}/suggest") @@ -154,7 +149,7 @@ public class TableEndpoint { principal); final Database database = databaseService.findById(databaseId); final Table table = tableService.findById(database, tableId); - if (!table.getOwner().getUsername().equals(principal.getName())) { + if (!table.getOwner().getId().equals(getId(principal))) { log.error("Failed to analyse table semantics: not owner"); throw new NotAllowedException("Failed to analyse table semantics: not owner"); } @@ -207,7 +202,7 @@ public class TableEndpoint { principal.getName()); final Database database = databaseService.findById(databaseId); final Table table = tableService.findById(database, tableId); - if (!table.getOwner().getUsername().equals(principal.getName())) { + if (!table.getOwner().getId().equals(getId(principal))) { log.error("Failed to update table statistics: not owner"); throw new NotAllowedException("Failed to update table statistics: not owner"); } @@ -266,19 +261,14 @@ public class TableEndpoint { 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(database, tableId); - if (!UserUtil.hasRole(principal, "modify-foreign-table-column-semantics")) { - endpointValidator.validateOnlyAccess(table.getDatabase(), principal, true); - endpointValidator.validateOnlyOwnerOrWriteAll(table, user); + if (!hasRole(principal, "modify-foreign-table-column-semantics")) { + endpointValidator.validateOnlyAccess(database, principal, true); + endpointValidator.validateOnlyOwnerOrWriteAll(table, userService.findById(getId(principal))); } - TableColumn column = tableService.findColumnById(table, columnId); - column = tableService.update(column, updateDto); - log.info("Updated table semantics of table with id {}", tableId); - final ColumnDto columnDto = metadataMapper.tableColumnToColumnDto(column); - log.trace("find table data resulted in column {}", columnDto); return ResponseEntity.accepted() - .body(columnDto); + .body(metadataMapper.tableColumnToColumnDto(tableService.update( + tableService.findColumnById(table, columnId), updateDto))); } @GetMapping("/{tableId}/column/{columnId}/suggest") @@ -317,12 +307,10 @@ public class TableEndpoint { throws MalformedException, TableNotFoundException, DatabaseNotFoundException { 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() - .body(dtos); + .body(entityService.suggestByColumn( + tableService.findColumnById( + tableService.findById(databaseService.findById(databaseId), tableId), columnId))); } @PostMapping @@ -380,11 +368,9 @@ public class TableEndpoint { final Database database = databaseService.findById(databaseId); endpointValidator.validateOnlyAccess(database, principal, true); endpointValidator.validateColumnCreateConstraints(data); - final Table table = tableService.createTable(database, data, principal); - final TableDto dto = metadataMapper.customTableToTableDto(table); - log.info("Created table with id {}", dto.getId()); return ResponseEntity.status(HttpStatus.CREATED) - .body(dto); + .body(metadataMapper.customTableToTableDto( + tableService.createTable(database, data, principal))); } @PutMapping("/{tableId}") @@ -436,14 +422,13 @@ public class TableEndpoint { 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())) { + if (!table.getOwner().getId().equals(getId(principal))) { log.error("Failed to update table: not owner"); throw new NotAllowedException("Failed to update table: not owner"); } - final TableDto dto = metadataMapper.customTableToTableDto(tableService.updateTable(table, data)); - log.info("Updated table with id {}", dto.getId()); - return ResponseEntity.status(HttpStatus.ACCEPTED) - .body(dto); + return ResponseEntity.accepted() + .body(metadataMapper.customTableToTableDto( + tableService.updateTable(table, data))); } @GetMapping("/{tableId}") @@ -494,25 +479,22 @@ public class TableEndpoint { log.debug("endpoint find table, databaseId={}, tableId={}", databaseId, tableId); final Database database = databaseService.findById(databaseId); final Table table = tableService.findById(database, tableId); - boolean hasAccess = UserUtil.isSystem(principal); + boolean hasAccess = isSystem(principal); boolean isOwner = false; try { if (principal != null) { - final User user = userService.findByUsername(principal.getName()); - accessService.find(table.getDatabase(), user); + accessService.find(table.getDatabase(), userService.findById(getId(principal))); hasAccess = true; - isOwner = table.getOwner().getId().equals(user.getId()); + isOwner = table.getOwner().getId().equals(getId(principal)); } } catch (UserNotFoundException | AccessNotFoundException e) { /* ignore */ } - final boolean includeSchema = UserUtil.isSystem(principal) || isOwner || table.getIsSchemaPublic(); + final boolean includeSchema = isSystem(principal) || isOwner || table.getIsSchemaPublic(); log.trace("user has access: {}", hasAccess); log.trace("include schema in mapping: {}", includeSchema); - final TableDto dto = metadataMapper.customTableToTableDto(table, hasAccess, table.getDatabase().getIsPublic(), - includeSchema); final HttpHeaders headers = new HttpHeaders(); - if (UserUtil.isSystem(principal)) { + if (isSystem(principal)) { headers.set("X-Username", table.getDatabase().getContainer().getPrivilegedUsername()); headers.set("X-Password", table.getDatabase().getContainer().getPrivilegedPassword()); headers.set("X-Host", table.getDatabase().getContainer().getHost()); @@ -522,9 +504,10 @@ public class TableEndpoint { headers.set("X-Table", table.getInternalName()); headers.set("Access-Control-Expose-Headers", "X-Username X-Password X-Host X-Port X-Type X-Database X-Table"); } - return ResponseEntity.status(HttpStatus.OK) + return ResponseEntity.ok() .headers(headers) - .body(dto); + .body(metadataMapper.customTableToTableDto(table, hasAccess, table.getDatabase().getIsPublic(), + includeSchema)); } @DeleteMapping("/{tableId}") @@ -573,7 +556,7 @@ public class TableEndpoint { 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")) { + if (!table.getOwner().getId().equals(getId(principal)) && !hasRole(principal, "delete-foreign-table")) { log.error("Failed to delete table: not owned by current user"); throw new NotAllowedException("Failed to delete table: not owned by current user"); } diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/UnitEndpoint.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/UnitEndpoint.java index c992f151b5a32bafaf62a85a1a930ffbe7d0bdbe..45aef3645ba93cb1298c6da2e658656f645778ed 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/UnitEndpoint.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/endpoints/UnitEndpoint.java @@ -14,7 +14,10 @@ import lombok.extern.log4j.Log4j2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.CrossOrigin; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; import java.util.List; @@ -22,7 +25,7 @@ import java.util.List; @CrossOrigin(origins = "*") @RestController @RequestMapping(path = "/api/unit") -public class UnitEndpoint { +public class UnitEndpoint extends AbstractEndpoint { private final UnitService unitService; private final MetadataMapper metadataMapper; @@ -47,12 +50,11 @@ public class UnitEndpoint { }) public ResponseEntity<List<UnitDto>> findAll() { log.debug("endpoint list units"); - final List<UnitDto> dtos = unitService.findAll() - .stream() - .map(metadataMapper::tableColumnUnitToUnitDto) - .toList(); return ResponseEntity.ok() - .body(dtos); + .body(unitService.findAll() + .stream() + .map(metadataMapper::tableColumnUnitToUnitDto) + .toList()); } } 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 151169c2446f2bc699cb108f56623fbb6a6a3fba..1b1947253fa6abdbd473b216564ae2a57137eaac 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 @@ -16,7 +16,6 @@ import at.tuwien.mapper.MetadataMapper; import at.tuwien.service.AuthenticationService; import at.tuwien.service.DatabaseService; import at.tuwien.service.UserService; -import at.tuwien.utils.UserUtil; import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.ArraySchema; @@ -44,7 +43,7 @@ import java.util.UUID; @CrossOrigin(origins = "*") @RestController @RequestMapping(path = "/api/user") -public class UserEndpoint { +public class UserEndpoint extends AbstractEndpoint { private final UserService userService; private final MetadataMapper userMapper; @@ -82,7 +81,8 @@ public class UserEndpoint { } try { log.trace("filter by username: {}", username); - return ResponseEntity.ok(List.of(userMapper.userToUserBriefDto(userService.findByUsername(username)))); + return ResponseEntity.ok(List.of(userMapper.userToUserBriefDto( + userService.findByUsername(username)))); } catch (UserNotFoundException e) { log.trace("filter by username {} failed: return empty list", username); return ResponseEntity.ok(List.of()); @@ -141,10 +141,9 @@ public class UserEndpoint { log.debug("endpoint create user, data.username={}", data.getUsername()); userService.validateUsernameNotExists(data.getUsername()); userService.validateEmailNotExists(data.getEmail()); - final User user = userService.create(data, authenticationService.create(data).getAttributes().getLdapId()[0]); - log.info("Created user with id: {}", user.getId()); return ResponseEntity.status(HttpStatus.CREATED) - .body(userMapper.userToUserDto(user)); + .body(userMapper.userToUserDto( + userService.create(data, authenticationService.create(data).getAttributes().getLdapId()[0]))); } @PostMapping("/token") @@ -193,7 +192,6 @@ public class UserEndpoint { AccountNotSetupException { log.debug("endpoint get token, data.username={}", data.getUsername()); /* check */ - final TokenDto token = authenticationService.obtainToken(data); try { userService.findByUsername(data.getUsername()); } catch (UserNotFoundException e) { @@ -213,7 +211,7 @@ public class UserEndpoint { log.info("Patched missing user information for user with username: {}", data.getUsername()); } return ResponseEntity.accepted() - .body(token); + .body(authenticationService.obtainToken(data)); } @PutMapping("/token") @@ -246,9 +244,8 @@ public class UserEndpoint { throws AuthServiceConnectionException, CredentialsInvalidException { log.debug("endpoint refresh token"); /* check */ - final TokenDto token = authenticationService.refreshToken(data.getRefreshToken()); return ResponseEntity.accepted() - .body(token); + .body(authenticationService.refreshToken(data.getRefreshToken())); } @GetMapping("/{userId}") @@ -281,21 +278,18 @@ public class UserEndpoint { log.debug("endpoint find a user, userId={}, principal.name={}", userId, principal.getName()); /* check */ final User user = userService.findById(userId); - if (!user.getUsername().equals(principal.getName())) { - if (!UserUtil.hasRole(principal, "find-foreign-user")) { - log.error("Failed to find user: foreign user"); - throw new NotAllowedException("Failed to find user: foreign user"); - } + if (!user.getId().equals(getId(principal)) && !hasRole(principal, "find-foreign-user")) { + log.error("Failed to find user: foreign user"); + throw new NotAllowedException("Failed to find user: foreign user"); } - final UserDto dto = userMapper.userToUserDto(user); final HttpHeaders headers = new HttpHeaders(); - if (UserUtil.isSystem(principal)) { + if (isSystem(principal)) { headers.set("X-Username", user.getUsername()); headers.set("X-Password", user.getMariadbPassword()); } return ResponseEntity.status(HttpStatus.OK) .headers(headers) - .body(dto); + .body(userMapper.userToUserDto(user)); } @PutMapping("/{userId}") @@ -333,13 +327,13 @@ public class UserEndpoint { UserNotFoundException, DatabaseNotFoundException { log.debug("endpoint modify a user, userId={}, data={}", userId, data); final User user = userService.findById(userId); - if (!user.getUsername().equals(principal.getName())) { + if (!user.getId().equals(getId(principal))) { log.error("Failed to modify user: not current user {}", user.getId()); throw new NotAllowedException("Failed to modify user: not current user " + user.getId()); } - final UserDto dto = userMapper.userToUserDto(userService.modify(user, data)); return ResponseEntity.accepted() - .body(dto); + .body(userMapper.userToUserDto( + userService.modify(user, data))); } @PutMapping("/{userId}/password") @@ -383,14 +377,14 @@ public class UserEndpoint { @NotNull Principal principal) throws NotAllowedException, AuthServiceException, AuthServiceConnectionException, UserNotFoundException, DatabaseNotFoundException, DataServiceException, DataServiceConnectionException, CredentialsInvalidException { - log.debug("endpoint modify a user password, userId={}", userId); + log.debug("endpoint modify a user password, userId={}, principal.name={}", userId, principal.getName()); final User user = userService.findById(userId); if (!user.getUsername().equals(principal.getName())) { log.error("Failed to modify user password: not current user"); throw new NotAllowedException("Failed to modify user password: not current user"); } authenticationService.updatePassword(user, data); - for (Database database : databaseService.findAllAccess(userId)) { + for (Database database : databaseService.findAllPublicOrReadAccess(userId)) { databaseService.updatePassword(database, user); } userService.updatePassword(user, data); 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 012206289e19f654cb8154668aee2dac598b61b0..99a2856d448ffc0d00b6b83565b8ddf1805499e4 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 @@ -13,7 +13,6 @@ import at.tuwien.mapper.MetadataMapper; import at.tuwien.service.DatabaseService; import at.tuwien.service.UserService; import at.tuwien.service.ViewService; -import at.tuwien.utils.UserUtil; import io.micrometer.observation.annotation.Observed; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.headers.Header; @@ -42,7 +41,7 @@ import java.util.stream.Collectors; @CrossOrigin(origins = "*") @RestController @RequestMapping(path = "/api/database/{databaseId}/view") -public class ViewEndpoint { +public class ViewEndpoint extends AbstractEndpoint { private final UserService userService; private final ViewService viewService; @@ -81,13 +80,16 @@ public class ViewEndpoint { DatabaseNotFoundException { log.debug("endpoint find all views, databaseId={}", databaseId); final Database database = databaseService.findById(databaseId); - final User user = principal != null ? userService.findByUsername(principal.getName()) : null; - log.trace("find all views for database {}", database); - final List<ViewBriefDto> views = viewService.findAll(database, user) + final User caller; + if (principal != null) { + caller = userService.findById(getId(principal)); + } else { + caller = null; + } + return ResponseEntity.ok(viewService.findAll(database, caller) .stream() .map(metadataMapper::viewToViewBriefDto) - .collect(Collectors.toList()); - return ResponseEntity.ok(views); + .collect(Collectors.toList())); } @PostMapping @@ -141,17 +143,14 @@ public class ViewEndpoint { UserNotFoundException, SearchServiceException, SearchServiceConnectionException { log.debug("endpoint create view, databaseId={}, data={}", databaseId, data); final Database database = databaseService.findById(databaseId); - final User caller = userService.findByUsername(principal.getName()); - if (!database.getOwner().getId().equals(caller.getId())) { + if (!database.getOwner().getId().equals(getId(principal))) { log.error("Failed to create view: not the database owner"); throw new NotAllowedException("Failed to create view: not the database owner"); } log.trace("create view for database {}", database); - final View view; - view = viewService.create(database, caller, data); - final ViewBriefDto dto = metadataMapper.viewToViewBriefDto(view); return ResponseEntity.status(HttpStatus.CREATED) - .body(dto); + .body(metadataMapper.viewToViewBriefDto( + viewService.create(database, userService.findById(getId(principal)), data))); } @GetMapping("/{viewId}") @@ -193,13 +192,13 @@ public class ViewEndpoint { final Database database = databaseService.findById(databaseId); final View view = viewService.findById(database, viewId); final HttpHeaders headers = new HttpHeaders(); - if (UserUtil.isSystem(principal)) { - headers.set("X-Username", view.getDatabase().getContainer().getPrivilegedUsername()); - headers.set("X-Password", view.getDatabase().getContainer().getPrivilegedPassword()); - headers.set("X-Host", view.getDatabase().getContainer().getHost()); - headers.set("X-Port", "" + view.getDatabase().getContainer().getPort()); - headers.set("X-Type", view.getDatabase().getContainer().getImage().getJdbcMethod()); - headers.set("X-Database", view.getDatabase().getInternalName()); + if (isSystem(principal)) { + headers.set("X-Username", database.getContainer().getPrivilegedUsername()); + headers.set("X-Password", database.getContainer().getPrivilegedPassword()); + headers.set("X-Host", database.getContainer().getHost()); + headers.set("X-Port", "" + database.getContainer().getPort()); + headers.set("X-Type", database.getContainer().getImage().getJdbcMethod()); + headers.set("X-Database", database.getInternalName()); headers.set("X-View", view.getInternalName()); headers.set("Access-Control-Expose-Headers", "X-Username X-Password X-Host X-Port X-Type X-Database X-View"); } @@ -256,7 +255,7 @@ public class ViewEndpoint { SearchServiceConnectionException { log.debug("endpoint delete view, databaseId={}, viewId={}", databaseId, viewId); final Database database = databaseService.findById(databaseId); - if (!database.getOwner().getUsername().equals(principal.getName())) { + if (!database.getOwner().getId().equals(getId(principal))) { log.error("Failed to delete view: not the database owner {}", database.getOwner().getId()); throw new NotAllowedException("Failed to delete view: not the database owner " + database.getOwner().getId()); } @@ -311,12 +310,13 @@ 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().getUsername().equals(principal.getName()) && !view.getOwner().getUsername().equals(principal.getName())) { + if (!database.getOwner().getId().equals(getId(principal)) && !view.getOwner().getId().equals(getId(principal))) { 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"); } return ResponseEntity.accepted() - .body(metadataMapper.viewToViewDto(viewService.update(database, view, data))); + .body(metadataMapper.viewToViewDto( + viewService.update(database, view, data))); } } diff --git a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/validation/EndpointValidator.java b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/validation/EndpointValidator.java index 70f2e4e420eb104b7e76caaa702ed23850fe9565..a748c0d82dab0032ea0b75f6e649f1d1973469d4 100644 --- a/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/validation/EndpointValidator.java +++ b/dbrepo-metadata-service/rest-service/src/main/java/at/tuwien/validation/EndpointValidator.java @@ -5,6 +5,7 @@ import at.tuwien.api.database.table.TableCreateDto; import at.tuwien.api.database.table.columns.ColumnCreateDto; import at.tuwien.api.database.table.columns.ColumnTypeDto; import at.tuwien.api.identifier.IdentifierSaveDto; +import at.tuwien.endpoints.AbstractEndpoint; import at.tuwien.entities.database.AccessType; import at.tuwien.entities.database.Database; import at.tuwien.entities.database.DatabaseAccess; @@ -13,7 +14,6 @@ import at.tuwien.entities.user.User; import at.tuwien.exception.*; import at.tuwien.service.AccessService; import at.tuwien.service.UserService; -import at.tuwien.utils.UserUtil; import lombok.extern.log4j.Log4j2; import org.apache.commons.validator.GenericValidator; import org.springframework.beans.factory.annotation.Autowired; @@ -27,7 +27,7 @@ import java.util.Optional; @Log4j2 @Component -public class EndpointValidator { +public class EndpointValidator extends AbstractEndpoint { public static final List<ColumnTypeDto> NEED_NOTHING = List.of(ColumnTypeDto.BOOL, ColumnTypeDto.SERIAL); public static final List<ColumnTypeDto> NEED_SIZE = List.of(ColumnTypeDto.VARCHAR, ColumnTypeDto.BINARY, ColumnTypeDto.VARBINARY); @@ -62,8 +62,7 @@ public class EndpointValidator { if (principal == null) { throw new NotAllowedException("No principal provided"); } - final User user = userService.findByUsername(principal.getName()); - final DatabaseAccess access = accessService.find(database, user); + final DatabaseAccess access = accessService.find(database, userService.findById(getId(principal))); log.trace("found access: {}", access); if (writeAccessOnly && !(access.getType().equals(AccessType.WRITE_OWN) || access.getType().equals(AccessType.WRITE_ALL))) { log.error("Access not allowed: no write access"); @@ -167,7 +166,7 @@ public class EndpointValidator { } public boolean validateOnlyMineOrWriteAccessOrHasRole(User owner, Principal principal, DatabaseAccess access, String role) { - if (UserUtil.hasRole(principal, role)) { + if (hasRole(principal, role)) { log.debug("validation passed: role {} present", role); return true; } @@ -234,7 +233,7 @@ public class EndpointValidator { throw new NotAllowedException("Access not allowed: no authorization provided"); } log.trace("principal: {}", principal.getName()); - if (!UserUtil.hasRole(principal, role)) { + if (!hasRole(principal, role)) { log.error("Access not allowed: role {} missing", role); throw new NotAllowedException("Access not allowed: role " + role + " missing"); } 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 b788fd206b962c89644d2f0e6802b1a15282627a..9a8c031e1168eeb73eb6d72cca152558303d524c 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 @@ -276,51 +276,51 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void list_anonymous_succeeds() throws DatabaseNotFoundException { + public void list_anonymous_succeeds() throws DatabaseNotFoundException, UserNotFoundException { /* pre-condition */ assertFalse(DATABASE_1_PUBLIC); /* test */ - list_generic(List.of(DATABASE_1), null); + list_generic(List.of(DATABASE_1), null, null); } @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"list-databases"}) - public void list_hasRole_succeeds() throws DatabaseNotFoundException { + public void list_hasRole_succeeds() throws DatabaseNotFoundException, UserNotFoundException { /* pre-condition */ assertTrue(DATABASE_3_PUBLIC); /* test */ - list_generic(List.of(DATABASE_3), null); + list_generic(List.of(DATABASE_3), null, USER_1_PRINCIPAL); } @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"list-databases"}) - public void list_hasRoleForeign_succeeds() throws DatabaseNotFoundException { + public void list_hasRoleForeign_succeeds() throws DatabaseNotFoundException, UserNotFoundException { /* pre-condition */ assertTrue(DATABASE_3_PUBLIC); /* test */ - list_generic(List.of(DATABASE_3), null); + list_generic(List.of(DATABASE_3), null, USER_1_PRINCIPAL); } @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"list-databases"}) - public void list_hasRoleFilter_succeeds() throws DatabaseNotFoundException { + public void list_hasRoleFilter_succeeds() throws DatabaseNotFoundException, UserNotFoundException { /* test */ - list_generic(List.of(DATABASE_3), DATABASE_3_INTERNALNAME); + list_generic(List.of(DATABASE_3), DATABASE_3_INTERNALNAME, USER_1_PRINCIPAL); } @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"list-databases"}) - public void list_hasRoleFilterNoResult_succeeds() throws DatabaseNotFoundException { + public void list_hasRoleFilterNoResult_succeeds() throws DatabaseNotFoundException, UserNotFoundException { /* test */ - list_generic(List.of(), "i_do_not_exist"); + list_generic(List.of(), "i_do_not_exist", USER_1_PRINCIPAL); } @Test @@ -536,11 +536,12 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @Test @WithAnonymousUser - public void findById_anonymous_succeeds() throws DataServiceException, DataServiceConnectionException, - DatabaseNotFoundException, ExchangeNotFoundException, UserNotFoundException { + public void findById_anonymous_fails() { /* test */ - findById_generic(DATABASE_1_ID, DATABASE_1, null); + assertThrows(NotAllowedException.class, () -> { + findById_generic(DATABASE_1_ID, DATABASE_1, null); + }); } @Test @@ -556,7 +557,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"find-database"}) public void findById_hasRole_succeeds() throws DataServiceException, DataServiceConnectionException, - DatabaseNotFoundException, ExchangeNotFoundException, UserNotFoundException { + DatabaseNotFoundException, ExchangeNotFoundException, UserNotFoundException, NotAllowedException { /* pre-condition */ assertTrue(DATABASE_3_PUBLIC); @@ -568,7 +569,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"find-database"}) public void findById_hasRoleForeign_succeeds() throws DataServiceException, DataServiceConnectionException, - DatabaseNotFoundException, ExchangeNotFoundException, UserNotFoundException { + DatabaseNotFoundException, ExchangeNotFoundException, UserNotFoundException, NotAllowedException { /* pre-condition */ assertTrue(DATABASE_3_PUBLIC); @@ -580,7 +581,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { @Test @WithMockUser(username = USER_1_USERNAME, authorities = {"find-database"}) public void findById_ownerSeesAccessRights_succeeds() throws DataServiceException, DataServiceConnectionException, - DatabaseNotFoundException, ExchangeNotFoundException, UserNotFoundException { + DatabaseNotFoundException, ExchangeNotFoundException, UserNotFoundException, NotAllowedException { /* mock */ when(accessService.list(DATABASE_1)) @@ -643,24 +644,25 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { /* ## GENERIC TEST CASES ## */ /* ################################################################################################### */ - public void list_generic(List<Database> databases, String internalName) throws DatabaseNotFoundException { + public void list_generic(List<Database> databases, String internalName, Principal principal) + throws DatabaseNotFoundException, UserNotFoundException { /* mock */ when(databaseService.findAll()) .thenReturn(databases); if (internalName != null) { if (!databases.isEmpty()) { - when(databaseService.findByInternalName(internalName)) - .thenReturn(databases.get(0)); + when(databaseService.findAllPublicByInternalName(internalName)) + .thenReturn(List.of(databases.get(0))); } else { doThrow(DatabaseNotFoundException.class) .when(databaseService) - .findByInternalName(internalName); + .findAllPublicByInternalName(internalName); } } /* test */ - final ResponseEntity<List<DatabaseBriefDto>> response = databaseEndpoint.list(internalName); + final ResponseEntity<List<DatabaseBriefDto>> response = databaseEndpoint.list(internalName, principal); assertEquals(HttpStatus.OK, response.getStatusCode()); assertNotNull(response.getBody()); final List<DatabaseBriefDto> body = response.getBody(); @@ -709,7 +711,7 @@ public class DatabaseEndpointUnitTest extends AbstractUnitTest { public DatabaseDto findById_generic(Long databaseId, Database database, Principal principal) throws DataServiceConnectionException, DatabaseNotFoundException, ExchangeNotFoundException, - DataServiceException, UserNotFoundException { + DataServiceException, UserNotFoundException, NotAllowedException { /* mock */ if (database != null) { 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 54cef2ca4b1e08b2feacc94cc00781687a5e8881..12dc533cb9b44c726c87e552aa845c21025857b3 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 @@ -512,7 +512,7 @@ public class UserEndpointUnitTest extends AbstractUnitTest { doNothing() .when(userService) .updatePassword(USER_1, data); - when(databaseService.findAllAccess(USER_1_ID)) + when(databaseService.findAllPublicOrReadAccess(USER_1_ID)) .thenReturn(List.of(DATABASE_1)); doNothing() .when(databaseService) diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/BrokerServiceGatewayUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/BrokerServiceGatewayUnitTest.java index fc2a9c2c220c4fa601138ee9ee8333d3cd67f493..32a8c8b1907c816d4000e544b2ec0e9d7e8a01fc 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/BrokerServiceGatewayUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/BrokerServiceGatewayUnitTest.java @@ -113,7 +113,7 @@ public class BrokerServiceGatewayUnitTest extends AbstractUnitTest { @Test public void grantVirtualHostPermission_invalidResponseCode2_fails() { - final ResponseEntity<Void> mock = ResponseEntity.status(HttpStatus.ACCEPTED) + final ResponseEntity<Void> mock = ResponseEntity.accepted() .build(); /* mock */ diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/DataServiceGatewayUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/DataServiceGatewayUnitTest.java index 698f7ed524c13bbb3d9fbe5fca37003419f51a4c..daeb1c1a96340323c85ca15080a3bc9d2685823e 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/DataServiceGatewayUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/DataServiceGatewayUnitTest.java @@ -116,7 +116,7 @@ public class DataServiceGatewayUnitTest extends AbstractUnitTest { /* mock */ when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class))) - .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .thenReturn(ResponseEntity.accepted() .build()); /* test */ @@ -184,7 +184,7 @@ public class DataServiceGatewayUnitTest extends AbstractUnitTest { /* mock */ when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.DELETE), eq(HttpEntity.EMPTY), eq(Void.class))) - .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .thenReturn(ResponseEntity.accepted() .build()); /* test */ @@ -322,7 +322,7 @@ public class DataServiceGatewayUnitTest extends AbstractUnitTest { /* mock */ when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class))) - .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .thenReturn(ResponseEntity.accepted() .build()); /* test */ @@ -502,7 +502,7 @@ public class DataServiceGatewayUnitTest extends AbstractUnitTest { /* mock */ when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.DELETE), any(HttpEntity.class), eq(Void.class))) - .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .thenReturn(ResponseEntity.accepted() .build()); /* test */ @@ -653,7 +653,7 @@ public class DataServiceGatewayUnitTest extends AbstractUnitTest { /* mock */ when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.DELETE), eq(HttpEntity.EMPTY), eq(Void.class))) - .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .thenReturn(ResponseEntity.accepted() .build()); /* test */ diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/SearchServiceGatewayUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/SearchServiceGatewayUnitTest.java index aa1c9d4f056f61680aeb341f2cebafdbe262a2b5..b1ce21d4e5e8315b08087dc0d85712509a07973e 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/SearchServiceGatewayUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/gateway/SearchServiceGatewayUnitTest.java @@ -37,7 +37,7 @@ public class SearchServiceGatewayUnitTest extends AbstractUnitTest { @Test public void update_succeeds() throws DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException { - final ResponseEntity<DatabaseDto> mock = ResponseEntity.status(HttpStatus.ACCEPTED) + final ResponseEntity<DatabaseDto> mock = ResponseEntity.accepted() .build(); /* mock */ @@ -109,7 +109,7 @@ public class SearchServiceGatewayUnitTest extends AbstractUnitTest { @Test public void delete_succeeds() throws DatabaseNotFoundException, SearchServiceException, SearchServiceConnectionException { - final ResponseEntity<Void> mock = ResponseEntity.status(HttpStatus.ACCEPTED) + final ResponseEntity<Void> mock = ResponseEntity.accepted() .build(); /* mock */ diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mapper/MetadataMapperUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mapper/MetadataMapperUnitTest.java index fb574f35cae9dd3f3e10ae53be29d2d2b87aa8ff..5e7e1dbc5b233694ba7afe8eafa312103ae34fb5 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mapper/MetadataMapperUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/mapper/MetadataMapperUnitTest.java @@ -2,14 +2,11 @@ package at.tuwien.mapper; import at.tuwien.api.database.DatabaseDto; import at.tuwien.api.database.ViewDto; -import at.tuwien.api.database.table.TableBriefDto; -import at.tuwien.api.identifier.IdentifierBriefDto; -import at.tuwien.api.identifier.IdentifierDto; import at.tuwien.api.identifier.IdentifierTypeDto; import at.tuwien.api.user.UserBriefDto; import at.tuwien.api.user.UserDto; -import at.tuwien.entities.container.Container; -import at.tuwien.entities.identifier.*; +import at.tuwien.entities.identifier.Identifier; +import at.tuwien.entities.identifier.IdentifierType; import at.tuwien.test.AbstractUnitTest; import lombok.extern.log4j.Log4j2; import org.junit.jupiter.api.BeforeEach; @@ -24,7 +21,6 @@ import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.format.DateTimeFormatter; -import java.util.List; import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.*; @@ -78,42 +74,7 @@ public class MetadataMapperUnitTest extends AbstractUnitTest { /* test */ final Identifier response = metadataMapper.identifierCreateDtoToIdentifier(IDENTIFIER_1_CREATE_DTO); - assertNotNull(response.getTitles()); - final List<IdentifierTitle> titles = response.getTitles(); - assertEquals(2, titles.size()); - final IdentifierTitle title0 = titles.get(0); - assertEquals(IDENTIFIER_1_TITLE_1_TITLE, title0.getTitle()); - assertEquals(IDENTIFIER_1_TITLE_1_LANG, title0.getLanguage()); - assertEquals(IDENTIFIER_1_TITLE_1_TYPE, title0.getTitleType()); - final IdentifierTitle title1 = titles.get(1); - assertEquals(IDENTIFIER_1_TITLE_2_TITLE, title1.getTitle()); - assertEquals(IDENTIFIER_1_TITLE_2_LANG, title1.getLanguage()); - assertEquals(IDENTIFIER_1_TITLE_2_TYPE, title1.getTitleType()); - assertNotNull(response.getDescriptions()); - assertEquals(1, response.getDescriptions().size()); - final List<IdentifierDescription> descriptions = response.getDescriptions(); - final IdentifierDescription description0 = descriptions.get(0); - assertNull(description0.getId()); - assertEquals(IDENTIFIER_1_DESCRIPTION_1_DESCRIPTION, description0.getDescription()); - assertEquals(IDENTIFIER_1_DESCRIPTION_1_LANG, description0.getLanguage()); - assertEquals(IDENTIFIER_1_DESCRIPTION_1_TYPE, description0.getDescriptionType()); - assertNotNull(response.getCreators()); - assertEquals(1, response.getCreators().size()); - final Creator creator0 = response.getCreators().get(0); - assertNotNull(creator0); - assertNull(creator0.getId()); - assertEquals(IDENTIFIER_1_CREATOR_1_FIRSTNAME, creator0.getFirstname()); - assertEquals(IDENTIFIER_1_CREATOR_1_LASTNAME, creator0.getLastname()); - assertEquals(IDENTIFIER_1_CREATOR_1_NAME, creator0.getCreatorName()); - assertEquals(IDENTIFIER_1_CREATOR_1_ORCID, creator0.getNameIdentifier()); - assertEquals(IDENTIFIER_1_CREATOR_1_IDENTIFIER_SCHEME_TYPE, creator0.getNameIdentifierScheme()); - assertEquals(IDENTIFIER_1_CREATOR_1_AFFILIATION, creator0.getAffiliation()); - assertEquals(IDENTIFIER_1_CREATOR_1_AFFILIATION_IDENTIFIER, creator0.getAffiliationIdentifier()); - assertEquals(IDENTIFIER_1_CREATOR_1_AFFILIATION_IDENTIFIER_SCHEME, creator0.getAffiliationIdentifierScheme()); - assertEquals(IDENTIFIER_1_CREATOR_1_AFFILIATION_IDENTIFIER_SCHEME_URI, creator0.getAffiliationIdentifierSchemeUri()); - assertNotNull(response.getFunders()); - assertEquals(1, response.getFunders().size()); - assertNull(response.getRelatedIdentifiers()); /* mapstruct strategy for empty values is to set null */ + assertEquals(IDENTIFIER_1, response); } @Test @@ -147,66 +108,15 @@ public class MetadataMapperUnitTest extends AbstractUnitTest { /* test */ final Identifier response = metadataMapper.identifierCreateDtoToIdentifier(IDENTIFIER_3_CREATE_DTO); - assertNull(response.getDatabase()); - assertNull(response.getQueryId()); - assertNull(response.getTableId()); - assertEquals(IDENTIFIER_3_VIEW_ID, response.getViewId()); - assertNull(response.getDoi()); - assertEquals(IDENTIFIER_3_TYPE, response.getType()); + assertEquals(IDENTIFIER_3, response); } @Test public void customDatabaseToDatabaseDto_succeeds() { /* test */ - final DatabaseDto response = metadataMapper.customDatabaseToDatabaseDto(DATABASE_1, USER_1); - assertEquals(DATABASE_1_ID, response.getId()); - assertNotNull(response.getContact()); - assertEquals(USER_1_ID, response.getContact().getId()); - assertEquals(DATABASE_1_PUBLIC, response.getIsPublic()); - assertEquals(DATABASE_1_SCHEMA_PUBLIC, response.getIsSchemaPublic()); - /* identifiers formatted */ - assertEquals(4, response.getIdentifiers().size()); - final IdentifierBriefDto identifier1 = response.getIdentifiers().get(0); - assertEquals(DATABASE_1_ID, identifier1.getDatabaseId()); - final IdentifierBriefDto identifier2 = response.getIdentifiers().get(1); - assertEquals(DATABASE_1_ID, identifier2.getDatabaseId()); - final IdentifierBriefDto identifier3 = response.getIdentifiers().get(2); - assertEquals(DATABASE_1_ID, identifier3.getDatabaseId()); - final IdentifierBriefDto identifier4 = response.getIdentifiers().get(3); - assertEquals(DATABASE_1_ID, identifier4.getDatabaseId()); - /* Table 1 formatted */ - final TableBriefDto table0 = response.getTables().get(0); - assertEquals(TABLE_1_ID, table0.getId()); - assertEquals(TABLE_1_NAME, table0.getName()); - assertEquals(TABLE_1_INTERNAL_NAME, table0.getInternalName()); - assertEquals(TABLE_1_DESCRIPTION, table0.getDescription()); - assertEquals(DATABASE_1_ID, table0.getDatabaseId()); - assertEquals(TABLE_1_SCHEMA_PUBLIC, table0.getIsSchemaPublic()); - /* Table 2 formatted */ - final TableBriefDto table1 = response.getTables().get(1); - assertEquals(TABLE_2_ID, table1.getId()); - assertEquals(TABLE_2_NAME, table1.getName()); - assertEquals(TABLE_2_INTERNALNAME, table1.getInternalName()); - assertEquals(TABLE_2_DESCRIPTION, table1.getDescription()); - assertEquals(DATABASE_1_ID, table1.getDatabaseId()); - assertEquals(TABLE_2_SCHEMA_PUBLIC, table1.getIsSchemaPublic()); - /* Table 3 formatted */ - final TableBriefDto table2 = response.getTables().get(2); - assertEquals(TABLE_3_ID, table2.getId()); - assertEquals(TABLE_3_NAME, table2.getName()); - assertEquals(TABLE_3_INTERNALNAME, table2.getInternalName()); - assertEquals(TABLE_3_DESCRIPTION, table2.getDescription()); - assertEquals(DATABASE_1_ID, table2.getDatabaseId()); - assertEquals(TABLE_3_SCHEMA_PUBLIC, table2.getIsSchemaPublic()); - /* Table 4 formatted */ - final TableBriefDto table3 = response.getTables().get(3); - assertEquals(TABLE_4_ID, table3.getId()); - assertEquals(TABLE_4_NAME, table3.getName()); - assertEquals(TABLE_4_INTERNALNAME, table3.getInternalName()); - assertEquals(TABLE_4_DESCRIPTION, table3.getDescription()); - assertEquals(DATABASE_1_ID, table3.getDatabaseId()); - assertEquals(TABLE_4_SCHEMA_PUBLIC, table3.getIsSchemaPublic()); + final DatabaseDto response = metadataMapper.customDatabaseToDatabaseDto(DATABASE_1); + assertEquals(DATABASE_1_DTO, response); } public static Stream<Arguments> nameToInternalName_parameters() { @@ -234,23 +144,6 @@ public class MetadataMapperUnitTest extends AbstractUnitTest { assertNotEquals(USER_1_DTO, USER_2_DTO); } - @Test - public void userEquals_identity_succeeds() { - - /* test */ - assertEquals(USER_1_DTO, USER_1_DTO); - } - - @Test - public void userEquals_similar_succeeds() { - final UserDto tmp = UserDto.builder() - .id(USER_1_ID) - .build(); - - /* test */ - assertEquals(USER_1_DTO, tmp); - } - @Test public void userToUserBriefDto_succeeds() { @@ -265,8 +158,7 @@ public class MetadataMapperUnitTest extends AbstractUnitTest { /* test */ final UserDto response = metadataMapper.userToUserDto(USER_1); - assertEquals(USER_1_NAME, response.getName()); - assertEquals(USER_1_NAME + " — @" + USER_1_USERNAME, response.getQualifiedName()); + assertEquals(USER_1_DTO, response); } @Test @@ -274,22 +166,7 @@ public class MetadataMapperUnitTest extends AbstractUnitTest { /* test */ final ViewDto response = metadataMapper.viewToViewDto(VIEW_1); - assertEquals(VIEW_1_ID, response.getId()); - assertEquals(VIEW_1_DATABASE_ID, response.getVdbid()); - assertEquals(VIEW_1_NAME, response.getName()); - assertEquals(VIEW_1_INTERNAL_NAME, response.getInternalName()); - assertNotNull(response.getDatabase()); - assertEquals(VIEW_1_DATABASE_ID, response.getDatabase().getId()); - assertEquals(VIEW_1_QUERY, response.getQuery()); - assertEquals(VIEW_1_QUERY_HASH, response.getQueryHash()); - assertNotNull(response.getIdentifiers()); - assertEquals(1, response.getIdentifiers().size()); - final IdentifierDto identifier0 = response.getIdentifiers().get(0); - assertEquals(IDENTIFIER_3_ID, identifier0.getId()); - assertEquals(VIEW_1_DATABASE_ID, identifier0.getDatabaseId()); - assertEquals(VIEW_1_ID, identifier0.getViewId()); - assertEquals(VIEW_1_QUERY, identifier0.getQuery()); - assertEquals(VIEW_1_QUERY_HASH, identifier0.getQueryHash()); + assertEquals(VIEW_1_DTO, response); } } 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 578f6276c791ab8465b46f115acc05ace1b7e948..5ae4aad0187cc52749416bdb3208d3ff678d5285 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 @@ -202,7 +202,7 @@ public class PrometheusEndpointMvcTest extends AbstractUnitTest { /* mock */ try { - databaseEndpoint.list(null); + databaseEndpoint.list(null, null); } catch (Exception e) { /* ignore */ } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/AccessServiceUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/AccessServiceUnitTest.java index 54015177aaff7d3e52a98b5c2db7103a8c272fc1..c647cdbd7403b5f5c742953fd9978e0c8d98ab06 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/AccessServiceUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/AccessServiceUnitTest.java @@ -81,7 +81,7 @@ public class AccessServiceUnitTest extends AbstractUnitTest { .thenReturn(ResponseEntity.status(HttpStatus.CREATED) .build()); when(searchServiceRestTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(DatabaseDto.class))) - .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .thenReturn(ResponseEntity.accepted() .build()); /* test */ @@ -228,10 +228,10 @@ public class AccessServiceUnitTest extends AbstractUnitTest { when(databaseRepository.save(any(Database.class))) .thenReturn(DATABASE_1); when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class))) - .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .thenReturn(ResponseEntity.accepted() .build()); when(searchServiceRestTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(DatabaseDto.class))) - .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .thenReturn(ResponseEntity.accepted() .build()); /* test */ @@ -301,7 +301,7 @@ public class AccessServiceUnitTest extends AbstractUnitTest { when(databaseRepository.save(any(Database.class))) .thenReturn(DATABASE_1); when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class))) - .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .thenReturn(ResponseEntity.accepted() .build()); doThrow(HttpClientErrorException.BadRequest.class) .when(searchServiceRestTemplate) @@ -320,7 +320,7 @@ public class AccessServiceUnitTest extends AbstractUnitTest { when(databaseRepository.save(any(Database.class))) .thenReturn(DATABASE_1); when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class))) - .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .thenReturn(ResponseEntity.accepted() .build()); doThrow(HttpClientErrorException.Unauthorized.class) .when(searchServiceRestTemplate) @@ -339,7 +339,7 @@ public class AccessServiceUnitTest extends AbstractUnitTest { when(databaseRepository.save(any(Database.class))) .thenReturn(DATABASE_1); when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class))) - .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .thenReturn(ResponseEntity.accepted() .build()); doThrow(HttpClientErrorException.NotFound.class) .when(searchServiceRestTemplate) @@ -358,7 +358,7 @@ public class AccessServiceUnitTest extends AbstractUnitTest { when(databaseRepository.save(any(Database.class))) .thenReturn(DATABASE_1); when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(Void.class))) - .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .thenReturn(ResponseEntity.accepted() .build()); doThrow(HttpServerErrorException.InternalServerError.class) .when(searchServiceRestTemplate) @@ -380,10 +380,10 @@ public class AccessServiceUnitTest extends AbstractUnitTest { when(databaseRepository.save(any(Database.class))) .thenReturn(DATABASE_1); when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.DELETE), any(HttpEntity.class), eq(Void.class))) - .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .thenReturn(ResponseEntity.accepted() .build()); when(searchServiceRestTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class), eq(DatabaseDto.class))) - .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .thenReturn(ResponseEntity.accepted() .build()); /* test */ @@ -441,7 +441,7 @@ public class AccessServiceUnitTest extends AbstractUnitTest { when(databaseRepository.save(any(Database.class))) .thenReturn(DATABASE_1); when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.DELETE), any(HttpEntity.class), eq(Void.class))) - .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .thenReturn(ResponseEntity.accepted() .build()); doThrow(HttpClientErrorException.BadRequest.class) .when(searchServiceRestTemplate) @@ -462,7 +462,7 @@ public class AccessServiceUnitTest extends AbstractUnitTest { when(databaseRepository.save(any(Database.class))) .thenReturn(DATABASE_1); when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.DELETE), any(HttpEntity.class), eq(Void.class))) - .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .thenReturn(ResponseEntity.accepted() .build()); doThrow(HttpClientErrorException.Unauthorized.class) .when(searchServiceRestTemplate) @@ -483,7 +483,7 @@ public class AccessServiceUnitTest extends AbstractUnitTest { when(databaseRepository.save(any(Database.class))) .thenReturn(DATABASE_1); when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.DELETE), any(HttpEntity.class), eq(Void.class))) - .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .thenReturn(ResponseEntity.accepted() .build()); doThrow(HttpClientErrorException.NotFound.class) .when(searchServiceRestTemplate) @@ -504,7 +504,7 @@ public class AccessServiceUnitTest extends AbstractUnitTest { when(databaseRepository.save(any(Database.class))) .thenReturn(DATABASE_1); when(dataServiceRestTemplate.exchange(anyString(), eq(HttpMethod.DELETE), any(HttpEntity.class), eq(Void.class))) - .thenReturn(ResponseEntity.status(HttpStatus.ACCEPTED) + .thenReturn(ResponseEntity.accepted() .build()); doThrow(HttpServerErrorException.InternalServerError.class) .when(searchServiceRestTemplate) diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServicePersistenceTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServicePersistenceTest.java index bda2fc0ee5b103393a14b32b4244018c242d3f5a..4fb6f0f0b2a30f8ebc300b3d56aa46bb483bbec7 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServicePersistenceTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServicePersistenceTest.java @@ -64,11 +64,12 @@ public class DatabaseServicePersistenceTest extends AbstractUnitTest { @Test @Transactional(readOnly = true) - public void findByInternalName_succeeds() throws DatabaseNotFoundException { + public void findAllPublicByInternalName_succeeds() { /* test */ - final Database response = databaseService.findByInternalName(DATABASE_1_INTERNALNAME); - assertEquals(DATABASE_1, response); + final List<Database> response = databaseService.findAllPublicByInternalName(DATABASE_1_INTERNALNAME); + assertEquals(1, response.size()); + assertEquals(DATABASE_1, response.get(0)); } } diff --git a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceUnitTest.java b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceUnitTest.java index 7815c4ae69a98c5dfd5171e1c83cd9fdb6de0a72..7f84b3b09ca165cf9ca654efba512c6f480ca5d8 100644 --- a/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceUnitTest.java +++ b/dbrepo-metadata-service/rest-service/src/test/java/at/tuwien/service/DatabaseServiceUnitTest.java @@ -88,15 +88,15 @@ public class DatabaseServiceUnitTest extends AbstractUnitTest { } @Test - public void findByInternalName_notFound_fails() { + public void findAllPublicByInternalName_notFound_fails() { /* mock */ - when(databaseRepository.findByInternalName(DATABASE_1_INTERNALNAME)) - .thenReturn(Optional.empty()); + when(databaseRepository.findAllPublicByInternalNameDesc(DATABASE_1_INTERNALNAME)) + .thenReturn(List.of()); /* test */ assertThrows(DatabaseNotFoundException.class, () -> { - databaseService.findByInternalName(DATABASE_1_INTERNALNAME); + databaseService.findAllPublicByInternalName(DATABASE_1_INTERNALNAME); }); } @@ -105,7 +105,7 @@ public class DatabaseServiceUnitTest extends AbstractUnitTest { DataServiceConnectionException { /* mock */ - when(databaseRepository.findReadAccess(USER_1_ID)) + when(databaseRepository.findAllPublicOrReadAccessDesc(USER_1_ID)) .thenReturn(List.of(DATABASE_1)); doNothing() .when(dataServiceGateway) diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/DatabaseService.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/DatabaseService.java index d7c036049b84cfe9d028fa60fa532aa6ba00dc75..416025270d83a2eea36b765f071a5b23bb3eff7d 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/DatabaseService.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/DatabaseService.java @@ -21,20 +21,23 @@ public interface DatabaseService { */ List<Database> findAll(); + List<Database> findAllPublic(); + + List<Database> findAllPublicOrReadAccessByInternalName(UUID userId, String internalName); + /** * Finds all databases stored in the metadata database. * * @param userId The user id. * @return List of databases. */ - List<Database> findAllAccess(UUID userId); + List<Database> findAllPublicOrReadAccess(UUID userId); /** * @param internalName The database internal name. - * @return The database if found. - * @throws DatabaseNotFoundException The database was not found. + * @return The databases if found. */ - Database findByInternalName(String internalName) throws DatabaseNotFoundException; + List<Database> findAllPublicByInternalName(String internalName); /** * Find a database by id, only used in the authentication service diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/UserService.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/UserService.java index 8e7c715ad06d434bfdb947136546f686e91835ad..9957100710dde1db321ce600227497b7b6bddfcf 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/UserService.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/UserService.java @@ -1,9 +1,12 @@ package at.tuwien.service; import at.tuwien.api.auth.SignupRequestDto; -import at.tuwien.api.user.*; +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.exception.EmailExistsException; +import at.tuwien.exception.UserExistsException; +import at.tuwien.exception.UserNotFoundException; import java.util.List; import java.util.UUID; diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceImpl.java index f3f4cccc5d5d8742d4c35d12b982001e0cfbb431..828a1dec7362c710e484dad95781e5f88486481b 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/DatabaseServiceImpl.java @@ -57,19 +57,23 @@ public class DatabaseServiceImpl implements DatabaseService { } @Override - public List<Database> findAllAccess(UUID userId) { - return databaseRepository.findReadAccess(userId); + public List<Database> findAllPublic() { + return databaseRepository.findAllPublicDesc(); } @Override - public Database findByInternalName(String internalName) throws DatabaseNotFoundException { - log.trace("find database by internal name: {}", internalName); - final Optional<Database> database = databaseRepository.findByInternalName(internalName); - if (database.isEmpty()) { - log.error("Failed to find database with internal name {} in metadata database", internalName); - throw new DatabaseNotFoundException("Failed to find database in metadata database"); - } - return database.get(); + public List<Database> findAllPublicOrReadAccessByInternalName(UUID userId, String internalName) { + return databaseRepository.findAllPublicOrReadAccessByInternalNameDesc(userId, internalName); + } + + @Override + public List<Database> findAllPublicOrReadAccess(UUID userId) { + return databaseRepository.findAllPublicOrReadAccessDesc(userId); + } + + @Override + public List<Database> findAllPublicByInternalName(String internalName) { + return databaseRepository.findAllPublicByInternalNameDesc(internalName); } @Override @@ -137,7 +141,7 @@ public class DatabaseServiceImpl implements DatabaseService { @Transactional(readOnly = true) public void updatePassword(Database database, User user) throws DataServiceException, DataServiceConnectionException, DatabaseNotFoundException { - final List<Database> databases = databaseRepository.findReadAccess(user.getId()) + final List<Database> databases = databaseRepository.findAllPublicOrReadAccessDesc(user.getId()) .stream() .distinct() .toList(); 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 8706e18bbc7719b7d8beec8c36a33834b4397471..bf7498d4bb164991e5006a9e52f0c52dd10d3cd3 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 @@ -184,44 +184,44 @@ public class IdentifierServiceImpl implements IdentifierService { identifier.setType(metadataMapper.identifierTypeDtoToIdentifierType(data.getType())); /* create in metadata database */ if (data.getCreators() != null) { - identifier.setCreators(new LinkedList<>(data.getCreators() + identifier.setCreators(data.getCreators() .stream() .map(metadataMapper::creatorCreateDtoToCreator) - .peek(c -> c.setIdentifier(identifier)) - .toList())); - log.debug("set {} creator(s)", identifier.getCreators().size()); + .toList()); + identifier.getCreators() + .forEach(c -> c.setIdentifier(identifier)); } if (data.getRelatedIdentifiers() != null) { - identifier.setRelatedIdentifiers(new LinkedList<>(data.getRelatedIdentifiers() + identifier.setRelatedIdentifiers(data.getRelatedIdentifiers() .stream() .map(metadataMapper::relatedIdentifierCreateDtoToRelatedIdentifier) - .peek(r -> r.setIdentifier(identifier)) - .toList())); - log.debug("set {} related identifier(s)", identifier.getRelatedIdentifiers().size()); + .toList()); + identifier.getRelatedIdentifiers() + .forEach(r -> r.setIdentifier(identifier)); } if (data.getTitles() != null) { - identifier.setTitles(new LinkedList<>(data.getTitles() + identifier.setTitles(data.getTitles() .stream() .map(metadataMapper::identifierCreateTitleDtoToIdentifierTitle) - .peek(t -> t.setIdentifier(identifier)) - .toList())); - log.debug("set {} title(s)", identifier.getTitles().size()); + .toList()); + identifier.getTitles() + .forEach(t -> t.setIdentifier(identifier)); } if (data.getDescriptions() != null) { - identifier.setDescriptions(new LinkedList<>(data.getDescriptions() + identifier.setDescriptions(data.getDescriptions() .stream() .map(metadataMapper::identifierCreateDescriptionDtoToIdentifierDescription) - .peek(d -> d.setIdentifier(identifier)) - .toList())); - log.debug("set {} description(s)", identifier.getDescriptions().size()); + .toList()); + identifier.getDescriptions() + .forEach(d -> d.setIdentifier(identifier)); } if (data.getFunders() != null) { - identifier.setFunders(new LinkedList<>(data.getFunders() + identifier.setFunders(data.getFunders() .stream() .map(metadataMapper::identifierFunderSaveDtoToIdentifierFunder) - .peek(d -> d.setIdentifier(identifier)) - .toList())); - log.debug("set {} funder(s)", identifier.getFunders().size()); + .toList()); + identifier.getFunders() + .forEach(f -> f.setIdentifier(identifier)); } return save(identifier); } @@ -238,45 +238,44 @@ public class IdentifierServiceImpl implements IdentifierService { identifier.setStatus(IdentifierStatusType.DRAFT); /* create in metadata database */ if (data.getCreators() != null) { - identifier.setCreators(new LinkedList<>(data.getCreators() + identifier.setCreators(data.getCreators() .stream() .map(metadataMapper::creatorCreateDtoToCreator) - .peek(c -> c.setIdentifier(identifier)) - .toList())); - log.debug("set {} creator(s)", identifier.getCreators().size()); + .toList()); + identifier.getCreators() + .forEach(c -> c.setIdentifier(identifier)); } if (data.getRelatedIdentifiers() != null) { - identifier.setRelatedIdentifiers(new LinkedList<>(data.getRelatedIdentifiers() + identifier.setRelatedIdentifiers(data.getRelatedIdentifiers() .stream() .map(metadataMapper::relatedIdentifierCreateDtoToRelatedIdentifier) - .peek(r -> r.setIdentifier(identifier)) - .toList())); - log.debug("set {} related identifier(s)", identifier.getRelatedIdentifiers().size()); + .toList()); + identifier.getRelatedIdentifiers() + .forEach(r -> r.setIdentifier(identifier)); } if (data.getTitles() != null) { - identifier.setTitles(null); - identifier.setTitles(new LinkedList<>(data.getTitles() + identifier.setTitles(data.getTitles() .stream() .map(metadataMapper::identifierCreateTitleDtoToIdentifierTitle) - .peek(t -> t.setIdentifier(identifier)) - .toList())); - log.debug("set {} title(s)", identifier.getTitles().size()); + .toList()); + identifier.getTitles() + .forEach(t -> t.setIdentifier(identifier)); } if (data.getDescriptions() != null) { - identifier.setDescriptions(new LinkedList<>(data.getDescriptions() + identifier.setDescriptions(data.getDescriptions() .stream() .map(metadataMapper::identifierCreateDescriptionDtoToIdentifierDescription) - .peek(d -> d.setIdentifier(identifier)) - .toList())); - log.debug("set {} description(s)", identifier.getDescriptions().size()); + .toList()); + identifier.getDescriptions() + .forEach(d -> d.setIdentifier(identifier)); } if (data.getFunders() != null) { - identifier.setFunders(new LinkedList<>(data.getFunders() + identifier.setFunders(data.getFunders() .stream() .map(metadataMapper::identifierFunderSaveDtoToIdentifierFunder) - .peek(d -> d.setIdentifier(identifier)) - .toList())); - log.debug("set {} funder(s)", identifier.getFunders().size()); + .toList()); + identifier.getFunders() + .forEach(f -> f.setIdentifier(identifier)); } return save(identifier); } diff --git a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/UserServiceImpl.java b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/UserServiceImpl.java index 7e07b68d1c965ed42261ab508273770be50a6454..f18d3c1da66bdb640d84f59d362b754a5033503a 100644 --- a/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/UserServiceImpl.java +++ b/dbrepo-metadata-service/services/src/main/java/at/tuwien/service/impl/UserServiceImpl.java @@ -1,9 +1,12 @@ package at.tuwien.service.impl; import at.tuwien.api.auth.SignupRequestDto; -import at.tuwien.api.user.*; +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.exception.EmailExistsException; +import at.tuwien.exception.UserExistsException; +import at.tuwien.exception.UserNotFoundException; import at.tuwien.repository.UserRepository; import at.tuwien.service.UserService; import lombok.extern.log4j.Log4j2; diff --git a/dbrepo-ui/components/JumboBox.vue b/dbrepo-ui/components/JumboBox.vue new file mode 100644 index 0000000000000000000000000000000000000000..10b1a8a6697d44bda97e402ef056dc1ba093a8ff --- /dev/null +++ b/dbrepo-ui/components/JumboBox.vue @@ -0,0 +1,58 @@ +<template> + <div> + <v-row> + <v-col + offset-md="2" + md="8"> + <v-card + class="mx-auto" + :title="title" + :subtitle="subtitle" + :text="text"> + <template v-slot:prepend> + <v-icon + :color="iconColor"> + {{ icon }} + </v-icon> + </template> + </v-card> + </v-col> + </v-row> + </div> +</template> +<script> +export default { + props: { + title: { + type: String, + default: () => { + return 'Title' + } + }, + subtitle: { + type: String, + default: () => { + return 'Subtitle' + } + }, + text: { + type: String, + default: () => { + return 'Text' + } + }, + icon: { + type: String, + default: () => { + return 'mdi-alert-rhombus-outline' + } + }, + iconColor: { + type: String, + default: () => { + return 'warning' + } + } + } +} +</script> diff --git a/dbrepo-ui/locales/en-US.json b/dbrepo-ui/locales/en-US.json index 655ec2a345b98294cf6512c531f83a67c9196d3c..102ba3fd0a01f24cde64c070ec6fb51ee5efc68f 100644 --- a/dbrepo-ui/locales/en-US.json +++ b/dbrepo-ui/locales/en-US.json @@ -1088,6 +1088,18 @@ } }, "error": { + "permission": { + "title": "You do not have permission to view this resource", + "text": "This a default-fallback error message since this resource marked as private. Please try logging in or request read-access permissions from the owner." + }, + "missing": { + "title": "The requested resource was not found", + "text": "We could not find the requested resource anywhere." + }, + "gone": { + "title": "The requested resource does not exist anymore", + "text": "We could not find the requested resource anymore." + }, "auth": { "connection": "Failed to contact auth service", "invalid": "Failed to authenticate in auth service" @@ -1120,7 +1132,7 @@ }, "database": { "connection": "Failed to contact database", - "create": "Failed to create database in data service", + "create": "Failed to create database in data service", "invalid": "Failed to perform action in database", "querystore": "Failed to insert query into query store", "missing": "Failed to find database in metadata database" diff --git a/dbrepo-ui/pages/database/[database_id]/info.vue b/dbrepo-ui/pages/database/[database_id]/info.vue index 5b739987fdcaa422d31e0fc2545bcdeacbdf38ad..f5c68e328f603d06dffb0a5a8d8a06999297c77a 100644 --- a/dbrepo-ui/pages/database/[database_id]/info.vue +++ b/dbrepo-ui/pages/database/[database_id]/info.vue @@ -1,7 +1,9 @@ <template> <div> - <DatabaseToolbar /> + <DatabaseToolbar + v-if="!isError" /> <v-window + v-if="!isError" v-model="tab"> <v-window-item value="1"> <Summary @@ -167,28 +169,23 @@ </v-card> </v-window-item> </v-window> + <JumboBox + v-if="isError" + :title="errorTitle" + :subtitle="errorSubtitle" + :text="errorText" /> <v-breadcrumbs :items="items" class="pa-0 mt-2" /> </div> </template> - -<script setup> -const config = useRuntimeConfig() -const { database_id } = useRoute().params -const { data } = await useFetch(`${config.public.api.server}/api/database/${database_id}`) -if (data.value) { - const identifierService = useIdentifierService() - useServerHead(identifierService.databaseToServerHead(data.value)) - useServerSeoMeta(identifierService.databaseToServerSeoMeta(data.value)) -} -</script> <script> import DatabaseToolbar from '@/components/database/DatabaseToolbar.vue' import Summary from '@/components/identifier/Summary.vue' import Select from '@/components/identifier/Select.vue' import UserBadge from '@/components/user/UserBadge.vue' -import { formatTimestampUTCLabel, sizeToHumanLabel } from '@/utils' +import JumboBox from '@/components/JumboBox.vue' +import { sizeToHumanLabel } from '@/utils' import { useUserStore } from '@/stores/user' import { useCacheStore } from '@/stores/cache' @@ -197,7 +194,25 @@ export default { DatabaseToolbar, Summary, Select, - UserBadge + UserBadge, + JumboBox + }, + setup () { + const config = useRuntimeConfig() + const { database_id } = useRoute().params + const { error, data } = useFetch(`${config.public.api.server}/api/database/${database_id}`, { + immediate: true, + timeout: 90_000 + }) + if (data.value) { + const identifierService = useIdentifierService() + useServerHead(identifierService.databaseToServerHead(data.value)) + useServerSeoMeta(identifierService.databaseToServerSeoMeta(data.value)) + } + return { + database: data, + error + } }, data () { return { @@ -275,9 +290,6 @@ export default { access () { return this.userStore.getAccess }, - database () { - return this.cacheStore.getDatabase - }, pid () { return this.$route.query.pid }, @@ -372,6 +384,33 @@ export default { return null } return this.database.preview_image + }, + isError () { + return this.error + }, + errorTitle () { + switch (this.error.statusCode) { + case 404: + return this.$t('error.missing.title') + default: + return this.$t('error.permission.title') + } + }, + errorSubtitle () { + switch (this.error.statusCode) { + case 404: + return 'ERROR_NOT_FOUND' + default: + return 'ERROR_NOT_AUTHORIZED' + } + }, + errorText () { + switch (this.error.statusCode) { + case 404: + return this.$t('error.missing.text') + default: + return this.$t('error.permission.text') + } } } } diff --git a/dbrepo-ui/stores/cache.js b/dbrepo-ui/stores/cache.js index 5004b1beb0170862f5062627656fcf6e8844dd7a..bbe4f966c2577724e6c9a8f08f5a1143794b7497 100644 --- a/dbrepo-ui/stores/cache.js +++ b/dbrepo-ui/stores/cache.js @@ -72,6 +72,7 @@ export const useCacheStore = defineStore('cache', { databaseService.findOne(databaseId) .then(database => this.database = database) .catch((error) => { + this.database = null console.error('Failed to set route database', error) }) }, diff --git a/dbrepo-upload-service/pom.xml b/dbrepo-upload-service/pom.xml index db626827a1e4b98662866815b8a6cf4c87e2d5c8..f2bea092361406c7f933a5c26f8eadb0ecbcb131 100644 --- a/dbrepo-upload-service/pom.xml +++ b/dbrepo-upload-service/pom.xml @@ -11,9 +11,9 @@ <groupId>at.tuwien</groupId> <artifactId>dbrepo-upload-service</artifactId> <name>dbrepo-upload-service</name> - <version>1.6.0</version> + <version>1.6.1</version> - <url>https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.5/</url> + <url>https://www.ifs.tuwien.ac.at/infrastructures/dbrepo/1.6/</url> <developers> <developer> <name>Martin Weise</name>