Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
19cbe8c39f | ||
|
|
d8bcc11a95 | ||
|
|
9f203cf7d7 | ||
|
|
06a612481f | ||
|
|
682d6597e4 | ||
|
|
a59372cbe3 | ||
|
|
101f6fc103 | ||
|
|
23c618e1c9 | ||
|
|
0bc044fa67 | ||
|
|
5bdccb6e63 | ||
|
|
6d7338e64d | ||
|
|
0358298090 | ||
|
|
0e3dc74bb4 | ||
|
|
302e1acabd | ||
|
|
c9db4a0d16 | ||
|
|
cc239149ba | ||
|
|
c4a5f8d707 | ||
|
|
75a2d880f6 | ||
|
|
e5cba59a02 | ||
|
|
0e8868a650 | ||
|
|
7f49b891df | ||
|
|
0ac471d160 | ||
|
|
370cb611d7 | ||
|
|
d4b57edede | ||
|
|
85dd1e92ad | ||
|
|
ef0b30b1ca | ||
|
|
0d8adf9ced | ||
|
|
695c008245 | ||
|
|
96fccd28a9 | ||
|
|
5f3965ff0a | ||
|
|
6062084128 | ||
|
|
01d1e6f706 | ||
|
|
9eb7c1cbea | ||
|
|
5d70803d6d | ||
|
|
53b5b59f56 | ||
|
|
17acce3e7b | ||
|
|
d3dd5c0b56 | ||
|
|
71e7a7c481 | ||
|
|
0b707be615 | ||
|
|
179332ed5a | ||
|
|
a8a7574e69 | ||
|
|
e30d2eca90 | ||
|
|
4bc6dcca67 | ||
|
|
46a8c1ad6a | ||
|
|
3e575e2f43 | ||
|
|
b11b2a2f50 | ||
|
|
1bfd8d7f3c | ||
|
|
f1da4f5de8 | ||
|
|
5a7583654f | ||
|
|
cfa7bef407 | ||
|
|
8997f616a2 | ||
|
|
f50f799b88 | ||
|
|
3bcac26ff9 | ||
|
|
c5f4a56c0c | ||
|
|
d74320f06e | ||
|
|
b003f76903 | ||
|
|
ebc3460fce | ||
|
|
ed51fe475e | ||
|
|
f2bd3933c6 | ||
|
|
862f101772 | ||
|
|
6d555645e9 | ||
|
|
e587ef404c | ||
|
|
fe753bd272 | ||
|
|
c07c153f15 | ||
|
|
3416184236 | ||
|
|
6e3ee1c607 | ||
|
|
b512404c85 | ||
|
|
5bb6e9133f | ||
|
|
344c236d72 | ||
|
|
b4b2a4ff67 | ||
|
|
205a661922 | ||
|
|
eead9b77e7 | ||
|
|
47e734dbf2 | ||
|
|
ce372a73bf | ||
|
|
10c5d25735 | ||
|
|
81dcc91747 | ||
|
|
3a62fc5a2a | ||
|
|
10adb6a11b | ||
|
|
82fade7645 | ||
|
|
37dced23f0 | ||
|
|
6f857bdbcb | ||
|
|
6ba9c192ce | ||
|
|
221af6caa6 | ||
|
|
e22492ad51 | ||
|
|
2b8efc6361 | ||
|
|
73430a2062 | ||
|
|
fc411bfc49 | ||
|
|
4450145d31 | ||
|
|
cd84200135 | ||
|
|
6997d0149e | ||
|
|
5981f4bd13 | ||
|
|
5113fda7a6 | ||
|
|
7ce07f7dcf | ||
|
|
078a959e3d | ||
|
|
b4f517f7ff | ||
|
|
36dc2e9d2a | ||
|
|
858c85adbe | ||
|
|
2cd86449d0 | ||
|
|
c37fb061bd | ||
|
|
dc9cc3730b | ||
|
|
872b60de5c | ||
|
|
5d2ce142dd | ||
|
|
9666bd6c8d | ||
|
|
0b3c79865e | ||
|
|
9c903f944c | ||
|
|
541d9dfcb4 | ||
|
|
b9d3006915 | ||
|
|
68b7ddb592 | ||
|
|
4309aa3ba7 | ||
|
|
f9bbadfc6a | ||
|
|
c6f8918983 | ||
|
|
16c95d21a7 | ||
|
|
bae912fa40 | ||
|
|
ca3ec76db6 | ||
|
|
4050545f7c | ||
|
|
975bcd9fb0 | ||
|
|
3cd547f879 | ||
|
|
5736e173ea | ||
|
|
5a26cad588 | ||
|
|
3b616b2fb1 | ||
|
|
35f05e49b3 | ||
|
|
61fa8b16c9 | ||
|
|
3258851425 | ||
|
|
0f5450c6d2 | ||
|
|
07f18a1b05 | ||
|
|
02ecc82e73 | ||
|
|
0d111e0fb6 | ||
|
|
7af597eca2 | ||
|
|
64c71becc6 | ||
|
|
ffec77d50b | ||
|
|
d69b4282c8 | ||
|
|
aa973fc8ae | ||
|
|
8c91d40932 | ||
|
|
2f5fb6a996 | ||
|
|
cfc338c5f0 | ||
|
|
32403920fe | ||
|
|
e9384615dc | ||
|
|
07d965ea46 | ||
|
|
a43b70e360 | ||
|
|
095e11247d | ||
|
|
88162c683e | ||
|
|
cf3c696f7e | ||
|
|
02eaf787e9 | ||
|
|
e5c249e81c | ||
|
|
c0b868b53b | ||
|
|
39a14920e3 | ||
|
|
5cf9dea9a8 | ||
|
|
0b7eafaca0 | ||
|
|
ed8aeed818 | ||
|
|
0b91244f91 | ||
|
|
46c67a2f4e | ||
|
|
c87e925991 | ||
|
|
5fb80af90e | ||
|
|
77467209c2 | ||
|
|
cd613ded0a | ||
|
|
e8283173ba |
No files matched your search
@@ -8,7 +8,7 @@ updates:
|
||||
- "Dependencies"
|
||||
commit-message:
|
||||
prefix: "Docker dependency"
|
||||
|
||||
|
||||
- package-ecosystem: "pip"
|
||||
directory: "/"
|
||||
schedule:
|
||||
@@ -17,7 +17,7 @@ updates:
|
||||
- "Dependencies"
|
||||
commit-message:
|
||||
prefix: "Python dependency"
|
||||
|
||||
|
||||
- package-ecosystem: "pip"
|
||||
directory: "/tools"
|
||||
schedule:
|
||||
@@ -25,8 +25,8 @@ updates:
|
||||
labels:
|
||||
- "Dependencies"
|
||||
commit-message:
|
||||
prefix: "Python dependency"
|
||||
|
||||
prefix: "Python dependency"
|
||||
|
||||
- package-ecosystem: "pip"
|
||||
directory: "/web/regression"
|
||||
schedule:
|
||||
@@ -34,8 +34,8 @@ updates:
|
||||
labels:
|
||||
- "Dependencies"
|
||||
commit-message:
|
||||
prefix: "Python dependency"
|
||||
|
||||
prefix: "Python dependency"
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/runtime"
|
||||
schedule:
|
||||
@@ -43,8 +43,8 @@ updates:
|
||||
labels:
|
||||
- "Dependencies"
|
||||
commit-message:
|
||||
prefix: "Python dependency"
|
||||
|
||||
prefix: "Javascript dependency"
|
||||
|
||||
- package-ecosystem: "npm"
|
||||
directory: "/web"
|
||||
schedule:
|
||||
@@ -52,4 +52,4 @@ updates:
|
||||
labels:
|
||||
- "Dependencies"
|
||||
commit-message:
|
||||
prefix: "Python dependency"
|
||||
prefix: "Javascript dependency"
|
||||
@@ -13,7 +13,7 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
build-container:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
|
||||
@@ -13,7 +13,7 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
build-docs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
|
||||
@@ -13,7 +13,7 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
check-javascript-style:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
|
||||
@@ -13,7 +13,7 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
build-python-package:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
|
||||
@@ -13,7 +13,7 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
check-python-style:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
|
||||
@@ -13,7 +13,7 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
build-tarball:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
|
||||
@@ -13,7 +13,7 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
check-translations:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
|
||||
@@ -13,7 +13,7 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
run-feature-tests-epas:
|
||||
# Only run if the tests are enabled
|
||||
# TODO: Figure out a way to test for the presence of the secrets instead
|
||||
if: vars.ENABLE_EPAS_TESTS == 'true'
|
||||
|
||||
@@ -16,11 +16,11 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
run-feature-tests-pg:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
pgver: [11, 12, 13, 14, 15]
|
||||
pgver: [12, 13, 14, 15, 16]
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
run-javascript-tests:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
@@ -22,11 +22,16 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '18.x'
|
||||
|
||||
- name: Upgrade yarn
|
||||
run: |
|
||||
yarn set version berry
|
||||
yarn set version 3
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Install Node modules
|
||||
run: |
|
||||
@@ -36,4 +41,4 @@ jobs:
|
||||
- name: Run the tests
|
||||
run: |
|
||||
cd web
|
||||
yarn run test:karma-once
|
||||
yarn run test:js-once
|
||||
@@ -23,7 +23,7 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
run-python-tests-epas:
|
||||
# Only run if the tests are enabled
|
||||
# TODO: Figure out a way to test for the presence of the secrets instead
|
||||
if: vars.ENABLE_EPAS_TESTS == 'true'
|
||||
|
||||
@@ -16,12 +16,12 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
run-python-tests-pg:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [macos-latest, ubuntu-latest, windows-latest]
|
||||
pgver: [11, 12, 13, 14, 15]
|
||||
pgver: [12, 13, 14, 15, 16]
|
||||
|
||||
runs-on: ${{ matrix.os }}
|
||||
|
||||
@@ -57,7 +57,9 @@ jobs:
|
||||
- name: Install platform dependencies on Windows
|
||||
if: ${{ matrix.os == 'windows-latest' }}
|
||||
run: |
|
||||
choco install -y postgresql${{ matrix.pgver }} --params "/Password:postgres /Port:59${{ matrix.pgver }}" --ia "--prefix C:\PostgreSQL\${{ matrix.pgver }} --datadir C:\PostgreSQL\${{ matrix.pgver }}\data --install_runtimes 0 --disable-components pgAdmin,stackbuilder --enable-components server,commandlinetools"
|
||||
FOR /f "delims=" %%F IN ('python tools\get_sb_package.py "https://www.postgresql.org/applications-v2.xml" "postgresql_${{ matrix.pgver }}" "windows-x64"') DO SET INSTALLER_EXE=%%F
|
||||
ECHO Running %INSTALLER_EXE%...
|
||||
%INSTALLER_EXE% --prefix C:\PostgreSQL\${{ matrix.pgver }} --datadir C:\PostgreSQL\${{ matrix.pgver }}\data --serverport 59${{ matrix.pgver }} --superpassword postgres --install_runtimes 0 --mode unattended --unattendedmodeui none --disable-components pgAdmin,stackbuilder --enable-components server,commandlinetools"
|
||||
choco install -y mitkerberos
|
||||
|
||||
REM Ignore error 3010 (reboot required)
|
||||
|
||||
@@ -18,7 +18,7 @@ concurrency:
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
build:
|
||||
run-sonarqube-scan:
|
||||
# Only run if the project key is set
|
||||
if: vars.SONARQUBE_PROJECT_KEY != null
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
[pycodestyle]
|
||||
ignore = E402,W504,W605,E231,W605
|
||||
ignore = E402,W504,E231
|
||||
max-line-length = 79
|
||||
statistics = True
|
||||
show-source = False
|
||||
|
||||
@@ -47,6 +47,7 @@ WORKDIR /pgadmin4/web
|
||||
# Build the JS vendor code in the app-builder, and then remove the vendor source.
|
||||
RUN export CPPFLAGS="-DPNG_ARM_NEON_OPT=0" && \
|
||||
yarn set version berry && \
|
||||
yarn set version 3 && \
|
||||
yarn install && \
|
||||
yarn run bundle && \
|
||||
rm -rf node_modules \
|
||||
@@ -55,7 +56,8 @@ RUN export CPPFLAGS="-DPNG_ARM_NEON_OPT=0" && \
|
||||
.[^.]* \
|
||||
babel.cfg \
|
||||
webpack.* \
|
||||
karma.conf.js \
|
||||
jest.config.js \
|
||||
babel.* \
|
||||
./pgadmin/static/js/generated/.cache
|
||||
|
||||
#########################################################################
|
||||
@@ -114,20 +116,15 @@ RUN rm -rf /pgadmin4/docs/en_US/_build/html/_static/*.png
|
||||
# Create additional builders to get all of the PostgreSQL utilities
|
||||
#########################################################################
|
||||
|
||||
FROM postgres:11-alpine AS pg11-builder
|
||||
FROM postgres:12-alpine AS pg12-builder
|
||||
FROM postgres:13-alpine AS pg13-builder
|
||||
FROM postgres:14-alpine AS pg14-builder
|
||||
FROM postgres:15-alpine AS pg15-builder
|
||||
FROM postgres:16-alpine AS pg16-builder
|
||||
|
||||
FROM alpine:latest AS tool-builder
|
||||
|
||||
# Copy the PG binaries
|
||||
COPY --from=pg11-builder /usr/local/bin/pg_dump /usr/local/pgsql/pgsql-11/
|
||||
COPY --from=pg11-builder /usr/local/bin/pg_dumpall /usr/local/pgsql/pgsql-11/
|
||||
COPY --from=pg11-builder /usr/local/bin/pg_restore /usr/local/pgsql/pgsql-11/
|
||||
COPY --from=pg11-builder /usr/local/bin/psql /usr/local/pgsql/pgsql-11/
|
||||
|
||||
COPY --from=pg12-builder /usr/local/bin/pg_dump /usr/local/pgsql/pgsql-12/
|
||||
COPY --from=pg12-builder /usr/local/bin/pg_dumpall /usr/local/pgsql/pgsql-12/
|
||||
COPY --from=pg12-builder /usr/local/bin/pg_restore /usr/local/pgsql/pgsql-12/
|
||||
@@ -148,6 +145,11 @@ COPY --from=pg15-builder /usr/local/bin/pg_dumpall /usr/local/pgsql/pgsql-15/
|
||||
COPY --from=pg15-builder /usr/local/bin/pg_restore /usr/local/pgsql/pgsql-15/
|
||||
COPY --from=pg15-builder /usr/local/bin/psql /usr/local/pgsql/pgsql-15/
|
||||
|
||||
COPY --from=pg16-builder /usr/local/bin/pg_dump /usr/local/pgsql/pgsql-16/
|
||||
COPY --from=pg16-builder /usr/local/bin/pg_dumpall /usr/local/pgsql/pgsql-16/
|
||||
COPY --from=pg16-builder /usr/local/bin/pg_restore /usr/local/pgsql/pgsql-16/
|
||||
COPY --from=pg16-builder /usr/local/bin/psql /usr/local/pgsql/pgsql-16/
|
||||
|
||||
#########################################################################
|
||||
# Assemble everything into the final container.
|
||||
#########################################################################
|
||||
@@ -159,9 +161,14 @@ COPY --from=env-builder /venv /venv
|
||||
|
||||
# Copy in the tools
|
||||
COPY --from=tool-builder /usr/local/pgsql /usr/local/
|
||||
COPY --from=pg15-builder /usr/local/lib/libpq.so.5.15 /usr/lib/
|
||||
RUN ln -s libpq.so.5.15 /usr/lib/libpq.so.5 && \
|
||||
ln -s libpq.so.5.15 /usr/lib/libpq.so
|
||||
COPY --from=pg16-builder /usr/local/lib/libpq.so.5.16 /usr/lib/
|
||||
COPY --from=pg16-builder /usr/lib/libzstd.so.1.5.5 /usr/lib/
|
||||
COPY --from=pg16-builder /usr/lib/liblz4.so.1.9.4 /usr/lib/
|
||||
|
||||
RUN ln -s libpq.so.5.16 /usr/lib/libpq.so.5 && \
|
||||
ln -s libpq.so.5.16 /usr/lib/libpq.so && \
|
||||
ln -s libzstd.so.1.5.5 /usr/lib/libzstd.so.1 && \
|
||||
ln -s liblz4.so.1.9.4 /usr/lib/liblz4.so.1
|
||||
|
||||
WORKDIR /pgadmin4
|
||||
ENV PYTHONPATH=/pgadmin4
|
||||
|
||||
@@ -26,8 +26,8 @@ CALL :CLEAN || EXIT /B 1
|
||||
CALL :CREATE_VIRTUAL_ENV || EXIT /B 1
|
||||
CALL :CREATE_PYTHON_ENV || EXIT /B 1
|
||||
CALL :CREATE_RUNTIME_ENV || EXIT /B 1
|
||||
CALL :CREATE_INSTALLER || EXIT /B 1
|
||||
CALL :GENERATE_SBOM || EXIT /B 1
|
||||
CALL :CREATE_INSTALLER || EXIT /B 1
|
||||
CALL :SIGN_INSTALLER || EXIT /B 1
|
||||
|
||||
EXIT /B %ERRORLEVEL%
|
||||
@@ -315,8 +315,8 @@ REM Main build sequence Ends
|
||||
|
||||
ECHO Staging PostgreSQL components...
|
||||
COPY "%PGADMIN_POSTGRES_DIR%\bin\libpq.dll" "%BUILDROOT%\runtime" > nul || EXIT /B 1
|
||||
COPY "%PGADMIN_POSTGRES_DIR%\bin\libcrypto-1_1-x64.dll" "%BUILDROOT%\runtime" > nul || EXIT /B 1
|
||||
COPY "%PGADMIN_POSTGRES_DIR%\bin\libssl-1_1-x64.dll" "%BUILDROOT%\runtime" > nul || EXIT /B 1
|
||||
COPY "%PGADMIN_POSTGRES_DIR%\bin\libcrypto-*-x64.dll" "%BUILDROOT%\runtime" > nul || EXIT /B 1
|
||||
COPY "%PGADMIN_POSTGRES_DIR%\bin\libssl-*-x64.dll" "%BUILDROOT%\runtime" > nul || EXIT /B 1
|
||||
IF EXIST "%PGADMIN_POSTGRES_DIR%\bin\libintl-*.dll" COPY "%PGADMIN_POSTGRES_DIR%\bin\libintl-*.dll" "%BUILDROOT%\runtime" > nul
|
||||
IF EXIST "%PGADMIN_POSTGRES_DIR%\bin\libiconv-*.dll" COPY "%PGADMIN_POSTGRES_DIR%\bin\libiconv-*.dll" "%BUILDROOT%\runtime" > nul
|
||||
COPY "%PGADMIN_POSTGRES_DIR%\bin\zlib.dll" "%BUILDROOT%\runtime" > nul || EXIT /B 1
|
||||
@@ -364,7 +364,7 @@ REM Main build sequence Ends
|
||||
|
||||
:GENERATE_SBOM
|
||||
ECHO Generating SBOM...
|
||||
syft "%BUILDROOT%\" -o cyclonedx-json > "%BUILDROOT%\sbom.json"
|
||||
CALL syft "%BUILDROOT%" -o cyclonedx-json > "%BUILDROOT%\sbom.json"
|
||||
|
||||
:SIGN_INSTALLER
|
||||
ECHO Attempting to sign the installer...
|
||||
|
||||
@@ -42,7 +42,7 @@ linter:
|
||||
cd web && yarn run linter
|
||||
|
||||
check: install-node bundle linter check-pep8
|
||||
cd web && yarn run karma start --single-run && python regression/runtests.py
|
||||
cd web && yarn run test:js-once && python regression/runtests.py
|
||||
|
||||
check-audit:
|
||||
cd web && yarn run audit
|
||||
@@ -77,10 +77,10 @@ check-feature: install-node bundle
|
||||
cd web && python regression/runtests.py --pkg feature_tests
|
||||
|
||||
check-js: install-node linter
|
||||
cd web && yarn run karma start --single-run
|
||||
cd web && yarn run test:js-once
|
||||
|
||||
check-js-coverage:
|
||||
cd web && yarn run test:karma-coverage
|
||||
cd web && yarn run test:js-coverage
|
||||
|
||||
# Include all clean sub-targets in clean
|
||||
clean: clean-appbundle clean-debian clean-dist clean-docs clean-node clean-pip clean-redhat clean-src
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# pgAdmin 4
|
||||
# pgAdmin 4
|
||||
|
||||
pgAdmin 4 is a rewrite of the popular pgAdmin3 management tool for the
|
||||
PostgreSQL (http://www.postgresql.org) database.
|
||||
PostgreSQL (http://www.postgresql.org) database.
|
||||
|
||||
In the following documentation and examples, *$PGADMIN4_SRC/* is used to denote
|
||||
the top-level directory of a copy of the pgAdmin source tree, either from a
|
||||
@@ -9,9 +9,8 @@ tarball or a git checkout.
|
||||
|
||||
## Architecture
|
||||
|
||||
pgAdmin 4 is written as a web application in Python, using jQuery and Bootstrap
|
||||
for the client side processing and UI. On the server side, Flask is being
|
||||
utilised.
|
||||
pgAdmin 4 is written as a web application with Python(Flask) on the server side
|
||||
and ReactJS, HTML5 with CSS for the client side processing and UI.
|
||||
|
||||
Although developed using web technologies, pgAdmin 4 can be deployed either on
|
||||
a web server using a browser, or standalone on a workstation. The runtime/
|
||||
@@ -22,7 +21,7 @@ which will execute the Python server and display the UI.
|
||||
|
||||
To build the runtime, the following packages must be installed:
|
||||
|
||||
* NodeJS 12+
|
||||
* NodeJS 16+
|
||||
* Yarn
|
||||
|
||||
Change into the runtime directory, and run *yarn install*. This will install the
|
||||
@@ -59,20 +58,20 @@ simple - adapt as required for your distribution:
|
||||
```bash
|
||||
$ python3 -m venv venv
|
||||
```
|
||||
|
||||
|
||||
2. Now activate the virtual environment:
|
||||
|
||||
```bash
|
||||
$ source venv/bin/activate
|
||||
```
|
||||
|
||||
|
||||
3. Some of the components used by pgAdmin require a very recent version of *pip*,
|
||||
so update that to the latest:
|
||||
|
||||
|
||||
```bash
|
||||
$ pip install --upgrade pip
|
||||
```
|
||||
|
||||
|
||||
4. Ensure that a PostgreSQL installation's bin/ directory is in the path (so
|
||||
pg_config can be found for building psycopg3), and install the required
|
||||
packages:
|
||||
@@ -80,20 +79,20 @@ simple - adapt as required for your distribution:
|
||||
```bash
|
||||
(venv) $ PATH=$PATH:/usr/local/pgsql/bin pip install -r $PGADMIN4_SRC/requirements.txt
|
||||
```
|
||||
|
||||
|
||||
If you are planning to run the regression tests, you also need to install
|
||||
additional requirements from web/regression/requirements.txt:
|
||||
|
||||
```bash
|
||||
(venv) $ pip install -r $PGADMIN4_SRC/web/regression/requirements.txt
|
||||
```
|
||||
|
||||
|
||||
5. Create a local configuration file for pgAdmin. Edit
|
||||
$PGADMIN4_SRC/web/config_local.py and add any desired configuration options
|
||||
(use the config.py file as a reference - any settings duplicated in
|
||||
config_local.py will override those in config.py). A typical development
|
||||
configuration may look like:
|
||||
|
||||
|
||||
```python
|
||||
from config import *
|
||||
|
||||
@@ -126,7 +125,7 @@ simple - adapt as required for your distribution:
|
||||
'pgadmin4-server.db'
|
||||
)
|
||||
```
|
||||
|
||||
|
||||
This configuration allows easy switching between server and desktop modes
|
||||
for testing.
|
||||
|
||||
@@ -137,13 +136,13 @@ simple - adapt as required for your distribution:
|
||||
```bash
|
||||
(venv) $ python3 $PGADMIN4_SRC/web/setup.py
|
||||
```
|
||||
|
||||
|
||||
or by starting pgAdmin 4:
|
||||
|
||||
```bash
|
||||
(venv) $ python3 $PGADMIN4_SRC/web/pgAdmin4.py
|
||||
```
|
||||
|
||||
|
||||
Whilst it is possible to automatically run setup in desktop mode by running
|
||||
the runtime, that will not work in server mode as the runtime doesn't allow
|
||||
command line interaction with the setup program.
|
||||
@@ -228,7 +227,7 @@ To build a source tarball:
|
||||
(venv) $ make src
|
||||
```
|
||||
|
||||
To build a PIP Wheel, activate either a Python 3 virtual environment, configured
|
||||
To build a PIP Wheel, activate either a Python 3 virtual environment, configured
|
||||
with all the required packages, and then run:
|
||||
|
||||
```bash
|
||||
@@ -266,7 +265,7 @@ See https://www.pgadmin.org/support/ for support options.
|
||||
|
||||
If you would like to report a security issue with pgAdmin, please email
|
||||
**security (at) pgadmin (dot) org**.
|
||||
|
||||
|
||||
Note that this address should only be used for reporting security issues
|
||||
that you believe you've found in the design or code of pgAdmin, pgAgent,
|
||||
and the pgAdmin website. It should not be used to ask security questions.
|
||||
|
||||
@@ -251,6 +251,16 @@ tab to provide other backup options.
|
||||
table locks at the beginning of the dump. Instead, fail if unable to lock a
|
||||
table within the specified timeout.
|
||||
|
||||
Click the *Objects* tab to continue.
|
||||
|
||||
.. image:: images/backup_object_selection.png
|
||||
:alt: Select objects in backup dialog
|
||||
:align: center
|
||||
|
||||
* Select the objects from tree to take backup of selected objects only.
|
||||
* If Schema is selected then it will take the backup of that selected schema only.
|
||||
* If any Table, View, Materialized View, Sequences, or Foreign Table is selected then it will take the backup of those selected objects.
|
||||
|
||||
When you’ve specified the details that will be incorporated into the pg_dump
|
||||
command:
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
**********************
|
||||
|
||||
The bulk of pgAdmin is a Python web application written using the Flask framework
|
||||
on the backend, and HTML5 with CSS3, Bootstrap and jQuery on the front end. A
|
||||
on the backend, and HTML5 with CSS3,ReactJS on the front end. A
|
||||
desktop runtime is also included for users that prefer a desktop application to
|
||||
a web application, which is written using NWjs (Node Webkit).
|
||||
|
||||
@@ -207,8 +207,7 @@ Front End
|
||||
|
||||
pgAdmin uses javascript extensively for the front-end implementation. It uses
|
||||
require.js to allow the lazy loading (or, say load only when required),
|
||||
bootstrap and MaterialUI for UI look and feel, React for generating
|
||||
properties/create dialog for selected node. We have
|
||||
ReactJS with CSS and MaterialUI for UI look and feel. We have
|
||||
divided each module in small chunks as much as possible. Not all javascript
|
||||
modules are required to be loaded (i.e. loading a javascript module for
|
||||
database will make sense only when a server node is loaded completely.) Please
|
||||
|
||||
@@ -22,14 +22,12 @@ purpose or how it works if not obvious from a quick review of the code itself.
|
||||
CSS 3
|
||||
*****
|
||||
|
||||
CSS3 is used for styling and layout throughout the application. Extensive use is
|
||||
made of the Bootstrap Framework to aid in that process, however additional
|
||||
styles must still be created from time to time.
|
||||
CSS3 is used for styling and layout throughout the application.
|
||||
|
||||
Most custom styling comes from individual modules which may advertise static
|
||||
stylesheets to be included in the module that is loading them via hooks.
|
||||
|
||||
Styling overrides (for example, to alter the Bootstrap look and feel) will
|
||||
Styling overrides (for example, to alter the look and feel) will
|
||||
typically be found in the **overrides.css** file in the main static file
|
||||
directory for the application.
|
||||
|
||||
@@ -64,7 +62,7 @@ All HTML must be HTML 5 compliant.
|
||||
Javascript
|
||||
**********
|
||||
|
||||
Client-side code is written in Javascript using jQuery and various plugins.
|
||||
Client-side code is written in Javascript using ReactJS and various plugins.
|
||||
Whilst much of the code is rendered from static files, there is also code that
|
||||
is rendered from templates using Jinja2 (often to inject the users settings) or
|
||||
constructed on the fly from module hooks.
|
||||
|
||||
@@ -39,6 +39,10 @@ are disabled if inapplicable.)
|
||||
a text value.
|
||||
* Use the drop-down listbox next to *Collation* to apply a collation setting to
|
||||
the column.
|
||||
* Use the drop-down listbox next to *Compression* to set the compression method
|
||||
for the column. Compression is supported only for variable-width data types,
|
||||
and is used only when the column's storage mode is main or extended. This
|
||||
option is available from v14 and above.
|
||||
|
||||
Click the *Constraints* tab to continue.
|
||||
|
||||
|
||||
@@ -53,11 +53,11 @@ The default binary paths set in the container are as follows:
|
||||
.. code-block:: bash
|
||||
|
||||
DEFAULT_BINARY_PATHS = {
|
||||
'pg-16': '/usr/local/pgsql-16',
|
||||
'pg-15': '/usr/local/pgsql-15',
|
||||
'pg-14': '/usr/local/pgsql-14',
|
||||
'pg-13': '/usr/local/pgsql-13',
|
||||
'pg-12': '/usr/local/pgsql-12',
|
||||
'pg-11': '/usr/local/pgsql-11'
|
||||
'pg-12': '/usr/local/pgsql-12'
|
||||
}
|
||||
|
||||
this may be changed in the :ref:`preferences`.
|
||||
|
||||
@@ -19,6 +19,9 @@ Use the fields in the *General* tab to identify the database:
|
||||
|
||||
* Use the *Database* field to add a descriptive name for the database. The name
|
||||
will be displayed in the *pgAdmin* tree control.
|
||||
* Use the *OID* field to specify the object identifier to be used for the new
|
||||
database. Users can specify the value greater than 16383. This option is available
|
||||
from v15 and above.
|
||||
* Select the owner of the database from the drop-down listbox in the *Owner*
|
||||
field.
|
||||
* Store notes about the database in the *Comment* field.
|
||||
@@ -38,11 +41,22 @@ Use the *Definition* tab to set properties for the database:
|
||||
* Select a tablespace from the drop-down listbox in the *Tablespace* field. The
|
||||
selected tablespace will be the default tablespace used to contain database
|
||||
objects.
|
||||
* Select the strategy from the drop-down listbox in the *Strategy* field while
|
||||
creating a new database. This option is available from v15 and above.
|
||||
* Select the locale provider from the drop-down listbox in the *Locale Provider*
|
||||
field to set the default collation for this database. Possible values are: icu, libc.
|
||||
This option is available from v15 and above.
|
||||
* Select the collation order from the drop-down listbox in the *Collation* field.
|
||||
* Select the character classification from the drop-down listbox in the
|
||||
*Character Type* field. This affects the categorization of characters, e.g.
|
||||
lower, upper and digit. The default, or a blank field, uses the character
|
||||
classification of the template database.
|
||||
* Select the icu locale from the drop-down listbox in the *ICU Locale* to
|
||||
specifies the ICU locale ID if the ICU locale provider is used.
|
||||
This option is available from v15 and above.
|
||||
* Specify the icu rules in the *ICU Rules* field as additional collation
|
||||
rules to customize the behavior of the default collation of this database.
|
||||
This option is available from v16 and above.
|
||||
* Specify a connection limit in the *Connection Limit* field to configure the
|
||||
maximum number of connection requests. The default value (*-1*) allows
|
||||
unlimited connections to the database.
|
||||
|
||||
|
After Width: | Height: | Size: 126 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 110 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 56 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 82 KiB |
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 110 KiB |
|
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 88 KiB |
|
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 154 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 60 KiB |
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 96 KiB |
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 105 KiB |
|
Before Width: | Height: | Size: 78 KiB After Width: | Height: | Size: 122 KiB |
|
Before Width: | Height: | Size: 28 KiB |
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 74 KiB |
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 67 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 8.3 KiB |
|
Before Width: | Height: | Size: 111 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 83 KiB After Width: | Height: | Size: 94 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 34 KiB |
@@ -170,6 +170,7 @@ The following example shows both a minimally defined and a fully defined server:
|
||||
"SSLCrl": "/path/to/sslcrl.crl",
|
||||
"SSLCompression": 1,
|
||||
"Shared": false,
|
||||
"SharedUsername": "postgres",
|
||||
"BGColor": "#ff9900",
|
||||
"FGColor": "#000000",
|
||||
"Service": "postgresql-10",
|
||||
|
||||
@@ -31,17 +31,6 @@ Use the fields in the *General* tab to identify the materialized view:
|
||||
Click the *Definition* tab to continue.
|
||||
|
||||
.. image:: images/materialized_view_definition.png
|
||||
:alt: Materialized view dialog definition tab
|
||||
:align: center
|
||||
|
||||
Use the text editor field in the *Definition* tab to provide the query that will
|
||||
populate the materialized view. Please note that updating the definition of existing
|
||||
materialized view would result in loss of Parameter(Table, Toast), Security(Privileges & Security labels),
|
||||
Indexes and other dependent objects.
|
||||
|
||||
Click the *Storage* tab to continue.
|
||||
|
||||
.. image:: images/materialized_view_storage.png
|
||||
:alt: Materialized view dialog storage tab
|
||||
:align: center
|
||||
|
||||
@@ -52,10 +41,24 @@ Use the fields in the *Storage* tab to maintain the materialized view:
|
||||
cannot be queried until you invoke REFRESH MATERIALIZED VIEW.
|
||||
* Use the drop-down listbox next to *Tablespace* to select a location for the
|
||||
materialized view.
|
||||
* Use the drop-down list box next to Access Method to specify the table access method to use to store the contents
|
||||
for the new materialized view; the method needs to be an access method of type TABLE. This field is optional.
|
||||
This option is available from v12 and above.
|
||||
* Use the *Fill Factor* field to specify a fill factor for the materialized
|
||||
view. The fill factor for a table is a percentage between 10 and 100. 100
|
||||
(complete packing) is the default.
|
||||
|
||||
Click the *Code* tab to continue.
|
||||
|
||||
.. image:: images/materialized_view_code.png
|
||||
:alt: Materialized view dialog definition tab
|
||||
:align: center
|
||||
|
||||
Use the text editor field in the *Code* tab to provide the query that will
|
||||
populate the materialized view. Please note that updating the definition of existing
|
||||
materialized view would result in loss of Parameter(Table, Toast), Security(Privileges & Security labels),
|
||||
Indexes and other dependent objects.
|
||||
|
||||
Click the *Parameter* tab to continue.
|
||||
|
||||
.. image:: images/materialized_view_parameter.png
|
||||
|
||||
@@ -25,9 +25,6 @@ Use the *File* menu to access the following options:
|
||||
+-------------------------+---------------------------------------------------------------------------------------------------------+
|
||||
| *Reset Layout* | If you have modified the workspace, click to restore the default layout. |
|
||||
+-------------------------+---------------------------------------------------------------------------------------------------------+
|
||||
| *Lock Layout* | Click to open a submenu to select the level for locking the UI layout |
|
||||
| | This can also be changed from browser display :ref:`preferences <preferences>` |
|
||||
+-------------------------+---------------------------------------------------------------------------------------------------------+
|
||||
| *Runtime* | Click to open a submenu to Configure, View Log and Zoom settings. Only visible when pgAdmin4 runs in |
|
||||
| | desktop mode. To know more about runtime menu :ref:`click here <desktop_deployment>` |
|
||||
+-------------------------+---------------------------------------------------------------------------------------------------------+
|
||||
|
||||
@@ -12,6 +12,10 @@ installed in Server mode. You can copy these settings from *config.py* file
|
||||
and modify the values for the following parameters:
|
||||
|
||||
|
||||
.. _AzureAD: https://learn.microsoft.com/en-us/security/zero-trust/develop/configure-tokens-group-claims-app-roles
|
||||
.. _GitLab: https://docs.gitlab.com/ee/integration/openid_connect_provider.html#shared-information
|
||||
|
||||
|
||||
.. csv-table::
|
||||
:header: "**Parameter**", "**Description**"
|
||||
:class: longtable
|
||||
@@ -39,6 +43,9 @@ and modify the values for the following parameters:
|
||||
"OAUTH2_AUTO_CREATE_USER", "Set the value to *True* if you want to automatically
|
||||
create a pgAdmin user corresponding to a successfully authenticated Oauth2 user.
|
||||
Please note that password is not stored in the pgAdmin database."
|
||||
"OAUTH2_ADDITIONAL_CLAIMS", "If a dictionary is provided, pgAdmin will check for a matching key and value on the userinfo endpoint
|
||||
and in the Id Token. In case there is no match with the provided config, the user will receive an authorization error.
|
||||
Useful for checking AzureAD_ *wids* or *groups*, GitLab_ *owner*, *maintainer* and *reporter* claims."
|
||||
|
||||
Redirect URL
|
||||
============
|
||||
|
||||
@@ -46,19 +46,6 @@ Use the fields on the *Display* panel to specify general display preferences:
|
||||
* When the *Hide shared servers?* switch is set to *True*, the client will hide
|
||||
all the shared servers from the object explorer.
|
||||
|
||||
* Use the *Lock layout* field to lock the UI layout at different levels. This
|
||||
can also be changed from File menu on the :ref:`menu bar <menu_bar>`
|
||||
|
||||
+---------------------+-------------------------------------------------------------------+
|
||||
| Option | Action |
|
||||
+=====================+===================================================================+
|
||||
| *None* | No locking. Every panel is resizable and dockable. |
|
||||
+---------------------+-------------------------------------------------------------------+
|
||||
| *Prevent docking* | This will disable the docking/undocking of the panels |
|
||||
+---------------------+-------------------------------------------------------------------+
|
||||
| *Full* | This will disable resizing, docking/undocking of the panels |
|
||||
+---------------------+-------------------------------------------------------------------+
|
||||
|
||||
* When the *Show empty object collections?* switch is turned off, then all object
|
||||
collections which are empty will be hidden from browser tree.
|
||||
* When the *Show system objects?* switch is set to *True*, the client will
|
||||
|
||||
@@ -11,6 +11,9 @@ notes for it.
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
release_notes_8_0
|
||||
release_notes_7_8
|
||||
release_notes_7_7
|
||||
release_notes_7_6
|
||||
release_notes_7_5
|
||||
release_notes_7_4
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
***********
|
||||
Version 7.7
|
||||
***********
|
||||
|
||||
Release date: 2023-09-21
|
||||
|
||||
This release contains a number of bug fixes and new features since the release of pgAdmin 4 v7.6.
|
||||
|
||||
Supported Database Servers
|
||||
**************************
|
||||
**PostgreSQL**: 11, 12, 13, 14 and 15
|
||||
|
||||
**EDB Advanced Server**: 11, 12, 13, 14 and 15
|
||||
|
||||
Bundled PostgreSQL Utilities
|
||||
****************************
|
||||
**psql**, **pg_dump**, **pg_dumpall**, **pg_restore**: 15.4
|
||||
|
||||
|
||||
New features
|
||||
************
|
||||
|
||||
| `Issue #642 <https://github.com/pgadmin-org/pgadmin4/issues/642>`_ - Added support to select/deselect objects in the Backup dialog.
|
||||
| `Issue #4805 <https://github.com/pgadmin-org/pgadmin4/issues/4805>`_ - Added all the new options of the 'WITH' clause in the subscription dialog.
|
||||
| `Issue #6378 <https://github.com/pgadmin-org/pgadmin4/issues/6378>`_ - Added USING method while creating the table.
|
||||
| `Issue #6379 <https://github.com/pgadmin-org/pgadmin4/issues/6379>`_ - Added compression method option while creating a column.
|
||||
| `Issue #6383 <https://github.com/pgadmin-org/pgadmin4/issues/6383>`_ - Added Strategy, Locale Provider, ICU Locale, ICU Rules, and OID options while creating a database.
|
||||
| `Issue #6400 <https://github.com/pgadmin-org/pgadmin4/issues/6400>`_ - Added USING method while creating the materialized view.
|
||||
| `Issue #6736 <https://github.com/pgadmin-org/pgadmin4/issues/6736>`_ - Add support for additional ID token claim checks for OAuth 2 authentication.
|
||||
|
||||
Housekeeping
|
||||
************
|
||||
|
||||
| `Issue #2411 <https://github.com/pgadmin-org/pgadmin4/issues/2411>`_ - Added the 'data type' column in the properties tab of the Columns collection node.
|
||||
|
||||
Bug fixes
|
||||
*********
|
||||
|
||||
| `Issue #6274 <https://github.com/pgadmin-org/pgadmin4/issues/6274>`_ - Fix an issue where user is not able to change the password when SMTP is not configured.
|
||||
| `Issue #6704 <https://github.com/pgadmin-org/pgadmin4/issues/6704>`_ - Ensure user is redirected to login page after failed login.
|
||||
| `Issue #6712 <https://github.com/pgadmin-org/pgadmin4/issues/6712>`_ - Ensure that Materialized view size fields in "Statistics" should be human-readable.
|
||||
| `Issue #6730 <https://github.com/pgadmin-org/pgadmin4/issues/6730>`_ - Fix an issue where changing the password shows success but the new password is not working.
|
||||
| `Issue #6738 <https://github.com/pgadmin-org/pgadmin4/issues/6738>`_ - Fix an issue where login form doesn't appear if internal auth source is removed.
|
||||
| `Issue #6764 <https://github.com/pgadmin-org/pgadmin4/issues/6764>`_ - Fix a security related issue where an authenticated user can run remote command using validate binary path API (CVE-2023-5002).
|
||||
@@ -0,0 +1,51 @@
|
||||
***********
|
||||
Version 7.8
|
||||
***********
|
||||
|
||||
Release date: 2023-10-19
|
||||
|
||||
This release contains a number of bug fixes and new features since the release of pgAdmin 4 v7.7.
|
||||
|
||||
Supported Database Servers
|
||||
**************************
|
||||
**PostgreSQL**: 12, 13, 14, 15, and 16
|
||||
|
||||
**EDB Advanced Server**: 12, 13, 14 and 15
|
||||
|
||||
Bundled PostgreSQL Utilities
|
||||
****************************
|
||||
**psql**, **pg_dump**, **pg_dumpall**, **pg_restore**: 16.0
|
||||
|
||||
|
||||
New features
|
||||
************
|
||||
|
||||
| `Issue #640 <https://github.com/pgadmin-org/pgadmin4/issues/640>`_ - Add support for foreign table's new functionality for PG 11 and above.
|
||||
| `Issue #6229 <https://github.com/pgadmin-org/pgadmin4/issues/6229>`_ - Allow setting custom username for shared servers, with default as username of server being shared.
|
||||
| `Issue #6373 <https://github.com/pgadmin-org/pgadmin4/issues/6373>`_ - Add 'GENERATED ALWAYS AS..' option while creating column constraints for Foreign Table.
|
||||
| `Issue #6797 <https://github.com/pgadmin-org/pgadmin4/issues/6797>`_ - GUI representation of the system's activity using the 'system_stats' extension.
|
||||
| `Issue #6802 <https://github.com/pgadmin-org/pgadmin4/issues/6802>`_ - Added 'load_balance_hosts' connection string parameter for PG 16 and above.
|
||||
|
||||
Housekeeping
|
||||
************
|
||||
|
||||
| `Issue #6782 <https://github.com/pgadmin-org/pgadmin4/issues/6782>`_ - Use PG16 as the default PostgreSQL version.
|
||||
|
||||
Bug fixes
|
||||
*********
|
||||
|
||||
| `Issue #4995 <https://github.com/pgadmin-org/pgadmin4/issues/4995>`_ - Fixed an issue in ERD tool where the downloaded images have a few links cut.
|
||||
| `Issue #5749 <https://github.com/pgadmin-org/pgadmin4/issues/5749>`_ - Fixed an issue where user was not able to assign new/old columns as primary key once column with primary key is deleted.
|
||||
| `Issue #6285 <https://github.com/pgadmin-org/pgadmin4/issues/6285>`_ - Add support for setting prepare threshold in server connection.
|
||||
| `Issue #6482 <https://github.com/pgadmin-org/pgadmin4/issues/6482>`_ - Fixed an issue where the wrong message "Current database has been moved or renamed" is displayed when debugging any function.
|
||||
| `Issue #6538 <https://github.com/pgadmin-org/pgadmin4/issues/6538>`_ - Fixed an issue where Processes tab displays wrong server name in some scenario.
|
||||
| `Issue #6579 <https://github.com/pgadmin-org/pgadmin4/issues/6579>`_ - Fix an issue where global/native keyboard shortcuts are not working when any cell of data output grid has focus.
|
||||
| `Issue #6666 <https://github.com/pgadmin-org/pgadmin4/issues/6666>`_ - Fixed query history slowness issue by storing query only for those having certain threshold max length.
|
||||
| `Issue #6674 <https://github.com/pgadmin-org/pgadmin4/issues/6674>`_ - Fix an issue where foreign table column name becomes "none" if the user changes any column data type.
|
||||
| `Issue #6718 <https://github.com/pgadmin-org/pgadmin4/issues/6718>`_ - Pin the cryptography version to fix PyO3 modules initialisation error.
|
||||
| `Issue #6790 <https://github.com/pgadmin-org/pgadmin4/issues/6790>`_ - Ensure that the backup works properly for PG 16 on the latest docker image.
|
||||
| `Issue #6799 <https://github.com/pgadmin-org/pgadmin4/issues/6799>`_ - Fixed an issue where the user is unable to select objects on the backup dialog due to tree flickering.
|
||||
| `Issue #6836 <https://github.com/pgadmin-org/pgadmin4/issues/6836>`_ - Fixed an issue where non-super PostgreSQL users are not able to terminate their own connections from dashboard.
|
||||
| `Issue #6851 <https://github.com/pgadmin-org/pgadmin4/issues/6851>`_ - Fix an issue where scale in columns is not allowed to have value as 0 or below.
|
||||
| `Issue #6858 <https://github.com/pgadmin-org/pgadmin4/issues/6858>`_ - Fix an issue in graphical explain plan where query tool crashes when the plan has parallel workers details and sort node is clicked for details.
|
||||
| `Issue #6865 <https://github.com/pgadmin-org/pgadmin4/issues/6865>`_ - Fix an issue where user login is not working if username/email contains single quote in server mode.
|
||||
@@ -0,0 +1,59 @@
|
||||
***********
|
||||
Version 8.0
|
||||
***********
|
||||
|
||||
Release date: 2023-11-23
|
||||
|
||||
This release contains a number of bug fixes and new features since the release of pgAdmin 4 v7.8.
|
||||
|
||||
Supported Database Servers
|
||||
**************************
|
||||
**PostgreSQL**: 12, 13, 14, 15, and 16
|
||||
|
||||
**EDB Advanced Server**: 12, 13, 14, 15, and 16
|
||||
|
||||
Bundled PostgreSQL Utilities
|
||||
****************************
|
||||
**psql**, **pg_dump**, **pg_dumpall**, **pg_restore**: 16.0
|
||||
|
||||
|
||||
New features
|
||||
************
|
||||
|
||||
| `Issue #2821 <https://github.com/pgadmin-org/pgadmin4/issues/2821>`_ - Have close buttons on individual panel tabs instead of common.
|
||||
| `Issue #4733 <https://github.com/pgadmin-org/pgadmin4/issues/4733>`_ - Allow closing all the tabs, including SQL and Properties.
|
||||
| `Issue #5394 <https://github.com/pgadmin-org/pgadmin4/issues/5394>`_ - Changes in the context menu on panel tabs - Add close, close all and close others menu items.
|
||||
|
||||
Housekeeping
|
||||
************
|
||||
|
||||
| `Issue #6441 <https://github.com/pgadmin-org/pgadmin4/issues/6441>`_ - Update app bundle built to use notarytool instead of altool.
|
||||
| `Issue #6479 <https://github.com/pgadmin-org/pgadmin4/issues/6479>`_ - Replace the current layout library wcDocker with ReactJS based rc-dock.
|
||||
| `Issue #6850 <https://github.com/pgadmin-org/pgadmin4/issues/6850>`_ - Upgrade Flask, Werkzeug and other modules depends on the latest version of Flask.
|
||||
|
||||
Bug fixes
|
||||
*********
|
||||
|
||||
| `Issue #2986 <https://github.com/pgadmin-org/pgadmin4/issues/2986>`_ - Fix an issue where the scroll position of panels was not remembered on Firefox.
|
||||
| `Issue #5770 <https://github.com/pgadmin-org/pgadmin4/issues/5770>`_ - Add DROP SQL for foreign keys in SQL generated by ERD when using WITH DROP option.
|
||||
| `Issue #5807 <https://github.com/pgadmin-org/pgadmin4/issues/5807>`_ - Fixed an issue where psql was not taking the role used to connect in server properties.
|
||||
| `Issue #6017 <https://github.com/pgadmin-org/pgadmin4/issues/6017>`_ - Fixed an issue where Geometry Viewer renders geometry incorrectly after trying to view 3D or non-4326 SRID geometry.
|
||||
| `Issue #6459 <https://github.com/pgadmin-org/pgadmin4/issues/6459>`_ - Fix the sorting of size on the statistics panel.
|
||||
| `Issue #6487 <https://github.com/pgadmin-org/pgadmin4/issues/6487>`_ - Fixed restoration of query tool database connection after dropping and re-creating the database with the same name.
|
||||
| `Issue #6602 <https://github.com/pgadmin-org/pgadmin4/issues/6602>`_ - Fix an issue where the default server-group is being deleted if the load-server json file contains no servers.
|
||||
| `Issue #6720 <https://github.com/pgadmin-org/pgadmin4/issues/6720>`_ - Fix an issue of the incorrect format (no indent) of SQL stored functions/procedures.
|
||||
| `Issue #6769 <https://github.com/pgadmin-org/pgadmin4/issues/6769>`_ - Server config information in the about dialog should be only visible to admin users.
|
||||
| `Issue #6784 <https://github.com/pgadmin-org/pgadmin4/issues/6784>`_ - Fixed an issue where Schema Diff does not work when the user language is set to any language other than English in Preferences.
|
||||
| `Issue #6817 <https://github.com/pgadmin-org/pgadmin4/issues/6817>`_ - Fixed the query generated when creating subscription where copy_data parameter was missing.
|
||||
| `Issue #6820 <https://github.com/pgadmin-org/pgadmin4/issues/6820>`_ - Ensure backup/restore/maintenance works with invalid pgpass file parameter.
|
||||
| `Issue #6835 <https://github.com/pgadmin-org/pgadmin4/issues/6835>`_ - Fix an issue where OAUTH_ADDITIONAL_CLAIMS does not recognise AzureAD with > 150 groups.
|
||||
| `Issue #6840 <https://github.com/pgadmin-org/pgadmin4/issues/6840>`_ - Fixed circular import error occurring while deploying cloud PostgreSQL instance from pgAdmin.
|
||||
| `Issue #6874 <https://github.com/pgadmin-org/pgadmin4/issues/6874>`_ - Fix an issue where the browser window stuck on spinning with an Oauth user without email.
|
||||
| `Issue #6875 <https://github.com/pgadmin-org/pgadmin4/issues/6875>`_ - Fix an issue where import/export data is not working for shared servers.
|
||||
| `Issue #6877 <https://github.com/pgadmin-org/pgadmin4/issues/6877>`_ - Remove the max length of 255 from password exec command in server configuration dialog.
|
||||
| `Issue #6884 <https://github.com/pgadmin-org/pgadmin4/issues/6884>`_ - Remove gettext from empty strings in the title of the storage graph.
|
||||
| `Issue #6902 <https://github.com/pgadmin-org/pgadmin4/issues/6902>`_ - Fixed an issue where the change server password is not working in desktop mode.
|
||||
| `Issue #6904 <https://github.com/pgadmin-org/pgadmin4/issues/6904>`_ - Fix a crash issue occurring when debugging a function with arguments when using pgAdmin with external config database.
|
||||
| `Issue #6920 <https://github.com/pgadmin-org/pgadmin4/issues/6920>`_ - Fix an issue in ERD tool where SQL generated is missing columns for the table.
|
||||
| `Issue #6934 <https://github.com/pgadmin-org/pgadmin4/issues/6934>`_ - Clear the password field in the config database on clear saved server password.
|
||||
| `Issue #6962 <https://github.com/pgadmin-org/pgadmin4/issues/6962>`_ - Fixed an issue where the data type of the array type was not visible for the column in the Foreign Table dialog.
|
||||
@@ -44,6 +44,9 @@ Use the fields in the *General* tab to identify the server:
|
||||
Please note that once the server is shared, it's icon is changed in the
|
||||
object explorer.
|
||||
|
||||
* Use the *Shared Username* field to fill the username of the shared server
|
||||
connection. By default, it will take the username of the server being shared.
|
||||
|
||||
* Provide a comment about the server in the *Comments* field.
|
||||
|
||||
Click the *Connection* tab to continue.
|
||||
@@ -203,6 +206,12 @@ Use the fields in the *Advanced* tab to configure a connection:
|
||||
the password will not expire until your pgAdmin session does.
|
||||
Zero means the command will be executed for each new connection or reconnection that is made.
|
||||
If the generated password is not valid indefinitely, set this value to slightly before it will expire.
|
||||
* Use the *Prepare threshold* field to specify the number of times a query is
|
||||
executed before it is prepared. If it is set to 0, every query is prepared
|
||||
the first time it is executed. If it is set to blank, prepared statements are disabled
|
||||
on the connection. This is particularly useful with external connection poolers,
|
||||
such as PgBouncer, which is not compatible with prepared statements. Set this to
|
||||
blank in such cases.
|
||||
|
||||
.. note:: The password file option is only supported when pgAdmin is using libpq
|
||||
v10.0 or later to connect to the server.
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
Use the *Subscription* dialog to create a subscription. A subscription defines the connection to another database and set of publications (one or more) to which it wants to subscribe.
|
||||
|
||||
The *subscription* dialog organizes the development of a subscription through the following dialog tabs: *General*, *Connection* and *With*. The *SQL* tab displays the SQL code generated by dialog selections.
|
||||
The *subscription* dialog organizes the development of a subscription through the following dialog tabs: *General*, *Connection*, *SSL* and *With*. The *SQL* tab displays the SQL code generated by dialog selections.
|
||||
|
||||
.. image:: images/subscription_general.png
|
||||
:alt: Subscription dialog general tab
|
||||
@@ -83,7 +83,11 @@ icon that is located to the right of each of the following fields.
|
||||
|
||||
Click the *With* tab to continue.
|
||||
|
||||
.. image:: images/subscription_with.png
|
||||
.. image:: images/subscription_with_1.png
|
||||
:alt: Subscription dialog with tab
|
||||
:align: center
|
||||
|
||||
.. image:: images/subscription_with_2.png
|
||||
:alt: Subscription dialog with tab
|
||||
:align: center
|
||||
|
||||
@@ -95,6 +99,13 @@ Use the *With* tab to define some parameters for a subscription:
|
||||
* The *Connect?* specifies whether the CREATE SUBSCRIPTION should connect to the publisher at all. By default, it is set to *Yes*. Setting this to *No* will change default values of enabled, create_slot and copy_data to *No*.
|
||||
* Use the *Slot Name* field to specify the name of the replication slot to use. By default, it uses the name of the subscription for the slot name.
|
||||
* Use the *Synchronous commit* field to override the synchronous_commit setting. By default, it is set to *off*. It is safe to use off for logical replication: If the subscriber loses transactions because of missing synchronization, the data will be sent again from the publisher.
|
||||
* Use the *Streaming* field to specify whether to enable streaming of in-progress transactions for this subscription. The default value is *off*, meaning all transactions are fully decoded on the publisher and only then sent to the subscriber as a whole. This option is available only on PostgreSQL 14 and above.
|
||||
* Use the *Binary?* switch to specify whether the subscription will request the publisher to send the data in binary format (as opposed to text). The default is *false*. This option is available only on PostgreSQL 14 and above.
|
||||
* Use the *Two phase?* switch to specify whether two-phase commit is enabled for this subscription. The default is *false*. This option is available only on PostgreSQL 15 and above.
|
||||
* Use the *Disable on error?* switch to specify whether the subscription should be automatically disabled if any errors are detected by subscription workers during data replication from the publisher. The default is *false*. This option is available only on PostgreSQL 15 and above.
|
||||
* Move the *Run as owner?* switch to *true* position to specify all replication actions are performed as the subscription owner. If *false*, replication workers will perform actions on each table as the owner of that table. The default is *false*. This option is available only on PostgreSQL 16 and above.
|
||||
* Use the *Password required?* to specify whether connections to the publisher made as a result of this subscription must use password authentication. This setting is ignored when the subscription is owned by a superuser. The default is true. Only superusers can set this value to *false*. This option is available only on PostgreSQL 16 and above.
|
||||
* Use the *Origin* to specify whether the subscription will request the publisher to only send changes that don't have an origin or send changes regardless of origin. The default is *any*. This option is available only on PostgreSQL 16 and above.
|
||||
|
||||
Click the *SQL* tab to continue.
|
||||
|
||||
|
||||
@@ -394,6 +394,9 @@ Use the fields in the *Advanced* tab to define advanced features for the table:
|
||||
* Use the drop-down listbox next to *Of type* to copy the table structure from
|
||||
the specified composite type. Please note that a typed table will be dropped
|
||||
if the type is dropped (with DROP TYPE ... CASCADE).
|
||||
* Use the drop-down list box next to Access Method to specify the table access method to use to store
|
||||
the contents for the new table; the method needs to be an access method of type TABLE. This field is optional.
|
||||
This option is available from v12 and above.
|
||||
* Use the *Fill Factor* field to specify a fill factor for the table. The fill
|
||||
factor for a table is a percentage between 10 and 100. 100 (complete packing)
|
||||
is the default.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
html{
|
||||
background-color: #fff;
|
||||
|
||||
|
||||
}
|
||||
|
||||
body {
|
||||
@@ -10,6 +10,7 @@ body {
|
||||
font-family: Roboto, Helvetica Neue, -apple-system, BlinkMacSystemFont, Segoe UI, Arial, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
background-color: #fff;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
div.body {
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
****************
|
||||
|
||||
The pgAdmin toolbar provides shortcut buttons for frequently used features like
|
||||
View Data and the Query Tool which are most frequently used in pgAdmin. This
|
||||
toolbar is visible on the Browser panel. Buttons get enabled/disabled based on
|
||||
the selected browser node.
|
||||
the Query Tool, View/Edit Data, Search Object and the PSQL Tool. This
|
||||
toolbar is visible on the Object explorer panel. Buttons get enabled/disabled based on
|
||||
the selected object node.
|
||||
|
||||
.. image:: /images/toolbar.png
|
||||
:alt: pgAdmin Toolbar
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
`Tree Control`:index:
|
||||
*********************
|
||||
|
||||
The left pane of the main window displays a tree control (the *pgAdmin* tree
|
||||
control) that provides access to the objects that reside on a server.
|
||||
The left pane of the main window displays a tree control (Object explorer)
|
||||
that provides access to the objects that reside on a server.
|
||||
|
||||
.. image:: /images/main_left_pane.png
|
||||
:alt: object explorer panel
|
||||
|
||||
@@ -19,19 +19,18 @@ CA_FILE = '/etc/ssl/certs/ca-certificates.crt'
|
||||
LOG_FILE = '/dev/null'
|
||||
HELP_PATH = '../../docs'
|
||||
DEFAULT_BINARY_PATHS = {
|
||||
'pg': '/usr/local/pgsql-15',
|
||||
'pg': '/usr/local/pgsql-16',
|
||||
'pg-16': '/usr/local/pgsql-16',
|
||||
'pg-15': '/usr/local/pgsql-15',
|
||||
'pg-14': '/usr/local/pgsql-14',
|
||||
'pg-13': '/usr/local/pgsql-13',
|
||||
'pg-12': '/usr/local/pgsql-12',
|
||||
'pg-11': '/usr/local/pgsql-11',
|
||||
'pg-10': '/usr/local/pgsql-10'
|
||||
'pg-12': '/usr/local/pgsql-12'
|
||||
}
|
||||
EOF
|
||||
|
||||
# This is a bit kludgy, but necessary as the container uses BusyBox/ash as
|
||||
# it's shell and not bash which would allow a much cleaner implementation
|
||||
for var in $(env | grep PGADMIN_CONFIG_ | cut -d "=" -f 1); do
|
||||
for var in $(env | grep "^PGADMIN_CONFIG_" | cut -d "=" -f 1); do
|
||||
# shellcheck disable=SC2086
|
||||
# shellcheck disable=SC2046
|
||||
echo ${var#PGADMIN_CONFIG_} = $(eval "echo \$$var") >> /pgadmin4/config_distro.py
|
||||
|
||||
@@ -224,7 +224,7 @@ _copy_code() {
|
||||
cp "${SOURCEDIR}/pkg/linux/config_distro.py" "${SERVERROOT}/usr/${APP_NAME}/web/"
|
||||
cd "${SERVERROOT}/usr/${APP_NAME}/web/" || exit
|
||||
rm -f pgadmin4.db config_local.*
|
||||
rm -rf karma.conf.js package.json node_modules/ regression/ tools/ pgadmin/static/js/generated/.cache
|
||||
rm -rf jest.config.js babel.* package.json node_modules/ regression/ tools/ pgadmin/static/js/generated/.cache
|
||||
find . -name "tests" -type d -print0 | xargs -0 rm -rf
|
||||
find . -name "feature_tests" -type d -print0 | xargs -0 rm -rf
|
||||
find . -name "__pycache__" -type d -print0 | xargs -0 rm -rf
|
||||
|
||||
@@ -298,7 +298,7 @@ _complete_bundle() {
|
||||
cp -r "${SOURCE_DIR}/web" "${BUNDLE_DIR}/Contents/Resources/"
|
||||
cd "${BUNDLE_DIR}/Contents/Resources/web" || exit
|
||||
rm -f pgadmin4.db config_local.*
|
||||
rm -rf karma.conf.js package.json .yarn* yarn* .editorconfig .eslint* node_modules/ regression/ tools/ pgadmin/static/js/generated/.cache
|
||||
rm -rf jest.config.js babel.* package.json .yarn* yarn* .editorconfig .eslint* node_modules/ regression/ tools/ pgadmin/static/js/generated/.cache
|
||||
find . -name "tests" -type d -print0 | xargs -0 rm -rf
|
||||
find . -name "feature_tests" -type d -print0 | xargs -0 rm -rf
|
||||
find . -name "__pycache__" -type d -print0 | xargs -0 rm -rf
|
||||
@@ -432,59 +432,32 @@ _notarize_pkg() {
|
||||
return
|
||||
fi
|
||||
|
||||
# Notarize the package. Try three times, to allow for upload issues
|
||||
for i in {1..3}; do
|
||||
echo "Uploading DMG for notarisation (attempt ${i} of 3)..."
|
||||
STATUS=$(xcrun altool --notarize-app \
|
||||
-f "${DMG_NAME}" \
|
||||
--asc-provider "${DEVELOPER_NAME}" \
|
||||
--primary-bundle-id org.pgadmin.pgadmin4 \
|
||||
-u "${DEVELOPER_USER}" \
|
||||
-p "${DEVELOPER_ASP}" 2>&1)
|
||||
RETVAL=$?
|
||||
echo "Uploading DMG for Notarization ..."
|
||||
STATUS=$(xcrun notarytool submit "${DMG_NAME}" \
|
||||
--team-id "${DEVELOPER_TEAM_ID}" \
|
||||
--apple-id "${DEVELOPER_USER}" \
|
||||
--password "${DEVELOPER_ASP}" 2>&1)
|
||||
|
||||
if [ ${RETVAL} != 0 ]; then
|
||||
echo "Attempt ${i} failure: ${STATUS}"
|
||||
else
|
||||
# Success!
|
||||
break;
|
||||
fi
|
||||
done
|
||||
# Get the submission ID
|
||||
SUBMISSION_ID=$(echo "${STATUS}" | awk -F ': ' '/id:/ { print $2; exit; }')
|
||||
echo "Notarization submission ID: ${SUBMISSION_ID}"
|
||||
|
||||
# print error if above command fails
|
||||
if [ ${RETVAL} != 0 ]; then
|
||||
echo "Notarization failed."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Get the request ID
|
||||
REQUEST_UUID=$(echo "${STATUS}" | awk '/RequestUUID/ { print $NF; }')
|
||||
echo "Notarization request ID: ${REQUEST_UUID}"
|
||||
|
||||
# Now we need to wait for the results. Try 60 times.
|
||||
for i in {1..60}; do
|
||||
echo "Waiting 30 seconds..."
|
||||
sleep 30
|
||||
|
||||
echo "Requesting notarisation result (attempt ${i} of 60)..."
|
||||
REQUEST_STATUS=$(xcrun altool --notarization-info "${REQUEST_UUID}" \
|
||||
--username "${DEVELOPER_USER}" \
|
||||
--password "${DEVELOPER_ASP}" 2>&1 | \
|
||||
awk -F ': ' '/Status:/ { print $2; }' )
|
||||
|
||||
if [[ "${REQUEST_STATUS}" == "success" ]]; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
# Print status information
|
||||
xcrun altool --notarization-info "${REQUEST_UUID}" \
|
||||
--username "${DEVELOPER_USER}" \
|
||||
echo "Waiting for Notarization to be completed ..."
|
||||
xcrun notarytool wait "${SUBMISSION_ID}" \
|
||||
--team-id "${DEVELOPER_TEAM_ID}" \
|
||||
--apple-id "${DEVELOPER_USER}" \
|
||||
--password "${DEVELOPER_ASP}"
|
||||
|
||||
if [[ "${REQUEST_STATUS}" != "success" ]]; then
|
||||
echo "Notarization failed."
|
||||
exit 1
|
||||
# Print status information
|
||||
REQUEST_STATUS=$(xcrun notarytool info "${SUBMISSION_ID}" \
|
||||
--team-id "${DEVELOPER_TEAM_ID}" \
|
||||
--apple-id "${DEVELOPER_USER}" \
|
||||
--password "${DEVELOPER_ASP}" 2>&1 | \
|
||||
awk -F ': ' '/status:/ { print $2; }')
|
||||
|
||||
if [[ "${REQUEST_STATUS}" != "Accepted" ]]; then
|
||||
echo "Notarization failed."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Staple the notarization
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# In order to enable notarization of the Mac Appbundle, copy this file to
|
||||
# notarization.conf, and edit the values below to reflect your Apple
|
||||
# Developer User ID, app-specific password and Provider Shortname.
|
||||
# Developer User ID, app-specific password and Team ID.
|
||||
#
|
||||
# You can use the following command to see the available shortnames for your
|
||||
# Apple Developer ID (substituting the appropriate username/password):
|
||||
@@ -9,4 +9,4 @@
|
||||
|
||||
DEVELOPER_USER=user@example.com
|
||||
DEVELOPER_ASP=1234-abcd-5678-efgh
|
||||
DEVELOPER_NAME=MyCompany
|
||||
DEVELOPER_TEAM_ID=MyTeamID
|
||||
@@ -20,7 +20,7 @@ AppPublisher={#MyAppPublisher}
|
||||
AppPublisherURL={#MyAppURL}
|
||||
AppSupportURL={#MyAppURL}
|
||||
AppUpdatesURL={#MyAppURL}
|
||||
DefaultDirName={autopf}\{#MyAppName}\{#MyAppVersion}
|
||||
DefaultDirName={autopf}\{#MyAppName}
|
||||
DefaultGroupName={#MyAppName}
|
||||
DisableWelcomePage=no
|
||||
DisableProgramGroupPage=auto
|
||||
|
||||
@@ -8,26 +8,32 @@
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
Flask==2.2.*
|
||||
Flask==2.3.*; python_version > '3.7'
|
||||
Flask==2.2.*; python_version <= '3.7'
|
||||
Flask-Gravatar==0.*
|
||||
Flask-Login==0.*
|
||||
Flask-Mail==0.*
|
||||
Flask-Migrate==4.*
|
||||
greenlet==1.1.2; python_version <= '3.10'
|
||||
Flask-SQLAlchemy==3.0.*
|
||||
Flask-WTF==1.1.1
|
||||
Flask-SQLAlchemy==3.1.*; python_version > '3.7'
|
||||
Flask-SQLAlchemy==3.0.*; python_version <= '3.7'
|
||||
Flask-WTF==1.2.*; python_version > '3.7'
|
||||
Flask-WTF==1.1.1; python_version <= '3.7'
|
||||
Flask-Compress==1.*
|
||||
Flask-Paranoid==0.*
|
||||
Flask-Babel==3.1.*
|
||||
Flask-Security-Too==5.1.*
|
||||
Flask-Babel==4.0.*; python_version > '3.7'
|
||||
Flask-Babel==3.1.*; python_version <= '3.7'
|
||||
Flask-Security-Too==5.2.*; python_version > '3.7'
|
||||
Flask-Security-Too==5.1.*; python_version <= '3.7'
|
||||
Flask-SocketIO==5.3.*
|
||||
WTForms==3.0.*
|
||||
WTForms==3.1.*; python_version > '3.7'
|
||||
WTForms==3.0.*; python_version <= '3.7'
|
||||
passlib==1.*
|
||||
pytz==2023.*
|
||||
speaklater3==1.*
|
||||
sqlparse==0.*
|
||||
psutil==5.9.*
|
||||
psycopg[c]==3.1.9
|
||||
psycopg[c]==3.1.12
|
||||
python-dateutil==2.*
|
||||
SQLAlchemy==2.*
|
||||
bcrypt==4.0.*
|
||||
@@ -42,15 +48,16 @@ pywinpty==2.0.*; sys_platform=="win32"
|
||||
Authlib==1.2.*
|
||||
pyotp==2.*
|
||||
qrcode==7.*
|
||||
Pillow==9.*
|
||||
boto3==1.28.*
|
||||
botocore==1.31.*
|
||||
urllib3==1.26.*
|
||||
azure-mgmt-rdbms==10.1.0
|
||||
azure-mgmt-resource==23.0.1
|
||||
azure-mgmt-subscription==3.1.1
|
||||
azure-identity==1.13.0
|
||||
azure-identity==1.15.0
|
||||
google-api-python-client==2.*
|
||||
google-auth-oauthlib==1.0.0
|
||||
Werkzeug==2.2.3
|
||||
keyring==23.*
|
||||
google-auth-oauthlib==1.1.0
|
||||
keyring==24.*; python_version > '3.7'
|
||||
keyring==23.*; python_version <= '3.7'
|
||||
Werkzeug==2.3.*; python_version > '3.7'
|
||||
Werkzeug==2.2.3; python_version <= '3.7'
|
||||
@@ -12,7 +12,6 @@ module.exports = {
|
||||
'browser': true,
|
||||
'es6': true,
|
||||
'amd': true,
|
||||
'jasmine': true,
|
||||
},
|
||||
'extends': [
|
||||
'eslint:recommended',
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
checksumBehavior: update
|
||||
|
||||
logFilters:
|
||||
- code: YN0013
|
||||
level: discard
|
||||
|
||||
nodeLinker: node-modules
|
||||
@@ -23,11 +23,11 @@
|
||||
"256": "assets/pgAdmin4.png"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.4.0",
|
||||
"axios": "^1.5.1",
|
||||
"bootstrap": "^4.5.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^8.42.0",
|
||||
"eslint": "^8.50.0",
|
||||
"nw": "0.77.0"
|
||||
},
|
||||
"scripts": {
|
||||
|
||||
@@ -24,9 +24,9 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"@eslint-community/regexpp@npm:^4.6.1":
|
||||
version: 4.6.2
|
||||
resolution: "@eslint-community/regexpp@npm:4.6.2"
|
||||
checksum: a3c341377b46b54fa228f455771b901d1a2717f95d47dcdf40199df30abc000ba020f747f114f08560d119e979d882a94cf46cfc51744544d54b00319c0f2724
|
||||
version: 4.10.0
|
||||
resolution: "@eslint-community/regexpp@npm:4.10.0"
|
||||
checksum: 2a6e345429ea8382aaaf3a61f865cae16ed44d31ca917910033c02dc00d505d939f10b81e079fa14d43b51499c640138e153b7e40743c4c094d9df97d4e56f7b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -47,21 +47,21 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@eslint/js@npm:^8.47.0":
|
||||
version: 8.47.0
|
||||
resolution: "@eslint/js@npm:8.47.0"
|
||||
checksum: 0ef57fe27b6d4c305b33f3b2d2fee1ab397a619006f1d6f4ce5ee4746b8f03d11a4e098805a7d78601ca534cf72917d37f0ac19896c992a32e26299ecb9f9de1
|
||||
"@eslint/js@npm:8.52.0":
|
||||
version: 8.52.0
|
||||
resolution: "@eslint/js@npm:8.52.0"
|
||||
checksum: 490893b8091a66415f4ac98b963d23eb287264ea3bd6af7ec788f0570705cf64fd6ab84b717785980f55e39d08ff5c7fde6d8e4391ccb507169370ce3a6d091a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@humanwhocodes/config-array@npm:^0.11.10":
|
||||
version: 0.11.10
|
||||
resolution: "@humanwhocodes/config-array@npm:0.11.10"
|
||||
"@humanwhocodes/config-array@npm:^0.11.13":
|
||||
version: 0.11.13
|
||||
resolution: "@humanwhocodes/config-array@npm:0.11.13"
|
||||
dependencies:
|
||||
"@humanwhocodes/object-schema": ^1.2.1
|
||||
"@humanwhocodes/object-schema": ^2.0.1
|
||||
debug: ^4.1.1
|
||||
minimatch: ^3.0.5
|
||||
checksum: 1b1302e2403d0e35bc43e66d67a2b36b0ad1119efc704b5faff68c41f791a052355b010fb2d27ef022670f550de24cd6d08d5ecf0821c16326b7dcd0ee5d5d8a
|
||||
checksum: f8ea57b0d7ed7f2d64cd3944654976829d9da91c04d9c860e18804729a33f7681f78166ef4c761850b8c324d362f7d53f14c5c44907a6b38b32c703ff85e4805
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -72,10 +72,10 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@humanwhocodes/object-schema@npm:^1.2.1":
|
||||
version: 1.2.1
|
||||
resolution: "@humanwhocodes/object-schema@npm:1.2.1"
|
||||
checksum: a824a1ec31591231e4bad5787641f59e9633827d0a2eaae131a288d33c9ef0290bd16fda8da6f7c0fcb014147865d12118df10db57f27f41e20da92369fcb3f1
|
||||
"@humanwhocodes/object-schema@npm:^2.0.1":
|
||||
version: 2.0.1
|
||||
resolution: "@humanwhocodes/object-schema@npm:2.0.1"
|
||||
checksum: 24929487b1ed48795d2f08346a0116cc5ee4634848bce64161fb947109352c562310fd159fc64dda0e8b853307f5794605191a9547f7341158559ca3c8262a45
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -116,18 +116,27 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"@types/node@npm:*":
|
||||
version: 20.5.0
|
||||
resolution: "@types/node@npm:20.5.0"
|
||||
checksum: 659bc5fc93b5c02bd88ca4bfae4f6b9dc307d45884d1dd9d69df85819a9943cdc00cd3c87eec3048866df6a67f52297f74d170e47a44f61edb3e8f770d94e85e
|
||||
version: 20.8.10
|
||||
resolution: "@types/node@npm:20.8.10"
|
||||
dependencies:
|
||||
undici-types: ~5.26.4
|
||||
checksum: 7c61190e43e8074a1b571e52ff14c880bc67a0447f2fe5ed0e1a023eb8a23d5f815658edb98890f7578afe0f090433c4a635c7c87311762544e20dd78723e515
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/responselike@npm:^1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "@types/responselike@npm:1.0.0"
|
||||
version: 1.0.2
|
||||
resolution: "@types/responselike@npm:1.0.2"
|
||||
dependencies:
|
||||
"@types/node": "*"
|
||||
checksum: e99fc7cc6265407987b30deda54c1c24bb1478803faf6037557a774b2f034c5b097ffd65847daa87e82a61a250d919f35c3588654b0fdaa816906650f596d1b0
|
||||
checksum: ff1767e947eb7d49849e4566040453efcd894888e85b398f7f8cb731552f303f26aceda573b680a142b77ec5fb6c79535d9c6d047d9f936c386dbf3863d2ae17
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@ungap/structured-clone@npm:^1.2.0":
|
||||
version: 1.2.0
|
||||
resolution: "@ungap/structured-clone@npm:1.2.0"
|
||||
checksum: 4f656b7b4672f2ce6e272f2427d8b0824ed11546a601d8d5412b9d7704e83db38a8d9f402ecdf2b9063fc164af842ad0ec4a55819f621ed7e7ea4d1efcc74524
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -141,11 +150,11 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"acorn@npm:^8.9.0":
|
||||
version: 8.10.0
|
||||
resolution: "acorn@npm:8.10.0"
|
||||
version: 8.11.2
|
||||
resolution: "acorn@npm:8.11.2"
|
||||
bin:
|
||||
acorn: bin/acorn
|
||||
checksum: 538ba38af0cc9e5ef983aee196c4b8b4d87c0c94532334fa7e065b2c8a1f85863467bb774231aae91613fcda5e68740c15d97b1967ae3394d20faddddd8af61d
|
||||
checksum: 818450408684da89423e3daae24e4dc9b68692db8ab49ea4569c7c5abb7a3f23669438bf129cc81dfdada95e1c9b944ee1bfca2c57a05a4dc73834a612fbf6a7
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -205,14 +214,14 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"axios@npm:^1.4.0":
|
||||
version: 1.4.0
|
||||
resolution: "axios@npm:1.4.0"
|
||||
"axios@npm:^1.5.1":
|
||||
version: 1.6.0
|
||||
resolution: "axios@npm:1.6.0"
|
||||
dependencies:
|
||||
follow-redirects: ^1.15.0
|
||||
form-data: ^4.0.0
|
||||
proxy-from-env: ^1.1.0
|
||||
checksum: 7fb6a4313bae7f45e89d62c70a800913c303df653f19eafec88e56cea2e3821066b8409bc68be1930ecca80e861c52aa787659df0ffec6ad4d451c7816b9386b
|
||||
checksum: c7c9f2ae9e0b9bad7d6f9a4dff030930b12ee667dedf54c3c776714f91681feb743c509ac0796ae5c01e12c4ab4a2bee74905068dd200fbc1ab86f9814578fb0
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -618,17 +627,18 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"eslint@npm:^8.42.0":
|
||||
version: 8.47.0
|
||||
resolution: "eslint@npm:8.47.0"
|
||||
"eslint@npm:^8.50.0":
|
||||
version: 8.52.0
|
||||
resolution: "eslint@npm:8.52.0"
|
||||
dependencies:
|
||||
"@eslint-community/eslint-utils": ^4.2.0
|
||||
"@eslint-community/regexpp": ^4.6.1
|
||||
"@eslint/eslintrc": ^2.1.2
|
||||
"@eslint/js": ^8.47.0
|
||||
"@humanwhocodes/config-array": ^0.11.10
|
||||
"@eslint/js": 8.52.0
|
||||
"@humanwhocodes/config-array": ^0.11.13
|
||||
"@humanwhocodes/module-importer": ^1.0.1
|
||||
"@nodelib/fs.walk": ^1.2.8
|
||||
"@ungap/structured-clone": ^1.2.0
|
||||
ajv: ^6.12.4
|
||||
chalk: ^4.0.0
|
||||
cross-spawn: ^7.0.2
|
||||
@@ -661,7 +671,7 @@ __metadata:
|
||||
text-table: ^0.2.0
|
||||
bin:
|
||||
eslint: bin/eslint.js
|
||||
checksum: 1988617f703eadc5c7540468d54dc8e5171cf2bb9483f6172799cd1ff54a9a5e4470f003784e8cef92687eaa14de37172732787040e67817581a20bcb9c15970
|
||||
checksum: fd22d1e9bd7090e31b00cbc7a3b98f3b76020a4c4641f987ae7d0c8f52e1b88c3b268bdfdabac2e1a93513e5d11339b718ff45cbff48a44c35d7e52feba510ed
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -813,29 +823,30 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"flat-cache@npm:^3.0.4":
|
||||
version: 3.0.4
|
||||
resolution: "flat-cache@npm:3.0.4"
|
||||
version: 3.1.1
|
||||
resolution: "flat-cache@npm:3.1.1"
|
||||
dependencies:
|
||||
flatted: ^3.1.0
|
||||
flatted: ^3.2.9
|
||||
keyv: ^4.5.3
|
||||
rimraf: ^3.0.2
|
||||
checksum: 4fdd10ecbcbf7d520f9040dd1340eb5dfe951e6f0ecf2252edeec03ee68d989ec8b9a20f4434270e71bcfd57800dc09b3344fca3966b2eb8f613072c7d9a2365
|
||||
checksum: 4958cfe0f46acf84953d4e16676ef5f0d38eab3a92d532a1e8d5f88f11eea8b36d5d598070ff2aeae15f1fde18f8d7d089eefaf9db10b5a587cc1c9072325c7a
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"flatted@npm:^3.1.0":
|
||||
version: 3.2.7
|
||||
resolution: "flatted@npm:3.2.7"
|
||||
checksum: 427633049d55bdb80201c68f7eb1cbd533e03eac541f97d3aecab8c5526f12a20ccecaeede08b57503e772c769e7f8680b37e8d482d1e5f8d7e2194687f9ea35
|
||||
"flatted@npm:^3.2.9":
|
||||
version: 3.2.9
|
||||
resolution: "flatted@npm:3.2.9"
|
||||
checksum: f14167fbe26a9d20f6fca8d998e8f1f41df72c8e81f9f2c9d61ed2bea058248f5e1cbd05e7f88c0e5087a6a0b822a1e5e2b446e879f3cfbe0b07ba2d7f80b026
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"follow-redirects@npm:^1.15.0":
|
||||
version: 1.15.2
|
||||
resolution: "follow-redirects@npm:1.15.2"
|
||||
version: 1.15.3
|
||||
resolution: "follow-redirects@npm:1.15.3"
|
||||
peerDependenciesMeta:
|
||||
debug:
|
||||
optional: true
|
||||
checksum: faa66059b66358ba65c234c2f2a37fcec029dc22775f35d9ad6abac56003268baf41e55f9ee645957b32c7d9f62baf1f0b906e68267276f54ec4b4c597c2b190
|
||||
checksum: 584da22ec5420c837bd096559ebfb8fe69d82512d5585004e36a3b4a6ef6d5905780e0c74508c7b72f907d1fa2b7bd339e613859e9c304d0dc96af2027fd0231
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -914,11 +925,11 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"globals@npm:^13.19.0":
|
||||
version: 13.21.0
|
||||
resolution: "globals@npm:13.21.0"
|
||||
version: 13.23.0
|
||||
resolution: "globals@npm:13.23.0"
|
||||
dependencies:
|
||||
type-fest: ^0.20.2
|
||||
checksum: 86c92ca8a04efd864c10852cd9abb1ebe6d447dcc72936783e66eaba1087d7dba5c9c3421a48d6ca722c319378754dbcc3f3f732dbe47592d7de908edf58a773
|
||||
checksum: 194c97cf8d1ef6ba59417234c2386549c4103b6e5f24b1ff1952de61a4753e5d2069435ba629de711a6480b1b1d114a98e2ab27f85e966d5a10c319c3bbd3dc3
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -1151,6 +1162,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"json-buffer@npm:3.0.1":
|
||||
version: 3.0.1
|
||||
resolution: "json-buffer@npm:3.0.1"
|
||||
checksum: 9026b03edc2847eefa2e37646c579300a1f3a4586cfb62bf857832b60c852042d0d6ae55d1afb8926163fa54c2b01d83ae24705f34990348bdac6273a29d4581
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"json-schema-traverse@npm:^0.4.1":
|
||||
version: 0.4.1
|
||||
resolution: "json-schema-traverse@npm:0.4.1"
|
||||
@@ -1165,6 +1183,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"keyv@npm:^4.5.3":
|
||||
version: 4.5.4
|
||||
resolution: "keyv@npm:4.5.4"
|
||||
dependencies:
|
||||
json-buffer: 3.0.1
|
||||
checksum: 74a24395b1c34bd44ad5cb2b49140d087553e170625240b86755a6604cd65aa16efdbdeae5cdb17ba1284a0fbb25ad06263755dbc71b8d8b06f74232ce3cdd72
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"lcid@npm:^1.0.0":
|
||||
version: 1.0.0
|
||||
resolution: "lcid@npm:1.0.0"
|
||||
@@ -1414,9 +1441,9 @@ __metadata:
|
||||
version: 0.0.0-use.local
|
||||
resolution: "pgadmin4@workspace:."
|
||||
dependencies:
|
||||
axios: ^1.4.0
|
||||
axios: ^1.5.1
|
||||
bootstrap: ^4.5.3
|
||||
eslint: ^8.42.0
|
||||
eslint: ^8.50.0
|
||||
nw: 0.77.0
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
@@ -1494,9 +1521,9 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"punycode@npm:^2.1.0":
|
||||
version: 2.3.0
|
||||
resolution: "punycode@npm:2.3.0"
|
||||
checksum: 39f760e09a2a3bbfe8f5287cf733ecdad69d6af2fe6f97ca95f24b8921858b91e9ea3c9eeec6e08cede96181b3bb33f95c6ffd8c77e63986508aa2e8159fa200
|
||||
version: 2.3.1
|
||||
resolution: "punycode@npm:2.3.1"
|
||||
checksum: bb0a0ceedca4c3c57a9b981b90601579058903c62be23c5e8e843d2c2d4148a3ecf029d5133486fb0e1822b098ba8bba09e89d6b21742d02fa26bda6441a6fb2
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -1784,6 +1811,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"undici-types@npm:~5.26.4":
|
||||
version: 5.26.5
|
||||
resolution: "undici-types@npm:5.26.5"
|
||||
checksum: 3192ef6f3fd5df652f2dc1cd782b49d6ff14dc98e5dced492aa8a8c65425227da5da6aafe22523c67f035a272c599bb89cfe803c1db6311e44bed3042fc25487
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"unzip-response@npm:^2.0.1":
|
||||
version: 2.0.1
|
||||
resolution: "unzip-response@npm:2.0.1"
|
||||
|
||||
@@ -21,7 +21,7 @@ PG_CODES_URLS = [
|
||||
"https://raw.githubusercontent.com/postgres/postgres/master/src/pl/"
|
||||
"plpgsql/src/pl_scanner.c",
|
||||
]
|
||||
PG_CODES_REGEX = "PG_KEYWORD\(\"([a-z]*)\"[A-Z_, ]*\)"
|
||||
PG_CODES_REGEX = r"PG_KEYWORD\(\"([a-z]*)\"[A-Z_, ]*\)"
|
||||
|
||||
PG_SQL_DOCS_URL = \
|
||||
"https://www.postgresql.org/docs/current/sql-keywords-appendix.html"
|
||||
|
||||
@@ -12,7 +12,6 @@ module.exports = {
|
||||
'browser': true,
|
||||
'es6': true,
|
||||
'amd': true,
|
||||
'jasmine': true,
|
||||
},
|
||||
'extends': [
|
||||
'eslint:recommended',
|
||||
@@ -41,10 +40,11 @@ module.exports = {
|
||||
'plugins': [
|
||||
'react',
|
||||
'@babel',
|
||||
'jest'
|
||||
],
|
||||
'overrides': [
|
||||
{
|
||||
'files': ['**/*.ts', '**/*.tsx'],
|
||||
'files': ['**/*.{ts,tsx}'],
|
||||
'plugins': [
|
||||
'@typescript-eslint',
|
||||
],
|
||||
@@ -55,10 +55,20 @@ module.exports = {
|
||||
'@typescript-eslint/no-this-alias': ['off'],
|
||||
}
|
||||
},
|
||||
{
|
||||
'files': ['**/*{spec,test}.{js,jsx}', './regression/javascript/**/*.{js}'],
|
||||
'extends': ['eslint:recommended'],
|
||||
'env': {
|
||||
'jest': true
|
||||
}
|
||||
},
|
||||
],
|
||||
'globals': {
|
||||
'_': true,
|
||||
'module': true,
|
||||
'__dirname': true,
|
||||
'global': true,
|
||||
'jest': true
|
||||
},
|
||||
'rules': {
|
||||
'indent': [
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
nodeLinker: node-modules
|
||||
checksumBehavior: update
|
||||
|
||||
logFilters:
|
||||
- code: YN0013
|
||||
level: discard
|
||||
- code: YN0013
|
||||
level: discard
|
||||
|
||||
nodeLinker: node-modules
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"presets": [["@babel/preset-env", {"modules": "commonjs", "useBuiltIns": "usage", "corejs": 3}], "@babel/preset-react", "@babel/preset-typescript"],
|
||||
"plugins": ["@babel/plugin-proposal-class-properties", "@babel/proposal-object-rest-spread", "@babel/plugin-transform-runtime"]
|
||||
}
|
||||
@@ -49,8 +49,8 @@ APP_ICON = 'pg-icon'
|
||||
#
|
||||
|
||||
# Application version number components
|
||||
APP_RELEASE = 7
|
||||
APP_REVISION = 6
|
||||
APP_RELEASE = 8
|
||||
APP_REVISION = 0
|
||||
|
||||
# Application version suffix, e.g. 'beta1', 'dev'. Usually an empty string
|
||||
# for GA releases.
|
||||
@@ -59,7 +59,7 @@ APP_SUFFIX = ''
|
||||
# Numeric application version for upgrade checks. Should be in the format:
|
||||
# [X]XYYZZ, where X is the release version, Y is the revision, with a leading
|
||||
# zero if needed, and Z represents the suffix, with a leading zero if needed
|
||||
APP_VERSION_INT = 70600
|
||||
APP_VERSION_INT = 80000
|
||||
|
||||
# DO NOT CHANGE!
|
||||
# The application version string, constructed from the components
|
||||
@@ -230,8 +230,8 @@ PROXY_X_PREFIX_COUNT = 0
|
||||
|
||||
# COMPRESSION
|
||||
COMPRESS_MIMETYPES = [
|
||||
'text/html', 'text/css', 'text/xml', 'application/json',
|
||||
'application/javascript'
|
||||
'text/html', 'text/css', 'text/xml', 'text/javascript',
|
||||
'application/json', 'application/javascript'
|
||||
]
|
||||
COMPRESS_LEVEL = 9
|
||||
COMPRESS_MIN_SIZE = 500
|
||||
@@ -414,10 +414,6 @@ SECURITY_EMAIL_SUBJECT_PASSWORD_CHANGE_NOTICE = \
|
||||
##########################################################################
|
||||
# Email address validation
|
||||
##########################################################################
|
||||
|
||||
# flask-security-too will validate email addresses and check deliverability
|
||||
# by default. Disable the deliverability check by default, which was the old
|
||||
# behaviour in <= v5.3
|
||||
CHECK_EMAIL_DELIVERABILITY = False
|
||||
SECURITY_EMAIL_VALIDATOR_ARGS = \
|
||||
{"check_deliverability": CHECK_EMAIL_DELIVERABILITY}
|
||||
@@ -477,14 +473,12 @@ STORAGE_DIR = os.path.join(DATA_DIR, 'storage')
|
||||
##########################################################################
|
||||
DEFAULT_BINARY_PATHS = {
|
||||
"pg": "",
|
||||
"pg-11": "",
|
||||
"pg-12": "",
|
||||
"pg-13": "",
|
||||
"pg-14": "",
|
||||
"pg-15": "",
|
||||
"pg-16": "",
|
||||
"ppas": "",
|
||||
"ppas-11": "",
|
||||
"ppas-12": "",
|
||||
"ppas-13": "",
|
||||
"ppas-14": "",
|
||||
@@ -793,6 +787,27 @@ OAUTH2_CONFIG = [
|
||||
'OAUTH2_ICON': None,
|
||||
# UI button colour, ex: #0000ff
|
||||
'OAUTH2_BUTTON_COLOR': None,
|
||||
# The additional claims to check on user ID Token or Userinfo response.
|
||||
# This is useful to provide additional authorization checks
|
||||
# before allowing access.
|
||||
# Example for GitLab: allowing all maintainers teams, and a specific
|
||||
# developers group to access pgadmin:
|
||||
# 'OAUTH2_ADDITIONAL_CLAIMS': {
|
||||
# 'https://gitlab.org/claims/groups/maintainer': [
|
||||
# 'kuberheads/applications',
|
||||
# 'kuberheads/dba',
|
||||
# 'kuberheads/support'
|
||||
# ],
|
||||
# 'https://gitlab.org/claims/groups/developer': [
|
||||
# 'kuberheads/applications/team01'
|
||||
# ],
|
||||
# }
|
||||
# Example for AzureAD:
|
||||
# 'OAUTH2_ADDITIONAL_CLAIMS': {
|
||||
# 'groups': ["0760b6cf-170e-4a14-91b3-4b78e0739963"],
|
||||
# 'wids': ["cf1c38e5-3621-4004-a7cb-879624dced7c"],
|
||||
# }
|
||||
'OAUTH2_ADDITIONAL_CLAIMS': None,
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
const webpackShimAlias = require('./webpack.shim').resolveAlias;
|
||||
|
||||
const webpackAliasToJestModules = ()=>{
|
||||
const ret = {
|
||||
'\\.svg': '<rootDir>/regression/javascript/__mocks__/svg.js'
|
||||
};
|
||||
Object.keys(webpackShimAlias).forEach((an)=>{
|
||||
// eg - sources: ./pgadmin/static/js/ to '^sources/(.*)$': '<rootDir>/pgadmin/static/js/$1'
|
||||
let ap = webpackShimAlias[an].replace(__dirname, '<rootDir>');
|
||||
if(ap.endsWith('/')) {
|
||||
ret[`^${an}/(.*)$`] = ap + '$1';
|
||||
return;
|
||||
}
|
||||
ret[`^${an}$`] = ap;
|
||||
});
|
||||
|
||||
// Overrides
|
||||
ret['^translations$'] = '<rootDir>/regression/javascript/fake_translations';
|
||||
ret['^pgadmin.browser.messages$'] = '<rootDir>/regression/javascript/fake_messages';
|
||||
ret['^pgadmin.browser.endpoints$'] = '<rootDir>/regression/javascript/fake_endpoints';
|
||||
ret['^pgadmin.browser.translations$'] = '<rootDir>/regression/javascript/fake_translations';
|
||||
ret['^pgadmin.user_management.current_user$'] = '<rootDir>/regression/javascript/fake_current_user';
|
||||
ret['^pgadmin.server.supported_servers$'] = '<rootDir>/regression/javascript/fake_supported_servers';
|
||||
|
||||
const sources = ret['^sources/(.*)$'];
|
||||
delete ret['^sources/(.*)$'];
|
||||
|
||||
ret['^sources/pgadmin$'] = '<rootDir>/regression/javascript/fake_pgadmin';
|
||||
ret['^sources/gettext$'] = '<rootDir>/regression/javascript/fake_gettext';
|
||||
ret['^sources/(.*)$'] = sources;
|
||||
|
||||
// Only for tests
|
||||
ret['^pgadmin.schema.dir/(.*)$'] = '<rootDir>/pgadmin/browser/server_groups/servers/databases/schemas/static/js/$1';
|
||||
ret['^browser/(.*)$'] = '<rootDir>/pgadmin/browser/static/js/$1';
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
'roots': ['<rootDir>/pgadmin/', '<rootDir>/regression/javascript'],
|
||||
'moduleFileExtensions': ['js', 'jsx', 'ts', 'tsx'],
|
||||
'moduleNameMapper': webpackAliasToJestModules(),
|
||||
'transform': {
|
||||
'^.+\\.(js|jsx|mjs|cjs|ts|tsx)$': 'babel-jest',
|
||||
},
|
||||
'setupFilesAfterEnv': [
|
||||
'<rootDir>/regression/javascript/setup-jest.js',
|
||||
],
|
||||
'testMatch': [
|
||||
'<rootDir>/regression/javascript/**/*{spec,test}.{js,jsx,ts,tsx}'
|
||||
],
|
||||
'testEnvironment': 'jsdom',
|
||||
'transformIgnorePatterns': [
|
||||
'[/\\\\]node_modules[/\\\\](?!react-dnd|dnd-core|@react-dnd).+\\.(js|jsx|mjs|cjs|ts|tsx)$',
|
||||
'^.+\\.module\\.(css|sass|scss)$'
|
||||
]
|
||||
};
|
||||
@@ -1,106 +0,0 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2023, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
// Karma configuration
|
||||
const webpackConfig = require('./webpack.test.config.js');
|
||||
const isDocker = require('is-docker')();
|
||||
const webpack = require('webpack');
|
||||
|
||||
module.exports = function (config) {
|
||||
config.set({
|
||||
frameworks: ['jasmine', 'source-map-support'],
|
||||
reporters: ['progress', 'kjhtml'],
|
||||
plugins: [
|
||||
'karma-webpack',
|
||||
'karma-chrome-launcher',
|
||||
'karma-jasmine',
|
||||
'karma-jasmine-html-reporter',
|
||||
'karma-source-map-support',
|
||||
'karma-sourcemap-loader',
|
||||
'karma-coverage',
|
||||
new webpack.SourceMapDevToolPlugin({
|
||||
/*
|
||||
* filename: null, // if no value is provided the sourcemap is inlined
|
||||
*/
|
||||
filename: '[name].js.map',
|
||||
test: /\.js$/i, // process .js files only
|
||||
}),
|
||||
],
|
||||
files: [
|
||||
{pattern: 'pgadmin/static/**/*.js', included: false, watched: true},
|
||||
{pattern: 'pgadmin/browser/static/js/**/*.js', included: false, watched: true},
|
||||
{pattern: 'regression/javascript/**/*.js', watched: true},
|
||||
],
|
||||
|
||||
// list of files to exclude
|
||||
exclude: [
|
||||
'pgadmin/static/vendor/**/*[Tt]est.js',
|
||||
'pgadmin/static/vendor/**/*[Ss]pec.js',
|
||||
],
|
||||
|
||||
// preprocess matching files before serving them to the browser
|
||||
// available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
|
||||
preprocessors: {
|
||||
'pgadmin/**/js/**/*.js?': ['sourcemap'],
|
||||
'regression/javascript/**/*.js': ['webpack', 'sourcemap'],
|
||||
},
|
||||
|
||||
// optionally, configure the reporter
|
||||
coverageReporter: {
|
||||
reporters: [
|
||||
// reporters not supporting the `file` property
|
||||
{ type: 'html', subdir: 'report-html' },
|
||||
{ type: 'lcovonly', subdir: 'report-lcov' },
|
||||
],
|
||||
dir : 'coverage/',
|
||||
includeAllSources: true,
|
||||
},
|
||||
|
||||
webpack: webpackConfig,
|
||||
webpackMiddleware: {
|
||||
stats: 'errors-only',
|
||||
},
|
||||
|
||||
port: 9876,
|
||||
|
||||
// enable / disable colors in the output (reporters and logs)
|
||||
colors: true,
|
||||
|
||||
// level of logging
|
||||
// possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
|
||||
logLevel: config.LOG_WARN,
|
||||
|
||||
|
||||
// enable / disable watching file and executing tests whenever any file changes
|
||||
autoWatch: true,
|
||||
usePolling: true,
|
||||
|
||||
|
||||
// start these browsers
|
||||
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
|
||||
customLaunchers: {
|
||||
ChromeCustom: {
|
||||
base: 'ChromeHeadless',
|
||||
// We must disable the Chrome sandbox when running Chrome inside Docker (Chrome's sandbox needs
|
||||
// more permissions than Docker allows by default)
|
||||
flags: isDocker ? ['--no-sandbox'] : [],
|
||||
},
|
||||
},
|
||||
browsers: ['ChromeCustom'],
|
||||
|
||||
|
||||
// Continuous Integration mode
|
||||
// if true, Karma captures browsers, runs the tests and exits
|
||||
singleRun: false,
|
||||
|
||||
// Concurrency level
|
||||
// how many browser should be started simultaneous
|
||||
concurrency: Infinity,
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,39 @@
|
||||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2023, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
"""Update DB to version 38
|
||||
|
||||
Removed max length from passexec_cmd column of server configuration.
|
||||
|
||||
Revision ID: 44926ac97232
|
||||
Revises: 44b9ce549393
|
||||
Create Date: 2023-11-03 19:56:51.277160
|
||||
|
||||
"""
|
||||
import sqlalchemy as sa
|
||||
from alembic import op
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '44926ac97232'
|
||||
down_revision = '44b9ce549393'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
with op.batch_alter_table("server") as batch_op:
|
||||
batch_op.alter_column('passexec_cmd',
|
||||
existing_type=sa.String(length=256),
|
||||
type_=sa.String())
|
||||
# ### end Alembic commands ###
|
||||
|
||||
|
||||
def downgrade():
|
||||
# pgAdmin only upgrades, downgrade not implemented.
|
||||
pass
|
||||
@@ -0,0 +1,54 @@
|
||||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2023, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
"""Add support for prepare_threshold param
|
||||
https://www.psycopg.org/psycopg3/docs/advanced/prepare.html#prepared-statements
|
||||
|
||||
Revision ID: 44b9ce549393
|
||||
Revises: 9426ad06a63b
|
||||
Create Date: 2023-10-12 12:15:01.757931
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '44b9ce549393'
|
||||
down_revision = '9426ad06a63b'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
with op.batch_alter_table(
|
||||
"server", table_kwargs={'sqlite_autoincrement': True}) as batch_op:
|
||||
batch_op.add_column(sa.Column('prepare_threshold', sa.Integer(),
|
||||
nullable=True))
|
||||
|
||||
with op.batch_alter_table("sharedserver") as batch_op:
|
||||
batch_op.add_column(sa.Column('prepare_threshold', sa.Integer(),
|
||||
nullable=True))
|
||||
|
||||
# get metadata from current connection
|
||||
meta = sa.MetaData()
|
||||
# define table representation
|
||||
meta.reflect(op.get_bind(), only=('server', 'sharedserver'))
|
||||
table = sa.Table('server', meta)
|
||||
op.execute(
|
||||
table.update().values(prepare_threshold=5)
|
||||
)
|
||||
table = sa.Table('sharedserver', meta)
|
||||
op.execute(
|
||||
table.update().values(prepare_threshold=5)
|
||||
)
|
||||
|
||||
def downgrade():
|
||||
# pgAdmin only upgrades, downgrade not implemented.
|
||||
pass
|
||||
@@ -0,0 +1,41 @@
|
||||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2023, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
""" Add the new column for shared server username and change
|
||||
autoincrement in server table
|
||||
Revision ID: 9426ad06a63b
|
||||
Revises: f656e56dfdc8
|
||||
Create Date: 2023-10-09 15:09:50.773035
|
||||
"""
|
||||
from alembic import op, context
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '9426ad06a63b'
|
||||
down_revision = 'f656e56dfdc8'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
# Added sqlite_autoincrement to force sqlite use auto increment instead of
|
||||
# last row id for next record. For future server table changes, we need to
|
||||
# add table_kwargs={'sqlite_autoincrement': True} as a param to
|
||||
# batch_alter_table
|
||||
with op.batch_alter_table(
|
||||
"server", table_kwargs={'sqlite_autoincrement': True}) as batch_op:
|
||||
if context.get_impl().bind.dialect.name == "sqlite":
|
||||
batch_op.alter_column('id', autoincrement=True)
|
||||
batch_op.add_column(sa.Column('shared_username', sa.String(64), nullable=True))
|
||||
|
||||
|
||||
def downgrade():
|
||||
# pgAdmin only upgrades, downgrade not implemented.
|
||||
pass
|
||||
@@ -12,6 +12,7 @@
|
||||
"@babel/eslint-plugin": "^7.17.7",
|
||||
"@babel/plugin-proposal-object-rest-spread": "^7.10.1",
|
||||
"@babel/plugin-syntax-jsx": "^7.16.0",
|
||||
"@babel/plugin-transform-runtime": "^7.22.15",
|
||||
"@babel/preset-env": "^7.10.2",
|
||||
"@babel/preset-typescript": "^7.22.5",
|
||||
"@emotion/core": "^10.0.14",
|
||||
@@ -19,46 +20,36 @@
|
||||
"@emotion/react": "^11.1.5",
|
||||
"@emotion/styled": "^11.11.0",
|
||||
"@emotion/utils": "^1.0.0",
|
||||
"@svgr/webpack": "^6.2.1",
|
||||
"@svgr/webpack": "^8.1.0",
|
||||
"@testing-library/jest-dom": "^6.1.2",
|
||||
"@testing-library/react": "12",
|
||||
"@testing-library/user-event": "^14.4.3",
|
||||
"@types/jest": "^29.5.4",
|
||||
"@typescript-eslint/eslint-plugin": "^5.59.9",
|
||||
"@typescript-eslint/parser": "^5.57.0",
|
||||
"@wojtekmaj/enzyme-adapter-react-17": "^0.8.0",
|
||||
"autoprefixer": "^10.2.4",
|
||||
"axios-mock-adapter": "^1.17.0",
|
||||
"babel-loader": "^8.1.0",
|
||||
"browserify": "^17.0.0",
|
||||
"buffer": "^6.0.3",
|
||||
"copy-webpack-plugin": "^11.0.0",
|
||||
"core-js": "^3.2.1",
|
||||
"cross-env": "^7.0.3",
|
||||
"css-loader": "^6.7.2",
|
||||
"css-minimizer-webpack-plugin": "^5.0.0",
|
||||
"enzyme": "^3.11.0",
|
||||
"eslint": "^8.37.0",
|
||||
"eslint-plugin-react": "^7.32.2",
|
||||
"eslint-plugin-jest": "^27.4.0",
|
||||
"eslint-plugin-react": "^7.33.2",
|
||||
"eslint-plugin-react-hooks": "^4.3.0",
|
||||
"exports-loader": "^4.0.0",
|
||||
"html-react-parser": "^4.2.0",
|
||||
"html-react-parser": "^4.2.2",
|
||||
"image-minimizer-webpack-plugin": "^3.8.2",
|
||||
"imagemin": "^8.0.1",
|
||||
"imagemin-mozjpeg": "^10.0.0",
|
||||
"imagemin-optipng": "^8.0.0",
|
||||
"imagemin-pngquant": "^9.0.2",
|
||||
"imports-loader": "^4.0.1",
|
||||
"is-docker": "^2.1.1",
|
||||
"istanbul-instrumenter-loader": "^3.0.1",
|
||||
"jasmine-core": "3.10.1",
|
||||
"jasmine-enzyme": "^7.1.2",
|
||||
"karma": "^6.3.15",
|
||||
"karma-babel-preprocessor": "^8.0.0",
|
||||
"karma-browserify": "^8.0.0",
|
||||
"karma-chrome-launcher": "^3.1.0",
|
||||
"karma-jasmine": "^4.0.1",
|
||||
"karma-jasmine-html-reporter": "^1.4.0",
|
||||
"karma-requirejs": "~1.1.0",
|
||||
"karma-source-map-support": "^1.4.0",
|
||||
"karma-sourcemap-loader": "^0.4.0",
|
||||
"karma-webpack": "^5.0.0",
|
||||
"jest": "^29.6.4",
|
||||
"jest-environment-jsdom": "^29.6.4",
|
||||
"loader-utils": "^3.2.1",
|
||||
"mini-css-extract-plugin": "^2.7.6",
|
||||
"postcss-loader": "^7.1.0",
|
||||
@@ -77,7 +68,7 @@
|
||||
"typescript": "^3.2.2",
|
||||
"url-loader": "^4.1.1",
|
||||
"webfonts-loader": "^8.0.1",
|
||||
"webpack": "^5.76.3",
|
||||
"webpack": "^5.88.2",
|
||||
"webpack-bundle-analyzer": "^4.8.0",
|
||||
"webpack-cli": "^4.5.0",
|
||||
"yarn-audit-html": "4.0.0"
|
||||
@@ -88,6 +79,7 @@
|
||||
"@date-io/core": "^1.3.6",
|
||||
"@date-io/date-fns": "1.x",
|
||||
"@emotion/sheet": "^1.0.1",
|
||||
"@fortawesome/fontawesome-free": "latest",
|
||||
"@material-ui/core": "4.12.4",
|
||||
"@material-ui/icons": "^4.11.2",
|
||||
"@material-ui/lab": "4.0.0-alpha.61",
|
||||
@@ -104,7 +96,6 @@
|
||||
"axios": "^1.4.0",
|
||||
"babelify": "~10.0.0",
|
||||
"bignumber.js": "^9.0.1",
|
||||
"bootstrap": "^4.3.1",
|
||||
"brace": "^0.11.1",
|
||||
"browserfs": "^1.4.3",
|
||||
"chart.js": "^3.0.0",
|
||||
@@ -117,15 +108,12 @@
|
||||
"dagre": "^0.8.4",
|
||||
"date-fns": "^2.24.0",
|
||||
"diff-arrays-of-objects": "^1.1.8",
|
||||
"html2canvas": "^1.0.0-rc.7",
|
||||
"html-to-image": "^1.11.11",
|
||||
"immutability-helper": "^3.0.0",
|
||||
"insert-if": "^1.1.0",
|
||||
"ip-address": "^7.1.0",
|
||||
"jquery": "^3.6.0",
|
||||
"jquery-contextmenu": "^2.9.2",
|
||||
"json-bignumber": "^1.0.1",
|
||||
"jsoneditor": "^9.5.4",
|
||||
"karma-coverage": "^2.0.3",
|
||||
"leaflet": "^1.5.1",
|
||||
"lodash": "4.*",
|
||||
"ml-matrix": "^6.5.0",
|
||||
@@ -138,22 +126,24 @@
|
||||
"pathfinding": "^0.4.18",
|
||||
"paths-js": "^0.4.9",
|
||||
"popper.js": "^1.16.1",
|
||||
"postcss": "^8.2.15",
|
||||
"postcss": "^8.4.31",
|
||||
"raf": "^3.4.1",
|
||||
"rc-dock": "^3.2.9",
|
||||
"react": "^17.0.1",
|
||||
"react-arborist": "^3.2.0",
|
||||
"react-aspen": "^1.1.0",
|
||||
"react-checkbox-tree": "^1.7.2",
|
||||
"react-data-grid": "https://github.com/pgadmin-org/react-data-grid.git#200d2f5e02de694e3e9ffbe177c279bc40240fb8",
|
||||
"react-dnd": "^16.0.1",
|
||||
"react-dnd-html5-backend": "^16.0.1",
|
||||
"react-dom": "^17.0.1",
|
||||
"react-draggable": "^4.4.4",
|
||||
"react-draggable": "^4.4.6",
|
||||
"react-dropzone": "^14.2.1",
|
||||
"react-frame-component": "^5.2.6",
|
||||
"react-leaflet": "^3.2.2",
|
||||
"react-new-window": "^1.0.1",
|
||||
"react-resize-detector": "^9.1.0",
|
||||
"react-rnd": "^10.3.5",
|
||||
"react-router-dom": "^6.2.2",
|
||||
"react-select": "^5.7.2",
|
||||
"react-table": "^7.6.3",
|
||||
"react-timer-hook": "^3.0.5",
|
||||
@@ -163,16 +153,15 @@
|
||||
"socket.io-client": "^4.5.0",
|
||||
"split.js": "^1.5.10",
|
||||
"styled-components": "^5.2.1",
|
||||
"tempusdominus-core": "^5.19.3",
|
||||
"uplot": "^1.6.24",
|
||||
"uplot-react": "^1.1.4",
|
||||
"valid-filename": "^2.0.1",
|
||||
"webcabin-docker": "https://github.com/pgadmin-org/wcdocker#460fc6d90ba170bb177faaa8277f5fbb8279522a",
|
||||
"wkx": "^0.5.0",
|
||||
"xterm": "^4.11.0",
|
||||
"xterm-addon-fit": "^0.5.0",
|
||||
"xterm-addon-search": "^0.8.0",
|
||||
"xterm-addon-web-links": "^0.4.0"
|
||||
"xterm-addon-web-links": "^0.4.0",
|
||||
"zustand": "^4.4.1"
|
||||
},
|
||||
"scripts": {
|
||||
"linter": "yarn eslint --no-eslintrc -c .eslintrc.js --ext .js --ext .jsx --ext .ts --ext .tsx .",
|
||||
@@ -181,17 +170,17 @@
|
||||
"bundle:watch": "yarn run linter && yarn run webpacker:watch",
|
||||
"bundle:dev": "yarn run linter && yarn run webpacker",
|
||||
"bundle:analyze": "cross-env NODE_ENV=production ANALYZE=true yarn run bundle:dev",
|
||||
"bundle": "cross-env NODE_ENV=production NODE_OPTIONS=--max-old-space-size=3072 yarn run bundle:dev",
|
||||
"test:karma-once": "yarn run linter && yarn run karma start --single-run",
|
||||
"test:karma": "yarn run linter && yarn run karma start",
|
||||
"test:karma-coverage": "yarn run test:karma-once --reporters coverage,progress",
|
||||
"bundle": "cross-env NODE_ENV=production NODE_OPTIONS=--max-old-space-size=2048 yarn run bundle:dev",
|
||||
"test:js-once": "yarn run linter && yarn run jest --maxWorkers=50%",
|
||||
"test:js": "yarn run test:js-once --watch",
|
||||
"test:js-coverage": "yarn run test:js-once --collect-coverage",
|
||||
"test:feature": "yarn run bundle && python regression/runtests.py --pkg feature_tests",
|
||||
"test": "yarn run test:karma-once && yarn run bundle && python regression/runtests.py",
|
||||
"test": "yarn run test:js-once && yarn run bundle && python regression/runtests.py",
|
||||
"pep8": "pycodestyle --config=../.pycodestyle ../docs && pycodestyle --config=../.pycodestyle ../pkg && pycodestyle --config=../.pycodestyle ../tools && pycodestyle --config=../.pycodestyle ../web",
|
||||
"auditjs-html": "yarn audit --json | yarn run yarn-audit-html --output ../auditjs.html",
|
||||
"auditjs": "yarn audit --groups dependencies",
|
||||
"auditpy": "safety check --full-report -i 51668 -i 52495",
|
||||
"audit": "yarn run auditjs && yarn run auditpy"
|
||||
},
|
||||
"packageManager": "yarn@3.5.0"
|
||||
"packageManager": "yarn@3.6.4"
|
||||
}
|
||||
@@ -152,6 +152,8 @@ else:
|
||||
if not app.PGADMIN_RUNTIME:
|
||||
app.wsgi_app = ReverseProxied(app.wsgi_app)
|
||||
|
||||
app.run_before_app_start()
|
||||
|
||||
|
||||
##########################################################################
|
||||
# The entry point
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
|
||||
class AbsProvider:
|
||||
""" Abstract provider """
|
||||
parser = None
|
||||
|
||||
@@ -24,7 +24,7 @@ import sys
|
||||
CURRENT_PATH = os.path.dirname(os.path.realpath(__file__))
|
||||
root = os.path.dirname(os.path.dirname(CURRENT_PATH))
|
||||
sys.path.insert(0, root)
|
||||
from pgadmin.misc.cloud.azure.azure_cache import load_persistent_cache, \
|
||||
from utils.azure_cache import load_persistent_cache, \
|
||||
TokenCachePersistenceOptions
|
||||
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ from flask_mail import Mail
|
||||
from flask_paranoid import Paranoid
|
||||
from flask_security import Security, SQLAlchemyUserDatastore, current_user
|
||||
from flask_security.utils import login_user, logout_user
|
||||
from flask_migrate import Migrate
|
||||
from werkzeug.datastructures import ImmutableDict
|
||||
from werkzeug.local import LocalProxy
|
||||
from werkzeug.utils import find_modules
|
||||
@@ -79,6 +80,7 @@ class PgAdmin(Flask):
|
||||
loader=VersionedTemplateLoader(self)
|
||||
)
|
||||
self.logout_hooks = []
|
||||
self.before_app_start = []
|
||||
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
@@ -105,13 +107,6 @@ class PgAdmin(Flask):
|
||||
if isinstance(blueprint, PgAdminModule):
|
||||
yield blueprint
|
||||
|
||||
@property
|
||||
def stylesheets(self):
|
||||
stylesheets = []
|
||||
for module in self.submodules:
|
||||
stylesheets.extend(getattr(module, "stylesheets", []))
|
||||
return set(stylesheets)
|
||||
|
||||
@property
|
||||
def messages(self):
|
||||
messages = dict()
|
||||
@@ -150,28 +145,6 @@ class PgAdmin(Flask):
|
||||
|
||||
yield 'pgadmin.root', wsgi_root_path
|
||||
|
||||
@property
|
||||
def javascripts(self):
|
||||
scripts = []
|
||||
scripts_names = []
|
||||
|
||||
# Remove duplicate javascripts from the list
|
||||
for module in self.submodules:
|
||||
module_scripts = getattr(module, "javascripts", [])
|
||||
for s in module_scripts:
|
||||
if s['name'] not in scripts_names:
|
||||
scripts.append(s)
|
||||
scripts_names.append(s['name'])
|
||||
|
||||
return scripts
|
||||
|
||||
@property
|
||||
def panels(self):
|
||||
panels = []
|
||||
for module in self.submodules:
|
||||
panels.extend(module.get_panels())
|
||||
return panels
|
||||
|
||||
@property
|
||||
def menu_items(self):
|
||||
from operator import attrgetter
|
||||
@@ -189,6 +162,15 @@ class PgAdmin(Flask):
|
||||
isinstance(getattr(module, 'on_logout'), MethodType):
|
||||
self.logout_hooks.append(module)
|
||||
|
||||
def register_before_app_start(self, callback):
|
||||
self.before_app_start.append(callback)
|
||||
|
||||
def run_before_app_start(self):
|
||||
# call before app starts or is exported
|
||||
with self.app_context(), self.test_request_context():
|
||||
for callback in self.before_app_start:
|
||||
callback()
|
||||
|
||||
|
||||
def _find_blueprint():
|
||||
if request.blueprint:
|
||||
@@ -355,6 +337,7 @@ def create_app(app_name=None):
|
||||
|
||||
# Create database connection object and mailer
|
||||
db.init_app(app)
|
||||
Migrate(app, db)
|
||||
|
||||
##########################################################################
|
||||
# Upgrade the schema (if required)
|
||||
|
||||
@@ -59,46 +59,50 @@ def index():
|
||||
info = {}
|
||||
# Get OS , NW.js, Browser details
|
||||
browser, os_details, nwjs_version = detect_browser(request)
|
||||
admin = is_admin(current_user.email)
|
||||
|
||||
if nwjs_version:
|
||||
info['nwjs'] = nwjs_version
|
||||
|
||||
info['browser_details'] = browser
|
||||
info['os_details'] = os_details
|
||||
info['config_db'] = config.SQLITE_PATH
|
||||
info['log_file'] = config.LOG_FILE
|
||||
info['version'] = config.APP_VERSION
|
||||
|
||||
if config.SERVER_MODE:
|
||||
info['app_mode'] = gettext('Server')
|
||||
admin = is_admin(current_user.email)
|
||||
info['admin'] = admin
|
||||
else:
|
||||
info['app_mode'] = gettext('Desktop')
|
||||
|
||||
info['browser_details'] = browser
|
||||
info['version'] = config.APP_VERSION
|
||||
info['admin'] = admin
|
||||
info['current_user'] = current_user.email
|
||||
|
||||
settings = ""
|
||||
for setting in dir(config):
|
||||
if not setting.startswith('_') and setting.isupper() and \
|
||||
setting not in ['CSRF_SESSION_KEY',
|
||||
'SECRET_KEY',
|
||||
'SECURITY_PASSWORD_SALT',
|
||||
'SECURITY_PASSWORD_HASH',
|
||||
'ALLOWED_HOSTS',
|
||||
'MAIL_PASSWORD',
|
||||
'LDAP_BIND_PASSWORD',
|
||||
'SECURITY_PASSWORD_HASH']:
|
||||
if isinstance(getattr(config, setting), str):
|
||||
settings = \
|
||||
settings + '{} = "{}"\n'.format(
|
||||
setting, getattr(config, setting))
|
||||
else:
|
||||
settings = \
|
||||
settings + '{} = {}\n'.format(
|
||||
setting, getattr(config, setting))
|
||||
if admin:
|
||||
settings = ""
|
||||
info['os_details'] = os_details
|
||||
info['log_file'] = config.LOG_FILE
|
||||
|
||||
info['settings'] = settings
|
||||
# If external datbase is used do not display SQLITE_PATH
|
||||
if not config.CONFIG_DATABASE_URI:
|
||||
info['config_db'] = config.SQLITE_PATH
|
||||
|
||||
for setting in dir(config):
|
||||
if not setting.startswith('_') and setting.isupper() and \
|
||||
setting not in ['CSRF_SESSION_KEY',
|
||||
'SECRET_KEY',
|
||||
'SECURITY_PASSWORD_SALT',
|
||||
'SECURITY_PASSWORD_HASH',
|
||||
'ALLOWED_HOSTS',
|
||||
'MAIL_PASSWORD',
|
||||
'LDAP_BIND_PASSWORD',
|
||||
'SECURITY_PASSWORD_HASH']:
|
||||
if isinstance(getattr(config, setting), str):
|
||||
settings = \
|
||||
settings + '{} = "{}"\n'.format(
|
||||
setting, getattr(config, setting))
|
||||
else:
|
||||
settings = \
|
||||
settings + '{} = {}\n'.format(
|
||||
setting, getattr(config, setting))
|
||||
|
||||
info['settings'] = settings
|
||||
|
||||
return make_json_response(
|
||||
data=info,
|
||||
|
||||
@@ -17,8 +17,8 @@ import { makeStyles } from '@material-ui/styles';
|
||||
import { InputText } from '../../../static/js/components/FormComponents';
|
||||
import getApiInstance from '../../../static/js/api_instance';
|
||||
import { copyToClipboard } from '../../../static/js/clipboard';
|
||||
import Notify from '../../../static/js/helpers/Notifier';
|
||||
import { useDelayedCaller } from '../../../static/js/custom_hooks';
|
||||
import { usePgAdmin } from '../../../static/js/BrowserComponent';
|
||||
|
||||
|
||||
const useStyles = makeStyles((theme)=>({
|
||||
@@ -44,6 +44,7 @@ export default function AboutComponent() {
|
||||
const revertCopiedText = useDelayedCaller(()=>{
|
||||
setCopyText(gettext('Copy'));
|
||||
});
|
||||
const pgAdmin = usePgAdmin();
|
||||
|
||||
useEffect(() => {
|
||||
const about_url = url_for('about.index');
|
||||
@@ -52,7 +53,7 @@ export default function AboutComponent() {
|
||||
api.get(about_url).then((res)=>{
|
||||
setAboutData(res.data.data);
|
||||
}).catch((err)=>{
|
||||
Notify.error(err);
|
||||
pgAdmin.Browser.notifier.error(err);
|
||||
});
|
||||
}, []);
|
||||
|
||||
@@ -100,32 +101,37 @@ export default function AboutComponent() {
|
||||
<InputLabel>{aboutData.browser_details}</InputLabel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid container spacing={0} style={{marginBottom: '8px'}}>
|
||||
<Grid item lg={3} md={3} sm={3} xs={12}>
|
||||
<InputLabel style={{fontWeight: 'bold'}}>{gettext('Operating System')}</InputLabel>
|
||||
{ aboutData.os_details &&
|
||||
<Grid container spacing={0} style={{marginBottom: '8px'}}>
|
||||
<Grid item lg={3} md={3} sm={3} xs={12}>
|
||||
<InputLabel style={{fontWeight: 'bold'}}>{gettext('Operating System')}</InputLabel>
|
||||
</Grid>
|
||||
<Grid item lg={9} md={9} sm={9} xs={12}>
|
||||
<InputLabel>{aboutData.os_details}</InputLabel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item lg={9} md={9} sm={9} xs={12}>
|
||||
<InputLabel>{aboutData.os_details}</InputLabel>
|
||||
}
|
||||
{ aboutData.config_db &&
|
||||
<Grid container spacing={0} style={{marginBottom: '8px'}}>
|
||||
<Grid item lg={3} md={3} sm={3} xs={12}>
|
||||
<InputLabel style={{fontWeight: 'bold'}}>{gettext('pgAdmin Database File')}</InputLabel>
|
||||
</Grid>
|
||||
<Grid item lg={9} md={9} sm={9} xs={12}>
|
||||
<InputLabel>{aboutData.config_db}</InputLabel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid container spacing={0} style={{marginBottom: '8px'}}>
|
||||
<Grid item lg={3} md={3} sm={3} xs={12}>
|
||||
<InputLabel style={{fontWeight: 'bold'}}>{gettext('pgAdmin Database File')}</InputLabel>
|
||||
}
|
||||
{ aboutData.log_file &&
|
||||
<Grid container spacing={0} style={{marginBottom: '8px'}}>
|
||||
<Grid item lg={3} md={3} sm={3} xs={12}>
|
||||
<InputLabel style={{fontWeight: 'bold'}}>{gettext('Log File')}</InputLabel>
|
||||
</Grid>
|
||||
<Grid item lg={9} md={9} sm={9} xs={12}>
|
||||
<InputLabel>{aboutData.log_file}</InputLabel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item lg={9} md={9} sm={9} xs={12}>
|
||||
<InputLabel>{aboutData.config_db}</InputLabel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid container spacing={0} style={{marginBottom: '8px'}}>
|
||||
<Grid item lg={3} md={3} sm={3} xs={12}>
|
||||
<InputLabel style={{fontWeight: 'bold'}}>{gettext('Log File')}</InputLabel>
|
||||
</Grid>
|
||||
<Grid item lg={9} md={9} sm={9} xs={12}>
|
||||
<InputLabel>{aboutData.log_file}</InputLabel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
{ (aboutData.app_mode == 'Desktop' || (aboutData.app_mode == 'Server' && aboutData.admin)) &&
|
||||
<>
|
||||
}
|
||||
{ aboutData.settings &&
|
||||
<Box flexGrow="1" display="flex" flexDirection="column">
|
||||
<Box>
|
||||
<span style={{fontWeight: 'bold'}}>{gettext('Server Configuration')}</span>
|
||||
@@ -140,7 +146,6 @@ export default function AboutComponent() {
|
||||
value={aboutData.settings}/>
|
||||
</Box>
|
||||
</Box>
|
||||
</>
|
||||
}
|
||||
</Box>
|
||||
);
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
|
||||
import React from 'react';
|
||||
import gettext from 'sources/gettext';
|
||||
import Notify from '../../../static/js/helpers/Notifier';
|
||||
import pgAdmin from 'sources/pgadmin';
|
||||
import AboutComponent from './AboutComponent';
|
||||
import current_user from 'pgadmin.user_management.current_user';
|
||||
@@ -41,9 +40,9 @@ class About {
|
||||
}
|
||||
|
||||
// Render About component
|
||||
Notify.showModal(gettext('About %s', pgAdmin.Browser.utils.app_name), () => {
|
||||
pgAdmin.Browser.notifier.showModal(gettext('About %s', pgAdmin.Browser.utils.app_name), () => {
|
||||
return <AboutComponent />;
|
||||
}, { isFullScreen: false, isResizeable: true, showFullScreen: true,
|
||||
}, { isFullScreen: false, isResizeable: true, showFullScreen: true,
|
||||
isFullWidth: true, dialogWidth: dlgWidth, dialogHeight: dlgHeight, minHeight: dlgHeight
|
||||
});
|
||||
}
|
||||
@@ -53,4 +52,4 @@ pgAdmin.About = About.getInstance();
|
||||
|
||||
module.exports = {
|
||||
About: About,
|
||||
};
|
||||
};
|
||||
@@ -18,15 +18,15 @@ from flask import current_app, flash, Response, request, url_for, \
|
||||
session, redirect, render_template
|
||||
from flask_babel import gettext
|
||||
from flask_security.views import _security, _ctx
|
||||
from flask_security.utils import get_post_logout_redirect, logout_user,\
|
||||
config_value
|
||||
from flask_security.utils import logout_user, config_value
|
||||
|
||||
from flask_login import current_user
|
||||
from flask_socketio import disconnect, ConnectionRefusedError
|
||||
|
||||
|
||||
from pgadmin.model import db, User
|
||||
from pgadmin.utils import PgAdminModule, get_safe_post_login_redirect
|
||||
from pgadmin.utils import PgAdminModule, get_safe_post_login_redirect, \
|
||||
get_safe_post_logout_redirect
|
||||
from pgadmin.utils.constants import KERBEROS, INTERNAL, OAUTH2, LDAP,\
|
||||
MessageType
|
||||
from pgadmin.authenticate.registry import AuthSourceRegistry
|
||||
@@ -135,7 +135,7 @@ def _login():
|
||||
'Administrator.'),
|
||||
MessageType.WARNING)
|
||||
logout_user()
|
||||
return redirect(get_post_logout_redirect())
|
||||
return redirect(get_safe_post_logout_redirect())
|
||||
|
||||
# Validate the user
|
||||
if not auth_obj.validate():
|
||||
@@ -161,7 +161,7 @@ def _login():
|
||||
flash_login_attempt_error = None
|
||||
flash(error, MessageType.WARNING)
|
||||
|
||||
return redirect(get_post_logout_redirect())
|
||||
return redirect(get_safe_post_logout_redirect())
|
||||
|
||||
# Authenticate the user
|
||||
status, msg = auth_obj.authenticate()
|
||||
@@ -177,7 +177,7 @@ def _login():
|
||||
'authenticate.kerberos_login'), url_for('browser.index')))
|
||||
|
||||
flash(msg, MessageType.ERROR)
|
||||
return redirect(get_post_logout_redirect())
|
||||
return redirect(get_safe_post_logout_redirect())
|
||||
|
||||
session['auth_source_manager'] = current_auth_obj
|
||||
|
||||
|
||||
@@ -154,7 +154,7 @@ class TOTPAuthenticator(BaseMFAuth):
|
||||
|
||||
img = qrcode.make(uri)
|
||||
buffered = BytesIO()
|
||||
img.save(buffered, format="JPEG")
|
||||
img.save(buffered)
|
||||
img_base64 = base64.b64encode(buffered.getvalue())
|
||||
|
||||
return dict(
|
||||
|
||||
@@ -16,13 +16,14 @@ from flask import current_app, url_for, session, request,\
|
||||
redirect, Flask, flash
|
||||
from flask_babel import gettext
|
||||
from flask_security import login_user, current_user
|
||||
from flask_security.utils import get_post_logout_redirect, logout_user
|
||||
from flask_security.utils import logout_user
|
||||
|
||||
from pgadmin.authenticate.internal import BaseAuthentication
|
||||
from pgadmin.model import User
|
||||
from pgadmin.tools.user_management import create_user
|
||||
from pgadmin.utils.constants import OAUTH2, MessageType
|
||||
from pgadmin.utils import PgAdminModule, get_safe_post_login_redirect
|
||||
from pgadmin.utils import PgAdminModule, get_safe_post_login_redirect, \
|
||||
get_safe_post_logout_redirect
|
||||
from pgadmin.utils.csrf import pgCSRFProtect
|
||||
from pgadmin.model import db
|
||||
|
||||
@@ -69,11 +70,11 @@ def init_app(app):
|
||||
@pgCSRFProtect.exempt
|
||||
def oauth_logout():
|
||||
if not current_user.is_authenticated:
|
||||
return redirect(get_post_logout_redirect())
|
||||
return redirect(get_safe_post_logout_redirect())
|
||||
for key in list(session.keys()):
|
||||
session.pop(key)
|
||||
logout_user()
|
||||
return redirect(get_post_logout_redirect())
|
||||
return redirect(get_safe_post_logout_redirect())
|
||||
|
||||
app.register_blueprint(blueprint)
|
||||
app.login_manager.logout_view = OAUTH2_LOGOUT
|
||||
@@ -150,6 +151,38 @@ class OAuth2Authentication(BaseAuthentication):
|
||||
current_app.logger.exception(error_msg)
|
||||
return False, gettext(error_msg)
|
||||
|
||||
additinal_claims = None
|
||||
if 'OAUTH2_ADDITIONAL_CLAIMS' in self.oauth2_config[
|
||||
self.oauth2_current_client]:
|
||||
|
||||
additinal_claims = self.oauth2_config[
|
||||
self.oauth2_current_client
|
||||
]['OAUTH2_ADDITIONAL_CLAIMS']
|
||||
|
||||
# checking oauth provider userinfo response
|
||||
valid_profile, reason = self.__is_any_claim_valid(profile,
|
||||
additinal_claims)
|
||||
current_app.logger.debug(f"profile claims: {profile}")
|
||||
current_app.logger.debug(f"reason: {reason}")
|
||||
|
||||
# checking oauth provider idtoken claims
|
||||
id_token_claims = session.get('oauth2_token', {}).get('userinfo',{})
|
||||
valid_idtoken, reason = self.__is_any_claim_valid(id_token_claims,
|
||||
additinal_claims)
|
||||
current_app.logger.debug(f"idtoken claims: {id_token_claims}")
|
||||
current_app.logger.debug(f"reason: {reason}")
|
||||
|
||||
if not valid_profile and not valid_idtoken:
|
||||
return_msg = "The user is not authorized to login" \
|
||||
" based on your identity profile." \
|
||||
" Please contact your administrator."
|
||||
audit_msg = f"The authenticated user {username} is not" \
|
||||
" authorized to access pgAdmin based on OAUTH2 config. " \
|
||||
f"Reason: additional claim required {additinal_claims}, " \
|
||||
f"profile claims {profile}, idtoken cliams {id_token_claims}."
|
||||
current_app.logger.warning(audit_msg)
|
||||
return False, return_msg
|
||||
|
||||
user, msg = self.__auto_create_user(username, email)
|
||||
if user:
|
||||
user = db.session.query(User).filter_by(
|
||||
@@ -203,3 +236,28 @@ class OAuth2Authentication(BaseAuthentication):
|
||||
})
|
||||
|
||||
return True, {'username': username}
|
||||
|
||||
def __is_any_claim_valid(self, identity, additional_claims):
|
||||
if additional_claims is None:
|
||||
reason = "Additional claim config is None, no check to do."
|
||||
return (True, reason)
|
||||
if not isinstance(additional_claims, dict):
|
||||
reason = "Additional claim check config is not a dict."
|
||||
return (False, reason)
|
||||
if additional_claims.keys() is None:
|
||||
reason = "Additional claim check config dict is empty."
|
||||
return (False, reason)
|
||||
for key in additional_claims.keys():
|
||||
claim = identity.get(key)
|
||||
if claim is None:
|
||||
continue
|
||||
if not isinstance(claim, list):
|
||||
claim = [claim]
|
||||
authorized_claims = additional_claims.get(key)
|
||||
if not isinstance(authorized_claims, list):
|
||||
authorized_claims = [authorized_claims]
|
||||
if any(item in authorized_claims for item in claim):
|
||||
reason = "Claim match found. Authorized access."
|
||||
return (True, reason)
|
||||
reason = f"No match was found."
|
||||
return (False, reason)
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
import url_for from 'sources/url_for';
|
||||
import userInfo from 'pgadmin.user_management.current_user';
|
||||
import pgConst from 'pgadmin.browser.constants';
|
||||
import {AUTH_METHODS} from 'pgadmin.browser.constants';
|
||||
|
||||
function fetch_ticket() {
|
||||
// Fetch the Kerberos Updated ticket through SPNEGO
|
||||
@@ -52,7 +52,7 @@ function fetch_ticket_lifetime () {
|
||||
function validate_kerberos_ticket() {
|
||||
// Ping pgAdmin server every 10 seconds
|
||||
// to fetch the Kerberos ticket lifetime left
|
||||
if (userInfo['current_auth_source'] != pgConst['KERBEROS']) return;
|
||||
if (userInfo['current_auth_source'] != AUTH_METHODS['KERBEROS']) return;
|
||||
|
||||
return setInterval(function() {
|
||||
let newPromise = fetch_ticket_lifetime();
|
||||
|
||||
@@ -30,13 +30,13 @@ from flask_babel import gettext
|
||||
from flask_gravatar import Gravatar
|
||||
from flask_login import current_user, login_required
|
||||
from flask_login.utils import login_url
|
||||
from flask_security.changeable import change_user_password
|
||||
from flask_security.changeable import send_password_changed_notice
|
||||
from flask_security.decorators import anonymous_user_required
|
||||
from flask_security.recoverable import reset_password_token_status, \
|
||||
generate_reset_password_token, update_password
|
||||
from flask_security.signals import reset_password_instructions_sent
|
||||
from flask_security.utils import config_value, do_flash, get_url, \
|
||||
get_message, slash_url_suffix, login_user, send_mail, \
|
||||
get_message, slash_url_suffix, login_user, send_mail, hash_password, \
|
||||
get_post_logout_redirect
|
||||
from flask_security.views import _security, view_commit, _ctx
|
||||
from werkzeug.datastructures import MultiDict
|
||||
@@ -88,61 +88,6 @@ PASS_ERROR = gettext('Error: {error}\n {pass_error}').format(
|
||||
class BrowserModule(PgAdminModule):
|
||||
LABEL = gettext('Browser')
|
||||
|
||||
def get_own_stylesheets(self):
|
||||
stylesheets = []
|
||||
context_menu_file = 'vendor/jQuery-contextMenu/' \
|
||||
'jquery.contextMenu.min.css'
|
||||
wcdocker_file = 'vendor/wcDocker/wcDocker.min.css'
|
||||
if current_app.debug:
|
||||
context_menu_file = 'vendor/jQuery-contextMenu/' \
|
||||
'jquery.contextMenu.css'
|
||||
wcdocker_file = 'vendor/wcDocker/wcDocker.css'
|
||||
# Add browser stylesheets
|
||||
for (endpoint, filename) in [
|
||||
('static', 'vendor/codemirror/codemirror.css'),
|
||||
('static', 'vendor/codemirror/addon/dialog/dialog.css'),
|
||||
('static', context_menu_file),
|
||||
('static', wcdocker_file)
|
||||
]:
|
||||
stylesheets.append(url_for(endpoint, filename=filename))
|
||||
return stylesheets
|
||||
|
||||
def get_own_menuitems(self):
|
||||
menus = {
|
||||
'file_items': [
|
||||
MenuItem(
|
||||
name='mnu_locklayout',
|
||||
module=PGADMIN_BROWSER,
|
||||
label=gettext('Lock Layout'),
|
||||
priority=999,
|
||||
menu_items=[MenuItem(
|
||||
name='mnu_lock_none',
|
||||
module=PGADMIN_BROWSER,
|
||||
callback='mnu_lock_none',
|
||||
priority=0,
|
||||
label=gettext('None'),
|
||||
checked=True
|
||||
), MenuItem(
|
||||
name='mnu_lock_docking',
|
||||
module=PGADMIN_BROWSER,
|
||||
callback='mnu_lock_docking',
|
||||
priority=1,
|
||||
label=gettext('Prevent Docking'),
|
||||
checked=False
|
||||
), MenuItem(
|
||||
name='mnu_lock_full',
|
||||
module=PGADMIN_BROWSER,
|
||||
callback='mnu_lock_full',
|
||||
priority=2,
|
||||
label=gettext('Full Lock'),
|
||||
checked=False
|
||||
)]
|
||||
)
|
||||
]
|
||||
}
|
||||
|
||||
return menus
|
||||
|
||||
def register_preferences(self):
|
||||
register_browser_preferences(self)
|
||||
|
||||
@@ -156,7 +101,6 @@ class BrowserModule(PgAdminModule):
|
||||
'browser.check_master_password',
|
||||
'browser.set_master_password',
|
||||
'browser.reset_master_password',
|
||||
'browser.lock_layout',
|
||||
]
|
||||
|
||||
def register(self, app, options):
|
||||
@@ -416,47 +360,6 @@ def _get_supported_browser():
|
||||
return browser_name, browser_known, version
|
||||
|
||||
|
||||
def check_browser_upgrade():
|
||||
"""
|
||||
This function is used to check the browser version.
|
||||
:return:
|
||||
"""
|
||||
data = None
|
||||
url = '%s?version=%s' % (config.UPGRADE_CHECK_URL, config.APP_VERSION)
|
||||
current_app.logger.debug('Checking version data at: %s' % url)
|
||||
|
||||
try:
|
||||
# Do not wait for more than 5 seconds.
|
||||
# It stuck on rendering the browser.html, while working in the
|
||||
# broken network.
|
||||
if os.path.exists(config.CA_FILE):
|
||||
response = urlopen(url, data, 5, cafile=config.CA_FILE)
|
||||
else:
|
||||
response = urlopen(url, data, 5)
|
||||
current_app.logger.debug(
|
||||
'Version check HTTP response code: %d' % response.getcode()
|
||||
)
|
||||
|
||||
if response.getcode() == 200:
|
||||
data = json.loads(response.read().decode('utf-8'))
|
||||
current_app.logger.debug('Response data: %s' % data)
|
||||
except Exception:
|
||||
current_app.logger.exception('Exception when checking for update')
|
||||
|
||||
if data is not None and \
|
||||
data[config.UPGRADE_CHECK_KEY]['version_int'] > \
|
||||
config.APP_VERSION_INT:
|
||||
msg = render_template(
|
||||
MODULE_NAME + "/upgrade.html",
|
||||
current_version=config.APP_VERSION,
|
||||
upgrade_version=data[config.UPGRADE_CHECK_KEY]['version'],
|
||||
product_name=config.APP_NAME,
|
||||
download_url=data[config.UPGRADE_CHECK_KEY]['download_url']
|
||||
)
|
||||
|
||||
flash(msg, MessageType.WARNING)
|
||||
|
||||
|
||||
@blueprint.route("/")
|
||||
@pgCSRFProtect.exempt
|
||||
@login_required
|
||||
@@ -491,15 +394,6 @@ def index():
|
||||
|
||||
flash(msg, MessageType.WARNING)
|
||||
|
||||
# Get the current version info from the website, and flash a message if
|
||||
# the user is out of date, and the check is enabled.
|
||||
if config.UPGRADE_CHECK_ENABLED:
|
||||
last_check = get_setting('LastUpdateCheck', default='0')
|
||||
today = time.strftime('%Y%m%d')
|
||||
if int(last_check) < int(today):
|
||||
check_browser_upgrade()
|
||||
store_setting('LastUpdateCheck', today)
|
||||
|
||||
session['allow_save_password'] = True
|
||||
|
||||
if config.SERVER_MODE and not config.MASTER_PASSWORD_REQUIRED and \
|
||||
@@ -605,7 +499,6 @@ def utils():
|
||||
editor_indent_with_tabs = False if editor_use_spaces else True
|
||||
|
||||
prefs = Preferences.module('browser')
|
||||
current_ui_lock = prefs.preference('lock_layout').get()
|
||||
# Try to fetch current libpq version from the driver
|
||||
try:
|
||||
from config import PG_DEFAULT_DRIVER
|
||||
@@ -668,11 +561,10 @@ def utils():
|
||||
mfa_enabled=is_mfa_enabled(),
|
||||
is_admin=current_user.has_role("Administrator"),
|
||||
login_url=login_url,
|
||||
username=current_user.username,
|
||||
username=current_user.username.replace("'","\\'"),
|
||||
auth_source=auth_source,
|
||||
heartbeat_timeout=config.SERVER_HEARTBEAT_TIMEOUT,
|
||||
password_length_min=config.PASSWORD_LENGTH_MIN,
|
||||
current_ui_lock=current_ui_lock,
|
||||
shared_storage_list=shared_storage_list,
|
||||
restricted_shared_storage_list=[] if current_user.has_role(
|
||||
"Administrator") else restricted_shared_storage_list,
|
||||
@@ -689,19 +581,6 @@ def exposed_urls():
|
||||
)
|
||||
|
||||
|
||||
@blueprint.route("/js/constants.js")
|
||||
@pgCSRFProtect.exempt
|
||||
def app_constants():
|
||||
return make_response(
|
||||
render_template('browser/js/constants.js',
|
||||
INTERNAL=INTERNAL,
|
||||
LDAP=LDAP,
|
||||
KERBEROS=KERBEROS,
|
||||
OAUTH2=OAUTH2),
|
||||
200, {'Content-Type': MIMETYPE_APP_JS}
|
||||
)
|
||||
|
||||
|
||||
@blueprint.route("/js/error.js")
|
||||
@pgCSRFProtect.exempt
|
||||
@login_required
|
||||
@@ -1033,21 +912,6 @@ def set_master_password():
|
||||
)
|
||||
|
||||
|
||||
@blueprint.route("/lock_layout", endpoint="lock_layout", methods=["PUT"])
|
||||
def lock_layout():
|
||||
data = None
|
||||
|
||||
if hasattr(request.data, 'decode'):
|
||||
data = request.data.decode('utf-8')
|
||||
|
||||
if data != '':
|
||||
data = json.loads(data)
|
||||
|
||||
blueprint.lock_layout.set(data['value'])
|
||||
|
||||
return make_json_response()
|
||||
|
||||
|
||||
# Only register route if SECURITY_CHANGEABLE is set to True
|
||||
# We can't access app context here so cannot
|
||||
# use app.config['SECURITY_CHANGEABLE']
|
||||
@@ -1071,30 +935,27 @@ if hasattr(config, 'SECURITY_CHANGEABLE') and config.SECURITY_CHANGEABLE:
|
||||
}
|
||||
elif req_json:
|
||||
form = form_class(MultiDict(req_json))
|
||||
if form.validate_on_submit():
|
||||
if form.validate():
|
||||
errormsg = None
|
||||
# change_user_password from flask-security logs out the user
|
||||
# this is undesirable, so change password on own
|
||||
try:
|
||||
change_user_password(current_user._get_current_object(),
|
||||
form.new_password.data,
|
||||
autologin=False)
|
||||
except SOCKETErrorException as e:
|
||||
# Handle socket errors which are not covered by
|
||||
# SMTPExceptions.
|
||||
logging.exception(str(e), exc_info=True)
|
||||
errormsg = gettext(SMTP_SOCKET_ERROR).format(e)
|
||||
except (SMTPConnectError, SMTPResponseException,
|
||||
SMTPServerDisconnected, SMTPDataError, SMTPHeloError,
|
||||
SMTPException, SMTPAuthenticationError,
|
||||
SMTPSenderRefused, SMTPRecipientsRefused) as ex:
|
||||
# Handle smtp specific exceptions.
|
||||
logging.exception(str(ex), exc_info=True)
|
||||
errormsg = gettext(SMTP_ERROR).format(ex)
|
||||
user = User.query.filter(
|
||||
User.fs_uniquifier == current_user.fs_uniquifier)\
|
||||
.first()
|
||||
user.password = hash_password(form.new_password.data)
|
||||
|
||||
try:
|
||||
send_password_changed_notice(user)
|
||||
except Exception as _:
|
||||
# No need to throw error if failed in sending email
|
||||
pass
|
||||
except Exception as e:
|
||||
# Handle other exceptions.
|
||||
logging.exception(str(e), exc_info=True)
|
||||
errormsg = gettext(PASS_ERROR).format(e)
|
||||
|
||||
if request.get_json(silent=True) is None and errormsg is None:
|
||||
if errormsg is None:
|
||||
old_key = get_crypt_key()[1]
|
||||
set_crypt_key(form.new_password.data, False)
|
||||
|
||||
@@ -1103,12 +964,12 @@ if hasattr(config, 'SECURITY_CHANGEABLE') and config.SECURITY_CHANGEABLE:
|
||||
reencrpyt_server_passwords(
|
||||
current_user.id, old_key, form.new_password.data)
|
||||
|
||||
return redirect(get_url(_security.post_change_view) or
|
||||
get_url(_security.post_login_view))
|
||||
db.session.commit()
|
||||
elif errormsg is not None:
|
||||
return internal_server_error(errormsg)
|
||||
else:
|
||||
return bad_request(list(form.errors.values())[0][0])
|
||||
|
||||
return make_json_response(
|
||||
success=1,
|
||||
info=gettext('pgAdmin user password changed successfully')
|
||||
|
||||
@@ -218,10 +218,6 @@ class CollectionNodeModule(PgAdminModule, PGChildModule, metaclass=ABCMeta):
|
||||
def node_path(self):
|
||||
return self.browser_url_prefix + self.node_type
|
||||
|
||||
@property
|
||||
def javascripts(self):
|
||||
return []
|
||||
|
||||
@property
|
||||
def show_node(self):
|
||||
"""
|
||||
|
||||
@@ -15,12 +15,6 @@ from pgadmin.utils.constants import PREF_LABEL_DISPLAY,\
|
||||
from flask import current_app
|
||||
import config
|
||||
|
||||
LOCK_LAYOUT_LEVEL = {
|
||||
'PREVENT_DOCKING': 'docking',
|
||||
'FULL': 'full',
|
||||
'NONE': 'none'
|
||||
}
|
||||
|
||||
|
||||
def register_browser_preferences(self):
|
||||
self.show_system_objects = self.preference.register(
|
||||
@@ -97,21 +91,6 @@ def register_browser_preferences(self):
|
||||
)
|
||||
)
|
||||
|
||||
self.lock_layout = self.preference.register(
|
||||
'display', 'lock_layout',
|
||||
gettext('Lock Layout'), 'radioModern', LOCK_LAYOUT_LEVEL['NONE'],
|
||||
category_label=PREF_LABEL_DISPLAY, options=[
|
||||
{'label': gettext('None'), 'value': LOCK_LAYOUT_LEVEL['NONE']},
|
||||
{'label': gettext('Prevent Docking'),
|
||||
'value': LOCK_LAYOUT_LEVEL['PREVENT_DOCKING']},
|
||||
{'label': gettext('Full Lock'),
|
||||
'value': LOCK_LAYOUT_LEVEL['FULL']},
|
||||
],
|
||||
help_str=gettext(
|
||||
'Lock the UI layout at different levels'
|
||||
)
|
||||
)
|
||||
|
||||
self.table_row_count_threshold = self.preference.register(
|
||||
'properties', 'table_row_count_threshold',
|
||||
gettext("Count rows if estimated less than"), 'integer', 2000,
|
||||
|
||||