diff --git a/server/bundles/io.cloudbeaver.server/db/cb-schema-create.sql b/server/bundles/io.cloudbeaver.server/db/cb-schema-create.sql index 0133e18035..2bedb9e1f1 100644 --- a/server/bundles/io.cloudbeaver.server/db/cb-schema-create.sql +++ b/server/bundles/io.cloudbeaver.server/db/cb-schema-create.sql @@ -9,18 +9,18 @@ CREATE TABLE CB_SERVER( ); CREATE TABLE CB_AUTH_SUBJECT( - SUBJECT_ID VARCHAR(64) NOT NULL, + SUBJECT_ID VARCHAR(128) NOT NULL, SUBJECT_TYPE VARCHAR(8) NOT NULL, PRIMARY KEY(SUBJECT_ID) ); CREATE TABLE CB_AUTH_PERMISSIONS( - SUBJECT_ID VARCHAR(32) NOT NULL, + SUBJECT_ID VARCHAR(128) NOT NULL, PERMISSION_ID VARCHAR(64) NOT NULL, GRANT_TIME TIMESTAMP NOT NULL, - GRANTED_BY VARCHAR(64) NOT NULL, + GRANTED_BY VARCHAR(128) NOT NULL, PRIMARY KEY(SUBJECT_ID,PERMISSION_ID), FOREIGN KEY(SUBJECT_ID) REFERENCES CB_AUTH_SUBJECT(SUBJECT_ID) ON DELETE CASCADE @@ -28,17 +28,17 @@ CREATE TABLE CB_AUTH_PERMISSIONS( CREATE TABLE CB_DATASOURCE_ACCESS( DATASOURCE_ID VARCHAR(128) NOT NULL, - SUBJECT_ID VARCHAR(32) NOT NULL, + SUBJECT_ID VARCHAR(128) NOT NULL, GRANT_TIME TIMESTAMP NOT NULL, - GRANTED_BY VARCHAR(64) NOT NULL, + GRANTED_BY VARCHAR(128) NOT NULL, PRIMARY KEY(SUBJECT_ID,DATASOURCE_ID), FOREIGN KEY(SUBJECT_ID) REFERENCES CB_AUTH_SUBJECT(SUBJECT_ID) ON DELETE CASCADE ); CREATE TABLE CB_USER( - USER_ID VARCHAR(64) NOT NULL, + USER_ID VARCHAR(128) NOT NULL, IS_ACTIVE CHAR(1) NOT NULL, CREATE_TIME TIMESTAMP NOT NULL, @@ -49,7 +49,7 @@ CREATE TABLE CB_USER( -- Additional user properties (profile) CREATE TABLE CB_USER_META( - USER_ID VARCHAR(64) NOT NULL, + USER_ID VARCHAR(128) NOT NULL, META_ID VARCHAR(32) NOT NULL, META_VALUE VARCHAR(1024), @@ -58,7 +58,7 @@ CREATE TABLE CB_USER_META( ); CREATE TABLE CB_ROLE( - ROLE_ID VARCHAR(32) NOT NULL, + ROLE_ID VARCHAR(128) NOT NULL, ROLE_NAME VARCHAR(100) NOT NULL, ROLE_DESCRIPTION VARCHAR(255) NOT NULL, @@ -69,11 +69,11 @@ CREATE TABLE CB_ROLE( ); CREATE TABLE CB_USER_ROLE( - USER_ID VARCHAR(64) NOT NULL, - ROLE_ID VARCHAR(32) NOT NULL, + USER_ID VARCHAR(128) NOT NULL, + ROLE_ID VARCHAR(128) NOT NULL, GRANT_TIME TIMESTAMP NOT NULL, - GRANTED_BY VARCHAR(32) NOT NULL, + GRANTED_BY VARCHAR(128) NOT NULL, PRIMARY KEY(USER_ID,ROLE_ID), FOREIGN KEY(USER_ID) REFERENCES CB_USER(USER_ID) ON DELETE CASCADE, @@ -97,7 +97,7 @@ CREATE TABLE CB_AUTH_CONFIGURATION( ); CREATE TABLE CB_USER_CREDENTIALS( - USER_ID VARCHAR(64) NOT NULL, + USER_ID VARCHAR(128) NOT NULL, PROVIDER_ID VARCHAR(32) NOT NULL, CRED_ID VARCHAR(32) NOT NULL, CRED_VALUE VARCHAR(1024) NOT NULL, @@ -109,7 +109,7 @@ CREATE TABLE CB_USER_CREDENTIALS( CREATE INDEX CB_USER_CREDENTIALS_SEARCH_IDX ON CB_USER_CREDENTIALS(PROVIDER_ID,CRED_ID); CREATE TABLE CB_USER_STATE( - USER_ID VARCHAR(64) NOT NULL, + USER_ID VARCHAR(128) NOT NULL, USER_CONFIGURATION TEXT NULL, @@ -121,7 +121,7 @@ CREATE TABLE CB_USER_STATE( CREATE TABLE CB_SESSION( SESSION_ID VARCHAR(64) NOT NULL, - USER_ID VARCHAR(64) NULL, + USER_ID VARCHAR(128) NULL, CREATE_TIME TIMESTAMP NOT NULL, LAST_ACCESS_REMOTE_ADDRESS NULL, diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBAppConfig.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBAppConfig.java index 6e27dbadf2..1b72a81742 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBAppConfig.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBAppConfig.java @@ -90,12 +90,26 @@ public class CBAppConfig { return defaultAuthProvider; } + public Map getPlugins() { + return plugins; + } + public Map getPluginConfig(String pluginId) { + return getPluginConfig(pluginId, false); + } + + public Map getPluginConfig(String pluginId, boolean create) { Object config = plugins.get(pluginId); if (config instanceof Map) { return (Map) config; } else { - return Collections.emptyMap(); + if (create) { + Map newConfig = new LinkedHashMap<>(); + plugins.put(pluginId, newConfig); + return newConfig; + } else { + return Collections.emptyMap(); + } } } diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBApplication.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBApplication.java index b8c5639b39..6a76a70130 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBApplication.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBApplication.java @@ -554,6 +554,7 @@ public class CBApplication extends BaseApplicationImpl { .setPrettyPrinting() .create(); try (JsonWriter json = gson.newJsonWriter(out)) { + json.setLenient(true); json.beginObject(); { json.name("server"); @@ -572,6 +573,11 @@ public class CBApplication extends BaseApplicationImpl { JSONUtils.field(json, "anonymousAccessEnabled", appConfig.isAnonymousAccessEnabled()); JSONUtils.field(json, "authenticationEnabled", appConfig.isAuthenticationEnabled()); JSONUtils.field(json, "supportsCustomConnections", appConfig.isSupportsCustomConnections()); + + if (!CommonUtils.isEmpty(appConfig.getPlugins())) { + JSONUtils.serializeProperties(json, "plugins", appConfig.getPlugins()); + } + json.endObject(); } json.endObject(); diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBDatabase.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBDatabase.java index 798e19c201..d3bcaddf14 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBDatabase.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBDatabase.java @@ -172,6 +172,8 @@ public class CBDatabase { // Create new admin user if (!CommonUtils.isEmpty(adminName) && !CommonUtils.isEmpty(adminPassword)) { createAdminUser(adminName, adminPassword); + } else { + grantAdminPermissionsToUser(adminName); } } @@ -344,16 +346,21 @@ public class CBDatabase { serverController.setUserCredentials(adminUser.getUserId(), authProvider, credentials); } - // Grant all roles - WebRole[] allRoles = serverController.readAllRoles(); - serverController.setUserRoles( - adminUser.getUserId(), - Arrays.stream(allRoles).map(WebRole::getRoleId).toArray(String[]::new), - adminUser.getUserId()); + grantAdminPermissionsToUser(adminUser.getUserId()); return adminUser; } + private void grantAdminPermissionsToUser(String userId) throws DBCException { + // Grant all roles + DBWSecurityController securityController = application.getSecurityController(); + WebRole[] allRoles = securityController.readAllRoles(); + securityController.setUserRoles( + userId, + Arrays.stream(allRoles).map(WebRole::getRoleId).toArray(String[]::new), + userId); + } + void shutdown() { log.debug("Shutdown database"); if (cbDataSource != null) { diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/DBWServiceServerConfigurator.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/DBWServiceServerConfigurator.java new file mode 100644 index 0000000000..39eca62987 --- /dev/null +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/service/DBWServiceServerConfigurator.java @@ -0,0 +1,33 @@ +/* + * DBeaver - Universal Database Manager + * Copyright (C) 2010-2020 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.cloudbeaver.service; + +import io.cloudbeaver.model.session.WebSession; +import io.cloudbeaver.server.CBAppConfig; +import org.jkiss.code.NotNull; +import org.jkiss.code.Nullable; +import org.jkiss.dbeaver.DBException; +import org.jkiss.dbeaver.model.app.DBPApplication; + +/** + * Web service implementation + */ +public interface DBWServiceServerConfigurator extends DBWServiceBinding { + + void configureServer(@NotNull DBPApplication application, @Nullable WebSession session, @NotNull CBAppConfig appConfig) throws DBException; + +} diff --git a/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/AdminServerConfig.java b/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/AdminServerConfig.java index f6f6af45cb..d86f828243 100644 --- a/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/AdminServerConfig.java +++ b/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/AdminServerConfig.java @@ -16,6 +16,8 @@ */ package io.cloudbeaver.service.admin; +import io.cloudbeaver.server.CBAppConfig; +import io.cloudbeaver.server.CBApplication; import org.jkiss.dbeaver.model.data.json.JSONUtils; import java.util.Map; @@ -41,9 +43,10 @@ public class AdminServerConfig { this.adminName = JSONUtils.getString(params, "adminName"); this.adminPassword = JSONUtils.getString(params, "adminPassword"); - this.anonymousAccessEnabled = JSONUtils.getBoolean(params, "anonymousAccessEnabled"); - this.authenticationEnabled = JSONUtils.getBoolean(params, "authenticationEnabled"); - this.customConnectionsEnabled = JSONUtils.getBoolean(params, "customConnectionsEnabled"); + CBAppConfig appConfig = CBApplication.getInstance().getAppConfiguration(); + this.anonymousAccessEnabled = JSONUtils.getBoolean(params, "anonymousAccessEnabled", appConfig.isAnonymousAccessEnabled()); + this.authenticationEnabled = JSONUtils.getBoolean(params, "authenticationEnabled", appConfig.isAuthenticationEnabled()); + this.customConnectionsEnabled = JSONUtils.getBoolean(params, "customConnectionsEnabled", appConfig.isSupportsCustomConnections()); this.sessionExpireTime = JSONUtils.getLong(params, "sessionExpireTime", -1); } diff --git a/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/impl/WebServiceAdmin.java b/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/impl/WebServiceAdmin.java index cd229569c8..ab6358af18 100644 --- a/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/impl/WebServiceAdmin.java +++ b/server/bundles/io.cloudbeaver.service.admin/src/io/cloudbeaver/service/admin/impl/WebServiceAdmin.java @@ -32,6 +32,7 @@ import io.cloudbeaver.registry.WebServiceRegistry; import io.cloudbeaver.server.CBAppConfig; import io.cloudbeaver.server.CBApplication; import io.cloudbeaver.server.CBPlatform; +import io.cloudbeaver.service.DBWServiceServerConfigurator; import io.cloudbeaver.service.admin.*; import org.jkiss.code.NotNull; import org.jkiss.dbeaver.Log; @@ -298,12 +299,31 @@ public class WebServiceAdmin implements DBWServiceAdmin { appConfig.setAnonymousAccessEnabled(config.isAnonymousAccessEnabled()); appConfig.setAuthenticationEnabled(config.isAuthenticationEnabled()); appConfig.setSupportsCustomConnections(config.isCustomConnectionsEnabled()); + String adminName = config.getAdminName(); + String adminPassword = config.getAdminPassword(); + if (CommonUtils.isEmpty(adminName)) { + // Grant admin permissions to the current user + WebUser curUser = webSession.getUser(); + adminName = curUser == null ? null : curUser.getUserId(); + adminPassword = null; + } + + // Patch configuration by services + for (DBWServiceServerConfigurator wsc : WebServiceRegistry.getInstance().getWebServices(DBWServiceServerConfigurator.class)) { + try { + wsc.configureServer(CBApplication.getInstance(), webSession, appConfig); + } catch (Exception e) { + log.warn("Error configuring server by web service " + wsc.getClass().getName(), e); + } + } + CBApplication.getInstance().finishConfiguration( config.getServerName(), - config.getAdminName(), - config.getAdminPassword(), + adminName, + adminPassword, config.getSessionExpireTime(), appConfig); + // Refresh active session webSession.forceUserRefresh(null); } catch (Throwable e) { diff --git a/webapp/packages/core-connections/src/Administration/Connections/ConnectionsAdministrationController.ts b/webapp/packages/core-connections/src/Administration/Connections/ConnectionsAdministrationController.ts index 73f2d4b47a..f6687122a1 100644 --- a/webapp/packages/core-connections/src/Administration/Connections/ConnectionsAdministrationController.ts +++ b/webapp/packages/core-connections/src/Administration/Connections/ConnectionsAdministrationController.ts @@ -84,8 +84,9 @@ export class ConnectionsAdministrationController { .filter(Boolean); const confirmed = await this.commonDialogService.open(ConfirmationDialog, { - title: 'authentication_administration_confirm_user_deletion', - message: `Would you like to delete connections: ${connectionNames.join(', ')}`, + title: 'authentication_administration_confirm_connection_deletion', + message: `You're going to delete these connections: ${connectionNames.join(', ')}. Are you sure?`, + confirmActionText: 'ui_delete', }); if (!confirmed) { diff --git a/webapp/packages/core-connections/src/ConnectionsManagerService.ts b/webapp/packages/core-connections/src/ConnectionsManagerService.ts index b28fcba503..10ff8f0638 100644 --- a/webapp/packages/core-connections/src/ConnectionsManagerService.ts +++ b/webapp/packages/core-connections/src/ConnectionsManagerService.ts @@ -83,7 +83,7 @@ export class ConnectionsManagerService { const confirmed = await this.commonDialogService.open(ConfirmationDialog, { title: 'app_shared_navigationTree_delete_connection_confirm', - message: `Would you like to delete ${connection.name} connection?`, + message: `You're going to delete ${connection.name} connection. Are you sure?`, confirmActionText: 'ui_delete', }); if (!confirmed) { diff --git a/webapp/packages/plugin-authentication/src/Administration/Users/UsersAdministrationController.ts b/webapp/packages/plugin-authentication/src/Administration/Users/UsersAdministrationController.ts index 4fd11f9e33..0846eaae08 100644 --- a/webapp/packages/plugin-authentication/src/Administration/Users/UsersAdministrationController.ts +++ b/webapp/packages/plugin-authentication/src/Administration/Users/UsersAdministrationController.ts @@ -99,7 +99,8 @@ export class UsersAdministrationController { const confirmed = await this.commonDialogService.open(ConfirmationDialog, { title: 'authentication_administration_confirm_user_deletion', - message: `Would you like to delete users: ${deletionList.join(', ')}`, + message: `You're going to delete these users: ${deletionList.join(', ')}. Are you sure?`, + confirmActionText: 'ui_delete', }); if (!confirmed) { diff --git a/webapp/packages/plugin-authentication/src/locales/en.ts b/webapp/packages/plugin-authentication/src/locales/en.ts index f69095eac0..2f49304f9f 100644 --- a/webapp/packages/plugin-authentication/src/locales/en.ts +++ b/webapp/packages/plugin-authentication/src/locales/en.ts @@ -14,6 +14,7 @@ export default [ ['authentication_administration_user_info', 'Info'], ['authentication_administration_item', 'Users'], ['authentication_administration_confirm_user_deletion', 'Confirm user deletion'], + ['authentication_administration_confirm_connection_deletion', 'Confirm connection deletion'], ['authentication_administration_user_updated', 'User updated'], ['authentication_administration_user_created', 'User was created successfully'], ['authentication_user_name', 'User name'], diff --git a/webapp/packages/plugin-authentication/src/locales/ru.ts b/webapp/packages/plugin-authentication/src/locales/ru.ts index 5a59ecddc9..611a5c701b 100644 --- a/webapp/packages/plugin-authentication/src/locales/ru.ts +++ b/webapp/packages/plugin-authentication/src/locales/ru.ts @@ -14,6 +14,7 @@ export default [ ['authentication_administration_user_info', 'Общее'], ['authentication_administration_item', 'Пользователи'], ['authentication_administration_confirm_user_deletion', 'Подтвердите удаление'], + ['authentication_administration_confirm_connection_deletion', 'Подтвердите удаление'], ['authentication_administration_user_updated', 'User updated'], ['authentication_administration_user_created', 'Пользователь создан успешно'], ['authentication_user_name', 'Имя'],