Compare commits

..
Author SHA1 Message Date
Ruslan 499cda86b3 dbeaver/pro#9724 fix graphql schema for doc 2026-07-31 12:47:47 +02:00
Ruslan ca03a8eff3 dbeaver/pro#9724 fix graphql schema for doc 2026-07-31 11:24:19 +02:00
Serge Rider 3a60e04a84 dbeaver/pro#9893 Project navigator model is required 2026-07-30 20:12:48 +03:00
dbeaver-devops 8b33e3a08f dbeaver/pro#10040 26.1.5 version bump 2026-07-28 19:27:19 +02:00
b021ceec4b dbeaver/pro#9665 adds global network profiles (#4465)
* dbeaver/pro#9665 adds global network profiles

* dbeaver/pro#9665 marks global profiles in selector

* dbeaver/pro#9665 cleanup

* dbeaver/pro#9665 fixes document-global G color so it adapts to the theme

* dbeaver/pro#9665 splits logic to tab service & bootstrap

* dbeaver/pro#9665 hides connections tab if no sub-tabs was registered

* Merge branch 'devel' into 9665-cb-global-network-profiles-in-cloudbeaver

---------

Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
Co-authored-by: kseniaguzeeva <112612526+kseniaguzeeva@users.noreply.github.com>
2026-07-28 19:52:23 +03:00
Ruslan Musaevandsergeyteleshev d318579745 dbeaver/pro#9755 navigator settings sync (#4491)
* dbeaver/pro#9755 navigator settings sync

* dbeaver/pro#9755 navigator settings sync

* dbeaver/pro#9755 navigator settings sync

* dbeaver/pro#9755 adds synchronization for changing connection settings

---------

Co-authored-by: sergeyteleshev <iamsergeyteleshev@gmail.com>
2026-07-28 19:25:16 +03:00
Ainur 8d17ed0ecd dbeaver/pro#9964 fix generating urls for saml with custom root uri (#4486) 2026-07-28 19:02:00 +03:00
DaniilandDaria Marutkina 3199a99b29 dbeaver/pro#9822 API for full DDL for PostgreSQL (#4477)
* dbeaver/pro#9822 API for full DDL for PostgreSQL

* dbeaver/pro#9822 linter fix

* dbeaver/pro#9822 linter fix

* dbeaver/pro#9822 add cancellable async tasks for DDL generation

* dbeaver/pro#9822 linter fix

* dbeaver/pro#9822 linter fix

* dbeaver/pro#9822 comment fix

* dbeaver/pro#9822 comment fix

* dbeaver/pro#9822 remove PostgreSQL-only restriction for full DDL feature

* dbeaver/pro#9822 review fix: add deprecated annotations to ghl schemas

* dbeaver/pro#9822 review fix: revert changes for metadataGetNodeDDL

---------

Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
2026-07-28 16:42:41 +02:00
Sychev AndreyandDaria Marutkina 39008f7170 dbeaver/pro#9865 feat: add title prop to SelectField component (#4501)
Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
2026-07-28 16:42:29 +02:00
8bf33d539f dbeaver/pro#9905 adds fallback to get connection from nodeId in case nodePath is not set (#4499)
Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
Co-authored-by: mr-anton-t <42037741+mr-anton-t@users.noreply.github.com>
2026-07-28 16:37:56 +02:00
Elizabeth 42f6720acd dbeaver/pro#10033 Fix file connections creation (#4503) 2026-07-28 16:08:27 +02:00
sergeyteleshevandEvgenia 0a3cb12c0b dbeaver/pro#9798 adds sorting for columns in user tables (#4484)
* dbeaver/pro#9798 adds sorting for columns in user tables

* dbeaver/pro#9798 adds comparator helpers

* dbeaver/pro#9798 moves user helpers to compareUser file

* dbeaver/pro#9798 fixes naming and any

* dbeaver/pro# adds grantedUsersIdsMap to make less computations

---------

Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
2026-07-28 13:22:43 +02:00
202823e731 dbeaver/pro#9719 move ai to community (#4471)
* dbeaver/pro#9719 move ai to community

* dbeaver/pro#9719 return prompt generator id input and fix system message type

* dbeaver/pro#9719 return prompt generator id for conversation

* dbeaver/pro#9719 remove rag

* dbeaver/pro#9719 move ai to ce

* dbeaver/pro#9719 fix description for ai chat

* dbeaver/pro#9719 clear feature

* dbeaver/pro#9719 fix conflicts

* dbeaver/pro#9719 remove unused import

---------

Co-authored-by: alex <48489896+devnaumov@users.noreply.github.com>
Co-authored-by: naumov <iamemptyhuh@gmail.com>
Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
Co-authored-by: mr-anton-t <42037741+mr-anton-t@users.noreply.github.com>
Co-authored-by: sergeyteleshev <iamsergeyteleshev@gmail.com>
2026-07-28 13:15:33 +02:00
Ruslan MusaevandAinur ed088fe923 dbeaver/pro#9934 api for user list downloaded (#4498)
Co-authored-by: Ainur <59531286+yagudin10@users.noreply.github.com>
2026-07-28 12:01:49 +02:00
df21c3396a dbeaver/pro#9617 api for data-import settings (#4423)
* dbeaver/pro#9617 api for data import settings

* dbeaver/pro#9617 api for data import settings

* dbeaver/pro#9617 api for data import settings

* dbeaver/pro#9617 api for data import settings

* dbeaver/pro#9617 api for data import settings

* dbeaver/pro#9617 api for data import settings

* dbeaver/pro#9617 feat: support new import API on FE

* dbeaver/pro#9617 api for data import settings

---------

Co-authored-by: Sychev Andrey <nukemoore@gmail.com>
Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
Co-authored-by: Ainur <59531286+yagudin10@users.noreply.github.com>
2026-07-28 12:01:24 +02:00
90ccdc6432 dbeaver/pro#9621 feat: add state to diagram tab (#4495)
Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
Co-authored-by: sergeyteleshev <iamsergeyteleshev@gmail.com>
2026-07-28 11:39:37 +02:00
sergeyteleshevandmr-anton-t dba371a320 dbeaver/pro#10011 fixes js-yaml, brace-expansion, postcss CVEs (#4500)
Co-authored-by: mr-anton-t <42037741+mr-anton-t@users.noreply.github.com>
2026-07-28 11:19:12 +02:00
d96cd8f0d2 dbeaver/pro#9912 add ability to save null for default auto commit mode (#4481)
* dbeaver/pro#9912 add ability to save null for default auto commit mode

* dbeaver/pro#9912 return null value by default

* dbeaver/pro#9912 return valid values

---------

Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
Co-authored-by: kseniaguzeeva <112612526+kseniaguzeeva@users.noreply.github.com>
2026-07-28 11:09:37 +02:00
ElizabethandDiana bd6e7d48f3 dbeaver/pro#9491 Handle exception from setUrl (#4479)
Co-authored-by: Diana <31996417+uslss@users.noreply.github.com>
2026-07-28 07:51:45 +02:00
8b41e4530f dbeaver/pro#4490 bump postgres version (#4493)
Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
2026-07-27 18:51:50 +02:00
alexandDaria Marutkina a555f1e759 dbeaver/pro#4425 add controlled mode (#4468)
* dbeaver/pro#4425 add controlled mode

* dbeaver/pro#4425 update yarn lock

* dbeaver/pro#4425 use controlled state for users

* dbeaver/pro#4425 update copyright

* dbeaver/pro#4425 update notice

* dbeaver/pro#4425 update tokens

---------

Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
2026-07-27 17:09:40 +02:00
alexandDaria Marutkina fdaa40e431 dbeaver/pro#8663 add auto resize textarea (#4497)
Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
2026-07-27 17:02:18 +02:00
sergeyteleshevandDaria Marutkina 4c2f9d92e5 dbeaver/pro#9170 adds download button for the script (#4474)
* dbeaver/pro#9170 adds download button for the script

* dbeaver/pro#9170 gets sql filename from node or model

* dbeaver/pro#9170 adds action buttons

* dbeaver/pro#9170 adds borders to the buttons

* dbeaver/pro#9170 fixes build

---------

Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
2026-07-27 14:35:17 +02:00
sergeyteleshevandmr-anton-t a92011eee6 dbeaver/pro#9967 fixes immutable & fast-uri CVEs (#4492)
Co-authored-by: mr-anton-t <42037741+mr-anton-t@users.noreply.github.com>
2026-07-27 11:52:01 +02:00
ElizabethandDiana 61a7757a0e dbeaver/pro#9445 Update Clickhouse driver version (#4480)
Co-authored-by: Diana <31996417+uslss@users.noreply.github.com>
2026-07-24 13:11:02 +02:00
Nikita Akilov a53ca3592f dbeaver/dbeaver-devops#2751 stop including curl with cloud products (#4494) 2026-07-24 11:22:42 +02:00
Sychev AndreyandEvgenia 9e682617e6 dbeaver/pro#9638 [CB] refresh is needed to see replaced connectionfolder in another instance (#4464)
* dbeaver/pro#9638 fix: update project filtering logic to use project IDs for active projects

Changed all four spots from reference equality to id comparison, matching the rest of the codebase, see https://github.com/dbeaver/cloudbeaver/issues/4430

* dbeaver/pro#9638 refactor(connectionUpdateHandler): move node to a new parent on change

* dbeaver/pro#9638 revert commit eb2ba7871e

* dbeaver/pro#9638 fix: update node parents on move in other session

Server events don't carry the actual data, so besides outdating (which lets the handlers invalidate the previous state, e.g. the old location in the navigation tree) we explicitly load the connection to guarantee that the handlers receive the actual state

* dbeaver/pro#9638 fix: sync connection folder move from another session

* dbeaver/pro#9638 fix: revert back connectionUpdateHandler

* dbeaver/pro#9638 fix: remove try catch

---------

Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
2026-07-23 17:33:26 +02:00
sergeyteleshevandDaria Marutkina 16dda810d7 dbeaver/pro#9171 adds ability to open sql editor with context from Generate SQL dialog (#4488)
Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
2026-07-23 16:30:47 +02:00
Sychev AndreyandEvgenia 6042f16342 dbeaver/pro#9426 feat: add loading state to save button (#4487)
Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
2026-07-23 16:30:31 +02:00
Viktor Kirst 0afdd06c80 dbeaver/pro#9768 Fix long-polling session cookie after session ID rotation (#4467) 2026-07-23 16:04:31 +03:00
Sychev Andreyandmr-anton-t 3158aebca4 dbeaver/pro#9877 UI fixes (#4473)
* dbeaver/pro#9877 fix: select render field popover

* dbeaver/pro#9877 fix: revert back ripple hover effect

* dbeaver/pro#9877 fix: make all outlines 1px by default

* dbeaver/pro#9877 fix: switch outline

* dbeaver/pro#9877 fix: topbar buttons outline

* dbeaver/pro#9877 fix: tablist styles

* dbeaver/pro#9877 fix: rule priorities

* dbeaver/pro#9877 fix: eslint

* dbeaver/pro#9877 fix: eslint

---------

Co-authored-by: mr-anton-t <42037741+mr-anton-t@users.noreply.github.com>
2026-07-23 13:07:10 +02:00
mayerro 99866fdc12 Revert "dbeaver/dbeaver-devops#2751 remove curl from base java to fix cve (#4483)"
This reverts commit f54f377344.
2026-07-23 11:17:11 +02:00
sergeyteleshev a58eb59a32 dbeaver/pro#9938 fixes 8 CVEs (#4478) 2026-07-23 11:08:30 +02:00
DaniilandEvgenia eda1f8720f dbeaver/pro#9721 [CB] Add a flag into reverse proxy allowing new user… (#4460)
* dbeaver/pro#9721 [CB] Add a flag into reverse proxy allowing new users creation

* dbeaver/pro#9721 [CB] code style fix

* dbeaver/pro#9721 [CB] code style fix

* dbeaver/pro#9721 move the method isAutoUserProvisioningEnabled to SMAuthProviderExternal

* dbeaver/pro#9721 linter fix

* dbeaver/pro#9721 code review fix

* dbeaver/pro#9721 code review fix

* dbeaver/pro#9721 code review fix

* dbeaver/pro#9721 Fix login for existing users without reverse proxy credentials when auto user provisioning is disabled

---------

Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
2026-07-23 10:09:30 +02:00
Nikolay f54f377344 dbeaver/dbeaver-devops#2751 remove curl from base java to fix cve (#4483)
* dbeaver/dbeaver-devops#2751 removed curl from base java to fix cve

* dbeaver/dbeaver-devops#2751 removed an extra comment
2026-07-22 16:31:49 +03:00
alex 81a9be17b8 dbeaver/pro#9659 add dnd scroll container (#4476) 2026-07-22 14:24:53 +02:00
alex af42d7f50a dbeaver/pro#9910 check key also (#4469) 2026-07-20 15:55:01 +02:00
Daria Marutkina d083ac1330 dbeaver/pro#9879 Update README file (#4472)
Added changelog for version 26.1.3, including updates on data editor, general improvements, data transfer enhancements, accessibility features, security fixes, and database driver updates.
2026-07-20 13:21:53 +02:00
Serge Rider cdb450dfde dbeaver/pro#7329 Navigator view actions model refactoring (get rid of UI).
Git service and navigator web service code style.
2026-07-15 12:01:30 +02:00
dbeaver-devops d0d9ee19ab dbeaver/pro#9879 26.1.4 version bump 2026-07-14 19:24:11 +02:00
9327ce0ac2 dbeaver/pro#9522 integrate profile selector to connection form (#4440)
* dbeaver/pro#9522 integrate profile selector to connection form

* dbeaver/pro#9522 handles edge cases

* dbeaver/pro#9522 uses rest instead of default getter

* dbeaver/pro#9522 adds preprocessing to handle null/undefined differences arrived from backend for both: connection form network handlers & profile form network handlers

* dbeaver/pro#9522 eslint fix

* dbeaver/pro#9522 refactors profiles

* dbeaver/pro#9522 removes preprocess

* dbeaver/pro#9522 adds header & footer items

* dbeaver/pro#9522 truncates items values

* dbeaver/pro#9522 fix retrieving creds from profiles

* dbeaver/pro#9522 fix test temporary connection

---------

Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
Co-authored-by: Ainur <ainur.iagudin@dbeaver.com>
Co-authored-by: kseniaguzeeva <112612526+kseniaguzeeva@users.noreply.github.com>
2026-07-14 18:50:59 +02:00
1fb9dd7b5a dbeaver/pro#9723 Fix UI styles for improved accessibility and consistency (#4459)
* dbeaver/pro#9723 feat: add focus-visible styles for improved accessibility

* dbeaver/pro#9723 fix: adjust gutter size in ComboboxPopover for consistent spacing

* dbeaver/pro#9723 fix: update button outline offset for consistency

* dbeaver/pro#9723 fix: update hover opacity

---------

Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
Co-authored-by: mr-anton-t <42037741+mr-anton-t@users.noreply.github.com>
2026-07-14 18:37:55 +02:00
alexandDaria Marutkina e82cac479b dbeaver/pro#9861 pass null as valid filter (#4461)
Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
2026-07-14 17:44:07 +02:00
bf6afb0340 dbeaver/pro#9712 Databend driver updated to 0.4.8 (#4453)
Co-authored-by: Ainur <59531286+yagudin10@users.noreply.github.com>
Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
2026-07-14 16:13:26 +02:00
4779c3b405 dbeaver/pro#9000 adds API token settings (#4455)
* dbeaver/pro#9000 adds API token settings

* dbeaver/pro#9000 adds save extend instead

* dbeaver/pro#9000 adds observable to the schema

* dbeaver/pro#9000 adds LooseObject in favor of server config part state extension

---------

Co-authored-by: Ainur <ainur.iagudin@dbeaver.com>
Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
2026-07-14 12:15:43 +02:00
31ee01b6fa dbeaver/pro#9614 add predefined param for connection type (#4454)
* dbeaver/pro#9614 add predefined param for connection type

* dbeaver/pro#9614 add connection type selector

* dbeaver/pro#9614 make menu indicator more visible

* dbeaver/pro#9614 add extra colors

* dbeaver/pro#9614 outdate connections

* dbeaver/pro#9614 load types in bootstrap phrase

* dbeaver/pro#9614 always use useConnectionTypeColor

* dbeaver/pro#9614 remove unused import

* dbeaver/pro#9614 add useConnectionTypeLoader hook

* dbeaver/pro#9614 add default hint

* dbeaver/pro#9614 do not wrap arg:item by default

* dbeaver/pro#9614 use predefined unset for all types

* dbeaver/pro#9614 use common mapped unset color

---------

Co-authored-by: Ainur <ainur.iagudin@dbeaver.com>
Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
2026-07-13 22:11:10 +02:00
025944a867 dbeaver/pro#8947 user provisioning return user ids (#4429)
Co-authored-by: Sychev Andrey <44414066+SychevAndrey@users.noreply.github.com>
Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
Co-authored-by: mr-anton-t <42037741+mr-anton-t@users.noreply.github.com>
2026-07-13 16:00:32 +02:00
Serge Rider caee9914b8 dbeaver/pro#9851 Refactor data transfer producer. Smart mapping bug fix. (#4458) 2026-07-13 15:43:53 +02:00
sergeyteleshevandEvgenia 6e2b1b7a17 dbeaver/pro#8849 fixes spacing for bind parameters popup (#4456)
Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
2026-07-09 19:22:41 +02:00
sergeyteleshevandDaria Marutkina a379c2d7ba dbeaver/pro#9755 adds frontend cleanup for js artifacts before each app build (#4450)
* dbeaver/pro#9755 adds frontend cleanup for js artifacts before each app build

* dbeaver/pro#9775 adds x to log (revert it)

* dbeaver/pro#9775 adds clear commands to build frontend script

---------

Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
2026-07-08 17:44:33 +02:00
sergeyteleshevandDaria Marutkina 8b1054a148 dbeaver/pro#9775 adds unit test for getLocalizedDisplayName (#4451)
* dbeaver/pro#9775 adds unit test for getLocalizedDisplayName

* dbeaver/pro#9775 adds unit test for core utils

---------

Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
2026-07-08 17:44:21 +02:00
Ruslan MusaevandEvgenia 7fdc8f7e61 dbeaver/pro#9714 fix ldap injection (#4441)
Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
2026-07-08 10:21:15 +02:00
Sychev AndreyandEvgenia 32bebd4bad dbeaver/pro#9303 feat: update edge color variable in CSS for execution plan (#4387)
* dbeaver/pro#9303 feat: update edge color variable in CSS for execution plan

* dbeaver/pro#9303 feat: update node cost bar background and add theme-light styles for edges and captions

* dbeaver/pro#9303 feat: update edge color in execution plan CSS

---------

Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
2026-07-08 09:47:46 +02:00
Serge RiderandAinur 4221ea7fe0 dbeaver/pro#8757 Test connection permissions required (#4434)
* dbeaver/pro#8757 Test connection permissions required (the same as createConnection)

* dbeaver/pro#8757 Anno added

* dbeaver/pro#8757 restrict private project use for gql

* dbeaver/pro#8757 change error message

---------

Co-authored-by: Ainur <ainur.iagudin@dbeaver.com>
2026-07-07 14:10:26 +02:00
sergeyteleshevandDaria Marutkina af11aaa8fe dbeaver/cloudbeaver#3815 upgrades lib to version where it works (#4165)
* dbeaver/cloudbeaver#3815 upgrades lib to version where it works

* dbeaver/pro#3815 updates react-hotkeys-hook lib

* dbeaver/pro#3815 fixes build

* dbeaver/pro#3815 fixes case dependant hotkeys activation

* dbeaver/pro#3815 allows textbox form tag to support sql editor

---------

Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
2026-07-07 14:09:27 +02:00
5c58343a10 dbeaver/pro#8402 feat: enable checkbox selection via keyboard in Team… (#4445)
* dbeaver/pro#8402 feat: enable checkbox selection via keyboard in Teams and Users tables

* dbeaver/pro#8402 feat: enable checkbox selection via keyboard and improve accessibility in tables

fix checkbox and header cell keyboard events

---------

Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
Co-authored-by: sergeyteleshev <iamsergeyteleshev@gmail.com>
2026-07-07 10:59:16 +02:00
Serge Rider a565beb777 dbeaver/pro#9764 Fix launch parameters for Java 25 (#4448) 2026-07-06 16:59:22 +02:00
9df99fb62e dbeaver/pro#8427 feat: enable default fold keymap in CodeMirror (#4446)
* dbeaver/pro#8427 feat: enable default fold keymap in CodeMirror

* dbeaver/pro#8427 feat: add SQL editor shortcuts for folding and unfolding code blocks

---------

Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
Co-authored-by: sergeyteleshev <iamsergeyteleshev@gmail.com>
2026-07-06 14:31:26 +02:00
Serge RiderandMashaKorax b3127b9aa7 dbeaver/pro#9682 AI config profiles (#4437)
Co-authored-by: MashaKorax <84867187+MashaKorax@users.noreply.github.com>
2026-07-06 13:49:35 +02:00
Daria Marutkina f8677a0689 dbeaver/pro#9745 Update README file (#4447)
Updated changelog for version 26.1.2, detailing new features, bug fixes
2026-07-06 11:32:53 +02:00
Ruslan Musaev f22a936507 dbeaver/pro#9749 fix sso login npe (#4443)
* dbeaver/pro#9749 fix sso login npe

* dbeaver/pro#9749 fix sso login npe
2026-07-01 20:05:26 +02:00
Serge Rider b5858637d6 dbeaver/pro#9222 Annotations and permissions 2026-07-01 09:48:04 +02:00
serge-rider 475c8129fc dbeaver/pro#4320 Annotations 2026-06-30 21:55:37 +02:00
dbeaver-devops 50d846d087 dbeaver/pro#9745 26.1.3 version bump 2026-06-30 19:42:04 +02:00
Ainur 16bd3ca575 dbeaver/pro#9612 api for connection types (#4426)
* dbeaver/pro#9612 api for connection types

* dbeaver/pro#9612 add more fields for connection type info

* dbeaver/pro#9612 renaming and event handling

* dbeaver/pro#9612 fix doc and add all inputs
2026-06-30 19:15:46 +02:00
Alexander SkoblikovandMashaKorax 927184e009 dbeaver/pro#3833 fix bug with "null" origin header (#4395)
Co-authored-by: MashaKorax <84867187+MashaKorax@users.noreply.github.com>
2026-06-30 18:27:18 +02:00
d4d9081936 dbeaver/pro#9652 refactor ref api (#4412)
* dbeaver/pro#9652 refactor ref api

* dbeaver/pro#9652 refactor ref api

* dbeaver/pro#9652 refactor ref api

* dbeaver/pro#9652 refactor ref api

* dbeaver/pro#9652 remove references

* dbeaver/pro#9652 add anyConstraint

* dbeaver/pro#9652 add references panel

* dbeaver/pro#9652 remove logs

* dbeaver/pro#9652 fix attr position

* dbeaver/pro#9652 fix review

* dbeaver/pro#9652 change naming

* dbeaver/pro#9652 fallback to custom if composite and more than 1 row

* dbeaver/pro#9652 add indicator

* dbeaver/pro#9652 show proper error

* dbeaver/pro#9652 fix review, add targetColumnIndex

* dbeaver/pro#9652 fix targetColumnIndex

* dbeaver/pro#9652 pass target index

* dbeaver/pro#9652 add icons

* dbeaver/pro#9652 check prev constaints, decrease blicking

* dbeaver/pro#9652 fix constraint overwriting

* dbeaver/pro#9652 pass anyConstraint flag to export

* dbeaver/pro#9652 disable references for editors and viewers

* dbeaver/pro#9652 update icons

* dbeaver/pro#9652 show placeholder instead of loader

* dbeaver/pro#9652 show combobox

---------

Co-authored-by: alex <48489896+devnaumov@users.noreply.github.com>
Co-authored-by: naumov <iamemptyhuh@gmail.com>
Co-authored-by: sergeyteleshev <iamsergeyteleshev@gmail.com>
2026-06-30 17:57:40 +02:00
a0bcfba73d dbeaver/pro#9639 load driver properties fix (#4420)
* dbeaver/pro#9639 load driver properties fix

* dbeaver/pro#9639 pass connection config to get driver properties

* dbeaver/pro#9639 execute format action before loading properties

* dbeaver/pro#9639 do not reset properties if tab is selected

* dbeaver/pro#9639 fix import

---------

Co-authored-by: Ainur <ainur.iagudin@dbeaver.com>
Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
Co-authored-by: mr-anton-t <42037741+mr-anton-t@users.noreply.github.com>
2026-06-30 17:38:36 +02:00
Sychev Andreyandmr-anton-t 09f4828006 dbeaver/pro#9704 [CB] Fixes outlines for several components (#4431)
* dbeaver/pro#9704 fix: adjust combobox and select control outline properties

* dbeaver/pro#9704 fix: add control outline color and width for checkbox and radio components

* dbeaver/pro#9704 fix: set outline color and width for disclosure component

* dbeaver/pro#9704 refactor: add text overflow handling for combobox item values

remove tw:truncate because it adds hidden text-sm font-size

* dbeaver/pro#9704 fix: update combobox popover and item classes

* dbeaver/pro#9704 fix: correct portal handling in SelectPopover component

* dbeaver/pro#9704 fix: ensure correct portal handling in ComboboxPopover component

* dbeaver/pro#9704 refactor: rename ComboboxType to IComboboxType for consistency

* dbeaver/pro#9704 fix: line-height for combobox items

* dbeaver/pro#9704 style: remove unnecessary letter-spacing from combobox item

---------

Co-authored-by: mr-anton-t <42037741+mr-anton-t@users.noreply.github.com>
2026-06-30 17:17:54 +02:00
alexandDaria Marutkina cde64e255b dbeaver/pro#9586 adjust validation (#4427)
* dbeaver/pro#9586 let editing of loaded truncated values

* Revert "dbeaver/pro#9586 let editing of loaded truncated values"

This reverts commit 6b412ef57c.

* dbeaver/pro#9586 adjust quota validation check

* dbeaver/pro#9586 show limit amount

---------

Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
2026-06-30 16:42:01 +02:00
7b134cef81 dbeaver/pro#9526 adds profile form (#4390)
* dbeaver/pro#9526 adds profile form base functionality

* dbeaver/pro#9526 adds profiles form

* dbeaver/pro#9526 moves SSHForm to connection-network-handlers to reuse it for admin settings in future without extra deps

* dbeaver/pro#9526 moves ssh files to connection-network-handlers-plugin

* pr fixes

* moves enable form switch inside SSHForm

* dbeaver/pro#9526 shares the rest logic for configuring the ssh with profiles form as well

* dbeaver/pro#9526 cleanup

* dbeaver/pro#9526 adds go back to profiles arrow action

* dbeaver/pro#9526 small ui adjustments

* dbeaver/pro#9618 pr fixes

* dbeaver/pro#9526 creates ProjectInfoOptionsPanelService to incapsulate opening logic with tabId

* dbeaver/pro#9526 adds core-network-handlers plugin

* dbeaver/pro#9526 moves ssh network handler layout to core-network-handlers conig + adds TODO to register it to connection form

* dbeaver/pro#9526 moves registration of connection SSH network handler to plugin-connection-network-handler (from plugin-connection)

* dbeaver/pro#9526 moves registration of connection SSL network handler to plugin-connection-network-handler (from plugin-connection)

* dbeaver/pro#9526 migrates localizations among the plugins + adds missing translations

* dbeaver/pro#9526 cleanup

* dbeaver/pro#9526 fixes build

* dbeaver/pro#9526 core-network-handlers -> plugin-network-handlers

* dbeaver/pro#9526 removes license from locale files

* dbeaver/pro#9526 CONNECTION_NETWORK_HANDLER_SCHEMA -> NETWORK_HANDLER_SCHEMA

* dbeaver/pro#9526 saveChanges interface update

* dbeaver/pro#9526 refactors core -> plugin tokens

* dbeaver/pro#9526 applies copilot suggestions

* dbeaver/pro#9526 pr fixes

* dbeaver/pro#9526 moves test tunnel functionality inside ssh form

* dbeaver/pro#9526 handle network profiles changes

* dbeaver/pro#9526 cleanup

* dbeaver/pro#9526 fixes after review

* dbeaver/pro#9526 fix sending event for profiles

---------

Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
Co-authored-by: Ainur <ainur.iagudin@dbeaver.com>
2026-06-30 16:41:10 +02:00
Ruslan Musaev fde7502df8 dbeaver/pro#9713 fix event filter for rotating session (#4436) 2026-06-30 12:36:31 +02:00
Sychev Andrey 955b28c520 dbeaver/pro#9699 fix: reorder items in sql toolbar (#4433) 2026-06-30 12:29:58 +02:00
Ainur 5cfc37e26f dbeaver/pro#9481 save api token max duration fix (#4435) 2026-06-30 12:28:24 +02:00
Ruslan Musaevandsergeyteleshev 42cb6b3a9d dbeaver/pro#9022 fix error file saving (#4424)
Co-authored-by: sergeyteleshev <iamsergeyteleshev@gmail.com>
2026-06-26 12:16:44 +02:00
Serge Riderandkseniaguzeeva ad245e9f4c dbeaver/pro#9700 Save RM datasources correctly (#4425)
* dbeaver/pro#9700 Save RM datasources correctly

* dbeaver/pro#9700 Fix empty collection parameters pass over remote client

---------

Co-authored-by: kseniaguzeeva <112612526+kseniaguzeeva@users.noreply.github.com>
2026-06-25 14:35:26 +02:00
08260e6a55 dbeaver/cloudbeaver#4249 added session rotation (#4274) (#4331)
* dbeaver/cloudbeaver#4249 added session rotation (#4274)

* dbeaver/cloudbeaver#4249 added session rotation

* dbeaver/pro#4249 update web session id

* dbeaver/pro#4249 remove log

* dbeaver/pro#4249 remove unused params

* dbeaver/pro#4249 revert non-related changes

* dbeaver/cloudbeaver#4249 rotate session before login

* dbeaver/cloudbeaver#4249 fix code style

* dbeaver/cloudbeaver#4249 rotate only for anon users

* dbeaver/cloudbeaver#4249 added notnulls

---------

Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>

* dbeaver/pro#4249 fix websocket for session rotation

---------

Co-authored-by: Dmitrii Barnukov <29237913+Nexus6v2@users.noreply.github.com>
Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
Co-authored-by: Ruslan <pupkinvasya7000@gmail.com>
2026-06-25 07:06:38 +02:00
Serge Rider aea12e9fed dbeaver/pro#9700 Save RM datasources correctly 2026-06-24 17:48:29 +02:00
Ruslan MusaevandDaria Marutkina caef729a8d dbeaver/pro#9599 fix allows unauthorized server file stream (#4411)
Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
2026-06-24 15:29:07 +02:00
12030822ea dbeaver/pro#9502 [CB] move chart settings export dialogs to the widget (#4399)
* dbeaver/pro#9502 feat: allow importing css files from core-blocks package

Plugins that build UI directly on ui-kit components need the CloudBeaver theme css for these components without importing the components themselves. Expose css files through package exports so a plugin can load them as a side effect.

* dbeaver/pro#9502 fix: update focus-visible styles for select component

* dbeaver/pro#9502 feat: add tokens for combobox items

* dbeaver/pro#9502 feat: load Select/Combobox base styles from core-blocks

ui-kit controls reuse these styles, but the CE wrapper components are lazy, so the CSS only shipped in the lazy chunk, we need those styles for widgets that use UI-kit controls

* dbeaver/pro#9502 feat: enhance Select component with value display styling

---------

Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
Co-authored-by: mr-anton-t <42037741+mr-anton-t@users.noreply.github.com>
2026-06-24 12:54:46 +02:00
Mikhailov GrigoriiandSerge Rider 97cf62d333 dbeaver/dbeaver-devops#2660 Added permissions read on contents pull-requests (#4422)
Co-authored-by: Serge Rider <serge@jkiss.org>
2026-06-24 05:01:41 +02:00
8240c92247 dbeaver/pro#8796 [CB] create a separate plugin for the execution plan (#4406)
* dbeaver/pro#8796 refactor: extract Execution Plan into separate plugin

Move all Execution Plan logic out of plugin-sql-editor into a new plugin-sql-editor-execution-plan. plugin-sql-editor no longer knows about execution plan and instead exposes generic extension points

Execution plan tab data now lives in-memory in SqlExecutionPlanService instead of the persisted editor state schema (these tabs are session-only).

* dbeaver/pro#8796 feat: add naming convention rule for exported interfaces

* dbeaver/pro#8796 fix: update js-helpers dependency version in yarn.lock

* dbeaver/pro#8796 refactor: reorder register method for better readability

---------

Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
Co-authored-by: mr-anton-t <42037741+mr-anton-t@users.noreply.github.com>
2026-06-23 21:51:29 +02:00
sergeyteleshevandEvgenia 62a194c1b0 dbeaver/pro#7510 adds last login info to users tables (#4421)
* dbeaver/pro#7510 adds last login info to users tables

* dbeaver/pro#7510 shows only date

---------

Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
2026-06-23 21:46:51 +02:00
sergeyteleshevandEvgenia 36e954c440 dbeaver/pro#9664 removes undici CVE (#4415)
Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
2026-06-23 13:05:38 +02:00
Sychev AndreyandEvgenia a674c183d5 dbeaver/pro#5015 [CB] Ability to use keyboard to enabledisable checkboxes in the properties tab (#4416)
* dbeaver/pro#5015 feat: enable keyboard navigation for context menu in ObjectMenuCell

* dbeaver/pro#5015 feat: enable keyboard activation for context menu in ObjectMenuCell

---------

Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
2026-06-23 12:51:04 +02:00
Sychev Andrey 4bab1025d7 dbeaver/pro#9660 fix: selection for search panel inputs (#4418) 2026-06-23 12:49:27 +02:00
Serge Riderandmr-anton-t 7d21186158 dbeaver/pro#9266 Refactor workspace path init and change (#4409)
Co-authored-by: mr-anton-t <42037741+mr-anton-t@users.noreply.github.com>
2026-06-22 16:54:26 +02:00
eb5f89dae3 dbeaver/pro#9644 Data filters thread safety (#4407)
Co-authored-by: mr-anton-t <42037741+mr-anton-t@users.noreply.github.com>
Co-authored-by: Diana <31996417+uslss@users.noreply.github.com>
2026-06-22 16:06:37 +02:00
70292cb9c0 dbeaver/pro#9588 remove top margin (#4405)
* dbeaver/pro#9588 remove top margin

* dbeaver/pro#9588 fix: move margin from indicator to checkbox itself

add multiline checkbox story for alignment with text

* Revert "dbeaver/pro#9588 remove top margin"

This reverts commit 0b25ed6f00.

---------

Co-authored-by: Sychev Andrey <nukemoore@gmail.com>
Co-authored-by: mr-anton-t <42037741+mr-anton-t@users.noreply.github.com>
2026-06-22 14:38:20 +02:00
Evgenia 950f45833a dbeaver/pro#9630 Update README file CB 26.1.1 (#4414)
Added changelog for version 26.1.1
2026-06-22 12:39:55 +02:00
Ainur 8eb012670d dbeaver/pro#9640 fix loading driver props for old api (#4404) 2026-06-18 14:09:28 +02:00
Ruslan MusaevandAinur 413d229028 dbeaver/pro#9568 move tests to ce (#4402)
* dbeaver/pro#9568 move tests to ce

* dbeaver/pro#9568 move tests to ce

* dbeaver/pro#9568 fix tests

* dbeaver/pro#9568 fix tests

* dbeaver/pro#9568 fix tests

---------

Co-authored-by: Ainur <59531286+yagudin10@users.noreply.github.com>
2026-06-18 11:30:08 +02:00
serge-rider b0fbd41b85 dbeaver/pro#9544 Refactor SM auth model 2026-06-18 06:47:14 +02:00
660c7d9e1f dbeaver/pro#9328 Network profiles model (#4375)
Co-authored-by: mr-anton-t <42037741+mr-anton-t@users.noreply.github.com>
Co-authored-by: kseniaguzeeva <112612526+kseniaguzeeva@users.noreply.github.com>
2026-06-17 17:21:34 +02:00
dbeaver-devops 0f79ef21e7 dbeaver/pro#9630 26.1.2 version bump 2026-06-16 19:25:24 +02:00
AinurandEvgenia d9b5a9a20d dbeaver/pro#9088 api for collecting driver properties with auth (#4396)
* dbeaver/pro#9088 api for collecting driver properties with auth

* dbeaver/pro#9088 fix loading props in desktop and filter secured props

---------

Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
2026-06-16 19:04:37 +02:00
Sychev Andreyandmr-anton-t b200148765 dbeaver/pro#9565 fix: lock @codemirror/search dependency to version 6.6.0 (#4401)
in 6.7.0 they have broken the replaceNext functionality and until they fix it we lock on the working version

Co-authored-by: mr-anton-t <42037741+mr-anton-t@users.noreply.github.com>
2026-06-16 18:55:26 +02:00
sergeyteleshevandmr-anton-t 18ecc829d3 dbeaver/pro#9618 removes form-data CVE (#4400)
Co-authored-by: mr-anton-t <42037741+mr-anton-t@users.noreply.github.com>
2026-06-16 18:52:21 +02:00
AinurandEvgenia 58f51ee5f6 dbeaver/pro#9222 validate data transfer by using product settings (#4394)
Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
2026-06-16 17:24:36 +02:00
Sychev Andreyandmr-anton-t 0f7c8fe69f dbeaver/pro#4867 refactor: use aria-labelledby instead of aria-label with the same text (#4366)
Co-authored-by: mr-anton-t <42037741+mr-anton-t@users.noreply.github.com>
2026-06-16 11:37:19 +02:00
sergeyteleshev 776a91767d dbeaver/pro#9605 removes esbuild CVE (#4398) 2026-06-16 11:24:15 +02:00
Serge Rider 9f4f543eb3 Update documentation link from Community to GitHub WIKI 2026-06-14 08:08:30 +02:00
Serge Rider e4e009e1ec Update README with documentation links
Added links to official documentation and community WIKI.
2026-06-14 08:07:16 +02:00
serge-rider 895d27eb84 Workflow update 2026-06-13 23:27:08 +02:00
serge-rider a0cbaa89f6 Workflow update 2026-06-13 23:23:12 +02:00
serge-rider 32d1ef9a70 dbeaver/pro#9573 Groom test deps. 2026-06-13 23:17:35 +02:00
8362946990 dbeaver/pro#7128 Remove deprecated API (#3820)
* dbeaver/pro#7128 Remove deprecated API

* dbeaver/pro#7128 Fix nodes

* dbeaver/pro#7128 Return DS id in objectId

* dbeaver/pro#7128 disable test

* dbeaver/pro#7128 fixes connectionId and node Uri

* dbeaver/pro#7128 use new node path patterns

* dbeaver/pro#7128 FS in root nodes

* dbeaver/pro#7128 FS in root nodes

* dbeaver/pro#7128 FS and clouds in root nodes

* dbeaver/pro#7128 fix getting connection part

* dbeaver/pro#7128 use node path by default

* dbeaver/pro#7128 remove unused import

* dbeaver/pro#7128 fix tests

* dbeaver/pro#7128 Fix web cloud explorer

* dbeaver/pro#7128 Path calculation fix. Delete legacy and dead code.

* dbeaver/pro#7128 support folders new path

* dbeaver/pro#7128 add rm prefix variable

* dbeaver/pro#7128 adjust tests

* dbeaver/pro#7128 Remove deprecated node id property

* dbeaver/pro#7128 use uri in db objects

* dbeaver/pro#7128 do not restore tab if wrong format is used

* makes isDatabaseObject less heuristic

* Revert "makes isDatabaseObject less heuristic"

This reverts commit f85acd91f9.

* local fix for folders open action

* disallow to open folders in object viewer

* uses helper to identify node for advanced view correct behavior

* dbeaver/pro#7128 fixes the test which falls from time to time

* dbeaver/pro#7128 fixes the test which falls from time to time

* dbeaver/pro#7128 fixes the test which falls from time to time 2

* dbeaver/pro#7128 fixes the test which falls from time to time 2

* dbeaver/pro#7128 isolates unit tests

* Revert "dbeaver/pro#7128 isolates unit tests"

This reverts commit 5bf6adbdd1.

* dbeaver/pro#7128 tries useTranslateMock to fix the issue

* removes mocks

* skips the tests

---------

Co-authored-by: Ruslan <pupkinvasya7000@gmail.com>
Co-authored-by: alex <48489896+devnaumov@users.noreply.github.com>
Co-authored-by: naumov <iamemptyhuh@gmail.com>
Co-authored-by: mr-anton-t <42037741+mr-anton-t@users.noreply.github.com>
Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
Co-authored-by: sergeyteleshev <iamsergeyteleshev@gmail.com>
2026-06-12 12:30:53 +02:00
AinurandEvgenia d3d71b79f0 dbeaver/pro#9120 cloudbeaver conf generator (#4388)
* dbeaver/pro#9120 cloudbeaver conf generator

* dbeaver/pro#9120 add tests and fix configs

---------

Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
2026-06-12 11:34:39 +02:00
Ainurandmr-anton-t c344210b8b dbeaver/pro#7923 fix logging and use sm session id for events (#4374)
* dbeaver/pro#7923 fix logging and use sm session id for events

* dbeaver/pro#7923 nullability and move function

---------

Co-authored-by: mr-anton-t <42037741+mr-anton-t@users.noreply.github.com>
2026-06-12 11:33:13 +02:00
f6aea971ef dbeaver/pro#9124 feat: replace Checkbox and Radio components with CheckboxIndicator and RadioIndicator for improved UI consistency (#4383)
* dbeaver/pro#9124 feat: introduce visual-only checkbox and radio indicators for improved nested interactive elements

* dbeaver/pro#9124 feat: add Checkbox and Radio components stories

* dbeaver/pro#9124 feat: export ControlSize type from controls module

* dbeaver/pro#9124 feat: add CheckboxIndicator and RadioIndicator components

* dbeaver/pro#9124 feat: replace Checkbox and Radio components with CheckboxIndicator and RadioIndicator for improved UI consistency

* dbeaver/pro#9124 refactor: rename CheckboxIndicatorProps to ICheckboxIndicatorProps for consistency

* dbeaver/pro#9124 refactor: rename RadioRootOwnProps to Props for consistency

* dbeaver/pro#9124 refactor: rename theme prop to variant in CheckboxIndicator for consistency

* dbeaver/pro#9124 refactor: rename RadioIndicatorProps to Props for consistency

---------

Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
Co-authored-by: mr-anton-t <42037741+mr-anton-t@users.noreply.github.com>
Co-authored-by: sergeyteleshev <iamsergeyteleshev@gmail.com>
2026-06-12 11:09:22 +02:00
Ruslan Musaevandmr-anton-t 3d9c4391d1 dbeaver/pro#9119 fix code vulnerability (#4380)
Co-authored-by: mr-anton-t <42037741+mr-anton-t@users.noreply.github.com>
2026-06-12 11:05:23 +02:00
sergeyteleshevandmr-anton-t 19284d33e7 dbeaver/pro#9550 removes critical CVE for shell-quote dependency (#4391)
Co-authored-by: mr-anton-t <42037741+mr-anton-t@users.noreply.github.com>
2026-06-12 10:41:40 +02:00
dc1e865545 dbeaver/pro#9436 feat: add isNumber and replaceMiddle utility functions (#4377)
* dbeaver/pro#9436 feat: add isNumber and replaceMiddle utility functions

* dbeaver/pro#9436 refactor: move uuid helper into @dbeaver/js-helpers

Move uuid() from @cloudbeaver/core-utils into the portable @dbeaver/js-helpers so chart widget code can depend on it without pulling in CloudBeaver. core-utils re-exports uuid/V4Options/V1Options from js-helpers, so existing importers are unaffected; the uuid npm dependency moves to js-helpers.

* dbeaver/pro#9436 style: update copyright year in uuid_ file

* dbeaver/pro#9436 refactor: reexport isNumber and replaceMiddle functions from @dbeaver/js-helpers

* dbeaver/pro#9436 refactor: rename uuid file to uuid_ and update exports

---------

Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
Co-authored-by: sergeyteleshev <iamsergeyteleshev@gmail.com>
Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
2026-06-11 14:20:45 +02:00
Sychev Andrey 4d62ddb5fc dbeaver/pro#9572 ci: add associations and references fields to SQL execute task results (#4393) 2026-06-11 14:08:40 +02:00
Ruslan MusaevandEvgenia 14df3b3120 dbeaver/pro#8981 add api for reference panel in cloudbeaver (#4313)
* dbeaver/pro#8981 add api for reference panel in cloudbeaver

* dbeaver/pro#8981 fixes

* dbeaver/pro#8981 api ref panel

* dbeaver/pro#8981 api ref panel

* dbeaver/pro#8981 api ref panel

* dbeaver/pro#8981 add api ref to table level

* dbeaver/pro#8981 fix tests

* dbeaver/pro#8981 fix review

* dbeaver/pro#8981 lazy loading fix

* dbeaver/pro#8981 separate association and refs

---------

Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
2026-06-11 12:15:12 +02:00
Ruslan Musaev 30f5bd3bb3 dbeaver/pro#9482 add last auth date for users (#4389) 2026-06-11 12:14:31 +02:00
04a4c19331 dbeaver/pro#8780 migrate switch component to ui-kit (#4373)
* dbeaver/pro#8780 moves switch to ui-kit component + adds story

* redesigns switch

* fixes dense example

* fixes animations

* removes outline for whole area of switch

* adds tied to the input label

* adds innerChecked

* adds composition to the Switch component

* refactors switch API to make it more composable

* adds specifity to win css race with font weight for label

* fixes dense font weight

---------

Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
Co-authored-by: mr-anton-t <42037741+mr-anton-t@users.noreply.github.com>
2026-06-11 10:40:51 +02:00
Anastasiya 5bc6ea3731 dbeaver/dbeaver-devops#2699 Revise security policy (#4392)
* dbeaver/dbeaver-devops#2699 Revise security policy

Updated the contact email for reporting security vulnerabilities.

* dbeaver/dbeaver-devops#2699 Update email format in SECURITY.md
2026-06-10 12:20:51 +03:00
Alexander Skoblikovandkseniaguzeeva d93d73bb44 dbeaver/pro#9508 use proto header without host (#4379)
* dbeaver/pro#9508 use proto header without host

* dbeaver/pro#9508 review fixes

---------

Co-authored-by: kseniaguzeeva <112612526+kseniaguzeeva@users.noreply.github.com>
2026-06-10 09:16:58 +02:00
6cdc6b2ee0 [CB] Render data viewer context menu on the root level (#4363)
* dbeaver/pro#9308 moves context menu from the cell level to table level

* cleanup

* adds DataGridMenuContextProvider

* uses context menu position from the hook useContextMenuPosition

* closes menu if cell is not visible

* adds useViewLeave hook to close menu if it is out of the view

* changes approach for re-opening menus + removes isMenuVisible logic

* removes redundant event prevent default and stopPropogation

* fixes focus stealing issue

* hides menu on scroll

* cleanup

* pr fixes

* cleanup

* uses cell key to open table

* pr fixes

* simplifies the menu api

* adds openMenuAt to reduce casting to mouse event while opening menu via shortcut

* cleanup

* removes isMenuOpened guard

* moves menu to the center of icon when opens from keyboard

* removes onClose handling and focus cell in sync workaround

* adds keyboard event handling for the context menu api

* compares cells with keys utils helper

* removes open menu at

* removes setContext

* cleanup

* simplifies interfaces

* fixes bug with menu not being able to rerender

* restores focus on close

* dbeaver/pro#9308 simplify logic

* adds closing menu on scroll

* pr fixes

* dbeaver/pro#9308 adds context menu sr-only for accessibility

* adds arialabel for icon button

* Revert "adds arialabel for icon button"

This reverts commit a830301f7a.

* adds span to make scrolling work

---------

Co-authored-by: alex <48489896+devnaumov@users.noreply.github.com>
Co-authored-by: naumov <iamemptyhuh@gmail.com>
Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
2026-06-10 00:30:31 +02:00
sergeyteleshevandEvgenia 96ba18da83 [CB] Create project form with options tab (#4386)
* dbeaver/pro#9525 register project-info plugin

* adds project info to the context menu

* adds project info form

* adds project options part info tab content

* separates logic with bootstraps

* removes unused locales

* pr fixes

* removes global and shared checkboxes

---------

Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
2026-06-09 19:52:04 +02:00
sergeyteleshevandmr-anton-t a16c138bba [CB] cleanup resolutions for package.json in all products (CE,EE, widgets) (#4376)
* dbeaver/pro#9234 removes happy-dom resolution

* removes all resolutions

* updates deps

* removes CVEs

* updates deps

---------

Co-authored-by: mr-anton-t <42037741+mr-anton-t@users.noreply.github.com>
2026-06-09 19:49:24 +02:00
Tsimafei Labanovich f728590b90 dbeaver/pro#8766 Migrage from junit 4 to junit 6 (#4290)
* dbeaver/pro#8766 Boom

* dbeaver/pro#8766 Boom

* dbeaver/pro#8766 Boom

* dbeaver/pro#8766 Boom
2026-06-09 16:26:42 +02:00
Sychev AndreyandEvgenia ba7268bb8f dbeaver/pro#8684 feat: unlock autoscroll when dragging in data grid (#4362)
* dbeaver/pro#8684 feat: unlock autoscroll when dragging in data grid

* dbeaver/pro#8684 fix: don't select value panel and rows input in the toolbar on drag

as a bonus enhance data grid context menu accessibility to improve user selection behavior when we start dragging from the menu button

return selection only when the cell is edited

* dbeaver/pro#8684 refactor: add selection background color for input in editing cell

---------

Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
2026-06-09 12:44:54 +02:00
Serge Rider 1b7c81fa24 Update readme 2026-06-09 09:26:58 +02:00
sergeyteleshevandmr-anton-t 98f8380962 [CB] Miragre Form Controls styles to CSS (#4365)
* dbeaver/pro#8782 migrates form controls from scss to css

* migrates all scss to css

* removes all scss mentions

* fixes input colors

* fixes thumb and link colors

* fixes padding & border errors (search panel & where filter)

* fixes disabled state for switches (input type="checkbox")

---------

Co-authored-by: mr-anton-t <42037741+mr-anton-t@users.noreply.github.com>
2026-06-08 19:37:32 +02:00
Nikita Akilov 2d40781960 dbeaver/dbeaver-devops#2313 switch to JDK 25 in base-java (#4382) 2026-06-04 15:41:38 +02:00
Ainur 166efa634f dbeaver/pro#9511 fix unknown struct presentation (#4378) 2026-06-04 14:37:16 +02:00
Sychev Andrey fad07f3d73 dbeaver/pro#9438 fix: fix the export lib version (#4369)
* dbeaver/pro#9438 fix: fix the export lib version

* dbeaver/pro#9438 fix: update modern-screenshot dependency to version 4.6.8
2026-06-01 14:45:15 +02:00
Anastasiya 4ca4976184 dbeaver/pro#9401 Update README.md to fix formatting (#4371) 2026-06-01 11:55:23 +02:00
Daria Marutkina ed4f5e45ed dbeaver/pro#9401 Update README file (#4370)
Updated changelog for version 26.1.0, including new features and bug fixes.
2026-06-01 11:42:10 +02:00
Ainur a333e5841a dbeaver/pro#9447 validate project path fix (#4367)
* dbeaver/pro#9447 validate project path fix

* dbeaver/pro#9447 validate project name on creating project

* dbeaver/pro#9447 validate project using general utils
2026-05-29 10:27:10 +02:00
Serge Rider 2c3afd61f0 dbeaver/pro#9392 Nullability annos. DEad code delete. 2026-05-28 14:10:27 +02:00
Sychev AndreyandEvgenia a817dcd92f dbeaver/pro#9407 fix: long values wrapping (#4364)
we mimic here the old input's behaviour, when we can't see the scroll but can navigate through the 1-line value with keyboard or mouse drag/selection

Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
2026-05-27 20:38:22 +02:00
Serge Riderandkseniaguzeeva c14e8f5ce3 dbeaver/pro#9397 Initialize datasource registry flow fix (#4360)
Co-authored-by: kseniaguzeeva <112612526+kseniaguzeeva@users.noreply.github.com>
2026-05-26 17:46:12 +02:00
dbeaver-devops cc3cf21890 dbeaver/pro#9401 26.1.1 version bump 2026-05-25 20:54:14 +02:00
sergeyteleshevandEvgenia 961430f988 [CB] Menu is displayed under opened forms in the Administration page (#4358)
* dbeaver/pro#9362 fixes z-indexes issues for dialogs and notifications

* moves getPersistentElements to dialog level so all dialogs can handle it

* adds data-dialog-persistent-notification

* fixes resize controls layering

* fixes issue with panel buttons layering

* cleanup

---------

Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
2026-05-25 17:53:03 +02:00
759b30a24b dbeaver/pro#9182 remove global secret controller for server apps (#4340)
Co-authored-by: kseniaguzeeva <112612526+kseniaguzeeva@users.noreply.github.com>
Co-authored-by: mr-anton-t <42037741+mr-anton-t@users.noreply.github.com>
2026-05-25 17:52:50 +02:00
Sychev AndreyandEvgenia 225ce91fd7 dbeaver/pro#8486 feat: add DataReadonlyReason API for data sources (#4354)
* dbeaver/pro#8486 feat: add DataReadonlyReason API for data sources

Previously TableStatusIndicator relied on model.isReadonly() which lost reasons. This caused the "Read-only connection" tooltip to show in grouping panel even on
editable connections — the connection wasn't read-only, the
presentation was.

Each data source now declares its specific reason via getReadonlyReason(). UI maps the typed reason to an accurate
message

* dbeaver/pro#8486 refactor: remove DataReadonlyReason references and use hasFeature flag

---------

Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
2026-05-25 12:36:20 +02:00
f7bdd80e9f dbeaver/pro#9131 use visual keys for copy & paste (#4350)
Co-authored-by: sergeyteleshev <iamsergeyteleshev@gmail.com>
Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
2026-05-22 16:55:18 +02:00
sergeyteleshevandDaria Marutkina e42d34ac58 [CB] Ability to add a new MCP agent (#4329)
* dbeaver/pro#9126 initial commit for PR message

* adds validations

* adds json linter

* reverts safeParseSchema

* removes reset button

---------

Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
2026-05-22 10:11:59 +02:00
sergeyteleshevandDaria Marutkina 89a1af2df9 [CB] Fix table spacing regression in admin UI (#4353)
Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
2026-05-21 19:49:34 +02:00
sergeyteleshevandDaria Marutkina e4260b4cd2 [CB] API token generation dropdown doesn't fit to the island (#4351)
Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
2026-05-21 19:47:45 +02:00
AinurandEvgenia 956ebaa515 dbeaver/pro#9306 disconnect event send fix (#4356)
Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
2026-05-21 19:45:55 +02:00
alexandDaria Marutkina bccf47020e dbeaver/pro#9095 load active connections before checking execution context (#4355)
Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
2026-05-21 18:22:42 +02:00
alexandEvgenia dcd2b608ea dbeaver/pro#9370 check all passwords, not only the first one (#4357)
Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
2026-05-21 18:20:29 +02:00
84af14d2f7 Closes dbeaver/pro#9327 Extract LibSQL driver from build (#4344)
* Closes dbeaver/pro#9327 Extract LibSQL driver from build

* dbeaver/pro#9327 load libsql from maven for cloudbeaver ce

---------

Co-authored-by: MashaKorax <84867187+MashaKorax@users.noreply.github.com>
Co-authored-by: Ainur <ainur.iagudin@dbeaver.com>
Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
2026-05-21 14:52:16 +02:00
sergeyteleshevandEvgenia f513f7dc44 [CB] Many warnings in the console when creating a new connection (#4352)
Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
2026-05-21 14:50:12 +02:00
Sychev AndreyandDaria Marutkina ffa7f730de dbeaver/pro#8741 fix: update container label visibility logic when no… (#4347)
Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
2026-05-21 12:24:15 +02:00
Sychev AndreyandDaria Marutkina 694d3b241f dbeaver/pro#9342 build: update node version to 24.13.1 in CI workflows (#4349)
Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
2026-05-20 21:38:49 +02:00
9c8f3c47e6 [CB] Add shortcut for the cell context menu in data and metadata editors (#4332)
* dbeaver/pro#8424 adds shortcut top open/close context menu for the data editor

* moves helper into parseHotkeys + simplifies it

* adds unit tests

* adds autoFocusOnShow prop to support backward compatibility

* dbeaver/pro#8424 use current state

* adds few test cases for the extra buttons pressed

---------

Co-authored-by: naumov <iamemptyhuh@gmail.com>
Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
2026-05-20 16:38:03 +02:00
sergeyteleshev f918c9e25e dbeaver/pro#8621 hides upload button for viewers roles and for disabled edit setting in data editor (#4348) 2026-05-20 16:37:43 +02:00
b84031bb84 dbeaver/cloudbeaver#4138 feat: support inline editing of multi-line v… (#4341)
* dbeaver/cloudbeaver#4138 feat: support inline editing of multi-line values in data grid cells

- TextEditor: switch <input> to <textarea rows=1> so newlines are preserved when editing. Suppress the trailing insertLineBreak from the Enter that opens the editor (would otherwise wipe the auto-selected value).
- ResultSetFormatAction.truncateText: substitute \n, \r, \r\n, \t with
  visible glyphs (↵, ␍, →) and collapse other control chars to a space
  in a single pass.

Perf note: the new replace should be faster than the prior
split('') + map + join. No intermediate array allocations, and the
callback runs only on matched chars (which are sparse in display text). \p{Cc} also expands coverage from charCode < 32 to include DEL and C1 controls (U+007F, U+0080–U+009F). (closer to Dbeaver behavior)

* dbeaver/pro#4138 feat: show raw text in title for text cells

* dbeaver/pro#4138 treat one cell differently

---------

Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
Co-authored-by: naumov <iamemptyhuh@gmail.com>
Co-authored-by: alex <48489896+devnaumov@users.noreply.github.com>
2026-05-20 14:28:08 +02:00
af651f9d10 dbeaver/pro#8459 trim username (#4343)
Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
2026-05-19 19:00:53 +02:00
sergeyteleshevandDaria Marutkina 3245943f3d [CB] It is impossible to open edit forms from entity tables via keyboard (Users, Teams, Drivers, Providers, Secret Management) (#4345)
* dbeaver/pro#8404 adds onCellKeyDownTableOpen helper to all side modal tables

* replaces onKeyDown with Command

---------

Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
2026-05-19 12:10:59 +02:00
Sychev AndreyandEvgenia fe01b23fce dbeaver/pro#9090 refactor: use new getters for sql execution plan (#4333)
Co-authored-by: Evgenia <139753579+EvgeniaBzzz@users.noreply.github.com>
2026-05-18 17:36:20 +02:00
alexandDaria Marutkina 8ec052e1b1 dbeaver/pro#9274 update whereFilter even if there is no result (#4336)
Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
2026-05-18 13:48:51 +02:00
Daria Marutkina b10b407270 dbeaver/pro#9290 Update README file (#4346)
Added changelog for version 26.0.5, detailing new features, fixes, and updates across various components including authorization, data editor, SQL editor, database drivers, and security improvements.
2026-05-18 12:30:10 +02:00
alexandDaria Marutkina 5f5a6743eb dbeaver/pro#9133 use common GridSelectAction (#4342)
Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
2026-05-18 11:22:26 +02:00
sergeyteleshev 4b30dc3ba5 [CB] Refresh of disconnected connection leads to 'Something went wrong' error (#4338)
* dbeaver/pro#8294 allows to refresh only connection root nodes for non-established connections

* renames variable

* checks if connection is connected to refresh it properly

* adds node check instead of connection directly
2026-05-15 13:27:33 +02:00
Ruslan Musaev 86e114d471 dbeaver/pro#9134 fix ldap error log (#4339) 2026-05-15 11:34:15 +02:00
dbeaver-devops d4d2e2d1fa dbeaver/pro#9290 26.1.0 version bump 2026-05-12 19:52:53 +02:00
1289 changed files with 29164 additions and 6242 deletions
+1 -1
View File
@@ -46,7 +46,7 @@ jobs:
- run: corepack enable
- uses: actions/setup-node@v4
with:
node-version: "lts/*"
node-version: "24.13.1"
cache: "yarn"
cache-dependency-path: |
cloudbeaver/webapp/yarn.lock
+1 -1
View File
@@ -25,7 +25,7 @@ jobs:
- run: corepack enable
- uses: actions/setup-node@v4
with:
node-version: "lts/*"
node-version: "24.13.1"
cache: "yarn"
cache-dependency-path: "./cloudbeaver/webapp/yarn.lock"
+4 -5
View File
@@ -6,6 +6,7 @@ on:
- opened
- synchronize
- reopened
- ready_for_review
push:
branches: [devel]
@@ -24,11 +25,6 @@ jobs:
project-deps: ./cloudbeaver/project.deps
timeout-minutes: 5
# build-server:
# name: Server
# uses: ./.github/workflows/backend-build.yml
# secrets: inherit
build-frontend:
name: Frontend
uses: ./.github/workflows/frontend-build.yml
@@ -38,6 +34,9 @@ jobs:
name: Server
uses: dbeaver/dbeaver-common/.github/workflows/java-checkstyle.yml@devel
secrets: inherit
permissions:
contents: read
pull-requests: read
lint-frontend:
name: Frontend
+1 -2
View File
@@ -14,7 +14,6 @@
"redhat.vscode-yaml",
"streetsidesoftware.code-spell-checker",
"streetsidesoftware.code-spell-checker-russian",
"syler.sass-indented",
"github.copilot-chat",
"yzhang.markdown-all-in-one",
"GraphQL.vscode-graphql-syntax",
@@ -22,4 +21,4 @@
"esbenp.prettier-vscode",
"devnaumov.licensify"
]
}
}
+1 -1
View File
@@ -48,6 +48,7 @@
"-Declipse.pde.launch=true",
"-XstartOnFirstThread",
"-Dfile.encoding=UTF-8",
"--enable-native-access=ALL-UNNAMED",
"--add-modules=ALL-DEFAULT",
"--add-opens=java.base/java.io=ALL-UNNAMED",
"--add-opens=java.base/java.lang=ALL-UNNAMED",
@@ -64,7 +65,6 @@
"--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED",
"--add-opens=java.base/sun.nio.ch=ALL-UNNAMED",
"--add-opens=java.base/sun.security.ssl=ALL-UNNAMED",
"--add-opens=java.base/sun.security.action=ALL-UNNAMED",
"--add-opens=java.base/sun.security.util=ALL-UNNAMED",
"--add-opens=java.security.jgss/sun.security.jgss=ALL-UNNAMED",
"--add-opens=java.security.jgss/sun.security.krb5=ALL-UNNAMED",
+106 -123
View File
@@ -5,13 +5,16 @@
Cloud Database Manager - Community Edition.
CloudBeaver is a web server that provides a rich web interface. The server itself is a Java application, and the web part is written in TypeScript and React.
It is free to use and open-source (licensed under [Apache 2](https://github.com/dbeaver/cloudbeaver/blob/devel/LICENSE) license).
See our [WIKI](https://github.com/dbeaver/cloudbeaver/wiki) for more details.
<a><img src="https://github.com/dbeaver/cloudbeaver/wiki/images/connection-creation-demo.png" width="400"/></a>
<img src="https://github.com/dbeaver/cloudbeaver/wiki/images/gis-demo.png" width="400"/>
<img src="https://github.com/dbeaver/cloudbeaver/wiki/images/data-transfer-demo.png" width="400"/>
<img src="https://github.com/dbeaver/cloudbeaver/wiki/images/sql-editor-demo.png" width="400"/>
## Documentation
- [GitHub WIKI](https://github.com/dbeaver/cloudbeaver/wiki)
- [Official documentation](https://dbeaver.com/docs/cloudbeaver/)
## Run in Docker
- [Official Docker repository](https://hub.docker.com/r/dbeaver/cloudbeaver)
@@ -19,156 +22,136 @@ See our [WIKI](https://github.com/dbeaver/cloudbeaver/wiki) for more details.
## Demo server
You can see a live demo of CloudBeaver here: https://demo.cloudbeaver.io
You can see a live demo of CloudBeaver server here: https://demo.cloudbeaver.io
[Database access instructions](https://github.com/dbeaver/cloudbeaver/wiki/Demo-Server)
## Changelog
### 26.0.4 2026-05-04
### 26.1.3 2026-07-20
- Data Editor:
- Added the ability to copy-paste multiple cells at once. Pasted values will be distributed across separate cells, not put in a single cell.
- Data Editor started to keep the state of column configurations, such as filters, sorting, and ordering, after the reconnect, page refresh, and re-login.
- Fixed copying of large JSON values in the Data Editor - now the full value can be copied and transferred.
- Updated the Reference panel to show only relevant rows when a foreign key is null.
- General:
- Added connection types to visually distinguish database environments using background colors across the Database Navigator and application UI. Users with edit permissions can assign built-in environment types color-coded configurations.
- Data Transfer:
- Improved memory usage when importing large CSV files.
- Fixed CSV export with multi-character quotes and improved quote/delimiter validation
- Accessibility:
- Enabled the use of the Enter or space keys to toggle checkboxes in the administration tabs and the metadata viewer.
- Added the ability to expand and collapse code block elements, including JSON, using the keyboard.
- Fixed shortcuts behavior for AZERTY keyboards. Now shortcuts like Ctrl/Cmd + Z work correctly.
- Security:
- Resolved an authorization vulnerability when testing connections by enforcing strict permission checks. This mitigation prevented unauthenticated users from exploiting JDBC requests to read arbitrary server files.
- Resolved an LDAP injection vulnerability by properly escaping user input in the authentication username field, preventing attackers from manipulating search filters, bypassing access restrictions, and enumerating directory users.
- Fixed the high vulnerability (GHSA-gv7w-rqvm-qjhr) in the esbuild library. The library was updated to version 0.28.1.
- Fixed the high vulnerability (CVE-2026-12143) in the form-data library. The library was updated to version 4.0.6.
- Databases and drivers:
- The Databend driver was updated to version 0.4.8.
- Fixed an issue related to the display of metadata in the navigation tree for DB2, Firebird, and MySQL.
### 26.1.2 2026-07-06
- Data Editor:
- Added the References panel showing related records from other tables connected by foreign keys. It helps to explore table relationships directly in the Data editor.
- Resolved an issue where the Data Editor ignored the text preview's maximum length quota. Increasing this quota now enables the ability to edit large values.
- General:
- Added the Last Login time to the user form and the user table in the administration part.
- Fixed the bug with the inability to select entered text in the Find and Replace panel in editors.
- Accessibility:
- Added the ability to use the Enter or Space key to turn checkboxes on/off in the connection properties tab.
- Security:
- Fixed CVE-2026-55449. Resolved a local file disclosure vulnerability by enforcing strict validation of file identifiers and path containment during data updates.
- Updated session handling to prevent session fixation vulnerabilities. The application generates new session identifiers upon login.
- Fixed the high vulnerability (CVE-2026-12151) in the undici library. The library was updated to version 6.27.0.
### 26.1.1 2026-06-22
- General: Added a "Project Info" tab containing the project description to the project context menu.
- Security:
- Fixed a cross-site scripting vulnerability caused by unsanitized user input in the web interface.
- Resolved a security flaw related to user-controlled file paths by adding strict validation to prevent unauthorized resource access.
- Fixed the critical vulnerability (CVE-2026-9277) in the shell-quote library (updated to version 1.8.4).
### 26.1.0 2026-06-01
### Changes since 26.0.0:
- Administration:
- Added support for custom startup arguments when running CloudBeaver in a container. Administrators can specify configuration file locations to adapt the application to their environment. (thanks to @MalteHei)
- Updated the manifest.webmanifest file to generate dynamically based on the CLOUDBEAVER_ROOT_URI environment variable. (thanks to @houssemexo26)
- Authorization:
- Added HTTP header authentication support for GraphQL queries. Users can provide API tokens via Authorization or X-Api-Key headers, allowing external data tools to authenticate without modifying request bodies.
- Fixed a bug in the authentication form: the existing password is now required for password changes.
- SQL Editor:
- Updated the SQL Editor to use real tab characters for indentation. The application displayed tabs as four-space gaps with a distinct visual marker.
- Added the ability to view and edit scripts without connecting to the database.
- Added more settings to the Generated SQL window, including the ability to select fully qualified names for query or use compact SQL formatting.
- Added the ability to open in the SQL Editor generated queries right from the Generate SQL window.
- Accessibility:
- Fixed contrast for elements across different application parts in the light and dark themes to meet WCAG requirements.
- General:
- Removed the "Folders" setting from the available settings for the Navigator Tree.
- Databases:
- DuckDB: Fixed map rendering for GEOMETRY types with CRS parameters.
- Firebird: Expanded database-specific SQL dialect coverage for the SQL Editor. Added more keywords, built-in functions, and SQL generators.
- MySQL: Fixed query boundaries recognition in the SQL Editor for scripts with the DELIMITER keyword.
- SQL Server: Fixed DDL generation for external tables.
- Security:
- Updated session handling to prompt the application to generate a new session identifier for each login.
- Fixed the high vulnerability (CVE-2026-3505) in the bcpg-jdk18on library. The library was updated to version 1.84.0.
### 26.0.3 2026-04-20
- Added an ability to view and edit scripts without connecting to the database.
- Added the ability to open generated queries right from the Generate SQL window.
- Added fuzzy search to SQL Editor auto-completion for object names. The feature allows users to find tables and containers even with typos or incorrect letter ordering.
- Added the tooltip about quoting rules for the Bind variables parameters dialog.
- Fixed keyword autocompletion for partially typed keywords to avoid redundant letters.
- Data Editor:
- Added the ability to copy-paste multiple cells at once. Pasted values will be distributed across selected cells.
- Added an ability to add, duplicate, delete, or set values to NULL in multiple highlighted rows via the Data Editor context menu.
- Added the Find and Replace functionality for the Data Editor with the ability to find data by matching case, whole word, or using regular expressions.
- Data Editor started to keep the state of column configurations, such as filters, sorting, and ordering, after the reconnect, page refresh, and re-login.
- Added key column mark for tables with unique keys in the data grid.
- Added the ability to paste a copied cell into multiple cells and to set multiple cells to NULL.
- Added more settings to the Generated SQL window, including the ability to select fully qualified names for query or use compact SQL formatting.
- Added a DDL generation option to the Data Editor and Result Set context menu.
- Fixed copy and paste behavior for multiline and special characters in the Data Editor. Added visual glyphs to indicate line breaks and tabs in the data grid.
- Fixed the ability to copy Boolean values in the clipboard in the Data Editor.
- Fixed the ability to calculate row count for non-standard SELECT statements. (thanks to @fdcastel)
- Navigator Tree:
- Navigator tree:
- Reorganized the context menu on the connection level to make it more compact.
- Added support for special symbols (pipe, comma, and asterisk) for the search field.
- Removed the "Folders" setting from the settings list for the Navigator Tree.
- Accessibility:
- Added the Skip to content option for quick keyboard access to the Navigator Tree, editors, and shortcuts to improve application accessibility.
- Added the Skip to content option for quick keyboard access to the Navigator Tree, editors, and shortcuts list tab to improve application accessibility.
- Improved keyboard navigation for context menu and buttons for Data Editor, SQL Editor, and Navigator tree.
- Added the Ctrl + / keyboard shortcut to open the context menu for selected cells in the Data Editor.
- Fixed the ability to switch tabs in the Data Editor using the keyboard.
- Fixed contrast for elements across different application parts in the light and dark themes to meet WCAG requirements.
- General:
- SQL Editor: Fixed keyword autocompletion for partially typed keywords. There are no extra letters for them after completion.
- Added support for custom startup arguments when running CloudBeaver in a container. Administrators can specify configuration file locations to adapt the application to their environment. (thanks to @MalteHei)
- Marked icons for non-saved (temporary) scripts with the hourglass symbol to add visual distinction from the saved ones.
- Added the ability to set to NULL any value in the Driver Properties.
- Fixed custom driver properties display for the connection page.
- Fixed data export in SQL format for values containing single quotes.
- Databases:
- ClickHouse: Fixed the display of Array(JSON) types in the data grid.
- Databases and drivers:
- ClickHouse:
- Fixed the display of Array(JSON) types in the data grid.
- Updated driver version to 0.9.7.
- Fixed IP address display in the Data Editor by removing the leading slash.
- Added support for the "prompt=false" connection property for DB2 for IBM i to turn off interactive prompts and prevent related errors.
- DuckDB:
- Fixed map rendering for GEOMETRY types with CRS parameters.
- Fixed geometry type display for database versions > 1.5.
- H2 database:
- Added new embedded driver version 2.4.2.
- Updated server driver to version 2.4.2.
- Firebird: Expanded database-specific SQL dialect coverage for the SQL Editor. Added more keywords, built-in functions, and SQL generators.
- MySQL: Fixed query boundaries recognition in the SQL Editor for scripts with the DELIMITER keyword.
- PostgreSQL:
- Updated driver to version 42.7.11
- Fixed missing INOUT parameters in CHECK generation for procedures and functions.
- Fixed handling of 24:xx values in time columns.
- Fixed an error when connecting via URL if the database name contains a hyphen.
- SQL Server:
- Fixed DDL generation for external tables.
- Fixed the database connectivity issue after the Java update.
- Security:
- Added an administrative setting to restrict SSH tunneling capabilities. Administrators can now limit tunnel configuration to authorized users, reducing the risk of unauthorized network access.
- Fixed the critical vulnerability (CVE-2025-62718) in the axios library. The library was updated to version 1.15.0.
- Fixed the high vulnerability (CVE-2026-4800) in the lodash library. The library was updated to version 4.18.0.
- Fixed the high vulnerability (CVE-2026-39363) in the vite library. The library was updated to version 7.3.2.
### 26.0.2 2026-04-06
- UI improvements:
- Marked icons for non-saved (temporary) scripts with the hourglass symbol to add visual distinction from the saved ones.
- Added the tooltip about quoting rules for the Bind variables parameters dialog.
- Improved keyboard navigation for context menu and buttons for Data Editor, SQL Editor, and Navigator tree.
- Authentication:
- Fixed the bug with the authentication form. Now the same password is required for the password change operation.
- Fixed the display of authentication fields for SQL Server with Active Directory - MSI. The unnecessary Password field was removed.
- Databases and drivers:
- DuckDB: Fixed geometry type display for database versions > 1.5. (thanks @EastLord).
- H2 database:
- Added new embedded driver version 2.4.2.
- Updated server driver to the version 2.4.2.
- Security:
- Fixed the high vulnerability (CVE-2026-42035) in the axios library. The library was updated to version 1.15.1.
- Fixed the high vulnerability (CVE-2026-3505) in the bcpg-jdk18on library. The library was updated to version 1.84.0.
- Fixed the high vulnerability (CVE-2026-33671) in the picomatch library. The library was updated to version 2.3.2.
- Fixed the high vulnerability (CVE-2026-33943) in the happy-dom library. The library was updated to version 20.8.8.
- Fixed the high vulnerability (CVE-2026-33228) in the flatted library. The library was updated to version 3.4.2.
### 26.0.1 2026-03-23
- Data Editor:
- Added the Find and Replace functionality for the Data Editor with the ability to find data by matching case, whole word, or using regular expressions.
- Added support for adding, duplicating, deleting, or setting values to NULL in multiple highlighted rows via the Data Editor context menu.
- SQL query generation in the Data Editor is now available for columns containing large object data.
- Improved column drag-and-drop behavior in the Data Editor. Users could drag columns from any area within the header and drop them onto any part of the target column or table body.
- SQL Editor:
- Added fuzzy search to SQL Editor auto-completion for object names. The feature allowed users to find tables and containers even with typos or incorrect letter ordering by matching strings that start with, contain, or resemble the input.
- Fixed data editing for SQL scripts with variables.
- General:
- Added a close button to the right tab when it is the only open tab (ex. Scripts). Users no longer needed to use the main menu to close a single tab.
- Replaced the generic "Something went wrong" message with a specific network error notification when the application cannot connect to the server.
- Null or empty values can now be assigned to the Driver properties for all drivers.
- Fixed an issue where re-selecting an existing SSH key file during connection edits caused problems.
- Fixed the ability to switch tabs in the Data editor using the keyboard.
- Fixed error notification spelling. Thanks to @Malcolm-B-Breaks.
- ClickHouse:
- Updated driver version to 0.9.7.
- Fixed IP address display in the Data Editor by removing the leading slash.
- PostgreSQL: Fixed an error when connecting via URL if the database name contains a hyphen.
- Security:
- Fixed the high vulnerability (CVE-2025-45141) in the tar library. The library was updated to version 7.5.11.
- Fixed the high vulnerability (CVE-2026-27148) in the storybook library. The library was updated to version 10.2.10.
- Fixed the high vulnerability (CVE-2026-27606) in the rollup library. The library was updated to version 4.59.0.
- Fixed the high vulnerability (CVE-2026-27904) in the minimatch library. The library was updated to version 3.1.3.
- Fixed the high vulnerability (CVE-2026-27959) in the koa library. The library was updated to version 2.16.4.
- Fixed the high vulnerability (CVE-2026-32141) in the flatted library. The library was updated to version 4.4.0.
### 26.0.0 2026-03-02
### Changes since 25.3.0:
- Security:
- Enforced complete logout and screen data clearance upon session expiration;
- Fixed the high vulnerability (CVE-2026-25639) in the axios library. The library was updated to version 1.13.5.
- Administration:
- Added support for mapping users to CloudBeaver teams based on LDAP memberOf group membership;
- Change the User list settings in the Administration part to show both active and inactive users by default.
- SQL Editor:
- Added support for parameters and variables in queries. This feature allows queries to be reused by changing parameters at execution time. Enabled by default and configurable in personal preferences;
- Added SQL preview to the Bind parameters/variables dialog to review queries with changed values on the fly;
- Enabled Tab key for autocompletion in the SQL Editor alongside the Enter key;
- Added a new setting in the SQL Editor to highlight spaces, tabs, and other whitespace characters to help users read, debug, and maintain their scripts. It is turned off by default and can be configured in personal preferences;
- Dangerous query confirmation is now shown for all DROP statements, not just for tables.
- Data Editor:
- Added ability to automatically generate INSERT, SELECT, DELETE, and UPDATE statements for the selected values;
- Added undo and redo functionality for cell edits, row operations, and other data modifications. Retains the last 50 actions across the Data Editor, result sets, and related panels;
- Added "Use local formatting" setting. Users can choose how to display numbers and dates: using the OS locale, a custom locale, or keeping values unformatted. This formatting applies only to displayed values. Data in the database remains unchanged;
- Added column pinning to keep key columns (e.g., IDs, names) visible while horizontal scrolling through wide tables;
- Added status indicator icon in the top-left corner with tooltips explaining table editability. Indicates presence of primary keys, read-only connection settings, or read-only columns;
- Added shortcut Ctrl/Cmd + . to cancel operations in Data Editor;
- Fixed application freeze in canceling fetch size requests for large tables.
- Navigator tree:
- Added the ability to duplicate connection configuration in the project navigation tree. The "Clone connection" feature is available in the context menu;
- Added the ability for users to configure the Simple or Advanced view in the Navigation tree for all connections or for each connection separately;
- Added the ability to show table objects, such as columns or keys, in the Navigation tree. The setting is disabled by default and can be turned on in the Navigator settings panel;
- Added the ability to rename connections via context menu in the Navigation Tree;
- Added Connection Info tab to display basic information about the current connection for all users.
- General:
- Added support for long polling as a fallback when WebSockets are unavailable or blocked. Ensures reliable communication for metadata updates and SQL execution;
- Extended browser support to versions up to three years old;
- Redesigned the connection configuration page. Reorganized form fields and sections to provide more input space and reduce visual clutter;
- Expanded pointer target areas for icons in the Navigator, editors, and tabs according to the accessibility standards;
- Fixed a keyboard navigation issue for panels to keep the focus inside;
- Renamed "Database Native" authentication type to "Username/password" in the connection dialog;
- Fixed issue where the missing pg_dump utility caused errors during initialization or deployment updates when PostgreSQL was selected as the inner database.
- Databases:
- ClickHouse:
- Updated driver to version 0.9.5
- Added spatial data support
- Fixed an issue with displaying arrays of UUID, IPv4/IPv6, and Map types
- Fixed JSON data type reading
- Resolved an issue with CTE expressions
- DuckDB:
- Updated driver to version 1.4.4.0;
- Added support for the dollar-quoted string syntax for the SQL Editor
- Oracle: Added a new "Set Username to OS_USER" option in the Misc section of Oracle connection settings. Automatically uses the current database username as the operating system user identifier in session metadata when enabled;
- PostgreSQL: Added DDL display support for PostgreSQL policies.
[We are happy to reward](https://dbeaver.com/help-dbeaver/) our most active contributors every major sprint.
- Fixed the medium vulnerability (CVE-2026-41305) in the postcss library. The library was updated to version 8.5.14.
+1 -13
View File
@@ -1,18 +1,6 @@
# Security Policy
## Supported Versions
Use this section to tell people about which versions of your project are
currently being supported with security updates.
| Version | Supported |
| ------- | --------- |
| 22.x | yes |
| 23.x | yes |
| 24.x | yes |
## Reporting a Vulnerability
Please report (suspected) security vulnerabilities to devops@dbeaver.com.
You will receive a response from us within 48 hours.
Please report (suspected) security vulnerabilities to <security@dbeaver.com>.
If the issue is confirmed, we will release a patch as soon as possible, depending on complexity, but historically, within a few days.
+61
View File
@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.cloudbeaver</groupId>
<artifactId>config-generator</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.13.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<mainClass>io.cloudbeaver.ConfigGenerator</mainClass>
</configuration>
</plugin>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.3.1</version>
<executions>
<execution>
<id>copy-external-config</id>
<phase>process-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.outputDirectory}/config</outputDirectory>
<resources>
<resource>
<directory>${project.basedir}/../../config/template</directory>
<includes>
<include>cloudbeaver-base.conf</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,235 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2026 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;
import com.google.gson.*;
import com.google.gson.reflect.TypeToken;
import java.io.Reader;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
public class ConfigGenerator {
private static final Gson gson = new GsonBuilder()
.setPrettyPrinting()
.disableHtmlEscaping()
.create();
private static final String EMPTY_STRING = "''";
public static void main(String[] args) throws Exception {
String baseConfigPath = System.getProperty("config.base");
if (baseConfigPath == null || baseConfigPath.isEmpty()) {
URL resource = ConfigGenerator.class.getClassLoader().getResource("config/cloudbeaver-base.conf");
if (resource == null) {
System.out.println("Base config path is required");
return;
}
baseConfigPath = resource.toURI().getPath();
if (System.getProperty("os.name").toLowerCase().contains("win")) {
// Fix for Windows in dev mode. Resource URI starts with / (e.g. /C:/some/folder)
// And this breaks Java NIO
if (baseConfigPath.startsWith("/")) {
baseConfigPath = baseConfigPath.substring(1);
}
}
}
String outputPath = System.getProperty("config.output");
if (outputPath == null || outputPath.isEmpty()) {
System.out.println("Output config path is required");
return;
}
String configPatches = System.getProperty("config.patches");
List<String> overrideConfigs = configPatches == null ? List.of() : Arrays.asList(configPatches.split(","));
Map<String, Object> config = readConfigurationFile(baseConfigPath);
System.out.println("Base config loaded");
for (String overrideConfig : overrideConfigs) {
if (Files.exists(Path.of(overrideConfig))) {
System.out.println("Applying override config: " + overrideConfig);
} else {
System.out.println("Override config not found, skipping: " + overrideConfig);
continue;
}
System.out.println("Processing override config: " + overrideConfig);
Map<String, Object> overrideConfigMap = readConfigurationFile(overrideConfig);
System.out.println("Override config loaded: " + overrideConfig);
applyProductConfig(config, overrideConfigMap);
System.out.println("Override config applied: " + overrideConfig);
}
Map<String, Object> finalMap = convertToOutputFormat(config);
System.out.println("Config converted to output format");
writeConfigurationFile(finalMap, outputPath);
System.out.println("Config written to: " + outputPath);
}
private static Map<String, Object> readConfigurationFile(String filePath) throws Exception {
Path path = Path.of(filePath);
if (!Files.exists(path)) {
throw new IllegalArgumentException("Configuration file not found: " + filePath);
}
try (Reader reader = Files.newBufferedReader(path)) {
return gson.fromJson(reader, TypeToken.getParameterized(Map.class, String.class, Object.class).getType());
}
}
private static void applyProductConfig(Map<String, Object> baseConfig, Map<String, Object> productConfig) {
if (productConfig.containsKey("add")) {
Map<String, Object> add = (Map<String, Object>) productConfig.get("add");
deepMergeMap(baseConfig, add);
}
if (productConfig.containsKey("remove")) {
Map<String, Object> remove = (Map<String, Object>) productConfig.get("remove");
deepRemoveMap(baseConfig, remove);
}
}
private static void deepMergeMap(Map<String, Object> target, Map<String, Object> source) {
for (Map.Entry<String, Object> entry : source.entrySet()) {
Object sourceValue = entry.getValue();
Object targetValue = target.get(entry.getKey());
if (sourceValue instanceof Map && targetValue instanceof Map) {
deepMergeMap((Map<String, Object>) targetValue, (Map<String, Object>) sourceValue);
} else {
target.put(entry.getKey(), sourceValue);
}
}
}
private static void deepRemoveMap(Map<String, Object> target, Map<String, Object> source) {
for (Map.Entry<String, Object> entry : source.entrySet()) {
Object sourceValue = entry.getValue();
Object targetValue = target.get(entry.getKey());
if (sourceValue instanceof Map && targetValue instanceof Map) {
deepRemoveMap((Map<String, Object>) targetValue, (Map<String, Object>) sourceValue);
} else {
target.remove(entry.getKey());
}
}
}
private static void writeConfigurationFile(Map<String, Object> map, String filePath) throws Exception {
JsonElement tree = gson.toJsonTree(map);
StringBuilder sb = new StringBuilder();
writeElement(tree, sb, 0);
Files.write(Path.of(filePath), sb.toString().getBytes());
}
private static void writeElement(JsonElement elem, StringBuilder sb, int count) {
String indent = " ";
if (elem.isJsonObject()) {
sb.append("{\n");
JsonObject obj = elem.getAsJsonObject();
var iterator = obj.entrySet().iterator();
while (iterator.hasNext()) {
var entry = iterator.next();
sb.repeat(indent, count + 1).append(entry.getKey()).append(": ");
writeElement(entry.getValue(), sb, count + 1);
if (iterator.hasNext()) {
sb.append(",");
}
sb.append("\n");
}
sb.repeat(indent, count).append("}");
} else if (elem.isJsonArray()) {
sb.append("[\n");
JsonArray array = elem.getAsJsonArray();
for (int i = 0; i < array.size(); i++) {
sb.repeat(indent, count + 1);
writeElement(array.get(i), sb, count + 1);
if (i < array.size() - 1) {
sb.append(",");
}
sb.append("\n");
}
sb.repeat(indent, count).append("]");
} else {
String valueStr = gson.toJson(elem).replace("\n", "\n" + indent);
sb.append(valueStr);
}
}
private static Map<String, Object> convertToOutputFormat(Map<String, Object> map) {
Map<String, Object> result = new LinkedHashMap<>();
for (Map.Entry<String, Object> entry : map.entrySet()) {
result.put(entry.getKey(), convertValue(entry.getValue()));
}
return result;
}
private static Object convertValue(Object value) {
if (value instanceof Map) {
Map<String, Object> map = (Map<String, Object>) value;
if (!map.isEmpty() && map.containsKey("value")) {
if (map.containsKey("env")) {
String env = (String) map.get("env");
Object defValue = map.get("value");
return "${" + env + ":" + formatDefaultValue(defValue) + "}";
} else {
return convertValue(map.get("value"));
}
}
Map<String, Object> result = new LinkedHashMap<>();
for (Map.Entry<String, Object> entry : map.entrySet()) {
result.put(entry.getKey(), convertValue(entry.getValue()));
}
return result;
} else if (value instanceof List) {
List<Object> list = (List<Object>) value;
List<Object> result = new ArrayList<>();
for (Object item : list) {
result.add(convertValue(item));
}
return result;
}
return value;
}
private static String formatDefaultValue(Object value) {
return switch (value) {
case null -> EMPTY_STRING;
case String str -> str.isEmpty() ? EMPTY_STRING : str;
case Boolean b -> value.toString();
case Number number -> {
if (number instanceof Double || number instanceof Float) {
long longVal = number.longValue();
if (longVal == number.doubleValue()) {
yield String.valueOf(longVal);
}
}
yield number.toString();
}
// TODO: handle list elements if needed
default -> value.toString();
};
}
}
-99
View File
@@ -1,99 +0,0 @@
{
server: {
serverPort: "${CLOUDBEAVER_WEB_SERVER_PORT:8978}",
forceHttps: "${CLOUDBEAVER_FORCE_HTTPS:false}",
contentRoot: "web",
driversLocation: "drivers",
sslConfigurationPath:"${CLOUDBEAVER_SSL_CONF_PATH:workspace/.data/ssl-config.xml}",
rootURI: "${CLOUDBEAVER_ROOT_URI:/}",
serviceURI: "/api/",
supportedHosts: [],
productSettings: {
# Global properties
core.theming.theme: "${CLOUDBEAVER_CORE_THEMING_THEME:system}",
core.localization.language: "${CLOUDBEAVER_CORE_LOCALIZATION:en}",
plugin.sql-editor.autoSave: "${CLOUDBEAVER_SQL_EDITOR_AUTOSAVE:true}",
plugin.sql-editor.disabled: "${CLOUDBEAVER_SQL_EDITOR_DISABLED:false}",
# max size of the file that can be uploaded to the editor (in kilobytes)
plugin.sql-editor.maxFileSize: "${CLOUDBEAVER_SQL_EDITOR_MAX_FILE_SIZE:10240}",
plugin.log-viewer.disabled: "${CLOUDBEAVER_LOG_VIEWER_DISABLED:false}",
plugin.log-viewer.logBatchSize: "${CLOUDBEAVER_LOG_VIEWER_LOG_BATCH_SIZE:1000}",
plugin.log-viewer.maxLogRecords: "${CLOUDBEAVER_LOG_VIEWER_MAX_LOG_RECORDS:2000}",
sql.proposals.insert.table.alias: "${CLOUDBEAVER_SQL_PROPOSALS_INSERT_TABLE_ALIAS:PLAIN}",
SQLEditor.ContentAssistant.experimental.mode: "${CLOUDBEAVER_SQL_EDITOR_CONTENT_ASSISTANT_EXPERIMENTAL_MODE:NEW}"
},
expireSessionAfterPeriod: "${CLOUDBEAVER_EXPIRE_SESSION_AFTER_PERIOD:1800000}",
bindSessionToIp: "${CLOUDBEAVER_BIND_SESSION_TO_IP:disable}",
develMode: "${CLOUDBEAVER_DEVEL_MODE:false}",
enableSecurityManager: false,
sm: {
enableBruteForceProtection: "${CLOUDBEAVER_BRUTE_FORCE_PROTECTION_ENABLED:true}",
maxFailedLogin: "${CLOUDBEAVER_MAX_FAILED_LOGINS:10}",
minimumLoginTimeout: "${CLOUDBEAVER_MINIMUM_LOGIN_TIMEOUT:1}",
blockLoginPeriod: "${CLOUDBEAVER_BLOCK_PERIOD:300}",
passwordPolicy: {
minLength: "${CLOUDBEAVER_POLICY_MIN_LENGTH:8}",
requireMixedCase: "${CLOUDBEAVER_POLICY_REQUIRE_MIXED_CASE:true}",
minNumberCount: "${CLOUDBEAVER_POLICY_MIN_NUMBER_COUNT:1}",
minSymbolCount: "${CLOUDBEAVER_POLICY_MIN_SYMBOL_COUNT:0}"
}
},
database: {
driver: "${CLOUDBEAVER_DB_DRIVER:h2_embedded_v2}",
url: "${CLOUDBEAVER_DB_URL:jdbc:h2:${workspace}/.data/cb.h2v2.dat}",
schema: "${CLOUDBEAVER_DB_SCHEMA:''}",
user: "${CLOUDBEAVER_DB_USER:''}",
password: "${CLOUDBEAVER_DB_PASSWORD:''}",
initialDataConfiguration: "${CLOUDBEAVER_DB_INITIAL_DATA:conf/initial-data.conf}",
pool: {
minIdleConnections: "${CLOUDBEAVER_DB_MIN_IDLE_CONNECTIONS:4}",
maxIdleConnections: "${CLOUDBEAVER_DB_MAX_IDLE_CONNECTIONS:10}",
maxConnections: "${CLOUDBEAVER_DB_MAX_CONNECTIONS:100}",
validationQuery: "${CLOUDBEAVER_DB_VALIDATION_QUERY:SELECT 1}"
},
backupEnabled: "${CLOUDBEAVER_DB_BACKUP_ENABLED:true}"
}
},
app: {
anonymousAccessEnabled: "${CLOUDBEAVER_APP_ANONYMOUS_ACCESS_ENABLED:true}",
anonymousUserRole: user,
defaultUserTeam: "${CLOUDBEAVER_APP_DEFAULT_USER_TEAM:user}",
grantConnectionsAccessToAnonymousTeam: "${CLOUDBEAVER_APP_GRANT_CONNECTIONS_ACCESS_TO_ANONYMOUS_TEAM:false}",
supportsCustomConnections: "${CLOUDBEAVER_APP_SUPPORTS_CUSTOM_CONNECTIONS:false}",
showReadOnlyConnectionInfo: "${CLOUDBEAVER_APP_READ_ONLY_CONNECTION_INFO:false}",
systemVariablesResolvingEnabled: "${CLOUDBEAVER_SYSTEM_VARIABLES_RESOLVING_ENABLED:false}",
forwardProxy: "${CLOUDBEAVER_APP_FORWARD_PROXY:false}",
publicCredentialsSaveEnabled: "${CLOUDBEAVER_APP_PUBLIC_CREDENTIALS_SAVE_ENABLED:true}",
adminCredentialsSaveEnabled: "${CLOUDBEAVER_APP_ADMIN_CREDENTIALS_SAVE_ENABLED:true}",
resourceManagerEnabled: "${CLOUDBEAVER_APP_RESOURCE_MANAGER_ENABLED:true}",
resourceQuotas: {
resourceManagerFileSizeLimit: "${CLOUDBEAVER_RESOURCE_QUOTA_RESOURCE_MANAGER_FILE_SIZE_LIMIT:500000}",
sqlMaxRunningQueries: "${CLOUDBEAVER_RESOURCE_QUOTA_SQL_MAX_RUNNING_QUERIES:100}",
sqlResultSetRowsLimit: "${CLOUDBEAVER_RESOURCE_QUOTA_SQL_RESULT_SET_ROWS_LIMIT:100000}",
sqlTextPreviewMaxLength: "${CLOUDBEAVER_RESOURCE_QUOTA_SQL_TEXT_PREVIEW_MAX_LENGTH:4096}",
sqlBinaryPreviewMaxLength: "${CLOUDBEAVER_RESOURCE_QUOTA_SQL_BINARY_PREVIEW_MAX_LENGTH:261120}"
},
enabledAuthProviders: [
"local"
],
disabledBetaFeatures: [
]
}
}
+271
View File
@@ -0,0 +1,271 @@
{
server: {
serverPort: {
env: "CLOUDBEAVER_WEB_SERVER_PORT",
value: 8978
},
forceHttps: {
env: "CLOUDBEAVER_FORCE_HTTPS",
value: false
},
contentRoot: {
env: "CLOUDBEAVER_CONTENT_ROOT",
value: "web"
},
driversLocation: {
env: "CLOUDBEAVER_DRIVERS_LOCATION",
value: "drivers"
},
sslConfigurationPath: {
env: "CLOUDBEAVER_SSL_CONF_PATH",
value: "workspace/.data/ssl-config.xml"
},
rootURI: {
env: "CLOUDBEAVER_ROOT_URI",
value: "/"
},
serviceURI: {
env: "CLOUDBEAVER_SERVICE_URI",
value: "/api/"
},
supportedHosts: [],
productSettings: {
core.theming.theme: {
env: "CLOUDBEAVER_CORE_THEMING_THEME",
value: "system"
},
core.localization.language: {
env: "CLOUDBEAVER_CORE_LOCALIZATION",
value: "en"
},
plugin.sql-editor.autoSave: {
env: "CLOUDBEAVER_SQL_EDITOR_AUTOSAVE",
value: true
},
plugin.sql-editor.disabled: {
env: "CLOUDBEAVER_SQL_EDITOR_DISABLED",
value: false
},
plugin.sql-editor.maxFileSize: {
env: "CLOUDBEAVER_SQL_EDITOR_MAX_FILE_SIZE",
value: 10240
},
plugin.log-viewer.disabled: {
env: "CLOUDBEAVER_LOG_VIEWER_DISABLED",
value: false
},
plugin.log-viewer.logBatchSize: {
env: "CLOUDBEAVER_LOG_VIEWER_LOG_BATCH_SIZE",
value: 1000
},
plugin.log-viewer.maxLogRecords: {
env: "CLOUDBEAVER_LOG_VIEWER_MAX_LOG_RECORDS",
value: 2000
},
sql.proposals.insert.table.alias: {
env: "CLOUDBEAVER_SQL_PROPOSALS_INSERT_TABLE_ALIAS",
value: "PLAIN"
},
SQLEditor.ContentAssistant.experimental.mode: {
env: "CLOUDBEAVER_SQL_EDITOR_CONTENT_ASSISTANT_EXPERIMENTAL_MODE",
value: "NEW"
}
},
expireSessionAfterPeriod: {
env: "CLOUDBEAVER_EXPIRE_SESSION_AFTER_PERIOD",
value: 1800000
},
bindSessionToIp: {
env: "CLOUDBEAVER_BIND_SESSION_TO_IP",
value: "disable"
},
develMode: {
env: "CLOUDBEAVER_DEVEL_MODE",
value: false
},
sm: {
enableBruteForceProtection: {
env: "CLOUDBEAVER_BRUTE_FORCE_PROTECTION_ENABLED",
value: true
},
maxFailedLogin: {
env: "CLOUDBEAVER_MAX_FAILED_LOGINS",
value: 10
},
minimumLoginTimeout: {
env: "CLOUDBEAVER_MINIMUM_LOGIN_TIMEOUT",
value: 1
},
blockLoginPeriod: {
env: "CLOUDBEAVER_BLOCK_PERIOD",
value: 300
},
passwordPolicy: {
minLength: {
env: "CLOUDBEAVER_POLICY_MIN_LENGTH",
value: 8
},
requireMixedCase: {
env: "CLOUDBEAVER_POLICY_REQUIRE_MIXED_CASE",
value: true
},
minNumberCount: {
env: "CLOUDBEAVER_POLICY_MIN_NUMBER_COUNT",
value: 1
},
minSymbolCount: {
env: "CLOUDBEAVER_POLICY_MIN_SYMBOL_COUNT",
value: 0
}
}
},
database: {
driver: {
env: "CLOUDBEAVER_DB_DRIVER",
value: "h2_embedded_v2"
},
url: {
env: "CLOUDBEAVER_DB_URL",
value: "jdbc:h2:${workspace}/.data/cb.h2v2.dat"
},
schema: {
env: "CLOUDBEAVER_DB_SCHEMA",
value: ""
},
user: {
env: "CLOUDBEAVER_DB_USER",
value: ""
},
password: {
env: "CLOUDBEAVER_DB_PASSWORD",
value: ""
},
initialDataConfiguration: {
env: "CLOUDBEAVER_DB_INITIAL_DATA",
value: "conf/initial-data.conf"
},
pool: {
minIdleConnections: {
env: "CLOUDBEAVER_DB_MIN_IDLE_CONNECTIONS",
value: 4
},
maxIdleConnections: {
env: "CLOUDBEAVER_DB_MAX_IDLE_CONNECTIONS",
value: 10
},
maxConnections: {
env: "CLOUDBEAVER_DB_MAX_CONNECTIONS",
value: 100
},
validationQuery: {
env: "CLOUDBEAVER_DB_VALIDATION_QUERY",
value: "SELECT 1"
}
},
backupEnabled: {
env: "CLOUDBEAVER_DB_BACKUP_ENABLED",
value: true
}
}
},
app: {
anonymousAccessEnabled: {
env: "CLOUDBEAVER_APP_ANONYMOUS_ACCESS_ENABLED",
value: true
},
anonymousUserRole: {
env: "CLOUDBEAVER_APP_ANONYMOUS_USER_ROLE",
value: "user"
},
defaultUserTeam: {
env: "CLOUDBEAVER_APP_DEFAULT_USER_TEAM",
value: "user"
},
grantConnectionsAccessToAnonymousTeam: {
env: "CLOUDBEAVER_APP_GRANT_CONNECTIONS_ACCESS_TO_ANONYMOUS_TEAM",
value: false
},
supportsCustomConnections: {
env: "CLOUDBEAVER_APP_SUPPORTS_CUSTOM_CONNECTIONS",
value: false
},
showReadOnlyConnectionInfo: {
env: "CLOUDBEAVER_APP_READ_ONLY_CONNECTION_INFO",
value: false
},
systemVariablesResolvingEnabled: {
env: "CLOUDBEAVER_SYSTEM_VARIABLES_RESOLVING_ENABLED",
value: false
},
forwardProxy: {
env: "CLOUDBEAVER_APP_FORWARD_PROXY",
value: false
},
publicCredentialsSaveEnabled: {
env: "CLOUDBEAVER_APP_PUBLIC_CREDENTIALS_SAVE_ENABLED",
value: true
},
adminCredentialsSaveEnabled: {
env: "CLOUDBEAVER_APP_ADMIN_CREDENTIALS_SAVE_ENABLED",
value: true
},
resourceManagerEnabled: {
env: "CLOUDBEAVER_APP_RESOURCE_MANAGER_ENABLED",
value: true
},
resourceQuotas: {
resourceManagerFileSizeLimit: {
env: "CLOUDBEAVER_RESOURCE_QUOTA_RESOURCE_MANAGER_FILE_SIZE_LIMIT",
value: 500000
},
sqlMaxRunningQueries: {
env: "CLOUDBEAVER_RESOURCE_QUOTA_SQL_MAX_RUNNING_QUERIES",
value: 100
},
sqlResultSetRowsLimit: {
env: "CLOUDBEAVER_RESOURCE_QUOTA_SQL_RESULT_SET_ROWS_LIMIT",
value: 100000
},
sqlTextPreviewMaxLength: {
env: "CLOUDBEAVER_RESOURCE_QUOTA_SQL_TEXT_PREVIEW_MAX_LENGTH",
value: 4096
},
sqlBinaryPreviewMaxLength: {
env: "CLOUDBEAVER_RESOURCE_QUOTA_SQL_BINARY_PREVIEW_MAX_LENGTH",
value: 261120
}
},
enabledAuthProviders: ["local"],
disabledBetaFeatures: []
}
}
+3 -1
View File
@@ -18,7 +18,6 @@ cd ../..
echo "Pull dbeaver platform"
[ ! -d dbeaver ] && git clone --depth 1 https://github.com/dbeaver/dbeaver.git
[ ! -d dbeaver-common ] && git clone --depth 1 https://github.com/dbeaver/dbeaver-common.git
[ ! -d dbeaver-jdbc-libsql ] && git clone --depth 1 https://github.com/dbeaver/dbeaver-jdbc-libsql.git
cd cloudbeaver/deploy
@@ -32,6 +31,9 @@ if [[ "$?" -ne 0 ]] ; then
fi
cd ../../../deploy
echo "Generate cloudbeaver.conf file"
mvn -f ../apps/config-generator compile exec:java -Dconfig.output="cloudbeaver/conf/cloudbeaver.conf"
echo "Copy server packages"
cp -rp ../server/product/web-server/target/products/io.cloudbeaver.product/all/all/all/* ./cloudbeaver/server
+9 -1
View File
@@ -8,7 +8,15 @@ mkdir -p ./cloudbeaver/web
cd ../../cloudbeaver/webapp
yarn install --immutable
cd ./packages/product-default
yarn clear
cd common-react
yarn clear
cd ../common-typescript
yarn clear
cd ../packages/product-default
yarn run bundle
if [[ "$?" -ne 0 ]] ; then
+3 -1
View File
@@ -20,7 +20,6 @@ echo Pull dbeaver platform
IF NOT EXIST dbeaver git clone https://github.com/dbeaver/dbeaver.git
IF NOT EXIST dbeaver-common git clone https://github.com/dbeaver/dbeaver-common.git
IF NOT EXIST dbeaver-jdbc-libsql git clone https://github.com/dbeaver/dbeaver-jdbc-libsql.git
cd cloudbeaver\deploy
@@ -43,6 +42,9 @@ copy ..\config\DefaultConfiguration\GlobalConfiguration\.dbeaver\data-sources.js
move drivers cloudbeaver >NUL
echo Generate cloudbeaver.conf file
call mvn -f ..\apps\config-generator compile exec:java -Dconfig.output="cloudbeaver\conf\cloudbeaver.conf" || goto :error
echo "Build static content"
mkdir .\cloudbeaver\web
+3 -4
View File
@@ -1,4 +1,5 @@
FROM ubuntu:24.04
# Ubuntu 24.04 (Noble Numbat)
FROM ubuntu:noble
MAINTAINER DBeaver Corp, devops@dbeaver.com
@@ -8,8 +9,6 @@ RUN set -eux; \
apt-get update && \
apt-get dist-upgrade -y --no-install-recommends && \
apt-get install -y --no-install-recommends \
# curl required for historical reasons, see https://github.com/adoptium/containers/issues/255
curl \
# java.lang.UnsatisfiedLinkError: libfontmanager.so: libfreetype.so.6: cannot open shared object file: No such file or directory
# java.lang.NoClassDefFoundError: Could not initialize class sun.awt.X11FontManager
# https://github.com/docker-library/openjdk/pull/235#issuecomment-424466077
@@ -31,7 +30,7 @@ RUN set -eux; \
ENV LANG=en_US.UTF-8
ENV JAVA_HOME=/opt/java/openjdk
COPY --from=eclipse-temurin:21 $JAVA_HOME $JAVA_HOME
COPY --from=eclipse-temurin:25-jdk-noble $JAVA_HOME $JAVA_HOME
ENV PATH="${JAVA_HOME}/bin:${PATH}"
RUN set -eux; \
+1 -1
View File
@@ -17,6 +17,7 @@ If Not Defined JAVA_OPTS (
java %JAVA_OPTS% ^
-Dfile.encoding=UTF-8 ^
--enable-native-access=ALL-UNNAMED ^
--add-modules=ALL-DEFAULT ^
--add-opens=java.base/java.io=ALL-UNNAMED ^
--add-opens=java.base/java.lang=ALL-UNNAMED ^
@@ -33,7 +34,6 @@ java %JAVA_OPTS% ^
--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED ^
--add-opens=java.base/sun.nio.ch=ALL-UNNAMED ^
--add-opens=java.base/sun.security.ssl=ALL-UNNAMED ^
--add-opens=java.base/sun.security.action=ALL-UNNAMED ^
--add-opens=java.base/sun.security.util=ALL-UNNAMED ^
--add-opens=java.security.jgss/sun.security.jgss=ALL-UNNAMED ^
--add-opens=java.security.jgss/sun.security.krb5=ALL-UNNAMED ^
+1 -1
View File
@@ -11,6 +11,7 @@ echo "Starting Cloudbeaver Server"
exec java ${JAVA_OPTS} \
-Dfile.encoding=UTF-8 \
--enable-native-access=ALL-UNNAMED \
--add-modules=ALL-DEFAULT \
--add-opens=java.base/java.io=ALL-UNNAMED \
--add-opens=java.base/java.lang=ALL-UNNAMED \
@@ -27,7 +28,6 @@ exec java ${JAVA_OPTS} \
--add-opens=java.base/jdk.internal.misc=ALL-UNNAMED \
--add-opens=java.base/sun.nio.ch=ALL-UNNAMED \
--add-opens=java.base/sun.security.ssl=ALL-UNNAMED \
--add-opens=java.base/sun.security.action=ALL-UNNAMED \
--add-opens=java.base/sun.security.util=ALL-UNNAMED \
--add-opens=java.security.jgss/sun.security.jgss=ALL-UNNAMED \
--add-opens=java.security.jgss/sun.security.krb5=ALL-UNNAMED \
-1
View File
@@ -1,3 +1,2 @@
dbeaver-common
dbeaver-jdbc-libsql
dbeaver
@@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2
Bundle-Vendor: DBeaver Corp
Bundle-Name: Cloudbeaver Web Model
Bundle-SymbolicName: io.cloudbeaver.model.cli;singleton:=true
Bundle-Version: 1.0.10.qualifier
Bundle-Release-Date: 20260518
Bundle-Version: 1.0.16.qualifier
Bundle-Release-Date: 20260817
Bundle-RequiredExecutionEnvironment: JavaSE-21
Bundle-ActivationPolicy: lazy
Require-Bundle: org.jkiss.dbeaver.model.cli;visibility:=reexport
@@ -10,7 +10,7 @@
<relativePath>../</relativePath>
</parent>
<artifactId>io.cloudbeaver.model.cli</artifactId>
<version>1.0.10-SNAPSHOT</version>
<version>1.0.16-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
</project>
@@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2
Bundle-Vendor: DBeaver Corp
Bundle-Name: Cloudbeaver Web Model
Bundle-SymbolicName: io.cloudbeaver.model;singleton:=true
Bundle-Version: 1.0.101.qualifier
Bundle-Release-Date: 20260518
Bundle-Version: 1.0.107.qualifier
Bundle-Release-Date: 20260817
Bundle-RequiredExecutionEnvironment: JavaSE-21
Bundle-ActivationPolicy: lazy
Require-Bundle: org.jkiss.dbeaver.data.gis;visibility:=reexport,
@@ -13,7 +13,7 @@ meta.io.cloudbeaver.model.app.ServletSystemInformationCollector.smDbProductName.
meta.io.cloudbeaver.model.app.ServletSystemInformationCollector.smDbProductVersion.name=Security manager database product version
meta.io.cloudbeaver.model.WebExpertSettingsProperties.readOnly.name = Read-only connection
meta.io.cloudbeaver.model.WebExpertSettingsProperties.autoCommit.name = Auto-commit
meta.io.cloudbeaver.model.WebExpertSettingsProperties.autoCommitMode.name = Auto-commit mode
meta.io.cloudbeaver.model.WebExpertSettingsProperties.keepAliveInterval.name = Keep-alive interval (seconds)
meta.io.cloudbeaver.model.WebExpertSettingsProperties.defaultSchema.name = Default schema
meta.io.cloudbeaver.model.WebExpertSettingsProperties.defaultCatalog.name = Default catalog
@@ -1,5 +1,5 @@
meta.io.cloudbeaver.model.WebExpertSettingsProperties.readOnly.name = Только для чтения
meta.io.cloudbeaver.model.WebExpertSettingsProperties.autoCommit.name = Авто-коммит
meta.io.cloudbeaver.model.WebExpertSettingsProperties.autoCommitMode.name = Авто-коммит
meta.io.cloudbeaver.model.WebExpertSettingsProperties.keepAliveInterval.name = Интервал Keep-alive (в секундах)
meta.io.cloudbeaver.model.WebExpertSettingsProperties.defaultSchema.name = Схема по умолчанию
meta.io.cloudbeaver.model.WebExpertSettingsProperties.defaultCatalog.name = Каталог по умолчанию
@@ -1,4 +1,4 @@
meta.io.cloudbeaver.model.WebExpertSettingsProperties.readOnly.name = Kết nối chỉ đọc
meta.io.cloudbeaver.model.WebExpertSettingsProperties.autoCommit.name = Tự động commit
meta.io.cloudbeaver.model.WebExpertSettingsProperties.autoCommitMode.name = Tự động commit
meta.io.cloudbeaver.model.WebExpertSettingsProperties.keepAliveInterval.name = Giữ kết nối (tính bằng giây)
meta.io.cloudbeaver.model.WebExpertSettingsProperties.keepAliveInterval.description = Không tự động ngắt kết nối
@@ -1,3 +1,3 @@
meta.io.cloudbeaver.model.WebExpertSettingsProperties.autoCommit.name = 自动提交
meta.io.cloudbeaver.model.WebExpertSettingsProperties.autoCommitMode.name = 自动提交
meta.io.cloudbeaver.model.WebExpertSettingsProperties.keepAliveInterval.name = 保持连接 (秒)
meta.io.cloudbeaver.model.WebExpertSettingsProperties.keepAliveInterval.description = 无自动断开连接
+1 -1
View File
@@ -10,7 +10,7 @@
<relativePath>../</relativePath>
</parent>
<artifactId>io.cloudbeaver.model</artifactId>
<version>1.0.101-SNAPSHOT</version>
<version>1.0.107-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
</project>
@@ -77,9 +77,7 @@ public class WebConnectionConfigInputHandler<T extends WebConnectionConfig, C ex
}
dataSource.setFolder(input.getFolder() != null ? registry.getFolder(input.getFolder()) : null);
if (input.isDefaultAutoCommit() != null) {
dataSource.getConnectionConfiguration().getBootstrap().setDefaultAutoCommit(input.isDefaultAutoCommit());
}
dataSource.getConnectionConfiguration().getBootstrap().setDefaultAutoCommit(input.isDefaultAutoCommit());
WebDataSourceUtils.setConnectionConfiguration(
dataSource.getDriver(),
dataSource.getConnectionConfiguration(),
@@ -1,6 +1,6 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2025 DBeaver Corp and others
* Copyright (C) 2010-2026 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.
@@ -17,6 +17,7 @@
package io.cloudbeaver;
import io.cloudbeaver.model.session.WebSession;
import io.cloudbeaver.utils.WebEventUtils;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.model.DBPDataSourceContainer;
import org.jkiss.dbeaver.model.DBPEvent;
@@ -46,7 +47,7 @@ public class WebDataSourceConnectEventListener implements DBPEventListener {
new WSDataSourceConnectEvent(
container.getProject().getId(),
container.getId(),
webSession.getSessionId(),
WebEventUtils.getSmSessionId(webSession),
webSession.getUserId()
)
);
@@ -30,6 +30,7 @@ import org.jkiss.dbeaver.model.app.DBPProject;
import org.jkiss.dbeaver.model.connection.DBPConnectionConfiguration;
import org.jkiss.dbeaver.model.connection.DBPDriver;
import org.jkiss.dbeaver.model.net.DBWNetworkProfile;
import org.jkiss.dbeaver.model.net.DBWNetworkProfileManager;
import org.jkiss.dbeaver.model.preferences.DBPPreferenceStore;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.secret.DBSSecretController;
@@ -258,28 +259,12 @@ public class WebGlobalProjectRegistryProxy implements DBPDataSourceRegistry, Dat
dataSourceRegistry.removeSavedFilter(filterName);
}
@Nullable
@Override
public DBWNetworkProfile getNetworkProfile(@Nullable String source, @NotNull String name) {
return dataSourceRegistry.getNetworkProfile(source, name);
}
@NotNull
@Override
public List<DBWNetworkProfile> getNetworkProfiles() {
public DBWNetworkProfileManager getNetworkProfiles() {
return dataSourceRegistry.getNetworkProfiles();
}
@Override
public void updateNetworkProfile(@NotNull DBWNetworkProfile profile) {
dataSourceRegistry.updateNetworkProfile(profile);
}
@Override
public void removeNetworkProfile(@NotNull DBWNetworkProfile profile) {
dataSourceRegistry.removeNetworkProfile(profile);
}
@Nullable
@Override
public DBAAuthProfile getAuthProfile(@NotNull String id) {
@@ -377,6 +362,12 @@ public class WebGlobalProjectRegistryProxy implements DBPDataSourceRegistry, Dat
return dataSourceRegistry.getPreferenceStore();
}
@Override
public void initializeDataSources() {
dataSourceRegistry.initializeDataSources();
}
@Nullable
@Override
public DataSourceParseResults loadDataSources(
@NotNull List<DBPDataSourceConfigurationStorage> storages,
@@ -392,6 +383,7 @@ public class WebGlobalProjectRegistryProxy implements DBPDataSourceRegistry, Dat
dataSourceRegistry.saveDataSources();
}
@NotNull
@Override
public DataSourceConfigurationManager getConfigurationManager() {
return dataSourceRegistry.getConfigurationManager();
@@ -1,6 +1,6 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2024 DBeaver Corp and others
* Copyright (C) 2010-2026 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.
@@ -23,8 +23,8 @@ import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.DBPDataSourceContainer;
import org.jkiss.dbeaver.model.DBPEvent;
import org.jkiss.dbeaver.model.app.DBPDataSourceRegistry;
import org.jkiss.dbeaver.model.auth.SMObjectType;
import org.jkiss.dbeaver.model.rm.RMProject;
import org.jkiss.dbeaver.model.security.SMObjectType;
import org.jkiss.dbeaver.model.security.user.SMObjectPermissions;
import java.util.Set;
@@ -1,6 +1,6 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2025 DBeaver Corp and others
* Copyright (C) 2010-2026 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.
@@ -29,11 +29,11 @@ import org.jkiss.dbeaver.model.DBPDataSourceContainer;
import org.jkiss.dbeaver.model.DBPObjectSettingsProvider;
import org.jkiss.dbeaver.model.app.DBPDataSourceRegistry;
import org.jkiss.dbeaver.model.app.DBPDataSourceRegistryCache;
import org.jkiss.dbeaver.model.auth.SMObjectType;
import org.jkiss.dbeaver.model.navigator.DBNModel;
import org.jkiss.dbeaver.model.rm.RMProject;
import org.jkiss.dbeaver.model.rm.RMUtils;
import org.jkiss.dbeaver.model.security.SMControllerUtils;
import org.jkiss.dbeaver.model.security.SMObjectType;
import org.jkiss.dbeaver.model.websocket.event.datasource.WSDataSourceEvent;
import org.jkiss.dbeaver.model.websocket.event.datasource.WSDataSourceProperty;
import org.jkiss.dbeaver.registry.DataSourceDescriptor;
@@ -103,7 +103,7 @@ public class WebSessionProjectImpl extends WebProjectImpl implements DBPAdaptabl
return projectSettings;
}
@Nullable
@NotNull
@Override
public DBNModel getNavigatorModel() {
return webSession.getNavigatorModel();
@@ -252,14 +252,14 @@ public class WebSessionProjectImpl extends WebProjectImpl implements DBPAdaptabl
}
case WSDataSourceEvent.UPDATED -> {
if (event.getProperty() == WSDataSourceProperty.CONFIGURATION) {
WebDataSourceUtils.disconnectDataSource(webSession, ds);
WebDataSourceUtils.disconnectDataSource(webSession, ds, true);
}
if (event.getProperty() != WSDataSourceProperty.INTERNAL) {
sendDataSourceUpdatedEvent = true;
}
}
case WSDataSourceEvent.DELETED -> {
WebDataSourceUtils.disconnectDataSource(webSession, ds);
WebDataSourceUtils.disconnectDataSource(webSession, ds, false);
if (registry instanceof DBPDataSourceRegistryCache dsrc) {
dsrc.removeDataSourceFromList(ds);
}
@@ -345,7 +345,7 @@ public class WebSessionProjectImpl extends WebProjectImpl implements DBPAdaptabl
@NotNull
private WebConnectionInfo closeAndDeleteConnection(@NotNull WebConnectionInfo connectionInfo) throws DBWebException {
DBPDataSourceContainer dataSourceContainer = connectionInfo.getDataSourceContainer();
WebDataSourceUtils.disconnectDataSource(webSession, dataSourceContainer);
WebDataSourceUtils.disconnectDataSource(webSession, dataSourceContainer, false);
DBPDataSourceRegistry registry = getDataSourceRegistry();
registry.removeDataSource(dataSourceContainer);
removeConnection(dataSourceContainer);
@@ -357,6 +357,13 @@ public class WebSessionProjectImpl extends WebProjectImpl implements DBPAdaptabl
return getInputConfigHandler(configInput).createDataSourceContainer();
}
public void updateDataSourceContainerFromInput(
@NotNull WebConnectionConfig configInput,
@NotNull DataSourceDescriptor dataSource
) throws DBWebException {
getInputConfigHandler(configInput).updateDataSource(dataSource);
}
@NotNull
public WebConnectionConfig getConnectionConfigInput(@Nullable Map<String, Object> configMap) {
return new WebConnectionConfig(configMap == null ? Map.of() : configMap);
@@ -69,6 +69,13 @@ public interface SMAuthProviderExternal<AUTH_SESSION extends SMSession> extends
@NotNull WebUser user,
boolean selfIdentity) throws DBException;
/**
* Whether a user that is not found should be provisioned (auto-created) on external login.
*/
default boolean isAutoUserProvisioningEnabled(@Nullable SMAuthProviderCustomConfiguration providerConfig) {
return true;
}
/**
* Make some post authentication actions
*/
@@ -0,0 +1,62 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2026 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.model;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.utils.CommonUtils;
public enum AutoCommitMode {
DEFAULT("Default", null),
AUTO_COMMIT("Auto commit", true),
MANUAL_COMMIT("Manual commit", false);
private final String title;
private final Boolean value;
AutoCommitMode(@NotNull String title, @Nullable Boolean value) {
this.title = title;
this.value = value;
}
@NotNull
@Override
public String toString() {
return title;
}
@Nullable
public Boolean getValue() {
return value;
}
@NotNull
public static AutoCommitMode fromValue(@Nullable Boolean value) {
if (value == null) {
return DEFAULT;
}
return value ? AUTO_COMMIT : MANUAL_COMMIT;
}
@Nullable
public static Boolean from(@Nullable String mode) {
if (CommonUtils.isEmpty(mode)) {
return null;
}
return valueOf(mode).getValue();
}
}
@@ -65,6 +65,7 @@ public class WebConnectionConfig {
private Boolean defaultAutoCommit;
private String defaultCatalogName;
private String defaultSchemaName;
private String connectionType;
@NotNull
private Map<String, String> defaultUserPreferences = new LinkedHashMap<>();
@@ -102,8 +103,14 @@ public class WebConnectionConfig {
expertSettingsValues != null ? expertSettingsValues : params, WebExpertSettingsProperties.PROP_KEEP_ALIVE_INTERVAL, -1);
readOnly = JSONUtils.getBoolean(
expertSettingsValues != null ? expertSettingsValues : params, WebExpertSettingsProperties.PROP_READ_ONLY);
defaultAutoCommit = JSONUtils.getBoolean(
expertSettingsValues != null ? expertSettingsValues : params, WebExpertSettingsProperties.PROP_AUTO_COMMIT, true);
if (expertSettingsValues != null) {
defaultAutoCommit = AutoCommitMode.from(
JSONUtils.getString(expertSettingsValues, WebExpertSettingsProperties.PROP_AUTO_COMMIT_MODE));
} else {
defaultAutoCommit = JSONUtils.getBoolean(params, WebExpertSettingsProperties.PROP_AUTO_COMMIT, true);
}
defaultCatalogName = JSONUtils.getString(
expertSettingsValues != null ? expertSettingsValues : params, WebExpertSettingsProperties.PROP_DEFAULT_CATALOG);
defaultSchemaName = JSONUtils.getString(
@@ -120,6 +127,7 @@ public class WebConnectionConfig {
for (Map<String, Object> nhc : JSONUtils.getObjectList(params, "networkHandlersConfig")) {
networkHandlersConfig.add(new WebNetworkHandlerConfigInput(nhc));
}
connectionType = JSONUtils.getString(params, "connectionType");
}
@Property
@@ -381,4 +389,13 @@ public class WebConnectionConfig {
public void setDefaultUserPreferences(@NotNull Map<String, String> defaultUserPreferences) {
this.defaultUserPreferences = defaultUserPreferences;
}
@Nullable
public String getConnectionType() {
return connectionType;
}
public void setConnectionType(@Nullable String connectionType) {
this.connectionType = connectionType;
}
}
@@ -39,7 +39,8 @@ import org.jkiss.dbeaver.model.connection.DBPDriverConfigurationType;
import org.jkiss.dbeaver.model.impl.auth.AuthModelDatabaseNative;
import org.jkiss.dbeaver.model.meta.Property;
import org.jkiss.dbeaver.model.navigator.DBNBrowseSettings;
import org.jkiss.dbeaver.model.navigator.DBNDataSource;
import org.jkiss.dbeaver.model.navigator.DBNDatabaseNode;
import org.jkiss.dbeaver.model.navigator.DBNUtils;
import org.jkiss.dbeaver.model.preferences.DBPPreferenceStore;
import org.jkiss.dbeaver.model.preferences.DBPPropertyDescriptor;
import org.jkiss.dbeaver.model.preferences.DBPPropertySource;
@@ -213,7 +214,8 @@ public class WebConnectionInfo {
@Property
public String getNodePath() {
return DBNDataSource.makeDataSourceItemPath(dataSourceContainer);
DBNDatabaseNode dsNode = DBNUtils.getNodeByObject(dataSourceContainer);
return dsNode == null ? null : dsNode.getNodeUri();
}
@Property
@@ -465,7 +467,7 @@ public class WebConnectionInfo {
@Property
public Map<String, Object> getExpertSettingsValues() {
Map<String, Object> expertSettings = new LinkedHashMap<>();
expertSettings.put(WebExpertSettingsProperties.PROP_AUTO_COMMIT, isAutocommit());
expertSettings.put(WebExpertSettingsProperties.PROP_AUTO_COMMIT_MODE, AutoCommitMode.fromValue(isAutocommit()));
expertSettings.put(WebExpertSettingsProperties.PROP_KEEP_ALIVE_INTERVAL, getKeepAliveInterval());
expertSettings.put(WebExpertSettingsProperties.PROP_READ_ONLY, isReadOnly());
expertSettings.put(WebExpertSettingsProperties.PROP_DEFAULT_CATALOG, getDefaultCatalogName());
@@ -539,12 +541,9 @@ public class WebConnectionInfo {
}
@Property
public boolean isAutocommit() {
Boolean isAutoCommit = dataSourceContainer.getConnectionConfiguration().getBootstrap().getDefaultAutoCommit();
if (isAutoCommit == null) {
return true;
}
return isAutoCommit;
@Nullable
public Boolean isAutocommit() {
return dataSourceContainer.getConnectionConfiguration().getBootstrap().getDefaultAutoCommit();
}
@Property
@@ -584,6 +583,11 @@ public class WebConnectionInfo {
return tools;
}
@NotNull
public String getConnectionType() {
return dataSourceContainer.getConnectionConfiguration().getConnectionType().getId();
}
/**
* Updates param that checks whether credentials were saved only in session.
*/
@@ -591,4 +595,13 @@ public class WebConnectionInfo {
this.credentialsSavedInSession = credentialsSavedInSession;
}
/**
* Database-dependent driver configuration used to drive data import
*/
@Property
@NotNull
public WebDriverConfiguration getDriverConfiguration() {
return new WebDriverConfiguration(dataSourceContainer);
}
}
@@ -0,0 +1,58 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2026 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.model;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.model.meta.Property;
/**
* Generic id/name/description dictionary value.
*/
public class WebDictionaryValueInfo {
@NotNull
private final String id;
@NotNull
private final String name;
@Nullable
private final String description;
public WebDictionaryValueInfo(@NotNull String id, @NotNull String name, @Nullable String description) {
this.id = id;
this.name = name;
this.description = description;
}
@Property
@NotNull
public String getId() {
return id;
}
@Property
@NotNull
public String getName() {
return name;
}
@Property
@Nullable
public String getDescription() {
return description;
}
}
@@ -0,0 +1,75 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2026 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.model;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.model.DBPDataSource;
import org.jkiss.dbeaver.model.DBPDataSourceContainer;
import org.jkiss.dbeaver.model.DBUtils;
import org.jkiss.dbeaver.model.meta.Property;
import org.jkiss.dbeaver.model.sql.SQLDialectInsertReplaceMethod;
import org.jkiss.dbeaver.model.sql.SQLDialectMetadata;
import org.jkiss.dbeaver.model.struct.DBSDataBulkLoader;
import org.jkiss.utils.CommonUtils;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
public class WebDriverConfiguration {
@NotNull
private final DBPDataSourceContainer dataSourceContainer;
public WebDriverConfiguration(@NotNull DBPDataSourceContainer dataSourceContainer) {
this.dataSourceContainer = dataSourceContainer;
}
/**
* 'On duplicate key' replace methods supported by this connection's SQL dialect
*/
@Property
@NotNull
public List<WebDictionaryValueInfo> getSupportedInsertReplaceMethods() {
SQLDialectMetadata dialect = dataSourceContainer.getDriver().getScriptDialect();
List<SQLDialectInsertReplaceMethod> replaceMethods = dialect.getSupportedInsertReplaceMethodsDescriptors();
if (CommonUtils.isEmpty(replaceMethods)) {
return Collections.emptyList();
}
return replaceMethods.stream()
.map(method -> new WebDictionaryValueInfo(method.getId(), method.getLabel(), method.getDescription()))
.collect(Collectors.toList());
}
/**
* Whether the connection's database supports bulk load during data import
*/
@Property
public boolean isSupportsBulkLoad() {
DBPDataSource dataSource = dataSourceContainer.getDataSource();
return dataSource != null && DBUtils.getAdapter(DBSDataBulkLoader.class, dataSource) != null;
}
/**
* Whether the connection's database supports transaction
*/
@Property
public boolean isSupportsTransactions() {
DBPDataSource dataSource = dataSourceContainer.getDataSource();
return dataSource != null && dataSource.getInfo().supportsTransactions();
}
}
@@ -1,3 +1,19 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2026 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.model;
import org.jkiss.code.NotNull;
@@ -5,6 +21,7 @@ import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.model.DBPObject;
import org.jkiss.dbeaver.model.connection.DBPDriver;
import org.jkiss.dbeaver.model.connection.DBPDriverConstants;
import org.jkiss.dbeaver.model.meta.IPropertyValueListProvider;
import org.jkiss.dbeaver.model.meta.IPropertyValueValidator;
import org.jkiss.dbeaver.model.meta.Property;
import org.jkiss.utils.CommonUtils;
@@ -15,6 +32,7 @@ import org.jkiss.utils.CommonUtils;
public class WebExpertSettingsProperties implements DBPObject {
public static final String PROP_READ_ONLY = "readOnly";
public static final String PROP_AUTO_COMMIT = "autocommit";
public static final String PROP_AUTO_COMMIT_MODE = "autoCommitMode";
public static final String PROP_KEEP_ALIVE_INTERVAL = "keepAliveInterval";
public static final String PROP_DEFAULT_CATALOG = "defaultCatalogName";
public static final String PROP_DEFAULT_SCHEMA = "defaultSchemaName";
@@ -30,9 +48,15 @@ public class WebExpertSettingsProperties implements DBPObject {
return 0;
}
@Property(order = 2, id = PROP_AUTO_COMMIT, visibleIf = AutoCommitFieldValidator.class)
public boolean isAutoCommit() {
return true;
@NotNull
@Property(
order = 2,
id = PROP_AUTO_COMMIT_MODE,
visibleIf = AutoCommitFieldValidator.class,
listProvider = AutoCommitListProvider.class
)
public AutoCommitMode isAutoCommitMode() {
return AutoCommitMode.DEFAULT;
}
@Property(order = 3, id = PROP_READ_ONLY, visibleIf = ReadOnlyFieldValidator.class)
@@ -40,11 +64,13 @@ public class WebExpertSettingsProperties implements DBPObject {
return false;
}
@Nullable
@Property(order = 4, id = PROP_DEFAULT_CATALOG, visibleIf = DefaultCatalogFieldVisibleValidator.class)
public String getDefaultCatalog() {
return null;
}
@Nullable
@Property(order = 5, id = PROP_DEFAULT_SCHEMA, visibleIf = DefaultSchemaFieldVisibleValidator.class)
public String getDefaultSchema() {
return null;
@@ -85,4 +111,18 @@ public class WebExpertSettingsProperties implements DBPObject {
return CommonUtils.toBoolean(object.driver.getDriverParameter(DBPDriverConstants.PARAM_SUPPORTS_SCHEMA_SELECTION), true);
}
}
public static class AutoCommitListProvider implements IPropertyValueListProvider<WebExpertSettingsProperties> {
@Override
public boolean allowCustomValue() {
return false;
}
@Nullable
@Override
public Object[] getPossibleValues(@Nullable WebExpertSettingsProperties object) {
return AutoCommitMode.values();
}
}
}
@@ -37,7 +37,6 @@ import org.jkiss.dbeaver.model.impl.app.BaseApplicationImpl;
import org.jkiss.dbeaver.model.impl.app.BaseWorkspaceImpl;
import org.jkiss.dbeaver.model.rm.RMController;
import org.jkiss.dbeaver.model.secret.DBSSecretController;
import org.jkiss.dbeaver.model.websocket.event.WSEventController;
import org.jkiss.dbeaver.runtime.IVariableResolver;
import org.jkiss.dbeaver.utils.GeneralUtils;
import org.jkiss.dbeaver.utils.RuntimeUtils;
@@ -89,12 +88,6 @@ public abstract class BaseServletApplication extends BaseApplicationImpl impleme
return new SharedFileLockManager(getApplicationInstanceId());
}
@Nullable
@Override
public Path getDefaultWorkingFolder() {
return getServerConfigurationController().getWorkspacePath();
}
@Override
public boolean isHeadlessMode() {
return true;
@@ -192,20 +185,20 @@ public abstract class BaseServletApplication extends BaseApplicationImpl impleme
@SuppressWarnings("unchecked")
public static void patchConfigurationWithProperties(
Map<String, Object> configProps, IVariableResolver varResolver
@NotNull Map<String, Object> configProps,
@NotNull IVariableResolver varResolver
) {
for (Map.Entry<String, Object> entry : configProps.entrySet()) {
Object propValue = entry.getValue();
if (propValue instanceof String) {
entry.setValue(GeneralUtils.replaceVariables((String) propValue, varResolver));
if (propValue instanceof String strValue) {
entry.setValue(GeneralUtils.replaceVariables(strValue, varResolver));
} else if (propValue instanceof Map) {
patchConfigurationWithProperties((Map<String, Object>) propValue, varResolver);
} else if (propValue instanceof List) {
List value = (List) propValue;
} else if (propValue instanceof List value) {
for (int i = 0; i < value.size(); i++) {
Object colItem = value.get(i);
if (colItem instanceof String) {
value.set(i, GeneralUtils.replaceVariables((String) colItem, varResolver));
if (colItem instanceof String strItem) {
value.set(i, GeneralUtils.replaceVariables(strItem, varResolver));
} else if (colItem instanceof Map) {
patchConfigurationWithProperties((Map<String, Object>) colItem, varResolver);
}
@@ -218,6 +211,8 @@ public abstract class BaseServletApplication extends BaseApplicationImpl impleme
@Override
public Object start(IApplicationContext context) {
initializeApplicationServices();
setWorkspacePath(getServerConfigurationController().getWorkspacePath());
try {
startServer();
} catch (Exception e) {
@@ -255,27 +250,17 @@ public abstract class BaseServletApplication extends BaseApplicationImpl impleme
}
@NotNull
@Override
public Path getWorkspaceDirectory() {
return getServerConfigurationController().getWorkspacePath();
}
public String getApplicationId() {
try {
return getApplicationInstanceId();
} catch (DBException e) {
return null;
// Fallback to hash code
return getClass().getSimpleName() + "#" + hashCode();
}
}
@NotNull
@Override
public WSEventController getEventController() {
return null;
}
public abstract ServletServerConfigurationController getServerConfigurationController();
public abstract ServletServerConfigurationController<?> getServerConfigurationController();
@Override
public boolean isEnvironmentVariablesAccessible() {
@@ -1,6 +1,6 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2024 DBeaver Corp and others
* Copyright (C) 2010-2026 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.
@@ -53,9 +53,6 @@ public interface ServletApplication extends DBPApplication {
@NotNull
Path getDataDirectory(boolean create);
@NotNull
Path getWorkspaceDirectory();
@NotNull
Path getHomeDirectory();
@@ -1,6 +1,6 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2025 DBeaver Corp and others
* Copyright (C) 2010-2026 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.
@@ -23,6 +23,7 @@ import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.DBException;
public interface ServletAuthApplication extends ServletApplication {
@NotNull
ServletAuthConfiguration getAuthConfiguration();
@Nullable
@@ -115,13 +115,6 @@ public class DBNResourceManagerProject extends DBNAbstractResourceManagerNode {
return ((DBNResourceManagerRoot) getParentNode()).getResourceController();
}
@NotNull
@Deprecated
@Override
public String getNodeItemPath() {
return getParentNode().getNodeItemPath() + "/" + getName();
}
@Nullable
@Override
public DBNNode refreshNode(@NotNull DBRProgressMonitor monitor, @Nullable Object source) throws DBException {
@@ -160,13 +160,6 @@ public class DBNResourceManagerResource extends DBNAbstractResourceManagerNode {
throw new DBException("Can't detect resource root node");
}
@NotNull
@Deprecated
@Override
public String getNodeItemPath() {
return getParentNode().getNodeItemPath() + "/" + getNodeDisplayName();
}
@Nullable
@Override
public DBNNode refreshNode(@NotNull DBRProgressMonitor monitor, @Nullable Object source) throws DBException {
@@ -115,14 +115,6 @@ public class DBNResourceManagerRoot extends DBNNode implements DBPHiddenObject,
return projects;
}
@NotNull
@Deprecated
@Override
public String getNodeItemPath() {
// Path doesn't include project name
return NodePathType.ext.getPrefix() + getNodeDisplayName();
}
@Nullable
@Override
public DBNNode refreshNode(@NotNull DBRProgressMonitor monitor, @Nullable Object source) throws DBException {
@@ -1,6 +1,6 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2025 DBeaver Corp and others
* Copyright (C) 2010-2026 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.
@@ -67,8 +67,7 @@ public abstract class BaseLocalResourceController implements RMController {
@Nullable
@Override
public RMProject getProject(@NotNull String projectId, boolean readResources, boolean readProperties)
throws DBException {
public RMProject getProject(@NotNull String projectId, boolean readResources, boolean readProperties) throws DBException {
RMProject project = makeProjectFromId(projectId, true);
if (project == null) {
return null;
@@ -110,8 +109,7 @@ public abstract class BaseLocalResourceController implements RMController {
}
@Override
public String getProjectsDataSources(@NotNull String projectId, @Nullable String[] dataSourceIds)
throws DBException {
public String getProjectsDataSources(@NotNull String projectId, @Nullable String[] dataSourceIds) throws DBException {
DBPProject projectMetadata = getWebProject(projectId, false);
return doFileReadOperation(
projectId,
@@ -33,26 +33,29 @@ import org.jkiss.dbeaver.model.app.DBPDataSourceRegistry;
import org.jkiss.dbeaver.model.app.DBPWorkspace;
import org.jkiss.dbeaver.model.auth.SMCredentials;
import org.jkiss.dbeaver.model.auth.SMCredentialsProvider;
import org.jkiss.dbeaver.model.auth.SMObjectType;
import org.jkiss.dbeaver.model.fs.lock.LockManager;
import org.jkiss.dbeaver.model.fs.lock.LockOptions;
import org.jkiss.dbeaver.model.fs.lock.LockTarget;
import org.jkiss.dbeaver.model.impl.app.BaseProjectImpl;
import org.jkiss.dbeaver.model.impl.auth.SessionContextImpl;
import org.jkiss.dbeaver.model.navigator.DBNLocalFolder;
import org.jkiss.dbeaver.model.net.DBWNetworkProfile;
import org.jkiss.dbeaver.model.rm.*;
import org.jkiss.dbeaver.model.security.SMAdminController;
import org.jkiss.dbeaver.model.security.SMObjectType;
import org.jkiss.dbeaver.model.sql.DBQuotaException;
import org.jkiss.dbeaver.model.websocket.event.MessageType;
import org.jkiss.dbeaver.model.websocket.event.WSSessionLogUpdatedEvent;
import org.jkiss.dbeaver.model.websocket.event.datasource.WSDataSourceEvent;
import org.jkiss.dbeaver.model.websocket.event.datasource.WSDataSourceProperty;
import org.jkiss.dbeaver.model.websocket.event.datasource.WSDatasourceFolderEvent;
import org.jkiss.dbeaver.model.websocket.event.datasource.WSNetworkProfileEvent;
import org.jkiss.dbeaver.registry.DataSourceDescriptor;
import org.jkiss.dbeaver.registry.DataSourceParseResults;
import org.jkiss.dbeaver.registry.ResourceTypeDescriptor;
import org.jkiss.dbeaver.registry.ResourceTypeRegistry;
import org.jkiss.dbeaver.runtime.DBWorkbench;
import org.jkiss.dbeaver.utils.GeneralUtils;
import org.jkiss.utils.CommonUtils;
import org.jkiss.utils.IOUtils;
import org.jkiss.utils.Pair;
@@ -283,7 +286,7 @@ public class LocalResourceController extends BaseLocalResourceController {
throw new DBException("Error creating shared project path", e);
}
}
validateResourcePath(name);
GeneralUtils.validateResourceNameUnconditionally(name);
validateProjectName(null, name);
var projectPath = sharedProjectsPath.resolve(name);
if (Files.exists(projectPath)) {
@@ -406,8 +409,13 @@ public class LocalResourceController extends BaseLocalResourceController {
registry::createDataSource
)
);
Map<String, DBWNetworkProfile> oldNetworkProfiles = registry.getNetworkProfiles().getProfiles().stream()
.collect(Collectors.toMap(
DBWNetworkProfile::getProfileId,
p -> p
));
DataSourceParseResults parseResults = super.updateProjectDataSourcesConfig(projectId, configuration, dataSourceIds);
sendDataSourcesConfigUpdatedEvent(registry, oldDataSources, parseResults);
sendConfigUpdatedEvent(registry, oldDataSources, oldNetworkProfiles, parseResults);
return parseResults != null;
}
@@ -500,14 +508,48 @@ public class LocalResourceController extends BaseLocalResourceController {
return DBNLocalFolder.makeLocalFolderItemPath(projectId, folderPath);
}
private void sendDataSourcesConfigUpdatedEvent(
private void sendConfigUpdatedEvent(
@NotNull DBPDataSourceRegistry registry,
@NotNull Map<String, DataSourceDescriptor> oldDataSources,
@NotNull Map<String, DBWNetworkProfile> oldNetworkProfiles,
@Nullable DataSourceParseResults parseResults
) {
if (parseResults == null || credentialsProvider.getActiveUserCredentials() == null || oldDataSources.isEmpty()) {
if (parseResults == null || credentialsProvider.getActiveUserCredentials() == null) {
return;
}
boolean profilesChanged = !parseResults.removedProfiles.isEmpty();
// We don't need to check for updated profiles if there are already added or removed profiles
if (!profilesChanged) {
for (DBWNetworkProfile updatedProfile : parseResults.updatedProfiles) {
if (oldNetworkProfiles.containsKey(updatedProfile.getProfileId())) {
DBWNetworkProfile oldProfile = oldNetworkProfiles.get(updatedProfile.getProfileId());
if (!oldProfile.equalConfigurations(updatedProfile)) {
profilesChanged = true;
break;
}
} else {
// profile was added
profilesChanged = true;
break;
}
}
}
if (profilesChanged) {
ServletAppUtils.getServletApplication().getEventController().addEvent(
WSNetworkProfileEvent.update(
credentialsProvider.getActiveUserCredentials().getSmSessionId(),
credentialsProvider.getActiveUserCredentials().getUserId(),
registry.getProject().getId()
)
);
}
if (oldDataSources.isEmpty()) {
return;
}
List<String> updatedConfigurationDataSourceIds = new ArrayList<>();
List<String> updatedNameDataSourceIds = new ArrayList<>();
List<String> updatedInternalConfigurationDataSourceIds = new ArrayList<>();
@@ -611,7 +653,6 @@ public class LocalResourceController extends BaseLocalResourceController {
)
);
}
}
@NotNull
@@ -1106,6 +1147,7 @@ public class LocalResourceController extends BaseLocalResourceController {
RMProjectName project = WebRMUtils.parseProjectName(projectId);
RMProjectType type = project.getType();
String projectName = project.getName();
GeneralUtils.validateResourceNameUnconditionally(projectName);
switch (type) {
case GLOBAL:
if (!projectName.equals(globalProjectName)) {
@@ -123,6 +123,16 @@ public abstract class BaseWebSession extends AbstractSessionPersistent {
}
}
public void migrateEventHandlersTo(@NotNull BaseWebSession target) {
synchronized (sessionEventHandlers) {
for (CBWebSessionEventHandler handler : sessionEventHandlers) {
handler.migrateToSession(target);
target.addEventHandler(handler);
}
sessionEventHandlers.clear();
}
}
public boolean updateSMSession(SMAuthInfo smAuthInfo) throws DBException {
return userContext.refresh(smAuthInfo);
}
@@ -209,7 +219,7 @@ public abstract class BaseWebSession extends AbstractSessionPersistent {
}
private void cleanUpSession(boolean sendSessionExpiredEvent) {
application.getEventController().addEvent(new WSEventDeleteTempFile(getSessionId()));
application.getEventController().addEvent(new WSEventDeleteTempFile(getUserContext().getSmSessionId()));
synchronized (sessionEventHandlers) {
var sessionExpiredEvent = new WSSessionExpiredEvent();
for (CBWebSessionEventHandler sessionEventHandler : sessionEventHandlers) {
@@ -313,7 +313,7 @@ public class WebSession extends BaseWebSession
loadProjects();
this.navigatorModel = new DBNModel(DBWorkbench.getPlatform(), getWorkspace().getProjects());
this.navigatorModel = new DBNModel(DBWorkbench.getPlatform(), getWorkspace());
this.navigatorModel.setModelAuthContext(getWorkspace().getAuthContext());
this.navigatorModel.initialize();
@@ -1,6 +1,6 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2024 DBeaver Corp and others
* Copyright (C) 2010-2026 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.
@@ -68,6 +68,13 @@ public class WebSessionEventsFilter {
}
}
public void migrateTo(@NotNull WebSessionEventsFilter target) {
synchronized (target.subscribedProjectIds) {
target.subscribedEventTopics.addAll(this.subscribedEventTopics);
target.subscribedProjectIds.addAll(this.subscribedProjectIds);
}
}
public boolean isEventAllowed(WSEvent event) {
if (event.isForceProcessed()) {
return true;
@@ -27,6 +27,7 @@ import org.jkiss.dbeaver.model.DBPImage;
import org.jkiss.dbeaver.model.app.DBPPlatform;
import org.jkiss.dbeaver.model.app.DBPProject;
import org.jkiss.dbeaver.model.app.DBPWorkspace;
import org.jkiss.dbeaver.model.fs.DBFFileSystemManager;
import org.jkiss.dbeaver.model.impl.auth.SessionContextImpl;
import org.jkiss.dbeaver.model.rm.RMUtils;
import org.jkiss.dbeaver.runtime.DBWorkbench;
@@ -46,6 +47,7 @@ public class WebSessionWorkspace implements DBPWorkspace {
private final SessionContextImpl workspaceAuthContext;
private final List<WebSessionProjectImpl> accessibleProjects = new ArrayList<>();
private WebSessionProjectImpl activeProject;
private DBFFileSystemManager fileSystemManager;
public WebSessionWorkspace(BaseWebSession session) {
this.session = session;
@@ -211,4 +213,17 @@ public class WebSessionWorkspace implements DBPWorkspace {
return ServletAppUtils.getServletApplication().getAppConfiguration().isFeatureEnabled(feature);
}
@NotNull
@Override
public synchronized DBFFileSystemManager getFileSystemManager() {
if (fileSystemManager == null) {
synchronized (this) {
if (fileSystemManager == null) {
fileSystemManager = new DBFFileSystemManager(session.getWorkspace());
}
}
}
return fileSystemManager;
}
}
@@ -1,6 +1,6 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2024 DBeaver Corp and others
* Copyright (C) 2010-2026 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.
@@ -245,7 +245,7 @@ public class WebUserContext implements SMCredentialsProvider {
return secretController;
}
@NotNull
@Nullable
public String getSmSessionId() {
return smSessionId;
}
@@ -114,4 +114,9 @@ public class WebUser {
public String getDisableReason() {
return user.getDisableReason();
}
@Nullable
public Instant getLastLoginTime() {
return user.getLastLoginTime();
}
}
@@ -82,4 +82,6 @@ public class CBConstants {
public static final String DEFAULT_CLOUD_PROJECT_NAME = "GlobalConfiguration";
public static final String SECURED_VALUE = "******";
public static final String PREF_DATA_EDITOR_EXPORT_DISABLED_OLD = "plugin.data-viewer.export.disabled";
public static final String PREF_DATA_EDITOR_IMPORT_DISABLED_OLD = "plugin.data-import.disabled";
}
@@ -54,7 +54,7 @@ public class ServerGlobalWorkspace extends BaseWorkspaceImpl {
@NotNull DBPPlatform platform,
@NotNull ServletApplication application
) {
super(platform, application.getWorkspaceDirectory());
super(platform, application.getWorkspacePath());
this.application = application;
}
@@ -31,6 +31,6 @@ public class ServerGlobalWorkspaceSession extends LocalWorkspaceSession {
@Nullable
@Override
public DBSSecretController getSecretController() {
return super.getSecretController();
return null;
}
}
@@ -1,6 +1,6 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2025 DBeaver Corp and others
* Copyright (C) 2010-2026 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.
@@ -30,7 +30,7 @@ public interface DBWServiceBindingServlet<APPLICATION extends ServletApplication
return true;
}
void addServlets(APPLICATION application, DBWServletContext servletContext) throws DBException;
void addServlets(@NotNull APPLICATION application, @NotNull DBWServletContext servletContext) throws DBException;
@NotNull
default List<String> getExcludedServletPaths(@NotNull APPLICATION application) {
@@ -192,13 +192,16 @@ public class ServletAppUtils {
@NotNull String serviceId,
@NotNull String origin
) throws DBException {
String finalOrigin = webAuthApplication.modifyOrigin(origin);
String finalOrigin = ServletAppUtils.substringBeforeRootURI(webAuthApplication.modifyOrigin(origin));
String serviceUriSegment = removeSideSlashes(webAuthApplication.getAuthServiceUriSegment());
String rootUri = removeSideSlashes(getServletApplication().getRootURI());
if (finalOrigin.endsWith("/" + rootUri) && serviceUriSegment.startsWith(rootUri + "/")) {
finalOrigin = finalOrigin.substring(0, finalOrigin.length() - rootUri.length());
}
StringBuilder authUriBuilder = new StringBuilder(removeSideSlashes(finalOrigin));
if (CommonUtils.isNotEmpty(rootUri)) {
authUriBuilder.append("/").append(rootUri);
}
if (CommonUtils.isNotEmpty(serviceUriSegment)) {
authUriBuilder.append("/").append(serviceUriSegment);
}
@@ -297,12 +300,21 @@ public class ServletAppUtils {
}
}
@NotNull
public static String getHostOriginFromRequest(@NotNull HttpServletRequest request) {
return substringBeforeRootURI(getOriginFromRequest(request));
}
@NotNull
public static String getOriginFromRequest(@NotNull HttpServletRequest request) {
String origin = request.getHeader(HEADER_ORIGIN);
if (log.isTraceEnabled()) {
log.trace("Origin header: " + origin);
}
if ("null".equals(origin)) {
//strange identity provider bug
origin = null;
}
if (CommonUtils.isEmpty(origin)) {
origin = request.getHeader(HEADER_X_ORIGIN);
if (log.isTraceEnabled()) {
@@ -319,8 +331,7 @@ public class ServletAppUtils {
if (log.isTraceEnabled()) {
log.trace("forwarded origin: " + origin);
}
}
if (CommonUtils.isEmpty(origin)) {
} else if (CommonUtils.isEmpty(origin)) {
URI requestUrl = URI.create(request.getRequestURL().toString());
if (log.isTraceEnabled()) {
log.trace("Request URL: " + requestUrl);
@@ -344,13 +355,34 @@ public class ServletAppUtils {
log.error("Failed to parse port from header: " + request.getHeader(HEADER_FORWARDED_PORT), e);
}
}
String finalScheme = uri.getScheme();
String finalHost = uri.getHost();
int finalPort = port;
boolean changed = false;
if (CommonUtils.isNotEmpty(forwardedScheme) && !forwardedScheme.equals(finalScheme)) {
finalScheme = forwardedScheme;
changed = true;
}
if (CommonUtils.isNotEmpty(forwardedHost) && !forwardedHost.equals(finalHost)) {
finalHost = forwardedHost;
changed = true;
}
if (DEFAULT_PORTS.contains(port)) {
finalPort = -1;
changed = true;
}
if (log.isTraceEnabled()) {
log.trace("Origin URI: " + origin);
}
if (changed) {
try {
origin = new URI(
uri.getScheme(),
finalScheme,
uri.getUserInfo(),
uri.getHost(),
-1,
finalHost,
finalPort,
uri.getPath(),
uri.getQuery(),
uri.getFragment()
@@ -359,9 +391,6 @@ public class ServletAppUtils {
log.error("Failed to create URI without port", e);
}
}
if (log.isTraceEnabled()) {
log.trace("Origin URI: " + origin);
}
return origin;
}
@@ -33,6 +33,7 @@ import org.jkiss.dbeaver.model.access.DBAAuthCredentials;
import org.jkiss.dbeaver.model.app.DBPDataSourceRegistry;
import org.jkiss.dbeaver.model.app.DBPProject;
import org.jkiss.dbeaver.model.connection.DBPConnectionConfiguration;
import org.jkiss.dbeaver.model.connection.DBPConnectionType;
import org.jkiss.dbeaver.model.connection.DBPDataSourceProviderDescriptor;
import org.jkiss.dbeaver.model.connection.DBPDriver;
import org.jkiss.dbeaver.model.impl.auth.AuthModelDatabaseNativeCredentials;
@@ -40,6 +41,7 @@ import org.jkiss.dbeaver.model.net.DBWHandlerConfiguration;
import org.jkiss.dbeaver.model.net.ssh.SSHConstants;
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
import org.jkiss.dbeaver.model.websocket.event.datasource.WSDataSourceDisconnectEvent;
import org.jkiss.dbeaver.registry.DataSourceProviderRegistry;
import org.jkiss.dbeaver.registry.network.NetworkHandlerDescriptor;
import org.jkiss.dbeaver.registry.network.NetworkHandlerRegistry;
import org.jkiss.dbeaver.runtime.DBWorkbench;
@@ -55,9 +57,12 @@ public class WebDataSourceUtils {
private WebDataSourceUtils() {
}
public static void saveCredentialsInDataSource(WebConnectionInfo webConnectionInfo, DBPDataSourceContainer dataSourceContainer, DBPConnectionConfiguration configuration) {
public static void saveCredentialsInDataSource(
@NotNull WebConnectionInfo webConnectionInfo,
@NotNull DBPDataSourceContainer dataSourceContainer,
@NotNull DBPConnectionConfiguration configuration
) {
// Properties passed from web
// webConnectionInfo may be null in some cases (e.g. connection test when no actual connection exist yet)
Map<String, Object> authProperties = webConnectionInfo.getSavedAuthProperties();
if (authProperties != null) {
authProperties.forEach((s, o) -> configuration.setAuthProperty(s, CommonUtils.toString(o)));
@@ -162,18 +167,24 @@ public class WebDataSourceUtils {
}
public static boolean disconnectDataSource(@NotNull WebSession webSession, @NotNull DBPDataSourceContainer dataSource) {
public static boolean disconnectDataSource(
@NotNull WebSession webSession,
@NotNull DBPDataSourceContainer dataSource,
boolean sendDisconnectEvent
) {
if (dataSource.isConnected()) {
try {
dataSource.disconnect(webSession.getProgressMonitor());
webSession.addSessionEvent(
new WSDataSourceDisconnectEvent(
dataSource.getProject().getId(),
dataSource.getId(),
webSession.getSessionId(),
webSession.getUserId()
)
);
if (sendDisconnectEvent) {
webSession.addSessionEvent(
new WSDataSourceDisconnectEvent(
dataSource.getProject().getId(),
dataSource.getId(),
WebEventUtils.getSmSessionId(webSession),
webSession.getUserId()
)
);
}
return true;
} catch (DBException e) {
log.error("Error closing connection", e);
@@ -299,9 +310,7 @@ public class WebDataSourceUtils {
if (config.getKeepAliveInterval() >= 0) {
dsConfig.setKeepAliveInterval(config.getKeepAliveInterval());
}
if (config.isDefaultAutoCommit() != null) {
dsConfig.getBootstrap().setDefaultAutoCommit(config.isDefaultAutoCommit());
}
dsConfig.getBootstrap().setDefaultAutoCommit(config.isDefaultAutoCommit());
dsConfig.getBootstrap().setDefaultCatalogName(config.getDefaultCatalogName());
dsConfig.getBootstrap().setDefaultSchemaName(config.getDefaultSchemaName());
// Save provider props
@@ -314,8 +323,19 @@ public class WebDataSourceUtils {
if (config.getConfigurationType() != null) {
dsConfig.setConfigurationType(config.getConfigurationType());
}
if (config.getConnectionType() != null) {
DBPConnectionType connectionType = DataSourceProviderRegistry.getInstance().getConnectionType(config.getConnectionType(), null);
if (connectionType != null) {
dsConfig.setConnectionType(connectionType);
}
}
if (CommonUtils.isEmpty(config.getUrl())) {
dsConfig.setUrl(driver.getConnectionURL(dsConfig));
try {
dsConfig.setUrl(driver.getConnectionURL(dsConfig));
} catch (DBException e) {
log.error("Error preparing connection URL", e);
}
}
// Save network handlers
if (config.getNetworkHandlersConfig() != null) {
@@ -1,6 +1,6 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2024 DBeaver Corp and others
* Copyright (C) 2010-2026 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.
@@ -17,119 +17,21 @@
package io.cloudbeaver.utils;
import io.cloudbeaver.model.WebAsyncTaskInfo;
import io.cloudbeaver.model.session.BaseWebSession;
import io.cloudbeaver.model.session.WebSession;
import io.cloudbeaver.websocket.event.task.WSSessionTaskInfoEvent;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.model.app.DBPProject;
import org.jkiss.dbeaver.model.security.SMSubjectType;
import org.jkiss.dbeaver.model.websocket.WSConstants;
import org.jkiss.dbeaver.model.websocket.event.WSEvent;
import org.jkiss.dbeaver.model.websocket.event.datasource.WSDataSourceEvent;
import org.jkiss.dbeaver.model.websocket.event.datasource.WSDataSourceProperty;
import org.jkiss.dbeaver.model.websocket.event.datasource.WSDatasourceFolderEvent;
import org.jkiss.dbeaver.model.websocket.event.permissions.WSSubjectPermissionEvent;
import org.jkiss.dbeaver.model.websocket.event.resource.WSResourceProperty;
import org.jkiss.dbeaver.model.websocket.event.resource.WSResourceUpdatedEvent;
import java.util.List;
import java.util.Objects;
public class WebEventUtils {
/**
* adds events of updated datasource to event controller
*
* @param project project of updated database
* @param session web session
* @param datasourceId id of datasource
* @param eventAction type of event
*/
public static void addDataSourceUpdatedEvent(
DBPProject project,
WebSession session,
String datasourceId,
WSConstants.EventAction eventAction,
WSDataSourceProperty property
) {
if (project == null) {
return;
}
WSEvent event = null;
switch (eventAction) {
case CREATE:
event = WSDataSourceEvent.create(
session.getUserContext().getSmSessionId(),
session.getUserId(),
project.getId(),
List.of(datasourceId),
property
);
break;
case DELETE:
event = WSDataSourceEvent.delete(
session.getUserContext().getSmSessionId(),
session.getUserId(),
project.getId(),
List.of(datasourceId),
property
);
break;
case UPDATE:
event = WSDataSourceEvent.update(
session.getUserContext().getSmSessionId(),
session.getUserId(),
project.getId(),
List.of(datasourceId),
property
);
break;
}
if (event == null) {
return;
}
ServletAppUtils.getServletApplication().getEventController().addEvent(event);
}
public static void addNavigatorNodeUpdatedEvent(
DBPProject project,
WebSession session,
String nodePath,
WSConstants.EventAction eventAction
) {
if (project == null) {
return;
}
WSEvent event = null;
switch (eventAction) {
case CREATE:
event = WSDatasourceFolderEvent.create(
session.getUserContext().getSmSessionId(),
session.getUserId(),
project.getId(),
List.of(nodePath)
);
break;
case DELETE:
event = WSDatasourceFolderEvent.delete(
session.getUserContext().getSmSessionId(),
session.getUserId(),
project.getId(),
List.of(nodePath)
);
break;
case UPDATE:
event = WSDatasourceFolderEvent.update(
session.getUserContext().getSmSessionId(),
session.getUserId(),
project.getId(),
List.of(nodePath)
);
break;
}
if (event == null) {
return;
}
ServletAppUtils.getServletApplication().getEventController().addEvent(event);
}
public static void addRmResourceUpdatedEvent(
String projectId,
@@ -153,7 +55,7 @@ public class WebEventUtils {
switch (eventAction) {
case CREATE:
event = WSResourceUpdatedEvent.create(
session.getUserContext().getSmSessionId(),
WebEventUtils.getSmSessionId(session),
session.getUserId(),
projectId,
resourcePath,
@@ -163,7 +65,7 @@ public class WebEventUtils {
break;
case DELETE:
event = WSResourceUpdatedEvent.delete(
session.getUserContext().getSmSessionId(),
WebEventUtils.getSmSessionId(session),
session.getUserId(),
projectId,
resourcePath,
@@ -173,7 +75,7 @@ public class WebEventUtils {
break;
case UPDATE:
event = WSResourceUpdatedEvent.update(
session.getUserContext().getSmSessionId(),
WebEventUtils.getSmSessionId(session),
session.getUserId(),
projectId,
resourcePath,
@@ -213,4 +115,12 @@ public class WebEventUtils {
ServletAppUtils.getServletApplication().getEventController().addEvent(event);
}
@Nullable
public static String getSmSessionId(@NotNull BaseWebSession webSession) {
return webSession.getUserContext().getSmSessionId();
}
public static boolean isSmSessionIdEquals(@NotNull BaseWebSession webSession, @Nullable String smSessionId) {
return Objects.equals(getSmSessionId(webSession), smSessionId);
}
}
@@ -1,6 +1,6 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2024 DBeaver Corp and others
* Copyright (C) 2010-2026 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.
@@ -16,6 +16,8 @@
*/
package io.cloudbeaver.websocket;
import io.cloudbeaver.model.session.BaseWebSession;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.model.websocket.event.WSEvent;
@@ -24,4 +26,6 @@ public interface CBWebSessionEventHandler {
void close();
void migrateToSession(@NotNull BaseWebSession newSession);
}
@@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2
Bundle-Vendor: DBeaver Corp
Bundle-Name: Cloudbeaver Community Product
Bundle-SymbolicName: io.cloudbeaver.product.ce;singleton:=true
Bundle-Version: 26.0.5.qualifier
Bundle-Release-Date: 20260518
Bundle-Version: 26.1.5.qualifier
Bundle-Release-Date: 20260817
Bundle-RequiredExecutionEnvironment: JavaSE-21
Bundle-ActivationPolicy: lazy
Require-Bundle: io.cloudbeaver.server.ce
@@ -16,6 +16,10 @@
</product>
</extension>
<extension point="io.cloudbeaver.feature">
<feature id="ai" label="AI Integration" description="Enables AI Chat in the application."/>
</extension>
<extension point="org.jkiss.dbeaver.application">
<application
id="cloudbeaver-ce"
@@ -10,7 +10,7 @@
<relativePath>../</relativePath>
</parent>
<artifactId>io.cloudbeaver.product.ce</artifactId>
<version>26.0.5-SNAPSHOT</version>
<version>26.1.5-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
</project>
@@ -2,8 +2,8 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: Cloudbeaver Base JDBC drivers
Bundle-SymbolicName: io.cloudbeaver.resources.drivers.base;singleton:=true
Bundle-Version: 1.0.146.qualifier
Bundle-Release-Date: 20260518
Bundle-Version: 1.0.152.qualifier
Bundle-Release-Date: 20260817
Bundle-Vendor: DBeaver Corp
Bundle-ActivationPolicy: lazy
Automatic-Module-Name: io.cloudbeaver.resources.drivers.base
@@ -16,6 +16,7 @@
<resource name="drivers/h2_v2"/>
<resource name="drivers/h2_v3"/>
<resource name="drivers/sqlite/xerial"/>
<resource name="drivers/libsql"/>
<resource name="drivers/mssql/new"/>
<resource name="drivers/trino"/>
<resource name="drivers/kyuubi"/>
@@ -38,6 +39,7 @@
<bundle id="drivers.h2_v2" label="H2 v2 drivers"/>
<bundle id="drivers.h2_v3" label="H2 v3 drivers"/>
<bundle id="drivers.sqlite.xerial" label="SQLite drivers"/>
<bundle id="drivers.libsql" label="LibSQL drivers"/>
<bundle id="drivers.mssql.new" label="SQL Server drivers"/>
<bundle id="drivers.trino" label="Trino drivers"/>
<bundle id="drivers.kyuubi" label="Apache Kyuubi drivers"/>
@@ -9,6 +9,6 @@
<relativePath>../</relativePath>
</parent>
<artifactId>io.cloudbeaver.resources.drivers.base</artifactId>
<version>1.0.146-SNAPSHOT</version>
<version>1.0.152-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
</project>
@@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2
Bundle-Vendor: DBeaver Corp
Bundle-Name: CloudBeaver Community
Bundle-SymbolicName: io.cloudbeaver.server.ce;singleton:=true
Bundle-Version: 26.0.5.qualifier
Bundle-Release-Date: 20260518
Bundle-Version: 26.1.5.qualifier
Bundle-Release-Date: 20260817
Bundle-RequiredExecutionEnvironment: JavaSE-21
Bundle-ActivationPolicy: lazy
Bundle-Activator: io.cloudbeaver.server.CBPlatformActivator
@@ -10,7 +10,7 @@
<relativePath>../</relativePath>
</parent>
<artifactId>io.cloudbeaver.server.ce</artifactId>
<version>26.0.5-SNAPSHOT</version>
<version>26.1.5-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
</project>
@@ -1,3 +1,7 @@
####################################################
# Core API
####################################################
extend type ServerConfig {
serverURL: String! @deprecated
rootURI: String!
@@ -14,11 +14,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.cloudbeaver.service.admin;
package io.cloudbeaver.model.config;
import io.cloudbeaver.model.config.CBAppConfig;
import io.cloudbeaver.server.CBApplication;
import io.cloudbeaver.server.CBConstants;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.data.json.JSONUtils;
@@ -57,7 +57,7 @@ public class AdminServerConfig {
@Nullable
private String bindSessionToIp;
public AdminServerConfig(Map<String, Object> params) {
public AdminServerConfig(@NotNull Map<String, Object> params) {
this.serverName = JSONUtils.getString(params, "serverName");
this.adminName = JSONUtils.getString(params, "adminName");
this.adminPassword = JSONUtils.getString(params, "adminPassword");
@@ -47,14 +47,14 @@ import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.DBConstants;
import org.jkiss.dbeaver.model.DBPDataSourceContainer;
import org.jkiss.dbeaver.model.app.DBPPlatform;
import org.jkiss.dbeaver.model.auth.AuthInfo;
import org.jkiss.dbeaver.model.auth.SMAuthConfiguration;
import org.jkiss.dbeaver.model.auth.SMCredentialsProvider;
import org.jkiss.dbeaver.model.auth.SMObjectType;
import org.jkiss.dbeaver.model.connection.DBPDriver;
import org.jkiss.dbeaver.model.data.json.JSONUtils;
import org.jkiss.dbeaver.model.impl.app.BaseApplicationImpl;
import org.jkiss.dbeaver.model.security.SMAdminController;
import org.jkiss.dbeaver.model.security.SMConstants;
import org.jkiss.dbeaver.model.security.SMObjectType;
import org.jkiss.dbeaver.model.websocket.event.WSEventController;
import org.jkiss.dbeaver.model.websocket.event.WSServerConfigurationChangedEvent;
import org.jkiss.dbeaver.runtime.DBWorkbench;
@@ -181,6 +181,7 @@ public abstract class CBApplication<T extends CBServerConfig>
return getServerConfigurationController().getServerConfiguration();
}
@NotNull
@Override
public ServletAuthConfiguration getAuthConfiguration() {
return getAppConfiguration();
@@ -228,11 +229,11 @@ public abstract class CBApplication<T extends CBServerConfig>
Location instanceLoc = Platform.getInstanceLocation();
try {
if (!instanceLoc.isSet()) { // always false?
URL wsLocationURL = getWorkspaceDirectory().toUri().toURL();
URL wsLocationURL = getWorkspacePath().toUri().toURL();
instanceLoc.set(wsLocationURL, true);
}
} catch (Exception e) {
log.error("Error setting workspace location to " + getWorkspaceDirectory().toAbsolutePath(), e);
log.error("Error setting workspace location to " + getWorkspacePath().toAbsolutePath(), e);
return;
}
this.systemInformationCollector = createSystemInformationCollector();
@@ -443,7 +444,7 @@ public abstract class CBApplication<T extends CBServerConfig>
@NotNull
public Path getDataDirectory(boolean create) {
Path dataDir = getWorkspaceDirectory().resolve(CBConstants.RUNTIME_DATA_DIR_NAME);
Path dataDir = getWorkspacePath().resolve(CBConstants.RUNTIME_DATA_DIR_NAME);
if (create && !Files.exists(dataDir)) {
try {
Files.createDirectories(dataDir);
@@ -534,7 +535,7 @@ public abstract class CBApplication<T extends CBServerConfig>
public synchronized void finishConfiguration(
@NotNull String adminName,
@Nullable String adminPassword,
@NotNull List<AuthInfo> authInfoList,
@NotNull List<SMAuthConfiguration> authInfoList,
@NotNull CBServerConfig serverConfig,
@NotNull CBAppConfig appConfig,
@Nullable SMCredentialsProvider credentialsProvider
@@ -591,7 +592,7 @@ public abstract class CBApplication<T extends CBServerConfig>
protected abstract void finishSecurityServiceConfiguration(
@NotNull String adminName,
@Nullable String adminPassword,
@NotNull List<AuthInfo> authInfoList
@NotNull List<SMAuthConfiguration> authInfoList
) throws DBException;
public synchronized void flushConfiguration(SMCredentialsProvider webSession) throws DBException {
@@ -743,7 +744,7 @@ public abstract class CBApplication<T extends CBServerConfig>
sendConfigChangedEvent(credentialsProvider);
}
protected void sendConfigChangedEvent(SMCredentialsProvider credentialsProvider) {
protected void sendConfigChangedEvent(@Nullable SMCredentialsProvider credentialsProvider) {
String sessionId = null;
if (credentialsProvider != null && credentialsProvider.getActiveUserCredentials() != null) {
sessionId = credentialsProvider.getActiveUserCredentials().getSmSessionId();
@@ -751,6 +752,7 @@ public abstract class CBApplication<T extends CBServerConfig>
eventController.addEvent(new WSServerConfigurationChangedEvent(sessionId, null));
}
@NotNull
@Override
public abstract CBServerConfigurationController<T> getServerConfigurationController();
@@ -27,7 +27,7 @@ import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.DBFileController;
import org.jkiss.dbeaver.model.app.DBPWorkspace;
import org.jkiss.dbeaver.model.auth.AuthInfo;
import org.jkiss.dbeaver.model.auth.SMAuthConfiguration;
import org.jkiss.dbeaver.model.auth.SMCredentialsProvider;
import org.jkiss.dbeaver.model.rm.RMController;
import org.jkiss.dbeaver.model.security.SMAdminController;
@@ -93,6 +93,7 @@ public class CBApplicationCE extends CBApplication<CBServerConfig> {
return new LocalFileController(DBWorkbench.getPlatform().getWorkspace().getAbsolutePath().resolve(DBFileController.DATA_FOLDER));
}
@NotNull
@Override
public CBServerConfigurationControllerEmbedded<CBServerConfig> getServerConfigurationController() {
return serverConfigController;
@@ -101,7 +102,7 @@ public class CBApplicationCE extends CBApplication<CBServerConfig> {
protected void finishSecurityServiceConfiguration(
@NotNull String adminName,
@Nullable String adminPassword,
@NotNull List<AuthInfo> authInfoList
@NotNull List<SMAuthConfiguration> authInfoList
) throws DBException {
if (securityController instanceof CBEmbeddedSecurityController<?> embeddedSecurityController) {
embeddedSecurityController.finishConfiguration(adminName, adminPassword, authInfoList);
@@ -1,6 +1,6 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2025 DBeaver Corp and others
* Copyright (C) 2010-2026 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.
@@ -20,10 +20,7 @@ import com.google.gson.*;
import com.google.gson.reflect.TypeToken;
import io.cloudbeaver.model.app.BaseServerConfigurationController;
import io.cloudbeaver.model.app.BaseServletApplication;
import io.cloudbeaver.model.config.CBAppConfig;
import io.cloudbeaver.model.config.CBServerConfig;
import io.cloudbeaver.model.config.PasswordPolicyConfiguration;
import io.cloudbeaver.model.config.SMControllerConfiguration;
import io.cloudbeaver.model.config.*;
import io.cloudbeaver.utils.ServletAppUtils;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
@@ -374,6 +371,7 @@ public abstract class CBServerConfigurationController<T extends CBServerConfig>
try (Writer out = new OutputStreamWriter(Files.newOutputStream(runtimeConfigPath), StandardCharsets.UTF_8)) {
Gson gson = new GsonBuilder()
.setStrictness(Strictness.LENIENT)
.setObjectToNumberStrategy(ToNumberPolicy.LONG_OR_DOUBLE)
.setPrettyPrinting()
.create();
gson.toJson(configurationProperties, out);
@@ -508,7 +506,7 @@ public abstract class CBServerConfigurationController<T extends CBServerConfig>
@NotNull
protected Map<String, Object> collectServerConfigProperties(
@NotNull CBServerConfig serverConfig,
Map<String, Object> originServerConfig
@NotNull Map<String, Object> originServerConfig
) {
var serverConfigProperties = new LinkedHashMap<String, Object>();
if (!CommonUtils.isEmpty(serverConfig.getServerName())) {
@@ -633,6 +631,9 @@ public abstract class CBServerConfigurationController<T extends CBServerConfig>
return serverConfiguration;
}
@NotNull
public abstract CBServerConfigurationMapper<T, ? extends AdminServerConfig> createServerConfigurationInputMapper();
public CBAppConfig getAppConfiguration() {
return appConfiguration;
}
@@ -1,6 +1,6 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2024 DBeaver Corp and others
* Copyright (C) 2010-2026 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.
@@ -19,6 +19,7 @@ package io.cloudbeaver.server;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.InstanceCreator;
import io.cloudbeaver.model.config.AdminServerConfig;
import io.cloudbeaver.model.config.CBServerConfig;
import io.cloudbeaver.model.config.WebDatabaseConfig;
import org.jkiss.code.NotNull;
@@ -41,6 +42,11 @@ public class CBServerConfigurationControllerEmbedded<T extends CBServerConfig> e
super(serverConfig, homeDirectory);
}
@NotNull
public CBServerConfigurationMapper<T, ? extends AdminServerConfig> createServerConfigurationInputMapper() {
return new CBServerConfigurationMapper<>();
}
@NotNull
@Override
protected Map<String, Object> collectServerConfigProperties(
@@ -0,0 +1,145 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2026 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.server;
import io.cloudbeaver.DBWFeatureSet;
import io.cloudbeaver.DBWebException;
import io.cloudbeaver.model.config.AdminServerConfig;
import io.cloudbeaver.model.config.CBAppConfig;
import io.cloudbeaver.model.config.CBServerConfig;
import io.cloudbeaver.utils.ServletAppUtils;
import io.cloudbeaver.utils.WebDataSourceUtils;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.connection.DBPDriver;
import org.jkiss.utils.CommonUtils;
import java.util.*;
public class CBServerConfigurationMapper<C extends CBServerConfig, I extends AdminServerConfig> {
private static final Log log = Log.getLog(CBServerConfigurationMapper.class);
@NotNull
public CBServerConfigurations loadServerConfigurationsFromParams(@NotNull Map<String, Object> params) {
CBAppConfig appConfig = new CBAppConfig(CBApplication.getInstance().getAppConfiguration());
C serverConfig = createServerConfiguration();
serverConfig.setServerName(CBApplication.getInstance().getServerName());
serverConfig.setMaxSessionIdleTime(CBApplication.getInstance().getMaxSessionIdleTime());
String adminName = null;
String adminPassword = null;
if (!params.isEmpty()) { // FE can send an empty configuration
I config = createInputConfiguration(params);
adminName = config.getAdminName();
adminPassword = config.getAdminPassword();
populateConfigurations(config, serverConfig, appConfig);
}
return new CBServerConfigurations(
serverConfig,
appConfig,
adminName,
adminPassword
);
}
protected void populateConfigurations(@NotNull I input, @NotNull C serverConfig, @NotNull CBAppConfig appConfig) {
appConfig.setAnonymousAccessEnabled(input.isAnonymousAccessEnabled());
appConfig.setSupportsCustomConnections(input.isCustomConnectionsEnabled());
appConfig.setPublicCredentialsSaveEnabled(input.isPublicCredentialsSaveEnabled());
appConfig.setAdminCredentialsSaveEnabled(input.isAdminCredentialsSaveEnabled());
updateDisabledFeaturesConfig(appConfig, input.getEnabledFeatures());
// custom logic for enabling embedded drivers
updateDisabledDriversConfig(appConfig, input.getDisabledDrivers());
appConfig.setResourceManagerEnabled(input.isResourceManagerEnabled());
appConfig.setSecretManagerEnabled(input.isSecretManagerEnabled());
if (CommonUtils.isEmpty(input.getEnabledAuthProviders())) {
// All of them
appConfig.setEnabledAuthProviders(new String[0]);
} else {
appConfig.setEnabledAuthProviders(input.getEnabledAuthProviders().toArray(new String[0]));
}
appConfig.setDefaultNavigatorSettings(
CBApplication.getInstance().getAppConfiguration().getDefaultNavigatorSettings());
serverConfig.setServerName(input.getServerName());
serverConfig.setMaxSessionIdleTime(input.getSessionExpireTime());
if (input.getForceHttps() != null) {
serverConfig.setForceHttps(input.getForceHttps());
}
if (input.getSupportedHosts() != null) {
serverConfig.setSupportedHosts(input.getSupportedHosts());
}
if (input.getBindSessionToIp() != null) {
serverConfig.setBindSessionToIp(input.getBindSessionToIp());
}
}
private void updateDisabledFeaturesConfig(@NotNull CBAppConfig appConfig, @NotNull List<String> enabledFeatures) {
Set<String> enabledIds = new LinkedHashSet<>(enabledFeatures);
appConfig.setEnabledFeatures(enabledFeatures.toArray(new String[0]));
String[] disabledFeatures = ServletAppUtils.getServletApplication().getFeatureRegistry().getWebFeatures().stream()
.map(DBWFeatureSet::getId)
.filter(id -> !enabledIds.contains(id))
.toArray(String[]::new);
appConfig.setDisabledFeatures(disabledFeatures);
}
// we disable embedded drivers by default and enable it in enabled drivers list
// that's why we need so complicated logic for disabling drivers
private void updateDisabledDriversConfig(@NotNull CBAppConfig appConfig, @NotNull String[] disabledDriversConfig) {
Set<String> disabledIds = new LinkedHashSet<>(Arrays.asList(disabledDriversConfig));
Set<String> enabledIds = new LinkedHashSet<>(Arrays.asList(appConfig.getEnabledDrivers()));
// remove all disabled embedded drivers from enabled drivers list
enabledIds.removeAll(disabledIds);
// enable embedded driver if it is not in disabled drivers list
for (String driverId : appConfig.getDisabledDrivers()) {
if (disabledIds.contains(driverId)) {
// driver is also disabled
continue;
}
// driver is removed from disabled list
// we need to enable if it is embedded
try {
DBPDriver driver = WebDataSourceUtils.getDriverById(driverId);
if (driver.isEmbedded()) {
enabledIds.add(driverId);
}
} catch (DBWebException e) {
log.error("Failed to find driver by id", e);
}
}
appConfig.setDisabledDrivers(disabledDriversConfig);
appConfig.setEnabledDrivers(enabledIds.toArray(String[]::new));
}
@NotNull
protected C createServerConfiguration() {
return (C) new CBServerConfig();
}
@NotNull
protected I createInputConfiguration(@NotNull Map<String, Object> params) {
return (I) new AdminServerConfig(params);
}
}
@@ -0,0 +1,30 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2026 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.server;
import io.cloudbeaver.model.config.CBAppConfig;
import io.cloudbeaver.model.config.CBServerConfig;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
public record CBServerConfigurations(
@NotNull CBServerConfig serverConfig,
@NotNull CBAppConfig appConfig,
@Nullable String adminName,
@Nullable String adminPassword
) {
}
@@ -24,6 +24,7 @@ import io.cloudbeaver.server.WebAppUtils;
import io.cloudbeaver.service.security.SMUtils;
import io.cloudbeaver.utils.ServletAppUtils;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.security.SMAdminController;
@@ -33,7 +34,6 @@ import org.jkiss.dbeaver.model.websocket.event.datasource.WSDataSourceEvent;
import org.jkiss.dbeaver.model.websocket.event.datasource.WSDataSourceProperty;
import org.jkiss.dbeaver.model.websocket.event.permissions.WSObjectPermissionEvent;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -43,10 +43,11 @@ import java.util.stream.Collectors;
public class WSObjectPermissionUpdatedEventHandler extends WSDefaultEventHandler<WSObjectPermissionEvent> {
private static final Log log = Log.getLog(WSObjectPermissionUpdatedEventHandler.class);
@Nullable
@Override
public void handleEvent(@NotNull WSObjectPermissionEvent event) {
protected Consumer<BaseWebSession> getEventConsumer(@NotNull WSObjectPermissionEvent event) {
String objectId = event.getObjectId();
Consumer<BaseWebSession> runnable = switch (event.getSmObjectType()) {
return switch (event.getSmObjectType()) {
case project:
yield getUpdateUserProjectsInfoConsumer(event, objectId);
case datasource:
@@ -61,23 +62,6 @@ public class WSObjectPermissionUpdatedEventHandler extends WSDefaultEventHandler
yield null;
}
};
if (runnable == null) {
return;
}
log.debug(event.getTopicId() + " event handled");
Collection<BaseWebSession> allSessions = CBApplication.getInstance().getSessionManager().getAllActiveSessions();
for (var activeUserSession : allSessions) {
if (!isAcceptableInSession(activeUserSession, event)) {
log.debug("Cannot handle %s event '%s' in session %s".formatted(
event.getTopicId(),
event.getId(),
activeUserSession.getSessionId()
));
continue;
}
log.debug("%s event '%s' handled".formatted(event.getTopicId(), event.getId()));
runnable.accept(activeUserSession);
}
}
@NotNull
@@ -156,10 +156,10 @@ public class RequestHostFilter implements Filter {
if (!availableHosts.contains(requestHost)) {
for (String errorPath : errorPaths) {
if (httpRequest.getServletPath().contains(errorPath)) {
log.warn("Request host '" + requestHost + "' is not allowed. Available hosts: " + availableHosts);
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
response.getWriter().write(
"Request host '" + requestHost + "' is not allowed. Available hosts: " + availableHosts
);
response.setContentType("text/plain;charset=UTF-8");
response.getWriter().write("Request host is not allowed. Available hosts: " + availableHosts);
return false;
}
}
@@ -1,6 +1,6 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2025 DBeaver Corp and others
* Copyright (C) 2010-2026 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.
@@ -24,9 +24,9 @@ import io.cloudbeaver.registry.WebSessionHandlerDescriptor;
import io.cloudbeaver.server.CBApplication;
import io.cloudbeaver.server.CBConstants;
import io.cloudbeaver.server.WebAppSessionManager;
import io.cloudbeaver.server.events.WSWebUtils;
import io.cloudbeaver.service.DBWSessionHandler;
import io.cloudbeaver.utils.ServletAppUtils;
import io.cloudbeaver.utils.WebEventUtils;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
@@ -60,6 +60,7 @@ public class CBSessionManager implements WebAppSessionManager {
/**
* Closes Web Session, associated to HttpSession from {@code request}
*/
@Nullable
@Override
public BaseWebSession closeSession(@NotNull HttpServletRequest request) {
HttpSession session = request.getSession();
@@ -69,11 +70,13 @@ public class CBSessionManager implements WebAppSessionManager {
return null;
}
@Nullable
@Override
public BaseWebSession closeSession(@NotNull String sessionId) {
return closeSession(sessionId, true);
}
@Nullable
@Override
public BaseWebSession closeSession(@NotNull String sessionId, boolean sendSessionExpiredEvent) {
BaseWebSession webSession;
@@ -199,12 +202,49 @@ public class CBSessionManager implements WebAppSessionManager {
return httpSession.getId();
}
/**
* Invalidates the current HTTP session, creates a new one, and binds a new {@link WebSession} to it.
*/
@NotNull
public WebSession rotateSession(
@NotNull HttpServletRequest request,
@NotNull WebSession oldWebSession
) throws DBWebException {
HttpSession oldHttpSession = request.getSession(false);
if (oldHttpSession != null) {
oldHttpSession.invalidate();
}
String newSessionId = request.getSession(true).getId();
String locale = oldWebSession.getLocale();
String remoteAddr = oldWebSession.getLastRemoteAddr();
String remoteUserAgent = oldWebSession.getLastRemoteUserAgent();
var requestInfo = new WebHttpRequestInfo(newSessionId, locale, remoteAddr, remoteUserAgent);
WebSession newWebSession;
try {
newWebSession = createWebSessionImpl(requestInfo);
} catch (DBException e) {
throw new DBWebException(e);
}
oldWebSession.migrateEventHandlersTo(newWebSession);
oldWebSession.getEventsFilter().migrateTo(newWebSession.getEventsFilter());
String oldSessionId = oldWebSession.getSessionId();
synchronized (sessionMap) {
sessionMap.remove(oldSessionId);
sessionMap.put(newSessionId, newWebSession);
}
oldWebSession.close(false, false);
log.debug("Session rotated '" + oldSessionId + "' -> '" + newSessionId + "'");
return newWebSession;
}
/**
* Returns not expired session from cache, or restore it.
*
* @return WebSession object or null, if session expired or invalid
*/
@Nullable
@NotNull
public WebSession getOrRestoreWebSession(@NotNull WebHttpRequestInfo requestInfo) {
final var sessionId = requestInfo.getId();
if (sessionId == null) {
@@ -283,19 +323,19 @@ public class CBSessionManager implements WebAppSessionManager {
@Override
@Nullable
public WebSession findWebSession(HttpServletRequest request) {
public WebSession findWebSession(@NotNull HttpServletRequest request) {
String sessionId = getSessionId(request);
WebSession webSession;
synchronized (sessionMap) {
var session = sessionMap.get(sessionId);
if (session instanceof WebSession) {
return (WebSession) session;
}
return null;
webSession = (session instanceof WebSession) ? (WebSession) session : null;
}
return webSession;
}
@Nullable
@Override
public WebSession findWebSession(HttpServletRequest request, boolean errorOnNoFound) throws DBWebException {
public WebSession findWebSession(@NotNull HttpServletRequest request, boolean errorOnNoFound) throws DBWebException {
WebSession webSession = findWebSession(request);
if (webSession != null) {
return webSession;
@@ -323,6 +363,7 @@ public class CBSessionManager implements WebAppSessionManager {
}
}
@NotNull
@Override
public Collection<BaseWebSession> getAllActiveSessions() {
synchronized (sessionMap) {
@@ -501,7 +542,7 @@ public class CBSessionManager implements WebAppSessionManager {
for (Iterator<BaseWebSession> iterator = sessionMap.values().iterator(); iterator.hasNext(); ) {
var session = iterator.next();
iterator.remove();
session.close(false, !WSWebUtils.isSessionIdEquals(session, initiatorSessionId));
session.close(false, !WebEventUtils.isSmSessionIdEquals(session, initiatorSessionId));
}
}
}
@@ -3,8 +3,8 @@ Bundle-ManifestVersion: 2
Bundle-Vendor: DBeaver Corp
Bundle-Name: Cloudbeaver Web Server
Bundle-SymbolicName: io.cloudbeaver.server;singleton:=true
Bundle-Version: 26.0.5.qualifier
Bundle-Release-Date: 20260518
Bundle-Version: 26.1.5.qualifier
Bundle-Release-Date: 20260817
Bundle-RequiredExecutionEnvironment: JavaSE-21
Bundle-ActivationPolicy: lazy
Require-Bundle: org.jkiss.dbeaver.model.sql;visibility:=reexport,
@@ -45,6 +45,9 @@
<eventHandler class="io.cloudbeaver.server.events.WSDataSourceUpdatedEventHandlerImpl">
<topic id="cb_datasource"/>
</eventHandler>
<eventHandler class="io.cloudbeaver.server.events.WSNetworkProfileEventHandler">
<topic id="cb_profiles"/>
</eventHandler>
<eventHandler class="io.cloudbeaver.server.events.WSFolderUpdatedEventHandlerImpl">
<topic id="cb_datasource_folder"/>
</eventHandler>
+1 -1
View File
@@ -10,7 +10,7 @@
<relativePath>../</relativePath>
</parent>
<artifactId>io.cloudbeaver.server</artifactId>
<version>26.0.5-SNAPSHOT</version>
<version>26.1.5-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>
</project>
@@ -1,6 +1,10 @@
# Any object (JSON)
####################################################
# Base schema
####################################################
"Any object (JSON)"
scalar Object
# Date/Time
"Date/Time"
scalar DateTime
scalar Date
@@ -556,7 +556,7 @@ type ConnectionInfo {
supportedDataFormats: [ ResultDataFormat! ]!
configurationType: DriverConfigurationType
#Access properties
"Access properties"
canViewSettings: Boolean!
canEdit: Boolean!
canDelete: Boolean!
@@ -570,6 +570,31 @@ type ConnectionInfo {
"List of tools that can be used with this connection. Returns empty list if no tools are available"
tools: [String!]! @since(version: "24.1.3")
connectionType: ID! @since(version: "26.1.2")
"Driver configuration"
driverConfiguration: DriverConfiguration! @since(version: "26.1.2")
}
"Database-dependent metadata describing features supported by the driver"
type DriverConfiguration {
"Supported 'on duplicate key' replace methods for this connection's SQL dialect"
supportedInsertReplaceMethods: [DictionaryValueInfo!]!
"Whether the connection's database supports bulk load during data import"
supportsBulkLoad: Boolean!
"Whether the connection's database supports transactions"
supportsTransactions: Boolean!
}
"Generic dictionary value: an identifier with a human readable name and an optional description"
type DictionaryValueInfo {
"Value ID"
id: ID!
"Human readable value name"
name: String!
"Value description"
description: String
}
type ConnectionFolderInfo {
@@ -633,6 +658,39 @@ type LogEntry {
stackTrace: String
}
type ConnectionType @since(version: "26.1.2") {
"Unique identifier of the connection type"
id: ID!
"Human-readable name of the connection type"
name: String!
"Description of the connection type"
description: String
"Color of the connection type (for light theme)"
colorLight: String!
"Alternative color of the connection type (for dark theme)"
colorDark: String
"Is autocommit enabled for this connection type"
autocommit: Boolean!
"Confirm execution of queries for this connection type"
confirmExecute: Boolean!
"Confirm data change operations (INSERT, UPDATE, DELETE) for this connection type"
confirmDataChange: Boolean!
"Smart commit mode is enabled for this connection type"
smartCommit: Boolean!
"Recover smart commit mode is enabled for this connection type"
smartCommitRecover: Boolean!
"Auto-close transactions is enabled for this connection type"
autoCloseTransactions: Boolean!
"Auto-close idle transactions period in seconds for this connection type"
closeIdleTransactionPeriod: Int!
"Auto-close connections is enabled for this connection type"
autoCloseConnections: Boolean!
"Auto-close idle connections period in seconds for this connection type"
closeIdleConnectionPeriod: Int!
"Specifies whether this connection type is system-defined or user-defined. System-defined connection types cannot be deleted."
predefined: Boolean!
}
####################################################
# Input types
####################################################
@@ -679,7 +737,7 @@ input ConnectionConfig {
"ID of database driver"
driverId: ID
# Custom connection parameters (all optional)
"Custom connection parameters (all optional)"
host: String
port: String
serverName: String
@@ -745,6 +803,8 @@ input ConnectionConfig {
defaultSchemaName: String @since(version: "25.0.5") @deprecated(reason: "25.2.1 use expertPropertyValues instead")
"Default user settings for connection"
defaultUserPreferences: Object @since(version: "26.0.2")
connectionType: ID @since(version: "26.1.2")
}
####################################################
@@ -787,6 +847,11 @@ extend type Query {
"Reads session log entries"
readSessionLog(maxEntries: Int, clearEntries: Boolean): [ LogEntry! ]!
"Returns connection driver properties based on configuration"
listConnectionDriverProperties( projectId: ID!, config: ConnectionConfig! ): [ObjectPropertyInfo!]!
listConnectionTypes: [ConnectionType!]! @since(version: "26.1.2")
}
extend type Mutation {
@@ -1,4 +1,7 @@
####################################################
# Datasource events
####################################################
extend enum CBServerEventId {
"Datasource created"
@@ -31,6 +31,10 @@ enum CBServerEventId {
"Open URL request in client"
cb_open_url @since(version: "25.3.1")
"User-specific object settings updated"
cb_object_settings_updated @since(version: "26.1.4")
"User-specific object settings deleted"
cb_object_settings_deleted @since(version: "26.1.4")
}
"Events sent by client"
@@ -57,6 +61,7 @@ enum CBEventTopic {
cb_workspace_configuration @since(version: "25.1.1")
cb_notification @since(version: "25.2.1")
cb_session_action @since(version: "25.3.1")
cb_object_settings @since(version: "26.1.4")
}
"Base server event interface"
@@ -178,6 +183,26 @@ type WSOpenUrlEvent implements CBServerEvent @since(version: "25.3.1") {
actionId: String!
}
"Type of the object that owns user-specific settings"
enum WSObjectSettingsType @since(version: "26.1.4") {
datasource
project
}
"User-specific object settings change event (e.g. navigator view)"
type WSObjectSettingsEvent implements CBServerEvent @since(version: "26.1.4") {
id: CBServerEventId!
topicId: CBEventTopic!
"Type of the object the settings belong to"
smObjectType: WSObjectSettingsType!
"Project of the object"
projectId: String
"Id of the object"
objectId: String!
"Ids of the settings that were changed"
settingIds: [String!]!
}
extend type Query {
emptyEvent: Boolean
}
@@ -1,3 +1,7 @@
####################################################
# SQL events
####################################################
extend enum CBServerEventId {
"Database output log updated (e.g., DBMS in Oracle)"
cb_database_output_log_updated,
@@ -1,4 +1,6 @@
####################################################
# Nodes, objects and properties
####################################################
type ObjectDescriptor {
id: Int
@@ -55,8 +57,6 @@ type DatabaseObjectInfo {
}
type NavigatorNodeInfo {
"Node ID - generally a full path to the node from root of tree"
id: ID!
"Node URI - a unique path to a node including all parent nodes"
uri: ID! @since(version: "23.3.1")
"Node human readable name"
@@ -145,7 +145,7 @@ extend type Query {
"Refreshes node based on the node path"
navRefreshNode( nodePath: ID! ): Boolean @deprecated # Use navReloadNode method from Mutation (24.2.4)
# contextId currently not using
"contextId currently not using"
navGetStructContainers( projectId: ID, connectionId: ID!, contextId: ID, catalog: ID ): DatabaseStructContainers!
}
@@ -38,7 +38,7 @@ type SQLCompletionProposal {
# Data read / SQL execution
####################################################
# SQL context must be created for each SQL editor
"SQL context must be created for each SQL editor"
type SQLContextInfo {
id: ID!
@@ -68,10 +68,41 @@ input SQLDataFilter {
limit: Int
constraints: [ SQLDataFilterConstraint ]
"When true constraints are combined with OR instead of AND"
anyConstraint: Boolean
where: String
orderBy: String
}
"Pair (source-row column index, target-entity column name) used to build a navigation filter"
type SQLReferenceColumnMapping @since(version: "26.1.2") {
"Position in the result-set bindings"
sourceColumnIndex: Int!
"Column name in the source result set"
sourceColumnName: String!
"Ordinal position of the column in the target entity definition"
targetColumnIndex: Int!
"Column name in the target entity"
targetColumnName: String!
}
type SQLResultAssociation @since(version: "26.1.2") {
"True for reverse references (incoming FKs)"
reference: Boolean!
"Name of the association (foreign key)"
associationName: String!
"Name of the catalog the target entity belongs to"
targetCatalogName: String
"Name of the schema the target entity belongs to"
targetSchemaName: String
"Plain name of the target entity"
targetEntityName: String
"Navigator node URI of the target entity, suitable for opening it directly in the UI. Null if the entity is not present in the navigator tree"
targetNodePath: String
"List of column mappings between the source result set and the target entity"
columnMapping: [SQLReferenceColumnMapping!]!
}
type SQLResultColumn {
position: Int!
name: String
@@ -122,10 +153,12 @@ type SQLResultSet {
"Returns list of rows in the result set. Each row contains data and metadata"
rowsWithMetaData: [SQLResultRowMetaData] @since(version: "23.3.5")
# True means that resultset was generated by single entity query
# New rows can be added, old rows can be deleted
"""
True means that resultset was generated by single entity query
New rows can be added, old rows can be deleted
"""
singleEntity: Boolean!
# server always returns hasMoreData = false
"server always returns hasMoreData = false"
hasMoreData: Boolean!
"Identifies if result set has row identifier. If true then it is possible update data or load LOB files"
hasRowIdentifier: Boolean! @deprecated (reason: "use rowIdentifierState (25.3.4)")
@@ -182,7 +215,7 @@ type SQLQueryResults {
updateRowCount: Float
sourceQuery: String
# Actual data format of this result
"Actual data format of this result"
dataFormat: ResultDataFormat
resultSet: SQLResultSet
@@ -190,17 +223,17 @@ type SQLQueryResults {
type SQLExecuteInfo {
# Status message
"Status message"
statusMessage: String
# Execute time (ms)
"Execute time (ms)"
duration: Int!
# Actual conditions applied to query
"Actual conditions applied to query"
filterText: String
# Full query that was executed, contains all used filters
"Full query that was executed, contains all used filters"
fullQuery: String
# Original query that was executed, without modifications
"Original query that was executed, without modifications"
originalQuery: String
# Results
"Results"
results: [ SQLQueryResults! ]!
}
@@ -265,6 +298,8 @@ type SQLQueryGenerator {
input SQLQueryGeneratorOptions {
useFullyQualifiedNames: Boolean!
compactSql: Boolean!
"Include nested objects, comments and permissions in generated DDL (since 26.0.4)"
showFullDdl: Boolean
}
####################################################
@@ -312,6 +347,15 @@ type TransactionLogInfos {
extend type Query {
"Foreign-key navigation metadata for the given result set. Set isReference to true for reverse references, false for forward associations, or omit it to get both"
sqlResultAssociations(
projectId: ID,
connectionId: ID!,
contextId: ID!,
resultsId: ID!,
isReference: Boolean
): [SQLResultAssociation!]! @since(version: "26.1.2")
"Returns SQL dialect info for the specified connection"
sqlDialectInfo( projectId: ID, connectionId: ID! ): SQLDialectInfo
@@ -357,7 +401,7 @@ extend type Query {
options: Object @deprecated(reason: "use generatorOptions (26.0.3)")
nodePathList: [String!]!,
generatorOptions: SQLQueryGeneratorOptions
): String!
): String! @deprecated(reason: "use asyncSqlGenerateEntityQuery")
"""
Returns an auto-generated SQL query based on provided rows data.
@@ -553,6 +597,13 @@ extend type Mutation {
"Returns row count for async SQL row data count task"
asyncSqlRowDataCountResult(taskId: ID!): Int!
"Creates async task to generate entity SQL. Generated SQL is returned in the taskResult field"
asyncSqlGenerateEntityQuery(
generatorId: String!,
nodePathList: [String!]!,
generatorOptions: SQLQueryGeneratorOptions
): AsyncTaskInfo!
"Reads dynamic trace from provided database results"
sqlGetDynamicTrace(
projectId: ID,
@@ -1,6 +1,6 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2025 DBeaver Corp and others
* Copyright (C) 2010-2026 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.
@@ -38,7 +38,9 @@ import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.DBPDataSourceContainer;
import org.jkiss.dbeaver.model.app.DBPDataSourceRegistry;
import org.jkiss.dbeaver.model.app.DBPProject;
import org.jkiss.dbeaver.model.connection.DBPConnectionConfiguration;
import org.jkiss.dbeaver.model.connection.DBPDriver;
import org.jkiss.dbeaver.model.impl.PropertyDescriptor;
import org.jkiss.dbeaver.model.navigator.DBNContainer;
import org.jkiss.dbeaver.model.navigator.DBNDataSource;
import org.jkiss.dbeaver.model.navigator.DBNNode;
@@ -47,6 +49,8 @@ import org.jkiss.dbeaver.model.preferences.DBPPropertyDescriptor;
import org.jkiss.dbeaver.model.rm.RMProjectType;
import org.jkiss.dbeaver.registry.DataSourceNavigatorSettings;
import org.jkiss.dbeaver.runtime.properties.PropertyCollector;
import org.jkiss.dbeaver.runtime.properties.PropertySourceCustom;
import org.jkiss.utils.ArrayUtils;
import org.jkiss.utils.CommonUtils;
import java.io.InputStream;
@@ -190,4 +194,52 @@ public class WebServiceUtils extends WebCommonUtils {
|| (node instanceof DBNResourceManagerResource
&& ((DBNResourceManagerResource) node).getResource().isFolder());
}
@NotNull
public static WebPropertyInfo[] getDriverProperties(
@NotNull WebSession webSession,
@NotNull DBPDriver driver,
@Nullable DBPDataSourceContainer dataSourceContainer,
@NotNull DBPConnectionConfiguration cfg
) {
try {
DBPPropertyDescriptor[] properties = driver.getDataSourceProvider().getConnectionProperties(
webSession.getProgressMonitor(),
driver,
dataSourceContainer,
cfg
);
Map<String, Object> connectionProperties = driver.getConnectionProperties();
for (Map.Entry<String, Object> connProp : connectionProperties.entrySet()) {
String propName = connProp.getKey();
Object propValue = connProp.getValue();
DBPPropertyDescriptor dbpPropertyDescriptor = new PropertyDescriptor(
null,
propName,
propName,
null,
false,
String.class,
propValue,
null
);
properties = ArrayUtils.add(DBPPropertyDescriptor.class, properties, dbpPropertyDescriptor);
cfg.setProperty(propName, (String) propValue);
}
if (properties == null) {
return new WebPropertyInfo[0];
}
PropertySourceCustom propertySource = new PropertySourceCustom(
properties,
cfg.getProperties()
);
return Arrays.stream(properties)
.map(p -> new WebPropertyInfo(webSession, p, propertySource)).toArray(WebPropertyInfo[]::new);
} catch (DBException e) {
log.error("Error reading driver properties:\n" + e.getMessage());
return new WebPropertyInfo[0];
}
}
}
@@ -1,6 +1,6 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2025 DBeaver Corp and others
* Copyright (C) 2010-2026 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.
@@ -19,11 +19,13 @@ package io.cloudbeaver.model;
import io.cloudbeaver.DBWebException;
import io.cloudbeaver.WebServiceUtils;
import io.cloudbeaver.model.session.WebSession;
import io.cloudbeaver.server.CBConstants;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.DBConstants;
import org.jkiss.dbeaver.model.DatabaseURL;
import org.jkiss.dbeaver.model.connection.*;
import org.jkiss.dbeaver.model.impl.PropertyDescriptor;
import org.jkiss.dbeaver.model.impl.auth.AuthModelDatabaseNative;
import org.jkiss.dbeaver.model.meta.Property;
import org.jkiss.dbeaver.model.preferences.DBPPropertyDescriptor;
@@ -177,47 +179,28 @@ public class WebDatabaseDriverInfo {
return driver.getDefaultConnectionProperties();
}
@NotNull
@Property
public WebPropertyInfo[] getDriverProperties() throws DBWebException {
try {
DBPConnectionConfiguration cfg = new DBPConnectionConfiguration();
cfg.setUrl(CommonUtils.notEmpty(driver.getSampleURL()));
cfg.setHostName(DBConstants.HOST_LOCALHOST);
cfg.setHostPort(driver.getDefaultPort());
cfg.setDatabaseName(driver.getDefaultDatabase());
DatabaseURL.Pattern dbUrlPattern = DatabaseURL.getUrlPattern(CommonUtils.notEmpty(driver.getSampleURL()));
for (String propName : dbUrlPattern.getMandatoryPropertyNames()) {
switch (propName) {
case DBConstants.PROP_HOST -> cfg.setHostName(CBConstants.HOST_LOCALHOST);
case DBConstants.PROP_PORT -> cfg.setHostPort(CommonUtils.notNull(driver.getDefaultPort(), "0"));
case DBConstants.PROP_SERVER -> cfg.setServerName(CommonUtils.notNull(driver.getDefaultServer(), propName));
case DBConstants.PROP_USER -> cfg.setUserName(CommonUtils.notNull(driver.getDefaultUser(), propName));
case DBConstants.PROP_DATABASE, DBConstants.PROP_FOLDER, DBConstants.PROP_FILE ->
cfg.setDatabaseName(CommonUtils.notNull(driver.getDefaultDatabase(), propName));
default -> log.debug("Unexpected mandatory URL property " + propName);
}
}
cfg.setUrl(driver.getConnectionURL(cfg));
DBPPropertyDescriptor[] properties = driver.getDataSourceProvider().getConnectionProperties(webSession.getProgressMonitor(), driver, cfg);
Map<String, Object> connectionProperties = driver.getConnectionProperties();
for (Map.Entry<String, Object> connProp : connectionProperties.entrySet()) {
String propName = connProp.getKey();
Object propValue = connProp.getValue();
DBPPropertyDescriptor dbpPropertyDescriptor = new PropertyDescriptor(
null,
propName,
propName,
null,
false,
String.class,
propValue,
null
);
properties = ArrayUtils.add(DBPPropertyDescriptor.class, properties, dbpPropertyDescriptor);
cfg.setProperty(propName, (String) propValue);
}
if (properties == null) {
return new WebPropertyInfo[0];
}
PropertySourceCustom propertySource = new PropertySourceCustom(
properties,
cfg.getProperties());
return Arrays.stream(properties)
.map(p -> new WebPropertyInfo(webSession, p, propertySource)).toArray(WebPropertyInfo[]::new);
return WebServiceUtils.getDriverProperties(webSession, driver, null, cfg);
} catch (DBException e) {
log.error("Error reading driver properties:\n" + e.getMessage());
return new WebPropertyInfo[0];
throw new DBWebException("Error obtaining driver properties", e);
}
}
@@ -24,16 +24,20 @@ import io.cloudbeaver.model.session.WebSession;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.jkiss.code.NotNull;
import org.jkiss.code.NotNullWhen;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.DBException;
import java.util.Collection;
public interface WebAppSessionManager {
@Nullable
BaseWebSession closeSession(@NotNull HttpServletRequest request);
@Nullable
BaseWebSession closeSession(@NotNull String sessionId);
@Nullable
BaseWebSession closeSession(@NotNull String sessionId, boolean sendSessionExpiredEvent);
@NotNull
@@ -53,21 +57,25 @@ public interface WebAppSessionManager {
BaseWebSession getSession(@NotNull String sessionId);
@Nullable
WebSession findWebSession(HttpServletRequest request);
WebSession findWebSession(@NotNull HttpServletRequest request);
WebSession findWebSession(HttpServletRequest request, boolean errorOnNoFound) throws DBWebException;
@NotNullWhen("errorOnNoFound")
WebSession findWebSession(@NotNull HttpServletRequest request, boolean errorOnNoFound) throws DBWebException;
@NotNull
Collection<BaseWebSession> getAllActiveSessions();
WebSession getOrRestoreWebSession(WebHttpRequestInfo httpRequest);
@NotNull
WebSession getOrRestoreWebSession(@NotNull WebHttpRequestInfo httpRequest);
@NotNullWhen("!create")
WebHeadlessSession getHeadlessSession(
@Nullable String smAccessToken,
@NotNull WebHttpRequestInfo requestInfo,
boolean create
) throws DBException;
boolean touchSession(HttpServletRequest request, HttpServletResponse response) throws DBWebException;
boolean touchSession(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response) throws DBWebException;
default void expireIdleSessions() {
@@ -1,6 +1,6 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2024 DBeaver Corp and others
* Copyright (C) 2010-2026 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.
@@ -22,6 +22,7 @@ import io.cloudbeaver.model.app.WebAppConfiguration;
import io.cloudbeaver.model.app.WebServerConfiguration;
import io.cloudbeaver.registry.WebDriverRegistry;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import java.net.InetAddress;
import java.util.List;
@@ -54,6 +55,7 @@ public interface WebApplication extends ServletApplication {
boolean isLicenseValid();
@Nullable
String getLicenseStatus();
@NotNull
@@ -1,6 +1,6 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2024 DBeaver Corp and others
* Copyright (C) 2010-2026 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.
@@ -18,14 +18,18 @@ package io.cloudbeaver.server.events;
import io.cloudbeaver.model.session.BaseWebSession;
import io.cloudbeaver.server.WebAppUtils;
import io.cloudbeaver.utils.WebEventUtils;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.websocket.WSEventHandler;
import org.jkiss.dbeaver.model.websocket.event.WSEvent;
import java.util.Collection;
import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Collectors;
public class WSDefaultEventHandler<EVENT extends WSEvent> implements WSEventHandler<EVENT> {
public abstract class WSDefaultEventHandler<EVENT extends WSEvent> implements WSEventHandler<EVENT> {
private static final Log log = Log.getLog(WSDefaultEventHandler.class);
@@ -34,19 +38,24 @@ public class WSDefaultEventHandler<EVENT extends WSEvent> implements WSEventHand
if (!WebAppUtils.isWebApplication()) {
return;
}
log.debug(event.getTopicId() + " event handled");
Collection<BaseWebSession> allSessions = WebAppUtils.getWebApplication()
.getSessionManager()
.getAllActiveSessions();
for (var activeUserSession : allSessions) {
if (!isAcceptableInSession(activeUserSession, event)) {
log.debug("Cannot handle " + event.getTopicId() + " event '" + event.getId() +
"' in session " + activeUserSession.getSessionId());
continue;
}
log.debug(event.getTopicId() + " event '" + event.getId() + "' handled");
updateSessionData(activeUserSession, event);
Consumer<BaseWebSession> consumer = getEventConsumer(event);
if (consumer == null) {
return;
}
Set<String> sessionIds = WebAppUtils.getWebApplication().getSessionManager().getAllActiveSessions().stream()
.filter(session -> isAcceptableInSession(session, event))
.peek(consumer)
.map(session -> session.getUserContext().getSmSessionId())
.collect(Collectors.toSet());
if (!sessionIds.isEmpty()) {
log.debug(event.getTopicId() + " event '" + event.getId() + "' handled in sessions: " + String.join(", ", sessionIds));
}
}
@Nullable
protected Consumer<BaseWebSession> getEventConsumer(@NotNull EVENT event) {
return (session) -> updateSessionData(session, event);
}
protected void updateSessionData(@NotNull BaseWebSession activeUserSession, @NotNull EVENT event) {
@@ -54,6 +63,6 @@ public class WSDefaultEventHandler<EVENT extends WSEvent> implements WSEventHand
}
protected boolean isAcceptableInSession(@NotNull BaseWebSession activeUserSession, @NotNull EVENT event) {
return !WSWebUtils.isSessionIdEquals(activeUserSession, event.getSessionId()); // skip events from current session
return !WebEventUtils.isSmSessionIdEquals(activeUserSession, event.getSessionId()); // skip events from current session
}
}
@@ -1,6 +1,6 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2024 DBeaver Corp and others
* Copyright (C) 2010-2026 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.
@@ -19,6 +19,7 @@ package io.cloudbeaver.server.events;
import io.cloudbeaver.server.BaseWebPlatform;
import io.cloudbeaver.server.WebAppUtils;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.runtime.VoidProgressMonitor;
import org.jkiss.dbeaver.model.websocket.WSEventHandler;
@@ -33,7 +34,10 @@ public class WSDeleteTempFileHandler implements WSEventHandler<WSEventDeleteTemp
private static final Log log = Log.getLog(WSDeleteTempFileHandler.class);
public void resetTempFolder(String sessionId) {
public void resetTempFolder(@Nullable String sessionId) {
if (sessionId == null) {
return;
}
Path path = WebAppUtils.getWebPlatform()
.getTempFolder(new VoidProgressMonitor(), BaseWebPlatform.TEMP_FILE_FOLDER)
.resolve(sessionId);
@@ -1,6 +1,6 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2024 DBeaver Corp and others
* Copyright (C) 2010-2026 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.
@@ -18,6 +18,7 @@ package io.cloudbeaver.server.events;
import io.cloudbeaver.model.WebServerMessage;
import io.cloudbeaver.model.session.BaseWebSession;
import io.cloudbeaver.utils.WebEventUtils;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.model.websocket.event.WSSessionLogUpdatedEvent;
@@ -28,6 +29,6 @@ public class WSLogEventHandler extends WSDefaultEventHandler<WSSessionLogUpdated
}
protected boolean isAcceptableInSession(@NotNull BaseWebSession activeUserSession, @NotNull WSSessionLogUpdatedEvent event) {
return WSWebUtils.isSessionIdEquals(activeUserSession, event.getSessionId());
return WebEventUtils.isSmSessionIdEquals(activeUserSession, event.getSessionId());
}
}
@@ -0,0 +1,56 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2026 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.server.events;
import io.cloudbeaver.WebSessionProjectImpl;
import io.cloudbeaver.model.session.BaseWebSession;
import io.cloudbeaver.model.session.WebSession;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.Log;
import org.jkiss.dbeaver.model.websocket.event.datasource.WSNetworkProfileEvent;
import org.jkiss.dbeaver.runtime.DBWorkbench;
public class WSNetworkProfileEventHandler extends WSDefaultEventHandler<WSNetworkProfileEvent> {
private static final Log log = Log.getLog(WSNetworkProfileEventHandler.class);
@Override
protected void updateSessionData(@NotNull BaseWebSession activeUserSession, @NotNull WSNetworkProfileEvent event) {
if (event.getProjectId() != null) {
if (activeUserSession instanceof WebSession webSession) {
WebSessionProjectImpl project = webSession.getProjectById(event.getProjectId());
if (project == null) {
log.debug("Project " + event.getProjectId() + " is not found in session " + webSession.getSessionId());
return;
}
project.getDataSourceRegistry().getNetworkProfiles().reloadProfiles();
} else {
super.updateSessionData(activeUserSession, event);
}
} else {
DBWorkbench.getPlatform().getNetworkProfiles().reloadProfiles();
super.updateSessionData(activeUserSession, event);
}
}
@Override
protected boolean isAcceptableInSession(@NotNull BaseWebSession activeUserSession, @NotNull WSNetworkProfileEvent event) {
if (event.getProjectId() != null && !activeUserSession.isProjectAccessible(event.getProjectId())) {
return false;
}
return super.isAcceptableInSession(activeUserSession, event);
}
}
@@ -1,6 +1,6 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2024 DBeaver Corp and others
* Copyright (C) 2010-2026 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.
@@ -18,6 +18,7 @@ package io.cloudbeaver.server.events;
import io.cloudbeaver.DBWConstants;
import io.cloudbeaver.model.session.BaseWebSession;
import io.cloudbeaver.utils.WebEventUtils;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.DBException;
import org.jkiss.dbeaver.Log;
@@ -54,7 +55,7 @@ public class WSProjectUpdatedEventHandler extends WSAbstractProjectEventHandler<
@Override
protected boolean isAcceptableInSession(@NotNull BaseWebSession activeUserSession, @NotNull WSProjectUpdateEvent event) {
return !WSWebUtils.isSessionIdEquals(activeUserSession, event.getSessionId()) &&
return !WebEventUtils.isSmSessionIdEquals(activeUserSession, event.getSessionId()) &&
(!event.getId().equals(WSProjectUpdateEvent.ADDED) ||
activeUserSession.getUserContext().hasPermission(DBWConstants.PERMISSION_ADMIN));
}
@@ -1,39 +0,0 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2022 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.server.events;
import io.cloudbeaver.model.session.BaseWebSession;
import io.cloudbeaver.model.session.WebSession;
import org.jkiss.code.NotNull;
import org.jkiss.code.Nullable;
import java.util.Objects;
public class WSWebUtils {
public static boolean isSessionIdEquals(@NotNull BaseWebSession webSession, @Nullable String sessionId) {
if (sessionId == null) {
return false;
}
if (Objects.equals(webSession.getSessionId(), sessionId)) {
return true;
}
if (webSession instanceof WebSession) {
return Objects.equals(webSession.getUserContext().getSmSessionId(), sessionId);
}
return false;
}
}
@@ -1,6 +1,6 @@
/*
* DBeaver - Universal Database Manager
* Copyright (C) 2010-2024 DBeaver Corp and others
* Copyright (C) 2010-2026 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.
@@ -19,17 +19,15 @@ package io.cloudbeaver.server.jobs;
import io.cloudbeaver.model.session.BaseWebSession;
import io.cloudbeaver.model.session.WebSession;
import io.cloudbeaver.server.WebAppSessionManager;
import io.cloudbeaver.utils.WebEventUtils;
import org.jkiss.code.NotNull;
import org.jkiss.dbeaver.model.DBPDataSource;
import org.jkiss.dbeaver.model.app.DBPPlatform;
import org.jkiss.dbeaver.model.app.DBPProject;
import org.jkiss.dbeaver.model.websocket.event.datasource.WSDataSourceDisconnectEvent;
import org.jkiss.dbeaver.model.websocket.event.datasource.WSDataSourceEvent;
import org.jkiss.dbeaver.model.websocket.event.datasource.WSDataSourceProperty;
import org.jkiss.dbeaver.runtime.jobs.DataSourceMonitorJob;
import java.util.Collection;
import java.util.List;
/**
* Web data source monitor job.
@@ -62,7 +60,7 @@ public class WebDataSourceMonitorJob extends DataSourceMonitorJob {
new WSDataSourceDisconnectEvent(
project.getId(),
dataSource.getContainer().getId(),
webSession.getSessionId(),
WebEventUtils.getSmSessionId(webSession),
webSession.getUserId()
)
);

Some files were not shown because too many files have changed in this diff Show More