From 5f4d132c8989fa7272d758f3926dc61e546d0f6a Mon Sep 17 00:00:00 2001
From: Martin Weise <martin.weise@tuwien.ac.at>
Date: Tue, 2 May 2023 22:07:44 +0200
Subject: [PATCH] WIP

- fixed some tests
- needed to refactor some entities
---
 .../dbrepo-realm.json                         |  60 +++---
 .../tuwien/endpoints/IdentifierEndpoint.java  |   4 +-
 .../tuwien/endpoints/PersistenceEndpoint.java |  17 +-
 .../IdentifierEndpointIntegrationTest.java    |  19 +-
 .../endpoint/PersistenceEndpointUnitTest.java |  37 +++-
 .../DataCiteIdentifierServiceUnitTest.java    |  20 +-
 .../IdentifierServiceIntegrationTest.java     |  38 ++--
 .../service/IdentifierServiceUnitTest.java    |  57 +----
 .../at/tuwien/config/IndexInitializer.java    |   2 -
 .../at/tuwien/mapper/IdentifierMapper.java    |  22 +-
 .../at/tuwien/service/IdentifierService.java  |   9 +-
 .../impl/DataCiteIdentifierServiceImpl.java   |  21 +-
 .../service/impl/IdentifierServiceImpl.java   |  43 ++--
 .../api/identifier/IdentifierUpdateDto.java   |  71 +++++++
 .../tuwien/entities/database/table/Table.java |  19 +-
 .../database/table/columns/TableColumn.java   |   9 +-
 .../tuwien/entities/identifier/Creator.java   |   7 +-
 .../entities/identifier/Identifier.java       |  24 +--
 .../identifier/RelatedIdentifier.java         |   7 +-
 .../main/java/at/tuwien/test/BaseTest.java    | 198 +++++++++++-------
 .../TableServiceIntegrationReadTest.java      |   4 +-
 .../TableServiceIntegrationWriteTest.java     |  21 +-
 .../java/at/tuwien/mapper/TableMapper.java    |   1 -
 .../tuwien/service/impl/TableServiceImpl.java |  15 +-
 dbrepo-ui/api/identifier.service.js           |  21 +-
 .../components/dialogs/DeleteIdentifier.vue   |  97 +++++++++
 dbrepo-ui/components/dialogs/Persist.vue      |  91 +++++---
 .../database/_database_id/info.vue            |  72 ++++---
 28 files changed, 624 insertions(+), 382 deletions(-)
 create mode 100644 dbrepo-metadata-db/api/src/main/java/at/tuwien/api/identifier/IdentifierUpdateDto.java
 create mode 100644 dbrepo-ui/components/dialogs/DeleteIdentifier.vue

diff --git a/dbrepo-authentication-service/dbrepo-realm.json b/dbrepo-authentication-service/dbrepo-realm.json
index 64c5e7a690..ea9bf881a2 100644
--- a/dbrepo-authentication-service/dbrepo-realm.json
+++ b/dbrepo-authentication-service/dbrepo-realm.json
@@ -249,14 +249,6 @@
       "clientRole" : false,
       "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0",
       "attributes" : { }
-    }, {
-      "id" : "36e87bdb-ed4c-47a4-a22a-871bc9728061",
-      "name" : "update-foreign-identifier",
-      "description" : "${update-foreign-identifier}",
-      "composite" : false,
-      "clientRole" : false,
-      "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0",
-      "attributes" : { }
     }, {
       "id" : "e14ab76b-1c24-484d-ae2d-478b8457edea",
       "name" : "list-licenses",
@@ -357,7 +349,7 @@
       "description" : "${escalated-identifier-handling}",
       "composite" : true,
       "composites" : {
-        "realm" : [ "update-foreign-identifier", "delete-identifier", "create-foreign-identifier", "modify-identifier-metadata" ]
+        "realm" : [ "delete-identifier", "create-foreign-identifier", "modify-identifier-metadata" ]
       },
       "clientRole" : false,
       "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0",
@@ -916,7 +908,7 @@
   "otpPolicyLookAheadWindow" : 1,
   "otpPolicyPeriod" : 30,
   "otpPolicyCodeReusable" : false,
-  "otpSupportedApplications" : [ "totpAppGoogleName", "totpAppMicrosoftAuthenticatorName", "totpAppFreeOTPName" ],
+  "otpSupportedApplications" : [ "totpAppMicrosoftAuthenticatorName", "totpAppGoogleName", "totpAppFreeOTPName" ],
   "webAuthnPolicyRpEntityName" : "keycloak",
   "webAuthnPolicySignatureAlgorithms" : [ "ES256" ],
   "webAuthnPolicyRpId" : "",
@@ -1906,7 +1898,7 @@
       "subType" : "authenticated",
       "subComponents" : { },
       "config" : {
-        "allowed-protocol-mapper-types" : [ "oidc-usermodel-attribute-mapper", "oidc-full-name-mapper", "saml-user-attribute-mapper", "saml-role-list-mapper", "saml-user-property-mapper", "oidc-usermodel-property-mapper", "oidc-address-mapper", "oidc-sha256-pairwise-sub-mapper" ]
+        "allowed-protocol-mapper-types" : [ "oidc-full-name-mapper", "saml-user-attribute-mapper", "saml-role-list-mapper", "saml-user-property-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-usermodel-attribute-mapper", "oidc-usermodel-property-mapper", "oidc-address-mapper" ]
       }
     }, {
       "id" : "3ab11d74-5e76-408a-b85a-26bf8950f979",
@@ -1915,7 +1907,7 @@
       "subType" : "anonymous",
       "subComponents" : { },
       "config" : {
-        "allowed-protocol-mapper-types" : [ "oidc-usermodel-property-mapper", "saml-role-list-mapper", "oidc-full-name-mapper", "oidc-address-mapper", "saml-user-attribute-mapper", "oidc-sha256-pairwise-sub-mapper", "saml-user-property-mapper", "oidc-usermodel-attribute-mapper" ]
+        "allowed-protocol-mapper-types" : [ "oidc-sha256-pairwise-sub-mapper", "saml-user-property-mapper", "oidc-full-name-mapper", "saml-role-list-mapper", "oidc-usermodel-property-mapper", "saml-user-attribute-mapper", "oidc-usermodel-attribute-mapper", "oidc-address-mapper" ]
       }
     } ],
     "org.keycloak.keys.KeyProvider" : [ {
@@ -1967,7 +1959,7 @@
   "internationalizationEnabled" : false,
   "supportedLocales" : [ ],
   "authenticationFlows" : [ {
-    "id" : "249e062c-149c-41d8-8edc-fff83c7fc496",
+    "id" : "901d9a10-19af-4e4a-9247-0f599f13e7fb",
     "alias" : "Account verification options",
     "description" : "Method with which to verity the existing account",
     "providerId" : "basic-flow",
@@ -1989,7 +1981,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "ff69ba5a-e5a4-4afd-b328-0e7e4775f6b3",
+    "id" : "2b17a070-b094-4b0a-a2a9-3a2af949a21e",
     "alias" : "Authentication Options",
     "description" : "Authentication options.",
     "providerId" : "basic-flow",
@@ -2018,7 +2010,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "6e865e2b-608e-48fb-b743-98df28be1a86",
+    "id" : "de7bed52-8c78-48d5-a4b3-93932613c102",
     "alias" : "Browser - Conditional OTP",
     "description" : "Flow to determine if the OTP is required for the authentication",
     "providerId" : "basic-flow",
@@ -2040,7 +2032,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "c92e182c-7dc1-4ed6-b9e5-42a47740db06",
+    "id" : "9fdcbe8c-2a29-4d72-a4a2-1c78ce40ff82",
     "alias" : "Direct Grant - Conditional OTP",
     "description" : "Flow to determine if the OTP is required for the authentication",
     "providerId" : "basic-flow",
@@ -2062,7 +2054,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "635e2eb2-8392-44ca-b3fe-76e7c7e7abb5",
+    "id" : "38898847-37a8-4e99-a6bf-fba242bec088",
     "alias" : "First broker login - Conditional OTP",
     "description" : "Flow to determine if the OTP is required for the authentication",
     "providerId" : "basic-flow",
@@ -2084,7 +2076,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "852b7951-4abc-4497-ada6-33d73e99b0b5",
+    "id" : "a6130e47-dc21-47e0-ab72-b1ebe2797c01",
     "alias" : "Handle Existing Account",
     "description" : "Handle what to do if there is existing account with same email/username like authenticated identity provider",
     "providerId" : "basic-flow",
@@ -2106,7 +2098,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "ee064caa-6fb5-404e-ae05-6b0c36c7834c",
+    "id" : "f6480693-ec91-4bef-8822-64c43dc819e0",
     "alias" : "Reset - Conditional OTP",
     "description" : "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.",
     "providerId" : "basic-flow",
@@ -2128,7 +2120,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "47769628-1cc9-49ab-bf34-79dc30ce9825",
+    "id" : "6d825b60-c203-4366-811c-7afdfd9a55f5",
     "alias" : "User creation or linking",
     "description" : "Flow for the existing/non-existing user alternatives",
     "providerId" : "basic-flow",
@@ -2151,7 +2143,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "687f20f9-c783-4876-a621-3260377fca2b",
+    "id" : "6c64cf67-ac2c-436d-bb86-01dcdf6cd720",
     "alias" : "Verify Existing Account by Re-authentication",
     "description" : "Reauthentication of existing account",
     "providerId" : "basic-flow",
@@ -2173,7 +2165,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "fd498e51-65ce-4049-84c7-e77da549d480",
+    "id" : "c6f6b53d-d316-4232-ba0f-5a23af03d684",
     "alias" : "browser",
     "description" : "browser based authentication",
     "providerId" : "basic-flow",
@@ -2209,7 +2201,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "d1809c1f-9ccd-424d-9838-27cffa9db66b",
+    "id" : "3fe7bf4c-56da-4751-a1bd-1cd88a5166b4",
     "alias" : "clients",
     "description" : "Base authentication for clients",
     "providerId" : "client-flow",
@@ -2245,7 +2237,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "8c240fe9-e58f-48b7-a158-6e0e6a9d67a6",
+    "id" : "6800db15-413f-4cd1-b97e-21aada87160a",
     "alias" : "direct grant",
     "description" : "OpenID Connect Resource Owner Grant",
     "providerId" : "basic-flow",
@@ -2274,7 +2266,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "35c71a49-4597-4658-bbbd-fd0d54714a40",
+    "id" : "3a324752-6a3e-4ac5-bb2e-740a92a1b39f",
     "alias" : "docker auth",
     "description" : "Used by Docker clients to authenticate against the IDP",
     "providerId" : "basic-flow",
@@ -2289,7 +2281,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "bf40550f-d32e-44ff-8f58-90029ac0d27f",
+    "id" : "fac438f8-81be-4abf-b47f-42f9a7d6a5f3",
     "alias" : "first broker login",
     "description" : "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account",
     "providerId" : "basic-flow",
@@ -2312,7 +2304,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "131b7668-84aa-411a-8653-a572de9f1dc2",
+    "id" : "4fe02d11-0e01-4b0a-8822-893ad191c903",
     "alias" : "forms",
     "description" : "Username, password, otp and other auth forms.",
     "providerId" : "basic-flow",
@@ -2334,7 +2326,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "7ba29293-f649-4078-84de-74a19510797c",
+    "id" : "5ca6cd7c-5bb8-4674-9946-1ed07833a4c2",
     "alias" : "http challenge",
     "description" : "An authentication flow based on challenge-response HTTP Authentication Schemes",
     "providerId" : "basic-flow",
@@ -2356,7 +2348,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "71a1fd3b-1b01-4a8c-b05b-6268b2cc9224",
+    "id" : "29bf7f84-ed23-4a3f-acf3-bb75a560ddbe",
     "alias" : "registration",
     "description" : "registration flow",
     "providerId" : "basic-flow",
@@ -2372,7 +2364,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "5e4a99ff-5621-467f-902a-59efede6ef12",
+    "id" : "39b44736-f873-42c7-ace8-1d6dc598f0e4",
     "alias" : "registration form",
     "description" : "registration form",
     "providerId" : "form-flow",
@@ -2408,7 +2400,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "3450e93e-3fd5-4eb3-9ae6-fac13f8129d5",
+    "id" : "23b1886e-4fff-4616-b579-12aded1625b2",
     "alias" : "reset credentials",
     "description" : "Reset credentials for a user if they forgot their password or something",
     "providerId" : "basic-flow",
@@ -2444,7 +2436,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "27b5c4c4-76e7-49ea-951a-bfdf357886bc",
+    "id" : "dab34786-6f6f-4c06-864e-415d53b60b02",
     "alias" : "saml ecp",
     "description" : "SAML ECP Profile Authentication Flow",
     "providerId" : "basic-flow",
@@ -2460,13 +2452,13 @@
     } ]
   } ],
   "authenticatorConfig" : [ {
-    "id" : "71966a64-76a7-4e1a-b9c7-5f1fbd45e8d0",
+    "id" : "599f9aae-4d0d-44ea-9862-2ce3df15afd4",
     "alias" : "create unique user config",
     "config" : {
       "require.password.update.after.registration" : "false"
     }
   }, {
-    "id" : "1068a85d-838b-47d8-9ca2-4545a7e464a4",
+    "id" : "fedc59c5-7dea-4a40-b605-e0c48c389b6b",
     "alias" : "review profile config",
     "config" : {
       "update.profile.on.first.login" : "missing"
diff --git a/dbrepo-identifier-service/rest-service/src/main/java/at/tuwien/endpoints/IdentifierEndpoint.java b/dbrepo-identifier-service/rest-service/src/main/java/at/tuwien/endpoints/IdentifierEndpoint.java
index 2a05154f3e..356c3d5458 100644
--- a/dbrepo-identifier-service/rest-service/src/main/java/at/tuwien/endpoints/IdentifierEndpoint.java
+++ b/dbrepo-identifier-service/rest-service/src/main/java/at/tuwien/endpoints/IdentifierEndpoint.java
@@ -4,8 +4,6 @@ import at.tuwien.api.error.ApiErrorDto;
 import at.tuwien.api.identifier.IdentifierCreateDto;
 import at.tuwien.api.identifier.IdentifierDto;
 import at.tuwien.api.identifier.IdentifierTypeDto;
-import at.tuwien.entities.database.AccessType;
-import at.tuwien.entities.database.DatabaseAccess;
 import at.tuwien.entities.identifier.Identifier;
 import at.tuwien.entities.user.User;
 import at.tuwien.exception.*;
@@ -135,7 +133,7 @@ public class IdentifierEndpoint {
                                                 @NotNull @RequestHeader(name = "Authorization") String authorization,
                                                 @NotNull Principal principal)
             throws IdentifierAlreadyExistsException, QueryNotFoundException, IdentifierPublishingNotAllowedException,
-            RemoteUnavailableException, UserNotFoundException, DatabaseNotFoundException, IdentifierRequestException, AccessDeniedException, NotAllowedException {
+            RemoteUnavailableException, UserNotFoundException, DatabaseNotFoundException, IdentifierRequestException, NotAllowedException {
         log.debug("endpoint create identifier, data={}, authorization=(hidden), principal={}", data, principal);
         if (data.getType().equals(IdentifierTypeDto.SUBSET) && data.getQid() == null) {
             log.error("Identifier of type subset need to have a qid present");
diff --git a/dbrepo-identifier-service/rest-service/src/main/java/at/tuwien/endpoints/PersistenceEndpoint.java b/dbrepo-identifier-service/rest-service/src/main/java/at/tuwien/endpoints/PersistenceEndpoint.java
index 46660e5664..dd1ab8510f 100644
--- a/dbrepo-identifier-service/rest-service/src/main/java/at/tuwien/endpoints/PersistenceEndpoint.java
+++ b/dbrepo-identifier-service/rest-service/src/main/java/at/tuwien/endpoints/PersistenceEndpoint.java
@@ -3,9 +3,8 @@ package at.tuwien.endpoints;
 import at.tuwien.api.error.ApiErrorDto;
 import at.tuwien.api.identifier.BibliographyTypeDto;
 import at.tuwien.api.identifier.IdentifierDto;
+import at.tuwien.api.identifier.IdentifierUpdateDto;
 import at.tuwien.config.EndpointConfig;
-import at.tuwien.entities.database.AccessType;
-import at.tuwien.entities.database.DatabaseAccess;
 import at.tuwien.entities.identifier.Identifier;
 import at.tuwien.entities.user.User;
 import at.tuwien.exception.*;
@@ -153,7 +152,7 @@ public class PersistenceEndpoint {
     @PutMapping("/{id}")
     @Transactional
     @Timed(value = "identifier.update", description = "Time needed to update an identifier")
-    @PreAuthorize("hasAuthority('update-identifier') or hasAuthority('update-foreign-identifier')")
+    @PreAuthorize("hasAuthority('modify-identifier-metadata')")
     @Operation(summary = "Update some identifier", security = @SecurityRequirement(name = "bearerAuth"))
     @ApiResponses(value = {
             @ApiResponse(responseCode = "202",
@@ -183,7 +182,7 @@ public class PersistenceEndpoint {
                             schema = @Schema(implementation = ApiErrorDto.class))}),
     })
     public ResponseEntity<IdentifierDto> update(@NotNull @PathVariable("id") Long id,
-                                                @NotNull @Valid @RequestBody IdentifierDto data,
+                                                @NotNull @Valid @RequestBody IdentifierUpdateDto data,
                                                 @NotNull Principal principal)
             throws IdentifierNotFoundException, IdentifierRequestException, UserNotFoundException, NotAllowedException {
         log.debug("endpoint update identifier, id={}, data={}", id, data);
@@ -197,6 +196,11 @@ public class PersistenceEndpoint {
                 throw new NotAllowedException("Failed to update identifier: insufficient access");
             }
         }
+        /* check */
+        if (identifier.getDoi() != null && !identifier.getDoi().equals(data.getDoi())) {
+            log.error("Failed to update identifier: once attached the DOI cannot be changed");
+            throw new IdentifierRequestException("Failed to update identifier: once attached the DOI cannot be changed");
+        }
         final IdentifierDto dto = identifierMapper.identifierToIdentifierDto(identifierService.update(id, data));
         log.debug("update identifier resulted in dto={}", dto);
         return ResponseEntity.accepted()
@@ -226,6 +230,11 @@ public class PersistenceEndpoint {
     public ResponseEntity<?> delete(@NotNull @PathVariable("id") Long id)
             throws IdentifierNotFoundException, NotAllowedException {
         log.debug("endpoint delete identifier, id={}", id);
+        final Identifier identifier = identifierService.find(id);
+        if (identifier.getDoi() != null) {
+            log.error("Failed to delete identifier: a DOI is already attached");
+            throw new NotAllowedException("Failed to delete identifier: a DOI is already attached");
+        }
         identifierService.delete(id);
         return ResponseEntity.accepted()
                 .build();
diff --git a/dbrepo-identifier-service/rest-service/src/test/java/at/tuwien/endpoint/IdentifierEndpointIntegrationTest.java b/dbrepo-identifier-service/rest-service/src/test/java/at/tuwien/endpoint/IdentifierEndpointIntegrationTest.java
index 831bf171d5..a3a0191d1a 100644
--- a/dbrepo-identifier-service/rest-service/src/test/java/at/tuwien/endpoint/IdentifierEndpointIntegrationTest.java
+++ b/dbrepo-identifier-service/rest-service/src/test/java/at/tuwien/endpoint/IdentifierEndpointIntegrationTest.java
@@ -6,6 +6,7 @@ import at.tuwien.api.identifier.IdentifierTypeDto;
 import at.tuwien.config.IndexInitializer;
 import at.tuwien.config.ReadyConfig;
 import at.tuwien.endpoints.IdentifierEndpoint;
+import at.tuwien.exception.NotAllowedException;
 import at.tuwien.repository.jpa.*;
 import lombok.extern.log4j.Log4j2;
 import org.junit.jupiter.api.BeforeEach;
@@ -87,7 +88,7 @@ public class IdentifierEndpointIntegrationTest extends BaseUnitTest {
     public void list_hasRole_succeeds() {
 
         /* mock */
-        identifierRepository.save(IDENTIFIER_1_SIMPLE);
+        identifierRepository.save(IDENTIFIER_1);
 
         /* test */
         final List<IdentifierDto> response = this.generic_list(null, null, null);
@@ -103,7 +104,7 @@ public class IdentifierEndpointIntegrationTest extends BaseUnitTest {
     public void list_noRole_succeeds() {
 
         /* mock */
-        identifierRepository.save(IDENTIFIER_1_SIMPLE);
+        identifierRepository.save(IDENTIFIER_1);
 
         /* test */
         final List<IdentifierDto> response = this.generic_list(null, null, null);
@@ -119,7 +120,7 @@ public class IdentifierEndpointIntegrationTest extends BaseUnitTest {
     public void list_databaseId_succeeds() {
 
         /* mock */
-        identifierRepository.save(IDENTIFIER_1_SIMPLE);
+        identifierRepository.save(IDENTIFIER_1);
 
         /* test */
         final List<IdentifierDto> response = this.generic_list(DATABASE_1_ID, null, null);
@@ -139,10 +140,10 @@ public class IdentifierEndpointIntegrationTest extends BaseUnitTest {
         containerRepository.save(CONTAINER_4_SIMPLE);
         databaseRepository.save(DATABASE_3_SIMPLE);
         databaseRepository.save(DATABASE_4_SIMPLE);
-        identifierRepository.save(IDENTIFIER_1_SIMPLE);
-        identifierRepository.save(IDENTIFIER_2_SIMPLE);
-        identifierRepository.save(IDENTIFIER_3_SIMPLE);
-        identifierRepository.save(IDENTIFIER_4_SIMPLE);
+        identifierRepository.save(IDENTIFIER_1);
+        identifierRepository.save(IDENTIFIER_2);
+        identifierRepository.save(IDENTIFIER_3);
+        identifierRepository.save(IDENTIFIER_4);
 
         /* test */
         final List<IdentifierDto> response = this.generic_list(DATABASE_4_ID, null, IdentifierTypeDto.DATABASE);
@@ -158,7 +159,7 @@ public class IdentifierEndpointIntegrationTest extends BaseUnitTest {
     public void list_subsetIdAndType_succeeds() {
 
         /* mock */
-        identifierRepository.save(IDENTIFIER_1_SIMPLE);
+        identifierRepository.save(IDENTIFIER_1);
 
         /* test */
         final List<IdentifierDto> response = this.generic_list(DATABASE_1_ID, QUERY_1_ID, IdentifierTypeDto.SUBSET);
@@ -188,7 +189,7 @@ public class IdentifierEndpointIntegrationTest extends BaseUnitTest {
         databaseRepository.save(DATABASE_3_SIMPLE);
 
         /* test */
-        assertThrows(at.tuwien.exception.AccessDeniedException.class, () -> {
+        assertThrows(NotAllowedException.class, () -> {
             identifierEndpoint.create(IDENTIFIER_3_DTO_REQUEST, "ABC", USER_1_PRINCIPAL);
         });
     }
diff --git a/dbrepo-identifier-service/rest-service/src/test/java/at/tuwien/endpoint/PersistenceEndpointUnitTest.java b/dbrepo-identifier-service/rest-service/src/test/java/at/tuwien/endpoint/PersistenceEndpointUnitTest.java
index d5121f9a49..1b92d61d59 100644
--- a/dbrepo-identifier-service/rest-service/src/test/java/at/tuwien/endpoint/PersistenceEndpointUnitTest.java
+++ b/dbrepo-identifier-service/rest-service/src/test/java/at/tuwien/endpoint/PersistenceEndpointUnitTest.java
@@ -4,14 +4,13 @@ import at.tuwien.BaseUnitTest;
 import at.tuwien.api.identifier.BibliographyTypeDto;
 import at.tuwien.api.identifier.CreatorDto;
 import at.tuwien.api.identifier.IdentifierDto;
+import at.tuwien.api.identifier.IdentifierUpdateDto;
 import at.tuwien.config.IndexInitializer;
 import at.tuwien.config.ReadyConfig;
 import at.tuwien.endpoints.PersistenceEndpoint;
 import at.tuwien.entities.identifier.Identifier;
 import at.tuwien.entities.user.User;
 import at.tuwien.exception.*;
-import at.tuwien.gateway.QueryServiceGateway;
-import at.tuwien.repository.jpa.IdentifierRepository;
 import at.tuwien.service.AccessService;
 import at.tuwien.service.IdentifierService;
 import at.tuwien.service.UserService;
@@ -33,7 +32,6 @@ import org.springframework.core.io.InputStreamResource;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.security.access.AccessDeniedException;
-import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException;
 import org.springframework.security.test.context.support.WithAnonymousUser;
 import org.springframework.security.test.context.support.WithMockUser;
 import org.springframework.test.context.junit.jupiter.SpringExtension;
@@ -530,7 +528,7 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest {
 
         /* test */
         assertThrows(AccessDeniedException.class, () -> {
-            generic_update(IDENTIFIER_3_ID, IDENTIFIER_3, IDENTIFIER_3_DTO, null, null, null);
+            generic_update(IDENTIFIER_3_ID, IDENTIFIER_3, IDENTIFIER_3_DTO_UPDATE_REQUEST, null, null, null);
         });
     }
 
@@ -540,12 +538,12 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest {
 
         /* test */
         assertThrows(org.springframework.security.access.AccessDeniedException.class, () -> {
-            generic_update(IDENTIFIER_3_ID, IDENTIFIER_3, IDENTIFIER_3_DTO, USER_4_USERNAME, USER_4, USER_4_PRINCIPAL);
+            generic_update(IDENTIFIER_3_ID, IDENTIFIER_3, IDENTIFIER_3_DTO_UPDATE_REQUEST, USER_4_USERNAME, USER_4, USER_4_PRINCIPAL);
         });
     }
 
     @Test
-    @WithMockUser(username = USER_3_USERNAME, authorities = {"update-identifier"})
+    @WithMockUser(username = USER_3_USERNAME, authorities = {"modify-identifier-metadata"})
     public void update_hasRoleNoAccess_succeeds() throws at.tuwien.exception.AccessDeniedException {
 
         /* mock */
@@ -555,12 +553,12 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest {
 
         /* test */
         assertThrows(NotAllowedException.class, () -> {
-            generic_update(IDENTIFIER_3_ID, IDENTIFIER_3, IDENTIFIER_3_DTO, USER_3_USERNAME, USER_3, USER_3_PRINCIPAL);
+            generic_update(IDENTIFIER_3_ID, IDENTIFIER_3, IDENTIFIER_3_DTO_UPDATE_REQUEST, USER_3_USERNAME, USER_3, USER_3_PRINCIPAL);
         });
     }
 
     @Test
-    @WithMockUser(username = USER_3_USERNAME, authorities = {"update-identifier"})
+    @WithMockUser(username = USER_3_USERNAME, authorities = {"modify-identifier-metadata"})
     public void update_hasRoleHasAccess_succeeds() throws IdentifierNotFoundException, IdentifierRequestException,
             UserNotFoundException, at.tuwien.exception.AccessDeniedException, NotAllowedException {
 
@@ -569,7 +567,24 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest {
                 .thenReturn(DATABASE_3_DATA_STEWARD_READ_ACCESS);
 
         /* test */
-        generic_update(IDENTIFIER_3_ID, IDENTIFIER_3, IDENTIFIER_3_DTO, USER_3_USERNAME, USER_3, USER_3_PRINCIPAL);
+        generic_update(IDENTIFIER_3_ID, IDENTIFIER_3, IDENTIFIER_3_DTO_UPDATE_REQUEST, USER_3_USERNAME, USER_3, USER_3_PRINCIPAL);
+    }
+
+    @Test
+    @WithMockUser(username = USER_1_USERNAME, authorities = {"modify-identifier-metadata"})
+    public void update_doiChange_fails() throws at.tuwien.exception.AccessDeniedException {
+        final IdentifierUpdateDto request = IdentifierUpdateDto.builder()
+                .doi("10.000/thisisadifferentdoi")
+                .build();
+
+        /* mock */
+        when(accessService.find(IDENTIFIER_1_DATABASE_ID, USER_1_ID))
+                .thenReturn(DATABASE_1_DATA_STEWARD_READ_ACCESS);
+
+        /* test */
+        assertThrows(IdentifierRequestException.class, () -> {
+            generic_update(IDENTIFIER_1_ID, IDENTIFIER_1, request, USER_1_USERNAME, USER_1, USER_1_PRINCIPAL);
+        });
     }
 
     @Test
@@ -604,9 +619,9 @@ public class PersistenceEndpointUnitTest extends BaseUnitTest {
         return IOUtils.toString(inputStream, StandardCharsets.UTF_8);
     }
 
-    protected void generic_update(Long id, Identifier identifier, IdentifierDto data, String username, User user,
+    protected void generic_update(Long id, Identifier identifier, IdentifierUpdateDto data, String username, User user,
                                   Principal principal) throws IdentifierNotFoundException, IdentifierRequestException,
-            UserNotFoundException, at.tuwien.exception.AccessDeniedException, NotAllowedException {
+            UserNotFoundException, NotAllowedException {
 
         /* mock */
         if (identifier != null) {
diff --git a/dbrepo-identifier-service/rest-service/src/test/java/at/tuwien/service/DataCiteIdentifierServiceUnitTest.java b/dbrepo-identifier-service/rest-service/src/test/java/at/tuwien/service/DataCiteIdentifierServiceUnitTest.java
index 36e265abba..9c36a4078d 100644
--- a/dbrepo-identifier-service/rest-service/src/test/java/at/tuwien/service/DataCiteIdentifierServiceUnitTest.java
+++ b/dbrepo-identifier-service/rest-service/src/test/java/at/tuwien/service/DataCiteIdentifierServiceUnitTest.java
@@ -5,7 +5,7 @@ import at.tuwien.api.datacite.DataCiteBody;
 import at.tuwien.api.datacite.DataCiteData;
 import at.tuwien.api.datacite.doi.DataCiteDoi;
 import at.tuwien.api.identifier.IdentifierCreateDto;
-import at.tuwien.api.identifier.IdentifierDto;
+import at.tuwien.api.identifier.IdentifierUpdateDto;
 import at.tuwien.config.DataCiteConfig;
 import at.tuwien.config.EndpointConfig;
 import at.tuwien.config.IndexInitializer;
@@ -167,24 +167,23 @@ public class DataCiteIdentifierServiceUnitTest extends BaseUnitTest {
                 new DataCiteBody<>(new DataCiteData<>(null, "dois", new DataCiteDoi(IDENTIFIER_1_DOI_NOT_NULL)));
 
         /* mock */
-        when(identifierService.update(eq(IDENTIFIER_1_ID), any(IdentifierDto.class)))
+        when(identifierService.update(eq(IDENTIFIER_1_ID), any(IdentifierUpdateDto.class)))
                 .thenAnswer((i) -> identifierRepository.save(IDENTIFIER_1_WITH_DOI));
         when(restTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class),
                 any(ParameterizedTypeReference.class), eq(IDENTIFIER_1_DOI_NOT_NULL)))
                 .thenReturn(ResponseEntity.ok(response));
 
         /* test */
-        Identifier result = dataCiteIdentifierService.update(IDENTIFIER_1_ID, IDENTIFIER_1_WITH_DOI_DTO);
+        Identifier result = dataCiteIdentifierService.update(IDENTIFIER_1_ID, IDENTIFIER_1_DTO_UPDATE_REQUEST);
         assertTrue(identifierRepository.existsById(IDENTIFIER_1_ID));
         assertEquals(IDENTIFIER_1_DOI_NOT_NULL, result.getDoi());
     }
 
     @Test
-    public void update_invalidMetadata_fails()
-            throws IdentifierRequestException, IdentifierNotFoundException {
+    public void update_invalidMetadata_fails() {
 
         /* mock */
-        when(identifierService.update(eq(IDENTIFIER_1_ID), any(IdentifierDto.class)))
+        when(identifierService.update(eq(IDENTIFIER_1_ID), any(IdentifierUpdateDto.class)))
                 .thenAnswer((i) -> identifierRepository.save(IDENTIFIER_1_WITH_DOI));
         when(restTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class),
                 any(ParameterizedTypeReference.class), eq(IDENTIFIER_1_DOI_NOT_NULL)))
@@ -192,17 +191,16 @@ public class DataCiteIdentifierServiceUnitTest extends BaseUnitTest {
 
         /* test */
         assertThrows(IdentifierRequestException.class, () -> {
-            dataCiteIdentifierService.update(IDENTIFIER_1_ID, IDENTIFIER_1_WITH_DOI_DTO);
+            dataCiteIdentifierService.update(IDENTIFIER_1_ID, IDENTIFIER_1_DTO_UPDATE_REQUEST);
         });
         assertEquals(0, identifierRepository.count());
     }
 
     @Test
-    public void update_restClientException_fails()
-            throws IdentifierRequestException, IdentifierNotFoundException {
+    public void update_restClientException_fails() {
 
         /* mock */
-        when(identifierService.update(eq(IDENTIFIER_1_ID), any(IdentifierDto.class)))
+        when(identifierService.update(eq(IDENTIFIER_1_ID), any(IdentifierUpdateDto.class)))
                 .thenAnswer((i) -> identifierRepository.save(IDENTIFIER_1_WITH_DOI));
         when(restTemplate.exchange(anyString(), eq(HttpMethod.PUT), any(HttpEntity.class),
                 any(ParameterizedTypeReference.class), eq(IDENTIFIER_1_DOI_NOT_NULL)))
@@ -210,7 +208,7 @@ public class DataCiteIdentifierServiceUnitTest extends BaseUnitTest {
 
         /* test */
         assertThrows(InternalError.class, () -> {
-            dataCiteIdentifierService.update(IDENTIFIER_1_ID, IDENTIFIER_1_WITH_DOI_DTO);
+            dataCiteIdentifierService.update(IDENTIFIER_1_ID, IDENTIFIER_1_DTO_UPDATE_REQUEST);
         });
         assertEquals(0, identifierRepository.count());
     }
diff --git a/dbrepo-identifier-service/rest-service/src/test/java/at/tuwien/service/IdentifierServiceIntegrationTest.java b/dbrepo-identifier-service/rest-service/src/test/java/at/tuwien/service/IdentifierServiceIntegrationTest.java
index 423c014e50..bf33cdcf14 100644
--- a/dbrepo-identifier-service/rest-service/src/test/java/at/tuwien/service/IdentifierServiceIntegrationTest.java
+++ b/dbrepo-identifier-service/rest-service/src/test/java/at/tuwien/service/IdentifierServiceIntegrationTest.java
@@ -23,11 +23,9 @@ import org.springframework.http.HttpMethod;
 import org.springframework.http.ResponseEntity;
 import org.springframework.test.annotation.DirtiesContext;
 import org.springframework.test.context.junit.jupiter.SpringExtension;
-import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.client.RestTemplate;
 
 import java.util.List;
-import java.util.Optional;
 
 import static org.junit.jupiter.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.*;
@@ -76,14 +74,14 @@ public class IdentifierServiceIntegrationTest extends BaseUnitTest {
 
     @BeforeEach
     public void beforeEach() {
-        imageRepository.save(IMAGE_1);
+        imageRepository.save(IMAGE_1_SIMPLE);
         realmRepository.save(REALM_DBREPO);
-        userRepository.save(USER_1);
-        userRepository.save(USER_2);
-        containerRepository.save(CONTAINER_1);
-        databaseRepository.save(DATABASE_1);
-        containerRepository.save(CONTAINER_2);
-        databaseRepository.save(DATABASE_2);
+        userRepository.save(USER_1_SIMPLE);
+        userRepository.save(USER_2_SIMPLE);
+        containerRepository.save(CONTAINER_1_SIMPLE);
+        databaseRepository.save(DATABASE_1_SIMPLE);
+        containerRepository.save(CONTAINER_2_SIMPLE);
+        databaseRepository.save(DATABASE_2_SIMPLE);
         identifierRepository.save(IDENTIFIER_1);
     }
 
@@ -134,42 +132,36 @@ public class IdentifierServiceIntegrationTest extends BaseUnitTest {
     }
 
     @Test
-    public void update_notFound_fails() {
-
-        /* test */
-        assertThrows(IdentifierNotFoundException.class, () -> {
-            identifierService.update(IDENTIFIER_2_ID, IDENTIFIER_1_DTO);
-        });
-    }
-
-    @Test
-    @Transactional(readOnly = true)
     public void update_succeeds()
-            throws IdentifierNotFoundException, IdentifierPublishingNotAllowedException, IdentifierRequestException {
+            throws IdentifierNotFoundException, IdentifierRequestException {
 
         /* mock */
         when(identifierIdxRepository.save(any(IdentifierDto.class)))
                 .thenReturn(IDENTIFIER_1_DTO);
 
         /* test */
-        final Identifier response = identifierService.update(IDENTIFIER_1_ID, IDENTIFIER_1_DTO);
+        final Identifier response = identifierService.update(IDENTIFIER_1_ID, IDENTIFIER_1_DTO_UPDATE_REQUEST);
         assertEquals(IDENTIFIER_1_ID, response.getId());
         assertEquals(IDENTIFIER_1_DATABASE_ID, response.getDatabaseId());
+        assertEquals(IDENTIFIER_1_TITLE_MODIFY, response.getTitle());
         assertEquals(IDENTIFIER_1_PUBLICATION_YEAR, response.getPublicationYear());
         assertEquals(IDENTIFIER_1_PUBLICATION_MONTH, response.getPublicationMonth());
         assertEquals(IDENTIFIER_1_PUBLICATION_DAY, response.getPublicationDay());
     }
 
     @Test
-    public void delete_succeeds() throws IdentifierNotFoundException, NotAllowedException {
+    public void delete_succeeds() throws IdentifierNotFoundException {
 
         /* mock */
+        when(identifierIdxRepository.existsById(IDENTIFIER_1_ID))
+                .thenReturn(true);
         doNothing()
                 .when(identifierIdxRepository)
-                        .deleteById(IDENTIFIER_1_ID);
+                .deleteById(IDENTIFIER_1_ID);
 
         /* test */
         identifierService.delete(IDENTIFIER_1_ID);
+        assertTrue(userRepository.findById(IDENTIFIER_1_CREATED_BY).isPresent()) /* no cascade of delete */;
     }
 
     @Test
diff --git a/dbrepo-identifier-service/rest-service/src/test/java/at/tuwien/service/IdentifierServiceUnitTest.java b/dbrepo-identifier-service/rest-service/src/test/java/at/tuwien/service/IdentifierServiceUnitTest.java
index 25cb2990f2..d7e8b28963 100644
--- a/dbrepo-identifier-service/rest-service/src/test/java/at/tuwien/service/IdentifierServiceUnitTest.java
+++ b/dbrepo-identifier-service/rest-service/src/test/java/at/tuwien/service/IdentifierServiceUnitTest.java
@@ -3,6 +3,7 @@ package at.tuwien.service;
 import at.tuwien.BaseUnitTest;
 import at.tuwien.api.database.query.QueryDto;
 import at.tuwien.api.identifier.IdentifierDto;
+import at.tuwien.api.identifier.IdentifierUpdateDto;
 import at.tuwien.config.IndexInitializer;
 import at.tuwien.entities.identifier.Identifier;
 import at.tuwien.entities.identifier.IdentifierType;
@@ -171,38 +172,6 @@ public class IdentifierServiceUnitTest extends BaseUnitTest {
         });
     }
 
-    @Test
-    public void update_notFound_fails() {
-
-        /* mock */
-        when(identifierRepository.findById(IDENTIFIER_1_ID))
-                .thenReturn(Optional.empty());
-        when(identifierRepository.save(IDENTIFIER_1))
-                .thenReturn(IDENTIFIER_1);
-
-        /* test */
-        assertThrows(IdentifierNotFoundException.class, () -> {
-            identifierService.update(IDENTIFIER_1_ID, IDENTIFIER_1_DTO);
-        });
-    }
-
-    @Test
-    public void update_doiChange_fails() {
-        final IdentifierDto request = IdentifierDto.builder()
-                .id(IDENTIFIER_1_ID)
-                .doi("10.000/thisisadifferentdoi")
-                .build();
-
-        /* mock */
-        when(identifierRepository.findById(IDENTIFIER_1_ID))
-                .thenReturn(Optional.of(IDENTIFIER_1_WITH_DOI));
-
-        /* test */
-        assertThrows(IdentifierRequestException.class, () -> {
-            identifierService.update(IDENTIFIER_1_ID, request);
-        });
-    }
-
     @Test
     public void create_database_succeeds()
             throws DatabaseNotFoundException, UserNotFoundException, IdentifierAlreadyExistsException,
@@ -264,11 +233,13 @@ public class IdentifierServiceUnitTest extends BaseUnitTest {
     }
 
     @Test
-    public void delete_succeeds() throws IdentifierNotFoundException, NotAllowedException {
+    public void delete_succeeds() throws IdentifierNotFoundException {
 
         /* mock */
-        when(identifierRepository.findById(IDENTIFIER_1_ID))
-                .thenReturn(Optional.of(IDENTIFIER_1));
+        when(identifierRepository.existsById(IDENTIFIER_1_ID))
+                .thenReturn(true);
+        when(identifierIdxRepository.existsById(IDENTIFIER_1_ID))
+                .thenReturn(true);
         doNothing()
                 .when(identifierRepository)
                 .delete(IDENTIFIER_1);
@@ -296,22 +267,6 @@ public class IdentifierServiceUnitTest extends BaseUnitTest {
         });
     }
 
-    @Test
-    public void delete_withDoi_fails() {
-
-        /* mock */
-        when(identifierRepository.findById(IDENTIFIER_1_ID))
-                .thenReturn(Optional.of(IDENTIFIER_1_WITH_DOI));
-        doNothing()
-                .when(identifierRepository)
-                .delete(IDENTIFIER_1);
-
-        /* test */
-        assertThrows(NotAllowedException.class, () -> {
-            identifierService.delete(IDENTIFIER_1_ID);
-        });
-    }
-
     @Test
     public void exportMetadata_succeeds() throws IdentifierNotFoundException {
 
diff --git a/dbrepo-identifier-service/services/src/main/java/at/tuwien/config/IndexInitializer.java b/dbrepo-identifier-service/services/src/main/java/at/tuwien/config/IndexInitializer.java
index 0592364d2d..68268cd3c2 100644
--- a/dbrepo-identifier-service/services/src/main/java/at/tuwien/config/IndexInitializer.java
+++ b/dbrepo-identifier-service/services/src/main/java/at/tuwien/config/IndexInitializer.java
@@ -11,7 +11,6 @@ import org.springframework.context.event.EventListener;
 import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
 import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
 import org.springframework.stereotype.Component;
-import org.springframework.transaction.annotation.Transactional;
 
 import java.util.List;
 import java.util.stream.Collectors;
@@ -35,7 +34,6 @@ public class IndexInitializer {
         this.elasticsearchOperations = elasticsearchOperations;
     }
 
-    @Transactional
     @EventListener(ApplicationReadyEvent.class)
     public void initIndex() {
         log.debug("creating identifierindex");
diff --git a/dbrepo-identifier-service/services/src/main/java/at/tuwien/mapper/IdentifierMapper.java b/dbrepo-identifier-service/services/src/main/java/at/tuwien/mapper/IdentifierMapper.java
index 08fa62a8ec..a327c6c970 100644
--- a/dbrepo-identifier-service/services/src/main/java/at/tuwien/mapper/IdentifierMapper.java
+++ b/dbrepo-identifier-service/services/src/main/java/at/tuwien/mapper/IdentifierMapper.java
@@ -6,31 +6,37 @@ import at.tuwien.entities.identifier.Identifier;
 import at.tuwien.entities.identifier.IdentifierType;
 import at.tuwien.entities.identifier.RelatedIdentifier;
 import org.mapstruct.Mapper;
-import org.springframework.transaction.annotation.Transactional;
+import org.mapstruct.Mapping;
+import org.mapstruct.Mappings;
 
 @Mapper(componentModel = "spring")
 public interface IdentifierMapper {
 
-    @Transactional
     IdentifierDto identifierToIdentifierDto(Identifier data);
 
-    @Transactional
+    @Mappings({
+            @Mapping(target = "containerId", source = "cid"),
+            @Mapping(target = "databaseId", source = "dbid"),
+            @Mapping(target = "queryId", source = "qid"),
+    })
     Identifier identifierCreateDtoToIdentifier(IdentifierCreateDto data);
 
+    @Mappings({
+            @Mapping(target = "containerId", source = "cid"),
+            @Mapping(target = "databaseId", source = "dbid"),
+            @Mapping(target = "queryId", source = "qid"),
+    })
+    Identifier identifierUpdateDtoToIdentifier(IdentifierUpdateDto data);
+
     /* keep */
-    @Transactional
     RelatedIdentifierDto relatedIdentifierToRelatedIdentifierDto(RelatedIdentifier data);
 
-    @Transactional
     Identifier identifierDtoToIdentifier(IdentifierDto data);
 
-    @Transactional
     Creator creatorDtoToCreator(CreatorDto data);
 
-    @Transactional
     Creator creatorCreateDtoToCreator(CreatorCreateDto data);
 
-    @Transactional
     RelatedIdentifier relatedIdentifierCreateDtoToRelatedIdentifier(RelatedIdentifierCreateDto data);
 
     IdentifierType identifierTypeDtoToIdentifierType(IdentifierTypeDto data);
diff --git a/dbrepo-identifier-service/services/src/main/java/at/tuwien/service/IdentifierService.java b/dbrepo-identifier-service/services/src/main/java/at/tuwien/service/IdentifierService.java
index 9507132060..f7bab0d2c2 100644
--- a/dbrepo-identifier-service/services/src/main/java/at/tuwien/service/IdentifierService.java
+++ b/dbrepo-identifier-service/services/src/main/java/at/tuwien/service/IdentifierService.java
@@ -2,7 +2,7 @@ package at.tuwien.service;
 
 import at.tuwien.api.identifier.BibliographyTypeDto;
 import at.tuwien.api.identifier.IdentifierCreateDto;
-import at.tuwien.api.identifier.IdentifierDto;
+import at.tuwien.api.identifier.IdentifierUpdateDto;
 import at.tuwien.entities.identifier.Identifier;
 import at.tuwien.exception.*;
 import org.springframework.core.io.InputStreamResource;
@@ -108,16 +108,15 @@ public interface IdentifierService {
      * @param identifierId The identifier id.
      * @param data         The metadata.
      * @return The updated identifier if successful.
-     * @throws IdentifierNotFoundException             TThe identifier was not found in the metadata database or was deleted.
+     * @throws IdentifierNotFoundException TThe identifier was not found in the metadata database or was deleted.
      */
-    Identifier update(Long identifierId, IdentifierDto data) throws IdentifierNotFoundException, IdentifierRequestException;
+    Identifier update(Long identifierId, IdentifierUpdateDto data) throws IdentifierNotFoundException, IdentifierRequestException;
 
     /**
      * Soft-deletes an identifier for a given id in the metadata database. Does not actually remove the entity from the database, but sets it as deleted.
      *
      * @param identifierId The identifier id.
      * @throws IdentifierNotFoundException The identifier was not found in the metadata database or was deleted.
-     * @throws NotAllowedException Identifiers with a valid DOI cannot be deleted.
      */
-    void delete(Long identifierId) throws IdentifierNotFoundException, NotAllowedException;
+    void delete(Long identifierId) throws IdentifierNotFoundException;
 }
diff --git a/dbrepo-identifier-service/services/src/main/java/at/tuwien/service/impl/DataCiteIdentifierServiceImpl.java b/dbrepo-identifier-service/services/src/main/java/at/tuwien/service/impl/DataCiteIdentifierServiceImpl.java
index 8b32eaba0f..4b0efb8671 100644
--- a/dbrepo-identifier-service/services/src/main/java/at/tuwien/service/impl/DataCiteIdentifierServiceImpl.java
+++ b/dbrepo-identifier-service/services/src/main/java/at/tuwien/service/impl/DataCiteIdentifierServiceImpl.java
@@ -6,7 +6,7 @@ import at.tuwien.api.datacite.doi.DataCiteCreateDoi;
 import at.tuwien.api.datacite.doi.DataCiteDoi;
 import at.tuwien.api.identifier.BibliographyTypeDto;
 import at.tuwien.api.identifier.IdentifierCreateDto;
-import at.tuwien.api.identifier.IdentifierDto;
+import at.tuwien.api.identifier.IdentifierUpdateDto;
 import at.tuwien.config.DataCiteConfig;
 import at.tuwien.config.EndpointConfig;
 import at.tuwien.entities.identifier.Identifier;
@@ -103,17 +103,17 @@ public class DataCiteIdentifierServiceImpl implements IdentifierService {
                     }
             );
 
-            if(response.getStatusCode() != HttpStatus.CREATED || response.getBody() == null) {
+            if (response.getStatusCode() != HttpStatus.CREATED || response.getBody() == null) {
                 log.error("Could not successfully create DOI. Response: {}", response);
                 throw new IdentifierRequestException("Could not successfully create DOI.");
             }
 
             identifier.setDoi(response.getBody().getData().getAttributes().getDoi());
             this.identifierRepository.save(identifier);
-        } catch(HttpClientErrorException e) {
+        } catch (HttpClientErrorException e) {
             log.error("Invalid DOI metadata.", e);
             throw new IdentifierRequestException("Invalid DOI metadata.", e);
-        } catch(RestClientException e) {
+        } catch (RestClientException e) {
             log.error("Could not fulfil request to DataCite server.", e);
             throw new InternalError("Could not fulfil request to DataCite server.", e);
         }
@@ -146,10 +146,10 @@ public class DataCiteIdentifierServiceImpl implements IdentifierService {
 
     @Override
     @Transactional(rollbackOn = {Exception.class})
-    public Identifier update(Long identifierId, IdentifierDto data)
+    public Identifier update(Long identifierId, IdentifierUpdateDto data)
             throws IdentifierNotFoundException, IdentifierRequestException {
         Identifier identifier = identifierService.update(identifierId, data);
-        if(identifier.getDoi() == null) {
+        if (identifier.getDoi() == null) {
             return identifier;
         }
 
@@ -178,17 +178,17 @@ public class DataCiteIdentifierServiceImpl implements IdentifierService {
                     identifier.getDoi()
             );
 
-            if(response.getStatusCode() != HttpStatus.OK || response.getBody() == null) {
+            if (response.getStatusCode() != HttpStatus.OK || response.getBody() == null) {
                 log.error("Could not successfully create DOI. Response: {}", response);
                 throw new IdentifierRequestException("Could not successfully create DOI.");
             }
 
             identifier.setDoi(response.getBody().getData().getAttributes().getDoi());
             this.identifierRepository.save(identifier);
-        } catch(HttpClientErrorException e) {
+        } catch (HttpClientErrorException e) {
             log.error("Invalid DOI metadata.", e);
             throw new IdentifierRequestException("Invalid DOI metadata.", e);
-        } catch(RestClientException e) {
+        } catch (RestClientException e) {
             log.error("Could not fulfil request to DataCite server.", e);
             throw new InternalError("Could not fulfil request to DataCite server.", e);
         }
@@ -197,7 +197,8 @@ public class DataCiteIdentifierServiceImpl implements IdentifierService {
     }
 
     @Override
-    public void delete(Long identifierId) throws IdentifierNotFoundException, NotAllowedException {
+    @Transactional
+    public void delete(Long identifierId) throws IdentifierNotFoundException {
         identifierService.delete(identifierId);
     }
 
diff --git a/dbrepo-identifier-service/services/src/main/java/at/tuwien/service/impl/IdentifierServiceImpl.java b/dbrepo-identifier-service/services/src/main/java/at/tuwien/service/impl/IdentifierServiceImpl.java
index 9228a1af79..a2232e0a65 100644
--- a/dbrepo-identifier-service/services/src/main/java/at/tuwien/service/impl/IdentifierServiceImpl.java
+++ b/dbrepo-identifier-service/services/src/main/java/at/tuwien/service/impl/IdentifierServiceImpl.java
@@ -20,7 +20,6 @@ import at.tuwien.service.IdentifierService;
 import at.tuwien.service.UserService;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.io.IOUtils;
-import org.springframework.context.annotation.Profile;
 import org.springframework.core.io.InputStreamResource;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -113,10 +112,8 @@ public class IdentifierServiceImpl implements IdentifierService {
         }
         /* identifier */
         final Identifier tmp = identifierMapper.identifierCreateDtoToIdentifier(data);
-        tmp.setContainerId(data.getCid());
-        tmp.setDatabaseId(data.getDbid());
         final User creator = userService.findByUsername(principal.getName());
-        tmp.setCreatedBy(creator.getId());
+        tmp.setCreator(creator);
         tmp.setCreators(List.of());
         if (data.getType().equals(IdentifierTypeDto.SUBSET)) {
             log.debug("identifier describes a subset");
@@ -136,7 +133,7 @@ public class IdentifierServiceImpl implements IdentifierService {
                 .map(c -> {
                     final Creator creatorDto = identifierMapper.creatorCreateDtoToCreator(c);
                     creatorDto.setPid(entity.getId());
-                    creatorDto.setCreatedBy(creator.getId());
+                    creatorDto.setCreator(creator);
                     return creatorDto;
                 })
                 .collect(Collectors.toList()));
@@ -146,7 +143,7 @@ public class IdentifierServiceImpl implements IdentifierService {
                     .forEach(r -> {
                         final RelatedIdentifier id = identifierMapper.relatedIdentifierCreateDtoToRelatedIdentifier(r);
                         id.setIid(entity.getId());
-                        id.setCreatedBy(creator.getId());
+                        id.setCreator(creator);
                         final RelatedIdentifier relatedIdentifier = relatedIdentifierRepository.save(id);
                         log.debug("identifier add related with id {}", relatedIdentifier.getId());
                         entity.getRelated().add(relatedIdentifier);
@@ -178,7 +175,7 @@ public class IdentifierServiceImpl implements IdentifierService {
         final Identifier identifier = find(id);
         /* context */
         final Context context = new Context();
-        if(identifier.getDoi() != null) {
+        if (identifier.getDoi() != null) {
             context.setVariable("identifierType", "DOI");
             context.setVariable("identifier", identifier.getDoi());
         } else {
@@ -208,7 +205,7 @@ public class IdentifierServiceImpl implements IdentifierService {
         final Identifier identifier = find(id);
         /* context */
         final Context context = new Context();
-        if(identifier.getDoi() != null) {
+        if (identifier.getDoi() != null) {
             context.setVariable("identifierType", "doi");
             context.setVariable("identifier", identifier.getDoi());
         } else {
@@ -253,16 +250,10 @@ public class IdentifierServiceImpl implements IdentifierService {
 
     @Override
     @Transactional
-    public Identifier update(Long identifierId, IdentifierDto data)
-            throws IdentifierNotFoundException, IdentifierRequestException {
-        /* check */
-        final Identifier old = find(identifierId);
-        if(data.getDoi() != null && !data.getDoi().equals(old.getDoi())) {
-            log.error("Failed to update: DOI needs to stay the same");
-            throw new IdentifierRequestException("Failed to update: DOI needs to stay the same");
-        }
+    public Identifier update(Long identifierId, IdentifierUpdateDto data) {
         /* map */
-        final Identifier entity = identifierMapper.identifierDtoToIdentifier(data);
+        final Identifier entity = identifierMapper.identifierUpdateDtoToIdentifier(data);
+        entity.setId(identifierId);
         entity.getCreators()
                 .forEach(creator -> creator.setPid(identifierId));
         /* update */
@@ -277,17 +268,17 @@ public class IdentifierServiceImpl implements IdentifierService {
 
     @Override
     @Transactional
-    public void delete(Long identifierId) throws IdentifierNotFoundException, NotAllowedException {
-        /* check */
-        final Identifier identifier = find(identifierId);
-        if(identifier.getDoi() != null) {
-            throw new NotAllowedException("Identifiers with a DOI cannot be deleted.");
+    public void delete(Long identifierId) throws IdentifierNotFoundException {
+        /* delete in metadata database */
+        if (!identifierRepository.existsById(identifierId)) {
+            throw new IdentifierNotFoundException("Identifier not found in metadata database");
         }
-        /* delete */
-        identifierRepository.delete(identifier);
+        identifierRepository.deleteById(identifierId);
         log.info("Deleted identifier with id {}", identifierId);
-        log.trace("deleted identifier {}", identifier);
-        /* elastic search */
+        /* delete in elastic search */
+        if (!identifierIdxRepository.existsById(identifierId)) {
+            throw new IdentifierNotFoundException("Identifier not found in metadata database");
+        }
         identifierIdxRepository.deleteById(identifierId);
         log.info("Deleted identifier with id {} in elastic search", identifierId);
     }
diff --git a/dbrepo-metadata-db/api/src/main/java/at/tuwien/api/identifier/IdentifierUpdateDto.java b/dbrepo-metadata-db/api/src/main/java/at/tuwien/api/identifier/IdentifierUpdateDto.java
new file mode 100644
index 0000000000..0f1f64b1df
--- /dev/null
+++ b/dbrepo-metadata-db/api/src/main/java/at/tuwien/api/identifier/IdentifierUpdateDto.java
@@ -0,0 +1,71 @@
+package at.tuwien.api.identifier;
+
+import at.tuwien.api.database.LanguageTypeDto;
+import at.tuwien.api.database.LicenseDto;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Builder;
+import lombok.Data;
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.NotEmpty;
+import java.util.List;
+
+@Data
+@Getter
+@Setter
+@Builder
+public class IdentifierUpdateDto {
+
+    @NotNull
+    private Long cid;
+
+    @NotNull
+    private Long dbid;
+
+    private Long qid;
+
+    @Schema(example = "10.1038/nphys1170")
+    private String doi;
+
+    @NotNull
+    private IdentifierTypeDto type;
+
+    @NotBlank
+    @Schema(example = "Airquality Stephansplatz, Vienna, Austria")
+    private String title;
+
+    @Schema(example = "Air quality reports at Stephansplatz, Vienna")
+    private String description;
+
+    @JsonProperty("publication_day")
+    @Schema(example = "15")
+    private Integer publicationDay;
+
+    @JsonProperty("publication_month")
+    @Schema(example = "12")
+    private Integer publicationMonth;
+
+    @Schema(example = "TU Wien")
+    private String publisher;
+
+    private LanguageTypeDto language;
+
+    private LicenseDto license;
+
+    @NotNull
+    @JsonProperty("publication_year")
+    @Schema(example = "2022")
+    private Integer publicationYear;
+
+    @NotNull
+    @NotEmpty
+    private List<CreatorDto> creators;
+
+    @JsonProperty("related_identifiers")
+    private List<RelatedIdentifierCreateDto> relatedIdentifiers;
+
+}
diff --git a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/database/table/Table.java b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/database/table/Table.java
index 6b9ee532fc..e05a1e03ae 100644
--- a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/database/table/Table.java
+++ b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/database/table/Table.java
@@ -7,16 +7,13 @@ import at.tuwien.entities.user.User;
 import lombok.*;
 import net.sf.jsqlparser.statement.select.FromItem;
 import org.hibernate.annotations.GenericGenerator;
-import org.hibernate.annotations.Type;
 import org.springframework.data.annotation.CreatedDate;
 import org.springframework.data.annotation.LastModifiedDate;
-import org.springframework.data.elasticsearch.annotations.Document;
 import org.springframework.data.jpa.domain.support.AuditingEntityListener;
 
 import javax.persistence.*;
 import java.time.Instant;
 import java.util.List;
-import java.util.UUID;
 
 @Data
 @Entity
@@ -42,14 +39,9 @@ public class Table {
     @EqualsAndHashCode.Include
     private Long tdbid;
 
-    @ToString.Exclude
-    @Column(name = "createdBy", nullable = false, columnDefinition = "VARCHAR(36)")
-    @Type(type = "uuid-char")
-    private UUID createdBy;
-
-    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
+    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
     @JoinColumns({
-            @JoinColumn(name = "createdBy", referencedColumnName = "ID", updatable = false, insertable = false)
+            @JoinColumn(name = "createdBy", referencedColumnName = "ID", nullable = false, columnDefinition = "VARCHAR(36)", updatable = false)
     })
     private User creator;
 
@@ -69,11 +61,11 @@ public class Table {
     private String description;
 
     @ToString.Exclude
-    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.MERGE)
+    @ManyToOne(fetch = FetchType.LAZY, cascade = {})
     @JoinColumn(name = "tdbid", insertable = false, updatable = false)
     private Database database;
 
-    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.MERGE, mappedBy = "table")
+    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "table")
     @OrderBy("ordinalPosition")
     private List<TableColumn> columns;
 
@@ -90,7 +82,8 @@ public class Table {
 
     @PreRemove
     public void preRemove() {
-        this.database = null;
+        this.creator = null;
+        this.columns.forEach(c -> c.setCreator(null));
     }
 
     /**
diff --git a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumn.java b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumn.java
index 1c95089830..02ad037bd6 100644
--- a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumn.java
+++ b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/database/table/columns/TableColumn.java
@@ -60,14 +60,9 @@ public class TableColumn implements Comparable<TableColumn> {
     })
     private Table table;
 
-    @ToString.Exclude
-    @Column(name = "createdBy", nullable = false, columnDefinition = "VARCHAR(36)")
-    @Type(type = "uuid-char")
-    private UUID createdBy;
-
-    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
+    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
     @JoinColumns({
-            @JoinColumn(name = "createdBy", referencedColumnName = "ID", insertable = false, updatable = false)
+            @JoinColumn(name = "createdBy", referencedColumnName = "ID", nullable = false, columnDefinition = "VARCHAR(36)", updatable = false)
     })
     private User creator;
 
diff --git a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/Creator.java b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/Creator.java
index 2b0a720cb7..740fe5a4e5 100644
--- a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/Creator.java
+++ b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/Creator.java
@@ -56,14 +56,9 @@ public class Creator {
     @CreatedDate
     private Instant created;
 
-    @ToString.Exclude
-    @Column(name = "createdBy", nullable = false, columnDefinition = "VARCHAR(36)")
-    @Type(type = "uuid-char")
-    private UUID createdBy;
-
     @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
     @JoinColumns({
-            @JoinColumn(name = "createdBy", referencedColumnName = "ID", insertable = false, updatable = false)
+            @JoinColumn(name = "createdBy", referencedColumnName = "ID", nullable = false, columnDefinition = "VARCHAR(36)", updatable = false)
     })
     private User creator;
 
diff --git a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/Identifier.java b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/Identifier.java
index 7ed3b864b3..294a9c954d 100644
--- a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/Identifier.java
+++ b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/Identifier.java
@@ -6,7 +6,6 @@ import at.tuwien.entities.database.License;
 import at.tuwien.entities.user.User;
 import lombok.*;
 import org.hibernate.annotations.GenericGenerator;
-import org.hibernate.annotations.Type;
 import org.springframework.data.annotation.CreatedDate;
 import org.springframework.data.annotation.LastModifiedDate;
 import org.springframework.data.jpa.domain.support.AuditingEntityListener;
@@ -16,7 +15,6 @@ import javax.validation.constraints.NotBlank;
 import java.io.Serializable;
 import java.time.Instant;
 import java.util.List;
-import java.util.UUID;
 
 @Data
 @Entity
@@ -46,14 +44,9 @@ public class Identifier implements Serializable {
     @Column(name = "qid")
     private Long queryId;
 
-    @ToString.Exclude
-    @Column(name = "createdBy", nullable = false, columnDefinition = "VARCHAR(36)")
-    @Type(type = "uuid-char")
-    private UUID createdBy;
-
-    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.MERGE)
+    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST)
     @JoinColumns({
-            @JoinColumn(name = "createdBy", referencedColumnName = "ID", insertable = false, updatable = false)
+            @JoinColumn(name = "createdBy", referencedColumnName = "ID", nullable = false, columnDefinition = "VARCHAR(36)", updatable = false)
     })
     private User creator;
 
@@ -108,13 +101,13 @@ public class Identifier implements Serializable {
     @Column
     private Integer publicationDay;
 
-    @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.MERGE)
+    @OneToOne(fetch = FetchType.LAZY, cascade = {})
     @JoinColumns({
             @JoinColumn(name = "dbid", referencedColumnName = "id", insertable = false, updatable = false)
     })
     private Database database;
 
-    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.MERGE)
+    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
     @JoinColumns({
             @JoinColumn(name = "iid", referencedColumnName = "id", insertable = false, updatable = false)
     })
@@ -123,7 +116,7 @@ public class Identifier implements Serializable {
     @Column
     private String doi;
 
-    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "identifier")
+    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "identifier")
     private List<Creator> creators;
 
     @Column(nullable = false, updatable = false)
@@ -134,6 +127,13 @@ public class Identifier implements Serializable {
     @LastModifiedDate
     private Instant lastModified;
 
+    @PreRemove
+    private void preRemove() {
+        this.creator = null;
+        this.related.forEach(r -> r.setCreator(null));
+        this.creators.forEach(c -> c.setCreator(null));
+    }
+
 }
 
 
diff --git a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/RelatedIdentifier.java b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/RelatedIdentifier.java
index aed2577656..54b90615a7 100644
--- a/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/RelatedIdentifier.java
+++ b/dbrepo-metadata-db/entities/src/main/java/at/tuwien/entities/identifier/RelatedIdentifier.java
@@ -50,14 +50,9 @@ public class RelatedIdentifier {
     @Enumerated(EnumType.STRING)
     private RelationType relation;
 
-    @ToString.Exclude
-    @Column(name = "created_by", nullable = false, columnDefinition = "VARCHAR(36)")
-    @Type(type = "uuid-char")
-    private UUID createdBy;
-
     @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
     @JoinColumns({
-            @JoinColumn(name = "created_by", referencedColumnName = "ID", insertable = false, updatable = false)
+            @JoinColumn(name = "created_by", referencedColumnName = "ID", nullable = false, columnDefinition = "VARCHAR(36)", updatable = false)
     })
     private User creator;
 
diff --git a/dbrepo-metadata-db/test/src/main/java/at/tuwien/test/BaseTest.java b/dbrepo-metadata-db/test/src/main/java/at/tuwien/test/BaseTest.java
index 7bd9dff9d6..322deab7f9 100644
--- a/dbrepo-metadata-db/test/src/main/java/at/tuwien/test/BaseTest.java
+++ b/dbrepo-metadata-db/test/src/main/java/at/tuwien/test/BaseTest.java
@@ -1496,6 +1496,8 @@ public abstract class BaseTest {
     public final static String TABLE_1_DESCRIPTION = "Weather in the world";
     public final static String TABLE_1_QUEUE_NAME = DATABASE_1_EXCHANGE + "." + TABLE_1_INTERNALNAME;
     public final static String TABLE_1_ROUTING_KEY = TABLE_1_QUEUE_NAME;
+    public final static UUID TABLE_1_CREATED_BY = USER_1_ID;
+    public final static Long TABLE_1_DATABASE_ID = DATABASE_1_ID;
     public final static Instant TABLE_1_CREATED = Instant.ofEpochSecond(1677399975) /* 2023-02-26 08:26:15 (UTC) */;
     public final static Instant TABLE_1_LAST_MODIFIED = Instant.ofEpochSecond(1677399975) /* 2023-02-26 08:26:15 (UTC) */;
 
@@ -1505,6 +1507,8 @@ public abstract class BaseTest {
     public final static String TABLE_2_DESCRIPTION = "Weather location";
     public final static String TABLE_2_QUEUE_NAME = DATABASE_1_EXCHANGE + "." + TABLE_2_INTERNALNAME;
     public final static String TABLE_2_ROUTING_KEY = TABLE_2_QUEUE_NAME;
+    public final static UUID TABLE_2_CREATED_BY = USER_1_ID;
+    public final static Long TABLE_2_DATABASE_ID = DATABASE_1_ID;
     public final static Instant TABLE_2_CREATED = Instant.ofEpochSecond(1677400007) /* 2023-02-26 08:26:47 (UTC) */;
     public final static Instant TABLE_2_LAST_MODIFIED = Instant.ofEpochSecond(1677400007) /* 2023-02-26 08:26:47 (UTC) */;
 
@@ -1514,6 +1518,8 @@ public abstract class BaseTest {
     public final static String TABLE_3_DESCRIPTION = "https://www.kaggle.com/laa283/zurich-public-transport/version/2";
     public final static String TABLE_3_QUEUE_NAME = DATABASE_1_EXCHANGE + "." + TABLE_3_INTERNALNAME;
     public final static String TABLE_3_ROUTING_KEY = TABLE_3_QUEUE_NAME;
+    public final static UUID TABLE_3_CREATED_BY = USER_1_ID;
+    public final static Long TABLE_3_DATABASE_ID = DATABASE_1_ID;
     public final static Instant TABLE_3_CREATED = Instant.ofEpochSecond(1677400031) /* 2023-02-26 08:27:11 (UTC) */;
     public final static Instant TABLE_3_LAST_MODIFIED = Instant.ofEpochSecond(1677400031) /* 2023-02-26 08:27:11 (UTC) */;
 
@@ -1589,7 +1595,7 @@ public abstract class BaseTest {
                     .id(1L)
                     .ordinalPosition(0)
                     .cdbid(DATABASE_1_ID)
-                    .tid(TABLE_1_ID)
+                    .tid(TABLE_7_ID)
                     .name("Timestamp")
                     .internalName("timestamp")
                     .columnType(TableColumnType.TIMESTAMP)
@@ -1597,12 +1603,13 @@ public abstract class BaseTest {
                     .isNullAllowed(false)
                     .autoGenerated(false)
                     .isPrimaryKey(true)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .id(2L)
                     .ordinalPosition(1)
                     .cdbid(DATABASE_1_ID)
-                    .tid(TABLE_1_ID)
+                    .tid(TABLE_7_ID)
                     .name("Value")
                     .internalName("value")
                     .columnType(TableColumnType.DECIMAL)
@@ -1610,6 +1617,7 @@ public abstract class BaseTest {
                     .isNullAllowed(true)
                     .autoGenerated(false)
                     .isPrimaryKey(false)
+                    .creator(USER_1)
                     .build());
 
     public final static Table TABLE_7 = Table.builder()
@@ -1621,7 +1629,6 @@ public abstract class BaseTest {
             .tdbid(DATABASE_1_ID)
             .queueName(TABLE_7_QUEUE_NAME)
             .routingKey(TABLE_7_ROUTING_KEY)
-            .createdBy(USER_1_ID)
             .columns(TABLE_7_COLUMNS)
             .creator(USER_1)
             .created(TABLE_7_CREATED)
@@ -1637,7 +1644,6 @@ public abstract class BaseTest {
             .tdbid(DATABASE_1_ID)
             .queueName(TABLE_7_QUEUE_NAME)
             .routingKey(TABLE_7_ROUTING_KEY)
-            .createdBy(USER_1_ID)
             .columns(List.of() /* for jpa */)
             .creator(null /* for jpa */)
             .created(TABLE_7_CREATED)
@@ -2236,6 +2242,7 @@ public abstract class BaseTest {
                     .isNullAllowed(COLUMN_8_1_NULL)
                     .autoGenerated(COLUMN_8_1_AUTO_GENERATED)
                     .isPrimaryKey(COLUMN_8_1_PRIMARY)
+                    .creator(USER_3)
                     .build(),
             TableColumn.builder()
                     .id(COLUMN_8_2_ID)
@@ -2249,6 +2256,7 @@ public abstract class BaseTest {
                     .isNullAllowed(COLUMN_8_2_NULL)
                     .autoGenerated(COLUMN_8_2_AUTO_GENERATED)
                     .isPrimaryKey(COLUMN_8_2_PRIMARY)
+                    .creator(USER_3)
                     .build());
 
     public final static Table TABLE_8 = Table.builder()
@@ -2261,7 +2269,6 @@ public abstract class BaseTest {
             .queueName(TABLE_8_QUEUE_NAME)
             .routingKey(TABLE_8_ROUTING_KEY)
             .columns(TABLE_8_COLUMNS)
-            .createdBy(USER_1_ID)
             .creator(USER_1)
             .created(TABLE_8_CREATED)
             .lastModified(TABLE_8_LAST_MODIFIED)
@@ -2560,6 +2567,7 @@ public abstract class BaseTest {
                     .autoGenerated(COLUMN_1_1_AUTO_GENERATED)
                     .isPrimaryKey(COLUMN_1_1_PRIMARY)
                     .enumValues(COLUMN_1_1_ENUM_VALUES)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .id(COLUMN_1_2_ID)
@@ -2575,6 +2583,7 @@ public abstract class BaseTest {
                     .autoGenerated(COLUMN_1_2_AUTO_GENERATED)
                     .isPrimaryKey(COLUMN_1_2_PRIMARY)
                     .enumValues(COLUMN_1_2_ENUM_VALUES)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .id(COLUMN_1_3_ID)
@@ -2589,6 +2598,7 @@ public abstract class BaseTest {
                     .autoGenerated(COLUMN_1_3_AUTO_GENERATED)
                     .isPrimaryKey(COLUMN_1_3_PRIMARY)
                     .enumValues(COLUMN_1_3_ENUM_VALUES)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .id(COLUMN_1_4_ID)
@@ -2603,6 +2613,7 @@ public abstract class BaseTest {
                     .autoGenerated(COLUMN_1_4_AUTO_GENERATED)
                     .isPrimaryKey(COLUMN_1_4_PRIMARY)
                     .enumValues(COLUMN_1_4_ENUM_VALUES)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .id(COLUMN_1_5_ID)
@@ -2617,6 +2628,7 @@ public abstract class BaseTest {
                     .autoGenerated(COLUMN_1_5_AUTO_GENERATED)
                     .isPrimaryKey(COLUMN_1_5_PRIMARY)
                     .enumValues(COLUMN_1_5_ENUM_VALUES)
+                    .creator(USER_1)
                     .build());
 
     public final static Table TABLE_1 = Table.builder()
@@ -2630,7 +2642,6 @@ public abstract class BaseTest {
             .tdbid(DATABASE_1_ID)
             .queueName(TABLE_1_QUEUE_NAME)
             .routingKey(TABLE_1_ROUTING_KEY)
-            .createdBy(USER_1_ID)
             .columns(TABLE_1_COLUMNS)
             .constraints(null) /* TABLE_1_CONSTRAINTS */
             .creator(USER_1)
@@ -2649,7 +2660,6 @@ public abstract class BaseTest {
             .tdbid(DATABASE_1_ID)
             .queueName(TABLE_1_QUEUE_NAME)
             .routingKey(TABLE_1_ROUTING_KEY)
-            .createdBy(USER_1_ID)
             .columns(List.of() /* for jpa */)
             .constraints(null /* for jpa */) /* TABLE_1_CONSTRAINTS */
             .creator(null /* for jpa */)
@@ -2670,6 +2680,7 @@ public abstract class BaseTest {
                     .autoGenerated(COLUMN_2_1_AUTO_GENERATED)
                     .isPrimaryKey(COLUMN_2_1_PRIMARY)
                     .enumValues(COLUMN_2_1_ENUM_VALUES)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .id(COLUMN_2_2_ID)
@@ -2684,6 +2695,7 @@ public abstract class BaseTest {
                     .autoGenerated(COLUMN_2_2_AUTO_GENERATED)
                     .isPrimaryKey(COLUMN_2_2_PRIMARY)
                     .enumValues(COLUMN_2_2_ENUM_VALUES)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .id(COLUMN_2_3_ID)
@@ -2698,6 +2710,7 @@ public abstract class BaseTest {
                     .autoGenerated(COLUMN_2_3_AUTO_GENERATED)
                     .isPrimaryKey(COLUMN_2_3_PRIMARY)
                     .enumValues(COLUMN_2_3_ENUM_VALUES)
+                    .creator(USER_1)
                     .build());
 
     public final static Table TABLE_2 = Table.builder()
@@ -2711,7 +2724,6 @@ public abstract class BaseTest {
             .tdbid(DATABASE_1_ID)
             .queueName(TABLE_2_QUEUE_NAME)
             .routingKey(TABLE_2_ROUTING_KEY)
-            .createdBy(USER_1_ID)
             .columns(TABLE_2_COLUMNS)
             .creator(USER_1)
             .created(TABLE_2_CREATED)
@@ -2729,7 +2741,6 @@ public abstract class BaseTest {
             .tdbid(DATABASE_1_ID)
             .queueName(TABLE_2_QUEUE_NAME)
             .routingKey(TABLE_2_ROUTING_KEY)
-            .createdBy(USER_1_ID)
             .columns(List.of() /* for jpa */)
             .creator(null /* for jpa */)
             .created(TABLE_2_CREATED)
@@ -2763,6 +2774,7 @@ public abstract class BaseTest {
                     .isPrimaryKey(true)
                     .dateFormat(null)
                     .enumValues(null)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .tid(TABLE_3_ID)
@@ -2776,6 +2788,7 @@ public abstract class BaseTest {
                     .isPrimaryKey(false)
                     .dateFormat(null)
                     .enumValues(null)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .tid(TABLE_3_ID)
@@ -2789,6 +2802,7 @@ public abstract class BaseTest {
                     .isPrimaryKey(false)
                     .dateFormat(null)
                     .enumValues(null)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .tid(TABLE_3_ID)
@@ -2802,6 +2816,7 @@ public abstract class BaseTest {
                     .isPrimaryKey(false)
                     .dfid(IMAGE_DATE_2_ID)
                     .enumValues(null)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .tid(TABLE_3_ID)
@@ -2815,6 +2830,7 @@ public abstract class BaseTest {
                     .isPrimaryKey(false)
                     .dateFormat(null)
                     .enumValues(null)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .tid(TABLE_3_ID)
@@ -2828,6 +2844,7 @@ public abstract class BaseTest {
                     .isPrimaryKey(false)
                     .dateFormat(null)
                     .enumValues(null)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .tid(TABLE_3_ID)
@@ -2841,6 +2858,7 @@ public abstract class BaseTest {
                     .isPrimaryKey(false)
                     .dateFormat(null)
                     .enumValues(null)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .tid(TABLE_3_ID)
@@ -2854,6 +2872,7 @@ public abstract class BaseTest {
                     .isPrimaryKey(false)
                     .dateFormat(null)
                     .enumValues(null)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .tid(TABLE_3_ID)
@@ -2867,6 +2886,7 @@ public abstract class BaseTest {
                     .isPrimaryKey(false)
                     .dateFormat(null)
                     .enumValues(null)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .tid(TABLE_3_ID)
@@ -2880,6 +2900,7 @@ public abstract class BaseTest {
                     .isPrimaryKey(false)
                     .dateFormat(null)
                     .enumValues(null)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .tid(TABLE_3_ID)
@@ -2893,6 +2914,7 @@ public abstract class BaseTest {
                     .isPrimaryKey(false)
                     .dfid(IMAGE_DATE_2_ID)
                     .enumValues(null)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .tid(TABLE_3_ID)
@@ -2906,6 +2928,7 @@ public abstract class BaseTest {
                     .isPrimaryKey(false)
                     .dateFormat(null)
                     .enumValues(null)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .tid(TABLE_3_ID)
@@ -2919,6 +2942,7 @@ public abstract class BaseTest {
                     .isPrimaryKey(false)
                     .dateFormat(null)
                     .enumValues(null)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .tid(TABLE_3_ID)
@@ -2932,6 +2956,7 @@ public abstract class BaseTest {
                     .isPrimaryKey(false)
                     .dateFormat(null)
                     .enumValues(null)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .tid(TABLE_3_ID)
@@ -2945,6 +2970,7 @@ public abstract class BaseTest {
                     .isPrimaryKey(false)
                     .dateFormat(null)
                     .enumValues(null)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .tid(TABLE_3_ID)
@@ -2958,6 +2984,7 @@ public abstract class BaseTest {
                     .isPrimaryKey(false)
                     .dateFormat(null)
                     .enumValues(null)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .tid(TABLE_3_ID)
@@ -2971,6 +2998,7 @@ public abstract class BaseTest {
                     .isPrimaryKey(false)
                     .dateFormat(null)
                     .enumValues(null)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .tid(TABLE_3_ID)
@@ -2984,6 +3012,7 @@ public abstract class BaseTest {
                     .isPrimaryKey(false)
                     .dateFormat(null)
                     .enumValues(null)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .tid(TABLE_3_ID)
@@ -2997,6 +3026,7 @@ public abstract class BaseTest {
                     .isPrimaryKey(false)
                     .dateFormat(null)
                     .enumValues(null)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .tid(TABLE_3_ID)
@@ -3010,6 +3040,7 @@ public abstract class BaseTest {
                     .isPrimaryKey(false)
                     .dfid(IMAGE_DATE_2_ID)
                     .enumValues(null)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .tid(TABLE_3_ID)
@@ -3023,6 +3054,7 @@ public abstract class BaseTest {
                     .isPrimaryKey(false)
                     .dateFormat(null)
                     .enumValues(null)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .tid(TABLE_3_ID)
@@ -3036,6 +3068,7 @@ public abstract class BaseTest {
                     .isPrimaryKey(false)
                     .dateFormat(null)
                     .enumValues(null)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .tid(TABLE_3_ID)
@@ -3049,6 +3082,7 @@ public abstract class BaseTest {
                     .isPrimaryKey(false)
                     .dateFormat(null)
                     .enumValues(null)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .tid(TABLE_3_ID)
@@ -3062,6 +3096,7 @@ public abstract class BaseTest {
                     .isPrimaryKey(false)
                     .dateFormat(null)
                     .enumValues(null)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .tid(TABLE_3_ID)
@@ -3075,6 +3110,7 @@ public abstract class BaseTest {
                     .isPrimaryKey(false)
                     .dateFormat(null)
                     .enumValues(null)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .tid(TABLE_3_ID)
@@ -3088,6 +3124,7 @@ public abstract class BaseTest {
                     .isPrimaryKey(false)
                     .dateFormat(null)
                     .enumValues(null)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .tid(TABLE_3_ID)
@@ -3101,6 +3138,7 @@ public abstract class BaseTest {
                     .isPrimaryKey(false)
                     .dateFormat(null)
                     .enumValues(null)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .tid(TABLE_3_ID)
@@ -3114,6 +3152,7 @@ public abstract class BaseTest {
                     .isPrimaryKey(false)
                     .dateFormat(null)
                     .enumValues(null)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .tid(TABLE_3_ID)
@@ -3127,6 +3166,7 @@ public abstract class BaseTest {
                     .isPrimaryKey(false)
                     .dateFormat(null)
                     .enumValues(null)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .tid(TABLE_3_ID)
@@ -3140,6 +3180,7 @@ public abstract class BaseTest {
                     .isPrimaryKey(false)
                     .dateFormat(null)
                     .enumValues(null)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .tid(TABLE_3_ID)
@@ -3153,6 +3194,7 @@ public abstract class BaseTest {
                     .isPrimaryKey(false)
                     .dateFormat(null)
                     .enumValues(null)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .tid(TABLE_3_ID)
@@ -3166,6 +3208,7 @@ public abstract class BaseTest {
                     .isPrimaryKey(false)
                     .dateFormat(null)
                     .enumValues(null)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .tid(TABLE_3_ID)
@@ -3179,6 +3222,7 @@ public abstract class BaseTest {
                     .isPrimaryKey(false)
                     .dateFormat(null)
                     .enumValues(null)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .tid(TABLE_3_ID)
@@ -3192,6 +3236,7 @@ public abstract class BaseTest {
                     .isPrimaryKey(false)
                     .dateFormat(null)
                     .enumValues(null)
+                    .creator(USER_1)
                     .build(),
             TableColumn.builder()
                     .tid(TABLE_3_ID)
@@ -3205,6 +3250,7 @@ public abstract class BaseTest {
                     .isPrimaryKey(false)
                     .dateFormat(null)
                     .enumValues(null)
+                    .creator(USER_1)
                     .build());
 
     public final static Constraints TABLE_3_CONSTRAINTS = Constraints.builder()
@@ -3224,7 +3270,6 @@ public abstract class BaseTest {
             .routingKey(TABLE_3_ROUTING_KEY)
             .columns(TABLE_3_COLUMNS)
             .constraints(TABLE_3_CONSTRAINTS)
-            .createdBy(USER_1_ID)
             .creator(USER_1)
             .created(TABLE_3_CREATED)
             .lastModified(TABLE_3_LAST_MODIFIED)
@@ -3243,7 +3288,6 @@ public abstract class BaseTest {
             .routingKey(TABLE_3_ROUTING_KEY)
             .columns(List.of() /* for jpa */)
             .constraints(TABLE_3_CONSTRAINTS)
-            .createdBy(USER_1_ID)
             .creator(null /* for jpa */)
             .created(TABLE_3_CREATED)
             .lastModified(TABLE_3_LAST_MODIFIED)
@@ -3262,6 +3306,7 @@ public abstract class BaseTest {
                     .autoGenerated(COLUMN_4_1_AUTO_GENERATED)
                     .isPrimaryKey(COLUMN_4_1_PRIMARY)
                     .enumValues(COLUMN_4_1_ENUM_VALUES)
+                    .creator(USER_2)
                     .build(),
             TableColumn.builder()
                     .id(COLUMN_4_2_ID)
@@ -3276,6 +3321,7 @@ public abstract class BaseTest {
                     .autoGenerated(COLUMN_4_2_AUTO_GENERATED)
                     .isPrimaryKey(COLUMN_4_2_PRIMARY)
                     .enumValues(COLUMN_4_2_ENUM_VALUES)
+                    .creator(USER_2)
                     .build(),
             TableColumn.builder()
                     .id(COLUMN_4_3_ID)
@@ -3290,6 +3336,7 @@ public abstract class BaseTest {
                     .autoGenerated(COLUMN_4_3_AUTO_GENERATED)
                     .isPrimaryKey(COLUMN_4_3_PRIMARY)
                     .enumValues(COLUMN_4_3_ENUM_VALUES)
+                    .creator(USER_2)
                     .build(),
             TableColumn.builder()
                     .id(COLUMN_4_4_ID)
@@ -3304,6 +3351,7 @@ public abstract class BaseTest {
                     .autoGenerated(COLUMN_4_4_AUTO_GENERATED)
                     .isPrimaryKey(COLUMN_4_4_PRIMARY)
                     .enumValues(COLUMN_4_4_ENUM_VALUES)
+                    .creator(USER_2)
                     .build(),
             TableColumn.builder()
                     .id(COLUMN_4_5_ID)
@@ -3318,6 +3366,7 @@ public abstract class BaseTest {
                     .autoGenerated(COLUMN_4_5_AUTO_GENERATED)
                     .isPrimaryKey(COLUMN_4_5_PRIMARY)
                     .enumValues(COLUMN_4_5_ENUM_VALUES)
+                    .creator(USER_2)
                     .build(),
             TableColumn.builder()
                     .id(COLUMN_4_6_ID)
@@ -3332,6 +3381,7 @@ public abstract class BaseTest {
                     .autoGenerated(COLUMN_4_6_AUTO_GENERATED)
                     .isPrimaryKey(COLUMN_4_6_PRIMARY)
                     .enumValues(COLUMN_4_6_ENUM_VALUES)
+                    .creator(USER_2)
                     .build(),
             TableColumn.builder()
                     .id(COLUMN_4_7_ID)
@@ -3346,6 +3396,7 @@ public abstract class BaseTest {
                     .autoGenerated(COLUMN_4_7_AUTO_GENERATED)
                     .isPrimaryKey(COLUMN_4_7_PRIMARY)
                     .enumValues(COLUMN_4_7_ENUM_VALUES)
+                    .creator(USER_2)
                     .build(),
             TableColumn.builder()
                     .id(COLUMN_4_8_ID)
@@ -3360,6 +3411,7 @@ public abstract class BaseTest {
                     .autoGenerated(COLUMN_4_8_AUTO_GENERATED)
                     .isPrimaryKey(COLUMN_4_8_PRIMARY)
                     .enumValues(COLUMN_4_8_ENUM_VALUES)
+                    .creator(USER_2)
                     .build(),
             TableColumn.builder()
                     .id(COLUMN_4_9_ID)
@@ -3374,6 +3426,7 @@ public abstract class BaseTest {
                     .autoGenerated(COLUMN_4_9_AUTO_GENERATED)
                     .isPrimaryKey(COLUMN_4_9_PRIMARY)
                     .enumValues(COLUMN_4_9_ENUM_VALUES)
+                    .creator(USER_2)
                     .build(),
             TableColumn.builder()
                     .id(COLUMN_4_10_ID)
@@ -3388,6 +3441,7 @@ public abstract class BaseTest {
                     .autoGenerated(COLUMN_4_10_AUTO_GENERATED)
                     .isPrimaryKey(COLUMN_4_10_PRIMARY)
                     .enumValues(COLUMN_4_10_ENUM_VALUES)
+                    .creator(USER_2)
                     .build(),
             TableColumn.builder()
                     .id(COLUMN_4_11_ID)
@@ -3402,6 +3456,7 @@ public abstract class BaseTest {
                     .autoGenerated(COLUMN_4_11_AUTO_GENERATED)
                     .isPrimaryKey(COLUMN_4_11_PRIMARY)
                     .enumValues(COLUMN_4_11_ENUM_VALUES)
+                    .creator(USER_2)
                     .build(),
             TableColumn.builder()
                     .id(COLUMN_4_12_ID)
@@ -3416,6 +3471,7 @@ public abstract class BaseTest {
                     .autoGenerated(COLUMN_4_12_AUTO_GENERATED)
                     .isPrimaryKey(COLUMN_4_12_PRIMARY)
                     .enumValues(COLUMN_4_12_ENUM_VALUES)
+                    .creator(USER_2)
                     .build(),
             TableColumn.builder()
                     .id(COLUMN_4_13_ID)
@@ -3430,6 +3486,7 @@ public abstract class BaseTest {
                     .autoGenerated(COLUMN_4_13_AUTO_GENERATED)
                     .isPrimaryKey(COLUMN_4_13_PRIMARY)
                     .enumValues(COLUMN_4_13_ENUM_VALUES)
+                    .creator(USER_2)
                     .build(),
             TableColumn.builder()
                     .id(COLUMN_4_14_ID)
@@ -3444,6 +3501,7 @@ public abstract class BaseTest {
                     .autoGenerated(COLUMN_4_14_AUTO_GENERATED)
                     .isPrimaryKey(COLUMN_4_14_PRIMARY)
                     .enumValues(COLUMN_4_14_ENUM_VALUES)
+                    .creator(USER_2)
                     .build(),
             TableColumn.builder()
                     .id(COLUMN_4_15_ID)
@@ -3458,6 +3516,7 @@ public abstract class BaseTest {
                     .autoGenerated(COLUMN_4_15_AUTO_GENERATED)
                     .isPrimaryKey(COLUMN_4_15_PRIMARY)
                     .enumValues(COLUMN_4_15_ENUM_VALUES)
+                    .creator(USER_2)
                     .build(),
             TableColumn.builder()
                     .id(COLUMN_4_16_ID)
@@ -3472,6 +3531,7 @@ public abstract class BaseTest {
                     .autoGenerated(COLUMN_4_16_AUTO_GENERATED)
                     .isPrimaryKey(COLUMN_4_16_PRIMARY)
                     .enumValues(COLUMN_4_16_ENUM_VALUES)
+                    .creator(USER_2)
                     .build(),
             TableColumn.builder()
                     .id(COLUMN_4_17_ID)
@@ -3486,6 +3546,7 @@ public abstract class BaseTest {
                     .autoGenerated(COLUMN_4_17_AUTO_GENERATED)
                     .isPrimaryKey(COLUMN_4_17_PRIMARY)
                     .enumValues(COLUMN_4_17_ENUM_VALUES)
+                    .creator(USER_2)
                     .build(),
             TableColumn.builder()
                     .id(COLUMN_4_18_ID)
@@ -3500,6 +3561,7 @@ public abstract class BaseTest {
                     .autoGenerated(COLUMN_4_18_AUTO_GENERATED)
                     .isPrimaryKey(COLUMN_4_18_PRIMARY)
                     .enumValues(COLUMN_4_18_ENUM_VALUES)
+                    .creator(USER_2)
                     .build(),
             TableColumn.builder()
                     .id(COLUMN_4_19_ID)
@@ -3514,6 +3576,7 @@ public abstract class BaseTest {
                     .autoGenerated(COLUMN_4_19_AUTO_GENERATED)
                     .isPrimaryKey(COLUMN_4_19_PRIMARY)
                     .enumValues(COLUMN_4_19_ENUM_VALUES)
+                    .creator(USER_2)
                     .build(),
             TableColumn.builder()
                     .id(COLUMN_4_20_ID)
@@ -3528,6 +3591,7 @@ public abstract class BaseTest {
                     .autoGenerated(COLUMN_4_20_AUTO_GENERATED)
                     .isPrimaryKey(COLUMN_4_20_PRIMARY)
                     .enumValues(COLUMN_4_20_ENUM_VALUES)
+                    .creator(USER_2)
                     .build(),
             TableColumn.builder()
                     .id(COLUMN_4_21_ID)
@@ -3542,6 +3606,7 @@ public abstract class BaseTest {
                     .autoGenerated(COLUMN_4_21_AUTO_GENERATED)
                     .isPrimaryKey(COLUMN_4_21_PRIMARY)
                     .enumValues(COLUMN_4_21_ENUM_VALUES)
+                    .creator(USER_2)
                     .build());
 
     public final static Constraints TABLE_4_CONSTRAINTS = Constraints.builder()
@@ -3560,7 +3625,6 @@ public abstract class BaseTest {
             .routingKey(TABLE_4_ROUTING_KEY)
             .columns(TABLE_4_COLUMNS)
             .constraints(TABLE_4_CONSTRAINTS)
-            .createdBy(USER_1_ID)
             .creator(USER_1)
             .build();
 
@@ -3627,6 +3691,7 @@ public abstract class BaseTest {
                     .autoGenerated(COLUMN_5_1_AUTO_GENERATED)
                     .isPrimaryKey(COLUMN_5_1_PRIMARY)
                     .enumValues(COLUMN_5_1_ENUM_VALUES)
+                    .creator(USER_2)
                     .build(),
             TableColumn.builder()
                     .id(COLUMN_5_2_ID)
@@ -3641,6 +3706,7 @@ public abstract class BaseTest {
                     .autoGenerated(COLUMN_5_2_AUTO_GENERATED)
                     .isPrimaryKey(COLUMN_5_2_PRIMARY)
                     .enumValues(COLUMN_5_2_ENUM_VALUES)
+                    .creator(USER_2)
                     .build(),
             TableColumn.builder()
                     .id(COLUMN_5_3_ID)
@@ -3655,6 +3721,7 @@ public abstract class BaseTest {
                     .autoGenerated(COLUMN_5_3_AUTO_GENERATED)
                     .isPrimaryKey(COLUMN_5_3_PRIMARY)
                     .enumValues(COLUMN_5_3_ENUM_VALUES)
+                    .creator(USER_2)
                     .build());
 
     public final static Constraints TABLE_5_CONSTRAINTS = Constraints.builder()
@@ -3673,7 +3740,6 @@ public abstract class BaseTest {
             .routingKey(TABLE_5_ROUTING_KEY)
             .columns(TABLE_5_COLUMNS)
             .constraints(TABLE_5_CONSTRAINTS)
-            .createdBy(USER_1_ID)
             .creator(USER_1)
             .created(TABLE_5_CREATED)
             .lastModified(TABLE_5_LAST_MODIFIED)
@@ -3778,6 +3844,7 @@ public abstract class BaseTest {
                     .autoGenerated(COLUMN_6_1_AUTO_GENERATED)
                     .isPrimaryKey(COLUMN_6_1_PRIMARY)
                     .enumValues(COLUMN_6_1_ENUM_VALUES)
+                    .creator(USER_2)
                     .build(),
             TableColumn.builder()
                     .id(COLUMN_6_2_ID)
@@ -3792,6 +3859,7 @@ public abstract class BaseTest {
                     .autoGenerated(COLUMN_6_2_AUTO_GENERATED)
                     .isPrimaryKey(COLUMN_6_2_PRIMARY)
                     .enumValues(COLUMN_6_2_ENUM_VALUES)
+                    .creator(USER_2)
                     .build());
 
     public final static Table TABLE_6 = Table.builder()
@@ -3804,7 +3872,6 @@ public abstract class BaseTest {
             .tdbid(DATABASE_2_ID)
             .queueName(TABLE_6_QUEUE_NAME)
             .routingKey(TABLE_6_ROUTING_KEY)
-            .createdBy(USER_1_ID)
             .columns(TABLE_6_COLUMNS)
             .creator(USER_1)
             .created(TABLE_6_CREATED)
@@ -3821,7 +3888,6 @@ public abstract class BaseTest {
             .tdbid(DATABASE_1_ID)
             .queueName(TABLE_7_QUEUE_NAME)
             .routingKey(TABLE_7_ROUTING_KEY)
-            .createdBy(USER_1_ID)
             .columns(List.of())
             .creator(USER_1)
             .build();
@@ -4053,6 +4119,7 @@ public abstract class BaseTest {
     public final static String IDENTIFIER_1_DESCRIPTION = "Selecting all from the weather Austrian table";
     public final static String IDENTIFIER_1_DESCRIPTION_MODIFY = "Selecting some from the weather Austrian table";
     public final static String IDENTIFIER_1_TITLE = "Austrian weather data";
+    public final static String IDENTIFIER_1_MODIFY_TITLE = "Austrian weather data2";
     public final static String IDENTIFIER_1_TITLE_MODIFY = "Austrian weather some data";
     public final static String IDENTIFIER_1_DOI = null;
     public final static String IDENTIFIER_1_DOI_NOT_NULL = "10.1000/183";
@@ -4080,7 +4147,6 @@ public abstract class BaseTest {
             .lastname(CREATOR_1_LASTNAME)
             .orcid(CREATOR_1_ORCID)
             .affiliation(CREATOR_1_AFFIL)
-            .createdBy(IDENTIFIER_1_CREATED_BY)
             .creator(IDENTIFIER_1_CREATOR)
             .build();
 
@@ -4112,7 +4178,6 @@ public abstract class BaseTest {
             .resultNumber(IDENTIFIER_1_RESULT_NUMBER)
             .publisher(IDENTIFIER_1_PUBLISHER)
             .type(IDENTIFIER_1_TYPE)
-            .createdBy(USER_1_ID)
             .creator(USER_1)
             .creators(List.of(IDENTIFIER_1_CREATOR_1))
             .build();
@@ -4137,7 +4202,6 @@ public abstract class BaseTest {
             .resultNumber(IDENTIFIER_1_RESULT_NUMBER)
             .publisher(IDENTIFIER_1_PUBLISHER)
             .type(IDENTIFIER_1_TYPE)
-            .createdBy(USER_1_ID)
             .creator(null /* for jpa */)
             .creators(List.of() /* for jpa */)
             .build();
@@ -4163,7 +4227,6 @@ public abstract class BaseTest {
             .publisher(IDENTIFIER_1_PUBLISHER)
             .type(IDENTIFIER_1_TYPE)
             .creator(USER_1)
-            .createdBy(USER_1_ID)
             .creators(List.of(IDENTIFIER_1_CREATOR_1))
             .build();
 
@@ -4239,38 +4302,40 @@ public abstract class BaseTest {
     public final static UUID IDENTIFIER_2_CREATED_BY = USER_2_ID;
     public final static User IDENTIFIER_2_CREATOR = USER_2;
 
+    public final static Long IDENTIFIER_2_CREATOR_1_ID = 2L;
+
     public final static Creator IDENTIFIER_2_CREATOR_1 = Creator.builder()
-            .id(CREATOR_1_ID)
+            .id(IDENTIFIER_2_CREATOR_1_ID)
             .pid(IDENTIFIER_2_ID)
             .firstname(CREATOR_1_FIRSTNAME)
             .lastname(CREATOR_1_LASTNAME)
             .orcid(CREATOR_1_ORCID)
             .affiliation(CREATOR_1_AFFIL)
-            .createdBy(IDENTIFIER_2_CREATED_BY)
             .creator(IDENTIFIER_2_CREATOR)
             .build();
 
     public final static CreatorDto IDENTIFIER_2_CREATOR_1_DTO = CreatorDto.builder()
-            .id(CREATOR_1_ID)
+            .id(IDENTIFIER_2_CREATOR_1_ID)
             .firstname(CREATOR_1_FIRSTNAME)
             .lastname(CREATOR_1_LASTNAME)
             .orcid(CREATOR_1_ORCID)
             .affiliation(CREATOR_1_AFFIL)
             .build();
 
+    public final static Long IDENTIFIER_2_CREATOR_2_ID = 3L;
+
     public final static Creator IDENTIFIER_2_CREATOR_2 = Creator.builder()
-            .id(CREATOR_2_ID)
+            .id(IDENTIFIER_2_CREATOR_2_ID)
             .pid(IDENTIFIER_2_ID)
             .firstname(CREATOR_2_FIRSTNAME)
             .lastname(CREATOR_2_LASTNAME)
             .orcid(CREATOR_2_ORCID)
             .affiliation(CREATOR_2_AFFIL)
-            .createdBy(IDENTIFIER_2_CREATED_BY)
             .creator(IDENTIFIER_2_CREATOR)
             .build();
 
     public final static CreatorDto IDENTIFIER_2_CREATOR_2_DTO = CreatorDto.builder()
-            .id(CREATOR_2_ID)
+            .id(IDENTIFIER_2_CREATOR_2_ID)
             .firstname(CREATOR_2_FIRSTNAME)
             .lastname(CREATOR_2_LASTNAME)
             .orcid(CREATOR_2_ORCID)
@@ -4298,7 +4363,6 @@ public abstract class BaseTest {
             .resultNumber(IDENTIFIER_2_RESULT_NUMBER)
             .publisher(IDENTIFIER_2_PUBLISHER)
             .type(IDENTIFIER_2_TYPE)
-            .createdBy(USER_2_ID)
             .creator(USER_2)
             .creators(List.of(IDENTIFIER_2_CREATOR_1, IDENTIFIER_2_CREATOR_2))
             .build();
@@ -4324,7 +4388,6 @@ public abstract class BaseTest {
             .resultNumber(IDENTIFIER_2_RESULT_NUMBER)
             .publisher(IDENTIFIER_2_PUBLISHER)
             .type(IDENTIFIER_2_TYPE)
-            .createdBy(USER_2_ID)
             .creator(null /* for jpa */)
             .creators(List.of() /* for jpa */)
             .build();
@@ -4450,28 +4513,16 @@ public abstract class BaseTest {
             .type(IDENTIFIER_1_TYPE_DTO)
             .build();
 
-    public final static IdentifierCreateDto IDENTIFIER_1_DTO_TRUSTED_REQUEST = IdentifierCreateDto.builder()
+    public final static IdentifierUpdateDto IDENTIFIER_1_DTO_UPDATE_REQUEST = IdentifierUpdateDto.builder()
             .cid(IDENTIFIER_1_CONTAINER_ID)
             .dbid(IDENTIFIER_1_DATABASE_ID)
             .description(IDENTIFIER_1_DESCRIPTION)
-            .title(IDENTIFIER_1_TITLE)
-            .relatedIdentifiers(List.of())
-            .publicationMonth(IDENTIFIER_1_PUBLICATION_MONTH)
-            .publicationYear(IDENTIFIER_1_PUBLICATION_YEAR)
-            .creators(List.of(CREATOR_1_CREATE_DTO))
-            .publisher(IDENTIFIER_1_PUBLISHER)
-            .type(IDENTIFIER_1_TYPE_DTO)
-            .build();
-
-    public final static IdentifierCreateDto IDENTIFIER_1_DTO_SELF_REQUEST = IdentifierCreateDto.builder()
-            .cid(IDENTIFIER_1_CONTAINER_ID)
-            .dbid(IDENTIFIER_1_DATABASE_ID)
-            .description(IDENTIFIER_1_DESCRIPTION)
-            .title(IDENTIFIER_1_TITLE)
+            .title(IDENTIFIER_1_MODIFY_TITLE)
+            .doi(IDENTIFIER_1_DOI)
             .relatedIdentifiers(List.of())
             .publicationMonth(IDENTIFIER_1_PUBLICATION_MONTH)
             .publicationYear(IDENTIFIER_1_PUBLICATION_YEAR)
-            .creators(List.of(CREATOR_1_CREATE_DTO))
+            .creators(List.of(CREATOR_1_DTO))
             .publisher(IDENTIFIER_1_PUBLISHER)
             .type(IDENTIFIER_1_TYPE_DTO)
             .build();
@@ -4514,6 +4565,23 @@ public abstract class BaseTest {
             .type(IDENTIFIER_2_TYPE_DTO)
             .build();
 
+    public final static IdentifierUpdateDto IDENTIFIER_2_DTO_UPDATE_REQUEST = IdentifierUpdateDto.builder()
+            .qid(IDENTIFIER_2_QUERY_ID)
+            .cid(IDENTIFIER_2_CONTAINER_ID)
+            .qid(IDENTIFIER_2_QUERY_ID)
+            .dbid(IDENTIFIER_2_DATABASE_ID)
+            .description(IDENTIFIER_2_DESCRIPTION)
+            .title(IDENTIFIER_2_TITLE)
+            .doi(IDENTIFIER_2_DOI)
+            .relatedIdentifiers(List.of(IDENTIFIER_1_RELATED_IDENTIFIER_2_CREATE_DTO))
+            .publicationDay(IDENTIFIER_2_PUBLICATION_DAY)
+            .publicationMonth(IDENTIFIER_2_PUBLICATION_MONTH)
+            .publicationYear(IDENTIFIER_2_PUBLICATION_YEAR)
+            .creators(List.of(CREATOR_1_DTO, CREATOR_2_DTO))
+            .publisher(IDENTIFIER_2_PUBLISHER)
+            .type(IDENTIFIER_2_TYPE_DTO)
+            .build();
+
     public final static Long IDENTIFIER_3_ID = 3L;
     public final static Long IDENTIFIER_3_QUERY_ID = QUERY_3_ID;
     public final static Long IDENTIFIER_3_CONTAINER_ID = CONTAINER_3_ID;
@@ -4538,57 +4606,60 @@ public abstract class BaseTest {
     public final static UUID IDENTIFIER_3_CREATOR_ID = USER_3_ID;
     public final static User IDENTIFIER_3_CREATOR = USER_3;
 
+    private final static Long IDENTIFIER_3_CREATOR_1_ID = 4L;
+
     public final static Creator IDENTIFIER_3_CREATOR_1 = Creator.builder()
-            .id(CREATOR_1_ID)
+            .id(IDENTIFIER_3_CREATOR_1_ID)
             .pid(IDENTIFIER_3_ID)
             .firstname(CREATOR_1_FIRSTNAME)
             .lastname(CREATOR_1_LASTNAME)
             .orcid(CREATOR_1_ORCID)
             .affiliation(CREATOR_1_AFFIL)
-            .createdBy(IDENTIFIER_3_CREATOR_ID)
             .creator(IDENTIFIER_3_CREATOR)
             .build();
 
     public final static CreatorDto IDENTIFIER_3_CREATOR_1_DTO = CreatorDto.builder()
-            .id(CREATOR_1_ID)
+            .id(IDENTIFIER_3_CREATOR_1_ID)
             .firstname(CREATOR_1_FIRSTNAME)
             .lastname(CREATOR_1_LASTNAME)
             .orcid(CREATOR_1_ORCID)
             .affiliation(CREATOR_1_AFFIL)
             .build();
 
+    private final static Long IDENTIFIER_3_CREATOR_2_ID = 5L;
+
     public final static Creator IDENTIFIER_3_CREATOR_2 = Creator.builder()
-            .id(CREATOR_2_ID)
+            .id(IDENTIFIER_3_CREATOR_2_ID)
             .pid(IDENTIFIER_3_ID)
             .firstname(CREATOR_2_FIRSTNAME)
             .lastname(CREATOR_2_LASTNAME)
             .orcid(CREATOR_2_ORCID)
             .affiliation(CREATOR_2_AFFIL)
-            .createdBy(IDENTIFIER_3_CREATOR_ID)
             .creator(IDENTIFIER_3_CREATOR)
             .build();
 
     public final static CreatorDto IDENTIFIER_3_CREATOR_2_DTO = CreatorDto.builder()
-            .id(CREATOR_2_ID)
+            .id(IDENTIFIER_3_CREATOR_2_ID)
             .firstname(CREATOR_2_FIRSTNAME)
             .lastname(CREATOR_2_LASTNAME)
             .orcid(CREATOR_2_ORCID)
             .affiliation(CREATOR_2_AFFIL)
             .build();
 
+    private final static Long IDENTIFIER_3_CREATOR_3_ID = 6L;
+
     public final static Creator IDENTIFIER_3_CREATOR_3 = Creator.builder()
-            .id(CREATOR_3_ID)
+            .id(IDENTIFIER_3_CREATOR_3_ID)
             .pid(IDENTIFIER_3_ID)
             .firstname(CREATOR_3_FIRSTNAME)
             .lastname(CREATOR_3_LASTNAME)
             .orcid(CREATOR_3_ORCID)
             .affiliation(CREATOR_3_AFFIL)
-            .createdBy(IDENTIFIER_3_CREATOR_ID)
             .creator(IDENTIFIER_3_CREATOR)
             .build();
 
     public final static CreatorDto IDENTIFIER_3_CREATOR_3_DTO = CreatorDto.builder()
-            .id(CREATOR_3_ID)
+            .id(IDENTIFIER_3_CREATOR_3_ID)
             .firstname(CREATOR_3_FIRSTNAME)
             .lastname(CREATOR_3_LASTNAME)
             .orcid(CREATOR_3_ORCID)
@@ -4616,7 +4687,6 @@ public abstract class BaseTest {
             .resultNumber(IDENTIFIER_3_RESULT_NUMBER)
             .publisher(IDENTIFIER_3_PUBLISHER)
             .type(IDENTIFIER_3_TYPE)
-            .createdBy(IDENTIFIER_3_CREATOR_ID)
             .creator(IDENTIFIER_3_CREATOR)
             .creators(List.of(IDENTIFIER_3_CREATOR_1, IDENTIFIER_3_CREATOR_2, IDENTIFIER_3_CREATOR_3))
             .build();
@@ -4642,7 +4712,6 @@ public abstract class BaseTest {
             .resultNumber(IDENTIFIER_3_RESULT_NUMBER)
             .publisher(IDENTIFIER_3_PUBLISHER)
             .type(IDENTIFIER_3_TYPE)
-            .createdBy(USER_3_ID)
             .creator(null /* for jpa */)
             .creators(List.of() /* for jpa */)
             .build();
@@ -4686,28 +4755,17 @@ public abstract class BaseTest {
             .type(IDENTIFIER_3_TYPE_DTO)
             .build();
 
-    public final static IdentifierCreateDto IDENTIFIER_3_DTO_TRUSTED_REQUEST = IdentifierCreateDto.builder()
-            .cid(IDENTIFIER_3_CONTAINER_ID)
-            .dbid(IDENTIFIER_3_DATABASE_ID)
-            .description(IDENTIFIER_3_DESCRIPTION)
-            .title(IDENTIFIER_3_TITLE)
-            .relatedIdentifiers(List.of())
-            .publicationMonth(IDENTIFIER_3_PUBLICATION_MONTH)
-            .publicationYear(IDENTIFIER_3_PUBLICATION_YEAR)
-            .creators(List.of(CREATOR_1_CREATE_DTO))
-            .publisher(IDENTIFIER_3_PUBLISHER)
-            .type(IDENTIFIER_3_TYPE_DTO)
-            .build();
-
-    public final static IdentifierCreateDto IDENTIFIER_3_DTO_SELF_REQUEST = IdentifierCreateDto.builder()
+    public final static IdentifierUpdateDto IDENTIFIER_3_DTO_UPDATE_REQUEST = IdentifierUpdateDto.builder()
             .cid(IDENTIFIER_3_CONTAINER_ID)
             .dbid(IDENTIFIER_3_DATABASE_ID)
+            .qid(IDENTIFIER_3_QUERY_ID)
             .description(IDENTIFIER_3_DESCRIPTION)
             .title(IDENTIFIER_3_TITLE)
+            .doi(IDENTIFIER_3_DOI)
             .relatedIdentifiers(List.of())
             .publicationMonth(IDENTIFIER_3_PUBLICATION_MONTH)
             .publicationYear(IDENTIFIER_3_PUBLICATION_YEAR)
-            .creators(List.of(CREATOR_1_CREATE_DTO))
+            .creators(List.of(CREATOR_1_DTO))
             .publisher(IDENTIFIER_3_PUBLISHER)
             .type(IDENTIFIER_3_TYPE_DTO)
             .build();
@@ -4754,7 +4812,6 @@ public abstract class BaseTest {
             .resultNumber(IDENTIFIER_4_RESULT_NUMBER)
             .publisher(IDENTIFIER_4_PUBLISHER)
             .type(IDENTIFIER_4_TYPE)
-            .createdBy(USER_3_ID)
             .creator(USER_3)
             .creators(List.of())
             .build();
@@ -4779,7 +4836,6 @@ public abstract class BaseTest {
             .resultNumber(IDENTIFIER_4_RESULT_NUMBER)
             .publisher(IDENTIFIER_4_PUBLISHER)
             .type(IDENTIFIER_4_TYPE)
-            .createdBy(USER_3_ID)
             .creator(null /* for jpa */)
             .creators(List.of() /* for jpa */)
             .build();
diff --git a/dbrepo-table-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationReadTest.java b/dbrepo-table-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationReadTest.java
index d6e09d1624..7f209d1d86 100644
--- a/dbrepo-table-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationReadTest.java
+++ b/dbrepo-table-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationReadTest.java
@@ -100,8 +100,8 @@ public class TableServiceIntegrationReadTest extends BaseUnitTest {
         containerRepository.save(CONTAINER_1_SIMPLE);
         containerRepository.save(CONTAINER_2_SIMPLE);
         databaseRepository.save(DATABASE_1_SIMPLE);
-        tableRepository.save(TABLE_1_SIMPLE);
-        tableRepository.save(TABLE_2_SIMPLE);
+        tableRepository.save(TABLE_1);
+        tableRepository.save(TABLE_2);
     }
 
     @Test
diff --git a/dbrepo-table-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationWriteTest.java b/dbrepo-table-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationWriteTest.java
index 4fab7905dd..2bdbfed18a 100644
--- a/dbrepo-table-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationWriteTest.java
+++ b/dbrepo-table-service/rest-service/src/test/java/at/tuwien/service/TableServiceIntegrationWriteTest.java
@@ -29,6 +29,7 @@ import java.security.Principal;
 import java.util.List;
 
 import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyList;
 import static org.mockito.Mockito.doNothing;
@@ -99,8 +100,8 @@ public class TableServiceIntegrationWriteTest extends BaseUnitTest {
         containerRepository.save(CONTAINER_1_SIMPLE);
         containerRepository.save(CONTAINER_2_SIMPLE);
         databaseRepository.save(DATABASE_1_SIMPLE);
-        tableRepository.save(TABLE_1_SIMPLE);
-        tableRepository.save(TABLE_2_SIMPLE);
+        tableRepository.save(TABLE_1);
+        tableRepository.save(TABLE_2);
     }
 
     @AfterEach
@@ -181,6 +182,22 @@ public class TableServiceIntegrationWriteTest extends BaseUnitTest {
 
         /* test */
         tableService.deleteTable(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID);
+        assertTrue(userRepository.findById(TABLE_1_CREATED_BY).isPresent());
+        assertTrue(databaseRepository.findById(TABLE_1_DATABASE_ID).isPresent());
+    }
+
+    @Test
+    public void delete_notFound_fails() {
+
+        /* mock */
+        doNothing()
+                .when(tableidxRepository)
+                .delete(any(TableDto.class));
+
+        /* test */
+        assertThrows(TableNotFoundException.class, () -> {
+            tableService.deleteTable(CONTAINER_1_ID, DATABASE_1_ID, 9999L);
+        });
     }
 
 }
diff --git a/dbrepo-table-service/services/src/main/java/at/tuwien/mapper/TableMapper.java b/dbrepo-table-service/services/src/main/java/at/tuwien/mapper/TableMapper.java
index 311067b40c..d12f4c9e43 100644
--- a/dbrepo-table-service/services/src/main/java/at/tuwien/mapper/TableMapper.java
+++ b/dbrepo-table-service/services/src/main/java/at/tuwien/mapper/TableMapper.java
@@ -208,7 +208,6 @@ public interface TableMapper {
             @Mapping(source = "table.creator", target = "creator"),
             @Mapping(source = "table", target = "table"),
             @Mapping(target = "id", ignore = true),
-            @Mapping(target = "createdBy", source = "table.createdBy"),
             @Mapping(target = "autoGenerated", expression = "java(data.getInternalName() == \"id\" && query.getGenerated())"),
             @Mapping(source = "data.name", target = "name"),
             @Mapping(source = "data.internalName", target = "internalName"),
diff --git a/dbrepo-table-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java b/dbrepo-table-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java
index 4e27bb9b51..8523187a3a 100644
--- a/dbrepo-table-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java
+++ b/dbrepo-table-service/services/src/main/java/at/tuwien/service/impl/TableServiceImpl.java
@@ -2,7 +2,6 @@ package at.tuwien.service.impl;
 
 import at.tuwien.api.database.table.TableCreateDto;
 import at.tuwien.api.database.table.TableCreateRawQuery;
-import at.tuwien.api.database.table.TableDto;
 import at.tuwien.api.database.table.columns.concepts.ColumnSemanticsUpdateDto;
 import at.tuwien.entities.container.Container;
 import at.tuwien.entities.database.Database;
@@ -98,14 +97,10 @@ public class TableServiceImpl extends HibernateConnector implements TableService
         } finally {
             dataSource.close();
         }
-        log.info("Deleted table with id {}", table.getId());
-        log.trace("deleted table {}", table);
-        /* delete in database_index - elastic search */
-        tableIdxRepository.deleteById(tableId);
-        /* delete in column_index - elastic search */
-        table.getColumns()
-                .forEach(column -> tableColumnIdxRepository.deleteById(column.getId()));
-        log.info("Deleted columns in elastic search with id {}", databaseId);
+        tableRepository.delete(table);
+        log.info("Deleted table with id {} in metadata database", table.getId());
+        tableIdxRepository.delete(tableMapper.tableToTableDto(table));
+        log.info("Deleted table with id {} in search service", table.getId());
     }
 
     @Override
@@ -174,7 +169,7 @@ public class TableServiceImpl extends HibernateConnector implements TableService
         tmp.setColumns(List.of());
         tmp.setConstraints(null);
         final User creator = userService.findByUsername(principal.getName());
-        tmp.setCreatedBy(creator.getId());
+        tmp.setCreator(creator);
         /* save in metadata database */
         final Table entity = tableRepository.save(tmp);
         entity.setColumns(createDto.getColumns()
diff --git a/dbrepo-ui/api/identifier.service.js b/dbrepo-ui/api/identifier.service.js
index 9410ccf904..5372e0711d 100644
--- a/dbrepo-ui/api/identifier.service.js
+++ b/dbrepo-ui/api/identifier.service.js
@@ -51,8 +51,25 @@ class IdentifierService {
         })
         .catch((error) => {
           const { code, message } = error
-          console.error('Failed to load identifier', error)
-          Vue.$toast.error(`[${code}] Failed to load identifier: ${message}`)
+          console.error('Failed to create identifier', error)
+          Vue.$toast.error(`[${code}] Failed to create identifier: ${message}`)
+          reject(error)
+        })
+    })
+  }
+
+  update (id, data) {
+    return new Promise((resolve, reject) => {
+      api.put(`/api/pid/${id}`, data, { headers: { Accept: 'application/json' } })
+        .then((response) => {
+          const identifier = response.data
+          console.debug('response identifier', identifier)
+          resolve(identifier)
+        })
+        .catch((error) => {
+          const { code, message } = error
+          console.error('Failed to update identifier', error)
+          Vue.$toast.error(`[${code}] Failed to update identifier: ${message}`)
           reject(error)
         })
     })
diff --git a/dbrepo-ui/components/dialogs/DeleteIdentifier.vue b/dbrepo-ui/components/dialogs/DeleteIdentifier.vue
new file mode 100644
index 0000000000..85f0f50795
--- /dev/null
+++ b/dbrepo-ui/components/dialogs/DeleteIdentifier.vue
@@ -0,0 +1,97 @@
+<template>
+  <div>
+    <v-card>
+      <v-card-title v-text="title" />
+      <v-card-text>
+        <v-row dense>
+          <v-col>
+            This action cannot be undone! Type the identifier <strong>{{ confirmText }}</strong> below if you really want to delete it.
+          </v-col>
+        </v-row>
+        <v-row dense>
+          <v-col>
+            <v-text-field
+              id="confirm"
+              v-model="confirm"
+              name="confirm"
+              label="Identifier *"
+              autofocus
+              required />
+          </v-col>
+        </v-row>
+      </v-card-text>
+      <v-card-actions>
+        <v-spacer />
+        <v-btn
+          class="mb-2"
+          @click="cancel">
+          Cancel
+        </v-btn>
+        <v-btn
+          class="mb-2 mr-1"
+          color="error"
+          :loading="loadingDelete"
+          :disabled="confirm !== confirmText"
+          @click="deleteIdentifier">
+          Delete
+        </v-btn>
+      </v-card-actions>
+    </v-card>
+  </div>
+</template>
+
+<script>
+import IdentifierService from '@/api/identifier.service'
+
+export default {
+  props: {
+    identifier: {
+      type: Object,
+      default () {
+        return {}
+      }
+    }
+  },
+  data () {
+    return {
+      confirm: null,
+      loadingDelete: false
+    }
+  },
+  computed: {
+    title () {
+      if (this.identifier.doi) {
+        return `DOI ${this.identifier.doi}`
+      }
+      return `Identifier with id ${this.identifier.id}`
+    },
+    confirmText () {
+      if (this.identifier.doi) {
+        return this.identifier.doi
+      }
+      return `/pid/${this.identifier.id}`
+    }
+  },
+  methods: {
+    cancel () {
+      this.$parent.$parent.$parent.persistQueryDialog = false
+      this.$emit('close', { action: 'closed' })
+    },
+    deleteIdentifier () {
+      if (!this.identifier.id) {
+        return
+      }
+      this.loadingDelete = true
+      IdentifierService.delete(this.identifier.id)
+        .then(() => {
+          console.info('Deleted identifier with id ', this.identifier.id)
+          this.$toast.success('Successfully deleted identifier with id ' + this.identifier.id)
+          this.$emit('close', { action: 'deleted' })
+        })
+        .finally(() => {
+          this.loadingDelete = false
+        })
+    }
+  }
+}
+</script>
diff --git a/dbrepo-ui/components/dialogs/Persist.vue b/dbrepo-ui/components/dialogs/Persist.vue
index d44f784ca5..9eceb29062 100644
--- a/dbrepo-ui/components/dialogs/Persist.vue
+++ b/dbrepo-ui/components/dialogs/Persist.vue
@@ -1,7 +1,7 @@
 <template>
   <div>
     <v-card>
-      <v-card-title v-text="`Persist ${title}`" />
+      <v-card-title v-text="title" />
       <v-card-text>
         <v-alert
           v-if="isSubset"
@@ -167,6 +167,16 @@
           Cancel
         </v-btn>
         <v-btn
+          v-if="isUpdate"
+          class="mb-2"
+          :loading="loading"
+          :disabled="!formValid || loading"
+          color="primary"
+          @click="update">
+          Update
+        </v-btn>
+        <v-btn
+          v-if="!isUpdate"
           class="mb-2"
           :loading="loading"
           :disabled="!formValid || loading"
@@ -202,28 +212,7 @@ export default {
       loading: false,
       error: false, // XXX: `error` is never changed
       licenses: [],
-      identifier: {
-        cid: parseInt(this.$route.params.container_id),
-        dbid: parseInt(this.$route.params.database_id),
-        qid: parseInt(this.$route.params.query_id),
-        title: null,
-        description: null,
-        publisher: null,
-        publication_year: formatYearUTC(Date.now()),
-        publication_month: formatMonthUTC(Date.now()),
-        publication_day: formatDayUTC(Date.now()),
-        license: null,
-        type: this.type,
-        creators: [
-          {
-            firstname: null,
-            lastname: null,
-            affiliation: null,
-            orcid: null
-          }
-        ],
-        related_identifiers: []
-      },
+      identifier: {},
       relatedTypes: [
         { value: 'DOI' },
         { value: 'URL' },
@@ -298,13 +287,17 @@ export default {
     isDatabase () {
       return this.type === 'database'
     },
+    isUpdate () {
+      return this.identifier.id !== null
+    },
     title () {
+      let title = (this.isUpdate ? 'Update' : 'Assign') + ' '
       if (this.isSubset) {
-        return 'subset'
+        title += 'subset'
       } else if (this.isDatabase) {
-        return 'database'
+        title += 'database'
       }
-      return ''
+      return (title + ' identifier')
     },
     prefix () {
       if (this.isSubset) {
@@ -317,11 +310,12 @@ export default {
   },
   mounted () {
     this.loadLicenses()
-    this.identifier.publisher = this.$config.defaultPublisher
+    if (this.database.identifier) {
+      this.init(this.database.identifier)
+    }
   },
   methods: {
     cancel () {
-      this.$parent.$parent.$parent.persistQueryDialog = false
       this.$emit('close', { action: 'closed' })
     },
     addCreator () {
@@ -360,6 +354,18 @@ export default {
           this.loading = false
         })
     },
+    update () {
+      this.loading = true
+      IdentifierService.update(this.identifier.id, this.identifier)
+        .then(() => {
+          this.$store.dispatch('reloadDatabase')
+          this.$toast.success(this.prefix + ' successfully updated')
+          this.$emit('close', { action: 'persisted' })
+        })
+        .finally(() => {
+          this.loading = false
+        })
+    },
     loadLicenses () {
       if (!this.token) {
         return
@@ -372,6 +378,35 @@ export default {
         .finally(() => {
           this.loading = false
         })
+    },
+    init (identifier) {
+      if (identifier) {
+        console.debug('=====>', identifier)
+        this.identifier = Object.assign(identifier, {})
+        return
+      }
+      this.identifier = {
+        cid: parseInt(this.$route.params.container_id),
+        dbid: parseInt(this.$route.params.database_id),
+        qid: parseInt(this.$route.params.query_id),
+        title: null,
+        description: null,
+        publisher: this.$config.defaultPublisher,
+        publication_year: formatYearUTC(Date.now()),
+        publication_month: formatMonthUTC(Date.now()),
+        publication_day: formatDayUTC(Date.now()),
+        license: null,
+        type: this.type,
+        creators: [
+          {
+            firstname: null,
+            lastname: null,
+            affiliation: null,
+            orcid: null
+          }
+        ],
+        related_identifiers: []
+      }
     }
   }
 }
diff --git a/dbrepo-ui/pages/container/_container_id/database/_database_id/info.vue b/dbrepo-ui/pages/container/_container_id/database/_database_id/info.vue
index 62a3aadb51..e613944602 100644
--- a/dbrepo-ui/pages/container/_container_id/database/_database_id/info.vue
+++ b/dbrepo-ui/pages/container/_container_id/database/_database_id/info.vue
@@ -113,15 +113,22 @@
                 v-if="canCreateIdentifier"
                 small
                 color="primary"
-                @click="editDbDialog = true">
+                @click="persistDialog = true">
                 Get Database PID
               </v-btn>
               <v-btn
-                v-if="canDeleteIdentifier"
+                v-if="canEditIdentifier"
+                small
+                color="secondary"
+                @click="persistDialog = true">
+                Edit Database PID
+              </v-btn>
+              <v-btn
+                v-if="canDeleteIdentifier && hasIdentifier"
                 small
                 :loading="loadingDelete"
                 color="error"
-                @click="deleteIdentifier">
+                @click="deleteDialog = true">
                 Delete Database PID
               </v-btn>
             </v-card-actions>
@@ -214,10 +221,16 @@
       </v-tab-item>
     </v-tabs-items>
     <v-dialog
-      v-model="editDbDialog"
+      v-model="persistDialog"
       persistent
       max-width="860">
-      <Persist type="database" :database="database" @close="closeDialog" />
+      <Persist type="database" :database="database" @close="closePersistDialog" />
+    </v-dialog>
+    <v-dialog
+      v-model="deleteDialog"
+      persistent
+      max-width="480">
+      <DeleteIdentifier :identifier="identifier" @close="closeDeleteDialog" />
     </v-dialog>
     <v-breadcrumbs :items="items" class="pa-0 mt-2" />
   </div>
@@ -231,10 +244,11 @@ import Citation from '@/components/identifier/Citation'
 import { formatTimestampUTCLabel } from '@/utils'
 import Banner from '@/components/identifier/Banner'
 import DatabaseMapper from '@/api/database.mapper'
-import IdentifierService from '@/api/identifier.service'
+import DeleteIdentifier from '@/components/dialogs/DeleteIdentifier.vue'
 
 export default {
   components: {
+    DeleteIdentifier,
     DBToolbar,
     Persist,
     OrcidIcon,
@@ -245,7 +259,9 @@ export default {
     return {
       loading: false,
       loadingDelete: false,
-      editDbDialog: false,
+      editDialog: false,
+      deleteDialog: false,
+      persistDialog: false,
       items: [
         { text: 'Databases', to: '/container', activeClass: '' },
         {
@@ -288,7 +304,7 @@ export default {
       if (!this.database) {
         return null
       }
-      return this.$store.state?.database.identifier
+      return this.database.identifier
     },
     access () {
       return this.$store.state.access
@@ -332,8 +348,17 @@ export default {
       }
       return this.roles.includes('create-identifier') || this.roles.includes('create-foreign-identifier')
     },
+    canEditIdentifier () {
+      if (!this.roles) {
+        return false
+      }
+      if (!this.hasIdentifier) {
+        return false
+      }
+      return this.roles.includes('modify-identifier-metadata')
+    },
     canDeleteIdentifier () {
-      if (!this.user) {
+      if (!this.user || this.hasDoi) {
         return false
       }
       return this.roles.includes('delete-identifier')
@@ -362,6 +387,12 @@ export default {
       }
       return false
     },
+    hasDoi () {
+      if (!this.hasIdentifier) {
+        return false
+      }
+      return this.database.identifier.doi !== null
+    },
     accessDescription () {
       if (!this.access) {
         return
@@ -379,27 +410,18 @@ export default {
     }
   },
   methods: {
-    async closeDialog (event) {
+    async closePersistDialog (event) {
       if (event.action === 'persisted') {
-        await this.loadDatabase()
+        await this.$store.dispatch('reloadDatabase')
       }
-      this.editDbDialog = false
+      this.persistDialog = false
       this.editVisibilityDialog = false
     },
-    deleteIdentifier () {
-      if (!this.database.identifier.id) {
-        return
+    async closeDeleteDialog (event) {
+      if (event.action === 'deleted') {
+        await this.$store.dispatch('reloadDatabase')
       }
-      this.loadingDelete = true
-      IdentifierService.delete(this.database.identifier.id)
-        .then(async () => {
-          console.info('Deleted identifier with id ', this.database.identifier.id)
-          this.$toast.success('Successfully deleted identifier with id ' + this.database.identifier.id)
-          await this.$store.dispatch('reloadDatabase')
-        })
-        .finally(() => {
-          this.loadingDelete = false
-        })
+      this.deleteDialog = false
     }
   }
 }
-- 
GitLab