Compare commits

..
135 Commits
Author SHA1 Message Date
Akshay Joshi 173acd46a5 Update version for release 2019-06-25 01:44:21 +05:30
Aditya Toshniwal c39d257bf6 Fix an XSS issue when username contains XSS vulnerable text. Fixes #4386 2019-06-24 16:06:03 +05:30
Identifier Anonymous b3490ba3de Update Japanese translation 2019-06-24 05:52:53 +05:30
Fred Escallier 4e5d8fe8e2 Update French translation 2019-06-21 16:46:13 +05:30
Akshay Joshi c4de5474a4 Update message catalogs 2019-06-21 15:59:14 +05:30
Aditya Toshniwal ebb5e3fe65 Ensure Python escaping matched JS escaping and fix a minor XSS issue in the Query Tool that required superuser access to trigger. Fixes #4378 2019-06-21 09:53:57 +01:00
Dave Page 644624eabe PEP-8 fixes. 2019-06-20 14:30:31 +01:00
Dave Page 9dbb74367d Fix regression tests. 2019-06-20 14:02:15 +01:00
Khushboo Vashi c07e52b9de Ensure that both columns and partitions can be edited at the same time in the table dialog. Fixes #4380 2019-06-20 13:37:36 +01:00
Aditya Toshniwal 78d55c7cc0 Fix regression tests. 2019-06-20 13:26:06 +01:00
Dave Page 81752bb998 Remove additional "SETOF" included when generating CREATE scripts for trigger functions. Fixes #4362 2019-06-20 13:18:30 +01:00
Dave Page fb4afce629 Fix formatting change which inadvertently broke the feature tests. 2019-06-20 12:43:07 +01:00
Aditya Toshniwal 6e8ebbd375 Allow editing of data where a primary key column includes a % sign in the value. Fixes #4036
Fix an XSS issue seen in View/Edit data mode if a column name includes HTML. Fixes #4367
2019-06-20 12:21:37 +01:00
Akshay Joshi 5c0ea0c012 Capitalize the word 'export' used in Import/Export module. Fixes #4345 2019-06-19 16:17:29 +05:30
Aditya Toshniwal ce7679c4bd Added missing __init__.py file in debugger utils which is required for Python 2.7 2019-06-19 13:31:48 +05:30
Akshay Joshi b36d5d153b Ensure the debugger control buttons are only enabled once initialisation is complete. Fixes #4360 2019-06-18 14:46:28 +01:00
Akshay Joshi 9e65c971a3 Add a framework for testing reversed engineered SQL and CRUD API endpoints. Fixes #4202 2019-06-18 14:28:25 +01:00
Dave Page 71919a4ce9 Prevent the "Please login to access this page" message displaying multiple times. Fixes #4306 2019-06-17 14:12:36 +01:00
Aditya Toshniwal 402dfd07db Change icons for table inheritance (icons by Chethana Kumar) Fixes #3174
Along with this, I have also fixed few other issues/icons found on the way:
1) Dependencies tab for inherited tables/foreign keys shows partial text (Fixes ##3994).
2) Dependencies tab for child partition table shows parent partition table as Function.
3) Dependencies tab for triggers shows trigger functions as plain functions.
4) Dependents tab for partitioned table shows the child partition tables as normal table instead for partitioned tables.
2019-06-17 10:36:30 +01:00
Akshay Joshi bf548dda3f Fix help links for backup globals and backup server. Fixes #4365 2019-06-17 13:27:21 +05:30
Aditya Toshniwal 2894c6cd14 Add minor change missed in previous commit. Fixes #4329 2019-06-14 12:46:48 +01:00
Aditya Toshniwal 3b69f92d70 Ensure strings are properly encoded in the Query History. Fixes #4349 2019-06-14 09:17:02 +01:00
Aditya Toshniwal 82bd94e696 Fix connection restoration issue when pgAdmin server is restarted and the page is refreshed. Fixes #4357 2019-06-14 11:50:01 +05:30
Akshay Joshi 04328b76ba Fix syntax error for Default value of column. It is a regression of #4253 2019-06-13 18:04:43 +05:30
Murtuza Zabuawala 08b78fb6a1 Ensure we include the CSRF token when uploading files. Fixes #4350 2019-06-12 13:52:18 +01:00
Aditya Toshniwal 23364464c2 Ensure the correct label is used in panel headers when viewing filtered rows. Fixes #4228 2019-06-11 15:11:23 +01:00
Akshay Joshi d774a0ff67 Fix issue where property dialog of column should open properly for EPAS v12. Fixes #4343 2019-06-11 17:48:01 +05:30
Aditya Toshniwal 5437a8adab Fix an initialisation error when two functions with parameters are debugged in parallel. Fixes #4329 2019-06-10 14:58:07 +01:00
Dave Page 6d52f2b911 Initial support for PostgreSQL 12. Fixes #4283. Fixes #4288. Fixes #4290. 2019-06-10 14:24:45 +01:00
Dave Page 2ca11c84e8 Ensure that the Return key can be used to submit the Master Password dialogue. Fixes #4310
Ensure that browser auto-fill doesn't cause Help pages to be opened unexpectedly. Fixes #4317
2019-06-10 14:03:56 +01:00
Aditya Toshniwal f561c0cee6 Fix keyboard navigation in "inner" tabsets such as the Query Tool and Debugger. Fixes #4195 2019-06-10 11:10:49 +01:00
Fred Escallier 321b445a7e Update French translation. 2019-06-10 10:08:27 +01:00
Aditya Toshniwal 7ff85903e4 Fix issue where reverse engineered SQL was failing for foreign tables, if it had = in the options. Fixes #4171 2019-06-10 12:15:12 +05:30
Aditya Toshniwal 8b9c50ee5c Fix issue where new column should be created with Default value. Fixes #4235 2019-06-10 11:53:16 +05:30
Ma Yanhong 4b6e9b031c Update Chinese translation. 2019-06-06 10:06:28 +01:00
Dave Page e691885881 Clarify warnings about disabling the master password. 2019-06-05 15:32:47 +01:00
Dave Page caf181d5e3 Clarify docs around configuration files and disabling the master password. 2019-06-05 15:20:38 +01:00
Aditya Toshniwal d90136d93d Prevent the geometry viewer grabbing key presses when not in focus under Firefox, IE and Edge. Fixes #4255 2019-06-05 12:00:09 +01:00
Aditya Toshniwal 9a00a8a60b Update codemirror version. Fixes #4035 2019-06-05 12:12:56 +05:30
Aditya Toshniwal a588c2994d 1) Fix issue where SSH tunnel connection using password is failing, it's regression of Master Password. Fixes #4320
2) Fix some more issues related to SSH Tunnel(By: Akshay Joshi)
2019-06-05 12:07:24 +05:30
Dave Page 13704a4f34 Disable upgrade checks whilst testing. 2019-06-03 11:35:59 -04:00
Usman Muzaffar 912db8913f Ensure that successful maintenance tasks don't leave a notifier window behind when running regression tests. 2019-06-03 11:33:32 -04:00
Akshay Joshi 969a2961fe Update version for release. 2019-06-01 14:19:28 +05:30
Akshay Joshi 6b80523872 Update message catalogs. 2019-06-01 14:14:04 +05:30
Akshay Joshi c16c593322 Update the release date in the release note. 2019-06-01 14:11:34 +05:30
Akshay Joshi 6a7339bbe4 Fix syntax error while opening properties tab of functions and procedures inside packages. 2019-06-01 14:02:33 +05:30
Dave Page 41a20e0252 Fix PEP-8 issue. 2019-05-31 12:12:04 -04:00
Dave Page 2dd075161d Allow the UI layout to be fully locked or to prevent docking changes. Fixes #2653 2019-05-31 11:51:30 -04:00
Aditya Toshniwal 91075cc3f5 Disable the master password in test mode (for now). 2019-05-31 10:19:04 -04:00
Akshay Joshi 26c7d76d4f Fix the issue of accessing the SQL for Views and Materialized Views. Regression of pluralisation of folder names. Fixes #4308 2019-05-31 11:02:37 +05:30
Aditya Toshniwal 2185ea302d Omit the geometry viewer in the Query Tool from layout saving. Fixes #4169 2019-05-30 15:15:37 -04:00
Murtuza Zabuawala 32defc91cc Improve the performance of explain plan by embedding the images only when downloading it. Fixes #4307 2019-05-30 17:49:43 +05:30
Dave Page 37bde4aaf4 Credit reporter who provided test script. 2019-05-29 16:34:04 -04:00
Dave Page 1f76d207f2 Minor phrasing fix. 2019-05-29 16:32:35 -04:00
Dave Page 8eab534c95 Fix typo 2019-05-29 16:27:56 -04:00
Dave Page 0eb3008426 Tidy up keyboard shortcut docs. 2019-05-29 16:24:29 -04:00
Aditya Toshniwal dd187b9122 Prevent Alertify from inadvertently opening help pages. 2019-05-29 13:46:39 -04:00
Aditya Toshniwal 15252b0a26 Added Help button on all master password dialogs. 2019-05-29 13:07:50 +05:30
Akshay Joshi aa95ff9f57 Fix encoding issue for background process, it is regression of Master Password. Fixes #4303 2019-05-29 12:50:48 +05:30
Fred Escallier dad0d690db Update French translation. 2019-05-29 12:25:37 +05:30
Dave Page 2fa849dc26 Also need openssl-dev 2019-05-28 18:11:42 -04:00
Dave Page f340cd044b build-deps doesn't exist any more. 2019-05-28 18:09:06 -04:00
Dave Page 991f667f9f Argh, they are Alpine packages, not Python. 2019-05-28 18:01:56 -04:00
Dave Page 307637b969 Looks like we also need build tools for the cryptography module. 2019-05-28 17:56:54 -04:00
Dave Page 91595593d3 Doc builds now need the cryptography module. 2019-05-28 17:50:11 -04:00
Identifier Anonymous 12186a0fd6 Update Japanese translation. 2019-05-28 17:11:27 +05:30
Ashesh Vashi 9fdf68d559 Fix fatal error on launch of pgAdmin4. Fixes #4298 2019-05-28 17:05:54 +05:30
Akshay Joshi 8851cb0704 Update version for release 2019-05-28 12:09:33 +05:30
Akshay Joshi a936f708de Update message catalogs. 2019-05-28 12:06:44 +05:30
Aditya Toshniwal dfa892d2a2 1. Added Master Password to increase the security of saved passwords. Fixes #4184
2. In server(web) mode, update all the saved server credentials when user password is changed. Fixes #3377
2019-05-28 12:00:18 +05:30
Khushboo Vashi 6f0eafb223 Fixed CSRF security vulnerability issue. per Alvin Lindstam. Fixes #4217
Initial patch by: Khushboo Vashi
Modified by: Ashesh Vashi and Murtuza Zabuawala
2019-05-28 10:59:51 +05:30
Akshay Joshi 90a45557b9 1. Fix syntax error when adding more than one column to the existing table. Fixes #4162
2. Fix syntax error when creating a table with a serial column. Fixes #4284
2019-05-27 13:09:11 +05:30
Akshay Joshi 2790d01c31 Update message catalogs. 2019-05-24 17:26:26 +05:30
Dave Page 4d23bb24a5 Add a missing fix. 2019-05-24 09:36:33 +01:00
Aditya Toshniwal 361f7077fd Update the UI logo. Artwork by Chethana Kumar. Fixes #4208 2019-05-23 16:39:10 +01:00
Usman Muzaffar dcd163ac02 Feature test stabilisation. 2019-05-23 09:31:52 +01:00
Aditya Toshniwal ee37be56f9 Fix handling of JSON in the Query Tool with NULL elements. Fixes #4263 2019-05-23 08:53:29 +01:00
Dave Page f1ef7b0346 Validate permissions on the session directory itself, not it's parent, per Felix Pusch. Fixes #4276 2019-05-21 12:14:36 +01:00
Dave Page 0ee50ac248 Clarify wording for the NO INHERIT option on constraints, per Michel Feinstein. Fixes #4275 2019-05-21 11:51:19 +01:00
Dave Page ea4dbd31e8 Don't try to set permissions on Windows. It won't work anyway. Fixes #4276 2019-05-20 13:53:08 +01:00
Murtuza Zabuawala 155768a2d7 Prevent Backgrid Password cells from losing focus if the browser opens an autocomplete list. Fixes #4278 2019-05-20 13:34:47 +01:00
Dave Page da8da7bb49 Relax the permission check on the directory containing the config database, as it may fail in some environments such as OpenShift. Fixes #4276 2019-05-20 09:46:02 +01:00
Murtuza Zabuawala 5786c17569 Fix navigation of switch cells in grids. Fixes #4269 2019-05-17 16:27:14 +01:00
Dave Page 941dea99f5 Fix typo. 2019-05-17 09:04:04 +01:00
Sander Eikelenboom ab5f35da8d Fixed error on displaying table properties of a table partitioned by list having a default partition. Fixes #4262 2019-05-15 18:36:16 +05:30
Aditya Toshniwal db4bb22cc6 Ensure that element should get highlighted when they get focus on using Tab key. Fixes #4245 2019-05-15 17:42:07 +05:30
Aditya Toshniwal 2cd58efcdd 1) Fixed Tab key navigation for Maintenance dialog. Fixes #4227
2) Fix Tab key issue for Toggle switch controls and button on the dialog footer in Safari browser. Fixes #4244
2019-05-15 16:37:06 +05:30
Aditya Toshniwal ed8d1cde00 Fix accessibility issue for menu navigation. Fixes #4194 2019-05-15 15:38:33 +05:30
Akshay Joshi b7121bb2d2 1) Make folder name pluralise inside 'templates' folder and fix naming inconsistency.
2) Remove unwanted functions "module_js()" from the code.
3) Change naming convention for 'Roles' module.
2019-05-15 15:11:54 +05:30
Dave Page 3364350b01 Fix the check target. 2019-05-15 10:03:29 +01:00
Dave Page 4b421550d3 Stop using application/x-javascript as a mime type and use the RFC-compliant application/javascript instead. Fixes #4261 2019-05-15 09:44:57 +01:00
Dave Page 020d9bb018 Clarify when the container will load server definitions. 2019-05-14 09:27:47 +01:00
Murtuza Zabuawala eb189844e7 Fixed console error when subnode control is used in panels. Fixes #4246 2019-05-10 11:24:15 +05:30
Akshay Joshi 20c42d878b Updated jQuery version as they have fixed some vulnerability issue. 2019-05-03 16:47:35 +05:30
Aditya Toshniwal 036bd66638 Fix file browser path issue which occurs when client is on Windows and server is on Mac/Linux. Fixes #4164 2019-05-03 11:58:06 +05:30
Dave Page f02f91cbf1 Ensure popper.js is installed when needed. Fixes #4219 2019-04-30 13:57:10 +01:00
Neel Patel 34b59da526 Properly assign dropdownParent in Select2 controls. Fixes #4218 2019-04-30 12:57:17 +01:00
Fred Escallier 277bf85645 Update French translation. 2019-04-30 11:47:17 +05:30
Akshay Joshi 991fe3d797 Update version for release. 2019-04-30 10:49:49 +05:30
Identifier Anonymous 4009ac3108 Update Japanese translation 2019-04-29 09:21:55 +01:00
Akshay Joshi 92e6a47713 Update message catalogs. 2019-04-26 17:39:45 +05:30
Dave Page e53c2b1a5d Ensure the treeview shows all sequences except those used to implement IDENTITY columns (which can be edited as part of the column). Show all if Show System Objects is enabled. Fixes #4154 2019-04-26 12:36:56 +01:00
Dave Page e536408ce2 Don't try to install Chromedriver using the chromedriver_installer module as it no longer works and doesn't seem to be supported. 2019-04-25 09:41:40 +01:00
Dave Page f74448a1b2 Add a script for installing the required Chromedriver version. 2019-04-25 09:38:52 +01:00
Akshay Joshi 9b5a6e2bb7 Prevent duplicate columns being included in reverse engineered SQL for tables. Fixes #4163 2019-04-24 11:35:20 +01:00
Aditya Toshniwal 3fef078ec8 Remove some unecessary React libraries. 2019-04-24 09:29:01 +01:00
Khushboo Vashi 74af8976c9 Ensure that newly added row in backgrid should be visible. 2019-04-23 17:32:00 +05:30
Khushboo Vashi ecded18333 Fix an issue where 'GRANT UPDATE' sql should be displayed for default sequence privileges. Fixes #4087 2019-04-22 12:24:47 +05:30
Khushboo Vashi 5452bff49e Fixed 'Increment value cannot be empty' error for existing tables. Fixes #4160 2019-04-22 12:04:49 +05:30
Aditya Toshniwal 05ae330030 Improvement for 'beforeunload' event, bind the event only from where it is required. 2019-04-22 11:30:33 +05:30
Dave Page 94e1820ccd Fix skip on Windows. 2019-04-18 11:18:06 +01:00
Aditya Toshniwal 49b318c39e Ensure that confirmation dialog should be popped up before reload of query tool or debugger
if it is opened in a new browser tab. Fixes #4101
2019-04-18 15:39:36 +05:30
Dave Page 4ac064de42 Urgh. Typo. 2019-04-18 09:13:55 +01:00
Dave Page 2ef71cf749 Skip the permissions test on Windows which doesn't support Unix style file permissions. 2019-04-18 09:13:00 +01:00
Aditya Toshniwal d96f453e7f Fixed 'Location cannot be empty' error when open Tablespace properties. Fixes #4134 2019-04-18 12:31:35 +05:30
Khushboo Vashi 0b47d1dbf6 1) Fix an issue where Deleting N number of rows makes first N number of rows disable. Fixes #3605
2) Ensure that on clicking Delete button should not delete rows immediately from the database server,
   it should be deleted when Save button will be clicked. Fixes #2392
2019-04-18 12:09:35 +05:30
Dave Page d728ee7436 Ensure sanity of the permissions on the storage and session directories and the config database. Fixes #4182 2019-04-17 16:57:34 +01:00
Dave Page 1a192109d6 Ensure we create a DMG file that's compatible with macOS 10.10+ 2019-04-15 12:12:46 +01:00
Aditya Toshniwal 024cfd2fab 1) Ensure that JSON strings as comments should be added properly for all the objects. Fixes #3582
2) Fixed alignment issue of columns in definition section of Index node. Fixes #4121
2019-04-12 15:07:07 +05:30
Murtuza Zabuawala a25bb2b7db Add tests for the CSV download. 2019-04-11 17:15:01 +01:00
Fred Escallier fd3337024f Update French translation. 2019-04-11 13:51:40 +01:00
Dave Page ded446fe8a Depend on psycopg2-binary in the Python wheel, rather than psycopg2. Fixes #4165 2019-04-11 10:08:44 +01:00
Khushboo Vashi a9d964b5ca 1) Added support for Default Partition. Fixes #3938
2) Ensure that record should be add/edited for root partition table with primary keys. Fixes #4104
2019-04-11 13:25:24 +05:30
Akshay Joshi 9c3925e448 Ensure that parameters of procedures for EPAS server 10 and below should be set/reset properly. Fixes #4161 2019-04-10 13:22:52 +05:30
Murtuza Zabuawala 6016a5ee98 Fix an issue where the dropdown becomes misaligned/displaced. Fixes #4138 2019-04-09 12:09:25 +05:30
Akshay Joshi 490999f528 Updated release notes 2019-04-08 18:33:20 +05:30
Akshay Joshi ceb0e39e14 Update version for release 2019-04-08 18:31:51 +05:30
Akshay Joshi 3bed332439 Update message catalogs. 2019-04-08 18:24:36 +05:30
Khushboo Vashi c21ea3c342 Ensure that pgAdmin4 should work properly with psycopg2 v2.8. Fixes #4143 2019-04-08 17:49:50 +05:30
Murtuza Zabuawala 84ecffa4d9 Added recommended ESLinter checks. Fixes #4142 2019-04-05 13:07:43 +05:30
Akshay Joshi 9bff6c7157 Fixed pep8 issue 2019-04-05 12:53:50 +05:30
Usman Muzaffar 5c4c09f237 Fixed feature test issues 2019-04-05 12:25:03 +05:30
Dave Page f706f7ed0c Relabel the Save button on the datagrid text editor to avoid confusion with the actual Save button that updates the database. Fixes #4131 2019-04-02 17:20:43 +01:00
Identifier Anonymous fb12b2e2fc Updated Japanese tanslation. 2019-04-02 14:41:05 +01:00
Fred Escallier badbbade08 Updated French tanslation. 2019-04-02 14:38:47 +01:00
989 changed files with 34542 additions and 76921 deletions

No files matched your search

+5 -2
View File
@@ -31,8 +31,8 @@ bundle-dev:
linter:
cd web && yarn run linter
check: install-node bundle linter
cd web && pycodestyle --config=.pycodestyle . && yarn run karma start --single-run && python regression/runtests.py
check: install-node bundle linter check-pep8
cd web && yarn run karma start --single-run && python regression/runtests.py
check-pep8:
pycodestyle --config=.pycodestyle docs/
@@ -43,6 +43,9 @@ check-pep8:
check-python:
cd web && python regression/runtests.py --exclude feature_tests
check-resql:
cd web && python regression/runtests.py --pkg resql --exclude feature_tests
check-feature: install-node bundle
cd web && python regression/runtests.py --pkg feature_tests
+3 -2
View File
@@ -33,8 +33,9 @@ Click the *Definition* tab to continue.
Use the fields in the *Definition* tab to define the check constraint:
* Provide the expression that a row must satisfy in the *Check* field.
* Move the *No Inherit?* switch to the *Yes* position to specify this constraint
is automatically inherited by a table's children. The default is *No*.
* Move the *No Inherit?* switch to the *Yes* position to specify that this
constraint is not automatically inherited by a table's children. The default
is *No*, meaning that the constraint will be inherited by any children.
* Move the *Don't validate?* switch to the *No* position to skip validation of
existing data; the constraint may not hold for all rows in the table. The
default is *Yes*.
+7
View File
@@ -24,6 +24,13 @@ dialog, right-click on the *Servers* node of the tree control, and select
server_dialog
A master password is required to secure and later unlock saved server passwords.
It is set by the user and can be disabled using config.
.. toctree::
master_password
After defining a server connection, right-click on the server name, and select
*Connect to server* to authenticate with the server, and start using pgAdmin to
manage objects that reside on the server.
+3 -2
View File
@@ -88,7 +88,6 @@ instances:
This is the working directory in which pgAdmin stores session data, user files,
configuration files, and it's configuration database. Mapping this directory
onto the host machine gives you an easy way to maintain configuration between
invocations of the container.
*/pgadmin4/config_local.py*
@@ -101,7 +100,9 @@ required.
If this file is mapped, server definitions found in it will be loaded at launch
time. This allows connection information to be pre-loaded into the instance of
pgAdmin in the container.
pgAdmin in the container. Note that server definitions are only loaded on first
launch, i.e. when the configuration database is created, and not on subsequent
launches using the same configuration database.
*/certs/server.cert*
+6 -2
View File
@@ -45,11 +45,15 @@ are as follows:
* ``config_distro.py``: This file is read after ``config.py`` and is intended for
packagers to change any settings that are required for their pgAdmin distribution.
This may typically include certain paths and file locations.
This may typically include certain paths and file locations. This file is optional,
and may be created by packagers in the same directory as ``config.py`` if
needed.
* ``config_local.py``: This file is read after ``config_distro.py`` and is intended
for end users to change any default or packaging specific settings that they may
wish to adjust to meet local preferences or standards.
wish to adjust to meet local preferences or standards.This file is optional,
and may be created by users in the same directory as ``config.py`` if
needed.
.. note:: If the SERVER_MODE setting is changed in ``config_distro.py`` or ``config_local.py``,
you will most likely need to re-set the LOG_FILE, SQLITE_PATH, SESSION_DB_PATH
Executable → Regular
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 53 KiB

Executable → Regular
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 82 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

After

Width:  |  Height:  |  Size: 168 KiB

BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 261 KiB

After

Width:  |  Height:  |  Size: 247 KiB

Executable → Regular
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 79 KiB

Executable → Regular
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 44 KiB

Executable → Regular
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 112 KiB

After

Width:  |  Height:  |  Size: 111 KiB

+67 -65
View File
@@ -73,49 +73,49 @@ When using the syntax-highlighting SQL editors, the following shortcuts are avai
:class: longtable
:widths: 2 2 3
+--------------------------+------------------+-------------------------------------+
| Shortcut (Windows/Linux) | Shortcut (Mac) | Function |
+==========================+==================+=====================================+
| Alt+Left | Option+Left | Move to the beginning of the line |
+--------------------------+------------------+-------------------------------------+
| Alt+Right | Option+Right | Move to the end of the line |
+--------------------------+------------------+-------------------------------------+
| Ctrl+Alt+Left | Cmd+Option+Left | Move left one word |
+--------------------------+------------------+-------------------------------------+
| Ctrl+Alt+Right | Cmd+Option+Right | Move right one word |
+--------------------------+------------------+-------------------------------------+
| Ctrl+/ | Cmd+/ | Comment selected code (Inline) |
+--------------------------+------------------+-------------------------------------+
| Ctrl+. | Cmd+. | Uncomment selected code (Inline) |
+--------------------------+------------------+-------------------------------------+
| Ctrl+Shift+/ | Cmd+Shift+/ | Comment/Uncomment code (Block) |
+--------------------------+------------------+-------------------------------------+
| Ctrl+A | Cmd+A | Select all |
+--------------------------+------------------+-------------------------------------+
| Ctrl+C | Cmd+C | Copy selected text to the clipboard |
+--------------------------+------------------+-------------------------------------+
| Ctrl+R | Cmd+R | Redo last edit un-done |
+--------------------------+------------------+-------------------------------------+
| Ctrl+V | Cmd+V | Paste text from the clipboard |
+--------------------------+------------------+-------------------------------------+
| Ctrl+Z | Cmd+Z | Undo last edit |
+--------------------------+------------------+-------------------------------------+
| Tab | Tab | Indent selected text |
+--------------------------+------------------+-------------------------------------+
| Shift+Tab | Shift+Tab | Un-indent selected text |
+--------------------------+------------------+-------------------------------------+
| Alt+G | Alt+G | Jump (to line:column) |
+--------------------------+------------------+-------------------------------------+
| Ctrl+Space | Ctrl+Space | Auto-complete |
+--------------------------+------------------+-------------------------------------+
| Ctrl+F | Cmd+F | Find |
+--------------------------+------------------+-------------------------------------+
| Ctrl+G | Cmd+G | Find next |
+--------------------------+------------------+-------------------------------------+
| Ctrl+Shift+G | Cmd+Shift+G | Find previous |
+--------------------------+------------------+-------------------------------------+
| Ctrl+Shift+F | Cmd+Shift+F | Replace |
+--------------------------+------------------+-------------------------------------+
+--------------------------+----------------------+-------------------------------------+
| Shortcut (Windows/Linux) | Shortcut (Mac) | Function |
+==========================+======================+=====================================+
| Alt + Left | Option + Left | Move to the beginning of the line |
+--------------------------+----------------------+-------------------------------------+
| Alt + Right | Option + Right | Move to the end of the line |
+--------------------------+----------------------+-------------------------------------+
| Ctrl + Alt + Left | Cmd + Option + Left | Move left one word |
+--------------------------+----------------------+-------------------------------------+
| Ctrl + Alt + Right | Cmd + Option + Right | Move right one word |
+--------------------------+----------------------+-------------------------------------+
| Ctrl + / | Cmd + / | Comment selected code (Inline) |
+--------------------------+----------------------+-------------------------------------+
| Ctrl + . | Cmd + . | Uncomment selected code (Inline) |
+--------------------------+----------------------+-------------------------------------+
| Ctrl + Shift + / | Cmd + Shift + / | Comment/Uncomment code (Block) |
+--------------------------+----------------------+-------------------------------------+
| Ctrl + a | Cmd + a | Select all |
+--------------------------+----------------------+-------------------------------------+
| Ctrl + c | Cmd + c | Copy selected text to the clipboard |
+--------------------------+----------------------+-------------------------------------+
| Ctrl + r | Cmd + r | Redo last edit un-done |
+--------------------------+----------------------+-------------------------------------+
| Ctrl + v | Cmd + v | Paste text from the clipboard |
+--------------------------+----------------------+-------------------------------------+
| Ctrl + z | Cmd + z | Undo last edit |
+--------------------------+----------------------+-------------------------------------+
| Tab | Tab | Indent selected text |
+--------------------------+----------------------+-------------------------------------+
| Shift + Tab | Shift + Tab | Un-indent selected text |
+--------------------------+----------------------+-------------------------------------+
| Alt + g | Option + g | Jump (to line:column) |
+--------------------------+----------------------+-------------------------------------+
| Ctrl + Space | Ctrl + Space | Auto-complete |
+--------------------------+----------------------+-------------------------------------+
| Ctrl + f | Cmd + f | Find |
+--------------------------+----------------------+-------------------------------------+
| Ctrl + g | Cmd + g | Find next |
+--------------------------+----------------------+-------------------------------------+
| Ctrl + Shift + g | Cmd + Shift + g | Find previous |
+--------------------------+----------------------+-------------------------------------+
| Ctrl + Shift + f | Cmd + Shift + f | Replace |
+--------------------------+----------------------+-------------------------------------+
Query Tool
**********
@@ -133,7 +133,7 @@ When using the Query Tool, the following shortcuts are available:
+--------------------------+--------------------+-----------------------------------+
| F7 | F7 | EXPLAIN query |
+--------------------------+--------------------+-----------------------------------+
| Shift+F7 | Shift+F7 | EXPLAIN ANALYZE query |
| Shift + F7 | Shift + F7 | EXPLAIN ANALYZE query |
+--------------------------+--------------------+-----------------------------------+
| F8 | F8 | Execute query to CSV file |
+--------------------------+--------------------+-----------------------------------+
@@ -190,11 +190,11 @@ When using the Debugger, the following shortcuts are available:
+--------------------------+--------------------+-----------------------------------+
| <accesskey> + s | <accesskey> + s | Stop |
+--------------------------+--------------------+-----------------------------------+
| Alt + Shift + q | Alt + Shift + q | Enter or Edit values in Grid |
| Alt + Shift + q | Option + Shift + q | Enter or Edit values in Grid |
+--------------------------+--------------------+-----------------------------------+
Inner Panel Navigation
**********************
Inner Tab and Panel Navigation
******************************
When using the Query Tool and Debugger, the following shortcuts are available
for inner panel navigation:
@@ -203,13 +203,15 @@ for inner panel navigation:
:class: longtable
:widths: 2 2 3
+--------------------------+---------------------------+------------------------------+
| Shortcut (Windows/Linux) | Shortcut (Mac) | Function |
+==========================+===========================+==============================+
| Alt + Shift + Right Arrow| Alt + Shift + Right Arrow | Move to next inner panel |
+--------------------------+---------------------------+------------------------------+
| Alt + Shift + Left Arrow | Alt + Shift + Left Arrow | Move to previous inner panel |
+--------------------------+---------------------------+------------------------------+
+--------------------------+---------------------------+------------------------------------+
| Shortcut (Windows/Linux) | Shortcut (Mac) | Function |
+==========================+===========================+====================================+
| Alt + Shift + ] | Alt + Shift + ] | Move to next tab within a panel |
+--------------------------+---------------------------+------------------------------------+
| Alt + Shift + [ | Alt + Shift + [ | Move to previous tab within a panel|
+--------------------------+---------------------------+------------------------------------+
| Alt + Shift + Tab | Alt + Shift + Tab | Move between inner panels |
+--------------------------+---------------------------+------------------------------------+
Access Key
**********
@@ -221,14 +223,14 @@ default access keys for supported browsers.
:class: longtable
:widths: 2 1 1 1
+-------------------+------------+------------+------------+
| | Windows | Linux | Mac |
+===================+============+============+============+
| Internet Explorer | Alt | Alt | |
+-------------------+------------+------------+------------+
| Chrome | Alt | Alt | Ctrl+Alt |
+-------------------+------------+------------+------------+
| Firefox | Alt+Shift | Alt+Shift | Ctrl+Alt |
+-------------------+------------+------------+------------+
| Safari | Alt | | Ctrl+Alt |
+-------------------+------------+------------+------------+
+-------------------+-------------+-------------+---------------+
| | Windows | Linux | Mac |
+===================+=============+=============+===============+
| Internet Explorer | Alt | Alt | |
+-------------------+-------------+-------------+---------------+
| Chrome | Alt | Alt | Ctrl + Option |
+-------------------+-------------+-------------+---------------+
| Firefox | Alt + Shift | Alt + Shift | Ctrl + Option |
+-------------------+-------------+-------------+---------------+
| Safari | Alt | | Ctrl + Option |
+-------------------+-------------+-------------+---------------+
+1
View File
@@ -16,6 +16,7 @@ Use the fields in the *Login* dialog to authenticate your connection:
field.
* Provide your password in the *Password* field.
* Click the *Login* button to securely log into pgAdmin.
* Please note that, if the pgAdmin server is restarted then you will be logged out. You need to re-login to continue.
Recovering a Lost Password
**************************
+57
View File
@@ -0,0 +1,57 @@
.. _master_password:
************************
`Master Password`:index:
************************
A master password is required to secure and later unlock the saved server
passwords. This is applicable only for desktop mode users.
* You are prompted to enter the master password when you open the window for
the first time after starting the application.
* Once you set the master password, all the existing saved passwords will be
re-encrypted using the master password.
* The server passwords which are saved in the SQLite DB file are encrypted and
decrypted using the master password.
.. image:: images/master_password_set.png
:alt: Set master password
:align: center
* You can disable the master password by setting the configuration parameter
*MASTER_PASSWORD_REQUIRED=False*. See :ref:`Desktop Deployment <desktop_deployment>`
for more information.
.. note:: If the master password is disabled, then all the saved passwords will
be removed.
.. warning:: If the master password is disabled, then the saved passwords will
be encrypted using a key which is derived from information within the
configuration database. Use of a master password ensures that the encryption
key does not need to be stored anywhere, and thus prevents possible access
to server credentials if the configuration database becomes available to an
attacker.
It is **strongly** recommended that you use the master password if you use
the *Save Password* option.
* The master password is not stored anywhere on the physical storage. It is
temporarily stored in the application memory and it does not get saved when
the application is restarted.
* You are prompted to enter the master password when pgAdmin server is
restarted.
.. image:: images/master_password_enter.png
:alt: Enter master password
:align: center
* If you forget the master password, you can use the *Reset Master Password*
button to reset the password.
.. image:: images/master_password_reset.png
:alt: Reset master password
:align: center
.. warning:: Resetting the master password will also remove all saved passwords
and close all existing established connections.
+3
View File
@@ -25,6 +25,9 @@ Use the *File* menu to access the following options:
+-------------------------+---------------------------------------------------------------------------------------------------------+
| *Reset Layout* | If you have modified the workspace, click to restore the default layout. |
+-------------------------+---------------------------------------------------------------------------------------------------------+
| *Lock Layout* | Click to open a submenu to select the level for locking the UI layout |
| | This can also be changed from browser display :ref:`preferences <preferences>` |
+-------------------------+---------------------------------------------------------------------------------------------------------+
The Object Menu
***************
+17 -4
View File
@@ -38,10 +38,6 @@ Use the fields on the *Display* panel to specify general display preferences:
attempt to catch browser close or refresh events and prompt before allowing
them to continue.
* When the *Show system objects?* switch is set to *True*, the client will
display system objects such as system schemas (for example, *pg_temp*) or
system columns (for example, *xmin* or *ctid*) in the tree control.
* When the *Enable browser tree animation?* switch is set to *True*, the client
will display the animated tree control otherwise it will be unanimated.
@@ -49,6 +45,23 @@ Use the fields on the *Display* panel to specify general display preferences:
the client will display the animated dialogues/notifications otherwise it
will be unanimated.
* Use the *Lock layout* field to lock the UI layout at different levels. This
can also be changed from File menu on the :ref:`menu bar <menu_bar>`
+---------------------+-------------------------------------------------------------------+
| Option | Action |
+=====================+===================================================================+
| *None* | No locking. Every panel is resizable and dockable. |
+---------------------+-------------------------------------------------------------------+
| *Prevent docking* | This will disable the docking/undocking of the panels |
+---------------------+-------------------------------------------------------------------+
| *Full* | This will disable resizing, docking/undocking of the panels |
+---------------------+-------------------------------------------------------------------+
* When the *Show system objects?* switch is set to *True*, the client will
display system objects such as system schemas (for example, *pg_temp*) or
system columns (for example, *xmin* or *ctid*) in the tree control.
Use the fields on the *Keyboard shortcuts* panel to configure shortcuts for the
main window navigation:
+5
View File
@@ -11,6 +11,11 @@ notes for it.
.. toctree::
:maxdepth: 1
release_notes_4_9
release_notes_4_8
release_notes_4_7
release_notes_4_6
release_notes_4_5
release_notes_4_4
release_notes_4_3
release_notes_4_2
+17
View File
@@ -0,0 +1,17 @@
***********
Version 4.5
***********
Release date: 2019-04-10
This release contains a number of new features and fixes reported since the
release of pgAdmin4 4.4.
Bug fixes
*********
| `Bug #2214 <https://redmine.postgresql.org/issues/2214>`_ - Fixed 'Change Password' issue for SCRAM authentication.
| `Bug #3656 <https://redmine.postgresql.org/issues/3656>`_ - Ensure that two consecutive SELECT statements should work properly.
| `Bug #4131 <https://redmine.postgresql.org/issues/4131>`_ - Relabel the Save button on the datagrid text editor to avoid confusion with the actual Save button that updates the database.
| `Bug #4142 <https://redmine.postgresql.org/issues/4142>`_ - Added recommended ESLinter checks.
| `Bug #4143 <https://redmine.postgresql.org/issues/4143>`_ - Ensure that pgAdmin4 should work properly with psycopg2 v2.8
+33
View File
@@ -0,0 +1,33 @@
***********
Version 4.6
***********
Release date: 2019-05-02
This release contains a number of new features and fixes reported since the
release of pgAdmin4 4.5
Features
********
| `Feature #4165 <https://redmine.postgresql.org/issues/4165>`_ - Depend on psycopg2-binary in the Python wheel, rather than psycopg2.
Bug fixes
*********
| `Bug #2392 <https://redmine.postgresql.org/issues/2392>`_ - Ensure that on clicking Delete button should not delete rows immediately from the database server, it should be deleted when Save button will be clicked.
| `Bug #3327 <https://redmine.postgresql.org/issues/3327>`_ - Ensure that newly added row in backgrid should be visible.
| `Bug #3582 <https://redmine.postgresql.org/issues/3582>`_ - Ensure that JSON strings as comments should be added properly for all the objects.
| `Bug #3605 <https://redmine.postgresql.org/issues/3605>`_ - Fix an issue where Deleting N number of rows makes first N number of rows disable.
| `Bug #3938 <https://redmine.postgresql.org/issues/3938>`_ - Added support for Default Partition.
| `Bug #4087 <https://redmine.postgresql.org/issues/4087>`_ - Fix an issue where 'GRANT UPDATE' sql should be displayed for default sequence privileges.
| `Bug #4101 <https://redmine.postgresql.org/issues/4101>`_ - Ensure that confirmation dialog should be popped up before reload of query tool or debugger if it is opened in a new browser tab.
| `Bug #4104 <https://redmine.postgresql.org/issues/4104>`_ - Ensure that record should be add/edited for root partition table with primary keys.
| `Bug #4121 <https://redmine.postgresql.org/issues/4121>`_ - Fixed alignment issue of columns in definition section of Index node.
| `Bug #4134 <https://redmine.postgresql.org/issues/4134>`_ - Fixed 'Location cannot be empty' error when open Tablespace properties.
| `Bug #4138 <https://redmine.postgresql.org/issues/4138>`_ - Fix an issue where the dropdown becomes misaligned/displaced.
| `Bug #4154 <https://redmine.postgresql.org/issues/4154>`_ - Ensure the treeview shows all sequences except those used to implement IDENTITY columns (which can be edited as part of the column). Show all if Show System Objects is enabled.
| `Bug #4160 <https://redmine.postgresql.org/issues/4160>`_ - Fixed 'Increment value cannot be empty' error for existing tables.
| `Bug #4161 <https://redmine.postgresql.org/issues/4161>`_ - Ensure that parameters of procedures for EPAS server 10 and below should be set/reset properly.
| `Bug #4163 <https://redmine.postgresql.org/issues/4163>`_ - Prevent duplicate columns being included in reverse engineered SQL for tables.
| `Bug #4182 <https://redmine.postgresql.org/issues/4182>`_ - Ensure sanity of the permissions on the storage and session directories and the config database.
+34
View File
@@ -0,0 +1,34 @@
***********
Version 4.7
***********
Release date: 2019-05-30
This release contains a number of bug fixes since the release of pgAdmin4 4.6.
Bug fixes
*********
| `Bug #3377 <https://redmine.postgresql.org/issues/3377>`_ - In server mode, update all the saved server credentials when user password is changed.
| `Bug #3885 <https://redmine.postgresql.org/issues/3885>`_ - Fix the responsive layout of the main menu bar.
| `Bug #4162 <https://redmine.postgresql.org/issues/4162>`_ - Fix syntax error when adding more than one column to the existing table.
| `Bug #4164 <https://redmine.postgresql.org/issues/4164>`_ - Fix file browser path issue which occurs when client is on Windows and server is on Mac/Linux.
| `Bug #4184 <https://redmine.postgresql.org/issues/4184>`_ - Added Master Password to increase the security of saved passwords.
| `Bug #4194 <https://redmine.postgresql.org/issues/4194>`_ - Fix accessibility issue for menu navigation.
| `Bug #4208 <https://redmine.postgresql.org/issues/4208>`_ - Update the UI logo.
| `Bug #4217 <https://redmine.postgresql.org/issues/4217>`_ - Fixed CSRF security vulnerability issue, per Alvin Lindstam
| `Bug #4218 <https://redmine.postgresql.org/issues/4218>`_ - Properly assign dropdownParent in Select2 controls.
| `Bug #4219 <https://redmine.postgresql.org/issues/4219>`_ - Ensure popper.js is installed when needed.
| `Bug #4227 <https://redmine.postgresql.org/issues/4227>`_ - Fixed Tab key navigation for Maintenance dialog.
| `Bug #4244 <https://redmine.postgresql.org/issues/4244>`_ - Fix Tab key issue for Toggle switch controls and button on the dialog footer in Safari browser.
| `Bug #4245 <https://redmine.postgresql.org/issues/4245>`_ - Ensure that element should get highlighted when they get focus on using Tab key.
| `Bug #4246 <https://redmine.postgresql.org/issues/4246>`_ - Fixed console error when subnode control is used in panels.
| `Bug #4261 <https://redmine.postgresql.org/issues/4261>`_ - Stop using application/x-javascript as a mime type and use the RFC-compliant application/javascript instead.
| `Bug #4262 <https://redmine.postgresql.org/issues/4262>`_ - Fixed error on displaying table properties of a table partitioned by list having a default partition.
| `Bug #4263 <https://redmine.postgresql.org/issues/4263>`_ - Fix handling of JSON in the Query Tool with NULL elements.
| `Bug #4269 <https://redmine.postgresql.org/issues/4269>`_ - Fix navigation of switch cells in grids.
| `Bug #4275 <https://redmine.postgresql.org/issues/4275>`_ - Clarify wording for the NO INHERIT option on constraints, per Michel Feinstein.
| `Bug #4276 <https://redmine.postgresql.org/issues/4276>`_ - Relax the permission check on the directory containing the config database, as it may fail in some environments such as OpenShift.
| `Bug #4278 <https://redmine.postgresql.org/issues/4278>`_ - Prevent Backgrid Password cells from losing focus if the browser opens an autocomplete list.
| `Bug #4284 <https://redmine.postgresql.org/issues/4284>`_ - Fix syntax error when creating a table with a serial column.
+19
View File
@@ -0,0 +1,19 @@
***********
Version 4.8
***********
Release date: 2019-06-03
This release contains a number of bug fixes and new features since the release of pgAdmin4 4.7.
New features
************
| `Feature #2653 <https://redmine.postgresql.org/issues/2653>`_ - Allow the UI layout to be fully locked or to prevent docking changes.
Bug fixes
*********
| `Bug #4169 <https://redmine.postgresql.org/issues/4169>`_ - Omit the geometry viewer in the Query Tool from layout saving.
| `Bug #4307 <https://redmine.postgresql.org/issues/4307>`_ - Improve the performance of explain plan by embedding the images only when downloading it.
| `Bug #4308 <https://redmine.postgresql.org/issues/4308>`_ - Fix the issue of accessing the SQL for Views and Materialized Views. Regression of pluralisation of folder names.
+44
View File
@@ -0,0 +1,44 @@
***********
Version 4.9
***********
Release date: 2019-06-27
This release contains a number of bug fixes and new features since the release of pgAdmin4 4.8.
New features
************
| `Feature #3174 <https://redmine.postgresql.org/issues/3174>`_ - Visually distinguish simple tables from tables that are inherited and from which other tables are inherited.
| `Feature #4202 <https://redmine.postgresql.org/issues/4202>`_ - Add a framework for testing reversed engineered SQL and CRUD API endpoints.
Bug fixes
*********
| `Bug #3994 <https://redmine.postgresql.org/issues/3994>`_ - Fix issue where the dependencies tab for inherited tables/foreign keys shows partial text.
| `Bug #4036 <https://redmine.postgresql.org/issues/4036>`_ - Allow editing of data where a primary key column includes a % sign in the value.
| `Bug #4171 <https://redmine.postgresql.org/issues/4171>`_ - Fix issue where reverse engineered SQL was failing for foreign tables, if it had "=" in the options.
| `Bug #4195 <https://redmine.postgresql.org/issues/4195>`_ - Fix keyboard navigation in "inner" tabsets such as the Query Tool and Debugger.
| `Bug #4228 <https://redmine.postgresql.org/issues/4228>`_ - Ensure the correct label is used in panel headers when viewing filtered rows.
| `Bug #4253 <https://redmine.postgresql.org/issues/4253>`_ - Fix issue where new column should be created with Default value.
| `Bug #4283 <https://redmine.postgresql.org/issues/4283>`_ - Initial support for PostgreSQL 12.
| `Bug #4288 <https://redmine.postgresql.org/issues/4288>`_ - Initial support for PostgreSQL 12.
| `Bug #4290 <https://redmine.postgresql.org/issues/4290>`_ - Initial support for PostgreSQL 12.
| `Bug #4255 <https://redmine.postgresql.org/issues/4255>`_ - Prevent the geometry viewer grabbing key presses when not in focus under Firefox, IE and Edge.
| `Bug #4306 <https://redmine.postgresql.org/issues/4306>`_ - Prevent the "Please login to access this page" message displaying multiple times.
| `Bug #4310 <https://redmine.postgresql.org/issues/4310>`_ - Ensure that the Return key can be used to submit the Master Password dialogue.
| `Bug #4317 <https://redmine.postgresql.org/issues/4317>`_ - Ensure that browser auto-fill doesn't cause Help pages to be opened unexpectedly.
| `Bug #4320 <https://redmine.postgresql.org/issues/4320>`_ - Fix issue where SSH tunnel connection using password is failing, it's regression of Master Password.
| `Bug #4329 <https://redmine.postgresql.org/issues/4329>`_ - Fix an initialisation error when two functions with parameters are debugged in parallel.
| `Bug #4343 <https://redmine.postgresql.org/issues/4343>`_ - Fix issue where property dialog of column should open properly for EPAS v12.
| `Bug #4345 <https://redmine.postgresql.org/issues/4345>`_ - Capitalize the word 'export' used in Import/Export module.
| `Bug #4349 <https://redmine.postgresql.org/issues/4349>`_ - Ensure strings are properly encoded in the Query History.
| `Bug #4350 <https://redmine.postgresql.org/issues/4350>`_ - Ensure we include the CSRF token when uploading files.
| `Bug #4357 <https://redmine.postgresql.org/issues/4357>`_ - Fix connection restoration issue when pgAdmin server is restarted and the page is refreshed.
| `Bug #4360 <https://redmine.postgresql.org/issues/4360>`_ - Ensure the debugger control buttons are only enabled once initialisation is complete.
| `Bug #4362 <https://redmine.postgresql.org/issues/4362>`_ - Remove additional "SETOF" included when generating CREATE scripts for trigger functions.
| `Bug #4365 <https://redmine.postgresql.org/issues/4365>`_ - Fix help links for backup globals and backup server.
| `Bug #4367 <https://redmine.postgresql.org/issues/4367>`_ - Fix an XSS issue seen in View/Edit data mode if a column name includes HTML.
| `Bug #4378 <https://redmine.postgresql.org/issues/4378>`_ - Ensure Python escaping matched JS escaping and fix a minor XSS issue in the Query Tool that required superuser access to trigger.
| `Bug #4380 <https://redmine.postgresql.org/issues/4380>`_ - Ensure that both columns and partitions can be edited at the same time in the table dialog.
| `Bug #4386 <https://redmine.postgresql.org/issues/4386>`_ - Fix an XSS issue when username contains XSS vulnerable text.
+6 -2
View File
@@ -68,11 +68,15 @@ pgAdmin. These are as follows:
* ``config_distro.py``: This file is read after ``config.py`` and is intended for
packagers to change any settings that are required for their pgAdmin distribution.
This may typically include certain paths and file locations.
This may typically include certain paths and file locations. This file is optional,
and may be created by packagers in the same directory as ``config.py`` if
needed.
* ``config_local.py``: This file is read after ``config_distro.py`` and is intended
for end users to change any default or packaging specific settings that they may
wish to adjust to meet local preferences or standards.
wish to adjust to meet local preferences or standards. This file is optional,
and may be created by administrators in the same directory as ``config.py`` if
needed.
Python
------
+5 -3
View File
@@ -264,8 +264,9 @@ Use the fields in the *Definition* tab to define the check constraint:
* Provide the expression that a row must satisfy in the *Check* field. This
field is required.
* Move the *No Inherit?* switch to the *Yes* position to specify this constraint
is automatically inherited by a table's children. The default is *No*.
* Move the *No Inherit?* switch to the *Yes* position to specify that this
constraint is not automatically inherited by a table's children. The default
is *No*, meaning that the constraint will be inherited by any children.
* Move the *Don't validate?* switch to the *No* position to skip validation of
existing data; the constraint may not hold for all rows in the table. The
default is *Yes*.
@@ -442,6 +443,7 @@ icon (+) to add each partition:
* Move the *Operation* switch to *attach* to attach the partition, by default it
is *create*.
* Use the *Name* field to add the name of the partition.
* If partition type is Range or List then *Default* field will be enabled.
* If partition type is Range then *From* and *To* fields will be enabled.
* If partition type is List then *In* field will be enabled.
* If partition type is Hash then *Modulus* and *Remainder* fields will be
@@ -523,4 +525,4 @@ three columns and a primary key constraint on the *category_id* column.
* Click the *Info* button (i) to access online help.
* Click the *Save* button to save work.
* Click the *Cancel* button to exit without saving work.
* Click the *Reset* button to restore configuration parameters.
* Click the *Reset* button to restore configuration parameters.
+2 -2
View File
@@ -22,8 +22,8 @@ RUN yarn install --cache-folder ./ycache --verbose && \
FROM python:3.7-alpine3.9 as docs-builder
# Install only dependencies absolutely required for documentation building
RUN apk add --no-cache make && \
pip install --no-cache-dir sphinx flask_security flask_paranoid python-dateutil flask_sqlalchemy flask_gravatar flask_migrate simplejson
RUN apk add --no-cache make build-base openssl-dev libffi-dev && \
pip install --no-cache-dir sphinx flask_security flask_paranoid python-dateutil flask_sqlalchemy flask_gravatar flask_migrate simplejson cryptography
COPY ./pgadmin4/ /pgadmin4
+1 -1
View File
@@ -29,7 +29,7 @@ for src in "${DMG_SOURCES}"; do
done
echo "Creating image"
${HDIUTIL} create -quiet -srcfolder "$DMG_DIR" -format UDZO -volname "${DMG_VOLUME_NAME}" -ov "${DMG_IMAGE}" || exit 1
${HDIUTIL} create -quiet -srcfolder "$DMG_DIR" -fs HFS+ -format UDZO -volname "${DMG_VOLUME_NAME}" -ov "${DMG_IMAGE}" || exit 1
rm -rf "${DMG_DIR}" || exit 1
echo "Attaching License to image"
+5
View File
@@ -37,6 +37,11 @@ with open(req_file, 'r') as reqf:
for index, req in enumerate(required):
if ";" in req or req.startswith("#") or req == "":
required.remove(req)
continue
# Ensure the Wheel will use psycopg2-binary, not the source distro
if 'psycopg2' in req:
required[index] = req.replace('psycopg2', 'psycopg2-binary')
# Get the app version
if sys.version_info[:2] >= (3, 3):
+1 -1
View File
@@ -21,7 +21,7 @@ sqlparse==0.2.4
WTForms==2.2.1
Flask-Paranoid==0.2.0
psutil==5.5.1
psycopg2>=2.7.7
psycopg2>=2.8
python-dateutil>=2.8.0
htmlmin==0.1.12
Flask-HTMLmin==1.5.0
+2 -2
View File
@@ -8,9 +8,9 @@
<key>CFBundleName</key>
<string>pgAdmin 4</string>
<key>CFBundleShortVersionString</key>
<string>4.4.0</string>
<string>4.9.0</string>
<key>CFBundleVersion</key>
<string>4.4.0</string>
<string>4.9.0</string>
<key>LSMinimumSystemVersion</key>
<string>10.10</string>
<key>NSHumanReadableCopyright</key>
+1 -1
View File
@@ -1,4 +1,4 @@
VERSION = 4.4.0.0
VERSION = 4.9.0.0
QMAKE_TARGET_COMPANY = "The pgAdmin Development Team"
QMAKE_TARGET_PRODUCT = "pgAdmin 4"
QMAKE_TARGET_DESCRIPTION = "pgAdmin 4 Desktop Runtime"
+204
View File
@@ -0,0 +1,204 @@
# -*- coding: utf-8 -*-
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2019, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
# Get the correct version of chromedriver for the version of Chrome on the
# machine and save it to the specified location.
import argparse
import os
import platform
import subprocess
import sys
import urllib.request
import zipfile
def read_command_line():
"""Read the command line arguments.
Returns:
ArgumentParser: The parsed arguments object
"""
parser = argparse.ArgumentParser(
description='Get the correct version of chromedriver for the '
'specified Chrome installation and save it.')
if platform.system() != 'Windows':
parser.add_argument("chrome", metavar="CHROME",
help="the Chrome executable")
parser.add_argument("directory", metavar="DIRECTORY",
help="the directory in which to save chromedriver")
args = parser.parse_args()
return args
def get_chrome_version(args):
"""Get the Chrome version number.
Args:
args: The parsed arguments object
Returns:
The Chrome version number
"""
if platform.system() == 'Windows':
# On Windows we need to examine the resource section of the binary
import winreg
def _read_registry(root, key, value):
try:
hkey = winreg.OpenKey(root, key)
except Exception as e:
return None
try:
(val, typ) = winreg.QueryValueEx(hkey, value)
except Exception as e:
winreg.CloseKey(hkey)
return None
winreg.CloseKey(hkey)
return val
key = r'SOFTWARE\Google\Chrome\BLBeacon'
version_str = _read_registry(winreg.HKEY_CURRENT_USER, key, 'Version')
# On a 64b host, look for a 32b installation
if not version_str:
key = r'SOFTWARE\Wow6432Node\Google\Chrome\BLBeacon'
version_str = _read_registry(winreg.HKEY_CURRENT_USER, key,
'Version')
if not version_str:
print('The Chrome version could not be read from the registry.')
sys.exit(1)
chrome_version = '.'.join(version_str.split()[-1].split('.')[:-1])
else:
# On Linux/Mac we run the Chrome executable with the --version flag,
# then parse the output.
try:
result = subprocess.run([args.chrome, '--version'],
stdout=subprocess.PIPE)
except FileNotFoundError as e:
print('The specified Chrome executable could not be found.')
sys.exit(1)
version_str = result.stdout.decode("utf-8").strip()
# Check for 'Chrom' not 'Chrome' in case the user is using Chromium.
if "Chrom" not in version_str:
print('The specified Chrome executable output an unexpected '
'version string: {}.'.format(version_str))
sys.exit(1)
chrome_version = '.'.join(version_str.split()[-1].split('.')[:-1])
if chrome_version.count('.') != 2:
print('The specified Chrome executable output an unexpected '
'version string: {}.'.format(version_str))
sys.exit(1)
return chrome_version
def get_chromedriver_version(chrome_version):
"""Get the required chromedriver version number.
Args:
chrome_version: The chrome version number
Returns:
The chromedriver version number
"""
url = 'https://chromedriver.storage.googleapis.com/LATEST_RELEASE_{}' \
.format(chrome_version)
try:
fp = urllib.request.urlopen(url)
except urllib.error.URLError as e:
print('The chromedriver catalog URL could not be accessed: {}'
.format(e))
sys.exit(1)
version = fp.read().decode("utf-8").strip()
fp.close()
return version
def get_system():
"""Get the system name as known to chromedriver
Returns:
The system name
"""
if platform.system() == 'Darwin':
return 'mac64'
elif platform.system() == 'Linux':
return 'linux64'
elif platform.system() == 'Windows':
return 'win32'
else:
print("Unknown or unsupported operating system: {}"
.format(platform.system()))
sys.exit(1)
"""The core structure of the app."""
# Read the command line options
args = read_command_line()
chrome_version = get_chrome_version(args)
# Check the directory exists
if not os.path.isdir(args.directory):
print('The specified output directory could not be accessed.')
sys.exit(1)
chromedriver_version = get_chromedriver_version(chrome_version)
system = get_system()
url = 'https://chromedriver.storage.googleapis.com/{}/chromedriver_{}.zip' \
.format(chromedriver_version, system)
print('Downloading chromedriver v{} for Chrome v{} on {}...'
.format(chromedriver_version, chrome_version, system))
try:
file, headers = urllib.request.urlretrieve(url)
except urllib.error.URLError as e:
print('The chromedriver download URL could not be accessed: {}'
.format(e))
sys.exit(1)
# Unzip chromedriver
print('Extracting chromedriver...')
found = False
fp = open(file, 'rb')
z = zipfile.ZipFile(fp)
for name in z.namelist():
if (system == 'win32' and name == 'chromedriver.exe') or \
(system != 'win32' and name == 'chromedriver'):
z.extract(name, args.directory)
found = True
fp.close()
if not found:
print("chromedriver could not be found in the downloaded archive: {}"
.format(file))
sys.exit(1)
# Set the permissions
if system == 'mac64' or system == 'linux64':
os.chmod(os.path.join(args.directory, 'chromedriver'), 0o755)
print('Chromedriver downloaded to: {}'.format(args.directory))
+5
View File
@@ -14,6 +14,9 @@ module.exports = {
'amd': true,
'jasmine': true,
},
'extends': [
'eslint:recommended',
],
'parserOptions': {
'ecmaVersion': 2018,
'sourceType': 'module',
@@ -43,5 +46,7 @@ module.exports = {
'always-multiline'
],
'no-console': ["error", { allow: ["warn", "error"] }],
// We need to exclude below for RegEx case
"no-useless-escape": 0,
},
};
+12 -5
View File
@@ -50,7 +50,7 @@ APP_ICON = 'pg-icon'
# Application version number components
APP_RELEASE = 4
APP_REVISION = 4
APP_REVISION = 9
# Application version suffix, e.g. 'beta1', 'dev'. Usually an empty string
# for GA releases.
@@ -59,7 +59,7 @@ APP_SUFFIX = ''
# Numeric application version for upgrade checks. Should be in the format:
# [X]XYYZZ, where X is the release version, Y is the revision, with a leading
# zero if needed, and Z represents the suffix, with a leading zero if needed
APP_VERSION_INT = 40400
APP_VERSION_INT = 40900
# DO NOT CHANGE!
# The application version string, constructed from the components
@@ -123,6 +123,10 @@ if (not hasattr(builtins, 'SERVER_MODE')) or builtins.SERVER_MODE is None:
else:
SERVER_MODE = builtins.SERVER_MODE
# HTTP headers to search for CSRF token when it is not provided in the form.
# Default is ['X-CSRFToken', 'X-CSRF-Token']
WTF_CSRF_HEADERS = ['X-pgA-CSRFToken']
# User ID (email address) to use for the default user in desktop mode.
# The default should be fine here, as it's not exposed in the app.
DESKTOP_USER = 'pgadmin4@pgadmin.org'
@@ -141,9 +145,6 @@ DEFAULT_SERVER = '127.0.0.1'
# environment by the runtime
DEFAULT_SERVER_PORT = 5050
# Enable CSRF protection?
CSRF_ENABLED = True
# Enable X-Frame-Option protection.
# Set to one of "SAMEORIGIN", "ALLOW-FROM origin" or "" to disable.
# Note that "DENY" is NOT supported (and will be silently ignored).
@@ -418,6 +419,12 @@ SUPPORT_SSH_TUNNEL = True
# Set to False to disable password saving.
ALLOW_SAVE_TUNNEL_PASSWORD = False
##########################################################################
# Master password is used to encrypt/decrypt saved server passwords
# Applicable for desktop mode only
##########################################################################
MASTER_PASSWORD_REQUIRED = True
##########################################################################
# Local config settings
##########################################################################
+51
View File
@@ -0,0 +1,51 @@
"""empty message
Revision ID: 35f29b1701bd
Revises: ec1cac3399c9
Create Date: 2019-04-26 16:38:08.368471
"""
import base64
import os
import sys
from pgadmin.model import db, Server
# revision identifiers, used by Alembic.
revision = '35f29b1701bd'
down_revision = 'ec1cac3399c9'
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,
email VARCHAR(256) NOT NULL,
password VARCHAR(256),
active BOOLEAN NOT NULL,
confirmed_at DATETIME,
masterpass_check VARCHAR(256),
PRIMARY KEY (id),
UNIQUE (email),
CHECK (active IN (0, 1))
);
""")
db.engine.execute("""
INSERT INTO user (
id, email, password, active, confirmed_at
) SELECT
id, email, password, active, confirmed_at
FROM user_old""")
db.engine.execute("DROP TABLE user_old")
def downgrade():
pass
+4 -1
View File
@@ -31,7 +31,10 @@ def upgrade():
Security(app, user_datastore, register_blueprint=False)
else:
app.config['SECURITY_PASSWORD_SALT'] = current_salt
users = User.query.all()
users = User.query.with_entities(
User.id, User.email, User.password, User.active, User.confirmed_at)\
.all()
# This will upgrade the plaintext password of all the user as per the
# SECURITY_PASSWORD_HASH.
for user in users:
+4 -5
View File
@@ -56,7 +56,7 @@
"bootstrap4-toggle": "3.4.0",
"bowser": "2.1.2",
"browserify": "~16.2.3",
"codemirror": "^5.44.0",
"codemirror": "^5.47.0",
"css-loader": "2.1.0",
"cssnano": "^4.1.10",
"dropzone": "^5.5.1",
@@ -67,15 +67,14 @@
"immutability-helper": "^3.0.0",
"imports-loader": "^0.8.0",
"ip-address": "^5.8.9",
"jquery": "3.3.1",
"jquery": "^3.4.0",
"jquery-contextmenu": "^2.8.0",
"jquery-ui": "^1.12.1",
"json-bignumber": "^1.0.1",
"leaflet": "^1.4.0",
"leaflet": "^1.5.1",
"moment": "^2.24.0",
"moment-timezone": "^0.5.23",
"mousetrap": "^1.6.3",
"prop-types": "^15.7.2",
"requirejs": "~2.3.6",
"select2": "^4.0.6-rc.1",
"shim-loader": "^1.0.1",
@@ -90,7 +89,7 @@
"underscore": "^1.9.1",
"underscore.string": "^3.3.5",
"watchify": "~3.11.1",
"webcabin-docker": "git+https://github.com/EnterpriseDB/wcDocker/#e191a1063c111d5542ff26a7c163940be180333d",
"webcabin-docker": "git+https://github.com/EnterpriseDB/wcDocker/#f3c79e4b9a9e76a8e34736fc33473e65c524050c",
"wkx": "^0.4.6"
},
"scripts": {
+41 -4
View File
@@ -23,20 +23,21 @@ from flask_login import user_logged_in, user_logged_out
from flask_mail import Mail
from flask_paranoid import Paranoid
from flask_security import Security, SQLAlchemyUserDatastore, current_user
from flask_security.utils import login_user
from flask_security.utils import login_user, logout_user
from werkzeug.datastructures import ImmutableDict
from werkzeug.local import LocalProxy
from werkzeug.utils import find_modules
from pgadmin.model import db, Role, Server, ServerGroup, \
User, Keys, Version, SCHEMA_VERSION as CURRENT_SCHEMA_VERSION
from pgadmin.utils import PgAdminModule, driver
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 pgadmin.utils.ajax import internal_server_error
from pgadmin.utils.csrf import pgCSRFProtect
# If script is running under python3, it will not have the xrange function
@@ -235,6 +236,8 @@ def create_app(app_name=None):
os.environ['PGADMIN_TESTING_MODE'] == '1'
):
config.SQLITE_PATH = config.TEST_SQLITE_PATH
config.MASTER_PASSWORD_REQUIRED = False
config.UPGRADE_CHECK_ENABLED = False
# Ensure the various working directories exist
from pgadmin.setup import create_app_data_directory, db_upgrade
@@ -338,6 +341,9 @@ def create_app(app_name=None):
set_version(CURRENT_SCHEMA_VERSION)
db.session.commit()
if os.name != 'nt':
os.chmod(config.SQLITE_PATH, 0o600)
Mail(app)
import pgadmin.utils.paths as paths
@@ -364,7 +370,10 @@ def create_app(app_name=None):
'CSRF_SESSION_KEY': config.CSRF_SESSION_KEY,
'SECRET_KEY': config.SECRET_KEY,
'SECURITY_PASSWORD_SALT': config.SECURITY_PASSWORD_SALT,
'SESSION_COOKIE_DOMAIN': config.SESSION_COOKIE_DOMAIN
'SESSION_COOKIE_DOMAIN': config.SESSION_COOKIE_DOMAIN,
# CSRF Token expiration till session expires
'WTF_CSRF_TIME_LIMIT': getattr(config, 'CSRF_TIME_LIMIT', None),
'WTF_CSRF_METHODS': ['GET', 'POST', 'PUT', 'DELETE'],
}))
security.init_app(app, user_datastore)
@@ -567,12 +576,23 @@ def create_app(app_name=None):
def force_session_write(app, user):
session.force_write = True
@user_logged_in.connect_via(app)
def store_crypt_key(app, user):
# in desktop mode, master password is used to encrypt/decrypt
# and is stored in the keyManager memory
if config.SERVER_MODE:
if 'password' in request.form:
current_app.keyManager.set(request.form['password'])
@user_logged_out.connect_via(app)
def current_user_cleanup(app, user):
from config import PG_DEFAULT_DRIVER
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)
@@ -623,6 +643,15 @@ def create_app(app_name=None):
abort(401)
login_user(user)
# 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:
if current_app.keyManager.get() is None and \
request.endpoint not in ('security.login',
'security.logout'):
logout_user()
@app.after_request
def after_request(response):
if 'key' in request.args:
@@ -703,8 +732,16 @@ def create_app(app_name=None):
current_app.logger.error(e, exc_info=True)
return e
# Intialize the key manager
app.keyManager = KeyManager()
##########################################################################
# Protection against CSRF attacks
##########################################################################
with app.app_context():
pgCSRFProtect.init_app(app)
##########################################################################
# All done!
##########################################################################
return app
+209 -35
View File
@@ -18,7 +18,7 @@ from socket import error as SOCKETErrorException
import six
from flask import current_app, render_template, url_for, make_response, \
flash, Response, request, after_this_request, redirect
flash, Response, request, after_this_request, redirect, session
from flask_babelex import gettext
from flask_gravatar import Gravatar
from flask_login import current_user, login_required
@@ -37,9 +37,14 @@ from pgadmin import current_blueprint
from pgadmin.settings import get_setting
from pgadmin.utils import PgAdminModule
from pgadmin.utils.ajax import make_json_response
from pgadmin.utils.csrf import pgCSRFProtect
from pgadmin.utils.preferences import Preferences
from pgadmin.utils.menu import MenuItem
from pgadmin.browser.register_browser_preferences import \
register_browser_preferences
from pgadmin.utils.master_password import validate_master_password, \
set_masterpass_check_text, cleanup_master_password, get_crypt_key, \
set_crypt_key, process_masterpass_disabled
try:
import urllib.request as urlreq
@@ -211,6 +216,40 @@ class BrowserModule(PgAdminModule):
scripts.extend(module.get_own_javascripts())
return scripts
def get_own_menuitems(self):
return {
'file_items': [
MenuItem(
name='mnu_locklayout',
module='pgAdmin.Browser',
label=gettext('Lock Layout'),
priority=999,
menu_items=[MenuItem(
name='mnu_lock_none',
module='pgAdmin.Browser',
callback='mnu_lock_none',
priority=0,
label=gettext('None'),
checked=True
), MenuItem(
name='mnu_lock_docking',
module='pgAdmin.Browser',
callback='mnu_lock_docking',
priority=1,
label=gettext('Prevent Docking'),
checked=False
), MenuItem(
name='mnu_lock_full',
module='pgAdmin.Browser',
callback='mnu_lock_full',
priority=2,
label=gettext('Full Lock'),
checked=False
)]
)
]
}
def register_preferences(self):
register_browser_preferences(self)
@@ -219,7 +258,11 @@ class BrowserModule(PgAdminModule):
Returns:
list: a list of url endpoints exposed to the client.
"""
return ['browser.index', 'browser.nodes']
return ['browser.index', 'browser.nodes',
'browser.check_master_password',
'browser.set_master_password',
'browser.reset_master_password',
'browser.lock_layout']
blueprint = BrowserModule(MODULE_NAME, __name__)
@@ -478,6 +521,7 @@ class BrowserPluginModule(PgAdminModule):
@blueprint.route("/")
@pgCSRFProtect.exempt
@login_required
def index():
"""Render and process the main browser window."""
@@ -561,6 +605,7 @@ def index():
@blueprint.route("/js/utils.js")
@pgCSRFProtect.exempt
@login_required
def utils():
layout = get_setting('Browser/Layout', default='')
@@ -623,61 +668,37 @@ def utils():
pg_libpq_version=pg_libpq_version,
support_ssh_tunnel=config.SUPPORT_SSH_TUNNEL
),
200, {'Content-Type': 'application/x-javascript'})
200, {'Content-Type': 'application/javascript'})
@blueprint.route("/js/endpoints.js")
@pgCSRFProtect.exempt
def exposed_urls():
return make_response(
render_template('browser/js/endpoints.js'),
200, {'Content-Type': 'application/x-javascript'}
200, {'Content-Type': 'application/javascript'}
)
@blueprint.route("/js/error.js")
@pgCSRFProtect.exempt
@login_required
def error_js():
return make_response(
render_template('browser/js/error.js', _=gettext),
200, {'Content-Type': 'application/x-javascript'})
@blueprint.route("/js/node.js")
@login_required
def node_js():
prefs = Preferences.module('paths')
pg_help_path_pref = prefs.preference('pg_help_path')
pg_help_path = pg_help_path_pref.get()
edbas_help_path_pref = prefs.preference('edbas_help_path')
edbas_help_path = edbas_help_path_pref.get()
return make_response(
render_template('browser/js/node.js',
pg_help_path=pg_help_path,
edbas_help_path=edbas_help_path,
_=gettext
),
200, {'Content-Type': 'application/x-javascript'})
200, {'Content-Type': 'application/javascript'})
@blueprint.route("/js/messages.js")
@pgCSRFProtect.exempt
def messages_js():
return make_response(
render_template('browser/js/messages.js', _=gettext),
200, {'Content-Type': 'application/x-javascript'})
@blueprint.route("/js/collection.js")
@login_required
def collection_js():
return make_response(
render_template('browser/js/collection.js', _=gettext),
200, {'Content-Type': 'application/x-javascript'})
200, {'Content-Type': 'application/javascript'})
@blueprint.route("/browser.css")
@pgCSRFProtect.exempt
@login_required
def browser_css():
"""Render and return CSS snippets from the nodes and modules."""
@@ -703,6 +724,148 @@ def get_nodes():
return make_json_response(data=nodes)
def form_master_password_response(existing=True, present=False, errmsg=None):
content_new = (
gettext("Set Master Password"),
"<br/>".join([
gettext("Please set a master password for pgAdmin."),
gettext("This will be used to secure and later unlock saved "
"passwords and other credentials.")])
)
content_existing = (
gettext("Unlock Saved Passwords"),
"<br/>".join([
gettext("Please enter your master password."),
gettext("This is required to unlock saved passwords and "
"reconnect to the database server(s).")])
)
return make_json_response(data={
'present': present,
'title': content_existing[0] if existing else content_new[0],
'content': render_template(
'browser/master_password.html',
content_text=content_existing[1] if existing else content_new[1],
errmsg=errmsg
),
'reset': existing
})
@blueprint.route("/master_password", endpoint="check_master_password",
methods=["GET"])
def check_master_password():
"""
Checks if the master password is available in the memory
This password will be used to encrypt/decrypt saved server passwords
"""
return make_json_response(data=get_crypt_key()[0])
@blueprint.route("/master_password", endpoint="reset_master_password",
methods=["DELETE"])
def reset_master_password():
"""
Removes the master password and remove all saved passwords
This password will be used to encrypt/decrypt saved server passwords
"""
cleanup_master_password()
return make_json_response(data=get_crypt_key()[0])
@blueprint.route("/master_password", endpoint="set_master_password",
methods=["POST"])
def set_master_password():
"""
Set the master password and store in the memory
This password will be used to encrypt/decrypt saved server passwords
"""
data = None
if hasattr(request.data, 'decode'):
data = request.data.decode('utf-8')
if data != '':
data = json.loads(data)
# Master password is not applicable for server mode
if not config.SERVER_MODE and config.MASTER_PASSWORD_REQUIRED:
if data != '' and data.get('password', '') != '':
# if master pass is set previously
if current_user.masterpass_check is not None:
if not validate_master_password(data.get('password')):
return form_master_password_response(
existing=True,
present=False,
errmsg=gettext("Incorrect master password")
)
# store the master pass in the memory
set_crypt_key(data.get('password'))
if current_user.masterpass_check is None:
# master check is not set, which means the server password
# data is old and is encrypted with old key
# Re-encrypt with new key
from pgadmin.browser.server_groups.servers.utils \
import reencrpyt_server_passwords
reencrpyt_server_passwords(
current_user.id, current_user.password,
data.get('password'))
# set the encrypted sample text with the new
# master pass
set_masterpass_check_text(data.get('password'))
elif not get_crypt_key()[0] and \
current_user.masterpass_check is not None:
return form_master_password_response(
existing=True,
present=False,
)
elif not get_crypt_key()[0]:
return form_master_password_response(
existing=False,
present=False,
)
# if master password is disabled now, but was used once then
# remove all the saved passwords
process_masterpass_disabled()
if config.SERVER_MODE and current_user.masterpass_check is None:
crypt_key = get_crypt_key()[1]
from pgadmin.browser.server_groups.servers.utils \
import reencrpyt_server_passwords
reencrpyt_server_passwords(
current_user.id, current_user.password, crypt_key)
set_masterpass_check_text(crypt_key)
return form_master_password_response(
present=True,
)
@blueprint.route("/lock_layout", endpoint="lock_layout", methods=["PUT"])
def lock_layout():
data = None
if hasattr(request.data, 'decode'):
data = request.data.decode('utf-8')
if data != '':
data = json.loads(data)
blueprint.lock_layout.set(data['value'])
return make_json_response()
# Only register route if SECURITY_CHANGEABLE is set to True
# We can't access app context here so cannot
# use app.config['SECURITY_CHANGEABLE']
@@ -711,6 +874,7 @@ def get_nodes():
if hasattr(config, 'SECURITY_CHANGEABLE') and config.SECURITY_CHANGEABLE:
@blueprint.route("/change_password", endpoint="change_password",
methods=['GET', 'POST'])
@pgCSRFProtect.exempt
@login_required
def change_password():
"""View function which handles a change password request."""
@@ -760,6 +924,15 @@ if hasattr(config, 'SECURITY_CHANGEABLE') and config.SECURITY_CHANGEABLE:
if request.json is None and not has_error:
after_this_request(_commit)
do_flash(*get_message('PASSWORD_CHANGE'))
old_key = get_crypt_key()[1]
set_crypt_key(form.new_password.data, False)
from pgadmin.browser.server_groups.servers.utils \
import reencrpyt_server_passwords
reencrpyt_server_passwords(
current_user.id, old_key, form.new_password.data)
return redirect(get_url(_security.post_change_view) or
get_url(_security.post_login_view))
@@ -794,6 +967,7 @@ if hasattr(config, 'SECURITY_RECOVERABLE') and config.SECURITY_RECOVERABLE:
@blueprint.route("/reset_password", endpoint="forgot_password",
methods=['GET', 'POST'])
@pgCSRFProtect.exempt
@anonymous_user_required
def forgot_password():
"""View function that handles a forgotten password request."""
@@ -860,10 +1034,10 @@ if hasattr(config, 'SECURITY_RECOVERABLE') and config.SECURITY_RECOVERABLE:
methods=['GET', 'POST'],
endpoint='reset_password'
)
@pgCSRFProtect.exempt
@anonymous_user_required
def reset_password(token):
"""View function that handles a reset password request."""
expired, invalid, user = reset_password_token_status(token)
if invalid:
@@ -8,6 +8,12 @@
##########################################################################
from flask_babelex import gettext
LOCK_LAYOUT_LEVEL = {
'PREVENT_DOCKING': 'docking',
'FULL': 'full',
'NONE': 'none'
}
def register_browser_preferences(self):
self.show_system_objects = self.preference.register(
@@ -58,6 +64,21 @@ def register_browser_preferences(self):
)
)
self.lock_layout = self.preference.register(
'display', 'lock_layout',
gettext('Lock Layout'), 'radioModern', LOCK_LAYOUT_LEVEL['NONE'],
category_label=gettext('Display'), options=[
{'label': gettext('None'), 'value': LOCK_LAYOUT_LEVEL['NONE']},
{'label': gettext('Prevent Docking'),
'value': LOCK_LAYOUT_LEVEL['PREVENT_DOCKING']},
{'label': gettext('Full Lock'),
'value': LOCK_LAYOUT_LEVEL['FULL']},
],
help_str=gettext(
'Lock the UI layout at different levels'
)
)
self.table_row_count_threshold = self.preference.register(
'properties', 'table_row_count_threshold',
gettext("Count rows if estimated less than"), 'integer', 2000,
@@ -26,6 +26,8 @@ import config
from config import PG_DEFAULT_DRIVER
from pgadmin.model import db, Server, ServerGroup, User
from pgadmin.utils.driver import get_driver
from pgadmin.utils.master_password import get_crypt_key
from pgadmin.utils.exception import CryptKeyMissing
def has_any(data, keys):
@@ -117,9 +119,16 @@ class ServerModule(sg.ServerGroupPluginModule):
driver = get_driver(PG_DEFAULT_DRIVER)
for server in servers:
manager = driver.connection_manager(server.id)
conn = manager.connection()
connected = conn.connected()
connected = False
manager = None
try:
manager = driver.connection_manager(server.id)
conn = manager.connection()
connected = conn.connected()
except CryptKeyMissing:
# show the nodes at least even if not able to connect.
pass
in_recovery = None
wal_paused = None
@@ -723,6 +732,11 @@ class ServerNode(PGChildNodeView):
request.data, encoding='utf-8'
)
# Get enc key
crypt_key_present, crypt_key = get_crypt_key()
if not crypt_key_present:
raise CryptKeyMissing
# Some fields can be provided with service file so they are optional
if 'service' in data and not data['service']:
required_args.extend([
@@ -807,7 +821,7 @@ class ServerNode(PGChildNodeView):
# login with password
have_password = True
password = data['password']
password = encrypt(password, current_user.password)
password = encrypt(password, crypt_key)
elif 'passfile' in data and data["passfile"] != '':
passfile = data['passfile']
setattr(server, 'passfile', passfile)
@@ -817,7 +831,7 @@ class ServerNode(PGChildNodeView):
have_tunnel_password = True
tunnel_password = data['tunnel_password']
tunnel_password = \
encrypt(tunnel_password, current_user.password)
encrypt(tunnel_password, crypt_key)
status, errmsg = conn.connect(
password=password,
@@ -930,7 +944,7 @@ class ServerNode(PGChildNodeView):
"servers/supported_servers.js",
server_types=ServerType.types()
),
200, {'Content-Type': 'application/x-javascript'}
200, {'Content-Type': 'application/javascript'}
)
def connect_status(self, gid, sid):
@@ -998,6 +1012,11 @@ class ServerNode(PGChildNodeView):
manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(sid)
conn = manager.connection()
# Get enc key
crypt_key_present, crypt_key = get_crypt_key()
if not crypt_key_present:
raise CryptKeyMissing
# If server using SSH Tunnel
if server.use_ssh_tunnel:
if 'tunnel_password' not in data:
@@ -1014,12 +1033,12 @@ class ServerNode(PGChildNodeView):
# Encrypt the password before saving with user's login
# password key.
try:
tunnel_password = encrypt(tunnel_password, user.password) \
tunnel_password = encrypt(tunnel_password, crypt_key) \
if tunnel_password is not None else \
server.tunnel_password
except Exception as e:
current_app.logger.exception(e)
return internal_server_error(errormsg=e.message)
return internal_server_error(errormsg=str(e))
if 'password' not in data:
conn_passwd = getattr(conn, 'password', None)
@@ -1038,11 +1057,11 @@ class ServerNode(PGChildNodeView):
# Encrypt the password before saving with user's login
# password key.
try:
password = encrypt(password, user.password) \
password = encrypt(password, crypt_key) \
if password is not None else server.password
except Exception as e:
current_app.logger.exception(e)
return internal_server_error(errormsg=e.message)
return internal_server_error(errormsg=str(e))
# Check do we need to prompt for the database server or ssh tunnel
# password or both. Return the password template in case password is
@@ -1235,6 +1254,7 @@ class ServerNode(PGChildNodeView):
"""
try:
data = json.loads(request.form['data'], encoding='utf-8')
crypt_key = get_crypt_key()[1]
# Fetch Server Details
server = Server.query.filter_by(id=sid).first()
@@ -1292,7 +1312,7 @@ class ServerNode(PGChildNodeView):
# Check against old password only if no pgpass file
if not is_passfile:
decrypted_password = decrypt(manager.password, user.password)
decrypted_password = decrypt(manager.password, crypt_key)
if isinstance(decrypted_password, bytes):
decrypted_password = decrypted_password.decode()
@@ -1328,7 +1348,7 @@ class ServerNode(PGChildNodeView):
# Store password in sqlite only if no pgpass file
if not is_passfile:
password = encrypt(data['newPassword'], user.password)
password = encrypt(data['newPassword'], crypt_key)
# Check if old password was stored in pgadmin4 sqlite database.
# If yes then update that password.
if server.password is not None and config.ALLOW_SAVE_PASSWORD:
@@ -1472,6 +1492,7 @@ class ServerNode(PGChildNodeView):
def get_response_for_password(self, server, status, prompt_password=False,
prompt_tunnel_password=False, errmsg=None):
if server.use_ssh_tunnel:
return make_json_response(
success=0,
@@ -1498,7 +1519,7 @@ class ServerNode(PGChildNodeView):
server_label=server.name,
username=server.username,
errmsg=errmsg,
_=gettext
_=gettext,
)
)
@@ -166,7 +166,6 @@ class DatabaseView(PGChildNodeView):
def wrap(f):
@wraps(f)
def wrapped(self, *args, **kwargs):
self.manager = get_driver(
PG_DEFAULT_DRIVER
).connection_manager(
@@ -805,7 +804,12 @@ class DatabaseView(PGChildNodeView):
data = {}
for k, v in request.args.items():
try:
data[k] = json.loads(v, encoding='utf-8')
# comments should be taken as is because if user enters a
# json comment it is parsed by loads which should not happen
if k in ('comments',):
data[k] = v
else:
data[k] = json.loads(v, encoding='utf-8')
except ValueError:
data[k] = v
status, res = self.get_sql(gid, sid, data, did)
@@ -208,7 +208,7 @@ class CastView(PGChildNodeView):
).connection_manager(kwargs['sid'])
self.conn = self.manager.connection(did=kwargs['did'])
# Set template path for the SQL scripts
self.template_path = 'cast/sql/#{0}#'.format(self.manager.version)
self.template_path = 'casts/sql/#{0}#'.format(self.manager.version)
return f(*args, **kwargs)
@@ -0,0 +1,9 @@
-- Cast: money -> bigint
-- DROP CAST (money AS bigint);
CREATE CAST (money AS bigint)
WITHOUT FUNCTION
AS IMPLICIT;
COMMENT ON CAST (money AS bigint) IS 'Cast from money to bigint';
@@ -0,0 +1,7 @@
-- Cast: money -> bigint
-- DROP CAST (money AS bigint);
CREATE CAST (money AS bigint)
WITHOUT FUNCTION
AS IMPLICIT;
@@ -0,0 +1,68 @@
{
"scenarios": [
{
"type": "create",
"name": "Create IMPLICIT Cast",
"endpoint": "NODE-cast.obj",
"sql_endpoint": "NODE-cast.sql_id",
"data": {
"castcontext": "IMPLICIT",
"encoding": "UTF8",
"name": "money->bigint",
"srctyp": "money",
"trgtyp": "bigint"
},
"expected_sql_file": "create_implicit_cast.sql"
},
{
"type": "alter",
"name": "Alter IMPLICIT Cast",
"endpoint": "NODE-cast.obj_id",
"sql_endpoint": "NODE-cast.sql_id",
"data": {
"description": "Cast from money to bigint"
},
"expected_sql_file": "alter_implicit_cast.sql"
},
{
"type": "delete",
"name": "Drop IMPLICIT Cast",
"endpoint": "NODE-cast.delete_id",
"data": {
"name": "money->bigint"
}
},
{
"type": "create",
"name":"Create EXPLICIT Cast",
"endpoint": "NODE-cast.obj",
"sql_endpoint": "NODE-cast.sql_id",
"data": {
"castcontext": "EXPLICIT",
"encoding": "UTF8",
"name": "money->bigint",
"srctyp": "money",
"trgtyp": "bigint"
},
"expected_sql": "-- Cast: money -> bigint\n\n-- DROP CAST (money AS bigint);\n\nCREATE CAST (money AS bigint)\n\tWITHOUT FUNCTION;"
},
{
"type": "alter",
"name": "Alter EXPLICIT Cast",
"endpoint": "NODE-cast.obj_id",
"sql_endpoint": "NODE-cast.sql_id",
"data": {
"description": "Cast from money to bigint"
},
"expected_sql": "-- Cast: money -> bigint\n\n-- DROP CAST (money AS bigint);\n\nCREATE CAST (money AS bigint)\n\tWITHOUT FUNCTION;\n\nCOMMENT ON CAST (money AS bigint) IS 'Cast from money to bigint';"
},
{
"type": "delete",
"name": "Drop EXPLICIT Cast",
"endpoint": "NODE-cast.delete_id",
"data": {
"name": "money->bigint"
}
}
]
}
@@ -555,7 +555,12 @@ class ForeignDataWrapperView(PGChildNodeView):
data = {}
for k, v in request.args.items():
try:
data[k] = json.loads(v, encoding='utf-8')
# comments should be taken as is because if user enters a
# json comment it is parsed by loads which should not happen
if k in ('description',):
data[k] = v
else:
data[k] = json.loads(v, encoding='utf-8')
except ValueError:
data[k] = v
try:
@@ -116,10 +116,6 @@ class ForeignServerView(PGChildNodeView):
* __init__(**kwargs)
- Method is used to initialize the ForeignServerView and it's base view.
* module_js()
- This property defines (if javascript) exists for this node.
Override this property for your own logic
* check_precondition()
- This function will behave as a decorator which will checks
database connection before running view, it will also attaches
@@ -192,23 +188,9 @@ class ForeignServerView(PGChildNodeView):
'msql': [{'get': 'msql'}, {'get': 'msql'}],
'stats': [{'get': 'statistics'}],
'dependency': [{'get': 'dependencies'}],
'dependent': [{'get': 'dependents'}],
'module.js': [{}, {}, {'get': 'module_js'}]
'dependent': [{'get': 'dependents'}]
})
def module_js(self):
"""
This property defines (if javascript) exists for this node.
Override this property for your own logic.
"""
return make_response(
render_template(
"foreign_servers/js/foreign_servers.js",
_=gettext
),
200, {'Content-Type': 'application/x-javascript'}
)
def check_precondition(f):
"""
This function will behave as a decorator which will checks
@@ -578,7 +560,12 @@ class ForeignServerView(PGChildNodeView):
data = {}
for k, v in request.args.items():
try:
data[k] = json.loads(v, encoding='utf-8')
# comments should be taken as is because if user enters a
# json comment it is parsed by loads which should not happen
if k in ('description',):
data[k] = v
else:
data[k] = json.loads(v, encoding='utf-8')
except ValueError:
data[k] = v
try:
@@ -132,10 +132,6 @@ class UserMappingView(PGChildNodeView):
* __init__(**kwargs)
- Method is used to initialize the UserMappingView and it's base view.
* module_js()
- This property defines (if javascript) exists for this node.
Override this property for your own logic
* check_precondition()
- This function will behave as a decorator which will checks
database connection before running view, it will also attaches
@@ -209,23 +205,9 @@ class UserMappingView(PGChildNodeView):
'msql': [{'get': 'msql'}, {'get': 'msql'}],
'stats': [{'get': 'statistics'}],
'dependency': [{'get': 'dependencies'}],
'dependent': [{'get': 'dependents'}],
'module.js': [{}, {}, {'get': 'module_js'}]
'dependent': [{'get': 'dependents'}]
})
def module_js(self):
"""
This property defines (if javascript) exists for this node.
Override this property for your own logic.
"""
return make_response(
render_template(
"user_mappings/js/user_mappings.js",
_=gettext
),
200, {'Content-Type': 'application/x-javascript'}
)
def check_precondition(f):
"""
This function will behave as a decorator which will checks
@@ -558,7 +558,12 @@ class LanguageView(PGChildNodeView):
data = {}
for k, v in request.args.items():
try:
data[k] = json.loads(v, encoding='utf-8')
# comments should be taken as is because if user enters a
# json comment it is parsed by loads which should not happen
if k in ('description',):
data[k] = v
else:
data[k] = json.loads(v, encoding='utf-8')
except ValueError:
data[k] = v
try:
@@ -237,7 +237,7 @@ class SchemaView(PGChildNodeView):
self.manager = None
self.conn = None
self.template_path = None
self.template_initial = 'schema'
self.template_initial = 'schemas'
@staticmethod
def ppas_template_path(ver):
@@ -724,7 +724,12 @@ It may have been removed by another user.
data = dict()
for k, v in request.args.items():
try:
data[k] = json.loads(v, encoding='utf-8')
# comments should be taken as is because if user enters a
# json comment it is parsed by loads which should not happen
if k in ('description',):
data[k] = v
else:
data[k] = json.loads(v, encoding='utf-8')
except ValueError:
data[k] = v
@@ -128,8 +128,7 @@ class CatalogObjectView(PGChildNodeView):
'nodes': [{'get': 'node'}, {'get': 'nodes'}],
'sql': [{'get': 'sql'}],
'dependency': [{'get': 'dependencies'}],
'dependent': [{'get': 'dependents'}],
'module.js': [{}, {}, {'get': 'module_js'}]
'dependent': [{'get': 'dependents'}]
})
def check_precondition(f):
@@ -155,8 +155,7 @@ class CatalogObjectColumnsView(PGChildNodeView):
'nodes': [{'get': 'node'}, {'get': 'nodes'}],
'sql': [{'get': 'sql'}],
'dependency': [{'get': 'dependencies'}],
'dependent': [{'get': 'dependents'}],
'module.js': [{}, {}, {'get': 'module_js'}]
'dependent': [{'get': 'dependents'}]
})
def check_precondition(f):
@@ -171,7 +171,6 @@ class CollationView(PGChildNodeView):
'stats': [{'get': 'statistics'}],
'dependency': [{'get': 'dependencies'}],
'dependent': [{'get': 'dependents'}],
'module.js': [{}, {}, {'get': 'module_js'}],
'get_collations': [{'get': 'get_collation'},
{'get': 'get_collation'}]
})
@@ -193,7 +192,7 @@ class CollationView(PGChildNodeView):
self.conn = self.manager.connection(did=kwargs['did'])
# Set the template path for the SQL scripts
self.template_path = compile_template_path(
'collation/sql/',
'collations/sql/',
self.manager.server_type,
self.manager.version
)
@@ -602,7 +601,12 @@ class CollationView(PGChildNodeView):
data = dict()
for k, v in request.args.items():
try:
data[k] = json.loads(v, encoding='utf-8')
# comments should be taken as is because if user enters a
# json comment it is parsed by loads which should not happen
if k in ('description',):
data[k] = v
else:
data[k] = json.loads(v, encoding='utf-8')
except ValueError:
data[k] = v
@@ -11,6 +11,5 @@ from pgadmin.utils.route import BaseTestGenerator
class CollationTestGenerator(BaseTestGenerator):
def generate_tests(self):
def runTest(self):
return
@@ -95,9 +95,6 @@ class DomainView(PGChildNodeView, DataTypeReader):
- Works as a decorator.
Validating request on the request of create, update and modified SQL.
* module_js():
- Load JS file (domains.js) for this module.
* check_precondition(f):
- Works as a decorator.
- Checks database connection status.
@@ -168,7 +165,6 @@ class DomainView(PGChildNodeView, DataTypeReader):
'stats': [{'get': 'statistics'}],
'dependency': [{'get': 'dependencies'}],
'dependent': [{'get': 'dependents'}],
'module.js': [{}, {}, {'get': 'module_js'}],
'get_types': [{'get': 'types'}, {'get': 'types'}],
'get_collations': [
{'get': 'get_collations'},
@@ -246,18 +242,6 @@ class DomainView(PGChildNodeView, DataTypeReader):
return wrap
def module_js(self):
"""
Load JS file (domains.js) for this module.
"""
return make_response(
render_template(
"domains/js/domains.js",
_=gettext
),
200, {'Content-Type': 'application/x-javascript'}
)
def check_precondition(f):
"""
Works as a decorator.
@@ -109,9 +109,6 @@ class ForeignTableView(PGChildNodeView, DataTypeReader):
- Works as a decorator.
Validating request on the request of create, update and modified SQL.
* module_js():
- Overrides this property to define javascript for Foreign Table node.
* check_precondition(f):
- Works as a decorator.
- Checks database connection status.
@@ -204,7 +201,6 @@ class ForeignTableView(PGChildNodeView, DataTypeReader):
'stats': [{'get': 'statistics'}],
'dependency': [{'get': 'dependencies'}],
'dependent': [{'get': 'dependents'}],
'module.js': [{}, {}, {'get': 'module_js'}],
'get_collations': [
{'get': 'get_collations'},
{'get': 'get_collations'}
@@ -319,18 +315,6 @@ class ForeignTableView(PGChildNodeView, DataTypeReader):
return wrap
def module_js(self):
"""
Load JS file (foreign_tables.js) for this module.
"""
return make_response(
render_template(
"foreign_tables/js/foreign_tables.js",
_=gettext
),
200, {'Content-Type': 'application/x-javascript'}
)
def check_precondition(f):
"""
Works as a decorator.
@@ -1208,7 +1192,9 @@ class ForeignTableView(PGChildNodeView, DataTypeReader):
if db_variables is not None:
for row in db_variables:
var_name, var_value = row.split("=")
# The value may contain equals in string, split on
# first equals only
var_name, var_value = row.split("=", 1)
var_dict = {'option': var_name, 'value': var_value}
@@ -0,0 +1,8 @@
SELECT
oid as conoid, conname, contype, pg_get_constraintdef(oid, true) as consrc,
connoinherit, convalidated, conislocal
FROM
pg_constraint
WHERE
conrelid={{foid}}::oid
ORDER by conname;
@@ -108,10 +108,6 @@ class FtsConfigurationView(PGChildNodeView):
- Method is used to initialize the FtsConfigurationView and it's base
view.
* module_js()
- This property defines (if javascript) exists for this node.
Override this property for your own logic
* check_precondition()
- This function will behave as a decorator which will checks
database connection before running view, it will also attaches
@@ -200,7 +196,6 @@ class FtsConfigurationView(PGChildNodeView):
'stats': [{'get': 'statistics'}],
'dependency': [{'get': 'dependencies'}],
'dependent': [{'get': 'dependents'}],
'module.js': [{}, {}, {'get': 'module_js'}],
'parsers': [{'get': 'parsers'},
{'get': 'parsers'}],
'copyConfig': [{'get': 'copyConfig'},
@@ -215,18 +210,6 @@ class FtsConfigurationView(PGChildNodeView):
self.manager = None
super(FtsConfigurationView, self).__init__(**kwargs)
def module_js(self):
"""
Load JS file (fts_configuration.js) for this module.
"""
return make_response(
render_template(
"fts_configuration/js/fts_configuration.js",
_=_
),
200, {'Content-Type': 'application/x-javascript'}
)
def check_precondition(f):
"""
This function will behave as a decorator which will checks
@@ -242,7 +225,7 @@ class FtsConfigurationView(PGChildNodeView):
kwargs['sid'])
self.conn = self.manager.connection(did=kwargs['did'])
# Set the template path for the SQL scripts
self.template_path = 'fts_configuration/sql/#{0}#'.format(
self.template_path = 'fts_configurations/sql/#{0}#'.format(
self.manager.version)
return f(*args, **kwargs)
@@ -612,7 +595,12 @@ class FtsConfigurationView(PGChildNodeView):
data = {}
for k, v in request.args.items():
try:
data[k] = json.loads(v, encoding='utf-8')
# comments should be taken as is because if user enters a
# json comment it is parsed by loads which should not happen
if k in ('description',):
data[k] = v
else:
data[k] = json.loads(v, encoding='utf-8')
except ValueError:
data[k] = v
Loaded 100 of 989 files, more files were not shown because too many files have changed in this diff. Show more