Compare commits

...
184 Commits
Author SHA1 Message Date
Rahul Shirsat ab04b30726 1. Unverified email id is getting locked.
2. Admin should be able to lock the user, as currently it only unlocks it via
   user management dialog.
3. There were some indefinite login page loading issues when trying to log in
   with invalid password, where it should redirect to the login page again instead.

refs #6337 (Initial patch by Khushboo Vashi)
2021-08-09 21:04:49 +05:30
Yogesh Mahajan dc4f59e664 Handle null values more correctly.
refs #5198
2021-08-09 20:11:39 +05:30
Akshay Joshi 8738f6dd98 Update version for release. 2021-08-09 14:44:52 +05:30
Akshay Joshi 039766b492 Update DEPENDENCIES. 2021-08-09 14:42:24 +05:30
Libor M 2da970a26c Update Czech translation. 2021-08-09 14:34:32 +05:30
fn ln 86e1f33231 Update Japanese translation. 2021-08-09 14:33:02 +05:30
Domenico Sgarbossa 702fbac1c0 Update Italian translation. 2021-08-09 14:31:37 +05:30
Pradip Parkale 7483ddf2b2 Added support to copy SQL from main window to query tool. Fixes #4904 2021-08-09 14:29:31 +05:30
Khushboo Vashi 78b041465e Fixed an issue where even if the user is locked, he can reset the password and can login into pgAdmin. Fixes #6664 2021-08-09 14:24:26 +05:30
Akshay Joshi 5e3aa305fd Update message catalogs. 2021-08-06 19:35:30 +05:30
Nikhil Mohite 703478c13d Fixed an issue where the titles in query tabs are different. Fixes #6618 2021-08-06 19:09:39 +05:30
Yogesh Mahajan 8d53c10643 Fixed styling for JSON Editor to match with pgAdmin4 style.
refs #5198
2021-08-06 18:01:50 +05:30
Akshay Joshi 025c98ced8 1) Flash warning message of N no of attempts left for the unsuccessful login attempt.
2) Updated some strings in the Preferences for the "Maximum column width" option.
2021-08-03 17:06:06 +05:30
Yogesh Mahajan 8e214ca8fb Added support for formatted JSON viewer/editor when interacting with data in a JSON column. Fixes #5198 2021-08-03 11:36:45 +05:30
Akshay Joshi 23265061b2 Fixed an issue where an empty SQLite database file is created when try to get the version. 2021-07-30 15:44:46 +05:30
Aditya Toshniwal 9d985d3d8f Fixed potential bug in the table node. 2021-07-30 13:28:07 +05:30
Akshay Joshi 03477d407e Fixed dashboard server activity issue when active_since parameter is None. Fixes #6650 2021-07-29 11:49:27 +05:30
Rahul Shirsat 2dd88e5a4e Ensure that all the required options should be loaded when the Range data type
is selected while creating a custom data type.

Fixes #6643
2021-07-29 10:43:27 +05:30
Aditya Toshniwal 2452d90300 Fixed incorrect tablespace options in the drop-down for move objects dialog. Fixes #6586 2021-07-27 17:28:38 +05:30
Akshay Joshi 508f97b08e Rename the "Resize by data?" to "Columns sized by" and disabled the 'Maximum column width'
button if 'Columns sized by' is set to 'Column data'. Fixes #6622
2021-07-27 15:17:06 +05:30
Akshay Joshi 3f67f512ec Fixed incorrect binary path issue when the user deletes the binary path from the preferences. Fixes #6619 2021-07-26 11:49:48 +05:30
Akshay Joshi fdc3028124 Fixed linter error. 2021-07-23 12:57:40 +05:30
zhangjie2@fujitsu.com 3a3eea0320 Correct the string for shared server test case. 2021-07-23 12:44:16 +05:30
Nikhil Mohite d95a6f2af7 Fixed an issue where paste is not working through Right-Click option on PSQL. Fixes #6574 2021-07-23 12:41:48 +05:30
Florian Sabonchi a3d3c74e67 Ensure that the login account should be locked after N number of attempts. N is configurable using the 'MAX_LOGIN_ATTEMPTS' parameter. Fixes #6337 2021-07-22 12:24:43 +05:30
Dave Page c2db647379 Run apt update before doing anything else. 2021-07-21 15:48:59 +01:00
Rahul Shirsat 6cc3423cbe Fixed session expiration API test case. 2021-07-20 16:29:03 +05:30
Akshay Joshi eb658a75ab Modified the bulk insert logic to the user table in the migration file. 2021-07-20 13:27:03 +05:30
Pradip Parkale b2205fc6e1 Fixed an issue in the search object when searching in 'all types' or 'subscription' if the user doesn't have access to the subscription. Fixes #6448 2021-07-19 14:11:10 +05:30
Nikhil Mohite 5768ade198 Added exception handling for SQLAlchemy function to check the table exists or not. 2021-07-19 14:01:45 +05:30
Rahul Shirsat b0727cc532 Fixed CSRF errors for stale sessions by increasing the session expiration time for desktop mode. Fixes #6369 2021-07-15 17:49:42 +05:30
Rahul Shirsat 9e8af67202 Fixed TypeError 'NoneType' object is not sub scriptable. Fixes #6580 2021-07-15 17:46:31 +05:30
Fred Escallier 69d0fbe419 Update French translation. 2021-07-15 17:38:57 +05:30
Akshay Joshi 7b050a4c31 Update version for release. 2021-07-12 16:35:25 +05:30
Akshay Joshi 96085213fe Update Dependencies. 2021-07-12 16:26:00 +05:30
Domenico Sgarbossa 2ce2b457bf Update Italian translation. 2021-07-12 14:12:12 +05:30
Identifier Anonymous a2171aa27b Update Japanese translation. 2021-07-12 14:10:22 +05:30
Libor M ea3d71c0df Update Czech translation. 2021-07-12 14:08:58 +05:30
Akshay Joshi b154be24ec Update message catalog. 2021-07-09 21:53:33 +05:30
Khushboo Vashi 3590c9172c Fixed an issue where the user unable to login with OAuth2 when LDAP & OAuth2 configured as login sources. Fixes #6594 2021-07-09 21:50:50 +05:30
Khushboo Vashi e981868246 Fixed an issue where the user unable to add server in Kerberos Authentication Mode with Master Password. Fixes #6595 2021-07-09 21:47:34 +05:30
Khushboo Vashi 5ee8045916 Informative error should be shown if Oauth2 profile does not have email id registered. Fixes #6590 2021-07-07 17:58:49 +05:30
Khushboo Vashi 36086722b3 RESQL testcase fixes for Triggers. 2021-07-07 17:56:30 +05:30
Rahul Shirsat 8edd5946e5 1) Modified some labels and controls.
2) Fixed issue where the same user is showing in SQL query.

3) Added SQL tab in the dialog.

refs #3893
2021-07-07 10:44:02 +05:30
Akshay Joshi a0b2a28ee2 1) Set the default value of the long-running threshold to 2 minutes for warning and 5 minutes for the alert.
2) Use $color-danger for the alert threshold.
2021-07-06 19:52:37 +05:30
Identifier Anonymous 39a845ad31 Remove extra brackets in CREATE script and DDL comparison for trigger node. 2021-07-06 19:07:35 +05:30
Nikhil Mohite 669bdc7e38 Resolved the issue when the user selects the folder 'Select' button is not getting enabled for 'Select folder' dialog.
refs #6536
2021-07-06 19:00:08 +05:30
Pradip Parkale 5d4c073730 Fixed an issue where Schema Diff and Debugger give a blank white panel.
refs #6398
2021-07-06 18:56:21 +05:30
Khushboo Vashi 48ca83f31d Added support for OAuth 2 authentication. Fixes #5940
Initial patch sent by: Florian Sabonchi
2021-07-06 13:22:58 +05:30
Dave Page fff4060b31 Don't use fuzzy matching when updating message catalogs, to avoid issues where the number string substitution placeholders changes, per discussion. 2021-07-05 09:49:56 +01:00
Rahul Shirsat 9fdda038a9 Resolve the log in issue for a user having a non-existing email id
1) Added CHECK_EMAIL_DELIVERABILITY & SECURITY_EMAIL_VALIDATOR_ARGS.
  2) Added test cases for deliverability check.

Fixes #6550
2021-07-05 12:55:40 +05:30
Akshay Joshi ef67409d61 Highlighted long running queries on the dashboards. Fixes #1975 2021-07-01 18:10:55 +05:30
Dave Page d90472014d Remove leading whitespace and replace it with '[...] ' in the Query Tool data grid so cells don't look empty.
Fixes #6427
2021-07-01 09:17:35 +01:00
Dave Page a2b67b933e PEP-8 fix. 2021-06-30 11:04:50 +01:00
Dave Page b98e881d84 Disable email deliverability check that was introduced in flask-security-too by default to maintain backwards compatibility.
Fixes #6550
2021-06-30 10:46:32 +01:00
Dave Page e978621597 Fix typo in filename. 2021-06-28 15:23:18 +01:00
Rahul Shirsat 5fe52b9cfe Added support for Reassign/Drop Owned for login roles. Fixes #3893 2021-06-28 18:55:52 +05:30
Nikhil Mohite 5c6d00d545 Fixed directory selection issue with the folder dialog. Fixes #6536 2021-06-28 18:55:52 +05:30
Dave Page 6429a5b31a Clarify when container config envvars may be ignored. 2021-06-28 09:48:24 +01:00
Akshay Joshi e68c8305a2 Added option to provide maximum width of the column when 'Resize by data?’ option in the preferences is set to True. Fixes #6559 2021-06-28 11:51:21 +05:30
Pradip Parkale e095d382b3 Fixed an issue where incorrect column name listed in the properties of Index. Fixes #6557 2021-06-27 19:00:16 +05:30
Akshay Joshi 25ada15546 Temporary comment the logic to check API test cases are fixed for EPAS/PG 9.6 2021-06-25 19:40:52 +05:30
Pradip Parkale 5581f0909a Fixed an issue where Debugger and ERD tool panel give a blank white panel, missing from the last patch.
refs #6398
2021-06-25 11:38:02 +05:30
Pradip Parkale 462b86df8d Remove some configuration from the about dialog. 2021-06-25 11:11:28 +05:30
Nikhil Mohite 6645625e6b Fixed copy/paste issues for PSQL tool terminal. Fixes #6547. 2021-06-24 20:00:52 +05:30
Ashesh Vashi cfb68d73a0 Fixed server mode api test case failure. 2021-06-24 19:41:58 +05:30
Ashesh Vashi 9574f43f87 Refactor the registry class logic and remove duplicate code for the same functionality. 2021-06-24 11:30:11 +05:30
Akshay Joshi a53be65ab0 Fixed Czech translation string for 'Login' keyword. Fixes #6555
Patch sent by: Waclaw
2021-06-24 11:19:26 +05:30
Libor M cc989c5c08 Added missing gettexts and text space improvements. 2021-06-24 11:15:50 +05:30
Nikhil Mohite 313224e6f5 Ensure that Data Output panel can be snapped back after it is detached. Fixes #4189 2021-06-23 15:06:06 +05:30
Nikhil Mohite 2adb29ffc0 Fixed an issue where the New Connection Drop Down has lost default maintenance database, auto-select, and tab-through functionality. Fixes #6505 2021-06-23 12:48:17 +05:30
Pradip Parkale 80ccd62d38 Fixed an issue in the search object when searching in 'all types' or 'subscription' if the user doesn't have access to the subscription. Fixes #6448 2021-06-23 12:39:55 +05:30
Aditya Toshniwal b81ff45d34 Fixed replace keyboard shortcut issue in the query tool on the normal keyboard layout. Fixes #6388 2021-06-23 12:34:01 +05:30
Aditya Toshniwal 81b78dd2b2 Do not block the query editor window when running a query. Fixes #3920 2021-06-23 12:22:24 +05:30
Nikhil Mohite e2302a6c9b Ensure that setting 'Open in new browser tab' should be visible, it should not be based on the value of 'ENABLE_PSQL'. Fixes #6541 2021-06-23 11:59:56 +05:30
Yogesh Mahajan 2486b79450 Fixed feature tests failure issue due to binary path feature. 2021-06-23 11:55:27 +05:30
Pradip Parkale 0b52ef6eb0 Fixed an issue where detaching the query editor panel gives a blank white panel. Fixes #6398 2021-06-23 11:49:40 +05:30
Nikhil Mohite a533620684 Fixed an issue where Execute/Refresh button should not be disabled when we run the empty query. Fixes #6489 2021-06-23 11:49:40 +05:30
Dave Page 09d8d0f362 Fix path on windows. Fixes #6558 2021-06-23 07:04:59 +01:00
Dave Page 4e067835c3 Revert "Fixed API test cases for PG/EPAS 9.6" per Khushboo.
This reverts commit 37278f2cd3.
2021-06-17 13:27:33 +01:00
Khushboo Vashi 37278f2cd3 Fixed API test cases for PG/EPAS 9.6 2021-06-17 16:22:53 +05:30
Akshay Joshi 16d2a3096a 1) Fixed an issue where the binary path is not correctly parsed for version 9.6. Fixes #6534
2) Added the default binary path in the container. 
3) Fixed the typo in the documentation.
2021-06-15 19:49:46 +05:30
Dave Page 083509eb97 Show the full range of options for the default binary path dict. 2021-06-15 14:32:05 +01:00
Dave Page 0c154deeec Fix dict definition. 2021-06-15 14:19:31 +01:00
Akshay Joshi 082c9707c0 Fixed documentation issue 'Definition list ends without a blank line; unexpected unindent.' 2021-06-15 16:45:16 +05:30
Akshay Joshi 15798ee168 Updated DEFAULT_BINARY_PATHS for container. 2021-06-15 16:08:15 +05:30
Dave Page e37b7eae3f Cleanup psql docs. 2021-06-15 11:09:52 +01:00
Akshay Joshi ae2d588f46 Update version for release. 2021-06-14 21:00:26 +05:30
Akshay Joshi 12d93d0805 Update DEPENDENCIES. 2021-06-14 20:59:05 +05:30
Nikhil Mohite 2549688bdf 1) Disable the PSQL feature entirely in server mode by default.
2) Remove the code that attempts to filter out commands.

refs #2341
2021-06-14 20:53:11 +05:30
Akshay Joshi c2ed799113 If the binary path contains '' then show as it is on GUI if the path contains valid utilities. 2021-06-14 19:23:26 +05:30
Nikhil Mohite 71526ac79f Ensure that the calendar control should be disabled in the properties panel for Role. Fixes #6469. 2021-06-14 16:59:04 +05:30
Pradip Parkale 3d685ef96c Updated variable name as per review comments. 2021-06-14 16:42:27 +05:30
Akshay Joshi 2fdde6218a Fixed binary path issue on Windows platform. refs #5370 2021-06-14 15:01:49 +05:30
Nikhil Mohite 09693d14d1 Added check if the Windows version is not supporting the ConPty or WinPty disable the PSQL for that version.
refs #2341
2021-06-14 11:47:40 +05:30
Fred Escallier dcaeb20e29 Update French translation. 2021-06-14 11:47:40 +05:30
fn ln d93ec3bb91 Update Japanese translation. 2021-06-14 11:47:40 +05:30
Libor M f29852f6f0 Update Czech translation. 2021-06-14 11:47:40 +05:30
Domenico Sgarbossa 7d5fc84747 Update Italian translation. 2021-06-14 11:47:40 +05:30
Dave Page 4a3a5174b2 Disable browser password saving in the runtime. Fixes #6473 2021-06-11 15:10:38 +01:00
Pradip Parkale e0d094b2aa Fixed issues related to About dialog:
1) On resizing, the server configuration text area should be resized.
2) Any password should not be visible in the configuration.
3) Configurations are not properly quoted.
4) Added the "Copy" button so that the user can copy the configuration directly.

refs #6231
2021-06-11 19:30:32 +05:30
Pradip Parkale e3190b86ab Fixed an issue where a decimal number is appended for character varying fields while downloading the data in CSV format. Fixes #6520 2021-06-11 19:29:20 +05:30
Akshay Joshi b9b0a573e5 Update message catalogs. 2021-06-11 19:17:40 +05:30
Akshay Joshi 0dbfbd8dfc 1) Fixed Selenoid test cases.
2) Fixed RESQL test case failing on Jenkins.
2021-06-11 15:34:12 +05:30
Aditya Toshniwal 6e42d9113b Fixed user password-related issues.
refs #6225
2021-06-10 22:56:38 +05:30
Khushboo Vashi 460fb7ec29 Fixed an issue where pgAdmin does not open after password reset in server mode. Fixes #6513 2021-06-10 22:55:31 +05:30
Akshay Joshi c86a2b643a 1) Binary path set to the default location in which we install the binaries.
2) Validate path not working if there is a space in the binary path.
3) Handle the case when the path contains '$DIR'. 

refs #5370
2021-06-10 22:49:05 +05:30
Yogesh Mahajan b2042f48cd Added RESQL/MSQL test cases for Table and its child nodes. Fixes #4622 2021-06-09 18:16:50 +05:30
Dave Page d276f37e87 Support non-admin installation on Windows. Fixes #6524 2021-06-09 13:32:48 +01:00
Nikhil Mohite 7c88ee7cff Added a mechanism to detect a corrupt/broken config database file. Fixes #6460 2021-06-08 19:41:47 +05:30
Nikhil Mohite 93ddc4a5ba Ensure that the user should be able to add members in Login/Role group while creating it. Fixes #6466 2021-06-08 19:33:03 +05:30
Nikhil Mohite 9f12747d9b Added PSQL tool support for the Windows platform.
Fixed following issues:
1. If the database name contains escape characters then PSQL unable to connect.
2. If the user terminates the connection by typing the 'exit' command, PSQL
   will show the connection termination msg.

Fixes #2341
2021-06-08 14:58:43 +05:30
Akshay Joshi 5a086a9173 Fixed API test cases failed due to wrong handling of default binary path. 2021-06-08 13:24:17 +05:30
Nikhil Mohite e1067ffe67 Ensure that the Query Tool connection string should not be changed as per the 'Query Tool tab title'. Fixes #6404 2021-06-07 22:07:51 +05:30
Rahul Shirsat d5f537aae4 Added extra check for verifying the rename of the database.
refs #4203
2021-06-07 21:11:28 +05:30
Nikhil Mohite 5b12483416 Fixed an issue where the Foreground Color property of server dialog does not work. Fixes #6482 2021-06-07 21:09:04 +05:30
Akshay Joshi 07eb541806 1) Added logic to set the appropriate default binary path if DEFAULT_BINARY_PATH is
set in the config and the user not updated the preferences.
2) Remove 'gpdb' from DEFAULT_BINARY_PATH.
3) Fixed API test cases. 

refs #5370
2021-06-07 20:36:34 +05:30
Aditya Toshniwal 065a3aa2f5 Updated Flask-Security-Too to the latest v4. Fixes #6225 2021-06-06 13:58:06 +05:30
Akshay Joshi 2aa2d79de2 Fixed Jenkins build, added 'user-agents' in requirements.txt which was missing in the last patch. 2021-06-04 18:49:19 +05:30
Pradip Parkale a0deab901d Fixed OS detail issue for Linux and MacOS Big Sur. Fixes #6231. 2021-06-04 17:57:58 +05:30
Akshay Joshi 4bc4ca1ba9 1) Added browse button to select the binary path in the Preferences. Fixes #1561
2) Added support to set the binary path for the different database server versions. Fixes #5370
2021-06-04 17:55:35 +05:30
Rahul Shirsat ac8e8961ce Added Grant Wizard option under Package node. Fixes #1591 2021-06-04 12:47:37 +05:30
Pradip Parkale 2c51925638 Added OS, Browser, Configuration details in the About dialog. Fixes #6231 2021-06-01 20:18:24 +05:30
Nikhil Mohite e0eac875b6 Disable the PSQL tool for Windows, the 'fcntl' module is not working on Windows. 2021-06-01 20:04:43 +05:30
Rahul Shirsat 9ac08c263b Fixed duplicate SQL issue for tables with more than one partition. Fixes #6478 2021-05-31 12:46:07 +05:30
Rahul Shirsat 658a2de619 Fixed the issue of renaming the database by another user. Fixes #4203 2021-05-31 12:41:09 +05:30
Ashesh Vashi a487a51135 Fixes SonarQube issues. 2021-05-29 12:55:59 +05:30
Yogesh Mahajan 2d58f60a53 Modifies the way to execute feature tests in parallel and it should be configured in Server Mode. 2021-05-27 11:01:25 +05:30
Yogesh Mahajan faa49687be Added support to rotate the pgadmin log file on the basis of Size and Age. Fixes #6395 2021-05-25 20:18:46 +05:30
Nikhil Mohite 3ddf941cd7 Added support to launch PSQL for the connected database server. Fixes #2341 2021-05-25 20:12:57 +05:30
Rahul Shirsat 37dece2cd8 Added window maximize/restore functionality for properties dialog. Fixes #4064 2021-05-24 22:08:23 +05:30
Dave Page 1ead82f9b8 Various fixes to the setup process description. 2021-05-24 17:03:42 +01:00
Libor M 48dbf5a3dc Update Czech translation. 2021-05-18 13:42:49 +05:30
Akshay Joshi 0a95550fc0 Hardcoded 'itsdangerous' version to <=1.1.0, as the latest version not working correctly for pgAdmin. 2021-05-18 13:41:14 +05:30
Akshay Joshi 1c2b312d49 Update version for release. 2021-05-17 19:15:27 +05:30
Akshay Joshi 62e08d2b7e Update Dependencies. 2021-05-17 19:09:29 +05:30
Aditya Toshniwal f34adaca41 Fixed column sizing issue when there are no rows in a table.
refs #5954
2021-05-17 17:55:13 +05:30
Identifier Anonymous aaf5d64fe0 Update Japanese translation. 2021-05-17 13:13:23 +05:30
Fred Escallier 3f5fb4b61c Update French translation. 2021-05-17 13:12:05 +05:30
Domenico Sgarbossa f9254126e5 Update Italian translation. 2021-05-17 13:10:38 +05:30
Pradip Parkale 4676d7ef02 Fixed an issue where the Help message not displaying correctly on Login/Group role. Fixes #6414 2021-05-17 13:08:38 +05:30
Akshay Joshi 42b8dbb58f Update message catalog. 2021-05-14 17:38:30 +05:30
Aditya Toshniwal b7c0914f33 Fixed 'No password supplied' error occurring on auto-detected servers. 2021-05-14 15:14:18 +05:30
Aditya Toshniwal c8a2057410 Fixed JS audit warnings 2021-05-14 13:24:45 +05:30
Akshay Joshi 64e42bebe2 Update the correct redmine numbers, wrongly added in the last commit. 2021-05-14 12:42:06 +05:30
Khushboo Vashi 7275ce906e 1) Fixed an issue where the user is not warned if Kerberos ticket expiration
is less than 30 min while initiating a global backup. Fixes #6444

2) Ensure that proper identification should be there when the server is
   connected using Kerberos or without Kerberos. Fixes #6445
2021-05-14 12:33:01 +05:30
Pradip Parkale 7ed97eeec4 Fixed an issue where file dialog showing incorrect files for the selected file types. Fixes #6443 2021-05-14 12:12:17 +05:30
Pradip Parkale 0bb40de1c4 Ensure that the user should not be able to add duplicate panels. Fixes #6399 2021-05-12 15:19:41 +05:30
Akshay Joshi bd7808a104 Fixed an issue where the filter 'Include/Exclude By Selection' not working for null values. Fixes #6392 2021-05-11 19:12:43 +05:30
Akshay Joshi 4842d589a6 Added missing validation for data type. Fixes #6407 2021-05-11 18:21:53 +05:30
Akshay Joshi 11c541adc6 Update document and screenshot for 'Resize by data?' option. 2021-05-11 17:55:22 +05:30
Dave Page c746cfddfe Fix width of table row. 2021-05-11 11:47:38 +01:00
Dave Page 2b7f8d8298 Improve some strings. 2021-05-11 11:31:14 +01:00
huangj.fnst@fujitsu.com fe6f9aae61 Fix a number of typos. 2021-05-11 11:16:38 +01:00
Dave Page 8bc07c45f5 Cleanup the install-node target so it just calls yarn. 2021-05-11 09:44:48 +01:00
Aditya Toshniwal 058afad9eb Added support for cache bust webpack chunk files. Fixes #5477 2021-05-11 13:48:53 +05:30
Akshay Joshi 1e6eca1787 Ensure that pgAdmin4 shut down completely on the Quit command. Fixes #6420 2021-05-10 15:28:45 +05:30
Khushboo Vashi 89b0028684 Update Kerberos docs for phase 2. 2021-05-10 10:20:47 +01:00
Akshay Joshi d80087f6d5 Added support to set auto width of columns by content size in the data output window. Fixes #5954 2021-05-07 17:18:50 +05:30
Yogesh Mahajan b0df4d3604 Added support for the creation of Nested Table and Varying Array Type for Advanced Server. Fixes #6407 2021-05-07 12:39:54 +05:30
Dave Page c32ff3a7ee Expect the yum repo metadata to be GPG signed. 2021-05-06 15:27:22 +01:00
Murtuza Zabuawala 4c55044440 Remove duplicate code and avoid DOM search operation.
refs #6355
2021-05-06 10:53:32 +05:30
Akshay Joshi b13627398b Fixed API test cases 2021-05-05 13:12:20 +05:30
Khushboo Vashi b30ec71098 Ensure that while connecting to the server using SSPI login, it should not prompt for the password. Fixes #5776 2021-05-05 11:40:48 +05:30
Dave Page 649ca2eeac Make the error messages on exit show something useful. 2021-05-04 14:12:13 +01:00
Murtuza Zabuawala 98546e1876 Update require.js library to the latest version. 2021-05-04 17:48:13 +05:30
Akshay Joshi 7e79814cb0 Added 'IF NOT EXISTS' clause while creating tables and partition tables which is convenient while using the ERD tool. Fixes #6397 2021-05-04 15:59:34 +05:30
Akshay Joshi ac403d0dfa Fixed an issue where the current debug line is not visible in the 'Dark' theme. Fixes #6409 2021-05-04 12:34:03 +05:30
Khushboo Vashi 72f3730c34 Added support to connect PostgreSQL servers via Kerberos authentication. Fixes #6158 2021-05-03 16:10:45 +05:30
Akshay Joshi aa9a4c30d3 Fixed an issue where duplicate columns are visible in the browser tree, which is owned by two sequences. Fixes #6413 2021-05-03 14:53:21 +05:30
Pradip Parkale 3a2145e5fa Fixed an issue where query editor is not being closed if the user clicks on the 'Don't Save' button. Fixes #6417 2021-05-03 12:52:28 +05:30
Pradip Parkale 333a22496c Fixed an issue where drag and drop object is not correct in codemirror for properties dialog. Fixes #4436 2021-04-29 13:19:36 +05:30
Rahul Shirsat 488dc1849d Fixed an issue where data is displayed in the wrong order when executing the query repeatedly. Fixes #5555 2021-04-29 13:13:52 +05:30
Akshay Joshi e718be72e3 Added comment column in the properties panel for View and Materialized View collection node. Fixes #6416 2021-04-28 18:44:28 +05:30
Pradip Parkale 9dd1bae3c7 Ensure that pgAdmin should not allow opening external files that are dragged into it. Fixes #6355 2021-04-28 11:59:45 +05:30
Cyril Jouve 718ac02806 Fixed ModuleNotFoundError when running setup.py from outside of the root. Fixes #6408 2021-04-27 12:54:57 +05:30
Pradip Parkale 7bab200e4d Added more checks so that it will pick the correct shared server.
refs #6385
2021-04-27 11:58:47 +05:30
Rahul Shirsat f5ef022ef5 Fixed an issue where indexes showing TABLESPACE pg_default for partition SQL, which should not be shown.
refs #6329
2021-04-27 11:54:56 +05:30
Pradip Parkale 5a302684f7 Fixed an issue where long float values cause the rendering issue on the UI side.
It's a regression of the original commit for 6341.

refs #6341
2021-04-26 17:16:48 +05:30
Akshay Joshi 7d6f077cf8 Fixed an issue where schema diff does not create DROP DEFAULT statement for columns. Fixes #6377 2021-04-26 16:41:20 +05:30
Rahul Shirsat b853bda2a2 Fixed an issue where the wrong SQL is showing for the child partition tables. Fixes #6329 2021-04-26 14:32:34 +05:30
Pradip Parkale abdd3190fe Fixed some SonarQube issues. 2021-04-22 17:40:41 +05:30
Pradip Parkale 5894001eb2 Fixed an issue where CSV download quotes the numeric columns. Fixes #6341 2021-04-22 17:35:51 +05:30
Pradip Parkale 8ae8fea6d2 Ensure that Backup and Restore should work on shared servers as some cases were failing due to initial changes.
Fixes #6385
2021-04-22 17:29:04 +05:30
849 changed files with 65217 additions and 27308 deletions

No files matched your search

+186 -193
View File
@@ -23,19 +23,18 @@ Python Dependencies
Name Version Licence URL
---- ------- ------- ---
cheroot 8.5.2 UNKNOWN https://cheroot.cherrypy.org
Flask 1.1.2 BSD-3-Clause https://palletsprojects.com/p/flask/
Flask 1.1.4 BSD-3-Clause https://palletsprojects.com/p/flask/
Flask-Gravatar 0.5.0 BSD https://github.com/zzzsochi/Flask-Gravatar/
Flask-Login 0.5.0 MIT https://github.com/maxcountryman/flask-login
Flask-Mail 0.9.1 BSD https://github.com/rduplain/flask-mail
Flask-Migrate 2.6.0 MIT http://github.com/miguelgrinberg/flask-migrate/
Flask-SQLAlchemy 2.4.4 BSD-3-Clause https://github.com/pallets/flask-sqlalchemy
Flask-Migrate 2.7.0 MIT http://github.com/miguelgrinberg/flask-migrate/
Flask-SQLAlchemy 2.5.1 BSD-3-Clause https://github.com/pallets/flask-sqlalchemy
Flask-WTF 0.14.3 BSD https://github.com/lepture/flask-wtf
Flask-Compress 1.8.0 MIT https://github.com/colour-science/flask-compress
Flask-Compress 1.9.0 MIT https://github.com/colour-science/flask-compress
passlib 1.7.4 BSD https://passlib.readthedocs.io
pytz 2021.1 MIT http://pythonhosted.org/pytz
simplejson 3.17.2 MIT License https://github.com/simplejson/simplejson
six 1.15.0 MIT https://github.com/benjaminp/six
six 1.16.0 MIT https://github.com/benjaminp/six
speaklater3 1.4 UNKNOWN https://github.com/ThomasWaldmann/speaklater
sqlparse 0.4.1 BSD-3-Clause https://github.com/andialbrecht/sqlparse
WTForms 2.3.3 BSD-3-Clause https://wtforms.readthedocs.io/
@@ -43,16 +42,27 @@ Flask-Paranoid 0.2.0
psutil 5.8.0 BSD https://github.com/giampaolo/psutil
psycopg2 2.8.6 LGPL with exceptions https://psycopg.org/
python-dateutil 2.8.1 Dual License https://dateutil.readthedocs.io
SQLAlchemy 1.3.23 MIT http://www.sqlalchemy.org
Flask-Security-Too 3.4.5 MIT https://github.com/Flask-Middleware/flask-security
SQLAlchemy 1.3.24 MIT http://www.sqlalchemy.org
itsdangerous 1.1.0 BSD https://palletsprojects.com/p/itsdangerous/
Flask-Security-Too 4.0.1 MIT https://github.com/Flask-Middleware/flask-security
bcrypt 3.2.0 Apache License, Version 2.0 https://github.com/pyca/bcrypt/
cryptography 3.3.1 BSD or Apache License, Version 2.0 https://github.com/pyca/cryptography
cryptography 3.4.7 BSD or Apache License, Version 2.0 https://github.com/pyca/cryptography
sshtunnel 0.4.0 MIT https://github.com/pahaz/sshtunnel
ldap3 2.9 LGPL v3 https://github.com/cannatag/ldap3
Flask-BabelEx 0.9.4 BSD http://github.com/mrjoes/flask-babelex
gssapi 1.6.12 LICENSE.txt https://github.com/pythongssapi/python-gssapi
Flask-SocketIO 5.0.3 MIT http://github.com/miguelgrinberg/Flask-SocketIO/
eventlet 0.31.0 UNKNOWN http://eventlet.net
httpagentparser 1.9.1 http://www.opensource.org/licenses/mit-license.php http://shon.github.com/httpagentparser
user-agents 2.2.0 MIT https://github.com/selwin/python-user-agents
pywinpty 1.1.1 Unknown Unknown
Authlib 0.15.4 BSD-3-Clause https://authlib.org/
requests 2.25.1 Apache 2.0 https://requests.readthedocs.io
28 dependencies listed.
NOTE: This report was generated using Python 3.9. Full information may not be
shown for Python modules that are not required with this version.
35 dependencies listed.
Javascript Dependencies
=======================
@@ -60,50 +70,52 @@ Javascript Dependencies
Name Version Licence URL
---- ------- ------- ---
@babel/code-frame 7.12.13 MIT https://github.com/babel/babel.git
@babel/core 7.12.13 MIT https://github.com/babel/babel.git
@babel/generator 7.12.15 MIT https://github.com/babel/babel.git
@babel/compat-data 7.14.0 MIT https://github.com/babel/babel.git
@babel/core 7.14.3 MIT https://github.com/babel/babel.git
@babel/generator 7.14.3 MIT https://github.com/babel/babel.git
@babel/helper-annotate-as-pure 7.12.13 MIT https://github.com/babel/babel.git
@babel/helper-create-class-features-plugin 7.12.13 MIT https://github.com/babel/babel.git
@babel/helper-function-name 7.12.13 MIT https://github.com/babel/babel.git
@babel/helper-compilation-targets 7.13.16 MIT https://github.com/babel/babel.git
@babel/helper-create-class-features-plugin 7.14.3 MIT https://github.com/babel/babel.git
@babel/helper-function-name 7.14.2 MIT https://github.com/babel/babel.git
@babel/helper-get-function-arity 7.12.13 MIT https://github.com/babel/babel.git
@babel/helper-member-expression-to-functions 7.12.13 MIT https://github.com/babel/babel.git
@babel/helper-module-imports 7.12.13 MIT https://github.com/babel/babel.git
@babel/helper-module-transforms 7.12.13 MIT https://github.com/babel/babel.git
@babel/helper-member-expression-to-functions 7.13.12 MIT https://github.com/babel/babel.git
@babel/helper-module-imports 7.13.12 MIT https://github.com/babel/babel.git
@babel/helper-module-transforms 7.14.2 MIT https://github.com/babel/babel.git
@babel/helper-optimise-call-expression 7.12.13 MIT https://github.com/babel/babel.git
@babel/helper-plugin-utils 7.12.13 MIT https://github.com/babel/babel.git
@babel/helper-replace-supers 7.12.13 MIT https://github.com/babel/babel.git
@babel/helper-simple-access 7.12.13 MIT https://github.com/babel/babel.git
@babel/helper-plugin-utils 7.13.0 MIT https://github.com/babel/babel.git
@babel/helper-replace-supers 7.14.3 MIT https://github.com/babel/babel.git
@babel/helper-simple-access 7.13.12 MIT https://github.com/babel/babel.git
@babel/helper-split-export-declaration 7.12.13 MIT https://github.com/babel/babel.git
@babel/helper-validator-identifier 7.12.11 MIT https://github.com/babel/babel.git
@babel/helpers 7.12.13 MIT https://github.com/babel/babel.git
@babel/highlight 7.12.13 MIT https://github.com/babel/babel.git
@babel/parser 7.12.15 MIT https://github.com/babel/babel.git
@babel/plugin-proposal-class-properties 7.12.13 MIT https://github.com/babel/babel.git
@babel/helper-validator-identifier 7.14.0 MIT https://github.com/babel/babel.git
@babel/helper-validator-option 7.12.17 MIT https://github.com/babel/babel.git
@babel/helpers 7.14.0 MIT https://github.com/babel/babel.git
@babel/highlight 7.14.0 MIT https://github.com/babel/babel.git
@babel/parser 7.14.3 MIT https://github.com/babel/babel.git
@babel/plugin-proposal-class-properties 7.13.0 MIT https://github.com/babel/babel.git
@babel/plugin-syntax-jsx 7.12.13 MIT https://github.com/babel/babel.git
@babel/plugin-transform-react-display-name 7.12.13 MIT https://github.com/babel/babel.git
@babel/plugin-transform-react-jsx 7.12.13 MIT https://github.com/babel/babel.git
@babel/plugin-transform-react-jsx-development 7.12.12 MIT https://github.com/babel/babel.git
@babel/plugin-transform-react-display-name 7.14.2 MIT https://github.com/babel/babel.git
@babel/plugin-transform-react-jsx 7.14.3 MIT https://github.com/babel/babel.git
@babel/plugin-transform-react-jsx-development 7.12.17 MIT https://github.com/babel/babel.git
@babel/plugin-transform-react-pure-annotations 7.12.1 MIT https://github.com/babel/babel.git
@babel/preset-react 7.12.13 MIT https://github.com/babel/babel.git
@babel/preset-react 7.13.13 MIT https://github.com/babel/babel.git
@babel/template 7.12.13 MIT https://github.com/babel/babel.git
@babel/traverse 7.12.13 MIT https://github.com/babel/babel.git
@babel/types 7.12.13 MIT https://github.com/babel/babel.git
@istanbuljs/schema 0.1.2 MIT git+https://github.com/istanbuljs/schema.git
@popperjs/core 2.6.0 MIT https://github.com/popperjs/popper-core.git
@projectstorm/geometry 6.4.2 MIT https://github.com/projectstorm/react-diagrams.git
@projectstorm/react-canvas-core 6.4.2 MIT https://github.com/projectstorm/react-diagrams.git
@projectstorm/react-diagrams 6.4.2 MIT https://github.com/projectstorm/react-diagrams.git
@projectstorm/react-diagrams-core 6.4.2 MIT https://github.com/projectstorm/react-diagrams.git
@projectstorm/react-diagrams-defaults 6.4.2 MIT https://github.com/projectstorm/react-diagrams.git
@projectstorm/react-diagrams-routing 6.4.2 MIT https://github.com/projectstorm/react-diagrams.git
@simonwep/pickr 1.8.0 MIT https://github.com/Simonwep/pickr.git
@tippyjs/react 4.2.0 MIT git+https://github.com/atomiks/tippyjs-react.git
@types/estree 0.0.46 MIT https://github.com/DefinitelyTyped/DefinitelyTyped.git
@babel/traverse 7.14.2 MIT https://github.com/babel/babel.git
@babel/types 7.14.2 MIT https://github.com/babel/babel.git
@istanbuljs/schema 0.1.3 MIT git+https://github.com/istanbuljs/schema.git
@popperjs/core 2.9.2 MIT https://github.com/popperjs/popper-core.git
@projectstorm/geometry 6.5.2 MIT https://github.com/projectstorm/react-diagrams.git
@projectstorm/react-canvas-core 6.5.2 MIT https://github.com/projectstorm/react-diagrams.git
@projectstorm/react-diagrams 6.5.2 MIT https://github.com/projectstorm/react-diagrams.git
@projectstorm/react-diagrams-core 6.5.2 MIT https://github.com/projectstorm/react-diagrams.git
@projectstorm/react-diagrams-defaults 6.5.2 MIT https://github.com/projectstorm/react-diagrams.git
@projectstorm/react-diagrams-routing 6.5.2 MIT https://github.com/projectstorm/react-diagrams.git
@simonwep/pickr 1.8.1 MIT https://github.com/Simonwep/pickr.git
@tippyjs/react 4.2.5 MIT git+https://github.com/atomiks/tippyjs-react.git
@types/component-emitter 1.2.10 MIT https://github.com/DefinitelyTyped/DefinitelyTyped.git
@types/json-schema 7.0.7 MIT https://github.com/DefinitelyTyped/DefinitelyTyped.git
@types/node 14.14.25 MIT https://github.com/DefinitelyTyped/DefinitelyTyped.git
@types/q 1.5.4 MIT https://github.com/DefinitelyTyped/DefinitelyTyped.git
@types/node 15.6.1 MIT https://github.com/DefinitelyTyped/DefinitelyTyped.git
@types/parse-json 4.0.0 MIT https://www.github.com/DefinitelyTyped/DefinitelyTyped.git
acitree 4.5.0-rc.7 MIT https://github.com/imsurinder90/jquery-aciTree.git
acorn 7.4.1 MIT https://github.com/acornjs/acorn.git
ajv 6.12.6 MIT https://github.com/ajv-validator/ajv.git
ajv 5.5.2 MIT https://github.com/epoberezkin/ajv.git
ajv-keywords 3.5.2 MIT git+https://github.com/epoberezkin/ajv-keywords.git
@@ -111,8 +123,8 @@ alertifyjs 1.7.1
alphanum-sort 1.0.2 MIT https://github.com/TrySound/alphanum-sort.git
ansi-regex 2.1.1 MIT https://github.com/chalk/ansi-regex.git
ansi-styles 3.2.1 MIT https://github.com/chalk/ansi-styles.git
ansi-styles 4.3.0 MIT https://github.com/chalk/ansi-styles.git
ansi-styles 2.2.1 MIT https://github.com/chalk/ansi-styles.git
argparse 1.0.10 MIT https://github.com/nodeca/argparse.git
axios 0.21.1 MIT https://github.com/axios/axios.git
babel-code-frame 6.26.0 MIT https://github.com/babel/babel/tree/master/packages/babel-code-frame
babel-generator 6.26.1 MIT https://github.com/babel/babel/tree/master/packages/babel-generator
@@ -130,132 +142,112 @@ backform 0.2.0
backgrid 0.3.8 MIT http://github.com/cloudflare/backgrid
backgrid-filter 0.3.7 MIT git://github.com/wyuenho/backgrid-text-cell.git
backgrid-select-all 0.3.5 MIT git://github.com/wyuenho/backgrid-select-all.git
balanced-match 1.0.0 MIT git://github.com/juliangruber/balanced-match.git
backo2 1.0.2 MIT https://github.com/mokesmokes/backo.git
balanced-match 1.0.2 MIT git://github.com/juliangruber/balanced-match.git
base64-arraybuffer 0.2.0 MIT https://github.com/niklasvh/base64-arraybuffer
base64-arraybuffer 0.1.4 MIT https://github.com/niklasvh/base64-arraybuffer
big.js 5.2.2 MIT https://github.com/MikeMcl/big.js.git
bignumber.js 9.0.1 MIT https://github.com/MikeMcl/bignumber.js.git
bignumber.js 7.2.1 MIT https://github.com/MikeMcl/bignumber.js.git
bootstrap 4.6.0 MIT git+https://github.com/twbs/bootstrap.git
bootstrap4-toggle 3.6.1 MIT https://github.com/gitbrent/bootstrap4-toggle.git
brace-expansion 1.1.11 MIT git://github.com/juliangruber/brace-expansion.git
browserslist 4.16.3 MIT https://github.com/browserslist/browserslist.git
call-bind 1.0.2 MIT git+https://github.com/ljharb/call-bind.git
caller-callsite 2.0.0 MIT https://github.com/sindresorhus/caller-callsite.git
caller-path 2.0.0 MIT https://github.com/sindresorhus/caller-path.git
callsites 2.0.0 MIT https://github.com/sindresorhus/callsites.git
camelcase 6.2.0 MIT https://github.com/sindresorhus/camelcase.git
browserslist 4.16.6 MIT https://github.com/browserslist/browserslist.git
callsites 3.1.0 MIT https://github.com/sindresorhus/callsites.git
caniuse-api 3.0.0 MIT https://github.com/nyalab/caniuse-api.git
chalk 2.4.2 MIT https://github.com/chalk/chalk.git
chalk 4.1.1 MIT https://github.com/chalk/chalk.git
chalk 1.1.3 MIT https://github.com/chalk/chalk.git
chart.js 2.9.4 MIT https://github.com/chartjs/Chart.js.git
chartjs-color 2.4.1 MIT https://github.com/chartjs/chartjs-color.git
chartjs-color-string 0.6.0 MIT https://github.com/chartjs/chartjs-color-string.git
closest 0.0.1 MIT https://github.com/ForbesLindesay/closest.git
co 4.6.0 MIT https://github.com/tj/co.git
coa 2.0.2 MIT git://github.com/veged/coa.git
codemirror 5.59.2 MIT https://github.com/codemirror/CodeMirror.git
color 3.1.3 MIT https://github.com/Qix-/color.git
codemirror 5.61.1 MIT https://github.com/codemirror/CodeMirror.git
color-convert 1.9.3 MIT https://github.com/Qix-/color-convert.git
color-convert 2.0.1 MIT https://github.com/Qix-/color-convert.git
color-name 1.1.3 MIT git@github.com:dfcreative/color-name.git
color-name 1.1.4 MIT git@github.com:colorjs/color-name.git
color-string 1.5.4 MIT https://github.com/Qix-/color-string.git
colorette 1.2.1 MIT https://github.com/jorgebucaran/colorette.git
colord 2.0.0 MIT https://github.com/omgovich/colord.git
colorette 1.2.2 MIT https://github.com/jorgebucaran/colorette.git
commander 7.2.0 MIT https://github.com/tj/commander.js.git
component-emitter 1.3.0 MIT https://github.com/component/emitter.git
concat-map 0.0.1 MIT git://github.com/substack/node-concat-map.git
convert-source-map 1.7.0 MIT git://github.com/thlorenz/convert-source-map.git
core-js 3.8.3 MIT https://github.com/zloirock/core-js.git
core-js 3.13.0 MIT https://github.com/zloirock/core-js.git
core-js 2.6.12 MIT https://github.com/zloirock/core-js.git
cosmiconfig 5.2.1 MIT git+https://github.com/davidtheclark/cosmiconfig.git
cosmiconfig 7.0.0 MIT git+https://github.com/davidtheclark/cosmiconfig.git
css-color-names 1.0.1 MIT git://github.com/bahamas10/css-color-names.git
css-color-names 0.0.4 MIT git://github.com/bahamas10/css-color-names.git
css-declaration-sorter 4.0.1 MIT https://github.com/Siilwyn/css-declaration-sorter.git
css-line-break 1.1.1 MIT git+ssh://git@github.com/niklasvh/css-line-break.git
css-loader 5.0.2 MIT https://github.com/webpack-contrib/css-loader.git
css-select-base-adapter 0.1.1 MIT https://github.com/nrkn/css-select-base-adapter.git
css-tree 1.0.0-alpha.37 MIT https://github.com/csstree/csstree.git
css-tree 1.1.2 MIT https://github.com/csstree/csstree.git
css-loader 5.2.6 MIT https://github.com/webpack-contrib/css-loader.git
css-tree 1.1.3 MIT https://github.com/csstree/csstree.git
cssesc 3.0.0 MIT https://github.com/mathiasbynens/cssesc.git
cssnano 4.1.10 MIT https://github.com/cssnano/cssnano.git
cssnano-preset-default 4.0.7 MIT https://github.com/cssnano/cssnano.git
cssnano-util-get-arguments 4.0.0 MIT https://github.com/cssnano/cssnano.git
cssnano-util-get-match 4.0.0 MIT https://github.com/cssnano/cssnano.git
cssnano-util-raw-cache 4.0.1 MIT https://github.com/cssnano/cssnano.git
cssnano-util-same-parent 4.0.1 MIT https://github.com/cssnano/cssnano.git
cssnano 5.0.4 MIT https://github.com/cssnano/cssnano.git
cssnano-preset-default 5.1.1 MIT https://github.com/cssnano/cssnano.git
cssnano-utils 2.0.1 MIT https://github.com/cssnano/cssnano.git
csso 4.2.0 MIT https://github.com/css/csso.git
dagre 0.8.5 MIT https://github.com/dagrejs/dagre.git
debug 4.3.1 MIT git://github.com/visionmedia/debug.git
debug 2.6.9 MIT git://github.com/visionmedia/debug.git
define-properties 1.1.3 MIT git://github.com/ljharb/define-properties.git
detect-indent 4.0.0 MIT https://github.com/sindresorhus/detect-indent.git
dom-serializer 0.2.2 MIT git://github.com/cheeriojs/dom-renderer.git
dot-prop 5.3.0 MIT https://github.com/sindresorhus/dot-prop.git
dropzone 5.7.6 MIT https://github.com/dropzone/dropzone.git
dom-serializer 1.3.2 MIT git://github.com/cheeriojs/dom-renderer.git
dropzone 5.9.2 MIT https://github.com/dropzone/dropzone.git
emojis-list 3.0.0 MIT git+https://github.com/kikobeats/emojis-list.git
engine.io-client 5.1.1 MIT https://github.com/socketio/engine.io-client.git
engine.io-parser 4.0.2 MIT git@github.com:socketio/engine.io-parser.git
error-ex 1.3.2 MIT https://github.com/qix-/node-error-ex.git
es-abstract 1.18.0-next.2 MIT git://github.com/ljharb/es-abstract.git
es-abstract 1.17.7 MIT git://github.com/ljharb/es-abstract.git
es-to-primitive 1.2.1 MIT git://github.com/ljharb/es-to-primitive.git
escalade 3.1.1 MIT https://github.com/lukeed/escalade.git
escape-string-regexp 1.0.5 MIT https://github.com/sindresorhus/escape-string-regexp.git
fast-deep-equal 3.1.3 MIT git+https://github.com/epoberezkin/fast-deep-equal.git
fast-deep-equal 1.1.0 MIT git+https://github.com/epoberezkin/fast-deep-equal.git
fast-json-stable-stringify 2.1.0 MIT git://github.com/epoberezkin/fast-json-stable-stringify.git
follow-redirects 1.13.2 MIT git@github.com:follow-redirects/follow-redirects.git
function-bind 1.1.1 MIT git://github.com/Raynos/function-bind.git
follow-redirects 1.14.1 MIT git@github.com:follow-redirects/follow-redirects.git
gensync 1.0.0-beta.2 MIT https://github.com/loganfsmyth/gensync.git
get-intrinsic 1.1.1 MIT git+https://github.com/ljharb/get-intrinsic.git
globals 11.12.0 MIT https://github.com/sindresorhus/globals.git
globals 9.18.0 MIT https://github.com/sindresorhus/globals.git
graphlib 2.1.8 MIT https://github.com/dagrejs/graphlib.git
has 1.0.3 MIT git://github.com/tarruda/has.git
has-ansi 2.0.0 MIT https://github.com/sindresorhus/has-ansi.git
has-cors 1.1.0 MIT git://github.com/component/has-cors.git
has-flag 3.0.0 MIT https://github.com/sindresorhus/has-flag.git
has-flag 4.0.0 MIT https://github.com/sindresorhus/has-flag.git
has-symbols 1.0.1 MIT git://github.com/ljharb/has-symbols.git
hex-color-regex 1.1.0 MIT https://github.com/regexps/hex-color-regex.git
hsl-regex 1.0.0 MIT https://github.com/regexps/hsl-regex.git
hsla-regex 1.0.0 MIT https://github.com/regexps/hsla-regex.git
html-comment-regex 1.1.2 MIT https://github.com/stevemao/html-comment-regex.git
html-escaper 2.0.2 MIT https://github.com/WebReflection/html-escaper.git
html2canvas 1.0.0-rc.7 MIT git@github.com:niklasvh/html2canvas.git
immutability-helper 3.1.1 MIT git+https://github.com/kolodny/immutability-helper.git
import-fresh 2.0.0 MIT https://github.com/sindresorhus/import-fresh.git
import-fresh 3.3.0 MIT https://github.com/sindresorhus/import-fresh.git
imports-loader 2.0.0 MIT https://github.com/webpack-contrib/imports-loader.git
indexes-of 1.0.1 MIT git://github.com/dominictarr/indexes-of.git
invariant 2.2.4 MIT https://github.com/zertosh/invariant
ip-address 7.1.0 MIT git://github.com/beaugunderson/ip-address.git
is-absolute-url 2.1.0 MIT https://github.com/sindresorhus/is-absolute-url.git
is-any-array 0.1.0 MIT https://github.com/cheminfo-js/is-any-array.git
is-absolute-url 3.0.3 MIT https://github.com/sindresorhus/is-absolute-url.git
is-any-array 1.0.0 MIT https://github.com/cheminfo-js/is-any-array.git
is-arrayish 0.2.1 MIT https://github.com/qix-/node-is-arrayish.git
is-arrayish 0.3.2 MIT https://github.com/qix-/node-is-arrayish.git
is-callable 1.2.3 MIT git://github.com/ljharb/is-callable.git
is-color-stop 1.1.0 MIT git+https://github.com/pigcan/is-color-stop.git
is-date-object 1.0.2 MIT git://github.com/ljharb/is-date-object.git
is-directory 0.3.1 MIT https://github.com/jonschlinkert/is-directory.git
is-finite 1.1.0 MIT https://github.com/sindresorhus/is-finite.git
is-negative-zero 2.0.1 MIT git://github.com/inspect-js/is-negative-zero.git
is-obj 2.0.0 MIT https://github.com/sindresorhus/is-obj.git
is-regex 1.1.2 MIT git://github.com/inspect-js/is-regex.git
is-svg 3.0.0 MIT https://github.com/sindresorhus/is-svg.git
is-symbol 1.0.3 MIT git://github.com/inspect-js/is-symbol.git
istanbul-instrumenter-loader 3.0.1 MIT https://github.com/webpack-contrib/istanbul-instrumenter-loader.git
jquery 3.5.1 MIT https://github.com/jquery/jquery.git
javascript-natural-sort 0.7.1 MIT https://github.com/Bill4Time/javascript-natural-sort.git
jquery 3.6.0 MIT https://github.com/jquery/jquery.git
jquery-contextmenu 2.9.2 MIT git://github.com/swisnl/jQuery-contextMenu.git
jquery-ui 1.12.1 MIT git://github.com/jquery/jquery-ui.git
js-tokens 4.0.0 MIT https://github.com/lydell/js-tokens.git
js-tokens 3.0.2 MIT https://github.com/lydell/js-tokens.git
js-yaml 3.14.1 MIT https://github.com/nodeca/js-yaml.git
jsbn 1.1.0 MIT https://github.com/andyperlitch/jsbn.git
jsesc 2.5.2 MIT https://github.com/mathiasbynens/jsesc.git
jsesc 1.3.0 MIT https://github.com/mathiasbynens/jsesc.git
json-bignumber 1.0.2 MIT git@github.com:wbuss/JSONBigNumber.git
json-parse-better-errors 1.0.2 MIT https://github.com/zkat/json-parse-better-errors
json-parse-even-better-errors 2.3.1 MIT https://github.com/npm/json-parse-even-better-errors
json-schema-traverse 0.4.1 MIT git+https://github.com/epoberezkin/json-schema-traverse.git
json-schema-traverse 0.3.1 MIT git+https://github.com/epoberezkin/json-schema-traverse.git
json-source-map 0.6.1 MIT git+https://github.com/epoberezkin/json-source-map.git
json5 2.2.0 MIT git+https://github.com/json5/json5.git
json5 1.0.1 MIT git+https://github.com/json5/json5.git
karma-coverage 2.0.3 MIT git://github.com/karma-runner/karma-coverage.git
lines-and-columns 1.1.6 MIT https://github.com/eventualbuddha/lines-and-columns.git
loader-utils 2.0.0 MIT https://github.com/webpack/loader-utils.git
loader-utils 1.4.0 MIT https://github.com/webpack/loader-utils.git
lodash 4.17.20 MIT https://github.com/lodash/lodash.git
lodash 4.17.21 MIT https://github.com/lodash/lodash.git
lodash.memoize 4.1.2 MIT https://github.com/lodash/lodash.git
lodash.uniq 4.5.0 MIT https://github.com/lodash/lodash.git
loose-envify 1.4.0 MIT git://github.com/zertosh/loose-envify.git
@@ -263,147 +255,130 @@ lunr 0.7.2
make-dir 3.1.0 MIT https://github.com/sindresorhus/make-dir.git
matches-selector 0.0.1 MIT https://github.com/ForbesLindesay/matches-selector.git
minimist 1.2.5 MIT git://github.com/substack/minimist.git
mkdirp 0.5.5 MIT https://github.com/substack/node-mkdirp.git
ml-array-max 1.2.0 MIT git+https://github.com/mljs/array.git
ml-array-min 1.2.0 MIT git+https://github.com/mljs/array.git
ml-array-rescale 1.3.2 MIT git+https://github.com/mljs/array.git
ml-matrix 6.6.0 MIT https://github.com/mljs/matrix.git
ml-array-max 1.2.3 MIT git+https://github.com/mljs/array.git
ml-array-min 1.2.2 MIT git+https://github.com/mljs/array.git
ml-array-rescale 1.3.5 MIT git+https://github.com/mljs/array.git
ml-matrix 6.8.0 MIT https://github.com/mljs/matrix.git
mobius1-selectr 2.4.13 MIT git+https://github.com/Mobius1/Selectr.git
moment 2.29.1 MIT https://github.com/moment/moment.git
moment 2.24.0 MIT https://github.com/moment/moment.git
moment-timezone 0.5.33 MIT https://github.com/moment/moment-timezone.git
ms 2.1.2 MIT https://github.com/zeit/ms.git
ms 2.0.0 MIT https://github.com/zeit/ms.git
nanoid 3.1.20 MIT https://github.com/ai/nanoid.git
nanoid 3.1.23 MIT https://github.com/ai/nanoid.git
nanopop 2.1.0 MIT https://github.com/Simonwep/nanopop.git
node-releases 1.1.70 MIT git+https://github.com/chicoxyzzy/node-releases.git
normalize-url 3.3.0 MIT https://github.com/sindresorhus/normalize-url.git
node-releases 1.1.72 MIT git+https://github.com/chicoxyzzy/node-releases.git
normalize-url 4.5.1 MIT https://github.com/sindresorhus/normalize-url.git
object-assign 4.1.1 MIT https://github.com/sindresorhus/object-assign.git
object-inspect 1.9.0 MIT git://github.com/inspect-js/object-inspect.git
object-keys 1.1.1 MIT git://github.com/ljharb/object-keys.git
object.assign 4.1.2 MIT git://github.com/ljharb/object.assign.git
object.getownpropertydescriptors 2.1.1 MIT git://github.com/es-shims/object.getownpropertydescriptors.git
object.values 1.1.2 MIT git://github.com/es-shims/Object.values.git
parse-json 4.0.0 MIT https://github.com/sindresorhus/parse-json.git
parent-module 1.0.1 MIT https://github.com/sindresorhus/parent-module.git
parse-json 5.2.0 MIT https://github.com/sindresorhus/parse-json.git
parseqs 0.0.6 MIT https://github.com/get/querystring.git
parseuri 0.0.6 MIT https://github.com/get/parseuri.git
path-type 4.0.0 MIT https://github.com/sindresorhus/path-type.git
pathfinding 0.4.18 MIT git://github.com/qiao/PathFinding.js.git
performance-now 2.1.0 MIT git://github.com/braveg1rl/performance-now.git
picomodal 3.0.0 MIT https://github.com/Nycto/PicoModal.git
popper.js 1.16.1 MIT git+https://github.com/FezVrasta/popper.js.git
postcss 8.2.5 MIT https://github.com/postcss/postcss.git
postcss 7.0.35 MIT https://github.com/postcss/postcss.git
postcss-calc 7.0.5 MIT https://github.com/postcss/postcss-calc.git
postcss-colormin 4.0.3 MIT https://github.com/cssnano/cssnano.git
postcss-convert-values 4.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-discard-comments 4.0.2 MIT https://github.com/cssnano/cssnano.git
postcss-discard-duplicates 4.0.2 MIT https://github.com/cssnano/cssnano.git
postcss-discard-empty 4.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-discard-overridden 4.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-merge-longhand 4.0.11 MIT https://github.com/cssnano/cssnano.git
postcss-merge-rules 4.0.3 MIT https://github.com/cssnano/cssnano.git
postcss-minify-font-values 4.0.2 MIT https://github.com/cssnano/cssnano.git
postcss-minify-gradients 4.0.2 MIT https://github.com/cssnano/cssnano.git
postcss-minify-params 4.0.2 MIT https://github.com/cssnano/cssnano.git
postcss-minify-selectors 4.0.2 MIT https://github.com/cssnano/cssnano.git
postcss 8.3.0 MIT https://github.com/postcss/postcss.git
postcss-calc 8.0.0 MIT https://github.com/postcss/postcss-calc.git
postcss-colormin 5.1.1 MIT https://github.com/cssnano/cssnano.git
postcss-convert-values 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-discard-comments 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-discard-duplicates 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-discard-empty 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-discard-overridden 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-merge-longhand 5.0.2 MIT https://github.com/cssnano/cssnano.git
postcss-merge-rules 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-minify-font-values 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-minify-gradients 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-minify-params 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-minify-selectors 5.1.0 MIT https://github.com/cssnano/cssnano.git
postcss-modules-local-by-default 4.0.0 MIT https://github.com/css-modules/postcss-modules-local-by-default.git
postcss-normalize-charset 4.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-normalize-display-values 4.0.2 MIT https://github.com/cssnano/cssnano.git
postcss-normalize-positions 4.0.2 MIT https://github.com/cssnano/cssnano.git
postcss-normalize-repeat-style 4.0.2 MIT https://github.com/cssnano/cssnano.git
postcss-normalize-string 4.0.2 MIT https://github.com/cssnano/cssnano.git
postcss-normalize-timing-functions 4.0.2 MIT https://github.com/cssnano/cssnano.git
postcss-normalize-unicode 4.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-normalize-url 4.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-normalize-whitespace 4.0.2 MIT https://github.com/cssnano/cssnano.git
postcss-ordered-values 4.1.2 MIT https://github.com/cssnano/cssnano.git
postcss-reduce-initial 4.0.3 MIT https://github.com/cssnano/cssnano.git
postcss-reduce-transforms 4.0.2 MIT https://github.com/cssnano/cssnano.git
postcss-selector-parser 6.0.4 MIT https://github.com/postcss/postcss-selector-parser.git
postcss-selector-parser 3.1.2 MIT https://github.com/postcss/postcss-selector-parser.git
postcss-svgo 4.0.2 MIT https://github.com/cssnano/cssnano.git
postcss-unique-selectors 4.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-normalize-charset 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-normalize-display-values 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-normalize-positions 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-normalize-repeat-style 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-normalize-string 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-normalize-timing-functions 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-normalize-unicode 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-normalize-url 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-normalize-whitespace 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-ordered-values 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-reduce-initial 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-reduce-transforms 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-selector-parser 6.0.6 MIT https://github.com/postcss/postcss-selector-parser.git
postcss-svgo 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-unique-selectors 5.0.1 MIT https://github.com/cssnano/cssnano.git
postcss-value-parser 4.1.0 MIT https://github.com/TrySound/postcss-value-parser.git
postcss-value-parser 3.3.1 MIT https://github.com/TrySound/postcss-value-parser.git
punycode 2.1.1 MIT https://github.com/bestiejs/punycode.js.git
q 1.5.1 MIT git://github.com/kriskowal/q.git
raf 3.4.1 MIT git://github.com/chrisdickinson/raf.git
react 17.0.1 MIT https://github.com/facebook/react.git
react-dom 17.0.1 MIT https://github.com/facebook/react.git
react 17.0.2 MIT https://github.com/facebook/react.git
react-dom 17.0.2 MIT https://github.com/facebook/react.git
regenerator-runtime 0.11.1 MIT https://github.com/facebook/regenerator/tree/master/packages/regenerator-runtime
repeating 2.0.1 MIT https://github.com/sindresorhus/repeating.git
requirejs 2.3.6 MIT https://github.com/jrburke/r.js.git
resolve-from 3.0.0 MIT https://github.com/sindresorhus/resolve-from.git
resolve-from 4.0.0 MIT https://github.com/sindresorhus/resolve-from.git
rgb-regex 1.0.1 MIT https://github.com/regexps/rgb-regex.git
rgba-regex 1.0.0 MIT https://github.com/johnotander/rgba-regex.git
rollup 1.32.1 MIT https://github.com/rollup/rollup.git
safe-buffer 5.1.2 MIT git://github.com/feross/safe-buffer.git
scheduler 0.20.1 MIT https://github.com/facebook/react.git
scheduler 0.20.2 MIT https://github.com/facebook/react.git
schema-utils 3.0.0 MIT https://github.com/webpack/schema-utils.git
schema-utils 0.3.0 MIT git+https://github.com/webpack-contrib/schema-utils.git
select2 4.0.13 MIT git://github.com/select2/select2.git
shim-loader 1.0.1 MIT https://github.com/zinserjan/shim-loader
simple-swizzle 0.2.2 MIT https://github.com/qix-/node-simple-swizzle.git
slickgrid 2.3.16 MIT git+https://github.com/6pac/SlickGrid.git
snapsvg-cjs 0.0.6 MIT git+https://github.com/geelen/Snap.svg-cjs.git
socket.io-client 4.1.2 MIT https://github.com/socketio/socket.io-client.git
socket.io-parser 4.0.4 MIT https://github.com/socketio/socket.io-parser.git
source-list-map 1.1.2 MIT https://github.com/webpack/source-list-map.git
split.js 1.6.2 MIT https://github.com/nathancahill/split
split.js 1.6.4 MIT https://github.com/nathancahill/split
stable 0.1.8 MIT https://github.com/Two-Screen/stable.git
string.prototype.trimend 1.0.3 MIT git://github.com/es-shims/String.prototype.trimEnd.git
string.prototype.trimstart 1.0.3 MIT git://github.com/es-shims/String.prototype.trimStart.git
strip-ansi 3.0.1 MIT https://github.com/chalk/strip-ansi.git
strip-comments 2.0.1 MIT https://github.com/jonschlinkert/strip-comments.git
stylehacks 4.0.3 MIT https://github.com/cssnano/cssnano.git
stylehacks 5.0.1 MIT https://github.com/cssnano/cssnano.git
supports-color 5.5.0 MIT https://github.com/chalk/supports-color.git
supports-color 6.1.0 MIT https://github.com/chalk/supports-color.git
supports-color 2.0.0 MIT https://github.com/chalk/supports-color.git
supports-color 7.2.0 MIT https://github.com/chalk/supports-color.git
svgo 1.3.2 MIT git://github.com/svg/svgo.git
supports-color 2.0.0 MIT https://github.com/chalk/supports-color.git
svgo 2.3.0 MIT git://github.com/svg/svgo.git
tempusdominus-bootstrap-4 5.39.0 MIT https://github.com/tempusdominus/bootstrap-4.git
tempusdominus-core 5.19.0 MIT https://github.com/tempusdominus/core.git
timsort 0.3.0 MIT https://github.com/mziccard/node-timsort.git
tippy.js 6.2.7 MIT git+https://github.com/atomiks/tippyjs.git
tippy.js 6.3.1 MIT git+https://github.com/atomiks/tippyjs.git
to-fast-properties 2.0.0 MIT https://github.com/sindresorhus/to-fast-properties.git
to-fast-properties 1.0.3 MIT https://github.com/sindresorhus/to-fast-properties.git
trim-right 1.0.1 MIT https://github.com/sindresorhus/trim-right.git
underscore 1.12.0 MIT git://github.com/jashkenas/underscore.git
uniq 1.0.1 MIT git://github.com/mikolalysenko/uniq.git
underscore 1.13.1 MIT git://github.com/jashkenas/underscore.git
uniqs 2.0.0 MIT git://github.com/fgnass/uniqs.git
unquote 1.1.1 MIT https://github.com/lakenen/node-unquote.git
util-deprecate 1.0.2 MIT git://github.com/TooTallNate/util-deprecate.git
util.promisify 1.0.1 MIT git+https://github.com/ljharb/util.promisify.git
vendors 1.0.4 MIT https://github.com/wooorm/vendors.git
webpack-sources 0.2.3 MIT git+https://github.com/webpack/webpack-sources.git
wkx 0.5.0 MIT http://github.com/cschwarz/wkx.git
@fortawesome/fontawesome-free 5.15.2 (CC-BY-4.0 AND OFL-1.1 AND MIT) https://github.com/FortAwesome/Font-Awesome
ws 7.4.6 MIT https://github.com/websockets/ws.git
xterm 4.12.0 MIT https://github.com/xtermjs/xterm.js
xterm-addon-fit 0.5.0 MIT https://github.com/xtermjs/xterm.js
xterm-addon-search 0.8.0 MIT https://github.com/xtermjs/xterm.js
xterm-addon-web-links 0.4.0 MIT https://github.com/xtermjs/xterm.js
yeast 0.1.2 MIT https://github.com/unshiftio/yeast.git
@fortawesome/fontawesome-free 5.15.3 (CC-BY-4.0 AND OFL-1.1 AND MIT) https://github.com/FortAwesome/Font-Awesome
@sphinxxxx/color-conversion 2.2.2 ISC git+https://github.com/Sphinxxxx/color-conversion.git
@trysound/sax 0.1.1 ISC git://github.com/svg/sax.git
boolbase 1.0.0 ISC https://github.com/fb55/boolbase
electron-to-chromium 1.3.661 ISC https://github.com/kilian/electron-to-chromium/
css-declaration-sorter 6.0.3 ISC https://github.com/Siilwyn/css-declaration-sorter.git
electron-to-chromium 1.3.740 ISC https://github.com/kilian/electron-to-chromium/
icss-utils 5.1.0 ISC git+https://github.com/css-modules/icss-utils.git
is-resolvable 1.1.0 ISC https://github.com/shinnn/is-resolvable.git
jsonrepair 2.2.1 ISC https://github.com/josdejong/jsonrepair.git
lru-cache 6.0.0 ISC git://github.com/isaacs/node-lru-cache.git
minimatch 3.0.4 ISC git://github.com/isaacs/minimatch.git
postcss-modules-extract-imports 3.0.0 ISC https://github.com/css-modules/postcss-modules-extract-imports.git
postcss-modules-scope 3.0.0 ISC https://github.com/css-modules/postcss-modules-scope.git
postcss-modules-values 4.0.0 ISC git+https://github.com/css-modules/postcss-modules-values.git
sax 1.2.4 ISC git://github.com/isaacs/sax-js.git
semver 7.3.4 ISC https://github.com/npm/node-semver
semver 7.3.5 ISC https://github.com/npm/node-semver
semver 5.7.1 ISC https://github.com/npm/node-semver
semver 6.3.0 ISC https://github.com/npm/node-semver
vanilla-picker 2.11.2 ISC https://github.com/Sphinxxxx/vanilla-picker.git
yallist 4.0.0 ISC git+https://github.com/isaacs/yallist.git
bootstrap-datepicker 1.9.0 Apache-2.0 https://github.com/uxsolutions/bootstrap-datepicker.git
eve 0.5.4 Apache-2.0 git@github.com:adobe-webplatform/eve.git
paths-js 0.4.11 Apache-2.0 https://github.com/andreaferretti/paths-js.git
snapsvg 0.5.1 Apache-2.0 git@github.com:adobe-webplatform/Snap.svg.git
caniuse-lite 1.0.30001185 CC-BY-4.0 https://github.com/ben-eb/caniuse-lite.git
css-select 2.1.0 BSD-2-Clause git://github.com/fb55/css-select.git
css-what 3.4.2 BSD-2-Clause https://github.com/fb55/css-what
domelementtype 1.3.1 BSD-2-Clause git://github.com/fb55/domelementtype.git
domelementtype 2.1.0 BSD-2-Clause git://github.com/fb55/domelementtype.git
domutils 1.7.0 BSD-2-Clause git://github.com/FB55/domutils.git
entities 2.2.0 BSD-2-Clause git://github.com/fb55/entities.git
esprima 4.0.1 BSD-2-Clause https://github.com/jquery/esprima.git
esutils 2.0.3 BSD-2-Clause http://github.com/estools/esutils.git
leaflet 1.7.1 BSD-2-Clause git://github.com/Leaflet/Leaflet.git
nth-check 1.0.2 BSD-2-Clause https://github.com/fb55/nth-check
uri-js 4.4.1 BSD-2-Clause http://github.com/garycourt/uri-js
FileSaver 0.10.0 UNKNOWN Unknown
heap 0.2.5 UNKNOWN git://github.com/qiao/heap.js.git
yaml 1.10.2 ISC https://github.com/eemeli/yaml.git
ace-builds 1.4.12 BSD-3-Clause https://github.com/ajaxorg/ace-builds.git
istanbul-lib-coverage 1.2.1 BSD-3-Clause git@github.com:istanbuljs/istanbuljs.git
istanbul-lib-coverage 3.0.0 BSD-3-Clause git+ssh://git@github.com/istanbuljs/istanbuljs.git
istanbul-lib-instrument 1.10.2 BSD-3-Clause git@github.com:istanbuljs/istanbuljs.git
@@ -413,14 +388,32 @@ istanbul-lib-source-maps 4.0.0
istanbul-reports 3.0.2 BSD-3-Clause git+ssh://git@github.com/istanbuljs/istanbuljs.git
source-map 0.5.7 BSD-3-Clause http://github.com/mozilla/source-map.git
source-map 0.6.1 BSD-3-Clause http://github.com/mozilla/source-map.git
sprintf-js 1.0.3 BSD-3-Clause https://github.com/alexei/sprintf.js.git
source-map-js 0.6.2 BSD-3-Clause http://github.com/7rulnik/source-map.git
sprintf-js 1.1.2 BSD-3-Clause https://github.com/alexei/sprintf.js.git
mdn-data 2.0.4 CC0-1.0 https://github.com/mdn/data.git
bootstrap-datepicker 1.9.0 Apache-2.0 https://github.com/uxsolutions/bootstrap-datepicker.git
eve 0.5.4 Apache-2.0 git@github.com:adobe-webplatform/eve.git
jmespath 0.15.0 Apache-2.0 git://github.com/jmespath/jmespath.js
jsoneditor 9.5.3 Apache-2.0 https://github.com/josdejong/jsoneditor.git
paths-js 0.4.11 Apache-2.0 https://github.com/andreaferretti/paths-js.git
snapsvg 0.5.1 Apache-2.0 git@github.com:adobe-webplatform/Snap.svg.git
caniuse-lite 1.0.30001230 CC-BY-4.0 https://github.com/browserslist/caniuse-lite.git
css-select 3.1.2 BSD-2-Clause git://github.com/fb55/css-select.git
css-what 4.0.0 BSD-2-Clause https://github.com/fb55/css-what
domelementtype 2.2.0 BSD-2-Clause git://github.com/fb55/domelementtype.git
domhandler 4.2.0 BSD-2-Clause git://github.com/fb55/domhandler.git
domutils 2.6.0 BSD-2-Clause git://github.com/fb55/domutils.git
entities 2.2.0 BSD-2-Clause git://github.com/fb55/entities.git
esutils 2.0.3 BSD-2-Clause http://github.com/estools/esutils.git
leaflet 1.7.1 BSD-2-Clause git://github.com/Leaflet/Leaflet.git
nth-check 2.0.0 BSD-2-Clause https://github.com/fb55/nth-check
uri-js 4.4.1 BSD-2-Clause http://github.com/garycourt/uri-js
FileSaver 0.10.0 UNKNOWN Unknown
heap 0.2.5 UNKNOWN git://github.com/qiao/heap.js.git
mdn-data 2.0.14 CC0-1.0 https://github.com/mdn/data.git
mousetrap 1.6.5 Apache-2.0 WITH LLVM-exception git://github.com/ccampbell/mousetrap.git
precond 0.2.3 MIT* https://github.com/MathieuTurcotte/node-precond.git
webcabin-docker 2.2.4-dev MIT* Unknown
webcabin-docker 2.2.5 MIT* Unknown
tablesorter 2.31.3 (MIT OR GPL-2.0) git://github.com/Mottie/tablesorter.git
362 dependencies listed.
345 dependencies listed.
+2 -11
View File
@@ -24,16 +24,7 @@ appbundle:
./pkg/mac/build.sh
install-node:
cd web && npm install
cd web && npm audit fix
rm -f web/yarn.lock
cd web && yarn import
# Commented the below line to avoid vulnerability in lodash package.
# Refer https://www.npmjs.com/advisories/1523.
# Once fixed we will uncomment it.
# cd web && yarn audit
rm -f package-lock.json
rm -f web/package-lock.json
cd web && yarn install
bundle:
cd web && yarn run bundle
@@ -151,7 +142,7 @@ msg-extract:
cd web && pybabel extract -F babel.cfg -o pgadmin/messages.pot pgadmin
msg-update:
cd web && pybabel update -i pgadmin/messages.pot -d pgadmin/translations
cd web && pybabel update --no-fuzzy-matching -i pgadmin/messages.pot -d pgadmin/translations
.PHONY: docs
+1 -1
View File
@@ -109,7 +109,7 @@ Click the *Variables* tab to continue.
:alt: Column dialog variables tab
:align: center
Use the *Variables* tab to to specify the number of distinct values that may be
Use the *Variables* tab to specify the number of distinct values that may be
present in the column; this value overrides estimates made by the ANALYZE
command. Click the *Add* icon (+) to add a *Name*/*Value* pair:
+1 -1
View File
@@ -43,7 +43,7 @@ The configuration files are as follows:
Linux,/etc/pgadmin/config_system.py
macOS,/Library/Preferences/pgadmin/config_system.py
Windows,%CommonProgramFiles%\pgadmin\config_system.py
Windows,%CommonProgramFiles%\\pgadmin\\config_system.py
.. note:: If the SERVER_MODE setting is changed in ``config_distro.py``,
``config_local.py``, or ``config_system.py`` you will most likely need to
+20 -3
View File
@@ -23,8 +23,19 @@ server:
* PostgreSQL 12: */usr/local/pgsql-12*
* PostgreSQL 13: */usr/local/pgsql-13*
The most recent version of the utilities is used by default; this may be
changed in the :ref:`preferences`.
The default binary paths set in the container are as follows:
.. code-block:: bash
DEFAULT_BINARY_PATHS = {
'pg-13': '/usr/local/pgsql-13'
'pg-12': '/usr/local/pgsql-12'
'pg-11': '/usr/local/pgsql-11'
'pg-10': '/usr/local/pgsql-10'
'pg-9.6': '/usr/local/pgsql-9.6'
}
this may be changed in the :ref:`preferences`.
Environment Variables
*********************
@@ -104,7 +115,7 @@ Adjust the number of threads the Gunicorn server uses to handle incoming
requests. This should typically be left as-is, except in highly loaded systems
where it may be increased.
**PGADMIN_CONFIG_**
**PGADMIN_CONFIG_***
This is a variable prefix that can be used to override any of the configuration
options in pgAdmin's *config.py* file. Add the *PGADMIN_CONFIG_* prefix to any
@@ -117,6 +128,12 @@ is read after */pgadmin4/config.py* and before */pgadmin4/config_local.py*.
Any settings given will therefore override anything in config.py, but can be
overridden by settings in config_local.py.
Settings are only written to */pgadmin4/config_distro.py* once, typically on
first launch of the container. If */pgadmin4/config_distro.py* contains one or
more lines, then no changes are made; for example, if the container instance is
restarted, or */pgadmin4/config_distro.py* is mapped to a file on persistent
storage (not recommended - use */pgadmin4/config_local.py* instead)!
See :ref:`config_py` for more information on the available configuration settings.
Mapped Files and Directories
+1
View File
@@ -16,3 +16,4 @@ PL/SQL code.
editgrid
schema_diff
erd_tool
psql_tool
+80
View File
@@ -107,6 +107,86 @@ properties of the geometries directly in map, just click the specific geometry:
- *Internet access:* An internet connection is required for the Geometry Viewer
to function correctly.
**JSON Data Editor**
A built in json editor is provided for *JSON/JSONB Data*.Double clicking on json/jsonb
data type cell in data grid will open JSON Editor.Editor provides different mode to
view and edit json data.
.. image:: images/json_editor_modes.png
:alt: Json Editor
:align: center
*Code Mode*:
Provides way to format & compact json data.Also provides ability to repair json data
by fixing quotes and escape characters, removing comments and JSONP notation and
turn JavaScript objects into JSON.
*Tree Mode*:
Enabled to change, add, move, remove, and duplicate fields and values.Provides ability
to searh & hilight data.
*Form Mode*:
Allows only to edit values in json data there by providing ability to keep data structure
unchanged while editing.
*Preview Mode*:
Provides ability to check data before saving and also shows size of current json data.
Format and compact json data as well.
*Editor Toolbar*
Different options are provided to manipulate json data.
Code/Preview mode:
.. image:: images/json_editor_code_preview_tool_bar.png
:alt: Json Editor Code/Preview mode Tool Bar
:align: center
Tree/Form mode:
.. image:: images/json_editor_tree_form_mode_tool_bar.png
:alt: Json Editor Tree/Form mode Tool Bar
:align: center
.. table::
:class: longtable
:widths: 1 3 2
+----------------------+----------------------------------------------------------------------------------------+---------------------------+
| Icon | Behavior | Available in mode |
+======================+========================================================================================+===========================+
| *Format Json* | Click to *Format Json* format json data with proper indentation. | Code, Preview |
+----------------------+----------------------------------------------------------------------------------------+---------------------------+
| *Compact Json* | Click to *Compact Json* get compacted json data. | Code, Preview |
+----------------------+----------------------------------------------------------------------------------------+---------------------------+
| *Sort* | Click to *Sort* icon to set sorting criteria for the data using file values. | Code, Preview, Tree |
+----------------------+----------------------------------------------------------------------------------------+---------------------------+
| *Transform* | Click to *Transform* to filter data using JSME query language. | Code, Preview, Tree |
+----------------------+----------------------------------------------------------------------------------------+---------------------------+
| *Undo* | Click to *Undo* to undo last action performed on data . | Code, Preview, Tree, From |
+----------------------+----------------------------------------------------------------------------------------+---------------------------+
| *Redo* | Click to *Redo* to repat last action performed on data . | Code, Preview, Tree, From |
+----------------------+----------------------------------------------------------------------------------------+---------------------------+
| *Mode* | Click to *Mode* dropdown to change dipaly mode of editor.Different modes avaialble | Code, Tree, From, Preview |
| | are Code, Preview, Tree, From. | |
+----------------------+----------------------------------------------------------------------------------------+---------------------------+
| *Expand All* | Click to *Expand All* to expand json data. | Tree, From |
+----------------------+----------------------------------------------------------------------------------------+---------------------------+
| *Collapse All* | Click to *Redo* to collapse json data. | Tree, From |
+----------------------+----------------------------------------------------------------------------------------+---------------------------+
| *Search Box* | Enter partial/complete string to search in data. | Tree, From |
+----------------------+----------------------------------------------------------------------------------------+---------------------------+
Sort/Filter options dialog
**************************
+1 -1
View File
@@ -49,7 +49,7 @@ Click the *Columns* tab to continue.
:alt: Foreign table dialog columns tab
:align: center
Use the fields in the *Columns* tab to to add columns and their attributes to
Use the fields in the *Columns* tab to add columns and their attributes to
the table. Click the *Add* icon (+) to define a column:
* Use the *Name* field to add a descriptive name for the column.
+2
View File
@@ -35,8 +35,10 @@ Mode is pre-configured for security.
login
user_management
change_user_password
restore_locked_user
ldap
kerberos
oauth2
.. note:: Pre-compiled and configured installation packages are available for
Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 387 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 KiB

After

Width:  |  Height:  |  Size: 156 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 142 KiB

After

Width:  |  Height:  |  Size: 237 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 208 KiB

After

Width:  |  Height:  |  Size: 183 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

After

Width:  |  Height:  |  Size: 53 KiB

+76 -16
View File
@@ -4,7 +4,12 @@
`Enabling Kerberos Authentication`:index:
*****************************************
To configure Kerberos authentication, you must set your Kerberos Server and generate the *kinit* ticket on the client. To enable the Kerberos authentication for pgAdmin, you must configure the Kerberos settings in *config_local.py* or *config_system.py* (see the :ref:`config.py <config_py>` documentation) on the system where pgAdmin is installed in Server mode. You can copy these settings from *config.py* file and modify the values for the following parameters.
To configure Kerberos authentication, you must setup your Kerberos Server and
generate a ticket on the client using *kinit*. To enable Kerberos authentication
for pgAdmin, you must configure the Kerberos settings in *config_local.py* or
*config_system.py* (see the :ref:`config.py <config_py>` documentation) on the
system where pgAdmin is installed in Server mode. You can copy these settings
from *config.py* file and modify the values for the following parameters.
.. csv-table::
:header: "**Parameter**", "**Description**"
@@ -12,25 +17,43 @@ To configure Kerberos authentication, you must set your Kerberos Server and gene
:widths: 35, 55
"AUTHENTICATION_SOURCES","The default value for this parameter is *internal*.
To enable Kerberos authentication, you must include *kerberos* in the list of values for this parameter. you can modify the value as follows:
To enable Kerberos authentication, you must include *kerberos* in the
list of values for this parameter. you can modify the value as follows:
* [‘kerberos’]: pgAdmin will use only Kerberos authentication.
* [‘kerberos’, ‘internal’]: pgAdmin will first try to authenticate the user through kerberos. If that authentication fails, then it will return back to the login dialog where you need to provide internal pgAdmin user credentials for authentication."
"KERBEROS_AUTO_CREATE_USER", "Specify value to *True* if you want to automatically create a pgAdmin user corresponding to the kerberos user credentials. Please note that password is not stored in the pgAdmin database."
"KRB_APP_HOST_NAME", "Specify the name of *pgAdmin webserver hostname*. Please note that if it is not set, it will take the value of *default_server* parameter."
* [‘kerberos’, ‘internal’]: pgAdmin will first try to authenticate the user
through kerberos. If that authentication fails, then it will return back
to the login dialog where you need to provide internal pgAdmin user
credentials for authentication."
"KERBEROS_AUTO_CREATE_USER", "Set the value to *True* if you want to
automatically create a pgAdmin user corresponding to a successfully
authenticated Kerberos user. Please note that password is not stored in the
pgAdmin database."
"KRB_APP_HOST_NAME", "Specify the name of *pgAdmin webserver hostname*.
Please note that if it is not set, it will take the value of
*default_server* parameter."
Keytab file for HTTP Service
============================
* Generate the *Keytab* file for the HTTP service principal and copy it to the *pgAdmin* webserver machine. Ensure that the operating system user owning the *pgAdmin* webserver is the owner of this file and should be accessible by that user.
* Generate the *Keytab* file for the HTTP service principal and copy it to the
*pgAdmin* webserver machine. Ensure that the operating system user owning
the *pgAdmin* webserver is the owner of this file and should be accessible
by that user.
* Please note that either you should set *default_keytab_name* parameter in *krb5.conf* file or the environment variable *KRB5_KTNAME*. If not set then explicitly set *KRB_KTNAME* to the location of your *Keytab* file in the *config_local.py* or *config_system.py* file.
* Please note that either you should set *default_keytab_name* parameter in
*krb5.conf* file or the environment variable *KRB5_KTNAME*. If not set then
explicitly set *KRB_KTNAME* to the location of your *Keytab* file in the
*config_local.py* or *config_system.py* file.
Apache HTTPD Configuration
==========================
If the *pgAdmin* server is under the Apache Server, then you need to add the following parameters in *Directory* directive of :ref:`Apache HTTPD Configuration <server_deployment>`:
If the *pgAdmin* server is under the Apache Server, then you need to add the
following parameters in *Directory* directive of
:ref:`Apache HTTPD Configuration <server_deployment>`:
* WSGIScriptReloading On
@@ -40,30 +63,67 @@ If the *pgAdmin* server is under the Apache Server, then you need to add the fol
Browser settings to configure Kerberos Authentication
=====================================================
You need to do the browser settings on the client machine to use the *Spnego/Kerberos*.
You need to configure the browser settings on the client machine to use
Kerberos authentication via *SPNEGO*.
- For Mozilla Firefox
- Open the low level Firefox configuration page by loading the *about:config* page.
- Open the low level Firefox configuration page by entering *about:config* in
the address bar.
- In the Search text box, enter: *network.negotiate-auth.trusted-uris*
- Double-click the *network.negotiate-auth.trusted-uris* preference and enter the hostname or the domain of the web server that is protected by Kerberos HTTP SPNEGO. Separate multiple domains and hostnames with a comma.
- Double-click the *network.negotiate-auth.trusted-uris* preference and enter
the hostname or the domain of the web server that is protected by Kerberos
HTTP SPNEGO. Separate multiple domains and hostnames with a comma.
- Click OK.
- For Google Chrome
- For Windows:
- On Windows:
* Open the Control Panel to access the Internet Options dialog.
* Select the Security tab.
* Select the Local Intranet zone and click the Sites button.
* Make sure that the first two options, Include all local (intranet) sites not listed in other zones and Include all sites that bypass the proxy server are checked.
* Click Advanced and add the names of the domains that are protected by Kerberos HTTP SPNEGO, one at a time, to the list of websites. For example, myhost.example.com. Click Close.
* Make sure that the first two options, *Include all local (intranet) sites
not listed in other zones* and *Include all sites that bypass the proxy
server* are checked.
* Click Advanced and add the names of the domains that are protected by
Kerberos HTTP SPNEGO, one at a time, to the list of websites. For example,
myhost.example.com. Click Close.
* Click OK to save your configuration changes.
- For Linux or MacOS:
- On Linux or macOS:
* Add the *--auth-server-whitelist* parameter to the google-chrome command. For example, to run Chrome from a Linux prompt, run the google-chrome command as follows:
* Add the *--auth-server-whitelist* parameter to the google-chrome command.
For example, to run Chrome from a Linux prompt, run the google-chrome
command as follows:
.. code-block:: text
google-chrome --auth-server-whitelist = "hostname/domain"
PostgreSQL Server settings to configure Kerberos Authentication
===============================================================
* To connect the PostgreSQL server with Kerberos authentication, GSSAPI support
has to be enabled when PostgreSQL is built and the necessary
`configuration <https://www.postgresql.org/docs/current/gssapi-auth.html>`_
has to be in place.
* In pgAdmin you need to enable Kerberos authentication for the PostgreSQL
server by setting "Kerberos authentication" flag to True in the Server dialog.
Once it is enabled, pgAdmin will not prompt for a password and will try to
connect to the PostgreSQL server using Kerberos.
* Note that, you have to login into pgAdmin with Kerberos authentication to
then connect to PostgreSQL using Kerberos.
Master Password
===============
In the multi user mode, pgAdmin uses user's login password to encrypt/decrypt the PostgreSQL server password.
In the Kerberos authentication, the pgAdmin user does not have the password, so we need an encryption key to store
the PostgreSQL server password for the servers which are not configured to use the Kerberos authentication.
To accomplish this, set the configuration parameter MASTER_PASSWORD to *True*, so upon setting the master password,
it will be used as an encryption key while storing the password. If it is False, the server password can not be stored.
+11 -4
View File
@@ -10,16 +10,16 @@ Use the *Login* dialog to log in to pgAdmin:
:alt: pgAdmin login dialog
:align: center
Use the fields in the *Login* dialog to authenticate your connection. There are
Use the fields in the *Login* dialog to authenticate your connection. There are
two ways to authenticate your connection:
- From pgAdmin version 4.21 onwards, support for LDAP authentication
has been added. If LDAP authentication has been enabled for your pgAdmin
application, you can use your LDAP credentials to log in to pgAdmin:
* Provide the LDAP username in the *Email Address/Username* field.
* Provide the LDAP username in the *Email Address/Username* field.
* Provide your LDAP password in the Password field.
* Provide your LDAP password in the Password field.
- Alternatively, you can use the following information to log in to pgAdmin:
@@ -53,6 +53,13 @@ If you have forgotten the email associated with your account, please contact
your administrator.
Please note that your LDAP password cannot be recovered using this dialog. If
you enter your LDAP username in the *Email Address/Username* field, and then
you enter your LDAP username in the *Email Address/Username* field, and then
enter your email to recover your password, an error message will be displayed
asking you to contact the LDAP administrator to recover your LDAP password.
Avoiding a bruteforce attack
****************************
You have the possibility to lock an account by setting ``MAX_LOGIN_ATTEMPTS``
once it has reached the maximum number of login attempts.
You can disable this feature by setting the value to zero.
+2 -1
View File
@@ -18,4 +18,5 @@ database, right-click on the *Databases* node, and select *Create Database...*
move_objects
resource_group_dialog
role_dialog
tablespace_dialog
tablespace_dialog
role_reassign_dialog
+3 -1
View File
@@ -21,7 +21,7 @@ Use the *File* menu to access the following options:
+-------------------------+---------------------------------------------------------------------------------------------------------+
| Option | Action |
+=========================+=========================================================================================================+
| *Preferences* | Click to open the :ref:`Preferences <preferences>` dialog to to customize your pgAdmin settings. |
| *Preferences* | Click to open the :ref:`Preferences <preferences>` dialog to customize your pgAdmin settings. |
+-------------------------+---------------------------------------------------------------------------------------------------------+
| *Reset Layout* | If you have modified the workspace, click to restore the default layout. |
+-------------------------+---------------------------------------------------------------------------------------------------------+
@@ -128,6 +128,8 @@ Use the *Tools* menu to access the following options (in alphabetical order):
+---------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
| *Search Objects...* | Click to open the :ref:`Search Objects... <search_objects>` and start searching any kind of objects in a database. |
+---------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
| *PSQL Tool* | Click to open the :ref:`PSQL Tool <psql_tool>` and start PSQL in the current database context. |
+---------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
The Help Menu
*************
+1 -1
View File
@@ -4,7 +4,7 @@
`Move Objects Dialog`:index:
****************************
Use the *Move Objects* dialog to to move database objects from one tablespace to
Use the *Move Objects* dialog to move database objects from one tablespace to
another tablespace.
The *Move Objects* dialog organizes the movement of database objects with the
+61
View File
@@ -0,0 +1,61 @@
.. _oauth2:
*****************************************
`Enabling OAUTH2 Authentication`:index:
*****************************************
To enable OAUTH2 authentication for pgAdmin, you must configure the OAUTH2
settings in the *config_local.py* or *config_system.py* file (see the
:ref:`config.py <config_py>` documentation) on the system where pgAdmin is
installed in Server mode. You can copy these settings from *config.py* file
and modify the values for the following parameters:
.. csv-table::
:header: "**Parameter**", "**Description**"
:class: longtable
:widths: 35, 55
"AUTHENTICATION_SOURCES", "The default value for this parameter is *internal*.
To enable OAUTH2 authentication, you must include *oauth2* in the list of values
for this parameter. you can modify the value as follows:
* [‘oauth2’, ‘internal’]: pgAdmin will display an additional button for authenticating with oauth2"
"OAUTH2_NAME", "The name of the Oauth2 provider, ex: Google, Github"
"OAUTH2_DISPLAY_NAME", "Oauth2 display name in pgAdmin"
"OAUTH2_CLIENT_ID", "Oauth2 Client ID"
"OAUTH2_CLIENT_SECRET", "Oauth2 Client Secret"
"OAUTH2_TOKEN_URL", "Oauth2 Access Token endpoint"
"OAUTH2_AUTHORIZATION_URL", "Endpoint for user authorization"
"OAUTH2_API_BASE_URL", "Oauth2 base URL endpoint to make requests simple, ex: *https://api.github.com/*"
"OAUTH2_USERINFO_ENDPOINT", "User Endpoint, ex: *user* (for github) and *useinfo* (for google)"
"OAUTH2_ICON", "The Font-awesome icon to be placed on the oauth2 button, ex: fa-github"
"OAUTH2_BUTTON_COLOR", "Oauth2 button color"
"OAUTH2_AUTO_CREATE_USER", "Set the value to *True* if you want to automatically
create a pgAdmin user corresponding to a successfully authenticated Oauth2 user.
Please note that password is not stored in the pgAdmin database."
Redirect URL
============
The redirect url to configure Oauth2 server is *http://<pgAdmin Server URL>/oauth2/authorize*
Master Password
===============
In the multi user mode, pgAdmin uses user's login password to encrypt/decrypt the PostgreSQL server password.
In the Oauth2 authentication, the pgAdmin does not store the user's password, so we need an encryption key to store
the PostgreSQL server password.
To accomplish this, set the configuration parameter MASTER_PASSWORD to *True*, so upon setting the master password,
it will be used as an encryption key while storing the password. If it is False, the server password can not be stored.
Login Page
============
After configuration, on restart, you can see the login page with the Oauth2 login button(s).
.. image:: images/oauth2_login.png
:alt: Oauth2 login
:align: center
+1 -1
View File
@@ -45,7 +45,7 @@ Click the *Security* tab to continue.
:alt: Package dialog security tab
:align: center
Use the fields in the *Security* tab to to assign EXECUTE privileges for the
Use the fields in the *Security* tab to assign EXECUTE privileges for the
package to a role. Click the *Add* icon (+) to set privileges for the package:
* Select the name of the role from the drop-down listbox in the *Grantee* field.
+27 -11
View File
@@ -154,6 +154,9 @@ the graphs on the *Dashboard* tab:
:alt: Preferences dialog dashboard display options
:align: center
* Set the warning and alert threshold value to highlight the long-running
queries on the dashboard.
* When the *Show activity?* switch is set to *True*, activity tables will be
displayed on dashboards.
@@ -211,21 +214,23 @@ files.
:align: center
Use the fields on the *Binary paths* panel to specify the path to the directory
that contains the utility programs (pg_dump, pg_restore, and pg_dumpall) for
that contains the utility programs (pg_dump, pg_dumpall, pg_restore and psql) for
monitored databases:
* Use the *EDB Advanced Server Binary Path* field to specify the location of the
EDB Postgres Advanced Server utility programs. If this path is not set,
pgAdmin will attempt to find the utilities in standard locations used by
EnterpriseDB.
* Use the *EDB Advanced Server Binary Path* grid to specify the location of the
EDB Postgres Advanced Server utility programs based on the server version.
If the respective path is not set, then pgAdmin will pick up the path for which
'Set as default' is checked else pgAdmin will attempt to find the utilities in
standard locations used by EnterpriseDB.
* Use the *Greenplum Database Binary Path* field to specify the location of the
Greenplum database utility programs. If this path is not set, pgAdmin will
attempt to find the utilities in standard locations used by Greenplum.
* Use the *PostgreSQL Binary Path* grid to specify the location of the
PostgreSQL utility programs based on the server version. If the respective
path is not set, then pgAdmin will pick up the path for which 'Set as default'
is checked else pgAdmin will attempt to find the utilities in standard
locations used by PostgreSQL.
* Use the *PostgreSQL Binary Path* field to specify the location of the
PostgreSQL utility programs. If this path is not set, pgAdmin will attempt
to find the utilities in standard locations used by PostgreSQL.
**Note:** Use the 'Validate path' button to check the existence of the utility
programs (pg_dump, pg_dumpall, pg_restore and psql) and there respective versions.
.. image:: images/preferences_paths_help.png
:alt: Preferences dialog binary path help section
@@ -348,6 +353,10 @@ Use the fields on the *Options* panel to manage editor preferences.
* When the *Auto-Rollback?* switch is set to *True*, failed queries are rolled
back.
* When the *Copy SQL from main window to query tool?* switch is set to *True*,
the CREATE sql of the selected object will be copied to query tool when query tool
will open.
* When the *Prompt to save unsaved data changes?* switch is set to *True*, the
editor will prompt the user to saved unsaved data when exiting the data
editor.
@@ -372,6 +381,13 @@ Use the fields on the *Options* panel to manage editor preferences.
Use the fields on the *Results grid* panel to specify your formatting
preferences for copied data.
* When the *Columns sized by* is set to *Column data*, then data columns will
auto-size to the maximum width of the data in the column as loaded in the
first batch. If set to *Column name*, the column will be sized to the widest
of the data type or column name.
* Specify the maximum width of the column in pixels when 'Columns sized by' is
set to *Column data*. If 'Columns sized by' is set to *Column name* then this
setting won't have any effect.
* 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
+30
View File
@@ -0,0 +1,30 @@
.. _psql_tool:
******************
`PSQL Tool`:index:
******************
The PSQL tool allows users to connect to PostgreSQL or EDB Advanced server using
the psql command line interface through their browser.
* Open the PSQL tool from the Tools or browser tree context menu, or use PSQL
tool button at the top of the browser tree.
* PSQL will connect to the current connected database from the browser tree.
.. image:: images/psql_tool.png
:alt: PSQL tool window
:align: center
You can open multiple instances of the PSQL tool in individual tabs simultaneously.
To close the PSQL tool, click the *X* in the upper-right hand corner of the tab bar.
**Note:** On the Windows platform, this feature is available on Windows 10 (1809
version), and Windows Server 2019 and onwards.
**Note:** The PSQL tool is always available when pgAdmin is running in Desktop
mode, but is disabled by default in Server mode. This is because users can run
arbitrary shell commands through psql which may be considered a security risk in
some deployments. System Administrators can enable the use of the PSQL tool in
the pgAdmin configuration by setting the *ENABLE_PSQL* option to *True*; see
:ref:`config_py` for more information.
+4
View File
@@ -11,6 +11,10 @@ notes for it.
.. toctree::
:maxdepth: 1
release_notes_5_6
release_notes_5_5
release_notes_5_4
release_notes_5_3
release_notes_5_2
release_notes_5_1
release_notes_5_0
+1 -2
View File
@@ -23,7 +23,7 @@ Bug fixes
| `Issue #5908 <https://redmine.postgresql.org/issues/5908>`_ - Fixed an issue where shortcut keys are not working with manage macro.
| `Issue #6076 <https://redmine.postgresql.org/issues/6076>`_ - Fixed an issue where correct error not thrown while importing servers and JSON file has incorrect/insufficient keys.
| `Issue #6082 <https://redmine.postgresql.org/issues/6082>`_ - Ensure that the user should not be to change the connection when a long query is running.
| `Issue #6106 <https://redmine.postgresql.org/issues/6106>`_ - Fixed flickering issue of the input box on check constraints.
| `Issue #6107 <https://redmine.postgresql.org/issues/6107>`_ - Fixed flickering issue of the input box on check constraints.
| `Issue #6161 <https://redmine.postgresql.org/issues/6161>`_ - Fixed an issue where the cursor shifts its focus to the wrong window for all the query tool related model dialogs.
| `Issue #6220 <https://redmine.postgresql.org/issues/6220>`_ - Corrected the syntax for 'CREATE TRIGGER', use 'EXECUTE FUNCTION' instead of 'EXECUTE PROCEDURE' from v11 onwards.
| `Issue #6274 <https://redmine.postgresql.org/issues/6274>`_ - Ensure that the strings in the LDAP auth module are translatable.
@@ -40,4 +40,3 @@ Bug fixes
| `Issue #6375 <https://redmine.postgresql.org/issues/6375>`_ - Fixed an issue where users are unable to see data of the partitions using the View/Edit data option.
| `Issue #6376 <https://redmine.postgresql.org/issues/6376>`_ - Fixed an issue where a connection warning should be displayed on the user clicks on explain or explain analyze and the database server is disconnected from the browser tree.
| `Issue #6379 <https://redmine.postgresql.org/issues/6379>`_ - Fixed an issue where foreign data wrapper properties are not visible if the host option contains two host addresses.
| `Issue #6385 <https://redmine.postgresql.org/issues/6385>`_ - Ensure that Backup and Restore should work on shared servers.
+44
View File
@@ -0,0 +1,44 @@
************
Version 5.3
************
Release date: 2021-05-20
This release contains a number of bug fixes and new features since the release of pgAdmin4 5.2.
New features
************
| `Issue #5954 <https://redmine.postgresql.org/issues/5954>`_ - Added support to set auto width of columns by content size in the data output window.
| `Issue #6158 <https://redmine.postgresql.org/issues/6158>`_ - Added support to connect PostgreSQL servers via Kerberos authentication.
| `Issue #6397 <https://redmine.postgresql.org/issues/6397>`_ - Added "IF NOT EXISTS" clause while creating tables and partition tables which is convenient while using the ERD tool.
Housekeeping
************
Bug fixes
*********
| `Issue #4436 <https://redmine.postgresql.org/issues/4436>`_ - Fixed an issue where drag and drop object is not correct in codemirror for properties dialog.
| `Issue #5477 <https://redmine.postgresql.org/issues/5477>`_ - Added support for cache bust webpack chunk files.
| `Issue #5555 <https://redmine.postgresql.org/issues/5555>`_ - Fixed an issue where data is displayed in the wrong order when executing the query repeatedly.
| `Issue #5776 <https://redmine.postgresql.org/issues/5776>`_ - Ensure that while connecting to the server using SSPI login, it should not prompt for the password.
| `Issue #6329 <https://redmine.postgresql.org/issues/6329>`_ - Fixed an issue where the wrong SQL is showing for the child partition tables.
| `Issue #6341 <https://redmine.postgresql.org/issues/6341>`_ - Fixed an issue where CSV download quotes the numeric columns.
| `Issue #6355 <https://redmine.postgresql.org/issues/6355>`_ - Ensure that pgAdmin should not allow opening external files that are dragged into it.
| `Issue #6377 <https://redmine.postgresql.org/issues/6377>`_ - Fixed an issue where schema diff does not create DROP DEFAULT statement for columns.
| `Issue #6385 <https://redmine.postgresql.org/issues/6385>`_ - Ensure that Backup and Restore should work on shared servers.
| `Issue #6392 <https://redmine.postgresql.org/issues/6392>`_ - Fixed an issue where the filter 'Include/Exclude By Selection' not working for null values.
| `Issue #6399 <https://redmine.postgresql.org/issues/6399>`_ - Ensure that the user should not be able to add duplicate panels.
| `Issue #6407 <https://redmine.postgresql.org/issues/6407>`_ - Added support for the creation of Nested Table and Varying Array Type for Advanced Server.
| `Issue #6408 <https://redmine.postgresql.org/issues/6408>`_ - Fixed ModuleNotFoundError when running setup.py from outside of the root.
| `Issue #6409 <https://redmine.postgresql.org/issues/6409>`_ - Fixed an issue where the current debug line is not visible in the 'Dark' theme.
| `Issue #6413 <https://redmine.postgresql.org/issues/6413>`_ - Fixed an issue where duplicate columns are visible in the browser tree, which is owned by two sequences.
| `Issue #6414 <https://redmine.postgresql.org/issues/6414>`_ - Fixed an issue where the Help message not displaying correctly on Login/Group role.
| `Issue #6416 <https://redmine.postgresql.org/issues/6416>`_ - Added comment column in the properties panel for View and Materialized View collection node.
| `Issue #6417 <https://redmine.postgresql.org/issues/6417>`_ - Fixed an issue where query editor is not being closed if the user clicks on the 'Don't Save' button.
| `Issue #6420 <https://redmine.postgresql.org/issues/6420>`_ - Ensure that pgAdmin4 shut down completely on the Quit command.
| `Issue #6443 <https://redmine.postgresql.org/issues/6443>`_ - Fixed an issue where file dialog showing incorrect files for the selected file types.
| `Issue #6444 <https://redmine.postgresql.org/issues/6444>`_ - Fixed an issue where the user is not warned if Kerberos ticket expiration is less than 30 min while initiating a global backup.
| `Issue #6445 <https://redmine.postgresql.org/issues/6445>`_ - Ensure that proper identification should be there when the server is connected using Kerberos or without Kerberos.
+40
View File
@@ -0,0 +1,40 @@
************
Version 5.4
************
Release date: 2021-06-17
This release contains a number of bug fixes and new features since the release of pgAdmin4 5.3.
New features
************
| `Issue #1561 <https://redmine.postgresql.org/issues/1561>`_ - Added browse button to select the binary path in the Preferences.
| `Issue #1591 <https://redmine.postgresql.org/issues/1591>`_ - Added Grant Wizard option under Package node.
| `Issue #2341 <https://redmine.postgresql.org/issues/2341>`_ - Added support to launch PSQL for the connected database server.
| `Issue #4064 <https://redmine.postgresql.org/issues/4064>`_ - Added window maximize/restore functionality for properties dialog.
| `Issue #5370 <https://redmine.postgresql.org/issues/5370>`_ - Added support to set the binary path for the different database server versions.
| `Issue #6231 <https://redmine.postgresql.org/issues/6231>`_ - Added OS, Browser, Configuration details in the About dialog.
| `Issue #6395 <https://redmine.postgresql.org/issues/6395>`_ - Added support for rotating the pgAdmin log file on the basis of size and age.
| `Issue #6524 <https://redmine.postgresql.org/issues/6524>`_ - Support non-admin installation on Windows.
Housekeeping
************
| `Issue #4622 <https://redmine.postgresql.org/issues/4622>`_ - Added RESQL/MSQL test cases for Table and its child nodes.
| `Issue #6225 <https://redmine.postgresql.org/issues/6225>`_ - Updated Flask-Security-Too to the latest v4.
| `Issue #6460 <https://redmine.postgresql.org/issues/6460>`_ - Added a mechanism to detect a corrupt/broken config database file.
Bug fixes
*********
| `Issue #4203 <https://redmine.postgresql.org/issues/4203>`_ - Fixed the issue of renaming the database by another user.
| `Issue #6404 <https://redmine.postgresql.org/issues/6404>`_ - Ensure that the Query Tool connection string should not be changed as per the 'Query Tool tab title'.
| `Issue #6466 <https://redmine.postgresql.org/issues/6466>`_ - Ensure that the user should be able to add members in Login/Role group while creating it.
| `Issue #6469 <https://redmine.postgresql.org/issues/6469>`_ - Ensure that the calendar control should be disabled in the properties panel for Role.
| `Issue #6473 <https://redmine.postgresql.org/issues/6473>`_ - Disable browser password saving in the runtime.
| `Issue #6478 <https://redmine.postgresql.org/issues/6478>`_ - Fixed duplicate SQL issue for tables with more than one partition.
| `Issue #6482 <https://redmine.postgresql.org/issues/6482>`_ - Fixed an issue where the Foreground Color property of server dialog does not work.
| `Issue #6513 <https://redmine.postgresql.org/issues/6513>`_ - Fixed an issue where pgAdmin does not open after password reset in server mode.
| `Issue #6520 <https://redmine.postgresql.org/issues/6520>`_ - Fixed an issue where a decimal number is appended for character varying fields while downloading the data in CSV format.
+37
View File
@@ -0,0 +1,37 @@
************
Version 5.5
************
Release date: 2021-07-15
This release contains a number of bug fixes and new features since the release of pgAdmin4 5.4.
New features
************
| `Issue #1975 <https://redmine.postgresql.org/issues/1975>`_ - Highlighted long running queries on the dashboards.
| `Issue #3893 <https://redmine.postgresql.org/issues/3893>`_ - Added support for Reassign/Drop Owned for login roles.
| `Issue #3920 <https://redmine.postgresql.org/issues/3920>`_ - Do not block the query editor window when running a query.
| `Issue #5940 <https://redmine.postgresql.org/issues/5940>`_ - Added support for OAuth 2 authentication.
| `Issue #6559 <https://redmine.postgresql.org/issues/6559>`_ - Added option to provide maximum width of the column when 'Resize by data?’ option in the preferences is set to True.
Housekeeping
************
Bug fixes
*********
| `Issue #4189 <https://redmine.postgresql.org/issues/4189>`_ - Ensure that the Data Output panel can be snapped back after it is detached.
| `Issue #6388 <https://redmine.postgresql.org/issues/6388>`_ - Fixed replace keyboard shortcut issue in the query tool on the normal keyboard layout.
| `Issue #6398 <https://redmine.postgresql.org/issues/6398>`_ - Fixed an issue where detaching the query editor panel gives a blank white panel.
| `Issue #6427 <https://redmine.postgresql.org/issues/6427>`_ - Remove leading whitespace and replace it with '[...] ' in the Query Tool data grid so cells don't look empty.
| `Issue #6448 <https://redmine.postgresql.org/issues/6448>`_ - Fixed an issue in the search object when searching in 'all types' or 'subscription' if the user doesn't have access to the subscription.
| `Issue #6489 <https://redmine.postgresql.org/issues/6489>`_ - Fixed an issue where Execute/Refresh button should not be disabled when we run the empty query.
| `Issue #6505 <https://redmine.postgresql.org/issues/6505>`_ - Fixed an issue where the New Connection Drop Down has lost default maintenance database, auto-select, and tab-through functionality.
| `Issue #6536 <https://redmine.postgresql.org/issues/6536>`_ - Fixed directory selection issue with the folder dialog.
| `Issue #6541 <https://redmine.postgresql.org/issues/6541>`_ - Ensure that setting 'Open in new browser tab' should be visible, it should not be based on the value of 'ENABLE_PSQL'.
| `Issue #6547 <https://redmine.postgresql.org/issues/6547>`_ - Fixed copy/paste issues for PSQL tool terminal.
| `Issue #6550 <https://redmine.postgresql.org/issues/6550>`_ - Disable email deliverability check that was introduced in flask-security-too by default to maintain backwards compatibility.
| `Issue #6555 <https://redmine.postgresql.org/issues/6555>`_ - Fixed Czech translation string for 'Login' keyword.
| `Issue #6557 <https://redmine.postgresql.org/issues/6557>`_ - Fixed an issue where incorrect column name listed in the properties of Index.
+33
View File
@@ -0,0 +1,33 @@
************
Version 5.6
************
Release date: 2021-08-12
This release contains a number of bug fixes and new features since the release of pgAdmin4 5.5.
New features
************
| `Issue #4904 <https://redmine.postgresql.org/issues/4904>`_ - Added support to copy SQL from main window to query tool.
| `Issue #5198 <https://redmine.postgresql.org/issues/5198>`_ - Added support for formatted JSON viewer/editor when interacting with data in a JSON column.
Housekeeping
************
| `Issue #6622 <https://redmine.postgresql.org/issues/6622>`_ - Rename the "Resize by data?" to "Columns sized by" and disabled the 'Maximum column width' button if 'Columns sized by' is set to 'Column data'.
Bug fixes
*********
| `Issue #6337 <https://redmine.postgresql.org/issues/6337>`_ - Ensure that the login account should be locked after N number of attempts. N is configurable using the 'MAX_LOGIN_ATTEMPTS' parameter.
| `Issue #6369 <https://redmine.postgresql.org/issues/6369>`_ - Fixed CSRF errors for stale sessions by increasing the session expiration time for desktop mode.
| `Issue #6448 <https://redmine.postgresql.org/issues/6448>`_ - Fixed an issue in the search object when searching in 'all types' or 'subscription' if the user doesn't have access to the subscription.
| `Issue #6574 <https://redmine.postgresql.org/issues/6574>`_ - Fixed an issue where paste is not working through Right-Click option on PSQL.
| `Issue #6580 <https://redmine.postgresql.org/issues/6580>`_ - Fixed TypeError 'NoneType' object is not sub scriptable.
| `Issue #6586 <https://redmine.postgresql.org/issues/6586>`_ - Fixed incorrect tablespace options in the drop-down for move objects dialog.
| `Issue #6618 <https://redmine.postgresql.org/issues/6618>`_ - Fixed an issue where the titles in query tabs are different.
| `Issue #6619 <https://redmine.postgresql.org/issues/6619>`_ - Fixed incorrect binary path issue when the user deletes the binary path from the preferences.
| `Issue #6643 <https://redmine.postgresql.org/issues/6643>`_ - Ensure that all the required options should be loaded when the Range data type is selected while creating a custom data type.
| `Issue #6650 <https://redmine.postgresql.org/issues/6650>`_ - Fixed dashboard server activity issue when active_since parameter is None.
| `Issue #6664 <https://redmine.postgresql.org/issues/6664>`_ - Fixed an issue where even if the user is locked, he can reset the password and can login into pgAdmin.
+50
View File
@@ -0,0 +1,50 @@
.. _restore_locked_user:
*****************************
`Lock/Restore Account`:index:
*****************************
Account locking/unlocking via user management dialog:
An admin can lock and unlock user from the user management dialog. This allows the admin to lock or restore
the user when there are several failed login attempts. This page guides you through configuring per-user
locking/restoring. For more details visit :ref:`User management <user_management>`.
.. csv-table::
:header: "**Parameter**", "**Description**"
:class: longtable
:widths: 35, 55
"MAX_LOGIN_ATTEMPTS", "Which sets the number of failed login that
are allowed. If this value is exceeded, the account is locked and can be reset by an administrator.
By setting the variable to the value zero this feature is deactivated."
When Administrator itself gets locked, following steps may be considered to restore it:
- Increase MAX_LOGIN_ATTEMPTS, and try to successfully login to restore the account.
OR
By updating SQLite DB (pgAdmin4.db):
* Locate the pgAdmin4.db file and open it using any DB Browser (or DB Browser for SQLite)
* After opening the DB file, head towards 'Execute SQL' section.
* Run below query -
*UPDATE USER SET LOCKED = false, LOGIN_ATTEMPTS = 0 WHERE USERNAME = <YOUR_EMAIL_ID>*
* Make sure the query changes are committed.
Account locking by failed login attempts:
.. image:: images/login_attempt_user.png
:alt: Failed login attempt for current user
:align: center
pgAdmin application is configured to lock a user account when a number of consecutive failed login attempts are
exceeded.
MAX_LOGIN_ATTEMPTS is defaulted to 3 unsuccessful login attempts, after which the account would be locked.
The only way to restore the user account is by contacting the Administrator and ask to unlock it.
+51
View File
@@ -0,0 +1,51 @@
.. _role_reassign_dialog:
**************************************
`Role Reassign/Drop Own Dialog`:index:
**************************************
Use the *Reassign/Drop Own* dialog to change the ownership of database objects owned
by a database role. This dialog instructs the system to change the ownership of database
objects owned by any of the *old_roles* to *new_role*.
The *Reassign/Drop Own* dialog organizes the Reassign & Drop role through General tab.
.. image:: images/role_reassign_dialog.png
:alt: Reassign/Drop Own dialog
:align: center
* Use the *Operation* field to provide Reassign option.
* Provide a new role in the *Reassign Objects to* field; The ownership of all the objects within the selected database,
and of all shared objects (databases, tablespaces), owned by the *old_role* will be reassigned to *new_role*.
* Provide a database on which the reassignment is to be carried out.
The above example demonstrates reassigning *old_role* to *new_role*.
Click the *SQL* tab to continue.
.. image:: images/role_reassign_dialog_sql.png
:alt: Reassign/Drop Own dialog sql
:align: center
Removing database objects owned by a database role.
.. image:: images/role_drop_dialog.png
:alt: Reassign/Drop Own dialog
:align: center
* Use the *Operation* field to provide Drop option.
* Use the *Cascade?* field to provide Yes, No is default.
* Provide a database on which the drop of objects is to be carried out.
Click the *SQL* tab to continue.
.. image:: images/role_drop_dialog_sql.png
:alt: Reassign/Drop Own dialog sql
:align: center
The above examples demonstrates drop owned by *role*.
* Click the *Help* button (?) to access online help.
* Click the *OK* button to save work.
* Click the *Cancel* button to exit without saving work.
+8 -3
View File
@@ -31,15 +31,18 @@ Use the fields in the *General* tab to identify the server:
connection to the server upon completion of the dialog; this is the default
* If the *Shared?* switch is moved to *Yes* then that server can be
shared with all the other users. This option is available only to admin users. For more information on users see :ref:`User Management Dialog <user_management>`. The users can access the shared servers with some restritctions. The Users accessing the shared servers cannot do the following operations on the shared servers:
shared with all the other users. This option is available only to admin users.
For more information on users see :ref:`User Management Dialog <user_management>`.
Users can access the shared servers with some restrictions - the following
operations on shared servers are not permitted:
* Create a server
* Delete the server
* Rename the server
* Rename the group server
* Change of host, port, and maintenance database
Please note that once the server is shared, it's icon is changed in the browser tree.
Please note that once the server is shared, it's icon is changed in the
browser tree.
* Provide a comment about the server in the *Comments* field.
@@ -62,6 +65,8 @@ Use the fields in the *Connection* tab to configure a connection:
installed on that database.
* Use the *Username* field to specify the name of a role that will be used when
authenticating with the server.
* When *Kerberos authentication?* is set to *True*, pgAdmin will try to connect
the PostgreSQL server using Kerberos authentication.
* Use the *Password* field to provide a password that will be supplied when
authenticating with the server.
* Check the box next to *Save password?* to instruct pgAdmin to save the
+1 -1
View File
@@ -365,7 +365,7 @@ Click the *Columns* tab to continue.
:alt: Table dialog exclusion constraint columns
:align: center
Use the fields in the *Columns* tab to to specify the column(s) to which the
Use the fields in the *Columns* tab to specify the column(s) to which the
constraint applies. Use the drop-down listbox next to *Column* to select a
column and click the *Add* icon (+) to provide details of the action on the
column:
+3 -1
View File
@@ -20,4 +20,6 @@ the selected browser node.
* Use the :ref:`Filtered Rows <viewdata_filter>` button to access the Data Filter popup
to apply a filter to a set of data for viewing/editing.
* Use the :ref:`Search objects <search_objects>` button to access the search objects
dialog. It helps you search any database object.
dialog. It helps you search any database object.
* Use the :ref:`PSQL Tool <psql_tool>` button to open the PSQL in the current
database context.
+1 -1
View File
@@ -123,7 +123,7 @@ Click the *Security* tab to continue.
Use the *Security* tab to assign privileges and define security labels.
Use the *Privileges* panel to assign usage privileges for the trigger function
to a role. Click the *Add* icon (+) to to add a role to the table.
to a role. Click the *Add* icon (+) to add a role to the table.
* Select the name of the role from the drop-down listbox in the *Grantee* field.
* Click inside the *Privileges* field. Check the boxes to the left of one or
+2
View File
@@ -58,6 +58,8 @@ Provide information about the new pgAdmin role in the row:
as authentication source since LDAP password is not stored in the pgAdmin database.
* Re-enter the password in the *Confirm password* field. This field is disabled
if you select *ldap* as authentication source.
* Move the *Locked* switch to the *True* position if you want to lock the account;
the default is *False*. This functionality is useful when a user is locked by trying unsuccessful login attempts.
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.
+1 -2
View File
@@ -4,8 +4,7 @@
set -e
# Debugging shizz
trap 'last_command=$current_command; current_command=$BASH_COMMAND' DEBUG
trap 'if [ $? -ne 0 ]; then echo "\"${last_command}\" command filed with exit code $?."; fi' EXIT
trap 'ERRCODE=$? && if [ ${ERRCODE} -ne 0 ]; then echo "The command \"${BASH_COMMAND}\" failed in \"${FUNCNAME}\" with exit code ${ERRCODE}."; fi' EXIT
OS_VERSION=$(cat /etc/os-release | grep "^VERSION_ID=" | awk -F "=" '{ print $2 }' | sed 's/"//g')
OS_NAME=$(cat /etc/os-release | grep "^ID=" | awk -F "=" '{ print $2 }' | sed 's/"//g')
+3
View File
@@ -5,6 +5,9 @@ if [ "$EUID" -ne 0 ]
exit 1
fi
echo "Running apt update..."
apt update
echo "Installing system pre-requisites..."
apt install -y curl apt-transport-https ca-certificates gnupg
+6 -1
View File
@@ -10,7 +10,12 @@ CA_FILE = '/etc/ssl/certs/ca-certificates.crt'
LOG_FILE = '/dev/null'
HELP_PATH = '../../docs'
DEFAULT_BINARY_PATHS = {
'pg': '/usr/local/pgsql-13'
'pg': '/usr/local/pgsql-13',
'pg-13': '/usr/local/pgsql-13',
'pg-12': '/usr/local/pgsql-12',
'pg-11': '/usr/local/pgsql-11',
'pg-10': '/usr/local/pgsql-10',
'pg-9.6': '/usr/local/pgsql-9.6'
}
EOF
+1 -2
View File
@@ -6,8 +6,7 @@
set -e -E
# Debugging shizz
trap 'last_command=$current_command; current_command=$BASH_COMMAND' DEBUG
trap 'if [ $? -ne 0 ]; then echo "\"${last_command}\" command filed with exit code $?."; fi' EXIT
trap 'ERRCODE=$? && if [ ${ERRCODE} -ne 0 ]; then echo "The command \"${BASH_COMMAND}\" failed in \"${FUNCNAME}\" with exit code ${ERRCODE}."; fi' EXIT
SCRIPT_DIR=$(cd `dirname $0` && pwd)
SOURCE_DIR=$(realpath ${SCRIPT_DIR}/../..)
+1 -2
View File
@@ -4,8 +4,7 @@
set -e
# Debugging shizz
trap 'last_command=$current_command; current_command=$BASH_COMMAND' DEBUG
trap 'if [ $? -ne 0 ]; then echo "\"${last_command}\" command filed with exit code $?."; fi' EXIT
trap 'ERRCODE=$? && if [ ${ERRCODE} -ne 0 ]; then echo "The command \"${BASH_COMMAND}\" failed in \"${FUNCNAME}\" with exit code ${ERRCODE}."; fi' EXIT
OS_VERSION=$(cat /etc/os-release | grep "^VERSION_ID=" | awk -F "=" '{ print $2 }' | sed 's/"//g')
OS_NAME=$(cat /etc/os-release | grep "^ID=" | awk -F "=" '{ print $2 }' | sed 's/"//g')
+2 -1
View File
@@ -1,7 +1,7 @@
#!/bin/bash
# Set the repo RPM version and build
REPO_RPM_VERSION=1
REPO_RPM_VERSION=2
REPO_RPM_BUILD=1
# Set the repo base directory
@@ -55,6 +55,7 @@ enabled=1
EOF
if [ ${INCLUDE_KEY} -eq 1 ]; then
echo repo_gpgcheck=1 >> "${BUILDROOT}/${DISTRO}-repo/etc/yum.repos.d/pgadmin4.repo"
echo gpgcheck=1 >> "${BUILDROOT}/${DISTRO}-repo/etc/yum.repos.d/pgadmin4.repo"
echo gpgkey=file:///etc/pki/rpm-gpg/PGADMIN_PKG_KEY >> "${BUILDROOT}/${DISTRO}-repo/etc/yum.repos.d/pgadmin4.repo"
else
+29 -17
View File
@@ -6,21 +6,27 @@ builds may still work with suitable adjustments.
## Installing build requirements
1. Install Visual Studio 2017 Pro from https://my.visualstudio.com/Downloads?q=Visual%20Studio%202017
Choose the Desktop development with C++ option.
1. Install Visual Studio 2017 Pro from https://my.visualstudio.com/Downloads?q=Visual%20Studio%202017.
Choose the Desktop development with C++ option, and ensure that you add the
'Visual C++ MFC for x86 and x64' option.
2. Install Chocolatey from https://chocolatey.org/install#individual
3. Install various command line tools:
choco install -y bzip2 cmake diffutils dotnet3.5 gzip git innosetup nodejs-lts python strawberryperl wget yarn
choco install -y awk bzip2 cmake diffutils dotnet3.5 gnuwin32-coreutils.install gzip git html-help-workshop innosetup nodejs-lts python sed strawberryperl wget yarn
4. Upgrade pip (this may give a permissions error that can be ignored):
4. Ensure the GNU CoreUtils and Microsoft HTML Help Workshop are in the system path - add:
pip install --upgrade pip
* C:\Program Files (x86)\GnuWin32\bin
* C:\Program Files (x86)\HTML Help Workshop
5. Install virtualenv:
5. Upgrade pip:
python -m pip install --upgrade pip
6. Install virtualenv:
pip install virtualenv
@@ -39,19 +45,22 @@ prompt.
tar -zxvf zlib-1.2.11.tar.gz
cd zlib-1.2.11
cmake -DCMAKE_INSTALL_PREFIX=C:/build64/zlib -G "Visual Studio 15 2017 Win64" .
msbuild ALL_BUILD.vcxproj /p:Configuration=Release
msbuild RUN_TESTS.vcxproj /p:Configuration=Release
msbuild INSTALL.vcxproj /p:Configuration=Release
copy C:\build64\zlib\lib\zlib.lib C:\build64\zlib\lib\zdll.lib
cd ..
3. Download the OpenSSL source code, unpack and build it:
wget https://www.openssl.org/source/openssl-1.1.1g.tar.gz
tar -zxvf openssl-1.1.1g.tar.gz
cd openssl-1.1.1g
wget https://www.openssl.org/source/openssl-1.1.1k.tar.gz
tar -zxvf openssl-1.1.1k.tar.gz
cd openssl-1.1.1k
perl Configure VC-WIN64A no-asm --prefix=C:\build64\openssl no-ssl2 no-ssl3 no-comp
nmake
nmake test
nmake install
cd ..
Note that if you are not working in an administrative account, you may need to
create and give your regular account appropriate permissions to write/modify
@@ -63,8 +72,10 @@ users could potentially write to.
In a *32bit* Visual Studio 2017 command prompt:
wget https://kerberos.org/dist/krb5/1.19/krb5-1.19.1.tar.gz
tar -zxvf krb5-1.19.1.tar.gz
mkdir C:\build64\krb5
cd krb5-1.18.3\src
cd krb5-1.19.1\src
set KRB_INSTALL_DIR=C:\build64\krb5
nmake -f Makefile.in prep-windows
@@ -75,17 +86,18 @@ users could potentially write to.
In a *64bit* Visual Studio 2017 command prompt:
cd krb5-1.18.3\src
cd krb5-1.19.1\src
set PATH=%PATH%;"%WindowsSdkVerBinPath%"\x86
set KRB_INSTALL_DIR=C:\build64\krb5
nmake NODEBUG=1
nmake install NODEBUG=1
cd ..\..
5. Download the PostgreSQL source code, unpack and build it:
wget https://ftp.postgresql.org/pub/source/v12.3/postgresql-13.1.tar.bz2
tar -zxvf postgresql-13.1.tar.gz
cd postgresql-13.1\src\tools\msvc
wget https://ftp.postgresql.org/pub/source/v13.3/postgresql-13.3.tar.gz
tar -zxvf postgresql-13.3.tar.gz
cd postgresql-13.3\src\tools\msvc
>> config.pl echo # Configuration arguments for vcbuild.
>> config.pl echo use strict;
@@ -154,9 +166,9 @@ Studio 2017 64bit command prompt. Note that the examples shown below are the
defaults for the build system, so if they match your requirements you don't
need to set them:
SET "PGADMIN_POSTGRES_DIR=C:\Program Files\PostgreSQL\13"
SET "PGADMIN_POSTGRES_DIR=C:\build64\pgsql"
SET "PGADMIN_PYTHON_DIR=C:\Python39"
SET "PGADMIN_KRB5_DIR=C:\jenkins\build64\krb5"
SET "PGADMIN_KRB5_DIR=C:\build64\krb5"
SET "PGADMIN_INNOTOOL_DIR=C:\Program Files (x86)\Inno Setup 6"
SET "PGADMIN_SIGNTOOL_DIR=C:\Program Files (x86)\Windows Kits\10\bin\10.0.17763.0\x64"
SET "PGADMIN_VCREDIST_DIR=C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Redist\MSVC\14.16.27012"
+8 -7
View File
@@ -19,7 +19,7 @@ AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={commonpf}\{#MyAppName}\{#MyAppVersion}
DefaultDirName={autopf}\{#MyAppName}\{#MyAppVersion}
DefaultGroupName={#MyAppName}
DisableWelcomePage=no
DisableProgramGroupPage=auto
@@ -28,9 +28,10 @@ OutputBaseFilename=pgadmin4-setup
SetupIconFile=Resources\pgAdmin4.ico
Compression=lzma
SolidCompression=yes
PrivilegesRequired=admin
PrivilegesRequired=lowest
PrivilegesRequiredOverridesAllowed=dialog
ChangesEnvironment=yes
;UninstallFilesDir={app}\{#MyAppVersion}
UninstallDisplayIcon={app}\runtime\{#MyAppExeName}
ArchitecturesInstallIn64BitMode={#MyAppArchitecturesMode}
AllowNoIcons=yes
WizardImageFile=sidebar.bmp
@@ -57,10 +58,10 @@ Source: "..\..\win-build\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdi
Filename: "{app}\installer\{#MyAppVCDist}"; StatusMsg: "VC runtime redistributable package"; Parameters: "/passive /verysilent /norestart"; Check: InstallVC;
[Registry]
Root: HKLM; Subkey: "Software\{#MyAppName}\{#MyAppVersion}"; Flags: uninsdeletekeyifempty
Root: HKLM; Subkey: "Software\{#MyAppName}\{#MyAppVersion}"; Flags: uninsdeletekey
Root: HKLM; Subkey: "Software\{#MyAppName}\{#MyAppVersion}"; ValueType: string; ValueName: "InstallPath"; ValueData: "{app}"
Root: HKLM; Subkey: "Software\{#MyAppName}\{#MyAppVersion}"; ValueType: string; ValueName: "Version"; ValueData: "{#MyAppFullVersion}"
Root: HKA; Subkey: "Software\{#MyAppName}\{#MyAppVersion}"; Flags: uninsdeletekeyifempty
Root: HKA; Subkey: "Software\{#MyAppName}\{#MyAppVersion}"; Flags: uninsdeletekey
Root: HKA; Subkey: "Software\{#MyAppName}\{#MyAppVersion}"; ValueType: string; ValueName: "InstallPath"; ValueData: "{app}"
Root: HKA; Subkey: "Software\{#MyAppName}\{#MyAppVersion}"; ValueType: string; ValueName: "Version"; ValueData: "{#MyAppFullVersion}"
[Code]
var
+9 -2
View File
@@ -8,7 +8,6 @@
#
###############################################################################
cheroot==8.*
Flask==1.*
Flask-Gravatar==0.*
Flask-Login==0.*
@@ -29,10 +28,18 @@ psutil==5.*
psycopg2==2.8.*
python-dateutil==2.*
SQLAlchemy==1.3.*
Flask-Security-Too==3.*
itsdangerous<=1.1.0
Flask-Security-Too==4.*
bcrypt==3.*
cryptography==3.*
sshtunnel==0.*
ldap3==2.*
Flask-BabelEx==0.*
gssapi==1.6.*
flask-socketio>=5.0.1
eventlet==0.31.0
httpagentparser==1.9.*
user-agents==2.2.0
pywinpty==1.1.1; sys_platform=="win32"
Authlib==0.15.*
requests==2.25.*
+1
View File
@@ -6,6 +6,7 @@
"author": "pgAdmin Development Team (https://www.pgadmin.org/)",
"license": "PostgreSQL",
"chromium-args": "--disable-popup-blocking",
"user-agent": "Nwjs:%nwver-%osinfo-%chromium_ver",
"window": {
"width": 440,
"height": 170,
+11
View File
@@ -28,6 +28,17 @@
margin-bottom: 10px;
}
</style>
<!-- Disable/block all password saving in nw.js -->
<script type="text/javascript">
chrome.passwordsPrivate.getSavedPasswordList(function(passwords) {
passwords.forEach((p, i) => {
chrome.passwordsPrivate.removeSavedPassword(i);
});
});
chrome.privacy.services.passwordSavingEnabled.set({ value: false });
</script>
<script type="text/javascript">
let platform = require("os").platform;
</script>
-3
View File
@@ -218,9 +218,6 @@ const cleanupAndQuitApp = () => {
}
if (pgAdminWindowObject != null) {
// Close the window.
pgAdminWindowObject.close(true);
// Remove all the cookies.
pgAdminWindowObject.cookies.getAll({}, function(cookies) {
try {
+117 -9
View File
@@ -43,7 +43,7 @@ APP_ICON = 'pg-icon'
# Application version number components
APP_RELEASE = 5
APP_REVISION = 2
APP_REVISION = 6
# Application version suffix, e.g. 'beta1', 'dev'. Usually an empty string
# for GA releases.
@@ -52,7 +52,7 @@ APP_SUFFIX = ''
# Numeric application version for upgrade checks. Should be in the format:
# [X]XYYZZ, where X is the release version, Y is the revision, with a leading
# zero if needed, and Z represents the suffix, with a leading zero if needed
APP_VERSION_INT = 50200
APP_VERSION_INT = 50600
# DO NOT CHANGE!
# The application version string, constructed from the components
@@ -156,8 +156,8 @@ X_FRAME_OPTIONS = "SAMEORIGIN"
# such as JavaScript, CSS, or pretty much anything that the browser loads.
# see https://content-security-policy.com/#source_list for more info
# e.g. "default-src https: data: 'unsafe-inline' 'unsafe-eval';"
CONTENT_SECURITY_POLICY = "default-src http: data: blob: 'unsafe-inline' " \
"'unsafe-eval';"
CONTENT_SECURITY_POLICY = "default-src ws: http: data: blob: 'unsafe-inline'" \
" 'unsafe-eval';"
# STRICT_TRANSPORT_SECURITY_ENABLED when set to True will set the
# Strict-Transport-Security header
@@ -286,6 +286,13 @@ if SERVER_MODE and not IS_WIN:
else:
LOG_FILE = os.path.join(DATA_DIR, 'pgadmin4.log')
# Log rotation setting
# Log file will be rotated considering values for LOG_ROTATION_SIZE
# & LOG_ROTATION_AGE. Rotated file will be named in format
# - LOG_FILE.Y-m-d_H-M-S
LOG_ROTATION_SIZE = 10 # In MBs
LOG_ROTATION_AGE = 1440 # In minutes
LOG_ROTATION_MAX_LOG_FILES = 90 # Maximum number of backups to retain
##########################################################################
# Server Connection Driver Settings
##########################################################################
@@ -374,6 +381,17 @@ SECURITY_EMAIL_SUBJECT_PASSWORD_NOTICE = "Your %s password has been reset" \
SECURITY_EMAIL_SUBJECT_PASSWORD_CHANGE_NOTICE = \
"Your password for %s has been changed" % APP_NAME
##########################################################################
# Email address validation
##########################################################################
# flask-security-too will validate email addresses and check deliverability
# by default. Disable the deliverability check by default, which was the old
# behaviour in <= v5.3
CHECK_EMAIL_DELIVERABILITY = False
SECURITY_EMAIL_VALIDATOR_ARGS = \
{"check_deliverability": CHECK_EMAIL_DELIVERABILITY}
##########################################################################
# Upgrade checks
##########################################################################
@@ -416,6 +434,10 @@ STORAGE_DIR = os.path.join(DATA_DIR, 'storage')
#
# A default location can be specified for each database driver ID, in
# a dictionary. Either an absolute or relative path can be specified.
#
# Version-specific defaults can also be specified, which will take priority
# over un-versioned paths.
#
# In cases where it may be difficult to know what the working directory
# is, "$DIR" can be specified. This will be replaced with the path to the
# top-level pgAdmin4.py file. For example, on macOS we might use:
@@ -425,8 +447,17 @@ STORAGE_DIR = os.path.join(DATA_DIR, 'storage')
##########################################################################
DEFAULT_BINARY_PATHS = {
"pg": "",
"pg-9.6": "",
"pg-10": "",
"pg-11": "",
"pg-12": "",
"pg-13": "",
"ppas": "",
"gpdb": ""
"ppas-9.6": "",
"ppas-10": "",
"ppas-11": "",
"ppas-12": "",
"ppas-13": ""
}
##########################################################################
@@ -482,6 +513,10 @@ SESSION_SKIP_PATHS = [
# expire after the specified number of *days*.
SESSION_EXPIRATION_TIME = 1
# Make SESSION_EXPIRATION_TIME to 1 week in DESKTOP mode
if not SERVER_MODE:
SESSION_EXPIRATION_TIME = 7
# CHECK_SESSION_FILES_INTERVAL is interval in Hours. Application will check
# the session files for cleanup after specified number of *hours*.
CHECK_SESSION_FILES_INTERVAL = 24
@@ -531,13 +566,26 @@ ENHANCED_COOKIE_PROTECTION = True
##########################################################################
# Default setting is internal
# External Supported Sources: ldap, kerberos
# External Supported Sources: ldap, kerberos, oauth2
# Multiple authentication can be achieved by setting this parameter to
# ['ldap', 'internal']. pgAdmin will authenticate the user with ldap first,
# in case of failure internal authentication will be done.
# ['ldap', 'internal'] or ['oauth2', 'internal'] etc.
# pgAdmin will authenticate the user with ldap/oauth2 whatever first in the
# list, in case of failure the second authentication option will be considered.
AUTHENTICATION_SOURCES = ['internal']
##########################################################################
# MAX_LOGIN_ATTEMPTS which sets the number of failed login attempts that
# are allowed. If this value is exceeded the account is locked and can be
# reset by an administrator. By setting the variable to the value zero
# this feature is deactivated.
##########################################################################
MAX_LOGIN_ATTEMPTS = 3
##########################################################################
# Only consider password to check the failed login attempts, email is
# excluded from this check
LOGIN_ATTEMPT_FIELDS = ['password']
##########################################################################
# LDAP Configuration
##########################################################################
@@ -614,7 +662,6 @@ LDAP_CA_CERT_FILE = ''
LDAP_CERT_FILE = ''
LDAP_KEY_FILE = ''
##########################################################################
# Kerberos Configuration
##########################################################################
@@ -634,6 +681,65 @@ KRB_KTNAME = '<KRB5_KEYTAB_FILE>'
KRB_AUTO_CREATE_USER = True
KERBEROS_CCACHE_DIR = os.path.join(DATA_DIR, 'krbccache')
##########################################################################
# OAuth2 Configuration
##########################################################################
# Multiple OAUTH2 providers can be added in the list like [{...},{...}]
# All parameters are required
OAUTH2_CONFIG = [
{
# The name of the of the oauth provider, ex: github, google
'OAUTH2_NAME': None,
# The display name, ex: Google
'OAUTH2_DISPLAY_NAME': '<Oauth2 Display Name>',
# Oauth client id
'OAUTH2_CLIENT_ID': None,
# Oauth secret
'OAUTH2_CLIENT_SECRET': None,
# URL to generate a token,
# Ex: https://github.com/login/oauth/access_token
'OAUTH2_TOKEN_URL': None,
# URL is used for authentication,
# Ex: https://github.com/login/oauth/authorize
'OAUTH2_AUTHORIZATION_URL': None,
# Oauth base url, ex: https://api.github.com/
'OAUTH2_API_BASE_URL': None,
# Name of the Endpoint, ex: user
'OAUTH2_USERINFO_ENDPOINT': None,
# Font-awesome icon, ex: fa-github
'OAUTH2_ICON': None,
# UI button colour, ex: #0000ff
'OAUTH2_BUTTON_COLOR': None,
}
]
# After Oauth authentication, user will be added into the SQLite database
# automatically, if set to True.
# Set it to False, if user should not be added automatically,
# in this case Admin has to add the user manually in the SQLite database.
OAUTH2_AUTO_CREATE_USER = True
##########################################################################
# PSQL tool settings
##########################################################################
# This will enable PSQL tool in pgAdmin when running in server mode.
# PSQL is always enabled in Desktop mode, however in server mode it is
# disabled by default because users can run arbitrary commands on the
# server through it.
ENABLE_PSQL = False
##########################################################################
# ENABLE_BINARY_PATH_BROWSING setting is used to enable the browse button
# while selecting binary path for the database server in server mode.
# In Desktop mode it is always enabled and setting is of no use.
##########################################################################
ENABLE_BINARY_PATH_BROWSING = False
##########################################################################
# Local config settings
##########################################################################
@@ -673,3 +779,5 @@ if 'PGADMIN_CONFIG_DEFAULT_SERVER' in os.environ:
# Disable USER_INACTIVITY_TIMEOUT when SERVER_MODE=False
if not SERVER_MODE:
USER_INACTIVITY_TIMEOUT = 0
# Enable PSQL in Desktop Mode.
ENABLE_PSQL = True
+33
View File
@@ -0,0 +1,33 @@
"""empty message
Revision ID: 6650c52670c2
Revises: c465fee44968
Create Date: 2021-07-10 18:12:38.821602
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
from pgadmin import db
revision = '6650c52670c2'
down_revision = 'c465fee44968'
branch_labels = None
depends_on = None
def upgrade():
db.engine.execute(
'ALTER TABLE user ADD COLUMN locked BOOLEAN DEFAULT FALSE'
)
db.engine.execute(
'ALTER TABLE user ADD COLUMN login_attempts int DEFAULT 0'
)
def downgrade():
# pgAdmin only upgrades, downgrade not implemented.
pass
+64
View File
@@ -0,0 +1,64 @@
"""empty message
Revision ID: c465fee44968
Revises: d0bc9f32b2b9
Create Date: 2021-06-04 14:42:12.843116
"""
from pgadmin.model import db, User
from sqlalchemy.sql import text
import uuid
# revision identifiers, used by Alembic.
revision = 'c465fee44968'
down_revision = 'd0bc9f32b2b9'
branch_labels = None
depends_on = None
def upgrade():
db.engine.execute("ALTER TABLE user RENAME TO user_old")
db.engine.execute("""
CREATE TABLE user (
id INTEGER NOT NULL,
username VARCHAR(256) NOT NULL,
email VARCHAR(256),
password VARCHAR(256),
active BOOLEAN NOT NULL,
confirmed_at DATETIME,
masterpass_check VARCHAR(256),
auth_source VARCHAR(256) NOT NULL DEFAULT 'internal',
fs_uniquifier NOT NULL UNIQUE,
PRIMARY KEY (id),
UNIQUE (username, auth_source),
CHECK (active IN (0, 1))
);
""")
user_old = db.engine.execute(
'select id, username, email, password, active, '
'confirmed_at, masterpass_check, auth_source '
'from user_old')
statement = text("""
INSERT INTO user(id, username, email, password, active,
confirmed_at, masterpass_check, auth_source, fs_uniquifier)
VALUES(:id, :username, :email, :password, :active, :confirmed_at,
:masterpass_check, :auth_source, :fs_uniquifier)""")
db.engine.execute(statement, [
{
**row,
'fs_uniquifier': uuid.uuid4().hex
} for row in user_old
])
db.engine.execute("DROP TABLE user_old")
def downgrade():
# pgAdmin only upgrades, downgrade not implemented.
pass
+28
View File
@@ -0,0 +1,28 @@
"""empty message
Revision ID: c6974f64df08
Revises: a39bd015b644
Create Date: 2021-04-22 10:06:21.282770
"""
from pgadmin.model import db
# revision identifiers, used by Alembic.
revision = 'c6974f64df08'
down_revision = 'a39bd015b644'
branch_labels = None
depends_on = None
def upgrade():
db.engine.execute(
'ALTER TABLE sharedserver ADD COLUMN osid INTEGER'
)
def downgrade():
# pgAdmin only upgrades, downgrade not implemented.
pass
+28
View File
@@ -0,0 +1,28 @@
"""empty message
Revision ID: d0bc9f32b2b9
Revises: c6974f64df08
Create Date: 2021-04-27 12:40:08.899712
"""
from alembic import op
import sqlalchemy as sa
from pgadmin.model import db
# revision identifiers, used by Alembic.
revision = 'd0bc9f32b2b9'
down_revision = 'c6974f64df08'
branch_labels = None
depends_on = None
def upgrade():
db.engine.execute(
'ALTER TABLE server ADD COLUMN kerberos_conn INTEGER DEFAULT 0'
)
def downgrade():
# pgAdmin only upgrades, downgrade not implemented.
pass
+14 -10
View File
@@ -24,7 +24,7 @@
"copy-webpack-plugin": "^7.0.0",
"core-js": "^3.2.1",
"cross-env": "^7.0.3",
"css-minimizer-webpack-plugin": "^1.2.0",
"css-minimizer-webpack-plugin": "^3.0.0",
"enzyme": "^3.11.0",
"eslint": "^7.19.0",
"eslint-plugin-react": "^7.20.5",
@@ -37,7 +37,7 @@
"is-docker": "^2.1.1",
"jasmine-core": "^3.6.0",
"jasmine-enzyme": "^7.1.2",
"karma": "^6.1.0",
"karma": "^6.3.2",
"karma-babel-preprocessor": "^8.0.0",
"karma-browserify": "^8.0.0",
"karma-chrome-launcher": "^3.1.0",
@@ -53,7 +53,6 @@
"process": "^0.11.10",
"prop-types": "^15.7.2",
"resize-observer-polyfill": "^1.5.1",
"resolve-url-loader": "^3.1.2",
"sass": "^1.24.4",
"sass-loader": "^11.0.0",
"sass-resources-loader": "^2.2.1",
@@ -89,7 +88,7 @@
"closest": "^0.0.1",
"codemirror": "^5.59.2",
"css-loader": "^5.0.1",
"cssnano": "^4.1.10",
"cssnano": "^5.0.2",
"dagre": "^0.8.4",
"dropzone": "^5.7.4",
"html2canvas": "^1.0.0-rc.7",
@@ -97,10 +96,11 @@
"imports-loader": "^2.0.0",
"ip-address": "^7.1.0",
"istanbul-instrumenter-loader": "^3.0.1",
"jquery": "^3.5.1",
"jquery": "^3.6.0",
"jquery-contextmenu": "^2.9.2",
"jquery-ui": "^1.12.1",
"json-bignumber": "^1.0.1",
"jsoneditor": "^9.5.1",
"karma-coverage": "^2.0.3",
"leaflet": "^1.5.1",
"lodash": "4.*",
@@ -110,22 +110,26 @@
"mousetrap": "^1.6.3",
"pathfinding": "^0.4.18",
"paths-js": "^0.4.9",
"postcss": "^8.2.4",
"postcss": "^8.2.15",
"raf": "^3.4.1",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"requirejs": "~2.3.6",
"select2": "^4.0.13",
"shim-loader": "^1.0.1",
"slickgrid": "git+https://github.com/6pac/SlickGrid.git#2.3.16",
"snapsvg-cjs": "^0.0.6",
"socket.io-client": "^4.0.0",
"split.js": "^1.5.10",
"tablesorter": "^2.31.2",
"tempusdominus-bootstrap-4": "^5.1.2",
"tempusdominus-core": "^5.0.3",
"underscore": "^1.9.1",
"webcabin-docker": "git+https://github.com/EnterpriseDB/wcDocker/#c4a3398b89588408dc705895675bce7bd7660d36",
"wkx": "^0.5.0"
"underscore": "^1.13.1",
"webcabin-docker": "git+https://github.com/EnterpriseDB/wcDocker/#06daee1a8111b4ed08d58670674a2967e4f68313",
"wkx": "^0.5.0",
"xterm": "^4.11.0",
"xterm-addon-fit": "^0.5.0",
"xterm-addon-search": "^0.8.0",
"xterm-addon-web-links": "^0.4.0"
},
"scripts": {
"linter": "yarn eslint --no-eslintrc -c .eslintrc.js --ext .js --ext .jsx .",
+12 -11
View File
@@ -13,7 +13,7 @@ to start a web server."""
import sys
from cheroot.wsgi import Server as CherootServer
if sys.version_info < (3, 4):
raise RuntimeError('This application must be run under Python 3.4 '
@@ -37,7 +37,7 @@ else:
builtins.SERVER_MODE = None
import config
from pgadmin import create_app
from pgadmin import create_app, socketio
from pgadmin.utils import u_encode, fs_encoding, file_quote
from pgadmin.utils.constants import INTERNAL
# Get the config database schema version. We store this in pgadmin.model
@@ -97,6 +97,8 @@ if not os.path.isfile(config.SQLITE_PATH):
##########################################################################
app = create_app()
app.debug = False
app.config['sessions'] = dict()
if config.SERVER_MODE:
app.wsgi_app = ReverseProxied(app.wsgi_app)
@@ -206,17 +208,16 @@ def main():
else:
# Can use cheroot instead of flask dev server when not in debug
# 10 is default thread count in CherootServer
num_threads = 10 if config.THREADED_MODE else 1
prod_server = CherootServer(
(config.DEFAULT_SERVER, config.EFFECTIVE_SERVER_PORT),
wsgi_app=app,
numthreads=num_threads,
server_name=config.APP_NAME)
# num_threads = 10 if config.THREADED_MODE else 1
try:
print("Using production server...")
prod_server.start()
socketio.run(
app,
host=config.DEFAULT_SERVER,
port=config.EFFECTIVE_SERVER_PORT,
)
except KeyboardInterrupt:
prod_server.stop()
print("CLOSE SERVER")
socketio.stop()
except IOError:
app.logger.error("Error starting the app server: %s", sys.exc_info())
+89 -19
View File
@@ -14,11 +14,14 @@ import os
import sys
import re
import ipaddress
import traceback
from types import MethodType
from collections import defaultdict
from importlib import import_module
from flask import Flask, abort, request, current_app, session, url_for
from flask_socketio import SocketIO
from werkzeug.exceptions import HTTPException
from flask_babelex import Babel, gettext
from flask_babelex import gettext as _
@@ -37,25 +40,31 @@ from pgadmin.utils import PgAdminModule, driver, KeyManager
from pgadmin.utils.preferences import Preferences
from pgadmin.utils.session import create_session_interface, pga_unauthorised
from pgadmin.utils.versioned_template_loader import VersionedTemplateLoader
from datetime import timedelta
from pgadmin.setup import get_version, set_version
from datetime import timedelta, datetime
from pgadmin.setup import get_version, set_version, check_db_tables
from pgadmin.utils.ajax import internal_server_error, make_json_response
from pgadmin.utils.csrf import pgCSRFProtect
from pgadmin import authenticate
from pgadmin.utils.security_headers import SecurityHeaders
from pgadmin.utils.constants import KERBEROS
from pgadmin.utils.constants import KERBEROS, OAUTH2, INTERNAL, LDAP
# Explicitly set the mime-types so that a corrupted windows registry will not
# affect pgAdmin 4 to be load properly. This will avoid the issues that may
# occur due to security fix of X_CONTENT_TYPE_OPTIONS = "nosniff".
import mimetypes
mimetypes.add_type('application/javascript', '.js')
mimetypes.add_type('text/css', '.css')
winreg = None
if os.name == 'nt':
import winreg
socketio = SocketIO(manage_session=False, async_mode='threading',
logger=False, engineio_logger=False, debug=False,
ping_interval=25, ping_timeout=120)
class PgAdmin(Flask):
def __init__(self, *args, **kwargs):
@@ -256,7 +265,13 @@ def create_app(app_name=None):
create_app_data_directory(config)
# File logging
fh = logging.FileHandler(config.LOG_FILE, encoding='utf-8')
from pgadmin.utils.enhanced_log_rotation import \
EnhancedRotatingFileHandler
fh = EnhancedRotatingFileHandler(config.LOG_FILE,
config.LOG_ROTATION_SIZE,
config.LOG_ROTATION_AGE,
config.LOG_ROTATION_MAX_LOG_FILES)
fh.setLevel(config.FILE_LOG_LEVEL)
fh.setFormatter(logging.Formatter(config.FILE_LOG_FORMAT))
app.logger.addHandler(fh)
@@ -293,7 +308,7 @@ def create_app(app_name=None):
if current_user.is_authenticated:
user_id = current_user.id
else:
user = user_datastore.get_user(config.DESKTOP_USER)
user = user_datastore.find_user(email=config.DESKTOP_USER)
if user is not None:
user_id = user.id
user_language = Preferences.raw_value(
@@ -337,6 +352,44 @@ def create_app(app_name=None):
##########################################################################
# Upgrade the schema (if required)
##########################################################################
def backup_db_file():
"""
Create a backup of the current database file
and create new database file with default settings.
"""
backup_file_name = "{0}.{1}".format(
SQLITE_PATH, datetime.now().strftime('%Y%m%d%H%M%S'))
os.rename(SQLITE_PATH, backup_file_name)
app.logger.error('Exception in database migration.')
app.logger.info('Creating new database file.')
try:
db_upgrade(app)
os.environ[
'CORRUPTED_DB_BACKUP_FILE'] = backup_file_name
app.logger.info('Database migration completed.')
except Exception as e:
app.logger.error('Database migration failed')
app.logger.error(traceback.format_exc())
raise RuntimeError('Migration failed')
def upgrade_db():
"""
Execute the migrations.
"""
try:
db_upgrade(app)
os.environ['CORRUPTED_DB_BACKUP_FILE'] = ''
except Exception as e:
backup_db_file()
# check all tables are present in the db.
is_db_error, invalid_tb_names = check_db_tables()
if is_db_error:
app.logger.error(
'Table(s) {0} are missing in the'
' database'.format(invalid_tb_names))
backup_db_file()
with app.app_context():
# Run migration for the first time i.e. create database
from config import SQLITE_PATH
@@ -348,21 +401,29 @@ def create_app(app_name=None):
# If running in cli mode then don't try to upgrade, just raise
# the exception
if not cli_mode:
db_upgrade(app)
upgrade_db()
else:
if not os.path.exists(SQLITE_PATH):
raise FileNotFoundError(
'SQLite database file "' + SQLITE_PATH +
'" does not exists.')
raise RuntimeError('Specified SQLite database file '
'is not valid.')
raise RuntimeError(
'The configuration database file is not valid.')
else:
schema_version = get_version()
# Run migration if current schema version is greater than the
# schema version stored in version table
if CURRENT_SCHEMA_VERSION >= schema_version:
db_upgrade(app)
upgrade_db()
else:
# check all tables are present in the db.
is_db_error, invalid_tb_names = check_db_tables()
if is_db_error:
app.logger.error(
'Table(s) {0} are missing in the'
' database'.format(invalid_tb_names))
backup_db_file()
# Update schema version to the latest
if CURRENT_SCHEMA_VERSION > schema_version:
@@ -404,6 +465,15 @@ def create_app(app_name=None):
# CSRF Token expiration till session expires
'WTF_CSRF_TIME_LIMIT': getattr(config, 'CSRF_TIME_LIMIT', None),
'WTF_CSRF_METHODS': ['GET', 'POST', 'PUT', 'DELETE'],
# Disable deliverable check for email addresss
'SECURITY_EMAIL_VALIDATOR_ARGS': config.SECURITY_EMAIL_VALIDATOR_ARGS
}))
app.config.update(dict({
'INTERNAL': INTERNAL,
'LDAP': LDAP,
'KERBEROS': KERBEROS,
'OAUTH2': OAUTH2
}))
security.init_app(app, user_datastore)
@@ -610,15 +680,15 @@ def create_app(app_name=None):
from pgadmin.utils.driver import get_driver
from flask import current_app
# remove key
current_app.keyManager.reset()
for mdl in current_app.logout_hooks:
try:
mdl.on_logout(user)
except Exception as e:
current_app.logger.exception(e)
# remove key
current_app.keyManager.reset()
_driver = get_driver(PG_DEFAULT_DRIVER)
_driver.gc_own()
@@ -685,7 +755,7 @@ def create_app(app_name=None):
abort(401)
if not config.SERVER_MODE and not current_user.is_authenticated:
user = user_datastore.get_user(config.DESKTOP_USER)
user = user_datastore.find_user(email=config.DESKTOP_USER)
# Throw an error if we failed to find the desktop user, to give
# the sysadmin a hint. We'll continue to try to login anyway as
# that'll through a nice 500 error for us.
@@ -697,19 +767,18 @@ def create_app(app_name=None):
)
abort(401)
login_user(user)
elif config.SERVER_MODE and\
app.PGADMIN_EXTERNAL_AUTH_SOURCE ==\
KERBEROS and \
elif config.SERVER_MODE and \
not current_user.is_authenticated and \
request.endpoint in ('redirects.index', 'security.login'):
return authenticate.login()
if app.PGADMIN_EXTERNAL_AUTH_SOURCE == KERBEROS:
return authenticate.login()
# if the server is restarted the in memory key will be lost
# but the user session may still be active. Logout the user
# to get the key again when login
if config.SERVER_MODE and current_user.is_authenticated and \
app.PGADMIN_EXTERNAL_AUTH_SOURCE != \
KERBEROS and \
KERBEROS and app.PGADMIN_EXTERNAL_AUTH_SOURCE != \
OAUTH2 and\
current_app.keyManager.get() is None and \
request.endpoint not in ('security.login', 'security.logout'):
logout_user()
@@ -811,4 +880,5 @@ def create_app(app_name=None):
##########################################################################
# All done!
##########################################################################
socketio.init_app(app)
return app
+67 -5
View File
@@ -10,13 +10,17 @@
"""A blueprint module implementing the about box."""
import sys
from flask import Response, render_template, __version__, url_for
from flask import Response, render_template, __version__, url_for, request
from flask_babelex import gettext
from flask_security import current_user, login_required
from pgadmin.utils import PgAdminModule
from pgadmin.utils.menu import MenuItem
from pgadmin.utils.constants import MIMETYPE_APP_JS
import config
import httpagentparser
from pgadmin.model import User
from user_agents import parse
import platform
MODULE_NAME = 'about'
@@ -59,23 +63,81 @@ blueprint = AboutModule(MODULE_NAME, __name__, static_url_path='')
@login_required
def index():
"""Render the about box."""
info = {
'python_version': sys.version,
'flask_version': __version__
}
info = {}
# Get OS , NW.js, Browser details
browser, os_details, nwjs_version = detect_browser(request)
if nwjs_version:
info['nwjs'] = nwjs_version
info['browser_details'] = browser
info['os_details'] = os_details
info['config_db'] = config.SQLITE_PATH
info['log_file'] = config.LOG_FILE
if config.SERVER_MODE:
info['app_mode'] = gettext('Server')
admin = is_admin(current_user.email)
info['admin'] = admin
else:
info['app_mode'] = gettext('Desktop')
info['current_user'] = current_user.email
settings = ""
for setting in dir(config):
if not setting.startswith('_') and setting.isupper() and \
setting not in ['CSRF_SESSION_KEY',
'SECRET_KEY',
'SECURITY_PASSWORD_SALT',
'SECURITY_PASSWORD_HASH',
'ALLOWED_HOSTS',
'MAIL_PASSWORD',
'LDAP_BIND_PASSWORD',
'SECURITY_PASSWORD_HASH']:
if isinstance(getattr(config, setting), str):
settings = \
settings + '{} = "{}"\n'.format(
setting, gettext(getattr(config, setting)))
else:
settings = \
settings + '{} = {}\n'.format(
setting, gettext(getattr(config, setting)))
info['settings'] = settings
return render_template(
MODULE_NAME + '/index.html', info=info, _=gettext
)
def is_admin(load_user):
user = User.query.filter_by(email=load_user).first()
return user.has_role("Administrator")
def detect_browser(request):
"""This function returns the browser and os details"""
nwjs_version = None
agent = request.environ.get('HTTP_USER_AGENT')
os_details = parse(platform.platform()).ua_string
if 'Nwjs' in agent:
agent = agent.split('-')
nwjs_version = agent[0].split(':')[1]
browser = 'Chromium' + ' ' + agent[2]
else:
browser = httpagentparser.detect(agent)
if not browser:
browser = agent.split('/')[0]
else:
browser = browser['browser']['name'] + ' ' + browser['browser'][
'version']
return browser, os_details, nwjs_version
@blueprint.route("/about.js")
@login_required
def script():
+27 -7
View File
@@ -9,9 +9,9 @@
define(
['jquery', 'alertify', 'sources/pgadmin', 'sources/gettext',
'sources/url_for','sources/utils',
'sources/url_for','sources/utils','pgadmin.user_management.current_user',
],
function($, alertify, pgAdmin, gettext, url_for, commonUtils) {
function($, alertify, pgAdmin, gettext, url_for, commonUtils, current_user) {
pgAdmin = pgAdmin || window.pgAdmin || {};
/* Return back, this has been called more than once */
@@ -45,14 +45,28 @@ define(
},
hooks:{
onshow:function(){
var self = this;
var container = $(this.elements.footer).find('button:not([disabled])');
commonUtils.findAndSetFocus(container);
$('#copy_textarea').on('click', function(){
//Copy the server configuration details
let textarea = document.getElementById('about-textarea');
textarea.select();
document.execCommand('copy');
$('#copy_textarea').text('Copied');
});
$(this.elements.resizeHandle).on('click', function(){
// Set the height of the Textarea
var height = self.elements.dialog.scrollHeight - 300;
if (height < 0)
height = self.elements.dialog.scrollHeight - 150;
$('#about-textarea').css({'height':height});
});
},
},
prepare:function() {
this.setContent(this.message);
},
};
});
@@ -60,9 +74,15 @@ define(
$.get(url_for('about.index'),
function(data) {
alertify.aboutDialog(
gettext('About %s', pgAdmin.Browser.utils.app_name), data
).resizeTo(pgAdmin.Browser.stdW.md, pgAdmin.Browser.stdH.md);
if(!current_user.is_admin && pgAdmin.server_mode){
alertify.aboutDialog(
gettext('About %s', pgAdmin.Browser.utils.app_name), data
).resizeTo(pgAdmin.Browser.stdW.md, 300);
}else{
alertify.aboutDialog(
gettext('About %s', pgAdmin.Browser.utils.app_name), data
).resizeTo(750, 470);
}
});
},
};
+32 -17
View File
@@ -3,18 +3,6 @@
<div class="col-sm-3"><strong>{{ _('Version') }}</strong></div>
<div class="col-sm-9">{{ config.APP_VERSION }}</div>
</div>
<div class="row">
<div class="col-sm-3"><strong>{{ _('Copyright') }}</strong></div>
<div class="col-sm-9">{{ config.APP_COPYRIGHT }}</div>
</div>
<div class="row">
<div class="col-sm-3"><strong>{{ _('Python Version') }}</strong></div>
<div class="col-sm-9">{{ info.python_version }}</div>
</div>
<div class="row">
<div class="col-sm-3"><strong>{{ _('Flask Version') }}</strong></div>
<div class="col-sm-9">{{ info.flask_version }}</div>
</div>
<div class="row">
<div class="col-sm-3"><strong>{{ _('Application Mode') }}</strong></div>
<div class="col-sm-9">{{ info.app_mode }}</div>
@@ -23,10 +11,37 @@
<div class="col-sm-3"><strong>{{ _('Current User') }}</strong></div>
<div class="col-sm-9">{{ info.current_user }}</div>
</div>
<div class="row">
<div class="col-12 text-right"><img
src="{{ url_for('static', filename='img/logo-right-128.png') }}"
alt="{{ config.APP_NAME }} {{ _('logo') }}"
></div>
{% if info.nwjs %}
<div class="row">
<div class="col-sm-3"><strong>{{ _('NW.js Version') }}</strong></div>
<div class="col-sm-9">{{ info.nwjs }}</div>
</div>
{% endif %}
<div class="row">
<div class="col-sm-3"><strong>{{ _('Browser') }}</strong></div>
<div class="col-sm-9">{{ info.browser_details }}</div>
</div>
<div class="row">
<div class="col-sm-3"><strong>{{ _('Operating System') }}</strong></div>
<div class="col-sm-9">{{ info.os_details }}</div>
</div>
<div class="row">
<div class="col-sm-3"><strong>{{ _('pgAdmin Database File') }}</strong></div>
<div class="col-sm-9">{{ info.config_db }}</div>
</div>
<div class="row">
<div class="col-sm-3"><strong>{{ _('Log File') }}</strong></div>
<div class="col-sm-9">{{ info.log_file }}</div>
</div>
{%if (info.app_mode == 'Desktop') or (info.app_mode == 'Server' and info.admin)%}
<div class="row">
<div class="col-sm-3"><b>{{ _('Server Configuration') }}</b></div>
</div>
<div class="row">
<div class="col-sm-9">
<textarea id="about-textarea" rows="7" cols="150" style="position: relative;width:105%; white-space: pre-wrap;" readonly>{{ info.settings|safe }}</textarea>
<button class="btn btn-secondary about-copy" id="copy_textarea" style="position:absolute;top:0;right:0;z-index:20;">Copy</button>
</div>
</div>
{% endif %}
</div>
+99 -66
View File
@@ -9,57 +9,33 @@
"""A blueprint module implementing the Authentication."""
import flask
import pickle
from flask import current_app, flash, Response, request, url_for,\
render_template
from flask_security import current_user
from flask_security.views import _security, _ctx
from flask_security.utils import config_value, get_post_logout_redirect, \
import config
import copy
from flask import current_app, flash, Response, request, url_for, \
session, redirect
from flask_babelex import gettext
from flask_security.views import _security
from flask_security.utils import get_post_logout_redirect, \
get_post_login_redirect, logout_user
from flask import session
import config
from pgadmin import db, User
from pgadmin.utils import PgAdminModule
from pgadmin.utils.constants import KERBEROS
from pgadmin.utils.csrf import pgCSRFProtect
from .registry import AuthSourceRegistry
from pgadmin.utils.constants import KERBEROS, INTERNAL, OAUTH2, LDAP
from pgadmin.authenticate.registry import AuthSourceRegistry
MODULE_NAME = 'authenticate'
auth_obj = None
class AuthenticateModule(PgAdminModule):
def get_exposed_url_endpoints(self):
return ['authenticate.login',
'authenticate.kerberos_login',
'authenticate.kerberos_logout']
return ['authenticate.login']
blueprint = AuthenticateModule(MODULE_NAME, __name__, static_url_path='')
@blueprint.route("/login/kerberos",
endpoint="kerberos_login", methods=["GET"])
@pgCSRFProtect.exempt
def kerberos_login():
logout_user()
return Response(render_template("browser/kerberos_login.html",
login_url=url_for('security.login'),
))
@blueprint.route("/logout/kerberos",
endpoint="kerberos_logout", methods=["GET"])
@pgCSRFProtect.exempt
def kerberos_logout():
logout_user()
return Response(render_template("browser/kerberos_logout.html",
login_url=url_for('security.login'),
))
@blueprint.route('/login', endpoint='login', methods=['GET', 'POST'])
def login():
"""
@@ -67,15 +43,53 @@ def login():
The user input will be validated and authenticated.
"""
form = _security.login_form()
auth_obj = AuthSourceManager(form, config.AUTHENTICATION_SOURCES)
session['_auth_source_manager_obj'] = None
auth_obj = AuthSourceManager(form, copy.deepcopy(
config.AUTHENTICATION_SOURCES))
if OAUTH2 in config.AUTHENTICATION_SOURCES \
and 'oauth2_button' in request.form:
session['auth_obj'] = auth_obj
session['auth_source_manager'] = None
username = form.data['email']
user = User.query.filter_by(username=username,
auth_source=INTERNAL).first()
if user:
if user.login_attempts >= config.MAX_LOGIN_ATTEMPTS > 0:
user.locked = True
else:
user.locked = False
db.session.commit()
if user.login_attempts >= config.MAX_LOGIN_ATTEMPTS > 0:
flash(gettext('Your account is locked. Please contact the '
'Administrator.'),
'warning')
logout_user()
return redirect(get_post_logout_redirect())
# Validate the user
if not auth_obj.validate():
for field in form.errors:
flash_login_attempt_error = None
if user and field in config.LOGIN_ATTEMPT_FIELDS:
if config.MAX_LOGIN_ATTEMPTS > 0:
user.login_attempts += 1
left_attempts = \
config.MAX_LOGIN_ATTEMPTS - user.login_attempts
flash_login_attempt_error = \
gettext('You are left with {0} more attempts.'.
format(left_attempts))
db.session.commit()
for error in form.errors[field]:
flash(error, 'warning')
return flask.redirect(get_post_logout_redirect())
if flash_login_attempt_error:
flash(flash_login_attempt_error, 'warning')
return redirect(get_post_logout_redirect())
# Authenticate the user
status, msg = auth_obj.authenticate()
@@ -83,34 +97,48 @@ def login():
# Login the user
status, msg = auth_obj.login()
current_auth_obj = auth_obj.as_dict()
if not status:
if current_auth_obj['current_source'] ==\
if current_auth_obj['current_source'] == \
KERBEROS:
return flask.redirect('{0}?next={1}'.format(url_for(
return redirect('{0}?next={1}'.format(url_for(
'authenticate.kerberos_login'), url_for('browser.index')))
flash(msg, 'danger')
return flask.redirect(get_post_logout_redirect())
return redirect(get_post_logout_redirect())
session['_auth_source_manager_obj'] = current_auth_obj
return flask.redirect(get_post_login_redirect())
session['auth_source_manager'] = current_auth_obj
if user:
user.login_attempts = 0
db.session.commit()
if 'auth_obj' in session:
session.pop('auth_obj')
return redirect(get_post_login_redirect())
elif isinstance(msg, Response):
return msg
elif 'oauth2_button' in request.form and not isinstance(msg, str):
return msg
if 'auth_obj' in session:
session.pop('auth_obj')
flash(msg, 'danger')
response = flask.redirect(get_post_logout_redirect())
response = redirect(get_post_logout_redirect())
return response
class AuthSourceManager():
class AuthSourceManager:
"""This class will manage all the authentication sources.
"""
def __init__(self, form, sources):
self.form = form
self.auth_sources = sources
self.source = None
self.source_friendly_name = None
self.current_source = None
self.source_friendly_name = INTERNAL
self.current_source = INTERNAL
self.update_auth_sources()
def as_dict(self):
"""
@@ -124,6 +152,17 @@ class AuthSourceManager():
return res
def update_auth_sources(self):
for auth_src in [KERBEROS, OAUTH2]:
if auth_src in self.auth_sources:
if 'internal_button' in request.form:
self.auth_sources.remove(auth_src)
else:
if INTERNAL in self.auth_sources:
self.auth_sources.remove(INTERNAL)
if LDAP in self.auth_sources:
self.auth_sources.remove(LDAP)
def set_current_source(self, source):
self.current_source = source
@@ -159,32 +198,19 @@ class AuthSourceManager():
msg = None
for src in self.auth_sources:
source = get_auth_sources(src)
self.set_source(source)
current_app.logger.debug(
"Authentication initiated via source: %s" %
source.get_source_name())
if self.form.data['email'] and self.form.data['password'] and \
source.get_source_name() == KERBEROS:
continue
status, msg = source.authenticate(self.form)
# When server sends Unauthorized header to get the ticket over HTTP
# OR When kerberos authentication failed while accessing pgadmin,
# we need to break the loop as no need to authenticate further
# even if the authentication sources set to multiple
if not status and (hasattr(msg, 'status') and
msg.status == '401 UNAUTHORIZED') or \
(source.get_source_name() == KERBEROS and
request.method == 'GET'):
break
if status:
self.set_source(source)
self.set_current_source(source.get_source_name())
if msg is not None and 'username' in msg:
self.form._fields['email'].data = msg['username']
return status, msg
return status, msg
def login(self):
@@ -194,6 +220,13 @@ class AuthSourceManager():
current_app.logger.debug(
"Authentication and Login successfully done via source : %s" %
self.source.get_source_name())
# Set the login, logout view as per source if available
current_app.login_manager.login_view = getattr(
self.source, 'LOGIN_VIEW', 'security.login')
current_app.login_manager.logout_view = getattr(
self.source, 'LOGOUT_VIEW', 'security.logout')
return status, msg
@@ -208,7 +241,7 @@ def get_auth_sources(type):
if type in auth_sources:
return auth_sources[type]
auth_source = AuthSourceRegistry.create(type)
auth_source = AuthSourceRegistry.get(type)
if auth_source is not None:
auth_sources[type] = auth_source
@@ -221,6 +254,6 @@ def init_app(app):
auth_sources = dict()
setattr(app, '_pgadmin_auth_sources', auth_sources)
AuthSourceRegistry.load_auth_sources()
AuthSourceRegistry.load_modules(app)
return auth_sources
+4 -2
View File
@@ -10,7 +10,7 @@
"""Implements Internal Authentication"""
import six
from flask import current_app
from flask import current_app, flash
from flask_security import login_user
from abc import abstractmethod, abstractproperty
from flask_babelex import gettext
@@ -31,6 +31,8 @@ class BaseAuthentication(object):
'PASSWORD_NOT_PROVIDED': gettext('Password not provided'),
'INVALID_EMAIL': gettext('Email/Username is not valid')
}
LOGIN_VIEW = 'security.login'
LOGOUT_VIEW = 'security.logout'
@abstractmethod
def get_source_name(self):
@@ -97,7 +99,7 @@ class InternalAuthentication(BaseAuthentication):
"""User validation"""
# validate the email id first
if not validate_email(form.data['email']):
form.errors['email'] = [self.messages('INVALID_EMAIL')]
flash(self.messages('INVALID_EMAIL'), 'warning')
return False
# Flask security validation
return form.validate_on_submit()
+137 -11
View File
@@ -10,22 +10,28 @@
"""A blueprint module implementing the Spnego/Kerberos authentication."""
import base64
from os import environ
from os import environ, path, remove
from werkzeug.datastructures import Headers
from werkzeug.datastructures import Headers, MultiDict
from flask_babelex import gettext
from flask import Flask, request, Response, session,\
current_app, render_template, flash
from flask import request, Response, session,\
current_app, render_template, flash, url_for
from flask_security.views import _security
from flask_security.utils import logout_user
from flask_security import login_required
import config
from pgadmin.model import User
from pgadmin.tools.user_management import create_user
from pgadmin.utils.constants import KERBEROS
from pgadmin.utils import PgAdminModule
from pgadmin.utils.ajax import make_json_response, internal_server_error
from flask_security.views import _security
from werkzeug.datastructures import MultiDict
from .internal import BaseAuthentication
from pgadmin.authenticate.internal import BaseAuthentication
from pgadmin.authenticate import get_auth_sources
from pgadmin.utils.csrf import pgCSRFProtect
try:
import gssapi
@@ -46,8 +52,110 @@ if config.KRB_KTNAME and config.KRB_KTNAME != '<KRB5_KEYTAB_FILE>':
environ['KRB5_KTNAME'] = config.KRB_KTNAME
class KerberosModule(PgAdminModule):
def register(self, app, options, first_registration=False):
# Do not look for the sub_modules,
# instead call blueprint.register(...) directly
super(PgAdminModule, self).register(app, options, first_registration)
def get_exposed_url_endpoints(self):
return ['kerberos.login',
'kerberos.logout',
'kerberos.update_ticket',
'kerberos.validate_ticket']
def init_app(app):
MODULE_NAME = 'kerberos'
blueprint = KerberosModule(MODULE_NAME, __name__, static_url_path='')
@blueprint.route("/login",
endpoint="login", methods=["GET"])
@pgCSRFProtect.exempt
def kerberos_login():
logout_user()
return Response(render_template("browser/kerberos_login.html",
login_url=url_for('security.login'),
))
@blueprint.route("/logout",
endpoint="logout", methods=["GET"])
@pgCSRFProtect.exempt
def kerberos_logout():
logout_user()
if 'KRB5CCNAME' in session:
# Remove the credential cache
cache_file_path = session['KRB5CCNAME'].split(":")[1]
if path.exists(cache_file_path):
remove(cache_file_path)
return Response(render_template("browser/kerberos_logout.html",
login_url=url_for('security.login'),
))
@blueprint.route("/update_ticket",
endpoint="update_ticket", methods=["GET"])
@pgCSRFProtect.exempt
@login_required
def kerberos_update_ticket():
"""
Update the kerberos ticket.
"""
from werkzeug.datastructures import Headers
headers = Headers()
authorization = request.headers.get("Authorization", None)
if authorization is None:
# Send the Negotiate header to the client
# if Kerberos ticket is not found.
headers.add('WWW-Authenticate', 'Negotiate')
return Response("Unauthorised", 401, headers)
else:
source = get_auth_sources(KERBEROS)
auth_header = authorization.split()
in_token = auth_header[1]
# Validate the Kerberos ticket
status, context = source.negotiate_start(in_token)
if status:
return Response("Ticket updated successfully.")
return Response(context, 500)
@blueprint.route("/validate_ticket",
endpoint="validate_ticket", methods=["GET"])
@pgCSRFProtect.exempt
@login_required
def kerberos_validate_ticket():
"""
Return the kerberos ticket lifetime left after getting the
ticket from the credential cache
"""
import gssapi
try:
del_creds = gssapi.Credentials(store={
'ccache': session['KRB5CCNAME']})
creds = del_creds.acquire(store={'ccache': session['KRB5CCNAME']})
except Exception as e:
current_app.logger.exception(e)
return internal_server_error(errormsg=str(e))
return make_json_response(
data={'ticket_lifetime': creds.lifetime},
status=200
)
app.register_blueprint(blueprint)
class KerberosAuthentication(BaseAuthentication):
LOGIN_VIEW = 'kerberos.login'
LOGOUT_VIEW = 'kerberos.logout'
def get_source_name(self):
return KERBEROS
@@ -85,7 +193,7 @@ class KerberosAuthentication(BaseAuthentication):
if status:
# Saving the first 15 characters of the kerberos key
# to encrypt/decrypt database password
session['kerberos_key'] = auth_header[1][0:15]
session['pass_enc_key'] = auth_header[1][0:15]
# Create user
retval = self.__auto_create_user(
str(negotiate.initiator_name))
@@ -128,23 +236,41 @@ class KerberosAuthentication(BaseAuthentication):
if out_token and not context.complete:
return False, out_token
if context.complete:
deleg_creds = context.delegated_creds
if not hasattr(deleg_creds, 'name'):
error_msg = gettext('Delegated credentials not supplied.')
current_app.logger.error(error_msg)
return False, Exception(error_msg)
try:
cache_file_path = path.join(
config.KERBEROS_CCACHE_DIR, 'pgadmin_cache_{0}'.format(
deleg_creds.name)
)
CCACHE = 'FILE:{0}'.format(cache_file_path)
store = {'ccache': CCACHE}
deleg_creds.store(store, overwrite=True, set_default=True)
session['KRB5CCNAME'] = CCACHE
except Exception as e:
current_app.logger.exception(e)
return False, e
return True, context
else:
return False, None
def negotiate_end(self, context):
# Free gss_cred_id_t
# Free Delegated Credentials
del_creds = getattr(context, 'delegated_creds', None)
if del_creds:
deleg_creds = context.delegated_creds
del(deleg_creds)
def __auto_create_user(self, username):
"""Add the ldap user to the internal SQLite database."""
"""Add the kerberos user to the internal SQLite database."""
username = str(username)
if config.KRB_AUTO_CREATE_USER:
user = User.query.filter_by(
username=username).first()
username=username, auth_source=KERBEROS).first()
if user is None:
return create_user({
'username': username,
+176
View File
@@ -0,0 +1,176 @@
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2021, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
"""A blueprint module implementing the Oauth2 authentication."""
import config
from authlib.integrations.flask_client import OAuth
from flask import current_app, url_for, session, request,\
redirect, Flask, flash
from flask_babelex import gettext
from flask_security import login_user, current_user
from flask_security.utils import get_post_logout_redirect, \
get_post_login_redirect, logout_user
from pgadmin.authenticate.internal import BaseAuthentication
from pgadmin.model import User
from pgadmin.tools.user_management import create_user
from pgadmin.utils.constants import OAUTH2
from pgadmin.utils import PgAdminModule
from pgadmin.utils.csrf import pgCSRFProtect
from pgadmin.model import db
OAUTH2_LOGOUT = 'oauth2.logout'
OAUTH2_AUTHORIZE = 'oauth2.authorize'
class Oauth2Module(PgAdminModule):
def register(self, app, options, first_registration=False):
# Do not look for the sub_modules,
# instead call blueprint.register(...) directly
super(PgAdminModule, self).register(app, options, first_registration)
def get_exposed_url_endpoints(self):
return [OAUTH2_AUTHORIZE,
OAUTH2_LOGOUT]
def init_app(app):
MODULE_NAME = 'oauth2'
blueprint = Oauth2Module(MODULE_NAME, __name__, static_url_path='')
@blueprint.route('/authorize', endpoint="authorize",
methods=['GET', 'POST'])
@pgCSRFProtect.exempt
def oauth_authorize():
auth_obj = session['auth_obj']
auth_obj.set_current_source(auth_obj.source.get_source_name())
status, msg = auth_obj.login()
if status:
session['auth_source_manager'] = auth_obj.as_dict()
if 'auth_obj' in session:
session.pop('auth_obj')
return redirect(get_post_login_redirect())
if 'auth_obj' in session:
session.pop('auth_obj')
logout_user()
flash(msg, 'danger')
return redirect(get_post_login_redirect())
@blueprint.route('/logout', endpoint="logout",
methods=['GET', 'POST'])
@pgCSRFProtect.exempt
def oauth_logout():
if not current_user.is_authenticated:
return redirect(get_post_logout_redirect())
for key in list(session.keys()):
session.pop(key)
logout_user()
return redirect(get_post_logout_redirect())
app.register_blueprint(blueprint)
app.login_manager.logout_view = OAUTH2_LOGOUT
class OAuth2Authentication(BaseAuthentication):
"""OAuth Authentication Class"""
LOGOUT_VIEW = OAUTH2_LOGOUT
oauth_obj = OAuth(Flask(__name__))
oauth2_clients = {}
oauth2_config = {}
def __init__(self):
for oauth2_config in config.OAUTH2_CONFIG:
OAuth2Authentication.oauth2_config[
oauth2_config['OAUTH2_NAME']] = oauth2_config
OAuth2Authentication.oauth2_clients[
oauth2_config['OAUTH2_NAME']
] = OAuth2Authentication.oauth_obj.register(
name=oauth2_config['OAUTH2_NAME'],
client_id=oauth2_config['OAUTH2_CLIENT_ID'],
client_secret=oauth2_config['OAUTH2_CLIENT_SECRET'],
access_token_url=oauth2_config['OAUTH2_TOKEN_URL'],
authorize_url=oauth2_config['OAUTH2_AUTHORIZATION_URL'],
api_base_url=oauth2_config['OAUTH2_API_BASE_URL'],
client_kwargs={'scope': 'email profile'}
)
def get_source_name(self):
return OAUTH2
def get_friendly_name(self):
return self.oauth2_config[self.oauth2_current_client]['OAUTH2_NAME']
def validate(self, form):
return True
def login(self, form):
profile = self.get_user_profile()
if 'email' not in profile or not profile['email']:
current_app.logger.exception(
"An email id is required to login into pgAdmin. "
"Please update your Oauth2 profile."
)
return False, gettext(
"An email id is required to login into pgAdmin. "
"Please update your Oauth2 profile.")
user, msg = self.__auto_create_user(profile)
if user:
user = db.session.query(User).filter_by(
username=profile['email'], auth_source=OAUTH2).first()
current_app.login_manager.logout_view = \
OAuth2Authentication.LOGOUT_VIEW
return login_user(user), None
return False, msg
def get_user_profile(self):
session['oauth2_token'] = self.oauth2_clients[
self.oauth2_current_client].authorize_access_token()
session['pass_enc_key'] = session['oauth2_token']['access_token']
resp = self.oauth2_clients[self.oauth2_current_client].get(
self.oauth2_config[
self.oauth2_current_client]['OAUTH2_USERINFO_ENDPOINT'],
token=session['oauth2_token']
)
resp.raise_for_status()
return resp.json()
def authenticate(self, form):
self.oauth2_current_client = request.form['oauth2_button']
redirect_url = url_for(OAUTH2_AUTHORIZE, _external=True)
if self.oauth2_current_client not in self.oauth2_clients:
return False, gettext(
"Please set the configuration parameters properly.")
return False, self.oauth2_clients[
self.oauth2_current_client].authorize_redirect(redirect_url)
def __auto_create_user(self, resp):
if config.OAUTH2_AUTO_CREATE_USER:
user = User.query.filter_by(username=resp['email'],
auth_source=OAUTH2).first()
if not user:
return create_user({
'username': resp['email'],
'email': resp['email'],
'role': 2,
'active': True,
'auth_source': OAUTH2
})
return True, {'username': resp['email']}
+4 -51
View File
@@ -10,56 +10,9 @@
"""External Authentication Registry."""
from flask_babelex import gettext
from abc import ABCMeta
from pgadmin.utils.dynamic_registry import create_registry_metaclass
def _decorate_cls_name(module_name):
length = len(__package__) + 1
if len(module_name) > length and module_name.startswith(__package__):
return module_name[length:]
return module_name
class AuthSourceRegistry(ABCMeta):
registry = None
auth_sources = dict()
def __init__(self, name, bases, d):
# Register this type of auth_sources, based on the module name
# Avoid registering the BaseAuthentication itself
AuthSourceRegistry.registry[_decorate_cls_name(d['__module__'])] = self
ABCMeta.__init__(self, name, bases, d)
@classmethod
def create(cls, name, **kwargs):
if name in AuthSourceRegistry.auth_sources:
return AuthSourceRegistry.auth_sources[name]
if name in AuthSourceRegistry.registry:
AuthSourceRegistry.auth_sources[name] = \
(AuthSourceRegistry.registry[name])(**kwargs)
return AuthSourceRegistry.auth_sources[name]
raise NotImplementedError(
gettext(
"Authentication source '{0}' has not been implemented."
).format(name)
)
@classmethod
def load_auth_sources(cls):
# Initialize the registry only if it has not yet been initialized
if AuthSourceRegistry.registry is None:
AuthSourceRegistry.registry = dict()
from importlib import import_module
from werkzeug.utils import find_modules
for module_name in find_modules(__package__, True):
import_module(module_name)
AuthSourceRegistry = create_registry_metaclass(
"AuthSourceRegistry", __package__, decorate_as_module=True
)
@@ -0,0 +1,68 @@
/////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2021, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
import url_for from 'sources/url_for';
import userInfo from 'pgadmin.user_management.current_user';
import pgConst from 'pgadmin.browser.constants';
function fetch_ticket() {
// Fetch the Kerberos Updated ticket through SPNEGO
return fetch(url_for('kerberos.update_ticket')
)
.then(function(response){
if (response.status >= 200 && response.status < 300) {
return Promise.resolve(response);
} else {
return Promise.reject(new Error(response.statusText));
}
});
}
function fetch_ticket_lifetime () {
// Fetch the Kerberos ticket lifetime left
return fetch(url_for('kerberos.validate_ticket')
)
.then(
function(response){
if (response.status >= 200 && response.status < 300) {
return response.json();
} else {
return Promise.reject(new Error(response.statusText));
}
}
)
.then(function(response){
let ticket_lifetime = response.data.ticket_lifetime;
if (ticket_lifetime > 0) {
return Promise.resolve(ticket_lifetime);
} else {
return Promise.reject();
}
});
}
function validate_kerberos_ticket() {
// Ping pgAdmin server every 10 seconds
// to fetch the Kerberos ticket lifetime left
if (userInfo['current_auth_source'] != pgConst['KERBEROS']) return;
return setInterval(function() {
let newPromise = fetch_ticket_lifetime();
newPromise.then(
function() {
return;
},
fetch_ticket
);
}, 10000);
}
export {fetch_ticket, validate_kerberos_ticket, fetch_ticket_lifetime};
+62 -20
View File
@@ -31,8 +31,9 @@ from flask_security.recoverable import reset_password_token_status, \
generate_reset_password_token, update_password
from flask_security.signals import reset_password_instructions_sent
from flask_security.utils import config_value, do_flash, get_url, \
get_message, slash_url_suffix, login_user, send_mail, logout_user
from flask_security.views import _security, _commit, _ctx
get_message, slash_url_suffix, login_user, send_mail, logout_user, \
get_post_logout_redirect
from flask_security.views import _security, view_commit, _ctx
from werkzeug.datastructures import MultiDict
import config
@@ -50,7 +51,8 @@ from pgadmin.utils.master_password import validate_master_password, \
set_crypt_key, process_masterpass_disabled
from pgadmin.model import User
from pgadmin.utils.constants import MIMETYPE_APP_JS, PGADMIN_NODE,\
INTERNAL, KERBEROS
INTERNAL, KERBEROS, LDAP, QT_DEFAULT_PLACEHOLDER, OAUTH2
from pgadmin.authenticate import AuthSourceManager
try:
from flask_security.views import default_render_json
@@ -197,7 +199,8 @@ class BrowserModule(PgAdminModule):
for name, script in [
[PGADMIN_BROWSER, 'js/browser'],
['pgadmin.browser.endpoints', 'js/endpoints'],
['pgadmin.browser.error', 'js/error']
['pgadmin.browser.error', 'js/error'],
['pgadmin.browser.constants', 'js/constants']
]:
scripts.append({
'name': name,
@@ -341,6 +344,7 @@ class BrowserModule(PgAdminModule):
list: a list of url endpoints exposed to the client.
"""
return [BROWSER_INDEX, 'browser.nodes',
'browser.check_corrupted_db_file',
'browser.check_master_password',
'browser.set_master_password',
'browser.reset_master_password',
@@ -604,14 +608,8 @@ class BrowserPluginModule(PgAdminModule):
def _get_logout_url():
if config.SERVER_MODE and\
session['_auth_source_manager_obj']['current_source'] == \
KERBEROS:
return '{0}?next={1}'.format(url_for(
'authenticate.kerberos_logout'), url_for(BROWSER_INDEX))
return '{0}?next={1}'.format(
url_for('security.logout'), url_for(BROWSER_INDEX))
url_for(current_app.login_manager.logout_view), url_for(BROWSER_INDEX))
def _get_supported_browser():
@@ -745,10 +743,10 @@ def index():
if len(config.AUTHENTICATION_SOURCES) == 1\
and INTERNAL in config.AUTHENTICATION_SOURCES:
auth_only_internal = True
auth_source = session['_auth_source_manager_obj'][
auth_source = session['auth_source_manager'][
'source_friendly_name']
if session['_auth_source_manager_obj']['current_source'] == KERBEROS:
if not config.MASTER_PASSWORD_REQUIRED and 'pass_enc_key' in session:
session['allow_save_password'] = False
response = Response(render_template(
@@ -850,7 +848,10 @@ def utils():
app_version_int=config.APP_VERSION_INT,
pg_libpq_version=pg_libpq_version,
support_ssh_tunnel=config.SUPPORT_SSH_TUNNEL,
logout_url=_get_logout_url()
logout_url=_get_logout_url(),
platform=sys.platform,
qt_default_placeholder=QT_DEFAULT_PLACEHOLDER,
enable_psql=config.ENABLE_PSQL
),
200, {'Content-Type': MIMETYPE_APP_JS})
@@ -864,6 +865,19 @@ def exposed_urls():
)
@blueprint.route("/js/constants.js")
@pgCSRFProtect.exempt
def app_constants():
return make_response(
render_template('browser/js/constants.js',
INTERNAL=INTERNAL,
LDAP=LDAP,
KERBEROS=KERBEROS,
OAUTH2=OAUTH2),
200, {'Content-Type': MIMETYPE_APP_JS}
)
@blueprint.route("/js/error.js")
@pgCSRFProtect.exempt
@login_required
@@ -936,6 +950,19 @@ def form_master_password_response(existing=True, present=False, errmsg=None):
})
@blueprint.route("/check_corrupted_db_file",
endpoint="check_corrupted_db_file", methods=["GET"])
def check_corrupted_db_file():
"""
Get the corrupted database file path.
"""
file_location = os.environ['CORRUPTED_DB_BACKUP_FILE'] \
if 'CORRUPTED_DB_BACKUP_FILE' in os.environ else ''
# reset the corrupted db file path in env.
os.environ['CORRUPTED_DB_BACKUP_FILE'] = ''
return make_json_response(data=file_location)
@blueprint.route("/master_password", endpoint="check_master_password",
methods=["GET"])
def check_master_password():
@@ -974,8 +1001,10 @@ def set_master_password():
data = json.loads(data)
# Master password is not applicable for server mode
if not config.SERVER_MODE and config.MASTER_PASSWORD_REQUIRED:
# Enable master password if oauth is used
if not config.SERVER_MODE or OAUTH2 in config.AUTHENTICATION_SOURCES \
or KERBEROS in config.AUTHENTICATION_SOURCES \
and config.MASTER_PASSWORD_REQUIRED:
# if master pass is set previously
if current_user.masterpass_check is not None and \
data.get('button_click') and \
@@ -1012,7 +1041,7 @@ def set_master_password():
existing=True,
present=False,
)
elif not get_crypt_key()[0]:
elif not get_crypt_key()[1]:
error_message = None
if data.get('button_click') and data.get('password') == '':
# If user attempted to enter a blank password, then throw error
@@ -1104,7 +1133,8 @@ if hasattr(config, 'SECURITY_CHANGEABLE') and config.SECURITY_CHANGEABLE:
if form.validate_on_submit():
try:
change_user_password(current_user, form.new_password.data)
change_user_password(current_user._get_current_object(),
form.new_password.data)
except SOCKETErrorException as e:
# Handle socket errors which are not covered by SMTPExceptions.
logging.exception(str(e), exc_info=True)
@@ -1130,7 +1160,7 @@ if hasattr(config, 'SECURITY_CHANGEABLE') and config.SECURITY_CHANGEABLE:
has_error = True
if request.json is None and not has_error:
after_this_request(_commit)
after_this_request(view_commit)
do_flash(*get_message('PASSWORD_CHANGE'))
old_key = get_crypt_key()[1]
@@ -1296,9 +1326,21 @@ if hasattr(config, 'SECURITY_RECOVERABLE') and config.SECURITY_RECOVERABLE:
has_error = True
if not has_error:
after_this_request(_commit)
after_this_request(view_commit)
auth_obj = AuthSourceManager(form, [INTERNAL])
session['_auth_source_manager_obj'] = auth_obj.as_dict()
if user.login_attempts >= config.MAX_LOGIN_ATTEMPTS > 0:
flash(gettext('You successfully reset your password but'
' your account is locked. Please contact '
'the Administrator.'),
'warning')
return redirect(get_post_logout_redirect())
do_flash(*get_message('PASSWORD_RESET'))
login_user(user)
auth_obj = AuthSourceManager(form, [INTERNAL])
session['auth_source_manager'] = auth_obj.as_dict()
return redirect(get_url(_security.post_reset_view) or
get_url(_security.post_login_view))
@@ -6,10 +6,12 @@
# This software is released under the PostgreSQL Licence
#
##########################################################################
import sys
from flask_babelex import gettext
from pgadmin.utils.constants import PREF_LABEL_DISPLAY,\
PREF_LABEL_KEYBOARD_SHORTCUTS, PREF_LABEL_TABS_SETTINGS, \
PREF_LABEL_OPTIONS
PREF_LABEL_OPTIONS, QT_DEFAULT_PLACEHOLDER
from flask_security import current_user
import config
LOCK_LAYOUT_LEVEL = {
@@ -468,7 +470,7 @@ def register_browser_preferences(self):
self.qt_tab_title = self.preference.register(
'tab_settings', 'qt_tab_title_placeholder',
gettext("Query tool tab title"),
'text', '%DATABASE%/%USERNAME%@%SERVER%',
'text', QT_DEFAULT_PLACEHOLDER,
category_label=PREF_LABEL_DISPLAY,
help_str=gettext(
'Supported placeholders are %DATABASE%, %USERNAME%, and %SERVER%. '
@@ -504,17 +506,27 @@ def register_browser_preferences(self):
)
)
ope_new_tab_options = [
{'label': gettext('Query Tool'), 'value': 'qt'},
{'label': gettext('Debugger'), 'value': 'debugger'},
{'label': gettext('Schema Diff'), 'value': 'schema_diff'},
{'label': gettext('ERD Tool'), 'value': 'erd_tool'}]
# Allow psq tool to open in new browser tab if ENABLE_PSQL is set to True
if config.ENABLE_PSQL:
ope_new_tab_options.append(
{'label': gettext('PSQL Tool'), 'value': 'psql_tool'})
self.open_in_new_tab = self.preference.register(
'tab_settings', 'new_browser_tab_open',
gettext("Open in new browser tab"), 'select2', None,
category_label=PREF_LABEL_OPTIONS,
options=[{'label': gettext('Query Tool'), 'value': 'qt'},
{'label': gettext('Debugger'), 'value': 'debugger'},
{'label': gettext('Schema Diff'), 'value': 'schema_diff'},
{'label': gettext('ERD Tool'), 'value': 'erd_tool'}],
help_str=gettext('Select Query Tool, Debugger, or Schema Diff from '
'the drop-down to set open in new browser tab for '
'that particular module.'),
options=ope_new_tab_options,
help_str=gettext(
'Select Query Tool, Debugger, Schema Diff, ERD Tool '
'or PSQL Tool from the drop-down to set '
'open in new browser tab for that particular module.'
),
select2={
'multiple': True, 'allowClear': False,
'tags': True, 'first_empty': False,
@@ -523,3 +535,18 @@ def register_browser_preferences(self):
'placeholder': gettext('Select open new tab...')
}
)
# Set PSQL tool tab title if ENABLE_PSQL is set to True
if config.ENABLE_PSQL:
self.psql_tab_title = self.preference.register(
'tab_settings', 'psql_tab_title_placeholder',
gettext("PSQL tool tab title"),
'text', '%DATABASE%/%USERNAME%@%SERVER%',
category_label=PREF_LABEL_DISPLAY,
help_str=gettext(
'Supported placeholders are %DATABASE%, %USERNAME%, '
'and %SERVER%. Users can provide any string with or without'
' placeholders of their choice. The blank title will be revert'
' back to the default title with placeholders.'
)
)
@@ -34,6 +34,7 @@ from pgadmin.utils.constants import UNAUTH_REQ, MIMETYPE_APP_JS, \
SERVER_CONNECTION_CLOSED
from sqlalchemy import or_
from pgadmin.utils.preferences import Preferences
from .... import socketio as sio
def has_any(data, keys):
@@ -253,7 +254,9 @@ class ServerModule(sg.ServerGroupPluginModule):
errmsg=errmsg,
user_id=server.user_id,
user_name=server.username,
shared=server.shared
shared=server.shared,
is_kerberos_conn=bool(server.kerberos_conn),
gss_authenticated=manager.gss_authenticated
)
@property
@@ -339,6 +342,7 @@ class ServerModule(sg.ServerGroupPluginModule):
db.session.rollback()
user = User.query.filter_by(id=data.user_id).first()
shared_server = SharedServer(
osid=data.id,
user_id=current_user.id,
server_owner=user.username,
servergroup_id=gid,
@@ -388,14 +392,14 @@ class ServerModule(sg.ServerGroupPluginModule):
"""
shared_server = SharedServer.query.filter_by(
name=server.name, user_id=current_user.id,
servergroup_id=gid).first()
servergroup_id=gid, osid=server.id).first()
if shared_server is None:
ServerModule.create_shared_server(server, gid)
shared_server = SharedServer.query.filter_by(
name=server.name, user_id=current_user.id,
servergroup_id=gid).first()
servergroup_id=gid, osid=server.id).first()
return shared_server
@@ -546,7 +550,9 @@ class ServerNode(PGChildNodeView):
if server.tunnel_password is not None else False,
errmsg=errmsg,
user_name=server.username,
shared=server.shared
shared=server.shared,
is_kerberos_conn=bool(server.kerberos_conn),
gss_authenticated=manager.gss_authenticated
)
)
@@ -613,11 +619,13 @@ class ServerNode(PGChildNodeView):
if server.tunnel_password is not None else False,
errmsg=errmsg,
shared=server.shared,
user_name=server.username
user_name=server.username,
is_kerberos_conn=bool(server.kerberos_conn),
gss_authenticated=manager.gss_authenticated
),
)
def delete_shared_server(self, server_name, gid):
def delete_shared_server(self, server_name, gid, osid):
"""
Delete the shared server
:param server_name:
@@ -625,7 +633,8 @@ class ServerNode(PGChildNodeView):
"""
try:
shared_server = SharedServer.query.filter_by(name=server_name,
servergroup_id=gid)
servergroup_id=gid,
osid=osid)
for s in shared_server:
get_driver(PG_DEFAULT_DRIVER).delete_manager(s.id)
db.session.delete(s)
@@ -661,7 +670,7 @@ class ServerNode(PGChildNodeView):
get_driver(PG_DEFAULT_DRIVER).delete_manager(s.id)
db.session.delete(s)
db.session.commit()
self.delete_shared_server(server_name, gid)
self.delete_shared_server(server_name, gid, sid)
QueryHistory.clear_history(current_user.id, sid)
except Exception as e:
@@ -719,7 +728,8 @@ class ServerNode(PGChildNodeView):
'tunnel_username': 'tunnel_username',
'tunnel_authentication': 'tunnel_authentication',
'tunnel_identity_file': 'tunnel_identity_file',
'shared': 'shared'
'shared': 'shared',
'kerberos_conn': 'kerberos_conn',
}
disp_lbl = {
@@ -818,7 +828,7 @@ class ServerNode(PGChildNodeView):
if 'shared' in data and not data['shared']:
# Delete the shared server from DB if server
# owner uncheck shared property
self.delete_shared_server(server.name, gid)
self.delete_shared_server(server.name, gid, server.id)
if arg == 'sslcompression':
value = 1 if value else 0
self._update_server_details(server, sharedserver,
@@ -983,7 +993,10 @@ class ServerNode(PGChildNodeView):
'tunnel_username': tunnel_username,
'tunnel_identity_file': server.tunnel_identity_file
if server.tunnel_identity_file else None,
'tunnel_authentication': tunnel_authentication
'tunnel_authentication': tunnel_authentication,
'kerberos_conn': bool(server.kerberos_conn),
'gss_authenticated': manager.gss_authenticated,
'gss_encrypted': manager.gss_encrypted
}
return ajax_response(response)
@@ -1070,7 +1083,8 @@ class ServerNode(PGChildNodeView):
tunnel_authentication=data.get('tunnel_authentication', 0),
tunnel_identity_file=data.get('tunnel_identity_file', None),
shared=data.get('shared', None),
passfile=data.get('passfile', None)
passfile=data.get('passfile', None),
kerberos_conn=1 if data.get('kerberos_conn', False) else 0,
)
db.session.add(server)
db.session.commit()
@@ -1152,7 +1166,10 @@ class ServerNode(PGChildNodeView):
else 'pg',
version=manager.version
if manager and manager.version
else None
else None,
is_kerberos_conn=bool(server.kerberos_conn),
gss_authenticated=manager.gss_authenticated if
manager and manager.gss_authenticated else False
)
)
@@ -1346,7 +1363,8 @@ class ServerNode(PGChildNodeView):
except Exception as e:
current_app.logger.exception(e)
return internal_server_error(errormsg=str(e))
if 'password' not in data:
if 'password' not in data and (server.kerberos_conn is False or
server.kerberos_conn is None):
conn_passwd = getattr(conn, 'password', None)
if conn_passwd is None and not server.save_password and \
server.passfile is None and server.service is None:
@@ -1398,6 +1416,9 @@ class ServerNode(PGChildNodeView):
"Could not connect to server(#{0}) - '{1}'.\nError: {2}"
.format(server.id, server.name, errmsg)
)
if errmsg.find('Ticket expired') != -1:
return internal_server_error(errmsg)
return self.get_response_for_password(server, 401, True,
True, errmsg)
else:
@@ -1465,6 +1486,8 @@ class ServerNode(PGChildNodeView):
'is_password_saved': bool(server.save_password),
'is_tunnel_password_saved': True
if server.tunnel_password is not None else False,
'is_kerberos_conn': bool(server.kerberos_conn),
'gss_authenticated': manager.gss_authenticated
}
)
@@ -1477,6 +1500,13 @@ class ServerNode(PGChildNodeView):
# Release Connection
manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(sid)
# Check if any psql terminal is running for the current disconnecting
# server. If any terminate the psql tool connection.
if 'sid_soid_mapping' in current_app.config and str(sid) in \
current_app.config['sid_soid_mapping']:
if str(sid) in current_app.config['sid_soid_mapping']:
for i in current_app.config['sid_soid_mapping'][str(sid)]:
sio.emit('disconnect-psql', namespace='/pty', to=i)
status = manager.release()
@@ -1878,7 +1908,7 @@ class ServerNode(PGChildNodeView):
if server.shared and server.user_id != current_user.id:
shared_server = SharedServer.query.filter_by(
name=server.name, user_id=current_user.id,
servergroup_id=gid).first()
servergroup_id=gid, osid=server.id).first()
if shared_server is None:
return make_json_response(
@@ -490,6 +490,7 @@ class DatabaseView(PGChildNodeView):
did, errmsg
)
)
return internal_server_error(errmsg)
else:
current_app.logger.info(
@@ -405,7 +405,7 @@ class CastView(PGChildNodeView, SchemaDiffObjectCompare):
if not status:
return internal_server_error(errormsg=res)
# we need oid to to add object in tree at browser, below sql will
# we need oid to add object in tree at browser, below sql will
# gives the same
last_system_oid = 0 if self.blueprint.show_system_objects else \
self.datlastsysoid
@@ -189,12 +189,7 @@ define('pgadmin.node.language', [
});
}
return res;
}, disabled: function(m) {
if (m.isNew()) {
return m.get('template_list').indexOf(m.get('name')) != -1;
}
return false;
},
}, disabled: 'isDisabled',
readonly: function(m) {return !m.isNew();},
},{
id: 'laninl', label: gettext('Inline function'), type: 'text', control: 'node-ajax-options',
@@ -214,12 +209,7 @@ define('pgadmin.node.language', [
});
}
return res;
}, disabled: function(m) {
if (m.isNew()) {
return m.get('template_list').indexOf(m.get('name')) != -1;
}
return false;
},
}, disabled: 'isDisabled',
readonly: function(m) {return !m.isNew();},
},{
id: 'lanval', label: gettext('Validator function'), type: 'text', control: 'node-ajax-options',
@@ -239,12 +229,7 @@ define('pgadmin.node.language', [
});
}
return res;
}, disabled: function(m) {
if (m.isNew()) {
return m.get('template_list').indexOf(m.get('name')) != -1;
}
return false;
},
}, disabled: 'isDisabled',
readonly: function(m) {return !m.isNew();},
}, {
id: 'lanacl', label: gettext('Privileges'), type: 'collection',
@@ -292,6 +277,12 @@ define('pgadmin.node.language', [
return null;
},
isDisabled: function(m){
if (m.isNew()) {
return m.get('template_list').indexOf(m.get('name')) != -1;
}
return false;
},
}),
});
}
@@ -630,7 +630,7 @@ It may have been removed by another user.
errormsg=res
)
# we need oid to to add object in tree at browser,
# we need oid to add object in tree at browser,
# below sql will gives the same
SQL = render_template(
"/".join([self.template_path, 'sql/oid.sql']),
@@ -490,7 +490,7 @@ class CollationView(PGChildNodeView, SchemaDiffObjectCompare):
if not status:
return internal_server_error(errormsg=res)
# We need oid to to add object in tree at browser
# We need oid to add object in tree at browser
SQL = render_template(
"/".join([self.template_path, self._OID_SQL]), data=data
)
@@ -598,7 +598,7 @@ class CollationView(PGChildNodeView, SchemaDiffObjectCompare):
if not status:
return internal_server_error(errormsg=res)
# We need oid to to add object in tree at browser
# We need oid to add object in tree at browser
SQL = render_template("/".join([self.template_path,
self._OID_SQL]), coid=coid)
@@ -590,7 +590,7 @@ AND relkind != 'c'))"""
if not status:
return internal_server_error(errormsg=res)
# We need oid to to add object in tree at browser, below sql will
# We need oid to add object in tree at browser, below sql will
# gives the same
SQL = render_template("/".join([self.template_path,
self._OID_SQL]),
@@ -418,7 +418,7 @@ class FtsParserView(PGChildNodeView, SchemaDiffObjectCompare):
if not status:
return internal_server_error(errormsg=res)
# we need fts_parser id to to add object in tree at browser,
# we need fts_parser id to add object in tree at browser,
# below sql will give the same
sql = render_template(
"/".join([self.template_path, self._PROPERTIES_SQL]),
@@ -389,7 +389,7 @@ class FtsTemplateView(PGChildNodeView, SchemaDiffObjectCompare):
if not status:
return internal_server_error(errormsg=res)
# we need fts_template id to to add object in tree at browser,
# we need fts_template id to add object in tree at browser,
# below sql will give the same
sql = render_template(
"/".join([self.template_path, self._PROPERTIES_SQL]),
@@ -823,9 +823,9 @@ class TableView(BaseTableView, DataTypeReader, SchemaDiffTableCompare):
if 'relacl' in data:
data['relacl'] = parse_priv_to_db(data['relacl'], self.acl)
# Parse & format columns
data = column_utils.parse_format_columns(data)
data = TableView.check_and_convert_name_to_string(data)
# Parse & format columns
data = column_utils.parse_format_columns(data)
data = TableView.check_and_convert_name_to_string(data)
# 'coll_inherits' is Array but it comes as string from browser
# We will convert it again to list
@@ -937,7 +937,7 @@ class TableView(BaseTableView, DataTypeReader, SchemaDiffTableCompare):
if not status:
return internal_server_error(errormsg=new_scid)
# we need oid to to add object in tree at browser
# we need oid to add object in tree at browser
sql = render_template(
"/".join([self.table_template_path, self._OID_SQL]),
scid=new_scid, data=data
@@ -413,7 +413,7 @@ class ColumnsView(PGChildNodeView, DataTypeReader):
if not status:
return internal_server_error(errormsg=res)
# we need oid to to add object in tree at browser
# we need oid to add object in tree at browser
SQL = render_template(
"/".join([self.template_path, 'get_position.sql']),
tid=tid, data=data
@@ -600,12 +600,7 @@ define('pgadmin.node.column', [
},{
id: 'seqstart', label: gettext('Start'), type: 'int',
mode: ['properties', 'create', 'edit'], group: gettext('Constraints'),
disabled: function(m) {
let isIdentity = m.get('attidentity');
if(!_.isUndefined(isIdentity) && !_.isNull(isIdentity) && !_.isEmpty(isIdentity))
return false;
return true;
}, deps: ['attidentity', 'colconstype'],
disabled: 'isIdentityColumn', deps: ['attidentity', 'colconstype'],
visible: 'isTypeIdentity',
},{
id: 'seqmin', label: gettext('Minimum'), type: 'int',
@@ -0,0 +1,4 @@
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
ALTER COLUMN "col__1_$%{}[]()&*^!@""'`\/#" SET DEFAULT 'changed default value';
GRANT SELECT("col__1_$%{}[]()&*^!@""'`\/#") ON testschema."table_2_$%{}[]()&*^!@""'`\/#" TO PUBLIC;
@@ -0,0 +1,11 @@
-- Column: testschema."table_2_$%{}[]()&*^!@""'`\/#"."col__1_$%{}[]()&*^!@""'`\/#"
-- ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#" DROP COLUMN "col__1_$%{}[]()&*^!@""'`\/#";
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col__1_$%{}[]()&*^!@""'`\/#" text COLLATE pg_catalog."default" DEFAULT 'changed default value'::text;
COMMENT ON COLUMN testschema."table_2_$%{}[]()&*^!@""'`\/#"."col__1_$%{}[]()&*^!@""'`\/#"
IS 'test comment';
GRANT SELECT("col__1_$%{}[]()&*^!@""'`\/#") ON testschema."table_2_$%{}[]()&*^!@""'`\/#" TO PUBLIC;
@@ -0,0 +1,7 @@
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
ALTER COLUMN "col__2_$%{}[]()&*^!@""'`\/#" TYPE time(6) with time zone ;
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
ALTER COLUMN "col__2_$%{}[]()&*^!@""'`\/#" SET NOT NULL;
COMMENT ON COLUMN testschema."table_2_$%{}[]()&*^!@""'`\/#"."col__2_$%{}[]()&*^!@""'`\/#"
IS 'test comment modification';
@@ -0,0 +1,9 @@
-- Column: testschema."table_2_$%{}[]()&*^!@""'`\/#"."col__2_$%{}[]()&*^!@""'`\/#"
-- ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#" DROP COLUMN "col__2_$%{}[]()&*^!@""'`\/#";
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col__2_$%{}[]()&*^!@""'`\/#" time(6) with time zone NOT NULL DEFAULT now();
COMMENT ON COLUMN testschema."table_2_$%{}[]()&*^!@""'`\/#"."col__2_$%{}[]()&*^!@""'`\/#"
IS 'test comment modification';
@@ -0,0 +1,3 @@
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
ALTER COLUMN "col__3_$%{}[]()&*^!@""'`\/#"
SET (n_distinct=2);
@@ -0,0 +1,13 @@
-- Column: testschema."table_2_$%{}[]()&*^!@""'`\/#"."col__3_$%{}[]()&*^!@""'`\/#"
-- ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#" DROP COLUMN "col__3_$%{}[]()&*^!@""'`\/#";
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col__3_$%{}[]()&*^!@""'`\/#" integer[] NOT NULL;
COMMENT ON COLUMN testschema."table_2_$%{}[]()&*^!@""'`\/#"."col__3_$%{}[]()&*^!@""'`\/#"
IS 'comment';
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
ALTER COLUMN "col__3_$%{}[]()&*^!@""'`\/#"
SET (n_distinct=2);
@@ -1,5 +1,5 @@
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
ADD COLUMN "col_2_$%{}[]()&*^!@""'`\/#" character varying(50, None) COLLATE pg_catalog."C" DEFAULT None;
ADD COLUMN "col_2_$%{}[]()&*^!@""'`\/#" character varying(50) COLLATE pg_catalog."C";
COMMENT ON COLUMN testschema."table_2_$%{}[]()&*^!@""'`\/#"."col_2_$%{}[]()&*^!@""'`\/#"
IS 'Comment for create';
IS 'Comment for create';
Loaded 100 of 849 files, more files were not shown because too many files have changed in this diff. Show more