mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-10-16 14:50:15 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f7218fb819 | ||
|
|
4162aeb942 | ||
|
|
544cd0fa5b | ||
|
|
9aace7c0ce | ||
|
|
168fb9c272 | ||
|
|
0f253672dd | ||
|
|
41861efb8d | ||
|
|
d719008944 | ||
|
|
1330b95580 | ||
|
|
027b986757 | ||
|
|
7db7049fe3 | ||
|
|
d6cd15c5e6 | ||
|
|
b66fce12e2 | ||
|
|
1d5dc1468b | ||
|
|
5f26449f30 | ||
|
|
0f1cac99f3 | ||
|
|
c5182b298f | ||
|
|
071fec6b77 | ||
|
|
82fa392ff4 | ||
|
|
b865948f0d | ||
|
|
22c6cfc82b | ||
|
|
0faf4f7076 | ||
|
|
56333d524e | ||
|
|
7a14f903ba | ||
|
|
ba881a242d | ||
|
|
6784715ba4 | ||
|
|
b9210072ab | ||
|
|
3557e54d1f | ||
|
|
046a540ff8 | ||
|
|
b5f884efcb | ||
|
|
da0ea15f17 | ||
|
|
5041798447 | ||
|
|
9f092b83d0 | ||
|
|
89df586a6e | ||
|
|
9eb32a0428 | ||
|
|
c671532ebf | ||
|
|
a9d1d42378 | ||
|
|
e9601257a3 | ||
|
|
d5dcdaff15 | ||
|
|
a37aae9c23 | ||
|
|
33205ad78a | ||
|
|
94041e9b44 | ||
|
|
7517bdac71 | ||
|
|
b0e3deccb4 | ||
|
|
9ea97aa54e | ||
|
|
0175d66c33 | ||
|
|
883d71e387 | ||
|
|
95be398806 | ||
|
|
65bbe89875 | ||
|
|
982485b312 | ||
|
|
4d7ea213d4 | ||
|
|
9bfe982a4c | ||
|
|
a41a1308e7 | ||
|
|
5cb45878c4 | ||
|
|
674569795a | ||
|
|
6a998a030c | ||
|
|
2a448cb6a4 | ||
|
|
fb72d2a15a | ||
|
|
3ee3758969 | ||
|
|
4c38b08b1d | ||
|
|
b317966e47 | ||
|
|
939a6042cb | ||
|
|
1e62fcf3e3 | ||
|
|
b1614dd237 | ||
|
|
eed97a392e | ||
|
|
1c68241fe0 | ||
|
|
6067c0a384 | ||
|
|
27f748da73 | ||
|
|
7a36620f11 | ||
|
|
7e92d4b36f | ||
|
|
58b508ceaf | ||
|
|
a0ee9a0e4a | ||
|
|
7b05e9bba6 | ||
|
|
b5f645a864 | ||
|
|
0ed32eb3e8 | ||
|
|
bbee98292d | ||
|
|
46e406c9b1 | ||
|
|
931ede5056 | ||
|
|
4a55f5a425 | ||
|
|
96b9ebf3f6 | ||
|
|
dbfccc8cb9 | ||
|
|
ac39d453c0 | ||
|
|
0a9e8a7a0c | ||
|
|
bb76f01886 | ||
|
|
aa8189c9eb | ||
|
|
b68f6cce3b | ||
|
|
16398bbec4 | ||
|
|
a9bede499a | ||
|
|
1f9e5e12c0 | ||
|
|
a74e29daf8 | ||
|
|
4cb5828b6f | ||
|
|
2eaf272197 | ||
|
|
100341a724 | ||
|
|
68bcb4500c | ||
|
|
6bc5bb4ae8 | ||
|
|
e3c02ed8f5 | ||
|
|
942372fd6a | ||
|
|
76106d3e25 | ||
|
|
bed9c984c0 | ||
|
|
7d410a6460 | ||
|
|
934092510f | ||
|
|
ecd5c6fd2e | ||
|
|
2de8ec84a5 | ||
|
|
22276de1ba | ||
|
|
bceefc19f4 | ||
|
|
ab43d60ecc | ||
|
|
281c63a47d | ||
|
|
7d3fdf9643 | ||
|
|
eb1ff96487 | ||
|
|
a2dbeb8d20 | ||
|
|
dcddb57cee | ||
|
|
c0f9d8d232 | ||
|
|
7f06dd5632 | ||
|
|
987d8aaa6f | ||
|
|
6003684277 | ||
|
|
03b83ebf73 | ||
|
|
a06097b464 | ||
|
|
c2abce61db | ||
|
|
7e78859957 | ||
|
|
9c38508009 | ||
|
|
b7670d15d2 | ||
|
|
cdd4ecc50c | ||
|
|
2f7c674ab9 | ||
|
|
a3366ef3fe | ||
|
|
0ef0b319aa | ||
|
|
8b4d59079a | ||
|
|
038d38879f | ||
|
|
694302f41c | ||
|
|
582924335c | ||
|
|
d8d929ecda | ||
|
|
2818824965 | ||
|
|
3050cd8b45 | ||
|
|
a2b7b6701d | ||
|
|
128c3c310b | ||
|
|
bd2d518eed | ||
|
|
ebe24f7e97 | ||
|
|
3c3d2f9b35 | ||
|
|
50a898b75a | ||
|
|
db83920588 | ||
|
|
4f8b2e1494 | ||
|
|
db1ea4451e | ||
|
|
0f00c234d3 | ||
|
|
2fc9f36ddb | ||
|
|
63186a17c4 | ||
|
|
2cbdba177a | ||
|
|
3fd5f4d011 | ||
|
|
35901cbf15 | ||
|
|
69aaaf00b7 | ||
|
|
f61ac47c1c | ||
|
|
13a0fc258c | ||
|
|
072646c9e0 | ||
|
|
807365f42c | ||
|
|
30c450efb7 | ||
|
|
d20cda4398 | ||
|
|
d4b9bdd3c2 | ||
|
|
91bec0b813 | ||
|
|
2bb259379a | ||
|
|
da0055fb75 | ||
|
|
17f9b70dc9 | ||
|
|
215b557273 | ||
|
|
9ccf56f7d4 | ||
|
|
e5d6ad121d | ||
|
|
5779100b9a | ||
|
|
6c456c8a63 | ||
|
|
13888efe95 | ||
|
|
1493f18e0e | ||
|
|
3e2530ec55 | ||
|
|
985cc8078b | ||
|
|
a8df087958 | ||
|
|
9e2a6ce35a | ||
|
|
a68737f329 | ||
|
|
5117dcc106 | ||
|
|
8d47238938 | ||
|
|
ee1433af49 | ||
|
|
1b5a5ac5fa | ||
|
|
60c320708a | ||
|
|
272690b8c1 | ||
|
|
77c493d5fa | ||
|
|
571830f1ae | ||
|
|
9522b176f5 | ||
|
|
9a69f4e660 | ||
|
|
a62ac973dc | ||
|
|
e9081598e3 | ||
|
|
923dadee86 | ||
|
|
6ed92dab14 | ||
|
|
e6d3458855 | ||
|
|
d19dfd0c8f | ||
|
|
583d342c8b | ||
|
|
ef93be4842 | ||
|
|
a46c5fc974 | ||
|
|
21a9e78381 | ||
|
|
a5b9041cf0 | ||
|
|
b561a8f707 | ||
|
|
43f50f2ff3 | ||
|
|
96a163c50e | ||
|
|
36061a03c4 | ||
|
|
a9e727a9d2 | ||
|
|
1220e4ba38 | ||
|
|
f58f2a3c90 | ||
|
|
bb3ee1d822 | ||
|
|
ca378a4e53 | ||
|
|
9b728aec67 | ||
|
|
b83cd0d883 | ||
|
|
ad9cebdaf9 | ||
|
|
669ad9cb66 | ||
|
|
5aa474a000 | ||
|
|
53ea6dce4f | ||
|
|
e899e49cb6 | ||
|
|
fc518b2ef5 | ||
|
|
a09c63d639 | ||
|
|
f0e5e639dc | ||
|
|
df585f1852 | ||
|
|
6953e6fa9a | ||
|
|
b4d31d396d | ||
|
|
081dcfcda5 | ||
|
|
b710f55684 | ||
|
|
da688df4f9 | ||
|
|
c8d29fe57f | ||
|
|
d5828c2689 | ||
|
|
bcbfd7e2df | ||
|
|
8ba210bd81 | ||
|
|
8293cd4515 | ||
|
|
e4e1e179c0 | ||
|
|
1c0dbb15f6 | ||
|
|
0a04d60512 | ||
|
|
edfd4ad063 | ||
|
|
4ea74d92f8 | ||
|
|
07781c3c85 | ||
|
|
e8bf1baf51 | ||
|
|
ef8a4809fa | ||
|
|
c3d6490efb | ||
|
|
76a440c482 | ||
|
|
660c175c66 | ||
|
|
772864451e | ||
|
|
65c2631d43 | ||
|
|
5a0558731d | ||
|
|
e68269efc1 | ||
|
|
6075fe0003 | ||
|
|
65bb6661be | ||
|
|
9b48c42a59 | ||
|
|
9b8f52aaf6 | ||
|
|
bf7e23ebb4 | ||
|
|
1e45a8185e | ||
|
|
90a3c561a4 | ||
|
|
d3894a487c | ||
|
|
cecc47a3d1 | ||
|
|
88a23978ee | ||
|
|
afe39be839 | ||
|
|
da9ff59cae | ||
|
|
07a636b57f | ||
|
|
76d4b49ac0 | ||
|
|
0ecadc2617 | ||
|
|
9972c9aa60 | ||
|
|
6179ed2202 | ||
|
|
3f5e9a45cd | ||
|
|
f997c09575 | ||
|
|
a319b1fec3 | ||
|
|
dfd572aa4c | ||
|
|
c6e8d27e31 | ||
|
|
af19435e12 | ||
|
|
6299e73bcd | ||
|
|
ec3ef25871 | ||
|
|
39135e8cb4 | ||
|
|
da010a55ff | ||
|
|
bc03a698b2 | ||
|
|
7de1d8ce66 | ||
|
|
d4f733ebd9 | ||
|
|
63329ddfc5 | ||
|
|
78d680a736 | ||
|
|
d087a4b5b0 | ||
|
|
519c6ded3f | ||
|
|
a1c0ed439d | ||
|
|
756310d8ee | ||
|
|
9949286788 | ||
|
|
229281f0aa | ||
|
|
3b27dd835d | ||
|
|
179751b34d | ||
|
|
212f4a1712 | ||
|
|
f50df1f859 | ||
|
|
c60598104a | ||
|
|
792b2725e0 | ||
|
|
067f79dca4 | ||
|
|
9fce0c897b | ||
|
|
b451fb32d6 | ||
|
|
6a3fd79858 | ||
|
|
1653f7709f | ||
|
|
e3608a2504 | ||
|
|
b3c1cebd69 | ||
|
|
0610759ac2 | ||
|
|
ff770a1270 | ||
|
|
4c7b9fca95 | ||
|
|
f98b9aa989 | ||
|
|
1ecdced23e | ||
|
|
cb60358ae6 | ||
|
|
0f9e7b650c | ||
|
|
b2eab058c9 | ||
|
|
4f0fa25d83 | ||
|
|
a3bdfb68fe | ||
|
|
584dd1ce4f | ||
|
|
5255ee96db | ||
|
|
e68c44ed73 | ||
|
|
e4f01a3fa8 | ||
|
|
a5c9073e6f | ||
|
|
b7d32ad676 | ||
|
|
a520aa1f20 | ||
|
|
8e4c0c11a4 | ||
|
|
72b3838fa9 | ||
|
|
df9de51bda | ||
|
|
390f53f36b | ||
|
|
d3cf9e3938 | ||
|
|
97dc309bcb | ||
|
|
6c609d7f62 | ||
|
|
f67835d2d2 | ||
|
|
98197c8829 | ||
|
|
997936328e | ||
|
|
f7832b56fa | ||
|
|
81ce6b6ac7 | ||
|
|
518410c2e8 | ||
|
|
4645a8e3d1 | ||
|
|
be59a4dab9 | ||
|
|
3a92d7d23d | ||
|
|
d44e6b4e7a | ||
|
|
d87115d753 | ||
|
|
245d49b892 | ||
|
|
3831abc880 | ||
|
|
e818f1658c | ||
|
|
739a6f7f11 | ||
|
|
ab985673b0 | ||
|
|
abf3e7247c | ||
|
|
49f321462e | ||
|
|
d0a820d27b | ||
|
|
bd9a18bc50 | ||
|
|
3fa1130608 | ||
|
|
fe2c7b76be | ||
|
|
4344dce700 | ||
|
|
dc402f1940 | ||
|
|
bdcda6a1fb | ||
|
|
baef7fbae6 | ||
|
|
b52c2788b1 | ||
|
|
48b9326336 | ||
|
|
37d76c428d | ||
|
|
01bcf9479d | ||
|
|
31355b81f8 | ||
|
|
226762c5f9 | ||
|
|
6b58613c83 | ||
|
|
e3f04bcbb0 | ||
|
|
c5d0e4bade | ||
|
|
45335f5dd7 | ||
|
|
ff4c453f8d | ||
|
|
be5bb95154 | ||
|
|
ece5e8f3f1 | ||
|
|
9dcd287c61 | ||
|
|
97b43c044f | ||
|
|
4550a71298 |
@@ -0,0 +1,35 @@
|
||||
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
|
||||
// README at: https://github.com/devcontainers/templates/tree/main/src/java
|
||||
{
|
||||
"name": "Java",
|
||||
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
|
||||
"image": "mcr.microsoft.com/devcontainers/java:1-17-bookworm",
|
||||
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/java:1": {
|
||||
"version": "none",
|
||||
"installMaven": "true",
|
||||
"installGradle": "false"
|
||||
},
|
||||
"ghcr.io/devcontainers/features/github-cli:1": {},
|
||||
"ghcr.io/devcontainers/features/node:1": {}
|
||||
},
|
||||
|
||||
"hostRequirements": {
|
||||
"cpus": 8,
|
||||
"memory": "16gb",
|
||||
"storage": "64gb"
|
||||
}
|
||||
|
||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||
// "forwardPorts": [],
|
||||
|
||||
// Use 'postCreateCommand' to run commands after the container is created.
|
||||
// "postCreateCommand": "java -version",
|
||||
|
||||
// Configure tool-specific properties.
|
||||
// "customizations": {},
|
||||
|
||||
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
|
||||
// "remoteUser": "root"
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
name: frontend-cache
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["devel"]
|
||||
paths:
|
||||
- "webapp/**"
|
||||
|
||||
# Allows you to run this workflow manually from the Actions tab
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build_and_test:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ./webapp
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "18"
|
||||
|
||||
- name: Get yarn cache directory path
|
||||
id: yarn-cache-dir-path
|
||||
run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: restore yarn cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-
|
||||
|
||||
- name: restore node_modules
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: ${{ runner.os }}-node_modules-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-node_modules-
|
||||
|
||||
- name: restore typescript cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: "**/packages/*/dist"
|
||||
key: ${{ runner.os }}-dist-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-dist-
|
||||
|
||||
- name: yarn install
|
||||
uses: borales/actions-yarn@v4
|
||||
with:
|
||||
dir: webapp
|
||||
cmd: install
|
||||
|
||||
- name: yarn lerna bootstrap
|
||||
uses: borales/actions-yarn@v4
|
||||
with:
|
||||
dir: webapp
|
||||
cmd: lerna bootstrap
|
||||
|
||||
- name: build
|
||||
uses: borales/actions-yarn@v4
|
||||
with:
|
||||
dir: webapp/packages/product-default
|
||||
cmd: build # build tyescript source code
|
||||
|
||||
- name: test
|
||||
uses: borales/actions-yarn@v4
|
||||
with:
|
||||
dir: webapp
|
||||
cmd: lerna run test # build packages that have test script
|
||||
@@ -0,0 +1,29 @@
|
||||
name: cleanup caches by a branch
|
||||
on:
|
||||
pull_request:
|
||||
types:
|
||||
- closed
|
||||
|
||||
jobs:
|
||||
cleanup:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Cleanup
|
||||
run: |
|
||||
gh extension install actions/gh-actions-cache
|
||||
|
||||
echo "Fetching list of cache key"
|
||||
cacheKeysForPR=$(gh actions-cache list -R $REPO -B $BRANCH -L 100 | cut -f 1 )
|
||||
|
||||
## Setting this to not fail the workflow while deleting cache keys.
|
||||
set +e
|
||||
echo "Deleting caches..."
|
||||
for cacheKey in $cacheKeysForPR
|
||||
do
|
||||
gh actions-cache delete $cacheKey -R $REPO -B $BRANCH --confirm
|
||||
done
|
||||
echo "Done"
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
REPO: ${{ github.repository }}
|
||||
BRANCH: refs/pull/${{ github.event.pull_request.number }}/merge
|
||||
@@ -0,0 +1,80 @@
|
||||
name: frontend
|
||||
|
||||
on:
|
||||
# Triggers the workflow on push or pull request events but only for the "devel" branch
|
||||
pull_request:
|
||||
branches: ["devel"]
|
||||
paths:
|
||||
- "webapp/**" # monitor for the frontend changes
|
||||
|
||||
# Allows you to run this workflow manually from the Actions tab
|
||||
workflow_dispatch:
|
||||
|
||||
# Allows you to reuse workflows by referencing their YAML files
|
||||
workflow_call:
|
||||
|
||||
jobs:
|
||||
build_and_test:
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ./webapp
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "20"
|
||||
|
||||
- name: Get yarn cache directory path
|
||||
id: yarn-cache-dir-path
|
||||
run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: restore yarn cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-
|
||||
|
||||
- name: restore node_modules
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: "**/node_modules"
|
||||
key: ${{ runner.os }}-node_modules-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-node_modules-
|
||||
|
||||
- name: restore typescript cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: "**/packages/*/dist"
|
||||
key: ${{ runner.os }}-dist-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-dist-
|
||||
|
||||
- name: yarn install
|
||||
uses: borales/actions-yarn@v4
|
||||
with:
|
||||
dir: webapp
|
||||
cmd: install
|
||||
|
||||
- name: yarn lerna bootstrap
|
||||
uses: borales/actions-yarn@v4
|
||||
with:
|
||||
dir: webapp
|
||||
cmd: lerna bootstrap
|
||||
|
||||
- name: build
|
||||
uses: borales/actions-yarn@v4
|
||||
with:
|
||||
dir: webapp/packages/product-default
|
||||
cmd: bundle
|
||||
|
||||
- name: test
|
||||
uses: borales/actions-yarn@v4
|
||||
with:
|
||||
dir: webapp
|
||||
cmd: lerna run test
|
||||
@@ -1,72 +0,0 @@
|
||||
name: Run Jest Tests
|
||||
|
||||
# Controls when the workflow will run
|
||||
on:
|
||||
# Triggers the workflow on push or pull request events but only for the "devel" branch
|
||||
pull_request:
|
||||
branches: ["devel"]
|
||||
paths:
|
||||
- "webapp/**" # monitor for the frontend changes
|
||||
|
||||
# Allows you to run this workflow manually from the Actions tab
|
||||
workflow_dispatch:
|
||||
|
||||
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
|
||||
jobs:
|
||||
# This workflow contains a single job called "build"
|
||||
run-jest-tests:
|
||||
# The type of runner that the job will run on
|
||||
runs-on: ubuntu-latest
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ./webapp
|
||||
# Steps represent a sequence of tasks that will be executed as part of the job
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "18"
|
||||
|
||||
- name: Cache node modules
|
||||
id: cache-npm
|
||||
uses: actions/cache@v3
|
||||
env:
|
||||
cache-name: cache-node-modules
|
||||
with:
|
||||
# npm cache files are stored in `~/.npm` on Linux/macOS
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-build-${{ env.cache-name }}-
|
||||
${{ runner.os }}-build-
|
||||
${{ runner.os }}-
|
||||
|
||||
- if: ${{ steps.cache-npm.outputs.cache-hit != 'true' }}
|
||||
name: List the state of node modules
|
||||
continue-on-error: true
|
||||
run: npm list
|
||||
|
||||
- name: Run install
|
||||
uses: borales/actions-yarn@v4
|
||||
with:
|
||||
dir: webapp
|
||||
cmd: install
|
||||
|
||||
- name: Run lerna bootstrap
|
||||
uses: borales/actions-yarn@v4
|
||||
with:
|
||||
dir: webapp
|
||||
cmd: lerna bootstrap
|
||||
|
||||
- name: Run pre test
|
||||
uses: borales/actions-yarn@v4
|
||||
with:
|
||||
dir: webapp
|
||||
cmd: pretest
|
||||
|
||||
- name: Run test
|
||||
uses: borales/actions-yarn@v4
|
||||
with:
|
||||
dir: webapp
|
||||
cmd: lerna run test
|
||||
@@ -1,4 +1,4 @@
|
||||
name: "Commit Message Validation"
|
||||
name: validation
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
@@ -11,7 +11,7 @@ on:
|
||||
- edited
|
||||
- ready_for_review
|
||||
- labeled
|
||||
|
||||
|
||||
jobs:
|
||||
validate-commit-message:
|
||||
uses: dbeaver/dbeaver/.github/workflows/reused-commit-msgs-validator.yml@devel
|
||||
commit-message:
|
||||
uses: dbeaver/dbeaver/.github/workflows/reused-commit-msgs-validator.yml@devel
|
||||
Vendored
+13
-4
@@ -5,9 +5,18 @@
|
||||
"type": "chrome",
|
||||
"request": "launch",
|
||||
"name": "Chrome",
|
||||
"url": "http://127.0.0.1:3100",
|
||||
"url": "http://localhost:8080",
|
||||
"webRoot": "${workspaceFolder}/..",
|
||||
"sourceMaps": true
|
||||
"sourceMaps": true,
|
||||
"sourceMapPathOverrides": {
|
||||
"webpack:///*": "${workspaceFolder}/../*"
|
||||
},
|
||||
"skipFiles": [
|
||||
"<node_internals>/**",
|
||||
"**/node_modules/**",
|
||||
"${workspaceFolder}/webapp/**/node_modules/**/*.js",
|
||||
"${workspaceFolder}/webapp/**/dist/**/*.js"
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "java",
|
||||
@@ -21,7 +30,7 @@
|
||||
"request": "launch",
|
||||
"mainClass": "org.eclipse.equinox.launcher.Main",
|
||||
"classPaths": [
|
||||
"${workspaceFolder}/../eclipse/eclipse/plugins/org.eclipse.equinox.launcher_1.6.400.v20210924-0641.jar"
|
||||
"${workspaceFolder}/../eclipse/eclipse/plugins/org.eclipse.equinox.launcher_1.6.600.v20231106-1826.jar"
|
||||
],
|
||||
"args": [
|
||||
"-product",
|
||||
@@ -56,7 +65,7 @@
|
||||
"request": "launch",
|
||||
"mainClass": "org.eclipse.equinox.launcher.Main",
|
||||
"classPaths": [
|
||||
"${workspaceFolder}/../eclipse/Eclipse.app/Contents/Eclipse/plugins/org.eclipse.equinox.launcher_1.6.400.v20210924-0641.jar"
|
||||
"${workspaceFolder}/../eclipse/Eclipse.app/Contents/Eclipse/plugins/org.eclipse.equinox.launcher_1.6.600.v20231106-1826.jar"
|
||||
],
|
||||
"args": [
|
||||
"-product",
|
||||
|
||||
Vendored
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"license": {
|
||||
"scope": "typescript,typescriptreact,javascript,javascriptreact",
|
||||
"scope": "typescript,typescriptreact,javascript,javascriptreact,css,scss",
|
||||
"prefix": "license",
|
||||
"body": [
|
||||
"/*",
|
||||
|
||||
Vendored
+1
-1
@@ -9,6 +9,7 @@
|
||||
"java.jdt.ls.vmargs": "-XX:+UseParallelGC -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -Dsun.zip.disableMemoryMapping=true -Xmx16G -Xms100m -Xlog:disable",
|
||||
"java.compile.nullAnalysis.mode": "automatic",
|
||||
|
||||
"typescript.preferences.useAliasesForRenames": false,
|
||||
"typescript.preferences.importModuleSpecifier": "relative",
|
||||
"typescript.preferences.includePackageJsonAutoImports": "on",
|
||||
"typescript.preferences.quoteStyle": "single",
|
||||
@@ -21,7 +22,6 @@
|
||||
"typescript",
|
||||
"typescriptreact"
|
||||
],
|
||||
"eslint.packageManager": "yarn",
|
||||
"eslint.workingDirectories": ["webapp"],
|
||||
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
|
||||
Vendored
+10
-16
@@ -13,7 +13,7 @@
|
||||
},
|
||||
"tasks": [
|
||||
{
|
||||
"label": "Run Tests",
|
||||
"label": "Run Tests CE",
|
||||
"type": "shell",
|
||||
"command": "yarn",
|
||||
"group": "test",
|
||||
@@ -53,19 +53,13 @@
|
||||
{
|
||||
"label": "Yarn Install",
|
||||
"type": "shell",
|
||||
"command": "yarn",
|
||||
"args": []
|
||||
},
|
||||
{
|
||||
"label": "Lerna Bootstrap",
|
||||
"type": "shell",
|
||||
"command": "yarn",
|
||||
"args": ["lerna", "bootstrap"]
|
||||
},
|
||||
{
|
||||
"label": "Bootstrap",
|
||||
"dependsOrder": "sequence",
|
||||
"dependsOn": ["Yarn Install", "Lerna Bootstrap"]
|
||||
"command": "yarn install; yarn lerna bootstrap",
|
||||
"args": [],
|
||||
"presentation": {
|
||||
"reveal": "silent",
|
||||
"close": true,
|
||||
"clear": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
@@ -73,8 +67,8 @@
|
||||
"type": "pickString",
|
||||
"id": "stage.ce",
|
||||
"description": "CE Stage servers",
|
||||
"default": "http://127.0.0.1:8978/",
|
||||
"options": ["http://127.0.0.1:8978/"]
|
||||
"default": "http://localhost:8978/",
|
||||
"options": ["http://localhost:8978/"]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -22,47 +22,41 @@ You can see live demo of CloudBeaver here: https://demo.cloudbeaver.io
|
||||
|
||||
## Changelog
|
||||
|
||||
### CloudBeaver 23.2.1 - 2023-09-25
|
||||
|
||||
- The Output tab has been implemented, which includes warnings, info and notices generated by the database when executing user queries;
|
||||
- Scrollbars have been made theme-independent, resolving interface issues with light theme;
|
||||
- Fixed an issue in the SQL editor where it was not possible to switch the active schema when working with Oracle databases;
|
||||
- Different bug fixes and enhancements have been made.
|
||||
|
||||
|
||||
23.2.0 - 2023-09-04
|
||||
|
||||
### 23.3.1, 2023-12-25
|
||||
- Performance:
|
||||
- Pagination has been added to the Navigation tree and metadata viewer, allowing working with more than 1000 database items;
|
||||
- Access Management:
|
||||
- Access permissions can be specified for pre-configured connections via the configuration file;
|
||||
- Reverse Proxy authentication now includes the option to provide users' First name and Last name;
|
||||
- Authorization:
|
||||
- The SSL option is now available for establishing connections in MySQL, PostgreSQL, Clickhouse;
|
||||
- Connections:
|
||||
- Connections are consistently displayed now when they are pre-configured into the workspace in the Global Configuration json file
|
||||
- Navigation tree:
|
||||
- The filters for the Navigation tree now allow hiding and showing schemas within the interface.
|
||||
- The search request considers file names and excludes the .sql file extension for now;
|
||||
- Data Editor:
|
||||
- The ability to rearrange columns in the Data Editor has been added;
|
||||
- The ability to use custom functions in the Grouping panel has been added;
|
||||
- Administration:
|
||||
- New Settings panel displays the product configuration settings such as Minimum fetch size, Maximum fetch size, and Default fetch size from the Data Editor;
|
||||
- "Connection Management" tab has been renamed to "Connection Templates" - now only connection templates are displayed;
|
||||
- SQL Editor:
|
||||
- Users can simultaneously edit resources for now, allowing them to work together;
|
||||
- Support for displaying tables with nested arrays of objects has been added;
|
||||
- The ability to compress export files allowed to increase in download speed, especially for larger files;
|
||||
- UX in the search bar has been improved - users can delete a query or request by clicking on the cross icon;
|
||||
- Upgraded to Jetty 11, delivering improved performance, enhanced features, and better alignment with the latest Java specifications.
|
||||
- Resource management:
|
||||
- Read-only scripts now have a padlock icon.
|
||||
- UX improvement:
|
||||
- Added validation for mandatory fields in all forms for creating and editing entities.
|
||||
- Driver management:
|
||||
- Custom settings have been added to the interface for the following dialogue connections: SQLite, DB2, SQL Server, MySQL, Oracle and PostgreSQL;
|
||||
- Trino driver has been updated;
|
||||
- Security:
|
||||
- Password autofill functionality was removed;
|
||||
- The "eye" icon for password fields has been removed - the passwords entered into fields will not be displayed in the interface for now;
|
||||
- Apache Derby driver has been removed because of the vulnerability issues.
|
||||
- Many small bug fixes, enhancements, and improvements have been made
|
||||
|
||||
### Changes since 23.2.0:
|
||||
|
||||
- Security:
|
||||
- Unauthorized access vulnerability was fixed;
|
||||
- All embedded drivers are disabled by default. Administrators can re-enable them in the Server configuration.
|
||||
- Access Management:
|
||||
- Administrators have gained the ability to permanently delete users and their data.
|
||||
- Authorization:
|
||||
- The SSL option is available for establishing a connection in SQL Server.
|
||||
- Connections:
|
||||
- The 'Save credentials' checkbox has been removed from a template creating form as credentials are not stored in templates.
|
||||
- SQL Editor:
|
||||
- Support for using custom delimiters has been added in MySQL;
|
||||
- The Output tab has been implemented, which includes warnings, info, and notices generated by the database when executing user queries;
|
||||
- Fixed an issue in the SQL editor where it was impossible to switch the active schema when working with Oracle databases;
|
||||
- Added ability to select shared connections for private scripts;
|
||||
- Private connections can be chosen for shared scripts, but this change won’t be saved to the script file.
|
||||
- Data Editor:
|
||||
- Scrollbars have been made theme-independent;
|
||||
- Added the ability to edit binary values in a table;
|
||||
- Added the ability to count the total number of entries in the table.
|
||||
- Driver management:
|
||||
- Updated the version of the Clickhouse driver to 0.4.6.
|
||||
- Many small bug fixes, enhancements, and improvements have been made
|
||||
|
||||
### Old CloudBeaver releases
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
{
|
||||
subjectId: "user",
|
||||
name: "User",
|
||||
description: "Standard user",
|
||||
description: "All users, including anonymous.",
|
||||
permissions: [ ]
|
||||
}
|
||||
]
|
||||
|
||||
@@ -16,14 +16,11 @@
|
||||
maxLogRecords: 2000,
|
||||
maxFailedRequests: 3
|
||||
}
|
||||
},
|
||||
authentication: {
|
||||
primaryAuthProvider: 'local'
|
||||
}
|
||||
},
|
||||
// Notifications config
|
||||
core_events: {
|
||||
notificationsPool: 5
|
||||
notificationsPool: 20
|
||||
},
|
||||
plugin_data_spreadsheet_new: {
|
||||
hidden: false
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
contentRoot: "web",
|
||||
driversLocation: "drivers",
|
||||
|
||||
sslConfigurationPath:"${CLOUDBEAVER_SSL_CONF_PATH:workspace/.data/ssl-config.xml}",
|
||||
|
||||
rootURI: "/",
|
||||
serviceURI: "/api/",
|
||||
|
||||
@@ -17,6 +19,13 @@
|
||||
|
||||
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}"
|
||||
},
|
||||
|
||||
database: {
|
||||
driver="h2_embedded_v2",
|
||||
url: "jdbc:h2:${workspace}/.data/cb.h2v2.dat",
|
||||
|
||||
Executable
+61
@@ -0,0 +1,61 @@
|
||||
#!/bin/bash
|
||||
set -Eeo pipefail
|
||||
set +u
|
||||
|
||||
# #command line arguments
|
||||
# CONFIGURATION_PATH=${1-"../config/sample-databases/DefaultConfiguration"}
|
||||
# SAMPLE_DATABASE_PATH=${2-""}
|
||||
|
||||
# echo $CONFIGURATION_PATH
|
||||
# echo $SAMPLE_DATABASE_PATH
|
||||
echo "Clone and build Cloudbeaver"
|
||||
|
||||
rm -rf ./drivers
|
||||
rm -rf ./cloudbeaver
|
||||
mkdir ./cloudbeaver
|
||||
mkdir ./cloudbeaver/server
|
||||
mkdir ./cloudbeaver/conf
|
||||
mkdir ./cloudbeaver/workspace
|
||||
mkdir ./cloudbeaver/web
|
||||
|
||||
echo "Pull cloudbeaver platform"
|
||||
|
||||
cd ../..
|
||||
|
||||
echo "Pull dbeaver platform"
|
||||
[ ! -d dbeaver ] && git clone https://github.com/dbeaver/dbeaver.git
|
||||
|
||||
cd cloudbeaver/deploy
|
||||
|
||||
echo "Build CloudBeaver server"
|
||||
|
||||
cd ../server/product/aggregate
|
||||
mvn clean verify $MAVEN_COMMON_OPTS -Dheadless-platform
|
||||
if [[ "$?" -ne 0 ]] ; then
|
||||
echo 'Could not perform package'; exit $rc
|
||||
fi
|
||||
cd ../../../deploy
|
||||
|
||||
echo "Copy server packages"
|
||||
|
||||
cp -rp ../server/product/web-server/target/products/io.cloudbeaver.product/all/all/all/* ./cloudbeaver/server
|
||||
cp -p ./scripts/* ./cloudbeaver
|
||||
mkdir cloudbeaver/samples
|
||||
|
||||
if [[ -z $SAMPLE_DATABASE_PATH ]]; then
|
||||
SAMPLE_DATABASE_PATH=""
|
||||
else
|
||||
mkdir cloudbeaver/samples/db
|
||||
cp -rp "${SAMPLE_DATABASE_PATH}" cloudbeaver/samples/
|
||||
fi
|
||||
|
||||
if [[ -z "$CONFIGURATION_PATH" ]]; then
|
||||
CONFIGURATION_PATH="../config/sample-databases/DefaultConfiguration"
|
||||
fi
|
||||
|
||||
cp -rp ../config/core/* cloudbeaver/conf
|
||||
cp -rp "${CONFIGURATION_PATH}"/GlobalConfiguration/.dbeaver/data-sources.json cloudbeaver/conf/initial-data-sources.conf
|
||||
cp -p "${CONFIGURATION_PATH}"/*.conf cloudbeaver/conf/
|
||||
mv drivers cloudbeaver
|
||||
|
||||
echo "End of backend build"
|
||||
Executable
+21
@@ -0,0 +1,21 @@
|
||||
#!/bin/bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
echo "Build static content"
|
||||
|
||||
cd ../../cloudbeaver/webapp
|
||||
|
||||
yarn
|
||||
yarn lerna run bootstrap
|
||||
yarn lerna run bundle --no-bail --stream --scope=@cloudbeaver/product-default #-- -- --env source-map
|
||||
if [[ "$?" -ne 0 ]] ; then
|
||||
echo 'Application build failed'; exit $rc
|
||||
fi
|
||||
|
||||
cd ../deploy
|
||||
|
||||
echo "Copy static content"
|
||||
|
||||
cp -rp ../webapp/packages/product-default/lib/* cloudbeaver/web
|
||||
|
||||
echo "Cloudbeaver is ready. Run run-server.bat in cloudbeaver folder to start the server."
|
||||
@@ -1 +1,9 @@
|
||||
./build.sh '../config/sample-databases/SQLiteConfiguration' '../config/sample-databases/db'
|
||||
#!/bin/bash
|
||||
set -Eeuo pipefail
|
||||
|
||||
#command line arguments
|
||||
CONFIGURATION_PATH='../config/sample-databases/SQLiteConfiguration'
|
||||
SAMPLE_DATABASE_PATH='../config/sample-databases/db'
|
||||
|
||||
source build-backend.sh
|
||||
source build-frontend.sh
|
||||
+1
-1
@@ -57,7 +57,7 @@ cd ..\cloudbeaver\webapp
|
||||
|
||||
call yarn
|
||||
call yarn lerna bootstrap
|
||||
call yarn lerna run build --no-bail --stream --scope=@cloudbeaver/product-default &::-- -- --env source-map
|
||||
call yarn lerna run bundle --no-bail --stream --scope=@cloudbeaver/product-default &::-- -- --env source-map
|
||||
|
||||
cd ..\deploy
|
||||
|
||||
|
||||
+4
-66
@@ -2,70 +2,8 @@
|
||||
set -Eeuo pipefail
|
||||
|
||||
#command line arguments
|
||||
CONFIGURATION_PATH=${1-"../config/sample-databases/DefaultConfiguration"}
|
||||
SAMPLE_DATABASE_PATH=${2-""}
|
||||
CONFIGURATION_PATH="../config/sample-databases/DefaultConfiguration"
|
||||
SAMPLE_DATABASE_PATH=""
|
||||
|
||||
echo "Clone and build Cloudbeaver"
|
||||
|
||||
rm -rf ./drivers
|
||||
rm -rf ./cloudbeaver
|
||||
mkdir ./cloudbeaver
|
||||
mkdir ./cloudbeaver/server
|
||||
mkdir ./cloudbeaver/conf
|
||||
mkdir ./cloudbeaver/workspace
|
||||
mkdir ./cloudbeaver/web
|
||||
|
||||
echo "Pull cloudbeaver platform"
|
||||
|
||||
cd ../..
|
||||
|
||||
echo "Pull dbeaver platform"
|
||||
[ ! -d dbeaver ] && git clone https://github.com/dbeaver/dbeaver.git
|
||||
|
||||
cd cloudbeaver/deploy
|
||||
|
||||
echo "Build CloudBeaver server"
|
||||
|
||||
cd ../server/product/aggregate
|
||||
mvn clean verify -U -Dheadless-platform
|
||||
if [[ "$?" -ne 0 ]] ; then
|
||||
echo 'Could not perform package'; exit $rc
|
||||
fi
|
||||
cd ../../../deploy
|
||||
|
||||
echo "Copy server packages"
|
||||
|
||||
cp -rp ../server/product/web-server/target/products/io.cloudbeaver.product/all/all/all/* ./cloudbeaver/server
|
||||
cp -p ./scripts/* ./cloudbeaver
|
||||
mkdir cloudbeaver/samples
|
||||
|
||||
if [[ ! -z "${SAMPLE_DATABASE_PATH}" ]]; then
|
||||
mkdir cloudbeaver/samples/db
|
||||
cp -rp "${SAMPLE_DATABASE_PATH}" cloudbeaver/samples/
|
||||
fi
|
||||
|
||||
cp -rp ../config/core/* cloudbeaver/conf
|
||||
cp -rp "${CONFIGURATION_PATH}"/GlobalConfiguration/.dbeaver/data-sources.json cloudbeaver/conf/initial-data-sources.conf
|
||||
cp -p "${CONFIGURATION_PATH}"/*.conf cloudbeaver/conf/
|
||||
mv drivers cloudbeaver
|
||||
|
||||
echo "Build static content"
|
||||
|
||||
cd ../
|
||||
|
||||
cd ../cloudbeaver/webapp
|
||||
|
||||
yarn
|
||||
yarn lerna run bootstrap
|
||||
yarn lerna run build --no-bail --stream --scope=@cloudbeaver/product-default #-- -- --env source-map
|
||||
if [[ "$?" -ne 0 ]] ; then
|
||||
echo 'Application build failed'; exit $rc
|
||||
fi
|
||||
|
||||
cd ../deploy
|
||||
|
||||
echo "Copy static content"
|
||||
|
||||
cp -rp ../webapp/packages/product-default/lib/* cloudbeaver/web
|
||||
|
||||
echo "Cloudbeaver is ready. Run run-server.bat in cloudbeaver folder to start the server."
|
||||
source build-backend.sh
|
||||
source build-frontend.sh
|
||||
@@ -1,4 +1,48 @@
|
||||
FROM eclipse-temurin:17.0.4.1_1-jre-focal
|
||||
FROM ubuntu:23.04
|
||||
|
||||
MAINTAINER DBeaver Corp, devops@dbeaver.com
|
||||
|
||||
RUN set -eux; \
|
||||
apt-get update; \
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
||||
# curl required for historical reasons, see https://github.com/adoptium/containers/issues/255
|
||||
curl \
|
||||
wget \
|
||||
# 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
|
||||
fontconfig \
|
||||
# utilities for keeping Ubuntu and OpenJDK CA certificates in sync
|
||||
# https://github.com/adoptium/containers/issues/293
|
||||
ca-certificates p11-kit \
|
||||
# jlink --strip-debug on 13+ needs objcopy: https://github.com/docker-library/openjdk/issues/351
|
||||
# Error: java.io.IOException: Cannot run program "objcopy": error=2, No such file or directory
|
||||
binutils \
|
||||
tzdata \
|
||||
# locales ensures proper character encoding and locale-specific behaviors using en_US.UTF-8
|
||||
locales \
|
||||
nano \
|
||||
; \
|
||||
echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen; \
|
||||
locale-gen en_US.UTF-8; \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ENV LANG=en_US.UTF-8
|
||||
|
||||
ENV JAVA_HOME=/opt/java/openjdk
|
||||
COPY --from=eclipse-temurin:17 $JAVA_HOME $JAVA_HOME
|
||||
ENV PATH="${JAVA_HOME}/bin:${PATH}"
|
||||
|
||||
RUN set -eux; \
|
||||
# https://github.com/docker-library/openjdk/issues/331#issuecomment-498834472
|
||||
find "$JAVA_HOME/lib" -name '*.so' -exec dirname '{}' ';' | sort -u > /etc/ld.so.conf.d/docker-openjdk.conf; \
|
||||
ldconfig; \
|
||||
# https://github.com/docker-library/openjdk/issues/212#issuecomment-420979840
|
||||
# https://openjdk.java.net/jeps/341
|
||||
java -Xshare:dump;
|
||||
|
||||
### Patch java security
|
||||
COPY java.security* ${JAVA_HOME}/conf/security/java.security
|
||||
|
||||
COPY cloudbeaver /opt/cloudbeaver
|
||||
|
||||
|
||||
@@ -10,4 +10,38 @@ IF NOT EXIST workspace\.metadata (
|
||||
)
|
||||
)
|
||||
|
||||
java %JAVA_OPTS% --add-modules=ALL-SYSTEM --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.reflect=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.nio=ALL-UNNAMED --add-opens=java.base/java.nio.charset=ALL-UNNAMED --add-opens=java.base/java.text=ALL-UNNAMED --add-opens=java.base/java.time=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED --add-opens=java.base/jdk.internal.vm=ALL-UNNAMED --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 --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED -jar %launcherJar% -product io.cloudbeaver.product.ce.product -web-config conf/cloudbeaver.conf -nl en -registryMultiLanguage
|
||||
SET VMARGS_OPTS = ""
|
||||
If Not Defined JAVA_OPTS (
|
||||
SET VMARGS_OPTS = "-Xmx2048M"
|
||||
)
|
||||
|
||||
java %JAVA_OPTS% ^
|
||||
-Dfile.encoding=UTF-8 ^
|
||||
--add-modules=ALL-SYSTEM ^
|
||||
--add-opens=java.base/java.io=ALL-UNNAMED ^
|
||||
--add-opens=java.base/java.lang=ALL-UNNAMED ^
|
||||
--add-opens=java.base/java.lang.reflect=ALL-UNNAMED ^
|
||||
--add-opens=java.base/java.net=ALL-UNNAMED ^
|
||||
--add-opens=java.base/java.nio=ALL-UNNAMED ^
|
||||
--add-opens=java.base/java.nio.charset=ALL-UNNAMED ^
|
||||
--add-opens=java.base/java.text=ALL-UNNAMED ^
|
||||
--add-opens=java.base/java.time=ALL-UNNAMED ^
|
||||
--add-opens=java.base/java.util=ALL-UNNAMED ^
|
||||
--add-opens=java.base/java.util.concurrent=ALL-UNNAMED ^
|
||||
--add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED ^
|
||||
--add-opens=java.base/jdk.internal.vm=ALL-UNNAMED ^
|
||||
--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 ^
|
||||
--add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED ^
|
||||
--add-opens=java.sql/java.sql=ALL-UNNAMED ^
|
||||
-jar %launcherJar% ^
|
||||
-product io.cloudbeaver.product.ce.product ^
|
||||
-data %workspacePath% ^
|
||||
-web-config conf/cloudbeaver.conf ^
|
||||
-nl en ^
|
||||
-registryMultiLanguage
|
||||
|
||||
@@ -4,6 +4,37 @@ launcherJar=( server/plugins/org.eclipse.equinox.launcher*.jar )
|
||||
|
||||
echo "Starting Cloudbeaver Server"
|
||||
|
||||
[ ! -d "workspace/.metadata" ] && mkdir -p workspace/.metadata && mkdir -p workspace/GlobalConfiguration/.dbeaver && [ ! -f "workspace/GlobalConfiguration/.dbeaver/data-sources.json" ] && cp conf/initial-data-sources.conf workspace/GlobalConfiguration/.dbeaver/data-sources.json
|
||||
[ ! -d "workspace/.metadata" ] && mkdir -p workspace/.metadata \
|
||||
&& mkdir -p workspace/GlobalConfiguration/.dbeaver \
|
||||
&& [ ! -f "workspace/GlobalConfiguration/.dbeaver/data-sources.json" ] \
|
||||
&& cp conf/initial-data-sources.conf workspace/GlobalConfiguration/.dbeaver/data-sources.json
|
||||
|
||||
java ${JAVA_OPTS} --add-modules=ALL-SYSTEM --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.reflect=ALL-UNNAMED --add-opens=java.base/java.net=ALL-UNNAMED --add-opens=java.base/java.nio=ALL-UNNAMED --add-opens=java.base/java.nio.charset=ALL-UNNAMED --add-opens=java.base/java.text=ALL-UNNAMED --add-opens=java.base/java.time=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.base/java.util.concurrent=ALL-UNNAMED --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED --add-opens=java.base/jdk.internal.vm=ALL-UNNAMED --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 --add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED -jar ${launcherJar} -product io.cloudbeaver.product.ce.product -web-config conf/cloudbeaver.conf -nl en -registryMultiLanguage
|
||||
java ${JAVA_OPTS} \
|
||||
-Dfile.encoding=UTF-8 \
|
||||
--add-modules=ALL-SYSTEM \
|
||||
--add-opens=java.base/java.io=ALL-UNNAMED \
|
||||
--add-opens=java.base/java.lang=ALL-UNNAMED \
|
||||
--add-opens=java.base/java.lang.reflect=ALL-UNNAMED \
|
||||
--add-opens=java.base/java.net=ALL-UNNAMED \
|
||||
--add-opens=java.base/java.nio=ALL-UNNAMED \
|
||||
--add-opens=java.base/java.nio.charset=ALL-UNNAMED \
|
||||
--add-opens=java.base/java.text=ALL-UNNAMED \
|
||||
--add-opens=java.base/java.time=ALL-UNNAMED \
|
||||
--add-opens=java.base/java.util=ALL-UNNAMED \
|
||||
--add-opens=java.base/java.util.concurrent=ALL-UNNAMED \
|
||||
--add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED \
|
||||
--add-opens=java.base/jdk.internal.vm=ALL-UNNAMED \
|
||||
--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 \
|
||||
--add-opens=java.base/java.util.concurrent.atomic=ALL-UNNAMED \
|
||||
--add-opens=java.sql/java.sql=ALL-UNNAMED \
|
||||
-jar ${launcherJar} \
|
||||
-product io.cloudbeaver.product.ce.product \
|
||||
-web-config conf/cloudbeaver.conf \
|
||||
-nl en \
|
||||
-registryMultiLanguage
|
||||
|
||||
@@ -3,12 +3,12 @@ Bundle-ManifestVersion: 2
|
||||
Bundle-Vendor: DBeaver Corp
|
||||
Bundle-Name: Cloudbeaver Web Model
|
||||
Bundle-SymbolicName: io.cloudbeaver.model;singleton:=true
|
||||
Bundle-Version: 1.0.38.qualifier
|
||||
Bundle-Release-Date: 20230209
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-11
|
||||
Bundle-Version: 1.0.44.qualifier
|
||||
Bundle-Release-Date: 20240108
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-17
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Bundle-ClassPath: .
|
||||
Require-Bundle: org.jkiss.dbeaver.data.gis;visibility:=reexport,
|
||||
Require-Bundle: org.jkiss.dbeaver.data.gis;visibility:=reexport,
|
||||
org.jkiss.dbeaver.model;visibility:=reexport,
|
||||
org.jkiss.dbeaver.model.sm;visibility:=reexport,
|
||||
org.jkiss.dbeaver.model.event;visibility:=reexport,
|
||||
@@ -18,7 +18,7 @@ Require-Bundle: org.jkiss.dbeaver.data.gis;visibility:=reexport,
|
||||
org.jkiss.bundle.graphql.java;visibility:=reexport,
|
||||
org.jkiss.bundle.apache.dbcp,
|
||||
com.google.gson;visibility:=reexport,
|
||||
jakarta.servlet-api;visibility:=reexport
|
||||
jakarta.servlet;visibility:=reexport
|
||||
Export-Package: io.cloudbeaver,
|
||||
io.cloudbeaver.auth,
|
||||
io.cloudbeaver.auth.provider,
|
||||
@@ -27,12 +27,13 @@ Export-Package: io.cloudbeaver,
|
||||
io.cloudbeaver.websocket,
|
||||
io.cloudbeaver.model,
|
||||
io.cloudbeaver.model.app,
|
||||
io.cloudbeaver.model.fs,
|
||||
io.cloudbeaver.model.rm,
|
||||
io.cloudbeaver.model.rm.local,
|
||||
io.cloudbeaver.model.rm.lock,
|
||||
io.cloudbeaver.model.rm.fs.nio,
|
||||
io.cloudbeaver.model.session,
|
||||
io.cloudbeaver.model.user,
|
||||
io.cloudbeaver.model.utils,
|
||||
io.cloudbeaver.registry,
|
||||
io.cloudbeaver.server,
|
||||
io.cloudbeaver.service,
|
||||
|
||||
@@ -19,4 +19,9 @@
|
||||
</metaParameters>
|
||||
</extension>
|
||||
|
||||
<extension point="com.dbeaver.secretController">
|
||||
<controller id="void-secret" class="io.cloudbeaver.model.app.VoidSecretController"
|
||||
label="Default secret controller" description="Default void secret controller"/>
|
||||
</extension>
|
||||
|
||||
</plugin>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<relativePath>../</relativePath>
|
||||
</parent>
|
||||
<artifactId>io.cloudbeaver.model</artifactId>
|
||||
<version>1.0.38-SNAPSHOT</version>
|
||||
<version>1.0.44-SNAPSHOT</version>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -14,11 +14,6 @@
|
||||
<meta.element />
|
||||
</appInfo>
|
||||
</annotation>
|
||||
<complexType>
|
||||
<sequence>
|
||||
<element ref="propertyGroup"/>
|
||||
</sequence>
|
||||
</complexType>
|
||||
</element>
|
||||
|
||||
<element name="driver">
|
||||
|
||||
@@ -62,6 +62,12 @@ public class BaseWebProjectImpl extends BaseProjectImpl implements RMControllerP
|
||||
return resourceController;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public RMProject getRMProject() {
|
||||
return project;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isVirtual() {
|
||||
return true;
|
||||
|
||||
+3
@@ -41,6 +41,9 @@ public interface SMAuthProviderFederated {
|
||||
@Nullable
|
||||
String getMetadataLink(String id, @NotNull Map<String, Object> providerConfig) throws DBException;
|
||||
|
||||
@Nullable
|
||||
String getAcsLink(String id, @NotNull Map<String, Object> providerConfig) throws DBException;
|
||||
|
||||
@Nullable
|
||||
default String getRedirectLink(String id, @NotNull Map<String, Object> providerConfig) throws DBException {
|
||||
return null;
|
||||
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* DBeaver - Universal Database Manager
|
||||
* Copyright (C) 2010-2023 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.auth;
|
||||
|
||||
import org.jkiss.code.NotNull;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface SMBruteForceProtected {
|
||||
Object getInputUsername(@NotNull Map<String, Object> cred);
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
package io.cloudbeaver.model;
|
||||
|
||||
import org.jkiss.code.NotNull;
|
||||
import org.jkiss.dbeaver.DBException;
|
||||
import org.jkiss.dbeaver.model.DBPDataSourceContainer;
|
||||
import org.jkiss.dbeaver.model.DBPDataSourceHandler;
|
||||
import org.jkiss.dbeaver.model.connection.DBPDriver;
|
||||
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
|
||||
|
||||
public abstract class BaseDatasourceAccessCheckHandler implements DBPDataSourceHandler {
|
||||
@Override
|
||||
public void beforeConnect(
|
||||
DBRProgressMonitor monitor,
|
||||
@NotNull DBPDataSourceContainer dataSourceContainer
|
||||
) throws DBException {
|
||||
if (isDriverDisabled(dataSourceContainer.getDriver())) {
|
||||
throw new DBException("Driver disabled");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeDisconnect(
|
||||
DBRProgressMonitor monitor,
|
||||
@NotNull DBPDataSourceContainer dataSourceContainer
|
||||
) throws DBException {
|
||||
|
||||
}
|
||||
|
||||
protected abstract boolean isDriverDisabled(DBPDriver driver);
|
||||
}
|
||||
+11
-2
@@ -18,8 +18,14 @@ package io.cloudbeaver.model;
|
||||
|
||||
import org.jkiss.code.NotNull;
|
||||
import org.jkiss.dbeaver.model.net.DBWHandlerConfiguration;
|
||||
import org.jkiss.dbeaver.model.net.DBWHandlerDescriptor;
|
||||
import org.jkiss.dbeaver.model.net.DBWHandlerType;
|
||||
import org.jkiss.dbeaver.model.net.ssh.SSHConstants;
|
||||
import org.jkiss.dbeaver.model.preferences.DBPPropertyDescriptor;
|
||||
import org.jkiss.dbeaver.model.preferences.DBPPropertySource;
|
||||
import org.jkiss.dbeaver.model.runtime.VoidProgressMonitor;
|
||||
import org.jkiss.dbeaver.registry.RegistryConstants;
|
||||
import org.jkiss.dbeaver.runtime.properties.PropertySourceMap;
|
||||
import org.jkiss.utils.CommonUtils;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
@@ -83,8 +89,11 @@ public class WebNetworkHandlerConfig {
|
||||
@NotNull
|
||||
public Map<String, String> getSecureProperties() {
|
||||
Map<String, String> secureProperties = new LinkedHashMap<>(configuration.getSecureProperties());
|
||||
for (Map.Entry<String, String> property : secureProperties.entrySet()) {
|
||||
property.setValue(CommonUtils.isEmpty(property.getValue()) ? null : WebConnectionInfo.SECURED_VALUE);
|
||||
DBPPropertyDescriptor[] descriptor = configuration.getHandlerDescriptor().getHandlerProperties();
|
||||
for (DBPPropertyDescriptor p : descriptor) {
|
||||
if (p.hasFeature(RegistryConstants.ATTR_PASSWORD)) {
|
||||
secureProperties.computeIfPresent(p.getId(), (k, v) -> CommonUtils.isEmpty(v) ? null : WebConnectionInfo.SECURED_VALUE);
|
||||
}
|
||||
}
|
||||
return secureProperties;
|
||||
}
|
||||
|
||||
@@ -88,6 +88,11 @@ public class WebPropertyInfo {
|
||||
}
|
||||
}
|
||||
|
||||
@Property
|
||||
public String getHint() {
|
||||
return property.getHint();
|
||||
}
|
||||
|
||||
@Property
|
||||
public int getOrder() {
|
||||
return property instanceof ObjectPropertyDescriptor ? ((ObjectPropertyDescriptor) property).getOrderNumber() : -1;
|
||||
@@ -168,6 +173,11 @@ public class WebPropertyInfo {
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
@Property
|
||||
public boolean isRequired() {
|
||||
return property.isRequired();
|
||||
}
|
||||
|
||||
public boolean hasFeature(@NotNull String feature) {
|
||||
return property.hasFeature(feature);
|
||||
}
|
||||
|
||||
+27
-2
@@ -16,6 +16,8 @@
|
||||
*/
|
||||
package io.cloudbeaver.model.app;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import io.cloudbeaver.DataSourceFilter;
|
||||
import io.cloudbeaver.WebProjectImpl;
|
||||
import io.cloudbeaver.WebSessionProjectImpl;
|
||||
@@ -33,6 +35,7 @@ import org.jkiss.dbeaver.model.DBFileController;
|
||||
import org.jkiss.dbeaver.model.app.DBPPlatform;
|
||||
import org.jkiss.dbeaver.model.app.DBPWorkspace;
|
||||
import org.jkiss.dbeaver.model.auth.SMCredentialsProvider;
|
||||
import org.jkiss.dbeaver.model.auth.SMSessionContext;
|
||||
import org.jkiss.dbeaver.model.data.json.JSONUtils;
|
||||
import org.jkiss.dbeaver.model.impl.app.ApplicationRegistry;
|
||||
import org.jkiss.dbeaver.model.rm.RMController;
|
||||
@@ -142,6 +145,14 @@ public abstract class BaseWebApplication extends BaseApplicationImpl implements
|
||||
return null;
|
||||
}
|
||||
|
||||
public Path getLogbackConfigPath() {
|
||||
Path configFilePath = getMainConfigurationFilePath().toAbsolutePath();
|
||||
Path configFolder = configFilePath.getParent();
|
||||
|
||||
// Configure logging
|
||||
return getLogbackConfigPath(configFolder);
|
||||
}
|
||||
|
||||
private Path getMainConfigurationFilePath() {
|
||||
String configPath = DEFAULT_CONFIG_FILE_PATH;
|
||||
|
||||
@@ -189,11 +200,14 @@ public abstract class BaseWebApplication extends BaseApplicationImpl implements
|
||||
* Advanced apps may implement it differently.
|
||||
*/
|
||||
@Override
|
||||
public DBSSecretController getSecretController(@NotNull SMCredentialsProvider credentialsProvider) throws DBException {
|
||||
public DBSSecretController getSecretController(
|
||||
@NotNull SMCredentialsProvider credentialsProvider,
|
||||
SMSessionContext smSessionContext
|
||||
) throws DBException {
|
||||
return VoidSecretController.INSTANCE;
|
||||
}
|
||||
|
||||
protected Map<String, Object> getServerConfigProps(Map<String, Object> configProps) {
|
||||
protected static Map<String, Object> getServerConfigProps(Map<String, Object> configProps) {
|
||||
return JSONUtils.getObject(configProps, "server");
|
||||
}
|
||||
|
||||
@@ -221,6 +235,7 @@ public abstract class BaseWebApplication extends BaseApplicationImpl implements
|
||||
|
||||
@Override
|
||||
public Object start(IApplicationContext context) {
|
||||
initializeApplicationServices();
|
||||
try {
|
||||
startServer();
|
||||
} catch (Exception e) {
|
||||
@@ -255,4 +270,14 @@ public abstract class BaseWebApplication extends BaseApplicationImpl implements
|
||||
return null;
|
||||
}
|
||||
|
||||
protected Gson getGson() {
|
||||
return getGsonBuilder().create();
|
||||
}
|
||||
|
||||
protected abstract GsonBuilder getGsonBuilder();
|
||||
|
||||
@Override
|
||||
public boolean isEnvironmentVariablesAccessible() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+11
-1
@@ -19,12 +19,15 @@ package io.cloudbeaver.model.app;
|
||||
import org.jkiss.code.NotNull;
|
||||
import org.jkiss.code.Nullable;
|
||||
import org.jkiss.dbeaver.DBException;
|
||||
import org.jkiss.dbeaver.model.auth.SMCredentialsProvider;
|
||||
import org.jkiss.dbeaver.model.auth.SMSessionContext;
|
||||
import org.jkiss.dbeaver.model.secret.DBSSecretController;
|
||||
import org.jkiss.dbeaver.model.secret.DBSSecretControllerAuthorized;
|
||||
|
||||
/**
|
||||
* Void secret controller.
|
||||
*/
|
||||
public class VoidSecretController implements DBSSecretController {
|
||||
public class VoidSecretController implements DBSSecretController, DBSSecretControllerAuthorized {
|
||||
|
||||
public static final VoidSecretController INSTANCE = new VoidSecretController();
|
||||
|
||||
@@ -47,4 +50,11 @@ public class VoidSecretController implements DBSSecretController {
|
||||
public void flushChanges() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void authorize(
|
||||
@Nullable SMCredentialsProvider credentialsProvider,
|
||||
@Nullable SMSessionContext smSessionContext
|
||||
) throws DBException {
|
||||
|
||||
}
|
||||
}
|
||||
+5
-1
@@ -25,6 +25,7 @@ import org.jkiss.dbeaver.model.DBFileController;
|
||||
import org.jkiss.dbeaver.model.app.DBPApplication;
|
||||
import org.jkiss.dbeaver.model.app.DBPWorkspace;
|
||||
import org.jkiss.dbeaver.model.auth.SMCredentialsProvider;
|
||||
import org.jkiss.dbeaver.model.auth.SMSessionContext;
|
||||
import org.jkiss.dbeaver.model.rm.RMController;
|
||||
import org.jkiss.dbeaver.model.rm.RMProject;
|
||||
import org.jkiss.dbeaver.model.secret.DBSSecretController;
|
||||
@@ -60,7 +61,10 @@ public interface WebApplication extends DBPApplication {
|
||||
|
||||
SMAdminController getAdminSecurityController(@NotNull SMCredentialsProvider credentialsProvider) throws DBException;
|
||||
|
||||
DBSSecretController getSecretController(@NotNull SMCredentialsProvider credentialsProvider) throws DBException;
|
||||
DBSSecretController getSecretController(
|
||||
@NotNull SMCredentialsProvider credentialsProvider,
|
||||
SMSessionContext smSessionContext
|
||||
) throws DBException;
|
||||
|
||||
RMController createResourceController(
|
||||
@NotNull SMCredentialsProvider credentialsProvider,
|
||||
|
||||
+3
@@ -18,6 +18,7 @@
|
||||
package io.cloudbeaver.model.app;
|
||||
|
||||
import io.cloudbeaver.auth.CBAuthConstants;
|
||||
import org.jkiss.dbeaver.DBException;
|
||||
|
||||
public interface WebAuthApplication extends WebApplication {
|
||||
WebAuthConfiguration getAuthConfiguration();
|
||||
@@ -27,4 +28,6 @@ public interface WebAuthApplication extends WebApplication {
|
||||
default long getMaxSessionIdleTime() {
|
||||
return CBAuthConstants.MAX_SESSION_IDLE_TIME;
|
||||
}
|
||||
|
||||
void flushConfiguration() throws DBException;
|
||||
}
|
||||
|
||||
+3
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
package io.cloudbeaver.model.app;
|
||||
|
||||
import org.jkiss.code.NotNull;
|
||||
import org.jkiss.code.Nullable;
|
||||
import org.jkiss.dbeaver.model.security.SMAuthProviderCustomConfiguration;
|
||||
|
||||
@@ -36,4 +37,6 @@ public interface WebAuthConfiguration {
|
||||
|
||||
@Nullable
|
||||
SMAuthProviderCustomConfiguration getAuthProviderConfiguration(String configId);
|
||||
|
||||
void addAuthProviderConfiguration(@NotNull SMAuthProviderCustomConfiguration config);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* DBeaver - Universal Database Manager
|
||||
* Copyright (C) 2010-2023 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.fs;
|
||||
|
||||
import io.cloudbeaver.DBWebException;
|
||||
import io.cloudbeaver.model.session.WebSession;
|
||||
import org.jkiss.code.NotNull;
|
||||
import org.jkiss.dbeaver.DBException;
|
||||
import org.jkiss.dbeaver.model.fs.DBFVirtualFileSystem;
|
||||
import org.jkiss.dbeaver.model.navigator.DBNModel;
|
||||
import org.jkiss.dbeaver.model.navigator.DBNNode;
|
||||
import org.jkiss.dbeaver.model.navigator.fs.DBNPathBase;
|
||||
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class FSUtils {
|
||||
@NotNull
|
||||
public static String makeUniqueFsId(@NotNull DBFVirtualFileSystem fileSystem) {
|
||||
return fileSystem.getType() + "://" + fileSystem.getId();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Path getPathFromNode(@NotNull WebSession webSession, @NotNull String nodePath) throws DBException {
|
||||
DBNPathBase dbnPath = getNodeByPath(webSession, nodePath);
|
||||
Path path = dbnPath.getPath();
|
||||
if (path == null) {
|
||||
throw new DBWebException("Path from node '" + nodePath + "' is empty");
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static DBNPathBase getNodeByPath(@NotNull WebSession webSession, @NotNull String nodePath) throws DBException {
|
||||
DBRProgressMonitor monitor = webSession.getProgressMonitor();
|
||||
|
||||
DBNModel navigatorModel = webSession.getNavigatorModel();
|
||||
DBNNode node = navigatorModel.getNodeByPath(monitor, nodePath);
|
||||
if (!(node instanceof DBNPathBase dbnPath)) {
|
||||
throw new DBWebException("Node '" + nodePath + "' is not found in File Systems");
|
||||
}
|
||||
return dbnPath;
|
||||
}
|
||||
}
|
||||
+10
-3
@@ -56,19 +56,25 @@ public class DBNResourceManagerProject extends DBNAbstractResourceManagerNode {
|
||||
return project.getId();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getNodeId() {
|
||||
return project.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNodeType() {
|
||||
return "rm.project";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNodeName() {
|
||||
public String getNodeDisplayName() {
|
||||
return project.getDisplayName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLocalizedName(String locale) {
|
||||
return getNodeName();
|
||||
return getNodeDisplayName();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -105,6 +111,7 @@ public class DBNResourceManagerProject extends DBNAbstractResourceManagerNode {
|
||||
return ((DBNResourceManagerRoot) getParentNode()).getResourceController();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public String getNodeItemPath() {
|
||||
return getParentNode().getNodeItemPath() + "/" + getName();
|
||||
@@ -118,7 +125,7 @@ public class DBNResourceManagerProject extends DBNAbstractResourceManagerNode {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getNodeName();
|
||||
return getNodeDisplayName();
|
||||
}
|
||||
|
||||
|
||||
|
||||
+6
-5
@@ -55,7 +55,7 @@ public class DBNResourceManagerResource extends DBNAbstractResourceManagerNode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNodeName() {
|
||||
public String getNodeDisplayName() {
|
||||
return resource.getName();
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ public class DBNResourceManagerResource extends DBNAbstractResourceManagerNode {
|
||||
}
|
||||
return DBIcon.TREE_FOLDER;
|
||||
} else {
|
||||
var fileExtension = IOUtils.getFileExtension(getNodeName());
|
||||
var fileExtension = IOUtils.getFileExtension(getNodeDisplayName());
|
||||
if (!CommonUtils.isEmpty(fileExtension)) {
|
||||
RMProject project = getProjectNode();
|
||||
if (project != null) {
|
||||
@@ -154,9 +154,10 @@ public class DBNResourceManagerResource extends DBNAbstractResourceManagerNode {
|
||||
throw new DBException("Can't detect resource root node");
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public String getNodeItemPath() {
|
||||
return getParentNode().getNodeItemPath() + "/" + getNodeName();
|
||||
return getParentNode().getNodeItemPath() + "/" + getNodeDisplayName();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -174,7 +175,7 @@ public class DBNResourceManagerResource extends DBNAbstractResourceManagerNode {
|
||||
String resourceName = resource.getName();
|
||||
try {
|
||||
if (newName.indexOf('.') == -1) {
|
||||
String ext = IOUtils.getFileExtension(getNodeName());
|
||||
String ext = IOUtils.getFileExtension(getNodeDisplayName());
|
||||
if (!CommonUtils.isEmpty(ext)) {
|
||||
newName += "." + ext;
|
||||
}
|
||||
@@ -193,7 +194,7 @@ public class DBNResourceManagerResource extends DBNAbstractResourceManagerNode {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getNodeName();
|
||||
return getNodeDisplayName();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
+9
-7
@@ -54,8 +54,14 @@ public class DBNResourceManagerRoot extends DBNNode implements DBPHiddenObject,
|
||||
return "rm";
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String getNodeName() {
|
||||
public String getNodeId() {
|
||||
return "rm";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNodeDisplayName() {
|
||||
return "resources";
|
||||
}
|
||||
|
||||
@@ -103,10 +109,11 @@ public class DBNResourceManagerRoot extends DBNNode implements DBPHiddenObject,
|
||||
return projects;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@Override
|
||||
public String getNodeItemPath() {
|
||||
// Path doesn't include project name
|
||||
return NodePathType.ext.getPrefix() + getNodeName();
|
||||
return NodePathType.ext.getPrefix() + getNodeDisplayName();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -115,11 +122,6 @@ public class DBNResourceManagerRoot extends DBNNode implements DBPHiddenObject,
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getNodeName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHidden() {
|
||||
return true;
|
||||
|
||||
+8
-13
@@ -48,6 +48,7 @@ import org.jkiss.dbeaver.model.websocket.event.WSEventType;
|
||||
import org.jkiss.dbeaver.model.websocket.event.WSSessionLogUpdatedEvent;
|
||||
import org.jkiss.dbeaver.registry.*;
|
||||
import org.jkiss.dbeaver.runtime.DBWorkbench;
|
||||
import org.jkiss.dbeaver.utils.GeneralUtils;
|
||||
import org.jkiss.utils.ArrayUtils;
|
||||
import org.jkiss.utils.CommonUtils;
|
||||
import org.jkiss.utils.IOUtils;
|
||||
@@ -56,6 +57,7 @@ import org.jkiss.utils.Pair;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.*;
|
||||
import java.text.MessageFormat;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.util.*;
|
||||
@@ -280,7 +282,7 @@ public class LocalResourceController implements RMController {
|
||||
throw new DBException("Error creating shared project path", e);
|
||||
}
|
||||
}
|
||||
validateResourcePath(name, PROJECT_REGEX);
|
||||
validateResourcePath(name);
|
||||
RMProject project;
|
||||
var projectPath = sharedProjectsPath.resolve(name);
|
||||
if (Files.exists(projectPath)) {
|
||||
@@ -309,7 +311,8 @@ public class LocalResourceController implements RMController {
|
||||
RMProject project = makeProjectFromId(projectId, false);
|
||||
Path targetPath = getProjectPath(projectId);
|
||||
if (!Files.exists(targetPath)) {
|
||||
throw new DBException("Project '" + project.getName() + "' doesn't exists");
|
||||
log.debug(MessageFormat.format("Project folder ''{0}'' is not found", projectId));
|
||||
return;
|
||||
}
|
||||
try {
|
||||
log.debug("Deleting project '" + projectId + "'");
|
||||
@@ -459,6 +462,7 @@ public class LocalResourceController implements RMController {
|
||||
DBPDataSourceRegistry registry = project.getDataSourceRegistry();
|
||||
var result = Path.of(folderPath);
|
||||
var newName = result.getFileName().toString();
|
||||
GeneralUtils.validateResourceName(newName);
|
||||
var parent = result.getParent();
|
||||
var parentFolder = parent == null ? null : registry.getFolder(parent.toString().replace("\\", "/"));
|
||||
DBPDataSourceFolder newFolder = registry.addFolder(parentFolder, newName);
|
||||
@@ -833,19 +837,10 @@ public class LocalResourceController implements RMController {
|
||||
}
|
||||
|
||||
private void validateResourcePath(String resourcePath) throws DBException {
|
||||
validateResourcePath(resourcePath, FILE_REGEX);
|
||||
}
|
||||
|
||||
private void validateResourcePath(String resourcePath, String regex) throws DBException {
|
||||
var fullPath = Paths.get(resourcePath);
|
||||
for (Path path : fullPath) {
|
||||
if (path.toString().startsWith(".")) {
|
||||
throw new DBException("Resource path '" + resourcePath + "' can't start with dot");
|
||||
}
|
||||
}
|
||||
if (!resourcePath.matches(regex)) {
|
||||
String illegalCharacters = resourcePath.replaceAll(regex, " ").strip();
|
||||
throw new DBException("Resource path '" + resourcePath + "' contains illegal characters: " + illegalCharacters);
|
||||
String fileName = IOUtils.getFileNameWithoutExtension(path);
|
||||
GeneralUtils.validateResourceName(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+9
@@ -30,6 +30,7 @@ import org.jkiss.dbeaver.model.auth.SMSessionContext;
|
||||
import org.jkiss.dbeaver.model.auth.impl.AbstractSessionPersistent;
|
||||
import org.jkiss.dbeaver.model.meta.Property;
|
||||
import org.jkiss.dbeaver.model.websocket.event.WSEvent;
|
||||
import org.jkiss.dbeaver.model.websocket.event.WSEventDeleteTempFile;
|
||||
import org.jkiss.dbeaver.model.websocket.event.session.WSSessionExpiredEvent;
|
||||
|
||||
import java.time.Instant;
|
||||
@@ -132,6 +133,11 @@ public abstract class BaseWebSession extends AbstractSessionPersistent {
|
||||
return workspace.getAuthContext();
|
||||
}
|
||||
|
||||
protected void clearSessionContext() {
|
||||
this.workspace.getAuthContext().clear();
|
||||
this.workspace.getAuthContext().addSession(this);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Property
|
||||
public String getSessionId() {
|
||||
@@ -166,6 +172,7 @@ public abstract class BaseWebSession extends AbstractSessionPersistent {
|
||||
public void close() {
|
||||
super.close();
|
||||
var sessionExpiredEvent = new WSSessionExpiredEvent();
|
||||
application.getEventController().addEvent(new WSEventDeleteTempFile(getSessionId()));
|
||||
synchronized (sessionEventHandlers) {
|
||||
for (CBWebSessionEventHandler sessionEventHandler : sessionEventHandlers) {
|
||||
try {
|
||||
@@ -178,6 +185,8 @@ public abstract class BaseWebSession extends AbstractSessionPersistent {
|
||||
sessionEventHandlers.clear();
|
||||
|
||||
workspace.dispose();
|
||||
|
||||
clearSessionContext();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -54,7 +54,8 @@ public class WebAuthInfo implements SMSessionPrincipal {
|
||||
@NotNull WebAuthProviderDescriptor authProvider,
|
||||
@NotNull DBWUserIdentity userIdentity,
|
||||
@NotNull SMSession authSession,
|
||||
@NotNull OffsetDateTime loginTime) {
|
||||
@NotNull OffsetDateTime loginTime
|
||||
) {
|
||||
this.session = session;
|
||||
this.user = user;
|
||||
this.authProvider = authProvider;
|
||||
|
||||
+15
-24
@@ -33,6 +33,9 @@ import io.cloudbeaver.service.sql.WebSQLConstants;
|
||||
import io.cloudbeaver.utils.CBModelConstants;
|
||||
import io.cloudbeaver.utils.WebAppUtils;
|
||||
import io.cloudbeaver.utils.WebDataSourceUtils;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.http.HttpSession;
|
||||
import org.eclipse.core.runtime.IAdaptable;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
@@ -83,10 +86,6 @@ import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
/**
|
||||
* Web session.
|
||||
* Is the main source of data in web application
|
||||
@@ -99,7 +98,6 @@ public class WebSession extends BaseWebSession
|
||||
public static final SMSessionType CB_SESSION_TYPE = new SMSessionType("CloudBeaver");
|
||||
private static final String WEB_SESSION_AUTH_CONTEXT_TYPE = "web-session";
|
||||
private static final String ATTR_LOCALE = "locale";
|
||||
|
||||
private static final AtomicInteger TASK_ID = new AtomicInteger();
|
||||
|
||||
private final AtomicInteger taskCount = new AtomicInteger();
|
||||
@@ -275,28 +273,22 @@ public class WebSession extends BaseWebSession
|
||||
continue;
|
||||
}
|
||||
switch (type) {
|
||||
case DATASOURCE_CREATED: {
|
||||
case DATASOURCE_CREATED -> {
|
||||
WebConnectionInfo connectionInfo = new WebConnectionInfo(this, ds);
|
||||
this.connections.put(connectionInfo.getId(), connectionInfo);
|
||||
sendDataSourceUpdatedEvent = true;
|
||||
break;
|
||||
}
|
||||
case DATASOURCE_UPDATED: {
|
||||
// if settings were changed we need to send event
|
||||
case DATASOURCE_UPDATED -> // if settings were changed we need to send event
|
||||
sendDataSourceUpdatedEvent |= !ds.equalSettings(oldDataSources.get(dsId));
|
||||
break;
|
||||
}
|
||||
case DATASOURCE_DELETED: {
|
||||
case DATASOURCE_DELETED -> {
|
||||
WebDataSourceUtils.disconnectDataSource(this, ds);
|
||||
if (registry instanceof DBPDataSourceRegistryCache) {
|
||||
((DBPDataSourceRegistryCache) registry).removeDataSourceFromList(ds);
|
||||
if (registry instanceof DBPDataSourceRegistryCache dsrc) {
|
||||
dsrc.removeDataSourceFromList(ds);
|
||||
}
|
||||
this.connections.remove(ds.getId());
|
||||
sendDataSourceUpdatedEvent = true;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
default -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -313,6 +305,7 @@ public class WebSession extends BaseWebSession
|
||||
log.error(e);
|
||||
}
|
||||
refreshUserData();
|
||||
clearSessionContext();
|
||||
}
|
||||
|
||||
private void initNavigatorModel() {
|
||||
@@ -766,8 +759,8 @@ public class WebSession extends BaseWebSession
|
||||
public <T> T getAttribute(String name) {
|
||||
synchronized (attributes) {
|
||||
Object value = attributes.get(name);
|
||||
if (value instanceof PersistentAttribute) {
|
||||
value = ((PersistentAttribute) value).getValue();
|
||||
if (value instanceof PersistentAttribute persistentAttribute) {
|
||||
value = persistentAttribute.getValue();
|
||||
}
|
||||
return (T) value;
|
||||
}
|
||||
@@ -782,8 +775,8 @@ public class WebSession extends BaseWebSession
|
||||
public <T> T getAttribute(String name, Function<T, T> creator, Function<T, T> disposer) {
|
||||
synchronized (attributes) {
|
||||
Object value = attributes.get(name);
|
||||
if (value instanceof PersistentAttribute) {
|
||||
value = ((PersistentAttribute) value).getValue();
|
||||
if (value instanceof PersistentAttribute persistentAttribute) {
|
||||
value = persistentAttribute.getValue();
|
||||
}
|
||||
if (value == null) {
|
||||
value = creator.apply(null);
|
||||
@@ -967,9 +960,7 @@ public class WebSession extends BaseWebSession
|
||||
|
||||
private <T> boolean isAuthInfoInstanceOf(WebAuthInfo authInfo, Class<T> adapter) {
|
||||
if (authInfo != null && authInfo.getAuthSession() != null) {
|
||||
if (adapter.isInstance(authInfo.getAuthSession())) {
|
||||
return true;
|
||||
}
|
||||
return adapter.isInstance(authInfo.getAuthSession());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
-11
@@ -17,7 +17,6 @@
|
||||
|
||||
package io.cloudbeaver.model.session;
|
||||
|
||||
import io.cloudbeaver.DBWConstants;
|
||||
import io.cloudbeaver.DBWUserIdentity;
|
||||
import io.cloudbeaver.DBWebException;
|
||||
import io.cloudbeaver.auth.SMAuthProviderExternal;
|
||||
@@ -38,7 +37,6 @@ import org.jkiss.utils.CommonUtils;
|
||||
|
||||
import java.time.OffsetDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -114,15 +112,6 @@ public class WebSessionAuthProcessor {
|
||||
SMAuthProviderExternal<?> authProviderExternal = authProviderInstance instanceof SMAuthProviderExternal<?> ?
|
||||
(SMAuthProviderExternal<?>) authProviderInstance : null;
|
||||
|
||||
boolean providerDisabled = !isProviderEnabled(providerId);
|
||||
if (configMode || webSession.hasPermission(DBWConstants.PERMISSION_ADMIN)) {
|
||||
// 1. Admin can authorize in any providers
|
||||
// 2. When it authorizes in non-local provider for the first time we force linkUser flag
|
||||
if (providerDisabled && webSession.getUser() != null) {
|
||||
linkWithActiveUser = true;
|
||||
}
|
||||
}
|
||||
|
||||
SMSession authSession;
|
||||
|
||||
if (authProviderExternal != null && !configMode && !alreadyLoggedIn) {
|
||||
|
||||
+2
-9
@@ -22,7 +22,6 @@ import org.jkiss.code.Nullable;
|
||||
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.auth.SMSessionContext;
|
||||
import org.jkiss.dbeaver.model.impl.auth.SessionContextImpl;
|
||||
import org.jkiss.dbeaver.model.rm.RMUtils;
|
||||
import org.jkiss.dbeaver.runtime.DBWorkbench;
|
||||
@@ -103,7 +102,7 @@ public class WebSessionWorkspace implements DBPWorkspace {
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public WebProjectImpl getProjectById(String projectId) {
|
||||
public WebProjectImpl getProjectById(@NotNull String projectId) {
|
||||
if (projectId == null) {
|
||||
return activeProject;
|
||||
}
|
||||
@@ -117,21 +116,15 @@ public class WebSessionWorkspace implements DBPWorkspace {
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public SMSessionContext getAuthContext() {
|
||||
public SessionContextImpl getAuthContext() {
|
||||
return workspaceAuthContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
clearAuthData();
|
||||
|
||||
clearProjects();
|
||||
}
|
||||
|
||||
void clearAuthData() {
|
||||
workspaceAuthContext.close();
|
||||
}
|
||||
|
||||
public void setActiveProject(DBPProject activeProject) {
|
||||
this.activeProject = (WebProjectImpl) activeProject;
|
||||
}
|
||||
|
||||
+5
-2
@@ -161,7 +161,7 @@ public class WebUserContext implements SMCredentialsProvider {
|
||||
this.user = null;
|
||||
this.securityController = application.createSecurityController(this);
|
||||
this.adminSecurityController = null;
|
||||
this.secretController = application.getSecretController(this);
|
||||
this.secretController = null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -220,7 +220,10 @@ public class WebUserContext implements SMCredentialsProvider {
|
||||
this.userPermissions = permissions;
|
||||
}
|
||||
|
||||
public DBSSecretController getSecretController() {
|
||||
public DBSSecretController getSecretController() throws DBException {
|
||||
if (this.securityController == null) {
|
||||
this.secretController = application.getSecretController(this, workspace.getAuthContext());
|
||||
}
|
||||
return secretController;
|
||||
}
|
||||
|
||||
|
||||
+12
-12
@@ -14,9 +14,10 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.cloudbeaver.server;
|
||||
package io.cloudbeaver.model.utils;
|
||||
|
||||
import org.jkiss.code.NotNull;
|
||||
import org.jkiss.code.Nullable;
|
||||
import org.jkiss.dbeaver.model.connection.DBPDriver;
|
||||
import org.jkiss.utils.ArrayUtils;
|
||||
|
||||
@@ -24,19 +25,18 @@ public class ConfigurationUtils {
|
||||
private ConfigurationUtils() {
|
||||
}
|
||||
|
||||
public static boolean isDriverEnabled(@NotNull DBPDriver driver) {
|
||||
var driverId = driver.getFullId();
|
||||
|
||||
String[] disabledDrivers = CBApplication.getInstance().getAppConfiguration().getDisabledDrivers();
|
||||
if (ArrayUtils.contains(disabledDrivers, driverId)) {
|
||||
public static boolean isDriverEnabled(
|
||||
@NotNull DBPDriver driver,
|
||||
@Nullable String[] enabledDrivers,
|
||||
@Nullable String[] disabledDrivers
|
||||
) {
|
||||
if (ArrayUtils.contains(enabledDrivers, driver.getFullId())) {
|
||||
return true;
|
||||
}
|
||||
if (ArrayUtils.contains(disabledDrivers, driver.getFullId())) {
|
||||
return false;
|
||||
}
|
||||
String[] enabledDrivers = CBApplication.getInstance().getAppConfiguration().getEnabledDrivers();
|
||||
if (enabledDrivers.length > 0 && !ArrayUtils.contains(enabledDrivers, driverId)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return !driver.isEmbedded();
|
||||
}
|
||||
|
||||
}
|
||||
+6
@@ -102,6 +102,12 @@ public class WebAuthProviderConfiguration {
|
||||
return instance instanceof SMAuthProviderFederated ? ((SMAuthProviderFederated) instance).getMetadataLink(getId(), config.getParameters()) : null;
|
||||
}
|
||||
|
||||
@Property
|
||||
public String getAcsLink() throws DBException {
|
||||
SMAuthProvider<?> instance = providerDescriptor.getInstance();
|
||||
return instance instanceof SMAuthProviderFederated ? ((SMAuthProviderFederated) instance).getAcsLink(getId(), config.getParameters()) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getDisplayName();
|
||||
|
||||
+6
@@ -55,6 +55,7 @@ public class WebAuthProviderDescriptor extends AbstractDescriptor {
|
||||
private final boolean trusted;
|
||||
private final boolean isPrivate;
|
||||
private final String[] requiredFeatures;
|
||||
private final boolean isRequired;
|
||||
|
||||
public WebAuthProviderDescriptor(IConfigurationElement cfg) {
|
||||
super(cfg);
|
||||
@@ -64,6 +65,7 @@ public class WebAuthProviderDescriptor extends AbstractDescriptor {
|
||||
this.configurable = CommonUtils.toBoolean(cfg.getAttribute("configurable"));
|
||||
this.trusted = CommonUtils.toBoolean(cfg.getAttribute("trusted"));
|
||||
this.isPrivate = CommonUtils.toBoolean(cfg.getAttribute("private"));
|
||||
this.isRequired = CommonUtils.toBoolean(cfg.getAttribute("required"));
|
||||
|
||||
for (IConfigurationElement cfgElement : cfg.getChildren("configuration")) {
|
||||
for (IConfigurationElement propGroup : ArrayUtils.safeArray(cfgElement.getChildren(PropertyDescriptor.TAG_PROPERTY_GROUP))) {
|
||||
@@ -124,6 +126,10 @@ public class WebAuthProviderDescriptor extends AbstractDescriptor {
|
||||
return isPrivate;
|
||||
}
|
||||
|
||||
public boolean isRequired() {
|
||||
return isRequired;
|
||||
}
|
||||
|
||||
public List<PropertyDescriptor> getConfigurationParameters() {
|
||||
return new ArrayList<>(configurationParameters.values());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* DBeaver - Universal Database Manager
|
||||
* Copyright (C) 2010-2023 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;
|
||||
|
||||
public interface HttpConstants {
|
||||
String CONTENT_TYPE = "Content-Type";
|
||||
|
||||
String TYPE_JSON = "application/json";
|
||||
}
|
||||
+6
-2
@@ -17,11 +17,11 @@
|
||||
package io.cloudbeaver.service;
|
||||
|
||||
import io.cloudbeaver.model.app.WebAppConfiguration;
|
||||
import io.cloudbeaver.model.app.WebApplication;
|
||||
import io.cloudbeaver.model.session.WebSession;
|
||||
import org.jkiss.code.NotNull;
|
||||
import org.jkiss.code.Nullable;
|
||||
import org.jkiss.dbeaver.DBException;
|
||||
import org.jkiss.dbeaver.model.app.DBPApplication;
|
||||
|
||||
/**
|
||||
* Web service implementation
|
||||
@@ -29,11 +29,15 @@ import org.jkiss.dbeaver.model.app.DBPApplication;
|
||||
public interface DBWServiceServerConfigurator extends DBWServiceBinding {
|
||||
|
||||
void configureServer(
|
||||
@NotNull DBPApplication application,
|
||||
@NotNull WebApplication application,
|
||||
@Nullable WebSession session,
|
||||
@NotNull WebAppConfiguration appConfig
|
||||
) throws DBException;
|
||||
|
||||
default void migrateConfigurationIfNeeded(@NotNull WebApplication application) throws DBException {
|
||||
|
||||
}
|
||||
|
||||
void reloadConfiguration(@NotNull WebAppConfiguration appConfig) throws DBException;
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ package io.cloudbeaver.service;
|
||||
|
||||
import org.jkiss.dbeaver.DBException;
|
||||
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import jakarta.servlet.http.HttpServlet;
|
||||
|
||||
public interface DBWServletContext {
|
||||
void addServlet(String servletId, HttpServlet servlet, String mapping) throws DBException;
|
||||
|
||||
+2
-2
@@ -19,8 +19,8 @@ package io.cloudbeaver.service;
|
||||
import io.cloudbeaver.model.session.WebSession;
|
||||
import org.jkiss.dbeaver.DBException;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
|
||||
+31
-1
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* DBeaver - Universal Database Manager
|
||||
* Copyright (C) 2010-2023 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.cloudbeaver.service.security;
|
||||
|
||||
import io.cloudbeaver.DBWConstants;
|
||||
@@ -10,6 +26,7 @@ import org.jkiss.dbeaver.model.auth.SMCredentialsProvider;
|
||||
import org.jkiss.dbeaver.model.rm.RMConstants;
|
||||
import org.jkiss.dbeaver.model.rm.RMProject;
|
||||
import org.jkiss.dbeaver.model.rm.RMProjectPermission;
|
||||
import org.jkiss.dbeaver.model.security.exception.SMAccessTokenExpiredException;
|
||||
import org.jkiss.dbeaver.model.security.exception.SMRefreshTokenExpiredException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -55,7 +72,7 @@ public class SMUtils {
|
||||
return permissionInfos;
|
||||
}
|
||||
|
||||
public static boolean isTokenExpiredExceptionWasHandled(Throwable ex) {
|
||||
public static boolean isRefreshTokenExpiredExceptionWasHandled(Throwable ex) {
|
||||
if (ex instanceof SMRefreshTokenExpiredException) {
|
||||
return true;
|
||||
}
|
||||
@@ -69,4 +86,17 @@ public class SMUtils {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isAccessTokenExpiredExceptionWasHandled(Throwable ex) {
|
||||
if (ex instanceof SMAccessTokenExpiredException) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Throwable cause = ex;
|
||||
while ((cause = cause.getCause()) != null) {
|
||||
if (cause instanceof SMAccessTokenExpiredException) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+9
-3
@@ -22,9 +22,7 @@ import org.jkiss.dbeaver.model.DBPDataSource;
|
||||
import org.jkiss.dbeaver.model.DBUtils;
|
||||
import org.jkiss.dbeaver.model.data.DBDAttributeBinding;
|
||||
import org.jkiss.dbeaver.model.data.DBDRowIdentifier;
|
||||
import org.jkiss.dbeaver.model.struct.DBSAttributeBase;
|
||||
import org.jkiss.dbeaver.model.struct.DBSDataContainer;
|
||||
import org.jkiss.dbeaver.model.struct.DBSTypedObject;
|
||||
import org.jkiss.dbeaver.model.struct.*;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@@ -126,4 +124,12 @@ public class WebSQLResultsInfo {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean canRefreshResults() {
|
||||
DBSEntity entity = getDefaultRowIdentifier().getEntity();
|
||||
// FIXME: do not refresh documents for now. Can be solved by extracting document ID attributes
|
||||
// FIXME: but it will require to provide dynamic document metadata.
|
||||
return entity == null || entity.getDataSource() == null ||
|
||||
(!(entity instanceof DBSDocumentContainer) && !entity.getDataSource().getInfo().isDynamicMetadata());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,9 +16,12 @@
|
||||
*/
|
||||
package io.cloudbeaver.utils;
|
||||
|
||||
import io.cloudbeaver.DBWebException;
|
||||
import io.cloudbeaver.WebProjectImpl;
|
||||
import io.cloudbeaver.auth.NoAuthCredentialsProvider;
|
||||
import io.cloudbeaver.model.app.WebApplication;
|
||||
import io.cloudbeaver.model.app.WebAuthApplication;
|
||||
import io.cloudbeaver.model.session.WebSession;
|
||||
import org.jkiss.code.NotNull;
|
||||
import org.jkiss.code.Nullable;
|
||||
import org.jkiss.dbeaver.DBException;
|
||||
@@ -30,11 +33,14 @@ import org.jkiss.dbeaver.runtime.DBWorkbench;
|
||||
import org.jkiss.dbeaver.utils.GeneralUtils;
|
||||
import org.jkiss.utils.CommonUtils;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.http.Cookie;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class WebAppUtils {
|
||||
private static final Log log = Log.getLog(WebAppUtils.class);
|
||||
@@ -176,12 +182,11 @@ public class WebAppUtils {
|
||||
String path = getWebApplication().getRootURI();
|
||||
|
||||
if (sameSite != null) {
|
||||
if (sameSite.toLowerCase() == "none" && request.isSecure() == false) {
|
||||
if (!request.isSecure()) {
|
||||
log.debug("Attempt to set Cookie `" + cookieName + "` with `SameSite=None` failed, it require a secure context/HTTPS");
|
||||
} else {
|
||||
sessionCookie.setSecure(true);
|
||||
path = path.concat("; SameSite=" + sameSite);
|
||||
}
|
||||
sessionCookie.setSecure(true);
|
||||
path = path.concat("; SameSite=" + sameSite);
|
||||
}
|
||||
|
||||
sessionCookie.setPath(path);
|
||||
@@ -209,4 +214,12 @@ public class WebAppUtils {
|
||||
return RMProjectType.GLOBAL.getPrefix() + "_" + globalConfigurationName;
|
||||
}
|
||||
|
||||
public static WebProjectImpl getProjectById(WebSession webSession, String projectId) throws DBWebException {
|
||||
WebProjectImpl project = webSession.getProjectById(projectId);
|
||||
if (project == null) {
|
||||
throw new DBWebException("Project '" + projectId + "' not found");
|
||||
}
|
||||
return project;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -56,7 +56,7 @@ public class WebConnectionFolderUtils {
|
||||
} else if (folderNode instanceof DBNLocalFolder) {
|
||||
return ((DBNLocalFolder) folderNode).getFolder();
|
||||
} else {
|
||||
throw new DBWebException("Navigator node '" + folderNode.getNodeItemPath() + "' is not a folder node");
|
||||
throw new DBWebException("Navigator node '" + folderNode.getNodeUri() + "' is not a folder node");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ package io.cloudbeaver.utils;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import org.jkiss.dbeaver.model.data.json.JSONUtils;
|
||||
import org.jkiss.dbeaver.utils.GeneralUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
@@ -55,6 +56,7 @@ public class WebTestUtils {
|
||||
HttpRequest.Builder requestBuilder = HttpRequest.newBuilder()
|
||||
.uri(URI.create(apiUrl))
|
||||
.POST(HttpRequest.BodyPublishers.ofString(input))
|
||||
.setHeader("TE-Client-Version", GeneralUtils.getMajorVersion())
|
||||
.header("Content-Type", "application/json");
|
||||
|
||||
if (!headers.isEmpty()) {
|
||||
@@ -74,6 +76,7 @@ public class WebTestUtils {
|
||||
public static boolean getServerStatus(HttpClient client, String apiUrl) {
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(URI.create(apiUrl))
|
||||
.setHeader("TE-Client-Version", GeneralUtils.getMajorVersion())
|
||||
.GET()
|
||||
.build();
|
||||
try {
|
||||
|
||||
+1
@@ -23,4 +23,5 @@ public interface CBWebSessionEventHandler {
|
||||
void handleWebSessionEvent(WSEvent event) throws DBException;
|
||||
|
||||
void close();
|
||||
|
||||
}
|
||||
|
||||
@@ -3,9 +3,9 @@ Bundle-ManifestVersion: 2
|
||||
Bundle-Vendor: DBeaver Corp
|
||||
Bundle-Name: Cloudbeaver Community Product
|
||||
Bundle-SymbolicName: io.cloudbeaver.product.ce;singleton:=true
|
||||
Bundle-Version: 23.2.2.qualifier
|
||||
Bundle-Release-Date: 20230209
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-11
|
||||
Bundle-Version: 23.3.2.qualifier
|
||||
Bundle-Release-Date: 20240108
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-17
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Bundle-ClassPath: .
|
||||
Require-Bundle: io.cloudbeaver.server
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<relativePath>../</relativePath>
|
||||
</parent>
|
||||
<artifactId>io.cloudbeaver.product.ce</artifactId>
|
||||
<version>23.2.2-SNAPSHOT</version>
|
||||
<version>23.3.2-SNAPSHOT</version>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -2,9 +2,8 @@ Manifest-Version: 1.0
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: Base JDBC drivers
|
||||
Bundle-SymbolicName: io.cloudbeaver.resources.drivers.base;singleton:=true
|
||||
Bundle-Version: 1.0.83.qualifier
|
||||
Bundle-Release-Date: 20230209
|
||||
Bundle-Version: 1.0.89.qualifier
|
||||
Bundle-Release-Date: 20240108
|
||||
Bundle-Vendor: DBeaver Corp
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Automatic-Module-Name: io.cloudbeaver.resources.drivers.base
|
||||
Require-Bundle: io.cloudbeaver.server
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
<resource name="drivers/postgresql"/>
|
||||
<resource name="drivers/clickhouse"/>
|
||||
<resource name="drivers/clickhouse_com"/>
|
||||
<resource name="drivers/derby"/>
|
||||
<resource name="drivers/jaybird"/>
|
||||
<resource name="drivers/h2"/>
|
||||
<resource name="drivers/h2_v2"/>
|
||||
@@ -29,7 +28,6 @@
|
||||
<bundle id="drivers.postgresql" label="PostgreSQL drivers"/>
|
||||
<bundle id="drivers.clickhouse" label="Clickhouse (legacy) drivers"/>
|
||||
<bundle id="drivers.clickhouse_com" label="Clickhouse drivers"/>
|
||||
<bundle id="drivers.derby" label="Derby drivers"/>
|
||||
<bundle id="drivers.firebird" label="Firebird drivers"/>
|
||||
<bundle id="drivers.h2" label="H2 drivers"/>
|
||||
<bundle id="drivers.h2_v2" label="H2 v2 drivers"/>
|
||||
@@ -49,7 +47,6 @@
|
||||
<driver id="jaybird:jaybird"/>
|
||||
<driver id="clickhouse:yandex_clickhouse"/>
|
||||
<driver id="clickhouse:com_clickhouse"/>
|
||||
<driver id="generic:derby_server"/>
|
||||
<driver id="h2:h2_embedded"/>
|
||||
<driver id="h2:h2_embedded_v2"/>
|
||||
<driver id="sqlite:sqlite_jdbc"/>
|
||||
|
||||
@@ -9,6 +9,6 @@
|
||||
<relativePath>../</relativePath>
|
||||
</parent>
|
||||
<artifactId>io.cloudbeaver.resources.drivers.base</artifactId>
|
||||
<version>1.0.83-SNAPSHOT</version>
|
||||
<version>1.0.89-SNAPSHOT</version>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
</project>
|
||||
|
||||
@@ -3,9 +3,9 @@ Bundle-ManifestVersion: 2
|
||||
Bundle-Vendor: DBeaver Corp
|
||||
Bundle-Name: Cloudbeaver Web Server
|
||||
Bundle-SymbolicName: io.cloudbeaver.server;singleton:=true
|
||||
Bundle-Version: 23.2.2.qualifier
|
||||
Bundle-Release-Date: 20230209
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-11
|
||||
Bundle-Version: 23.3.2.qualifier
|
||||
Bundle-Release-Date: 20240108
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-17
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Bundle-Activator: io.cloudbeaver.server.CBPlatformActivator
|
||||
Bundle-ClassPath: .
|
||||
|
||||
@@ -6,14 +6,6 @@
|
||||
<extension-point id="io.cloudbeaver.driver" name="Web drivers" schema="schema/io.cloudbeaver.driver.exsd"/>
|
||||
<extension-point id="io.cloudbeaver.handler" name="Web handlers" schema="schema/io.cloudbeaver.handler.exsd"/>
|
||||
|
||||
<extension point="org.eclipse.core.runtime.adapters">
|
||||
<factory adaptableType="org.jkiss.dbeaver.runtime.DBWorkbench" class="io.cloudbeaver.server.WebPlatformAdapterFactory">
|
||||
<adapter type="org.jkiss.dbeaver.model.app.DBPPlatform"/>
|
||||
<adapter type="org.jkiss.dbeaver.runtime.ui.DBPPlatformUI"/>
|
||||
</factory>
|
||||
</extension>
|
||||
|
||||
|
||||
<!-- Needed to instantiate connections thru navigator model -->
|
||||
<extension point="org.jkiss.dbeaver.service">
|
||||
<service name="org.jkiss.dbeaver.runtime.DBServiceConnections" class="io.cloudbeaver.server.WebServiceConnectionsImpl"/>
|
||||
@@ -47,7 +39,6 @@
|
||||
<extension point="org.jkiss.dbeaver.ws.event.handler">
|
||||
<eventHandler class="io.cloudbeaver.server.events.WSDefaultEventHandler">
|
||||
<topic id="cb_config"/>
|
||||
<topic id="cb_workspace_configuration"/>
|
||||
</eventHandler>
|
||||
<eventHandler class="io.cloudbeaver.server.events.WSDataSourceUpdatedEventHandlerImpl">
|
||||
<topic id="cb_datasource"/>
|
||||
@@ -73,6 +64,15 @@
|
||||
<eventHandler class="io.cloudbeaver.server.events.WSLogEventHandler">
|
||||
<topic id="cb_session_log"/>
|
||||
</eventHandler>
|
||||
<eventHandler class="io.cloudbeaver.server.events.WSEventHandlerWorkspaceConfigUpdate">
|
||||
<topic id="cb_workspace_configuration"/>
|
||||
</eventHandler>
|
||||
<eventHandler class="io.cloudbeaver.server.events.WSDeleteTempFileHandler">
|
||||
<topic id="cb_delete_temp_folder"/>
|
||||
</eventHandler>
|
||||
<eventHandler class="io.cloudbeaver.server.events.WSUserDeletedEventHandler">
|
||||
<topic id="cb_user"/>
|
||||
</eventHandler>
|
||||
</extension>
|
||||
|
||||
</plugin>
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<relativePath>../</relativePath>
|
||||
</parent>
|
||||
<artifactId>io.cloudbeaver.server</artifactId>
|
||||
<version>23.2.2-SNAPSHOT</version>
|
||||
<version>23.3.2-SNAPSHOT</version>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
|
||||
</project>
|
||||
|
||||
@@ -8,7 +8,7 @@ input PageInput {
|
||||
offset: Int
|
||||
}
|
||||
|
||||
directive @since(version: String!) on OBJECT|SCALAR|QUERY|MUTATION|FIELD|VARIABLE_DEFINITION|OBJECT|FIELD_DEFINITION|ARGUMENT_DEFINITION|INTERFACE|ENUM|ENUM_VALUE|INPUT_OBJECT|INPUT_FIELD_DEFINITION
|
||||
directive @since(version: String!) repeatable on OBJECT|SCALAR|QUERY|MUTATION|FIELD|VARIABLE_DEFINITION|OBJECT|FIELD_DEFINITION|ARGUMENT_DEFINITION|INTERFACE|ENUM|ENUM_VALUE|INPUT_OBJECT|INPUT_FIELD_DEFINITION
|
||||
|
||||
type Query
|
||||
|
||||
|
||||
@@ -12,6 +12,8 @@ type ObjectPropertyInfo {
|
||||
displayName: String
|
||||
# Property description
|
||||
description: String
|
||||
# Property hint
|
||||
hint: String @since(version: "23.2.3")
|
||||
# Property category (may be used if object has a lot of properties)
|
||||
category: String
|
||||
# Property data type (int, String, etc)
|
||||
@@ -34,6 +36,8 @@ type ObjectPropertyInfo {
|
||||
order: Int!
|
||||
# Supported configuration types (for driver properties)
|
||||
supportedConfigurationTypes: [ String! ]
|
||||
# Required parameters
|
||||
required: Boolean! @since(version: "23.3.1")
|
||||
}
|
||||
|
||||
enum ObjectPropertyLength {
|
||||
|
||||
@@ -51,7 +51,8 @@ enum CBEventTopic {
|
||||
cb_projects,
|
||||
cb_object_permissions,
|
||||
cb_subject_permissions,
|
||||
cb_database_output_log
|
||||
cb_database_output_log,
|
||||
cb_delete_temp_folder
|
||||
}
|
||||
|
||||
# Base server event interface
|
||||
|
||||
@@ -56,6 +56,8 @@ 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
|
||||
name: String
|
||||
#Node full name
|
||||
@@ -76,6 +78,10 @@ type NavigatorNodeInfo {
|
||||
# Associated object. Maybe null for non-database objects
|
||||
object: DatabaseObjectInfo
|
||||
|
||||
# Associated object. Return value depends on the node type - connectionId for connection node, resource path for resource node, etc.
|
||||
# null - if node currently not support this property
|
||||
objectId: String @since(version: "23.2.4")
|
||||
|
||||
# Supported features: item, container, leaf
|
||||
# canDelete, canRename
|
||||
features: [ String! ]
|
||||
|
||||
@@ -356,4 +356,12 @@ extend type Mutation {
|
||||
# Returns SQLExecutionPlan
|
||||
asyncSqlExplainExecutionPlanResult(taskId: ID!): SQLExecutionPlan !
|
||||
|
||||
asyncSqlRowDataCount(
|
||||
projectId: ID,
|
||||
connectionId: ID!,
|
||||
contextId: ID!,
|
||||
resultsId: ID!
|
||||
): AsyncTaskInfo!
|
||||
|
||||
asyncSqlRowDataCountResult(taskId: ID!): Int!
|
||||
}
|
||||
|
||||
+9
-2
@@ -19,7 +19,9 @@ package io.cloudbeaver.model;
|
||||
import io.cloudbeaver.DBWebException;
|
||||
import io.cloudbeaver.WebServiceUtils;
|
||||
import io.cloudbeaver.model.session.WebSession;
|
||||
import io.cloudbeaver.server.ConfigurationUtils;
|
||||
import io.cloudbeaver.model.utils.ConfigurationUtils;
|
||||
import io.cloudbeaver.server.CBAppConfig;
|
||||
import io.cloudbeaver.server.CBApplication;
|
||||
import org.jkiss.dbeaver.DBException;
|
||||
import org.jkiss.dbeaver.Log;
|
||||
import org.jkiss.dbeaver.model.DBConstants;
|
||||
@@ -236,7 +238,12 @@ public class WebDatabaseDriverInfo {
|
||||
|
||||
@Property
|
||||
public boolean isEnabled() {
|
||||
return ConfigurationUtils.isDriverEnabled(driver);
|
||||
CBAppConfig config = CBApplication.getInstance().getAppConfiguration();
|
||||
return ConfigurationUtils.isDriverEnabled(
|
||||
driver,
|
||||
config.getEnabledDrivers(),
|
||||
config.getDisabledDrivers()
|
||||
);
|
||||
}
|
||||
|
||||
@Property
|
||||
|
||||
+11
-16
@@ -17,23 +17,18 @@
|
||||
|
||||
package io.cloudbeaver.model;
|
||||
|
||||
import io.cloudbeaver.server.ConfigurationUtils;
|
||||
import org.jkiss.code.NotNull;
|
||||
import org.jkiss.dbeaver.DBException;
|
||||
import org.jkiss.dbeaver.model.DBPDataSourceContainer;
|
||||
import org.jkiss.dbeaver.model.DBPDataSourceHandler;
|
||||
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
|
||||
import io.cloudbeaver.model.utils.ConfigurationUtils;
|
||||
import io.cloudbeaver.server.CBAppConfig;
|
||||
import io.cloudbeaver.server.CBApplication;
|
||||
import org.jkiss.dbeaver.model.connection.DBPDriver;
|
||||
|
||||
public class WebDatasourceAccessCheckHandler implements DBPDataSourceHandler {
|
||||
public class WebDatasourceAccessCheckHandler extends BaseDatasourceAccessCheckHandler {
|
||||
@Override
|
||||
public void beforeConnect(DBRProgressMonitor monitor, @NotNull DBPDataSourceContainer dataSourceContainer) throws DBException {
|
||||
if (!ConfigurationUtils.isDriverEnabled(dataSourceContainer.getDriver())) {
|
||||
throw new DBException("Driver disabled");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeDisconnect(DBRProgressMonitor monitor, @NotNull DBPDataSourceContainer dataSourceContainer) throws DBException {
|
||||
|
||||
protected boolean isDriverDisabled(DBPDriver driver) {
|
||||
CBAppConfig config = CBApplication.getInstance().getAppConfiguration();
|
||||
return !ConfigurationUtils.isDriverEnabled(
|
||||
driver,
|
||||
config.getEnabledDrivers(),
|
||||
config.getDisabledDrivers());
|
||||
}
|
||||
}
|
||||
|
||||
+4
@@ -83,6 +83,10 @@ public class WebAuthProviderInfo {
|
||||
return descriptor.isPrivate();
|
||||
}
|
||||
|
||||
public boolean isRequired() {
|
||||
return descriptor.isRequired();
|
||||
}
|
||||
|
||||
public boolean isSupportProvisioning() {
|
||||
return descriptor.getInstance() instanceof SMProvisioner;
|
||||
}
|
||||
|
||||
@@ -18,23 +18,29 @@ package io.cloudbeaver.server;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import io.cloudbeaver.DBWebException;
|
||||
import io.cloudbeaver.WebServiceUtils;
|
||||
import io.cloudbeaver.model.app.BaseAuthWebAppConfiguration;
|
||||
import io.cloudbeaver.model.app.WebAuthConfiguration;
|
||||
import io.cloudbeaver.registry.WebAuthProviderDescriptor;
|
||||
import io.cloudbeaver.registry.WebAuthProviderRegistry;
|
||||
import org.jkiss.code.NotNull;
|
||||
import org.jkiss.dbeaver.DBException;
|
||||
import org.jkiss.dbeaver.Log;
|
||||
import org.jkiss.dbeaver.model.connection.DBPDriver;
|
||||
import org.jkiss.dbeaver.model.navigator.DBNBrowseSettings;
|
||||
import org.jkiss.dbeaver.registry.DataSourceNavigatorSettings;
|
||||
import org.jkiss.utils.ArrayUtils;
|
||||
import org.jkiss.utils.CommonUtils;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Application configuration
|
||||
*/
|
||||
public class CBAppConfig extends BaseAuthWebAppConfiguration implements WebAuthConfiguration {
|
||||
private static final Log log = Log.getLog(CBAppConfig.class);
|
||||
public static final DataSourceNavigatorSettings.Preset PRESET_WEB = new DataSourceNavigatorSettings.Preset("web", "Web", "Default view");
|
||||
|
||||
public static final DataSourceNavigatorSettings DEFAULT_VIEW_SETTINGS = PRESET_WEB.getSettings();
|
||||
@@ -161,10 +167,6 @@ public class CBAppConfig extends BaseAuthWebAppConfiguration implements WebAuthC
|
||||
return enabledDrivers;
|
||||
}
|
||||
|
||||
public void setEnabledDrivers(String[] enabledDrivers) {
|
||||
this.enabledDrivers = enabledDrivers;
|
||||
}
|
||||
|
||||
public String[] getDisabledDrivers() {
|
||||
return disabledDrivers;
|
||||
}
|
||||
@@ -260,4 +262,39 @@ public class CBAppConfig extends BaseAuthWebAppConfiguration implements WebAuthC
|
||||
return grantConnectionsAccessToAnonymousTeam;
|
||||
}
|
||||
|
||||
|
||||
// we disable embedded drivers by default and enable it in enabled drivers list
|
||||
// that's why we need so complicated logic for disabling drivers
|
||||
|
||||
public void updateDisabledDriversConfig(String[] disabledDriversConfig) {
|
||||
Set<String> disabledIds = new LinkedHashSet<>(Arrays.asList(disabledDriversConfig));
|
||||
Set<String> enabledIds = new LinkedHashSet<>(Arrays.asList(this.enabledDrivers));
|
||||
|
||||
// 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 : this.disabledDrivers) {
|
||||
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 = WebServiceUtils.getDriverById(driverId);
|
||||
if (driver.isEmbedded()) {
|
||||
enabledIds.add(driverId);
|
||||
}
|
||||
} catch (DBWebException e) {
|
||||
log.error("Failed to find driver by id", e);
|
||||
}
|
||||
}
|
||||
this.disabledDrivers = disabledDriversConfig;
|
||||
this.enabledDrivers = enabledIds.toArray(String[]::new);
|
||||
}
|
||||
|
||||
public boolean isDriverForceEnabled(@NotNull String driverId) {
|
||||
return ArrayUtils.containsIgnoreCase(getEnabledDrivers(), driverId);
|
||||
}
|
||||
}
|
||||
|
||||
+149
-52
@@ -21,10 +21,10 @@ import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.InstanceCreator;
|
||||
import io.cloudbeaver.WebServiceUtils;
|
||||
import io.cloudbeaver.auth.CBAuthConstants;
|
||||
import io.cloudbeaver.auth.NoAuthCredentialsProvider;
|
||||
import io.cloudbeaver.model.app.BaseWebApplication;
|
||||
import io.cloudbeaver.model.app.WebAuthApplication;
|
||||
import io.cloudbeaver.model.app.WebAuthConfiguration;
|
||||
import io.cloudbeaver.model.session.WebAuthInfo;
|
||||
import io.cloudbeaver.registry.WebDriverRegistry;
|
||||
import io.cloudbeaver.registry.WebServiceRegistry;
|
||||
import io.cloudbeaver.server.jetty.CBJettyServer;
|
||||
@@ -43,18 +43,23 @@ import org.jkiss.dbeaver.Log;
|
||||
import org.jkiss.dbeaver.ModelPreferences;
|
||||
import org.jkiss.dbeaver.model.DBPDataSourceContainer;
|
||||
import org.jkiss.dbeaver.model.app.DBPApplication;
|
||||
import org.jkiss.dbeaver.model.app.DBPPlatform;
|
||||
import org.jkiss.dbeaver.model.auth.AuthInfo;
|
||||
import org.jkiss.dbeaver.model.auth.SMCredentialsProvider;
|
||||
import org.jkiss.dbeaver.model.data.json.JSONUtils;
|
||||
import org.jkiss.dbeaver.model.navigator.DBNBrowseSettings;
|
||||
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
|
||||
import org.jkiss.dbeaver.model.security.*;
|
||||
import org.jkiss.dbeaver.model.security.user.SMObjectPermissions;
|
||||
import org.jkiss.dbeaver.model.security.SMAdminController;
|
||||
import org.jkiss.dbeaver.model.security.SMAuthProviderCustomConfiguration;
|
||||
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.registry.BaseApplicationImpl;
|
||||
import org.jkiss.dbeaver.registry.DataSourceNavigatorSettings;
|
||||
import org.jkiss.dbeaver.runtime.DBWorkbench;
|
||||
import org.jkiss.dbeaver.runtime.IVariableResolver;
|
||||
import org.jkiss.dbeaver.runtime.ui.DBPPlatformUI;
|
||||
import org.jkiss.dbeaver.utils.ContentUtils;
|
||||
import org.jkiss.dbeaver.utils.GeneralUtils;
|
||||
import org.jkiss.dbeaver.utils.PrefUtils;
|
||||
@@ -90,6 +95,8 @@ public abstract class CBApplication extends BaseWebApplication implements WebAut
|
||||
* In configuration mode sessions expire after a week
|
||||
*/
|
||||
private static final long CONFIGURATION_MODE_SESSION_IDLE_TIME = 60 * 60 * 1000 * 24 * 7;
|
||||
public static final String HOST_LOCALHOST = "localhost";
|
||||
public static final String HOST_127_0_0_1 = "127.0.0.1";
|
||||
|
||||
|
||||
static {
|
||||
@@ -106,6 +113,7 @@ public abstract class CBApplication extends BaseWebApplication implements WebAut
|
||||
protected int serverPort = CBConstants.DEFAULT_SERVER_PORT;
|
||||
private String serverHost = null;
|
||||
private String serverName = null;
|
||||
private String sslConfigurationPath = null;
|
||||
private String contentRoot = CBConstants.DEFAULT_CONTENT_ROOT;
|
||||
private String rootURI = CBConstants.DEFAULT_ROOT_URI;
|
||||
private String servicesURI = CBConstants.DEFAULT_SERVICES_URI;
|
||||
@@ -256,8 +264,9 @@ public abstract class CBApplication extends BaseWebApplication implements WebAut
|
||||
if (CommonUtils.isEmpty(localHostAddress)) {
|
||||
localHostAddress = System.getProperty(CBConstants.VAR_CB_LOCAL_HOST_ADDR);
|
||||
}
|
||||
if (CommonUtils.isEmpty(localHostAddress) || "127.0.0.1".equals(localHostAddress) || "::0".equals(localHostAddress)) {
|
||||
localHostAddress = "localhost";
|
||||
if (CommonUtils.isEmpty(localHostAddress) || HOST_127_0_0_1.equals(localHostAddress) || "::0".equals(
|
||||
localHostAddress)) {
|
||||
localHostAddress = HOST_LOCALHOST;
|
||||
}
|
||||
|
||||
final Runtime runtime = Runtime.getRuntime();
|
||||
@@ -278,8 +287,10 @@ public abstract class CBApplication extends BaseWebApplication implements WebAut
|
||||
}
|
||||
|
||||
log.debug(GeneralUtils.getProductName() + " " + GeneralUtils.getProductVersion() + " is starting"); //$NON-NLS-1$
|
||||
log.debug("\tOS: " + System.getProperty(StandardConstants.ENV_OS_NAME) + " " + System.getProperty(StandardConstants.ENV_OS_VERSION) + " (" + System.getProperty(StandardConstants.ENV_OS_ARCH) + ")");
|
||||
log.debug("\tJava version: " + System.getProperty(StandardConstants.ENV_JAVA_VERSION) + " by " + System.getProperty(StandardConstants.ENV_JAVA_VENDOR) + " (" + System.getProperty(StandardConstants.ENV_JAVA_ARCH) + "bit)");
|
||||
log.debug("\tOS: " + System.getProperty(StandardConstants.ENV_OS_NAME) + " " + System.getProperty(
|
||||
StandardConstants.ENV_OS_VERSION) + " (" + System.getProperty(StandardConstants.ENV_OS_ARCH) + ")");
|
||||
log.debug("\tJava version: " + System.getProperty(StandardConstants.ENV_JAVA_VERSION) + " by " + System.getProperty(
|
||||
StandardConstants.ENV_JAVA_VENDOR) + " (" + System.getProperty(StandardConstants.ENV_JAVA_ARCH) + "bit)");
|
||||
log.debug("\tInstall path: '" + SystemVariablesResolver.getInstallPath() + "'"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
log.debug("\tGlobal workspace: '" + instanceLoc.getURL() + "'"); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
log.debug("\tMemory available " + (runtime.totalMemory() / (1024 * 1024)) + "Mb/" + (runtime.maxMemory() / (1024 * 1024)) + "Mb");
|
||||
@@ -309,7 +320,8 @@ public abstract class CBApplication extends BaseWebApplication implements WebAut
|
||||
}
|
||||
{
|
||||
// Perform services initialization
|
||||
for (DBWServiceInitializer wsi : WebServiceRegistry.getInstance().getWebServices(DBWServiceInitializer.class)) {
|
||||
for (DBWServiceInitializer wsi : WebServiceRegistry.getInstance()
|
||||
.getWebServices(DBWServiceInitializer.class)) {
|
||||
try {
|
||||
wsi.initializeService(this);
|
||||
} catch (Exception e) {
|
||||
@@ -319,14 +331,6 @@ public abstract class CBApplication extends BaseWebApplication implements WebAut
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
try {
|
||||
initializeSecurityController();
|
||||
} catch (Exception e) {
|
||||
log.error("Error initializing database", e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
try {
|
||||
initializeServer();
|
||||
} catch (DBException e) {
|
||||
@@ -334,6 +338,14 @@ public abstract class CBApplication extends BaseWebApplication implements WebAut
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
initializeSecurityController();
|
||||
} catch (Exception e) {
|
||||
log.error("Error initializing database", e);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (configurationMode) {
|
||||
// Try to configure automatically
|
||||
performAutoConfiguration(configPath.toFile().getParentFile());
|
||||
@@ -379,7 +391,8 @@ public abstract class CBApplication extends BaseWebApplication implements WebAut
|
||||
String autoAdminName = System.getenv(CBConstants.VAR_AUTO_CB_ADMIN_NAME);
|
||||
String autoAdminPassword = System.getenv(CBConstants.VAR_AUTO_CB_ADMIN_PASSWORD);
|
||||
|
||||
if (CommonUtils.isEmpty(autoServerName) || CommonUtils.isEmpty(autoAdminName) || CommonUtils.isEmpty(autoAdminPassword)) {
|
||||
if (CommonUtils.isEmpty(autoServerName) || CommonUtils.isEmpty(autoAdminName) || CommonUtils.isEmpty(
|
||||
autoAdminPassword)) {
|
||||
// Try to load from auto config file
|
||||
if (configPath.exists()) {
|
||||
File autoConfigFile = new File(configPath, CBConstants.AUTO_CONFIG_FILE_NAME);
|
||||
@@ -393,13 +406,15 @@ public abstract class CBApplication extends BaseWebApplication implements WebAut
|
||||
autoAdminName = autoProps.getProperty(CBConstants.VAR_AUTO_CB_ADMIN_NAME);
|
||||
autoAdminPassword = autoProps.getProperty(CBConstants.VAR_AUTO_CB_ADMIN_PASSWORD);
|
||||
} catch (IOException e) {
|
||||
log.error("Error loading auto configuration file '" + autoConfigFile.getAbsolutePath() + "'", e);
|
||||
log.error("Error loading auto configuration file '" + autoConfigFile.getAbsolutePath() + "'",
|
||||
e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (CommonUtils.isEmpty(autoServerName) || CommonUtils.isEmpty(autoAdminName) || CommonUtils.isEmpty(autoAdminPassword)) {
|
||||
if (CommonUtils.isEmpty(autoServerName) || CommonUtils.isEmpty(autoAdminName) || CommonUtils.isEmpty(
|
||||
autoAdminPassword)) {
|
||||
log.info("No auto configuration was found. Server must be configured manually");
|
||||
return;
|
||||
}
|
||||
@@ -420,7 +435,14 @@ public abstract class CBApplication extends BaseWebApplication implements WebAut
|
||||
}
|
||||
|
||||
protected void initializeServer() throws DBException {
|
||||
|
||||
for (DBWServiceServerConfigurator wsc : WebServiceRegistry.getInstance()
|
||||
.getWebServices(DBWServiceServerConfigurator.class)) {
|
||||
try {
|
||||
wsc.migrateConfigurationIfNeeded(this);
|
||||
} catch (Exception e) {
|
||||
log.warn("Error migration configuration " + wsc.getClass().getName(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void determineLocalAddresses() {
|
||||
@@ -495,6 +517,7 @@ public abstract class CBApplication extends BaseWebApplication implements WebAut
|
||||
protected Path loadServerConfiguration() throws DBException {
|
||||
Path path = super.loadServerConfiguration();
|
||||
|
||||
|
||||
File runtimeConfigFile = getRuntimeAppConfigFile();
|
||||
if (runtimeConfigFile.exists()) {
|
||||
log.debug("Runtime configuration [" + runtimeConfigFile.getAbsolutePath() + "]");
|
||||
@@ -514,7 +537,9 @@ public abstract class CBApplication extends BaseWebApplication implements WebAut
|
||||
parseConfiguration(configPath.toFile());
|
||||
}
|
||||
// Set default preferences
|
||||
PrefUtils.setDefaultPreferenceValue(ModelPreferences.getPreferences(), ModelPreferences.UI_DRIVERS_HOME, getDriversLocation());
|
||||
PrefUtils.setDefaultPreferenceValue(ModelPreferences.getPreferences(),
|
||||
ModelPreferences.UI_DRIVERS_HOME,
|
||||
getDriversLocation());
|
||||
}
|
||||
|
||||
private void parseConfiguration(File configFile) throws DBException {
|
||||
@@ -536,12 +561,18 @@ public abstract class CBApplication extends BaseWebApplication implements WebAut
|
||||
} else if (serverURL == null) {
|
||||
String hostName = serverHost;
|
||||
if (CommonUtils.isEmpty(hostName)) {
|
||||
hostName = InetAddress.getLocalHost().getHostName();
|
||||
try {
|
||||
hostName = InetAddress.getLocalHost().getHostName();
|
||||
} catch (UnknownHostException e) {
|
||||
log.debug("Error resolving localhost address: " + e.getMessage());
|
||||
hostName = HOST_LOCALHOST;
|
||||
}
|
||||
}
|
||||
serverURL = "http://" + hostName + ":" + serverPort;
|
||||
}
|
||||
|
||||
serverName = JSONUtils.getString(serverConfig, CBConstants.PARAM_SERVER_NAME, serverName);
|
||||
sslConfigurationPath = JSONUtils.getString(serverConfig, CBConstants.PARAM_SSL_CONFIGURATION_PATH, sslConfigurationPath);
|
||||
contentRoot = WebAppUtils.getRelativePath(
|
||||
JSONUtils.getString(serverConfig, CBConstants.PARAM_CONTENT_ROOT, contentRoot), homeFolder);
|
||||
rootURI = readRootUri(serverConfig);
|
||||
@@ -551,10 +582,14 @@ public abstract class CBApplication extends BaseWebApplication implements WebAut
|
||||
workspaceLocation = WebAppUtils.getRelativePath(
|
||||
JSONUtils.getString(serverConfig, CBConstants.PARAM_WORKSPACE_LOCATION, workspaceLocation), homeFolder);
|
||||
|
||||
maxSessionIdleTime = JSONUtils.getLong(serverConfig, CBConstants.PARAM_SESSION_EXPIRE_PERIOD, maxSessionIdleTime);
|
||||
maxSessionIdleTime = JSONUtils.getLong(serverConfig,
|
||||
CBConstants.PARAM_SESSION_EXPIRE_PERIOD,
|
||||
maxSessionIdleTime);
|
||||
|
||||
develMode = JSONUtils.getBoolean(serverConfig, CBConstants.PARAM_DEVEL_MODE, develMode);
|
||||
enableSecurityManager = JSONUtils.getBoolean(serverConfig, CBConstants.PARAM_SECURITY_MANAGER, enableSecurityManager);
|
||||
enableSecurityManager = JSONUtils.getBoolean(serverConfig,
|
||||
CBConstants.PARAM_SECURITY_MANAGER,
|
||||
enableSecurityManager);
|
||||
//SM config
|
||||
gson.fromJson(
|
||||
gson.toJsonTree(JSONUtils.getObject(serverConfig, CBConstants.PARAM_SM_CONFIGURATION)),
|
||||
@@ -578,7 +613,7 @@ public abstract class CBApplication extends BaseWebApplication implements WebAut
|
||||
}
|
||||
}
|
||||
parseAdditionalConfiguration(configProps);
|
||||
} catch (IOException | DBException e) {
|
||||
} catch (Exception e) {
|
||||
throw new DBException("Error parsing server configuration", e);
|
||||
}
|
||||
|
||||
@@ -636,7 +671,8 @@ public abstract class CBApplication extends BaseWebApplication implements WebAut
|
||||
|
||||
}
|
||||
|
||||
protected void readProductConfiguration(Map<String, Object> serverConfig, Gson gson, String homeFolder) throws DBException {
|
||||
protected void readProductConfiguration(Map<String, Object> serverConfig, Gson gson, String homeFolder)
|
||||
throws DBException {
|
||||
String productConfigPath = WebAppUtils.getRelativePath(
|
||||
JSONUtils.getString(
|
||||
serverConfig,
|
||||
@@ -652,7 +688,8 @@ public abstract class CBApplication extends BaseWebApplication implements WebAut
|
||||
log.error("Product configuration file not found (" + productConfigFile.getAbsolutePath() + "'");
|
||||
} else {
|
||||
log.debug("Load product configuration from '" + productConfigFile.getAbsolutePath() + "'");
|
||||
try (Reader reader = new InputStreamReader(new FileInputStream(productConfigFile), StandardCharsets.UTF_8)) {
|
||||
try (Reader reader = new InputStreamReader(new FileInputStream(productConfigFile),
|
||||
StandardCharsets.UTF_8)) {
|
||||
productConfiguration.putAll(JSONUtils.parseMap(gson, reader));
|
||||
} catch (Exception e) {
|
||||
throw new DBException("Error reading product configuration", e);
|
||||
@@ -673,11 +710,13 @@ public abstract class CBApplication extends BaseWebApplication implements WebAut
|
||||
}
|
||||
|
||||
protected Map<String, Object> readConnectionsPermissionsConfiguration(Path parentPath) {
|
||||
String permissionsConfigPath = WebAppUtils.getRelativePath(CBConstants.DEFAULT_DATASOURCE_PERMISSIONS_CONFIGURATION, parentPath);
|
||||
String permissionsConfigPath = WebAppUtils.getRelativePath(CBConstants.DEFAULT_DATASOURCE_PERMISSIONS_CONFIGURATION,
|
||||
parentPath);
|
||||
File permissionsConfigFile = new File(permissionsConfigPath);
|
||||
if (permissionsConfigFile.exists()) {
|
||||
log.debug("Load permissions configuration from '" + permissionsConfigFile.getAbsolutePath() + "'");
|
||||
try (Reader reader = new InputStreamReader(new FileInputStream(permissionsConfigFile), StandardCharsets.UTF_8)) {
|
||||
try (Reader reader = new InputStreamReader(new FileInputStream(permissionsConfigFile),
|
||||
StandardCharsets.UTF_8)) {
|
||||
return JSONUtils.parseMap(getGson(), reader);
|
||||
} catch (Exception e) {
|
||||
log.error("Error reading permissions configuration", e);
|
||||
@@ -728,18 +767,16 @@ public abstract class CBApplication extends BaseWebApplication implements WebAut
|
||||
}
|
||||
}
|
||||
|
||||
private Gson getGson() {
|
||||
protected GsonBuilder getGsonBuilder() {
|
||||
// Stupid way to populate existing objects but ok google (https://github.com/google/gson/issues/431)
|
||||
InstanceCreator<CBAppConfig> appConfigCreator = type -> appConfiguration;
|
||||
InstanceCreator<DataSourceNavigatorSettings> navSettingsCreator = type -> (DataSourceNavigatorSettings) appConfiguration.getDefaultNavigatorSettings();
|
||||
InstanceCreator<SMControllerConfiguration> smConfigCreator = type -> securityManagerConfiguration;
|
||||
|
||||
return new GsonBuilder()
|
||||
.setLenient()
|
||||
.registerTypeAdapter(CBAppConfig.class, appConfigCreator)
|
||||
.registerTypeAdapter(DataSourceNavigatorSettings.class, navSettingsCreator)
|
||||
.registerTypeAdapter(SMControllerConfiguration.class, smConfigCreator)
|
||||
.create();
|
||||
.registerTypeAdapter(SMControllerConfiguration.class, smConfigCreator);
|
||||
}
|
||||
|
||||
protected void readAdditionalConfiguration(Map<String, Object> rootConfig) throws DBException {
|
||||
@@ -805,7 +842,7 @@ public abstract class CBApplication extends BaseWebApplication implements WebAut
|
||||
@NotNull String newServerURL,
|
||||
@NotNull String adminName,
|
||||
@Nullable String adminPassword,
|
||||
@NotNull List<WebAuthInfo> authInfoList,
|
||||
@NotNull List<AuthInfo> authInfoList,
|
||||
long sessionExpireTime,
|
||||
@NotNull CBAppConfig appConfig,
|
||||
@Nullable SMCredentialsProvider credentialsProvider
|
||||
@@ -841,7 +878,8 @@ public abstract class CBApplication extends BaseWebApplication implements WebAut
|
||||
configurationMode = CommonUtils.isEmpty(serverName);
|
||||
|
||||
// Reloading configuration by services
|
||||
for (DBWServiceServerConfigurator wsc : WebServiceRegistry.getInstance().getWebServices(DBWServiceServerConfigurator.class)) {
|
||||
for (DBWServiceServerConfigurator wsc : WebServiceRegistry.getInstance()
|
||||
.getWebServices(DBWServiceServerConfigurator.class)) {
|
||||
try {
|
||||
wsc.reloadConfiguration(appConfig);
|
||||
} catch (Exception e) {
|
||||
@@ -865,11 +903,15 @@ public abstract class CBApplication extends BaseWebApplication implements WebAut
|
||||
protected abstract void finishSecurityServiceConfiguration(
|
||||
@NotNull String adminName,
|
||||
@Nullable String adminPassword,
|
||||
@NotNull List<WebAuthInfo> authInfoList
|
||||
@NotNull List<AuthInfo> authInfoList
|
||||
) throws DBException;
|
||||
|
||||
public synchronized void flushConfiguration(SMCredentialsProvider credentialsProvider) throws DBException {
|
||||
saveRuntimeConfig(serverName, serverURL, maxSessionIdleTime, appConfiguration, credentialsProvider);
|
||||
public synchronized void flushConfiguration(SMCredentialsProvider webSession) throws DBException {
|
||||
saveRuntimeConfig(serverName, serverURL, maxSessionIdleTime, appConfiguration, webSession);
|
||||
}
|
||||
|
||||
public synchronized void flushConfiguration() throws DBException {
|
||||
saveRuntimeConfig(serverName, serverURL, maxSessionIdleTime, appConfiguration, new NoAuthCredentialsProvider());
|
||||
}
|
||||
|
||||
|
||||
@@ -878,7 +920,9 @@ public abstract class CBApplication extends BaseWebApplication implements WebAut
|
||||
String anonymousTeamId = appConfig.getAnonymousUserTeam();
|
||||
var securityController = getSecurityController();
|
||||
for (DBPDataSourceContainer ds : WebServiceUtils.getGlobalDataSourceRegistry().getDataSources()) {
|
||||
var datasourcePermissions = securityController.getObjectPermissions(anonymousTeamId, ds.getId(), SMObjectType.datasource);
|
||||
var datasourcePermissions = securityController.getObjectPermissions(anonymousTeamId,
|
||||
ds.getId(),
|
||||
SMObjectType.datasource);
|
||||
if (ArrayUtils.isEmpty(datasourcePermissions.getPermissions())) {
|
||||
securityController.setObjectPermissions(
|
||||
Set.of(ds.getId()),
|
||||
@@ -897,7 +941,8 @@ public abstract class CBApplication extends BaseWebApplication implements WebAut
|
||||
private void grantPermissionsToConnections() {
|
||||
try {
|
||||
var globalRegistry = WebDataSourceUtils.getGlobalDataSourceRegistry();
|
||||
var permissionsConfiguration = readConnectionsPermissionsConfiguration(globalRegistry.getProject().getMetadataFolder(false));
|
||||
var permissionsConfiguration = readConnectionsPermissionsConfiguration(globalRegistry.getProject()
|
||||
.getMetadataFolder(false));
|
||||
if (permissionsConfiguration == null) {
|
||||
return;
|
||||
}
|
||||
@@ -905,7 +950,8 @@ public abstract class CBApplication extends BaseWebApplication implements WebAut
|
||||
var dataSourceId = entry.getKey();
|
||||
var ds = globalRegistry.getDataSource(dataSourceId);
|
||||
if (ds == null) {
|
||||
log.error("Connection " + dataSourceId + " is not found in project " + globalRegistry.getProject().getName());
|
||||
log.error("Connection " + dataSourceId + " is not found in project " + globalRegistry.getProject()
|
||||
.getName());
|
||||
}
|
||||
List<String> permissions = JSONUtils.getStringList(permissionsConfiguration, dataSourceId);
|
||||
var securityController = getSecurityController();
|
||||
@@ -971,7 +1017,10 @@ public abstract class CBApplication extends BaseWebApplication implements WebAut
|
||||
var originServerConfig = getServerConfigProps(this.originalConfigurationProperties); // get server properties from original configuration file
|
||||
rootConfig.put("server", serverConfigProperties);
|
||||
if (!CommonUtils.isEmpty(newServerName)) {
|
||||
copyConfigValue(originServerConfig, serverConfigProperties, CBConstants.PARAM_SERVER_NAME, newServerName);
|
||||
copyConfigValue(originServerConfig,
|
||||
serverConfigProperties,
|
||||
CBConstants.PARAM_SERVER_NAME,
|
||||
newServerName);
|
||||
}
|
||||
if (!CommonUtils.isEmpty(newServerURL)) {
|
||||
copyConfigValue(
|
||||
@@ -979,10 +1028,14 @@ public abstract class CBApplication extends BaseWebApplication implements WebAut
|
||||
}
|
||||
if (sessionExpireTime > 0) {
|
||||
copyConfigValue(
|
||||
originServerConfig, serverConfigProperties, CBConstants.PARAM_SESSION_EXPIRE_PERIOD, sessionExpireTime);
|
||||
originServerConfig,
|
||||
serverConfigProperties,
|
||||
CBConstants.PARAM_SESSION_EXPIRE_PERIOD,
|
||||
sessionExpireTime);
|
||||
}
|
||||
var databaseConfigProperties = new LinkedHashMap<String, Object>();
|
||||
Map<String, Object> oldRuntimeDBConfig = JSONUtils.getObject(originServerConfig, CBConstants.PARAM_DB_CONFIGURATION);
|
||||
Map<String, Object> oldRuntimeDBConfig = JSONUtils.getObject(originServerConfig,
|
||||
CBConstants.PARAM_DB_CONFIGURATION);
|
||||
if (!CommonUtils.isEmpty(databaseConfiguration) && !isDistributed()) {
|
||||
for (Map.Entry<String, Object> mp : databaseConfiguration.entrySet()) {
|
||||
copyConfigValue(oldRuntimeDBConfig, databaseConfigProperties, mp.getKey(), mp.getValue());
|
||||
@@ -998,23 +1051,41 @@ public abstract class CBApplication extends BaseWebApplication implements WebAut
|
||||
copyConfigValue(
|
||||
oldAppConfig, appConfigProperties, "anonymousAccessEnabled", appConfig.isAnonymousAccessEnabled());
|
||||
copyConfigValue(
|
||||
oldAppConfig, appConfigProperties, "supportsCustomConnections", appConfig.isSupportsCustomConnections());
|
||||
oldAppConfig,
|
||||
appConfigProperties,
|
||||
"supportsCustomConnections",
|
||||
appConfig.isSupportsCustomConnections());
|
||||
copyConfigValue(
|
||||
oldAppConfig, appConfigProperties, "publicCredentialsSaveEnabled", appConfig.isPublicCredentialsSaveEnabled());
|
||||
oldAppConfig,
|
||||
appConfigProperties,
|
||||
"publicCredentialsSaveEnabled",
|
||||
appConfig.isPublicCredentialsSaveEnabled());
|
||||
copyConfigValue(
|
||||
oldAppConfig, appConfigProperties, "adminCredentialsSaveEnabled", appConfig.isAdminCredentialsSaveEnabled());
|
||||
oldAppConfig,
|
||||
appConfigProperties,
|
||||
"adminCredentialsSaveEnabled",
|
||||
appConfig.isAdminCredentialsSaveEnabled());
|
||||
copyConfigValue(
|
||||
oldAppConfig, appConfigProperties, "enableReverseProxyAuth", appConfig.isEnabledReverseProxyAuth());
|
||||
copyConfigValue(
|
||||
oldAppConfig, appConfigProperties, "forwardProxy", appConfig.isEnabledForwardProxy());
|
||||
copyConfigValue(
|
||||
oldAppConfig, appConfigProperties, "linkExternalCredentialsWithUser", appConfig.isLinkExternalCredentialsWithUser());
|
||||
oldAppConfig,
|
||||
appConfigProperties,
|
||||
"linkExternalCredentialsWithUser",
|
||||
appConfig.isLinkExternalCredentialsWithUser());
|
||||
copyConfigValue(
|
||||
oldAppConfig, appConfigProperties, "redirectOnFederatedAuth", appConfig.isRedirectOnFederatedAuth());
|
||||
copyConfigValue(
|
||||
oldAppConfig, appConfigProperties, CBConstants.PARAM_RESOURCE_MANAGER_ENABLED, appConfig.isResourceManagerEnabled());
|
||||
oldAppConfig,
|
||||
appConfigProperties,
|
||||
CBConstants.PARAM_RESOURCE_MANAGER_ENABLED,
|
||||
appConfig.isResourceManagerEnabled());
|
||||
copyConfigValue(
|
||||
oldAppConfig, appConfigProperties, CBConstants.PARAM_SHOW_READ_ONLY_CONN_INFO, appConfig.isShowReadOnlyConnectionInfo());
|
||||
oldAppConfig,
|
||||
appConfigProperties,
|
||||
CBConstants.PARAM_SHOW_READ_ONLY_CONN_INFO,
|
||||
appConfig.isShowReadOnlyConnectionInfo());
|
||||
copyConfigValue(
|
||||
oldAppConfig,
|
||||
appConfigProperties,
|
||||
@@ -1022,7 +1093,8 @@ public abstract class CBApplication extends BaseWebApplication implements WebAut
|
||||
appConfig.isGrantConnectionsAccessToAnonymousTeam());
|
||||
|
||||
Map<String, Object> resourceQuotas = new LinkedHashMap<>();
|
||||
Map<String, Object> originResourceQuotas = JSONUtils.getObject(oldAppConfig, CBConstants.PARAM_RESOURCE_QUOTAS);
|
||||
Map<String, Object> originResourceQuotas = JSONUtils.getObject(oldAppConfig,
|
||||
CBConstants.PARAM_RESOURCE_QUOTAS);
|
||||
for (Map.Entry<String, Object> mp : appConfig.getResourceQuotas().entrySet()) {
|
||||
copyConfigValue(originResourceQuotas, resourceQuotas, mp.getKey(), mp.getValue());
|
||||
}
|
||||
@@ -1136,7 +1208,12 @@ public abstract class CBApplication extends BaseWebApplication implements WebAut
|
||||
}
|
||||
|
||||
// gets info about patterns from original configuration file and saves it to runtime config
|
||||
private void copyConfigValue(Map<String, Object> oldConfig, Map<String, Object> newConfig, String key, Object defaultValue) {
|
||||
private void copyConfigValue(
|
||||
Map<String, Object> oldConfig,
|
||||
Map<String, Object> newConfig,
|
||||
String key,
|
||||
Object defaultValue
|
||||
) {
|
||||
Object value = oldConfig.get(key);
|
||||
if (value instanceof Map && defaultValue instanceof Map) {
|
||||
Map<String, Object> subValue = new LinkedHashMap<>();
|
||||
@@ -1167,4 +1244,24 @@ public abstract class CBApplication extends BaseWebApplication implements WebAut
|
||||
}
|
||||
return containerId;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Path getSslConfigurationPath() {
|
||||
if (sslConfigurationPath == null) {
|
||||
return null;
|
||||
}
|
||||
var sslConfiguration = Path.of(sslConfigurationPath);
|
||||
return sslConfiguration.isAbsolute() ? sslConfiguration : getHomeDirectory().resolve(sslConfiguration);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Class<? extends DBPPlatform> getPlatformClass() {
|
||||
return CBPlatform.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends DBPPlatformUI> getPlatformUIClass() {
|
||||
return CBPlatformUI.class;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
*/
|
||||
package io.cloudbeaver.server;
|
||||
|
||||
import org.jkiss.dbeaver.model.auth.AuthInfo;
|
||||
import io.cloudbeaver.auth.NoAuthCredentialsProvider;
|
||||
import io.cloudbeaver.model.rm.local.LocalResourceController;
|
||||
import io.cloudbeaver.model.session.WebAuthInfo;
|
||||
import io.cloudbeaver.service.security.CBEmbeddedSecurityController;
|
||||
import io.cloudbeaver.service.security.EmbeddedSecurityControllerFactory;
|
||||
import org.jkiss.code.NotNull;
|
||||
@@ -31,7 +31,6 @@ import org.jkiss.dbeaver.model.auth.SMCredentialsProvider;
|
||||
import org.jkiss.dbeaver.model.rm.RMController;
|
||||
import org.jkiss.dbeaver.model.security.SMAdminController;
|
||||
import org.jkiss.dbeaver.model.security.SMController;
|
||||
import org.jkiss.dbeaver.registry.BasePlatformImpl;
|
||||
import org.jkiss.dbeaver.registry.LocalFileController;
|
||||
import org.jkiss.dbeaver.runtime.DBWorkbench;
|
||||
|
||||
@@ -94,7 +93,7 @@ public class CBApplicationCE extends CBApplication {
|
||||
protected void finishSecurityServiceConfiguration(
|
||||
@NotNull String adminName,
|
||||
@Nullable String adminPassword,
|
||||
@NotNull List<WebAuthInfo> authInfoList
|
||||
@NotNull List<AuthInfo> authInfoList
|
||||
) throws DBException {
|
||||
if (securityController instanceof CBEmbeddedSecurityController) {
|
||||
((CBEmbeddedSecurityController) securityController).finishConfiguration(adminName, adminPassword, authInfoList);
|
||||
|
||||
@@ -28,6 +28,7 @@ public class CBConstants {
|
||||
public static final String PARAM_SERVER_PORT = "serverPort";
|
||||
public static final String PARAM_SERVER_HOST = "serverHost";
|
||||
public static final String PARAM_SERVER_NAME = "serverName";
|
||||
public static final String PARAM_SSL_CONFIGURATION_PATH = "sslConfigurationPath";
|
||||
public static final String PARAM_CONTENT_ROOT = "contentRoot";
|
||||
public static final String PARAM_SERVER_URL = "serverURL";
|
||||
public static final String PARAM_ROOT_URI = "rootURI";
|
||||
|
||||
@@ -22,8 +22,10 @@ import io.cloudbeaver.server.jobs.SessionStateJob;
|
||||
import io.cloudbeaver.server.jobs.WebSessionMonitorJob;
|
||||
import io.cloudbeaver.service.session.WebSessionManager;
|
||||
import org.eclipse.core.resources.ResourcesPlugin;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Platform;
|
||||
import org.eclipse.core.runtime.Plugin;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.jkiss.code.NotNull;
|
||||
import org.jkiss.code.Nullable;
|
||||
import org.jkiss.dbeaver.DBException;
|
||||
@@ -39,6 +41,7 @@ import org.jkiss.dbeaver.model.impl.app.DefaultCertificateStorage;
|
||||
import org.jkiss.dbeaver.model.preferences.DBPPreferenceStore;
|
||||
import org.jkiss.dbeaver.model.qm.QMRegistry;
|
||||
import org.jkiss.dbeaver.model.qm.QMUtils;
|
||||
import org.jkiss.dbeaver.model.runtime.AbstractJob;
|
||||
import org.jkiss.dbeaver.model.runtime.DBRProgressMonitor;
|
||||
import org.jkiss.dbeaver.model.runtime.VoidProgressMonitor;
|
||||
import org.jkiss.dbeaver.registry.BasePlatformImpl;
|
||||
@@ -49,13 +52,13 @@ import org.jkiss.dbeaver.runtime.qm.QMLogFileWriter;
|
||||
import org.jkiss.dbeaver.runtime.qm.QMRegistryImpl;
|
||||
import org.jkiss.dbeaver.utils.ContentUtils;
|
||||
import org.jkiss.dbeaver.utils.GeneralUtils;
|
||||
import org.jkiss.utils.IOUtils;
|
||||
import org.osgi.framework.Bundle;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -67,6 +70,7 @@ public class CBPlatform extends BasePlatformImpl {
|
||||
public static final String PLUGIN_ID = "io.cloudbeaver.server"; //$NON-NLS-1$
|
||||
|
||||
private static final Log log = Log.getLog(CBPlatform.class);
|
||||
private static final String TEMP_FILE_FOLDER = "temp-sql-upload-files";
|
||||
|
||||
public static final String WORK_DATA_FOLDER_NAME = ".work-data";
|
||||
|
||||
@@ -121,7 +125,7 @@ public class CBPlatform extends BasePlatformImpl {
|
||||
return WebPlatformActivator.getInstance().getPreferences();
|
||||
}
|
||||
|
||||
private CBPlatform() {
|
||||
CBPlatform() {
|
||||
}
|
||||
|
||||
public static void setApplication(CBApplication application) {
|
||||
@@ -153,12 +157,25 @@ public class CBPlatform extends BasePlatformImpl {
|
||||
|
||||
refreshApplicableDrivers();
|
||||
|
||||
refreshDisabledDriversConfig();
|
||||
|
||||
new WebSessionMonitorJob(this)
|
||||
.scheduleMonitor();
|
||||
|
||||
new SessionStateJob(this)
|
||||
.scheduleMonitor();
|
||||
|
||||
new AbstractJob("Delete temp folder") {
|
||||
@Override
|
||||
protected IStatus run(DBRProgressMonitor monitor) {
|
||||
try {
|
||||
IOUtils.deleteDirectory(getTempFolder(monitor, TEMP_FILE_FOLDER));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return Status.OK_STATUS;
|
||||
}
|
||||
}.schedule();
|
||||
log.info("Web platform initialized (" + (System.currentTimeMillis() - startTime) + "ms)");
|
||||
}
|
||||
|
||||
@@ -312,6 +329,18 @@ public class CBPlatform extends BasePlatformImpl {
|
||||
log.info("Available drivers: " + applicableDrivers.stream().map(DBPDriver::getFullName).collect(Collectors.joining(",")));
|
||||
}
|
||||
|
||||
private void refreshDisabledDriversConfig() {
|
||||
CBAppConfig config = application.getAppConfiguration();
|
||||
Set<String> disabledDrivers = new LinkedHashSet<>(Arrays.asList(config.getDisabledDrivers()));
|
||||
for (DBPDriver driver : applicableDrivers) {
|
||||
if (!driver.isEmbedded() || config.isDriverForceEnabled(driver.getFullId())) {
|
||||
continue;
|
||||
}
|
||||
disabledDrivers.add(driver.getFullId());
|
||||
}
|
||||
config.setDisabledDrivers(disabledDrivers.toArray(new String[0]));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public DBFileController createFileController() {
|
||||
|
||||
@@ -25,4 +25,8 @@ public class CBPlatformUI extends ConsoleUserInterface {
|
||||
|
||||
public static final CBPlatformUI INSTANCE = new CBPlatformUI();
|
||||
|
||||
protected void initialize() {
|
||||
// just a placeholder for injection
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
-46
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* DBeaver - Universal Database Manager
|
||||
* Copyright (C) 2010-2023 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 org.eclipse.core.runtime.IAdapterFactory;
|
||||
import org.jkiss.dbeaver.model.app.DBPPlatform;
|
||||
import org.jkiss.dbeaver.runtime.DBWorkbench;
|
||||
import org.jkiss.dbeaver.runtime.ui.DBPPlatformUI;
|
||||
|
||||
public class WebPlatformAdapterFactory implements IAdapterFactory {
|
||||
|
||||
private static final Class<?>[] CLASSES = new Class[] { DBPPlatform.class, DBPPlatformUI.class };
|
||||
|
||||
@Override
|
||||
public <T> T getAdapter(Object adaptableObject, Class<T> adapterType) {
|
||||
if (adaptableObject instanceof DBWorkbench) {
|
||||
if (adapterType == DBPPlatform.class) {
|
||||
return adapterType.cast(CBPlatform.getInstance());
|
||||
} else if (adapterType == DBPPlatformUI.class) {
|
||||
return adapterType.cast(CBPlatformUI.INSTANCE);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?>[] getAdapterList() {
|
||||
return CLASSES;
|
||||
}
|
||||
|
||||
}
|
||||
+3
-3
@@ -20,9 +20,9 @@ import io.cloudbeaver.model.session.WebSession;
|
||||
import io.cloudbeaver.service.DBWServletHandler;
|
||||
import org.jkiss.dbeaver.DBException;
|
||||
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.Servlet;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
|
||||
+2
-2
@@ -20,8 +20,8 @@ import io.cloudbeaver.model.session.WebSession;
|
||||
import io.cloudbeaver.service.DBWSessionHandler;
|
||||
import org.jkiss.dbeaver.DBException;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
public abstract class AbstractActionSessionHandler implements DBWSessionHandler {
|
||||
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* DBeaver - Universal Database Manager
|
||||
* Copyright (C) 2010-2023 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.server.CBPlatform;
|
||||
import org.jkiss.code.NotNull;
|
||||
import org.jkiss.dbeaver.Log;
|
||||
import org.jkiss.dbeaver.model.runtime.VoidProgressMonitor;
|
||||
import org.jkiss.dbeaver.model.websocket.WSEventHandler;
|
||||
import org.jkiss.dbeaver.model.websocket.event.WSEventDeleteTempFile;
|
||||
import org.jkiss.utils.IOUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class WSDeleteTempFileHandler implements WSEventHandler<WSEventDeleteTempFile> {
|
||||
|
||||
private static final Log log = Log.getLog(WSDeleteTempFileHandler.class);
|
||||
private static final String TEMP_FILE_FOLDER = "temp-sql-upload-files";
|
||||
|
||||
public void resetTempFolder(String sessionId) {
|
||||
Path path = CBPlatform.getInstance()
|
||||
.getTempFolder(new VoidProgressMonitor(), TEMP_FILE_FOLDER)
|
||||
.resolve(sessionId);
|
||||
if (Files.exists(path)) {
|
||||
try {
|
||||
IOUtils.deleteDirectory(path);
|
||||
} catch (IOException e) {
|
||||
log.error("Error deleting temp path", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleEvent(@NotNull WSEventDeleteTempFile event) {
|
||||
resetTempFolder(event.getSessionId());
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* DBeaver - Universal Database Manager
|
||||
* Copyright (C) 2010-2023 DBeaver Corp
|
||||
*
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* NOTICE: All information contained herein is, and remains
|
||||
* the property of DBeaver Corp and its suppliers, if any.
|
||||
* The intellectual and technical concepts contained
|
||||
* herein are proprietary to DBeaver Corp and its suppliers
|
||||
* and may be covered by U.S. and Foreign Patents,
|
||||
* patents in process, and are protected by trade secret or copyright law.
|
||||
* Dissemination of this information or reproduction of this material
|
||||
* is strictly forbidden unless prior written permission is obtained
|
||||
* from DBeaver Corp.
|
||||
*/
|
||||
package io.cloudbeaver.server.events;
|
||||
|
||||
import org.jkiss.code.NotNull;
|
||||
import org.jkiss.dbeaver.Log;
|
||||
import org.jkiss.dbeaver.model.WorkspaceConfigEventManager;
|
||||
import org.jkiss.dbeaver.model.websocket.event.WSEventType;
|
||||
import org.jkiss.dbeaver.model.websocket.event.WSWorkspaceConfigurationChangedEvent;
|
||||
|
||||
public class WSEventHandlerWorkspaceConfigUpdate extends WSDefaultEventHandler<WSWorkspaceConfigurationChangedEvent> {
|
||||
private static final Log log = Log.getLog(WSEventHandlerWorkspaceConfigUpdate.class);
|
||||
|
||||
@Override
|
||||
public void handleEvent(@NotNull WSWorkspaceConfigurationChangedEvent event) {
|
||||
String configFileName = event.getConfigFilePath();
|
||||
WorkspaceConfigEventManager.fireConfigChangedEvent(configFileName);
|
||||
super.handleEvent(event);
|
||||
}
|
||||
|
||||
}
|
||||
+16
-24
@@ -18,21 +18,18 @@ package io.cloudbeaver.server.events;
|
||||
|
||||
import io.cloudbeaver.model.session.BaseWebSession;
|
||||
import io.cloudbeaver.model.session.WebSession;
|
||||
import io.cloudbeaver.server.CBPlatform;
|
||||
import io.cloudbeaver.utils.WebAppUtils;
|
||||
import org.jkiss.code.NotNull;
|
||||
import org.jkiss.dbeaver.DBException;
|
||||
import org.jkiss.dbeaver.Log;
|
||||
import org.jkiss.dbeaver.model.security.SMObjectPermissionsGrant;
|
||||
import org.jkiss.dbeaver.model.security.SMObjectType;
|
||||
import org.jkiss.dbeaver.model.websocket.event.WSEventType;
|
||||
import org.jkiss.dbeaver.model.websocket.event.WSProjectUpdateEvent;
|
||||
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.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class WSObjectPermissionUpdatedEventHandler extends WSDefaultEventHandler<WSObjectPermissionEvent> {
|
||||
private static final Log log = Log.getLog(WSObjectPermissionUpdatedEventHandler.class);
|
||||
@@ -44,24 +41,16 @@ public class WSObjectPermissionUpdatedEventHandler extends WSDefaultEventHandler
|
||||
if (event.getSmObjectType() == SMObjectType.datasource && !(activeUserSession instanceof WebSession)) {
|
||||
return;
|
||||
}
|
||||
var user = activeUserSession.getUserContext().getUser();
|
||||
var objectId = event.getObjectId();
|
||||
|
||||
var userSubjects = new HashSet<>(Set.of(user.getTeams()));
|
||||
userSubjects.add(user.getUserId());
|
||||
|
||||
var smController = CBPlatform.getInstance().getApplication().getSecurityController();
|
||||
var shouldBeAccessible = smController.getObjectPermissionGrants(event.getObjectId(), event.getSmObjectType())
|
||||
.stream()
|
||||
.map(SMObjectPermissionsGrant::getSubjectId)
|
||||
.anyMatch(userSubjects::contains);
|
||||
boolean isAccessibleNow;
|
||||
switch (event.getSmObjectType()) {
|
||||
case project:
|
||||
var accessibleProjectIds = activeUserSession.getUserContext().getAccessibleProjectIds();
|
||||
isAccessibleNow = accessibleProjectIds.contains(objectId);
|
||||
if (shouldBeAccessible && !isAccessibleNow) {
|
||||
// adding project to session cache
|
||||
if (WSEventType.OBJECT_PERMISSIONS_UPDATED.getEventId().equals(event.getId())) {
|
||||
var accessibleProjectIds = activeUserSession.getUserContext().getAccessibleProjectIds();
|
||||
if (accessibleProjectIds.contains(event.getObjectId())) {
|
||||
return;
|
||||
}
|
||||
activeUserSession.addSessionProject(objectId);
|
||||
activeUserSession.addSessionEvent(
|
||||
WSProjectUpdateEvent.create(
|
||||
@@ -70,8 +59,7 @@ public class WSObjectPermissionUpdatedEventHandler extends WSDefaultEventHandler
|
||||
objectId
|
||||
)
|
||||
);
|
||||
} else if (!shouldBeAccessible && isAccessibleNow) {
|
||||
// removing project from session cache
|
||||
} else if (WSEventType.OBJECT_PERMISSIONS_DELETED.getEventId().equals(event.getId())) {
|
||||
activeUserSession.removeSessionProject(objectId);
|
||||
activeUserSession.addSessionEvent(
|
||||
WSProjectUpdateEvent.delete(
|
||||
@@ -80,19 +68,23 @@ public class WSObjectPermissionUpdatedEventHandler extends WSDefaultEventHandler
|
||||
objectId
|
||||
)
|
||||
);
|
||||
};
|
||||
}
|
||||
break;
|
||||
case datasource:
|
||||
var webSession = (WebSession) activeUserSession;
|
||||
var dataSources = List.of(objectId);
|
||||
|
||||
var project = webSession.getProjectById(WebAppUtils.getGlobalProjectId());
|
||||
if (project == null) {
|
||||
log.error("Project " + WebAppUtils.getGlobalProjectId() +
|
||||
" is not found in session " + activeUserSession.getSessionId());
|
||||
return;
|
||||
}
|
||||
isAccessibleNow = webSession.findWebConnectionInfo(objectId) != null;
|
||||
var dataSources = List.of(objectId);
|
||||
if (shouldBeAccessible && !isAccessibleNow) {
|
||||
if (WSEventType.OBJECT_PERMISSIONS_UPDATED.getEventId().equals(event.getId())) {
|
||||
isAccessibleNow = webSession.findWebConnectionInfo(objectId) != null;
|
||||
if (isAccessibleNow) {
|
||||
return;
|
||||
}
|
||||
webSession.addAccessibleConnectionToCache(objectId);
|
||||
webSession.addSessionEvent(
|
||||
WSDataSourceEvent.create(
|
||||
@@ -103,7 +95,7 @@ public class WSObjectPermissionUpdatedEventHandler extends WSDefaultEventHandler
|
||||
WSDataSourceProperty.CONFIGURATION
|
||||
)
|
||||
);
|
||||
} else if (!shouldBeAccessible && isAccessibleNow) {
|
||||
} else if (WSEventType.OBJECT_PERMISSIONS_DELETED.getEventId().equals(event.getId())) {
|
||||
webSession.removeAccessibleConnectionFromCache(objectId);
|
||||
webSession.addSessionEvent(
|
||||
WSDataSourceEvent.delete(
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* DBeaver - Universal Database Manager
|
||||
* Copyright (C) 2010-2023 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.server.CBPlatform;
|
||||
import org.jkiss.code.NotNull;
|
||||
import org.jkiss.dbeaver.model.websocket.WSEventHandler;
|
||||
import org.jkiss.dbeaver.model.websocket.event.WSUserDeletedEvent;
|
||||
|
||||
public class WSUserDeletedEventHandler<EVENT extends WSUserDeletedEvent> implements WSEventHandler<EVENT> {
|
||||
@Override
|
||||
public void handleEvent(@NotNull EVENT event) {
|
||||
CBPlatform.getInstance().getSessionManager().closeUserSessions(event.getDeletedUserId());
|
||||
}
|
||||
}
|
||||
+14
-4
@@ -31,15 +31,17 @@ import io.cloudbeaver.WebServiceUtils;
|
||||
import io.cloudbeaver.model.session.WebSession;
|
||||
import io.cloudbeaver.registry.WebServiceRegistry;
|
||||
import io.cloudbeaver.server.CBApplication;
|
||||
import io.cloudbeaver.server.HttpConstants;
|
||||
import io.cloudbeaver.service.DBWServiceBindingGraphQL;
|
||||
import io.cloudbeaver.service.WebServiceBindingBase;
|
||||
import org.jkiss.dbeaver.Log;
|
||||
import org.jkiss.utils.CommonUtils;
|
||||
import org.jkiss.utils.IOUtils;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServlet;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
@@ -152,6 +154,14 @@ public class GraphQLEndpoint extends HttpServlet {
|
||||
|
||||
@Override
|
||||
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
|
||||
String contentType = request.getContentType();
|
||||
if (CommonUtils.isEmpty(contentType) || !contentType.startsWith(HttpConstants.TYPE_JSON)) {
|
||||
String error = "Bad request," + (CommonUtils.isEmpty(contentType)
|
||||
? " content type is missing"
|
||||
: " incorrect content type:" + contentType);
|
||||
response.sendError(400, error);
|
||||
return;
|
||||
}
|
||||
String postBody = IOUtils.readToString(request.getReader());
|
||||
JsonElement json = gson.fromJson(postBody, JsonElement.class);
|
||||
if (json instanceof JsonArray) {
|
||||
|
||||
+24
-7
@@ -33,7 +33,9 @@ import org.eclipse.jetty.servlet.ErrorPageErrorHandler;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.eclipse.jetty.servlet.ServletMapping;
|
||||
import org.eclipse.jetty.util.resource.PathResource;
|
||||
import org.eclipse.jetty.websocket.server.config.JettyWebSocketServletContainerInitializer;
|
||||
import org.eclipse.jetty.xml.XmlConfiguration;
|
||||
import org.jkiss.code.NotNull;
|
||||
import org.jkiss.dbeaver.DBException;
|
||||
import org.jkiss.dbeaver.Log;
|
||||
@@ -71,11 +73,25 @@ public class CBJettyServer {
|
||||
JettyServer server;
|
||||
int serverPort = application.getServerPort();
|
||||
String serverHost = application.getServerHost();
|
||||
if (CommonUtils.isEmpty(serverHost)) {
|
||||
server = new JettyServer(serverPort);
|
||||
Path sslPath = application.getSslConfigurationPath();
|
||||
|
||||
boolean sslConfigurationExists = sslPath != null && Files.exists(sslPath);
|
||||
if (sslConfigurationExists) {
|
||||
server = new JettyServer();
|
||||
XmlConfiguration sslConfiguration = new XmlConfiguration(new PathResource(sslPath));
|
||||
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||
// method sslConfiguration.configure() does not see the context class of the Loader,
|
||||
// so we have to configure it manually, then return the old classLoader.
|
||||
Thread.currentThread().setContextClassLoader(this.getClass().getClassLoader());
|
||||
sslConfiguration.configure(server);
|
||||
Thread.currentThread().setContextClassLoader(classLoader);
|
||||
} else {
|
||||
server = new JettyServer(
|
||||
InetSocketAddress.createUnresolved(serverHost, serverPort));
|
||||
if (CommonUtils.isEmpty(serverHost)) {
|
||||
server = new JettyServer(serverPort);
|
||||
} else {
|
||||
server = new JettyServer(
|
||||
InetSocketAddress.createUnresolved(serverHost, serverPort));
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
@@ -112,8 +128,6 @@ public class CBJettyServer {
|
||||
|
||||
server.setHandler(servletContextHandler);
|
||||
|
||||
var serverConnector = new ServerConnector(server);
|
||||
server.addConnector(serverConnector);
|
||||
JettyWebSocketServletContainerInitializer.configure(servletContextHandler,
|
||||
(context, wsContainer) -> {
|
||||
wsContainer.setIdleTimeout(Duration.ofMinutes(5));
|
||||
@@ -205,11 +219,14 @@ public class CBJettyServer {
|
||||
servletContextHandler.setSessionHandler(sessionHandler);
|
||||
}
|
||||
|
||||
private static class JettyServer extends Server {
|
||||
public static class JettyServer extends Server {
|
||||
public JettyServer(int serverPort) {
|
||||
super(serverPort);
|
||||
}
|
||||
|
||||
public JettyServer() {
|
||||
super();
|
||||
}
|
||||
public JettyServer(InetSocketAddress addr) {
|
||||
super(addr);
|
||||
}
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.jkiss.dbeaver.DBException;
|
||||
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import jakarta.servlet.http.HttpServlet;
|
||||
|
||||
public class CBJettyServletContext implements DBWServletContext {
|
||||
private final ServletContextHandler contextHandler;
|
||||
|
||||
+3
-3
@@ -19,9 +19,9 @@ package io.cloudbeaver.server.jetty;
|
||||
import io.cloudbeaver.server.CBApplication;
|
||||
import io.cloudbeaver.server.CBConstants;
|
||||
|
||||
import javax.servlet.ServletContextEvent;
|
||||
import javax.servlet.ServletContextListener;
|
||||
import javax.servlet.SessionCookieConfig;
|
||||
import jakarta.servlet.ServletContextEvent;
|
||||
import jakarta.servlet.ServletContextListener;
|
||||
import jakarta.servlet.SessionCookieConfig;
|
||||
|
||||
public class CBServerContextListener implements ServletContextListener {
|
||||
|
||||
|
||||
+23
-23
@@ -83,31 +83,31 @@ public class SqlOutputLogReaderJob extends AbstractJob {
|
||||
|
||||
private void dumpOutput(DBRProgressMonitor monitor) {
|
||||
if (!monitor.isCanceled()) {
|
||||
if (dbcServerOutputReader.isAsyncOutputReadSupported()) {
|
||||
try {
|
||||
if (!dbcStatement.isStatementClosed()) {
|
||||
List<WSOutputLogInfo> messages = new ArrayList<>();
|
||||
dbcServerOutputReader.readServerOutput(monitor, dbcExecutionContext, null, dbcStatement, new DBCOutputWriter() {
|
||||
@Override
|
||||
public void println(@Nullable DBCOutputSeverity severity, @Nullable String message) {
|
||||
if (message != null && severity != null) {
|
||||
messages.add(new WSOutputLogInfo(severity.getName(), message));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
messages.clear();
|
||||
}
|
||||
});
|
||||
webSession.addSessionEvent(new WSOutputDBLogEvent(
|
||||
contextInfoId,
|
||||
messages,
|
||||
System.currentTimeMillis()));
|
||||
List<WSOutputLogInfo> messages = new ArrayList<>();
|
||||
final DBCOutputWriter writer = new DBCOutputWriter() {
|
||||
@Override
|
||||
public void println(@Nullable DBCOutputSeverity severity, @Nullable String message) {
|
||||
if (message != null) {
|
||||
messages.add(new WSOutputLogInfo(severity == null ? null : severity.getName(), message));
|
||||
}
|
||||
} catch (DBCException e) {
|
||||
log.error(e);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() {
|
||||
messages.clear();
|
||||
}
|
||||
};
|
||||
try {
|
||||
dbcServerOutputReader.readServerOutput(monitor, dbcExecutionContext, null, null, writer);
|
||||
if (dbcServerOutputReader.isAsyncOutputReadSupported() && !dbcStatement.isStatementClosed()) {
|
||||
dbcServerOutputReader.readServerOutput(monitor, dbcExecutionContext, null, dbcStatement, writer);
|
||||
}
|
||||
webSession.addSessionEvent(new WSOutputDBLogEvent(
|
||||
contextInfoId,
|
||||
messages,
|
||||
System.currentTimeMillis()));
|
||||
} catch (DBCException e) {
|
||||
log.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -5,10 +5,10 @@ import org.jkiss.dbeaver.Log;
|
||||
import org.jkiss.utils.CommonUtils;
|
||||
import org.jkiss.utils.IOUtils;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServlet;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
+4
-4
@@ -47,10 +47,10 @@ import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Map;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.annotation.WebServlet;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
@WebServlet(urlPatterns = "/")
|
||||
public class CBStaticServlet extends DefaultServlet {
|
||||
|
||||
+4
-4
@@ -7,10 +7,10 @@ import org.jkiss.dbeaver.Log;
|
||||
import org.jkiss.dbeaver.model.data.json.JSONUtils;
|
||||
import org.jkiss.dbeaver.utils.GeneralUtils;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.annotation.WebServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.annotation.WebServlet;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
-1
@@ -101,7 +101,6 @@ public class CBEventsWebSocket extends CBAbstractWebSocket implements CBWebSessi
|
||||
public void handleWebSessionEvent(WSEvent event) {
|
||||
super.handleEvent(event);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleEventException(Exception e) {
|
||||
super.handleEventException(e);
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ import org.jkiss.dbeaver.DBException;
|
||||
import org.jkiss.dbeaver.Log;
|
||||
import org.jkiss.dbeaver.model.security.exception.SMAccessTokenExpiredException;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user