Compare commits

...
156 Commits
Author SHA1 Message Date
Aditya Toshniwal 7c74b7cdb7 - Pin Electron to v35.4.0 as the v36 is not working on many OS.
- Pin html-to-image to v1.11.11 as latest version breaks ERD image downloads.
2025-05-27 13:02:11 +05:30
Khushboo Vashi e8826863e0 Updated version for v9.4 2025-05-26 18:47:53 +05:30
Pravesh Sharma 4f79deac0b Fixed CSS issue found during testing of issue 6510 2025-05-26 18:32:07 +05:30
Akshay Joshi 695166bde5 Revert "Trying to fix pip error on Windows build machine. pin the pip version to 24.2"
This reverts commit 9ce0e77e61.
2025-05-26 18:10:31 +05:30
Akshay Joshi 9ce0e77e61 Trying to fix pip error on Windows build machine. pin the pip version to 24.2 2025-05-26 13:28:28 +05:30
Libor M. 0b911bf58c Updated Czech translation for v9.4. 2025-05-26 11:14:34 +05:30
yuki 15ca0ba1b6 Updated Portuguese (Brazilian) translation for v9.4 2025-05-26 11:13:57 +05:30
Aditya Toshniwal c6183c9d03 Fixed more issues found while testing changes for large file download. #3369 2025-05-24 15:25:07 +05:30
Aditya Toshniwal dfd896db10 Fixed an issue where pgAdmin failed to focus when previously unfocused and then quit. #8760 2025-05-24 15:23:17 +05:30
yuki ac8f8fb0b0 Updated Portuguese (Brazilian) translation for v9.4
Added new translations there were missing.
2025-05-23 11:31:42 +05:30
Domenico Sgarbossa d6ae6b2773 Updated Italian translation for v9.4 2025-05-22 18:51:25 +05:30
Akshay Joshi a42f789ff0 Fixed an issue where correct error message not displayed when sql statement contains Arabic letters. #7926 2025-05-22 18:49:42 +05:30
Aditya Toshniwal 5d8ec6e5b0 Fix issues found while testing changes for large file download. #3369 2025-05-22 16:41:17 +05:30
Akshay Joshi e711a1bbc6 Updated message catalogs for v9.4 2025-05-22 15:58:58 +05:30
Pravesh Sharma b6e1223e88 Fixed an issue where the result grid slowed down when any column contained a large amount of data. #6510 2025-05-21 18:57:47 +05:30
Akshay Joshi 28921be00f Updated Python and Javascript dependencies. 2025-05-20 14:07:38 +05:30
Anil Sahoo 4e8f29f328 Fixed an issue where light theme briefly appears when pgAdmin loads or tools open, even when a dark or system UI theme is preferred. #8711 2025-05-20 10:36:29 +05:30
Aditya Toshniwal 126e1fb53d Enabled large file downloads for desktop users within the query tool. #3369 2025-05-14 15:30:17 +05:30
Allen HernandezandAllen Hernandez ebf4963758 Fixes venv notations for web build
2) Removes venv notation from web bundling directions
3) Add venv notation after activation

---------
Co-authored-by: Allen Hernandez <2349718+AllenSH12@users.noreply.github.com>
2025-05-14 14:17:13 +05:30
Akshay Joshi eece396b30 Fixed an issue where the PSQL tool would hang when the database encoding was set to SQL_ASCII and certain commands were executed. 2025-05-14 14:05:29 +05:30
Anil Sahoo abcb5f8830 Fixed an issue where the options key was not working as expected in the PSQL tool. #6968 2025-05-14 13:46:16 +05:30
Akshay Joshi ebb4c9994f Update Python and Javascript dependencies. 2025-05-13 12:59:25 +05:30
Aditya Toshniwal 971eee32ea Update MUI from v6 to v7. 2025-05-13 12:51:00 +05:30
Rohit Bhati af84d6b1e0 Handle result grid data changes in View/Edit Data mode by automatically reconnecting to the server if a disconnection occurs. #8608 2025-05-13 11:35:58 +05:30
Koren Peretz 2cb69f09b9 Update the Dockerfile to use UID 5050 instead of the pgadmin user to prevent Kubernetes deployments from failing when securityContext.runAsNonRoot is set to true without specifying securityContext.runAsUser. 2025-05-09 15:24:42 +05:30
Akshay Joshi 0403079a4b 1) Fixed an issue where the Cancel button did not work when attempting to delete a user from the User Management.
2) Fixed an issue where automatic user creation via LDAP failed if an existing Internal user with the same username was already present.
2025-05-09 13:28:23 +05:30
Anil Sahoo 97984eb3ec Fix an issue where, after a database disconnection, the server would disconnect, and the reconnect dialog would repeatedly appear when clicking the Execute button. #8607 2025-05-08 15:48:49 +05:30
Aditya Toshniwal c46fd30446 Fix JS test cases failing because of latest version of @tanstack/react-virtual. 2025-05-07 17:07:56 +05:30
Rohit Bhati ff8a301f6a Enhance contrast for selected and hovered items in the Object Explorer to improve visibility and accessibility. #8595 2025-05-07 12:33:04 +05:30
Aditya Toshniwal 27bd28ee97 Replace Grid with Grid2 as the former is deprecated by MUI 2025-05-06 19:39:33 +05:30
Akshay Joshi fb4d25d907 1) Updated Python and JavaScript dependencies.
2) Updated release note.
2025-05-06 19:07:29 +05:30
Pravesh Sharma ca6f52e7c7 Fixed issues related to column range selection using shift + click. #8713 2025-05-06 15:52:20 +05:30
Yogesh Mahajan 3bdeb9ace1 Implement API fetch error display for select dropdown. #8668 2025-05-06 10:52:42 +05:30
Akshay Joshi f64b59e735 Updated release note. 2025-05-05 14:59:48 +05:30
Pravesh Sharma 5d78f4a89f Fix the issue where an error is displayed when a table is dropped while a query is running. #6564 2025-05-02 14:12:06 +05:30
Anil Sahoo 695f870ce1 Fixed an issue where the query tool returns "cannot unpack non-iterable Response object" when running any query with a database name change. #8607 2025-05-02 10:57:43 +05:30
Akshay Joshi 593b111fdf Add all missing options to the Import/Export Data functionality, and update the syntax of the COPY command to align with the latest standards. #8583
Add support for exporting table data based on a custom query. #8681
2025-04-30 17:51:04 +05:30
Aditya Toshniwal 82efd188c4 Fix pep8 issues from the last commit 2025-04-30 15:38:44 +05:30
Aditya Toshniwal 9df7275429 Add a python script to parse a release note file and convert to Email, Markdown and HTML formats required for pgAdmin release 2025-04-30 15:31:20 +05:30
Akshay Joshi 829876c2e0 1) Sorted requirements.txt alphabetically.
2) Remove packages for Python 3.8.
3) Update JavaScript dependencies.
4) Update Python packages.
2025-04-30 12:43:02 +05:30
Akshay Joshi 41ba6bd1f4 Delete .python-version file 2025-04-29 15:07:31 +05:30
Khushboo Vashi aa282711f8 Try to fix the Fedora build failure. 2025-04-28 14:33:46 +05:30
Akshay Joshi 5a501603ac Updated version for v9.3 2025-04-28 11:00:39 +05:30
Libor M. e7f8cb4ea3 Czech translation for version 9.3 2025-04-28 10:58:35 +05:30
Pravesh Sharma 78d9aa5b76 Fixed issue found while testing PostGIS spatial type constructor support. #2256 2025-04-25 11:13:18 +05:30
Domenico Sgarbossa 038029eb2d Italian translation for v9.3 2025-04-24 18:43:33 +05:30
Aditya Toshniwal a14cc1bd77 Updated message catalogs for v9.3. 2025-04-24 16:19:42 +05:30
Yogesh Mahajan 33389fc48e Fix feature test failures for PG servers. 2025-04-24 15:57:48 +05:30
Aditya Toshniwal d468c16ca2 Fixed more issues found while testing role permissions feature. #7310 2025-04-23 15:47:51 +05:30
Khushboo Vashi fcf7cf5eb2 Update release notes. 2025-04-23 15:41:43 +05:30
Pravesh Sharma b08e90ea88 Add support for type constructors for PostGIS spatial types. #2256 2025-04-23 15:35:42 +05:30
Yogesh Mahajan 75dc42cf24 Allow OAuth 2 login using the username claim if the email is absent from the user profile. #8652 2025-04-23 15:21:25 +05:30
Aditya Toshniwal ec3d142ad9 Fix issues while testing role permissions feature. #7310 2025-04-21 15:14:18 +05:30
Aditya Toshniwal 280f0b0038 Revert "Rebase fork pgadmin-org/react-data-grid to get latest changes and update pgAdmin package.json"
It requires React 19.

This reverts commit 7307c52250.
2025-04-21 15:12:27 +05:30
Aditya Toshniwal 7307c52250 Rebase fork pgadmin-org/react-data-grid to get latest changes and update pgAdmin package.json 2025-04-21 13:48:43 +05:30
Aditya Toshniwal e8cb962890 Add Cache-Control no-cache,no-store,must-revalidate header to dynamically generated utils.js file. #3688 2025-04-16 11:23:35 +05:30
Akshay Joshi 934f17c65e Ensure that the server list is alphabetically sorted in the Query Tool/PSQL workspace. #8636 2025-04-15 16:12:49 +05:30
Akshay Joshi 55f36912f9 Updated JavaScript dependencies. 2025-04-15 11:52:44 +05:30
Akshay Joshi 7b1ad5fa67 Fixed an issue where changes to foreign key constraints were not detected in the schema diff. #8627 2025-04-15 11:46:12 +05:30
Aditya Toshniwal 7d8a915ee0 Add support for custom roles and role permissions management in pgAdmin. #7310 2025-04-15 11:25:31 +05:30
Aditya Toshniwal 8b4df8beb1 Change the shortcut for canceling a running query as it conflicts with the shortcut to open a new query tool. #8628 2025-04-14 13:46:59 +05:30
Aditya Toshniwal f98a74b526 Fixed an issue where the user management tab is not opening in the classic layout. #8651 2025-04-14 13:32:05 +05:30
Aditya Toshniwal 8a0eae2bb0 Fixed an issue where drag and drop function with no parameters does not work. #8613 2025-04-14 12:57:26 +05:30
Aditya Toshniwal 18f47a59c5 Fixed an issue where the query tool went blank when converting history dates to the appropriate locale format. #8632 2025-04-14 12:43:05 +05:30
Akshay Joshi 31b1af2f84 Fixed an issue where filtering on a view caused an error. #8630 2025-04-09 19:00:32 +05:30
Akshay Joshi 4c56e49c66 Updated Javascript dependencies. 2025-04-09 11:56:07 +05:30
Rohit Bhati 2de2c30545 Fixed an issue where Ctrl/Cmd+A in cell editor would select all rows. #8572 2025-04-08 18:29:05 +05:30
Kijong Han 51897dc804 Fixed an issue where shift + click on rows/columns for range selection did not work in the query tool data output window. #5266 2025-04-08 12:43:05 +05:30
Akshay Joshi bbef00a151 Fixed an issue where the scroll position in the Object Explorer was not retained when switching workspaces. #8497 2025-04-07 13:31:00 +05:30
Akshay Joshi 627aa5d695 Added ability to use SQL in the 'DB Restriction' field. #2767 2025-04-04 15:53:12 +05:30
Akshay Joshi 0d8b3c4389 Ensure that graph data is updated even when the Dashboard tab is inactive. #8556 2025-04-04 11:39:37 +05:30
Khushboo Vashi 8031c35160 Fixed an issue where the debugger hangs when stepping into nested function/procedure. #8443 2025-04-03 19:20:28 +05:30
Akshay Joshi 8cf14222ff Updated Javascript dependencies. 2025-04-03 19:07:02 +05:30
Mike Christensen 10b15b3986 Added support for font ligatures. #8629 2025-04-03 19:06:40 +05:30
Aditya Toshniwal 73fefb8603 Fixed an issue where query tool is crashing on macOS 15.4 due to a locale issue. #8623 2025-04-02 15:15:23 +05:30
Akshay Joshi af6c1a24cf 1) Upgraded Gunicorn to version 23.0.0 to address a security vulnerability present in Gunicorn.
2) Resolved an issue where an empty PSQL panel would open if the psql utility was not found in the binary path.
2025-04-01 16:33:50 +05:30
Aditya Toshniwal cfca6f6218 Fixed issues while testing multiple popups issue. #8316 2025-03-31 14:28:56 +05:30
Akshay Joshi c001b7b50a Fixed an issue where closing the pgAdmin main window did not automatically close the View Logs and Configure Runtime dialogs. 2025-03-31 12:59:03 +05:30
Akshay Joshi bd259cda42 Updated version for release v9.2 2025-03-31 11:34:12 +05:30
Akshay Joshi 75be0bc22d Fixed a remote code execution issue in the Query Tool and Cloud Deployment (CVE-2025-2945). #8603 2025-03-31 11:33:37 +05:30
Akshay Joshi 1305d9910b Fixed an XSS vulnerability issue in the Query Tool and View/Edit Data (CVE-2025-2946). #8602 2025-03-31 11:30:26 +05:30
Libor M. 6a850fff10 Czech translation for version 9.2 2025-03-31 11:10:19 +05:30
Aditya Toshniwal 6b9f002366 Fixed an issue where user management tab was not focussed when opened from a non default workspace. #8574 2025-03-28 15:31:51 +05:30
Domenico Sgarbossa 0eb8d6c8d6 Italian translation update for v9.2 2025-03-28 12:18:00 +05:30
Aditya Toshniwal 8a2a5fda1d Update release notes. 2025-03-28 10:42:00 +05:30
Rohit Bhati a2b35b35f3 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. #8483 2025-03-28 10:38:30 +05:30
Aditya Toshniwal f250f5de5e Fixed an issue where delete/rename was done on the wrong file after sorting in Storage Manager. #8597 2025-03-28 10:31:11 +05:30
Akshay Joshi fa60ab0f6a Updated message catalogs. 2025-03-27 19:23:57 +05:30
Akshay Joshi 1d3e0a4455 Revert the fix for #8006 2025-03-27 12:32:46 +05:30
Aditya Toshniwal 82c5febde6 Font family should fallback to Source Code Pro if not valid. #392
Update user management docs.
2025-03-27 11:03:39 +05:30
Akshay Joshi 0914ec24ad Updated release note. 2025-03-26 15:54:52 +05:30
Aditya Toshniwal 57d757d4de Fixed an issue where pgAdmin should fallback to main screen if the last opened screen is disconnected. #8362 2025-03-26 09:21:53 +05:30
Akshay Joshi 7edaac1da7 1) Updated Security.md file.
2) Updated release note.
2025-03-25 12:40:46 +05:30
Aditya Toshniwal 9ab451e163 Open user management in a separate tab instead of a dialog to enhance UI/UX. #8574 2025-03-25 12:33:49 +05:30
jackfromeast 213be44e29 Create SECURITY.md file. 2025-03-25 12:32:10 +05:30
Anil Sahoo cb597d0acb 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. #8577 2025-03-25 11:44:23 +05:30
Akshay Joshi badc6f33bf Updated JavaScript Dependencies. 2025-03-24 17:42:37 +05:30
Akshay Joshi a5993549b8 Disable controls for shared servers that cannot be edited by the users. 2025-03-24 14:30:56 +05:30
Mike Christensen 13b44fffc7 Add an ability to configure the font family for SQL editors. #392 2025-03-24 11:08:49 +05:30
Akshay Joshi fc1a1610a3 Ensure the newly added parameters in the server dialog are incorporated into the Import/Export Servers functionality. #8514 2025-03-20 15:49:43 +05:30
Rohit Bhati 47eca9a19c Fixed an issue where updating the grantee was not correctly applying the privileges. #8546 2025-03-20 15:35:46 +05:30
Akshay Joshi f635df6ccf Added support for post-connection SQL execution, which will be run automatically on each connection made to any database of the server. #4503 2025-03-18 16:54:38 +05:30
Yogesh Mahajan b2669930f5 Ensure that modal dialogs are not triggered more than once to avoid duplicates. #8316 2025-03-18 15:58:16 +05:30
Akshay Joshi f25cde8c5f 1) Unpin the electron version for RHEL 8 as respective issue is fixed.
2) Updated Javascript dependencies.
2025-03-18 10:27:21 +05:30
Rohit Bhati 797bdb8696 Fixed directory owner update & UI issues. #8034 2025-03-17 12:22:06 +05:30
Akshay Joshi c80be9b3a3 1) Align cancel query icon properly on the Dashboard.
2) Update release note.
2025-03-13 16:37:24 +05:30
Pravesh Sharma 84e2b844e0 Removed the pre-install script from the Red Hat build function as it was causing a No such file or directory warning during the update. #8006 2025-03-13 16:35:21 +05:30
Rohit Bhati be534be674 Update the stop/terminate icon at all the places for better UX. #8473 2025-03-12 12:31:23 +05:30
Chris Bandy 846d0eafe6 Change session files garbage collection strategy. #8335
Currently GC for session files is done by the /misc/cleanup endpoint which requires browser UI
to be running. With this change, the pgAdmin server will open a separate thread at a fixed frequency
which will take care of GC independently.
2025-03-11 16:32:30 +05:30
Akshay Joshi cd179a3e9f Updated release note. 2025-03-11 16:17:58 +05:30
Lau Ernebjerg Josefsen 2d10e95311 Add an option to load/replace the servers.json file on each container startup. #8540 2025-03-11 16:14:06 +05:30
Pravesh Sharma f9af74529c Fixed an issue where geometries in the geometry viewer will render partially when the container was resized. #8462 2025-03-10 18:44:24 +05:30
Akshay Joshi 8c9ab2afd9 Update Javascript dependencies. 2025-03-10 17:22:36 +05:30
Yogesh Mahajan 708a570ba0 On the Ubuntu runner, uninstall the default PostgreSQL version before installing any other PostgreSQL version. 2025-03-10 15:39:41 +05:30
Akshay Joshi 074db05f7a Updated release note. 2025-03-10 11:42:43 +05:30
Pravesh Sharma 73b437c0f5 Added support to automatically open a file after it is downloaded in the desktop mode. #4194 2025-03-10 11:38:13 +05:30
Rohit Bhati df5dced926 Change icon buttons to show tooltip even when disabled. #8449 2025-03-08 11:48:08 +05:30
Rohit Bhati 1590df8dfd Change the stop/terminate icon at all the places for better UX. #8473 2025-03-07 11:26:13 +05:30
Akshay Joshi 5ee33cf162 Fixed an issue where the PSQL terminal displays keyname for non alphanumeric keys. #8437 2025-03-05 18:31:49 +05:30
Aditya Toshniwal 7a25da9b06 Add support for restoring plain SQL database dumps. #5871 2025-03-05 18:22:44 +05:30
Akshay Joshi d7faa85338 Pin the electron version to 33.3.2 for RHEL 8 2025-03-05 12:37:50 +05:30
Akshay Joshi cf2328d2cd Fixed PEP8 2025-03-04 15:49:41 +05:30
Akshay Joshi 4e52a8664c Updated Javascript dependencies. 2025-03-03 19:00:59 +05:30
Rohit Bhati 7bae1eb663 Added support for creating Directory nodes in EPAS. #8034 2025-03-03 18:45:21 +05:30
Akshay Joshi 4791897578 Fixed an issue where the Schema Diff was not displaying the difference query when a table had a UNIQUE NULLS NOT DISTINCT constraint. #8479 2025-03-03 18:39:09 +05:30
Aditya Toshniwal 1cbdb435df Update the README.md file based on latest requirements. #8345 2025-02-25 17:06:49 +05:30
Akshay Joshi b59495603a 1) By Default 'Open in a new tab?' should be false.
2) Updated version for release v9.1
3) Updated the release note
2025-02-25 16:50:45 +05:30
Akshay Joshi 58f86a3c32 Updated Javascript dependencies. 2025-02-25 11:38:37 +05:30
Akshay Joshi adcf089357 Updated release note. 2025-02-21 15:00:01 +05:30
Yogesh Mahajan 636821f2ac Added an option to open the file in a new tab within the query tool. #1235 2025-02-21 14:45:41 +05:30
Pravesh Sharma b983b094a3 Fixed an issue where drop-down menus were hidden behind the dock. #8439 2025-02-20 12:12:29 +05:30
Akshay Joshi 53077b6c04 1) Updated chart.js to 4.4.7
2) Fixed an issue where Default Workspace and Preferences button is disabled when
   selecting any node from object explorer.
2025-02-19 16:12:17 +05:30
Aditya Toshniwal a0ddfad655 Fixed an issue where deleting rows in the query tool would delete all rows in the table when 'Select All Remaining Rows' was used. #8460 2025-02-18 17:34:24 +05:30
Yogesh Mahajan 39f92ffae4 Fixed GUI test cases failures on Github actions. 2025-02-18 14:44:32 +05:30
Akshay Joshi 84a5467a5e Updated Sphinx to 7.4.7 2025-02-18 13:34:20 +05:30
Akshay Joshi 35d6277f00 Rename all '10_plus' folders to 'default' as modulewise RESQL tests are not running. 2025-02-18 13:07:03 +05:30
Pravesh Sharma 85290d4e61 Fixed an issue where the column order displayed was incorrect for exclusion constraints with multiple columns. #8430 2025-02-18 11:57:42 +05:30
Yogesh Mahajan 48a26e8979 Ensure the saved passwords are decrypted with the correct encryption key for external authentication in server mode. #8435 2025-02-18 11:54:57 +05:30
Akshay Joshi 53a8cac7f8 Update Javascript dependencies. 2025-02-17 18:37:48 +05:30
Akshay Joshi 96128f6a15 1) Enable the ability to close the 'Welcome' tab in the Query Tool/PSQL Workspace. #8436
2) 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. #8418
3) Revert the change of OS from Ubuntu 22.04 to 24.04 for github action failure.
2025-02-17 18:28:56 +05:30
Anil Sahoo e2a80b2465 Fixed an issue where pasting text containing JSON data into the query tool grid would result in incorrect parsing. #8296 2025-02-17 17:41:05 +05:30
Pravesh SharmaandAditya Toshniwal 6dd91c8277 Fixed an issue where the ERD tool fails to open a saved file containing parent-child relationship within the same table. #8389
Fixed an issue in ERD where link notation end-points were not rendering occasionally.

---------

Co-authored-by: Aditya Toshniwal <aditya.toshniwal@enterprisedb.com>
2025-02-17 17:37:30 +05:30
Michal Charemza 83ade5dcc2 Update the query that fetches roles to be faster with many roles.
This changes the query that fetches roles from using the
pg_catalog.shobj_description function to using an explicit join on
pg_catalog.pg_shdescription. In my specific case, in a production system with
over 20k roles, this reduces the query time down from 8 minutes(!) down to
~40ms. Just in case it was a locking issue, I did use pg_activity to
investigate locks, and nothing was being blocked during the 8 minutes.

This fixes a problem that exists only for certain users, and specifically in my
case where the user that runs the query is themselves a member (directly and
indirectly) of a high number of roles. Running the existing query as a user
that has a low number of roles (and specifically, the master user in an AWS RDS
database), the existing query is fairly performant.

My best explanation as to the performance difference comes from the definition
of shobj_description
https://github.com/postgres/postgres/blob/2a8a00674e973dec4d7d74d5e16c7d7cdedf2be5/src/backend/catalog/system_functions.sql#L303-L312.
Each time it's called it runs a query against pg_shdescription and pg_class,
and so in my case runs 20k times, compared to the equivalent of once when doing
the explicit join on pg_shdescription. It should also be noted that in my case
pg_class is quite big - currently about 500k rows (although it has grown to ~5
million in the past, but that was borderline a mistake).

See https://github.com/pgadmin-org/pgadmin4/pull/8457#issue-2853052114 for
EXPLAIN ANALYZE results of the existing query and the updated query.
2025-02-17 17:20:28 +05:30
Akshay Joshi 5c257fe1b9 Change the Operating System from Ubuntu 22.04 to 24.04 to test whether it fixes the github actions. 2025-02-17 12:38:28 +05:30
Yogesh Mahajan 740a50680e Fix the following SonarQube issues:
1. Do not use the Array index in keys
2. Visible, non-interactive elements with click handlers must have at least one keyboard listener.
3. Add replacement fields or use a normal string instead of an f-string.
4. Add a parameter to the parent lambda function
2025-02-13 11:56:10 +05:30
Matthias Wilhelm 706eec0d5b Fix wrong parameter description for Password Exec Command
The documentation mentions that `%HOST%` can be used as a replacement parameter for the Password Exec Field in the Advanced tab of the Server Dialog, but the parameter is actually `%HOSTNAME%`:
2025-02-12 18:12:02 +05:30
Akshay Joshi f63190dc93 Fixed an issue where pgAdmin does not support pg_vector column length/precision. #8181 2025-02-12 16:14:31 +05:30
Akshay Joshi 58bb14253e Revert changes from the previous commit to restore the 'Object Explorer' title. 2025-02-11 20:18:10 +05:30
Akshay Joshi eb7c3ef361 Workspace Layout Update - Enhanced Query Tool and PSQL Behaviour:
With these changes, the Query Tool and PSQL tabs will now open in the same active workspace where the action is initiated.
2025-02-11 15:36:03 +05:30
Pravesh Sharma 2c37ff2893 Fixing following SonarQube Issues:
1. Ternary operators should not be nested.
2. "Exception" and "BaseException" should not be raised.
2025-02-11 12:03:43 +05:30
Akshay Joshi a30a722e11 Update release note. 2025-02-10 15:07:35 +05:30
Aditya Toshniwal 650a15beec Fixed an issue where the query tool was not treating IDENTITY columns as columns with default values when inserting new rows. #8341 2025-02-10 15:05:09 +05:30
Pravesh Sharma 2fc65589c8 Add support for one to one relationship in the ERD tool. #5128 2025-02-10 14:40:20 +05:30
Akshay Joshi bf7f8cdd73 1) Added missing GLOBALLY_DELIVERABLE config parameter in the config.py from the last commit.
2) Fixed API test cases for DBMS_JOB_SCHEDULER
2025-02-07 13:36:11 +05:30
Igor Serko ae76ea3585 Fixed Docker image entrypoint.sh email validation. #8410
Introduces a GLOBALLY_DELIVERABLE variable so that it can be passed to the email validator library
and ultimately allowing the email admin@localhost to be valid, as long as False is passed in.

Also:
* Adjusted the indentation of a command above it in the entrypoint.sh
* Added printing out the output of the validation library so that we can better find what the actual issue is
2025-02-07 12:34:23 +05:30
Akshay Joshi 0b46bdf901 1) Updated Javascript and Python dependencies.
2) Added release note for v9.1
2025-02-07 11:52:08 +05:30
522 changed files with 46023 additions and 31964 deletions

No files matched your search

+13 -1
View File
@@ -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",
+5 -1
View File
@@ -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' }}
+16 -2
View File
@@ -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
View File
@@ -1 +0,0 @@
3.8.0
+2 -2
View File
@@ -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
+1 -1
View File
@@ -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
+83 -85
View File
@@ -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
+82
View File
@@ -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`.
+8
View File
@@ -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*
+87
View File
@@ -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.
+16
View File
@@ -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
***************************
+91
View File
@@ -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
Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 KiB

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 105 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 237 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 KiB

After

Width:  |  Height:  |  Size: 254 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 188 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 182 KiB

After

Width:  |  Height:  |  Size: 320 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 209 KiB

After

Width:  |  Height:  |  Size: 280 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 193 KiB

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 186 KiB

After

Width:  |  Height:  |  Size: 183 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 176 KiB

After

Width:  |  Height:  |  Size: 188 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 141 KiB

After

Width:  |  Height:  |  Size: 195 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 67 KiB

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

+32 -8
View File
@@ -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
+24 -15
View File
@@ -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'"
}
}
}
}
+1
View File
@@ -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
+2 -1
View File
@@ -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
+40 -38
View File
@@ -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
*************
+38 -1
View File
@@ -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",
}
}
+1 -1
View File
@@ -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 .
+2 -1
View File
@@ -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: | |
+4
View File
@@ -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
+44
View File
@@ -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.
+54
View File
@@ -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.
+48
View File
@@ -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.
+44
View File
@@ -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.
+1 -1
View File
@@ -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
+2
View File
@@ -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.
+32 -15
View File
@@ -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
+101 -42
View File
@@ -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
***********
+2 -2
View File
@@ -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
+33 -13
View File
@@ -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.
+2 -2
View File
@@ -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
+2 -3
View File
@@ -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
+1 -1
View File
@@ -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)
+3 -6
View File
@@ -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
+43 -43
View File
@@ -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'
+15
View File
@@ -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': '^_',
},
],
},
},
];
+6 -5
View File
@@ -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"
}
}
+141
View File
@@ -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);
});
}
+84 -35
View File
@@ -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 {
+8
View File
@@ -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)
});
+39
View File
@@ -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);
}
}
+240 -124
View File
@@ -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
+495
View File
@@ -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 '&#9;' (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 -2
View File
@@ -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
+2 -2
View File
@@ -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
+2 -1
View File
@@ -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
##########################################################################
+50
View File
@@ -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
+33
View File
@@ -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
+32 -32
View File
@@ -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"
},
+6 -2
View File
@@ -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
+2
View File
@@ -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)
+20 -20
View File
@@ -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>
+1 -1
View File
@@ -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'
});
}
}
Loaded 100 of 522 files, more files were not shown because too many files have changed in this diff. Show more