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>