diff --git a/config/core/product.conf b/config/core/product.conf index ebdd856ea3..516326626e 100644 --- a/config/core/product.conf +++ b/config/core/product.conf @@ -16,9 +16,6 @@ maxLogRecords: 2000, maxFailedRequests: 3 } - }, - authentication: { - primaryAuthProvider: 'local' } }, // Notifications config diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/app/WebAuthApplication.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/app/WebAuthApplication.java index 8ac69c9f3f..65e39c79d2 100644 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/app/WebAuthApplication.java +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/app/WebAuthApplication.java @@ -18,6 +18,7 @@ package io.cloudbeaver.model.app; import io.cloudbeaver.auth.CBAuthConstants; +import org.jkiss.dbeaver.DBException; public interface WebAuthApplication extends WebApplication { WebAuthConfiguration getAuthConfiguration(); @@ -27,4 +28,6 @@ public interface WebAuthApplication extends WebApplication { default long getMaxSessionIdleTime() { return CBAuthConstants.MAX_SESSION_IDLE_TIME; } + + void flushConfiguration() throws DBException; } diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/app/WebAuthConfiguration.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/app/WebAuthConfiguration.java index 930b2d5efd..843b8e8e03 100644 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/app/WebAuthConfiguration.java +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/model/app/WebAuthConfiguration.java @@ -16,6 +16,7 @@ */ package io.cloudbeaver.model.app; +import org.jkiss.code.NotNull; import org.jkiss.code.Nullable; import org.jkiss.dbeaver.model.security.SMAuthProviderCustomConfiguration; @@ -36,4 +37,6 @@ public interface WebAuthConfiguration { @Nullable SMAuthProviderCustomConfiguration getAuthProviderConfiguration(String configId); + + void addAuthProviderConfiguration(@NotNull SMAuthProviderCustomConfiguration config); } diff --git a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/service/DBWServiceServerConfigurator.java b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/service/DBWServiceServerConfigurator.java index b0f3e632ba..adf6300d7e 100644 --- a/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/service/DBWServiceServerConfigurator.java +++ b/server/bundles/io.cloudbeaver.model/src/io/cloudbeaver/service/DBWServiceServerConfigurator.java @@ -17,11 +17,11 @@ package io.cloudbeaver.service; import io.cloudbeaver.model.app.WebAppConfiguration; +import io.cloudbeaver.model.app.WebApplication; import io.cloudbeaver.model.session.WebSession; 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 @@ -29,11 +29,15 @@ import org.jkiss.dbeaver.model.app.DBPApplication; public interface DBWServiceServerConfigurator extends DBWServiceBinding { void configureServer( - @NotNull DBPApplication application, + @NotNull WebApplication application, @Nullable WebSession session, @NotNull WebAppConfiguration appConfig ) throws DBException; + default void migrateConfigurationIfNeeded(@NotNull WebApplication application) { + + } + void reloadConfiguration(@NotNull WebAppConfiguration appConfig) throws DBException; } 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 d5c57c5807..1490f29247 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 @@ -16,12 +16,12 @@ */ package io.cloudbeaver.server; -import org.jkiss.dbeaver.model.auth.AuthInfo; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.InstanceCreator; import io.cloudbeaver.WebServiceUtils; import io.cloudbeaver.auth.CBAuthConstants; +import io.cloudbeaver.auth.NoAuthCredentialsProvider; import io.cloudbeaver.model.app.BaseWebApplication; import io.cloudbeaver.model.app.WebAuthApplication; import io.cloudbeaver.model.app.WebAuthConfiguration; @@ -43,6 +43,7 @@ import org.jkiss.dbeaver.Log; import org.jkiss.dbeaver.ModelPreferences; import org.jkiss.dbeaver.model.DBPDataSourceContainer; import org.jkiss.dbeaver.model.app.DBPApplication; +import org.jkiss.dbeaver.model.auth.AuthInfo; import org.jkiss.dbeaver.model.auth.SMCredentialsProvider; import org.jkiss.dbeaver.model.data.json.JSONUtils; import org.jkiss.dbeaver.model.navigator.DBNBrowseSettings; @@ -430,7 +431,14 @@ public abstract class CBApplication extends BaseWebApplication implements WebAut } protected void initializeServer() throws DBException { - + for (DBWServiceServerConfigurator wsc : WebServiceRegistry.getInstance() + .getWebServices(DBWServiceServerConfigurator.class)) { + try { + wsc.migrateConfigurationIfNeeded(this); + } catch (Exception e) { + log.warn("Error migration configuration " + wsc.getClass().getName(), e); + } + } } private void determineLocalAddresses() { @@ -889,8 +897,12 @@ public abstract class CBApplication extends BaseWebApplication implements WebAut @NotNull List authInfoList ) throws DBException; - public synchronized void flushConfiguration(SMCredentialsProvider credentialsProvider) throws DBException { - saveRuntimeConfig(serverName, serverURL, maxSessionIdleTime, appConfiguration, credentialsProvider); + public synchronized void flushConfiguration(SMCredentialsProvider webSession) throws DBException { + saveRuntimeConfig(serverName, serverURL, maxSessionIdleTime, appConfiguration, webSession); + } + + public synchronized void flushConfiguration() throws DBException { + saveRuntimeConfig(serverName, serverURL, maxSessionIdleTime, appConfiguration, new NoAuthCredentialsProvider()); } diff --git a/server/test/io.cloudbeaver.test.platform/workspace/conf/product.conf b/server/test/io.cloudbeaver.test.platform/workspace/conf/product.conf index b834cd326b..6a72ce6e70 100644 --- a/server/test/io.cloudbeaver.test.platform/workspace/conf/product.conf +++ b/server/test/io.cloudbeaver.test.platform/workspace/conf/product.conf @@ -20,9 +20,6 @@ # max size of the file that can be uploaded to the editor (in kilobytes) maxFileSize: 100 } - }, - authentication: { - primaryAuthProvider: 'local' } }, // Notifications config diff --git a/webapp/packages/core-authentication/src/AuthProvidersResource.ts b/webapp/packages/core-authentication/src/AuthProvidersResource.ts index 62a6522df2..bc7bd6c107 100644 --- a/webapp/packages/core-authentication/src/AuthProvidersResource.ts +++ b/webapp/packages/core-authentication/src/AuthProvidersResource.ts @@ -67,26 +67,10 @@ export class AuthProvidersResource extends CachedMapResource app.init()); const equalConfig = { core: { authentication: { - baseAuthProvider: 'sd', - primaryAuthProvider: 'sd', disableAnonymousAccess: true, } as AuthSettings, }, @@ -64,7 +62,5 @@ test('Read settings', async () => { await config.refresh(); - expect(settings.settings.getValue('baseAuthProvider')).toBe('sd'); - expect(settings.settings.getValue('primaryAuthProvider')).toBe('sd'); expect(settings.settings.getValue('disableAnonymousAccess')).toBe(true); }); diff --git a/webapp/packages/core-authentication/src/AuthSettingsService.ts b/webapp/packages/core-authentication/src/AuthSettingsService.ts index 3fd7d03790..9cbe88f892 100644 --- a/webapp/packages/core-authentication/src/AuthSettingsService.ts +++ b/webapp/packages/core-authentication/src/AuthSettingsService.ts @@ -12,8 +12,6 @@ import { SettingsManagerService } from '@cloudbeaver/core-settings'; import { AUTH_SETTINGS_GROUP, settings } from './AUTH_SETTINGS_GROUP'; const defaultSettings = { - baseAuthProvider: undefined as undefined | string, - primaryAuthProvider: 'local', disableAnonymousAccess: false, }; diff --git a/webapp/packages/core-root/src/__custom_mocks__/data/defaultProductConfiguration.ts b/webapp/packages/core-root/src/__custom_mocks__/data/defaultProductConfiguration.ts index 63a88b8877..8cffc844fd 100644 --- a/webapp/packages/core-root/src/__custom_mocks__/data/defaultProductConfiguration.ts +++ b/webapp/packages/core-root/src/__custom_mocks__/data/defaultProductConfiguration.ts @@ -23,9 +23,6 @@ export const defaultProductConfiguration: Record = { maxFailedRequests: 3.0, }, }, - authentication: { - primaryAuthProvider: 'local', - }, }, plugin_data_export: { disabled: false, diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/ServerConfiguration/AuthenticationProviders.tsx b/webapp/packages/plugin-authentication-administration/src/Administration/ServerConfiguration/AuthenticationProviders.tsx index 8810379ffc..825bb6861c 100644 --- a/webapp/packages/plugin-authentication-administration/src/Administration/ServerConfiguration/AuthenticationProviders.tsx +++ b/webapp/packages/plugin-authentication-administration/src/Administration/ServerConfiguration/AuthenticationProviders.tsx @@ -8,16 +8,11 @@ import { observer } from 'mobx-react-lite'; import React, { useContext } from 'react'; -import { - AUTH_PROVIDER_LOCAL_ID, - AuthProvider, - AuthProviderService, - AuthProvidersResource, - AuthSettingsService, -} from '@cloudbeaver/core-authentication'; +import { AUTH_PROVIDER_LOCAL_ID, AuthProviderService, AuthProvidersResource, AuthSettingsService } from '@cloudbeaver/core-authentication'; import { FormContext, Group, GroupTitle, PlaceholderComponent, Switch, useExecutor, useResource, useTranslate } from '@cloudbeaver/core-blocks'; import { useService } from '@cloudbeaver/core-di'; import { CachedMapAllKey } from '@cloudbeaver/core-resource'; +import { isDefined } from '@cloudbeaver/core-utils'; import type { IConfigurationPlaceholderProps } from '@cloudbeaver/plugin-administration'; import { ServerConfigurationAdminForm } from './ServerConfigurationAdminForm'; @@ -36,17 +31,24 @@ export const AuthenticationProviders: PlaceholderComponent((provider): provider is AuthProvider => { - if (configurationWizard && (provider?.configurable || provider?.private)) { + const localProvider = providers.resource.get(AUTH_PROVIDER_LOCAL_ID); + const providerList = providers.data.filter(isDefined).filter(provider => { + if (provider.private) { return false; } + if (configurationWizard) { + const disabledByFeature = provider.requiredFeatures.some(feat => !serverConfig.enabledFeatures?.includes(feat)); + + if (provider.configurable || disabledByFeature) { + return false; + } + } + return true; }); - const localProvider = providers.resource.get(AUTH_PROVIDER_LOCAL_ID); - const primaryProvider = providers.resource.get(providers.resource.getPrimary()); - const externalAuthentication = localProvider === undefined && providerList.length === 1; + const externalAuthentication = providerList.length === 0; const authenticationDisabled = serverConfig.enabledAuthProviders?.length === 0; const isAnonymousAccessDisabled = authSettingsService.settings.getValue('disableAnonymousAccess'); @@ -57,8 +59,6 @@ export const AuthenticationProviders: PlaceholderComponent { const links = authProviderService.getServiceDescriptionLinks(provider); - let disabled = provider.requiredFeatures.some(feat => !serverConfig.enabledFeatures?.includes(feat)); + const disabled = provider.requiredFeatures.some(feat => !serverConfig.enabledFeatures?.includes(feat)); const tooltip = disabled ? `Following services need to be enabled: "${provider.requiredFeatures.join(', ')}"` : ''; - if ( - !localProvider && - primaryProvider?.id === provider.id && - serverConfig.enabledAuthProviders?.length === 1 && - serverConfig.enabledAuthProviders.includes(provider.id) - ) { - disabled = true; - } - - if (provider.private || (configurationWizard && (disabled || provider.id !== AUTH_PROVIDER_LOCAL_ID))) { - return null; - } - return ( { - if (provider.id === primaryId && adminPageActive && accessRequest) { - return true; - } - if (provider.federated || provider.trusted || provider.private) { return false; } @@ -170,9 +165,6 @@ export function useAuthDialogState(accessRequest: boolean, providerId: string | get configure(): boolean { if (state.activeProvider) { - if (this.adminPageActive && authProvidersResource.resource.isPrimary(state.activeProvider.id)) { - return false; - } return !authProvidersResource.resource.isAuthEnabled(state.activeProvider.id); } return false;