Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7c74b7cdb7 | ||
|
|
e8826863e0 | ||
|
|
4f79deac0b | ||
|
|
695166bde5 | ||
|
|
9ce0e77e61 | ||
|
|
0b911bf58c | ||
|
|
15ca0ba1b6 | ||
|
|
c6183c9d03 | ||
|
|
dfd896db10 | ||
|
|
ac8f8fb0b0 | ||
|
|
d6ae6b2773 | ||
|
|
a42f789ff0 | ||
|
|
5d8ec6e5b0 | ||
|
|
e711a1bbc6 | ||
|
|
b6e1223e88 | ||
|
|
28921be00f | ||
|
|
4e8f29f328 | ||
|
|
126e1fb53d | ||
|
|
ebf4963758 | ||
|
|
eece396b30 | ||
|
|
abcb5f8830 | ||
|
|
ebb4c9994f | ||
|
|
971eee32ea | ||
|
|
af84d6b1e0 | ||
|
|
2cb69f09b9 | ||
|
|
0403079a4b | ||
|
|
97984eb3ec | ||
|
|
c46fd30446 | ||
|
|
ff8a301f6a | ||
|
|
27bd28ee97 | ||
|
|
fb4d25d907 | ||
|
|
ca6f52e7c7 | ||
|
|
3bdeb9ace1 | ||
|
|
f64b59e735 | ||
|
|
5d78f4a89f | ||
|
|
695f870ce1 | ||
|
|
593b111fdf | ||
|
|
82efd188c4 | ||
|
|
9df7275429 | ||
|
|
829876c2e0 | ||
|
|
41ba6bd1f4 | ||
|
|
aa282711f8 | ||
|
|
5a501603ac | ||
|
|
e7f8cb4ea3 | ||
|
|
78d9aa5b76 | ||
|
|
038029eb2d | ||
|
|
a14cc1bd77 | ||
|
|
33389fc48e | ||
|
|
d468c16ca2 | ||
|
|
fcf7cf5eb2 | ||
|
|
b08e90ea88 | ||
|
|
75dc42cf24 | ||
|
|
ec3d142ad9 | ||
|
|
280f0b0038 | ||
|
|
7307c52250 | ||
|
|
e8cb962890 | ||
|
|
934f17c65e | ||
|
|
55f36912f9 | ||
|
|
7b1ad5fa67 | ||
|
|
7d8a915ee0 | ||
|
|
8b4df8beb1 | ||
|
|
f98a74b526 | ||
|
|
8a0eae2bb0 | ||
|
|
18f47a59c5 | ||
|
|
31b1af2f84 | ||
|
|
4c56e49c66 | ||
|
|
2de2c30545 | ||
|
|
51897dc804 | ||
|
|
bbef00a151 | ||
|
|
627aa5d695 | ||
|
|
0d8b3c4389 | ||
|
|
8031c35160 | ||
|
|
8cf14222ff | ||
|
|
10b15b3986 | ||
|
|
73fefb8603 | ||
|
|
af6c1a24cf | ||
|
|
cfca6f6218 | ||
|
|
c001b7b50a | ||
|
|
bd259cda42 | ||
|
|
75be0bc22d | ||
|
|
1305d9910b | ||
|
|
6a850fff10 | ||
|
|
6b9f002366 | ||
|
|
0eb8d6c8d6 | ||
|
|
8a2a5fda1d | ||
|
|
a2b35b35f3 | ||
|
|
f250f5de5e | ||
|
|
fa60ab0f6a | ||
|
|
1d3e0a4455 | ||
|
|
82c5febde6 | ||
|
|
0914ec24ad | ||
|
|
57d757d4de | ||
|
|
7edaac1da7 | ||
|
|
9ab451e163 | ||
|
|
213be44e29 | ||
|
|
cb597d0acb | ||
|
|
badc6f33bf | ||
|
|
a5993549b8 | ||
|
|
13b44fffc7 | ||
|
|
fc1a1610a3 | ||
|
|
47eca9a19c | ||
|
|
f635df6ccf | ||
|
|
b2669930f5 | ||
|
|
f25cde8c5f | ||
|
|
797bdb8696 | ||
|
|
c80be9b3a3 | ||
|
|
84e2b844e0 | ||
|
|
be534be674 | ||
|
|
846d0eafe6 | ||
|
|
cd179a3e9f | ||
|
|
2d10e95311 | ||
|
|
f9af74529c | ||
|
|
8c9ab2afd9 | ||
|
|
708a570ba0 | ||
|
|
074db05f7a | ||
|
|
73b437c0f5 | ||
|
|
df5dced926 | ||
|
|
1590df8dfd | ||
|
|
5ee33cf162 | ||
|
|
7a25da9b06 | ||
|
|
d7faa85338 | ||
|
|
cf2328d2cd | ||
|
|
4e52a8664c | ||
|
|
7bae1eb663 | ||
|
|
4791897578 | ||
|
|
1cbdb435df | ||
|
|
b59495603a | ||
|
|
58f86a3c32 | ||
|
|
adcf089357 | ||
|
|
636821f2ac | ||
|
|
b983b094a3 | ||
|
|
53077b6c04 | ||
|
|
a0ddfad655 | ||
|
|
39f92ffae4 | ||
|
|
84a5467a5e | ||
|
|
35d6277f00 | ||
|
|
85290d4e61 | ||
|
|
48a26e8979 | ||
|
|
53a8cac7f8 | ||
|
|
96128f6a15 | ||
|
|
e2a80b2465 | ||
|
|
6dd91c8277 | ||
|
|
83ade5dcc2 | ||
|
|
5c257fe1b9 | ||
|
|
740a50680e | ||
|
|
706eec0d5b | ||
|
|
f63190dc93 | ||
|
|
58bb14253e | ||
|
|
eb7c3ef361 | ||
|
|
2c37ff2893 | ||
|
|
a30a722e11 | ||
|
|
650a15beec | ||
|
|
2fc65589c8 | ||
|
|
bf7f8cdd73 | ||
|
|
ae76ea3585 | ||
|
|
0b46bdf901 |
No files matched your search
@@ -32,6 +32,18 @@ jobs:
|
||||
sudo sh -c 'echo "deb https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
|
||||
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
|
||||
|
||||
- name: Uninstall PostgreSQL if already present
|
||||
run: |
|
||||
if [ -n "$(ls /etc/postgresql/*/*/postgresql.conf 2>/dev/null)" ]; then
|
||||
# Extract the major version from pg_config
|
||||
installed_pg_version=$( pg_config --version | cut -d ' ' -f 2 | cut -d '.' -f 1 )
|
||||
echo "Installed PostgreSQL version: $installed_pg_version"
|
||||
if [ $installed_pg_version != ${{ matrix.pgver }} ]; then
|
||||
sudo pg_dropcluster $installed_pg_version main --stop
|
||||
sudo apt-get -y remove "postgresql-${installed_pg_version}"
|
||||
fi
|
||||
fi
|
||||
|
||||
- name: Install platform dependencies
|
||||
run: |
|
||||
sudo apt update
|
||||
@@ -119,7 +131,7 @@ jobs:
|
||||
"comment": "PostgreSQL ${{ matrix.pgver }} Server",
|
||||
"db_username": "postgres",
|
||||
"host": "/var/run/postgresql",
|
||||
"db_password": "postgres",
|
||||
"db_password": "",
|
||||
"db_port": 59${{ matrix.pgver }},
|
||||
"maintenance_db": "postgres",
|
||||
"sslmode": "prefer",
|
||||
|
||||
@@ -48,7 +48,7 @@ jobs:
|
||||
if: ${{ matrix.os == 'ubuntu-22.04' }}
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install -y libpq-dev libffi-dev libssl-dev libkrb5-dev zlib1g-dev edb-as${{ matrix.pgver }}-server edb-as${{ matrix.pgver }}-server-pldebugger
|
||||
sudo apt install -y libpq-dev libffi-dev libssl-dev libkrb5-dev zlib1g-dev edb-as${{ matrix.pgver }}-server edb-as${{ matrix.pgver }}-server-pldebugger edb-as${{ matrix.pgver }}-postgis34
|
||||
|
||||
- name: Install pgagent on Linux
|
||||
if: ${{ matrix.os == 'ubuntu-22.04' && matrix.pgver <= 16 }}
|
||||
@@ -105,6 +105,10 @@ jobs:
|
||||
- name: Create pgagent extension on Linux
|
||||
if: ${{ matrix.os == 'ubuntu-22.04' && matrix.pgver <= 16 }}
|
||||
run: psql -U enterprisedb -d postgres -p 58${{ matrix.pgver }} -c 'CREATE EXTENSION IF NOT EXISTS pgagent;'
|
||||
|
||||
- name: Create postgis extension on Linux
|
||||
if: ${{ matrix.os == 'ubuntu-22.04' }}
|
||||
run: psql -U enterprisedb -d postgres -p 58${{ matrix.pgver }} -c 'CREATE EXTENSION IF NOT EXISTS postgis;'
|
||||
|
||||
- name: Install Python dependencies on Linux
|
||||
if: ${{ matrix.os == 'ubuntu-22.04' }}
|
||||
|
||||
@@ -34,11 +34,24 @@ jobs:
|
||||
sudo sh -c 'echo "deb https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list'
|
||||
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
|
||||
|
||||
- name: Uninstall PostgreSQL if already present on linux
|
||||
if: ${{ matrix.os == 'ubuntu-22.04' }}
|
||||
run: |
|
||||
if [ -n "$(ls /etc/postgresql/*/*/postgresql.conf 2>/dev/null)" ]; then
|
||||
# Extract the major version from pg_config
|
||||
installed_pg_version=$( pg_config --version | cut -d ' ' -f 2 | cut -d '.' -f 1 )
|
||||
echo "Installed PostgreSQL version: $installed_pg_version"
|
||||
if [ $installed_pg_version != ${{ matrix.pgver }} ]; then
|
||||
sudo pg_dropcluster $installed_pg_version main --stop
|
||||
sudo apt-get -y remove "postgresql-${installed_pg_version}"
|
||||
fi
|
||||
fi
|
||||
|
||||
- name: Install platform dependencies on Linux
|
||||
if: ${{ matrix.os == 'ubuntu-22.04' }}
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install -y libpq-dev libffi-dev libssl-dev libkrb5-dev zlib1g-dev postgresql-${{ matrix.pgver }} postgresql-${{ matrix.pgver }}-pldebugger pgagent
|
||||
sudo apt install -y libpq-dev libffi-dev libssl-dev libkrb5-dev zlib1g-dev postgresql-${{ matrix.pgver }} postgresql-${{ matrix.pgver }}-pldebugger pgagent postgresql-${{ matrix.pgver }}-postgis-3
|
||||
|
||||
- name: Install platform dependencies on macOS
|
||||
if: ${{ matrix.os == 'macos-latest' }}
|
||||
@@ -46,7 +59,7 @@ jobs:
|
||||
brew install postgresql@${{ matrix.pgver }}
|
||||
echo "/opt/homebrew/opt/postgresql@${{ matrix.pgver }}/bin" >> $GITHUB_PATH
|
||||
|
||||
- name: Uninstall PostgreSQL if already present
|
||||
- name: Uninstall PostgreSQL if already present on windows
|
||||
if: ${{ matrix.os == 'windows-latest' }}
|
||||
run: |
|
||||
if exist "C:\Program Files\PostgreSQL\{{ matrix.pgver }}\uninstall-postgresql.exe" (
|
||||
@@ -100,6 +113,7 @@ jobs:
|
||||
|
||||
psql -U postgres -p 59${{ matrix.pgver }} -c 'CREATE EXTENSION pgagent;'
|
||||
psql -U postgres -p 59${{ matrix.pgver }} -c 'CREATE EXTENSION pldbgapi;'
|
||||
psql -U postgres -p 59${{ matrix.pgver }} -c 'CREATE EXTENSION postgis;'
|
||||
|
||||
- name: Start PostgreSQL on macOS
|
||||
if: ${{ matrix.os == 'macos-latest' }}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
3.8.0
|
||||
@@ -208,7 +208,7 @@ RUN apk add --no-cache \
|
||||
libedit \
|
||||
libldap \
|
||||
libcap && \
|
||||
/venv/bin/python3 -m pip install --no-cache-dir gunicorn==22.0.0 && \
|
||||
/venv/bin/python3 -m pip install --no-cache-dir gunicorn==23.0.0 && \
|
||||
find / -type d -name '__pycache__' -exec rm -rf {} + && \
|
||||
useradd -r -u 5050 -g root -s /sbin/nologin pgadmin && \
|
||||
mkdir -p /run/pgadmin /var/lib/pgadmin && \
|
||||
@@ -222,7 +222,7 @@ RUN apk add --no-cache \
|
||||
echo "pgadmin ALL = NOPASSWD: /usr/sbin/postfix start" > /etc/sudoers.d/postfix && \
|
||||
echo "pgadminr ALL = NOPASSWD: /usr/sbin/postfix start" >> /etc/sudoers.d/postfix
|
||||
|
||||
USER pgadmin
|
||||
USER 5050
|
||||
|
||||
# Finish up
|
||||
VOLUME /var/lib/pgadmin
|
||||
|
||||
@@ -284,7 +284,7 @@ REM Main build sequence Ends
|
||||
|
||||
REM WGET
|
||||
FOR /f "tokens=*" %%i IN ('npm info electron version') DO SET "ELECTRON_VERSION=%%i"
|
||||
SET ELECTRON_VERSION="33.3.2"
|
||||
SET ELECTRON_VERSION="35.4.0"
|
||||
:GET_NW
|
||||
wget https://github.com/electron/electron/releases/download/v%ELECTRON_VERSION%/electron-v%ELECTRON_VERSION%-win32-x64.zip -O "%TMPDIR%\electron-v%ELECTRON_VERSION%-win32-x64.zip"
|
||||
IF %ERRORLEVEL% NEQ 0 GOTO GET_NW
|
||||
|
||||
@@ -15,33 +15,51 @@ 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/
|
||||
subdirectory contains an Electron based runtime application intended to allow this,
|
||||
which will execute the Python server and display the UI.
|
||||
which will fork a Python server process and display the UI.
|
||||
|
||||
## Building the Runtime
|
||||
## Prerequisites
|
||||
1. Install Node.js 20 and above (https://nodejs.org/en/download)
|
||||
2. yarn (https://yarnpkg.com/getting-started/install)
|
||||
3. Python 3.8 and above (https://www.python.org/downloads/)
|
||||
4. PostgreSQL server (https://www.postgresql.org/download)
|
||||
|
||||
To build the runtime, the following packages must be installed:
|
||||
Start by enabling Corepack, if it isn't already;
|
||||
this will add the yarn binary to your PATH:
|
||||
```bash
|
||||
corepack enable
|
||||
```
|
||||
|
||||
* NodeJS 16+
|
||||
* Yarn
|
||||
# Building the Web Assets
|
||||
|
||||
Change into the runtime directory, and run *yarn install*. This will install the
|
||||
dependencies required.
|
||||
pgAdmin is dependent on a number of third party Javascript libraries. These,
|
||||
along with it's own Javascript code, CSS code and images must be
|
||||
compiled into a "bundle" which is transferred to the browser for execution
|
||||
and rendering. This is far more efficient than simply requesting each
|
||||
asset as it's needed by the client.
|
||||
|
||||
In order to use the runtime in a development environment, you'll need to copy
|
||||
*dev_config.json.in* file to *dev_config.json*, and edit the paths to the Python
|
||||
executable and *pgAdmin.py* file, otherwise the runtime will use the default
|
||||
paths it would expect to find in the standard package for your platform.
|
||||
|
||||
You can then execute the runtime by running something like:
|
||||
To create the bundle, you will need the 'yarn' package management tool to be
|
||||
installed. Then, you can run the following commands on a *nix system to
|
||||
download the required packages and build the bundle:
|
||||
|
||||
```bash
|
||||
yarn run start
|
||||
$ cd $PGADMIN4_SRC
|
||||
$ make install-node
|
||||
$ make bundle
|
||||
```
|
||||
|
||||
On Windows systems (where "make" is not available), the following commands
|
||||
can be used:
|
||||
|
||||
```
|
||||
C:\> cd $PGADMIN4_SRC\web
|
||||
C:\$PGADMIN4_SRC\web> yarn install
|
||||
C:\$PGADMIN4_SRC\web> yarn run bundle
|
||||
```
|
||||
|
||||
# Configuring the Python Environment
|
||||
|
||||
In order to run the Python code, a suitable runtime environment is required.
|
||||
Python version 3.7 and later are currently supported. It is recommended that a
|
||||
Python version 3.8 and later are currently supported. It is recommended that a
|
||||
Python Virtual Environment is setup for this purpose, rather than using the
|
||||
system Python environment. On Linux and Mac systems, the process is fairly
|
||||
simple - adapt as required for your distribution:
|
||||
@@ -63,7 +81,7 @@ simple - adapt as required for your distribution:
|
||||
so update that to the latest:
|
||||
|
||||
```bash
|
||||
$ pip install --upgrade pip
|
||||
(venv) $ pip install --upgrade pip
|
||||
```
|
||||
|
||||
4. Ensure that a PostgreSQL installation's bin/ directory is in the path (so
|
||||
@@ -88,36 +106,44 @@ simple - adapt as required for your distribution:
|
||||
configuration may look like:
|
||||
|
||||
```python
|
||||
from config import *
|
||||
import os
|
||||
import logging
|
||||
|
||||
# Debug mode
|
||||
DEBUG = True
|
||||
# Change pgAdmin data directory
|
||||
DATA_DIR = '/Users/myuser/.pgadmin_dev'
|
||||
|
||||
# App mode
|
||||
SERVER_MODE = True
|
||||
#Change pgAdmin server and port
|
||||
DEFAULT_SERVER = '127.0.0.1'
|
||||
DEFAULT_SERVER_PORT = 5051
|
||||
|
||||
# Enable the test module
|
||||
MODULE_BLACKLIST.remove('test')
|
||||
# Switch between server and desktop mode
|
||||
SERVER_MODE = True
|
||||
|
||||
# Log
|
||||
CONSOLE_LOG_LEVEL = DEBUG
|
||||
FILE_LOG_LEVEL = DEBUG
|
||||
#Change pgAdmin config DB path in case external DB is used.
|
||||
CONFIG_DATABASE_URI="postgresql://postgres:postgres@localhost:5436/pgadmin"
|
||||
|
||||
DEFAULT_SERVER = '127.0.0.1'
|
||||
#Setup SMTP
|
||||
MAIL_SERVER = 'smtp.gmail.com'
|
||||
MAIL_PORT = 465
|
||||
MAIL_USE_SSL = True
|
||||
MAIL_USERNAME = 'user@gmail.com'
|
||||
MAIL_PASSWORD = 'xxxxxxxxxx'
|
||||
|
||||
UPGRADE_CHECK_ENABLED = True
|
||||
# Change log level
|
||||
CONSOLE_LOG_LEVEL = logging.INFO
|
||||
FILE_LOG_LEVEL = logging.INFO
|
||||
|
||||
# Use a different config DB for each server mode.
|
||||
if SERVER_MODE == False:
|
||||
SQLITE_PATH = os.path.join(
|
||||
DATA_DIR,
|
||||
'pgadmin4-desktop.db'
|
||||
)
|
||||
else:
|
||||
SQLITE_PATH = os.path.join(
|
||||
DATA_DIR,
|
||||
'pgadmin4-server.db'
|
||||
)
|
||||
# Use a different config DB for each server mode.
|
||||
if SERVER_MODE == False:
|
||||
SQLITE_PATH = os.path.join(
|
||||
DATA_DIR,
|
||||
'pgadmin4-desktop.db'
|
||||
)
|
||||
else:
|
||||
SQLITE_PATH = os.path.join(
|
||||
DATA_DIR,
|
||||
'pgadmin4-server.db'
|
||||
)
|
||||
```
|
||||
|
||||
This configuration allows easy switching between server and desktop modes
|
||||
@@ -137,9 +163,9 @@ simple - adapt as required for your distribution:
|
||||
(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.
|
||||
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.
|
||||
|
||||
At this point you will be able to run pgAdmin 4 from the command line in either
|
||||
server or desktop mode, and access it from a web browser using the URL shown in
|
||||
@@ -148,49 +174,6 @@ the terminal once pgAdmin has started up.
|
||||
Setup of an environment on Windows is somewhat more complicated unfortunately,
|
||||
please see *pkg/win32/README.txt* for complete details.
|
||||
|
||||
# Building the Web Assets
|
||||
|
||||
pgAdmin is dependent on a number of third party Javascript libraries. These,
|
||||
along with it's own Javascript code, SCSS/CSS code and images must be
|
||||
compiled into a "bundle" which is transferred to the browser for execution
|
||||
and rendering. This is far more efficient than simply requesting each
|
||||
asset as it's needed by the client.
|
||||
|
||||
To create the bundle, you will need the 'yarn' package management tool to be
|
||||
installed. Then, you can run the following commands on a *nix system to
|
||||
download the required packages and build the bundle:
|
||||
|
||||
```bash
|
||||
(venv) $ cd $PGADMIN4_SRC
|
||||
(venv) $ make install-node
|
||||
(venv) $ make bundle
|
||||
```
|
||||
|
||||
On Windows systems (where "make" is not available), the following commands
|
||||
can be used:
|
||||
|
||||
```
|
||||
C:\> cd $PGADMIN4_SRC\web
|
||||
C:\$PGADMIN4_SRC\web> yarn install
|
||||
C:\$PGADMIN4_SRC\web> yarn run bundle
|
||||
```
|
||||
|
||||
# Creating pgAdmin themes
|
||||
|
||||
To create a pgAdmin theme, you need to create a directory under
|
||||
*web/pgadmin/static/scss/resources*.
|
||||
Copy the sample file *_theme.variables.scss.sample* to the new directory and
|
||||
rename it to *_theme.variables.scss*. Change the desired hexadecimal values of
|
||||
the colors and bundle pgAdmin. You can also add a preview image in the theme
|
||||
directory with the name as *\<dir name>_preview.png*. It is recommended that the
|
||||
preview image should not be larger in size as it may take time to load on slow
|
||||
networks. Run the *yarn run bundle* and you're good to go. No other changes are
|
||||
required, pgAdmin bundle will read the directory and create other required
|
||||
entries to make them available in preferences.
|
||||
|
||||
The name of the theme is derived from the directory name. Underscores (_) and
|
||||
hyphens (-) will be replaced with spaces and the result will be camel cased.
|
||||
|
||||
# Building the documentation
|
||||
|
||||
In order to build the docs, an additional Python package is required in the
|
||||
@@ -210,6 +193,21 @@ The docs can then be built using the Makefile in *$PGADMIN4_SRC*, e.g.
|
||||
|
||||
The output can be found in *$PGADMIN4_SRC/docs/en_US/_build/html/index.html*
|
||||
|
||||
## Building the Runtime
|
||||
Change into the runtime directory, and run *yarn install*. This will install the
|
||||
dependencies required.
|
||||
|
||||
In order to use the runtime in a development environment, you'll need to copy
|
||||
*dev_config.json.in* file to *dev_config.json*, and edit the paths to the Python
|
||||
executable and *pgAdmin.py* file, otherwise the runtime will use the default
|
||||
paths it would expect to find in the standard package for your platform.
|
||||
|
||||
You can then execute the runtime by running something like:
|
||||
|
||||
```bash
|
||||
yarn run start
|
||||
```
|
||||
|
||||
# Building packages
|
||||
|
||||
Most packages can be built using the Makefile in $PGADMIN4_SRC, provided all
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
Only the latest version receives security updates. Users are encouraged to upgrade to the latest stable release.
|
||||
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
We take security seriously and appreciate your efforts to responsibly disclose vulnerabilities. If you believe you have found a vulnerability, please follow the guidelines below to submit a report.
|
||||
|
||||
### **What to Include in Your Report**
|
||||
To help us quickly understand and address the issue, please include the following sections in your report:
|
||||
|
||||
#### 1. **Summary**
|
||||
- A brief description of the vulnerability.
|
||||
|
||||
#### 2. **Affected Versions**
|
||||
- The version(s) of the project affected by the vulnerability.
|
||||
- Example: "Affects versions 3.4.0 to 3.6.23."
|
||||
|
||||
#### 3. **Details**
|
||||
- A detailed explanation of the vulnerability, including:
|
||||
- How to reproduce the issue (step-by-step instructions).
|
||||
- The code or component where the vulnerability exists.
|
||||
- The expected vs. actual behavior.
|
||||
|
||||
#### 4. **Proof of Concept (PoC)**
|
||||
- Provide a proof of concept to demonstrate the vulnerability. This could be:
|
||||
- Code snippets.
|
||||
- Screenshots or videos.
|
||||
- A minimal reproducible example.
|
||||
|
||||
#### 5. **Patches (if applicable)**
|
||||
- If you have a suggested fix or patch, include it in your report.
|
||||
- Example: "Sanitize user input using `DOMPurify`."
|
||||
|
||||
#### 6. **Impact**
|
||||
- Describe the potential impact of the vulnerability, such as:
|
||||
- Remote Code Execution.
|
||||
- CSRF.
|
||||
- Data exposure.
|
||||
- Denial of service.
|
||||
|
||||
|
||||
|
||||
### **What to Expect**
|
||||
- **Acknowledgement**: You will receive an acknowledgement of your report within **48 hours**.
|
||||
- **Timeline**: We will provide a timeline for investigating and addressing the issue.
|
||||
- **Updates**: You will receive regular updates on the progress of the vulnerability resolution.
|
||||
- **CVE ID**: If the vulnerability is confirmed, we will request a CVE ID to acknowledge the issue officially and include it in the release notes.
|
||||
|
||||
|
||||
### **Out of Scope**
|
||||
The following issues are considered out of scope for security reports:
|
||||
- Vulnerabilities in outdated or unsupported versions.
|
||||
- Issues related to non-security-impacting bugs or feature requests.
|
||||
- Vulnerabilities requiring physical access to the device or social engineering.
|
||||
|
||||
|
||||
|
||||
## Security Updates
|
||||
|
||||
We are committed to providing timely security updates for supported versions. Here’s our process:
|
||||
1. **Assessment**:
|
||||
- All reported vulnerabilities are assessed for severity and impact.
|
||||
2. **Patch Development**:
|
||||
- Patches are developed and tested in a private repository to prevent premature disclosure.
|
||||
3. **Release**:
|
||||
- Security patches are released as soon as possible, along with a detailed advisory.
|
||||
|
||||
|
||||
|
||||
## Acknowledgments
|
||||
|
||||
We deeply appreciate the efforts of security researchers and users who help us improve the security of our project.
|
||||
|
||||
|
||||
|
||||
## Contact
|
||||
|
||||
For any questions or concerns regarding security, please contact us at `security@pgadmin.org`.
|
||||
@@ -134,6 +134,14 @@ Override the default file path for the server definition list. See the
|
||||
/pgadmin4/servers.json mapped file below for more information. See the format
|
||||
of the `Servers JSON file <https://www.pgadmin.org/docs/pgadmin4/latest/import_export_servers.html#json-format>`_.
|
||||
|
||||
**PGADMIN_REPLACE_SERVERS_ON_STARTUP**
|
||||
|
||||
*Default: null*
|
||||
|
||||
By default, the server definitions are only loaded on first launch, i.e. when initializing the configuration database. See PGADMIN_SERVER_JSON_FILE above.
|
||||
|
||||
If this variable is set to True, the server definitions will be replaced on every launch. This can be used to declaratively manage the server definitions.
|
||||
|
||||
**PGADMIN_PREFERENCES_JSON_FILE**
|
||||
|
||||
*Default: /pgadmin4/preferences.json*
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
.. _directory_dialog:
|
||||
|
||||
*************************
|
||||
`Directory Dialog`:index:
|
||||
*************************
|
||||
|
||||
Use the Directory dialog to create an alias for a file system directory path.
|
||||
To create directories, you must have the CREATE ANY DIRECTORY system privilege.
|
||||
When you create a directory, you are automatically granted READ and WRITE privileges
|
||||
on the directory, and you can grant READ and WRITE privileges to other users and roles.
|
||||
The superuser can also grant these privileges to other users and roles.
|
||||
|
||||
Please note that directories are supported when connected to EDB Postgres Advanced Server.
|
||||
For more information about using directories, please see the EDB Postgres Advanced Server Guide, available at:
|
||||
|
||||
https://www.enterprisedb.com/docs/epas/latest/epas_compat_sql/
|
||||
|
||||
|
||||
The *Directory* dialog organizes the definition of a directory through the
|
||||
following tabs: *General*, *Definition*, *Security*, and *SQL*.
|
||||
The *SQL* tab displays the SQL code generated by dialog selections.
|
||||
|
||||
.. image:: images/directory_general.png
|
||||
:alt: Directory general tab
|
||||
:align: center
|
||||
|
||||
Use the fields on the *General* tab to specify directory attributes:
|
||||
|
||||
* Use the *Name* field to add a directory alias name. This name will be displayed in the object explorer.
|
||||
* Select the owner of the directory from the drop-down listbox in the *Owner*
|
||||
field.
|
||||
|
||||
Click the *Definition* tab to continue.
|
||||
|
||||
.. image:: images/directory_definition.png
|
||||
:alt: Directory dialog definition tab
|
||||
:align: center
|
||||
|
||||
* Use the *Location* field to specify a fully qualified directory path represented
|
||||
by the alias name. The CREATE DIRECTORY command doesn't create the operating system directory.
|
||||
The physical directory must be created independently using operating system commands.
|
||||
|
||||
Click the *Security* tab to continue.
|
||||
|
||||
.. image:: images/directory_security.png
|
||||
:alt: Directory dialog security tab
|
||||
:align: center
|
||||
|
||||
NOTE:- This *Security* tab will be only available for EPAS 17.
|
||||
|
||||
Use the *Security* tab to assign privileges for the directory.
|
||||
|
||||
Use the *Privileges* panel to assign security privileges. Click the *Add* icon
|
||||
(+) to assign a set of privileges:
|
||||
|
||||
* Select the name of the role from the drop-down listbox in the *Grantee* field.
|
||||
* The current user, who is the default grantor for granting the privilege, is displayed in the *Grantor* field.
|
||||
* Click inside the *Privileges* field. Check the boxes to the left of one or
|
||||
more privileges to grant the selected privileges to the specified user.
|
||||
|
||||
Click the *Add* icon to assign additional sets of privileges; to discard a
|
||||
privilege, click the trash icon to the left of the row and confirm deletion in
|
||||
the *Delete Row* popup.
|
||||
|
||||
Click the *SQL* tab to continue.
|
||||
|
||||
Your entries in the *Directory* dialog generate a SQL command (see an example
|
||||
below). Use the *SQL* tab for review; revisit or switch tabs to make any changes
|
||||
to the SQL command.
|
||||
|
||||
Example
|
||||
*******
|
||||
|
||||
The following is an example of the sql command generated by user selections in
|
||||
the *Directory* dialog:
|
||||
|
||||
.. image:: images/directory_sql.png
|
||||
:alt: Directory dialog sql tab
|
||||
:align: center
|
||||
|
||||
The example shown demonstrates creating a directory named *test1*. It has a
|
||||
*location* value equal to */home/test_dir*.
|
||||
|
||||
* Click the *Info* button (i) to access online help.
|
||||
* Click the *Save* button to save work.
|
||||
* Click the *Close* button to exit without saving work.
|
||||
* Click the *Reset* button to restore configuration parameters.
|
||||
@@ -207,6 +207,22 @@ The table node shows table details in a graphical representation:
|
||||
* you can click on the node and drag to move on the canvas.
|
||||
* Upon double click on the table node or by clicking the edit button from the toolbar, the table dialog opens where you can change the table details. Refer :ref:`table dialog <table_dialog>` for information on different fields.
|
||||
|
||||
The One to One Link Dialog
|
||||
***************************
|
||||
|
||||
.. image:: images/erd_11_dialog.png
|
||||
:alt: ERD tool 1-1 dialog
|
||||
:align: center
|
||||
|
||||
The one to one link dialog allows you to:
|
||||
|
||||
* Add a one to one relationship between two tables.
|
||||
* *Local Table* is the table that references a table and has the *one* end point.
|
||||
* *Local Column* the column that references.
|
||||
* *Select Constraint* To implement one to one relationship, the *Local Column* must have primaty key or unique constraint. The default is a unique constraint. Please note that this field is visible only when the selected *Local Column* does not have either of the mentioned constraints.
|
||||
* *Referenced Table* is the table that is being referred and has the *one* end point.
|
||||
* *Referenced Column* the column that is being referred.
|
||||
|
||||
The One to Many Link Dialog
|
||||
***************************
|
||||
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
.. _export_data_using_query:
|
||||
|
||||
***************************************
|
||||
`Export Data Using Query Dialog`:index:
|
||||
***************************************
|
||||
|
||||
Use the *Export Data Using Query* dialog to copy data to a file.
|
||||
|
||||
The *Export Data Using Query* dialog organizes the export of data through the
|
||||
*General*, *Options* and *Query* tabs.
|
||||
|
||||
.. image:: images/export_query_general.png
|
||||
:alt: Export data using query dialog general tab
|
||||
:align: center
|
||||
|
||||
Use the fields in the *General* tab to specify export preferences:
|
||||
|
||||
* Enter the name of the target file in the *Filename* field.
|
||||
Optionally, select the *Browse* icon (ellipsis) to the right to navigate
|
||||
into a directory and select a file.
|
||||
|
||||
* Use the drop-down listbox in the *Format* field to specify the file type.
|
||||
Select:
|
||||
|
||||
* *binary* for a .bin file.
|
||||
* *csv* for a .csv file.
|
||||
* *text* for a .txt file.
|
||||
|
||||
* Use the drop-down listbox in the *Encoding* field to specify the type of
|
||||
character encoding.
|
||||
|
||||
.. image:: images/export_query_options.png
|
||||
:alt: Export data using query dialog options tab
|
||||
:align: center
|
||||
|
||||
* Use the fields in the *Options* tab to specify additional information:
|
||||
|
||||
* Move the *Header* switch to the *Yes* position to include the table header
|
||||
with the data rows. If you include the table header, the first row of the
|
||||
file will contain the column names.
|
||||
* If you are exporting data, specify the delimiter that will separate the
|
||||
columns within the target file in the *Delimiter* field. The separating
|
||||
character can be a colon, semicolon, a vertical bar, or a tab.
|
||||
* Specify a quoting character used in the *Quote* field. Quoting can be
|
||||
applied to string columns only (i.e. numeric columns will not be quoted)
|
||||
or all columns regardless of data type. The character used for quoting can
|
||||
be a single quote or a double quote.
|
||||
* Specify a character that should appear before a data character that matches
|
||||
the *QUOTE* value in the *Escape* field.
|
||||
* Use the *NULL String* field to specify a string that will represent a null
|
||||
value within the source or target file.
|
||||
|
||||
Click the *Query* tab to continue.
|
||||
|
||||
.. image:: images/export_query.png
|
||||
:alt: Export data using query dialog query tab
|
||||
:align: center
|
||||
|
||||
Use the fields in the *Query* tab to write the query that will be exported:
|
||||
|
||||
* Use the *Export Data Query* field to specifies A SELECT, VALUES, INSERT, UPDATE,
|
||||
DELETE, or MERGE command whose results are to be copied .
|
||||
|
||||
* Use *Force Quote columns* field to forces quoting to be used for all non-NULL
|
||||
values in each specified column. NULL output is never quoted. This is a creatable
|
||||
select control. If you would like to quote all columns then provide only '*' in
|
||||
the field.
|
||||
|
||||
After completing the *Export Data Using Query* dialog, click the *OK* button to
|
||||
perform the export. pgAdmin will notify you when the background
|
||||
process completes:
|
||||
|
||||
.. image:: images/export_query_complete.png
|
||||
:alt: Export data using query completion notification
|
||||
:align: center
|
||||
|
||||
|
||||
Use the *View Processes* button on the notification to open the *Process
|
||||
Watcher* and review detailed information about the execution of the command
|
||||
that performed the export:
|
||||
|
||||
Use the **End Process** button to end the Export process.
|
||||
|
||||
.. image:: images/export_query_pw.png
|
||||
:alt: Export data using query process watcher
|
||||
:align: center
|
||||
|
||||
.. note:: If you are running *pgAdmin* in *Server Mode* you can click on the |sm_icon| icon in the process watcher window to open the file location in the Storage Manager. You can use the :ref:`Storage Manager <storage_manager>` to download the exported file on the client machine .
|
||||
|
||||
|
||||
.. |sm_icon| image:: images/sm_icon.png
|
||||
|
After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 47 KiB |
|
Before Width: | Height: | Size: 152 KiB After Width: | Height: | Size: 156 KiB |
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 105 KiB |
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 84 KiB |
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 108 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 106 KiB |
|
Before Width: | Height: | Size: 41 KiB After Width: | Height: | Size: 83 KiB |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 9.5 KiB |
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 62 KiB |
|
After Width: | Height: | Size: 79 KiB |
|
After Width: | Height: | Size: 87 KiB |
|
After Width: | Height: | Size: 122 KiB |
|
After Width: | Height: | Size: 65 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 237 KiB |
|
After Width: | Height: | Size: 108 KiB |
|
Before Width: | Height: | Size: 93 KiB After Width: | Height: | Size: 254 KiB |
|
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 85 KiB |
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 188 KiB |
|
Before Width: | Height: | Size: 182 KiB After Width: | Height: | Size: 320 KiB |
|
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 123 KiB |
|
After Width: | Height: | Size: 87 KiB |
|
After Width: | Height: | Size: 164 KiB |
|
Before Width: | Height: | Size: 209 KiB After Width: | Height: | Size: 280 KiB |
|
Before Width: | Height: | Size: 193 KiB After Width: | Height: | Size: 96 KiB |
|
Before Width: | Height: | Size: 186 KiB After Width: | Height: | Size: 183 KiB |
|
Before Width: | Height: | Size: 176 KiB After Width: | Height: | Size: 188 KiB |
|
Before Width: | Height: | Size: 141 KiB After Width: | Height: | Size: 195 KiB |
|
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 7.4 KiB After Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 46 KiB |
|
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 121 KiB |
|
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 64 KiB |
|
Before Width: | Height: | Size: 87 KiB After Width: | Height: | Size: 76 KiB |
|
After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 43 KiB |
|
Before Width: | Height: | Size: 78 KiB |
|
After Width: | Height: | Size: 62 KiB |
@@ -33,18 +33,29 @@ Use the fields in the *General* tab to specify import and export preferences:
|
||||
* Use the drop-down listbox in the *Encoding* field to specify the type of
|
||||
character encoding.
|
||||
|
||||
* use the drop-down listbox in the *On Error* field to specify how to behave
|
||||
when encountering an error converting a columns input value into its data type.
|
||||
An error_action value of stop means fail the command, while ignore means discard
|
||||
the input row and continue with the next one. The default is stop. This option is
|
||||
available from PG/EPAS version 17 and above.
|
||||
|
||||
* use the drop-down listbox in the *Log Verbosity* field to specify the amount
|
||||
of messages emitted by a COPY command: default or verbose. This is currently
|
||||
used in Import only when ON_ERROR option is set to ignore. This option is
|
||||
available from PG/EPAS version 17 and above.
|
||||
|
||||
.. image:: images/import_export_options.png
|
||||
:alt: Import Export data dialog options tab
|
||||
:align: center
|
||||
|
||||
* Use the fields in the *Options* tab to specify additional information:
|
||||
|
||||
* Move the *OID* switch to the *Yes* position to include the *OID* column.
|
||||
The *OID* is a system-assigned value that may not be modified. The default
|
||||
is *No*.
|
||||
* Move the *Header* switch to the *Yes* position to include the table header
|
||||
with the data rows. If you include the table header, the first row of the
|
||||
file will contain the column names.
|
||||
* Move the *Freeze* switch to the *Yes* position to requests copying the
|
||||
data with rows already frozen, just as they would be after running the
|
||||
VACUUM FREEZE command.
|
||||
* If you are exporting data, specify the delimiter that will separate the
|
||||
columns within the target file in the *Delimiter* field. The separating
|
||||
character can be a colon, semicolon, a vertical bar, or a tab.
|
||||
@@ -54,8 +65,11 @@ Use the fields in the *General* tab to specify import and export preferences:
|
||||
be a single quote or a double quote.
|
||||
* Specify a character that should appear before a data character that matches
|
||||
the *QUOTE* value in the *Escape* field.
|
||||
* Use the *NULL Strings* field to specify a string that will represent a null
|
||||
* Use the *NULL String* field to specify a string that will represent a null
|
||||
value within the source or target file.
|
||||
* Use the *Default String* field to specify a string that will represent a default value.
|
||||
Each time the string is found in the input file, the default value of the corresponding
|
||||
column will be used. This option is available from PG/EPAS version 16 and above.
|
||||
|
||||
Click the *Columns* tab to continue.
|
||||
|
||||
@@ -71,29 +85,39 @@ or exported:
|
||||
the left of the column name. Click an empty spot inside the field to access
|
||||
the drop-down list.
|
||||
|
||||
* If enabled, click inside the *Force Quote columns* field to forces quoting
|
||||
to be used for all non-NULL values in each specified column. NULL output is
|
||||
never quoted. To delete a column, click the *x* to the left of the column name.
|
||||
|
||||
* If enabled, click inside the *NOT NULL columns* field to select one or more
|
||||
columns that will not be checked for a NULL value. To delete a column, click
|
||||
the *x* to the left of the column name.
|
||||
|
||||
* If enabled, click inside the *NULL columns* field to match the specified columns
|
||||
values against the null string, even if it has been quoted, and if a match is
|
||||
found set the value to NULL. To delete a column, click the *x* to the left of the
|
||||
column name.
|
||||
|
||||
After completing the *Import/Export data* dialog, click the *OK* button to
|
||||
perform the import or export. pgAdmin will inform you when the background
|
||||
perform the import or export. pgAdmin will notify you when the background
|
||||
process completes:
|
||||
|
||||
.. image:: images/import_export_complete.png
|
||||
:alt: Import Export data completion notification
|
||||
:align: center
|
||||
|
||||
Use the **Stop Process** button to stop the Import/Export process.
|
||||
|
||||
Use the *Click here for details* link on the notification to open the *Process
|
||||
Use the *View Processes* button on the notification to open the *Process
|
||||
Watcher* and review detailed information about the execution of the command
|
||||
that performed the import or export:
|
||||
|
||||
Use the **End Process** button to end the Import/Export process.
|
||||
|
||||
.. image:: images/import_export_pw.png
|
||||
:alt: Import Export data process watcher
|
||||
:align: center
|
||||
|
||||
.. note:: If you are running *pgAdmin* in *Server Mode* you can click on the |sm_icon| icon in the process watcher window to open the file location in the Storage Manager. You can use the :ref:`Storage Manager <storage_manager>` to download the backup file on the client machine .
|
||||
.. note:: If you are running *pgAdmin* in *Server Mode* you can click on the |sm_icon| icon in the process watcher window to open the file location in the Storage Manager. You can use the :ref:`Storage Manager <storage_manager>` to download the exported file on the client machine .
|
||||
|
||||
|
||||
.. |sm_icon| image:: images/sm_icon.png
|
||||
@@ -148,41 +148,50 @@ The following example shows both a minimally defined and a fully defined server:
|
||||
"Port": 5432,
|
||||
"Username": "postgres",
|
||||
"Host": "localhost",
|
||||
"SSLMode": "prefer",
|
||||
"MaintenanceDB": "postgres"
|
||||
"MaintenanceDB": "postgres",
|
||||
"ConnectionParameters": {
|
||||
"sslmode": "prefer",
|
||||
"connect_timeout": 10
|
||||
}
|
||||
},
|
||||
"2": {
|
||||
"Name": "Fully Defined Server",
|
||||
"Group": "Server Group 2",
|
||||
"Host": "host.domain.com",
|
||||
"HostAddr": "192.168.1.2",
|
||||
"Port": 5432,
|
||||
"MaintenanceDB": "postgres",
|
||||
"Username": "postgres",
|
||||
"Role": "my_role_name",
|
||||
"SSLMode": "require",
|
||||
"Comment": "This server has every option configured in the JSON",
|
||||
"DBRestriction": "live_db test_db",
|
||||
"PassFile": "/path/to/pgpassfile",
|
||||
"SSLCert": "/path/to/sslcert.crt",
|
||||
"SSLKey": "/path/to/sslcert.key",
|
||||
"SSLRootCert": "/path/to/sslroot.crt",
|
||||
"SSLCrl": "/path/to/sslcrl.crl",
|
||||
"SSLCompression": 1,
|
||||
"Shared": false,
|
||||
"SharedUsername": "postgres",
|
||||
"BGColor": "#ff9900",
|
||||
"FGColor": "#000000",
|
||||
"Service": "postgresql-10",
|
||||
"Timeout": 60,
|
||||
"UseSSHTunnel": 1,
|
||||
"TunnelHost": "192.168.1.253",
|
||||
"TunnelPort": 22,
|
||||
"TunnelUsername": "username",
|
||||
"TunnelAuthentication": 0,
|
||||
"TunnelAuthentication": 1,
|
||||
"TunnelIdentityFile": "/Users/<user>/.ssh/id_rsa.pub",
|
||||
"TunnelKeepAlive": 30,
|
||||
"PasswordExecCommand": "echo 'test'",
|
||||
"PasswordExecExpiration": 100
|
||||
"PasswordExecExpiration": 100,
|
||||
"KerberosAuthentication": true,
|
||||
"ConnectionParameters": {
|
||||
"sslmode": "prefer",
|
||||
"connect_timeout": 10,
|
||||
"passfile": "/Users/<user>/.pgpass",
|
||||
"sslcert": "/Users/<user>/.ssh/cert"
|
||||
},
|
||||
"Tags": [
|
||||
{
|
||||
"color": "#EC0BB4",
|
||||
"text": "Development"
|
||||
}
|
||||
],
|
||||
"PostConnectionSQL": "set timezone='America/New_York'"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,6 +14,7 @@ granting user privileges, and performing VACUUM, ANALYZE and REINDEX functions.
|
||||
add_restore_point_dialog
|
||||
change_password_dialog
|
||||
grant_wizard
|
||||
export_data_using_query
|
||||
import_export_data
|
||||
maintenance_dialog
|
||||
storage_manager
|
||||
@@ -20,4 +20,5 @@ database, right-click on the *Databases* node, and select *Create Database...*
|
||||
tablespace_dialog
|
||||
replica_nodes_dialog
|
||||
pgd_replication_group_dialog
|
||||
role_reassign_dialog
|
||||
role_reassign_dialog
|
||||
directory_dialog
|
||||
@@ -103,44 +103,46 @@ The Tools Menu
|
||||
|
||||
Use the *Tools* menu to access the following options (in alphabetical order):
|
||||
|
||||
+---------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| Option | Action |
|
||||
+===========================+===========================================================================================================================================+
|
||||
| *ERD Tool* | Click to open the :ref:`ERD Tool <erd_tool>` and start designing your database. |
|
||||
+---------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| *Grant Wizard...* | Click to access the :ref:`Grant Wizard <grant_wizard>` tool. |
|
||||
+---------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| *PSQL Tool* | Click to open the :ref:`PSQL Tool <psql_tool>` and start PSQL in the current database context. |
|
||||
+---------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| *Query tool* | Click to open the :ref:`Query tool <query_tool>` for the currently selected object. |
|
||||
+---------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| *Schema Diff* | Click to open the :ref:`Schema Diff <schema_diff_feature>` and start comparing two database or two schema. |
|
||||
+---------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| *Backup Globals...* | Click to open the :ref:`Backup Globals... <backup_globals_dialog>` dialog to backup cluster objects. |
|
||||
+---------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| *Backup Server...* | Click to open the :ref:`Backup Server... <backup_server_dialog>` dialog to backup a server. |
|
||||
+---------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| *Backup...* | Click to open the :ref:`Backup... <backup_dialog>` dialog to backup database objects. |
|
||||
+---------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| *Restore...* | Click to access the :ref:`Restore <restore_dialog>` dialog to restore database files from a backup. |
|
||||
+---------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| *Import/Export Data...* | Click to open the :ref:`Import/Export data... <import_export_data>` dialog to import or export data from a table. |
|
||||
+---------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| *Maintenance...* | Click to open the :ref:`Maintenance... <maintenance_dialog>` dialog to VACUUM, ANALYZE, REINDEX, or CLUSTER. |
|
||||
+---------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| *Search Objects...* | Click to open the :ref:`Search Objects... <search_objects>` and start searching any kind of objects in a database. |
|
||||
+---------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| *Add named restore point* | Click to open the :ref:`Add named restore point... <add_restore_point_dialog>` dialog to take a point-in-time snapshot of the current |
|
||||
| | server state. |
|
||||
+---------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| *Pause replay of WAL* | Click to pause the replay of the WAL log. |
|
||||
+---------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| *Resume replay of WAL* | Click to resume the replay of the WAL log. |
|
||||
+---------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| *Reload Configuration...* | Click to update configuration files without restarting the server. |
|
||||
+---------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| *Storage Manager* | Click to open the :ref:`Storage Manager <storage_manager>` to upload, delete, or download the backup files. |
|
||||
+---------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
+------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| Option | Action |
|
||||
+==============================+===========================================================================================================================================+
|
||||
| *ERD Tool* | Click to open the :ref:`ERD Tool <erd_tool>` and start designing your database. |
|
||||
+------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| *Grant Wizard...* | Click to access the :ref:`Grant Wizard <grant_wizard>` tool. |
|
||||
+------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| *PSQL Tool* | Click to open the :ref:`PSQL Tool <psql_tool>` and start PSQL in the current database context. |
|
||||
+------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| *Query tool* | Click to open the :ref:`Query tool <query_tool>` for the currently selected object. |
|
||||
+------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| *Schema Diff* | Click to open the :ref:`Schema Diff <schema_diff_feature>` and start comparing two database or two schema. |
|
||||
+------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| *Backup Globals...* | Click to open the :ref:`Backup Globals... <backup_globals_dialog>` dialog to backup cluster objects. |
|
||||
+------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| *Backup Server...* | Click to open the :ref:`Backup Server... <backup_server_dialog>` dialog to backup a server. |
|
||||
+------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| *Backup...* | Click to open the :ref:`Backup... <backup_dialog>` dialog to backup database objects. |
|
||||
+------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| *Restore...* | Click to access the :ref:`Restore <restore_dialog>` dialog to restore database files from a backup. |
|
||||
+------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| *Export Data Using Query...* | Click to open the :ref:`Export Data Using Query... <export_data_using_query>` dialog to export data from a table using query. |
|
||||
+------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| *Import/Export Data...* | Click to open the :ref:`Import/Export data... <import_export_data>` dialog to import or export data from a table. |
|
||||
+------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| *Maintenance...* | Click to open the :ref:`Maintenance... <maintenance_dialog>` dialog to VACUUM, ANALYZE, REINDEX, or CLUSTER. |
|
||||
+------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| *Search Objects...* | Click to open the :ref:`Search Objects... <search_objects>` and start searching any kind of objects in a database. |
|
||||
+------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| *Add named restore point* | Click to open the :ref:`Add named restore point... <add_restore_point_dialog>` dialog to take a point-in-time snapshot of the current |
|
||||
| | server state. |
|
||||
+------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| *Pause replay of WAL* | Click to pause the replay of the WAL log. |
|
||||
+------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| *Resume replay of WAL* | Click to resume the replay of the WAL log. |
|
||||
+------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| *Reload Configuration...* | Click to update configuration files without restarting the server. |
|
||||
+------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| *Storage Manager* | Click to open the :ref:`Storage Manager <storage_manager>` to upload, delete, or download the backup files. |
|
||||
+------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
|
||||
The Help Menu
|
||||
*************
|
||||
|
||||
@@ -273,6 +273,24 @@ The Miscellaneous Node
|
||||
|
||||
Expand the *Miscellaneous* node to specify miscellaneous display preferences.
|
||||
|
||||
.. image:: images/preferences_misc_file_downloads.png
|
||||
:alt: Preferences dialog file downloads section
|
||||
:align: center
|
||||
|
||||
Use the fields on the *File Downloads* panel to manage file downloads related preferences.
|
||||
|
||||
* When the *Automatically open downloaded files?* switch is set to *True*
|
||||
the downloaded file will automatically open in the system's default
|
||||
application associated with that file type.
|
||||
|
||||
* When the *Prompt for the download location?* switch is set to *True*
|
||||
a prompt will appear after clicking the download button, allowing you
|
||||
to choose the download location.
|
||||
|
||||
**Note:** File Downloads related settings are applicable and visible only in desktop mode.
|
||||
|
||||
Use the fields on the *User Interface* panel to set the user interface related preferences.
|
||||
|
||||
.. image:: images/preferences_misc_user_interface.png
|
||||
:alt: Preferences dialog user interface section
|
||||
:align: center
|
||||
@@ -286,6 +304,11 @@ Expand the *Miscellaneous* node to specify miscellaneous display preferences.
|
||||
areas for the Query Tool, PSQL, and Schema Diff tools. 'Workspace' layout is
|
||||
the default layout, but user can change it to 'Classic'.
|
||||
|
||||
* When the *Open the Query Tool/PSQL in their respective workspaces* switch is set to *True*
|
||||
then all Query Tool/PSQL tabs will open in their respective workspaces. By default,
|
||||
this setting is False, meaning that Query Tool/PSQL tabs will open in the currently
|
||||
active workspace (either the default or the workspace selected at the time of opening).
|
||||
|
||||
* Use the *Themes* drop-down listbox to select the theme for pgAdmin. You'll also get a preview just below the
|
||||
drop down. You can also submit your own themes,
|
||||
check `here <https://github.com/pgadmin-org/pgadmin4/blob/master/README.md>`_ how.
|
||||
@@ -394,6 +417,14 @@ Use the fields on the *Editor* panel to change settings of the query editor.
|
||||
* When the *Code folding?* switch is set to *False*, the editor will disable
|
||||
code folding. Disabling will improve editor performance with large files.
|
||||
|
||||
* Use the *Font family* field to be used for all SQL editors. The specified
|
||||
font should already be installed on your system. If the font is not found,
|
||||
the editor will fall back to the default font, Source Code Pro.
|
||||
|
||||
* When the *Font ligatures?* switch is set to *True*, ligatures will be
|
||||
enabled in SQL text boxes and editors provided the configured font family
|
||||
supports them.
|
||||
|
||||
* Use the *Font size* field to specify the font size that will be used in text
|
||||
boxes and editors.
|
||||
|
||||
@@ -469,6 +500,9 @@ Use the fields on the *Options* panel to manage editor preferences.
|
||||
editor will prompt the user to saved unsaved data when exiting the data
|
||||
editor.
|
||||
|
||||
* When the *Open the file in a new tab?* switch is set to *True*, the
|
||||
editor will open the new file in new tab of the Query Tool.
|
||||
|
||||
* When the *Prompt to save unsaved query changes?* switch is set to *True*, the
|
||||
editor will prompt the user to saved unsaved query modifications when exiting
|
||||
the Query Tool.
|
||||
@@ -508,6 +542,9 @@ preferences for copied data.
|
||||
setting won't have any effect.
|
||||
* Specify the number of records to fetch in one batch. Changing this value will
|
||||
override DATA_RESULT_ROWS_PER_PAGE setting from config file.
|
||||
* Use the *Max column data display length* to specify the maximum number of
|
||||
characters to be visible in the data output cell. If the data is larger
|
||||
than this value, it will be truncated.
|
||||
* Use the *Result copy field separator* drop-down listbox to select the field
|
||||
separator for copied data.
|
||||
* Use the *Result copy quote character* drop-down listbox to select the quote
|
||||
@@ -661,7 +698,7 @@ The following is an typical example for preferences.json :
|
||||
"browser:display:show_system_objects": true,
|
||||
"browser:display:show_user_defined_templates": true,
|
||||
"browser:display:confirm_on_refresh_close": false,
|
||||
"misc:themes:theme": "dark",
|
||||
"misc:user_interface:theme": "dark",
|
||||
|
||||
}
|
||||
}
|
||||
@@ -42,7 +42,7 @@ Process Watcher
|
||||
|
||||
The Process Watcher logs all the activity associated with the process/task and provides
|
||||
additional information for troubleshooting
|
||||
Use the **Stop Process** button to stop the Backup process.
|
||||
Use the **End Process** button to end the process.
|
||||
|
||||
.. note:: If you are running *pgAdmin* in *Server Mode* you can click on the |sm_icon| icon in the process watcher window to open the file location in the Storage Manager. You can use the :ref:`Storage Manager <storage_manager>` to download the backup file on the client machine .
|
||||
|
||||
|
||||
@@ -29,7 +29,8 @@ File Options
|
||||
+----------------------+---------------------------------------------------------------------------------------------------+----------------+
|
||||
| Icon | Behavior | Shortcut |
|
||||
+======================+===================================================================================================+================+
|
||||
| *Open File* | Click the *Open File* icon to display a previously saved query in the SQL Editor. | Cmd/Ctrl + O |
|
||||
| *Open File* | Click the *Open File* icon to display a previously saved query in the same tab of the SQL Editor. | |
|
||||
| | To open the file in a new tab, select *Open in a new tab?* option from the dropdown. | Cmd/Ctrl + O |
|
||||
+----------------------+---------------------------------------------------------------------------------------------------+----------------+
|
||||
| *Save File* | Click the *Save* icon to perform a quick-save of a previously saved query, or to access the | Cmd/Ctrl + S |
|
||||
| | *Save* menu: | |
|
||||
|
||||
@@ -12,6 +12,10 @@ notes for it.
|
||||
:maxdepth: 1
|
||||
|
||||
|
||||
release_notes_9_4
|
||||
release_notes_9_3
|
||||
release_notes_9_2
|
||||
release_notes_9_1
|
||||
release_notes_9_0
|
||||
release_notes_8_14
|
||||
release_notes_8_13
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
***********
|
||||
Version 9.1
|
||||
***********
|
||||
|
||||
Release date: 2025-02-28
|
||||
|
||||
This release contains a number of bug fixes and new features since the release of pgAdmin 4 v9.0.
|
||||
|
||||
Supported Database Servers
|
||||
**************************
|
||||
**PostgreSQL**: 13, 14, 15, 16 and 17
|
||||
|
||||
**EDB Advanced Server**: 13, 14, 15, 16 and 17
|
||||
|
||||
Bundled PostgreSQL Utilities
|
||||
****************************
|
||||
**psql**, **pg_dump**, **pg_dumpall**, **pg_restore**: 17.2
|
||||
|
||||
|
||||
New features
|
||||
************
|
||||
|
||||
| `Issue #1235 <https://github.com/pgadmin-org/pgadmin4/issues/1235>`_ - Added an option to open the file in a new tab within the query tool.
|
||||
| `Issue #5128 <https://github.com/pgadmin-org/pgadmin4/issues/5128>`_ - Add support for one to one relationship in the ERD tool.
|
||||
| `Issue #8436 <https://github.com/pgadmin-org/pgadmin4/issues/8436>`_ - Enable the ability to close the 'Welcome' tab in the Query Tool/PSQL Workspace.
|
||||
|
||||
Housekeeping
|
||||
************
|
||||
|
||||
| `Issue #8068 <https://github.com/pgadmin-org/pgadmin4/issues/8068>`_ - Added support for Python 3.13
|
||||
|
||||
Bug fixes
|
||||
*********
|
||||
|
||||
| `Issue #8181 <https://github.com/pgadmin-org/pgadmin4/issues/8181>`_ - Fixed an issue where pgAdmin does not support pg_vector column length/precision.
|
||||
| `Issue #8296 <https://github.com/pgadmin-org/pgadmin4/issues/8296>`_ - Fixed an issue where pasting text containing JSON data into the query tool grid would result in incorrect parsing.
|
||||
| `Issue #8341 <https://github.com/pgadmin-org/pgadmin4/issues/8341>`_ - Fixed an issue where the query tool was not treating IDENTITY columns as columns with default values when inserting new rows.
|
||||
| `Issue #8389 <https://github.com/pgadmin-org/pgadmin4/issues/8389>`_ - Fixed an issue where the ERD tool fails to open a saved file containing parent-child relationship within the same table.
|
||||
| `Issue #8410 <https://github.com/pgadmin-org/pgadmin4/issues/8410>`_ - Fixed Docker image entrypoint.sh email validation.
|
||||
| `Issue #8418 <https://github.com/pgadmin-org/pgadmin4/issues/8418>`_ - Fixed an issue where the User Management and Change Password dialogs were hidden when selecting a menu while a workspace other than 'Default' was active.
|
||||
| `Issue #8430 <https://github.com/pgadmin-org/pgadmin4/issues/8430>`_ - Fixed an issue where the column order displayed was incorrect for exclusion constraints with multiple columns.
|
||||
| `Issue #8435 <https://github.com/pgadmin-org/pgadmin4/issues/8435>`_ - Ensure the saved passwords are decrypted with the correct encryption key for external authentication in server mode.
|
||||
| `Issue #8439 <https://github.com/pgadmin-org/pgadmin4/issues/8439>`_ - Fixed an issue where drop-down menus were hidden behind the dock.
|
||||
| `Issue #8460 <https://github.com/pgadmin-org/pgadmin4/issues/8460>`_ - Fixed an issue where deleting rows in the query tool would delete all rows in the table when 'Select All Remaining Rows' was used.
|
||||
@@ -0,0 +1,54 @@
|
||||
***********
|
||||
Version 9.2
|
||||
***********
|
||||
|
||||
Release date: 2025-04-03
|
||||
|
||||
This release contains a number of bug fixes and new features since the release of pgAdmin 4 v9.1.
|
||||
|
||||
Supported Database Servers
|
||||
**************************
|
||||
**PostgreSQL**: 13, 14, 15, 16 and 17
|
||||
|
||||
**EDB Advanced Server**: 13, 14, 15, 16 and 17
|
||||
|
||||
Bundled PostgreSQL Utilities
|
||||
****************************
|
||||
**psql**, **pg_dump**, **pg_dumpall**, **pg_restore**: 17.2
|
||||
|
||||
|
||||
New features
|
||||
************
|
||||
|
||||
| `Issue #0392 <https://github.com/pgadmin-org/pgadmin4/issues/0392>`_ - Added an ability to configure the font family for SQL editors.
|
||||
| `Issue #4194 <https://github.com/pgadmin-org/pgadmin4/issues/4194>`_ - Added support to automatically open a file after it is downloaded in the desktop mode.
|
||||
| `Issue #4503 <https://github.com/pgadmin-org/pgadmin4/issues/4503>`_ - Added support for post-connection SQL execution, which will be run automatically on each connection made to any database of the server.
|
||||
| `Issue #5871 <https://github.com/pgadmin-org/pgadmin4/issues/5871>`_ - Add support for restoring plain SQL database dumps.
|
||||
| `Issue #8034 <https://github.com/pgadmin-org/pgadmin4/issues/8034>`_ - Added support for creating Directory nodes in EPAS.
|
||||
| `Issue #8449 <https://github.com/pgadmin-org/pgadmin4/issues/8449>`_ - Change icon buttons to show tooltip even when disabled.
|
||||
| `Issue #8540 <https://github.com/pgadmin-org/pgadmin4/issues/8540>`_ - Add an option to load/replace the servers.json file on each container startup.
|
||||
| `Issue #8574 <https://github.com/pgadmin-org/pgadmin4/issues/8574>`_ - Open user management in a separate tab instead of a dialog to enhance UI/UX.
|
||||
|
||||
Housekeeping
|
||||
************
|
||||
|
||||
| `Issue #8545 <https://github.com/pgadmin-org/pgadmin4/issues/8545>`_ - Added Security.md file.
|
||||
|
||||
Bug fixes
|
||||
*********
|
||||
|
||||
| `Issue #8316 <https://github.com/pgadmin-org/pgadmin4/issues/8316>`_ - Ensure that modal dialogs are not triggered more than once to avoid duplicates.
|
||||
| `Issue #8355 <https://github.com/pgadmin-org/pgadmin4/issues/8355>`_ - Change session files garbage collection strategy.
|
||||
| `Issue #8362 <https://github.com/pgadmin-org/pgadmin4/issues/8362>`_ - Fixed an issue where pgAdmin should fallback to main screen if the last opened screen is disconnected.
|
||||
| `Issue #8437 <https://github.com/pgadmin-org/pgadmin4/issues/8437>`_ - Fixed an issue where the PSQL terminal displays keyname for non alphanumeric keys.
|
||||
| `Issue #8462 <https://github.com/pgadmin-org/pgadmin4/issues/8462>`_ - Fixed an issue where geometries in the geometry viewer will render partially when the container was resized.
|
||||
| `Issue #8473 <https://github.com/pgadmin-org/pgadmin4/issues/8473>`_ - Change the stop/terminate icon at all the places for better UX.
|
||||
| `Issue #8479 <https://github.com/pgadmin-org/pgadmin4/issues/8479>`_ - Fixed an issue where the Schema Diff was not displaying the difference query when a table had a UNIQUE NULLS NOT DISTINCT constraint.
|
||||
| `Issue #8483 <https://github.com/pgadmin-org/pgadmin4/issues/8483>`_ - Fixed an issue where the query tool data grid did not respect the default value for columns of domain type when the domain had a default value.
|
||||
| `Issue #8514 <https://github.com/pgadmin-org/pgadmin4/issues/8514>`_ - Ensure the newly added parameters in the server dialog are incorporated into the Import/Export Servers functionality.
|
||||
| `Issue #8546 <https://github.com/pgadmin-org/pgadmin4/issues/8546>`_ - Fixed an issue where updating the grantee was not correctly applying the privileges.
|
||||
| `Issue #8577 <https://github.com/pgadmin-org/pgadmin4/issues/8577>`_ - Fixed an issue where the upgrade_check API returned an unexpected keyword argument 'cafile' due to changes in the urllib package supporting Python v3.13.
|
||||
| `Issue #8597 <https://github.com/pgadmin-org/pgadmin4/issues/8597>`_ - Fixed an issue where delete/rename was done on wrong file after sorting in Storage Manager.
|
||||
| `Issue #8602 <https://github.com/pgadmin-org/pgadmin4/issues/8602>`_ - Fixed an XSS vulnerability issue in the Query Tool and View/Edit Data (CVE-2025-2946).
|
||||
| `Issue #8603 <https://github.com/pgadmin-org/pgadmin4/issues/8603>`_ - Fixed a remote code execution issue in the Query Tool and Cloud Deployment (CVE-2025-2945).
|
||||
| `Issue #8623 <https://github.com/pgadmin-org/pgadmin4/issues/8623>`_ - Fixed an issue where query tool is crashing on macOS 15.4 due to a locale issue.
|
||||
@@ -0,0 +1,48 @@
|
||||
***********
|
||||
Version 9.3
|
||||
***********
|
||||
|
||||
Release date: 2025-04-30
|
||||
|
||||
This release contains a number of bug fixes and new features since the release of pgAdmin 4 v9.2.
|
||||
|
||||
Supported Database Servers
|
||||
**************************
|
||||
**PostgreSQL**: 13, 14, 15, 16 and 17
|
||||
|
||||
**EDB Advanced Server**: 13, 14, 15, 16 and 17
|
||||
|
||||
Bundled PostgreSQL Utilities
|
||||
****************************
|
||||
**psql**, **pg_dump**, **pg_dumpall**, **pg_restore**: 17.2
|
||||
|
||||
|
||||
New features
|
||||
************
|
||||
|
||||
| `Issue #2256 <https://github.com/pgadmin-org/pgadmin4/issues/2256>`_ - Add support for type constructors for PostGIS spatial types.
|
||||
| `Issue #2767 <https://github.com/pgadmin-org/pgadmin4/issues/2767>`_ - Added ability to use SQL in the "DB Restriction" field.
|
||||
| `Issue #7310 <https://github.com/pgadmin-org/pgadmin4/issues/7310>`_ - Add support for custom roles and role permissions management in pgAdmin.
|
||||
| `Issue #8629 <https://github.com/pgadmin-org/pgadmin4/issues/8629>`_ - Added support for font ligatures.
|
||||
|
||||
Housekeeping
|
||||
************
|
||||
|
||||
|
||||
Bug fixes
|
||||
*********
|
||||
|
||||
| `Issue #3688 <https://github.com/pgadmin-org/pgadmin4/issues/3688>`_ - Add Cache-Control no-cache,no-store,must-revalidate header to dynamically generated utils.js file.
|
||||
| `Issue #5266 <https://github.com/pgadmin-org/pgadmin4/issues/5266>`_ - Fixed an issue where shift + click on rows/columns for range selection did not work in the query tool data output window.
|
||||
| `Issue #8443 <https://github.com/pgadmin-org/pgadmin4/issues/8443>`_ - Fixed an issue where the debugger hangs when stepping into nested function/procedure.
|
||||
| `Issue #8497 <https://github.com/pgadmin-org/pgadmin4/issues/8497>`_ - Fixed an issue where the scroll position in the Object Explorer was not retained when switching workspaces.
|
||||
| `Issue #8556 <https://github.com/pgadmin-org/pgadmin4/issues/8556>`_ - Ensure that graph data is updated even when the Dashboard tab is inactive.
|
||||
| `Issue #8572 <https://github.com/pgadmin-org/pgadmin4/issues/8572>`_ - Fixed an issue where Ctrl/Cmd+A in cell editor would select all rows.
|
||||
| `Issue #8613 <https://github.com/pgadmin-org/pgadmin4/issues/8613>`_ - Fixed an issue where drag and drop function with no parameters does not work.
|
||||
| `Issue #8627 <https://github.com/pgadmin-org/pgadmin4/issues/8627>`_ - Fixed an issue where changes to foreign key constraints were not detected in the schema diff.
|
||||
| `Issue #8628 <https://github.com/pgadmin-org/pgadmin4/issues/8628>`_ - Change the shortcut for canceling a running query as it conflicts with the shortcut to open a new query tool.
|
||||
| `Issue #8630 <https://github.com/pgadmin-org/pgadmin4/issues/8630>`_ - Fixed an issue where filtering on a view caused an error.
|
||||
| `Issue #8632 <https://github.com/pgadmin-org/pgadmin4/issues/8632>`_ - Fixed an issue where the query tool went blank when converting history dates to the appropriate locale format.
|
||||
| `Issue #8636 <https://github.com/pgadmin-org/pgadmin4/issues/8636>`_ - Ensure that the server list is alphabetically sorted in the Query Tool/PSQL workspace.
|
||||
| `Issue #8651 <https://github.com/pgadmin-org/pgadmin4/issues/8651>`_ - Fixed an issue where the user management tab is not opening in the classic layout.
|
||||
| `Issue #8652 <https://github.com/pgadmin-org/pgadmin4/issues/8652>`_ - Allow OAuth 2 login using the username claim if the email is absent from the user profile.
|
||||
@@ -0,0 +1,44 @@
|
||||
***********
|
||||
Version 9.4
|
||||
***********
|
||||
|
||||
Release date: 2025-05-29
|
||||
|
||||
This release contains a number of bug fixes and new features since the release of pgAdmin 4 v9.3.
|
||||
|
||||
Supported Database Servers
|
||||
**************************
|
||||
**PostgreSQL**: 13, 14, 15, 16 and 17
|
||||
|
||||
**EDB Advanced Server**: 13, 14, 15, 16 and 17
|
||||
|
||||
Bundled PostgreSQL Utilities
|
||||
****************************
|
||||
**psql**, **pg_dump**, **pg_dumpall**, **pg_restore**: 17.2
|
||||
|
||||
|
||||
New features
|
||||
************
|
||||
|
||||
| `Issue #3369 <https://github.com/pgadmin-org/pgadmin4/issues/3369>`_ - Enabled large file downloads for desktop users within the query tool.
|
||||
| `Issue #8583 <https://github.com/pgadmin-org/pgadmin4/issues/8583>`_ - Add all missing options to the Import/Export Data functionality, and update the syntax of the COPY command to align with the latest standards.
|
||||
| `Issue #8681 <https://github.com/pgadmin-org/pgadmin4/issues/8681>`_ - Add support for exporting table data based on a custom query.
|
||||
|
||||
Housekeeping
|
||||
************
|
||||
|
||||
|
||||
Bug fixes
|
||||
*********
|
||||
|
||||
| `Issue #6510 <https://github.com/pgadmin-org/pgadmin4/issues/6510>`_ - Fixed an issue where the result grid slowed down when any column contained a large amount of data.
|
||||
| `Issue #6564 <https://github.com/pgadmin-org/pgadmin4/issues/6564>`_ - Fix the issue where an error is displayed when a table is dropped while a query is running.
|
||||
| `Issue #6968 <https://github.com/pgadmin-org/pgadmin4/issues/6968>`_ - Fixed an issue where the options key was not working as expected in the PSQL tool.
|
||||
| `Issue #7926 <https://github.com/pgadmin-org/pgadmin4/issues/7926>`_ - Fixed an issue where correct error message not displayed when sql statement contains Arabic letters.
|
||||
| `Issue #8595 <https://github.com/pgadmin-org/pgadmin4/issues/8595>`_ - Enhance contrast for selected and hovered items in the Object Explorer to improve visibility and accessibility.
|
||||
| `Issue #8607 <https://github.com/pgadmin-org/pgadmin4/issues/8607>`_ - Fixed an issue where the query tool returns "cannot unpack non-iterable Response object" when running any query with a database name change.
|
||||
| `Issue #8608 <https://github.com/pgadmin-org/pgadmin4/issues/8608>`_ - Handle result grid data changes in View/Edit Data mode by automatically reconnecting to the server if a disconnection occurs.
|
||||
| `Issue #8668 <https://github.com/pgadmin-org/pgadmin4/issues/8668>`_ - Implement API fetch error display for select dropdown.
|
||||
| `Issue #8711 <https://github.com/pgadmin-org/pgadmin4/issues/8711>`_ - Fixed an issue where light theme briefly appears when pgAdmin loads or tools open, even when a dark or system UI theme is preferred.
|
||||
| `Issue #8713 <https://github.com/pgadmin-org/pgadmin4/issues/8713>`_ - Fixed issues related to column range selection using shift + click.
|
||||
| `Issue #8760 <https://github.com/pgadmin-org/pgadmin4/issues/8760>`_ - Fixed an issue where pgAdmin failed to focus when previously unfocused and then quit.
|
||||
@@ -13,7 +13,7 @@ connected to EDB Postgres Advanced Server; for more information about using
|
||||
resource groups, please see the EDB Postgres Advanced Server Guide, available
|
||||
at:
|
||||
|
||||
http://www.enterprisedb.com/
|
||||
https://www.enterprisedb.com/docs/epas/latest/epas_compat_sql/
|
||||
|
||||
Fields used to create a resource group are located on the *General* tab. The
|
||||
*SQL* tab displays the SQL code generated by your selections on the *Resource
|
||||
|
||||
@@ -27,6 +27,8 @@ restore process:
|
||||
|
||||
* Select *Custom or tar* to restore from a custom archive file to create a
|
||||
copy of the backed-up object.
|
||||
* Select *Plain* to restore a plain SQL backup. When selecting this option
|
||||
all the other options will not be applicable.
|
||||
* Select *Directory* to restore from a compressed directory-format archive.
|
||||
|
||||
* Enter the complete path to the backup file in the *Filename* field.
|
||||
|
||||
@@ -195,19 +195,27 @@ Click the *Advanced* tab to continue.
|
||||
|
||||
Use the fields in the *Advanced* tab to configure a connection:
|
||||
|
||||
* Use the *DB restriction* field to provide a SQL restriction that will be used
|
||||
against the pg_database table to limit the databases that you see. For
|
||||
example, you might enter: *live_db test_db* so that only live_db and test_db
|
||||
are shown in the pgAdmin browser. Separate entries with a comma or tab as you
|
||||
type.
|
||||
* Specify the type of the database restriction that will be used to filter
|
||||
out the databases for restriction in the *DB restriction type* field:
|
||||
|
||||
* Select the *Databases* option to specify the name of the databases
|
||||
that will be used against the pg_database table to limit the databases
|
||||
that you see. This is the default.
|
||||
* Select the *SQL* option to provide a SQL restriction that will be used
|
||||
against the pg_database table to limit the databases that you see.
|
||||
|
||||
* Use the *DB restriction* field to provide a SQL restriction OR Database names
|
||||
that will be used against the pg_database table to limit the databases that you see.
|
||||
For example, you might enter: *live_db test_db* so that only live_db and test_db
|
||||
are shown in the pgAdmin object explorer.
|
||||
* Use the *Password exec command* field to specify a shell command to be executed
|
||||
to retrieve a password to be used for SQL authentication. The ``stdout`` of the
|
||||
command will be used as the SQL password. This may be useful when the password
|
||||
should be generated as a transient authorization token instead of providing a
|
||||
password when connecting in `PAM authentication <https://www.postgresql.org/docs/current/auth-pam.html>`_ scenarios.
|
||||
You can pass server hostname, port and DB username to the password exec command as variable by providing placeholders
|
||||
like ``%HOST%``, ``%PORT%`` and ``%USERNAME%`` which will be replace with the server connection information.
|
||||
Example: ``/path/to/script --hostnmae %HOST% --port %PORT% --username %USERNAME%``
|
||||
like ``%HOSTNAME%``, ``%PORT%`` and ``%USERNAME%`` which will be replace with the server connection information.
|
||||
Example: ``/path/to/script --hostname %HOSTNAME% --port %PORT% --username %USERNAME%``
|
||||
* Use the *Password exec expiration* field to specify a maximum age, in seconds,
|
||||
of the password generated with a *Password exec command*. If not specified,
|
||||
the password will not expire until your pgAdmin session does.
|
||||
@@ -225,14 +233,14 @@ Use the fields in the *Advanced* tab to configure a connection:
|
||||
|
||||
.. note:: The Password exec option is only supported when pgAdmin is run in desktop mode.
|
||||
|
||||
* Click the *Save* button to save your work.
|
||||
* Click the *Close* button to exit without saving your work.
|
||||
* Click the *Reset* button to return the values specified on the Server dialog
|
||||
to their original condition.
|
||||
Click the *Post Connection SQL* tab to continue.
|
||||
|
||||
.. toctree::
|
||||
.. image:: images/server_post_connection_sql.png
|
||||
:alt: Server dialog post connection sql tab
|
||||
:align: center
|
||||
|
||||
clear_saved_passwords
|
||||
* Use the *Post Connection SQL* field to write the SQL queries that will be
|
||||
executed in autocommit mode for each connection made to any database on this server.
|
||||
|
||||
|
||||
Click the *Tags* tab to continue.
|
||||
@@ -245,6 +253,15 @@ Use the table in the *Tags* tab to add tags. The tags will be shown on the right
|
||||
a server node label in the object explorer tree.
|
||||
|
||||
Click on the *+* button to add a new tag. Some of the parameters are:
|
||||
* *Text* field to specify the tag name.
|
||||
* *Color* field to select the accent color of the tag.
|
||||
|
||||
* *Text* field to specify the tag name.
|
||||
* *Color* field to select the accent color of the tag.
|
||||
|
||||
* Click the *Save* button to save your work.
|
||||
* Click the *Close* button to exit without saving your work.
|
||||
* Click the *Reset* button to return the values specified on the Server dialog
|
||||
to their original condition.
|
||||
|
||||
.. toctree::
|
||||
|
||||
clear_saved_passwords
|
||||
@@ -1,7 +1,7 @@
|
||||
.. _user_management:
|
||||
|
||||
*******************************
|
||||
`User Management Dialog`:index:
|
||||
`User Management`:index:
|
||||
*******************************
|
||||
|
||||
When invoking pgAdmin in desktop mode, a password is randomly generated, and
|
||||
@@ -9,14 +9,19 @@ then ignored. If you install pgAdmin in server mode, you will be prompted for
|
||||
an administrator email and password for the pgAdmin client.
|
||||
|
||||
When you authenticate with pgAdmin, the server definitions associated with that
|
||||
login role are made available in the tree control. An administrative user can
|
||||
use the *User Management* dialog to:
|
||||
login role are made available in the tree control.
|
||||
|
||||
* add or delete pgAdmin roles
|
||||
* assign privileges
|
||||
* manage the password associated with a role
|
||||
Users Tab
|
||||
*********
|
||||
An administrative user can use the *Users* tab to:
|
||||
|
||||
.. image:: images/user.png
|
||||
* manage pgAdmin users
|
||||
* change users role
|
||||
* change password for a user
|
||||
* deactivate user
|
||||
* unlock a locked user
|
||||
|
||||
.. image:: images/users.png
|
||||
:alt: pgAdmin user management window
|
||||
:align: center
|
||||
|
||||
@@ -26,7 +31,8 @@ the following criteria types: *Authentication source*, *Username*, or *Email*.
|
||||
For example, you can enter *ldap* in the search box and only the records having
|
||||
*ldap* as authentication source will be displayed in the *User Management* table.
|
||||
|
||||
To add a user, click the Add (+) button at the top right corner.
|
||||
To add a user, click the Add (+) button at the top left corner. It will open a
|
||||
dialog where you can fill in details for the new user.
|
||||
|
||||
.. image:: images/add_user.png
|
||||
:alt: pgAdmin user management window add new user
|
||||
@@ -34,34 +40,30 @@ To add a user, click the Add (+) button at the top right corner.
|
||||
|
||||
Provide information about the new pgAdmin role in the row:
|
||||
|
||||
* Use the drop-down list box next to *Authentication source* field to select the
|
||||
type of authentication that should be used for the user. If authentication
|
||||
source is only 'internal' then *Authentication source* field
|
||||
is disabled. Supported *Authentication source* are internal, ldap, kerberos,
|
||||
oauth2 and webserver.
|
||||
* Click in the *Username* field, and provide a username for the user. This field
|
||||
* Use the *Authentication source* field to select the type of authentication that
|
||||
should be used for the user. If authentication source in the pgAdmin server config
|
||||
has 'internal' only then *Authentication source* field will be disabled. Supported
|
||||
*Authentication source* are internal, ldap, kerberos, oauth2 and webserver.
|
||||
* Use the *Username* field to provide a username for the user. This field
|
||||
is enabled only when you select authentication source except *internal*. If you
|
||||
select *internal* as authentication source, your email address is displayed in the
|
||||
username field.
|
||||
* Click in the *Email* field, and provide an email address for the user.
|
||||
* Use the drop-down list box next to *Role* to select whether a user is an
|
||||
*Administrator* or a *User*.
|
||||
|
||||
select *internal* as authentication source, your email address will be taken as
|
||||
the username.
|
||||
* Use the *Email* field to provide an email address for the user. Email is a
|
||||
mandatory field for authentication source *internal*.
|
||||
* Use the *Role* field to select whether a user is an *Administrator* or a *User*.
|
||||
* Select *Administrator* if the user will have administrative privileges
|
||||
within the pgAdmin client.
|
||||
* Select *User* to create a non-administrative user account.
|
||||
|
||||
* Move the *Active* switch to the *No* position if the account is not currently
|
||||
active; the default is *Yes*. Use this switch to disable account activity
|
||||
without deleting an account.
|
||||
* Use the *Active* switch to enable or disable account activity without deleting an
|
||||
account; by default it is enabled.
|
||||
* Use the *New password* field to provide the password associated with the user
|
||||
specified in the *Email* field. This field is disabled if you select any
|
||||
authentication source except *internal*.
|
||||
* Re-enter the password in the *Confirm password* field. This field is disabled
|
||||
if you select *ldap* as authentication source.
|
||||
* *Locked* switch is disabled by default when set to *False*. It is only enabled
|
||||
when the user is locked by trying unsuccessful login attempts. Move the switch
|
||||
to the *False* position if you want to unlock the account.
|
||||
* *Locked* switch cannot be changed if is turned off. It can only be changed
|
||||
when the user is locked by trying unsuccessful login attempts. Turn off the
|
||||
switch if you want to unlock the account.
|
||||
|
||||
To discard a user, and revoke access to pgAdmin, click the trash icon to the
|
||||
left of the row and confirm deletion in the *Delete user?* dialog. If the user
|
||||
@@ -72,9 +74,62 @@ dialog will appear to change the ownership of a shared server.
|
||||
Users with the *Administrator* role are able to add, edit and remove pgAdmin
|
||||
users, but otherwise have the same capabilities as those with the *User* role.
|
||||
|
||||
* Click the *Refresh* button to get latest users list.
|
||||
* Click the *Help* button (?) to access online help.
|
||||
* Click the *Close* button to save work. You will be prompted to return to the
|
||||
dialog if your selections cannot be saved.
|
||||
|
||||
|
||||
Roles Tab
|
||||
*********
|
||||
An administrative user can use the *Roles* tab to:
|
||||
|
||||
* manage pgAdmin roles
|
||||
* delete roles
|
||||
|
||||
.. image:: images/roles.png
|
||||
:alt: pgAdmin roles management window
|
||||
:align: center
|
||||
|
||||
Use the *Search* field to specify criteria and review a list of roles
|
||||
that match the specified criteria. You can enter a value that matches
|
||||
the following criteria types: *Role Name* or *Description*.
|
||||
|
||||
To add a role, click the Add (+) button at the top left corner. It will open a
|
||||
dialog where you can fill in details for the new role.
|
||||
|
||||
.. image:: images/add_role.png
|
||||
:alt: pgAdmin roles management window add new role
|
||||
:align: center
|
||||
|
||||
Provide information about the new pgAdmin role in the row:
|
||||
|
||||
* Use the *Name* field to specify a unique name for the role.
|
||||
* Use the *Description* field to provide a brief description of the role.
|
||||
|
||||
To delete a role, click the trash icon to the left of the row and confirm deletion
|
||||
in the *Delete role?* dialog. If the role is associated with any users or resources,
|
||||
you may need to reassign those associations before deletion.
|
||||
|
||||
Roles allow administrators to group privileges and assign them to users more efficiently.
|
||||
This helps in managing permissions and access control within the pgAdmin client.
|
||||
|
||||
* Click the *Refresh* button to get the latest roles list.
|
||||
* Click the *Help* button (?) to access online help.
|
||||
|
||||
|
||||
Permissions Tab
|
||||
***************
|
||||
An administrative user can use the *Permissions* tab to manage pgAdmin permissions for
|
||||
a role.
|
||||
|
||||
.. image:: images/permissions.png
|
||||
:alt: pgAdmin permissions management window
|
||||
:align: center
|
||||
|
||||
* Filter permissions using the *Search* field by entering names that match the list.
|
||||
* Administrators can select permissions from the list of available permissions, and
|
||||
choose to grant or revoke these permissions for specific roles.
|
||||
* The permissions are applied to the selected role immediately.
|
||||
|
||||
|
||||
|
||||
Using 'setup.py' command line script
|
||||
@@ -107,10 +162,11 @@ email and password. role and active will be optional fields.
|
||||
|
||||
/path/to/python /path/to/setup.py add-user user1@gmail.com password
|
||||
|
||||
# to specify a role, admin and non-admin users:
|
||||
# to specify a role, either you can use --admin for Administrator role or provide the
|
||||
# role using --role. If both are provided --admin will be used:
|
||||
|
||||
/path/to/python /path/to/setup.py add-user user1@gmail.com password --admin
|
||||
/path/to/python /path/to/setup.py add-user user1@gmail.com password --nonadmin
|
||||
/path/to/python /path/to/setup.py add-user user1@gmail.com password --role Users
|
||||
|
||||
# to specify user's status
|
||||
|
||||
@@ -131,10 +187,11 @@ followed by email, password and authentication source. email, role and status wi
|
||||
|
||||
/path/to/python /path/to/setup.py add-external-user ldapuser ldap --email user1@gmail.com
|
||||
|
||||
# to specify a role, admin and non-admin user:
|
||||
# to specify a role, either you can use --admin for Administrator role or provide the
|
||||
# role using --role. If both are provided --admin will be used:
|
||||
|
||||
/path/to/python /path/to/setup.py add-external-user ldapuser ldap --admin
|
||||
/path/to/python /path/to/setup.py add-external-user ldapuser ldap --nonadmin
|
||||
/path/to/python /path/to/setup.py add-external-user ldapuser ldap --role Users
|
||||
|
||||
# to specify user's status
|
||||
|
||||
@@ -151,10 +208,11 @@ email address. password, role and active are updatable fields.
|
||||
|
||||
/path/to/python /path/to/setup.py update-user user1@gmail.com --password new-password
|
||||
|
||||
# to specify a role, admin and non-admin user:
|
||||
# to specify a role, either you can use --admin for Administrator role or provide the
|
||||
# role using --role. If both are provided --admin will be used:
|
||||
|
||||
/path/to/python /path/to/setup.py update-user user1@gmail.com password --role --admin
|
||||
/path/to/python /path/to/setup.py update-user user1@gmail.com password --role --nonadmin
|
||||
/path/to/python /path/to/setup.py update-user user1@gmail.com password --admin
|
||||
/path/to/python /path/to/setup.py update-user user1@gmail.com password --role Users
|
||||
|
||||
# to specify user's status
|
||||
|
||||
@@ -171,17 +229,18 @@ followed by username and auth source. email, password, role and active are updat
|
||||
|
||||
# to change email address:
|
||||
|
||||
/path/to/python /path/to/setup.py update-external-user ldap ldapuser --email newemail@gmail.com
|
||||
/path/to/python /path/to/setup.py update-external-user ldapuser --auth-source ldap --email newemail@gmail.com
|
||||
|
||||
# to specify a role, admin and non-admin user:
|
||||
# to specify a role, either you can use --admin for Administrator role or provide the
|
||||
# role using --role. If both are provided --admin will be used:
|
||||
|
||||
/path/to/python /path/to/setup.py update-user user1@gmail.com password --role --admin
|
||||
/path/to/python /path/to/setup.py update-user user1@gmail.com password --role --nonadmin
|
||||
/path/to/python /path/to/setup.py update-external-user user1@gmail.com password --role --admin
|
||||
/path/to/python /path/to/setup.py update-external-user user1@gmail.com password --role --role Users
|
||||
|
||||
# to change user's status
|
||||
|
||||
/path/to/python /path/to/setup.py update-user ldap ldapuser --active
|
||||
/path/to/python /path/to/setup.py update-user ldap ldapuser --inactive
|
||||
/path/to/python /path/to/setup.py update-user ldapuser --auth-source ldap --active
|
||||
/path/to/python /path/to/setup.py update-user ldapuser --auth-source ldap --inactive
|
||||
|
||||
Delete User
|
||||
***********
|
||||
|
||||
@@ -5,8 +5,8 @@ Debian and Ubuntu.
|
||||
|
||||
## Supported platforms
|
||||
|
||||
* Debian 9, 10 & 11 (testing)
|
||||
* Ubuntu 18.04, 20.04, 20.10
|
||||
* Debian 11 & 12
|
||||
* Ubuntu 22.04, 24.04 & 24.10
|
||||
|
||||
## Build configuration
|
||||
|
||||
|
||||
@@ -72,6 +72,27 @@ if [ -n "${PGADMIN_CONFIG_CONFIG_DATABASE_URI}" ]; then
|
||||
external_config_db_exists=$(cd /pgadmin4/pgadmin/utils && /venv/bin/python3 -c "from check_external_config_db import check_external_config_db; val = check_external_config_db("${PGADMIN_CONFIG_CONFIG_DATABASE_URI}"); print(val)")
|
||||
fi
|
||||
|
||||
# DRY of the code to load the PGADMIN_SERVER_JSON_FILE
|
||||
function load_server_json_file() {
|
||||
export PGADMIN_SERVER_JSON_FILE="${PGADMIN_SERVER_JSON_FILE:-/pgadmin4/servers.json}"
|
||||
|
||||
EXTRA_ARGS=""
|
||||
|
||||
if [ "${PGADMIN_REPLACE_SERVERS_ON_STARTUP}" = "True" ]; then
|
||||
EXTRA_ARGS="--replace"
|
||||
fi
|
||||
|
||||
if [ -f "${PGADMIN_SERVER_JSON_FILE}" ]; then
|
||||
# When running in Desktop mode, no user is created
|
||||
# so we have to import servers anonymously
|
||||
if [ "${PGADMIN_CONFIG_SERVER_MODE}" = "False" ]; then
|
||||
/venv/bin/python3 /pgadmin4/setup.py load-servers "${PGADMIN_SERVER_JSON_FILE}" ${EXTRA_ARGS}
|
||||
else
|
||||
/venv/bin/python3 /pgadmin4/setup.py load-servers "${PGADMIN_SERVER_JSON_FILE}" --user "${PGADMIN_DEFAULT_EMAIL}" ${EXTRA_ARGS}
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
if [ ! -f /var/lib/pgadmin/pgadmin4.db ] && [ "${external_config_db_exists}" = "False" ]; then
|
||||
if [ -z "${PGADMIN_DEFAULT_EMAIL}" ] || { [ -z "${PGADMIN_DEFAULT_PASSWORD}" ] && [ -z "${PGADMIN_DEFAULT_PASSWORD_FILE}" ]; }; then
|
||||
echo 'You need to define the PGADMIN_DEFAULT_EMAIL and PGADMIN_DEFAULT_PASSWORD or PGADMIN_DEFAULT_PASSWORD_FILE environment variables.'
|
||||
@@ -87,11 +108,16 @@ if [ ! -f /var/lib/pgadmin/pgadmin4.db ] && [ "${external_config_db_exists}" = "
|
||||
if [ -n "${PGADMIN_CONFIG_ALLOW_SPECIAL_EMAIL_DOMAINS}" ]; then
|
||||
ALLOW_SPECIAL_EMAIL_DOMAINS=${PGADMIN_CONFIG_ALLOW_SPECIAL_EMAIL_DOMAINS}
|
||||
fi
|
||||
email_config="{'CHECK_EMAIL_DELIVERABILITY': ${CHECK_EMAIL_DELIVERABILITY}, 'ALLOW_SPECIAL_EMAIL_DOMAINS': ${ALLOW_SPECIAL_EMAIL_DOMAINS}}"
|
||||
echo "email config is ${email_config}"
|
||||
GLOBALLY_DELIVERABLE="True"
|
||||
if [ -n "${PGADMIN_CONFIG_GLOBALLY_DELIVERABLE}" ]; then
|
||||
GLOBALLY_DELIVERABLE=${PGADMIN_CONFIG_GLOBALLY_DELIVERABLE}
|
||||
fi
|
||||
email_config="{'CHECK_EMAIL_DELIVERABILITY': ${CHECK_EMAIL_DELIVERABILITY}, 'ALLOW_SPECIAL_EMAIL_DOMAINS': ${ALLOW_SPECIAL_EMAIL_DOMAINS}, 'GLOBALLY_DELIVERABLE': ${GLOBALLY_DELIVERABLE}}"
|
||||
echo "email config is ${email_config}"
|
||||
is_valid_email=$(cd /pgadmin4/pgadmin/utils && /venv/bin/python3 -c "from validation_utils import validate_email; val = validate_email('${PGADMIN_DEFAULT_EMAIL}', ${email_config}); print(val)")
|
||||
if echo "${is_valid_email}" | grep "False" > /dev/null; then
|
||||
echo "'${PGADMIN_DEFAULT_EMAIL}' does not appear to be a valid email address. Please reset the PGADMIN_DEFAULT_EMAIL environment variable and try again."
|
||||
echo "Validation output: ${is_valid_email}"
|
||||
exit 1
|
||||
fi
|
||||
# Switch back to root directory for further process
|
||||
@@ -106,19 +132,11 @@ if [ ! -f /var/lib/pgadmin/pgadmin4.db ] && [ "${external_config_db_exists}" = "
|
||||
# Importing pgadmin4 (from this script) is enough
|
||||
/venv/bin/python3 run_pgadmin.py
|
||||
|
||||
export PGADMIN_SERVER_JSON_FILE="${PGADMIN_SERVER_JSON_FILE:-/pgadmin4/servers.json}"
|
||||
export PGADMIN_PREFERENCES_JSON_FILE="${PGADMIN_PREFERENCES_JSON_FILE:-/pgadmin4/preferences.json}"
|
||||
|
||||
# Pre-load any required servers
|
||||
if [ -f "${PGADMIN_SERVER_JSON_FILE}" ]; then
|
||||
# When running in Desktop mode, no user is created
|
||||
# so we have to import servers anonymously
|
||||
if [ "${PGADMIN_CONFIG_SERVER_MODE}" = "False" ]; then
|
||||
/venv/bin/python3 /pgadmin4/setup.py load-servers "${PGADMIN_SERVER_JSON_FILE}"
|
||||
else
|
||||
/venv/bin/python3 /pgadmin4/setup.py load-servers "${PGADMIN_SERVER_JSON_FILE}" --user "${PGADMIN_DEFAULT_EMAIL}"
|
||||
fi
|
||||
fi
|
||||
load_server_json_file
|
||||
|
||||
# Pre-load any required preferences
|
||||
if [ -f "${PGADMIN_PREFERENCES_JSON_FILE}" ]; then
|
||||
if [ "${PGADMIN_CONFIG_SERVER_MODE}" = "False" ]; then
|
||||
@@ -140,7 +158,9 @@ if [ ! -f /var/lib/pgadmin/pgadmin4.db ] && [ "${external_config_db_exists}" = "
|
||||
chmod 600 /var/lib/pgadmin/storage/${PGADMIN_USER_CONFIG_DIR}/.pgpass
|
||||
fi
|
||||
fi
|
||||
|
||||
# If already initialised and PGADMIN_REPLACE_SERVERS_ON_STARTUP is set to true, then load the server json file.
|
||||
elif [ "${PGADMIN_REPLACE_SERVERS_ON_STARTUP}" = "True" ]; then
|
||||
load_server_json_file
|
||||
fi
|
||||
|
||||
# Start Postfix to handle password resets etc.
|
||||
|
||||
@@ -69,7 +69,6 @@ _create_python_virtualenv() {
|
||||
|
||||
# Make sure we have the wheel package present, as well as the latest pip
|
||||
pip3 install --upgrade pip
|
||||
pip3 install setuptools
|
||||
pip3 install wheel
|
||||
|
||||
# Install the requirements
|
||||
@@ -141,7 +140,8 @@ _build_runtime() {
|
||||
fi
|
||||
|
||||
ELECTRON_VERSION="$(npm info electron version)"
|
||||
ELECTRON_VERSION="33.3.2"
|
||||
# Can't use the latest as it is not compatible with few OS versions.
|
||||
ELECTRON_VERSION="35.4.0"
|
||||
|
||||
pushd "${BUILDROOT}" > /dev/null || exit
|
||||
while true;do
|
||||
|
||||
@@ -34,7 +34,7 @@ _build_runtime() {
|
||||
fi
|
||||
|
||||
ELECTRON_VERSION="$(npm info electron version)"
|
||||
ELECTRON_VERSION="33.3.2"
|
||||
ELECTRON_VERSION="35.4.0"
|
||||
|
||||
pushd "${BUILD_ROOT}" > /dev/null || exit
|
||||
while true;do
|
||||
@@ -138,8 +138,7 @@ _build_docs() {
|
||||
source "${BUILD_ROOT}/venv/bin/activate"
|
||||
pip3 install --upgrade pip
|
||||
pip3 install -r "${SOURCE_DIR}/requirements.txt"
|
||||
# Due to issue https://github.com/sphinx-doc/sphinx/issues/11739, we have pinned the Sphinx version to 6.1.3.
|
||||
pip3 install sphinx==6.1.3
|
||||
pip3 install sphinx==7.4.7
|
||||
pip3 install sphinxcontrib-youtube
|
||||
|
||||
cd "${SOURCE_DIR}" || exit
|
||||
|
||||
@@ -5,7 +5,7 @@ Redhat distributions.
|
||||
|
||||
## Supported platforms
|
||||
|
||||
* Fedora 36 & 37
|
||||
* Fedora 40 & 41
|
||||
* RHEL 8
|
||||
* Rocky Linux 8 (x86_64)
|
||||
* AlmaLinux/RHEL/Rocky Linux 9 (x86_64)
|
||||
|
||||
@@ -39,18 +39,15 @@ yum groupinstall -y "Development Tools"
|
||||
|
||||
if [ "${OS_VERSION}" == "8" ]; then
|
||||
yum install -y expect fakeroot postgresql15-devel python3.9-devel nodejs yarn rpm-build rpm-sign yum-utils krb5-devel
|
||||
# Due to issue https://github.com/sphinx-doc/sphinx/issues/11739, we have pinned the Sphinx version to 6.1.3.
|
||||
pip3.9 install sphinx==6.1.3
|
||||
pip3.9 install sphinx==7.4.7
|
||||
pip3.9 install sphinxcontrib-youtube
|
||||
elif [ "${OS_VERSION}" == "9" ]; then
|
||||
yum install -y expect libpq5-devel postgresql15-devel python3-devel nodejs yarn rpm-build rpm-sign yum-utils krb5-devel
|
||||
# Due to issue https://github.com/sphinx-doc/sphinx/issues/11739, we have pinned the Sphinx version to 6.1.3.
|
||||
pip3 install sphinx==6.1.3
|
||||
pip3 install sphinx==7.4.7
|
||||
pip3 install sphinxcontrib-youtube
|
||||
else
|
||||
yum install -y expect fakeroot postgresql15-devel python3-devel nodejs yarn rpm-build rpm-sign yum-utils krb5-devel
|
||||
# Due to issue https://github.com/sphinx-doc/sphinx/issues/11739, we have pinned the Sphinx version to 6.1.3.
|
||||
pip3 install sphinx==6.1.3
|
||||
pip3 install sphinx==7.4.7
|
||||
pip3 install sphinxcontrib-youtube
|
||||
fi
|
||||
|
||||
|
||||
@@ -6,55 +6,55 @@
|
||||
# *must* ensure the DEB and RPM package maintainers are informed as soon as
|
||||
# possible.
|
||||
#
|
||||
# The packages listed below are sorted alphabetically. It is recommended to add
|
||||
# new packages in alphabetical order. However, exceptions can be made to
|
||||
# preserve dependency order—please add a comment in such cases and specify the
|
||||
# relevant packages.
|
||||
###############################################################################
|
||||
|
||||
Flask==3.0.*; python_version <= '3.8'
|
||||
Flask==3.1.*; python_version >= '3.9'
|
||||
Authlib==1.5.*
|
||||
azure-identity==1.23.0
|
||||
azure-mgmt-rdbms==10.1.0
|
||||
azure-mgmt-resource==23.3.0
|
||||
azure-mgmt-subscription==3.1.1
|
||||
bcrypt==4.3.*
|
||||
boto3==1.38.*
|
||||
cryptography==45.0.*
|
||||
Flask-Babel==4.0.*
|
||||
Flask-Compress==1.*
|
||||
Flask-Login==0.*
|
||||
Flask-Mail==0.*
|
||||
Flask-Migrate==4.*
|
||||
Flask-Paranoid==0.*
|
||||
Flask-Security-Too==5.4.*; python_version <= '3.9'
|
||||
Flask-Security-Too==5.6.*; python_version > '3.9'
|
||||
Flask-SocketIO==5.5.*
|
||||
Flask-SQLAlchemy==3.1.*
|
||||
Flask-WTF==1.2.*
|
||||
Flask-Compress==1.*
|
||||
Flask-Paranoid==0.*
|
||||
Flask-Babel==4.0.*
|
||||
Flask-Security-Too==5.5.*; python_version >= '3.10'
|
||||
Flask-Security-Too==5.4.*; python_version <= '3.9'
|
||||
Flask-SocketIO==5.5.*
|
||||
WTForms==3.2.*; python_version >= '3.10'
|
||||
WTForms==3.1.*; python_version <= '3.9'
|
||||
passlib==1.*
|
||||
pytz==2024.*
|
||||
speaklater3==1.*
|
||||
sqlparse==0.*
|
||||
psutil==6.1.*
|
||||
psycopg[c]==3.2.4
|
||||
python-dateutil==2.*
|
||||
SQLAlchemy==2.*
|
||||
bcrypt==4.2.*
|
||||
cryptography==44.0.*
|
||||
sshtunnel==0.*
|
||||
ldap3==2.*
|
||||
gssapi==1.9.*
|
||||
user-agents==2.2.0
|
||||
pywinpty==2.0.*; sys_platform=="win32"
|
||||
Authlib==1.3.*; python_version <= '3.8'
|
||||
Authlib==1.4.*; python_version >= '3.9'
|
||||
pyotp==2.*
|
||||
qrcode==7.*; python_version <= '3.8'
|
||||
qrcode[pil]==8.*; python_version >= '3.9'
|
||||
boto3==1.36.*
|
||||
urllib3==1.26.*
|
||||
azure-mgmt-rdbms==10.1.0
|
||||
azure-mgmt-resource==23.2.0
|
||||
azure-mgmt-subscription==3.1.1
|
||||
azure-identity==1.19.0
|
||||
Flask==3.1.*
|
||||
google-api-python-client==2.*
|
||||
google-auth-oauthlib==1.2.1
|
||||
keyring==25.*
|
||||
Werkzeug==3.0.*; python_version <= '3.8'
|
||||
Werkzeug==3.1.*; python_version >= '3.9'
|
||||
typer[all]==0.15.*
|
||||
setuptools==75.*; python_version >= '3.12'
|
||||
google-auth-oauthlib==1.2.2
|
||||
gssapi==1.9.*
|
||||
jsonformatter~=0.3.4
|
||||
libgravatar==1.0.*
|
||||
keyring==25.*
|
||||
ldap3==2.*
|
||||
libgravatar==1.0.*
|
||||
passlib==1.*
|
||||
psutil==7.0.*
|
||||
psycopg[c]==3.2.9
|
||||
pyotp==2.*
|
||||
python-dateutil==2.*
|
||||
pytz==2025.*
|
||||
pywinpty==2.0.*; sys_platform=="win32"
|
||||
qrcode[pil]==8.*; python_version >= '3.9'
|
||||
setuptools==80.*; python_version >= '3.12'
|
||||
SQLAlchemy==2.*
|
||||
sqlparse==0.*
|
||||
sshtunnel==0.*
|
||||
typer[all]==0.15.*
|
||||
urllib3==1.26.*; python_version <= '3.9'
|
||||
urllib3==2.4.*; python_version > '3.9'
|
||||
user-agents==2.2.0
|
||||
Werkzeug==3.1.*
|
||||
WTForms==3.1.*; python_version <= '3.9'
|
||||
WTForms==3.2.*; python_version > '3.9'
|
||||
@@ -8,6 +8,7 @@
|
||||
//////////////////////////////////////////////////////////////
|
||||
import globals from 'globals';
|
||||
import js from '@eslint/js';
|
||||
import unusedImports from 'eslint-plugin-unused-imports';
|
||||
|
||||
export default [
|
||||
js.configs.recommended,
|
||||
@@ -34,6 +35,9 @@ export default [
|
||||
'platform': 'readonly',
|
||||
},
|
||||
},
|
||||
'plugins': {
|
||||
'unused-imports': unusedImports,
|
||||
},
|
||||
'rules': {
|
||||
'indent': [
|
||||
'error',
|
||||
@@ -55,6 +59,17 @@ export default [
|
||||
'no-console': ['error', { allow: ['warn', 'error'] }],
|
||||
// We need to exclude below for RegEx case
|
||||
'no-useless-escape': 0,
|
||||
'no-unused-vars': 'off',
|
||||
'unused-imports/no-unused-imports': 'error',
|
||||
'unused-imports/no-unused-vars': [
|
||||
'warn',
|
||||
{
|
||||
'vars': 'all',
|
||||
'varsIgnorePattern': '^_',
|
||||
'args': 'after-used',
|
||||
'argsIgnorePattern': '^_',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
];
|
||||
@@ -12,12 +12,13 @@
|
||||
},
|
||||
"packageManager": "yarn@3.8.7",
|
||||
"devDependencies": {
|
||||
"electron": "33.3.2",
|
||||
"eslint": "^9.19.0"
|
||||
"electron": "36.2.1",
|
||||
"eslint": "^9.27.0",
|
||||
"eslint-plugin-unused-imports": "^4.1.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"axios": "^1.7.9",
|
||||
"electron-context-menu": "^4.0.4",
|
||||
"electron-store": "^10.0.0"
|
||||
"axios": "^1.9.0",
|
||||
"electron-context-menu": "^4.0.5",
|
||||
"electron-store": "^10.0.1"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2025, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
import { app, ipcMain, dialog, BrowserWindow, shell } from 'electron';
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { setBadge, clearBadge, clearProgress, setProgress } from './progress.js';
|
||||
import { writeServerLog } from './misc.js';
|
||||
|
||||
class DownloadItem {
|
||||
constructor(filePath, onUpdate, onRemove) {
|
||||
this.filePath = filePath;
|
||||
this.currentLoaded = 0;
|
||||
this.total = null;
|
||||
this.stream = fs.createWriteStream(filePath);;
|
||||
this.onUpdate = onUpdate;
|
||||
this.onRemove = onRemove;
|
||||
}
|
||||
write(chunk) {
|
||||
this.stream.write(chunk);
|
||||
this.currentLoaded += chunk.length;
|
||||
this.onUpdate?.();
|
||||
}
|
||||
setTotal(total) {
|
||||
this.total = total;
|
||||
}
|
||||
remove() {
|
||||
this.stream.end();
|
||||
this.onRemove?.();
|
||||
}
|
||||
}
|
||||
|
||||
const downloadQueue = {};
|
||||
|
||||
function updateProgress(callerWindow) {
|
||||
let count = Object.keys(downloadQueue).length;
|
||||
if (count === 0) {
|
||||
clearBadge();
|
||||
clearProgress.call(callerWindow);
|
||||
return;
|
||||
}
|
||||
setBadge(Object.keys(downloadQueue).length);
|
||||
let progress = 0;
|
||||
if(Object.values(downloadQueue).some((item) => item.total === null)) {
|
||||
// If any of the items in the queue does not have a total, we cannot calculate progress
|
||||
// so we return 2 to indicate that the progress is indeterminate.
|
||||
progress = 2;
|
||||
} else {
|
||||
const total = Object.values(downloadQueue).reduce((acc, item) => {
|
||||
if (item.total) {
|
||||
return acc + item.currentLoaded / item.total;
|
||||
}
|
||||
return acc + item.currentLoaded;
|
||||
}, 0);
|
||||
progress = total / Object.keys(downloadQueue).length;
|
||||
}
|
||||
setProgress.call(callerWindow, progress);
|
||||
}
|
||||
|
||||
async function fileDownloadPath(callerWindow, options, prompt=true) {
|
||||
let filePath = path.join(app.getPath('downloads'), options.defaultPath);
|
||||
// prompt is true when the user has set the preference to prompt for download location
|
||||
if(prompt) {
|
||||
const result = await dialog.showSaveDialog(callerWindow, {
|
||||
title: 'Save File',
|
||||
...options,
|
||||
});
|
||||
|
||||
if (result.canceled) {
|
||||
return;
|
||||
}
|
||||
filePath = result.filePath;
|
||||
}
|
||||
return filePath;
|
||||
}
|
||||
|
||||
export function setupDownloader() {
|
||||
// Listen for the renderer's request to show the open dialog
|
||||
ipcMain.handle('get-download-stream-path', async (event, options, prompt=true) => {
|
||||
try {
|
||||
const callerWindow = BrowserWindow.fromWebContents(event.sender);
|
||||
const filePath = await fileDownloadPath(callerWindow, options, prompt);
|
||||
downloadQueue[filePath] = new DownloadItem(filePath, () => {
|
||||
updateProgress(callerWindow);
|
||||
}, () => {
|
||||
delete downloadQueue[filePath];
|
||||
updateProgress(callerWindow);
|
||||
});
|
||||
|
||||
updateProgress(callerWindow);
|
||||
|
||||
return filePath;
|
||||
} catch (error) {
|
||||
writeServerLog(`Error in get-download-stream-path: ${error}`);
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.on('download-stream-save-total', (event, filePath, total) => {
|
||||
const item = downloadQueue[filePath];
|
||||
if (item) {
|
||||
item.setTotal(total);
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.on('download-stream-save-chunk', (event, filePath, chunk) => {
|
||||
const item = downloadQueue[filePath];
|
||||
if (item) {
|
||||
item.write(chunk);
|
||||
}
|
||||
});
|
||||
|
||||
ipcMain.on('download-stream-save-end', (event, filePath, openFile=false) => {
|
||||
const item = downloadQueue[filePath];
|
||||
if (item) {
|
||||
item.remove();
|
||||
openFile && shell.openPath(filePath);
|
||||
}
|
||||
});
|
||||
|
||||
// non-streaming direct download
|
||||
ipcMain.handle('download-base64-url-data', async (event, base64url, options, prompt=true, openFile=false) => {
|
||||
const callerWindow = BrowserWindow.fromWebContents(event.sender);
|
||||
const filePath = await fileDownloadPath(callerWindow, options, prompt);
|
||||
const buffer = Buffer.from(base64url.split(',')[1], 'base64');
|
||||
fs.writeFileSync(filePath, buffer);
|
||||
openFile && shell.openPath(filePath);
|
||||
});
|
||||
|
||||
ipcMain.handle('download-text-data', async (event, text, options, prompt=true, openFile=false) => {
|
||||
const callerWindow = BrowserWindow.fromWebContents(event.sender);
|
||||
const filePath = await fileDownloadPath(callerWindow, options, prompt);
|
||||
fs.writeFileSync(filePath, text);
|
||||
openFile && shell.openPath(filePath);
|
||||
});
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
import { app, BrowserWindow, dialog, ipcMain, Menu, shell } from 'electron';
|
||||
import { app, BrowserWindow, dialog, ipcMain, Menu, shell, screen } from 'electron';
|
||||
import axios from 'axios';
|
||||
import Store from 'electron-store';
|
||||
import fs from 'fs';
|
||||
@@ -16,6 +16,7 @@ import { spawn } from 'child_process';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { setupMenu } from './menu.js';
|
||||
import contextMenu from 'electron-context-menu';
|
||||
import { setupDownloader } from './downloader.js';
|
||||
|
||||
const configStore = new Store({
|
||||
defaults: {
|
||||
@@ -30,6 +31,9 @@ let startPageUrl = null;
|
||||
let serverCheckUrl = null;
|
||||
let pgAdminMainScreen = null;
|
||||
|
||||
let configureWindow = null,
|
||||
viewLogWindow = null;
|
||||
|
||||
let serverPort = 5050;
|
||||
let appStartTime = (new Date()).getTime();
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
@@ -75,22 +79,45 @@ contextMenu({
|
||||
|
||||
Menu.setApplicationMenu(null);
|
||||
|
||||
// Check if the given position is within the display bounds.
|
||||
// pgAdmin tried to open the window on the display where the it
|
||||
// was last closed.
|
||||
function isWithinDisplayBounds(pos) {
|
||||
const displays = screen.getAllDisplays();
|
||||
return displays.reduce((result, display) => {
|
||||
const area = display.workArea;
|
||||
return (
|
||||
result ||
|
||||
(pos.x >= area.x &&
|
||||
pos.y >= area.y &&
|
||||
pos.x < area.x + area.width &&
|
||||
pos.y < area.y + area.height)
|
||||
);
|
||||
}, false);
|
||||
}
|
||||
|
||||
function openConfigure() {
|
||||
const win = new BrowserWindow({
|
||||
show: false,
|
||||
width: 600,
|
||||
height: 580,
|
||||
position: 'center',
|
||||
resizable: false,
|
||||
icon: '../../assets/pgAdmin4.png',
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'other_preload.js'),
|
||||
},
|
||||
});
|
||||
win.loadFile('./src/html/configure.html');
|
||||
win.once('ready-to-show', ()=>{
|
||||
win.show();
|
||||
});
|
||||
if (configureWindow === null || configureWindow?.isDestroyed()) {
|
||||
configureWindow = new BrowserWindow({
|
||||
show: false,
|
||||
width: 600,
|
||||
height: 580,
|
||||
position: 'center',
|
||||
resizable: false,
|
||||
parent: pgAdminMainScreen,
|
||||
icon: '../../assets/pgAdmin4.png',
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'other_preload.js'),
|
||||
},
|
||||
});
|
||||
configureWindow.loadFile('./src/html/configure.html');
|
||||
configureWindow.once('ready-to-show', ()=>{
|
||||
configureWindow.show();
|
||||
});
|
||||
} else {
|
||||
configureWindow.hide();
|
||||
configureWindow.show();
|
||||
}
|
||||
}
|
||||
|
||||
function showErrorDialog(intervalID) {
|
||||
@@ -143,8 +170,9 @@ function startDesktopMode() {
|
||||
process.env.PGADMIN_SERVER_MODE = 'OFF';
|
||||
|
||||
// Start Page URL
|
||||
startPageUrl = 'http://127.0.0.1:' + serverPort + '/?key=' + UUID;
|
||||
serverCheckUrl = 'http://127.0.0.1:' + serverPort + '/misc/ping?key=' + UUID;
|
||||
const baseUrl = `http://127.0.0.1:${serverPort}`;
|
||||
startPageUrl = `${baseUrl}/?key=${UUID}`;
|
||||
serverCheckUrl = `${baseUrl}/misc/ping?key=${UUID}`;
|
||||
|
||||
// Write Python Path, pgAdmin file path and command in log file.
|
||||
misc.writeServerLog('pgAdmin Runtime Environment');
|
||||
@@ -281,28 +309,41 @@ function launchPgAdminWindow() {
|
||||
|
||||
setupMenu(pgAdminMainScreen, {
|
||||
'view_logs': ()=>{
|
||||
const win = new BrowserWindow({
|
||||
show: false,
|
||||
width: 800,
|
||||
height: 460,
|
||||
position: 'center',
|
||||
resizable: false,
|
||||
icon: '../../assets/pgAdmin4.png',
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'other_preload.js'),
|
||||
},
|
||||
});
|
||||
win.loadFile('./src/html/view_log.html');
|
||||
win.once('ready-to-show', ()=>{
|
||||
win.show();
|
||||
});
|
||||
if(viewLogWindow === null || viewLogWindow?.isDestroyed()) {
|
||||
viewLogWindow = new BrowserWindow({
|
||||
show: false,
|
||||
width: 800,
|
||||
height: 460,
|
||||
position: 'center',
|
||||
resizable: false,
|
||||
parent: pgAdminMainScreen,
|
||||
icon: '../../assets/pgAdmin4.png',
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'other_preload.js'),
|
||||
},
|
||||
});
|
||||
viewLogWindow.loadFile('./src/html/view_log.html');
|
||||
viewLogWindow.once('ready-to-show', ()=>{
|
||||
viewLogWindow.show();
|
||||
});
|
||||
} else {
|
||||
viewLogWindow.hide();
|
||||
viewLogWindow.show();
|
||||
}
|
||||
},
|
||||
'configure': openConfigure,
|
||||
'reloadApp': reloadApp,
|
||||
});
|
||||
|
||||
setupDownloader();
|
||||
|
||||
pgAdminMainScreen.loadURL(startPageUrl);
|
||||
pgAdminMainScreen.setBounds(configStore.get('bounds'));
|
||||
|
||||
const bounds = configStore.get('bounds');
|
||||
|
||||
(bounds && isWithinDisplayBounds({x: bounds.x, y: bounds.y})) ? pgAdminMainScreen.setBounds(bounds) :
|
||||
pgAdminMainScreen.setBounds({x: 0, y: 0, width: 1024, height: 768});
|
||||
|
||||
pgAdminMainScreen.show();
|
||||
|
||||
pgAdminMainScreen.webContents.setWindowOpenHandler(({url})=>{
|
||||
@@ -365,9 +406,17 @@ ipcMain.on('restartApp', ()=>{
|
||||
app.relaunch();
|
||||
app.exit(0);
|
||||
});
|
||||
ipcMain.on('log', (text) => ()=>{
|
||||
ipcMain.on('log', (_e, text) => ()=>{
|
||||
misc.writeServerLog(text);
|
||||
});
|
||||
ipcMain.on('focus', (e) => {
|
||||
app.focus({steal: true});
|
||||
const callerWindow = BrowserWindow.fromWebContents(e.sender)
|
||||
if (callerWindow) {
|
||||
if (callerWindow.isMinimized()) callerWindow.restore();
|
||||
callerWindow.focus();
|
||||
}
|
||||
});
|
||||
ipcMain.on('reloadApp', reloadApp);
|
||||
ipcMain.handle('checkPortAvailable', async (_e, fixedPort)=>{
|
||||
try {
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
const { contextBridge, ipcRenderer } = require('electron/renderer');
|
||||
|
||||
contextBridge.exposeInMainWorld('electronUI', {
|
||||
focus: () => ipcRenderer.send('focus'),
|
||||
onMenuClick: (callback) => ipcRenderer.on('menu-click', (_event, details) => callback(details)),
|
||||
setMenus: (menus) => {
|
||||
ipcRenderer.send('setMenus', menus);
|
||||
@@ -24,4 +25,11 @@ contextBridge.exposeInMainWorld('electronUI', {
|
||||
showSaveDialog: (options) => ipcRenderer.invoke('showSaveDialog', options),
|
||||
log: (text)=> ipcRenderer.send('log', text),
|
||||
reloadApp: ()=>{ipcRenderer.send('reloadApp');},
|
||||
// Download related functions
|
||||
getDownloadStreamPath: (...args) => ipcRenderer.invoke('get-download-stream-path', ...args),
|
||||
downloadStreamSaveChunk: (...args) => ipcRenderer.send('download-stream-save-chunk', ...args),
|
||||
downloadStreamSaveTotal: (...args) => ipcRenderer.send('download-stream-save-total', ...args),
|
||||
downloadStreamSaveEnd: (...args) => ipcRenderer.send('download-stream-save-end', ...args),
|
||||
downloadBase64UrlData: (...args) => ipcRenderer.invoke('download-base64-url-data', ...args),
|
||||
downloadTextData: (...args) => ipcRenderer.invoke('download-text-data', ...args)
|
||||
});
|
||||
@@ -0,0 +1,39 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2025, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
import { app } from 'electron';
|
||||
|
||||
export function setBadge(count) {
|
||||
const badgeCount = parseInt(count, 10);
|
||||
if (!isNaN(badgeCount)) {
|
||||
app.setBadgeCount(badgeCount);
|
||||
}
|
||||
}
|
||||
|
||||
// Function to clear badge
|
||||
export function clearBadge() {
|
||||
app.setBadgeCount(0);
|
||||
}
|
||||
|
||||
// Function to set progress bar
|
||||
export function setProgress(progress) {
|
||||
const progressValue = parseFloat(progress);
|
||||
if (this && !isNaN(progressValue) && progressValue >= 0 && progressValue <= 1) {
|
||||
this.setProgressBar(progressValue);
|
||||
} else if (this && progress === -1) {
|
||||
this.setProgressBar(-1);
|
||||
}
|
||||
}
|
||||
|
||||
// Function to clear progress
|
||||
export function clearProgress() {
|
||||
if (this) {
|
||||
this.setProgressBar(-1);
|
||||
}
|
||||
}
|
||||
@@ -25,13 +25,13 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"@eslint-community/eslint-utils@npm:^4.2.0":
|
||||
version: 4.4.1
|
||||
resolution: "@eslint-community/eslint-utils@npm:4.4.1"
|
||||
version: 4.7.0
|
||||
resolution: "@eslint-community/eslint-utils@npm:4.7.0"
|
||||
dependencies:
|
||||
eslint-visitor-keys: ^3.4.3
|
||||
peerDependencies:
|
||||
eslint: ^6.0.0 || ^7.0.0 || >=8.0.0
|
||||
checksum: a7ffc838eb6a9ef594cda348458ccf38f34439ac77dc090fa1c120024bcd4eb911dfd74d5ef44d42063e7949fa7c5123ce714a015c4abb917d4124be1bd32bfe
|
||||
checksum: b177e3b75c0b8d0e5d71f1c532edb7e40b31313db61f0c879f9bf19c3abb2783c6c372b5deb2396dab4432f2946b9972122ac682e77010376c029dfd0149c681
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -42,29 +42,36 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@eslint/config-array@npm:^0.19.0":
|
||||
version: 0.19.1
|
||||
resolution: "@eslint/config-array@npm:0.19.1"
|
||||
"@eslint/config-array@npm:^0.20.0":
|
||||
version: 0.20.0
|
||||
resolution: "@eslint/config-array@npm:0.20.0"
|
||||
dependencies:
|
||||
"@eslint/object-schema": ^2.1.5
|
||||
"@eslint/object-schema": ^2.1.6
|
||||
debug: ^4.3.1
|
||||
minimatch: ^3.1.2
|
||||
checksum: 421aad712a5ef1a3d118b5e0857f79c080f9dd619a76ce19d20105d381521583786f7abb1195744af9e62a5124e6657066eb6780e920f4001846bd91c1a665f0
|
||||
checksum: 55824ea31f0502166a6fea97176c9c25089a0354474cdc72a5f739b1cf6925f44f667bf8f4f3a9dabf1112ab0fa671778ca3f96f1499f31ec42caf84cae55005
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@eslint/core@npm:^0.10.0":
|
||||
version: 0.10.0
|
||||
resolution: "@eslint/core@npm:0.10.0"
|
||||
"@eslint/config-helpers@npm:^0.2.1":
|
||||
version: 0.2.2
|
||||
resolution: "@eslint/config-helpers@npm:0.2.2"
|
||||
checksum: 8a4091a2c8af5366513647ccad720f184c1b723f04c086755797a3a5cac69dc9013bc8a75453d9fc188fc4364460f0eae9f1584b77b28082e0d26bf48356ae8f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@eslint/core@npm:^0.14.0":
|
||||
version: 0.14.0
|
||||
resolution: "@eslint/core@npm:0.14.0"
|
||||
dependencies:
|
||||
"@types/json-schema": ^7.0.15
|
||||
checksum: 851fa099b3fef00e7ff8ece14523aff0822d3e1b47b047ab0a0d898e80c1362a22aa8b7778727231c383246932ecb63de79b4448ec1e500901c578580b087573
|
||||
checksum: d68b8282b6f38c5145234f812f18f491d12d716240875591bd54bf5ac32858d979bdf6d38e521997a6e01f2c4223a3e66049714151da7278d0a95ff15b5d46c8
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@eslint/eslintrc@npm:^3.2.0":
|
||||
version: 3.2.0
|
||||
resolution: "@eslint/eslintrc@npm:3.2.0"
|
||||
"@eslint/eslintrc@npm:^3.3.1":
|
||||
version: 3.3.1
|
||||
resolution: "@eslint/eslintrc@npm:3.3.1"
|
||||
dependencies:
|
||||
ajv: ^6.12.4
|
||||
debug: ^4.3.2
|
||||
@@ -75,31 +82,31 @@ __metadata:
|
||||
js-yaml: ^4.1.0
|
||||
minimatch: ^3.1.2
|
||||
strip-json-comments: ^3.1.1
|
||||
checksum: c898e4d12f4c9a79a61ee3c91e38eea5627a04e021cb749191e8537445858bfe32f810eca0cb2dc9902b8ad8b65ca07ef7221dc4bad52afe60cbbf50ec56c236
|
||||
checksum: 8241f998f0857abf5a615072273b90b1244d75c1c45d217c6a8eb444c6e12bbb5506b4879c14fb262eb72b7d8e3d2f0542da2db1a7f414a12496ebb790fb4d62
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@eslint/js@npm:9.19.0":
|
||||
version: 9.19.0
|
||||
resolution: "@eslint/js@npm:9.19.0"
|
||||
checksum: bf4077b390894408408c8b5ca48c2cdaf91bce94e0a3b7ff4e79a2cb2d3ecc76d87b52b30af812285acf550e7a849138d2aad2cab0b0b5c0c9f7944fd45ba31f
|
||||
"@eslint/js@npm:9.27.0":
|
||||
version: 9.27.0
|
||||
resolution: "@eslint/js@npm:9.27.0"
|
||||
checksum: b31cfd61bb64e187f8758d13c893bf710f0500c29ced5dd6958c4fda254059489f1cee69567c20ba21608ce51224019b1fd10975b09d41adf16616d875da6ea4
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@eslint/object-schema@npm:^2.1.5":
|
||||
version: 2.1.5
|
||||
resolution: "@eslint/object-schema@npm:2.1.5"
|
||||
checksum: 5facffc832bae93c510f4d38f0f1cbfebd3d7ec772ece6b801bd09bf2dce52e781f4dea500aa133d02257e04ed6a3958fa18cbaed1f9623974a804ee60a8ca54
|
||||
"@eslint/object-schema@npm:^2.1.6":
|
||||
version: 2.1.6
|
||||
resolution: "@eslint/object-schema@npm:2.1.6"
|
||||
checksum: e32e565319f6544d36d3fa69a3e163120722d12d666d1a4525c9a6f02e9b54c29d9b1f03139e25d7e759e08dda8da433590bc23c09db8d511162157ef1b86a4c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@eslint/plugin-kit@npm:^0.2.5":
|
||||
version: 0.2.5
|
||||
resolution: "@eslint/plugin-kit@npm:0.2.5"
|
||||
"@eslint/plugin-kit@npm:^0.3.1":
|
||||
version: 0.3.1
|
||||
resolution: "@eslint/plugin-kit@npm:0.3.1"
|
||||
dependencies:
|
||||
"@eslint/core": ^0.10.0
|
||||
"@eslint/core": ^0.14.0
|
||||
levn: ^0.4.1
|
||||
checksum: 423db33e67ff16f6db71bf8bfc8d5b0c2c4fe6f2209131e5886a573bf994bfc72ab4f825068d6521f186247731d4c9d48eb42a5e5ce389c6faa275752c0e9459
|
||||
checksum: 8de2438456d9a741c909dd22a60454793c0147e1a13833717e4109c46f5a6b090780e8d9e940a3b3b9bf3643d01a0e726cc74f28ccd7caac95053bb39c2e6c04
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -134,10 +141,10 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@humanwhocodes/retry@npm:^0.4.1":
|
||||
version: 0.4.1
|
||||
resolution: "@humanwhocodes/retry@npm:0.4.1"
|
||||
checksum: f11167c28e8266faba470fd273cbaafe2827523492bc18c5623015adb7ed66f46b2e542e3d756fed9ca614300249267814220c2f5f03a59e07fdfa64fc14ad52
|
||||
"@humanwhocodes/retry@npm:^0.4.2":
|
||||
version: 0.4.3
|
||||
resolution: "@humanwhocodes/retry@npm:0.4.3"
|
||||
checksum: d423455b9d53cf01f778603404512a4246fb19b83e74fe3e28c70d9a80e9d4ae147d2411628907ca983e91a855a52535859a8bb218050bc3f6dbd7a553b7b442
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -170,9 +177,9 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"@types/estree@npm:^1.0.6":
|
||||
version: 1.0.6
|
||||
resolution: "@types/estree@npm:1.0.6"
|
||||
checksum: 8825d6e729e16445d9a1dd2fb1db2edc5ed400799064cd4d028150701031af012ba30d6d03fe9df40f4d7a437d0de6d2b256020152b7b09bde9f2e420afdffd9
|
||||
version: 1.0.7
|
||||
resolution: "@types/estree@npm:1.0.7"
|
||||
checksum: d9312b7075bdd08f3c9e1bb477102f5458aaa42a8eec31a169481ce314ca99ac716645cff4fca81ea65a2294b0276a0de63159d1baca0f8e7b5050a92de950ad
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -199,21 +206,12 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/node@npm:*":
|
||||
version: 22.12.0
|
||||
resolution: "@types/node@npm:22.12.0"
|
||||
"@types/node@npm:*, @types/node@npm:^22.7.7":
|
||||
version: 22.15.19
|
||||
resolution: "@types/node@npm:22.15.19"
|
||||
dependencies:
|
||||
undici-types: ~6.20.0
|
||||
checksum: 2f6dd04abebc456900f7dab2311f63ab361818cd3ecf5078b72c63ed416a38a3e72711669a26cec070e0d2e09d7661976f7d1fa3fc029eb9383f0f7e421a1d55
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/node@npm:^20.9.0":
|
||||
version: 20.17.16
|
||||
resolution: "@types/node@npm:20.17.16"
|
||||
dependencies:
|
||||
undici-types: ~6.19.2
|
||||
checksum: dd19c04c592b602f20448187b4b6ab0293f22173a8bbe53aa3b559188f078b5261d748a107b84ee0580e2074cda760049b13d6e210f9850039bead01cb666a3f
|
||||
undici-types: ~6.21.0
|
||||
checksum: 5aa45bf93c62bba1193bf07a56dddd84b74f89a554a08e1bd7772610f529d8dc6f828d464bc28c10001bd0092b6b3d11736544b52e154f25f5ca0ed93f04c32b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -245,11 +243,11 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"acorn@npm:^8.14.0":
|
||||
version: 8.14.0
|
||||
resolution: "acorn@npm:8.14.0"
|
||||
version: 8.14.1
|
||||
resolution: "acorn@npm:8.14.1"
|
||||
bin:
|
||||
acorn: bin/acorn
|
||||
checksum: 8755074ba55fff94e84e81c72f1013c2d9c78e973c31231c8ae505a5f966859baf654bddd75046bffd73ce816b149298977fff5077a3033dedba0ae2aad152d4
|
||||
checksum: 260d9bb6017a1b6e42d31364687f0258f78eb20210b36ef2baad38fd619d78d4e95ff7dde9b3dbe0d81f137f79a8d651a845363a26e6985997f7b71145dc5e94
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -338,14 +336,14 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"axios@npm:^1.7.9":
|
||||
version: 1.7.9
|
||||
resolution: "axios@npm:1.7.9"
|
||||
"axios@npm:^1.9.0":
|
||||
version: 1.9.0
|
||||
resolution: "axios@npm:1.9.0"
|
||||
dependencies:
|
||||
follow-redirects: ^1.15.6
|
||||
form-data: ^4.0.0
|
||||
proxy-from-env: ^1.1.0
|
||||
checksum: cb8ce291818effda09240cb60f114d5625909b345e10f389a945320e06acf0bc949d0f8422d25720f5dd421362abee302c99f5e97edec4c156c8939814b23d19
|
||||
checksum: 631f02c9c279f2ae90637a4989cc9d75c1c27aefd16b6e8eb90f98a4d0bddaccfd1cb1387be12101d1ab0f9bbf0c47e2451b4de0cf2870462a7d9ed3de8da3f2
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -402,6 +400,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"call-bind-apply-helpers@npm:^1.0.1, call-bind-apply-helpers@npm:^1.0.2":
|
||||
version: 1.0.2
|
||||
resolution: "call-bind-apply-helpers@npm:1.0.2"
|
||||
dependencies:
|
||||
es-errors: ^1.3.0
|
||||
function-bind: ^1.1.2
|
||||
checksum: b2863d74fcf2a6948221f65d95b91b4b2d90cfe8927650b506141e669f7d5de65cea191bf788838bc40d13846b7886c5bc5c84ab96c3adbcf88ad69a72fcdc6b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"callsites@npm:^3.0.0":
|
||||
version: 3.1.0
|
||||
resolution: "callsites@npm:3.1.0"
|
||||
@@ -508,14 +516,14 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.3.1, debug@npm:^4.3.2":
|
||||
version: 4.4.0
|
||||
resolution: "debug@npm:4.4.0"
|
||||
version: 4.4.1
|
||||
resolution: "debug@npm:4.4.1"
|
||||
dependencies:
|
||||
ms: ^2.1.3
|
||||
peerDependenciesMeta:
|
||||
supports-color:
|
||||
optional: true
|
||||
checksum: fb42df878dd0e22816fc56e1fdca9da73caa85212fbe40c868b1295a6878f9101ae684f4eeef516c13acfc700f5ea07f1136954f43d4cd2d477a811144136479
|
||||
checksum: a43826a01cda685ee4cec00fb2d3322eaa90ccadbef60d9287debc2a886be3e835d9199c80070ede75a409ee57828c4c6cd80e4b154f2843f0dc95a570dc0729
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -587,14 +595,25 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"electron-context-menu@npm:^4.0.4":
|
||||
version: 4.0.4
|
||||
resolution: "electron-context-menu@npm:4.0.4"
|
||||
"dunder-proto@npm:^1.0.1":
|
||||
version: 1.0.1
|
||||
resolution: "dunder-proto@npm:1.0.1"
|
||||
dependencies:
|
||||
call-bind-apply-helpers: ^1.0.1
|
||||
es-errors: ^1.3.0
|
||||
gopd: ^1.2.0
|
||||
checksum: 149207e36f07bd4941921b0ca929e3a28f1da7bd6b6ff8ff7f4e2f2e460675af4576eeba359c635723dc189b64cdd4787e0255897d5b135ccc5d15cb8685fc90
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"electron-context-menu@npm:^4.0.5":
|
||||
version: 4.0.5
|
||||
resolution: "electron-context-menu@npm:4.0.5"
|
||||
dependencies:
|
||||
cli-truncate: ^4.0.0
|
||||
electron-dl: ^4.0.0
|
||||
electron-is-dev: ^3.0.1
|
||||
checksum: 43bb4d940f092f143484a02413087671ef2969b7daebc79b6fff544cb912259c4892a342a4c3d6a0aa2c1c4fc9aa07ee7b1c1b86b757e7ae6730f39284d88e68
|
||||
checksum: 4b486b65af658489661685414d605a388c433ca5f8543767310516509351043ffac242a34a66785d9cc68eee90640d765e49fba1237cbaa5c50490dc5509b9af
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -616,7 +635,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"electron-store@npm:^10.0.0":
|
||||
"electron-store@npm:^10.0.1":
|
||||
version: 10.0.1
|
||||
resolution: "electron-store@npm:10.0.1"
|
||||
dependencies:
|
||||
@@ -626,16 +645,16 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"electron@npm:33.3.2":
|
||||
version: 33.3.2
|
||||
resolution: "electron@npm:33.3.2"
|
||||
"electron@npm:36.2.1":
|
||||
version: 36.2.1
|
||||
resolution: "electron@npm:36.2.1"
|
||||
dependencies:
|
||||
"@electron/get": ^2.0.0
|
||||
"@types/node": ^20.9.0
|
||||
"@types/node": ^22.7.7
|
||||
extract-zip: ^2.0.1
|
||||
bin:
|
||||
electron: cli.js
|
||||
checksum: ba3b8cfa0d4dd39e176bf89ec5466045b2f6c59f011de9aae19d3ab17a5d91f2701b5b9244b5877ef49aa41542cc9e72e117c8ea28079485e9be41eb4fcecddf
|
||||
checksum: 01dafd108ce40004329a80f9ca45aba41537ff330f21165b4de93be0b2f46834466f2ffad1de4bd1bf78361e3a79067fec3e782ab2857db84b88432213a25cad
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -669,7 +688,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"es-define-property@npm:^1.0.0":
|
||||
"es-define-property@npm:^1.0.0, es-define-property@npm:^1.0.1":
|
||||
version: 1.0.1
|
||||
resolution: "es-define-property@npm:1.0.1"
|
||||
checksum: 0512f4e5d564021c9e3a644437b0155af2679d10d80f21adaf868e64d30efdfbd321631956f20f42d655fedb2e3a027da479fad3fa6048f768eb453a80a5f80a
|
||||
@@ -683,6 +702,27 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"es-object-atoms@npm:^1.0.0, es-object-atoms@npm:^1.1.1":
|
||||
version: 1.1.1
|
||||
resolution: "es-object-atoms@npm:1.1.1"
|
||||
dependencies:
|
||||
es-errors: ^1.3.0
|
||||
checksum: 214d3767287b12f36d3d7267ef342bbbe1e89f899cfd67040309fc65032372a8e60201410a99a1645f2f90c1912c8c49c8668066f6bdd954bcd614dda2e3da97
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"es-set-tostringtag@npm:^2.1.0":
|
||||
version: 2.1.0
|
||||
resolution: "es-set-tostringtag@npm:2.1.0"
|
||||
dependencies:
|
||||
es-errors: ^1.3.0
|
||||
get-intrinsic: ^1.2.6
|
||||
has-tostringtag: ^1.0.2
|
||||
hasown: ^2.0.2
|
||||
checksum: 789f35de4be3dc8d11fdcb91bc26af4ae3e6d602caa93299a8c45cf05d36cc5081454ae2a6d3afa09cceca214b76c046e4f8151e092e6fc7feeb5efb9e794fc6
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"es6-error@npm:^4.1.1":
|
||||
version: 4.1.1
|
||||
resolution: "es6-error@npm:4.1.1"
|
||||
@@ -711,13 +751,26 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"eslint-scope@npm:^8.2.0":
|
||||
version: 8.2.0
|
||||
resolution: "eslint-scope@npm:8.2.0"
|
||||
"eslint-plugin-unused-imports@npm:^4.1.4":
|
||||
version: 4.1.4
|
||||
resolution: "eslint-plugin-unused-imports@npm:4.1.4"
|
||||
peerDependencies:
|
||||
"@typescript-eslint/eslint-plugin": ^8.0.0-0 || ^7.0.0 || ^6.0.0 || ^5.0.0
|
||||
eslint: ^9.0.0 || ^8.0.0
|
||||
peerDependenciesMeta:
|
||||
"@typescript-eslint/eslint-plugin":
|
||||
optional: true
|
||||
checksum: 1f4ce3e3972699345513840f3af1b783033dbc3a3e85b62ce12b3f6a89fd8c92afe46d0c00af40bacb14465445983ba0ccc326a6fd5132553061fb0e47bcba19
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"eslint-scope@npm:^8.3.0":
|
||||
version: 8.3.0
|
||||
resolution: "eslint-scope@npm:8.3.0"
|
||||
dependencies:
|
||||
esrecurse: ^4.3.0
|
||||
estraverse: ^5.2.0
|
||||
checksum: 750eff4672ca2bf274ec0d1bbeae08aadd53c1907d5c6aff5564d8e047a5f49afa8ae6eee333cab637fd3ebcab2141659d8f2f040f6fdc982b0f61f8bf03136f
|
||||
checksum: 57a58b6716533e25d527089826c4add89a047aecf75e4a88fee05f113ef5a72b85392b304a69bf670646cc3e068354aec70361b9718c2453949a05fc4d9bfe73
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -735,20 +788,21 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"eslint@npm:^9.19.0":
|
||||
version: 9.19.0
|
||||
resolution: "eslint@npm:9.19.0"
|
||||
"eslint@npm:^9.27.0":
|
||||
version: 9.27.0
|
||||
resolution: "eslint@npm:9.27.0"
|
||||
dependencies:
|
||||
"@eslint-community/eslint-utils": ^4.2.0
|
||||
"@eslint-community/regexpp": ^4.12.1
|
||||
"@eslint/config-array": ^0.19.0
|
||||
"@eslint/core": ^0.10.0
|
||||
"@eslint/eslintrc": ^3.2.0
|
||||
"@eslint/js": 9.19.0
|
||||
"@eslint/plugin-kit": ^0.2.5
|
||||
"@eslint/config-array": ^0.20.0
|
||||
"@eslint/config-helpers": ^0.2.1
|
||||
"@eslint/core": ^0.14.0
|
||||
"@eslint/eslintrc": ^3.3.1
|
||||
"@eslint/js": 9.27.0
|
||||
"@eslint/plugin-kit": ^0.3.1
|
||||
"@humanfs/node": ^0.16.6
|
||||
"@humanwhocodes/module-importer": ^1.0.1
|
||||
"@humanwhocodes/retry": ^0.4.1
|
||||
"@humanwhocodes/retry": ^0.4.2
|
||||
"@types/estree": ^1.0.6
|
||||
"@types/json-schema": ^7.0.15
|
||||
ajv: ^6.12.4
|
||||
@@ -756,7 +810,7 @@ __metadata:
|
||||
cross-spawn: ^7.0.6
|
||||
debug: ^4.3.2
|
||||
escape-string-regexp: ^4.0.0
|
||||
eslint-scope: ^8.2.0
|
||||
eslint-scope: ^8.3.0
|
||||
eslint-visitor-keys: ^4.2.0
|
||||
espree: ^10.3.0
|
||||
esquery: ^1.5.0
|
||||
@@ -780,7 +834,7 @@ __metadata:
|
||||
optional: true
|
||||
bin:
|
||||
eslint: bin/eslint.js
|
||||
checksum: 173c77ac3fd8fa69a9367c457f8048088450911f6f927b189bcc2fd1dcca71422346952cdb7217948d692f67b3e36238f5264717187e83a1cdbd1b37b89e3877
|
||||
checksum: 7e2f220574466a6dcd4ebbec19d47a39c3d964bad5bb96706dee7e814d2000d6da78b4515a368515979e1addd59546e24841090101585e5d816c9819077f753c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -930,9 +984,9 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"flatted@npm:^3.2.9":
|
||||
version: 3.3.2
|
||||
resolution: "flatted@npm:3.3.2"
|
||||
checksum: ac3c159742e01d0e860a861164bcfd35bb567ccbebb8a0dd041e61cf3c64a435b917dd1e7ed1c380c2ebca85735fb16644485ec33665bc6aafc3b316aa1eed44
|
||||
version: 3.3.3
|
||||
resolution: "flatted@npm:3.3.3"
|
||||
checksum: 8c96c02fbeadcf4e8ffd0fa24983241e27698b0781295622591fc13585e2f226609d95e422bcf2ef044146ffacb6b68b1f20871454eddf75ab3caa6ee5f4a1fe
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -947,13 +1001,14 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"form-data@npm:^4.0.0":
|
||||
version: 4.0.1
|
||||
resolution: "form-data@npm:4.0.1"
|
||||
version: 4.0.2
|
||||
resolution: "form-data@npm:4.0.2"
|
||||
dependencies:
|
||||
asynckit: ^0.4.0
|
||||
combined-stream: ^1.0.8
|
||||
es-set-tostringtag: ^2.1.0
|
||||
mime-types: ^2.1.12
|
||||
checksum: ccee458cd5baf234d6b57f349fe9cc5f9a2ea8fd1af5ecda501a18fd1572a6dd3bf08a49f00568afd995b6a65af34cb8dec083cf9d582c4e621836499498dd84
|
||||
checksum: e887298b22c13c7c9c5a8ba3716f295a479a13ca78bfd855ef11cbce1bcf22bc0ae2062e94808e21d46e5c667664a1a1a8a7f57d7040193c1fefbfb11af58aab
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -968,6 +1023,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"function-bind@npm:^1.1.2":
|
||||
version: 1.1.2
|
||||
resolution: "function-bind@npm:1.1.2"
|
||||
checksum: 2b0ff4ce708d99715ad14a6d1f894e2a83242e4a52ccfcefaee5e40050562e5f6dafc1adbb4ce2d4ab47279a45dc736ab91ea5042d843c3c092820dfe032efb1
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"get-east-asian-width@npm:^1.0.0":
|
||||
version: 1.3.0
|
||||
resolution: "get-east-asian-width@npm:1.3.0"
|
||||
@@ -975,6 +1037,34 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"get-intrinsic@npm:^1.2.6":
|
||||
version: 1.3.0
|
||||
resolution: "get-intrinsic@npm:1.3.0"
|
||||
dependencies:
|
||||
call-bind-apply-helpers: ^1.0.2
|
||||
es-define-property: ^1.0.1
|
||||
es-errors: ^1.3.0
|
||||
es-object-atoms: ^1.1.1
|
||||
function-bind: ^1.1.2
|
||||
get-proto: ^1.0.1
|
||||
gopd: ^1.2.0
|
||||
has-symbols: ^1.1.0
|
||||
hasown: ^2.0.2
|
||||
math-intrinsics: ^1.1.0
|
||||
checksum: 301008e4482bb9a9cb49e132b88fee093bff373b4e6def8ba219b1e96b60158a6084f273ef5cafe832e42cd93462f4accb46a618d35fe59a2b507f2388c5b79d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"get-proto@npm:^1.0.1":
|
||||
version: 1.0.1
|
||||
resolution: "get-proto@npm:1.0.1"
|
||||
dependencies:
|
||||
dunder-proto: ^1.0.1
|
||||
es-object-atoms: ^1.0.0
|
||||
checksum: 4fc96afdb58ced9a67558698b91433e6b037aaa6f1493af77498d7c85b141382cf223c0e5946f334fb328ee85dfe6edd06d218eaf09556f4bc4ec6005d7f5f7b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"get-stream@npm:^5.1.0":
|
||||
version: 5.2.0
|
||||
resolution: "get-stream@npm:5.2.0"
|
||||
@@ -1024,7 +1114,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"gopd@npm:^1.0.1":
|
||||
"gopd@npm:^1.0.1, gopd@npm:^1.2.0":
|
||||
version: 1.2.0
|
||||
resolution: "gopd@npm:1.2.0"
|
||||
checksum: cc6d8e655e360955bdccaca51a12a474268f95bb793fc3e1f2bdadb075f28bfd1fd988dab872daf77a61d78cbaf13744bc8727a17cfb1d150d76047d805375f3
|
||||
@@ -1073,10 +1163,35 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"has-symbols@npm:^1.0.3, has-symbols@npm:^1.1.0":
|
||||
version: 1.1.0
|
||||
resolution: "has-symbols@npm:1.1.0"
|
||||
checksum: b2316c7302a0e8ba3aaba215f834e96c22c86f192e7310bdf689dd0e6999510c89b00fbc5742571507cebf25764d68c988b3a0da217369a73596191ac0ce694b
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"has-tostringtag@npm:^1.0.2":
|
||||
version: 1.0.2
|
||||
resolution: "has-tostringtag@npm:1.0.2"
|
||||
dependencies:
|
||||
has-symbols: ^1.0.3
|
||||
checksum: 999d60bb753ad714356b2c6c87b7fb74f32463b8426e159397da4bde5bca7e598ab1073f4d8d4deafac297f2eb311484cd177af242776bf05f0d11565680468d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"hasown@npm:^2.0.2":
|
||||
version: 2.0.2
|
||||
resolution: "hasown@npm:2.0.2"
|
||||
dependencies:
|
||||
function-bind: ^1.1.2
|
||||
checksum: e8516f776a15149ca6c6ed2ae3110c417a00b62260e222590e54aa367cbcd6ed99122020b37b7fbdf05748df57b265e70095d7bf35a47660587619b15ffb93db
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"http-cache-semantics@npm:^4.0.0":
|
||||
version: 4.1.1
|
||||
resolution: "http-cache-semantics@npm:4.1.1"
|
||||
checksum: 83ac0bc60b17a3a36f9953e7be55e5c8f41acc61b22583060e8dedc9dd5e3607c823a88d0926f9150e571f90946835c7fe150732801010845c72cd8bbff1a236
|
||||
version: 4.2.0
|
||||
resolution: "http-cache-semantics@npm:4.2.0"
|
||||
checksum: 7a7246ddfce629f96832791176fd643589d954e6f3b49548dadb4290451961237fab8fcea41cd2008fe819d95b41c1e8b97f47d088afc0a1c81705287b4ddbcc
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -1098,12 +1213,12 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"import-fresh@npm:^3.2.1":
|
||||
version: 3.3.0
|
||||
resolution: "import-fresh@npm:3.3.0"
|
||||
version: 3.3.1
|
||||
resolution: "import-fresh@npm:3.3.1"
|
||||
dependencies:
|
||||
parent-module: ^1.0.0
|
||||
resolve-from: ^4.0.0
|
||||
checksum: 2cacfad06e652b1edc50be650f7ec3be08c5e5a6f6d12d035c440a42a8cc028e60a5b99ca08a77ab4d6b1346da7d971915828f33cdab730d3d42f08242d09baa
|
||||
checksum: a06b19461b4879cc654d46f8a6244eb55eb053437afd4cbb6613cad6be203811849ed3e4ea038783092879487299fda24af932b86bdfff67c9055ba3612b8c87
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -1267,6 +1382,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"math-intrinsics@npm:^1.1.0":
|
||||
version: 1.1.0
|
||||
resolution: "math-intrinsics@npm:1.1.0"
|
||||
checksum: 0e513b29d120f478c85a70f49da0b8b19bc638975eca466f2eeae0071f3ad00454c621bf66e16dd435896c208e719fc91ad79bbfba4e400fe0b372e7c1c9c9a2
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"mime-db@npm:1.52.0":
|
||||
version: 1.52.0
|
||||
resolution: "mime-db@npm:1.52.0"
|
||||
@@ -1275,9 +1397,9 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"mime-db@npm:^1.28.0":
|
||||
version: 1.53.0
|
||||
resolution: "mime-db@npm:1.53.0"
|
||||
checksum: 3fd9380bdc0b085d0b56b580e4f89ca4fc3b823722310d795c248f0806b9a80afd5d8f4347f015ad943b9ecfa7cc0b71dffa0db96fa776d01a13474821a2c7fb
|
||||
version: 1.54.0
|
||||
resolution: "mime-db@npm:1.54.0"
|
||||
checksum: e99aaf2f23f5bd607deb08c83faba5dd25cf2fec90a7cc5b92d8260867ee08dab65312e1a589e60093dc7796d41e5fae013268418482f1db4c7d52d0a0960ac9
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -1437,11 +1559,12 @@ __metadata:
|
||||
version: 0.0.0-use.local
|
||||
resolution: "pgadmin4@workspace:."
|
||||
dependencies:
|
||||
axios: ^1.7.9
|
||||
electron: 33.3.2
|
||||
electron-context-menu: ^4.0.4
|
||||
electron-store: ^10.0.0
|
||||
eslint: ^9.19.0
|
||||
axios: ^1.9.0
|
||||
electron: 36.2.1
|
||||
electron-context-menu: ^4.0.5
|
||||
electron-store: ^10.0.1
|
||||
eslint: ^9.27.0
|
||||
eslint-plugin-unused-imports: ^4.1.4
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
@@ -1560,11 +1683,11 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"semver@npm:^7.3.2, semver@npm:^7.6.3":
|
||||
version: 7.6.3
|
||||
resolution: "semver@npm:7.6.3"
|
||||
version: 7.7.2
|
||||
resolution: "semver@npm:7.7.2"
|
||||
bin:
|
||||
semver: bin/semver.js
|
||||
checksum: 4110ec5d015c9438f322257b1c51fe30276e5f766a3f64c09edd1d7ea7118ecbc3f379f3b69032bacf13116dc7abc4ad8ce0d7e2bd642e26b0d271b56b61a7d8
|
||||
checksum: dd94ba8f1cbc903d8eeb4dd8bf19f46b3deb14262b6717d0de3c804b594058ae785ef2e4b46c5c3b58733c99c83339068203002f9e37cfe44f7e2cc5e3d2f621
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -1697,9 +1820,9 @@ __metadata:
|
||||
linkType: hard
|
||||
|
||||
"type-fest@npm:^4.18.2, type-fest@npm:^4.20.0":
|
||||
version: 4.33.0
|
||||
resolution: "type-fest@npm:4.33.0"
|
||||
checksum: 42c9a4e305ef86826f6c3e9fb0d230765523eba248b7927580e76fa0384a4a12dfcde3ba04ac94b3cfab664b16608f1f9b8fb6116a48c728b87350e8252fd32c
|
||||
version: 4.41.0
|
||||
resolution: "type-fest@npm:4.41.0"
|
||||
checksum: 7055c0e3eb188425d07403f1d5dc175ca4c4f093556f26871fe22041bc93d137d54bef5851afa320638ca1379106c594f5aa153caa654ac1a7f22c71588a4e80
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
@@ -1710,17 +1833,10 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"undici-types@npm:~6.19.2":
|
||||
version: 6.19.8
|
||||
resolution: "undici-types@npm:6.19.8"
|
||||
checksum: de51f1b447d22571cf155dfe14ff6d12c5bdaec237c765085b439c38ca8518fc360e88c70f99469162bf2e14188a7b0bcb06e1ed2dc031042b984b0bb9544017
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"undici-types@npm:~6.20.0":
|
||||
version: 6.20.0
|
||||
resolution: "undici-types@npm:6.20.0"
|
||||
checksum: b7bc50f012dc6afbcce56c9fd62d7e86b20a62ff21f12b7b5cbf1973b9578d90f22a9c7fe50e638e96905d33893bf2f9f16d98929c4673c2480de05c6c96ea8b
|
||||
"undici-types@npm:~6.21.0":
|
||||
version: 6.21.0
|
||||
resolution: "undici-types@npm:6.21.0"
|
||||
checksum: 46331c7d6016bf85b3e8f20c159d62f5ae471aba1eb3dc52fff35a0259d58dcc7d592d4cc4f00c5f9243fa738a11cfa48bd20203040d4a9e6bc25e807fab7ab3
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
||||
@@ -0,0 +1,495 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2025, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
"""
|
||||
Parses a pgAdmin release note file in ReStructuredText (RST) format
|
||||
and converts it into Email (HTML), Markdown, and HTML (web) formats.
|
||||
Issue links are always omitted from lists in all outputs.
|
||||
Allows skipping specific issue numbers via command line.
|
||||
The Email HTML output can optionally be saved to a file.
|
||||
|
||||
Usage:
|
||||
python release_converter.py <input_rst_file_path> \\
|
||||
[--output-email-html <output_path.html>] \\
|
||||
[--skip-issues ISSUE_NUM [ISSUE_NUM ...]]
|
||||
|
||||
Examples:
|
||||
# Default: No issue links, don't skip issues, print all to console
|
||||
python release_converter.py path/to/notes.rst
|
||||
|
||||
# Skip issues 8602 and 8603
|
||||
python release_converter.py path/to/notes.rst --skip-issues 8602 8603
|
||||
|
||||
# Save email output, default skip behavior
|
||||
python release_converter.py path/to/notes.rst --output-email-html email.html
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import html
|
||||
import re
|
||||
import sys
|
||||
|
||||
|
||||
# --- PARSING FUNCTION (parse_rst_release_note) ---
|
||||
|
||||
|
||||
def parse_rst_release_note(rst_text):
|
||||
"""Parses the RST release note text to extract key information."""
|
||||
data = {
|
||||
'version': None,
|
||||
'release_date': None,
|
||||
'features': [],
|
||||
'bug_fixes': [],
|
||||
'housekeeping': []
|
||||
}
|
||||
|
||||
version_match = re.search(r'Version\s+([^\n\*]+)', rst_text)
|
||||
if version_match:
|
||||
data['version'] = version_match.group(1).strip()
|
||||
else:
|
||||
print("Warning: Could not parse version.", file=sys.stderr)
|
||||
|
||||
date_match = re.search(r'Release date:\s*(\d{4}-\d{2}-\d{2})', rst_text)
|
||||
if date_match:
|
||||
data['release_date'] = date_match.group(1).strip()
|
||||
else:
|
||||
print("Warning: Could not parse release date.", file=sys.stderr)
|
||||
|
||||
current_section_list = None
|
||||
lines = rst_text.splitlines()
|
||||
|
||||
for i, line_raw in enumerate(lines):
|
||||
line_stripped = line_raw.strip()
|
||||
if i > 0:
|
||||
prev_line_stripped = lines[i - 1].strip()
|
||||
# Check if the previous line looks like an RST section underline
|
||||
if len(prev_line_stripped) > 3 and \
|
||||
all(c == '*' for c in prev_line_stripped):
|
||||
if i > 1:
|
||||
# Header text is two lines above the current line
|
||||
header_text_line = lines[i - 2].strip().lower()
|
||||
if "new features" in header_text_line:
|
||||
current_section_list = data['features']
|
||||
elif "bug fixes" in header_text_line:
|
||||
current_section_list = data['bug_fixes']
|
||||
elif "housekeeping" in header_text_line:
|
||||
current_section_list = data['housekeeping']
|
||||
else:
|
||||
# Not a section we track, keep previous section active
|
||||
pass
|
||||
# Skip the (usually blank) line after the underline
|
||||
continue
|
||||
|
||||
# Parse items only if we are within a known section
|
||||
if current_section_list is not None and line_stripped.startswith('|'):
|
||||
line_to_parse = line_stripped
|
||||
# Try matching the standard 'Issue #' format
|
||||
item_match = re.match(
|
||||
r'\|\s*`Issue\s+#(\d+)\s+<([^>]+)>`_\s*-\s*(.*)',
|
||||
line_to_parse
|
||||
)
|
||||
if item_match:
|
||||
issue_num, url, description = item_match.groups()
|
||||
item_data = {
|
||||
'issue': issue_num.strip(),
|
||||
'url': url.strip(),
|
||||
'description': description.strip().rstrip('.')
|
||||
}
|
||||
current_section_list.append(item_data)
|
||||
else:
|
||||
# Fallback for items starting with '|' but without Issue link
|
||||
simple_match = re.match(r'\|\s*(.*)', line_to_parse)
|
||||
simple_text = (simple_match.group(1).strip().rstrip('.')
|
||||
if simple_match else None)
|
||||
if simple_text:
|
||||
item_data = {
|
||||
'issue': None,
|
||||
'url': None,
|
||||
'description': simple_text
|
||||
}
|
||||
current_section_list.append(item_data)
|
||||
|
||||
# Combine bug fixes and housekeeping for unified output sections
|
||||
data['bugs_housekeeping'] = data['bug_fixes'] + data['housekeeping']
|
||||
|
||||
# Add warnings if sections seem empty after parsing
|
||||
if not data['features']:
|
||||
print("Warning: No 'New features' items parsed.", file=sys.stderr)
|
||||
if not data['bugs_housekeeping']:
|
||||
print("Warning: No 'Bug fixes' or 'Housekeeping' items parsed.",
|
||||
file=sys.stderr)
|
||||
|
||||
return data
|
||||
|
||||
|
||||
# --- Helper for Plurals ---
|
||||
|
||||
|
||||
def pluralize(count, singular, plural=None):
|
||||
"""Adds 's' for pluralization if count is not 1."""
|
||||
if count == 1:
|
||||
return f"{count} {singular}"
|
||||
else:
|
||||
plural_form = plural if plural else singular + 's'
|
||||
return f"{count} {plural_form}"
|
||||
|
||||
|
||||
# --- Formatting Functions ---
|
||||
|
||||
|
||||
def format_email_html(data, skip_issues_set=None):
|
||||
"""Formats the extracted data into HTML suitable for email."""
|
||||
if skip_issues_set is None:
|
||||
skip_issues_set = set()
|
||||
if not data.get('version'):
|
||||
return "<p>Error: Version not found in parsed data.</p>"
|
||||
|
||||
version = data['version']
|
||||
release_url = (
|
||||
f"https://www.pgadmin.org/docs/pgadmin4/{version}/"
|
||||
f"release_notes_{version.replace('.', '_')}.html"
|
||||
)
|
||||
download_url = "https://www.pgadmin.org/download/"
|
||||
website_url = "https://www.pgadmin.org/"
|
||||
|
||||
# Filter lists first based on skip_issues_set
|
||||
filtered_features = [
|
||||
item for item in data.get('features', [])
|
||||
if item.get('issue') not in skip_issues_set
|
||||
]
|
||||
filtered_bugs = [
|
||||
item for item in data.get('bugs_housekeeping', [])
|
||||
if item.get('issue') not in skip_issues_set
|
||||
]
|
||||
num_features = len(filtered_features)
|
||||
num_bugs_housekeeping = len(filtered_bugs)
|
||||
|
||||
# Build HTML output
|
||||
output = f"<h2><strong>pgAdmin 4 v{version} Released</strong></h2>\n"
|
||||
output += (
|
||||
f"<p>The pgAdmin Development Team is pleased to announce "
|
||||
f"pgAdmin 4 version {version}.</p>\n"
|
||||
)
|
||||
output += (
|
||||
f"<p>This release of pgAdmin 4 includes "
|
||||
f"{pluralize(num_features, 'new feature')} and "
|
||||
f"{pluralize(num_bugs_housekeeping, 'bug fix', 'bug fixes')}/"
|
||||
f"housekeeping change"
|
||||
f"{'s' if num_bugs_housekeeping != 1 else ''}. "
|
||||
)
|
||||
output += (
|
||||
f'For more details please see the '
|
||||
f'<a href="{release_url}">Release Notes</a>.</p>\n'
|
||||
)
|
||||
output += (
|
||||
'<p>pgAdmin is the leading Open Source graphical management '
|
||||
'tool for PostgreSQL. For more information, please see</p>\n'
|
||||
)
|
||||
# Note: Removed '	' (HTML tab) as it's non-standard; use CSS if needed
|
||||
output += f'<p><a href="{website_url}">{website_url}</a></p>\n'
|
||||
output += "<p>Notable changes in this release include:</p>\n"
|
||||
|
||||
# Add features section only if items remain after filtering
|
||||
if filtered_features:
|
||||
output += "<p><strong>Features</strong></p>\n<ul>\n"
|
||||
for item in filtered_features:
|
||||
desc = html.escape(item.get('description', 'N/A').strip())
|
||||
output += f" <li>{desc}.</li>\n"
|
||||
output += "</ul>\n"
|
||||
|
||||
# Add bugs section only if items remain after filtering
|
||||
if filtered_bugs:
|
||||
# Note: Heading was "Bugs/Housekeeping" in pasted code,
|
||||
# changed to "Bug fixes" to match GDoc style mentioned earlier
|
||||
output += "<p><strong>Bug fixes</strong></p>\n<ul>\n"
|
||||
for item in filtered_bugs:
|
||||
desc = html.escape(item.get('description', 'N/A').strip())
|
||||
output += f" <li>{desc}.</li>\n"
|
||||
output += "</ul>\n"
|
||||
|
||||
output += (
|
||||
"<p>Builds for Windows and macOS are available now, along with "
|
||||
"a Python Wheel,<br>"
|
||||
)
|
||||
output += (
|
||||
"Docker Container, RPM, DEB Package, and source code tarball from:<br>"
|
||||
)
|
||||
output += f'<a href="{download_url}">{download_url}</a></p>\n'
|
||||
# Note: Adjusted sign-off slightly from pasted code to match GDoc examples
|
||||
output += "<p>--<br>The pgAdmin Team</p>\n"
|
||||
|
||||
return output
|
||||
|
||||
|
||||
def format_markdown(data, skip_issues_set=None):
|
||||
"""Formats the extracted data into Markdown (no issue links in lists)."""
|
||||
if skip_issues_set is None:
|
||||
skip_issues_set = set()
|
||||
if not data.get('version'):
|
||||
return "Error: Version not found in parsed data."
|
||||
|
||||
version = data['version']
|
||||
release_url = (
|
||||
f"https://www.pgadmin.org/docs/pgadmin4/{version}/"
|
||||
f"release_notes_{version.replace('.', '_')}.html"
|
||||
)
|
||||
download_url = "https://www.pgadmin.org/download/"
|
||||
website_url = "https://www.pgadmin.org/"
|
||||
|
||||
filtered_features = [
|
||||
item for item in data.get('features', [])
|
||||
if item.get('issue') not in skip_issues_set
|
||||
]
|
||||
filtered_bugs = [
|
||||
item for item in data.get('bugs_housekeeping', [])
|
||||
if item.get('issue') not in skip_issues_set
|
||||
]
|
||||
num_features = len(filtered_features)
|
||||
num_bugs_housekeeping = len(filtered_bugs)
|
||||
|
||||
output = (
|
||||
f"The pgAdmin Development Team is pleased to announce "
|
||||
f"pgAdmin 4 version {version}. "
|
||||
)
|
||||
output += (
|
||||
f"This release of pgAdmin 4 includes "
|
||||
f"{pluralize(num_features, 'new feature')} and "
|
||||
f"{pluralize(num_bugs_housekeeping, 'bug fix', 'bug fixes')}/"
|
||||
f"housekeeping change"
|
||||
f"{'s' if num_bugs_housekeeping != 1 else ''}. "
|
||||
)
|
||||
output += (f"For more details, "
|
||||
f"please see the [release notes]({release_url}).")
|
||||
# Ensure markdown paragraph break
|
||||
output += "\n \n"
|
||||
output += (
|
||||
f"pgAdmin is the leading Open Source graphical management "
|
||||
f"tool for PostgreSQL. For more information, please see "
|
||||
f"[the website]({website_url})."
|
||||
)
|
||||
output += "\n\n"
|
||||
output += "Notable changes in this release include:\n \n"
|
||||
|
||||
if filtered_features:
|
||||
output += "### Features:\n"
|
||||
for item in filtered_features:
|
||||
desc = item.get('description', 'N/A').strip()
|
||||
output += f"* {desc}.\n" # Link logic removed
|
||||
output += "\n"
|
||||
|
||||
if filtered_bugs:
|
||||
output += "### Bugs/Housekeeping:\n"
|
||||
for item in filtered_bugs:
|
||||
desc = item.get('description', 'N/A').strip()
|
||||
output += f"* {desc}.\n" # Link logic removed
|
||||
output += "\n"
|
||||
|
||||
output += (
|
||||
f"Builds for Windows and macOS are available now, along with "
|
||||
f"a Python Wheel, Docker Container, RPM, DEB Package, and "
|
||||
f"source code tarball from the [download area]({download_url})."
|
||||
)
|
||||
|
||||
return output
|
||||
|
||||
|
||||
def format_html(data, skip_issues_set=None):
|
||||
"""Formats extracted data into HTML for web news articles."""
|
||||
if skip_issues_set is None:
|
||||
skip_issues_set = set()
|
||||
# Removed local import html, using global one
|
||||
|
||||
if not data.get('version'):
|
||||
return "<p>Error: Version not found in parsed data.</p>"
|
||||
|
||||
version = data['version']
|
||||
# Use relative paths for web article links
|
||||
release_url = (
|
||||
f"/docs/pgadmin4/{version}/"
|
||||
f"release_notes_{version.replace('.', '_')}.html"
|
||||
)
|
||||
download_url = "/download"
|
||||
|
||||
filtered_features = [
|
||||
item for item in data.get('features', [])
|
||||
if item.get('issue') not in skip_issues_set
|
||||
]
|
||||
filtered_bugs = [
|
||||
item for item in data.get('bugs_housekeeping', [])
|
||||
if item.get('issue') not in skip_issues_set
|
||||
]
|
||||
num_features = len(filtered_features)
|
||||
num_bugs_housekeeping = len(filtered_bugs)
|
||||
|
||||
output = (
|
||||
f"<p>The pgAdmin Development Team is pleased to announce "
|
||||
f"pgAdmin 4 version {version}. "
|
||||
)
|
||||
output += (
|
||||
f"This release of pgAdmin 4 includes "
|
||||
f"{pluralize(num_features, 'new feature')} and "
|
||||
f"{pluralize(num_bugs_housekeeping, 'bug fix', 'bug fixes')}/"
|
||||
f"housekeeping change"
|
||||
f"{'s' if num_bugs_housekeeping != 1 else ''}. "
|
||||
)
|
||||
output += (
|
||||
f'For more details, please see the '
|
||||
f'<a href="{release_url}">release notes</a>.</p>\n'
|
||||
)
|
||||
output += "<p>Notable changes in this release include:</p>\n"
|
||||
|
||||
if filtered_features:
|
||||
output += "<p><strong>Features:</strong></p>\n<ul>\n"
|
||||
for item in filtered_features:
|
||||
desc = html.escape(item.get('description', 'N/A').strip())
|
||||
# Link logic removed, keep bolding for features in news format
|
||||
output += f" <li><strong>{desc}.</strong></li>\n"
|
||||
output += "</ul>\n"
|
||||
|
||||
if filtered_bugs:
|
||||
output += "<p><strong>Bugs/Housekeeping:</strong></p>\n<ul>\n"
|
||||
for item in filtered_bugs:
|
||||
desc = html.escape(item.get('description', 'N/A').strip())
|
||||
# Link logic removed, no bolding for bugs in news format
|
||||
output += f" <li>{desc}.</li>\n"
|
||||
output += "</ul>\n"
|
||||
|
||||
output += f'<p><a href="{download_url}">Download</a> your copy now!</p>'
|
||||
|
||||
return output
|
||||
|
||||
|
||||
# --- Main Execution ---
|
||||
if __name__ == "__main__":
|
||||
# --- Setup Argument Parser ---
|
||||
parser = argparse.ArgumentParser(
|
||||
description=(
|
||||
"Converts pgAdmin RST release notes to Email (HTML), Markdown, "
|
||||
"and HTML (web) formats.\nIssue links are omitted from lists. "
|
||||
"Allows skipping specific issues."
|
||||
),
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
epilog=(
|
||||
"Examples:\n"
|
||||
" # Default: Don't skip issues\n"
|
||||
" python release_converter.py path/to/notes.rst\n\n"
|
||||
" # Skip issues 8602 and 8603\n"
|
||||
" python release_converter.py path/to/notes.rst "
|
||||
"--skip-issues 8602 8603\n\n"
|
||||
" # Save email output, default skip behavior\n"
|
||||
" python release_converter.py path/to/notes.rst "
|
||||
"--output-email-html email.html"
|
||||
)
|
||||
)
|
||||
parser.add_argument(
|
||||
"input_file",
|
||||
metavar="<input_rst_file_path>",
|
||||
type=str,
|
||||
help="Path to the input ReStructuredText (.rst) release note file."
|
||||
)
|
||||
parser.add_argument(
|
||||
"--output-email-html",
|
||||
metavar="<email_output_path.html>",
|
||||
type=str,
|
||||
default=None, # Use None as default for optional args
|
||||
help="Optional path to save the Email HTML output to a file."
|
||||
)
|
||||
parser.add_argument(
|
||||
"--skip-issues",
|
||||
metavar="ISSUE_NUM",
|
||||
type=str,
|
||||
nargs='+', # Expect 1 or more arguments
|
||||
default=None, # Default to None if not provided
|
||||
help="List of issue numbers (e.g., 8602 8603) to skip from lists."
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
# --- Read Input File ---
|
||||
input_rst_content = ""
|
||||
try:
|
||||
with open(args.input_file, "r", encoding="utf-8") as f:
|
||||
input_rst_content = f.read()
|
||||
print(f"Successfully read file: {args.input_file}", file=sys.stderr)
|
||||
except FileNotFoundError:
|
||||
print(f"Error: Input file not found at '{args.input_file}'",
|
||||
file=sys.stderr)
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"Error reading file '{args.input_file}': {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
# --- Parse the input data ---
|
||||
print("Parsing release notes...", file=sys.stderr)
|
||||
parsed_data = parse_rst_release_note(input_rst_content)
|
||||
|
||||
if not parsed_data.get('version'):
|
||||
print("\nError: Parsing failed to find version. Cannot proceed.",
|
||||
file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
# --- Create skip set ---
|
||||
# Handle default=None for skip_issues
|
||||
skip_issues_set = set(args.skip_issues) if args.skip_issues else set()
|
||||
if skip_issues_set:
|
||||
print(f"Attempting to skip issues: "
|
||||
f"{', '.join(sorted(list(skip_issues_set)))}", file=sys.stderr)
|
||||
|
||||
# --- Generate the different formats ---
|
||||
print("Generating output formats...", file=sys.stderr)
|
||||
email_html_output = format_email_html(
|
||||
parsed_data, skip_issues_set=skip_issues_set
|
||||
)
|
||||
markdown_output = format_markdown(
|
||||
parsed_data, skip_issues_set=skip_issues_set
|
||||
)
|
||||
news_html_output = format_html(
|
||||
parsed_data, skip_issues_set=skip_issues_set
|
||||
)
|
||||
print("Format generation complete.", file=sys.stderr)
|
||||
|
||||
# --- Handle Outputs ---
|
||||
if args.output_email_html:
|
||||
try:
|
||||
output_filename = args.output_email_html
|
||||
# Recommend .html extension, but allow user override
|
||||
if not output_filename.lower().endswith(('.html', '.htm')):
|
||||
print(f"Warning: Output file '{output_filename}' does not end "
|
||||
f"with .html or .htm. The content is HTML.",
|
||||
file=sys.stderr)
|
||||
|
||||
with open(output_filename, "w", encoding="utf-8") as f:
|
||||
f.write(email_html_output)
|
||||
print(f"Email HTML output successfully "
|
||||
f"saved to: {output_filename}",
|
||||
file=sys.stderr)
|
||||
except Exception as e:
|
||||
print(f"Error writing Email HTML output to file "
|
||||
f"'{args.output_email_html}': {e}", file=sys.stderr)
|
||||
# Print to console as fallback if write fails
|
||||
print("\n--- Email HTML Output ---")
|
||||
print(email_html_output)
|
||||
print("\n---------------------------------\n")
|
||||
else:
|
||||
# Default: Print email HTML to console
|
||||
print("\n--- Email HTML Output ---")
|
||||
print(email_html_output)
|
||||
print("\n---------------------------------\n")
|
||||
|
||||
# --- Output Other Formats (always to console) ---
|
||||
print("--- Markdown Output ---")
|
||||
print(markdown_output)
|
||||
print("\n---------------------------------\n")
|
||||
|
||||
print("--- News Article HTML Output ---")
|
||||
print(news_html_output)
|
||||
print("\n---------------------------------\n")
|
||||
|
||||
print("Script finished.", file=sys.stderr)
|
||||
@@ -1,6 +1,5 @@
|
||||
requests>=2.21.0
|
||||
requests[security]>=2.21.0
|
||||
safety>=1.9.0
|
||||
# Due to issue https://github.com/sphinx-doc/sphinx/issues/11739, we have pinned the Sphinx version to 6.1.3.
|
||||
Sphinx==6.1.3
|
||||
Sphinx==7.4.7
|
||||
sphinxcontrib-youtube==1.4.1
|
||||
@@ -18,8 +18,8 @@ pip install --upgrade pip
|
||||
if [ ${TEST} -eq 1 ];
|
||||
then
|
||||
echo Installing requirements for running Python tests...
|
||||
pip install --no-cache-dir wheel sphinx==6.1.3 sphinxcontrib-youtube -r web/regression/requirements.txt || { echo 'ERROR: Failed to install Python requirements.' ; exit 1; }
|
||||
pip install --no-cache-dir wheel sphinx==7.4.7 sphinxcontrib-youtube -r web/regression/requirements.txt || { echo 'ERROR: Failed to install Python requirements.' ; exit 1; }
|
||||
else
|
||||
echo Installing requirements for executing and building only...
|
||||
pip install --no-cache-dir wheel sphinx==6.1.3 sphinxcontrib-youtube -r requirements.txt || { echo 'ERROR: Failed to install Python requirements.' ; exit 1; }
|
||||
pip install --no-cache-dir wheel sphinx==7.4.7 sphinxcontrib-youtube -r requirements.txt || { echo 'ERROR: Failed to install Python requirements.' ; exit 1; }
|
||||
fi
|
||||
@@ -402,7 +402,8 @@ CHECK_EMAIL_DELIVERABILITY = False
|
||||
SECURITY_EMAIL_VALIDATOR_ARGS = \
|
||||
{"check_deliverability": CHECK_EMAIL_DELIVERABILITY}
|
||||
ALLOW_SPECIAL_EMAIL_DOMAINS = []
|
||||
|
||||
# Disables global deliverable check while email validation
|
||||
GLOBALLY_DELIVERABLE = True
|
||||
##########################################################################
|
||||
# Upgrade checks
|
||||
##########################################################################
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2025, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
"""
|
||||
|
||||
Revision ID: 1f0eddc8fc79
|
||||
Revises: e982c040d9b5
|
||||
Create Date: 2025-03-26 15:58:24.131719
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from pgadmin.utils.constants import RESTRICTION_TYPE_DATABASES
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = '1f0eddc8fc79'
|
||||
down_revision = 'e982c040d9b5'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.add_column('server',
|
||||
sa.Column('db_res_type', sa.String(length=32),
|
||||
server_default=RESTRICTION_TYPE_DATABASES))
|
||||
|
||||
# For adding custom role permissions
|
||||
op.add_column('role', sa.Column('permissions', sa.Text()))
|
||||
|
||||
# get metadata from current connection
|
||||
meta = sa.MetaData()
|
||||
# define table representation
|
||||
meta.reflect(op.get_bind(), only=('role',))
|
||||
role_table = sa.Table('role', meta)
|
||||
|
||||
from pgadmin.tools.user_management.PgAdminPermissions import AllPermissionTypes
|
||||
op.execute(
|
||||
role_table.update().where(role_table.c.name == 'User')
|
||||
.values(permissions=",".join(AllPermissionTypes.list())))
|
||||
|
||||
|
||||
def downgrade():
|
||||
# pgAdmin only upgrades, downgrade not implemented.
|
||||
pass
|
||||
@@ -0,0 +1,33 @@
|
||||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2025, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
"""
|
||||
|
||||
Revision ID: e982c040d9b5
|
||||
Revises: 255e2842e4d7
|
||||
Create Date: 2025-03-13 16:55:26.893395
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'e982c040d9b5'
|
||||
down_revision = '255e2842e4d7'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.add_column('server', sa.Column('post_connection_sql', sa.String()))
|
||||
|
||||
|
||||
def downgrade():
|
||||
# pgAdmin only upgrades, downgrade not implemented.
|
||||
pass
|
||||
@@ -9,11 +9,11 @@
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.10.2",
|
||||
"@babel/eslint-parser": "^7.26.5",
|
||||
"@babel/eslint-plugin": "^7.24.7",
|
||||
"@babel/eslint-plugin": "^7.26.10",
|
||||
"@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/plugin-transform-runtime": "^7.27.1",
|
||||
"@babel/preset-env": "^7.27.2",
|
||||
"@babel/preset-typescript": "^7.24.7",
|
||||
"@emotion/memoize": "^0.9.0",
|
||||
"@emotion/react": "^11.11.3",
|
||||
@@ -22,24 +22,24 @@
|
||||
"@svgr/webpack": "^8.1.0",
|
||||
"@testing-library/dom": "10.4.0",
|
||||
"@testing-library/jest-dom": "^6.6.3",
|
||||
"@testing-library/react": "16.2.0",
|
||||
"@testing-library/react": "16.3.0",
|
||||
"@testing-library/user-event": "^14.5.2",
|
||||
"@types/jest": "^29.5.4",
|
||||
"autoprefixer": "^10.2.4",
|
||||
"autoprefixer": "^10.4.21",
|
||||
"axios-mock-adapter": "^2.1.0",
|
||||
"babel-loader": "^9.1.3",
|
||||
"babel-loader": "^10.0.0",
|
||||
"browserify": "^17.0.0",
|
||||
"buffer": "^6.0.3",
|
||||
"copy-webpack-plugin": "^12.0.2",
|
||||
"copy-webpack-plugin": "^13.0.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"css-loader": "^7.1.2",
|
||||
"css-minimizer-webpack-plugin": "^7.0.0",
|
||||
"eslint": "^9.19.0",
|
||||
"eslint": "^9.27.0",
|
||||
"eslint-plugin-jest": "^28.10.0",
|
||||
"eslint-plugin-react": "^7.37.3",
|
||||
"eslint-plugin-react": "^7.37.5",
|
||||
"eslint-plugin-unused-imports": "^4.1.4",
|
||||
"exports-loader": "^5.0.0",
|
||||
"globals": "^15.13.0",
|
||||
"globals": "^16.1.0",
|
||||
"html-react-parser": "^5.2.0",
|
||||
"image-minimizer-webpack-plugin": "^4.0.2",
|
||||
"imagemin": "^9.0.0",
|
||||
@@ -59,12 +59,12 @@
|
||||
"stylis": "^4.3.4",
|
||||
"svgo": "^3.3.2",
|
||||
"svgo-loader": "^4.0.0",
|
||||
"terser-webpack-plugin": "^5.1.1",
|
||||
"terser-webpack-plugin": "^5.3.12",
|
||||
"typescript": "^5.4.5",
|
||||
"typescript-eslint": "^8.8.0",
|
||||
"typescript-eslint": "^8.28.0",
|
||||
"url-loader": "^4.1.1",
|
||||
"webfonts-loader": "^8.0.1",
|
||||
"webpack": "^5.88.2",
|
||||
"webpack": "^5.98.0",
|
||||
"webpack-bundle-analyzer": "^4.8.0",
|
||||
"webpack-cli": "^6.0.1",
|
||||
"yarn-audit-html": "7.3.2"
|
||||
@@ -78,16 +78,15 @@
|
||||
"@date-io/date-fns": "3.x",
|
||||
"@emotion/sheet": "^1.0.1",
|
||||
"@fortawesome/fontawesome-free": "latest",
|
||||
"@mui/icons-material": "^6.4.0",
|
||||
"@mui/lab": "^6.0.0-beta.16",
|
||||
"@mui/material": "^6.1.10",
|
||||
"@mui/x-date-pickers": "^7.23.2",
|
||||
"@mui/icons-material": "^7.1.0",
|
||||
"@mui/material": "^7.1.0",
|
||||
"@mui/x-date-pickers": "^8.3.1",
|
||||
"@projectstorm/react-diagrams": "^7.0.4",
|
||||
"@simonwep/pickr": "^1.5.1",
|
||||
"@szhsin/react-menu": "^4.2.2",
|
||||
"@tanstack/react-query": "5.64.2",
|
||||
"@szhsin/react-menu": "^4.4.0",
|
||||
"@tanstack/react-query": "5.76.0",
|
||||
"@tanstack/react-table": "^8.16.0",
|
||||
"@tanstack/react-virtual": "^3.8.4",
|
||||
"@tanstack/react-virtual": "^3.13.6",
|
||||
"@types/classnames": "^2.3.4",
|
||||
"@types/react": "^18.0.2",
|
||||
"@types/react-dom": "^18.0.0",
|
||||
@@ -98,33 +97,33 @@
|
||||
"ajv": "^8.8.2",
|
||||
"anti-trojan-source": "^1.4.0",
|
||||
"aspen-decorations": "^1.0.2",
|
||||
"axios": "^1.7.9",
|
||||
"axios": "^1.9.0",
|
||||
"babelify": "~10.0.0",
|
||||
"bignumber.js": "^9.0.1",
|
||||
"bignumber.js": "^9.2.0",
|
||||
"brace": "^0.11.1",
|
||||
"browserfs": "^1.4.3",
|
||||
"chart.js": "^3.0.0",
|
||||
"chart.js": "^4.4.7",
|
||||
"chartjs-plugin-zoom": "^2.0.1",
|
||||
"codemirror": "^6.0.1",
|
||||
"convert-units": "^2.3.4",
|
||||
"date-fns": "^4.1.0",
|
||||
"diff-arrays-of-objects": "^1.1.8",
|
||||
"hotkeys-js": "^3.13.3",
|
||||
"html-to-image": "^1.11.11",
|
||||
"html-to-image": "1.11.11",
|
||||
"immutability-helper": "^3.0.0",
|
||||
"insert-if": "^1.1.0",
|
||||
"ip-address": "^10.0.1",
|
||||
"json-bignumber": "^1.0.1",
|
||||
"jsoneditor": "^10.1.2",
|
||||
"leaflet": "^1.9.4",
|
||||
"lodash": "4.*",
|
||||
"moment": "^2.29.4",
|
||||
"moment-timezone": "^0.5.34",
|
||||
"moment-timezone": "^0.5.48",
|
||||
"notificar": "^1.0.1",
|
||||
"notistack": "^3.0.1",
|
||||
"papaparse": "^5.5.2",
|
||||
"path-fx": "^2.0.0",
|
||||
"postcss": "^8.4.31",
|
||||
"rc-dock": "^3.2.9",
|
||||
"postcss": "^8.5.2",
|
||||
"rc-dock": "^3.3.2",
|
||||
"react": "^18.2.0",
|
||||
"react-arborist": "^3.2.0",
|
||||
"react-aspen": "^1.1.0",
|
||||
@@ -139,17 +138,18 @@
|
||||
"react-leaflet": "^4.2.1",
|
||||
"react-new-window": "^1.0.1",
|
||||
"react-resize-detector": "^12.0.2",
|
||||
"react-rnd": "^10.4.14",
|
||||
"react-rnd": "^10.5.1",
|
||||
"react-select": "^5.7.2",
|
||||
"react-timer-hook": "^3.0.5",
|
||||
"react-timer-hook": "^4.0.1",
|
||||
"react-virtualized-auto-sizer": "^1.0.6",
|
||||
"snapsvg-cjs": "^0.0.6",
|
||||
"socket.io-client": "^4.5.0",
|
||||
"split.js": "^1.5.10",
|
||||
"sql-formatter": "^15.4.0",
|
||||
"uplot": "^1.6.24",
|
||||
"sql-formatter": "^15.5.1",
|
||||
"uplot": "^1.6.32",
|
||||
"uplot-react": "^1.1.4",
|
||||
"valid-filename": "^4.0.0",
|
||||
"vanilla-jsoneditor": "^3.3.1",
|
||||
"wkx": "^0.5.0",
|
||||
"zustand": "^5.0.3"
|
||||
},
|
||||
|
||||
@@ -136,8 +136,12 @@ class GoogleProvider(AbsProvider):
|
||||
credentials = self._get_credentials(self._scopes)
|
||||
service = discovery.build('sqladmin', 'v1beta4',
|
||||
credentials=credentials)
|
||||
high_availability = \
|
||||
'REGIONAL' if eval(args.high_availability) else 'ZONAL'
|
||||
|
||||
_high_availability = args.high_availability.lower() in (
|
||||
'true', '1') if isinstance(args.high_availability, str
|
||||
) else args.high_availability
|
||||
|
||||
high_availability = 'REGIONAL' if _high_availability else 'ZONAL'
|
||||
|
||||
db_password = self._database_password \
|
||||
if self._database_password is not None else args.db_password
|
||||
|
||||
@@ -349,6 +349,8 @@ def create_app(app_name=None):
|
||||
app.config['SECURITY_MSG_INVALID_PASSWORD'] = \
|
||||
(gettext("Incorrect username or password."), "error")
|
||||
app.config['SECURITY_PASSWORD_LENGTH_MIN'] = config.PASSWORD_LENGTH_MIN
|
||||
app.config['SECURITY_MSG_UNAUTHORIZED'] = \
|
||||
(gettext("Unauthorised access, permission denied."), "error")
|
||||
|
||||
# Create database connection object and mailer
|
||||
db.init_app(app)
|
||||
|
||||
@@ -34,89 +34,89 @@ export default function AboutComponent() {
|
||||
return (
|
||||
<Box sx={{ padding: '16px', height: '100%', display: 'flex',flexDirection: 'column'}} ref={containerRef}>
|
||||
<Grid container spacing={0} style={{marginBottom: '8px'}}>
|
||||
<Grid item lg={3} md={3} sm={3} xs={12}>
|
||||
<Grid size={{ lg: 3, md: 3, sm: 3, xs: 12 }}>
|
||||
<InputLabel style={{fontWeight: 'bold'}}>{gettext('Version')}</InputLabel>
|
||||
</Grid>
|
||||
<Grid item lg={9} md={9} sm={9} xs={12}>
|
||||
<Grid size={{ lg: 9, md: 9, sm: 9, xs: 12 }}>
|
||||
<InputLabel>{aboutData.version}</InputLabel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid container spacing={0} style={{marginBottom: '8px'}}>
|
||||
<Grid item lg={3} md={3} sm={3} xs={12}>
|
||||
<Grid size={{ lg: 3, md: 3, sm: 3, xs: 12 }}>
|
||||
<InputLabel style={{fontWeight: 'bold'}}>{gettext('Application Mode')}</InputLabel>
|
||||
</Grid>
|
||||
<Grid item lg={9} md={9} sm={9} xs={12}>
|
||||
<Grid size={{ lg: 9, md: 9, sm: 9, xs: 12 }}>
|
||||
<InputLabel>{aboutData.app_mode}</InputLabel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid container spacing={0} style={{marginBottom: '8px'}}>
|
||||
<Grid item lg={3} md={3} sm={3} xs={12}>
|
||||
<Grid size={{ lg: 3, md: 3, sm: 3, xs: 12 }}>
|
||||
<InputLabel style={{fontWeight: 'bold'}}>{gettext('Commit')}</InputLabel>
|
||||
</Grid>
|
||||
<Grid item lg={9} md={9} sm={9} xs={12}>
|
||||
<Grid size={{ lg: 9, md: 9, sm: 9, xs: 12 }}>
|
||||
<InputLabel>{aboutData.commit_hash}</InputLabel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid container spacing={0} style={{marginBottom: '8px'}}>
|
||||
<Grid item lg={3} md={3} sm={3} xs={12}>
|
||||
<Grid size={{ lg: 3, md: 3, sm: 3, xs: 12 }}>
|
||||
<InputLabel style={{fontWeight: 'bold'}}>{gettext('Python Version')}</InputLabel>
|
||||
</Grid>
|
||||
<Grid item lg={9} md={9} sm={9} xs={12}>
|
||||
<Grid size={{ lg: 9, md: 9, sm: 9, xs: 12 }}>
|
||||
<InputLabel>{aboutData.python_version}</InputLabel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid container spacing={0} style={{marginBottom: '8px'}}>
|
||||
<Grid item lg={3} md={3} sm={3} xs={12}>
|
||||
<Grid size={{ lg: 3, md: 3, sm: 3, xs: 12 }}>
|
||||
<InputLabel style={{fontWeight: 'bold'}}>{gettext('Current User')}</InputLabel>
|
||||
</Grid>
|
||||
<Grid item lg={9} md={9} sm={9} xs={12}>
|
||||
<Grid size={{ lg: 9, md: 9, sm: 9, xs: 12 }}>
|
||||
<InputLabel>{aboutData.current_user}</InputLabel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
{ aboutData.electron &&
|
||||
<Grid container spacing={0} style={{marginBottom: '8px'}}>
|
||||
<Grid item lg={3} md={3} sm={3} xs={12}>
|
||||
<Grid size={{ lg: 3, md: 3, sm: 3, xs: 12 }}>
|
||||
<InputLabel style={{fontWeight: 'bold'}}>{gettext('Electron Version')}</InputLabel>
|
||||
</Grid>
|
||||
<Grid item lg={9} md={9} sm={9} xs={12}>
|
||||
<Grid size={{ lg: 9, md: 9, sm: 9, xs: 12 }}>
|
||||
<InputLabel>{aboutData.electron}</InputLabel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
}
|
||||
<Grid container spacing={0} style={{marginBottom: '8px'}}>
|
||||
<Grid item lg={3} md={3} sm={3} xs={12}>
|
||||
<Grid size={{ lg: 3, md: 3, sm: 3, xs: 12 }}>
|
||||
<InputLabel style={{fontWeight: 'bold'}}>{gettext('Browser')}</InputLabel>
|
||||
</Grid>
|
||||
<Grid item lg={9} md={9} sm={9} xs={12}>
|
||||
<Grid size={{ lg: 9, md: 9, sm: 9, xs: 12 }}>
|
||||
<InputLabel>{aboutData.browser_details}</InputLabel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
{ aboutData.os_details &&
|
||||
<Grid container spacing={0} style={{marginBottom: '8px'}}>
|
||||
<Grid item lg={3} md={3} sm={3} xs={12}>
|
||||
<Grid size={{ 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}>
|
||||
<Grid size={{ lg: 9, md: 9, sm: 9, xs: 12 }}>
|
||||
<InputLabel>{aboutData.os_details}</InputLabel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
}
|
||||
{ aboutData.config_db &&
|
||||
<Grid container spacing={0} style={{marginBottom: '8px'}}>
|
||||
<Grid item lg={3} md={3} sm={3} xs={12}>
|
||||
<Grid size={{ 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}>
|
||||
<Grid size={{ lg: 9, md: 9, sm: 9, xs: 12 }}>
|
||||
<InputLabel>{aboutData.config_db}</InputLabel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
}
|
||||
{ aboutData.log_file &&
|
||||
<Grid container spacing={0} style={{marginBottom: '8px'}}>
|
||||
<Grid item lg={3} md={3} sm={3} xs={12}>
|
||||
<Grid size={{ 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}>
|
||||
<Grid size={{ lg: 9, md: 9, sm: 9, xs: 12 }}>
|
||||
<InputLabel>{aboutData.log_file}</InputLabel>
|
||||
</Grid>
|
||||
</Grid>
|
||||
|
||||
@@ -43,7 +43,7 @@ class About {
|
||||
pgAdmin.Browser.notifier.showModal(gettext('About %s', pgAdmin.Browser.utils.app_name), () => {
|
||||
return <AboutComponent />;
|
||||
}, { isFullScreen: false, isResizeable: true, showFullScreen: true,
|
||||
isFullWidth: true, dialogWidth: dlgWidth, dialogHeight: dlgHeight, minHeight: dlgHeight
|
||||
isFullWidth: true, dialogWidth: dlgWidth, dialogHeight: dlgHeight, minHeight: dlgHeight, id:'id-about'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||