diff --git a/dbrepo-authentication-service/dbrepo-realm.json b/dbrepo-authentication-service/dbrepo-realm.json
index 6947bad026f5481d33856119f687844f2ef8f925..887674f1ab9ed8d1970045ccfa1a37c1ec82d70c 100644
--- a/dbrepo-authentication-service/dbrepo-realm.json
+++ b/dbrepo-authentication-service/dbrepo-realm.json
@@ -258,7 +258,7 @@
       "description" : "${default-data-steward-roles}",
       "composite" : true,
       "composites" : {
-        "realm" : [ "escalated-identifier-handling", "escalated-semantics-handling" ]
+        "realm" : [ "escalated-identifier-handling", "escalated-semantics-handling", "default-user-handling" ]
       },
       "clientRole" : false,
       "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0",
@@ -293,7 +293,7 @@
       "description" : "${escalated-semantics-handling}",
       "composite" : true,
       "composites" : {
-        "realm" : [ "create-ontology", "delete-ontology" ]
+        "realm" : [ "create-ontology", "delete-ontology", "modify-foreign-table-column-semantics" ]
       },
       "clientRole" : false,
       "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0",
@@ -365,6 +365,14 @@
       "clientRole" : false,
       "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0",
       "attributes" : { }
+    }, {
+      "id" : "d4f29937-3ca0-41e9-9786-2b7b921b6cdd",
+      "name" : "modify-foreign-table-column-semantics",
+      "description" : "${modify-foreign-table-column-semantics}",
+      "composite" : false,
+      "clientRole" : false,
+      "containerId" : "82c39861-d877-4667-a0f3-4daa2ee230e0",
+      "attributes" : { }
     }, {
       "id" : "8eda9f5c-938c-4915-bed5-6a81a1de15a8",
       "name" : "list-database-views",
@@ -1030,7 +1038,7 @@
   "otpPolicyLookAheadWindow" : 1,
   "otpPolicyPeriod" : 30,
   "otpPolicyCodeReusable" : false,
-  "otpSupportedApplications" : [ "totpAppMicrosoftAuthenticatorName", "totpAppGoogleName", "totpAppFreeOTPName" ],
+  "otpSupportedApplications" : [ "totpAppGoogleName", "totpAppFreeOTPName", "totpAppMicrosoftAuthenticatorName" ],
   "webAuthnPolicyRpEntityName" : "keycloak",
   "webAuthnPolicySignatureAlgorithms" : [ "ES256" ],
   "webAuthnPolicyRpId" : "",
@@ -2053,7 +2061,7 @@
       "subType" : "authenticated",
       "subComponents" : { },
       "config" : {
-        "allowed-protocol-mapper-types" : [ "oidc-full-name-mapper", "saml-user-attribute-mapper", "oidc-usermodel-property-mapper", "oidc-address-mapper", "saml-user-property-mapper", "oidc-usermodel-attribute-mapper", "saml-role-list-mapper", "oidc-sha256-pairwise-sub-mapper" ]
+        "allowed-protocol-mapper-types" : [ "oidc-usermodel-property-mapper", "oidc-full-name-mapper", "oidc-usermodel-attribute-mapper", "saml-user-property-mapper", "saml-role-list-mapper", "oidc-address-mapper", "oidc-sha256-pairwise-sub-mapper", "saml-user-attribute-mapper" ]
       }
     }, {
       "id" : "3ab11d74-5e76-408a-b85a-26bf8950f979",
@@ -2062,7 +2070,7 @@
       "subType" : "anonymous",
       "subComponents" : { },
       "config" : {
-        "allowed-protocol-mapper-types" : [ "saml-role-list-mapper", "saml-user-attribute-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-usermodel-property-mapper", "oidc-full-name-mapper", "saml-user-property-mapper", "oidc-usermodel-attribute-mapper", "oidc-address-mapper" ]
+        "allowed-protocol-mapper-types" : [ "oidc-usermodel-attribute-mapper", "saml-role-list-mapper", "oidc-address-mapper", "saml-user-attribute-mapper", "oidc-usermodel-property-mapper", "saml-user-property-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-full-name-mapper" ]
       }
     } ],
     "org.keycloak.keys.KeyProvider" : [ {
@@ -2114,7 +2122,7 @@
   "internationalizationEnabled" : false,
   "supportedLocales" : [ ],
   "authenticationFlows" : [ {
-    "id" : "78674e87-51ab-40ba-9ea5-b1ae1af14686",
+    "id" : "730765c7-b933-442f-98a8-6e0d53858c41",
     "alias" : "Account verification options",
     "description" : "Method with which to verity the existing account",
     "providerId" : "basic-flow",
@@ -2136,7 +2144,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "4246a8d3-31d4-4dc0-a491-91ad0ebfe616",
+    "id" : "6719a3b7-a2fd-4f2c-a533-6dcf0ec334c8",
     "alias" : "Authentication Options",
     "description" : "Authentication options.",
     "providerId" : "basic-flow",
@@ -2165,7 +2173,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "cb8d0d58-e8a2-4db2-88ac-3fd3ac769e55",
+    "id" : "2f17558d-ada7-426f-8eb4-5298758dc4af",
     "alias" : "Browser - Conditional OTP",
     "description" : "Flow to determine if the OTP is required for the authentication",
     "providerId" : "basic-flow",
@@ -2187,7 +2195,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "d09df934-4ac0-4dd7-b5fa-6ae4b48eaeee",
+    "id" : "938df868-97e0-4f21-b3b9-e9d33d03b39c",
     "alias" : "Direct Grant - Conditional OTP",
     "description" : "Flow to determine if the OTP is required for the authentication",
     "providerId" : "basic-flow",
@@ -2209,7 +2217,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "e26e3a1c-8540-4a1a-a44a-ce1b5da70c19",
+    "id" : "fe0ecfbc-042c-4007-a507-b7bab4a37f08",
     "alias" : "First broker login - Conditional OTP",
     "description" : "Flow to determine if the OTP is required for the authentication",
     "providerId" : "basic-flow",
@@ -2231,7 +2239,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "b5d17194-c21e-438b-bd58-187a70a98a31",
+    "id" : "822dfb8c-aed6-40d0-8126-7c1bf7fe658a",
     "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",
@@ -2253,7 +2261,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "1dd2d999-87a6-41a7-8fe7-86d3090ca0b2",
+    "id" : "03a6ffde-ed59-49c5-8d20-836f25690f8d",
     "alias" : "Reset - Conditional OTP",
     "description" : "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.",
     "providerId" : "basic-flow",
@@ -2275,7 +2283,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "38beafa8-7daf-4273-a18f-213af7111cbe",
+    "id" : "7efe11ce-09c9-4834-9630-e006f703cc80",
     "alias" : "User creation or linking",
     "description" : "Flow for the existing/non-existing user alternatives",
     "providerId" : "basic-flow",
@@ -2298,7 +2306,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "a701a337-4b1b-4856-8399-fdfa22b3f92a",
+    "id" : "c5dad7ff-453b-4792-91e5-3da229a44e15",
     "alias" : "Verify Existing Account by Re-authentication",
     "description" : "Reauthentication of existing account",
     "providerId" : "basic-flow",
@@ -2320,7 +2328,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "68e6d1b3-595c-4a92-9950-96d623ff91e3",
+    "id" : "0f78443a-a44a-4879-beeb-f58a243cc9ca",
     "alias" : "browser",
     "description" : "browser based authentication",
     "providerId" : "basic-flow",
@@ -2356,7 +2364,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "792000cd-85fe-4abc-9837-cf8f6ca4cdfd",
+    "id" : "bcf09a5f-2ead-4b5e-9768-0f7c774eb3b2",
     "alias" : "clients",
     "description" : "Base authentication for clients",
     "providerId" : "client-flow",
@@ -2392,7 +2400,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "89f2c77f-313b-49aa-8162-979c229d58e4",
+    "id" : "a4b48d58-7337-4053-b717-e62e3c8eba33",
     "alias" : "direct grant",
     "description" : "OpenID Connect Resource Owner Grant",
     "providerId" : "basic-flow",
@@ -2421,7 +2429,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "af512ed5-156d-4e4e-96e1-6d648c52e599",
+    "id" : "74d81399-4eb9-4982-9d38-33c33e45cfe4",
     "alias" : "docker auth",
     "description" : "Used by Docker clients to authenticate against the IDP",
     "providerId" : "basic-flow",
@@ -2436,7 +2444,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "a117196d-5479-481f-b704-3cff61c15084",
+    "id" : "7993e139-d713-45c7-9b92-fb2624f67f4a",
     "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",
@@ -2459,7 +2467,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "9e2577a4-1b38-421b-afbe-44004cd927a1",
+    "id" : "252ca365-eb9a-41a7-939f-f03cfb5f6f8c",
     "alias" : "forms",
     "description" : "Username, password, otp and other auth forms.",
     "providerId" : "basic-flow",
@@ -2481,7 +2489,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "85b4f758-8c22-4edc-8fbb-a21a36b3afd6",
+    "id" : "dddf77cf-ddf3-4f24-a600-f00e22244f5b",
     "alias" : "http challenge",
     "description" : "An authentication flow based on challenge-response HTTP Authentication Schemes",
     "providerId" : "basic-flow",
@@ -2503,7 +2511,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "3eb3523e-3ae2-4d7d-8778-37c8257bd546",
+    "id" : "66394e08-43ee-4a1d-9dc1-7fe85b099ca8",
     "alias" : "registration",
     "description" : "registration flow",
     "providerId" : "basic-flow",
@@ -2519,7 +2527,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "c479c0db-6acd-41be-8f00-4e5f1e9ba2ca",
+    "id" : "23873637-627e-4e5f-b4fd-51152614b516",
     "alias" : "registration form",
     "description" : "registration form",
     "providerId" : "form-flow",
@@ -2555,7 +2563,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "9c76b8ed-e8e2-4794-ad9e-5dab31f423c4",
+    "id" : "9741926c-d739-4c24-9a42-57774abc8fd1",
     "alias" : "reset credentials",
     "description" : "Reset credentials for a user if they forgot their password or something",
     "providerId" : "basic-flow",
@@ -2591,7 +2599,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "33fe3fb0-b198-41dd-81c2-e97fbe95380f",
+    "id" : "b7567a38-e720-45e0-9c6a-f4019787eace",
     "alias" : "saml ecp",
     "description" : "SAML ECP Profile Authentication Flow",
     "providerId" : "basic-flow",
@@ -2607,13 +2615,13 @@
     } ]
   } ],
   "authenticatorConfig" : [ {
-    "id" : "fd3fb013-0708-4af4-9b1e-1104109f8d2a",
+    "id" : "b5f895e9-cb7f-46b0-aa9b-3c4749d14135",
     "alias" : "create unique user config",
     "config" : {
       "require.password.update.after.registration" : "false"
     }
   }, {
-    "id" : "a8f8b4ca-cfad-4cbb-b233-ad3b0baf116a",
+    "id" : "4c8c4815-5dc5-4831-acdd-fe231e976d07",
     "alias" : "review profile config",
     "config" : {
       "update.profile.on.first.login" : "missing"
diff --git a/dbrepo-semantics-service/rest-service/src/main/java/at/tuwien/DbrepoSemanticsServiceApplication.java b/dbrepo-semantics-service/rest-service/src/main/java/at/tuwien/DbrepoSemanticsServiceApplication.java
index 78b4148a5c95cf6927c807fbf9706344ac91dade..bec2e19c3b2a0755da8c7352d63690bf8c121a9c 100644
--- a/dbrepo-semantics-service/rest-service/src/main/java/at/tuwien/DbrepoSemanticsServiceApplication.java
+++ b/dbrepo-semantics-service/rest-service/src/main/java/at/tuwien/DbrepoSemanticsServiceApplication.java
@@ -7,12 +7,10 @@ import org.springframework.boot.autoconfigure.domain.EntityScan;
 import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
 import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
 import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
-import org.springframework.transaction.annotation.EnableTransactionManagement;
 
 
 @EnableJpaAuditing
 @SpringBootApplication
-@EnableTransactionManagement
 @EntityScan(basePackages = {"at.tuwien.entities"})
 @EnableElasticsearchRepositories(basePackages = {"at.tuwien.repository.elastic"})
 @EnableJpaRepositories(basePackages = {"at.tuwien.repository.jpa"})
diff --git a/dbrepo-semantics-service/rest-service/src/main/java/at/tuwien/endpoints/OntologyEndpoint.java b/dbrepo-semantics-service/rest-service/src/main/java/at/tuwien/endpoints/OntologyEndpoint.java
index 9353601049d8e37f6925e7b17b5bd1955157cb3f..1cbcc7f86f283044814b86854605cae8ec332d23 100644
--- a/dbrepo-semantics-service/rest-service/src/main/java/at/tuwien/endpoints/OntologyEndpoint.java
+++ b/dbrepo-semantics-service/rest-service/src/main/java/at/tuwien/endpoints/OntologyEndpoint.java
@@ -18,7 +18,6 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 
 import jakarta.validation.Valid;
@@ -43,7 +42,6 @@ public class OntologyEndpoint {
     }
 
     @GetMapping
-    @Transactional(readOnly = true)
     @Timed(value = "semantics.ontology.list", description = "Time needed to list ontologies")
     @Operation(summary = "List all ontologies")
     @ApiResponses(value = {
@@ -64,7 +62,6 @@ public class OntologyEndpoint {
     }
 
     @GetMapping("/{id}")
-    @Transactional(readOnly = true)
     @Timed(value = "semantics.ontology.find", description = "Time needed to find a specific ontology")
     @Operation(summary = "Find one ontology")
     @ApiResponses(value = {
@@ -82,7 +79,6 @@ public class OntologyEndpoint {
     }
 
     @PostMapping
-    @Transactional
     @PreAuthorize("hasAuthority('create-ontology')")
     @Timed(value = "semantics.ontology.create", description = "Time needed to register a new ontology")
     @Operation(summary = "Register a new ontology", security = @SecurityRequirement(name = "bearerAuth"))
@@ -103,7 +99,6 @@ public class OntologyEndpoint {
     }
 
     @DeleteMapping("/{id}")
-    @Transactional
     @PreAuthorize("hasAuthority('delete-ontology')")
     @Timed(value = "semantics.ontology.delete", description = "Time needed to delete an ontology")
     @Operation(summary = "Delete an ontology", security = @SecurityRequirement(name = "bearerAuth"))
diff --git a/dbrepo-semantics-service/rest-service/src/main/java/at/tuwien/endpoints/QueryEndpoint.java b/dbrepo-semantics-service/rest-service/src/main/java/at/tuwien/endpoints/QueryEndpoint.java
index ceb1cdc6592457555cd29f9aa8a13f228d3245d5..5828965262702d36937192e32573faaaf6729bd9 100644
--- a/dbrepo-semantics-service/rest-service/src/main/java/at/tuwien/endpoints/QueryEndpoint.java
+++ b/dbrepo-semantics-service/rest-service/src/main/java/at/tuwien/endpoints/QueryEndpoint.java
@@ -20,7 +20,6 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.http.ResponseEntity;
 import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.List;
@@ -44,7 +43,6 @@ public class QueryEndpoint {
     }
 
     @PostMapping("/ontology/{id}/query")
-    @Transactional
     @PreAuthorize("hasAuthority('execute-semantic-query')")
     @Timed(value = "semantics.sparql.execute", description = "Time needed to execute a sparql query")
     @Operation(summary = "Register a new ontology", security = @SecurityRequirement(name = "bearerAuth"))
diff --git a/dbrepo-semantics-service/rest-service/src/main/java/at/tuwien/endpoints/SemanticsEndpoint.java b/dbrepo-semantics-service/rest-service/src/main/java/at/tuwien/endpoints/SemanticsEndpoint.java
index 805c743262c293440a1ac17416a10bf7bc2d713c..0e942b22e5ba264488ca3edf1a355ee9fb50ed96 100644
--- a/dbrepo-semantics-service/rest-service/src/main/java/at/tuwien/endpoints/SemanticsEndpoint.java
+++ b/dbrepo-semantics-service/rest-service/src/main/java/at/tuwien/endpoints/SemanticsEndpoint.java
@@ -18,7 +18,6 @@ import lombok.extern.log4j.Log4j2;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.ResponseEntity;
 import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 
 @Log4j2
@@ -37,7 +36,6 @@ public class SemanticsEndpoint {
     }
 
     @PostMapping("/concept")
-    @Transactional
     @PreAuthorize("hasAuthority('create-semantic-concept')")
     @Timed(value = "semantics.concept.save", description = "Time needed to create or update a semantic concept")
     @Operation(summary = "Create or update a semantic concept")
@@ -57,7 +55,6 @@ public class SemanticsEndpoint {
     }
 
     @PostMapping("/unit")
-    @Transactional
     @PreAuthorize("hasAuthority('create-semantic-unit')")
     @Timed(value = "semantics.unit.save", description = "Time needed to create or update a semantic unit")
     @Operation(summary = "Create or update a semantic unit")
diff --git a/dbrepo-semantics-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java b/dbrepo-semantics-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java
index 387c2e420cc64721bc0508314f17274183fbb364..cca4ac13eaee80431ae6fa826c703e13b324cc40 100644
--- a/dbrepo-semantics-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java
+++ b/dbrepo-semantics-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java
@@ -16,7 +16,6 @@ import lombok.extern.log4j.Log4j2;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.ResponseEntity;
 import org.springframework.security.access.prepost.PreAuthorize;
-import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.List;
@@ -35,7 +34,6 @@ public class TableEndpoint {
     }
 
     @GetMapping
-    @Transactional
     @PreAuthorize("hasAuthority('table-semantic-analyse')")
     @Timed(value = "semantics.table.analyse", description = "Time needed to analyse table semantics")
     @Operation(summary = "Suggest table semantics", security = @SecurityRequirement(name = "bearerAuth"))
diff --git a/dbrepo-semantics-service/services/src/main/java/at/tuwien/service/impl/SemanticServiceImpl.java b/dbrepo-semantics-service/services/src/main/java/at/tuwien/service/impl/SemanticServiceImpl.java
index 1007249b6e7983183b03d6e217eaaf64119de74c..66d9f751315b34f3ba2ef5343ba23b8451af391b 100644
--- a/dbrepo-semantics-service/services/src/main/java/at/tuwien/service/impl/SemanticServiceImpl.java
+++ b/dbrepo-semantics-service/services/src/main/java/at/tuwien/service/impl/SemanticServiceImpl.java
@@ -11,7 +11,6 @@ import at.tuwien.service.SemanticService;
 import lombok.extern.log4j.Log4j2;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
 
 @Log4j2
 @Service
@@ -30,7 +29,6 @@ public class SemanticServiceImpl implements SemanticService {
     }
 
     @Override
-    @Transactional
     public TableColumnConcept saveConcept(ConceptSaveDto data) {
         final TableColumnConcept entity = ontologyMapper.conceptSaveDtoToTableColumnConcept(data);
         final TableColumnConcept concept = tableColumnConceptRepository.save(entity);
@@ -39,7 +37,6 @@ public class SemanticServiceImpl implements SemanticService {
     }
 
     @Override
-    @Transactional
     public TableColumnUnit saveUnit(UnitSaveDto data) {
         final TableColumnUnit entity = ontologyMapper.unitSaveDtoToTableColumnUnit(data);
         final TableColumnUnit unit = tableColumnUnitRepository.save(entity);
diff --git a/dbrepo-table-service/rest-service/src/main/java/at/tuwien/endpoints/TableColumnEndpoint.java b/dbrepo-table-service/rest-service/src/main/java/at/tuwien/endpoints/TableColumnEndpoint.java
index 0977e057787e7dc965cad1492bc2b0beac759d3a..82d41b6d8662ff7689136c10e6678eeebc109523 100644
--- a/dbrepo-table-service/rest-service/src/main/java/at/tuwien/endpoints/TableColumnEndpoint.java
+++ b/dbrepo-table-service/rest-service/src/main/java/at/tuwien/endpoints/TableColumnEndpoint.java
@@ -4,6 +4,7 @@ import at.tuwien.api.database.table.columns.ColumnDto;
 import at.tuwien.api.database.table.columns.concepts.ColumnSemanticsUpdateDto;
 import at.tuwien.api.error.ApiErrorDto;
 import at.tuwien.entities.database.table.columns.TableColumn;
+import at.tuwien.entities.user.User;
 import at.tuwien.exception.*;
 import at.tuwien.mapper.TableMapper;
 import at.tuwien.service.TableService;
@@ -46,7 +47,7 @@ public class TableColumnEndpoint {
 
     @PutMapping
     @Transactional
-    @PreAuthorize("hasAuthority('modify-table-column-semantics')")
+    @PreAuthorize("hasAuthority('modify-table-column-semantics') or hasAuthority('modify-foreign-table-column-semantics')")
     @Timed(value = "semantics.column_update", description = "Time needed to update a table column semantic mapping")
     @Operation(summary = "Update a table column semantic mapping", security = @SecurityRequirement(name = "bearerAuth"))
     @ApiResponses(value = {
@@ -88,8 +89,10 @@ public class TableColumnEndpoint {
             SemanticEntityPersistException {
         log.debug("endpoint update table, containerId={}, databaseId={}, tableId={}, principal={}", containerId,
                 databaseId, tableId, principal);
-        endpointValidator.validateOnlyAccess(containerId, databaseId, principal, true);
-        endpointValidator.validateOnlyOwnerOrWriteAll(containerId, databaseId, tableId, principal);
+        if (!User.hasRole(principal, "modify-foreign-table-column-semantics")) {
+            endpointValidator.validateOnlyAccess(containerId, databaseId, principal, true);
+            endpointValidator.validateOnlyOwnerOrWriteAll(containerId, databaseId, tableId, principal);
+        }
         final TableColumn column = tableService.update(containerId, databaseId, tableId, columnId, updateDto, authorization);
         log.info("Updated table semantics of table with id {} and database with id {}", tableId, databaseId);
         final ColumnDto dto = tableMapper.tableColumnToColumnDto(column);
diff --git a/dbrepo-table-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java b/dbrepo-table-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java
index bc5c696fd912b6535ccf5adc778c29af0a738dd5..ab10207e973b73ece4339ab2072fbe77a60029ae 100644
--- a/dbrepo-table-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java
+++ b/dbrepo-table-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java
@@ -177,11 +177,9 @@ public class TableEndpoint {
                                              @NotNull @PathVariable("databaseId") Long databaseId,
                                              @NotNull @PathVariable("tableId") Long tableId,
                                              Principal principal)
-            throws TableNotFoundException, DatabaseNotFoundException, ContainerNotFoundException, NotAllowedException {
+            throws TableNotFoundException, DatabaseNotFoundException, ContainerNotFoundException {
         log.debug("endpoint find table, containerId={}, databaseId={}, tableId={}, principal={}", containerId,
                 databaseId, tableId, principal);
-//        endpointValidator.validateOnlyPrivateAccess(containerId, databaseId, principal);
-//        endpointValidator.validateOnlyPrivateHasRole(containerId, databaseId, principal, "find-table");
         final Table table = tableService.findById(containerId, databaseId, tableId);
         final TableDto dto = tableMapper.tableToTableDto(table);
         log.trace("find table resulted in table {}", dto);
diff --git a/dbrepo-table-service/services/src/main/java/at/tuwien/gateway/SemanticsServiceGateway.java b/dbrepo-table-service/services/src/main/java/at/tuwien/gateway/SemanticsServiceGateway.java
deleted file mode 100644
index f4534597104502eddb6f35eea6e7c9eb1185e628..0000000000000000000000000000000000000000
--- a/dbrepo-table-service/services/src/main/java/at/tuwien/gateway/SemanticsServiceGateway.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package at.tuwien.gateway;
-
-import at.tuwien.api.database.table.columns.concepts.ConceptDto;
-import at.tuwien.api.database.table.columns.concepts.ConceptSaveDto;
-import at.tuwien.api.database.table.columns.concepts.UnitDto;
-import at.tuwien.api.database.table.columns.concepts.UnitSaveDto;
-import at.tuwien.exception.SemanticEntityPersistException;
-
-public interface SemanticsServiceGateway {
-    ConceptDto saveConcept(ConceptSaveDto data, String authorization) throws SemanticEntityPersistException;
-
-    UnitDto saveUnit(UnitSaveDto data, String authorization) throws SemanticEntityPersistException;
-}
diff --git a/dbrepo-table-service/services/src/main/java/at/tuwien/gateway/impl/SemanticsServiceGatewayImpl.java b/dbrepo-table-service/services/src/main/java/at/tuwien/gateway/impl/SemanticsServiceGatewayImpl.java
deleted file mode 100644
index 16c8ea3c7a042daa5d0a824ec1301d118db39cdc..0000000000000000000000000000000000000000
--- a/dbrepo-table-service/services/src/main/java/at/tuwien/gateway/impl/SemanticsServiceGatewayImpl.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package at.tuwien.gateway.impl;
-
-import at.tuwien.api.database.table.columns.concepts.ConceptDto;
-import at.tuwien.api.database.table.columns.concepts.ConceptSaveDto;
-import at.tuwien.api.database.table.columns.concepts.UnitDto;
-import at.tuwien.api.database.table.columns.concepts.UnitSaveDto;
-import at.tuwien.exception.SemanticEntityPersistException;
-import at.tuwien.gateway.SemanticsServiceGateway;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.*;
-import org.springframework.stereotype.Service;
-import org.springframework.web.client.RestTemplate;
-
-@Slf4j
-@Service
-public class SemanticsServiceGatewayImpl implements SemanticsServiceGateway {
-
-    private final RestTemplate restTemplate;
-
-    @Autowired
-    public SemanticsServiceGatewayImpl(RestTemplate restTemplate) {
-        this.restTemplate = restTemplate;
-    }
-
-    @Override
-    public ConceptDto saveConcept(ConceptSaveDto data, String authorization) throws SemanticEntityPersistException {
-        final HttpHeaders headers = new HttpHeaders();
-        headers.set("Authorization", authorization);
-        final ResponseEntity<ConceptDto> response = restTemplate.exchange("/api/semantic/concept", HttpMethod.POST,
-                new HttpEntity<>(data, headers), ConceptDto.class);
-        if (!response.getStatusCode().equals(HttpStatus.ACCEPTED)) {
-            log.error("Failed to save concept with uri {}", data.getUri());
-            throw new SemanticEntityPersistException("Failed to save concept with uri " + data.getUri());
-        }
-        return response.getBody();
-    }
-
-    @Override
-    public UnitDto saveUnit(UnitSaveDto data, String authorization) throws SemanticEntityPersistException {
-        final HttpHeaders headers = new HttpHeaders();
-        headers.set("Authorization", authorization);
-        final ResponseEntity<UnitDto> response = restTemplate.exchange("/api/semantic/unit", HttpMethod.POST,
-                new HttpEntity<>(data, headers), UnitDto.class);
-        if (!response.getStatusCode().equals(HttpStatus.ACCEPTED)) {
-            log.error("Failed to save unit with uri {}", data.getUri());
-            throw new SemanticEntityPersistException("Failed to save unit with uri " + data.getUri());
-        }
-        return response.getBody();
-    }
-}
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 fae0a696e4cea9c71577c0ada10054c68baf944d..5dd576ce0fb3d26a1590c419a1869643ba1064d9 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
@@ -87,12 +87,12 @@ public interface TableMapper {
     @Mappings({
             @Mapping(source = "conceptUri", target = "uri")
     })
-    ConceptSaveDto columnSemanticsUpdateDtoToConceptSaveDto(ColumnSemanticsUpdateDto data);
+    TableColumnConcept columnSemanticsUpdateDtoToTableColumnConcept(ColumnSemanticsUpdateDto data);
 
     @Mappings({
             @Mapping(source = "unitUri", target = "uri")
     })
-    UnitSaveDto columnSemanticsUpdateDtoToUnitSaveDto(ColumnSemanticsUpdateDto data);
+    TableColumnUnit columnSemanticsUpdateDtoToTableColumnUnit(ColumnSemanticsUpdateDto data);
 
     default TableColumn columnNameToTableColumn(Table table, String name) throws TableMalformedException {
         String internalName = nameToInternalName(name);
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 b8168d4b2476b7c9f900b863816cc3a96aebf14e..9f46855a19dd069a71e28bf25d05f7060df204d9 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
@@ -11,7 +11,6 @@ import at.tuwien.entities.database.table.columns.TableColumnConcept;
 import at.tuwien.entities.database.table.columns.TableColumnUnit;
 import at.tuwien.entities.user.User;
 import at.tuwien.exception.*;
-import at.tuwien.gateway.SemanticsServiceGateway;
 import at.tuwien.mapper.TableMapper;
 import at.tuwien.repository.elastic.TableColumnIdxRepository;
 import at.tuwien.repository.elastic.TableIdxRepository;
@@ -49,7 +48,6 @@ public class TableServiceImpl extends HibernateConnector implements TableService
     private final ConceptRepository conceptRepository;
     private final TableIdxRepository tableIdxRepository;
     private final TableColumnRepository tableColumnRepository;
-    private final SemanticsServiceGateway semanticsServiceGateway;
     private final TableColumnIdxRepository tableColumnIdxRepository;
 
     @Autowired
@@ -57,7 +55,7 @@ public class TableServiceImpl extends HibernateConnector implements TableService
                             TableRepository tableRepository, DatabaseService databaseService,
                             ContainerService containerService, ConceptRepository conceptRepository,
                             TableIdxRepository tableIdxRepository, TableColumnRepository tableColumnRepository,
-                            SemanticsServiceGateway semanticsServiceGateway, TableColumnIdxRepository tableColumnIdxRepository) {
+                            TableColumnIdxRepository tableColumnIdxRepository) {
         this.tableMapper = tableMapper;
         this.userService = userService;
         this.unitRepository = unitRepository;
@@ -67,7 +65,6 @@ public class TableServiceImpl extends HibernateConnector implements TableService
         this.conceptRepository = conceptRepository;
         this.tableIdxRepository = tableIdxRepository;
         this.tableColumnRepository = tableColumnRepository;
-        this.semanticsServiceGateway = semanticsServiceGateway;
         this.tableColumnIdxRepository = tableColumnIdxRepository;
     }
 
@@ -217,12 +214,12 @@ public class TableServiceImpl extends HibernateConnector implements TableService
     public TableColumn update(Long containerId, Long databaseId, Long tableId, Long columnId,
                               ColumnSemanticsUpdateDto updateDto, String authorization)
             throws TableNotFoundException, DatabaseNotFoundException, ContainerNotFoundException,
-            TableMalformedException, UnitNotFoundException, ConceptNotFoundException, SemanticEntityPersistException {
+            TableMalformedException, UnitNotFoundException, ConceptNotFoundException {
         final Table table = findById(containerId, databaseId, tableId);
         final TableColumn column = findColumn(table, columnId);
         /* assign */
         if (updateDto.getUnitUri() != null) {
-            semanticsServiceGateway.saveUnit(tableMapper.columnSemanticsUpdateDtoToUnitSaveDto(updateDto), authorization);
+            unitRepository.save(tableMapper.columnSemanticsUpdateDtoToTableColumnUnit(updateDto));
             final TableColumnUnit unit = findUnit(updateDto.getUnitUri());
             column.setUnit(unit);
             log.debug("update unit of column, unit={}, column={}", unit, column);
@@ -231,7 +228,7 @@ public class TableServiceImpl extends HibernateConnector implements TableService
             log.debug("remove unit of column, column={}", column);
         }
         if (updateDto.getConceptUri() != null) {
-            semanticsServiceGateway.saveConcept(tableMapper.columnSemanticsUpdateDtoToConceptSaveDto(updateDto), authorization);
+            conceptRepository.save(tableMapper.columnSemanticsUpdateDtoToTableColumnConcept(updateDto));
             final TableColumnConcept concept = findConcept(updateDto.getConceptUri());
             column.setConcept(concept);
             log.debug("update ColumnConcept of column, concept={}, column={}", concept, column);
diff --git a/dbrepo-ui/api/database.service.js b/dbrepo-ui/api/database.service.js
index c01fc2ceae0933c0df03b49cdeccfc89d786b013..db440028953514abb7b97869dc1c21dac64a7109 100644
--- a/dbrepo-ui/api/database.service.js
+++ b/dbrepo-ui/api/database.service.js
@@ -107,7 +107,7 @@ class DatabaseService {
         .catch((error) => {
           const { code, message, response } = error
           const { status } = response
-          if (status !== 403 && status !== 405) { /* ignore no access errors */
+          if (status !== 401 && status !== 403 && status !== 405) { /* ignore no access errors */
             console.error('Failed to check database access', error)
             Vue.$toast.error(`[${code}] Failed to check database access: ${message}`)
             reject(error)
diff --git a/dbrepo-ui/components/dialogs/Semantics.vue b/dbrepo-ui/components/dialogs/Semantics.vue
index 7a5fb91c041e7e1ded9cdb43bf7e3cb3066395c6..f2f182d216442055ee8fd40d84df0e914851c3ff 100644
--- a/dbrepo-ui/components/dialogs/Semantics.vue
+++ b/dbrepo-ui/components/dialogs/Semantics.vue
@@ -4,8 +4,11 @@
       <v-card-title>Assign Semantic Information</v-card-title>
       <v-card-subtitle>We recommend the following ontologies</v-card-subtitle>
       <v-card-text>
-        <div v-for="(ontology,idx) in ontologies" :key="idx">
-          <strong>{{ ontology.prefix }}</strong>: <a :href="ontology.uri" target="_blank">{{ ontology.uri }}</a>
+        <v-skeleton-loader v-if="loadingOntologies" type="list-item-three-line" />
+        <div v-else>
+          <div v-for="(ontology,idx) in ontologies" :key="idx">
+            <strong>{{ ontology.prefix }}</strong>: <a :href="ontology.uri" target="_blank">{{ ontology.uri }}</a>
+          </div>
         </div>
       </v-card-text>
       <v-card-text>
@@ -20,7 +23,6 @@
               clearable
               single-line
               hide-details
-              :rules="[v => !!v || $t('Required')]"
               placeholder="http://www.wikidata.org/entity/Q468777"
               @click:clear="uri = null" />
           </v-toolbar>
@@ -84,6 +86,17 @@ export default {
   computed: {
   },
   watch: {
+    column () {
+      if (this.column.unit && this.mode === 'unit') {
+        this.uri = this.column.unit.uri
+        return
+      }
+      if (this.column.concept && this.mode === 'concept') {
+        this.uri = this.column.concept.uri
+        return
+      }
+      this.uri = null
+    }
   },
   mounted () {
     this.loadOntologies()
@@ -107,11 +120,8 @@ export default {
             action: 'assign'
           })
         })
-        .catch(() => {
-          this.loadingSave = true
-        })
         .finally(() => {
-          this.loadingSave = true
+          this.loadingSave = false
         })
     },
     loadOntologies () {
@@ -121,7 +131,7 @@ export default {
           this.ontologies = ontologies
         })
         .finally(() => {
-          this.loadingOntologies = true
+          this.loadingOntologies = false
         })
     },
     submit () {
diff --git a/dbrepo-ui/pages/container/_container_id/database/_database_id/table/_table_id/schema.vue b/dbrepo-ui/pages/container/_container_id/database/_database_id/table/_table_id/schema.vue
index ebcfc2d930cd965d99ca10a725b2cabe084c92af..d5c3d1b0778113e068d10088f25c87bce469a702 100644
--- a/dbrepo-ui/pages/container/_container_id/database/_database_id/table/_table_id/schema.vue
+++ b/dbrepo-ui/pages/container/_container_id/database/_database_id/table/_table_id/schema.vue
@@ -28,9 +28,9 @@
         <span v-if="item.auto_generated">●</span> {{ item.auto_generated }}
       </template>
       <template v-slot:item.column_concept="{ item }">
-        <v-btn v-if="canModify && !hasConcept(item)" small @click="pick(item, 'concept')">Assign</v-btn>
+        <v-btn v-if="canAssignSemanticInformation && !hasConcept(item)" small @click="pick(item, 'concept')">Assign</v-btn>
         <v-btn
-          v-if="canModify && hasConcept(item)"
+          v-if="canAssignSemanticInformation && hasConcept(item)"
           :title="item.concept.uri"
           color="secondary"
           small
@@ -38,15 +38,15 @@
           <span v-if="item.concept.name" v-text="item.concept.name" />
           <span v-else v-text="item.concept.uri" />
         </v-btn>
-        <a v-if="!canModify && hasConcept(item)" :href="item.concept.uri" target="_blank">
+        <a v-if="!canAssignSemanticInformation && hasConcept(item)" :href="item.concept.uri" target="_blank">
           <span v-if="item.concept.name" v-text="item.concept.name" />
           <span v-else v-text="item.concept.uri" />
         </a>
       </template>
       <template v-slot:item.column_unit="{ item }">
-        <v-btn v-if="canModify && !hasUnit(item)" small @click="pick(item, 'unit')">Assign</v-btn>
+        <v-btn v-if="canAssignSemanticInformation && !hasUnit(item)" small @click="pick(item, 'unit')">Assign</v-btn>
         <v-btn
-          v-if="canModify && hasUnit(item)"
+          v-if="canAssignSemanticInformation && hasUnit(item)"
           :title="item.unit.uri"
           color="secondary"
           small
@@ -54,7 +54,7 @@
           <span v-if="item.unit.name" v-text="item.unit.name" />
           <span v-else v-text="item.unit.uri" />
         </v-btn>
-        <a v-if="!canModify && hasUnit(item)" :href="item.unit.uri" target="_blank">
+        <a v-if="!canAssignSemanticInformation && hasUnit(item)" :href="item.unit.uri" target="_blank">
           <span v-if="item.unit.name" v-text="item.unit.name" />
           <span v-else v-text="item.unit.uri" />
         </a>
@@ -121,20 +121,6 @@ export default {
     }
   },
   computed: {
-    token () {
-      return this.$store.state.token
-    },
-    config () {
-      if (this.token === null) {
-        return {
-          headers: {},
-          progress: false
-        }
-      }
-      return {
-        headers: { Authorization: `Bearer ${this.token}` }
-      }
-    },
     user () {
       return this.$store.state.user
     },
@@ -147,12 +133,20 @@ export default {
     access () {
       return this.$store.state.access
     },
-    canModify () {
-      if (!this.token || !this.user.username) {
-        /* not yet loaded */
+    roles () {
+      return this.$store.state.roles
+    },
+    canAssignSemanticInformation () {
+      if (!this.user) {
+        return false
+      }
+      if (this.roles.includes('modify-foreign-table-column-semantics')) {
+        return true
+      }
+      if (!this.access) {
         return false
       }
-      return this.table.creator.username === this.user.username
+      return this.roles.includes('modify-table-column-semantics') && (this.access.type === 'write_all' || this.table.owner.username === this.user.username)
     },
     versionColor () {
       if (this.version === null) {