diff --git a/webapp/packages/core-administration/src/AdministrationSettingsService.ts b/webapp/packages/core-administration/src/AdministrationSettingsService.ts
new file mode 100644
index 0000000000..ed0762ac91
--- /dev/null
+++ b/webapp/packages/core-administration/src/AdministrationSettingsService.ts
@@ -0,0 +1,31 @@
+/*
+ * CloudBeaver - Cloud Database Manager
+ * Copyright (C) 2020-2021 DBeaver Corp and others
+ *
+ * Licensed under the Apache License, Version 2.0.
+ * you may not use this file except in compliance with the License.
+ */
+
+import { injectable } from '@cloudbeaver/core-di';
+import { PluginManagerService } from '@cloudbeaver/core-plugin';
+
+const defaultSettings = {
+ baseFeatures: [] as string[],
+};
+
+export type AdministrationSettings = typeof defaultSettings;
+
+@injectable()
+export class AdministrationSettingsService {
+ readonly settings = this.pluginManagerService.getPluginSettings('core.administration', defaultSettings);
+
+ constructor(private pluginManagerService: PluginManagerService) { }
+
+ isBase(feature: string): boolean {
+ return this.getBase().includes(feature);
+ }
+
+ getBase(): string[] {
+ return this.settings.getValue('baseFeatures');
+ }
+}
diff --git a/webapp/packages/core-administration/src/index.ts b/webapp/packages/core-administration/src/index.ts
index 87d36baa22..e0d2988178 100644
--- a/webapp/packages/core-administration/src/index.ts
+++ b/webapp/packages/core-administration/src/index.ts
@@ -9,6 +9,7 @@ export * from './AdministrationScreen/ConfigurationWizard/ConfigurationWizardSer
export * from './AdministrationScreen/ConfigurationWizard/WizardTopAppBar/WizardTopAppBarService';
export * from './AdministrationToolsPanelStyles';
export * from './AdministrationLocaleService';
+export * from './AdministrationSettingsService';
export * from './EAdminPermission';
export * from './useAdministrationSettings';
diff --git a/webapp/packages/core-blocks/src/FormControls/Checkboxes/Switch.tsx b/webapp/packages/core-blocks/src/FormControls/Checkboxes/Switch.tsx
index 09b630f321..a635f19b70 100644
--- a/webapp/packages/core-blocks/src/FormControls/Checkboxes/Switch.tsx
+++ b/webapp/packages/core-blocks/src/FormControls/Checkboxes/Switch.tsx
@@ -95,6 +95,7 @@ interface SwitchType {
export const Switch: SwitchType = observer(function Switch({
name,
+ id,
value,
defaultValue,
description,
@@ -142,7 +143,7 @@ export const Switch: SwitchType = observer(function Switch({
as='input'
{...rest}
type="checkbox"
- id={value || name}
+ id={id || value || name}
role="switch"
aria-checked={checkboxState.checked}
checked={checkboxState.checked}
@@ -151,7 +152,7 @@ export const Switch: SwitchType = observer(function Switch({
/>
- {children}
+ {children}
{description}
diff --git a/webapp/packages/core-blocks/src/FormControls/Checkboxes/useCheckboxState.ts b/webapp/packages/core-blocks/src/FormControls/Checkboxes/useCheckboxState.ts
index b7602a4e0f..cb57eaf1ea 100644
--- a/webapp/packages/core-blocks/src/FormControls/Checkboxes/useCheckboxState.ts
+++ b/webapp/packages/core-blocks/src/FormControls/Checkboxes/useCheckboxState.ts
@@ -87,5 +87,5 @@ export function useCheckboxState(options: CheckboxStateOpti
refresh(count + 1);
},
- }), { checked });
+ }), { checked }, ['change']);
}
diff --git a/webapp/packages/core-bootstrap/src/manifest.ts b/webapp/packages/core-bootstrap/src/manifest.ts
index 2f79e647db..116aefca46 100644
--- a/webapp/packages/core-bootstrap/src/manifest.ts
+++ b/webapp/packages/core-bootstrap/src/manifest.ts
@@ -8,6 +8,7 @@
import {
AdministrationLocaleService,
+ AdministrationSettingsService,
AdministrationTopAppBarService,
AdministrationScreenService,
AdministrationItemService,
@@ -117,6 +118,7 @@ export const coreManifest: PluginManifest = {
RouterService, // important, should be first because the router starts in load phase first after all plugins register phase
NetworkStateService,
AdministrationLocaleService,
+ AdministrationSettingsService,
AdministrationTopAppBarService,
AdministrationScreenService,
AdministrationScreenServiceBootstrap,
diff --git a/webapp/packages/core-root/src/ServerConfigResource.ts b/webapp/packages/core-root/src/ServerConfigResource.ts
index 32d7175ccf..449febd495 100644
--- a/webapp/packages/core-root/src/ServerConfigResource.ts
+++ b/webapp/packages/core-root/src/ServerConfigResource.ts
@@ -56,14 +56,20 @@ export class ServerConfigResource extends CachedDataResource();
- constructor(protected fallback?: ISettingsSource) {}
+ constructor(protected fallback?: ISettingsSource) {
+ makeObservable(this, {
+ store: observable,
+ });
+ }
has(key: string): boolean {
return this.store.has(key) || !!this.fallback?.has(key);
diff --git a/webapp/packages/core-utils/src/parseJSONFlat.ts b/webapp/packages/core-utils/src/parseJSONFlat.ts
index 862a73f812..10b438c8e3 100644
--- a/webapp/packages/core-utils/src/parseJSONFlat.ts
+++ b/webapp/packages/core-utils/src/parseJSONFlat.ts
@@ -12,6 +12,12 @@ export function parseJSONFlat(
scope?: string
) {
if (typeof object === 'object') {
+ if (Array.isArray(object)) {
+ if (scope) {
+ setValue(scope, object);
+ }
+ return;
+ }
for (const [key, value] of Object.entries(object)) {
parseJSONFlat(value, setValue, `${scope ? `${scope}.` : ''}${key}`);
}
diff --git a/webapp/packages/plugin-administration/src/ConfigurationWizard/ServerConfiguration/Form/ServerConfigurationFeaturesForm.tsx b/webapp/packages/plugin-administration/src/ConfigurationWizard/ServerConfiguration/Form/ServerConfigurationFeaturesForm.tsx
new file mode 100644
index 0000000000..4d27fb229d
--- /dev/null
+++ b/webapp/packages/plugin-administration/src/ConfigurationWizard/ServerConfiguration/Form/ServerConfigurationFeaturesForm.tsx
@@ -0,0 +1,65 @@
+/*
+ * CloudBeaver - Cloud Database Manager
+ * Copyright (C) 2020-2021 DBeaver Corp and others
+ *
+ * Licensed under the Apache License, Version 2.0.
+ * you may not use this file except in compliance with the License.
+ */
+
+import { observer } from 'mobx-react-lite';
+import { useContext } from 'react';
+import styled from 'reshadow';
+
+import { AdministrationSettingsService } from '@cloudbeaver/core-administration';
+import { BASE_CONTAINERS_STYLES, FormContext, GroupTitle, Loader, PlaceholderComponent, Switch, useDataResource } from '@cloudbeaver/core-blocks';
+import { useService } from '@cloudbeaver/core-di';
+import { useTranslate } from '@cloudbeaver/core-localization';
+import { FeaturesResource } from '@cloudbeaver/core-root';
+import { CachedMapAllKey } from '@cloudbeaver/core-sdk';
+import { useStyles } from '@cloudbeaver/core-theming';
+import type { IConfigurationPlaceholderProps } from '@cloudbeaver/plugin-administration';
+
+export const ServerConfigurationFeaturesForm: PlaceholderComponent = observer(function ServerConfigurationFeaturesForm({
+ state: { serverConfig },
+ configurationWizard,
+}) {
+ const administrationSettingsService = useService(AdministrationSettingsService);
+ const features = useDataResource(ServerConfigurationFeaturesForm, FeaturesResource, CachedMapAllKey);
+ const translate = useTranslate();
+ const styles = useStyles(BASE_CONTAINERS_STYLES);
+ const formContext = useContext(FormContext);
+
+ if (formContext === null) {
+ throw new Error('Form state should be provided');
+ }
+
+ if (features.data.length === 0) {
+ return null;
+ }
+
+ return styled(styles)(
+ <>
+ {translate('administration_configuration_wizard_configuration_features_group')}
+
+ {() => styled(styles)(
+ <>
+ {features.data.map(feature => (
+
+ {feature.label}
+
+ ))}
+ >
+ )}
+
+ >
+ );
+});
diff --git a/webapp/packages/plugin-administration/src/ConfigurationWizard/ServerConfiguration/ServerConfigurationPage.tsx b/webapp/packages/plugin-administration/src/ConfigurationWizard/ServerConfiguration/ServerConfigurationPage.tsx
index 458313479f..40b70e5b22 100644
--- a/webapp/packages/plugin-administration/src/ConfigurationWizard/ServerConfiguration/ServerConfigurationPage.tsx
+++ b/webapp/packages/plugin-administration/src/ConfigurationWizard/ServerConfiguration/ServerConfigurationPage.tsx
@@ -18,6 +18,7 @@ import { ServerConfigResource } from '@cloudbeaver/core-root';
import { useStyles } from '@cloudbeaver/core-theming';
import { ServerConfigurationConfigurationForm } from './Form/ServerConfigurationConfigurationForm';
+import { ServerConfigurationFeaturesForm } from './Form/ServerConfigurationFeaturesForm';
import { ServerConfigurationInfoForm } from './Form/ServerConfigurationInfoForm';
import { ServerConfigurationNavigatorViewForm } from './Form/ServerConfigurationNavigatorViewForm';
import { ServerConfigurationSecurityForm } from './Form/ServerConfigurationSecurityForm';
@@ -123,6 +124,7 @@ export const ServerConfigurationPage: AdministrationItemContentComponent = obser
{translate('administration_configuration_wizard_configuration_plugins')}
+
diff --git a/webapp/packages/plugin-authentication/src/Administration/ServerConfiguration/AuthenticationProviders.tsx b/webapp/packages/plugin-authentication/src/Administration/ServerConfiguration/AuthenticationProviders.tsx
index b5e48c5eb4..8457e777e4 100644
--- a/webapp/packages/plugin-authentication/src/Administration/ServerConfiguration/AuthenticationProviders.tsx
+++ b/webapp/packages/plugin-authentication/src/Administration/ServerConfiguration/AuthenticationProviders.tsx
@@ -35,7 +35,6 @@ export const AuthenticationProviders: PlaceholderComponent provider.id !== AUTH_PROVIDER_LOCAL_ID);
const externalAuthentication = providers.data.length === 1 && localProvider === undefined;
const authenticationDisabled = serverConfig.enabledAuthProviders?.length === 0;
@@ -54,10 +53,10 @@ export const AuthenticationProviders: PlaceholderComponent
- {localProvider && (
- <>
-
- {translate('administration_configuration_wizard_configuration_authentication_group')}
+
+ {translate('administration_configuration_wizard_configuration_authentication_group')}
+ {localProvider && (
+ <>
{translate('administration_configuration_wizard_configuration_anonymous_access')}
-
- {() => localProvider && styled(styles)(
-
- {localProvider.label}
-
- )}
-
-
- {configurationWizard && (
-
- )}
- >
- )}
- {services.length > 0 ? (
-
- {translate('administration_configuration_wizard_configuration_services')}
-
- {() => styled(styles)(
- <>
- {services.map(provider => {
- const links = authProviderService.getServiceDescriptionLinks(provider);
+ >
+ )}
+
+ {() => styled(styles)(
+ <>
+ {providers.resource.values.map(provider => {
+ const links = authProviderService.getServiceDescriptionLinks(provider);
- return (
-
- {provider.description}
- {links.map(link => {
- const Description = link.description();
- return ;
- })}
- >
- )}
- disabled={providers.resource.isBase(provider.id)}
- mod={['primary']}
- small
- autoHide
- >
- {provider.label}
-
- );
- })}
- >
- )}
-
-
+ return (
+
+ {provider.description}
+ {links.map(link => {
+ const Description = link.description();
+ return ;
+ })}
+ >
+ )}
+ disabled={providers.resource.isBase(provider.id)}
+ mod={['primary']}
+ small
+ autoHide
+ >
+ {provider.label}
+
+ );
+ })}
+ >
+ )}
+
+
+ {configurationWizard && localProvider ? (
+
) : }
- {!(configurationWizard && localProvider) && }
);
});
diff --git a/webapp/packages/plugin-authentication/src/Administration/ServerConfiguration/ServerConfigurationAuthenticationBootstrap.ts b/webapp/packages/plugin-authentication/src/Administration/ServerConfiguration/ServerConfigurationAuthenticationBootstrap.ts
index 9fd6cf71f5..2a06e2e494 100644
--- a/webapp/packages/plugin-authentication/src/Administration/ServerConfiguration/ServerConfigurationAuthenticationBootstrap.ts
+++ b/webapp/packages/plugin-authentication/src/Administration/ServerConfiguration/ServerConfigurationAuthenticationBootstrap.ts
@@ -56,6 +56,7 @@ export class ServerConfigurationAuthenticationBootstrap extends Bootstrap {
data.state.serverConfig.anonymousAccessEnabled = config.anonymousAccessEnabled;
data.state.serverConfig.enabledAuthProviders = [...config.enabledAuthProviders];
+ data.state.serverConfig.enabledFeatures = [...config.enabledFeatures];
} catch (exception) {
ExecutorInterrupter.interrupt(contexts);
this.notificationService.logException(exception, 'Can\'t load server configuration');
diff --git a/webapp/packages/plugin-authentication/src/Dialog/AuthDialog.tsx b/webapp/packages/plugin-authentication/src/Dialog/AuthDialog.tsx
index ad38952228..23fb53f7a0 100644
--- a/webapp/packages/plugin-authentication/src/Dialog/AuthDialog.tsx
+++ b/webapp/packages/plugin-authentication/src/Dialog/AuthDialog.tsx
@@ -85,8 +85,8 @@ export const AuthDialog: DialogComponent = observer(function
const controller = useController(AuthDialogController, link, providerId, rejectDialog);
const translate = useTranslate();
- if (!providerId) {
- controller.setAdminMode(administrationScreenService.activeScreen !== null);
+ if (administrationScreenService.activeScreen !== null) {
+ controller.setAdminMode(administrationScreenService.activeScreen !== null, providerId);
}
const additional = userInfo.data !== null
diff --git a/webapp/packages/plugin-authentication/src/Dialog/AuthDialogController.ts b/webapp/packages/plugin-authentication/src/Dialog/AuthDialogController.ts
index 860e02edb6..fe0185295a 100644
--- a/webapp/packages/plugin-authentication/src/Dialog/AuthDialogController.ts
+++ b/webapp/packages/plugin-authentication/src/Dialog/AuthDialogController.ts
@@ -92,11 +92,13 @@ export class AuthDialogController implements IInitializableController, IDestruct
this.loadProviders();
}
- setAdminMode(mode: boolean): void {
+ setAdminMode(mode: boolean, providerId: string | null): void {
if (this.admin !== mode) {
this.admin = mode;
- this.selectFirstAvailable();
+ if (!providerId) {
+ this.selectFirstAvailable();
+ }
}
}
diff --git a/webapp/packages/plugin-authentication/src/locales/en.ts b/webapp/packages/plugin-authentication/src/locales/en.ts
index 6d9220f8a8..22e24b877a 100644
--- a/webapp/packages/plugin-authentication/src/locales/en.ts
+++ b/webapp/packages/plugin-authentication/src/locales/en.ts
@@ -53,6 +53,7 @@ export default [
['administration_configuration_wizard_configuration_anonymous_access', 'Allow anonymous access'],
['administration_configuration_wizard_configuration_anonymous_access_description', 'Allows to work with CloudBeaver without user authentication'],
['administration_configuration_wizard_configuration_authentication_group', 'Authentication settings'],
+ ['administration_configuration_wizard_configuration_features_group', 'Features'],
['administration_configuration_wizard_configuration_services', 'Services'],
['administration_configuration_wizard_configuration_authentication', 'Enable users authentication'],
['administration_configuration_wizard_configuration_authentication_description', 'Allows users to authenticate. Otherwise only anonymous access is enabled'],
diff --git a/webapp/packages/plugin-authentication/src/locales/it.ts b/webapp/packages/plugin-authentication/src/locales/it.ts
index 34818ef585..49e1fc966c 100644
--- a/webapp/packages/plugin-authentication/src/locales/it.ts
+++ b/webapp/packages/plugin-authentication/src/locales/it.ts
@@ -51,6 +51,7 @@ export default [
['administration_configuration_wizard_configuration_anonymous_access', 'Permetti l\'accesso anonimo'],
['administration_configuration_wizard_configuration_anonymous_access_description', 'Permetti di lavorare con CloudBeaver senza autenticazione'],
['administration_configuration_wizard_configuration_authentication_group', 'Impostazioni di autenticazione'],
+ ['administration_configuration_wizard_configuration_features_group', 'Функции'],
['administration_configuration_wizard_configuration_services', 'Servizi'],
['administration_configuration_wizard_configuration_authentication', 'Abilita l\'autenticazione utente'],
['administration_configuration_wizard_configuration_authentication_description', 'Permetti agli utenti di autenticarsi. In alternativa solo l\'accesso anonimo sarà attivo'],