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 b345c7ced3a021bc3aef6707365c7b186016377d..f142018b3e407d40fcd18bbb1e6b6e8f894e2a8e 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
@@ -2,6 +2,7 @@ package at.tuwien.endpoints;
 
 import at.tuwien.api.database.table.*;
 import at.tuwien.api.error.ApiErrorDto;
+import at.tuwien.entities.database.Database;
 import at.tuwien.entities.database.table.Table;
 import at.tuwien.entities.user.User;
 import at.tuwien.exception.*;
@@ -139,7 +140,7 @@ public class TableEndpoint {
             NotAllowedException {
         log.debug("endpoint create table, containerId={}, databaseId={}, createDto={}, principal={}", containerId,
                 databaseId, createDto, principal);
-        endpointValidator.validateOnlyAccess(databaseId, principal, true);
+        endpointValidator.validateOnlyAccess(containerId, databaseId, principal, true);
         final Table table = tableService.createTable(containerId, databaseId, createDto, principal);
         amqpService.create(table);
         final TableBriefDto dto = tableMapper.tableToTableBriefDto(table);
@@ -183,10 +184,7 @@ public class TableEndpoint {
         log.debug("endpoint find table, containerId={}, databaseId={}, tableId={}, principal={}", containerId,
                 databaseId, tableId, principal);
         endpointValidator.validateOnlyPrivateAccess(containerId, databaseId, principal);
-        if (principal != null && User.hasRole(principal, "find-table")) {
-            log.error("Failed to find table: role is missing");
-            throw new NotAllowedException("Failed to find table: role is missing");
-        }
+        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);
@@ -240,10 +238,9 @@ public class TableEndpoint {
                                        @NotNull @PathVariable("tableId") Long tableId,
                                        @NotNull Principal principal)
             throws TableNotFoundException, DatabaseNotFoundException, ImageNotSupportedException,
-            DataProcessingException, ContainerNotFoundException, TableMalformedException, QueryMalformedException, NotAllowedException {
+            DataProcessingException, ContainerNotFoundException, TableMalformedException, QueryMalformedException {
         log.debug("endpoint delete table, containerId={}, databaseId={}, tableId={}, principal={}", containerId,
                 databaseId, tableId, principal);
-        endpointValidator.validateOnlyOwner(containerId, databaseId, principal);
         tableService.deleteTable(containerId, databaseId, tableId);
         return ResponseEntity.accepted()
                 .build();
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 ce238cc55a3eb8833cd7c000ad53f0b52f749c58..79326ff8a9267f781a92d7f7176a3e1d03eac28e 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
@@ -27,8 +27,8 @@ public class EndpointValidator {
         this.databaseService = databaseService;
     }
 
-    public void validateOnlyAccess(Long databaseId, Principal principal) throws NotAllowedException {
-        validateOnlyAccess(databaseId, principal, false);
+    public void validateOnlyAccess(Long containerId, Long databaseId, Principal principal) throws NotAllowedException, DatabaseNotFoundException {
+        validateOnlyAccess(containerId, databaseId, principal, false);
     }
 
     public void validateOnlyPrivateAccess(Long containerId, Long databaseId, Principal principal, boolean writeAccessOnly) throws NotAllowedException, DatabaseNotFoundException {
@@ -37,15 +37,15 @@ public class EndpointValidator {
             log.trace("database with id {} is public: no access needed", databaseId);
             return;
         }
-        validateOnlyAccess(databaseId, principal, writeAccessOnly);
+        validateOnlyAccess(containerId, databaseId, principal, writeAccessOnly);
     }
 
     public void validateOnlyPrivateAccess(Long containerId, Long databaseId, Principal principal) throws NotAllowedException, DatabaseNotFoundException {
         validateOnlyPrivateAccess(containerId, databaseId, principal, false);
     }
 
-    public void validateOnlyAccess(Long databaseId, Principal principal, boolean writeAccessOnly) throws NotAllowedException {
-        log.trace("database with id {} is private", databaseId);
+    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");
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 08554b354c24ea8081f222c1a2a3d86d30c7e7df..220a6fa3ff4de9195abdec860fa8c35426a710ba 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
@@ -9,12 +9,14 @@ import at.tuwien.config.ReadyConfig;
 import at.tuwien.endpoints.TableEndpoint;
 import at.tuwien.entities.database.Database;
 import at.tuwien.entities.database.DatabaseAccess;
+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;
 import com.rabbitmq.client.Channel;
 import lombok.extern.log4j.Log4j2;
 import org.junit.jupiter.api.BeforeEach;
@@ -27,6 +29,7 @@ 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;
@@ -36,8 +39,7 @@ import java.util.List;
 
 import static org.junit.jupiter.api.Assertions.*;
 import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.*;
 
 @Log4j2
 @EnableAutoConfiguration(exclude = RabbitAutoConfiguration.class)
@@ -64,10 +66,10 @@ public class TableEndpointUnitTest extends BaseUnitTest {
     private DatabaseService databaseService;
 
     @MockBean
-    private TableRepository tableRepository;
+    private AccessService accessService;
 
     @MockBean
-    private AccessService accessService;
+    private TableService tableService;
 
     @Autowired
     private TableEndpoint tableEndpoint;
@@ -166,6 +168,102 @@ public class TableEndpointUnitTest extends BaseUnitTest {
         });
     }
 
+    @Test
+    @WithAnonymousUser
+    public void findById_publicAnonymous_succeeds() throws UserNotFoundException, TableNotFoundException, NotAllowedException, TableMalformedException, QueryMalformedException, DatabaseNotFoundException, ImageNotSupportedException, AmqpException, TableNameExistsException, ContainerNotFoundException {
+
+        /* test */
+        generic_findById(CONTAINER_3_ID, DATABASE_3_ID, TABLE_8_ID, DATABASE_3, TABLE_8, null, null, null);
+    }
+
+    @Test
+    @WithMockUser(username = USER_1_USERNAME, authorities = "find-table")
+    public void findById_publicHasRoleTableNotFound_fails() {
+
+        /* test */
+        assertThrows(TableNotFoundException.class, () -> {
+            generic_findById(CONTAINER_3_ID, DATABASE_3_ID, TABLE_8_ID, DATABASE_3, null, USER_1_USERNAME, USER_1_PRINCIPAL, DATABASE_1_RESEARCHER_READ_ACCESS);
+        });
+    }
+
+    @Test
+    @WithMockUser(username = USER_1_USERNAME, authorities = "find-table")
+    public void findById_publicHasRoleDatabaseNotFound_fails() {
+
+        /* test */
+        assertThrows(DatabaseNotFoundException.class, () -> {
+            generic_findById(CONTAINER_3_ID, DATABASE_3_ID, TABLE_8_ID, null, TABLE_8, USER_1_USERNAME, USER_1_PRINCIPAL, DATABASE_1_RESEARCHER_READ_ACCESS);
+        });
+    }
+
+    @Test
+    @WithMockUser(username = USER_1_USERNAME, authorities = "find-table")
+    public void findById_publicHasRole_succeeds() throws DatabaseNotFoundException, NotAllowedException, UserNotFoundException, TableNotFoundException, TableMalformedException, QueryMalformedException, ImageNotSupportedException, AmqpException, TableNameExistsException, ContainerNotFoundException {
+
+        /* test */
+        final ResponseEntity<TableDto> response = generic_findById(CONTAINER_3_ID, DATABASE_3_ID, TABLE_8_ID, DATABASE_3, TABLE_8, USER_1_USERNAME, USER_1_PRINCIPAL, DATABASE_1_RESEARCHER_READ_ACCESS);
+        assertEquals(HttpStatus.OK, response.getStatusCode());
+        final TableDto body = response.getBody();
+        assertNotNull(body);
+    }
+
+    @Test
+    @WithMockUser(username = USER_4_USERNAME)
+    public void findById_publicNoRole_succeeds() throws UserNotFoundException, TableNotFoundException, NotAllowedException, TableMalformedException, QueryMalformedException, DatabaseNotFoundException, ImageNotSupportedException, AmqpException, TableNameExistsException, ContainerNotFoundException {
+
+        /* test */
+        generic_findById(CONTAINER_3_ID, DATABASE_3_ID, TABLE_8_ID, DATABASE_3, TABLE_8, USER_1_USERNAME, USER_1_PRINCIPAL, null);
+    }
+
+    @Test
+    @WithAnonymousUser
+    public void delete_publicAnonymous_fails() {
+
+        /* test */
+        assertThrows(AccessDeniedException.class, () -> {
+            generic_delete(CONTAINER_3_ID, DATABASE_3_ID, TABLE_8_ID, DATABASE_3, TABLE_3, null);
+        });
+    }
+
+    @Test
+    @WithMockUser(username = USER_1_USERNAME, authorities = "delete-table")
+    public void delete_publicHasRoleTableNotFound_fails() {
+
+        /* test */
+        assertThrows(TableNotFoundException.class, () -> {
+            generic_delete(CONTAINER_3_ID, DATABASE_3_ID, TABLE_8_ID, DATABASE_3, null, USER_1_PRINCIPAL);
+        });
+    }
+
+    @Test
+    @WithMockUser(username = USER_1_USERNAME, authorities = "delete-table")
+    public void delete_publiceHasRoleDatabaseNotFound_fails() {
+
+        /* test */
+        assertThrows(DatabaseNotFoundException.class, () -> {
+            generic_delete(CONTAINER_3_ID, DATABASE_3_ID, TABLE_8_ID, null, TABLE_8, USER_1_PRINCIPAL);
+        });
+    }
+
+    @Test
+    @WithMockUser(username = USER_1_USERNAME, authorities = "delete-table")
+    public void delete_publicHasRole_succeeds() throws DatabaseNotFoundException, NotAllowedException, TableNotFoundException, TableMalformedException, QueryMalformedException, ImageNotSupportedException, ContainerNotFoundException, DataProcessingException {
+
+        /* test */
+        final ResponseEntity<?> response = generic_delete(CONTAINER_3_ID, DATABASE_3_ID, TABLE_8_ID, DATABASE_3, TABLE_8, USER_1_PRINCIPAL);
+        assertEquals(HttpStatus.ACCEPTED, response.getStatusCode());
+    }
+
+    @Test
+    @WithMockUser(username = USER_4_USERNAME)
+    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);
+        });
+    }
+
     /* ################################################################################################### */
     /* ## PRIVATE DATABASES                                                                             ## */
     /* ################################################################################################### */
@@ -262,6 +360,106 @@ public class TableEndpointUnitTest extends BaseUnitTest {
         });
     }
 
+    @Test
+    @WithAnonymousUser
+    public void findById_privateAnonymous_fails() {
+
+        /* test */
+        assertThrows(NotAllowedException.class, () -> {
+            generic_findById(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, DATABASE_1, TABLE_1, null, null, null);
+        });
+    }
+
+    @Test
+    @WithMockUser(username = USER_1_USERNAME, authorities = "find-table")
+    public void findById_privateHasRoleTableNotFound_fails() {
+
+        /* test */
+        assertThrows(TableNotFoundException.class, () -> {
+            generic_findById(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, DATABASE_1, null, USER_1_USERNAME, USER_1_PRINCIPAL, DATABASE_1_RESEARCHER_READ_ACCESS);
+        });
+    }
+
+    @Test
+    @WithMockUser(username = USER_1_USERNAME, authorities = "find-table")
+    public void findById_privateHasRoleDatabaseNotFound_fails() {
+
+        /* test */
+        assertThrows(DatabaseNotFoundException.class, () -> {
+            generic_findById(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, null, TABLE_1, USER_1_USERNAME, USER_1_PRINCIPAL, DATABASE_1_RESEARCHER_READ_ACCESS);
+        });
+    }
+
+    @Test
+    @WithMockUser(username = USER_1_USERNAME, authorities = "find-table")
+    public void findById_privateHasRole_succeeds() throws DatabaseNotFoundException, NotAllowedException, UserNotFoundException, TableNotFoundException, TableMalformedException, QueryMalformedException, ImageNotSupportedException, AmqpException, TableNameExistsException, ContainerNotFoundException {
+
+        /* test */
+        final ResponseEntity<TableDto> response = generic_findById(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, DATABASE_1, TABLE_1, USER_1_USERNAME, USER_1_PRINCIPAL, DATABASE_1_RESEARCHER_READ_ACCESS);
+        assertEquals(HttpStatus.OK, response.getStatusCode());
+        final TableDto body = response.getBody();
+        assertNotNull(body);
+    }
+
+    @Test
+    @WithMockUser(username = USER_4_USERNAME)
+    public void findById_privateNoRole_fails() {
+
+        /* test */
+        assertThrows(NotAllowedException.class, () -> {
+            generic_findById(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, DATABASE_1, TABLE_1, USER_4_USERNAME, USER_4_PRINCIPAL, null);
+        });
+    }
+
+    @Test
+    @WithAnonymousUser
+    public void delete_privateAnonymous_fails() {
+
+        /* test */
+        assertThrows(AccessDeniedException.class, () -> {
+            generic_delete(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, DATABASE_1, TABLE_1, null);
+        });
+    }
+
+    @Test
+    @WithMockUser(username = USER_1_USERNAME, authorities = "delete-table")
+    public void delete_privateHasRoleTableNotFound_fails() {
+
+        /* test */
+        assertThrows(TableNotFoundException.class, () -> {
+            generic_delete(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, DATABASE_1, null, USER_1_PRINCIPAL);
+        });
+    }
+
+    @Test
+    @WithMockUser(username = USER_1_USERNAME, authorities = "delete-table")
+    public void delete_privateHasRoleDatabaseNotFound_fails() {
+
+        /* test */
+        assertThrows(DatabaseNotFoundException.class, () -> {
+            generic_delete(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, null, TABLE_1, USER_1_PRINCIPAL);
+        });
+    }
+
+    @Test
+    @WithMockUser(username = USER_1_USERNAME, authorities = "delete-table")
+    public void delete_privateHasRole_succeeds() throws DatabaseNotFoundException, NotAllowedException, TableNotFoundException, TableMalformedException, QueryMalformedException, ImageNotSupportedException, ContainerNotFoundException, DataProcessingException {
+
+        /* test */
+        final ResponseEntity<?> response = generic_delete(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, DATABASE_1, TABLE_1, USER_1_PRINCIPAL);
+        assertEquals(HttpStatus.ACCEPTED, response.getStatusCode());
+    }
+
+    @Test
+    @WithMockUser(username = USER_4_USERNAME)
+    public void delete_privateNoRole_fails() {
+
+        /* test */
+        assertThrows(NotAllowedException.class, () -> {
+            generic_findById(CONTAINER_1_ID, DATABASE_1_ID, TABLE_1_ID, DATABASE_1, TABLE_1, USER_4_USERNAME, USER_4_PRINCIPAL, null);
+        });
+    }
+
     /* ################################################################################################### */
     /* ## GENERIC TEST CASES                                                                            ## */
     /* ################################################################################################### */
@@ -272,15 +470,16 @@ public class TableEndpointUnitTest extends BaseUnitTest {
         if (database != null) {
             when(databaseService.find(containerId, databaseId))
                     .thenReturn(database);
-            log.trace("mock {} tables", database.getTables().size());
-            when(tableRepository.findByDatabaseOrderByCreatedDesc(any(Database.class)))
+            when(tableService.findAll(containerId, databaseId))
                     .thenReturn(database.getTables());
+            log.trace("mock {} table(s)", database.getTables().size());
         } else {
             doThrow(DatabaseNotFoundException.class)
                     .when(databaseService)
                     .find(containerId, databaseId);
-            when(tableRepository.findByDatabaseOrderByCreatedDesc(any(Database.class)))
+            when(tableService.findAll(containerId, databaseId))
                     .thenReturn(List.of());
+            log.trace("mock 0 tables");
         }
         if (access != null) {
             when(accessService.find(databaseId, username))
@@ -302,13 +501,13 @@ public class TableEndpointUnitTest extends BaseUnitTest {
             when(databaseService.find(containerId, databaseId))
                     .thenReturn(database);
             log.trace("mock {} tables", database.getTables().size());
-            when(tableRepository.findByDatabaseOrderByCreatedDesc(any(Database.class)))
+            when(tableService.findAll(containerId, databaseId))
                     .thenReturn(database.getTables());
         } else {
             doThrow(DatabaseNotFoundException.class)
                     .when(databaseService)
                     .find(containerId, databaseId);
-            when(tableRepository.findByDatabaseOrderByCreatedDesc(any(Database.class)))
+            when(tableService.findAll(containerId, databaseId))
                     .thenReturn(List.of());
         }
         if (access != null) {
@@ -323,4 +522,62 @@ public class TableEndpointUnitTest extends BaseUnitTest {
         /* test */
         return tableEndpoint.create(containerId, databaseId, data, principal);
     }
+
+    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 */
+        if (table != null) {
+            when(tableService.findById(containerId, databaseId, tableId))
+                    .thenReturn(table);
+            when(databaseService.find(containerId, databaseId))
+                    .thenReturn(database);
+        } else {
+            doThrow(TableNotFoundException.class)
+                    .when(tableService)
+                    .findById(containerId, databaseId, tableId);
+            when(tableService.findAll(containerId, databaseId))
+                    .thenReturn(List.of());
+        }
+        if (database != null) {
+            when(databaseService.find(containerId, databaseId))
+                    .thenReturn(database);
+        } else {
+            doThrow(DatabaseNotFoundException.class)
+                    .when(databaseService)
+                    .find(containerId, databaseId);
+        }
+        if (access != null) {
+            when(accessService.find(databaseId, username))
+                    .thenReturn(access);
+        } else {
+            doThrow(NotAllowedException.class)
+                    .when(accessService)
+                    .find(databaseId, username);
+        }
+
+        /* test */
+        return tableEndpoint.findById(containerId, databaseId, tableId, principal);
+    }
+
+    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 */
+        if (table != null) {
+            doNothing()
+                    .when(tableService)
+                    .deleteTable(containerId, databaseId, tableId);
+        } else {
+            doThrow(TableNotFoundException.class)
+                    .when(tableService)
+                    .deleteTable(containerId, databaseId, tableId);
+        }
+        if (database == null) {
+            doThrow(DatabaseNotFoundException.class)
+                    .when(tableService)
+                    .deleteTable(containerId, databaseId, tableId);
+        }
+
+        /* test */
+        return tableEndpoint.delete(containerId, databaseId, tableId, principal);
+    }
 }
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 a6323d65915ff7b22bbaf49563269307b4a13f72..4e27bb9b516159f1abcedead47d6506ee45c04cf 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
@@ -73,7 +73,9 @@ public class TableServiceImpl extends HibernateConnector implements TableService
     @Transactional(readOnly = true)
     public List<Table> findAll(Long containerId, Long databaseId) throws DatabaseNotFoundException {
         final Database database = databaseService.find(containerId, databaseId);
-        return tableRepository.findByDatabaseOrderByCreatedDesc(database);
+        final List<Table> tables = tableRepository.findByDatabaseOrderByCreatedDesc(database);
+        log.trace("found {} table(s) in database with id {}", tables.size(), databaseId);
+        return tables;
     }
 
     @Override