diff --git a/fda-authentication-service/dbrepo-realm.json b/fda-authentication-service/dbrepo-realm.json
index 3d79aeed6d66e21b9e24c6527a8389cded0efb02..0e26cf80c915b19958a8a38e106a8fc2afc9fda0 100644
--- a/fda-authentication-service/dbrepo-realm.json
+++ b/fda-authentication-service/dbrepo-realm.json
@@ -5,7 +5,7 @@
   "defaultSignatureAlgorithm" : "RS256",
   "revokeRefreshToken" : false,
   "refreshTokenMaxReuse" : 0,
-  "accessTokenLifespan" : 300,
+  "accessTokenLifespan" : 720,
   "accessTokenLifespanForImplicitFlow" : 900,
   "ssoSessionIdleTimeout" : 1800,
   "ssoSessionMaxLifespan" : 36000,
@@ -21,8 +21,8 @@
   "accessCodeLifespan" : 60,
   "accessCodeLifespanUserAction" : 300,
   "accessCodeLifespanLogin" : 1800,
-  "actionTokenGeneratedByAdminLifespan" : 259200,
-  "actionTokenGeneratedByUserLifespan" : 86400,
+  "actionTokenGeneratedByAdminLifespan" : 43200,
+  "actionTokenGeneratedByUserLifespan" : 1800,
   "oauth2DeviceCodeLifespan" : 600,
   "oauth2DevicePollingInterval" : 5,
   "enabled" : true,
@@ -1761,7 +1761,7 @@
       "subType" : "anonymous",
       "subComponents" : { },
       "config" : {
-        "allowed-protocol-mapper-types" : [ "saml-user-attribute-mapper", "oidc-usermodel-property-mapper", "oidc-full-name-mapper", "oidc-sha256-pairwise-sub-mapper", "saml-user-property-mapper", "saml-role-list-mapper", "oidc-address-mapper", "oidc-usermodel-attribute-mapper" ]
+        "allowed-protocol-mapper-types" : [ "oidc-usermodel-property-mapper", "oidc-sha256-pairwise-sub-mapper", "oidc-address-mapper", "oidc-usermodel-attribute-mapper", "saml-user-attribute-mapper", "oidc-full-name-mapper", "saml-role-list-mapper", "saml-user-property-mapper" ]
       }
     }, {
       "id" : "1849e52a-b8c9-44a8-af3d-ee19376a1ed1",
@@ -1787,11 +1787,11 @@
       "subType" : "authenticated",
       "subComponents" : { },
       "config" : {
-        "allowed-protocol-mapper-types" : [ "saml-user-attribute-mapper", "saml-role-list-mapper", "oidc-usermodel-attribute-mapper", "oidc-full-name-mapper", "oidc-usermodel-property-mapper", "oidc-address-mapper", "oidc-sha256-pairwise-sub-mapper", "saml-user-property-mapper" ]
+        "allowed-protocol-mapper-types" : [ "saml-user-property-mapper", "oidc-full-name-mapper", "oidc-usermodel-property-mapper", "saml-role-list-mapper", "oidc-usermodel-attribute-mapper", "saml-user-attribute-mapper", "oidc-address-mapper", "oidc-sha256-pairwise-sub-mapper" ]
       }
     } ],
     "org.keycloak.userprofile.UserProfileProvider" : [ {
-      "id" : "9ed551eb-c1e6-4af1-aaea-7aca5c7e6a97",
+      "id" : "2abcde8e-479c-4b3f-85ca-08687ff4b0cf",
       "providerId" : "declarative-user-profile",
       "subComponents" : { },
       "config" : { }
@@ -1845,7 +1845,7 @@
   "internationalizationEnabled" : false,
   "supportedLocales" : [ ],
   "authenticationFlows" : [ {
-    "id" : "813567bd-6600-4b6e-b286-b5dee1f5d064",
+    "id" : "5eb1d49c-38cd-41a8-9557-13bcffb1a642",
     "alias" : "Account verification options",
     "description" : "Method with which to verity the existing account",
     "providerId" : "basic-flow",
@@ -1867,7 +1867,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "9826cfed-0fa3-4147-89dc-b2682c24d1ae",
+    "id" : "29e68803-3d8d-4fe5-af03-0814e35a6ed3",
     "alias" : "Authentication Options",
     "description" : "Authentication options.",
     "providerId" : "basic-flow",
@@ -1896,7 +1896,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "c784fdf2-5c81-4c49-bfcd-4b4c1df23709",
+    "id" : "aeadaa3b-f3d2-47ef-9e0a-ea4b737fe684",
     "alias" : "Browser - Conditional OTP",
     "description" : "Flow to determine if the OTP is required for the authentication",
     "providerId" : "basic-flow",
@@ -1918,7 +1918,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "14ec8779-1edf-41cc-80b4-472bf39ea78b",
+    "id" : "4c958b93-579e-45da-8471-a6aebc439641",
     "alias" : "Direct Grant - Conditional OTP",
     "description" : "Flow to determine if the OTP is required for the authentication",
     "providerId" : "basic-flow",
@@ -1940,7 +1940,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "d1d343ce-85ea-4dd8-ace0-e2a89b1c8aa7",
+    "id" : "6878c43f-0aa7-40c6-bf28-f984029e893b",
     "alias" : "First broker login - Conditional OTP",
     "description" : "Flow to determine if the OTP is required for the authentication",
     "providerId" : "basic-flow",
@@ -1962,7 +1962,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "9cdaab34-3b7b-49f3-b563-fb5e5e5234ad",
+    "id" : "aae75803-fb3c-4c74-9ee7-73fc897aad05",
     "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",
@@ -1984,7 +1984,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "e52f4a8e-3e68-48b7-a332-e5d4cdea71f7",
+    "id" : "0987a7fe-5e31-40b1-be1f-6cd4a5a76e43",
     "alias" : "Reset - Conditional OTP",
     "description" : "Flow to determine if the OTP should be reset or not. Set to REQUIRED to force.",
     "providerId" : "basic-flow",
@@ -2006,7 +2006,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "26fe8be3-b879-4e42-ab17-984a779e4e3b",
+    "id" : "68078236-033e-4f17-b02f-fb5f401be3fe",
     "alias" : "User creation or linking",
     "description" : "Flow for the existing/non-existing user alternatives",
     "providerId" : "basic-flow",
@@ -2029,7 +2029,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "88be070e-9dca-477a-a309-ee6a128b3cdb",
+    "id" : "28c746e7-fc22-4c61-872a-26670fffb8ed",
     "alias" : "Verify Existing Account by Re-authentication",
     "description" : "Reauthentication of existing account",
     "providerId" : "basic-flow",
@@ -2051,7 +2051,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "3eae800e-9501-4a4d-a212-a5c9f6bb21a5",
+    "id" : "502957db-db9d-4138-a5e3-90fce22bff15",
     "alias" : "browser",
     "description" : "browser based authentication",
     "providerId" : "basic-flow",
@@ -2087,7 +2087,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "f590ef06-e384-409d-bbe7-7802d829464f",
+    "id" : "9312b6c7-f999-4285-ae9f-e365666066e7",
     "alias" : "clients",
     "description" : "Base authentication for clients",
     "providerId" : "client-flow",
@@ -2123,7 +2123,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "830f1845-6d89-4de7-9ad2-e5ee4b13d774",
+    "id" : "31c2af88-b37c-4fdb-8dec-23a5ba145114",
     "alias" : "direct grant",
     "description" : "OpenID Connect Resource Owner Grant",
     "providerId" : "basic-flow",
@@ -2152,7 +2152,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "6430a3fa-60ce-475d-a512-966c4046ad10",
+    "id" : "c11ae35d-772a-4a1f-9934-a1945b45d617",
     "alias" : "docker auth",
     "description" : "Used by Docker clients to authenticate against the IDP",
     "providerId" : "basic-flow",
@@ -2167,7 +2167,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "6ed62838-778b-48e8-9b0d-ca7a7232ec9e",
+    "id" : "0485179d-460c-4ad0-b0b2-02bbf57eb012",
     "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",
@@ -2190,7 +2190,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "368b31ba-3065-4425-832e-f565336e93f5",
+    "id" : "aa1b06b4-1c12-4f7c-9d5a-6422ab5bb89a",
     "alias" : "forms",
     "description" : "Username, password, otp and other auth forms.",
     "providerId" : "basic-flow",
@@ -2212,7 +2212,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "32618434-ca5d-4e5f-bcf7-a27f233e6ee2",
+    "id" : "fc52dc5f-16ee-499e-ad0a-ba04093efc33",
     "alias" : "http challenge",
     "description" : "An authentication flow based on challenge-response HTTP Authentication Schemes",
     "providerId" : "basic-flow",
@@ -2234,7 +2234,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "17dbfb8f-0e6a-4b3c-9a6f-02e7b210ffe1",
+    "id" : "576fb8d9-96b4-464a-a2b5-655c61755ec0",
     "alias" : "registration",
     "description" : "registration flow",
     "providerId" : "basic-flow",
@@ -2250,7 +2250,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "aef432b9-ac38-46b6-bb35-210ae9a01828",
+    "id" : "a026a910-1a04-4eb0-9fe2-6eb72139a39b",
     "alias" : "registration form",
     "description" : "registration form",
     "providerId" : "form-flow",
@@ -2286,7 +2286,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "64cff6f9-6931-4b12-a869-bbd6c767ffd7",
+    "id" : "0d0e32f3-7030-42fa-be83-528281d9eca0",
     "alias" : "reset credentials",
     "description" : "Reset credentials for a user if they forgot their password or something",
     "providerId" : "basic-flow",
@@ -2322,7 +2322,7 @@
       "userSetupAllowed" : false
     } ]
   }, {
-    "id" : "85c3536d-5812-403a-b7a9-59728f9d2a5f",
+    "id" : "ec850fcc-5b8c-4109-9cf4-a16f84cd7804",
     "alias" : "saml ecp",
     "description" : "SAML ECP Profile Authentication Flow",
     "providerId" : "basic-flow",
@@ -2338,13 +2338,13 @@
     } ]
   } ],
   "authenticatorConfig" : [ {
-    "id" : "2f156ed6-ea2d-4ed7-8974-283993cb0b8a",
+    "id" : "d42b19d3-2efe-4879-9ce0-7c055a3d949e",
     "alias" : "create unique user config",
     "config" : {
       "require.password.update.after.registration" : "false"
     }
   }, {
-    "id" : "50956254-36cd-4834-bc2e-f258c525309f",
+    "id" : "f1c71d63-f83f-432d-b9b4-e1a97095b5e1",
     "alias" : "review profile config",
     "config" : {
       "update.profile.on.first.login" : "missing"
diff --git a/fda-database-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java b/fda-database-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java
index 5176472cd2c1e7bb3cc8be47772b272a8f38dd3f..841d2d13a5423b0831015785b1013648a1cf978b 100644
--- a/fda-database-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java
+++ b/fda-database-service/rest-service/src/main/java/at/tuwien/endpoints/DatabaseEndpoint.java
@@ -98,14 +98,14 @@ public class DatabaseEndpoint {
 
     @PutMapping("/{databaseId}/visibility")
     @Transactional
-    @PreAuthorize("hasAuthority('modify-database')")
+    @PreAuthorize("hasAuthority('modify-database-visibility')")
     @Timed(value = "database.visibility", description = "Time needed to modify a database visibility")
     @Operation(summary = "Update database", security = @SecurityRequirement(name = "bearerAuth"))
     public ResponseEntity<DatabaseDto> visibility(@NotNull @PathVariable("id") Long containerId,
                                                   @NotNull @PathVariable Long databaseId,
                                                   @Valid @RequestBody DatabaseModifyVisibilityDto data,
                                                   @NotNull Principal principal)
-            throws DatabaseNotFoundException, NotAllowedException {
+            throws DatabaseNotFoundException {
         log.debug("endpoint update database, containerId={}, databaseId={}, data={}, principal={}", containerId,
                 databaseId, data, principal);
         final Database database = databaseService.visibility(containerId, databaseId, data);
@@ -117,14 +117,14 @@ public class DatabaseEndpoint {
 
     @PutMapping("/{databaseId}/transfer")
     @Transactional
-    @PreAuthorize("hasAuthority('transfer-database')")
+    @PreAuthorize("hasAuthority('modify-database-owner')")
     @Timed(value = "database.transfer", description = "Time needed to transfer a database ownership")
     @Operation(summary = "Transfer database", security = @SecurityRequirement(name = "bearerAuth"))
     public ResponseEntity<DatabaseDto> transfer(@NotNull @PathVariable("id") Long containerId,
                                                 @NotNull @PathVariable Long databaseId,
                                                 @Valid @RequestBody DatabaseTransferDto transferDto,
                                                 @NotNull Principal principal)
-            throws DatabaseNotFoundException, NotAllowedException, UserNotFoundException {
+            throws DatabaseNotFoundException, UserNotFoundException {
         log.debug("endpoint update database, containerId={}, databaseId={}, transferDto={}, principal={}", containerId,
                 databaseId, transferDto, principal);
         final Database database = databaseService.transfer(containerId, databaseId, transferDto);
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/container/ContainerBriefDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/container/ContainerBriefDto.java
index e48292d75310ad48545ef11501778970e166fe6e..b8a1b241b3395afa4ddf876576c038ed77247626 100644
--- a/fda-metadata-db/api/src/main/java/at/tuwien/api/container/ContainerBriefDto.java
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/container/ContainerBriefDto.java
@@ -30,6 +30,7 @@ public class ContainerBriefDto {
     @Schema(example = "Air Quality")
     private String name;
 
+    @NotNull
     private UserBriefDto creator;
 
     @NotBlank
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/database/DatabaseBriefDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/database/DatabaseBriefDto.java
index d91f7ce74dfda4a4ef483c774ab25f3b8f7e763e..b6c1807edc884159e457750f61976cdfeea5cb73 100644
--- a/fda-metadata-db/api/src/main/java/at/tuwien/api/database/DatabaseBriefDto.java
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/database/DatabaseBriefDto.java
@@ -40,6 +40,9 @@ public class DatabaseBriefDto {
     @Schema(example = "mariadb:10.5")
     private String engine;
 
+    @NotNull
+    private UserBriefDto owner;
+
     @ToString.Exclude
     @org.springframework.data.annotation.Transient
     private ContainerBriefDto container;
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/database/DatabaseDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/database/DatabaseDto.java
index 56f48fbc2c4cce92726f72707b631c9b34524afa..5d55626797f62f056b63ada80ef1b5dca348cc90 100644
--- a/fda-metadata-db/api/src/main/java/at/tuwien/api/database/DatabaseDto.java
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/database/DatabaseDto.java
@@ -40,9 +40,6 @@ public class DatabaseDto {
     @Schema(example = "dbrepo/air_quality")
     private String exchangeName;
 
-    @NotNull
-    private UserBriefDto creator;
-
     private IdentifierDto identifier;
 
     @NotBlank
@@ -69,6 +66,10 @@ public class DatabaseDto {
 
     private List<DatabaseAccessDto> accesses;
 
+    @NotNull
+    private UserBriefDto creator;
+
+    @NotNull
     private UserBriefDto owner;
 
     @Schema(example = "2020-08-04 11:12:00")
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserBriefDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserBriefDto.java
index fd4c54484fe1a7f755e71041899de9ffeaf547c2..43d341d894daa062c6881a55a36163ea44b5afce 100644
--- a/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserBriefDto.java
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserBriefDto.java
@@ -23,7 +23,6 @@ public class UserBriefDto {
     private String id;
 
     @NotNull
-    @JsonProperty("preferred_username")
     @Schema(example = "jcarberry", description = "Only contains lowercase characters")
     private String username;
 
diff --git a/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserDto.java b/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserDto.java
index f48aab4e6938cf87a4c9b9cf16089296621fcf1d..793be6f7f6ae3f6a5c31c0b084b092d399560c34 100644
--- a/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserDto.java
+++ b/fda-metadata-db/api/src/main/java/at/tuwien/api/user/UserDto.java
@@ -1,7 +1,6 @@
 package at.tuwien.api.user;
 
 import at.tuwien.api.container.ContainerDto;
-import com.fasterxml.jackson.annotation.JsonIgnore;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.*;
@@ -23,7 +22,6 @@ public class UserDto {
     private String id;
 
     @NotNull
-    @JsonProperty("preferred_username")
     @Schema(example = "jcarberry", description = "Only contains lowercase characters")
     private String username;
 
diff --git a/fda-table-service/rest-service/src/main/java/at/tuwien/endpoints/TableColumnEndpoint.java b/fda-table-service/rest-service/src/main/java/at/tuwien/endpoints/TableColumnEndpoint.java
index d5b44de563f3a387b183b5b515a847eb45d30547..b06b38e708957218a25a4b30c1852b549a8f1199 100644
--- a/fda-table-service/rest-service/src/main/java/at/tuwien/endpoints/TableColumnEndpoint.java
+++ b/fda-table-service/rest-service/src/main/java/at/tuwien/endpoints/TableColumnEndpoint.java
@@ -12,6 +12,7 @@ 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.*;
 
@@ -36,6 +37,7 @@ public class TableColumnEndpoint {
 
     @PutMapping
     @Transactional
+    @PreAuthorize("hasAuthority('modify-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"))
     public ResponseEntity<ColumnDto> update(@NotNull @PathVariable("id") Long containerId,
diff --git a/fda-table-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java b/fda-table-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java
index 6c6c1c4577f3b2d2668a4f85c2014f483988ec75..d0e56e313d7e812a2c8b74641ba5448fc95689bc 100644
--- a/fda-table-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java
+++ b/fda-table-service/rest-service/src/main/java/at/tuwien/endpoints/TableEndpoint.java
@@ -45,7 +45,6 @@ public class TableEndpoint {
     @GetMapping
     @Transactional(readOnly = true)
     @Timed(value = "table.list", description = "Time needed to list the tables")
-    @PreAuthorize("hasAuthority('find-tables')")
     @Operation(summary = "List all tables", security = @SecurityRequirement(name = "bearerAuth"))
     public ResponseEntity<List<TableBriefDto>> list(@NotNull @PathVariable("id") Long containerId,
                                                     @NotNull @PathVariable("databaseId") Long databaseId,
@@ -87,7 +86,6 @@ public class TableEndpoint {
     @GetMapping("/{tableId}")
     @Transactional(readOnly = true)
     @Timed(value = "table.find", description = "Time needed to find a table")
-    @PreAuthorize("hasAuthority('find-table')")
     @Operation(summary = "Get information about table", security = @SecurityRequirement(name = "bearerAuth"))
     public ResponseEntity<TableDto> findById(@NotNull @PathVariable("id") Long containerId,
                                              @NotNull @PathVariable("databaseId") Long databaseId,
diff --git a/fda-ui/api/database/index.js b/fda-ui/api/database/index.js
index 17d8bece4d303cfe1e7456f8eda96beaf94a6b33..986311fec70fbd6e6104b87451a46cd4c594904e 100644
--- a/fda-ui/api/database/index.js
+++ b/fda-ui/api/database/index.js
@@ -11,3 +11,22 @@ export function createDatabase (token, container) {
     }
   })
 }
+
+export function modifyVisibility (token, containerId, databaseId, isPublic) {
+  const payload = {
+    is_public: isPublic
+  }
+  return axios.put(`/api/container/${containerId}/database/${databaseId}/visibility`, payload, {
+    headers: {
+      Authorization: `Bearer ${token}`
+    }
+  })
+}
+
+export function findDatabase (token, containerId, databaseId) {
+  return axios.get(`/api/container/${containerId}/database/${databaseId}`, {
+    headers: {
+      Authorization: `Bearer ${token}`
+    }
+  })
+}
diff --git a/fda-ui/api/table/index.js b/fda-ui/api/table/index.js
new file mode 100644
index 0000000000000000000000000000000000000000..d0f5aa0b6fbb21b1610d13ef6ee45e5f7daa0109
--- /dev/null
+++ b/fda-ui/api/table/index.js
@@ -0,0 +1,17 @@
+const axios = require('axios/dist/browser/axios.cjs')
+
+export function listTables (token, containerId, databaseId) {
+  return axios.get(`/api/container/${containerId}/database/${databaseId}/table`, {
+    headers: {
+      Authorization: `Bearer ${token}`
+    }
+  })
+}
+
+export function createTable (token, containerId, databaseId, payload) {
+  return axios.post(`/api/container/${containerId}/database/${databaseId}/table`, payload, {
+    headers: {
+      Authorization: `Bearer ${token}`
+    }
+  })
+}
diff --git a/fda-ui/components/DBToolbar.vue b/fda-ui/components/DBToolbar.vue
index 309001e40b99871404d23562e44d2e72d8e127b9..3da290a9fa7b4fa5678c9962546df0ee3bf0eabe 100644
--- a/fda-ui/components/DBToolbar.vue
+++ b/fda-ui/components/DBToolbar.vue
@@ -86,22 +86,34 @@ export default {
       return this.$store.state.token
     },
     canImportCsv () {
+      if (!this.user) {
+        return false
+      }
       return this.user.roles.includes('insert-table-data')
     },
     canCreateSubset () {
+      if (!this.user) {
+        return false
+      }
       return this.user.roles.includes('execute-query')
     },
     canCreateView () {
+      if (!this.user) {
+        return false
+      }
       return this.user.roles.includes('create-database-view')
     },
     canCreateTable () {
+      if (!this.user) {
+        return false
+      }
       return this.user.roles.includes('create-table')
     },
     isOwner () {
-      if (!this.user || !this.database || !this.database.creator) {
+      if (!this.database || !this.user) {
         return false
       }
-      return this.database.creator.username === this.user.client_id
+      return this.database.owner.username === this.user.username
     },
     config () {
       if (this.token === null) {
diff --git a/fda-ui/components/DatabaseList.vue b/fda-ui/components/DatabaseList.vue
index 757d2be830618099451ea82033638535a60e30ce..572370fd26be5f68a538cece4bf8db087a2fbace 100644
--- a/fda-ui/components/DatabaseList.vue
+++ b/fda-ui/components/DatabaseList.vue
@@ -12,8 +12,8 @@
       <v-card-title v-if="hasDatabase(container)">
         <a :href="`/container/${container.id}/database/${container.database.id}`">{{ container.name }}</a>
       </v-card-title>
-      <v-card-subtitle v-if="!hasIdentifier(container)" class="db-subtitle" v-text="formatCreator(container.creator)" />
-      <v-card-subtitle v-if="hasIdentifier(container)" class="db-subtitle" v-text="formatCreatorz(container)" />
+      <v-card-subtitle v-if="!hasIdentifier(container)" class="db-subtitle" v-text="formatOwner(container)" />
+      <v-card-subtitle v-if="hasIdentifier(container)" class="db-subtitle" v-text="formatCreators(container)" />
       <v-card-text v-if="hasDatabase(container)" class="db-description">
         <div class="db-tags">
           <v-chip v-if="hasDatabase(container) && container.database.is_public" small color="green" outlined>Public</v-chip>
@@ -97,10 +97,13 @@ export default {
     this.loadContainers()
   },
   methods: {
-    formatCreator (creator) {
-      return formatUser(creator)
+    formatOwner (container) {
+      if (!('database' in container)) {
+        return formatUser(container.creator)
+      }
+      return formatUser(container.database?.owner)
     },
-    formatCreatorz (container) {
+    formatCreators (container) {
       const creators = formatCreators(container)
       return creators || this.formatCreator(container.creator)
     },
@@ -108,7 +111,7 @@ export default {
       if (!this.user) {
         return false
       }
-      if (container.creator.sub !== this.user.id) {
+      if (container.creator.sub !== this.user.sub) {
         return false
       }
       return !container.database
diff --git a/fda-ui/pages/container/_container_id/database/_database_id/query/create.vue b/fda-ui/pages/container/_container_id/database/_database_id/query/create.vue
index bc8e51ad13468dc5ac0899da3b72ca56d39ef974..52ca422a0a3dfd592e10acd9eb67c442f33a3692 100644
--- a/fda-ui/pages/container/_container_id/database/_database_id/query/create.vue
+++ b/fda-ui/pages/container/_container_id/database/_database_id/query/create.vue
@@ -1,13 +1,11 @@
 <template>
-  <div v-if="isResearcher">
+  <div v-if="canExecuteQuery">
     <QueryBuilder />
     <v-breadcrumbs :items="items" class="pa-0 mt-2" />
   </div>
 </template>
 
 <script>
-import { isResearcher } from '@/utils'
-
 export default {
   data () {
     return {
@@ -30,8 +28,11 @@ export default {
     user () {
       return this.$store.state.user
     },
-    isResearcher () {
-      return isResearcher(this.user)
+    canExecuteQuery () {
+      if (!this.user) {
+        return false
+      }
+      return this.user.roles.includes('execute-query')
     }
   }
 }
diff --git a/fda-ui/pages/container/_container_id/database/_database_id/settings.vue b/fda-ui/pages/container/_container_id/database/_database_id/settings.vue
index a22d9092ede9f2dca88c0e21c619011358dc403e..85631642ea9c0b656309f7024109171412c44176 100644
--- a/fda-ui/pages/container/_container_id/database/_database_id/settings.vue
+++ b/fda-ui/pages/container/_container_id/database/_database_id/settings.vue
@@ -4,19 +4,18 @@
     <v-progress-linear v-if="loading" />
     <v-tabs-items v-model="tab">
       <v-tab-item>
-        <v-card v-if="isCreator" flat tile>
+        <v-card v-if="isOwner" flat tile>
           <v-card-title>Modify database access</v-card-title>
           <v-card-subtitle>This is a dangerous operation</v-card-subtitle>
           <v-data-table
             :headers="headers"
             :items="database.accesses"
             :items-per-page="10">
-            <template v-if="isCreator" v-slot:item.user="{ item }">
+            <template v-slot:item.user="{ item }">
               {{ item.user.username }}
             </template>
-            <template v-if="isCreator" v-slot:item.action="{ item }">
+            <template v-slot:item.action="{ item }">
               <v-btn
-                :disabled="isCreator && item.user.username === user.username"
                 x-small
                 @click="modifyAccess(item)">
                 Modify
@@ -34,7 +33,7 @@
           </v-card-text>
         </v-card>
         <v-divider />
-        <v-card v-if="isCreator" flat tile>
+        <v-card v-if="canModifyVisibility" flat tile>
           <v-card-title>Modify database visibility</v-card-title>
           <v-card-subtitle>This is a dangerous operation</v-card-subtitle>
           <v-card-text>
@@ -78,6 +77,7 @@
 <script>
 import DBToolbar from '@/components/DBToolbar'
 import EditAccess from '@/components/dialogs/EditAccess'
+import { modifyVisibility } from '@/api/database'
 
 export default {
   components: {
@@ -139,14 +139,20 @@ export default {
     user () {
       return this.$store.state.user
     },
-    isCreator () {
+    isOwner () {
       if (!this.database || !this.user) {
         return false
       }
-      if (this.database.creator.username === null || this.user.username === null) {
+      if (this.database.owner.username === null || this.user.username === null) {
         return false
       }
-      return this.database.creator.username === this.user.username
+      return this.database.owner.username === this.user.username
+    },
+    canModifyVisibility () {
+      if (!this.isOwner) {
+        return false
+      }
+      return this.user.roles.includes('modify-database-visibility')
     }
   },
   watch: {
@@ -174,11 +180,12 @@ export default {
     async updateDatabaseVisibility () {
       try {
         this.loading = true
-        await this.$axios.put(`/api/container/${this.$route.params.container_id}/database/${this.$route.params.database_id}/visibility`, this.modifyVisibility, this.config)
-        this.$toast.success('Successfully updated the database')
+        await modifyVisibility(this.token, this.$route.params.container_id, this.$route.params.database_id, this.modifyVisibility.is_public)
+        this.$toast.success('Successfully updated the database visibility')
         location.reload()
-      } catch (err) {
-        this.$toast.error('Failed to update database')
+      } catch (error) {
+        console.error('Failed to update database visibility', error)
+        this.$toast.error('Failed to update database visibility')
       }
       this.loading = false
     },
diff --git a/fda-ui/pages/container/_container_id/database/_database_id/table/create.vue b/fda-ui/pages/container/_container_id/database/_database_id/table/create.vue
index 7d857015992f896db7abd8f66c1278820900e738..7a405ae2ed56946cd2d2fed6b936d0991ce344ea 100644
--- a/fda-ui/pages/container/_container_id/database/_database_id/table/create.vue
+++ b/fda-ui/pages/container/_container_id/database/_database_id/table/create.vue
@@ -1,9 +1,12 @@
 <template>
-  <div v-if="isResearcher">
+  <div v-if="canCreateTable">
     <v-toolbar flat>
       <v-toolbar-title>
-        <span>Create Table</span>
+        <v-btn id="back-btn" class="mr-2" :to="`/container/${$route.params.container_id}/database/${$route.params.database_id}/table`">
+          <v-icon left>mdi-arrow-left</v-icon>
+        </v-btn>
       </v-toolbar-title>
+      <v-toolbar-title>Create Table</v-toolbar-title>
     </v-toolbar>
     <v-stepper v-model="step" vertical flat tile>
       <v-stepper-step :complete="step > 1" step="1">
@@ -57,7 +60,9 @@
 
 <script>
 import TableSchema from '@/components/TableSchema'
-const { notEmpty, isResearcher } = require('@/utils')
+import { notEmpty } from '@/utils'
+import { createTable } from '@/api/table'
+import { findDatabase } from '@/api/database'
 
 export default {
   components: {
@@ -104,8 +109,11 @@ export default {
     database () {
       return this.$store.state.database
     },
-    isResearcher () {
-      return isResearcher(this.user)
+    canCreateTable () {
+      if (!this.user) {
+        return false
+      }
+      return this.user.roles.includes('create-table')
     },
     config () {
       if (this.token === null) {
@@ -144,7 +152,7 @@ export default {
     async createTable () {
       try {
         this.loading = true
-        const res = await this.$axios.post(`/api/container/${this.$route.params.container_id}/database/${this.databaseId}/table`, this.tableCreate, this.config)
+        const res = await createTable(this.token, this.$route.params.container_id, this.$route.params.database_id, this.tableCreate)
         if (res.status === 201) {
           this.error = false
           this.$toast.success('Table created')
@@ -174,11 +182,11 @@ export default {
       }
       try {
         this.loading = true
-        const res = await this.$axios.get(`/api/container/${this.$route.params.container_id}/database/${this.$route.params.database_id}`, this.config)
+        const res = await findDatabase(this.token, this.$route.params.container_id, this.$route.params.database_id)
         this.$store.commit('SET_DATABASE', res.data)
         console.debug('database', this.database)
-      } catch (err) {
-        console.error('Could not load database', err)
+      } catch (error) {
+        console.error('Could not load database', error)
         this.$toast.error('Could not load database')
       }
       this.loading = false
diff --git a/fda-ui/pages/container/_container_id/database/_database_id/table/import.vue b/fda-ui/pages/container/_container_id/database/_database_id/table/import.vue
index f8899888914a07c30838c165b5429f3ba5545020..634c92fbed91ef8cb7434461b7c6ddaf6c8616ee 100644
--- a/fda-ui/pages/container/_container_id/database/_database_id/table/import.vue
+++ b/fda-ui/pages/container/_container_id/database/_database_id/table/import.vue
@@ -1,5 +1,5 @@
 <template>
-  <div v-if="isResearcher">
+  <div v-if="canInsertTableData">
     <v-toolbar flat>
       <v-toolbar-title>Create Table Schema (and Import Data) from .csv/.tsv</v-toolbar-title>
     </v-toolbar>
@@ -186,7 +186,8 @@
 </template>
 <script>
 import TableSchema from '@/components/TableSchema'
-const { notEmpty, isNonNegativeInteger, isResearcher } = require('@/utils')
+import { notEmpty, isNonNegativeInteger, isResearcher } from '@/utils'
+import { listTables } from '@/api/table'
 
 export default {
   name: 'TableFromCSV',
@@ -284,6 +285,12 @@ export default {
         .replace(/\s+/g, '-')
         .replace(/[^\w-]+/g, '')
         .replace(/--+/g, '_'))
+    },
+    canInsertTableData () {
+      if (!this.user) {
+        return false
+      }
+      return this.user.roles.includes('insert-table-data')
     }
   },
   mounted () {
@@ -351,15 +358,13 @@ export default {
     async listTables () {
       try {
         this.loading = true
-        const res = await this.$axios.get(`/api/container/${this.$route.params.container_id}/database/${this.$route.params.database_id}/table`, {
-          headers: { Authorization: `Bearer ${this.token}` }
-        })
+        const res = await listTables(this.token, this.$route.params.container_id, this.$route.params.database_id)
         console.debug('tables', res.data)
         this.tableNames = res.data.map(t => t.internal_name)
-      } catch (err) {
+      } catch (error) {
         this.error = true
-        console.error('could not list tables', err)
-        this.$toast.error('Could not list tables')
+        console.error('Failed to list tables', error)
+        this.$toast.error('Failed to list tables')
       }
       this.loading = false
     },
diff --git a/fda-ui/pages/container/_container_id/database/_database_id/view/create.vue b/fda-ui/pages/container/_container_id/database/_database_id/view/create.vue
index f48a14aa6104492be83c7b55f6af506830932ce0..a78526e1bcf9b763334632ad8a51cb69f4b3ce98 100644
--- a/fda-ui/pages/container/_container_id/database/_database_id/view/create.vue
+++ b/fda-ui/pages/container/_container_id/database/_database_id/view/create.vue
@@ -1,13 +1,11 @@
 <template>
-  <div v-if="isResearcher">
+  <div v-if="canCreateView">
     <QueryBuilder mode="view" />
     <v-breadcrumbs :items="items" class="pa-0 mt-2" />
   </div>
 </template>
 
 <script>
-import { isResearcher } from '@/utils'
-
 export default {
   data () {
     return {
@@ -30,8 +28,11 @@ export default {
     user () {
       return this.$store.state.user
     },
-    isResearcher () {
-      return isResearcher(this.user)
+    canCreateView () {
+      if (!this.user) {
+        return false
+      }
+      return this.user.roles.includes('create-database-view')
     }
   }
 }
diff --git a/fda-ui/utils/index.js b/fda-ui/utils/index.js
index ce98464f42f4843294166b9398a27d872481def2..3772dbb7a808a9dcf52ab2a0c0f2b12a6b18f93d 100644
--- a/fda-ui/utils/index.js
+++ b/fda-ui/utils/index.js
@@ -55,10 +55,7 @@ function formatUser (user) {
     return null
   }
   if (!('firstname' in user) || !('lastname' in user) || user.firstname === null || user.lastname === null) {
-    if (!('preferred_username' in user)) {
-      return null
-    }
-    return user.preferred_username
+    return user?.username
   }
   return user.firstname + ' ' + user.lastname
 }