From 01bb47e823e92d4df390ed813e117a82a6f0d91d Mon Sep 17 00:00:00 2001 From: Martin Weise <martin.weise@tuwien.ac.at> Date: Fri, 21 Apr 2023 21:37:37 +0200 Subject: [PATCH] WIP - frontend still missing unique column constraints form --- Makefile | 19 +++++++++ .../tuwien/endpoints/ContainerEndpoint.java | 2 +- .../service/impl/ContainerServiceImpl.java | 4 +- .../at/tuwien/endpoints/DatabaseEndpoint.java | 8 ++-- .../at/tuwien/mapper/IdentifierMapper.java | 1 - .../service/impl/MariaDbServiceImpl.java | 7 ++-- .../tuwien/endpoints/IdentifierEndpoint.java | 2 +- .../service/impl/IdentifierServiceImpl.java | 6 +-- .../at/tuwien/api/database/ViewBriefDto.java | 3 +- .../java/at/tuwien/api/database/ViewDto.java | 3 +- .../api/database/query/QueryBriefDto.java | 3 +- .../tuwien/api/database/query/QueryDto.java | 6 +-- .../tuwien/entities/container/Container.java | 16 +++++++- .../at/tuwien/entities/database/Database.java | 26 ++++++++++-- .../entities/database/DatabaseAccess.java | 2 + .../at/tuwien/entities/database/View.java | 9 +++- .../tuwien/entities/database/table/Table.java | 8 +++- .../database/table/columns/TableColumn.java | 9 +++- .../tuwien/entities/identifier/Creator.java | 9 +++- .../entities/identifier/Identifier.java | 9 +++- .../identifier/RelatedIdentifier.java | 9 +++- .../at/tuwien/entities/user/Credential.java | 3 ++ .../java/at/tuwien/entities/user/Realm.java | 4 ++ .../java/at/tuwien/entities/user/Role.java | 4 ++ .../at/tuwien/entities/user/RoleMapping.java | 3 ++ .../java/at/tuwien/entities/user/User.java | 41 +++++++++++++++++-- .../tuwien/entities/user/UserAttribute.java | 3 ++ .../main/java/at/tuwien/test/BaseTest.java | 4 +- .../at/tuwien/endpoint/ExportEndpoint.java | 4 +- .../at/tuwien/endpoint/QueryEndpoint.java | 10 ++--- .../java/at/tuwien/endpoint/ViewEndpoint.java | 8 ++-- .../java/at/tuwien/mapper/ViewMapper.java | 3 -- .../tuwien/service/impl/ViewServiceImpl.java | 2 +- .../java/at/tuwien/mapper/TableMapper.java | 1 + .../tuwien/service/impl/TableServiceImpl.java | 2 +- dbrepo-ui/api/middleware.service.js | 8 ++-- dbrepo-ui/components/DBToolbar.vue | 8 ++-- dbrepo-ui/components/EMPTY.vue | 23 ----------- dbrepo-ui/components/TableToolbar.vue | 12 +++--- .../database/_database_id/table/import.vue | 11 ++--- dbrepo-user-service/Dockerfile | 2 +- dbrepo-user-service/pom.xml | 6 +++ .../java/at/tuwien/endpoint/UserEndpoint.java | 23 ++++++++--- .../src/main/resources/application-local.yml | 4 ++ .../src/main/resources/application.yml | 4 ++ .../src/test/java/at/tuwien/BaseUnitTest.java | 9 ++++ .../java/at/tuwien/mapper/UserMapperTest.java | 40 ++++++++++++++++++ .../java/at/tuwien/config/GatewayConfig.java | 16 ++++++++ .../java/at/tuwien/mapper/UserMapper.java | 2 +- .../tuwien/service/impl/UserServiceImpl.java | 9 ++-- 50 files changed, 317 insertions(+), 113 deletions(-) delete mode 100644 dbrepo-ui/components/EMPTY.vue create mode 100644 dbrepo-user-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java create mode 100644 dbrepo-user-service/rest-service/src/test/java/at/tuwien/mapper/UserMapperTest.java diff --git a/Makefile b/Makefile index af0b593ed7..2b252e8475 100644 --- a/Makefile +++ b/Makefile @@ -46,6 +46,25 @@ build-docker: docker compose build dbrepo-metadata-db docker compose build --parallel +build-docker-slow: + docker compose build dbrepo-analyse-service + docker compose build dbrepo-authentication-service + docker compose build dbrepo-broker-service + docker compose build dbrepo-metadata-db + docker compose build dbrepo-container-service + docker compose build dbrepo-database-service + docker compose build dbrepo-discovery-service + docker compose build dbrepo-gateway-service + docker compose build dbrepo-identifier-service + docker compose build dbrepo-metadata-service + docker compose build dbrepo-proxy + docker compose build dbrepo-query-service + docker compose build dbrepo-search-service + docker compose build dbrepo-semantics-service + docker compose build dbrepo-table-service + docker compose build dbrepo-ui + docker compose build dbrepo-user-service + build-frontend: yarn --cwd ./dbrepo-ui install --legacy-peer-deps yarn --cwd ./dbrepo-ui run build diff --git a/dbrepo-container-service/rest-service/src/main/java/at/tuwien/endpoints/ContainerEndpoint.java b/dbrepo-container-service/rest-service/src/main/java/at/tuwien/endpoints/ContainerEndpoint.java index 0c9cf4e4a6..38d02adb7b 100644 --- a/dbrepo-container-service/rest-service/src/main/java/at/tuwien/endpoints/ContainerEndpoint.java +++ b/dbrepo-container-service/rest-service/src/main/java/at/tuwien/endpoints/ContainerEndpoint.java @@ -245,7 +245,7 @@ public class ContainerEndpoint { }) public ResponseEntity<?> delete(@NotNull @PathVariable("id") Long containerId, @NotNull Principal principal) throws ContainerNotFoundException, - ContainerStillRunningException, ContainerAlreadyRemovedException, DockerClientException { + ContainerStillRunningException, ContainerAlreadyRemovedException { log.debug("endpoint delete container, containerId={}, principal={}", containerId, principal); containerService.remove(containerId); return ResponseEntity.accepted() diff --git a/dbrepo-container-service/services/src/main/java/at/tuwien/service/impl/ContainerServiceImpl.java b/dbrepo-container-service/services/src/main/java/at/tuwien/service/impl/ContainerServiceImpl.java index 34d1b40739..124a27ebda 100644 --- a/dbrepo-container-service/services/src/main/java/at/tuwien/service/impl/ContainerServiceImpl.java +++ b/dbrepo-container-service/services/src/main/java/at/tuwien/service/impl/ContainerServiceImpl.java @@ -99,8 +99,8 @@ public class ContainerServiceImpl implements ContainerService { response.getName() + ":/var/lib/mysql", availableTcpPort + ":" + image.get().getDefaultPort()); log.trace("host config {}", hostConfig); final User user = userService.findByUsername(principal.getName()); - container.setCreator(user); - container.setOwner(user); + container.setCreatedBy(user.getId()); + container.setOwnedBy(user.getId()); /* create the container */ final CreateContainerResponse response1; try { diff --git a/dbrepo-database-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java b/dbrepo-database-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java index b2c23b9183..f44d81db88 100644 --- a/dbrepo-database-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java +++ b/dbrepo-database-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java @@ -148,7 +148,7 @@ public class DatabaseEndpoint { principal); final Container container = containerService.find(containerId); final User user = userService.findByUsername(principal.getName()); - if (!container.getOwner().getId().equals(user.getId())) { + if (!container.getOwner().equals(user)) { log.error("Failed to create database: not owner"); throw new NotAllowedException(("Failed to create database: not owner")); } @@ -195,7 +195,7 @@ public class DatabaseEndpoint { databaseId, data, principal); final Database database = databaseService.findById(containerId, databaseId); final User user = userService.findByUsername(principal.getName()); - if (!database.getOwner().getId().equals(user.getId())) { + if (!database.getOwner().equals(user)) { log.error("Failed to create database: not owner"); throw new NotAllowedException(("Failed to create database: not owner")); } @@ -236,7 +236,7 @@ public class DatabaseEndpoint { databaseId, transferDto, principal); final Database database = databaseService.findById(containerId, databaseId); final User user = userService.findByUsername(principal.getName()); - if (!database.getOwner().getId().equals(user.getId())) { + if (!database.getOwner().equals(user)) { log.error("Failed to create database: not owner"); throw new NotAllowedException(("Failed to create database: not owner")); } @@ -274,7 +274,7 @@ public class DatabaseEndpoint { log.debug("endpoint find database, containerId={}, databaseId={}", containerId, databaseId); final Database database = databaseService.findById(containerId, databaseId); final DatabaseDto dto = databaseMapper.databaseToDatabaseDto(database); - if (principal != null && database.getOwner().getUsername().equals(principal.getName())) { + if (principal != null && database.getOwner().equals(principal)) { /* only owner sees the access rights */ // TODO improve this by proper mapping final List<DatabaseAccess> accesses = accessService.list(databaseId); dto.setAccesses(accesses.stream() diff --git a/dbrepo-database-service/services/src/main/java/at/tuwien/mapper/IdentifierMapper.java b/dbrepo-database-service/services/src/main/java/at/tuwien/mapper/IdentifierMapper.java index c390464c5e..86a2ab27e3 100644 --- a/dbrepo-database-service/services/src/main/java/at/tuwien/mapper/IdentifierMapper.java +++ b/dbrepo-database-service/services/src/main/java/at/tuwien/mapper/IdentifierMapper.java @@ -5,7 +5,6 @@ import at.tuwien.api.identifier.IdentifierDto; import at.tuwien.entities.identifier.Identifier; import org.mapstruct.Mapper; - @Mapper(componentModel = "spring") public interface IdentifierMapper { diff --git a/dbrepo-database-service/services/src/main/java/at/tuwien/service/impl/MariaDbServiceImpl.java b/dbrepo-database-service/services/src/main/java/at/tuwien/service/impl/MariaDbServiceImpl.java index 75b54f4fe7..69b821408c 100644 --- a/dbrepo-database-service/services/src/main/java/at/tuwien/service/impl/MariaDbServiceImpl.java +++ b/dbrepo-database-service/services/src/main/java/at/tuwien/service/impl/MariaDbServiceImpl.java @@ -133,8 +133,9 @@ public class MariaDbServiceImpl extends HibernateConnector implements DatabaseSe database.setId(containerId); database.setContainer(container); final User owner = userService.findByUsername(principal.getName()); - database.setCreator(owner); - database.setOwner(owner); + database.setOwnedBy(owner.getId()); + database.setCreatedBy(owner.getId()); + database.setContactPerson(owner.getId()); database.setExchangeName("dbrepo." + database.getInternalName()); final ComboPooledDataSource dataSource = getDataSource(container.getImage(), container, root); try { @@ -185,7 +186,7 @@ public class MariaDbServiceImpl extends HibernateConnector implements DatabaseSe final Database entity = findById(containerId, databaseId); final User user = userService.findByUsername(transferDto.getUsername()); /* update in metadata database */ - entity.setOwner(user); + entity.setOwnedBy(user.getId()); databaseIdxRepository.save(databaseMapper.databaseToDatabaseDto(entity)); log.info("Updated database in elastic search with id {}", entity.getId()); return entity; diff --git a/dbrepo-identifier-service/rest-service/src/main/java/at/tuwien/endpoints/IdentifierEndpoint.java b/dbrepo-identifier-service/rest-service/src/main/java/at/tuwien/endpoints/IdentifierEndpoint.java index fab253577a..f92574b85f 100644 --- a/dbrepo-identifier-service/rest-service/src/main/java/at/tuwien/endpoints/IdentifierEndpoint.java +++ b/dbrepo-identifier-service/rest-service/src/main/java/at/tuwien/endpoints/IdentifierEndpoint.java @@ -174,7 +174,7 @@ public class IdentifierEndpoint { }) public ResponseEntity<IdentifierDto> update(@NotNull @PathVariable("id") Long id, @NotNull @Valid @RequestBody IdentifierDto data) - throws IdentifierPublishingNotAllowedException, IdentifierNotFoundException, IdentifierRequestException { + throws IdentifierNotFoundException, IdentifierRequestException { log.debug("endpoint update identifier, id={}, data={}", id, data); final Identifier identifier = identifierService.update(id, data); return ResponseEntity.accepted() diff --git a/dbrepo-identifier-service/services/src/main/java/at/tuwien/service/impl/IdentifierServiceImpl.java b/dbrepo-identifier-service/services/src/main/java/at/tuwien/service/impl/IdentifierServiceImpl.java index f33ff8911b..f5a94274b6 100644 --- a/dbrepo-identifier-service/services/src/main/java/at/tuwien/service/impl/IdentifierServiceImpl.java +++ b/dbrepo-identifier-service/services/src/main/java/at/tuwien/service/impl/IdentifierServiceImpl.java @@ -116,7 +116,7 @@ public class IdentifierServiceImpl implements IdentifierService { tmp.setContainerId(data.getCid()); tmp.setDatabaseId(data.getDbid()); final User creator = userService.findByUsername(principal.getName()); - tmp.setCreator(creator); + tmp.setCreatedBy(creator.getId()); tmp.setCreators(List.of()); if (data.getType().equals(IdentifierTypeDto.SUBSET)) { log.debug("identifier describes a subset"); @@ -136,7 +136,7 @@ public class IdentifierServiceImpl implements IdentifierService { .map(c -> { final Creator creatorDto = identifierMapper.creatorCreateDtoToCreator(c); creatorDto.setPid(entity.getId()); - creatorDto.setCreator(creator); + creatorDto.setCreatedBy(creator.getId()); return creatorDto; }) .collect(Collectors.toList())); @@ -146,7 +146,7 @@ public class IdentifierServiceImpl implements IdentifierService { .forEach(r -> { final RelatedIdentifier id = identifierMapper.relatedIdentifierCreateDtoToRelatedIdentifier(r); id.setIid(entity.getId()); - id.setCreator(creator); + id.setCreatedBy(creator.getId()); final RelatedIdentifier relatedIdentifier = relatedIdentifierRepository.save(id); log.debug("identifier add related with id {}", relatedIdentifier.getId()); entity.getRelated().add(relatedIdentifier); diff --git a/dbrepo-metadata-db/api/src/main/java/at/tuwien/api/database/ViewBriefDto.java b/dbrepo-metadata-db/api/src/main/java/at/tuwien/api/database/ViewBriefDto.java index ab1c9766c2..ee656d297b 100644 --- a/dbrepo-metadata-db/api/src/main/java/at/tuwien/api/database/ViewBriefDto.java +++ b/dbrepo-metadata-db/api/src/main/java/at/tuwien/api/database/ViewBriefDto.java @@ -10,6 +10,7 @@ import lombok.*; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import java.time.Instant; +import java.util.UUID; @Getter @Setter @@ -52,7 +53,7 @@ public class ViewBriefDto { private Instant created; @JsonIgnore - private String createdBy; + private UUID createdBy; @NotNull private UserDto creator; diff --git a/dbrepo-metadata-db/api/src/main/java/at/tuwien/api/database/ViewDto.java b/dbrepo-metadata-db/api/src/main/java/at/tuwien/api/database/ViewDto.java index 3a7e78863f..867e83e771 100644 --- a/dbrepo-metadata-db/api/src/main/java/at/tuwien/api/database/ViewDto.java +++ b/dbrepo-metadata-db/api/src/main/java/at/tuwien/api/database/ViewDto.java @@ -11,6 +11,7 @@ import org.springframework.data.elasticsearch.annotations.Document; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import java.time.Instant; +import java.util.UUID; @Getter @Setter @@ -57,7 +58,7 @@ public class ViewDto { private Instant created; @JsonIgnore - private String createdBy; + private UUID createdBy; @NotNull private UserDto creator; diff --git a/dbrepo-metadata-db/api/src/main/java/at/tuwien/api/database/query/QueryBriefDto.java b/dbrepo-metadata-db/api/src/main/java/at/tuwien/api/database/query/QueryBriefDto.java index 895bf93ab0..3f641f1a1c 100644 --- a/dbrepo-metadata-db/api/src/main/java/at/tuwien/api/database/query/QueryBriefDto.java +++ b/dbrepo-metadata-db/api/src/main/java/at/tuwien/api/database/query/QueryBriefDto.java @@ -13,6 +13,7 @@ import lombok.*; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import java.time.Instant; +import java.util.UUID; @Getter @@ -35,7 +36,7 @@ public class QueryBriefDto { @JsonIgnore @NotNull(message = "created by is required") - private String createdBy; + private UUID createdBy; @NotNull(message = "creator is required") private UserDto creator; diff --git a/dbrepo-metadata-db/api/src/main/java/at/tuwien/api/database/query/QueryDto.java b/dbrepo-metadata-db/api/src/main/java/at/tuwien/api/database/query/QueryDto.java index d35bb51d7c..db5cb11fb7 100644 --- a/dbrepo-metadata-db/api/src/main/java/at/tuwien/api/database/query/QueryDto.java +++ b/dbrepo-metadata-db/api/src/main/java/at/tuwien/api/database/query/QueryDto.java @@ -5,15 +5,13 @@ import at.tuwien.api.user.UserDto; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; -import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; -import javax.persistence.EnumType; -import javax.persistence.Enumerated; import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotNull; import java.time.Instant; +import java.util.UUID; @Getter @@ -37,7 +35,7 @@ public class QueryDto { @JsonIgnore @EqualsAndHashCode.Exclude @NotNull(message = "created by is required") - private String createdBy; + private UUID createdBy; @NotNull(message = "creator is required") private UserDto creator; diff --git a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/container/Container.java b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/container/Container.java index b429c943a8..9fb7d40bbf 100644 --- a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/container/Container.java +++ b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/container/Container.java @@ -6,12 +6,14 @@ import at.tuwien.entities.user.User; import com.github.dockerjava.api.model.HealthCheck; import lombok.*; import org.hibernate.annotations.GenericGenerator; +import org.hibernate.annotations.Type; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; import javax.persistence.*; import java.time.Instant; +import java.util.UUID; @Data @Entity @@ -31,15 +33,25 @@ public class Container { @Column(updatable = false, nullable = false) private Long id; + @ToString.Exclude + @Column(name = "createdBy", nullable = false, columnDefinition = "VARCHAR(36)") + @Type(type = "uuid-char") + private UUID createdBy; + @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) @JoinColumns({ - @JoinColumn(name = "createdBy", referencedColumnName = "ID") + @JoinColumn(name = "createdBy", referencedColumnName = "ID", insertable = false, updatable = false) }) private User creator; + @ToString.Exclude + @Column(name = "ownedBy", nullable = false, columnDefinition = "VARCHAR(36)") + @Type(type = "uuid-char") + private UUID ownedBy; + @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) @JoinColumns({ - @JoinColumn(name = "ownedBy", referencedColumnName = "ID") + @JoinColumn(name = "ownedBy", referencedColumnName = "ID", insertable = false, updatable = false) }) private User owner; diff --git a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/database/Database.java b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/database/Database.java index 9615cbae1d..c02cf1a3ca 100644 --- a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/database/Database.java +++ b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/database/Database.java @@ -16,6 +16,7 @@ import javax.persistence.Entity; import java.io.Serializable; import java.time.Instant; import java.util.List; +import java.util.UUID; @Data @Entity @@ -34,15 +35,26 @@ public class Database implements Serializable { @Column(updatable = false, nullable = false) private Long id; + @ToString.Exclude + @Column(name = "created_by", nullable = false, columnDefinition = "VARCHAR(36)") + @Type(type = "uuid-char") + private UUID createdBy; + + @Type(type = "uuid-char") @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) @JoinColumns({ - @JoinColumn(name = "created_by", referencedColumnName = "ID") + @JoinColumn(name = "created_by", referencedColumnName = "ID", insertable = false, updatable = false) }) private User creator; - @ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL) + @ToString.Exclude + @Column(name = "owned_by", nullable = false, columnDefinition = "VARCHAR(36)") + @Type(type = "uuid-char") + private UUID ownedBy; + + @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) @JoinColumns({ - @JoinColumn(name = "owned_by", referencedColumnName = "ID") + @JoinColumn(name = "owned_by", referencedColumnName = "ID", insertable = false, updatable = false) }) private User owner; @@ -66,9 +78,15 @@ public class Database implements Serializable { @Column(columnDefinition = "TEXT") private String description; + @ToString.Exclude + @Column(name = "contact_person", nullable = false, columnDefinition = "VARCHAR(36)") + @Type(type = "uuid-char") + private UUID contactPerson; + + @Type(type = "uuid-char") @ManyToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL) @JoinColumns({ - @JoinColumn(name = "contact_person", referencedColumnName = "ID") + @JoinColumn(name = "contact_person", referencedColumnName = "ID", updatable = false, insertable = false) }) private User contact; diff --git a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/database/DatabaseAccess.java b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/database/DatabaseAccess.java index 5f6e684785..19d71711fe 100644 --- a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/database/DatabaseAccess.java +++ b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/database/DatabaseAccess.java @@ -2,6 +2,7 @@ package at.tuwien.entities.database; import at.tuwien.entities.user.User; import lombok.*; +import org.hibernate.annotations.Type; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; @@ -21,6 +22,7 @@ import java.util.UUID; public class DatabaseAccess { @Id + @Type(type = "uuid-char") @EqualsAndHashCode.Include @Column(name = "user_id", updatable = false, columnDefinition = "VARCHAR(36)") private UUID huserid; diff --git a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/database/View.java b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/database/View.java index 16fd29e30d..90cca36bed 100644 --- a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/database/View.java +++ b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/database/View.java @@ -5,6 +5,7 @@ import at.tuwien.entities.user.User; import lombok.*; import net.sf.jsqlparser.statement.select.FromItem; import org.hibernate.annotations.GenericGenerator; +import org.hibernate.annotations.Type; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.elasticsearch.annotations.Document; @@ -13,6 +14,7 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener; import javax.persistence.*; import java.time.Instant; import java.util.List; +import java.util.UUID; @Data @Entity @@ -40,9 +42,14 @@ public class View { @EqualsAndHashCode.Include private Long vdbid; + @ToString.Exclude + @Column(name = "createdBy", nullable = false, columnDefinition = "VARCHAR(36)") + @Type(type = "uuid-char") + private UUID createdBy; + @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) @JoinColumns({ - @JoinColumn(name = "createdBy", referencedColumnName = "ID") + @JoinColumn(name = "createdBy", referencedColumnName = "ID", insertable = false, updatable = false) }) private User creator; diff --git a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/database/table/Table.java b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/database/table/Table.java index 0840dca2e7..6b9ee532fc 100644 --- a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/database/table/Table.java +++ b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/database/table/Table.java @@ -7,6 +7,7 @@ import at.tuwien.entities.user.User; import lombok.*; import net.sf.jsqlparser.statement.select.FromItem; import org.hibernate.annotations.GenericGenerator; +import org.hibernate.annotations.Type; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.elasticsearch.annotations.Document; @@ -41,9 +42,14 @@ public class Table { @EqualsAndHashCode.Include private Long tdbid; + @ToString.Exclude + @Column(name = "createdBy", nullable = false, columnDefinition = "VARCHAR(36)") + @Type(type = "uuid-char") + private UUID createdBy; + @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) @JoinColumns({ - @JoinColumn(name = "createdBy", referencedColumnName = "ID", columnDefinition = "VARCHAR(36)") + @JoinColumn(name = "createdBy", referencedColumnName = "ID", updatable = false, insertable = false) }) private User creator; diff --git a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumn.java b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumn.java index 871070728e..1c95089830 100644 --- a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumn.java +++ b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumn.java @@ -6,6 +6,7 @@ import at.tuwien.entities.user.User; import lombok.*; import net.sf.jsqlparser.statement.select.SelectItem; import org.hibernate.annotations.GenericGenerator; +import org.hibernate.annotations.Type; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; @@ -13,6 +14,7 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener; import javax.persistence.*; import java.time.Instant; import java.util.List; +import java.util.UUID; @Data @Entity @@ -58,9 +60,14 @@ public class TableColumn implements Comparable<TableColumn> { }) private Table table; + @ToString.Exclude + @Column(name = "createdBy", nullable = false, columnDefinition = "VARCHAR(36)") + @Type(type = "uuid-char") + private UUID createdBy; + @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) @JoinColumns({ - @JoinColumn(name = "createdBy", referencedColumnName = "ID") + @JoinColumn(name = "createdBy", referencedColumnName = "ID", insertable = false, updatable = false) }) private User creator; diff --git a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/Creator.java b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/Creator.java index 51492e8ba5..2b0a720cb7 100644 --- a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/Creator.java +++ b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/Creator.java @@ -3,12 +3,14 @@ package at.tuwien.entities.identifier; import at.tuwien.entities.user.User; import lombok.*; import org.hibernate.annotations.GenericGenerator; +import org.hibernate.annotations.Type; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; import javax.persistence.*; import java.time.Instant; +import java.util.UUID; @Data @Entity @@ -54,9 +56,14 @@ public class Creator { @CreatedDate private Instant created; + @ToString.Exclude + @Column(name = "createdBy", nullable = false, columnDefinition = "VARCHAR(36)") + @Type(type = "uuid-char") + private UUID createdBy; + @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) @JoinColumns({ - @JoinColumn(name = "createdBy", referencedColumnName = "ID") + @JoinColumn(name = "createdBy", referencedColumnName = "ID", insertable = false, updatable = false) }) private User creator; diff --git a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/Identifier.java b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/Identifier.java index fb857a53db..66a68c8ff7 100644 --- a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/Identifier.java +++ b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/Identifier.java @@ -6,6 +6,7 @@ import at.tuwien.entities.database.License; import at.tuwien.entities.user.User; import lombok.*; import org.hibernate.annotations.GenericGenerator; +import org.hibernate.annotations.Type; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; @@ -15,6 +16,7 @@ import javax.validation.constraints.NotBlank; import java.io.Serializable; import java.time.Instant; import java.util.List; +import java.util.UUID; @Data @Entity @@ -44,9 +46,14 @@ public class Identifier implements Serializable { @Column(name = "qid") private Long queryId; + @ToString.Exclude + @Column(name = "createdBy", nullable = false, columnDefinition = "VARCHAR(36)") + @Type(type = "uuid-char") + private UUID createdBy; + @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.MERGE) @JoinColumns({ - @JoinColumn(name = "createdBy", referencedColumnName = "ID") + @JoinColumn(name = "createdBy", referencedColumnName = "ID", insertable = false, updatable = false) }) private User creator; diff --git a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/RelatedIdentifier.java b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/RelatedIdentifier.java index 9cb1c0ad1e..aed2577656 100644 --- a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/RelatedIdentifier.java +++ b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/RelatedIdentifier.java @@ -4,6 +4,7 @@ import at.tuwien.entities.user.User; import lombok.*; import org.hibernate.annotations.GenericGenerator; import org.hibernate.annotations.SQLDelete; +import org.hibernate.annotations.Type; import org.hibernate.annotations.Where; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedDate; @@ -11,6 +12,7 @@ import org.springframework.data.jpa.domain.support.AuditingEntityListener; import javax.persistence.*; import java.time.Instant; +import java.util.UUID; @Data @Entity @@ -48,9 +50,14 @@ public class RelatedIdentifier { @Enumerated(EnumType.STRING) private RelationType relation; + @ToString.Exclude + @Column(name = "created_by", nullable = false, columnDefinition = "VARCHAR(36)") + @Type(type = "uuid-char") + private UUID createdBy; + @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL) @JoinColumns({ - @JoinColumn(name = "created_by", referencedColumnName = "ID") + @JoinColumn(name = "created_by", referencedColumnName = "ID", insertable = false, updatable = false) }) private User creator; diff --git a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/user/Credential.java b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/user/Credential.java index a422eed5e9..85dafd353d 100644 --- a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/user/Credential.java +++ b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/user/Credential.java @@ -2,6 +2,7 @@ package at.tuwien.entities.user; import lombok.*; import org.hibernate.annotations.GenericGenerator; +import org.hibernate.annotations.Type; import org.springframework.data.jpa.domain.support.AuditingEntityListener; import javax.persistence.*; @@ -21,12 +22,14 @@ public class Credential { @Id @EqualsAndHashCode.Include @Column(name = "ID", nullable = false, columnDefinition = "VARCHAR(36)") + @Type(type = "uuid-char") private UUID id; @Column(nullable = false) private String type; @Column(name = "user_id", nullable = false, columnDefinition = "VARCHAR(36)") + @Type(type = "uuid-char") private UUID userId; @Column(nullable = false) diff --git a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/user/Realm.java b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/user/Realm.java index 96ba2ec661..3890974c2e 100644 --- a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/user/Realm.java +++ b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/user/Realm.java @@ -2,6 +2,8 @@ package at.tuwien.entities.user; import lombok.*; import org.hibernate.annotations.GenericGenerator; +import org.hibernate.annotations.Immutable; +import org.hibernate.annotations.Type; import javax.persistence.*; import java.util.List; @@ -13,6 +15,7 @@ import java.util.UUID; @AllArgsConstructor @NoArgsConstructor @ToString +@Immutable @EqualsAndHashCode(onlyExplicitlyIncluded = true) @Table(name = "realm") @NamedQueries({ @@ -23,6 +26,7 @@ public class Realm { @Id @EqualsAndHashCode.Include @Column(name = "ID", nullable = false, columnDefinition = "VARCHAR(36)") + @Type(type = "uuid-char") private UUID id; @Column(nullable = false) diff --git a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/user/Role.java b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/user/Role.java index 5d25bce86b..a06563f1d6 100644 --- a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/user/Role.java +++ b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/user/Role.java @@ -2,6 +2,8 @@ package at.tuwien.entities.user; import lombok.*; import org.hibernate.annotations.GenericGenerator; +import org.hibernate.annotations.Immutable; +import org.hibernate.annotations.Type; import org.springframework.data.jpa.domain.support.AuditingEntityListener; import javax.persistence.*; @@ -13,6 +15,7 @@ import java.util.UUID; @AllArgsConstructor @NoArgsConstructor @ToString +@Immutable @EntityListeners(AuditingEntityListener.class) @EqualsAndHashCode(onlyExplicitlyIncluded = true) @Table(name = "keycloak_role") @@ -21,6 +24,7 @@ public class Role { @Id @EqualsAndHashCode.Include @Column(name = "ID", nullable = false, columnDefinition = "VARCHAR(36)") + @Type(type = "uuid-char") private UUID id; @Column(name = "NAME", nullable = false) diff --git a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/user/RoleMapping.java b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/user/RoleMapping.java index 7317453872..19b46e3307 100644 --- a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/user/RoleMapping.java +++ b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/user/RoleMapping.java @@ -1,6 +1,7 @@ package at.tuwien.entities.user; import lombok.*; +import org.hibernate.annotations.Type; import org.springframework.data.jpa.domain.support.AuditingEntityListener; import javax.persistence.*; @@ -21,11 +22,13 @@ public class RoleMapping { @Id @EqualsAndHashCode.Include @Column(name = "USER_ID", nullable = false, columnDefinition = "VARCHAR(36)") + @Type(type = "uuid-char") private UUID userId; @Id @EqualsAndHashCode.Include @Column(name = "ROLE_ID", nullable = false, columnDefinition = "VARCHAR(36)") + @Type(type = "uuid-char") private UUID roleId; } diff --git a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/user/User.java b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/user/User.java index b4469d77bf..9325962eac 100644 --- a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/user/User.java +++ b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/user/User.java @@ -5,9 +5,12 @@ import at.tuwien.entities.database.Database; import at.tuwien.entities.identifier.Identifier; import lombok.*; import org.hibernate.annotations.GenericGenerator; +import org.hibernate.annotations.Type; import org.springframework.data.jpa.domain.support.AuditingEntityListener; +import org.springframework.security.core.Authentication; import javax.persistence.*; +import java.security.Principal; import java.util.List; import java.util.UUID; @@ -24,15 +27,16 @@ import java.util.UUID; @UniqueConstraint(columnNames = {"REALM_ID", "USERNAME"}) }) @NamedQueries({ - @NamedQuery(name = "User.findAll", query = "select u from User u join Realm r on r.name = 'dbrepo'"), - @NamedQuery(name = "User.findById", query = "select u from User u join Realm r on r.name = 'dbrepo' and u.id = ?1"), - @NamedQuery(name = "User.findByUsername", query = "select u from User u join Realm r on r.name = 'dbrepo' and u.username = ?1") + @NamedQuery(name = "User.findAll", query = "select u from User u join Realm r on r.name = 'dbrepo' and u.enabled = true"), + @NamedQuery(name = "User.findById", query = "select u from User u join Realm r on r.name = 'dbrepo' and u.id = ?1 and u.enabled = true"), + @NamedQuery(name = "User.findByUsername", query = "select u from User u join Realm r on r.name = 'dbrepo' and u.username = ?1 and u.enabled = true") }) public class User { @Id @EqualsAndHashCode.Include @Column(name = "ID", nullable = false, columnDefinition = "VARCHAR(36)") + @Type(type = "uuid-char") private UUID id; @Column(nullable = false) @@ -45,6 +49,7 @@ public class User { private String lastname; @Column(name = "REALM_ID", columnDefinition = "VARCHAR(36)") + @Type(type = "uuid-char") private UUID realmId; @Column(nullable = false) @@ -99,4 +104,34 @@ public class User { @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "creator") private List<at.tuwien.entities.database.table.Table> tables; + /** + * Compares if the user instance equals with another instance by the principal. + * + * @param principal The user principal. + * @return True if the user are equal, false otherwise. + */ + public boolean equals(Principal principal) { + if (principal == null) { + return false; + } + return this.username.equals(principal.getName()); + } + + /** + * Compares the user principal and checks if a certain role is present. + * + * @param principal The user principal. + * @param role The role. + * @return True if the role is present, false otherwise. + */ + public static boolean hasRole(Principal principal, String role) { + if (principal == null || role == null) { + return false; + } + final Authentication authentication = (Authentication) principal; + return authentication.getAuthorities() + .stream() + .anyMatch(a -> a.getAuthority().equals(role)); + } + } diff --git a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/user/UserAttribute.java b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/user/UserAttribute.java index 976fc09f81..bbc19e8ef8 100644 --- a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/user/UserAttribute.java +++ b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/user/UserAttribute.java @@ -2,6 +2,7 @@ package at.tuwien.entities.user; import lombok.*; import org.hibernate.annotations.GenericGenerator; +import org.hibernate.annotations.Type; import org.springframework.data.jpa.domain.support.AuditingEntityListener; import javax.persistence.*; @@ -21,10 +22,12 @@ public class UserAttribute { @Id @EqualsAndHashCode.Include @Column(name = "ID", nullable = false, columnDefinition = "VARCHAR(36)") + @Type(type = "uuid-char") private UUID id; @ToString.Exclude @Column(name = "USER_ID", nullable = false, columnDefinition = "VARCHAR(36)") + @Type(type = "uuid-char") private UUID userId; @Column(name = "NAME", nullable = false) diff --git a/dbrepo-metadata-db/test/src/main/java/at/tuwien/test/BaseTest.java b/dbrepo-metadata-db/test/src/main/java/at/tuwien/test/BaseTest.java index 64137ee49a..db3137f986 100644 --- a/dbrepo-metadata-db/test/src/main/java/at/tuwien/test/BaseTest.java +++ b/dbrepo-metadata-db/test/src/main/java/at/tuwien/test/BaseTest.java @@ -2170,7 +2170,7 @@ public abstract class BaseTest { .resultHash(QUERY_1_RESULT_HASH) .created(QUERY_1_CREATED) .execution(QUERY_1_EXECUTION) - .createdBy(USER_1_ID.toString()) + .createdBy(USER_1_ID) .creator(USER_1_DTO) .build(); @@ -2183,7 +2183,7 @@ public abstract class BaseTest { .resultHash(QUERY_1_RESULT_HASH) .created(QUERY_1_CREATED) .execution(QUERY_1_EXECUTION) - .createdBy(USER_1_ID.toString()) + .createdBy(USER_1_ID) .creator(USER_1_DTO) .build(); diff --git a/dbrepo-query-service/rest-service/src/main/java/at/tuwien/endpoint/ExportEndpoint.java b/dbrepo-query-service/rest-service/src/main/java/at/tuwien/endpoint/ExportEndpoint.java index f9a5a4f620..8e683d4348 100644 --- a/dbrepo-query-service/rest-service/src/main/java/at/tuwien/endpoint/ExportEndpoint.java +++ b/dbrepo-query-service/rest-service/src/main/java/at/tuwien/endpoint/ExportEndpoint.java @@ -2,6 +2,7 @@ package at.tuwien.endpoint; import at.tuwien.ExportResource; import at.tuwien.entities.database.Database; +import at.tuwien.entities.user.User; import at.tuwien.exception.*; import at.tuwien.service.*; import io.micrometer.core.annotation.Timed; @@ -55,8 +56,7 @@ public class ExportEndpoint { log.error("Failed to export private table: principal is null"); throw new NotAllowedException("Failed to export private table: principal is null"); } - final Authentication authentication = (Authentication) principal; - if (authentication.getAuthorities().stream().noneMatch(a -> a.getAuthority().equals("export-table-data"))) { + if (!User.hasRole(principal, "export-table-data")) { log.error("Failed to export private table: role missing"); throw new NotAllowedException("Failed to export private table: role missing"); } diff --git a/dbrepo-query-service/rest-service/src/main/java/at/tuwien/endpoint/QueryEndpoint.java b/dbrepo-query-service/rest-service/src/main/java/at/tuwien/endpoint/QueryEndpoint.java index 89c871b554..d80b31df72 100644 --- a/dbrepo-query-service/rest-service/src/main/java/at/tuwien/endpoint/QueryEndpoint.java +++ b/dbrepo-query-service/rest-service/src/main/java/at/tuwien/endpoint/QueryEndpoint.java @@ -4,6 +4,7 @@ import at.tuwien.ExportResource; import at.tuwien.SortType; import at.tuwien.api.database.query.*; import at.tuwien.entities.database.Database; +import at.tuwien.entities.user.User; import at.tuwien.querystore.Query; import at.tuwien.exception.*; import at.tuwien.service.*; @@ -114,8 +115,7 @@ public class QueryEndpoint { log.error("Failed to re-execute private query: principal is null"); throw new NotAllowedException("Failed to re-execute private query: principal is null"); } - final Authentication authentication = (Authentication) principal; - if (authentication.getAuthorities().stream().noneMatch(a -> a.getAuthority().equals("re-execute-query"))) { + if (!User.hasRole(principal, "re-execute-query")) { log.error("Failed to re-execute private query: role missing"); throw new NotAllowedException("Failed to re-execute private query: role missing"); } @@ -149,8 +149,7 @@ public class QueryEndpoint { log.error("Failed to re-execute private query: principal is null"); throw new NotAllowedException("Failed to re-execute private query: principal is null"); } - final Authentication authentication = (Authentication) principal; - if (authentication.getAuthorities().stream().noneMatch(a -> a.getAuthority().equals("re-execute-query"))) { + if (!User.hasRole(principal, "re-execute-query")) { log.error("Failed to re-execute private query: role missing"); throw new NotAllowedException("Failed to re-execute private query: role missing"); } @@ -183,8 +182,7 @@ public class QueryEndpoint { log.error("Failed to export private query: principal is null"); throw new NotAllowedException("Failed to export private query: principal is null"); } - final Authentication authentication = (Authentication) principal; - if (authentication.getAuthorities().stream().noneMatch(a -> a.getAuthority().equals("export-query-data"))) { + if (!User.hasRole(principal, "export-query-data")) { log.error("Failed to export private query: role missing"); throw new NotAllowedException("Failed to export private query: role missing"); } diff --git a/dbrepo-query-service/rest-service/src/main/java/at/tuwien/endpoint/ViewEndpoint.java b/dbrepo-query-service/rest-service/src/main/java/at/tuwien/endpoint/ViewEndpoint.java index 44ce21e70a..d176b8741b 100644 --- a/dbrepo-query-service/rest-service/src/main/java/at/tuwien/endpoint/ViewEndpoint.java +++ b/dbrepo-query-service/rest-service/src/main/java/at/tuwien/endpoint/ViewEndpoint.java @@ -7,6 +7,7 @@ import at.tuwien.api.database.query.QueryResultDto; import at.tuwien.api.error.ApiErrorDto; import at.tuwien.entities.database.Database; import at.tuwien.entities.database.View; +import at.tuwien.entities.user.User; import at.tuwien.exception.*; import at.tuwien.mapper.ViewMapper; import at.tuwien.service.*; @@ -149,7 +150,7 @@ public class ViewEndpoint { databaseId, data, principal); /* check */ final Database database = databaseService.find(containerId, databaseId); - if (!database.getOwner().getUsername().equals(principal.getName())) { + if (!database.getOwner().equals(principal)) { log.error("Failed to create view: not the database owner"); throw new NotAllowedException("Failed to create view: not the database owner"); } @@ -252,7 +253,7 @@ public class ViewEndpoint { databaseId, viewId, principal); /* check */ final Database database = databaseService.find(containerId, databaseId); - if (!database.getOwner().getUsername().equals(principal.getName())) { + if (!database.getOwner().equals(principal)) { log.error("Failed to delete view: not the database owner"); throw new NotAllowedException("Failed to delete view: not the database owner"); } @@ -341,8 +342,7 @@ public class ViewEndpoint { log.error("Failed to view data of private view: principal is null"); throw new NotAllowedException("Failed to view data of private view: principal is null"); } - final Authentication authentication = (Authentication) principal; - if (authentication.getAuthorities().stream().noneMatch(a -> a.getAuthority().equals("view-database-view-data"))) { + if (!User.hasRole(principal, "view-database-view-data")) { log.error("Failed to view data of private view: role missing"); throw new NotAllowedException("Failed to view data of private view: role missing"); } diff --git a/dbrepo-query-service/services/src/main/java/at/tuwien/mapper/ViewMapper.java b/dbrepo-query-service/services/src/main/java/at/tuwien/mapper/ViewMapper.java index 91fb6bc00c..6cb6d4d77b 100644 --- a/dbrepo-query-service/services/src/main/java/at/tuwien/mapper/ViewMapper.java +++ b/dbrepo-query-service/services/src/main/java/at/tuwien/mapper/ViewMapper.java @@ -40,9 +40,6 @@ public interface ViewMapper { }) ViewDto viewToViewDto(View data); - @Mappings({ - @Mapping(target = "createdBy", expression = "java(data.getCreator().getId().toString())") - }) ViewBriefDto viewToViewBriefDto(View data); default PreparedStatement viewToRawDeleteViewQuery(Connection connection, View view) diff --git a/dbrepo-query-service/services/src/main/java/at/tuwien/service/impl/ViewServiceImpl.java b/dbrepo-query-service/services/src/main/java/at/tuwien/service/impl/ViewServiceImpl.java index 0ab98c4ebe..0bc0916966 100644 --- a/dbrepo-query-service/services/src/main/java/at/tuwien/service/impl/ViewServiceImpl.java +++ b/dbrepo-query-service/services/src/main/java/at/tuwien/service/impl/ViewServiceImpl.java @@ -146,7 +146,7 @@ public class ViewServiceImpl extends HibernateConnector implements ViewService { .vdbid(databaseId) .name(data.getName()) .internalName(viewMapper.nameToInternalName(data.getName())) - .creator(user) + .createdBy(user.getId()) .database(database) .query(data.getQuery()) .isInitialView(false) diff --git a/dbrepo-table-service/services/src/main/java/at/tuwien/mapper/TableMapper.java b/dbrepo-table-service/services/src/main/java/at/tuwien/mapper/TableMapper.java index d12f4c9e43..311067b40c 100644 --- a/dbrepo-table-service/services/src/main/java/at/tuwien/mapper/TableMapper.java +++ b/dbrepo-table-service/services/src/main/java/at/tuwien/mapper/TableMapper.java @@ -208,6 +208,7 @@ public interface TableMapper { @Mapping(source = "table.creator", target = "creator"), @Mapping(source = "table", target = "table"), @Mapping(target = "id", ignore = true), + @Mapping(target = "createdBy", source = "table.createdBy"), @Mapping(target = "autoGenerated", expression = "java(data.getInternalName() == \"id\" && query.getGenerated())"), @Mapping(source = "data.name", target = "name"), @Mapping(source = "data.internalName", target = "internalName"), diff --git a/dbrepo-table-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java b/dbrepo-table-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java index 63a1199483..a6323d6591 100644 --- a/dbrepo-table-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java +++ b/dbrepo-table-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java @@ -172,7 +172,7 @@ public class TableServiceImpl extends HibernateConnector implements TableService tmp.setColumns(List.of()); tmp.setConstraints(null); final User creator = userService.findByUsername(principal.getName()); - tmp.setCreator(creator); + tmp.setCreatedBy(creator.getId()); /* save in metadata database */ final Table entity = tableRepository.save(tmp); entity.setColumns(createDto.getColumns() diff --git a/dbrepo-ui/api/middleware.service.js b/dbrepo-ui/api/middleware.service.js index ffa7bbf2b8..99899ab4aa 100644 --- a/dbrepo-ui/api/middleware.service.js +++ b/dbrepo-ui/api/middleware.service.js @@ -23,16 +23,16 @@ class MiddlewareService { buildQuery (data) { return new Promise((resolve, reject) => { - axios.post('/server-middleware/query/build', data, { headers: { 'Content-Type': 'multipart/form-data' } }) + axios.post('/server-middleware/query/build', data, { headers: { 'Content-Type': 'application/json' } }) .then((response) => { const file = response.data - console.debug('response file', file) + console.debug('response query', file) resolve(file) }) .catch((error) => { const { code, message } = error - console.error('Failed to create database', error) - Vue.$toast.error(`[${code}] Failed to create database: ${message}`) + console.error('Failed to build query', error) + Vue.$toast.error(`[${code}] Failed to build query: ${message}`) reject(error) }) }) diff --git a/dbrepo-ui/components/DBToolbar.vue b/dbrepo-ui/components/DBToolbar.vue index 973d45682b..4ccfbf2b98 100644 --- a/dbrepo-ui/components/DBToolbar.vue +++ b/dbrepo-ui/components/DBToolbar.vue @@ -29,16 +29,16 @@ <v-spacer /> <v-toolbar-title> <v-btn v-if="canImportCsv" class="mr-2 mb-1" :to="`/container/${$route.params.container_id}/database/${$route.params.database_id}/table/import`"> - Import .csv + <v-icon left>mdi-cloud-upload</v-icon> Import .csv </v-btn> <v-btn v-if="canCreateSubset" color="secondary" class="mb-1 white--text" :to="`/container/${$route.params.container_id}/database/${$route.params.database_id}/query/create`"> - Create Subset + <v-icon left>mdi-wrench</v-icon> Create Subset </v-btn> <v-btn v-if="canCreateView" color="secondary" class="ml-2 mr-2 mb-1 white--text" :to="`/container/${$route.params.container_id}/database/${$route.params.database_id}/view/create`"> - Create View + <v-icon left>mdi-view-carousel-outline</v-icon> Create View </v-btn> <v-btn v-if="canCreateTable" color="primary" class="mb-1" :to="`/container/${$route.params.container_id}/database/${$route.params.database_id}/table/create`"> - Create Table + <v-icon left>mdi-table-large-plus</v-icon> Create Table </v-btn> </v-toolbar-title> <template v-slot:extension> diff --git a/dbrepo-ui/components/EMPTY.vue b/dbrepo-ui/components/EMPTY.vue deleted file mode 100644 index f8f6dddfc2..0000000000 --- a/dbrepo-ui/components/EMPTY.vue +++ /dev/null @@ -1,23 +0,0 @@ -<template> - <div> - EMPTY - </div> -</template> - -<script> -export default { - data () { - return { - } - }, - computed: { - }, - mounted () { - }, - methods: { - } -} -</script> - -<style scoped> -</style> diff --git a/dbrepo-ui/components/TableToolbar.vue b/dbrepo-ui/components/TableToolbar.vue index b4006495ac..80a54b2813 100644 --- a/dbrepo-ui/components/TableToolbar.vue +++ b/dbrepo-ui/components/TableToolbar.vue @@ -12,22 +12,22 @@ <v-spacer /> <v-toolbar-title> <v-btn v-if="canAddTuple" class="mr-2 mb-1" @click="addTuple"> - Add + <v-icon left>mdi-plus</v-icon> Add </v-btn> <v-btn v-if="canEditTuple" color="warning" class="mr-2 mb-1 black--text" @click="editTuple"> - Edit + <v-icon left>mdi-pencil</v-icon> Edit </v-btn> <v-btn v-if="canDeleteTuple" color="error" class="mr-2 mb-1" :loading="loadingDelete" @click="deleteItems"> - Delete <span v-if="selection.length > 1"> {{ selection.length }}</span> + <v-icon left>mdi-delete</v-icon> Delete <span v-if="selection.length > 1"> {{ selection.length }}</span> </v-btn> <v-btn v-if="canExecuteQuery" class="mb-1" :to="`/container/${$route.params.container_id}/database/${$route.params.database_id}/query/create?tid=${$route.params.table_id}`" color="secondary"> - Create Subset + <v-icon left>mdi-wrench</v-icon> Create Subset </v-btn> <v-btn v-if="canCreateView" class="ml-2 mb-1" :to="`/container/${$route.params.container_id}/database/${$route.params.database_id}/view/create?tid=${$route.params.table_id}`" color="secondary"> - Create View + <v-icon left>mdi-view-carousel</v-icon> Create View </v-btn> <v-btn v-if="canImportCsv" class="ml-2 mb-1" :to="`/container/${$route.params.container_id}/database/${$route.params.database_id}/table/${$route.params.table_id}/import`"> - Import csv + <v-icon left>mdi-cloud-upload</v-icon> Import .csv </v-btn> </v-toolbar-title> </v-toolbar> diff --git a/dbrepo-ui/pages/container/_container_id/database/_database_id/table/import.vue b/dbrepo-ui/pages/container/_container_id/database/_database_id/table/import.vue index 46fd9bdd58..a5c4f5949c 100644 --- a/dbrepo-ui/pages/container/_container_id/database/_database_id/table/import.vue +++ b/dbrepo-ui/pages/container/_container_id/database/_database_id/table/import.vue @@ -194,8 +194,8 @@ </div> </template> <script> +import { notEmpty, isNonNegativeInteger } from '@/utils' import TableSchema from '@/components/TableSchema' -import { notEmpty, isNonNegativeInteger, isResearcher } from '@/utils' import ContainerService from '@/api/container.service' import TableService from '@/api/table.service' import MiddlewareService from '@/api/middleware.service' @@ -280,12 +280,6 @@ export default { roles () { return this.$store.state.roles }, - isResearcher () { - return isResearcher(this.user) - }, - fileConfig () { - return { headers: { 'Content-Type': 'multipart/form-data' } } - }, validTableName () { if (this.tableCreate.name === null) { return true @@ -387,7 +381,8 @@ export default { }, async loadDateFormats () { this.loading = true - this.dateFormats = await ContainerService.findOne(this.$route.params.container_id).image.date_formats + const res = await ContainerService.findOne(this.$route.params.container_id) + this.dateFormats = await ContainerService.findImage(res.image.id).date_formats this.loading = true }, createTable () { diff --git a/dbrepo-user-service/Dockerfile b/dbrepo-user-service/Dockerfile index 151ebf831c..f4fb17c5e4 100644 --- a/dbrepo-user-service/Dockerfile +++ b/dbrepo-user-service/Dockerfile @@ -1,5 +1,5 @@ ###### FIRST STAGE ###### -FROM fda-metadata-db:latest as dependency +FROM dbrepo-metadata-db:latest as dependency MAINTAINER Martin Weise <martin.weise@tuwien.ac.at> ###### SECOND STAGE ###### diff --git a/dbrepo-user-service/pom.xml b/dbrepo-user-service/pom.xml index 58cfe80e7c..8a5225c3fb 100644 --- a/dbrepo-user-service/pom.xml +++ b/dbrepo-user-service/pom.xml @@ -142,6 +142,12 @@ <version>${project.version}</version> <scope>compile</scope> </dependency> + <dependency> + <groupId>at.tuwien</groupId> + <artifactId>dbrepo-metadata-db-test</artifactId> + <version>${project.version}</version> + <scope>compile</scope> + </dependency> <!-- Testing --> <dependency> <groupId>org.springframework.boot</groupId> diff --git a/dbrepo-user-service/rest-service/src/main/java/at/tuwien/endpoint/UserEndpoint.java b/dbrepo-user-service/rest-service/src/main/java/at/tuwien/endpoint/UserEndpoint.java index 9ee7a22d2d..abee215b1e 100644 --- a/dbrepo-user-service/rest-service/src/main/java/at/tuwien/endpoint/UserEndpoint.java +++ b/dbrepo-user-service/rest-service/src/main/java/at/tuwien/endpoint/UserEndpoint.java @@ -106,7 +106,12 @@ public class UserEndpoint { @NotNull Principal principal) throws UserNotFoundException, ForeignUserException, UserAttributeNotFoundException { log.debug("endpoint modify a user, id={}, data={}, principal={}", id, data, principal); - final UserDto dto = userMapper.userToUserDto(userService.modify(UUID.fromString(id), data, principal)); + final User user = userService.find(UUID.fromString(id)); + if (!user.equals(principal)) { + log.error("Failed to modify user: attempting to modify other user"); + throw new ForeignUserException("Failed to modify user: attempting to modify other user"); + } + final UserDto dto = userMapper.userToUserDto(userService.modify(user.getId(), data, principal)); log.trace("modify user resulted in dto {}", dto); return ResponseEntity.status(HttpStatus.ACCEPTED) .body(dto); @@ -122,8 +127,12 @@ public class UserEndpoint { @NotNull Principal principal) throws UserNotFoundException, ForeignUserException, UserAttributeNotFoundException { log.debug("endpoint modify a user theme, id={}, data={}, principal={}", id, data, principal); - final User user = userService.toggleTheme(UUID.fromString(id), data, principal); - final UserDto dto = userMapper.userToUserDto(user); + final User user = userService.find(UUID.fromString(id)); + if (!user.equals(principal)) { + log.error("Failed to modify user: attempting to modify other user"); + throw new ForeignUserException("Failed to modify user: attempting to modify other user"); + } + final UserDto dto = userMapper.userToUserDto(userService.toggleTheme(user.getId(), data, principal)); log.trace("modify user theme resulted in dto {}", dto); return ResponseEntity.accepted() .body(dto); @@ -139,8 +148,12 @@ public class UserEndpoint { @NotNull Principal principal) throws UserNotFoundException, ForeignUserException { log.debug("endpoint modify a user password, id={}, data={}, principal={}", id, data, principal); - final User user = userService.updatePassword(UUID.fromString(id), data, principal); - final UserDto dto = userMapper.userToUserDto(user); + final User user = userService.find(UUID.fromString(id)); + if (!user.equals(principal)) { + log.error("Failed to modify user: attempting to modify other user"); + throw new ForeignUserException("Failed to modify user: attempting to modify other user"); + } + final UserDto dto = userMapper.userToUserDto(userService.updatePassword(user.getId(), data, principal)); log.trace("updated user password resulted in dto {}", dto); return ResponseEntity.accepted() .body(dto); diff --git a/dbrepo-user-service/rest-service/src/main/resources/application-local.yml b/dbrepo-user-service/rest-service/src/main/resources/application-local.yml index 7254853c65..6a5a1c57f8 100644 --- a/dbrepo-user-service/rest-service/src/main/resources/application-local.yml +++ b/dbrepo-user-service/rest-service/src/main/resources/application-local.yml @@ -20,6 +20,10 @@ spring: time_zone: UTC application: name: user-service + rabbitmq: + host: localhost + username: fda + password: fda cloud: loadbalancer.ribbon.enabled: false management.endpoints.web.exposure.include: health,info,prometheus diff --git a/dbrepo-user-service/rest-service/src/main/resources/application.yml b/dbrepo-user-service/rest-service/src/main/resources/application.yml index 7acd005839..f0606a3bf7 100644 --- a/dbrepo-user-service/rest-service/src/main/resources/application.yml +++ b/dbrepo-user-service/rest-service/src/main/resources/application.yml @@ -20,6 +20,10 @@ spring: time_zone: UTC application: name: user-service + rabbitmq: + host: broker-service + username: "${BROKER_USERNAME}" + password: "${BROKER_PASSWORD}" cloud: loadbalancer.ribbon.enabled: false management.endpoints.web.exposure.include: health,info,prometheus diff --git a/dbrepo-user-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java b/dbrepo-user-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java new file mode 100644 index 0000000000..c5adb93d3d --- /dev/null +++ b/dbrepo-user-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java @@ -0,0 +1,9 @@ +package at.tuwien; + +import at.tuwien.test.BaseTest; +import org.springframework.test.context.TestPropertySource; + +@TestPropertySource(locations = "classpath:application.properties") +public abstract class BaseUnitTest extends BaseTest { + +} \ No newline at end of file diff --git a/dbrepo-user-service/rest-service/src/test/java/at/tuwien/mapper/UserMapperTest.java b/dbrepo-user-service/rest-service/src/test/java/at/tuwien/mapper/UserMapperTest.java new file mode 100644 index 0000000000..613f43e10d --- /dev/null +++ b/dbrepo-user-service/rest-service/src/test/java/at/tuwien/mapper/UserMapperTest.java @@ -0,0 +1,40 @@ +package at.tuwien.mapper; + +import at.tuwien.BaseUnitTest; +import at.tuwien.entities.user.User; +import lombok.extern.log4j.Log4j2; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; + +@Log4j2 +@SpringBootTest +public class UserMapperTest extends BaseUnitTest { + + @Test + public void equals_fails() { + + /* test */ + assertNotEquals(USER_1, USER_2); + } + + @Test + public void equals_identitiy_succeeds() { + + /* test */ + assertEquals(USER_1, USER_1); + } + + @Test + public void equals_similar_succeeds() { + final User tmp = User.builder() + .id(USER_1_ID) + .build(); + + /* test */ + assertEquals(USER_1, tmp); + } + +} diff --git a/dbrepo-user-service/services/src/main/java/at/tuwien/config/GatewayConfig.java b/dbrepo-user-service/services/src/main/java/at/tuwien/config/GatewayConfig.java index 09e0ef8b0f..084171253f 100644 --- a/dbrepo-user-service/services/src/main/java/at/tuwien/config/GatewayConfig.java +++ b/dbrepo-user-service/services/src/main/java/at/tuwien/config/GatewayConfig.java @@ -6,6 +6,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.support.BasicAuthenticationInterceptor; import org.springframework.web.client.RestTemplate; import org.springframework.web.util.DefaultUriBuilderFactory; @@ -16,6 +17,12 @@ public class GatewayConfig { @Value("${fda.gateway.endpoint}") private String gatewayEndpoint; + @Value("${spring.rabbitmq.username}") + private String brokerUsername; + + @Value("${spring.rabbitmq.password}") + private String brokerPassword; + private final AuthenticationMapper authenticationMapper; @Autowired @@ -30,4 +37,13 @@ public class GatewayConfig { restTemplate.getMessageConverters().add(authenticationMapper.mappingJackson2HttpMessageConverter()); return restTemplate; } + + @Bean("brokerRestTemplate") + public RestTemplate brokerRestTemplate() { + final RestTemplate restTemplate = new RestTemplate(); + restTemplate.setUriTemplateHandler(new DefaultUriBuilderFactory(gatewayEndpoint)); + restTemplate.getInterceptors() + .add(new BasicAuthenticationInterceptor(brokerUsername, brokerPassword)); + return restTemplate; + } } diff --git a/dbrepo-user-service/services/src/main/java/at/tuwien/mapper/UserMapper.java b/dbrepo-user-service/services/src/main/java/at/tuwien/mapper/UserMapper.java index 9156ecd0c3..d0ea9d01a2 100644 --- a/dbrepo-user-service/services/src/main/java/at/tuwien/mapper/UserMapper.java +++ b/dbrepo-user-service/services/src/main/java/at/tuwien/mapper/UserMapper.java @@ -15,7 +15,6 @@ import org.springframework.security.core.authority.SimpleGrantedAuthority; import java.util.UUID; - @Mapper(componentModel = "spring") public interface UserMapper { @@ -41,6 +40,7 @@ public interface UserMapper { default UserAttribute tripleToUserAttribute(UUID userId, String name, String value) { return UserAttribute.builder() + .id(UUID.randomUUID()) .userId(userId) .name(name) .value(value) diff --git a/dbrepo-user-service/services/src/main/java/at/tuwien/service/impl/UserServiceImpl.java b/dbrepo-user-service/services/src/main/java/at/tuwien/service/impl/UserServiceImpl.java index 96fceaa61d..e791cc968e 100644 --- a/dbrepo-user-service/services/src/main/java/at/tuwien/service/impl/UserServiceImpl.java +++ b/dbrepo-user-service/services/src/main/java/at/tuwien/service/impl/UserServiceImpl.java @@ -17,6 +17,7 @@ import org.keycloak.common.util.Base64; import org.keycloak.common.util.PaddingUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.PBEKeySpec; @@ -85,6 +86,7 @@ public class UserServiceImpl implements UserService { .append(Base64.encodeBytes(salt)) .append("\",\"additionalParameters\":{}}"); Credential credential = Credential.builder() + .id(UUID.randomUUID()) .createdDate(Instant.now().toEpochMilli()) .secretData(secretData.toString()) .type("password") @@ -93,6 +95,7 @@ public class UserServiceImpl implements UserService { .build(); /* save */ User user = userMapper.signupRequestDtoToUser(data); + user.setId(UUID.randomUUID()); user.setEmailVerified(false); user.setEnabled(true); user.setRealmId(realm.getId()); @@ -171,13 +174,9 @@ public class UserServiceImpl implements UserService { @Override public User toggleTheme(UUID id, UserThemeSetDto data, Principal principal) throws UserNotFoundException, - ForeignUserException, UserAttributeNotFoundException { + UserAttributeNotFoundException { /* check */ final User user = find(id); - if (!user.getUsername().equals(principal.getName())) { - log.error("Failed to modify user: attempting to modify other user"); - throw new ForeignUserException("Failed to modify user: attempting to modify other user"); - } final UserAttribute entity = userAttributeService.update(user.getId(), "theme_dark", data.getThemeDark().toString()); log.info("Updated theme by updating attribute with id {}", entity.getId()); return user; -- GitLab