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 4b93e2f751ad1f2614bd239ae644733855b7e417..70f13b1f227608b48d96b7d29362c6ae483c9d68 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
@@ -16,6 +16,7 @@ import at.tuwien.api.database.table.TableCreateDto;
 import at.tuwien.api.database.table.TableCsvDto;
 import at.tuwien.api.database.table.columns.ColumnCreateDto;
 import at.tuwien.api.database.table.columns.ColumnTypeDto;
+import at.tuwien.api.database.table.columns.concepts.ColumnSemanticsUpdateDto;
 import at.tuwien.api.database.table.constraints.ConstraintsCreateDto;
 import at.tuwien.api.database.table.constraints.foreignKey.ForeignKeyCreateDto;
 import at.tuwien.api.identifier.*;
@@ -23,6 +24,7 @@ import at.tuwien.api.user.*;
 import at.tuwien.entities.container.image.ContainerImageDate;
 import at.tuwien.entities.database.*;
 import at.tuwien.entities.database.table.columns.TableColumnConcept;
+import at.tuwien.entities.database.table.columns.TableColumnUnit;
 import at.tuwien.entities.database.table.constraints.Constraints;
 import at.tuwien.entities.database.table.constraints.foreignKey.ForeignKey;
 import at.tuwien.entities.database.table.constraints.foreignKey.ForeignKeyReference;
@@ -1651,53 +1653,32 @@ public abstract class BaseTest {
     public final static Instant TABLE_8_CREATED = Instant.ofEpochSecond(1688400185) /* 2023-02-26 08:29:35 (UTC) */;
     public final static Instant TABLE_8_LAST_MODIFIED = Instant.ofEpochSecond(1688400185) /* 2023-02-26 08:29:35 (UTC) */;
 
-    public final static Table TABLE_8 = Table.builder()
-            .id(TABLE_8_ID)
-            .created(Instant.now())
-            .internalName(TABLE_8_INTERNAL_NAME)
-            .description(TABLE_8_DESCRIPTION)
-            .name(TABLE_8_NAME)
-            .tdbid(DATABASE_1_ID)
-            .queueName(TABLE_8_QUEUE_NAME)
-            .routingKey(TABLE_8_ROUTING_KEY)
-            .columns(List.of(TableColumn.builder()
-                            .id(1L)
-                            .ordinalPosition(0)
-                            .cdbid(DATABASE_3_ID)
-                            .tid(TABLE_8_ID)
-                            .name("ID")
-                            .internalName("id")
-                            .columnType(TableColumnType.NUMBER)
-                            .dfid(null)
-                            .isNullAllowed(false)
-                            .autoGenerated(true)
-                            .isPrimaryKey(true)
-                            .build(),
-                    TableColumn.builder()
-                            .id(2L)
-                            .ordinalPosition(1)
-                            .cdbid(DATABASE_3_ID)
-                            .tid(TABLE_8_ID)
-                            .name("Value")
-                            .internalName("value")
-                            .columnType(TableColumnType.DECIMAL)
-                            .dfid(null)
-                            .isNullAllowed(false)
-                            .autoGenerated(false)
-                            .isPrimaryKey(false)
-                            .build()))
-            .createdBy(USER_1_ID)
-            .creator(USER_1)
-            .created(TABLE_8_CREATED)
-            .lastModified(TABLE_8_LAST_MODIFIED)
-            .build();
-
     public final static TableCsvDto TABLE_8_CSV_DTO = TableCsvDto.builder()
             .data(new HashMap<>() {{
                 put("value", "2.1");
             }})
             .build();
 
+    public final static String COLUMN_CONCEPT_TEMPERATURE_NAME = "temperature";
+    public final static String COLUMN_CONCEPT_TEMPERATURE_URI = "https://www.wikidata.org/entity/Q11466";
+    public final static Instant COLUMN_CONCEPT_TEMPERATURE_CREATED = Instant.now();
+
+    public final static TableColumnConcept COLUMN_CONCEPT_TEMPERATURE = TableColumnConcept.builder()
+            .name(COLUMN_CONCEPT_TEMPERATURE_NAME)
+            .uri(COLUMN_CONCEPT_TEMPERATURE_URI)
+            .created(COLUMN_CONCEPT_TEMPERATURE_CREATED)
+            .build();
+
+    public final static String COLUMN_UNIT_DEGREES_CELSIUS_NAME = "Degrees Celsius";
+    public final static String COLUMN_UNIT_DEGREES_CELSIUS_URI = "http://www.ontology-of-units-of-measure.org/resource/om-2/degreeCelsius";
+    public final static Instant COLUMN_UNIT_DEGREES_CELSIUS_CREATED = Instant.now();
+
+    public final static TableColumnUnit COLUMN_UNIT_DEGREES_CELSIUS = TableColumnUnit.builder()
+            .name(COLUMN_UNIT_DEGREES_CELSIUS_NAME)
+            .uri(COLUMN_UNIT_DEGREES_CELSIUS_URI)
+            .created(COLUMN_CONCEPT_TEMPERATURE_CREATED)
+            .build();
+
     public final static Long COLUMN_1_1_ID = 1L;
     public final static Integer COLUMN_1_1_ORDINALPOS = 0;
     public final static Boolean COLUMN_1_1_PRIMARY = true;
@@ -1754,6 +1735,28 @@ public abstract class BaseTest {
     public final static String COLUMN_1_4_CHECK = null;
     public final static List<String> COLUMN_1_4_ENUM_VALUES = null;
 
+    public final static ColumnSemanticsUpdateDto COLUMN_1_4_SEMANTICS_UPDATE_DTO = ColumnSemanticsUpdateDto.builder()
+            .conceptUri(COLUMN_CONCEPT_TEMPERATURE_URI)
+            .unitUri(COLUMN_UNIT_DEGREES_CELSIUS_URI)
+            .build();
+
+    public final static TableColumn COLUMN_1_4_WITH_SEMANTICS = TableColumn.builder()
+            .id(COLUMN_1_4_ID)
+            .ordinalPosition(COLUMN_1_4_ORDINALPOS)
+            .cdbid(DATABASE_1_ID)
+            .tid(TABLE_1_ID)
+            .name(COLUMN_1_4_NAME)
+            .internalName(COLUMN_1_4_INTERNAL_NAME)
+            .columnType(COLUMN_1_4_TYPE)
+            .dfid(COLUMN_1_4_DATE_FORMAT)
+            .isNullAllowed(COLUMN_1_4_NULL)
+            .autoGenerated(COLUMN_1_4_AUTO_GENERATED)
+            .isPrimaryKey(COLUMN_1_4_PRIMARY)
+            .enumValues(COLUMN_1_4_ENUM_VALUES)
+            .concept(COLUMN_CONCEPT_TEMPERATURE)
+            .unit(COLUMN_UNIT_DEGREES_CELSIUS)
+            .build();
+
     public final static Long COLUMN_1_5_ID = 5L;
     public final static Integer COLUMN_1_5_ORDINALPOS = 4;
     public final static Boolean COLUMN_1_5_PRIMARY = false;
@@ -2170,6 +2173,100 @@ public abstract class BaseTest {
     public final static String COLUMN_5_4_CHECK = null;
     public final static List<String> COLUMN_5_4_ENUM_VALUES = null;
 
+    public final static Long COLUMN_8_1_ID = 26L;
+    public final static Integer COLUMN_8_1_ORDINALPOS = 0;
+    public final static Boolean COLUMN_8_1_PRIMARY = true;
+    public final static String COLUMN_8_1_NAME = "ID";
+    public final static String COLUMN_8_1_INTERNAL_NAME = "id";
+    public final static TableColumnType COLUMN_8_1_TYPE = TableColumnType.NUMBER;
+    public final static ColumnTypeDto COLUMN_8_1_TYPE_DTO = ColumnTypeDto.NUMBER;
+    public final static Long COLUMN_8_1_DATE_FORMAT = null;
+    public final static Boolean COLUMN_8_1_NULL = false;
+    public final static Boolean COLUMN_8_1_UNIQUE = true;
+    public final static Boolean COLUMN_8_1_AUTO_GENERATED = true;
+    public final static String COLUMN_8_1_FOREIGN_KEY = null;
+    public final static String COLUMN_8_1_CHECK = null;
+    public final static List<String> COLUMN_8_1_ENUM_VALUES = null;
+
+    public final static Long COLUMN_8_2_ID = 27L;
+    public final static Integer COLUMN_8_2_ORDINALPOS = 1;
+    public final static Boolean COLUMN_8_2_PRIMARY = true;
+    public final static String COLUMN_8_2_NAME = "ID";
+    public final static String COLUMN_8_2_INTERNAL_NAME = "id";
+    public final static TableColumnType COLUMN_8_2_TYPE = TableColumnType.NUMBER;
+    public final static ColumnTypeDto COLUMN_8_2_TYPE_DTO = ColumnTypeDto.NUMBER;
+    public final static Long COLUMN_8_2_DATE_FORMAT = null;
+    public final static Boolean COLUMN_8_2_NULL = false;
+    public final static Boolean COLUMN_8_2_UNIQUE = true;
+    public final static Boolean COLUMN_8_2_AUTO_GENERATED = true;
+    public final static String COLUMN_8_2_FOREIGN_KEY = null;
+    public final static String COLUMN_8_2_CHECK = null;
+    public final static List<String> COLUMN_8_2_ENUM_VALUES = null;
+
+    public final static ColumnSemanticsUpdateDto COLUMN_8_2_SEMANTICS_UPDATE_DTO = ColumnSemanticsUpdateDto.builder()
+            .conceptUri(COLUMN_CONCEPT_TEMPERATURE_URI)
+            .unitUri(COLUMN_UNIT_DEGREES_CELSIUS_URI)
+            .build();
+
+    public final static TableColumn COLUMN_8_2_WITH_SEMANTICS = TableColumn.builder()
+            .id(COLUMN_8_2_ID)
+            .ordinalPosition(COLUMN_8_2_ORDINALPOS)
+            .cdbid(DATABASE_3_ID)
+            .tid(TABLE_8_ID)
+            .name(COLUMN_8_2_NAME)
+            .internalName(COLUMN_8_2_INTERNAL_NAME)
+            .columnType(COLUMN_8_2_TYPE)
+            .dfid(COLUMN_8_2_DATE_FORMAT)
+            .isNullAllowed(COLUMN_8_2_NULL)
+            .autoGenerated(COLUMN_8_2_AUTO_GENERATED)
+            .isPrimaryKey(COLUMN_8_2_PRIMARY)
+            .unit(COLUMN_UNIT_DEGREES_CELSIUS)
+            .concept(COLUMN_CONCEPT_TEMPERATURE)
+            .build();
+
+    public final static List<TableColumn> TABLE_8_COLUMNS = List.of(TableColumn.builder()
+                    .id(COLUMN_8_1_ID)
+                    .ordinalPosition(COLUMN_8_1_ORDINALPOS)
+                    .cdbid(DATABASE_3_ID)
+                    .tid(TABLE_8_ID)
+                    .name(COLUMN_8_1_NAME)
+                    .internalName(COLUMN_8_1_INTERNAL_NAME)
+                    .columnType(COLUMN_8_1_TYPE)
+                    .dfid(COLUMN_8_1_DATE_FORMAT)
+                    .isNullAllowed(COLUMN_8_1_NULL)
+                    .autoGenerated(COLUMN_8_1_AUTO_GENERATED)
+                    .isPrimaryKey(COLUMN_8_1_PRIMARY)
+                    .build(),
+            TableColumn.builder()
+                    .id(COLUMN_8_2_ID)
+                    .ordinalPosition(COLUMN_8_2_ORDINALPOS)
+                    .cdbid(DATABASE_3_ID)
+                    .tid(TABLE_8_ID)
+                    .name(COLUMN_8_2_NAME)
+                    .internalName(COLUMN_8_2_INTERNAL_NAME)
+                    .columnType(COLUMN_8_2_TYPE)
+                    .dfid(COLUMN_8_2_DATE_FORMAT)
+                    .isNullAllowed(COLUMN_8_2_NULL)
+                    .autoGenerated(COLUMN_8_2_AUTO_GENERATED)
+                    .isPrimaryKey(COLUMN_8_2_PRIMARY)
+                    .build());
+
+    public final static Table TABLE_8 = Table.builder()
+            .id(TABLE_8_ID)
+            .created(Instant.now())
+            .internalName(TABLE_8_INTERNAL_NAME)
+            .description(TABLE_8_DESCRIPTION)
+            .name(TABLE_8_NAME)
+            .tdbid(DATABASE_1_ID)
+            .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)
+            .build();
+
     public final static List<String> CONSTRAINTS_1_UNIQUE_1 = List.of(COLUMN_1_1_NAME);
     public final static List<String> CONSTRAINTS_2_UNIQUE_1 = List.of(COLUMN_2_1_NAME);
     public final static List<String> CONSTRAINTS_3_UNIQUE_1 = List.of("id");
diff --git a/dbrepo-table-service/pom.xml b/dbrepo-table-service/pom.xml
index 60355319f10bdcb9745738a4fe41354c95b96ad0..46fde5c0506ed540b8ebaa6eb9c2d9529d55b0d0 100644
--- a/dbrepo-table-service/pom.xml
+++ b/dbrepo-table-service/pom.xml
@@ -233,7 +233,9 @@
                         <exclude>at/tuwien/mapper/**/*</exclude>
                         <exclude>at/tuwien/exception/**/*</exclude>
                         <exclude>at/tuwien/config/**/*</exclude>
-                        <exclude>**/DbrepoContainerManagingApplication.class</exclude>
+                        <exclude>at/tuwien/auth/**/*</exclude>
+                        <exclude>at/tuwien/handlers/**/*</exclude>
+                        <exclude>**/DbrepoTableServiceApplication.class</exclude>
                     </excludes>
                 </configuration>
                 <executions>
diff --git a/dbrepo-table-service/rest-service/src/main/java/at/tuwien/endpoints/AccessEndpoint.java b/dbrepo-table-service/rest-service/src/main/java/at/tuwien/endpoints/AccessEndpoint.java
deleted file mode 100644
index 412ca4a947e10b2ba1f6a91b6362aeb437fdaacb..0000000000000000000000000000000000000000
--- a/dbrepo-table-service/rest-service/src/main/java/at/tuwien/endpoints/AccessEndpoint.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package at.tuwien.endpoints;
-
-import at.tuwien.api.database.DatabaseAccessDto;
-import at.tuwien.api.error.ApiErrorDto;
-import at.tuwien.entities.database.DatabaseAccess;
-import at.tuwien.exception.AccessDeniedException;
-import at.tuwien.exception.NotAllowedException;
-import at.tuwien.mapper.DatabaseMapper;
-import at.tuwien.service.AccessService;
-import at.tuwien.service.DatabaseService;
-import io.micrometer.core.annotation.Timed;
-import io.swagger.v3.oas.annotations.Operation;
-import io.swagger.v3.oas.annotations.headers.Header;
-import io.swagger.v3.oas.annotations.media.Content;
-import io.swagger.v3.oas.annotations.media.Schema;
-import io.swagger.v3.oas.annotations.responses.ApiResponse;
-import io.swagger.v3.oas.annotations.responses.ApiResponses;
-import io.swagger.v3.oas.annotations.security.SecurityRequirement;
-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 javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
-import java.security.Principal;
-
-@Log4j2
-@CrossOrigin(origins = "*")
-@RestController
-@RequestMapping("/api/container/{id}/database/{databaseId}/table/{tableId}/access")
-public class AccessEndpoint {
-
-    private final AccessService accessService;
-    private final DatabaseMapper databaseMapper;
-
-    @Autowired
-    public AccessEndpoint(DatabaseService databaseService, AccessService accessService, DatabaseMapper databaseMapper) {
-        this.accessService = accessService;
-        this.databaseMapper = databaseMapper;
-    }
-
-    @GetMapping
-    @Transactional
-    @Timed(value = "access.check", description = "Time needed to check access to a table")
-    @PreAuthorize("hasAuthority('check-access')")
-    @Operation(summary = "Check access to some table", security = @SecurityRequirement(name = "bearerAuth"))
-    @ApiResponses(value = {
-            @ApiResponse(responseCode = "200",
-                    description = "Check access successfully",
-                    content = {@Content(
-                            mediaType = "application/json",
-                            schema = @Schema(implementation = DatabaseAccessDto.class))}),
-            @ApiResponse(responseCode = "403",
-                    description = "Access to the database is forbidden",
-                    content = {@Content(
-                            mediaType = "application/json",
-                            schema = @Schema(implementation = ApiErrorDto.class))}),
-            @ApiResponse(responseCode = "405",
-                    description = "Check access not permitted",
-                    content = {@Content(
-                            mediaType = "application/json",
-                            schema = @Schema(implementation = ApiErrorDto.class))}),
-    })
-    public ResponseEntity<DatabaseAccessDto> checkAccess(@NotBlank @PathVariable("id") Long containerId,
-                                                         @NotBlank @PathVariable("databaseId") Long databaseId,
-                                                         @NotBlank @PathVariable("tableId") Long tableId,
-                                                         @NotNull Principal principal)
-            throws AccessDeniedException {
-        log.debug("endpoint check access to database, containerId={}, databaseId={}, principal={}",
-                containerId, databaseId, principal);
-        final DatabaseAccess access = accessService.hasAccess(databaseId, tableId, principal.getName());
-        final DatabaseAccessDto dto = databaseMapper.databaseAccessToDatabaseAccessDto(access);
-        log.trace("check access resulted in dto {}", dto);
-        return ResponseEntity.ok(dto);
-    }
-
-}
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 24fe7d9b93e029ec46bae35d1aa05f6d543714b8..73df4fddb494a6f8b885c02c356798a1fe682220 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
@@ -1,6 +1,5 @@
 package at.tuwien.endpoints;
 
-import at.tuwien.api.database.DatabaseAccessDto;
 import at.tuwien.api.database.table.columns.ColumnDto;
 import at.tuwien.api.database.table.columns.concepts.ColumnSemanticsUpdateDto;
 import at.tuwien.api.error.ApiErrorDto;
@@ -8,6 +7,7 @@ import at.tuwien.entities.database.table.columns.TableColumn;
 import at.tuwien.exception.*;
 import at.tuwien.mapper.TableMapper;
 import at.tuwien.service.TableService;
+import at.tuwien.validation.EndpointValidator;
 import io.micrometer.core.annotation.Timed;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.media.Content;
@@ -34,11 +34,13 @@ public class TableColumnEndpoint {
 
     private final TableMapper tableMapper;
     private final TableService tableService;
+    private final EndpointValidator endpointValidator;
 
     @Autowired
-    public TableColumnEndpoint(TableMapper tableMapper, TableService tableService) {
+    public TableColumnEndpoint(TableMapper tableMapper, TableService tableService, EndpointValidator endpointValidator) {
         this.tableMapper = tableMapper;
         this.tableService = tableService;
+        this.endpointValidator = endpointValidator;
     }
 
     @PutMapping
@@ -78,11 +80,13 @@ public class TableColumnEndpoint {
                                             @NotNull @PathVariable("tableId") Long tableId,
                                             @NotNull @PathVariable("columnId") Long columnId,
                                             @NotNull @Valid @RequestBody ColumnSemanticsUpdateDto updateDto,
-                                            @NotNull Principal principal) throws NotAllowedException,
+                                            @NotNull Principal principal) throws
             TableNotFoundException, TableMalformedException, DatabaseNotFoundException,
-            ContainerNotFoundException, UnitNotFoundException, ConceptNotFoundException {
+            ContainerNotFoundException, UnitNotFoundException, ConceptNotFoundException, NotAllowedException {
         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);
         final TableColumn column = tableService.update(containerId, databaseId, tableId, columnId, updateDto, principal);
         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/validation/EndpointValidator.java b/dbrepo-table-service/rest-service/src/main/java/at/tuwien/validation/EndpointValidator.java
index 79326ff8a9267f781a92d7f7176a3e1d03eac28e..006f3b30a740aca837a50e657258848b83a1a6dc 100644
--- a/dbrepo-table-service/rest-service/src/main/java/at/tuwien/validation/EndpointValidator.java
+++ b/dbrepo-table-service/rest-service/src/main/java/at/tuwien/validation/EndpointValidator.java
@@ -3,11 +3,15 @@ package at.tuwien.validation;
 import at.tuwien.entities.database.AccessType;
 import at.tuwien.entities.database.Database;
 import at.tuwien.entities.database.DatabaseAccess;
+import at.tuwien.entities.database.table.Table;
 import at.tuwien.entities.user.User;
+import at.tuwien.exception.ContainerNotFoundException;
 import at.tuwien.exception.DatabaseNotFoundException;
 import at.tuwien.exception.NotAllowedException;
+import at.tuwien.exception.TableNotFoundException;
 import at.tuwien.service.AccessService;
 import at.tuwien.service.DatabaseService;
+import at.tuwien.service.TableService;
 import lombok.extern.log4j.Log4j2;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
@@ -20,15 +24,13 @@ public class EndpointValidator {
 
     private final AccessService accessService;
     private final DatabaseService databaseService;
+    private final TableService tableService;
 
     @Autowired
-    public EndpointValidator(AccessService accessService, DatabaseService databaseService) {
+    public EndpointValidator(AccessService accessService, DatabaseService databaseService, TableService tableService) {
         this.accessService = accessService;
         this.databaseService = databaseService;
-    }
-
-    public void validateOnlyAccess(Long containerId, Long databaseId, Principal principal) throws NotAllowedException, DatabaseNotFoundException {
-        validateOnlyAccess(containerId, databaseId, principal, false);
+        this.tableService = tableService;
     }
 
     public void validateOnlyPrivateAccess(Long containerId, Long databaseId, Principal principal, boolean writeAccessOnly) throws NotAllowedException, DatabaseNotFoundException {
@@ -45,34 +47,45 @@ public class EndpointValidator {
     }
 
     public void validateOnlyAccess(Long containerId, Long databaseId, Principal principal, boolean writeAccessOnly) throws NotAllowedException, DatabaseNotFoundException {
-        final Database database = databaseService.find(containerId, databaseId);
         if (principal == null) {
             log.error("Access not allowed: database with id {} is not public and no authorization provided", databaseId);
             throw new NotAllowedException("Access not allowed: database with id " + databaseId + " is not public and no authorization provided");
         }
-        log.trace("principal is {}", principal);
+        databaseService.find(containerId, databaseId);
+        log.trace("principal: {}", principal.getName());
         final DatabaseAccess access = accessService.find(databaseId, principal.getName());
-        log.trace("found access {}", access);
+        log.trace("found access: {}", access);
         if (writeAccessOnly && !(access.getType().equals(AccessType.WRITE_OWN) || access.getType().equals(AccessType.WRITE_ALL))) {
             log.error("Access not allowed: no write access");
             throw new NotAllowedException("Access not allowed: no write access");
         }
     }
 
-    public void validateOnlyOwner(Long containerId, Long databaseId, Principal principal)
-            throws DatabaseNotFoundException, NotAllowedException {
-        final Database database = databaseService.find(containerId, databaseId);
+    public void validateOnlyOwnerOrWriteAll(Long containerId, Long databaseId, Long tableId, Principal principal)
+            throws DatabaseNotFoundException, NotAllowedException, TableNotFoundException, ContainerNotFoundException {
         if (principal == null) {
             log.error("Access not allowed: no authorization provided");
             throw new NotAllowedException("Access not allowed: no authorization provided");
         }
-        log.trace("principal is {}", principal);
+        final Table table = tableService.findById(containerId, databaseId, tableId);
+        log.trace("principal: {}", principal.getName());
+        log.trace("table creator: {}", table.getCreator().getUsername());
         final DatabaseAccess access = accessService.find(databaseId, principal.getName());
         log.trace("found access {}", access);
-        if (!database.getOwner().equals(principal)) {
-            log.error("Access not allowed: not the owner of this database with id {}", databaseId);
-            throw new NotAllowedException("Access not allowed: not the owner of this database");
+        if (access.getType().equals(AccessType.READ)) {
+            log.error("Access not allowed: insufficient access (only read-access)");
+            throw new NotAllowedException("Access not allowed: insufficient access (only read-access)");
+        }
+        if (table.getCreator().equalsPrincipal(principal) && (access.getType().equals(AccessType.WRITE_OWN) || access.getType().equals(AccessType.WRITE_ALL))) {
+            log.trace("grant access: table creator with write access");
+            return;
+        }
+        if (access.getType().equals(AccessType.WRITE_ALL)) {
+            log.trace("grant access: write-all access");
+            return;
         }
+        log.error("Access not allowed: insufficient access (neither creator {} nor write-all access)", table.getCreator().getUsername());
+        throw new NotAllowedException("Access not allowed: insufficient access (neither creator nor write-all access)");
     }
 
     public void validateOnlyPrivateHasRole(Long containerId, Long databaseId, Principal principal, String role)
@@ -87,7 +100,7 @@ public class EndpointValidator {
             log.error("Access not allowed: no authorization provided");
             throw new NotAllowedException("Access not allowed: no authorization provided");
         }
-        log.trace("principal is {}", principal);
+        log.trace("principal: {}", principal.getName());
         if (!User.hasRole(principal, role)) {
             log.error("Access not allowed: role {} missing", role);
             throw new NotAllowedException("Access not allowed: role " + role + " missing");
diff --git a/dbrepo-table-service/rest-service/src/test/java/at/tuwien/endpoint/TableColumnEndpointUnitTest.java b/dbrepo-table-service/rest-service/src/test/java/at/tuwien/endpoint/TableColumnEndpointUnitTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..d1dd3b32603f7e4ebf80c9eb20b5bf30ad61071c
--- /dev/null
+++ b/dbrepo-table-service/rest-service/src/test/java/at/tuwien/endpoint/TableColumnEndpointUnitTest.java
@@ -0,0 +1,286 @@
+package at.tuwien.endpoint;
+
+import at.tuwien.BaseUnitTest;
+import at.tuwien.api.database.table.TableBriefDto;
+import at.tuwien.api.database.table.TableCreateDto;
+import at.tuwien.api.database.table.TableDto;
+import at.tuwien.api.database.table.columns.ColumnDto;
+import at.tuwien.api.database.table.columns.concepts.ColumnSemanticsUpdateDto;
+import at.tuwien.config.IndexConfig;
+import at.tuwien.config.ReadyConfig;
+import at.tuwien.endpoints.TableColumnEndpoint;
+import at.tuwien.endpoints.TableEndpoint;
+import at.tuwien.entities.container.Container;
+import at.tuwien.entities.database.Database;
+import at.tuwien.entities.database.DatabaseAccess;
+import at.tuwien.entities.database.table.Table;
+import at.tuwien.entities.database.table.columns.TableColumn;
+import at.tuwien.exception.*;
+import at.tuwien.repository.elastic.TableColumnIdxRepository;
+import at.tuwien.repository.elastic.TableIdxRepository;
+import at.tuwien.service.AccessService;
+import at.tuwien.service.ContainerService;
+import at.tuwien.service.DatabaseService;
+import at.tuwien.service.TableService;
+import com.rabbitmq.client.Channel;
+import lombok.extern.log4j.Log4j2;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.security.test.context.support.WithAnonymousUser;
+import org.springframework.security.test.context.support.WithMockUser;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import java.security.Principal;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.*;
+import static org.mockito.Mockito.*;
+
+@Log4j2
+@EnableAutoConfiguration(exclude = RabbitAutoConfiguration.class)
+@SpringBootTest
+@ExtendWith(SpringExtension.class)
+public class TableColumnEndpointUnitTest extends BaseUnitTest {
+
+    @MockBean
+    private ReadyConfig readyConfig;
+
+    @MockBean
+    private Channel channel;
+
+    @MockBean
+    private IndexConfig indexInitializer;
+
+    @MockBean
+    private TableIdxRepository tableidxRepository;
+
+    @MockBean
+    private TableColumnIdxRepository tableColumnidxRepository;
+
+    @MockBean
+    private AccessService accessService;
+
+    @MockBean
+    private DatabaseService databaseService;
+
+    @MockBean
+    private TableService tableService;
+
+    @Autowired
+    private TableColumnEndpoint tableColumnEndpoint;
+
+    @Test
+    @WithAnonymousUser
+    public void update_publicAnonymous_fails() {
+
+        /* test */
+        assertThrows(AccessDeniedException.class, () -> {
+            generic_update(CONTAINER_3_ID, DATABASE_3_ID, TABLE_8_ID, COLUMN_1_1_ID, DATABASE_3, TABLE_8, null, COLUMN_8_2_SEMANTICS_UPDATE_DTO, null, null, null);
+        });
+    }
+
+    @Test
+    @WithMockUser(username = USER_1_USERNAME, authorities = {"modify-table-column-semantics"})
+    public void update_publicHasRoleNoAccess_fails() {
+
+        /* test */
+        assertThrows(NotAllowedException.class, () -> {
+            generic_update(CONTAINER_3_ID, DATABASE_3_ID, TABLE_8_ID, COLUMN_1_1_ID, DATABASE_3, TABLE_8, null, COLUMN_8_2_SEMANTICS_UPDATE_DTO, USER_1_USERNAME, USER_1_PRINCIPAL, null);
+        });
+    }
+
+    @Test
+    @WithMockUser(username = USER_1_USERNAME, authorities = {"modify-table-column-semantics"})
+    public void update_publicHasRoleHasOnlyReadAccess_fails() {
+
+        /* test */
+        assertThrows(NotAllowedException.class, () -> {
+            generic_update(CONTAINER_3_ID, DATABASE_3_ID, TABLE_8_ID, COLUMN_1_1_ID, DATABASE_3, TABLE_8, null, COLUMN_8_2_SEMANTICS_UPDATE_DTO, USER_1_USERNAME, USER_1_PRINCIPAL, DATABASE_3_RESEARCHER_READ_ACCESS);
+        });
+    }
+
+    @Test
+    @WithMockUser(username = USER_1_USERNAME, authorities = {"modify-table-column-semantics"})
+    public void update_publicHasRoleHasOwnWriteAccess_succeeds() throws TableNotFoundException, NotAllowedException, TableMalformedException, UnitNotFoundException, DatabaseNotFoundException, ConceptNotFoundException, ContainerNotFoundException {
+
+        /* test */
+        generic_update(CONTAINER_3_ID, DATABASE_3_ID, TABLE_8_ID, COLUMN_1_1_ID, DATABASE_3, TABLE_8, COLUMN_8_2_WITH_SEMANTICS, COLUMN_8_2_SEMANTICS_UPDATE_DTO, USER_1_USERNAME, USER_1_PRINCIPAL, DATABASE_3_RESEARCHER_WRITE_OWN_ACCESS);
+    }
+
+    @Test
+    @WithMockUser(username = USER_2_USERNAME, authorities = {"modify-table-column-semantics"})
+    public void update_publicHasRoleForeignHasOwnWriteAccess_fails() {
+
+        /* test */
+        assertThrows(NotAllowedException.class, () -> {
+            generic_update(CONTAINER_3_ID, DATABASE_3_ID, TABLE_8_ID, COLUMN_1_1_ID, DATABASE_3, TABLE_8, null, COLUMN_8_2_SEMANTICS_UPDATE_DTO, USER_2_USERNAME, USER_2_PRINCIPAL, DATABASE_3_DEVELOPER_WRITE_OWN_ACCESS);
+        });
+    }
+
+    @Test
+    @WithMockUser(username = USER_1_USERNAME, authorities = {"modify-table-column-semantics"})
+    public void update_publicDatabaseNotFound_fails() {
+
+        /* test */
+        assertThrows(DatabaseNotFoundException.class, () -> {
+            generic_update(CONTAINER_3_ID, DATABASE_3_ID, TABLE_8_ID, COLUMN_1_1_ID, null, TABLE_8, null, COLUMN_8_2_SEMANTICS_UPDATE_DTO, USER_1_USERNAME, USER_1_PRINCIPAL, DATABASE_3_RESEARCHER_WRITE_OWN_ACCESS);
+        });
+    }
+
+    @Test
+    @WithMockUser(username = USER_1_USERNAME, authorities = {"modify-table-column-semantics"})
+    public void update_publicTableNotFound_fails() {
+
+        /* test */
+        assertThrows(TableNotFoundException.class, () -> {
+            generic_update(CONTAINER_3_ID, DATABASE_3_ID, TABLE_8_ID, COLUMN_1_1_ID, DATABASE_3, null, null, COLUMN_8_2_SEMANTICS_UPDATE_DTO, USER_1_USERNAME, USER_1_PRINCIPAL, DATABASE_3_RESEARCHER_WRITE_OWN_ACCESS);
+        });
+    }
+
+    @Test
+    @WithMockUser(username = USER_2_USERNAME, authorities = {"modify-table-column-semantics"})
+    public void update_publicHasRoleForeignHasAllWriteAccess_succeeds() throws TableNotFoundException,
+            NotAllowedException, TableMalformedException, UnitNotFoundException, DatabaseNotFoundException,
+            ConceptNotFoundException, ContainerNotFoundException {
+
+        /* test */
+        generic_update(CONTAINER_3_ID, DATABASE_3_ID, TABLE_8_ID, COLUMN_1_1_ID, DATABASE_3, TABLE_8, COLUMN_8_2_WITH_SEMANTICS, COLUMN_8_2_SEMANTICS_UPDATE_DTO, USER_2_USERNAME, USER_2_PRINCIPAL, DATABASE_3_DEVELOPER_WRITE_ALL_ACCESS);
+    }
+
+    /* ################################################################################################### */
+    /* ## PRIVATE DATABASES                                                                             ## */
+    /* ################################################################################################### */
+
+    @Test
+    @WithAnonymousUser
+    public void update_privateAnonymous_fails() {
+
+        /* test */
+        assertThrows(AccessDeniedException.class, () -> {
+            generic_update(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, COLUMN_1_1_ID, DATABASE_1, TABLE_1, null, COLUMN_1_4_SEMANTICS_UPDATE_DTO, null, null, null);
+        });
+    }
+
+    @Test
+    @WithMockUser(username = USER_1_USERNAME, authorities = {"modify-table-column-semantics"})
+    public void update_privateHasRoleNoAccess_fails() {
+
+        /* test */
+        assertThrows(NotAllowedException.class, () -> {
+            generic_update(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, COLUMN_1_1_ID, DATABASE_1, TABLE_1, null, COLUMN_1_4_SEMANTICS_UPDATE_DTO, USER_1_USERNAME, USER_1_PRINCIPAL, null);
+        });
+    }
+
+    @Test
+    @WithMockUser(username = USER_1_USERNAME, authorities = {"modify-table-column-semantics"})
+    public void update_privateHasRoleHasOnlyReadAccess_fails() {
+
+        /* test */
+        assertThrows(NotAllowedException.class, () -> {
+            generic_update(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, COLUMN_1_1_ID, DATABASE_1, TABLE_1, null, COLUMN_1_4_SEMANTICS_UPDATE_DTO, USER_1_USERNAME, USER_1_PRINCIPAL, DATABASE_1_RESEARCHER_READ_ACCESS);
+        });
+    }
+
+    @Test
+    @WithMockUser(username = USER_1_USERNAME, authorities = {"modify-table-column-semantics"})
+    public void update_privateHasRoleHasOwnWriteAccess_succeeds() throws TableNotFoundException, NotAllowedException, TableMalformedException, UnitNotFoundException, DatabaseNotFoundException, ConceptNotFoundException, ContainerNotFoundException {
+
+        /* test */
+        generic_update(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, COLUMN_1_1_ID, DATABASE_1, TABLE_1, COLUMN_1_4_WITH_SEMANTICS, COLUMN_1_4_SEMANTICS_UPDATE_DTO, USER_1_USERNAME, USER_1_PRINCIPAL, DATABASE_1_RESEARCHER_WRITE_OWN_ACCESS);
+    }
+
+    @Test
+    @WithMockUser(username = USER_2_USERNAME, authorities = {"modify-table-column-semantics"})
+    public void update_privateHasRoleForeignHasOwnWriteAccess_fails() {
+
+        /* test */
+        assertThrows(NotAllowedException.class, () -> {
+            generic_update(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, COLUMN_1_1_ID, DATABASE_1, TABLE_1, null, COLUMN_1_4_SEMANTICS_UPDATE_DTO, USER_2_USERNAME, USER_2_PRINCIPAL, DATABASE_1_DEVELOPER_WRITE_OWN_ACCESS);
+        });
+    }
+
+    @Test
+    @WithMockUser(username = USER_1_USERNAME, authorities = {"modify-table-column-semantics"})
+    public void update_privateDatabaseNotFound_fails() {
+
+        /* test */
+        assertThrows(DatabaseNotFoundException.class, () -> {
+            generic_update(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, COLUMN_1_1_ID, null, TABLE_1, null, COLUMN_1_4_SEMANTICS_UPDATE_DTO, USER_1_USERNAME, USER_1_PRINCIPAL, DATABASE_1_RESEARCHER_WRITE_OWN_ACCESS);
+        });
+    }
+
+    @Test
+    @WithMockUser(username = USER_1_USERNAME, authorities = {"modify-table-column-semantics"})
+    public void update_privateTableNotFound_fails() {
+
+        /* test */
+        assertThrows(TableNotFoundException.class, () -> {
+            generic_update(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, COLUMN_1_1_ID, DATABASE_1, null, null, COLUMN_1_4_SEMANTICS_UPDATE_DTO, USER_1_USERNAME, USER_1_PRINCIPAL, DATABASE_1_RESEARCHER_WRITE_OWN_ACCESS);
+        });
+    }
+
+    @Test
+    @WithMockUser(username = USER_2_USERNAME, authorities = {"modify-table-column-semantics"})
+    public void update_privateHasRoleForeignHasAllWriteAccess_succeeds() throws TableNotFoundException,
+            NotAllowedException, TableMalformedException, UnitNotFoundException, DatabaseNotFoundException,
+            ConceptNotFoundException, ContainerNotFoundException {
+
+        /* test */
+        generic_update(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, COLUMN_1_1_ID, DATABASE_1, TABLE_1, COLUMN_1_4_WITH_SEMANTICS, COLUMN_1_4_SEMANTICS_UPDATE_DTO, USER_2_USERNAME, USER_2_PRINCIPAL, DATABASE_1_DEVELOPER_WRITE_ALL_ACCESS);
+    }
+
+    /* ################################################################################################### */
+    /* ## GENERIC TEST CASES                                                                            ## */
+    /* ################################################################################################### */
+
+    protected ResponseEntity<ColumnDto> generic_update(Long containerId, Long databaseId, Long tableId, Long columnId,
+                                                       Database database, Table table, TableColumn column,
+                                                       ColumnSemanticsUpdateDto data, String username,
+                                                       Principal principal, DatabaseAccess access)
+            throws DatabaseNotFoundException, NotAllowedException, TableNotFoundException, TableMalformedException,
+            UnitNotFoundException, ConceptNotFoundException, ContainerNotFoundException {
+
+        /* mock */
+        if (database != null) {
+            when(databaseService.find(containerId, databaseId))
+                    .thenReturn(database);
+        } else {
+            doThrow(DatabaseNotFoundException.class)
+                    .when(databaseService)
+                    .find(containerId, databaseId);
+        }
+        if (table != null) {
+            when(tableService.findById(containerId, databaseId, tableId))
+                    .thenReturn(table);
+            when(tableService.update(containerId, databaseId, tableId, columnId, data, principal))
+                    .thenReturn(column);
+        } else {
+            doThrow(TableNotFoundException.class)
+                    .when(tableService)
+                    .update(containerId, databaseId, tableId, columnId, data, principal);
+            doThrow(TableNotFoundException.class)
+                    .when(tableService)
+                    .findById(containerId, databaseId, tableId);
+        }
+        if (access != null) {
+            when(accessService.find(containerId, username))
+                    .thenReturn(access);
+        } else {
+            doThrow(NotAllowedException.class)
+                    .when(accessService)
+                    .find(containerId, username);
+        }
+
+        /* test */
+        return tableColumnEndpoint.update(containerId, databaseId, tableId, columnId, data, principal);
+    }
+}
diff --git a/dbrepo-table-service/rest-service/src/test/java/at/tuwien/endpoint/TableEndpointIntegrationTest.java b/dbrepo-table-service/rest-service/src/test/java/at/tuwien/endpoint/TableEndpointIntegrationTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..40f8b173051ab18a42ce9b516adb4799cd4fe9aa
--- /dev/null
+++ b/dbrepo-table-service/rest-service/src/test/java/at/tuwien/endpoint/TableEndpointIntegrationTest.java
@@ -0,0 +1,113 @@
+package at.tuwien.endpoint;
+
+import at.tuwien.BaseUnitTest;
+import at.tuwien.config.DockerConfig;
+import at.tuwien.config.H2Utils;
+import at.tuwien.config.IndexConfig;
+import at.tuwien.config.ReadyConfig;
+import at.tuwien.endpoints.TableColumnEndpoint;
+import at.tuwien.endpoints.TableEndpoint;
+import at.tuwien.exception.*;
+import at.tuwien.repository.elastic.TableColumnIdxRepository;
+import at.tuwien.repository.elastic.TableIdxRepository;
+import at.tuwien.repository.jpa.*;
+import at.tuwien.service.AccessService;
+import at.tuwien.service.DatabaseService;
+import at.tuwien.service.TableService;
+import com.rabbitmq.client.Channel;
+import lombok.extern.log4j.Log4j2;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.security.test.context.support.WithMockUser;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.Mockito.doThrow;
+
+@Log4j2
+@EnableAutoConfiguration(exclude = RabbitAutoConfiguration.class)
+@SpringBootTest
+@ExtendWith(SpringExtension.class)
+public class TableEndpointIntegrationTest extends BaseUnitTest {
+
+    @MockBean
+    private ReadyConfig readyConfig;
+
+    @MockBean
+    private Channel channel;
+
+    @MockBean
+    private IndexConfig indexInitializer;
+
+    @MockBean
+    private TableIdxRepository tableidxRepository;
+
+    @MockBean
+    private TableColumnIdxRepository tableColumnidxRepository;
+
+    @Autowired
+    private ImageRepository imageRepository;
+
+    @Autowired
+    private ContainerRepository containerRepository;
+
+    @Autowired
+    private DatabaseRepository databaseRepository;
+
+    @Autowired
+    private UserRepository userRepository;
+
+    @Autowired
+    private RealmRepository realmRepository;
+
+    @Autowired
+    private DatabaseAccessRepository accessRepository;
+
+    @Autowired
+    private TableEndpoint tableEndpoint;
+
+    @Autowired
+    private H2Utils h2Utils;
+
+    @BeforeEach
+    public void beforeEach() {
+        afterEach();
+        /* create network */
+        DockerConfig.createAllNetworks();
+        /* metadata database */
+        h2Utils.runScript("schema.sql");
+        imageRepository.save(IMAGE_1);
+        realmRepository.save(REALM_DBREPO);
+        userRepository.save(USER_1_SIMPLE);
+        containerRepository.save(CONTAINER_1_SIMPLE);
+        databaseRepository.save(DATABASE_1_SIMPLE);
+    }
+
+    @AfterEach
+    public void afterEach() {
+        DockerConfig.removeAllContainers();
+        DockerConfig.removeAllNetworks();
+    }
+
+    @Test
+    @WithMockUser(username = USER_1_USERNAME, authorities = {"create-table"})
+    public void create_hasRoleHasAccess_succeeds() throws UserNotFoundException, TableMalformedException, NotAllowedException,
+            QueryMalformedException, DatabaseNotFoundException, ImageNotSupportedException, AmqpException,
+            TableNameExistsException, ContainerNotFoundException, InterruptedException {
+
+        /* mock */
+        DockerConfig.createContainer(null, CONTAINER_1, CONTAINER_1_ENV);
+        DockerConfig.startContainer(CONTAINER_1);
+        accessRepository.save(DATABASE_1_RESEARCHER_WRITE_OWN_ACCESS);
+
+        /* test */
+        tableEndpoint.create(CONTAINER_1_ID, DATABASE_1_ID, TABLE_3_CREATE_DTO, USER_1_PRINCIPAL);
+    }
+}
diff --git a/dbrepo-table-service/rest-service/src/test/java/at/tuwien/endpoint/TableEndpointUnitTest.java b/dbrepo-table-service/rest-service/src/test/java/at/tuwien/endpoint/TableEndpointUnitTest.java
index 220a6fa3ff4de9195abdec860fa8c35426a710ba..f99b308dd262ebfbac3a4a97f2fee56c2a757199 100644
--- a/dbrepo-table-service/rest-service/src/test/java/at/tuwien/endpoint/TableEndpointUnitTest.java
+++ b/dbrepo-table-service/rest-service/src/test/java/at/tuwien/endpoint/TableEndpointUnitTest.java
@@ -13,7 +13,6 @@ import at.tuwien.entities.database.table.Table;
 import at.tuwien.exception.*;
 import at.tuwien.repository.elastic.TableColumnIdxRepository;
 import at.tuwien.repository.elastic.TableIdxRepository;
-import at.tuwien.repository.jpa.*;
 import at.tuwien.service.AccessService;
 import at.tuwien.service.DatabaseService;
 import at.tuwien.service.TableService;
@@ -38,7 +37,6 @@ import java.security.Principal;
 import java.util.List;
 
 import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.*;
 
 @Log4j2
@@ -259,8 +257,8 @@ public class TableEndpointUnitTest extends BaseUnitTest {
     public void delete_publicNoRole_fails() {
 
         /* test */
-        assertThrows(NotAllowedException.class, () -> {
-            generic_findById(CONTAINER_3_ID, DATABASE_3_ID, TABLE_8_ID, DATABASE_3, TABLE_8, USER_4_USERNAME, USER_4_PRINCIPAL, null);
+        assertThrows(AccessDeniedException.class, () -> {
+            generic_delete(CONTAINER_3_ID, DATABASE_3_ID, TABLE_8_ID, DATABASE_3, TABLE_8, USER_4_PRINCIPAL);
         });
     }
 
@@ -466,7 +464,7 @@ public class TableEndpointUnitTest extends BaseUnitTest {
 
     protected ResponseEntity<List<TableBriefDto>> generic_list(Long containerId, Long databaseId, Database database, String username, Principal principal, DatabaseAccess access) throws DatabaseNotFoundException, NotAllowedException {
 
-        /* when */
+        /* mock */
         if (database != null) {
             when(databaseService.find(containerId, databaseId))
                     .thenReturn(database);
@@ -496,7 +494,7 @@ public class TableEndpointUnitTest extends BaseUnitTest {
 
     protected ResponseEntity<TableBriefDto> generic_create(Long containerId, Long databaseId, Database database, TableCreateDto data, String username, Principal principal, DatabaseAccess access) throws DatabaseNotFoundException, NotAllowedException, UserNotFoundException, TableMalformedException, QueryMalformedException, ImageNotSupportedException, AmqpException, TableNameExistsException, ContainerNotFoundException {
 
-        /* when */
+        /* mock */
         if (database != null) {
             when(databaseService.find(containerId, databaseId))
                     .thenReturn(database);
@@ -525,7 +523,7 @@ public class TableEndpointUnitTest extends BaseUnitTest {
 
     protected ResponseEntity<TableDto> generic_findById(Long containerId, Long databaseId, Long tableId, Database database, Table table, String username, Principal principal, DatabaseAccess access) throws DatabaseNotFoundException, NotAllowedException, UserNotFoundException, TableMalformedException, QueryMalformedException, ImageNotSupportedException, AmqpException, TableNameExistsException, ContainerNotFoundException, TableNotFoundException {
 
-        /* when */
+        /* mock */
         if (table != null) {
             when(tableService.findById(containerId, databaseId, tableId))
                     .thenReturn(table);
@@ -561,7 +559,7 @@ public class TableEndpointUnitTest extends BaseUnitTest {
 
     protected ResponseEntity<?> generic_delete(Long containerId, Long databaseId, Long tableId, Database database, Table table, Principal principal) throws DatabaseNotFoundException, NotAllowedException, ContainerNotFoundException, TableNotFoundException, TableMalformedException, QueryMalformedException, ImageNotSupportedException, DataProcessingException {
 
-        /* when */
+        /* mock */
         if (table != null) {
             doNothing()
                     .when(tableService)
diff --git a/dbrepo-table-service/rest-service/src/test/java/at/tuwien/gateway/QueryServiceGatewayUnitTest.java b/dbrepo-table-service/rest-service/src/test/java/at/tuwien/gateway/QueryServiceGatewayUnitTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..c84163790cc840f4ac929c175cd5846f6d88ee65
--- /dev/null
+++ b/dbrepo-table-service/rest-service/src/test/java/at/tuwien/gateway/QueryServiceGatewayUnitTest.java
@@ -0,0 +1,85 @@
+package at.tuwien.gateway;
+
+import at.tuwien.BaseUnitTest;
+import at.tuwien.config.IndexConfig;
+import at.tuwien.config.ReadyConfig;
+import at.tuwien.exception.AmqpException;
+import at.tuwien.repository.elastic.TableColumnIdxRepository;
+import at.tuwien.repository.elastic.TableIdxRepository;
+import com.rabbitmq.client.Channel;
+import lombok.extern.log4j.Log4j2;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+import org.springframework.web.client.RestTemplate;
+
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.ArgumentMatchers.*;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+@Log4j2
+@EnableAutoConfiguration(exclude = RabbitAutoConfiguration.class)
+@SpringBootTest
+@ExtendWith(SpringExtension.class)
+public class QueryServiceGatewayUnitTest extends BaseUnitTest {
+
+    @MockBean
+    private ReadyConfig readyConfig;
+
+    @MockBean
+    private Channel channel;
+
+    @MockBean
+    private IndexConfig indexInitializer;
+
+    @MockBean
+    private TableIdxRepository tableidxRepository;
+
+    @MockBean
+    private TableColumnIdxRepository tableColumnidxRepository;
+
+    @MockBean
+    private RestTemplate restTemplate;
+
+    @Autowired
+    private QueryServiceGateway queryServiceGateway;
+
+    @Test
+    public void declareConsumer_succeeds() throws AmqpException {
+        final ResponseEntity<Void> mock = ResponseEntity.status(HttpStatus.ACCEPTED)
+                .build();
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class)))
+                .thenReturn(mock);
+
+        /* test */
+        queryServiceGateway.declareConsumer(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, "abc");
+    }
+
+    @Test
+    public void declareConsumer_fails() {
+        final ResponseEntity<Void> mock = ResponseEntity.status(HttpStatus.NO_CONTENT)
+                .build();
+
+        /* mock */
+        when(restTemplate.exchange(anyString(), eq(HttpMethod.POST), any(HttpEntity.class), eq(Void.class)))
+                .thenReturn(mock);
+
+        /* test */
+        assertThrows(AmqpException.class, () -> {
+            queryServiceGateway.declareConsumer(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, "abc");
+        });
+    }
+
+}
diff --git a/dbrepo-table-service/services/src/main/java/at/tuwien/service/AccessService.java b/dbrepo-table-service/services/src/main/java/at/tuwien/service/AccessService.java
index efe2e564b81eb845098c09d481028a55aaf750f0..e09173e665459818c8e5885c7f9296f8ced6d517 100644
--- a/dbrepo-table-service/services/src/main/java/at/tuwien/service/AccessService.java
+++ b/dbrepo-table-service/services/src/main/java/at/tuwien/service/AccessService.java
@@ -11,13 +11,12 @@ public interface AccessService {
     DatabaseAccess find(Long databaseId, String username) throws NotAllowedException;
 
     /**
-     * Checks if the user with username has access to the table with given id in database with given id.
+     * Checks if the user with username has access to the database with given id.
      *
-     * @param databaseId  The database id.
-     * @param tableId     The table id.
-     * @param username    The username.
+     * @param databaseId The database id.
+     * @param username   The username.
      * @return The access object.
      * @throws AccessDeniedException The user does not have access.
      */
-    DatabaseAccess hasAccess(Long databaseId, Long tableId, String username) throws AccessDeniedException;
+    DatabaseAccess hasAccess(Long databaseId, String username) throws AccessDeniedException;
 }
diff --git a/dbrepo-table-service/services/src/main/java/at/tuwien/service/impl/AccessServiceImpl.java b/dbrepo-table-service/services/src/main/java/at/tuwien/service/impl/AccessServiceImpl.java
index 1a2f71eab8f384919c4cd22fa43526ac4c8d630f..91d4f41a8a4078d50971f24139efa933b73cd508 100644
--- a/dbrepo-table-service/services/src/main/java/at/tuwien/service/impl/AccessServiceImpl.java
+++ b/dbrepo-table-service/services/src/main/java/at/tuwien/service/impl/AccessServiceImpl.java
@@ -36,7 +36,7 @@ public class AccessServiceImpl implements AccessService {
 
     @Override
     @Transactional(readOnly = true)
-    public DatabaseAccess hasAccess(Long databaseId, Long tableId, String username) throws AccessDeniedException {
+    public DatabaseAccess hasAccess(Long databaseId, String username) throws AccessDeniedException {
         final Optional<DatabaseAccess> optional = databaseAccessRepository.findByDatabaseIdAndUsername(databaseId, username);
         if (optional.isEmpty()) {
             log.error("Failed to retrieve access, not found");