Compare commits

...
Author SHA1 Message Date
Ainur 549e55ef3e sqlite hotfixes (#2459)
* CB-4816 refresh disabled drivers after loading runtime config

* CB-4816 refresh drivers config only when starting server

* CB-4824 return network handlers for some embedded drivers
2024-03-07 09:25:43 +00:00
LonwoLonwo 99b0c11f2b Fix typo in the echo command 2024-03-07 10:16:31 +01:00
466af8f750 CB-4743 adds html sanitizer (#2420)
* CB-4743 adds html sanitizer

* CB-4743 adds license to sanitizeHtml

* CB-4743 do not use sanitize to purify the json line data

* CB-4743 fix: toSafeHtmlString test correct cases

---------

Co-authored-by: s.teleshev <s.teleshev@mu.se>
Co-authored-by: mr-anton-t <42037741+mr-anton-t@users.noreply.github.com>
2024-03-06 11:13:34 +01:00
Alexey 4523144d9f CB-4801 fix: remove baseFeatures setting (#2442) 2024-03-05 11:32:02 +03:00
alex 221bef13a6 CB-4779 grid perfomance (#2439) 2024-03-01 12:32:30 +01:00
DenisSinelnikovandDenisSinelnikov 3b2fd282c9 CB-4792. Change attribute names for rp identity provider (#2438)
Co-authored-by: DenisSinelnikov <denis.sinelnikov@dbaever.com>
2024-03-01 10:56:17 +00:00
Alexander Skoblikov 6828098650 CB-4777 do not call rm api if not authorized in sm (#2432) 2024-02-29 17:08:32 +00:00
Alexander Skoblikov fffb3a0842 CB-4773 show license validation error (#2427) 2024-02-28 17:42:30 +00:00
Aleksei Potsetsuev f345e5e25b chore: update browserlist 2024-02-28 14:58:07 +08:00
18 changed files with 105 additions and 143 deletions
+1 -1
View File
@@ -18,4 +18,4 @@ echo "Copy static content"
cp -rp ../webapp/packages/product-default/lib/* cloudbeaver/web
echo "Cloudbeaver is ready. Run run-server.bat in cloudbeaver folder to start the server."
echo "Cloudbeaver is ready. Run run-server.sh in cloudbeaver folder to start the server."
@@ -114,7 +114,9 @@ public abstract class BaseWebSession extends AbstractSessionPersistent {
public synchronized void refreshUserData() {
try {
userContext.refreshPermissions();
userContext.refreshAccessibleProjects();
if (userContext.isAuthorizedInSecurityManager()) {
userContext.refreshAccessibleProjects();
}
} catch (DBException e) {
addSessionError(e);
log.error("Error refreshing accessible projects", e);
@@ -214,12 +214,12 @@ public class WebDatabaseDriverInfo {
@Property
public String[] getApplicableNetworkHandlers() {
if (driver.isEmbedded()) {
return new String[0];
if (!driver.isEmbedded() || CommonUtils.toBoolean(driver.getDriverParameter(DBConstants.DRIVER_PARAM_ENABLE_NETWORK_PARAMETERS))) {
return NetworkHandlerRegistry.getInstance().getDescriptors(driver).stream()
.filter(h -> !h.isDesktopHandler())
.map(NetworkHandlerDescriptor::getId).toArray(String[]::new);
}
return NetworkHandlerRegistry.getInstance().getDescriptors(driver).stream()
.filter(h -> !h.isDesktopHandler())
.map(NetworkHandlerDescriptor::getId).toArray(String[]::new);
return new String[0];
}
@Property
@@ -48,6 +48,7 @@ import org.jkiss.dbeaver.model.app.DBPApplication;
import org.jkiss.dbeaver.model.app.DBPPlatform;
import org.jkiss.dbeaver.model.auth.AuthInfo;
import org.jkiss.dbeaver.model.auth.SMCredentialsProvider;
import org.jkiss.dbeaver.model.connection.DBPDriver;
import org.jkiss.dbeaver.model.data.json.JSONUtils;
import org.jkiss.dbeaver.model.navigator.DBNBrowseSettings;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
@@ -260,6 +261,7 @@ public abstract class CBApplication extends BaseWebApplication implements WebAut
log.error(e);
return;
}
refreshDisabledDriversConfig();
configurationMode = CommonUtils.isEmpty(serverName);
@@ -541,7 +543,6 @@ public abstract class CBApplication extends BaseWebApplication implements WebAut
log.debug("Runtime configuration [" + runtimeConfigFile.getAbsolutePath() + "]");
parseConfiguration(runtimeConfigFile);
}
return path;
}
@@ -1216,6 +1217,11 @@ public abstract class CBApplication extends BaseWebApplication implements WebAut
return false;
}
@Nullable
public String getLicenseStatus() {
return null;
}
/**
*
*/
@@ -1333,4 +1339,16 @@ public abstract class CBApplication extends BaseWebApplication implements WebAut
}
eventController.addEvent(new WSServerConfigurationChangedEvent(sessionId, null));
}
private void refreshDisabledDriversConfig() {
CBAppConfig config = getAppConfiguration();
Set<String> disabledDrivers = new LinkedHashSet<>(Arrays.asList(config.getDisabledDrivers()));
for (DBPDriver driver : CBPlatform.getInstance().getApplicableDrivers()) {
if (!driver.isEmbedded() || config.isDriverForceEnabled(driver.getFullId())) {
continue;
}
disabledDrivers.add(driver.getFullId());
}
config.setDisabledDrivers(disabledDrivers.toArray(new String[0]));
}
}
@@ -119,8 +119,6 @@ public class CBPlatform extends BasePlatformImpl {
refreshApplicableDrivers();
refreshDisabledDriversConfig();
new WebSessionMonitorJob(this)
.scheduleMonitor();
@@ -293,18 +291,6 @@ public class CBPlatform extends BasePlatformImpl {
log.info("Available drivers: " + applicableDrivers.stream().map(DBPDriver::getFullName).collect(Collectors.joining(",")));
}
private void refreshDisabledDriversConfig() {
CBAppConfig config = application.getAppConfiguration();
Set<String> disabledDrivers = new LinkedHashSet<>(Arrays.asList(config.getDisabledDrivers()));
for (DBPDriver driver : applicableDrivers) {
if (!driver.isEmbedded() || config.isDriverForceEnabled(driver.getFullId())) {
continue;
}
disabledDrivers.add(driver.getFullId());
}
config.setDisabledDrivers(disabledDrivers.toArray(new String[0]));
}
@NotNull
@Override
public DBFileController createFileController() {
@@ -265,8 +265,13 @@ public abstract class WebServiceBindingBase<API_TYPE extends DBWService> impleme
// Check license
if (application.isLicenseRequired() && !application.isLicenseValid()) {
if (!ArrayUtils.contains(reqPermissions, DBWConstants.PERMISSION_ADMIN)) {
String errorMessage = "Invalid server license";
String licenseStatus = application.getLicenseStatus();
if (licenseStatus != null) {
errorMessage = errorMessage + ": " + licenseStatus;
}
// Only admin permissions are allowed
throw new DBWebExceptionLicenseRequired("Invalid server license");
throw new DBWebExceptionLicenseRequired(errorMessage);
}
}
// Check permissions
@@ -29,8 +29,8 @@
<configuration>
<propertyGroup label="Configuration">
<property id="logout-url" label="Logout url" type="string" description="Logout url"/>
<property id="user-header" label="User header name" type="string" description="User header name"/>
<property id="team-header" label="Team name" type="string" description="Team header name"/>
<property id="user-header" label="Username header" type="string" description="Username header"/>
<property id="team-header" label="Team header" type="string" description="Team header"/>
<property id="team-delimiter" label="Team delimiter symbol" type="string" description="Team delimiter symbol, default: |"/>
<property id="first-name-header" label="First name header" type="string" description="First name header name"/>
<property id="last-name-header" label="Last name header" type="string" description="Last name header name"/>
@@ -1,67 +0,0 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 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 '@testing-library/jest-dom';
import { coreBrowserManifest } from '@cloudbeaver/core-browser';
import { coreClientActivityManifest } from '@cloudbeaver/core-client-activity';
import { coreEventsManifest } from '@cloudbeaver/core-events';
import { coreLocalizationManifest } from '@cloudbeaver/core-localization';
import { corePluginManifest } from '@cloudbeaver/core-plugin';
import { coreProductManifest } from '@cloudbeaver/core-product';
import { coreRootManifest, ServerConfigResource } from '@cloudbeaver/core-root';
import { createGQLEndpoint } from '@cloudbeaver/core-root/dist/__custom_mocks__/createGQLEndpoint';
import { mockAppInit } from '@cloudbeaver/core-root/dist/__custom_mocks__/mockAppInit';
import { mockGraphQL } from '@cloudbeaver/core-root/dist/__custom_mocks__/mockGraphQL';
import { mockServerConfig } from '@cloudbeaver/core-root/dist/__custom_mocks__/resolvers/mockServerConfig';
import { coreSDKManifest } from '@cloudbeaver/core-sdk';
import { coreSettingsManifest } from '@cloudbeaver/core-settings';
import { createApp } from '@cloudbeaver/tests-runner';
import { AdministrationSettings, AdministrationSettingsService } from './AdministrationSettingsService';
import { coreAdministrationManifest } from './manifest';
const endpoint = createGQLEndpoint();
const app = createApp(
coreAdministrationManifest,
coreEventsManifest,
corePluginManifest,
coreProductManifest,
coreRootManifest,
coreSDKManifest,
coreSettingsManifest,
coreBrowserManifest,
// coreRoutingManifest,
// coreThemingManifest,
coreLocalizationManifest,
coreClientActivityManifest,
);
const server = mockGraphQL(...mockAppInit(endpoint));
beforeAll(() => app.init());
const testValue = ['none'];
const equalConfig = {
core: {
administration: {
baseFeatures: testValue,
} as AdministrationSettings,
},
};
test('Read settings', async () => {
const settings = app.injector.getServiceByClass(AdministrationSettingsService);
const config = app.injector.getServiceByClass(ServerConfigResource);
server.use(endpoint.query('serverConfig', mockServerConfig(equalConfig)));
await config.refresh();
expect(settings.settings.getValue('baseFeatures')).toEqual(testValue);
});
@@ -1,33 +0,0 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 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, PluginSettings } from '@cloudbeaver/core-plugin';
import { schema } from '@cloudbeaver/core-utils';
const settingsSchema = schema.object({
baseFeatures: schema.array(schema.string()).default([]),
});
export type AdministrationSettings = schema.infer<typeof settingsSchema>;
@injectable()
export class AdministrationSettingsService {
readonly settings: PluginSettings<typeof settingsSchema>;
constructor(private readonly pluginManagerService: PluginManagerService) {
this.settings = this.pluginManagerService.createSettings('administration', 'core', settingsSchema);
}
isBase(feature: string): boolean {
return this.getBase().includes(feature);
}
getBase(): string[] {
return this.settings.getValue('baseFeatures');
}
}
@@ -9,5 +9,4 @@ export * from './AdministrationScreen/AdministrationScreenService';
export * from './AdministrationScreen/ConfigurationWizard/ConfigurationWizardService';
export * from './DataContext/DATA_CONTEXT_ADMINISTRATION_ITEM_ROUTE';
export * from './AdministrationLocaleService';
export * from './AdministrationSettingsService';
export * from './PermissionsResource';
@@ -11,7 +11,6 @@ import { AdministrationItemService } from './AdministrationItem/AdministrationIt
import { AdministrationLocaleService } from './AdministrationLocaleService';
import { AdministrationScreenService } from './AdministrationScreen/AdministrationScreenService';
import { ConfigurationWizardService } from './AdministrationScreen/ConfigurationWizard/ConfigurationWizardService';
import { AdministrationSettingsService } from './AdministrationSettingsService';
import { PermissionsResource } from './PermissionsResource';
export const coreAdministrationManifest: PluginManifest = {
@@ -19,12 +18,5 @@ export const coreAdministrationManifest: PluginManifest = {
name: 'Core Administration',
},
providers: [
AdministrationItemService,
PermissionsResource,
AdministrationScreenService,
ConfigurationWizardService,
AdministrationLocaleService,
AdministrationSettingsService,
],
providers: [AdministrationItemService, PermissionsResource, AdministrationScreenService, ConfigurationWizardService, AdministrationLocaleService],
};
@@ -5,6 +5,8 @@
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { makeObservable, observable } from 'mobx';
import { injectable } from '@cloudbeaver/core-di';
import { CachedDataResource } from '@cloudbeaver/core-resource';
import { GraphQLService, WebFeatureSet } from '@cloudbeaver/core-sdk';
@@ -16,10 +18,24 @@ export type ApplicationFeature = WebFeatureSet;
@injectable()
export class FeaturesResource extends CachedDataResource<ApplicationFeature[]> {
private baseFeatures: string[];
constructor(private readonly graphQLService: GraphQLService, permissionsResource: SessionPermissionsResource) {
super(() => []);
this.baseFeatures = [];
permissionsResource.require(this, EAdminPermission.admin).outdateResource(this);
makeObservable<this, 'baseFeatures'>(this, {
baseFeatures: observable,
});
}
isBase(id: string) {
return this.baseFeatures.includes(id);
}
setBaseFeatures(features: string[]) {
this.baseFeatures = features;
}
protected async loader(): Promise<ApplicationFeature[]> {
+1
View File
@@ -77,3 +77,4 @@ export * from './removeLineBreak';
export * from './replaceSubstring';
export * from './formatNumber';
export * from './withTimestamp';
export * from './toSafeHtmlString';
@@ -0,0 +1,28 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 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 { toSafeHtmlString } from './toSafeHtmlString';
describe('toSafeHtmlString', () => {
it('should make html string safe', () => {
const input = '<script>alert("some unsafe action")</script>';
const output = toSafeHtmlString(input);
expect(output).toBe('&lt;script&gt;alert("some unsafe action")&lt;/script&gt;');
});
it('should return empty string', () => {
const input = '';
const output = toSafeHtmlString(input);
expect(output).toBe('');
});
it('should return the same string', () => {
const input = 'some safe string';
const output = toSafeHtmlString(input);
expect(output).toBe(input);
});
});
@@ -0,0 +1,14 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
export function toSafeHtmlString(dirty: string): string {
const el = document.createElement('div');
el.innerText = el.textContent = dirty;
dirty = el.innerHTML;
return dirty;
}
@@ -8,9 +8,7 @@
import { observer } from 'mobx-react-lite';
import { useContext } from 'react';
import { AdministrationSettingsService } from '@cloudbeaver/core-administration';
import { FormContext, GroupTitle, PlaceholderComponent, Switch, useResource, useTranslate } from '@cloudbeaver/core-blocks';
import { useService } from '@cloudbeaver/core-di';
import { FeaturesResource } from '@cloudbeaver/core-root';
import type { IConfigurationPlaceholderProps } from '../ServerConfigurationService';
@@ -23,7 +21,6 @@ export const ServerConfigurationFeaturesForm: PlaceholderComponent<IConfiguratio
throw new Error('Form state should be provided');
}
const administrationSettingsService = useService(AdministrationSettingsService);
const features = useResource(ServerConfigurationFeaturesForm, FeaturesResource, configurationWizard ? null : undefined);
const translate = useTranslate();
@@ -41,7 +38,7 @@ export const ServerConfigurationFeaturesForm: PlaceholderComponent<IConfiguratio
name="enabledFeatures"
state={serverConfig}
description={feature.description}
disabled={administrationSettingsService.isBase(feature.id)}
disabled={features.resource.isBase(feature.id)}
mod={['primary']}
small
>
@@ -5,7 +5,7 @@
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { action, makeObservable, observable } from 'mobx';
import { action, computed, makeObservable, observable } from 'mobx';
import { DataTypeLogicalOperation, ResultDataFormat, SqlResultColumn } from '@cloudbeaver/core-sdk';
@@ -55,6 +55,10 @@ export class ResultSetViewAction extends DatabaseDataAction<any, IDatabaseResult
makeObservable<this, 'columnsOrder'>(this, {
columnsOrder: observable,
setColumnOrder: action,
rows: computed,
rowKeys: computed,
columns: computed,
columnKeys: computed,
});
}
+3 -3
View File
@@ -6429,9 +6429,9 @@ caniuse-api@^3.0.0:
lodash.uniq "^4.5.0"
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001538, caniuse-lite@^1.0.30001565:
version "1.0.30001566"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001566.tgz#61a8e17caf3752e3e426d4239c549ebbb37fef0d"
integrity sha512-ggIhCsTxmITBAMmK8yZjEhCO5/47jKXPu6Dha/wuCS4JePVL+3uiDEBuhu2aIoT+bqTOR8L76Ip1ARL9xYsEJA==
version "1.0.30001591"
resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001591.tgz"
integrity sha512-PCzRMei/vXjJyL5mJtzNiUCKP59dm8Apqc3PH8gJkMnMXZGox93RbE76jHsmLwmIo6/3nsYIpJtx0O7u5PqFuQ==
capital-case@^1.0.4:
version "1.0.4"