Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ab04b30726 | ||
|
|
dc4f59e664 | ||
|
|
8738f6dd98 | ||
|
|
039766b492 | ||
|
|
2da970a26c | ||
|
|
86e1f33231 | ||
|
|
702fbac1c0 | ||
|
|
7483ddf2b2 | ||
|
|
78b041465e | ||
|
|
5e3aa305fd | ||
|
|
703478c13d | ||
|
|
8d53c10643 | ||
|
|
025c98ced8 | ||
|
|
8e214ca8fb | ||
|
|
23265061b2 | ||
|
|
9d985d3d8f | ||
|
|
03477d407e | ||
|
|
2dd88e5a4e | ||
|
|
2452d90300 | ||
|
|
508f97b08e | ||
|
|
3f67f512ec | ||
|
|
fdc3028124 | ||
|
|
3a3eea0320 | ||
|
|
d95a6f2af7 | ||
|
|
a3d3c74e67 | ||
|
|
c2db647379 | ||
|
|
6cc3423cbe | ||
|
|
eb658a75ab | ||
|
|
b2205fc6e1 | ||
|
|
5768ade198 | ||
|
|
b0727cc532 | ||
|
|
9e8af67202 | ||
|
|
69d0fbe419 | ||
|
|
7b050a4c31 | ||
|
|
96085213fe | ||
|
|
2ce2b457bf | ||
|
|
a2171aa27b | ||
|
|
ea3d71c0df | ||
|
|
b154be24ec | ||
|
|
3590c9172c | ||
|
|
e981868246 | ||
|
|
5ee8045916 | ||
|
|
36086722b3 | ||
|
|
8edd5946e5 | ||
|
|
a0b2a28ee2 | ||
|
|
39a845ad31 | ||
|
|
669bdc7e38 | ||
|
|
5d4c073730 | ||
|
|
48ca83f31d | ||
|
|
fff4060b31 | ||
|
|
9fdda038a9 | ||
|
|
ef67409d61 | ||
|
|
d90472014d | ||
|
|
a2b67b933e | ||
|
|
b98e881d84 | ||
|
|
e978621597 | ||
|
|
5fe52b9cfe | ||
|
|
5c6d00d545 | ||
|
|
6429a5b31a | ||
|
|
e68c8305a2 | ||
|
|
e095d382b3 | ||
|
|
25ada15546 | ||
|
|
5581f0909a | ||
|
|
462b86df8d | ||
|
|
6645625e6b | ||
|
|
cfb68d73a0 | ||
|
|
9574f43f87 | ||
|
|
a53be65ab0 | ||
|
|
cc989c5c08 | ||
|
|
313224e6f5 | ||
|
|
2adb29ffc0 | ||
|
|
80ccd62d38 | ||
|
|
b81ff45d34 | ||
|
|
81b78dd2b2 | ||
|
|
e2302a6c9b | ||
|
|
2486b79450 | ||
|
|
0b52ef6eb0 | ||
|
|
a533620684 | ||
|
|
09d8d0f362 | ||
|
|
4e067835c3 | ||
|
|
37278f2cd3 | ||
|
|
16d2a3096a | ||
|
|
083509eb97 | ||
|
|
0c154deeec | ||
|
|
082c9707c0 | ||
|
|
15798ee168 | ||
|
|
e37b7eae3f | ||
|
|
ae2d588f46 | ||
|
|
12d93d0805 | ||
|
|
2549688bdf | ||
|
|
c2ed799113 | ||
|
|
71526ac79f | ||
|
|
3d685ef96c | ||
|
|
2fdde6218a | ||
|
|
09693d14d1 | ||
|
|
dcaeb20e29 | ||
|
|
d93ec3bb91 | ||
|
|
f29852f6f0 | ||
|
|
7d5fc84747 | ||
|
|
4a3a5174b2 | ||
|
|
e0d094b2aa | ||
|
|
e3190b86ab | ||
|
|
b9b0a573e5 | ||
|
|
0dbfbd8dfc | ||
|
|
6e42d9113b | ||
|
|
460fb7ec29 | ||
|
|
c86a2b643a | ||
|
|
b2042f48cd | ||
|
|
d276f37e87 | ||
|
|
7c88ee7cff | ||
|
|
93ddc4a5ba | ||
|
|
9f12747d9b | ||
|
|
5a086a9173 | ||
|
|
e1067ffe67 | ||
|
|
d5f537aae4 | ||
|
|
5b12483416 | ||
|
|
07eb541806 | ||
|
|
065a3aa2f5 | ||
|
|
2aa2d79de2 | ||
|
|
a0deab901d | ||
|
|
4bc4ca1ba9 | ||
|
|
ac8e8961ce | ||
|
|
2c51925638 | ||
|
|
e0eac875b6 | ||
|
|
9ac08c263b | ||
|
|
658a2de619 | ||
|
|
a487a51135 | ||
|
|
2d58f60a53 | ||
|
|
faa49687be | ||
|
|
3ddf941cd7 | ||
|
|
37dece2cd8 | ||
|
|
1ead82f9b8 | ||
|
|
48dbf5a3dc | ||
|
|
0a95550fc0 | ||
|
|
1c2b312d49 | ||
|
|
62e08d2b7e | ||
|
|
f34adaca41 | ||
|
|
aaf5d64fe0 | ||
|
|
3f5fb4b61c | ||
|
|
f9254126e5 | ||
|
|
4676d7ef02 | ||
|
|
42b8dbb58f | ||
|
|
b7c0914f33 | ||
|
|
c8a2057410 | ||
|
|
64e42bebe2 | ||
|
|
7275ce906e | ||
|
|
7ed97eeec4 | ||
|
|
0bb40de1c4 | ||
|
|
bd7808a104 | ||
|
|
4842d589a6 | ||
|
|
11c541adc6 | ||
|
|
c746cfddfe | ||
|
|
2b7f8d8298 | ||
|
|
fe6f9aae61 | ||
|
|
8bc07c45f5 | ||
|
|
058afad9eb | ||
|
|
1e6eca1787 | ||
|
|
89b0028684 | ||
|
|
d80087f6d5 | ||
|
|
b0df4d3604 | ||
|
|
c32ff3a7ee | ||
|
|
4c55044440 | ||
|
|
b13627398b | ||
|
|
b30ec71098 | ||
|
|
649ca2eeac | ||
|
|
98546e1876 | ||
|
|
7e79814cb0 | ||
|
|
ac403d0dfa | ||
|
|
72f3730c34 | ||
|
|
aa9a4c30d3 | ||
|
|
3a2145e5fa | ||
|
|
333a22496c | ||
|
|
488dc1849d | ||
|
|
e718be72e3 | ||
|
|
9dd1bae3c7 | ||
|
|
718ac02806 | ||
|
|
7bab200e4d | ||
|
|
f5ef022ef5 | ||
|
|
5a302684f7 | ||
|
|
7d6f077cf8 | ||
|
|
b853bda2a2 | ||
|
|
abdd3190fe | ||
|
|
5894001eb2 | ||
|
|
8ae8fea6d2 |
No files matched your search
@@ -23,19 +23,18 @@ Python Dependencies
|
||||
|
||||
Name Version Licence URL
|
||||
---- ------- ------- ---
|
||||
cheroot 8.5.2 UNKNOWN https://cheroot.cherrypy.org
|
||||
Flask 1.1.2 BSD-3-Clause https://palletsprojects.com/p/flask/
|
||||
Flask 1.1.4 BSD-3-Clause https://palletsprojects.com/p/flask/
|
||||
Flask-Gravatar 0.5.0 BSD https://github.com/zzzsochi/Flask-Gravatar/
|
||||
Flask-Login 0.5.0 MIT https://github.com/maxcountryman/flask-login
|
||||
Flask-Mail 0.9.1 BSD https://github.com/rduplain/flask-mail
|
||||
Flask-Migrate 2.6.0 MIT http://github.com/miguelgrinberg/flask-migrate/
|
||||
Flask-SQLAlchemy 2.4.4 BSD-3-Clause https://github.com/pallets/flask-sqlalchemy
|
||||
Flask-Migrate 2.7.0 MIT http://github.com/miguelgrinberg/flask-migrate/
|
||||
Flask-SQLAlchemy 2.5.1 BSD-3-Clause https://github.com/pallets/flask-sqlalchemy
|
||||
Flask-WTF 0.14.3 BSD https://github.com/lepture/flask-wtf
|
||||
Flask-Compress 1.8.0 MIT https://github.com/colour-science/flask-compress
|
||||
Flask-Compress 1.9.0 MIT https://github.com/colour-science/flask-compress
|
||||
passlib 1.7.4 BSD https://passlib.readthedocs.io
|
||||
pytz 2021.1 MIT http://pythonhosted.org/pytz
|
||||
simplejson 3.17.2 MIT License https://github.com/simplejson/simplejson
|
||||
six 1.15.0 MIT https://github.com/benjaminp/six
|
||||
six 1.16.0 MIT https://github.com/benjaminp/six
|
||||
speaklater3 1.4 UNKNOWN https://github.com/ThomasWaldmann/speaklater
|
||||
sqlparse 0.4.1 BSD-3-Clause https://github.com/andialbrecht/sqlparse
|
||||
WTForms 2.3.3 BSD-3-Clause https://wtforms.readthedocs.io/
|
||||
@@ -43,16 +42,27 @@ Flask-Paranoid 0.2.0
|
||||
psutil 5.8.0 BSD https://github.com/giampaolo/psutil
|
||||
psycopg2 2.8.6 LGPL with exceptions https://psycopg.org/
|
||||
python-dateutil 2.8.1 Dual License https://dateutil.readthedocs.io
|
||||
SQLAlchemy 1.3.23 MIT http://www.sqlalchemy.org
|
||||
Flask-Security-Too 3.4.5 MIT https://github.com/Flask-Middleware/flask-security
|
||||
SQLAlchemy 1.3.24 MIT http://www.sqlalchemy.org
|
||||
itsdangerous 1.1.0 BSD https://palletsprojects.com/p/itsdangerous/
|
||||
Flask-Security-Too 4.0.1 MIT https://github.com/Flask-Middleware/flask-security
|
||||
bcrypt 3.2.0 Apache License, Version 2.0 https://github.com/pyca/bcrypt/
|
||||
cryptography 3.3.1 BSD or Apache License, Version 2.0 https://github.com/pyca/cryptography
|
||||
cryptography 3.4.7 BSD or Apache License, Version 2.0 https://github.com/pyca/cryptography
|
||||
sshtunnel 0.4.0 MIT https://github.com/pahaz/sshtunnel
|
||||
ldap3 2.9 LGPL v3 https://github.com/cannatag/ldap3
|
||||
Flask-BabelEx 0.9.4 BSD http://github.com/mrjoes/flask-babelex
|
||||
gssapi 1.6.12 LICENSE.txt https://github.com/pythongssapi/python-gssapi
|
||||
Flask-SocketIO 5.0.3 MIT http://github.com/miguelgrinberg/Flask-SocketIO/
|
||||
eventlet 0.31.0 UNKNOWN http://eventlet.net
|
||||
httpagentparser 1.9.1 http://www.opensource.org/licenses/mit-license.php http://shon.github.com/httpagentparser
|
||||
user-agents 2.2.0 MIT https://github.com/selwin/python-user-agents
|
||||
pywinpty 1.1.1 Unknown Unknown
|
||||
Authlib 0.15.4 BSD-3-Clause https://authlib.org/
|
||||
requests 2.25.1 Apache 2.0 https://requests.readthedocs.io
|
||||
|
||||
28 dependencies listed.
|
||||
NOTE: This report was generated using Python 3.9. Full information may not be
|
||||
shown for Python modules that are not required with this version.
|
||||
|
||||
35 dependencies listed.
|
||||
|
||||
Javascript Dependencies
|
||||
=======================
|
||||
@@ -60,50 +70,52 @@ Javascript Dependencies
|
||||
Name Version Licence URL
|
||||
---- ------- ------- ---
|
||||
@babel/code-frame 7.12.13 MIT https://github.com/babel/babel.git
|
||||
@babel/core 7.12.13 MIT https://github.com/babel/babel.git
|
||||
@babel/generator 7.12.15 MIT https://github.com/babel/babel.git
|
||||
@babel/compat-data 7.14.0 MIT https://github.com/babel/babel.git
|
||||
@babel/core 7.14.3 MIT https://github.com/babel/babel.git
|
||||
@babel/generator 7.14.3 MIT https://github.com/babel/babel.git
|
||||
@babel/helper-annotate-as-pure 7.12.13 MIT https://github.com/babel/babel.git
|
||||
@babel/helper-create-class-features-plugin 7.12.13 MIT https://github.com/babel/babel.git
|
||||
@babel/helper-function-name 7.12.13 MIT https://github.com/babel/babel.git
|
||||
@babel/helper-compilation-targets 7.13.16 MIT https://github.com/babel/babel.git
|
||||
@babel/helper-create-class-features-plugin 7.14.3 MIT https://github.com/babel/babel.git
|
||||
@babel/helper-function-name 7.14.2 MIT https://github.com/babel/babel.git
|
||||
@babel/helper-get-function-arity 7.12.13 MIT https://github.com/babel/babel.git
|
||||
@babel/helper-member-expression-to-functions 7.12.13 MIT https://github.com/babel/babel.git
|
||||
@babel/helper-module-imports 7.12.13 MIT https://github.com/babel/babel.git
|
||||
@babel/helper-module-transforms 7.12.13 MIT https://github.com/babel/babel.git
|
||||
@babel/helper-member-expression-to-functions 7.13.12 MIT https://github.com/babel/babel.git
|
||||
@babel/helper-module-imports 7.13.12 MIT https://github.com/babel/babel.git
|
||||
@babel/helper-module-transforms 7.14.2 MIT https://github.com/babel/babel.git
|
||||
@babel/helper-optimise-call-expression 7.12.13 MIT https://github.com/babel/babel.git
|
||||
@babel/helper-plugin-utils 7.12.13 MIT https://github.com/babel/babel.git
|
||||
@babel/helper-replace-supers 7.12.13 MIT https://github.com/babel/babel.git
|
||||
@babel/helper-simple-access 7.12.13 MIT https://github.com/babel/babel.git
|
||||
@babel/helper-plugin-utils 7.13.0 MIT https://github.com/babel/babel.git
|
||||
@babel/helper-replace-supers 7.14.3 MIT https://github.com/babel/babel.git
|
||||
@babel/helper-simple-access 7.13.12 MIT https://github.com/babel/babel.git
|
||||
@babel/helper-split-export-declaration 7.12.13 MIT https://github.com/babel/babel.git
|
||||
@babel/helper-validator-identifier 7.12.11 MIT https://github.com/babel/babel.git
|
||||
@babel/helpers 7.12.13 MIT https://github.com/babel/babel.git
|
||||
@babel/highlight 7.12.13 MIT https://github.com/babel/babel.git
|
||||
@babel/parser 7.12.15 MIT https://github.com/babel/babel.git
|
||||
@babel/plugin-proposal-class-properties 7.12.13 MIT https://github.com/babel/babel.git
|
||||
@babel/helper-validator-identifier 7.14.0 MIT https://github.com/babel/babel.git
|
||||
@babel/helper-validator-option 7.12.17 MIT https://github.com/babel/babel.git
|
||||
@babel/helpers 7.14.0 MIT https://github.com/babel/babel.git
|
||||
@babel/highlight 7.14.0 MIT https://github.com/babel/babel.git
|
||||
@babel/parser 7.14.3 MIT https://github.com/babel/babel.git
|
||||
@babel/plugin-proposal-class-properties 7.13.0 MIT https://github.com/babel/babel.git
|
||||
@babel/plugin-syntax-jsx 7.12.13 MIT https://github.com/babel/babel.git
|
||||
@babel/plugin-transform-react-display-name 7.12.13 MIT https://github.com/babel/babel.git
|
||||
@babel/plugin-transform-react-jsx 7.12.13 MIT https://github.com/babel/babel.git
|
||||
@babel/plugin-transform-react-jsx-development 7.12.12 MIT https://github.com/babel/babel.git
|
||||
@babel/plugin-transform-react-display-name 7.14.2 MIT https://github.com/babel/babel.git
|
||||
@babel/plugin-transform-react-jsx 7.14.3 MIT https://github.com/babel/babel.git
|
||||
@babel/plugin-transform-react-jsx-development 7.12.17 MIT https://github.com/babel/babel.git
|
||||
@babel/plugin-transform-react-pure-annotations 7.12.1 MIT https://github.com/babel/babel.git
|
||||
@babel/preset-react 7.12.13 MIT https://github.com/babel/babel.git
|
||||
@babel/preset-react 7.13.13 MIT https://github.com/babel/babel.git
|
||||
@babel/template 7.12.13 MIT https://github.com/babel/babel.git
|
||||
@babel/traverse 7.12.13 MIT https://github.com/babel/babel.git
|
||||
@babel/types 7.12.13 MIT https://github.com/babel/babel.git
|
||||
@istanbuljs/schema 0.1.2 MIT git+https://github.com/istanbuljs/schema.git
|
||||
@popperjs/core 2.6.0 MIT https://github.com/popperjs/popper-core.git
|
||||
@projectstorm/geometry 6.4.2 MIT https://github.com/projectstorm/react-diagrams.git
|
||||
@projectstorm/react-canvas-core 6.4.2 MIT https://github.com/projectstorm/react-diagrams.git
|
||||
@projectstorm/react-diagrams 6.4.2 MIT https://github.com/projectstorm/react-diagrams.git
|
||||
@projectstorm/react-diagrams-core 6.4.2 MIT https://github.com/projectstorm/react-diagrams.git
|
||||
@projectstorm/react-diagrams-defaults 6.4.2 MIT https://github.com/projectstorm/react-diagrams.git
|
||||
@projectstorm/react-diagrams-routing 6.4.2 MIT https://github.com/projectstorm/react-diagrams.git
|
||||
@simonwep/pickr 1.8.0 MIT https://github.com/Simonwep/pickr.git
|
||||
@tippyjs/react 4.2.0 MIT git+https://github.com/atomiks/tippyjs-react.git
|
||||
@types/estree 0.0.46 MIT https://github.com/DefinitelyTyped/DefinitelyTyped.git
|
||||
@babel/traverse 7.14.2 MIT https://github.com/babel/babel.git
|
||||
@babel/types 7.14.2 MIT https://github.com/babel/babel.git
|
||||
@istanbuljs/schema 0.1.3 MIT git+https://github.com/istanbuljs/schema.git
|
||||
@popperjs/core 2.9.2 MIT https://github.com/popperjs/popper-core.git
|
||||
@projectstorm/geometry 6.5.2 MIT https://github.com/projectstorm/react-diagrams.git
|
||||
@projectstorm/react-canvas-core 6.5.2 MIT https://github.com/projectstorm/react-diagrams.git
|
||||
@projectstorm/react-diagrams 6.5.2 MIT https://github.com/projectstorm/react-diagrams.git
|
||||
@projectstorm/react-diagrams-core 6.5.2 MIT https://github.com/projectstorm/react-diagrams.git
|
||||
@projectstorm/react-diagrams-defaults 6.5.2 MIT https://github.com/projectstorm/react-diagrams.git
|
||||
@projectstorm/react-diagrams-routing 6.5.2 MIT https://github.com/projectstorm/react-diagrams.git
|
||||
@simonwep/pickr 1.8.1 MIT https://github.com/Simonwep/pickr.git
|
||||
@tippyjs/react 4.2.5 MIT git+https://github.com/atomiks/tippyjs-react.git
|
||||
@types/component-emitter 1.2.10 MIT https://github.com/DefinitelyTyped/DefinitelyTyped.git
|
||||
@types/json-schema 7.0.7 MIT https://github.com/DefinitelyTyped/DefinitelyTyped.git
|
||||
@types/node 14.14.25 MIT https://github.com/DefinitelyTyped/DefinitelyTyped.git
|
||||
@types/q 1.5.4 MIT https://github.com/DefinitelyTyped/DefinitelyTyped.git
|
||||
@types/node 15.6.1 MIT https://github.com/DefinitelyTyped/DefinitelyTyped.git
|
||||
@types/parse-json 4.0.0 MIT https://www.github.com/DefinitelyTyped/DefinitelyTyped.git
|
||||
acitree 4.5.0-rc.7 MIT https://github.com/imsurinder90/jquery-aciTree.git
|
||||
acorn 7.4.1 MIT https://github.com/acornjs/acorn.git
|
||||
ajv 6.12.6 MIT https://github.com/ajv-validator/ajv.git
|
||||
ajv 5.5.2 MIT https://github.com/epoberezkin/ajv.git
|
||||
ajv-keywords 3.5.2 MIT git+https://github.com/epoberezkin/ajv-keywords.git
|
||||
@@ -111,8 +123,8 @@ alertifyjs 1.7.1
|
||||
alphanum-sort 1.0.2 MIT https://github.com/TrySound/alphanum-sort.git
|
||||
ansi-regex 2.1.1 MIT https://github.com/chalk/ansi-regex.git
|
||||
ansi-styles 3.2.1 MIT https://github.com/chalk/ansi-styles.git
|
||||
ansi-styles 4.3.0 MIT https://github.com/chalk/ansi-styles.git
|
||||
ansi-styles 2.2.1 MIT https://github.com/chalk/ansi-styles.git
|
||||
argparse 1.0.10 MIT https://github.com/nodeca/argparse.git
|
||||
axios 0.21.1 MIT https://github.com/axios/axios.git
|
||||
babel-code-frame 6.26.0 MIT https://github.com/babel/babel/tree/master/packages/babel-code-frame
|
||||
babel-generator 6.26.1 MIT https://github.com/babel/babel/tree/master/packages/babel-generator
|
||||
@@ -130,132 +142,112 @@ backform 0.2.0
|
||||
backgrid 0.3.8 MIT http://github.com/cloudflare/backgrid
|
||||
backgrid-filter 0.3.7 MIT git://github.com/wyuenho/backgrid-text-cell.git
|
||||
backgrid-select-all 0.3.5 MIT git://github.com/wyuenho/backgrid-select-all.git
|
||||
balanced-match 1.0.0 MIT git://github.com/juliangruber/balanced-match.git
|
||||
backo2 1.0.2 MIT https://github.com/mokesmokes/backo.git
|
||||
balanced-match 1.0.2 MIT git://github.com/juliangruber/balanced-match.git
|
||||
base64-arraybuffer 0.2.0 MIT https://github.com/niklasvh/base64-arraybuffer
|
||||
base64-arraybuffer 0.1.4 MIT https://github.com/niklasvh/base64-arraybuffer
|
||||
big.js 5.2.2 MIT https://github.com/MikeMcl/big.js.git
|
||||
bignumber.js 9.0.1 MIT https://github.com/MikeMcl/bignumber.js.git
|
||||
bignumber.js 7.2.1 MIT https://github.com/MikeMcl/bignumber.js.git
|
||||
bootstrap 4.6.0 MIT git+https://github.com/twbs/bootstrap.git
|
||||
bootstrap4-toggle 3.6.1 MIT https://github.com/gitbrent/bootstrap4-toggle.git
|
||||
brace-expansion 1.1.11 MIT git://github.com/juliangruber/brace-expansion.git
|
||||
browserslist 4.16.3 MIT https://github.com/browserslist/browserslist.git
|
||||
call-bind 1.0.2 MIT git+https://github.com/ljharb/call-bind.git
|
||||
caller-callsite 2.0.0 MIT https://github.com/sindresorhus/caller-callsite.git
|
||||
caller-path 2.0.0 MIT https://github.com/sindresorhus/caller-path.git
|
||||
callsites 2.0.0 MIT https://github.com/sindresorhus/callsites.git
|
||||
camelcase 6.2.0 MIT https://github.com/sindresorhus/camelcase.git
|
||||
browserslist 4.16.6 MIT https://github.com/browserslist/browserslist.git
|
||||
callsites 3.1.0 MIT https://github.com/sindresorhus/callsites.git
|
||||
caniuse-api 3.0.0 MIT https://github.com/nyalab/caniuse-api.git
|
||||
chalk 2.4.2 MIT https://github.com/chalk/chalk.git
|
||||
chalk 4.1.1 MIT https://github.com/chalk/chalk.git
|
||||
chalk 1.1.3 MIT https://github.com/chalk/chalk.git
|
||||
chart.js 2.9.4 MIT https://github.com/chartjs/Chart.js.git
|
||||
chartjs-color 2.4.1 MIT https://github.com/chartjs/chartjs-color.git
|
||||
chartjs-color-string 0.6.0 MIT https://github.com/chartjs/chartjs-color-string.git
|
||||
closest 0.0.1 MIT https://github.com/ForbesLindesay/closest.git
|
||||
co 4.6.0 MIT https://github.com/tj/co.git
|
||||
coa 2.0.2 MIT git://github.com/veged/coa.git
|
||||
codemirror 5.59.2 MIT https://github.com/codemirror/CodeMirror.git
|
||||
color 3.1.3 MIT https://github.com/Qix-/color.git
|
||||
codemirror 5.61.1 MIT https://github.com/codemirror/CodeMirror.git
|
||||
color-convert 1.9.3 MIT https://github.com/Qix-/color-convert.git
|
||||
color-convert 2.0.1 MIT https://github.com/Qix-/color-convert.git
|
||||
color-name 1.1.3 MIT git@github.com:dfcreative/color-name.git
|
||||
color-name 1.1.4 MIT git@github.com:colorjs/color-name.git
|
||||
color-string 1.5.4 MIT https://github.com/Qix-/color-string.git
|
||||
colorette 1.2.1 MIT https://github.com/jorgebucaran/colorette.git
|
||||
colord 2.0.0 MIT https://github.com/omgovich/colord.git
|
||||
colorette 1.2.2 MIT https://github.com/jorgebucaran/colorette.git
|
||||
commander 7.2.0 MIT https://github.com/tj/commander.js.git
|
||||
component-emitter 1.3.0 MIT https://github.com/component/emitter.git
|
||||
concat-map 0.0.1 MIT git://github.com/substack/node-concat-map.git
|
||||
convert-source-map 1.7.0 MIT git://github.com/thlorenz/convert-source-map.git
|
||||
core-js 3.8.3 MIT https://github.com/zloirock/core-js.git
|
||||
core-js 3.13.0 MIT https://github.com/zloirock/core-js.git
|
||||
core-js 2.6.12 MIT https://github.com/zloirock/core-js.git
|
||||
cosmiconfig 5.2.1 MIT git+https://github.com/davidtheclark/cosmiconfig.git
|
||||
cosmiconfig 7.0.0 MIT git+https://github.com/davidtheclark/cosmiconfig.git
|
||||
css-color-names 1.0.1 MIT git://github.com/bahamas10/css-color-names.git
|
||||
css-color-names 0.0.4 MIT git://github.com/bahamas10/css-color-names.git
|
||||
css-declaration-sorter 4.0.1 MIT https://github.com/Siilwyn/css-declaration-sorter.git
|
||||
css-line-break 1.1.1 MIT git+ssh://git@github.com/niklasvh/css-line-break.git
|
||||
css-loader 5.0.2 MIT https://github.com/webpack-contrib/css-loader.git
|
||||
css-select-base-adapter 0.1.1 MIT https://github.com/nrkn/css-select-base-adapter.git
|
||||
css-tree 1.0.0-alpha.37 MIT https://github.com/csstree/csstree.git
|
||||
css-tree 1.1.2 MIT https://github.com/csstree/csstree.git
|
||||
css-loader 5.2.6 MIT https://github.com/webpack-contrib/css-loader.git
|
||||
css-tree 1.1.3 MIT https://github.com/csstree/csstree.git
|
||||
cssesc 3.0.0 MIT https://github.com/mathiasbynens/cssesc.git
|
||||
cssnano 4.1.10 MIT https://github.com/cssnano/cssnano.git
|
||||
cssnano-preset-default 4.0.7 MIT https://github.com/cssnano/cssnano.git
|
||||
cssnano-util-get-arguments 4.0.0 MIT https://github.com/cssnano/cssnano.git
|
||||
cssnano-util-get-match 4.0.0 MIT https://github.com/cssnano/cssnano.git
|
||||
cssnano-util-raw-cache 4.0.1 MIT https://github.com/cssnano/cssnano.git
|
||||
cssnano-util-same-parent 4.0.1 MIT https://github.com/cssnano/cssnano.git
|
||||
cssnano 5.0.4 MIT https://github.com/cssnano/cssnano.git
|
||||
cssnano-preset-default 5.1.1 MIT https://github.com/cssnano/cssnano.git
|
||||
cssnano-utils 2.0.1 MIT https://github.com/cssnano/cssnano.git
|
||||
csso 4.2.0 MIT https://github.com/css/csso.git
|
||||
dagre 0.8.5 MIT https://github.com/dagrejs/dagre.git
|
||||
debug 4.3.1 MIT git://github.com/visionmedia/debug.git
|
||||
debug 2.6.9 MIT git://github.com/visionmedia/debug.git
|
||||
define-properties 1.1.3 MIT git://github.com/ljharb/define-properties.git
|
||||
detect-indent 4.0.0 MIT https://github.com/sindresorhus/detect-indent.git
|
||||
dom-serializer 0.2.2 MIT git://github.com/cheeriojs/dom-renderer.git
|
||||
dot-prop 5.3.0 MIT https://github.com/sindresorhus/dot-prop.git
|
||||
dropzone 5.7.6 MIT https://github.com/dropzone/dropzone.git
|
||||
dom-serializer 1.3.2 MIT git://github.com/cheeriojs/dom-renderer.git
|
||||
dropzone 5.9.2 MIT https://github.com/dropzone/dropzone.git
|
||||
emojis-list 3.0.0 MIT git+https://github.com/kikobeats/emojis-list.git
|
||||
engine.io-client 5.1.1 MIT https://github.com/socketio/engine.io-client.git
|
||||
engine.io-parser 4.0.2 MIT git@github.com:socketio/engine.io-parser.git
|
||||
error-ex 1.3.2 MIT https://github.com/qix-/node-error-ex.git
|
||||
es-abstract 1.18.0-next.2 MIT git://github.com/ljharb/es-abstract.git
|
||||
es-abstract 1.17.7 MIT git://github.com/ljharb/es-abstract.git
|
||||
es-to-primitive 1.2.1 MIT git://github.com/ljharb/es-to-primitive.git
|
||||
escalade 3.1.1 MIT https://github.com/lukeed/escalade.git
|
||||
escape-string-regexp 1.0.5 MIT https://github.com/sindresorhus/escape-string-regexp.git
|
||||
fast-deep-equal 3.1.3 MIT git+https://github.com/epoberezkin/fast-deep-equal.git
|
||||
fast-deep-equal 1.1.0 MIT git+https://github.com/epoberezkin/fast-deep-equal.git
|
||||
fast-json-stable-stringify 2.1.0 MIT git://github.com/epoberezkin/fast-json-stable-stringify.git
|
||||
follow-redirects 1.13.2 MIT git@github.com:follow-redirects/follow-redirects.git
|
||||
function-bind 1.1.1 MIT git://github.com/Raynos/function-bind.git
|
||||
follow-redirects 1.14.1 MIT git@github.com:follow-redirects/follow-redirects.git
|
||||
gensync 1.0.0-beta.2 MIT https://github.com/loganfsmyth/gensync.git
|
||||
get-intrinsic 1.1.1 MIT git+https://github.com/ljharb/get-intrinsic.git
|
||||
globals 11.12.0 MIT https://github.com/sindresorhus/globals.git
|
||||
globals 9.18.0 MIT https://github.com/sindresorhus/globals.git
|
||||
graphlib 2.1.8 MIT https://github.com/dagrejs/graphlib.git
|
||||
has 1.0.3 MIT git://github.com/tarruda/has.git
|
||||
has-ansi 2.0.0 MIT https://github.com/sindresorhus/has-ansi.git
|
||||
has-cors 1.1.0 MIT git://github.com/component/has-cors.git
|
||||
has-flag 3.0.0 MIT https://github.com/sindresorhus/has-flag.git
|
||||
has-flag 4.0.0 MIT https://github.com/sindresorhus/has-flag.git
|
||||
has-symbols 1.0.1 MIT git://github.com/ljharb/has-symbols.git
|
||||
hex-color-regex 1.1.0 MIT https://github.com/regexps/hex-color-regex.git
|
||||
hsl-regex 1.0.0 MIT https://github.com/regexps/hsl-regex.git
|
||||
hsla-regex 1.0.0 MIT https://github.com/regexps/hsla-regex.git
|
||||
html-comment-regex 1.1.2 MIT https://github.com/stevemao/html-comment-regex.git
|
||||
html-escaper 2.0.2 MIT https://github.com/WebReflection/html-escaper.git
|
||||
html2canvas 1.0.0-rc.7 MIT git@github.com:niklasvh/html2canvas.git
|
||||
immutability-helper 3.1.1 MIT git+https://github.com/kolodny/immutability-helper.git
|
||||
import-fresh 2.0.0 MIT https://github.com/sindresorhus/import-fresh.git
|
||||
import-fresh 3.3.0 MIT https://github.com/sindresorhus/import-fresh.git
|
||||
imports-loader 2.0.0 MIT https://github.com/webpack-contrib/imports-loader.git
|
||||
indexes-of 1.0.1 MIT git://github.com/dominictarr/indexes-of.git
|
||||
invariant 2.2.4 MIT https://github.com/zertosh/invariant
|
||||
ip-address 7.1.0 MIT git://github.com/beaugunderson/ip-address.git
|
||||
is-absolute-url 2.1.0 MIT https://github.com/sindresorhus/is-absolute-url.git
|
||||
is-any-array 0.1.0 MIT https://github.com/cheminfo-js/is-any-array.git
|
||||
is-absolute-url 3.0.3 MIT https://github.com/sindresorhus/is-absolute-url.git
|
||||
is-any-array 1.0.0 MIT https://github.com/cheminfo-js/is-any-array.git
|
||||
is-arrayish 0.2.1 MIT https://github.com/qix-/node-is-arrayish.git
|
||||
is-arrayish 0.3.2 MIT https://github.com/qix-/node-is-arrayish.git
|
||||
is-callable 1.2.3 MIT git://github.com/ljharb/is-callable.git
|
||||
is-color-stop 1.1.0 MIT git+https://github.com/pigcan/is-color-stop.git
|
||||
is-date-object 1.0.2 MIT git://github.com/ljharb/is-date-object.git
|
||||
is-directory 0.3.1 MIT https://github.com/jonschlinkert/is-directory.git
|
||||
is-finite 1.1.0 MIT https://github.com/sindresorhus/is-finite.git
|
||||
is-negative-zero 2.0.1 MIT git://github.com/inspect-js/is-negative-zero.git
|
||||
is-obj 2.0.0 MIT https://github.com/sindresorhus/is-obj.git
|
||||
is-regex 1.1.2 MIT git://github.com/inspect-js/is-regex.git
|
||||
is-svg 3.0.0 MIT https://github.com/sindresorhus/is-svg.git
|
||||
is-symbol 1.0.3 MIT git://github.com/inspect-js/is-symbol.git
|
||||
istanbul-instrumenter-loader 3.0.1 MIT https://github.com/webpack-contrib/istanbul-instrumenter-loader.git
|
||||
jquery 3.5.1 MIT https://github.com/jquery/jquery.git
|
||||
javascript-natural-sort 0.7.1 MIT https://github.com/Bill4Time/javascript-natural-sort.git
|
||||
jquery 3.6.0 MIT https://github.com/jquery/jquery.git
|
||||
jquery-contextmenu 2.9.2 MIT git://github.com/swisnl/jQuery-contextMenu.git
|
||||
jquery-ui 1.12.1 MIT git://github.com/jquery/jquery-ui.git
|
||||
js-tokens 4.0.0 MIT https://github.com/lydell/js-tokens.git
|
||||
js-tokens 3.0.2 MIT https://github.com/lydell/js-tokens.git
|
||||
js-yaml 3.14.1 MIT https://github.com/nodeca/js-yaml.git
|
||||
jsbn 1.1.0 MIT https://github.com/andyperlitch/jsbn.git
|
||||
jsesc 2.5.2 MIT https://github.com/mathiasbynens/jsesc.git
|
||||
jsesc 1.3.0 MIT https://github.com/mathiasbynens/jsesc.git
|
||||
json-bignumber 1.0.2 MIT git@github.com:wbuss/JSONBigNumber.git
|
||||
json-parse-better-errors 1.0.2 MIT https://github.com/zkat/json-parse-better-errors
|
||||
json-parse-even-better-errors 2.3.1 MIT https://github.com/npm/json-parse-even-better-errors
|
||||
json-schema-traverse 0.4.1 MIT git+https://github.com/epoberezkin/json-schema-traverse.git
|
||||
json-schema-traverse 0.3.1 MIT git+https://github.com/epoberezkin/json-schema-traverse.git
|
||||
json-source-map 0.6.1 MIT git+https://github.com/epoberezkin/json-source-map.git
|
||||
json5 2.2.0 MIT git+https://github.com/json5/json5.git
|
||||
json5 1.0.1 MIT git+https://github.com/json5/json5.git
|
||||
karma-coverage 2.0.3 MIT git://github.com/karma-runner/karma-coverage.git
|
||||
lines-and-columns 1.1.6 MIT https://github.com/eventualbuddha/lines-and-columns.git
|
||||
loader-utils 2.0.0 MIT https://github.com/webpack/loader-utils.git
|
||||
loader-utils 1.4.0 MIT https://github.com/webpack/loader-utils.git
|
||||
lodash 4.17.20 MIT https://github.com/lodash/lodash.git
|
||||
lodash 4.17.21 MIT https://github.com/lodash/lodash.git
|
||||
lodash.memoize 4.1.2 MIT https://github.com/lodash/lodash.git
|
||||
lodash.uniq 4.5.0 MIT https://github.com/lodash/lodash.git
|
||||
loose-envify 1.4.0 MIT git://github.com/zertosh/loose-envify.git
|
||||
@@ -263,147 +255,130 @@ lunr 0.7.2
|
||||
make-dir 3.1.0 MIT https://github.com/sindresorhus/make-dir.git
|
||||
matches-selector 0.0.1 MIT https://github.com/ForbesLindesay/matches-selector.git
|
||||
minimist 1.2.5 MIT git://github.com/substack/minimist.git
|
||||
mkdirp 0.5.5 MIT https://github.com/substack/node-mkdirp.git
|
||||
ml-array-max 1.2.0 MIT git+https://github.com/mljs/array.git
|
||||
ml-array-min 1.2.0 MIT git+https://github.com/mljs/array.git
|
||||
ml-array-rescale 1.3.2 MIT git+https://github.com/mljs/array.git
|
||||
ml-matrix 6.6.0 MIT https://github.com/mljs/matrix.git
|
||||
ml-array-max 1.2.3 MIT git+https://github.com/mljs/array.git
|
||||
ml-array-min 1.2.2 MIT git+https://github.com/mljs/array.git
|
||||
ml-array-rescale 1.3.5 MIT git+https://github.com/mljs/array.git
|
||||
ml-matrix 6.8.0 MIT https://github.com/mljs/matrix.git
|
||||
mobius1-selectr 2.4.13 MIT git+https://github.com/Mobius1/Selectr.git
|
||||
moment 2.29.1 MIT https://github.com/moment/moment.git
|
||||
moment 2.24.0 MIT https://github.com/moment/moment.git
|
||||
moment-timezone 0.5.33 MIT https://github.com/moment/moment-timezone.git
|
||||
ms 2.1.2 MIT https://github.com/zeit/ms.git
|
||||
ms 2.0.0 MIT https://github.com/zeit/ms.git
|
||||
nanoid 3.1.20 MIT https://github.com/ai/nanoid.git
|
||||
nanoid 3.1.23 MIT https://github.com/ai/nanoid.git
|
||||
nanopop 2.1.0 MIT https://github.com/Simonwep/nanopop.git
|
||||
node-releases 1.1.70 MIT git+https://github.com/chicoxyzzy/node-releases.git
|
||||
normalize-url 3.3.0 MIT https://github.com/sindresorhus/normalize-url.git
|
||||
node-releases 1.1.72 MIT git+https://github.com/chicoxyzzy/node-releases.git
|
||||
normalize-url 4.5.1 MIT https://github.com/sindresorhus/normalize-url.git
|
||||
object-assign 4.1.1 MIT https://github.com/sindresorhus/object-assign.git
|
||||
object-inspect 1.9.0 MIT git://github.com/inspect-js/object-inspect.git
|
||||
object-keys 1.1.1 MIT git://github.com/ljharb/object-keys.git
|
||||
object.assign 4.1.2 MIT git://github.com/ljharb/object.assign.git
|
||||
object.getownpropertydescriptors 2.1.1 MIT git://github.com/es-shims/object.getownpropertydescriptors.git
|
||||
object.values 1.1.2 MIT git://github.com/es-shims/Object.values.git
|
||||
parse-json 4.0.0 MIT https://github.com/sindresorhus/parse-json.git
|
||||
parent-module 1.0.1 MIT https://github.com/sindresorhus/parent-module.git
|
||||
parse-json 5.2.0 MIT https://github.com/sindresorhus/parse-json.git
|
||||
parseqs 0.0.6 MIT https://github.com/get/querystring.git
|
||||
parseuri 0.0.6 MIT https://github.com/get/parseuri.git
|
||||
path-type 4.0.0 MIT https://github.com/sindresorhus/path-type.git
|
||||
pathfinding 0.4.18 MIT git://github.com/qiao/PathFinding.js.git
|
||||
performance-now 2.1.0 MIT git://github.com/braveg1rl/performance-now.git
|
||||
picomodal 3.0.0 MIT https://github.com/Nycto/PicoModal.git
|
||||
popper.js 1.16.1 MIT git+https://github.com/FezVrasta/popper.js.git
|
||||
postcss 8.2.5 MIT https://github.com/postcss/postcss.git
|
||||
postcss 7.0.35 MIT https://github.com/postcss/postcss.git
|
||||
postcss-calc 7.0.5 MIT https://github.com/postcss/postcss-calc.git
|
||||
postcss-colormin 4.0.3 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-convert-values 4.0.1 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-discard-comments 4.0.2 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-discard-duplicates 4.0.2 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-discard-empty 4.0.1 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-discard-overridden 4.0.1 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-merge-longhand 4.0.11 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-merge-rules 4.0.3 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-minify-font-values 4.0.2 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-minify-gradients 4.0.2 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-minify-params 4.0.2 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-minify-selectors 4.0.2 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss 8.3.0 MIT https://github.com/postcss/postcss.git
|
||||
postcss-calc 8.0.0 MIT https://github.com/postcss/postcss-calc.git
|
||||
postcss-colormin 5.1.1 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-convert-values 5.0.1 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-discard-comments 5.0.1 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-discard-duplicates 5.0.1 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-discard-empty 5.0.1 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-discard-overridden 5.0.1 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-merge-longhand 5.0.2 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-merge-rules 5.0.1 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-minify-font-values 5.0.1 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-minify-gradients 5.0.1 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-minify-params 5.0.1 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-minify-selectors 5.1.0 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-modules-local-by-default 4.0.0 MIT https://github.com/css-modules/postcss-modules-local-by-default.git
|
||||
postcss-normalize-charset 4.0.1 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-normalize-display-values 4.0.2 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-normalize-positions 4.0.2 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-normalize-repeat-style 4.0.2 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-normalize-string 4.0.2 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-normalize-timing-functions 4.0.2 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-normalize-unicode 4.0.1 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-normalize-url 4.0.1 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-normalize-whitespace 4.0.2 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-ordered-values 4.1.2 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-reduce-initial 4.0.3 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-reduce-transforms 4.0.2 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-selector-parser 6.0.4 MIT https://github.com/postcss/postcss-selector-parser.git
|
||||
postcss-selector-parser 3.1.2 MIT https://github.com/postcss/postcss-selector-parser.git
|
||||
postcss-svgo 4.0.2 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-unique-selectors 4.0.1 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-normalize-charset 5.0.1 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-normalize-display-values 5.0.1 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-normalize-positions 5.0.1 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-normalize-repeat-style 5.0.1 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-normalize-string 5.0.1 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-normalize-timing-functions 5.0.1 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-normalize-unicode 5.0.1 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-normalize-url 5.0.1 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-normalize-whitespace 5.0.1 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-ordered-values 5.0.1 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-reduce-initial 5.0.1 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-reduce-transforms 5.0.1 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-selector-parser 6.0.6 MIT https://github.com/postcss/postcss-selector-parser.git
|
||||
postcss-svgo 5.0.1 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-unique-selectors 5.0.1 MIT https://github.com/cssnano/cssnano.git
|
||||
postcss-value-parser 4.1.0 MIT https://github.com/TrySound/postcss-value-parser.git
|
||||
postcss-value-parser 3.3.1 MIT https://github.com/TrySound/postcss-value-parser.git
|
||||
punycode 2.1.1 MIT https://github.com/bestiejs/punycode.js.git
|
||||
q 1.5.1 MIT git://github.com/kriskowal/q.git
|
||||
raf 3.4.1 MIT git://github.com/chrisdickinson/raf.git
|
||||
react 17.0.1 MIT https://github.com/facebook/react.git
|
||||
react-dom 17.0.1 MIT https://github.com/facebook/react.git
|
||||
react 17.0.2 MIT https://github.com/facebook/react.git
|
||||
react-dom 17.0.2 MIT https://github.com/facebook/react.git
|
||||
regenerator-runtime 0.11.1 MIT https://github.com/facebook/regenerator/tree/master/packages/regenerator-runtime
|
||||
repeating 2.0.1 MIT https://github.com/sindresorhus/repeating.git
|
||||
requirejs 2.3.6 MIT https://github.com/jrburke/r.js.git
|
||||
resolve-from 3.0.0 MIT https://github.com/sindresorhus/resolve-from.git
|
||||
resolve-from 4.0.0 MIT https://github.com/sindresorhus/resolve-from.git
|
||||
rgb-regex 1.0.1 MIT https://github.com/regexps/rgb-regex.git
|
||||
rgba-regex 1.0.0 MIT https://github.com/johnotander/rgba-regex.git
|
||||
rollup 1.32.1 MIT https://github.com/rollup/rollup.git
|
||||
safe-buffer 5.1.2 MIT git://github.com/feross/safe-buffer.git
|
||||
scheduler 0.20.1 MIT https://github.com/facebook/react.git
|
||||
scheduler 0.20.2 MIT https://github.com/facebook/react.git
|
||||
schema-utils 3.0.0 MIT https://github.com/webpack/schema-utils.git
|
||||
schema-utils 0.3.0 MIT git+https://github.com/webpack-contrib/schema-utils.git
|
||||
select2 4.0.13 MIT git://github.com/select2/select2.git
|
||||
shim-loader 1.0.1 MIT https://github.com/zinserjan/shim-loader
|
||||
simple-swizzle 0.2.2 MIT https://github.com/qix-/node-simple-swizzle.git
|
||||
slickgrid 2.3.16 MIT git+https://github.com/6pac/SlickGrid.git
|
||||
snapsvg-cjs 0.0.6 MIT git+https://github.com/geelen/Snap.svg-cjs.git
|
||||
socket.io-client 4.1.2 MIT https://github.com/socketio/socket.io-client.git
|
||||
socket.io-parser 4.0.4 MIT https://github.com/socketio/socket.io-parser.git
|
||||
source-list-map 1.1.2 MIT https://github.com/webpack/source-list-map.git
|
||||
split.js 1.6.2 MIT https://github.com/nathancahill/split
|
||||
split.js 1.6.4 MIT https://github.com/nathancahill/split
|
||||
stable 0.1.8 MIT https://github.com/Two-Screen/stable.git
|
||||
string.prototype.trimend 1.0.3 MIT git://github.com/es-shims/String.prototype.trimEnd.git
|
||||
string.prototype.trimstart 1.0.3 MIT git://github.com/es-shims/String.prototype.trimStart.git
|
||||
strip-ansi 3.0.1 MIT https://github.com/chalk/strip-ansi.git
|
||||
strip-comments 2.0.1 MIT https://github.com/jonschlinkert/strip-comments.git
|
||||
stylehacks 4.0.3 MIT https://github.com/cssnano/cssnano.git
|
||||
stylehacks 5.0.1 MIT https://github.com/cssnano/cssnano.git
|
||||
supports-color 5.5.0 MIT https://github.com/chalk/supports-color.git
|
||||
supports-color 6.1.0 MIT https://github.com/chalk/supports-color.git
|
||||
supports-color 2.0.0 MIT https://github.com/chalk/supports-color.git
|
||||
supports-color 7.2.0 MIT https://github.com/chalk/supports-color.git
|
||||
svgo 1.3.2 MIT git://github.com/svg/svgo.git
|
||||
supports-color 2.0.0 MIT https://github.com/chalk/supports-color.git
|
||||
svgo 2.3.0 MIT git://github.com/svg/svgo.git
|
||||
tempusdominus-bootstrap-4 5.39.0 MIT https://github.com/tempusdominus/bootstrap-4.git
|
||||
tempusdominus-core 5.19.0 MIT https://github.com/tempusdominus/core.git
|
||||
timsort 0.3.0 MIT https://github.com/mziccard/node-timsort.git
|
||||
tippy.js 6.2.7 MIT git+https://github.com/atomiks/tippyjs.git
|
||||
tippy.js 6.3.1 MIT git+https://github.com/atomiks/tippyjs.git
|
||||
to-fast-properties 2.0.0 MIT https://github.com/sindresorhus/to-fast-properties.git
|
||||
to-fast-properties 1.0.3 MIT https://github.com/sindresorhus/to-fast-properties.git
|
||||
trim-right 1.0.1 MIT https://github.com/sindresorhus/trim-right.git
|
||||
underscore 1.12.0 MIT git://github.com/jashkenas/underscore.git
|
||||
uniq 1.0.1 MIT git://github.com/mikolalysenko/uniq.git
|
||||
underscore 1.13.1 MIT git://github.com/jashkenas/underscore.git
|
||||
uniqs 2.0.0 MIT git://github.com/fgnass/uniqs.git
|
||||
unquote 1.1.1 MIT https://github.com/lakenen/node-unquote.git
|
||||
util-deprecate 1.0.2 MIT git://github.com/TooTallNate/util-deprecate.git
|
||||
util.promisify 1.0.1 MIT git+https://github.com/ljharb/util.promisify.git
|
||||
vendors 1.0.4 MIT https://github.com/wooorm/vendors.git
|
||||
webpack-sources 0.2.3 MIT git+https://github.com/webpack/webpack-sources.git
|
||||
wkx 0.5.0 MIT http://github.com/cschwarz/wkx.git
|
||||
@fortawesome/fontawesome-free 5.15.2 (CC-BY-4.0 AND OFL-1.1 AND MIT) https://github.com/FortAwesome/Font-Awesome
|
||||
ws 7.4.6 MIT https://github.com/websockets/ws.git
|
||||
xterm 4.12.0 MIT https://github.com/xtermjs/xterm.js
|
||||
xterm-addon-fit 0.5.0 MIT https://github.com/xtermjs/xterm.js
|
||||
xterm-addon-search 0.8.0 MIT https://github.com/xtermjs/xterm.js
|
||||
xterm-addon-web-links 0.4.0 MIT https://github.com/xtermjs/xterm.js
|
||||
yeast 0.1.2 MIT https://github.com/unshiftio/yeast.git
|
||||
@fortawesome/fontawesome-free 5.15.3 (CC-BY-4.0 AND OFL-1.1 AND MIT) https://github.com/FortAwesome/Font-Awesome
|
||||
@sphinxxxx/color-conversion 2.2.2 ISC git+https://github.com/Sphinxxxx/color-conversion.git
|
||||
@trysound/sax 0.1.1 ISC git://github.com/svg/sax.git
|
||||
boolbase 1.0.0 ISC https://github.com/fb55/boolbase
|
||||
electron-to-chromium 1.3.661 ISC https://github.com/kilian/electron-to-chromium/
|
||||
css-declaration-sorter 6.0.3 ISC https://github.com/Siilwyn/css-declaration-sorter.git
|
||||
electron-to-chromium 1.3.740 ISC https://github.com/kilian/electron-to-chromium/
|
||||
icss-utils 5.1.0 ISC git+https://github.com/css-modules/icss-utils.git
|
||||
is-resolvable 1.1.0 ISC https://github.com/shinnn/is-resolvable.git
|
||||
jsonrepair 2.2.1 ISC https://github.com/josdejong/jsonrepair.git
|
||||
lru-cache 6.0.0 ISC git://github.com/isaacs/node-lru-cache.git
|
||||
minimatch 3.0.4 ISC git://github.com/isaacs/minimatch.git
|
||||
postcss-modules-extract-imports 3.0.0 ISC https://github.com/css-modules/postcss-modules-extract-imports.git
|
||||
postcss-modules-scope 3.0.0 ISC https://github.com/css-modules/postcss-modules-scope.git
|
||||
postcss-modules-values 4.0.0 ISC git+https://github.com/css-modules/postcss-modules-values.git
|
||||
sax 1.2.4 ISC git://github.com/isaacs/sax-js.git
|
||||
semver 7.3.4 ISC https://github.com/npm/node-semver
|
||||
semver 7.3.5 ISC https://github.com/npm/node-semver
|
||||
semver 5.7.1 ISC https://github.com/npm/node-semver
|
||||
semver 6.3.0 ISC https://github.com/npm/node-semver
|
||||
vanilla-picker 2.11.2 ISC https://github.com/Sphinxxxx/vanilla-picker.git
|
||||
yallist 4.0.0 ISC git+https://github.com/isaacs/yallist.git
|
||||
bootstrap-datepicker 1.9.0 Apache-2.0 https://github.com/uxsolutions/bootstrap-datepicker.git
|
||||
eve 0.5.4 Apache-2.0 git@github.com:adobe-webplatform/eve.git
|
||||
paths-js 0.4.11 Apache-2.0 https://github.com/andreaferretti/paths-js.git
|
||||
snapsvg 0.5.1 Apache-2.0 git@github.com:adobe-webplatform/Snap.svg.git
|
||||
caniuse-lite 1.0.30001185 CC-BY-4.0 https://github.com/ben-eb/caniuse-lite.git
|
||||
css-select 2.1.0 BSD-2-Clause git://github.com/fb55/css-select.git
|
||||
css-what 3.4.2 BSD-2-Clause https://github.com/fb55/css-what
|
||||
domelementtype 1.3.1 BSD-2-Clause git://github.com/fb55/domelementtype.git
|
||||
domelementtype 2.1.0 BSD-2-Clause git://github.com/fb55/domelementtype.git
|
||||
domutils 1.7.0 BSD-2-Clause git://github.com/FB55/domutils.git
|
||||
entities 2.2.0 BSD-2-Clause git://github.com/fb55/entities.git
|
||||
esprima 4.0.1 BSD-2-Clause https://github.com/jquery/esprima.git
|
||||
esutils 2.0.3 BSD-2-Clause http://github.com/estools/esutils.git
|
||||
leaflet 1.7.1 BSD-2-Clause git://github.com/Leaflet/Leaflet.git
|
||||
nth-check 1.0.2 BSD-2-Clause https://github.com/fb55/nth-check
|
||||
uri-js 4.4.1 BSD-2-Clause http://github.com/garycourt/uri-js
|
||||
FileSaver 0.10.0 UNKNOWN Unknown
|
||||
heap 0.2.5 UNKNOWN git://github.com/qiao/heap.js.git
|
||||
yaml 1.10.2 ISC https://github.com/eemeli/yaml.git
|
||||
ace-builds 1.4.12 BSD-3-Clause https://github.com/ajaxorg/ace-builds.git
|
||||
istanbul-lib-coverage 1.2.1 BSD-3-Clause git@github.com:istanbuljs/istanbuljs.git
|
||||
istanbul-lib-coverage 3.0.0 BSD-3-Clause git+ssh://git@github.com/istanbuljs/istanbuljs.git
|
||||
istanbul-lib-instrument 1.10.2 BSD-3-Clause git@github.com:istanbuljs/istanbuljs.git
|
||||
@@ -413,14 +388,32 @@ istanbul-lib-source-maps 4.0.0
|
||||
istanbul-reports 3.0.2 BSD-3-Clause git+ssh://git@github.com/istanbuljs/istanbuljs.git
|
||||
source-map 0.5.7 BSD-3-Clause http://github.com/mozilla/source-map.git
|
||||
source-map 0.6.1 BSD-3-Clause http://github.com/mozilla/source-map.git
|
||||
sprintf-js 1.0.3 BSD-3-Clause https://github.com/alexei/sprintf.js.git
|
||||
source-map-js 0.6.2 BSD-3-Clause http://github.com/7rulnik/source-map.git
|
||||
sprintf-js 1.1.2 BSD-3-Clause https://github.com/alexei/sprintf.js.git
|
||||
mdn-data 2.0.4 CC0-1.0 https://github.com/mdn/data.git
|
||||
bootstrap-datepicker 1.9.0 Apache-2.0 https://github.com/uxsolutions/bootstrap-datepicker.git
|
||||
eve 0.5.4 Apache-2.0 git@github.com:adobe-webplatform/eve.git
|
||||
jmespath 0.15.0 Apache-2.0 git://github.com/jmespath/jmespath.js
|
||||
jsoneditor 9.5.3 Apache-2.0 https://github.com/josdejong/jsoneditor.git
|
||||
paths-js 0.4.11 Apache-2.0 https://github.com/andreaferretti/paths-js.git
|
||||
snapsvg 0.5.1 Apache-2.0 git@github.com:adobe-webplatform/Snap.svg.git
|
||||
caniuse-lite 1.0.30001230 CC-BY-4.0 https://github.com/browserslist/caniuse-lite.git
|
||||
css-select 3.1.2 BSD-2-Clause git://github.com/fb55/css-select.git
|
||||
css-what 4.0.0 BSD-2-Clause https://github.com/fb55/css-what
|
||||
domelementtype 2.2.0 BSD-2-Clause git://github.com/fb55/domelementtype.git
|
||||
domhandler 4.2.0 BSD-2-Clause git://github.com/fb55/domhandler.git
|
||||
domutils 2.6.0 BSD-2-Clause git://github.com/fb55/domutils.git
|
||||
entities 2.2.0 BSD-2-Clause git://github.com/fb55/entities.git
|
||||
esutils 2.0.3 BSD-2-Clause http://github.com/estools/esutils.git
|
||||
leaflet 1.7.1 BSD-2-Clause git://github.com/Leaflet/Leaflet.git
|
||||
nth-check 2.0.0 BSD-2-Clause https://github.com/fb55/nth-check
|
||||
uri-js 4.4.1 BSD-2-Clause http://github.com/garycourt/uri-js
|
||||
FileSaver 0.10.0 UNKNOWN Unknown
|
||||
heap 0.2.5 UNKNOWN git://github.com/qiao/heap.js.git
|
||||
mdn-data 2.0.14 CC0-1.0 https://github.com/mdn/data.git
|
||||
mousetrap 1.6.5 Apache-2.0 WITH LLVM-exception git://github.com/ccampbell/mousetrap.git
|
||||
precond 0.2.3 MIT* https://github.com/MathieuTurcotte/node-precond.git
|
||||
webcabin-docker 2.2.4-dev MIT* Unknown
|
||||
webcabin-docker 2.2.5 MIT* Unknown
|
||||
tablesorter 2.31.3 (MIT OR GPL-2.0) git://github.com/Mottie/tablesorter.git
|
||||
|
||||
362 dependencies listed.
|
||||
345 dependencies listed.
|
||||
|
||||
@@ -24,16 +24,7 @@ appbundle:
|
||||
./pkg/mac/build.sh
|
||||
|
||||
install-node:
|
||||
cd web && npm install
|
||||
cd web && npm audit fix
|
||||
rm -f web/yarn.lock
|
||||
cd web && yarn import
|
||||
# Commented the below line to avoid vulnerability in lodash package.
|
||||
# Refer https://www.npmjs.com/advisories/1523.
|
||||
# Once fixed we will uncomment it.
|
||||
# cd web && yarn audit
|
||||
rm -f package-lock.json
|
||||
rm -f web/package-lock.json
|
||||
cd web && yarn install
|
||||
|
||||
bundle:
|
||||
cd web && yarn run bundle
|
||||
@@ -151,7 +142,7 @@ msg-extract:
|
||||
cd web && pybabel extract -F babel.cfg -o pgadmin/messages.pot pgadmin
|
||||
|
||||
msg-update:
|
||||
cd web && pybabel update -i pgadmin/messages.pot -d pgadmin/translations
|
||||
cd web && pybabel update --no-fuzzy-matching -i pgadmin/messages.pot -d pgadmin/translations
|
||||
|
||||
.PHONY: docs
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ Click the *Variables* tab to continue.
|
||||
:alt: Column dialog variables tab
|
||||
:align: center
|
||||
|
||||
Use the *Variables* tab to to specify the number of distinct values that may be
|
||||
Use the *Variables* tab to specify the number of distinct values that may be
|
||||
present in the column; this value overrides estimates made by the ANALYZE
|
||||
command. Click the *Add* icon (+) to add a *Name*/*Value* pair:
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ The configuration files are as follows:
|
||||
|
||||
Linux,/etc/pgadmin/config_system.py
|
||||
macOS,/Library/Preferences/pgadmin/config_system.py
|
||||
Windows,%CommonProgramFiles%\pgadmin\config_system.py
|
||||
Windows,%CommonProgramFiles%\\pgadmin\\config_system.py
|
||||
|
||||
.. note:: If the SERVER_MODE setting is changed in ``config_distro.py``,
|
||||
``config_local.py``, or ``config_system.py`` you will most likely need to
|
||||
|
||||
@@ -23,8 +23,19 @@ server:
|
||||
* PostgreSQL 12: */usr/local/pgsql-12*
|
||||
* PostgreSQL 13: */usr/local/pgsql-13*
|
||||
|
||||
The most recent version of the utilities is used by default; this may be
|
||||
changed in the :ref:`preferences`.
|
||||
The default binary paths set in the container are as follows:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
DEFAULT_BINARY_PATHS = {
|
||||
'pg-13': '/usr/local/pgsql-13'
|
||||
'pg-12': '/usr/local/pgsql-12'
|
||||
'pg-11': '/usr/local/pgsql-11'
|
||||
'pg-10': '/usr/local/pgsql-10'
|
||||
'pg-9.6': '/usr/local/pgsql-9.6'
|
||||
}
|
||||
|
||||
this may be changed in the :ref:`preferences`.
|
||||
|
||||
Environment Variables
|
||||
*********************
|
||||
@@ -104,7 +115,7 @@ Adjust the number of threads the Gunicorn server uses to handle incoming
|
||||
requests. This should typically be left as-is, except in highly loaded systems
|
||||
where it may be increased.
|
||||
|
||||
**PGADMIN_CONFIG_**
|
||||
**PGADMIN_CONFIG_***
|
||||
|
||||
This is a variable prefix that can be used to override any of the configuration
|
||||
options in pgAdmin's *config.py* file. Add the *PGADMIN_CONFIG_* prefix to any
|
||||
@@ -117,6 +128,12 @@ is read after */pgadmin4/config.py* and before */pgadmin4/config_local.py*.
|
||||
Any settings given will therefore override anything in config.py, but can be
|
||||
overridden by settings in config_local.py.
|
||||
|
||||
Settings are only written to */pgadmin4/config_distro.py* once, typically on
|
||||
first launch of the container. If */pgadmin4/config_distro.py* contains one or
|
||||
more lines, then no changes are made; for example, if the container instance is
|
||||
restarted, or */pgadmin4/config_distro.py* is mapped to a file on persistent
|
||||
storage (not recommended - use */pgadmin4/config_local.py* instead)!
|
||||
|
||||
See :ref:`config_py` for more information on the available configuration settings.
|
||||
|
||||
Mapped Files and Directories
|
||||
|
||||
@@ -16,3 +16,4 @@ PL/SQL code.
|
||||
editgrid
|
||||
schema_diff
|
||||
erd_tool
|
||||
psql_tool
|
||||
@@ -107,6 +107,86 @@ properties of the geometries directly in map, just click the specific geometry:
|
||||
- *Internet access:* An internet connection is required for the Geometry Viewer
|
||||
to function correctly.
|
||||
|
||||
|
||||
**JSON Data Editor**
|
||||
|
||||
A built in json editor is provided for *JSON/JSONB Data*.Double clicking on json/jsonb
|
||||
data type cell in data grid will open JSON Editor.Editor provides different mode to
|
||||
view and edit json data.
|
||||
|
||||
|
||||
.. image:: images/json_editor_modes.png
|
||||
:alt: Json Editor
|
||||
:align: center
|
||||
|
||||
*Code Mode*:
|
||||
Provides way to format & compact json data.Also provides ability to repair json data
|
||||
by fixing quotes and escape characters, removing comments and JSONP notation and
|
||||
turn JavaScript objects into JSON.
|
||||
|
||||
*Tree Mode*:
|
||||
Enabled to change, add, move, remove, and duplicate fields and values.Provides ability
|
||||
to searh & hilight data.
|
||||
|
||||
*Form Mode*:
|
||||
Allows only to edit values in json data there by providing ability to keep data structure
|
||||
unchanged while editing.
|
||||
|
||||
*Preview Mode*:
|
||||
Provides ability to check data before saving and also shows size of current json data.
|
||||
Format and compact json data as well.
|
||||
|
||||
|
||||
*Editor Toolbar*
|
||||
|
||||
Different options are provided to manipulate json data.
|
||||
|
||||
Code/Preview mode:
|
||||
|
||||
.. image:: images/json_editor_code_preview_tool_bar.png
|
||||
:alt: Json Editor Code/Preview mode Tool Bar
|
||||
:align: center
|
||||
|
||||
|
||||
Tree/Form mode:
|
||||
|
||||
.. image:: images/json_editor_tree_form_mode_tool_bar.png
|
||||
:alt: Json Editor Tree/Form mode Tool Bar
|
||||
:align: center
|
||||
|
||||
|
||||
.. table::
|
||||
:class: longtable
|
||||
:widths: 1 3 2
|
||||
|
||||
+----------------------+----------------------------------------------------------------------------------------+---------------------------+
|
||||
| Icon | Behavior | Available in mode |
|
||||
+======================+========================================================================================+===========================+
|
||||
| *Format Json* | Click to *Format Json* format json data with proper indentation. | Code, Preview |
|
||||
+----------------------+----------------------------------------------------------------------------------------+---------------------------+
|
||||
| *Compact Json* | Click to *Compact Json* get compacted json data. | Code, Preview |
|
||||
+----------------------+----------------------------------------------------------------------------------------+---------------------------+
|
||||
| *Sort* | Click to *Sort* icon to set sorting criteria for the data using file values. | Code, Preview, Tree |
|
||||
+----------------------+----------------------------------------------------------------------------------------+---------------------------+
|
||||
| *Transform* | Click to *Transform* to filter data using JSME query language. | Code, Preview, Tree |
|
||||
+----------------------+----------------------------------------------------------------------------------------+---------------------------+
|
||||
| *Undo* | Click to *Undo* to undo last action performed on data . | Code, Preview, Tree, From |
|
||||
+----------------------+----------------------------------------------------------------------------------------+---------------------------+
|
||||
| *Redo* | Click to *Redo* to repat last action performed on data . | Code, Preview, Tree, From |
|
||||
+----------------------+----------------------------------------------------------------------------------------+---------------------------+
|
||||
| *Mode* | Click to *Mode* dropdown to change dipaly mode of editor.Different modes avaialble | Code, Tree, From, Preview |
|
||||
| | are Code, Preview, Tree, From. | |
|
||||
+----------------------+----------------------------------------------------------------------------------------+---------------------------+
|
||||
| *Expand All* | Click to *Expand All* to expand json data. | Tree, From |
|
||||
+----------------------+----------------------------------------------------------------------------------------+---------------------------+
|
||||
| *Collapse All* | Click to *Redo* to collapse json data. | Tree, From |
|
||||
+----------------------+----------------------------------------------------------------------------------------+---------------------------+
|
||||
| *Search Box* | Enter partial/complete string to search in data. | Tree, From |
|
||||
+----------------------+----------------------------------------------------------------------------------------+---------------------------+
|
||||
|
||||
|
||||
|
||||
|
||||
Sort/Filter options dialog
|
||||
**************************
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ Click the *Columns* tab to continue.
|
||||
:alt: Foreign table dialog columns tab
|
||||
:align: center
|
||||
|
||||
Use the fields in the *Columns* tab to to add columns and their attributes to
|
||||
Use the fields in the *Columns* tab to add columns and their attributes to
|
||||
the table. Click the *Add* icon (+) to define a column:
|
||||
|
||||
* Use the *Name* field to add a descriptive name for the column.
|
||||
|
||||
@@ -35,8 +35,10 @@ Mode is pre-configured for security.
|
||||
login
|
||||
user_management
|
||||
change_user_password
|
||||
restore_locked_user
|
||||
ldap
|
||||
kerberos
|
||||
oauth2
|
||||
|
||||
|
||||
.. note:: Pre-compiled and configured installation packages are available for
|
||||
|
||||
|
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 387 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 185 KiB |
|
After Width: | Height: | Size: 110 KiB |
|
Before Width: | Height: | Size: 135 KiB After Width: | Height: | Size: 156 KiB |
|
Before Width: | Height: | Size: 142 KiB After Width: | Height: | Size: 237 KiB |
|
Before Width: | Height: | Size: 208 KiB After Width: | Height: | Size: 183 KiB |
|
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 147 KiB |
|
After Width: | Height: | Size: 112 KiB |
|
After Width: | Height: | Size: 56 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 58 KiB |
|
After Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 80 KiB |
|
Before Width: | Height: | Size: 96 KiB After Width: | Height: | Size: 100 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 53 KiB |
@@ -4,7 +4,12 @@
|
||||
`Enabling Kerberos Authentication`:index:
|
||||
*****************************************
|
||||
|
||||
To configure Kerberos authentication, you must set your Kerberos Server and generate the *kinit* ticket on the client. To enable the Kerberos authentication for pgAdmin, you must configure the Kerberos settings in *config_local.py* or *config_system.py* (see the :ref:`config.py <config_py>` documentation) on the system where pgAdmin is installed in Server mode. You can copy these settings from *config.py* file and modify the values for the following parameters.
|
||||
To configure Kerberos authentication, you must setup your Kerberos Server and
|
||||
generate a ticket on the client using *kinit*. To enable Kerberos authentication
|
||||
for pgAdmin, you must configure the Kerberos settings in *config_local.py* or
|
||||
*config_system.py* (see the :ref:`config.py <config_py>` documentation) on the
|
||||
system where pgAdmin is installed in Server mode. You can copy these settings
|
||||
from *config.py* file and modify the values for the following parameters.
|
||||
|
||||
.. csv-table::
|
||||
:header: "**Parameter**", "**Description**"
|
||||
@@ -12,25 +17,43 @@ To configure Kerberos authentication, you must set your Kerberos Server and gene
|
||||
:widths: 35, 55
|
||||
|
||||
"AUTHENTICATION_SOURCES","The default value for this parameter is *internal*.
|
||||
To enable Kerberos authentication, you must include *kerberos* in the list of values for this parameter. you can modify the value as follows:
|
||||
To enable Kerberos authentication, you must include *kerberos* in the
|
||||
list of values for this parameter. you can modify the value as follows:
|
||||
|
||||
* [‘kerberos’]: pgAdmin will use only Kerberos authentication.
|
||||
|
||||
* [‘kerberos’, ‘internal’]: pgAdmin will first try to authenticate the user through kerberos. If that authentication fails, then it will return back to the login dialog where you need to provide internal pgAdmin user credentials for authentication."
|
||||
"KERBEROS_AUTO_CREATE_USER", "Specify value to *True* if you want to automatically create a pgAdmin user corresponding to the kerberos user credentials. Please note that password is not stored in the pgAdmin database."
|
||||
"KRB_APP_HOST_NAME", "Specify the name of *pgAdmin webserver hostname*. Please note that if it is not set, it will take the value of *default_server* parameter."
|
||||
* [‘kerberos’, ‘internal’]: pgAdmin will first try to authenticate the user
|
||||
through kerberos. If that authentication fails, then it will return back
|
||||
to the login dialog where you need to provide internal pgAdmin user
|
||||
credentials for authentication."
|
||||
"KERBEROS_AUTO_CREATE_USER", "Set the value to *True* if you want to
|
||||
automatically create a pgAdmin user corresponding to a successfully
|
||||
authenticated Kerberos user. Please note that password is not stored in the
|
||||
pgAdmin database."
|
||||
"KRB_APP_HOST_NAME", "Specify the name of *pgAdmin webserver hostname*.
|
||||
Please note that if it is not set, it will take the value of
|
||||
*default_server* parameter."
|
||||
|
||||
|
||||
Keytab file for HTTP Service
|
||||
============================
|
||||
|
||||
* Generate the *Keytab* file for the HTTP service principal and copy it to the *pgAdmin* webserver machine. Ensure that the operating system user owning the *pgAdmin* webserver is the owner of this file and should be accessible by that user.
|
||||
* Generate the *Keytab* file for the HTTP service principal and copy it to the
|
||||
*pgAdmin* webserver machine. Ensure that the operating system user owning
|
||||
the *pgAdmin* webserver is the owner of this file and should be accessible
|
||||
by that user.
|
||||
|
||||
* Please note that either you should set *default_keytab_name* parameter in *krb5.conf* file or the environment variable *KRB5_KTNAME*. If not set then explicitly set *KRB_KTNAME* to the location of your *Keytab* file in the *config_local.py* or *config_system.py* file.
|
||||
* Please note that either you should set *default_keytab_name* parameter in
|
||||
*krb5.conf* file or the environment variable *KRB5_KTNAME*. If not set then
|
||||
explicitly set *KRB_KTNAME* to the location of your *Keytab* file in the
|
||||
*config_local.py* or *config_system.py* file.
|
||||
|
||||
Apache HTTPD Configuration
|
||||
==========================
|
||||
|
||||
If the *pgAdmin* server is under the Apache Server, then you need to add the following parameters in *Directory* directive of :ref:`Apache HTTPD Configuration <server_deployment>`:
|
||||
If the *pgAdmin* server is under the Apache Server, then you need to add the
|
||||
following parameters in *Directory* directive of
|
||||
:ref:`Apache HTTPD Configuration <server_deployment>`:
|
||||
|
||||
* WSGIScriptReloading On
|
||||
|
||||
@@ -40,30 +63,67 @@ If the *pgAdmin* server is under the Apache Server, then you need to add the fol
|
||||
Browser settings to configure Kerberos Authentication
|
||||
=====================================================
|
||||
|
||||
You need to do the browser settings on the client machine to use the *Spnego/Kerberos*.
|
||||
You need to configure the browser settings on the client machine to use
|
||||
Kerberos authentication via *SPNEGO*.
|
||||
|
||||
- For Mozilla Firefox
|
||||
|
||||
- Open the low level Firefox configuration page by loading the *about:config* page.
|
||||
- Open the low level Firefox configuration page by entering *about:config* in
|
||||
the address bar.
|
||||
- In the Search text box, enter: *network.negotiate-auth.trusted-uris*
|
||||
- Double-click the *network.negotiate-auth.trusted-uris* preference and enter the hostname or the domain of the web server that is protected by Kerberos HTTP SPNEGO. Separate multiple domains and hostnames with a comma.
|
||||
- Double-click the *network.negotiate-auth.trusted-uris* preference and enter
|
||||
the hostname or the domain of the web server that is protected by Kerberos
|
||||
HTTP SPNEGO. Separate multiple domains and hostnames with a comma.
|
||||
- Click OK.
|
||||
|
||||
- For Google Chrome
|
||||
|
||||
- For Windows:
|
||||
- On Windows:
|
||||
|
||||
* Open the Control Panel to access the Internet Options dialog.
|
||||
* Select the Security tab.
|
||||
* Select the Local Intranet zone and click the Sites button.
|
||||
* Make sure that the first two options, Include all local (intranet) sites not listed in other zones and Include all sites that bypass the proxy server are checked.
|
||||
* Click Advanced and add the names of the domains that are protected by Kerberos HTTP SPNEGO, one at a time, to the list of websites. For example, myhost.example.com. Click Close.
|
||||
* Make sure that the first two options, *Include all local (intranet) sites
|
||||
not listed in other zones* and *Include all sites that bypass the proxy
|
||||
server* are checked.
|
||||
* Click Advanced and add the names of the domains that are protected by
|
||||
Kerberos HTTP SPNEGO, one at a time, to the list of websites. For example,
|
||||
myhost.example.com. Click Close.
|
||||
* Click OK to save your configuration changes.
|
||||
|
||||
- For Linux or MacOS:
|
||||
- On Linux or macOS:
|
||||
|
||||
* Add the *--auth-server-whitelist* parameter to the google-chrome command. For example, to run Chrome from a Linux prompt, run the google-chrome command as follows:
|
||||
* Add the *--auth-server-whitelist* parameter to the google-chrome command.
|
||||
For example, to run Chrome from a Linux prompt, run the google-chrome
|
||||
command as follows:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
google-chrome --auth-server-whitelist = "hostname/domain"
|
||||
|
||||
|
||||
PostgreSQL Server settings to configure Kerberos Authentication
|
||||
===============================================================
|
||||
|
||||
* To connect the PostgreSQL server with Kerberos authentication, GSSAPI support
|
||||
has to be enabled when PostgreSQL is built and the necessary
|
||||
`configuration <https://www.postgresql.org/docs/current/gssapi-auth.html>`_
|
||||
has to be in place.
|
||||
|
||||
* In pgAdmin you need to enable Kerberos authentication for the PostgreSQL
|
||||
server by setting "Kerberos authentication" flag to True in the Server dialog.
|
||||
Once it is enabled, pgAdmin will not prompt for a password and will try to
|
||||
connect to the PostgreSQL server using Kerberos.
|
||||
|
||||
* Note that, you have to login into pgAdmin with Kerberos authentication to
|
||||
then connect to PostgreSQL using Kerberos.
|
||||
|
||||
|
||||
Master Password
|
||||
===============
|
||||
|
||||
In the multi user mode, pgAdmin uses user's login password to encrypt/decrypt the PostgreSQL server password.
|
||||
In the Kerberos authentication, the pgAdmin user does not have the password, so we need an encryption key to store
|
||||
the PostgreSQL server password for the servers which are not configured to use the Kerberos authentication.
|
||||
To accomplish this, set the configuration parameter MASTER_PASSWORD to *True*, so upon setting the master password,
|
||||
it will be used as an encryption key while storing the password. If it is False, the server password can not be stored.
|
||||
@@ -10,16 +10,16 @@ Use the *Login* dialog to log in to pgAdmin:
|
||||
:alt: pgAdmin login dialog
|
||||
:align: center
|
||||
|
||||
Use the fields in the *Login* dialog to authenticate your connection. There are
|
||||
Use the fields in the *Login* dialog to authenticate your connection. There are
|
||||
two ways to authenticate your connection:
|
||||
|
||||
- From pgAdmin version 4.21 onwards, support for LDAP authentication
|
||||
has been added. If LDAP authentication has been enabled for your pgAdmin
|
||||
application, you can use your LDAP credentials to log in to pgAdmin:
|
||||
|
||||
* Provide the LDAP username in the *Email Address/Username* field.
|
||||
* Provide the LDAP username in the *Email Address/Username* field.
|
||||
|
||||
* Provide your LDAP password in the Password field.
|
||||
* Provide your LDAP password in the Password field.
|
||||
|
||||
- Alternatively, you can use the following information to log in to pgAdmin:
|
||||
|
||||
@@ -53,6 +53,13 @@ If you have forgotten the email associated with your account, please contact
|
||||
your administrator.
|
||||
|
||||
Please note that your LDAP password cannot be recovered using this dialog. If
|
||||
you enter your LDAP username in the *Email Address/Username* field, and then
|
||||
you enter your LDAP username in the *Email Address/Username* field, and then
|
||||
enter your email to recover your password, an error message will be displayed
|
||||
asking you to contact the LDAP administrator to recover your LDAP password.
|
||||
|
||||
Avoiding a bruteforce attack
|
||||
****************************
|
||||
|
||||
You have the possibility to lock an account by setting ``MAX_LOGIN_ATTEMPTS``
|
||||
once it has reached the maximum number of login attempts.
|
||||
You can disable this feature by setting the value to zero.
|
||||
@@ -18,4 +18,5 @@ database, right-click on the *Databases* node, and select *Create Database...*
|
||||
move_objects
|
||||
resource_group_dialog
|
||||
role_dialog
|
||||
tablespace_dialog
|
||||
tablespace_dialog
|
||||
role_reassign_dialog
|
||||
@@ -21,7 +21,7 @@ Use the *File* menu to access the following options:
|
||||
+-------------------------+---------------------------------------------------------------------------------------------------------+
|
||||
| Option | Action |
|
||||
+=========================+=========================================================================================================+
|
||||
| *Preferences* | Click to open the :ref:`Preferences <preferences>` dialog to to customize your pgAdmin settings. |
|
||||
| *Preferences* | Click to open the :ref:`Preferences <preferences>` dialog to customize your pgAdmin settings. |
|
||||
+-------------------------+---------------------------------------------------------------------------------------------------------+
|
||||
| *Reset Layout* | If you have modified the workspace, click to restore the default layout. |
|
||||
+-------------------------+---------------------------------------------------------------------------------------------------------+
|
||||
@@ -128,6 +128,8 @@ Use the *Tools* menu to access the following options (in alphabetical order):
|
||||
+---------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| *Search Objects...* | Click to open the :ref:`Search Objects... <search_objects>` and start searching any kind of objects in a database. |
|
||||
+---------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
| *PSQL Tool* | Click to open the :ref:`PSQL Tool <psql_tool>` and start PSQL in the current database context. |
|
||||
+---------------------------+-------------------------------------------------------------------------------------------------------------------------------------------+
|
||||
|
||||
The Help Menu
|
||||
*************
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
`Move Objects Dialog`:index:
|
||||
****************************
|
||||
|
||||
Use the *Move Objects* dialog to to move database objects from one tablespace to
|
||||
Use the *Move Objects* dialog to move database objects from one tablespace to
|
||||
another tablespace.
|
||||
|
||||
The *Move Objects* dialog organizes the movement of database objects with the
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
.. _oauth2:
|
||||
|
||||
*****************************************
|
||||
`Enabling OAUTH2 Authentication`:index:
|
||||
*****************************************
|
||||
|
||||
|
||||
To enable OAUTH2 authentication for pgAdmin, you must configure the OAUTH2
|
||||
settings in the *config_local.py* or *config_system.py* file (see the
|
||||
:ref:`config.py <config_py>` documentation) on the system where pgAdmin is
|
||||
installed in Server mode. You can copy these settings from *config.py* file
|
||||
and modify the values for the following parameters:
|
||||
|
||||
|
||||
.. csv-table::
|
||||
:header: "**Parameter**", "**Description**"
|
||||
:class: longtable
|
||||
:widths: 35, 55
|
||||
|
||||
"AUTHENTICATION_SOURCES", "The default value for this parameter is *internal*.
|
||||
To enable OAUTH2 authentication, you must include *oauth2* in the list of values
|
||||
for this parameter. you can modify the value as follows:
|
||||
|
||||
* [‘oauth2’, ‘internal’]: pgAdmin will display an additional button for authenticating with oauth2"
|
||||
"OAUTH2_NAME", "The name of the Oauth2 provider, ex: Google, Github"
|
||||
"OAUTH2_DISPLAY_NAME", "Oauth2 display name in pgAdmin"
|
||||
"OAUTH2_CLIENT_ID", "Oauth2 Client ID"
|
||||
"OAUTH2_CLIENT_SECRET", "Oauth2 Client Secret"
|
||||
"OAUTH2_TOKEN_URL", "Oauth2 Access Token endpoint"
|
||||
"OAUTH2_AUTHORIZATION_URL", "Endpoint for user authorization"
|
||||
"OAUTH2_API_BASE_URL", "Oauth2 base URL endpoint to make requests simple, ex: *https://api.github.com/*"
|
||||
"OAUTH2_USERINFO_ENDPOINT", "User Endpoint, ex: *user* (for github) and *useinfo* (for google)"
|
||||
"OAUTH2_ICON", "The Font-awesome icon to be placed on the oauth2 button, ex: fa-github"
|
||||
"OAUTH2_BUTTON_COLOR", "Oauth2 button color"
|
||||
"OAUTH2_AUTO_CREATE_USER", "Set the value to *True* if you want to automatically
|
||||
create a pgAdmin user corresponding to a successfully authenticated Oauth2 user.
|
||||
Please note that password is not stored in the pgAdmin database."
|
||||
|
||||
Redirect URL
|
||||
============
|
||||
|
||||
The redirect url to configure Oauth2 server is *http://<pgAdmin Server URL>/oauth2/authorize*
|
||||
|
||||
Master Password
|
||||
===============
|
||||
|
||||
In the multi user mode, pgAdmin uses user's login password to encrypt/decrypt the PostgreSQL server password.
|
||||
In the Oauth2 authentication, the pgAdmin does not store the user's password, so we need an encryption key to store
|
||||
the PostgreSQL server password.
|
||||
To accomplish this, set the configuration parameter MASTER_PASSWORD to *True*, so upon setting the master password,
|
||||
it will be used as an encryption key while storing the password. If it is False, the server password can not be stored.
|
||||
|
||||
|
||||
Login Page
|
||||
============
|
||||
|
||||
After configuration, on restart, you can see the login page with the Oauth2 login button(s).
|
||||
|
||||
.. image:: images/oauth2_login.png
|
||||
:alt: Oauth2 login
|
||||
:align: center
|
||||
@@ -45,7 +45,7 @@ Click the *Security* tab to continue.
|
||||
:alt: Package dialog security tab
|
||||
:align: center
|
||||
|
||||
Use the fields in the *Security* tab to to assign EXECUTE privileges for the
|
||||
Use the fields in the *Security* tab to assign EXECUTE privileges for the
|
||||
package to a role. Click the *Add* icon (+) to set privileges for the package:
|
||||
|
||||
* Select the name of the role from the drop-down listbox in the *Grantee* field.
|
||||
|
||||
@@ -154,6 +154,9 @@ the graphs on the *Dashboard* tab:
|
||||
:alt: Preferences dialog dashboard display options
|
||||
:align: center
|
||||
|
||||
* Set the warning and alert threshold value to highlight the long-running
|
||||
queries on the dashboard.
|
||||
|
||||
* When the *Show activity?* switch is set to *True*, activity tables will be
|
||||
displayed on dashboards.
|
||||
|
||||
@@ -211,21 +214,23 @@ files.
|
||||
:align: center
|
||||
|
||||
Use the fields on the *Binary paths* panel to specify the path to the directory
|
||||
that contains the utility programs (pg_dump, pg_restore, and pg_dumpall) for
|
||||
that contains the utility programs (pg_dump, pg_dumpall, pg_restore and psql) for
|
||||
monitored databases:
|
||||
|
||||
* Use the *EDB Advanced Server Binary Path* field to specify the location of the
|
||||
EDB Postgres Advanced Server utility programs. If this path is not set,
|
||||
pgAdmin will attempt to find the utilities in standard locations used by
|
||||
EnterpriseDB.
|
||||
* Use the *EDB Advanced Server Binary Path* grid to specify the location of the
|
||||
EDB Postgres Advanced Server utility programs based on the server version.
|
||||
If the respective path is not set, then pgAdmin will pick up the path for which
|
||||
'Set as default' is checked else pgAdmin will attempt to find the utilities in
|
||||
standard locations used by EnterpriseDB.
|
||||
|
||||
* Use the *Greenplum Database Binary Path* field to specify the location of the
|
||||
Greenplum database utility programs. If this path is not set, pgAdmin will
|
||||
attempt to find the utilities in standard locations used by Greenplum.
|
||||
* Use the *PostgreSQL Binary Path* grid to specify the location of the
|
||||
PostgreSQL utility programs based on the server version. If the respective
|
||||
path is not set, then pgAdmin will pick up the path for which 'Set as default'
|
||||
is checked else pgAdmin will attempt to find the utilities in standard
|
||||
locations used by PostgreSQL.
|
||||
|
||||
* Use the *PostgreSQL Binary Path* field to specify the location of the
|
||||
PostgreSQL utility programs. If this path is not set, pgAdmin will attempt
|
||||
to find the utilities in standard locations used by PostgreSQL.
|
||||
**Note:** Use the 'Validate path' button to check the existence of the utility
|
||||
programs (pg_dump, pg_dumpall, pg_restore and psql) and there respective versions.
|
||||
|
||||
.. image:: images/preferences_paths_help.png
|
||||
:alt: Preferences dialog binary path help section
|
||||
@@ -348,6 +353,10 @@ Use the fields on the *Options* panel to manage editor preferences.
|
||||
* When the *Auto-Rollback?* switch is set to *True*, failed queries are rolled
|
||||
back.
|
||||
|
||||
* When the *Copy SQL from main window to query tool?* switch is set to *True*,
|
||||
the CREATE sql of the selected object will be copied to query tool when query tool
|
||||
will open.
|
||||
|
||||
* When the *Prompt to save unsaved data changes?* switch is set to *True*, the
|
||||
editor will prompt the user to saved unsaved data when exiting the data
|
||||
editor.
|
||||
@@ -372,6 +381,13 @@ Use the fields on the *Options* panel to manage editor preferences.
|
||||
Use the fields on the *Results grid* panel to specify your formatting
|
||||
preferences for copied data.
|
||||
|
||||
* When the *Columns sized by* is set to *Column data*, then data columns will
|
||||
auto-size to the maximum width of the data in the column as loaded in the
|
||||
first batch. If set to *Column name*, the column will be sized to the widest
|
||||
of the data type or column name.
|
||||
* Specify the maximum width of the column in pixels when 'Columns sized by' is
|
||||
set to *Column data*. If 'Columns sized by' is set to *Column name* then this
|
||||
setting won't have any effect.
|
||||
* Use the *Result copy field separator* drop-down listbox to select the field
|
||||
separator for copied data.
|
||||
* Use the *Result copy quote character* drop-down listbox to select the quote
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
.. _psql_tool:
|
||||
|
||||
******************
|
||||
`PSQL Tool`:index:
|
||||
******************
|
||||
|
||||
The PSQL tool allows users to connect to PostgreSQL or EDB Advanced server using
|
||||
the psql command line interface through their browser.
|
||||
|
||||
* Open the PSQL tool from the Tools or browser tree context menu, or use PSQL
|
||||
tool button at the top of the browser tree.
|
||||
|
||||
* PSQL will connect to the current connected database from the browser tree.
|
||||
|
||||
.. image:: images/psql_tool.png
|
||||
:alt: PSQL tool window
|
||||
:align: center
|
||||
|
||||
You can open multiple instances of the PSQL tool in individual tabs simultaneously.
|
||||
To close the PSQL tool, click the *X* in the upper-right hand corner of the tab bar.
|
||||
|
||||
**Note:** On the Windows platform, this feature is available on Windows 10 (1809
|
||||
version), and Windows Server 2019 and onwards.
|
||||
|
||||
**Note:** The PSQL tool is always available when pgAdmin is running in Desktop
|
||||
mode, but is disabled by default in Server mode. This is because users can run
|
||||
arbitrary shell commands through psql which may be considered a security risk in
|
||||
some deployments. System Administrators can enable the use of the PSQL tool in
|
||||
the pgAdmin configuration by setting the *ENABLE_PSQL* option to *True*; see
|
||||
:ref:`config_py` for more information.
|
||||
@@ -11,6 +11,10 @@ notes for it.
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
release_notes_5_6
|
||||
release_notes_5_5
|
||||
release_notes_5_4
|
||||
release_notes_5_3
|
||||
release_notes_5_2
|
||||
release_notes_5_1
|
||||
release_notes_5_0
|
||||
|
||||
@@ -23,7 +23,7 @@ Bug fixes
|
||||
| `Issue #5908 <https://redmine.postgresql.org/issues/5908>`_ - Fixed an issue where shortcut keys are not working with manage macro.
|
||||
| `Issue #6076 <https://redmine.postgresql.org/issues/6076>`_ - Fixed an issue where correct error not thrown while importing servers and JSON file has incorrect/insufficient keys.
|
||||
| `Issue #6082 <https://redmine.postgresql.org/issues/6082>`_ - Ensure that the user should not be to change the connection when a long query is running.
|
||||
| `Issue #6106 <https://redmine.postgresql.org/issues/6106>`_ - Fixed flickering issue of the input box on check constraints.
|
||||
| `Issue #6107 <https://redmine.postgresql.org/issues/6107>`_ - Fixed flickering issue of the input box on check constraints.
|
||||
| `Issue #6161 <https://redmine.postgresql.org/issues/6161>`_ - Fixed an issue where the cursor shifts its focus to the wrong window for all the query tool related model dialogs.
|
||||
| `Issue #6220 <https://redmine.postgresql.org/issues/6220>`_ - Corrected the syntax for 'CREATE TRIGGER', use 'EXECUTE FUNCTION' instead of 'EXECUTE PROCEDURE' from v11 onwards.
|
||||
| `Issue #6274 <https://redmine.postgresql.org/issues/6274>`_ - Ensure that the strings in the LDAP auth module are translatable.
|
||||
@@ -40,4 +40,3 @@ Bug fixes
|
||||
| `Issue #6375 <https://redmine.postgresql.org/issues/6375>`_ - Fixed an issue where users are unable to see data of the partitions using the View/Edit data option.
|
||||
| `Issue #6376 <https://redmine.postgresql.org/issues/6376>`_ - Fixed an issue where a connection warning should be displayed on the user clicks on explain or explain analyze and the database server is disconnected from the browser tree.
|
||||
| `Issue #6379 <https://redmine.postgresql.org/issues/6379>`_ - Fixed an issue where foreign data wrapper properties are not visible if the host option contains two host addresses.
|
||||
| `Issue #6385 <https://redmine.postgresql.org/issues/6385>`_ - Ensure that Backup and Restore should work on shared servers.
|
||||
@@ -0,0 +1,44 @@
|
||||
************
|
||||
Version 5.3
|
||||
************
|
||||
|
||||
Release date: 2021-05-20
|
||||
|
||||
This release contains a number of bug fixes and new features since the release of pgAdmin4 5.2.
|
||||
|
||||
New features
|
||||
************
|
||||
|
||||
| `Issue #5954 <https://redmine.postgresql.org/issues/5954>`_ - Added support to set auto width of columns by content size in the data output window.
|
||||
| `Issue #6158 <https://redmine.postgresql.org/issues/6158>`_ - Added support to connect PostgreSQL servers via Kerberos authentication.
|
||||
| `Issue #6397 <https://redmine.postgresql.org/issues/6397>`_ - Added "IF NOT EXISTS" clause while creating tables and partition tables which is convenient while using the ERD tool.
|
||||
|
||||
Housekeeping
|
||||
************
|
||||
|
||||
|
||||
Bug fixes
|
||||
*********
|
||||
|
||||
| `Issue #4436 <https://redmine.postgresql.org/issues/4436>`_ - Fixed an issue where drag and drop object is not correct in codemirror for properties dialog.
|
||||
| `Issue #5477 <https://redmine.postgresql.org/issues/5477>`_ - Added support for cache bust webpack chunk files.
|
||||
| `Issue #5555 <https://redmine.postgresql.org/issues/5555>`_ - Fixed an issue where data is displayed in the wrong order when executing the query repeatedly.
|
||||
| `Issue #5776 <https://redmine.postgresql.org/issues/5776>`_ - Ensure that while connecting to the server using SSPI login, it should not prompt for the password.
|
||||
| `Issue #6329 <https://redmine.postgresql.org/issues/6329>`_ - Fixed an issue where the wrong SQL is showing for the child partition tables.
|
||||
| `Issue #6341 <https://redmine.postgresql.org/issues/6341>`_ - Fixed an issue where CSV download quotes the numeric columns.
|
||||
| `Issue #6355 <https://redmine.postgresql.org/issues/6355>`_ - Ensure that pgAdmin should not allow opening external files that are dragged into it.
|
||||
| `Issue #6377 <https://redmine.postgresql.org/issues/6377>`_ - Fixed an issue where schema diff does not create DROP DEFAULT statement for columns.
|
||||
| `Issue #6385 <https://redmine.postgresql.org/issues/6385>`_ - Ensure that Backup and Restore should work on shared servers.
|
||||
| `Issue #6392 <https://redmine.postgresql.org/issues/6392>`_ - Fixed an issue where the filter 'Include/Exclude By Selection' not working for null values.
|
||||
| `Issue #6399 <https://redmine.postgresql.org/issues/6399>`_ - Ensure that the user should not be able to add duplicate panels.
|
||||
| `Issue #6407 <https://redmine.postgresql.org/issues/6407>`_ - Added support for the creation of Nested Table and Varying Array Type for Advanced Server.
|
||||
| `Issue #6408 <https://redmine.postgresql.org/issues/6408>`_ - Fixed ModuleNotFoundError when running setup.py from outside of the root.
|
||||
| `Issue #6409 <https://redmine.postgresql.org/issues/6409>`_ - Fixed an issue where the current debug line is not visible in the 'Dark' theme.
|
||||
| `Issue #6413 <https://redmine.postgresql.org/issues/6413>`_ - Fixed an issue where duplicate columns are visible in the browser tree, which is owned by two sequences.
|
||||
| `Issue #6414 <https://redmine.postgresql.org/issues/6414>`_ - Fixed an issue where the Help message not displaying correctly on Login/Group role.
|
||||
| `Issue #6416 <https://redmine.postgresql.org/issues/6416>`_ - Added comment column in the properties panel for View and Materialized View collection node.
|
||||
| `Issue #6417 <https://redmine.postgresql.org/issues/6417>`_ - Fixed an issue where query editor is not being closed if the user clicks on the 'Don't Save' button.
|
||||
| `Issue #6420 <https://redmine.postgresql.org/issues/6420>`_ - Ensure that pgAdmin4 shut down completely on the Quit command.
|
||||
| `Issue #6443 <https://redmine.postgresql.org/issues/6443>`_ - Fixed an issue where file dialog showing incorrect files for the selected file types.
|
||||
| `Issue #6444 <https://redmine.postgresql.org/issues/6444>`_ - Fixed an issue where the user is not warned if Kerberos ticket expiration is less than 30 min while initiating a global backup.
|
||||
| `Issue #6445 <https://redmine.postgresql.org/issues/6445>`_ - Ensure that proper identification should be there when the server is connected using Kerberos or without Kerberos.
|
||||
@@ -0,0 +1,40 @@
|
||||
************
|
||||
Version 5.4
|
||||
************
|
||||
|
||||
Release date: 2021-06-17
|
||||
|
||||
This release contains a number of bug fixes and new features since the release of pgAdmin4 5.3.
|
||||
|
||||
New features
|
||||
************
|
||||
|
||||
| `Issue #1561 <https://redmine.postgresql.org/issues/1561>`_ - Added browse button to select the binary path in the Preferences.
|
||||
| `Issue #1591 <https://redmine.postgresql.org/issues/1591>`_ - Added Grant Wizard option under Package node.
|
||||
| `Issue #2341 <https://redmine.postgresql.org/issues/2341>`_ - Added support to launch PSQL for the connected database server.
|
||||
| `Issue #4064 <https://redmine.postgresql.org/issues/4064>`_ - Added window maximize/restore functionality for properties dialog.
|
||||
| `Issue #5370 <https://redmine.postgresql.org/issues/5370>`_ - Added support to set the binary path for the different database server versions.
|
||||
| `Issue #6231 <https://redmine.postgresql.org/issues/6231>`_ - Added OS, Browser, Configuration details in the About dialog.
|
||||
| `Issue #6395 <https://redmine.postgresql.org/issues/6395>`_ - Added support for rotating the pgAdmin log file on the basis of size and age.
|
||||
| `Issue #6524 <https://redmine.postgresql.org/issues/6524>`_ - Support non-admin installation on Windows.
|
||||
|
||||
|
||||
Housekeeping
|
||||
************
|
||||
|
||||
| `Issue #4622 <https://redmine.postgresql.org/issues/4622>`_ - Added RESQL/MSQL test cases for Table and its child nodes.
|
||||
| `Issue #6225 <https://redmine.postgresql.org/issues/6225>`_ - Updated Flask-Security-Too to the latest v4.
|
||||
| `Issue #6460 <https://redmine.postgresql.org/issues/6460>`_ - Added a mechanism to detect a corrupt/broken config database file.
|
||||
|
||||
Bug fixes
|
||||
*********
|
||||
|
||||
| `Issue #4203 <https://redmine.postgresql.org/issues/4203>`_ - Fixed the issue of renaming the database by another user.
|
||||
| `Issue #6404 <https://redmine.postgresql.org/issues/6404>`_ - Ensure that the Query Tool connection string should not be changed as per the 'Query Tool tab title'.
|
||||
| `Issue #6466 <https://redmine.postgresql.org/issues/6466>`_ - Ensure that the user should be able to add members in Login/Role group while creating it.
|
||||
| `Issue #6469 <https://redmine.postgresql.org/issues/6469>`_ - Ensure that the calendar control should be disabled in the properties panel for Role.
|
||||
| `Issue #6473 <https://redmine.postgresql.org/issues/6473>`_ - Disable browser password saving in the runtime.
|
||||
| `Issue #6478 <https://redmine.postgresql.org/issues/6478>`_ - Fixed duplicate SQL issue for tables with more than one partition.
|
||||
| `Issue #6482 <https://redmine.postgresql.org/issues/6482>`_ - Fixed an issue where the Foreground Color property of server dialog does not work.
|
||||
| `Issue #6513 <https://redmine.postgresql.org/issues/6513>`_ - Fixed an issue where pgAdmin does not open after password reset in server mode.
|
||||
| `Issue #6520 <https://redmine.postgresql.org/issues/6520>`_ - Fixed an issue where a decimal number is appended for character varying fields while downloading the data in CSV format.
|
||||
@@ -0,0 +1,37 @@
|
||||
************
|
||||
Version 5.5
|
||||
************
|
||||
|
||||
Release date: 2021-07-15
|
||||
|
||||
This release contains a number of bug fixes and new features since the release of pgAdmin4 5.4.
|
||||
|
||||
New features
|
||||
************
|
||||
|
||||
| `Issue #1975 <https://redmine.postgresql.org/issues/1975>`_ - Highlighted long running queries on the dashboards.
|
||||
| `Issue #3893 <https://redmine.postgresql.org/issues/3893>`_ - Added support for Reassign/Drop Owned for login roles.
|
||||
| `Issue #3920 <https://redmine.postgresql.org/issues/3920>`_ - Do not block the query editor window when running a query.
|
||||
| `Issue #5940 <https://redmine.postgresql.org/issues/5940>`_ - Added support for OAuth 2 authentication.
|
||||
| `Issue #6559 <https://redmine.postgresql.org/issues/6559>`_ - Added option to provide maximum width of the column when 'Resize by data?’ option in the preferences is set to True.
|
||||
|
||||
Housekeeping
|
||||
************
|
||||
|
||||
|
||||
Bug fixes
|
||||
*********
|
||||
|
||||
| `Issue #4189 <https://redmine.postgresql.org/issues/4189>`_ - Ensure that the Data Output panel can be snapped back after it is detached.
|
||||
| `Issue #6388 <https://redmine.postgresql.org/issues/6388>`_ - Fixed replace keyboard shortcut issue in the query tool on the normal keyboard layout.
|
||||
| `Issue #6398 <https://redmine.postgresql.org/issues/6398>`_ - Fixed an issue where detaching the query editor panel gives a blank white panel.
|
||||
| `Issue #6427 <https://redmine.postgresql.org/issues/6427>`_ - Remove leading whitespace and replace it with '[...] ' in the Query Tool data grid so cells don't look empty.
|
||||
| `Issue #6448 <https://redmine.postgresql.org/issues/6448>`_ - Fixed an issue in the search object when searching in 'all types' or 'subscription' if the user doesn't have access to the subscription.
|
||||
| `Issue #6489 <https://redmine.postgresql.org/issues/6489>`_ - Fixed an issue where Execute/Refresh button should not be disabled when we run the empty query.
|
||||
| `Issue #6505 <https://redmine.postgresql.org/issues/6505>`_ - Fixed an issue where the New Connection Drop Down has lost default maintenance database, auto-select, and tab-through functionality.
|
||||
| `Issue #6536 <https://redmine.postgresql.org/issues/6536>`_ - Fixed directory selection issue with the folder dialog.
|
||||
| `Issue #6541 <https://redmine.postgresql.org/issues/6541>`_ - Ensure that setting 'Open in new browser tab' should be visible, it should not be based on the value of 'ENABLE_PSQL'.
|
||||
| `Issue #6547 <https://redmine.postgresql.org/issues/6547>`_ - Fixed copy/paste issues for PSQL tool terminal.
|
||||
| `Issue #6550 <https://redmine.postgresql.org/issues/6550>`_ - Disable email deliverability check that was introduced in flask-security-too by default to maintain backwards compatibility.
|
||||
| `Issue #6555 <https://redmine.postgresql.org/issues/6555>`_ - Fixed Czech translation string for 'Login' keyword.
|
||||
| `Issue #6557 <https://redmine.postgresql.org/issues/6557>`_ - Fixed an issue where incorrect column name listed in the properties of Index.
|
||||
@@ -0,0 +1,33 @@
|
||||
************
|
||||
Version 5.6
|
||||
************
|
||||
|
||||
Release date: 2021-08-12
|
||||
|
||||
This release contains a number of bug fixes and new features since the release of pgAdmin4 5.5.
|
||||
|
||||
New features
|
||||
************
|
||||
|
||||
| `Issue #4904 <https://redmine.postgresql.org/issues/4904>`_ - Added support to copy SQL from main window to query tool.
|
||||
| `Issue #5198 <https://redmine.postgresql.org/issues/5198>`_ - Added support for formatted JSON viewer/editor when interacting with data in a JSON column.
|
||||
|
||||
Housekeeping
|
||||
************
|
||||
|
||||
| `Issue #6622 <https://redmine.postgresql.org/issues/6622>`_ - Rename the "Resize by data?" to "Columns sized by" and disabled the 'Maximum column width' button if 'Columns sized by' is set to 'Column data'.
|
||||
|
||||
Bug fixes
|
||||
*********
|
||||
|
||||
| `Issue #6337 <https://redmine.postgresql.org/issues/6337>`_ - Ensure that the login account should be locked after N number of attempts. N is configurable using the 'MAX_LOGIN_ATTEMPTS' parameter.
|
||||
| `Issue #6369 <https://redmine.postgresql.org/issues/6369>`_ - Fixed CSRF errors for stale sessions by increasing the session expiration time for desktop mode.
|
||||
| `Issue #6448 <https://redmine.postgresql.org/issues/6448>`_ - Fixed an issue in the search object when searching in 'all types' or 'subscription' if the user doesn't have access to the subscription.
|
||||
| `Issue #6574 <https://redmine.postgresql.org/issues/6574>`_ - Fixed an issue where paste is not working through Right-Click option on PSQL.
|
||||
| `Issue #6580 <https://redmine.postgresql.org/issues/6580>`_ - Fixed TypeError 'NoneType' object is not sub scriptable.
|
||||
| `Issue #6586 <https://redmine.postgresql.org/issues/6586>`_ - Fixed incorrect tablespace options in the drop-down for move objects dialog.
|
||||
| `Issue #6618 <https://redmine.postgresql.org/issues/6618>`_ - Fixed an issue where the titles in query tabs are different.
|
||||
| `Issue #6619 <https://redmine.postgresql.org/issues/6619>`_ - Fixed incorrect binary path issue when the user deletes the binary path from the preferences.
|
||||
| `Issue #6643 <https://redmine.postgresql.org/issues/6643>`_ - Ensure that all the required options should be loaded when the Range data type is selected while creating a custom data type.
|
||||
| `Issue #6650 <https://redmine.postgresql.org/issues/6650>`_ - Fixed dashboard server activity issue when active_since parameter is None.
|
||||
| `Issue #6664 <https://redmine.postgresql.org/issues/6664>`_ - Fixed an issue where even if the user is locked, he can reset the password and can login into pgAdmin.
|
||||
@@ -0,0 +1,50 @@
|
||||
.. _restore_locked_user:
|
||||
|
||||
*****************************
|
||||
`Lock/Restore Account`:index:
|
||||
*****************************
|
||||
|
||||
Account locking/unlocking via user management dialog:
|
||||
|
||||
An admin can lock and unlock user from the user management dialog. This allows the admin to lock or restore
|
||||
the user when there are several failed login attempts. This page guides you through configuring per-user
|
||||
locking/restoring. For more details visit :ref:`User management <user_management>`.
|
||||
|
||||
.. csv-table::
|
||||
:header: "**Parameter**", "**Description**"
|
||||
:class: longtable
|
||||
:widths: 35, 55
|
||||
|
||||
"MAX_LOGIN_ATTEMPTS", "Which sets the number of failed login that
|
||||
are allowed. If this value is exceeded, the account is locked and can be reset by an administrator.
|
||||
By setting the variable to the value zero this feature is deactivated."
|
||||
|
||||
|
||||
When Administrator itself gets locked, following steps may be considered to restore it:
|
||||
|
||||
- Increase MAX_LOGIN_ATTEMPTS, and try to successfully login to restore the account.
|
||||
|
||||
OR
|
||||
|
||||
By updating SQLite DB (pgAdmin4.db):
|
||||
|
||||
* Locate the pgAdmin4.db file and open it using any DB Browser (or DB Browser for SQLite)
|
||||
* After opening the DB file, head towards 'Execute SQL' section.
|
||||
* Run below query -
|
||||
|
||||
*UPDATE USER SET LOCKED = false, LOGIN_ATTEMPTS = 0 WHERE USERNAME = <YOUR_EMAIL_ID>*
|
||||
|
||||
* Make sure the query changes are committed.
|
||||
|
||||
Account locking by failed login attempts:
|
||||
|
||||
.. image:: images/login_attempt_user.png
|
||||
:alt: Failed login attempt for current user
|
||||
:align: center
|
||||
|
||||
pgAdmin application is configured to lock a user account when a number of consecutive failed login attempts are
|
||||
exceeded.
|
||||
|
||||
MAX_LOGIN_ATTEMPTS is defaulted to 3 unsuccessful login attempts, after which the account would be locked.
|
||||
|
||||
The only way to restore the user account is by contacting the Administrator and ask to unlock it.
|
||||
@@ -0,0 +1,51 @@
|
||||
|
||||
.. _role_reassign_dialog:
|
||||
|
||||
**************************************
|
||||
`Role Reassign/Drop Own Dialog`:index:
|
||||
**************************************
|
||||
|
||||
Use the *Reassign/Drop Own* dialog to change the ownership of database objects owned
|
||||
by a database role. This dialog instructs the system to change the ownership of database
|
||||
objects owned by any of the *old_roles* to *new_role*.
|
||||
|
||||
The *Reassign/Drop Own* dialog organizes the Reassign & Drop role through General tab.
|
||||
|
||||
.. image:: images/role_reassign_dialog.png
|
||||
:alt: Reassign/Drop Own dialog
|
||||
:align: center
|
||||
|
||||
* Use the *Operation* field to provide Reassign option.
|
||||
* Provide a new role in the *Reassign Objects to* field; The ownership of all the objects within the selected database,
|
||||
and of all shared objects (databases, tablespaces), owned by the *old_role* will be reassigned to *new_role*.
|
||||
* Provide a database on which the reassignment is to be carried out.
|
||||
|
||||
The above example demonstrates reassigning *old_role* to *new_role*.
|
||||
|
||||
Click the *SQL* tab to continue.
|
||||
|
||||
.. image:: images/role_reassign_dialog_sql.png
|
||||
:alt: Reassign/Drop Own dialog sql
|
||||
:align: center
|
||||
|
||||
Removing database objects owned by a database role.
|
||||
|
||||
.. image:: images/role_drop_dialog.png
|
||||
:alt: Reassign/Drop Own dialog
|
||||
:align: center
|
||||
|
||||
* Use the *Operation* field to provide Drop option.
|
||||
* Use the *Cascade?* field to provide Yes, No is default.
|
||||
* Provide a database on which the drop of objects is to be carried out.
|
||||
|
||||
Click the *SQL* tab to continue.
|
||||
|
||||
.. image:: images/role_drop_dialog_sql.png
|
||||
:alt: Reassign/Drop Own dialog sql
|
||||
:align: center
|
||||
|
||||
The above examples demonstrates drop owned by *role*.
|
||||
|
||||
* Click the *Help* button (?) to access online help.
|
||||
* Click the *OK* button to save work.
|
||||
* Click the *Cancel* button to exit without saving work.
|
||||
@@ -31,15 +31,18 @@ Use the fields in the *General* tab to identify the server:
|
||||
connection to the server upon completion of the dialog; this is the default
|
||||
|
||||
* If the *Shared?* switch is moved to *Yes* then that server can be
|
||||
shared with all the other users. This option is available only to admin users. For more information on users see :ref:`User Management Dialog <user_management>`. The users can access the shared servers with some restritctions. The Users accessing the shared servers cannot do the following operations on the shared servers:
|
||||
shared with all the other users. This option is available only to admin users.
|
||||
For more information on users see :ref:`User Management Dialog <user_management>`.
|
||||
Users can access the shared servers with some restrictions - the following
|
||||
operations on shared servers are not permitted:
|
||||
|
||||
* Create a server
|
||||
* Delete the server
|
||||
* Rename the server
|
||||
* Rename the group server
|
||||
* Change of host, port, and maintenance database
|
||||
|
||||
Please note that once the server is shared, it's icon is changed in the browser tree.
|
||||
Please note that once the server is shared, it's icon is changed in the
|
||||
browser tree.
|
||||
|
||||
* Provide a comment about the server in the *Comments* field.
|
||||
|
||||
@@ -62,6 +65,8 @@ Use the fields in the *Connection* tab to configure a connection:
|
||||
installed on that database.
|
||||
* Use the *Username* field to specify the name of a role that will be used when
|
||||
authenticating with the server.
|
||||
* When *Kerberos authentication?* is set to *True*, pgAdmin will try to connect
|
||||
the PostgreSQL server using Kerberos authentication.
|
||||
* Use the *Password* field to provide a password that will be supplied when
|
||||
authenticating with the server.
|
||||
* Check the box next to *Save password?* to instruct pgAdmin to save the
|
||||
|
||||
@@ -365,7 +365,7 @@ Click the *Columns* tab to continue.
|
||||
:alt: Table dialog exclusion constraint columns
|
||||
:align: center
|
||||
|
||||
Use the fields in the *Columns* tab to to specify the column(s) to which the
|
||||
Use the fields in the *Columns* tab to specify the column(s) to which the
|
||||
constraint applies. Use the drop-down listbox next to *Column* to select a
|
||||
column and click the *Add* icon (+) to provide details of the action on the
|
||||
column:
|
||||
|
||||
@@ -20,4 +20,6 @@ the selected browser node.
|
||||
* Use the :ref:`Filtered Rows <viewdata_filter>` button to access the Data Filter popup
|
||||
to apply a filter to a set of data for viewing/editing.
|
||||
* Use the :ref:`Search objects <search_objects>` button to access the search objects
|
||||
dialog. It helps you search any database object.
|
||||
dialog. It helps you search any database object.
|
||||
* Use the :ref:`PSQL Tool <psql_tool>` button to open the PSQL in the current
|
||||
database context.
|
||||
@@ -123,7 +123,7 @@ Click the *Security* tab to continue.
|
||||
Use the *Security* tab to assign privileges and define security labels.
|
||||
|
||||
Use the *Privileges* panel to assign usage privileges for the trigger function
|
||||
to a role. Click the *Add* icon (+) to to add a role to the table.
|
||||
to a role. Click the *Add* icon (+) to add a role to the table.
|
||||
|
||||
* Select the name of the role from the drop-down listbox in the *Grantee* field.
|
||||
* Click inside the *Privileges* field. Check the boxes to the left of one or
|
||||
|
||||
@@ -58,6 +58,8 @@ Provide information about the new pgAdmin role in the row:
|
||||
as authentication source since LDAP password is not stored in the pgAdmin database.
|
||||
* Re-enter the password in the *Confirm password* field. This field is disabled
|
||||
if you select *ldap* as authentication source.
|
||||
* Move the *Locked* switch to the *True* position if you want to lock the account;
|
||||
the default is *False*. This functionality is useful when a user is locked by trying unsuccessful login attempts.
|
||||
|
||||
To discard a user, and revoke access to pgAdmin, click the trash icon to the
|
||||
left of the row and confirm deletion in the *Delete user?* dialog.
|
||||
|
||||
@@ -4,8 +4,7 @@
|
||||
set -e
|
||||
|
||||
# Debugging shizz
|
||||
trap 'last_command=$current_command; current_command=$BASH_COMMAND' DEBUG
|
||||
trap 'if [ $? -ne 0 ]; then echo "\"${last_command}\" command filed with exit code $?."; fi' EXIT
|
||||
trap 'ERRCODE=$? && if [ ${ERRCODE} -ne 0 ]; then echo "The command \"${BASH_COMMAND}\" failed in \"${FUNCNAME}\" with exit code ${ERRCODE}."; fi' EXIT
|
||||
|
||||
OS_VERSION=$(cat /etc/os-release | grep "^VERSION_ID=" | awk -F "=" '{ print $2 }' | sed 's/"//g')
|
||||
OS_NAME=$(cat /etc/os-release | grep "^ID=" | awk -F "=" '{ print $2 }' | sed 's/"//g')
|
||||
|
||||
@@ -5,6 +5,9 @@ if [ "$EUID" -ne 0 ]
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Running apt update..."
|
||||
apt update
|
||||
|
||||
echo "Installing system pre-requisites..."
|
||||
apt install -y curl apt-transport-https ca-certificates gnupg
|
||||
|
||||
|
||||
@@ -10,7 +10,12 @@ CA_FILE = '/etc/ssl/certs/ca-certificates.crt'
|
||||
LOG_FILE = '/dev/null'
|
||||
HELP_PATH = '../../docs'
|
||||
DEFAULT_BINARY_PATHS = {
|
||||
'pg': '/usr/local/pgsql-13'
|
||||
'pg': '/usr/local/pgsql-13',
|
||||
'pg-13': '/usr/local/pgsql-13',
|
||||
'pg-12': '/usr/local/pgsql-12',
|
||||
'pg-11': '/usr/local/pgsql-11',
|
||||
'pg-10': '/usr/local/pgsql-10',
|
||||
'pg-9.6': '/usr/local/pgsql-9.6'
|
||||
}
|
||||
EOF
|
||||
|
||||
|
||||
@@ -6,8 +6,7 @@
|
||||
set -e -E
|
||||
|
||||
# Debugging shizz
|
||||
trap 'last_command=$current_command; current_command=$BASH_COMMAND' DEBUG
|
||||
trap 'if [ $? -ne 0 ]; then echo "\"${last_command}\" command filed with exit code $?."; fi' EXIT
|
||||
trap 'ERRCODE=$? && if [ ${ERRCODE} -ne 0 ]; then echo "The command \"${BASH_COMMAND}\" failed in \"${FUNCNAME}\" with exit code ${ERRCODE}."; fi' EXIT
|
||||
|
||||
SCRIPT_DIR=$(cd `dirname $0` && pwd)
|
||||
SOURCE_DIR=$(realpath ${SCRIPT_DIR}/../..)
|
||||
|
||||
@@ -4,8 +4,7 @@
|
||||
set -e
|
||||
|
||||
# Debugging shizz
|
||||
trap 'last_command=$current_command; current_command=$BASH_COMMAND' DEBUG
|
||||
trap 'if [ $? -ne 0 ]; then echo "\"${last_command}\" command filed with exit code $?."; fi' EXIT
|
||||
trap 'ERRCODE=$? && if [ ${ERRCODE} -ne 0 ]; then echo "The command \"${BASH_COMMAND}\" failed in \"${FUNCNAME}\" with exit code ${ERRCODE}."; fi' EXIT
|
||||
|
||||
OS_VERSION=$(cat /etc/os-release | grep "^VERSION_ID=" | awk -F "=" '{ print $2 }' | sed 's/"//g')
|
||||
OS_NAME=$(cat /etc/os-release | grep "^ID=" | awk -F "=" '{ print $2 }' | sed 's/"//g')
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Set the repo RPM version and build
|
||||
REPO_RPM_VERSION=1
|
||||
REPO_RPM_VERSION=2
|
||||
REPO_RPM_BUILD=1
|
||||
|
||||
# Set the repo base directory
|
||||
@@ -55,6 +55,7 @@ enabled=1
|
||||
EOF
|
||||
|
||||
if [ ${INCLUDE_KEY} -eq 1 ]; then
|
||||
echo repo_gpgcheck=1 >> "${BUILDROOT}/${DISTRO}-repo/etc/yum.repos.d/pgadmin4.repo"
|
||||
echo gpgcheck=1 >> "${BUILDROOT}/${DISTRO}-repo/etc/yum.repos.d/pgadmin4.repo"
|
||||
echo gpgkey=file:///etc/pki/rpm-gpg/PGADMIN_PKG_KEY >> "${BUILDROOT}/${DISTRO}-repo/etc/yum.repos.d/pgadmin4.repo"
|
||||
else
|
||||
|
||||
@@ -6,21 +6,27 @@ builds may still work with suitable adjustments.
|
||||
|
||||
## Installing build requirements
|
||||
|
||||
1. Install Visual Studio 2017 Pro from https://my.visualstudio.com/Downloads?q=Visual%20Studio%202017
|
||||
|
||||
Choose the Desktop development with C++ option.
|
||||
1. Install Visual Studio 2017 Pro from https://my.visualstudio.com/Downloads?q=Visual%20Studio%202017.
|
||||
Choose the Desktop development with C++ option, and ensure that you add the
|
||||
'Visual C++ MFC for x86 and x64' option.
|
||||
|
||||
2. Install Chocolatey from https://chocolatey.org/install#individual
|
||||
|
||||
3. Install various command line tools:
|
||||
|
||||
choco install -y bzip2 cmake diffutils dotnet3.5 gzip git innosetup nodejs-lts python strawberryperl wget yarn
|
||||
choco install -y awk bzip2 cmake diffutils dotnet3.5 gnuwin32-coreutils.install gzip git html-help-workshop innosetup nodejs-lts python sed strawberryperl wget yarn
|
||||
|
||||
4. Upgrade pip (this may give a permissions error that can be ignored):
|
||||
4. Ensure the GNU CoreUtils and Microsoft HTML Help Workshop are in the system path - add:
|
||||
|
||||
pip install --upgrade pip
|
||||
* C:\Program Files (x86)\GnuWin32\bin
|
||||
* C:\Program Files (x86)\HTML Help Workshop
|
||||
|
||||
|
||||
5. Install virtualenv:
|
||||
5. Upgrade pip:
|
||||
|
||||
python -m pip install --upgrade pip
|
||||
|
||||
6. Install virtualenv:
|
||||
|
||||
pip install virtualenv
|
||||
|
||||
@@ -39,19 +45,22 @@ prompt.
|
||||
tar -zxvf zlib-1.2.11.tar.gz
|
||||
cd zlib-1.2.11
|
||||
cmake -DCMAKE_INSTALL_PREFIX=C:/build64/zlib -G "Visual Studio 15 2017 Win64" .
|
||||
msbuild ALL_BUILD.vcxproj /p:Configuration=Release
|
||||
msbuild RUN_TESTS.vcxproj /p:Configuration=Release
|
||||
msbuild INSTALL.vcxproj /p:Configuration=Release
|
||||
copy C:\build64\zlib\lib\zlib.lib C:\build64\zlib\lib\zdll.lib
|
||||
cd ..
|
||||
|
||||
3. Download the OpenSSL source code, unpack and build it:
|
||||
|
||||
wget https://www.openssl.org/source/openssl-1.1.1g.tar.gz
|
||||
tar -zxvf openssl-1.1.1g.tar.gz
|
||||
cd openssl-1.1.1g
|
||||
wget https://www.openssl.org/source/openssl-1.1.1k.tar.gz
|
||||
tar -zxvf openssl-1.1.1k.tar.gz
|
||||
cd openssl-1.1.1k
|
||||
perl Configure VC-WIN64A no-asm --prefix=C:\build64\openssl no-ssl2 no-ssl3 no-comp
|
||||
nmake
|
||||
nmake test
|
||||
nmake install
|
||||
cd ..
|
||||
|
||||
Note that if you are not working in an administrative account, you may need to
|
||||
create and give your regular account appropriate permissions to write/modify
|
||||
@@ -63,8 +72,10 @@ users could potentially write to.
|
||||
|
||||
In a *32bit* Visual Studio 2017 command prompt:
|
||||
|
||||
wget https://kerberos.org/dist/krb5/1.19/krb5-1.19.1.tar.gz
|
||||
tar -zxvf krb5-1.19.1.tar.gz
|
||||
mkdir C:\build64\krb5
|
||||
cd krb5-1.18.3\src
|
||||
cd krb5-1.19.1\src
|
||||
set KRB_INSTALL_DIR=C:\build64\krb5
|
||||
nmake -f Makefile.in prep-windows
|
||||
|
||||
@@ -75,17 +86,18 @@ users could potentially write to.
|
||||
|
||||
In a *64bit* Visual Studio 2017 command prompt:
|
||||
|
||||
cd krb5-1.18.3\src
|
||||
cd krb5-1.19.1\src
|
||||
set PATH=%PATH%;"%WindowsSdkVerBinPath%"\x86
|
||||
set KRB_INSTALL_DIR=C:\build64\krb5
|
||||
nmake NODEBUG=1
|
||||
nmake install NODEBUG=1
|
||||
cd ..\..
|
||||
|
||||
5. Download the PostgreSQL source code, unpack and build it:
|
||||
|
||||
wget https://ftp.postgresql.org/pub/source/v12.3/postgresql-13.1.tar.bz2
|
||||
tar -zxvf postgresql-13.1.tar.gz
|
||||
cd postgresql-13.1\src\tools\msvc
|
||||
wget https://ftp.postgresql.org/pub/source/v13.3/postgresql-13.3.tar.gz
|
||||
tar -zxvf postgresql-13.3.tar.gz
|
||||
cd postgresql-13.3\src\tools\msvc
|
||||
|
||||
>> config.pl echo # Configuration arguments for vcbuild.
|
||||
>> config.pl echo use strict;
|
||||
@@ -154,9 +166,9 @@ Studio 2017 64bit command prompt. Note that the examples shown below are the
|
||||
defaults for the build system, so if they match your requirements you don't
|
||||
need to set them:
|
||||
|
||||
SET "PGADMIN_POSTGRES_DIR=C:\Program Files\PostgreSQL\13"
|
||||
SET "PGADMIN_POSTGRES_DIR=C:\build64\pgsql"
|
||||
SET "PGADMIN_PYTHON_DIR=C:\Python39"
|
||||
SET "PGADMIN_KRB5_DIR=C:\jenkins\build64\krb5"
|
||||
SET "PGADMIN_KRB5_DIR=C:\build64\krb5"
|
||||
SET "PGADMIN_INNOTOOL_DIR=C:\Program Files (x86)\Inno Setup 6"
|
||||
SET "PGADMIN_SIGNTOOL_DIR=C:\Program Files (x86)\Windows Kits\10\bin\10.0.17763.0\x64"
|
||||
SET "PGADMIN_VCREDIST_DIR=C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\VC\Redist\MSVC\14.16.27012"
|
||||
|
||||
@@ -19,7 +19,7 @@ AppPublisher={#MyAppPublisher}
|
||||
AppPublisherURL={#MyAppURL}
|
||||
AppSupportURL={#MyAppURL}
|
||||
AppUpdatesURL={#MyAppURL}
|
||||
DefaultDirName={commonpf}\{#MyAppName}\{#MyAppVersion}
|
||||
DefaultDirName={autopf}\{#MyAppName}\{#MyAppVersion}
|
||||
DefaultGroupName={#MyAppName}
|
||||
DisableWelcomePage=no
|
||||
DisableProgramGroupPage=auto
|
||||
@@ -28,9 +28,10 @@ OutputBaseFilename=pgadmin4-setup
|
||||
SetupIconFile=Resources\pgAdmin4.ico
|
||||
Compression=lzma
|
||||
SolidCompression=yes
|
||||
PrivilegesRequired=admin
|
||||
PrivilegesRequired=lowest
|
||||
PrivilegesRequiredOverridesAllowed=dialog
|
||||
ChangesEnvironment=yes
|
||||
;UninstallFilesDir={app}\{#MyAppVersion}
|
||||
UninstallDisplayIcon={app}\runtime\{#MyAppExeName}
|
||||
ArchitecturesInstallIn64BitMode={#MyAppArchitecturesMode}
|
||||
AllowNoIcons=yes
|
||||
WizardImageFile=sidebar.bmp
|
||||
@@ -57,10 +58,10 @@ Source: "..\..\win-build\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdi
|
||||
Filename: "{app}\installer\{#MyAppVCDist}"; StatusMsg: "VC runtime redistributable package"; Parameters: "/passive /verysilent /norestart"; Check: InstallVC;
|
||||
|
||||
[Registry]
|
||||
Root: HKLM; Subkey: "Software\{#MyAppName}\{#MyAppVersion}"; Flags: uninsdeletekeyifempty
|
||||
Root: HKLM; Subkey: "Software\{#MyAppName}\{#MyAppVersion}"; Flags: uninsdeletekey
|
||||
Root: HKLM; Subkey: "Software\{#MyAppName}\{#MyAppVersion}"; ValueType: string; ValueName: "InstallPath"; ValueData: "{app}"
|
||||
Root: HKLM; Subkey: "Software\{#MyAppName}\{#MyAppVersion}"; ValueType: string; ValueName: "Version"; ValueData: "{#MyAppFullVersion}"
|
||||
Root: HKA; Subkey: "Software\{#MyAppName}\{#MyAppVersion}"; Flags: uninsdeletekeyifempty
|
||||
Root: HKA; Subkey: "Software\{#MyAppName}\{#MyAppVersion}"; Flags: uninsdeletekey
|
||||
Root: HKA; Subkey: "Software\{#MyAppName}\{#MyAppVersion}"; ValueType: string; ValueName: "InstallPath"; ValueData: "{app}"
|
||||
Root: HKA; Subkey: "Software\{#MyAppName}\{#MyAppVersion}"; ValueType: string; ValueName: "Version"; ValueData: "{#MyAppFullVersion}"
|
||||
|
||||
[Code]
|
||||
var
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
cheroot==8.*
|
||||
Flask==1.*
|
||||
Flask-Gravatar==0.*
|
||||
Flask-Login==0.*
|
||||
@@ -29,10 +28,18 @@ psutil==5.*
|
||||
psycopg2==2.8.*
|
||||
python-dateutil==2.*
|
||||
SQLAlchemy==1.3.*
|
||||
Flask-Security-Too==3.*
|
||||
itsdangerous<=1.1.0
|
||||
Flask-Security-Too==4.*
|
||||
bcrypt==3.*
|
||||
cryptography==3.*
|
||||
sshtunnel==0.*
|
||||
ldap3==2.*
|
||||
Flask-BabelEx==0.*
|
||||
gssapi==1.6.*
|
||||
flask-socketio>=5.0.1
|
||||
eventlet==0.31.0
|
||||
httpagentparser==1.9.*
|
||||
user-agents==2.2.0
|
||||
pywinpty==1.1.1; sys_platform=="win32"
|
||||
Authlib==0.15.*
|
||||
requests==2.25.*
|
||||
@@ -6,6 +6,7 @@
|
||||
"author": "pgAdmin Development Team (https://www.pgadmin.org/)",
|
||||
"license": "PostgreSQL",
|
||||
"chromium-args": "--disable-popup-blocking",
|
||||
"user-agent": "Nwjs:%nwver-%osinfo-%chromium_ver",
|
||||
"window": {
|
||||
"width": 440,
|
||||
"height": 170,
|
||||
|
||||
@@ -28,6 +28,17 @@
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- Disable/block all password saving in nw.js -->
|
||||
<script type="text/javascript">
|
||||
chrome.passwordsPrivate.getSavedPasswordList(function(passwords) {
|
||||
passwords.forEach((p, i) => {
|
||||
chrome.passwordsPrivate.removeSavedPassword(i);
|
||||
});
|
||||
});
|
||||
chrome.privacy.services.passwordSavingEnabled.set({ value: false });
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
let platform = require("os").platform;
|
||||
</script>
|
||||
|
||||
@@ -218,9 +218,6 @@ const cleanupAndQuitApp = () => {
|
||||
}
|
||||
|
||||
if (pgAdminWindowObject != null) {
|
||||
// Close the window.
|
||||
pgAdminWindowObject.close(true);
|
||||
|
||||
// Remove all the cookies.
|
||||
pgAdminWindowObject.cookies.getAll({}, function(cookies) {
|
||||
try {
|
||||
|
||||
@@ -43,7 +43,7 @@ APP_ICON = 'pg-icon'
|
||||
|
||||
# Application version number components
|
||||
APP_RELEASE = 5
|
||||
APP_REVISION = 2
|
||||
APP_REVISION = 6
|
||||
|
||||
# Application version suffix, e.g. 'beta1', 'dev'. Usually an empty string
|
||||
# for GA releases.
|
||||
@@ -52,7 +52,7 @@ APP_SUFFIX = ''
|
||||
# Numeric application version for upgrade checks. Should be in the format:
|
||||
# [X]XYYZZ, where X is the release version, Y is the revision, with a leading
|
||||
# zero if needed, and Z represents the suffix, with a leading zero if needed
|
||||
APP_VERSION_INT = 50200
|
||||
APP_VERSION_INT = 50600
|
||||
|
||||
# DO NOT CHANGE!
|
||||
# The application version string, constructed from the components
|
||||
@@ -156,8 +156,8 @@ X_FRAME_OPTIONS = "SAMEORIGIN"
|
||||
# such as JavaScript, CSS, or pretty much anything that the browser loads.
|
||||
# see https://content-security-policy.com/#source_list for more info
|
||||
# e.g. "default-src https: data: 'unsafe-inline' 'unsafe-eval';"
|
||||
CONTENT_SECURITY_POLICY = "default-src http: data: blob: 'unsafe-inline' " \
|
||||
"'unsafe-eval';"
|
||||
CONTENT_SECURITY_POLICY = "default-src ws: http: data: blob: 'unsafe-inline'" \
|
||||
" 'unsafe-eval';"
|
||||
|
||||
# STRICT_TRANSPORT_SECURITY_ENABLED when set to True will set the
|
||||
# Strict-Transport-Security header
|
||||
@@ -286,6 +286,13 @@ if SERVER_MODE and not IS_WIN:
|
||||
else:
|
||||
LOG_FILE = os.path.join(DATA_DIR, 'pgadmin4.log')
|
||||
|
||||
# Log rotation setting
|
||||
# Log file will be rotated considering values for LOG_ROTATION_SIZE
|
||||
# & LOG_ROTATION_AGE. Rotated file will be named in format
|
||||
# - LOG_FILE.Y-m-d_H-M-S
|
||||
LOG_ROTATION_SIZE = 10 # In MBs
|
||||
LOG_ROTATION_AGE = 1440 # In minutes
|
||||
LOG_ROTATION_MAX_LOG_FILES = 90 # Maximum number of backups to retain
|
||||
##########################################################################
|
||||
# Server Connection Driver Settings
|
||||
##########################################################################
|
||||
@@ -374,6 +381,17 @@ SECURITY_EMAIL_SUBJECT_PASSWORD_NOTICE = "Your %s password has been reset" \
|
||||
SECURITY_EMAIL_SUBJECT_PASSWORD_CHANGE_NOTICE = \
|
||||
"Your password for %s has been changed" % APP_NAME
|
||||
|
||||
##########################################################################
|
||||
# Email address validation
|
||||
##########################################################################
|
||||
|
||||
# flask-security-too will validate email addresses and check deliverability
|
||||
# by default. Disable the deliverability check by default, which was the old
|
||||
# behaviour in <= v5.3
|
||||
CHECK_EMAIL_DELIVERABILITY = False
|
||||
SECURITY_EMAIL_VALIDATOR_ARGS = \
|
||||
{"check_deliverability": CHECK_EMAIL_DELIVERABILITY}
|
||||
|
||||
##########################################################################
|
||||
# Upgrade checks
|
||||
##########################################################################
|
||||
@@ -416,6 +434,10 @@ STORAGE_DIR = os.path.join(DATA_DIR, 'storage')
|
||||
#
|
||||
# A default location can be specified for each database driver ID, in
|
||||
# a dictionary. Either an absolute or relative path can be specified.
|
||||
#
|
||||
# Version-specific defaults can also be specified, which will take priority
|
||||
# over un-versioned paths.
|
||||
#
|
||||
# In cases where it may be difficult to know what the working directory
|
||||
# is, "$DIR" can be specified. This will be replaced with the path to the
|
||||
# top-level pgAdmin4.py file. For example, on macOS we might use:
|
||||
@@ -425,8 +447,17 @@ STORAGE_DIR = os.path.join(DATA_DIR, 'storage')
|
||||
##########################################################################
|
||||
DEFAULT_BINARY_PATHS = {
|
||||
"pg": "",
|
||||
"pg-9.6": "",
|
||||
"pg-10": "",
|
||||
"pg-11": "",
|
||||
"pg-12": "",
|
||||
"pg-13": "",
|
||||
"ppas": "",
|
||||
"gpdb": ""
|
||||
"ppas-9.6": "",
|
||||
"ppas-10": "",
|
||||
"ppas-11": "",
|
||||
"ppas-12": "",
|
||||
"ppas-13": ""
|
||||
}
|
||||
|
||||
##########################################################################
|
||||
@@ -482,6 +513,10 @@ SESSION_SKIP_PATHS = [
|
||||
# expire after the specified number of *days*.
|
||||
SESSION_EXPIRATION_TIME = 1
|
||||
|
||||
# Make SESSION_EXPIRATION_TIME to 1 week in DESKTOP mode
|
||||
if not SERVER_MODE:
|
||||
SESSION_EXPIRATION_TIME = 7
|
||||
|
||||
# CHECK_SESSION_FILES_INTERVAL is interval in Hours. Application will check
|
||||
# the session files for cleanup after specified number of *hours*.
|
||||
CHECK_SESSION_FILES_INTERVAL = 24
|
||||
@@ -531,13 +566,26 @@ ENHANCED_COOKIE_PROTECTION = True
|
||||
##########################################################################
|
||||
|
||||
# Default setting is internal
|
||||
# External Supported Sources: ldap, kerberos
|
||||
# External Supported Sources: ldap, kerberos, oauth2
|
||||
# Multiple authentication can be achieved by setting this parameter to
|
||||
# ['ldap', 'internal']. pgAdmin will authenticate the user with ldap first,
|
||||
# in case of failure internal authentication will be done.
|
||||
# ['ldap', 'internal'] or ['oauth2', 'internal'] etc.
|
||||
# pgAdmin will authenticate the user with ldap/oauth2 whatever first in the
|
||||
# list, in case of failure the second authentication option will be considered.
|
||||
|
||||
AUTHENTICATION_SOURCES = ['internal']
|
||||
|
||||
##########################################################################
|
||||
# MAX_LOGIN_ATTEMPTS which sets the number of failed login attempts that
|
||||
# are allowed. If this value is exceeded the account is locked and can be
|
||||
# reset by an administrator. By setting the variable to the value zero
|
||||
# this feature is deactivated.
|
||||
##########################################################################
|
||||
MAX_LOGIN_ATTEMPTS = 3
|
||||
|
||||
##########################################################################
|
||||
# Only consider password to check the failed login attempts, email is
|
||||
# excluded from this check
|
||||
LOGIN_ATTEMPT_FIELDS = ['password']
|
||||
##########################################################################
|
||||
# LDAP Configuration
|
||||
##########################################################################
|
||||
@@ -614,7 +662,6 @@ LDAP_CA_CERT_FILE = ''
|
||||
LDAP_CERT_FILE = ''
|
||||
LDAP_KEY_FILE = ''
|
||||
|
||||
|
||||
##########################################################################
|
||||
# Kerberos Configuration
|
||||
##########################################################################
|
||||
@@ -634,6 +681,65 @@ KRB_KTNAME = '<KRB5_KEYTAB_FILE>'
|
||||
|
||||
KRB_AUTO_CREATE_USER = True
|
||||
|
||||
KERBEROS_CCACHE_DIR = os.path.join(DATA_DIR, 'krbccache')
|
||||
|
||||
##########################################################################
|
||||
# OAuth2 Configuration
|
||||
##########################################################################
|
||||
|
||||
# Multiple OAUTH2 providers can be added in the list like [{...},{...}]
|
||||
# All parameters are required
|
||||
|
||||
OAUTH2_CONFIG = [
|
||||
{
|
||||
# The name of the of the oauth provider, ex: github, google
|
||||
'OAUTH2_NAME': None,
|
||||
# The display name, ex: Google
|
||||
'OAUTH2_DISPLAY_NAME': '<Oauth2 Display Name>',
|
||||
# Oauth client id
|
||||
'OAUTH2_CLIENT_ID': None,
|
||||
# Oauth secret
|
||||
'OAUTH2_CLIENT_SECRET': None,
|
||||
# URL to generate a token,
|
||||
# Ex: https://github.com/login/oauth/access_token
|
||||
'OAUTH2_TOKEN_URL': None,
|
||||
# URL is used for authentication,
|
||||
# Ex: https://github.com/login/oauth/authorize
|
||||
'OAUTH2_AUTHORIZATION_URL': None,
|
||||
# Oauth base url, ex: https://api.github.com/
|
||||
'OAUTH2_API_BASE_URL': None,
|
||||
# Name of the Endpoint, ex: user
|
||||
'OAUTH2_USERINFO_ENDPOINT': None,
|
||||
# Font-awesome icon, ex: fa-github
|
||||
'OAUTH2_ICON': None,
|
||||
# UI button colour, ex: #0000ff
|
||||
'OAUTH2_BUTTON_COLOR': None,
|
||||
}
|
||||
]
|
||||
|
||||
# After Oauth authentication, user will be added into the SQLite database
|
||||
# automatically, if set to True.
|
||||
# Set it to False, if user should not be added automatically,
|
||||
# in this case Admin has to add the user manually in the SQLite database.
|
||||
|
||||
OAUTH2_AUTO_CREATE_USER = True
|
||||
|
||||
##########################################################################
|
||||
# PSQL tool settings
|
||||
##########################################################################
|
||||
# This will enable PSQL tool in pgAdmin when running in server mode.
|
||||
# PSQL is always enabled in Desktop mode, however in server mode it is
|
||||
# disabled by default because users can run arbitrary commands on the
|
||||
# server through it.
|
||||
ENABLE_PSQL = False
|
||||
|
||||
##########################################################################
|
||||
# ENABLE_BINARY_PATH_BROWSING setting is used to enable the browse button
|
||||
# while selecting binary path for the database server in server mode.
|
||||
# In Desktop mode it is always enabled and setting is of no use.
|
||||
##########################################################################
|
||||
ENABLE_BINARY_PATH_BROWSING = False
|
||||
|
||||
##########################################################################
|
||||
# Local config settings
|
||||
##########################################################################
|
||||
@@ -673,3 +779,5 @@ if 'PGADMIN_CONFIG_DEFAULT_SERVER' in os.environ:
|
||||
# Disable USER_INACTIVITY_TIMEOUT when SERVER_MODE=False
|
||||
if not SERVER_MODE:
|
||||
USER_INACTIVITY_TIMEOUT = 0
|
||||
# Enable PSQL in Desktop Mode.
|
||||
ENABLE_PSQL = True
|
||||
@@ -0,0 +1,33 @@
|
||||
|
||||
"""empty message
|
||||
|
||||
Revision ID: 6650c52670c2
|
||||
Revises: c465fee44968
|
||||
Create Date: 2021-07-10 18:12:38.821602
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
from pgadmin import db
|
||||
|
||||
revision = '6650c52670c2'
|
||||
down_revision = 'c465fee44968'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
db.engine.execute(
|
||||
'ALTER TABLE user ADD COLUMN locked BOOLEAN DEFAULT FALSE'
|
||||
)
|
||||
db.engine.execute(
|
||||
'ALTER TABLE user ADD COLUMN login_attempts int DEFAULT 0'
|
||||
)
|
||||
|
||||
|
||||
def downgrade():
|
||||
# pgAdmin only upgrades, downgrade not implemented.
|
||||
pass
|
||||
@@ -0,0 +1,64 @@
|
||||
|
||||
"""empty message
|
||||
|
||||
Revision ID: c465fee44968
|
||||
Revises: d0bc9f32b2b9
|
||||
Create Date: 2021-06-04 14:42:12.843116
|
||||
|
||||
"""
|
||||
from pgadmin.model import db, User
|
||||
from sqlalchemy.sql import text
|
||||
import uuid
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'c465fee44968'
|
||||
down_revision = 'd0bc9f32b2b9'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
db.engine.execute("ALTER TABLE user RENAME TO user_old")
|
||||
|
||||
db.engine.execute("""
|
||||
CREATE TABLE user (
|
||||
id INTEGER NOT NULL,
|
||||
username VARCHAR(256) NOT NULL,
|
||||
email VARCHAR(256),
|
||||
password VARCHAR(256),
|
||||
active BOOLEAN NOT NULL,
|
||||
confirmed_at DATETIME,
|
||||
masterpass_check VARCHAR(256),
|
||||
auth_source VARCHAR(256) NOT NULL DEFAULT 'internal',
|
||||
fs_uniquifier NOT NULL UNIQUE,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE (username, auth_source),
|
||||
CHECK (active IN (0, 1))
|
||||
);
|
||||
""")
|
||||
|
||||
user_old = db.engine.execute(
|
||||
'select id, username, email, password, active, '
|
||||
'confirmed_at, masterpass_check, auth_source '
|
||||
'from user_old')
|
||||
|
||||
statement = text("""
|
||||
INSERT INTO user(id, username, email, password, active,
|
||||
confirmed_at, masterpass_check, auth_source, fs_uniquifier)
|
||||
VALUES(:id, :username, :email, :password, :active, :confirmed_at,
|
||||
:masterpass_check, :auth_source, :fs_uniquifier)""")
|
||||
|
||||
db.engine.execute(statement, [
|
||||
{
|
||||
**row,
|
||||
'fs_uniquifier': uuid.uuid4().hex
|
||||
} for row in user_old
|
||||
])
|
||||
|
||||
db.engine.execute("DROP TABLE user_old")
|
||||
|
||||
|
||||
def downgrade():
|
||||
# pgAdmin only upgrades, downgrade not implemented.
|
||||
pass
|
||||
@@ -0,0 +1,28 @@
|
||||
|
||||
"""empty message
|
||||
|
||||
Revision ID: c6974f64df08
|
||||
Revises: a39bd015b644
|
||||
Create Date: 2021-04-22 10:06:21.282770
|
||||
|
||||
"""
|
||||
from pgadmin.model import db
|
||||
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'c6974f64df08'
|
||||
down_revision = 'a39bd015b644'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
db.engine.execute(
|
||||
'ALTER TABLE sharedserver ADD COLUMN osid INTEGER'
|
||||
)
|
||||
|
||||
|
||||
def downgrade():
|
||||
# pgAdmin only upgrades, downgrade not implemented.
|
||||
pass
|
||||
@@ -0,0 +1,28 @@
|
||||
|
||||
"""empty message
|
||||
|
||||
Revision ID: d0bc9f32b2b9
|
||||
Revises: c6974f64df08
|
||||
Create Date: 2021-04-27 12:40:08.899712
|
||||
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
from pgadmin.model import db
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'd0bc9f32b2b9'
|
||||
down_revision = 'c6974f64df08'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def upgrade():
|
||||
db.engine.execute(
|
||||
'ALTER TABLE server ADD COLUMN kerberos_conn INTEGER DEFAULT 0'
|
||||
)
|
||||
|
||||
|
||||
def downgrade():
|
||||
# pgAdmin only upgrades, downgrade not implemented.
|
||||
pass
|
||||
@@ -24,7 +24,7 @@
|
||||
"copy-webpack-plugin": "^7.0.0",
|
||||
"core-js": "^3.2.1",
|
||||
"cross-env": "^7.0.3",
|
||||
"css-minimizer-webpack-plugin": "^1.2.0",
|
||||
"css-minimizer-webpack-plugin": "^3.0.0",
|
||||
"enzyme": "^3.11.0",
|
||||
"eslint": "^7.19.0",
|
||||
"eslint-plugin-react": "^7.20.5",
|
||||
@@ -37,7 +37,7 @@
|
||||
"is-docker": "^2.1.1",
|
||||
"jasmine-core": "^3.6.0",
|
||||
"jasmine-enzyme": "^7.1.2",
|
||||
"karma": "^6.1.0",
|
||||
"karma": "^6.3.2",
|
||||
"karma-babel-preprocessor": "^8.0.0",
|
||||
"karma-browserify": "^8.0.0",
|
||||
"karma-chrome-launcher": "^3.1.0",
|
||||
@@ -53,7 +53,6 @@
|
||||
"process": "^0.11.10",
|
||||
"prop-types": "^15.7.2",
|
||||
"resize-observer-polyfill": "^1.5.1",
|
||||
"resolve-url-loader": "^3.1.2",
|
||||
"sass": "^1.24.4",
|
||||
"sass-loader": "^11.0.0",
|
||||
"sass-resources-loader": "^2.2.1",
|
||||
@@ -89,7 +88,7 @@
|
||||
"closest": "^0.0.1",
|
||||
"codemirror": "^5.59.2",
|
||||
"css-loader": "^5.0.1",
|
||||
"cssnano": "^4.1.10",
|
||||
"cssnano": "^5.0.2",
|
||||
"dagre": "^0.8.4",
|
||||
"dropzone": "^5.7.4",
|
||||
"html2canvas": "^1.0.0-rc.7",
|
||||
@@ -97,10 +96,11 @@
|
||||
"imports-loader": "^2.0.0",
|
||||
"ip-address": "^7.1.0",
|
||||
"istanbul-instrumenter-loader": "^3.0.1",
|
||||
"jquery": "^3.5.1",
|
||||
"jquery": "^3.6.0",
|
||||
"jquery-contextmenu": "^2.9.2",
|
||||
"jquery-ui": "^1.12.1",
|
||||
"json-bignumber": "^1.0.1",
|
||||
"jsoneditor": "^9.5.1",
|
||||
"karma-coverage": "^2.0.3",
|
||||
"leaflet": "^1.5.1",
|
||||
"lodash": "4.*",
|
||||
@@ -110,22 +110,26 @@
|
||||
"mousetrap": "^1.6.3",
|
||||
"pathfinding": "^0.4.18",
|
||||
"paths-js": "^0.4.9",
|
||||
"postcss": "^8.2.4",
|
||||
"postcss": "^8.2.15",
|
||||
"raf": "^3.4.1",
|
||||
"react": "^17.0.1",
|
||||
"react-dom": "^17.0.1",
|
||||
"requirejs": "~2.3.6",
|
||||
"select2": "^4.0.13",
|
||||
"shim-loader": "^1.0.1",
|
||||
"slickgrid": "git+https://github.com/6pac/SlickGrid.git#2.3.16",
|
||||
"snapsvg-cjs": "^0.0.6",
|
||||
"socket.io-client": "^4.0.0",
|
||||
"split.js": "^1.5.10",
|
||||
"tablesorter": "^2.31.2",
|
||||
"tempusdominus-bootstrap-4": "^5.1.2",
|
||||
"tempusdominus-core": "^5.0.3",
|
||||
"underscore": "^1.9.1",
|
||||
"webcabin-docker": "git+https://github.com/EnterpriseDB/wcDocker/#c4a3398b89588408dc705895675bce7bd7660d36",
|
||||
"wkx": "^0.5.0"
|
||||
"underscore": "^1.13.1",
|
||||
"webcabin-docker": "git+https://github.com/EnterpriseDB/wcDocker/#06daee1a8111b4ed08d58670674a2967e4f68313",
|
||||
"wkx": "^0.5.0",
|
||||
"xterm": "^4.11.0",
|
||||
"xterm-addon-fit": "^0.5.0",
|
||||
"xterm-addon-search": "^0.8.0",
|
||||
"xterm-addon-web-links": "^0.4.0"
|
||||
},
|
||||
"scripts": {
|
||||
"linter": "yarn eslint --no-eslintrc -c .eslintrc.js --ext .js --ext .jsx .",
|
||||
|
||||
@@ -13,7 +13,7 @@ to start a web server."""
|
||||
|
||||
|
||||
import sys
|
||||
from cheroot.wsgi import Server as CherootServer
|
||||
|
||||
|
||||
if sys.version_info < (3, 4):
|
||||
raise RuntimeError('This application must be run under Python 3.4 '
|
||||
@@ -37,7 +37,7 @@ else:
|
||||
builtins.SERVER_MODE = None
|
||||
|
||||
import config
|
||||
from pgadmin import create_app
|
||||
from pgadmin import create_app, socketio
|
||||
from pgadmin.utils import u_encode, fs_encoding, file_quote
|
||||
from pgadmin.utils.constants import INTERNAL
|
||||
# Get the config database schema version. We store this in pgadmin.model
|
||||
@@ -97,6 +97,8 @@ if not os.path.isfile(config.SQLITE_PATH):
|
||||
##########################################################################
|
||||
app = create_app()
|
||||
app.debug = False
|
||||
app.config['sessions'] = dict()
|
||||
|
||||
if config.SERVER_MODE:
|
||||
app.wsgi_app = ReverseProxied(app.wsgi_app)
|
||||
|
||||
@@ -206,17 +208,16 @@ def main():
|
||||
else:
|
||||
# Can use cheroot instead of flask dev server when not in debug
|
||||
# 10 is default thread count in CherootServer
|
||||
num_threads = 10 if config.THREADED_MODE else 1
|
||||
prod_server = CherootServer(
|
||||
(config.DEFAULT_SERVER, config.EFFECTIVE_SERVER_PORT),
|
||||
wsgi_app=app,
|
||||
numthreads=num_threads,
|
||||
server_name=config.APP_NAME)
|
||||
# num_threads = 10 if config.THREADED_MODE else 1
|
||||
try:
|
||||
print("Using production server...")
|
||||
prod_server.start()
|
||||
socketio.run(
|
||||
app,
|
||||
host=config.DEFAULT_SERVER,
|
||||
port=config.EFFECTIVE_SERVER_PORT,
|
||||
)
|
||||
except KeyboardInterrupt:
|
||||
prod_server.stop()
|
||||
print("CLOSE SERVER")
|
||||
socketio.stop()
|
||||
|
||||
except IOError:
|
||||
app.logger.error("Error starting the app server: %s", sys.exc_info())
|
||||
|
||||
@@ -14,11 +14,14 @@ import os
|
||||
import sys
|
||||
import re
|
||||
import ipaddress
|
||||
import traceback
|
||||
|
||||
from types import MethodType
|
||||
from collections import defaultdict
|
||||
from importlib import import_module
|
||||
|
||||
from flask import Flask, abort, request, current_app, session, url_for
|
||||
from flask_socketio import SocketIO
|
||||
from werkzeug.exceptions import HTTPException
|
||||
from flask_babelex import Babel, gettext
|
||||
from flask_babelex import gettext as _
|
||||
@@ -37,25 +40,31 @@ from pgadmin.utils import PgAdminModule, driver, KeyManager
|
||||
from pgadmin.utils.preferences import Preferences
|
||||
from pgadmin.utils.session import create_session_interface, pga_unauthorised
|
||||
from pgadmin.utils.versioned_template_loader import VersionedTemplateLoader
|
||||
from datetime import timedelta
|
||||
from pgadmin.setup import get_version, set_version
|
||||
from datetime import timedelta, datetime
|
||||
from pgadmin.setup import get_version, set_version, check_db_tables
|
||||
from pgadmin.utils.ajax import internal_server_error, make_json_response
|
||||
from pgadmin.utils.csrf import pgCSRFProtect
|
||||
from pgadmin import authenticate
|
||||
from pgadmin.utils.security_headers import SecurityHeaders
|
||||
from pgadmin.utils.constants import KERBEROS
|
||||
from pgadmin.utils.constants import KERBEROS, OAUTH2, INTERNAL, LDAP
|
||||
|
||||
# Explicitly set the mime-types so that a corrupted windows registry will not
|
||||
# affect pgAdmin 4 to be load properly. This will avoid the issues that may
|
||||
# occur due to security fix of X_CONTENT_TYPE_OPTIONS = "nosniff".
|
||||
import mimetypes
|
||||
|
||||
mimetypes.add_type('application/javascript', '.js')
|
||||
mimetypes.add_type('text/css', '.css')
|
||||
|
||||
|
||||
winreg = None
|
||||
if os.name == 'nt':
|
||||
import winreg
|
||||
|
||||
socketio = SocketIO(manage_session=False, async_mode='threading',
|
||||
logger=False, engineio_logger=False, debug=False,
|
||||
ping_interval=25, ping_timeout=120)
|
||||
|
||||
|
||||
class PgAdmin(Flask):
|
||||
def __init__(self, *args, **kwargs):
|
||||
@@ -256,7 +265,13 @@ def create_app(app_name=None):
|
||||
create_app_data_directory(config)
|
||||
|
||||
# File logging
|
||||
fh = logging.FileHandler(config.LOG_FILE, encoding='utf-8')
|
||||
from pgadmin.utils.enhanced_log_rotation import \
|
||||
EnhancedRotatingFileHandler
|
||||
fh = EnhancedRotatingFileHandler(config.LOG_FILE,
|
||||
config.LOG_ROTATION_SIZE,
|
||||
config.LOG_ROTATION_AGE,
|
||||
config.LOG_ROTATION_MAX_LOG_FILES)
|
||||
|
||||
fh.setLevel(config.FILE_LOG_LEVEL)
|
||||
fh.setFormatter(logging.Formatter(config.FILE_LOG_FORMAT))
|
||||
app.logger.addHandler(fh)
|
||||
@@ -293,7 +308,7 @@ def create_app(app_name=None):
|
||||
if current_user.is_authenticated:
|
||||
user_id = current_user.id
|
||||
else:
|
||||
user = user_datastore.get_user(config.DESKTOP_USER)
|
||||
user = user_datastore.find_user(email=config.DESKTOP_USER)
|
||||
if user is not None:
|
||||
user_id = user.id
|
||||
user_language = Preferences.raw_value(
|
||||
@@ -337,6 +352,44 @@ def create_app(app_name=None):
|
||||
##########################################################################
|
||||
# Upgrade the schema (if required)
|
||||
##########################################################################
|
||||
def backup_db_file():
|
||||
"""
|
||||
Create a backup of the current database file
|
||||
and create new database file with default settings.
|
||||
"""
|
||||
backup_file_name = "{0}.{1}".format(
|
||||
SQLITE_PATH, datetime.now().strftime('%Y%m%d%H%M%S'))
|
||||
os.rename(SQLITE_PATH, backup_file_name)
|
||||
app.logger.error('Exception in database migration.')
|
||||
app.logger.info('Creating new database file.')
|
||||
try:
|
||||
db_upgrade(app)
|
||||
os.environ[
|
||||
'CORRUPTED_DB_BACKUP_FILE'] = backup_file_name
|
||||
app.logger.info('Database migration completed.')
|
||||
except Exception as e:
|
||||
app.logger.error('Database migration failed')
|
||||
app.logger.error(traceback.format_exc())
|
||||
raise RuntimeError('Migration failed')
|
||||
|
||||
def upgrade_db():
|
||||
"""
|
||||
Execute the migrations.
|
||||
"""
|
||||
try:
|
||||
db_upgrade(app)
|
||||
os.environ['CORRUPTED_DB_BACKUP_FILE'] = ''
|
||||
except Exception as e:
|
||||
backup_db_file()
|
||||
|
||||
# check all tables are present in the db.
|
||||
is_db_error, invalid_tb_names = check_db_tables()
|
||||
if is_db_error:
|
||||
app.logger.error(
|
||||
'Table(s) {0} are missing in the'
|
||||
' database'.format(invalid_tb_names))
|
||||
backup_db_file()
|
||||
|
||||
with app.app_context():
|
||||
# Run migration for the first time i.e. create database
|
||||
from config import SQLITE_PATH
|
||||
@@ -348,21 +401,29 @@ def create_app(app_name=None):
|
||||
# If running in cli mode then don't try to upgrade, just raise
|
||||
# the exception
|
||||
if not cli_mode:
|
||||
db_upgrade(app)
|
||||
upgrade_db()
|
||||
else:
|
||||
if not os.path.exists(SQLITE_PATH):
|
||||
raise FileNotFoundError(
|
||||
'SQLite database file "' + SQLITE_PATH +
|
||||
'" does not exists.')
|
||||
raise RuntimeError('Specified SQLite database file '
|
||||
'is not valid.')
|
||||
raise RuntimeError(
|
||||
'The configuration database file is not valid.')
|
||||
else:
|
||||
schema_version = get_version()
|
||||
|
||||
# Run migration if current schema version is greater than the
|
||||
# schema version stored in version table
|
||||
if CURRENT_SCHEMA_VERSION >= schema_version:
|
||||
db_upgrade(app)
|
||||
upgrade_db()
|
||||
else:
|
||||
# check all tables are present in the db.
|
||||
is_db_error, invalid_tb_names = check_db_tables()
|
||||
if is_db_error:
|
||||
app.logger.error(
|
||||
'Table(s) {0} are missing in the'
|
||||
' database'.format(invalid_tb_names))
|
||||
backup_db_file()
|
||||
|
||||
# Update schema version to the latest
|
||||
if CURRENT_SCHEMA_VERSION > schema_version:
|
||||
@@ -404,6 +465,15 @@ def create_app(app_name=None):
|
||||
# CSRF Token expiration till session expires
|
||||
'WTF_CSRF_TIME_LIMIT': getattr(config, 'CSRF_TIME_LIMIT', None),
|
||||
'WTF_CSRF_METHODS': ['GET', 'POST', 'PUT', 'DELETE'],
|
||||
# Disable deliverable check for email addresss
|
||||
'SECURITY_EMAIL_VALIDATOR_ARGS': config.SECURITY_EMAIL_VALIDATOR_ARGS
|
||||
}))
|
||||
|
||||
app.config.update(dict({
|
||||
'INTERNAL': INTERNAL,
|
||||
'LDAP': LDAP,
|
||||
'KERBEROS': KERBEROS,
|
||||
'OAUTH2': OAUTH2
|
||||
}))
|
||||
|
||||
security.init_app(app, user_datastore)
|
||||
@@ -610,15 +680,15 @@ def create_app(app_name=None):
|
||||
from pgadmin.utils.driver import get_driver
|
||||
from flask import current_app
|
||||
|
||||
# remove key
|
||||
current_app.keyManager.reset()
|
||||
|
||||
for mdl in current_app.logout_hooks:
|
||||
try:
|
||||
mdl.on_logout(user)
|
||||
except Exception as e:
|
||||
current_app.logger.exception(e)
|
||||
|
||||
# remove key
|
||||
current_app.keyManager.reset()
|
||||
|
||||
_driver = get_driver(PG_DEFAULT_DRIVER)
|
||||
_driver.gc_own()
|
||||
|
||||
@@ -685,7 +755,7 @@ def create_app(app_name=None):
|
||||
abort(401)
|
||||
|
||||
if not config.SERVER_MODE and not current_user.is_authenticated:
|
||||
user = user_datastore.get_user(config.DESKTOP_USER)
|
||||
user = user_datastore.find_user(email=config.DESKTOP_USER)
|
||||
# Throw an error if we failed to find the desktop user, to give
|
||||
# the sysadmin a hint. We'll continue to try to login anyway as
|
||||
# that'll through a nice 500 error for us.
|
||||
@@ -697,19 +767,18 @@ def create_app(app_name=None):
|
||||
)
|
||||
abort(401)
|
||||
login_user(user)
|
||||
elif config.SERVER_MODE and\
|
||||
app.PGADMIN_EXTERNAL_AUTH_SOURCE ==\
|
||||
KERBEROS and \
|
||||
elif config.SERVER_MODE and \
|
||||
not current_user.is_authenticated and \
|
||||
request.endpoint in ('redirects.index', 'security.login'):
|
||||
return authenticate.login()
|
||||
|
||||
if app.PGADMIN_EXTERNAL_AUTH_SOURCE == KERBEROS:
|
||||
return authenticate.login()
|
||||
# if the server is restarted the in memory key will be lost
|
||||
# but the user session may still be active. Logout the user
|
||||
# to get the key again when login
|
||||
if config.SERVER_MODE and current_user.is_authenticated and \
|
||||
app.PGADMIN_EXTERNAL_AUTH_SOURCE != \
|
||||
KERBEROS and \
|
||||
KERBEROS and app.PGADMIN_EXTERNAL_AUTH_SOURCE != \
|
||||
OAUTH2 and\
|
||||
current_app.keyManager.get() is None and \
|
||||
request.endpoint not in ('security.login', 'security.logout'):
|
||||
logout_user()
|
||||
@@ -811,4 +880,5 @@ def create_app(app_name=None):
|
||||
##########################################################################
|
||||
# All done!
|
||||
##########################################################################
|
||||
socketio.init_app(app)
|
||||
return app
|
||||
@@ -10,13 +10,17 @@
|
||||
"""A blueprint module implementing the about box."""
|
||||
|
||||
import sys
|
||||
from flask import Response, render_template, __version__, url_for
|
||||
from flask import Response, render_template, __version__, url_for, request
|
||||
from flask_babelex import gettext
|
||||
from flask_security import current_user, login_required
|
||||
from pgadmin.utils import PgAdminModule
|
||||
from pgadmin.utils.menu import MenuItem
|
||||
from pgadmin.utils.constants import MIMETYPE_APP_JS
|
||||
import config
|
||||
import httpagentparser
|
||||
from pgadmin.model import User
|
||||
from user_agents import parse
|
||||
import platform
|
||||
|
||||
MODULE_NAME = 'about'
|
||||
|
||||
@@ -59,23 +63,81 @@ blueprint = AboutModule(MODULE_NAME, __name__, static_url_path='')
|
||||
@login_required
|
||||
def index():
|
||||
"""Render the about box."""
|
||||
info = {
|
||||
'python_version': sys.version,
|
||||
'flask_version': __version__
|
||||
}
|
||||
info = {}
|
||||
# Get OS , NW.js, Browser details
|
||||
browser, os_details, nwjs_version = detect_browser(request)
|
||||
|
||||
if nwjs_version:
|
||||
info['nwjs'] = nwjs_version
|
||||
|
||||
info['browser_details'] = browser
|
||||
info['os_details'] = os_details
|
||||
info['config_db'] = config.SQLITE_PATH
|
||||
info['log_file'] = config.LOG_FILE
|
||||
|
||||
if config.SERVER_MODE:
|
||||
info['app_mode'] = gettext('Server')
|
||||
admin = is_admin(current_user.email)
|
||||
info['admin'] = admin
|
||||
else:
|
||||
info['app_mode'] = gettext('Desktop')
|
||||
|
||||
info['current_user'] = current_user.email
|
||||
|
||||
settings = ""
|
||||
for setting in dir(config):
|
||||
if not setting.startswith('_') and setting.isupper() and \
|
||||
setting not in ['CSRF_SESSION_KEY',
|
||||
'SECRET_KEY',
|
||||
'SECURITY_PASSWORD_SALT',
|
||||
'SECURITY_PASSWORD_HASH',
|
||||
'ALLOWED_HOSTS',
|
||||
'MAIL_PASSWORD',
|
||||
'LDAP_BIND_PASSWORD',
|
||||
'SECURITY_PASSWORD_HASH']:
|
||||
if isinstance(getattr(config, setting), str):
|
||||
settings = \
|
||||
settings + '{} = "{}"\n'.format(
|
||||
setting, gettext(getattr(config, setting)))
|
||||
else:
|
||||
settings = \
|
||||
settings + '{} = {}\n'.format(
|
||||
setting, gettext(getattr(config, setting)))
|
||||
|
||||
info['settings'] = settings
|
||||
|
||||
return render_template(
|
||||
MODULE_NAME + '/index.html', info=info, _=gettext
|
||||
)
|
||||
|
||||
|
||||
def is_admin(load_user):
|
||||
user = User.query.filter_by(email=load_user).first()
|
||||
return user.has_role("Administrator")
|
||||
|
||||
|
||||
def detect_browser(request):
|
||||
"""This function returns the browser and os details"""
|
||||
nwjs_version = None
|
||||
agent = request.environ.get('HTTP_USER_AGENT')
|
||||
os_details = parse(platform.platform()).ua_string
|
||||
|
||||
if 'Nwjs' in agent:
|
||||
agent = agent.split('-')
|
||||
nwjs_version = agent[0].split(':')[1]
|
||||
browser = 'Chromium' + ' ' + agent[2]
|
||||
|
||||
else:
|
||||
browser = httpagentparser.detect(agent)
|
||||
if not browser:
|
||||
browser = agent.split('/')[0]
|
||||
else:
|
||||
browser = browser['browser']['name'] + ' ' + browser['browser'][
|
||||
'version']
|
||||
|
||||
return browser, os_details, nwjs_version
|
||||
|
||||
|
||||
@blueprint.route("/about.js")
|
||||
@login_required
|
||||
def script():
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
|
||||
define(
|
||||
['jquery', 'alertify', 'sources/pgadmin', 'sources/gettext',
|
||||
'sources/url_for','sources/utils',
|
||||
'sources/url_for','sources/utils','pgadmin.user_management.current_user',
|
||||
],
|
||||
function($, alertify, pgAdmin, gettext, url_for, commonUtils) {
|
||||
function($, alertify, pgAdmin, gettext, url_for, commonUtils, current_user) {
|
||||
pgAdmin = pgAdmin || window.pgAdmin || {};
|
||||
|
||||
/* Return back, this has been called more than once */
|
||||
@@ -45,14 +45,28 @@ define(
|
||||
},
|
||||
hooks:{
|
||||
onshow:function(){
|
||||
var self = this;
|
||||
var container = $(this.elements.footer).find('button:not([disabled])');
|
||||
commonUtils.findAndSetFocus(container);
|
||||
$('#copy_textarea').on('click', function(){
|
||||
//Copy the server configuration details
|
||||
let textarea = document.getElementById('about-textarea');
|
||||
textarea.select();
|
||||
document.execCommand('copy');
|
||||
$('#copy_textarea').text('Copied');
|
||||
});
|
||||
|
||||
$(this.elements.resizeHandle).on('click', function(){
|
||||
// Set the height of the Textarea
|
||||
var height = self.elements.dialog.scrollHeight - 300;
|
||||
if (height < 0)
|
||||
height = self.elements.dialog.scrollHeight - 150;
|
||||
$('#about-textarea').css({'height':height});
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
prepare:function() {
|
||||
this.setContent(this.message);
|
||||
|
||||
},
|
||||
};
|
||||
});
|
||||
@@ -60,9 +74,15 @@ define(
|
||||
|
||||
$.get(url_for('about.index'),
|
||||
function(data) {
|
||||
alertify.aboutDialog(
|
||||
gettext('About %s', pgAdmin.Browser.utils.app_name), data
|
||||
).resizeTo(pgAdmin.Browser.stdW.md, pgAdmin.Browser.stdH.md);
|
||||
if(!current_user.is_admin && pgAdmin.server_mode){
|
||||
alertify.aboutDialog(
|
||||
gettext('About %s', pgAdmin.Browser.utils.app_name), data
|
||||
).resizeTo(pgAdmin.Browser.stdW.md, 300);
|
||||
}else{
|
||||
alertify.aboutDialog(
|
||||
gettext('About %s', pgAdmin.Browser.utils.app_name), data
|
||||
).resizeTo(750, 470);
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
@@ -3,18 +3,6 @@
|
||||
<div class="col-sm-3"><strong>{{ _('Version') }}</strong></div>
|
||||
<div class="col-sm-9">{{ config.APP_VERSION }}</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3"><strong>{{ _('Copyright') }}</strong></div>
|
||||
<div class="col-sm-9">{{ config.APP_COPYRIGHT }}</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3"><strong>{{ _('Python Version') }}</strong></div>
|
||||
<div class="col-sm-9">{{ info.python_version }}</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3"><strong>{{ _('Flask Version') }}</strong></div>
|
||||
<div class="col-sm-9">{{ info.flask_version }}</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3"><strong>{{ _('Application Mode') }}</strong></div>
|
||||
<div class="col-sm-9">{{ info.app_mode }}</div>
|
||||
@@ -23,10 +11,37 @@
|
||||
<div class="col-sm-3"><strong>{{ _('Current User') }}</strong></div>
|
||||
<div class="col-sm-9">{{ info.current_user }}</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12 text-right"><img
|
||||
src="{{ url_for('static', filename='img/logo-right-128.png') }}"
|
||||
alt="{{ config.APP_NAME }} {{ _('logo') }}"
|
||||
></div>
|
||||
{% if info.nwjs %}
|
||||
<div class="row">
|
||||
<div class="col-sm-3"><strong>{{ _('NW.js Version') }}</strong></div>
|
||||
<div class="col-sm-9">{{ info.nwjs }}</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="row">
|
||||
<div class="col-sm-3"><strong>{{ _('Browser') }}</strong></div>
|
||||
<div class="col-sm-9">{{ info.browser_details }}</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3"><strong>{{ _('Operating System') }}</strong></div>
|
||||
<div class="col-sm-9">{{ info.os_details }}</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3"><strong>{{ _('pgAdmin Database File') }}</strong></div>
|
||||
<div class="col-sm-9">{{ info.config_db }}</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3"><strong>{{ _('Log File') }}</strong></div>
|
||||
<div class="col-sm-9">{{ info.log_file }}</div>
|
||||
</div>
|
||||
{%if (info.app_mode == 'Desktop') or (info.app_mode == 'Server' and info.admin)%}
|
||||
<div class="row">
|
||||
<div class="col-sm-3"><b>{{ _('Server Configuration') }}</b></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-9">
|
||||
<textarea id="about-textarea" rows="7" cols="150" style="position: relative;width:105%; white-space: pre-wrap;" readonly>{{ info.settings|safe }}</textarea>
|
||||
<button class="btn btn-secondary about-copy" id="copy_textarea" style="position:absolute;top:0;right:0;z-index:20;">Copy</button>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
@@ -9,57 +9,33 @@
|
||||
|
||||
"""A blueprint module implementing the Authentication."""
|
||||
|
||||
import flask
|
||||
import pickle
|
||||
from flask import current_app, flash, Response, request, url_for,\
|
||||
render_template
|
||||
from flask_security import current_user
|
||||
from flask_security.views import _security, _ctx
|
||||
from flask_security.utils import config_value, get_post_logout_redirect, \
|
||||
import config
|
||||
import copy
|
||||
|
||||
from flask import current_app, flash, Response, request, url_for, \
|
||||
session, redirect
|
||||
from flask_babelex import gettext
|
||||
from flask_security.views import _security
|
||||
from flask_security.utils import get_post_logout_redirect, \
|
||||
get_post_login_redirect, logout_user
|
||||
|
||||
from flask import session
|
||||
|
||||
import config
|
||||
from pgadmin import db, User
|
||||
from pgadmin.utils import PgAdminModule
|
||||
from pgadmin.utils.constants import KERBEROS
|
||||
from pgadmin.utils.csrf import pgCSRFProtect
|
||||
|
||||
from .registry import AuthSourceRegistry
|
||||
from pgadmin.utils.constants import KERBEROS, INTERNAL, OAUTH2, LDAP
|
||||
from pgadmin.authenticate.registry import AuthSourceRegistry
|
||||
|
||||
MODULE_NAME = 'authenticate'
|
||||
auth_obj = None
|
||||
|
||||
|
||||
class AuthenticateModule(PgAdminModule):
|
||||
def get_exposed_url_endpoints(self):
|
||||
return ['authenticate.login',
|
||||
'authenticate.kerberos_login',
|
||||
'authenticate.kerberos_logout']
|
||||
return ['authenticate.login']
|
||||
|
||||
|
||||
blueprint = AuthenticateModule(MODULE_NAME, __name__, static_url_path='')
|
||||
|
||||
|
||||
@blueprint.route("/login/kerberos",
|
||||
endpoint="kerberos_login", methods=["GET"])
|
||||
@pgCSRFProtect.exempt
|
||||
def kerberos_login():
|
||||
logout_user()
|
||||
return Response(render_template("browser/kerberos_login.html",
|
||||
login_url=url_for('security.login'),
|
||||
))
|
||||
|
||||
|
||||
@blueprint.route("/logout/kerberos",
|
||||
endpoint="kerberos_logout", methods=["GET"])
|
||||
@pgCSRFProtect.exempt
|
||||
def kerberos_logout():
|
||||
logout_user()
|
||||
return Response(render_template("browser/kerberos_logout.html",
|
||||
login_url=url_for('security.login'),
|
||||
))
|
||||
|
||||
|
||||
@blueprint.route('/login', endpoint='login', methods=['GET', 'POST'])
|
||||
def login():
|
||||
"""
|
||||
@@ -67,15 +43,53 @@ def login():
|
||||
The user input will be validated and authenticated.
|
||||
"""
|
||||
form = _security.login_form()
|
||||
auth_obj = AuthSourceManager(form, config.AUTHENTICATION_SOURCES)
|
||||
session['_auth_source_manager_obj'] = None
|
||||
|
||||
auth_obj = AuthSourceManager(form, copy.deepcopy(
|
||||
config.AUTHENTICATION_SOURCES))
|
||||
if OAUTH2 in config.AUTHENTICATION_SOURCES \
|
||||
and 'oauth2_button' in request.form:
|
||||
session['auth_obj'] = auth_obj
|
||||
|
||||
session['auth_source_manager'] = None
|
||||
|
||||
username = form.data['email']
|
||||
user = User.query.filter_by(username=username,
|
||||
auth_source=INTERNAL).first()
|
||||
|
||||
if user:
|
||||
if user.login_attempts >= config.MAX_LOGIN_ATTEMPTS > 0:
|
||||
user.locked = True
|
||||
else:
|
||||
user.locked = False
|
||||
db.session.commit()
|
||||
|
||||
if user.login_attempts >= config.MAX_LOGIN_ATTEMPTS > 0:
|
||||
flash(gettext('Your account is locked. Please contact the '
|
||||
'Administrator.'),
|
||||
'warning')
|
||||
logout_user()
|
||||
return redirect(get_post_logout_redirect())
|
||||
|
||||
# Validate the user
|
||||
if not auth_obj.validate():
|
||||
for field in form.errors:
|
||||
flash_login_attempt_error = None
|
||||
if user and field in config.LOGIN_ATTEMPT_FIELDS:
|
||||
if config.MAX_LOGIN_ATTEMPTS > 0:
|
||||
user.login_attempts += 1
|
||||
left_attempts = \
|
||||
config.MAX_LOGIN_ATTEMPTS - user.login_attempts
|
||||
flash_login_attempt_error = \
|
||||
gettext('You are left with {0} more attempts.'.
|
||||
format(left_attempts))
|
||||
db.session.commit()
|
||||
for error in form.errors[field]:
|
||||
flash(error, 'warning')
|
||||
return flask.redirect(get_post_logout_redirect())
|
||||
|
||||
if flash_login_attempt_error:
|
||||
flash(flash_login_attempt_error, 'warning')
|
||||
|
||||
return redirect(get_post_logout_redirect())
|
||||
|
||||
# Authenticate the user
|
||||
status, msg = auth_obj.authenticate()
|
||||
@@ -83,34 +97,48 @@ def login():
|
||||
# Login the user
|
||||
status, msg = auth_obj.login()
|
||||
current_auth_obj = auth_obj.as_dict()
|
||||
|
||||
if not status:
|
||||
if current_auth_obj['current_source'] ==\
|
||||
if current_auth_obj['current_source'] == \
|
||||
KERBEROS:
|
||||
return flask.redirect('{0}?next={1}'.format(url_for(
|
||||
return redirect('{0}?next={1}'.format(url_for(
|
||||
'authenticate.kerberos_login'), url_for('browser.index')))
|
||||
|
||||
flash(msg, 'danger')
|
||||
return flask.redirect(get_post_logout_redirect())
|
||||
return redirect(get_post_logout_redirect())
|
||||
|
||||
session['_auth_source_manager_obj'] = current_auth_obj
|
||||
return flask.redirect(get_post_login_redirect())
|
||||
session['auth_source_manager'] = current_auth_obj
|
||||
|
||||
if user:
|
||||
user.login_attempts = 0
|
||||
db.session.commit()
|
||||
|
||||
if 'auth_obj' in session:
|
||||
session.pop('auth_obj')
|
||||
return redirect(get_post_login_redirect())
|
||||
|
||||
elif isinstance(msg, Response):
|
||||
return msg
|
||||
elif 'oauth2_button' in request.form and not isinstance(msg, str):
|
||||
return msg
|
||||
if 'auth_obj' in session:
|
||||
session.pop('auth_obj')
|
||||
flash(msg, 'danger')
|
||||
response = flask.redirect(get_post_logout_redirect())
|
||||
response = redirect(get_post_logout_redirect())
|
||||
return response
|
||||
|
||||
|
||||
class AuthSourceManager():
|
||||
class AuthSourceManager:
|
||||
"""This class will manage all the authentication sources.
|
||||
"""
|
||||
|
||||
def __init__(self, form, sources):
|
||||
self.form = form
|
||||
self.auth_sources = sources
|
||||
self.source = None
|
||||
self.source_friendly_name = None
|
||||
self.current_source = None
|
||||
self.source_friendly_name = INTERNAL
|
||||
self.current_source = INTERNAL
|
||||
self.update_auth_sources()
|
||||
|
||||
def as_dict(self):
|
||||
"""
|
||||
@@ -124,6 +152,17 @@ class AuthSourceManager():
|
||||
|
||||
return res
|
||||
|
||||
def update_auth_sources(self):
|
||||
for auth_src in [KERBEROS, OAUTH2]:
|
||||
if auth_src in self.auth_sources:
|
||||
if 'internal_button' in request.form:
|
||||
self.auth_sources.remove(auth_src)
|
||||
else:
|
||||
if INTERNAL in self.auth_sources:
|
||||
self.auth_sources.remove(INTERNAL)
|
||||
if LDAP in self.auth_sources:
|
||||
self.auth_sources.remove(LDAP)
|
||||
|
||||
def set_current_source(self, source):
|
||||
self.current_source = source
|
||||
|
||||
@@ -159,32 +198,19 @@ class AuthSourceManager():
|
||||
msg = None
|
||||
for src in self.auth_sources:
|
||||
source = get_auth_sources(src)
|
||||
self.set_source(source)
|
||||
current_app.logger.debug(
|
||||
"Authentication initiated via source: %s" %
|
||||
source.get_source_name())
|
||||
|
||||
if self.form.data['email'] and self.form.data['password'] and \
|
||||
source.get_source_name() == KERBEROS:
|
||||
continue
|
||||
|
||||
status, msg = source.authenticate(self.form)
|
||||
|
||||
# When server sends Unauthorized header to get the ticket over HTTP
|
||||
# OR When kerberos authentication failed while accessing pgadmin,
|
||||
# we need to break the loop as no need to authenticate further
|
||||
# even if the authentication sources set to multiple
|
||||
if not status and (hasattr(msg, 'status') and
|
||||
msg.status == '401 UNAUTHORIZED') or \
|
||||
(source.get_source_name() == KERBEROS and
|
||||
request.method == 'GET'):
|
||||
break
|
||||
|
||||
if status:
|
||||
self.set_source(source)
|
||||
self.set_current_source(source.get_source_name())
|
||||
if msg is not None and 'username' in msg:
|
||||
self.form._fields['email'].data = msg['username']
|
||||
return status, msg
|
||||
|
||||
return status, msg
|
||||
|
||||
def login(self):
|
||||
@@ -194,6 +220,13 @@ class AuthSourceManager():
|
||||
current_app.logger.debug(
|
||||
"Authentication and Login successfully done via source : %s" %
|
||||
self.source.get_source_name())
|
||||
|
||||
# Set the login, logout view as per source if available
|
||||
current_app.login_manager.login_view = getattr(
|
||||
self.source, 'LOGIN_VIEW', 'security.login')
|
||||
current_app.login_manager.logout_view = getattr(
|
||||
self.source, 'LOGOUT_VIEW', 'security.logout')
|
||||
|
||||
return status, msg
|
||||
|
||||
|
||||
@@ -208,7 +241,7 @@ def get_auth_sources(type):
|
||||
if type in auth_sources:
|
||||
return auth_sources[type]
|
||||
|
||||
auth_source = AuthSourceRegistry.create(type)
|
||||
auth_source = AuthSourceRegistry.get(type)
|
||||
|
||||
if auth_source is not None:
|
||||
auth_sources[type] = auth_source
|
||||
@@ -221,6 +254,6 @@ def init_app(app):
|
||||
auth_sources = dict()
|
||||
|
||||
setattr(app, '_pgadmin_auth_sources', auth_sources)
|
||||
AuthSourceRegistry.load_auth_sources()
|
||||
AuthSourceRegistry.load_modules(app)
|
||||
|
||||
return auth_sources
|
||||
@@ -10,7 +10,7 @@
|
||||
"""Implements Internal Authentication"""
|
||||
|
||||
import six
|
||||
from flask import current_app
|
||||
from flask import current_app, flash
|
||||
from flask_security import login_user
|
||||
from abc import abstractmethod, abstractproperty
|
||||
from flask_babelex import gettext
|
||||
@@ -31,6 +31,8 @@ class BaseAuthentication(object):
|
||||
'PASSWORD_NOT_PROVIDED': gettext('Password not provided'),
|
||||
'INVALID_EMAIL': gettext('Email/Username is not valid')
|
||||
}
|
||||
LOGIN_VIEW = 'security.login'
|
||||
LOGOUT_VIEW = 'security.logout'
|
||||
|
||||
@abstractmethod
|
||||
def get_source_name(self):
|
||||
@@ -97,7 +99,7 @@ class InternalAuthentication(BaseAuthentication):
|
||||
"""User validation"""
|
||||
# validate the email id first
|
||||
if not validate_email(form.data['email']):
|
||||
form.errors['email'] = [self.messages('INVALID_EMAIL')]
|
||||
flash(self.messages('INVALID_EMAIL'), 'warning')
|
||||
return False
|
||||
# Flask security validation
|
||||
return form.validate_on_submit()
|
||||
|
||||
@@ -10,22 +10,28 @@
|
||||
"""A blueprint module implementing the Spnego/Kerberos authentication."""
|
||||
|
||||
import base64
|
||||
from os import environ
|
||||
from os import environ, path, remove
|
||||
|
||||
from werkzeug.datastructures import Headers
|
||||
from werkzeug.datastructures import Headers, MultiDict
|
||||
from flask_babelex import gettext
|
||||
from flask import Flask, request, Response, session,\
|
||||
current_app, render_template, flash
|
||||
from flask import request, Response, session,\
|
||||
current_app, render_template, flash, url_for
|
||||
from flask_security.views import _security
|
||||
from flask_security.utils import logout_user
|
||||
from flask_security import login_required
|
||||
|
||||
import config
|
||||
from pgadmin.model import User
|
||||
from pgadmin.tools.user_management import create_user
|
||||
from pgadmin.utils.constants import KERBEROS
|
||||
from pgadmin.utils import PgAdminModule
|
||||
from pgadmin.utils.ajax import make_json_response, internal_server_error
|
||||
|
||||
from flask_security.views import _security
|
||||
from werkzeug.datastructures import MultiDict
|
||||
|
||||
from .internal import BaseAuthentication
|
||||
from pgadmin.authenticate.internal import BaseAuthentication
|
||||
from pgadmin.authenticate import get_auth_sources
|
||||
from pgadmin.utils.csrf import pgCSRFProtect
|
||||
|
||||
|
||||
try:
|
||||
import gssapi
|
||||
@@ -46,8 +52,110 @@ if config.KRB_KTNAME and config.KRB_KTNAME != '<KRB5_KEYTAB_FILE>':
|
||||
environ['KRB5_KTNAME'] = config.KRB_KTNAME
|
||||
|
||||
|
||||
class KerberosModule(PgAdminModule):
|
||||
def register(self, app, options, first_registration=False):
|
||||
# Do not look for the sub_modules,
|
||||
# instead call blueprint.register(...) directly
|
||||
super(PgAdminModule, self).register(app, options, first_registration)
|
||||
|
||||
def get_exposed_url_endpoints(self):
|
||||
return ['kerberos.login',
|
||||
'kerberos.logout',
|
||||
'kerberos.update_ticket',
|
||||
'kerberos.validate_ticket']
|
||||
|
||||
|
||||
def init_app(app):
|
||||
MODULE_NAME = 'kerberos'
|
||||
|
||||
blueprint = KerberosModule(MODULE_NAME, __name__, static_url_path='')
|
||||
|
||||
@blueprint.route("/login",
|
||||
endpoint="login", methods=["GET"])
|
||||
@pgCSRFProtect.exempt
|
||||
def kerberos_login():
|
||||
logout_user()
|
||||
return Response(render_template("browser/kerberos_login.html",
|
||||
login_url=url_for('security.login'),
|
||||
))
|
||||
|
||||
@blueprint.route("/logout",
|
||||
endpoint="logout", methods=["GET"])
|
||||
@pgCSRFProtect.exempt
|
||||
def kerberos_logout():
|
||||
logout_user()
|
||||
if 'KRB5CCNAME' in session:
|
||||
# Remove the credential cache
|
||||
cache_file_path = session['KRB5CCNAME'].split(":")[1]
|
||||
if path.exists(cache_file_path):
|
||||
remove(cache_file_path)
|
||||
|
||||
return Response(render_template("browser/kerberos_logout.html",
|
||||
login_url=url_for('security.login'),
|
||||
))
|
||||
|
||||
@blueprint.route("/update_ticket",
|
||||
endpoint="update_ticket", methods=["GET"])
|
||||
@pgCSRFProtect.exempt
|
||||
@login_required
|
||||
def kerberos_update_ticket():
|
||||
"""
|
||||
Update the kerberos ticket.
|
||||
"""
|
||||
from werkzeug.datastructures import Headers
|
||||
headers = Headers()
|
||||
|
||||
authorization = request.headers.get("Authorization", None)
|
||||
|
||||
if authorization is None:
|
||||
# Send the Negotiate header to the client
|
||||
# if Kerberos ticket is not found.
|
||||
headers.add('WWW-Authenticate', 'Negotiate')
|
||||
return Response("Unauthorised", 401, headers)
|
||||
else:
|
||||
source = get_auth_sources(KERBEROS)
|
||||
auth_header = authorization.split()
|
||||
in_token = auth_header[1]
|
||||
|
||||
# Validate the Kerberos ticket
|
||||
status, context = source.negotiate_start(in_token)
|
||||
if status:
|
||||
return Response("Ticket updated successfully.")
|
||||
|
||||
return Response(context, 500)
|
||||
|
||||
@blueprint.route("/validate_ticket",
|
||||
endpoint="validate_ticket", methods=["GET"])
|
||||
@pgCSRFProtect.exempt
|
||||
@login_required
|
||||
def kerberos_validate_ticket():
|
||||
"""
|
||||
Return the kerberos ticket lifetime left after getting the
|
||||
ticket from the credential cache
|
||||
"""
|
||||
import gssapi
|
||||
|
||||
try:
|
||||
del_creds = gssapi.Credentials(store={
|
||||
'ccache': session['KRB5CCNAME']})
|
||||
creds = del_creds.acquire(store={'ccache': session['KRB5CCNAME']})
|
||||
except Exception as e:
|
||||
current_app.logger.exception(e)
|
||||
return internal_server_error(errormsg=str(e))
|
||||
|
||||
return make_json_response(
|
||||
data={'ticket_lifetime': creds.lifetime},
|
||||
status=200
|
||||
)
|
||||
|
||||
app.register_blueprint(blueprint)
|
||||
|
||||
|
||||
class KerberosAuthentication(BaseAuthentication):
|
||||
|
||||
LOGIN_VIEW = 'kerberos.login'
|
||||
LOGOUT_VIEW = 'kerberos.logout'
|
||||
|
||||
def get_source_name(self):
|
||||
return KERBEROS
|
||||
|
||||
@@ -85,7 +193,7 @@ class KerberosAuthentication(BaseAuthentication):
|
||||
if status:
|
||||
# Saving the first 15 characters of the kerberos key
|
||||
# to encrypt/decrypt database password
|
||||
session['kerberos_key'] = auth_header[1][0:15]
|
||||
session['pass_enc_key'] = auth_header[1][0:15]
|
||||
# Create user
|
||||
retval = self.__auto_create_user(
|
||||
str(negotiate.initiator_name))
|
||||
@@ -128,23 +236,41 @@ class KerberosAuthentication(BaseAuthentication):
|
||||
if out_token and not context.complete:
|
||||
return False, out_token
|
||||
if context.complete:
|
||||
deleg_creds = context.delegated_creds
|
||||
if not hasattr(deleg_creds, 'name'):
|
||||
error_msg = gettext('Delegated credentials not supplied.')
|
||||
current_app.logger.error(error_msg)
|
||||
return False, Exception(error_msg)
|
||||
try:
|
||||
cache_file_path = path.join(
|
||||
config.KERBEROS_CCACHE_DIR, 'pgadmin_cache_{0}'.format(
|
||||
deleg_creds.name)
|
||||
)
|
||||
CCACHE = 'FILE:{0}'.format(cache_file_path)
|
||||
store = {'ccache': CCACHE}
|
||||
deleg_creds.store(store, overwrite=True, set_default=True)
|
||||
session['KRB5CCNAME'] = CCACHE
|
||||
except Exception as e:
|
||||
current_app.logger.exception(e)
|
||||
return False, e
|
||||
|
||||
return True, context
|
||||
else:
|
||||
return False, None
|
||||
|
||||
def negotiate_end(self, context):
|
||||
# Free gss_cred_id_t
|
||||
# Free Delegated Credentials
|
||||
del_creds = getattr(context, 'delegated_creds', None)
|
||||
if del_creds:
|
||||
deleg_creds = context.delegated_creds
|
||||
del(deleg_creds)
|
||||
|
||||
def __auto_create_user(self, username):
|
||||
"""Add the ldap user to the internal SQLite database."""
|
||||
"""Add the kerberos user to the internal SQLite database."""
|
||||
username = str(username)
|
||||
if config.KRB_AUTO_CREATE_USER:
|
||||
user = User.query.filter_by(
|
||||
username=username).first()
|
||||
username=username, auth_source=KERBEROS).first()
|
||||
if user is None:
|
||||
return create_user({
|
||||
'username': username,
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
##########################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2021, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
|
||||
"""A blueprint module implementing the Oauth2 authentication."""
|
||||
|
||||
import config
|
||||
|
||||
from authlib.integrations.flask_client import OAuth
|
||||
from flask import current_app, url_for, session, request,\
|
||||
redirect, Flask, flash
|
||||
from flask_babelex import gettext
|
||||
from flask_security import login_user, current_user
|
||||
from flask_security.utils import get_post_logout_redirect, \
|
||||
get_post_login_redirect, logout_user
|
||||
|
||||
from pgadmin.authenticate.internal import BaseAuthentication
|
||||
from pgadmin.model import User
|
||||
from pgadmin.tools.user_management import create_user
|
||||
from pgadmin.utils.constants import OAUTH2
|
||||
from pgadmin.utils import PgAdminModule
|
||||
from pgadmin.utils.csrf import pgCSRFProtect
|
||||
from pgadmin.model import db
|
||||
|
||||
OAUTH2_LOGOUT = 'oauth2.logout'
|
||||
OAUTH2_AUTHORIZE = 'oauth2.authorize'
|
||||
|
||||
|
||||
class Oauth2Module(PgAdminModule):
|
||||
def register(self, app, options, first_registration=False):
|
||||
# Do not look for the sub_modules,
|
||||
# instead call blueprint.register(...) directly
|
||||
super(PgAdminModule, self).register(app, options, first_registration)
|
||||
|
||||
def get_exposed_url_endpoints(self):
|
||||
return [OAUTH2_AUTHORIZE,
|
||||
OAUTH2_LOGOUT]
|
||||
|
||||
|
||||
def init_app(app):
|
||||
MODULE_NAME = 'oauth2'
|
||||
|
||||
blueprint = Oauth2Module(MODULE_NAME, __name__, static_url_path='')
|
||||
|
||||
@blueprint.route('/authorize', endpoint="authorize",
|
||||
methods=['GET', 'POST'])
|
||||
@pgCSRFProtect.exempt
|
||||
def oauth_authorize():
|
||||
auth_obj = session['auth_obj']
|
||||
auth_obj.set_current_source(auth_obj.source.get_source_name())
|
||||
status, msg = auth_obj.login()
|
||||
if status:
|
||||
session['auth_source_manager'] = auth_obj.as_dict()
|
||||
if 'auth_obj' in session:
|
||||
session.pop('auth_obj')
|
||||
return redirect(get_post_login_redirect())
|
||||
if 'auth_obj' in session:
|
||||
session.pop('auth_obj')
|
||||
logout_user()
|
||||
flash(msg, 'danger')
|
||||
return redirect(get_post_login_redirect())
|
||||
|
||||
@blueprint.route('/logout', endpoint="logout",
|
||||
methods=['GET', 'POST'])
|
||||
@pgCSRFProtect.exempt
|
||||
def oauth_logout():
|
||||
if not current_user.is_authenticated:
|
||||
return redirect(get_post_logout_redirect())
|
||||
for key in list(session.keys()):
|
||||
session.pop(key)
|
||||
logout_user()
|
||||
return redirect(get_post_logout_redirect())
|
||||
|
||||
app.register_blueprint(blueprint)
|
||||
app.login_manager.logout_view = OAUTH2_LOGOUT
|
||||
|
||||
|
||||
class OAuth2Authentication(BaseAuthentication):
|
||||
"""OAuth Authentication Class"""
|
||||
|
||||
LOGOUT_VIEW = OAUTH2_LOGOUT
|
||||
|
||||
oauth_obj = OAuth(Flask(__name__))
|
||||
oauth2_clients = {}
|
||||
oauth2_config = {}
|
||||
|
||||
def __init__(self):
|
||||
for oauth2_config in config.OAUTH2_CONFIG:
|
||||
|
||||
OAuth2Authentication.oauth2_config[
|
||||
oauth2_config['OAUTH2_NAME']] = oauth2_config
|
||||
|
||||
OAuth2Authentication.oauth2_clients[
|
||||
oauth2_config['OAUTH2_NAME']
|
||||
] = OAuth2Authentication.oauth_obj.register(
|
||||
name=oauth2_config['OAUTH2_NAME'],
|
||||
client_id=oauth2_config['OAUTH2_CLIENT_ID'],
|
||||
client_secret=oauth2_config['OAUTH2_CLIENT_SECRET'],
|
||||
access_token_url=oauth2_config['OAUTH2_TOKEN_URL'],
|
||||
authorize_url=oauth2_config['OAUTH2_AUTHORIZATION_URL'],
|
||||
api_base_url=oauth2_config['OAUTH2_API_BASE_URL'],
|
||||
client_kwargs={'scope': 'email profile'}
|
||||
)
|
||||
|
||||
def get_source_name(self):
|
||||
return OAUTH2
|
||||
|
||||
def get_friendly_name(self):
|
||||
return self.oauth2_config[self.oauth2_current_client]['OAUTH2_NAME']
|
||||
|
||||
def validate(self, form):
|
||||
return True
|
||||
|
||||
def login(self, form):
|
||||
profile = self.get_user_profile()
|
||||
if 'email' not in profile or not profile['email']:
|
||||
current_app.logger.exception(
|
||||
"An email id is required to login into pgAdmin. "
|
||||
"Please update your Oauth2 profile."
|
||||
)
|
||||
return False, gettext(
|
||||
"An email id is required to login into pgAdmin. "
|
||||
"Please update your Oauth2 profile.")
|
||||
|
||||
user, msg = self.__auto_create_user(profile)
|
||||
if user:
|
||||
user = db.session.query(User).filter_by(
|
||||
username=profile['email'], auth_source=OAUTH2).first()
|
||||
current_app.login_manager.logout_view = \
|
||||
OAuth2Authentication.LOGOUT_VIEW
|
||||
return login_user(user), None
|
||||
return False, msg
|
||||
|
||||
def get_user_profile(self):
|
||||
session['oauth2_token'] = self.oauth2_clients[
|
||||
self.oauth2_current_client].authorize_access_token()
|
||||
|
||||
session['pass_enc_key'] = session['oauth2_token']['access_token']
|
||||
|
||||
resp = self.oauth2_clients[self.oauth2_current_client].get(
|
||||
self.oauth2_config[
|
||||
self.oauth2_current_client]['OAUTH2_USERINFO_ENDPOINT'],
|
||||
token=session['oauth2_token']
|
||||
)
|
||||
resp.raise_for_status()
|
||||
return resp.json()
|
||||
|
||||
def authenticate(self, form):
|
||||
self.oauth2_current_client = request.form['oauth2_button']
|
||||
redirect_url = url_for(OAUTH2_AUTHORIZE, _external=True)
|
||||
|
||||
if self.oauth2_current_client not in self.oauth2_clients:
|
||||
return False, gettext(
|
||||
"Please set the configuration parameters properly.")
|
||||
return False, self.oauth2_clients[
|
||||
self.oauth2_current_client].authorize_redirect(redirect_url)
|
||||
|
||||
def __auto_create_user(self, resp):
|
||||
if config.OAUTH2_AUTO_CREATE_USER:
|
||||
user = User.query.filter_by(username=resp['email'],
|
||||
auth_source=OAUTH2).first()
|
||||
if not user:
|
||||
return create_user({
|
||||
'username': resp['email'],
|
||||
'email': resp['email'],
|
||||
'role': 2,
|
||||
'active': True,
|
||||
'auth_source': OAUTH2
|
||||
})
|
||||
|
||||
return True, {'username': resp['email']}
|
||||
@@ -10,56 +10,9 @@
|
||||
"""External Authentication Registry."""
|
||||
|
||||
|
||||
from flask_babelex import gettext
|
||||
from abc import ABCMeta
|
||||
from pgadmin.utils.dynamic_registry import create_registry_metaclass
|
||||
|
||||
|
||||
def _decorate_cls_name(module_name):
|
||||
length = len(__package__) + 1
|
||||
|
||||
if len(module_name) > length and module_name.startswith(__package__):
|
||||
return module_name[length:]
|
||||
|
||||
return module_name
|
||||
|
||||
|
||||
class AuthSourceRegistry(ABCMeta):
|
||||
registry = None
|
||||
auth_sources = dict()
|
||||
|
||||
def __init__(self, name, bases, d):
|
||||
|
||||
# Register this type of auth_sources, based on the module name
|
||||
# Avoid registering the BaseAuthentication itself
|
||||
|
||||
AuthSourceRegistry.registry[_decorate_cls_name(d['__module__'])] = self
|
||||
ABCMeta.__init__(self, name, bases, d)
|
||||
|
||||
@classmethod
|
||||
def create(cls, name, **kwargs):
|
||||
|
||||
if name in AuthSourceRegistry.auth_sources:
|
||||
return AuthSourceRegistry.auth_sources[name]
|
||||
|
||||
if name in AuthSourceRegistry.registry:
|
||||
AuthSourceRegistry.auth_sources[name] = \
|
||||
(AuthSourceRegistry.registry[name])(**kwargs)
|
||||
return AuthSourceRegistry.auth_sources[name]
|
||||
|
||||
raise NotImplementedError(
|
||||
gettext(
|
||||
"Authentication source '{0}' has not been implemented."
|
||||
).format(name)
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def load_auth_sources(cls):
|
||||
# Initialize the registry only if it has not yet been initialized
|
||||
if AuthSourceRegistry.registry is None:
|
||||
AuthSourceRegistry.registry = dict()
|
||||
|
||||
from importlib import import_module
|
||||
from werkzeug.utils import find_modules
|
||||
|
||||
for module_name in find_modules(__package__, True):
|
||||
import_module(module_name)
|
||||
AuthSourceRegistry = create_registry_metaclass(
|
||||
"AuthSourceRegistry", __package__, decorate_as_module=True
|
||||
)
|
||||
@@ -0,0 +1,68 @@
|
||||
/////////////////////////////////////////////////////////////
|
||||
//
|
||||
// pgAdmin 4 - PostgreSQL Tools
|
||||
//
|
||||
// Copyright (C) 2013 - 2021, The pgAdmin Development Team
|
||||
// This software is released under the PostgreSQL Licence
|
||||
//
|
||||
//////////////////////////////////////////////////////////////
|
||||
|
||||
import url_for from 'sources/url_for';
|
||||
import userInfo from 'pgadmin.user_management.current_user';
|
||||
import pgConst from 'pgadmin.browser.constants';
|
||||
|
||||
function fetch_ticket() {
|
||||
// Fetch the Kerberos Updated ticket through SPNEGO
|
||||
return fetch(url_for('kerberos.update_ticket')
|
||||
)
|
||||
.then(function(response){
|
||||
if (response.status >= 200 && response.status < 300) {
|
||||
return Promise.resolve(response);
|
||||
} else {
|
||||
return Promise.reject(new Error(response.statusText));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function fetch_ticket_lifetime () {
|
||||
// Fetch the Kerberos ticket lifetime left
|
||||
|
||||
return fetch(url_for('kerberos.validate_ticket')
|
||||
)
|
||||
.then(
|
||||
function(response){
|
||||
if (response.status >= 200 && response.status < 300) {
|
||||
return response.json();
|
||||
} else {
|
||||
return Promise.reject(new Error(response.statusText));
|
||||
}
|
||||
}
|
||||
)
|
||||
.then(function(response){
|
||||
let ticket_lifetime = response.data.ticket_lifetime;
|
||||
if (ticket_lifetime > 0) {
|
||||
return Promise.resolve(ticket_lifetime);
|
||||
} else {
|
||||
return Promise.reject();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function validate_kerberos_ticket() {
|
||||
// Ping pgAdmin server every 10 seconds
|
||||
// to fetch the Kerberos ticket lifetime left
|
||||
if (userInfo['current_auth_source'] != pgConst['KERBEROS']) return;
|
||||
|
||||
return setInterval(function() {
|
||||
let newPromise = fetch_ticket_lifetime();
|
||||
newPromise.then(
|
||||
function() {
|
||||
return;
|
||||
},
|
||||
fetch_ticket
|
||||
);
|
||||
}, 10000);
|
||||
}
|
||||
|
||||
export {fetch_ticket, validate_kerberos_ticket, fetch_ticket_lifetime};
|
||||
@@ -31,8 +31,9 @@ from flask_security.recoverable import reset_password_token_status, \
|
||||
generate_reset_password_token, update_password
|
||||
from flask_security.signals import reset_password_instructions_sent
|
||||
from flask_security.utils import config_value, do_flash, get_url, \
|
||||
get_message, slash_url_suffix, login_user, send_mail, logout_user
|
||||
from flask_security.views import _security, _commit, _ctx
|
||||
get_message, slash_url_suffix, login_user, send_mail, logout_user, \
|
||||
get_post_logout_redirect
|
||||
from flask_security.views import _security, view_commit, _ctx
|
||||
from werkzeug.datastructures import MultiDict
|
||||
|
||||
import config
|
||||
@@ -50,7 +51,8 @@ from pgadmin.utils.master_password import validate_master_password, \
|
||||
set_crypt_key, process_masterpass_disabled
|
||||
from pgadmin.model import User
|
||||
from pgadmin.utils.constants import MIMETYPE_APP_JS, PGADMIN_NODE,\
|
||||
INTERNAL, KERBEROS
|
||||
INTERNAL, KERBEROS, LDAP, QT_DEFAULT_PLACEHOLDER, OAUTH2
|
||||
from pgadmin.authenticate import AuthSourceManager
|
||||
|
||||
try:
|
||||
from flask_security.views import default_render_json
|
||||
@@ -197,7 +199,8 @@ class BrowserModule(PgAdminModule):
|
||||
for name, script in [
|
||||
[PGADMIN_BROWSER, 'js/browser'],
|
||||
['pgadmin.browser.endpoints', 'js/endpoints'],
|
||||
['pgadmin.browser.error', 'js/error']
|
||||
['pgadmin.browser.error', 'js/error'],
|
||||
['pgadmin.browser.constants', 'js/constants']
|
||||
]:
|
||||
scripts.append({
|
||||
'name': name,
|
||||
@@ -341,6 +344,7 @@ class BrowserModule(PgAdminModule):
|
||||
list: a list of url endpoints exposed to the client.
|
||||
"""
|
||||
return [BROWSER_INDEX, 'browser.nodes',
|
||||
'browser.check_corrupted_db_file',
|
||||
'browser.check_master_password',
|
||||
'browser.set_master_password',
|
||||
'browser.reset_master_password',
|
||||
@@ -604,14 +608,8 @@ class BrowserPluginModule(PgAdminModule):
|
||||
|
||||
|
||||
def _get_logout_url():
|
||||
if config.SERVER_MODE and\
|
||||
session['_auth_source_manager_obj']['current_source'] == \
|
||||
KERBEROS:
|
||||
return '{0}?next={1}'.format(url_for(
|
||||
'authenticate.kerberos_logout'), url_for(BROWSER_INDEX))
|
||||
|
||||
return '{0}?next={1}'.format(
|
||||
url_for('security.logout'), url_for(BROWSER_INDEX))
|
||||
url_for(current_app.login_manager.logout_view), url_for(BROWSER_INDEX))
|
||||
|
||||
|
||||
def _get_supported_browser():
|
||||
@@ -745,10 +743,10 @@ def index():
|
||||
if len(config.AUTHENTICATION_SOURCES) == 1\
|
||||
and INTERNAL in config.AUTHENTICATION_SOURCES:
|
||||
auth_only_internal = True
|
||||
auth_source = session['_auth_source_manager_obj'][
|
||||
auth_source = session['auth_source_manager'][
|
||||
'source_friendly_name']
|
||||
|
||||
if session['_auth_source_manager_obj']['current_source'] == KERBEROS:
|
||||
if not config.MASTER_PASSWORD_REQUIRED and 'pass_enc_key' in session:
|
||||
session['allow_save_password'] = False
|
||||
|
||||
response = Response(render_template(
|
||||
@@ -850,7 +848,10 @@ def utils():
|
||||
app_version_int=config.APP_VERSION_INT,
|
||||
pg_libpq_version=pg_libpq_version,
|
||||
support_ssh_tunnel=config.SUPPORT_SSH_TUNNEL,
|
||||
logout_url=_get_logout_url()
|
||||
logout_url=_get_logout_url(),
|
||||
platform=sys.platform,
|
||||
qt_default_placeholder=QT_DEFAULT_PLACEHOLDER,
|
||||
enable_psql=config.ENABLE_PSQL
|
||||
),
|
||||
200, {'Content-Type': MIMETYPE_APP_JS})
|
||||
|
||||
@@ -864,6 +865,19 @@ def exposed_urls():
|
||||
)
|
||||
|
||||
|
||||
@blueprint.route("/js/constants.js")
|
||||
@pgCSRFProtect.exempt
|
||||
def app_constants():
|
||||
return make_response(
|
||||
render_template('browser/js/constants.js',
|
||||
INTERNAL=INTERNAL,
|
||||
LDAP=LDAP,
|
||||
KERBEROS=KERBEROS,
|
||||
OAUTH2=OAUTH2),
|
||||
200, {'Content-Type': MIMETYPE_APP_JS}
|
||||
)
|
||||
|
||||
|
||||
@blueprint.route("/js/error.js")
|
||||
@pgCSRFProtect.exempt
|
||||
@login_required
|
||||
@@ -936,6 +950,19 @@ def form_master_password_response(existing=True, present=False, errmsg=None):
|
||||
})
|
||||
|
||||
|
||||
@blueprint.route("/check_corrupted_db_file",
|
||||
endpoint="check_corrupted_db_file", methods=["GET"])
|
||||
def check_corrupted_db_file():
|
||||
"""
|
||||
Get the corrupted database file path.
|
||||
"""
|
||||
file_location = os.environ['CORRUPTED_DB_BACKUP_FILE'] \
|
||||
if 'CORRUPTED_DB_BACKUP_FILE' in os.environ else ''
|
||||
# reset the corrupted db file path in env.
|
||||
os.environ['CORRUPTED_DB_BACKUP_FILE'] = ''
|
||||
return make_json_response(data=file_location)
|
||||
|
||||
|
||||
@blueprint.route("/master_password", endpoint="check_master_password",
|
||||
methods=["GET"])
|
||||
def check_master_password():
|
||||
@@ -974,8 +1001,10 @@ def set_master_password():
|
||||
data = json.loads(data)
|
||||
|
||||
# Master password is not applicable for server mode
|
||||
if not config.SERVER_MODE and config.MASTER_PASSWORD_REQUIRED:
|
||||
|
||||
# Enable master password if oauth is used
|
||||
if not config.SERVER_MODE or OAUTH2 in config.AUTHENTICATION_SOURCES \
|
||||
or KERBEROS in config.AUTHENTICATION_SOURCES \
|
||||
and config.MASTER_PASSWORD_REQUIRED:
|
||||
# if master pass is set previously
|
||||
if current_user.masterpass_check is not None and \
|
||||
data.get('button_click') and \
|
||||
@@ -1012,7 +1041,7 @@ def set_master_password():
|
||||
existing=True,
|
||||
present=False,
|
||||
)
|
||||
elif not get_crypt_key()[0]:
|
||||
elif not get_crypt_key()[1]:
|
||||
error_message = None
|
||||
if data.get('button_click') and data.get('password') == '':
|
||||
# If user attempted to enter a blank password, then throw error
|
||||
@@ -1104,7 +1133,8 @@ if hasattr(config, 'SECURITY_CHANGEABLE') and config.SECURITY_CHANGEABLE:
|
||||
|
||||
if form.validate_on_submit():
|
||||
try:
|
||||
change_user_password(current_user, form.new_password.data)
|
||||
change_user_password(current_user._get_current_object(),
|
||||
form.new_password.data)
|
||||
except SOCKETErrorException as e:
|
||||
# Handle socket errors which are not covered by SMTPExceptions.
|
||||
logging.exception(str(e), exc_info=True)
|
||||
@@ -1130,7 +1160,7 @@ if hasattr(config, 'SECURITY_CHANGEABLE') and config.SECURITY_CHANGEABLE:
|
||||
has_error = True
|
||||
|
||||
if request.json is None and not has_error:
|
||||
after_this_request(_commit)
|
||||
after_this_request(view_commit)
|
||||
do_flash(*get_message('PASSWORD_CHANGE'))
|
||||
|
||||
old_key = get_crypt_key()[1]
|
||||
@@ -1296,9 +1326,21 @@ if hasattr(config, 'SECURITY_RECOVERABLE') and config.SECURITY_RECOVERABLE:
|
||||
has_error = True
|
||||
|
||||
if not has_error:
|
||||
after_this_request(_commit)
|
||||
after_this_request(view_commit)
|
||||
auth_obj = AuthSourceManager(form, [INTERNAL])
|
||||
session['_auth_source_manager_obj'] = auth_obj.as_dict()
|
||||
|
||||
if user.login_attempts >= config.MAX_LOGIN_ATTEMPTS > 0:
|
||||
flash(gettext('You successfully reset your password but'
|
||||
' your account is locked. Please contact '
|
||||
'the Administrator.'),
|
||||
'warning')
|
||||
return redirect(get_post_logout_redirect())
|
||||
do_flash(*get_message('PASSWORD_RESET'))
|
||||
login_user(user)
|
||||
auth_obj = AuthSourceManager(form, [INTERNAL])
|
||||
session['auth_source_manager'] = auth_obj.as_dict()
|
||||
|
||||
return redirect(get_url(_security.post_reset_view) or
|
||||
get_url(_security.post_login_view))
|
||||
|
||||
|
||||
@@ -6,10 +6,12 @@
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##########################################################################
|
||||
import sys
|
||||
from flask_babelex import gettext
|
||||
from pgadmin.utils.constants import PREF_LABEL_DISPLAY,\
|
||||
PREF_LABEL_KEYBOARD_SHORTCUTS, PREF_LABEL_TABS_SETTINGS, \
|
||||
PREF_LABEL_OPTIONS
|
||||
PREF_LABEL_OPTIONS, QT_DEFAULT_PLACEHOLDER
|
||||
from flask_security import current_user
|
||||
import config
|
||||
|
||||
LOCK_LAYOUT_LEVEL = {
|
||||
@@ -468,7 +470,7 @@ def register_browser_preferences(self):
|
||||
self.qt_tab_title = self.preference.register(
|
||||
'tab_settings', 'qt_tab_title_placeholder',
|
||||
gettext("Query tool tab title"),
|
||||
'text', '%DATABASE%/%USERNAME%@%SERVER%',
|
||||
'text', QT_DEFAULT_PLACEHOLDER,
|
||||
category_label=PREF_LABEL_DISPLAY,
|
||||
help_str=gettext(
|
||||
'Supported placeholders are %DATABASE%, %USERNAME%, and %SERVER%. '
|
||||
@@ -504,17 +506,27 @@ def register_browser_preferences(self):
|
||||
)
|
||||
)
|
||||
|
||||
ope_new_tab_options = [
|
||||
{'label': gettext('Query Tool'), 'value': 'qt'},
|
||||
{'label': gettext('Debugger'), 'value': 'debugger'},
|
||||
{'label': gettext('Schema Diff'), 'value': 'schema_diff'},
|
||||
{'label': gettext('ERD Tool'), 'value': 'erd_tool'}]
|
||||
|
||||
# Allow psq tool to open in new browser tab if ENABLE_PSQL is set to True
|
||||
if config.ENABLE_PSQL:
|
||||
ope_new_tab_options.append(
|
||||
{'label': gettext('PSQL Tool'), 'value': 'psql_tool'})
|
||||
|
||||
self.open_in_new_tab = self.preference.register(
|
||||
'tab_settings', 'new_browser_tab_open',
|
||||
gettext("Open in new browser tab"), 'select2', None,
|
||||
category_label=PREF_LABEL_OPTIONS,
|
||||
options=[{'label': gettext('Query Tool'), 'value': 'qt'},
|
||||
{'label': gettext('Debugger'), 'value': 'debugger'},
|
||||
{'label': gettext('Schema Diff'), 'value': 'schema_diff'},
|
||||
{'label': gettext('ERD Tool'), 'value': 'erd_tool'}],
|
||||
help_str=gettext('Select Query Tool, Debugger, or Schema Diff from '
|
||||
'the drop-down to set open in new browser tab for '
|
||||
'that particular module.'),
|
||||
options=ope_new_tab_options,
|
||||
help_str=gettext(
|
||||
'Select Query Tool, Debugger, Schema Diff, ERD Tool '
|
||||
'or PSQL Tool from the drop-down to set '
|
||||
'open in new browser tab for that particular module.'
|
||||
),
|
||||
select2={
|
||||
'multiple': True, 'allowClear': False,
|
||||
'tags': True, 'first_empty': False,
|
||||
@@ -523,3 +535,18 @@ def register_browser_preferences(self):
|
||||
'placeholder': gettext('Select open new tab...')
|
||||
}
|
||||
)
|
||||
|
||||
# Set PSQL tool tab title if ENABLE_PSQL is set to True
|
||||
if config.ENABLE_PSQL:
|
||||
self.psql_tab_title = self.preference.register(
|
||||
'tab_settings', 'psql_tab_title_placeholder',
|
||||
gettext("PSQL tool tab title"),
|
||||
'text', '%DATABASE%/%USERNAME%@%SERVER%',
|
||||
category_label=PREF_LABEL_DISPLAY,
|
||||
help_str=gettext(
|
||||
'Supported placeholders are %DATABASE%, %USERNAME%, '
|
||||
'and %SERVER%. Users can provide any string with or without'
|
||||
' placeholders of their choice. The blank title will be revert'
|
||||
' back to the default title with placeholders.'
|
||||
)
|
||||
)
|
||||
@@ -34,6 +34,7 @@ from pgadmin.utils.constants import UNAUTH_REQ, MIMETYPE_APP_JS, \
|
||||
SERVER_CONNECTION_CLOSED
|
||||
from sqlalchemy import or_
|
||||
from pgadmin.utils.preferences import Preferences
|
||||
from .... import socketio as sio
|
||||
|
||||
|
||||
def has_any(data, keys):
|
||||
@@ -253,7 +254,9 @@ class ServerModule(sg.ServerGroupPluginModule):
|
||||
errmsg=errmsg,
|
||||
user_id=server.user_id,
|
||||
user_name=server.username,
|
||||
shared=server.shared
|
||||
shared=server.shared,
|
||||
is_kerberos_conn=bool(server.kerberos_conn),
|
||||
gss_authenticated=manager.gss_authenticated
|
||||
)
|
||||
|
||||
@property
|
||||
@@ -339,6 +342,7 @@ class ServerModule(sg.ServerGroupPluginModule):
|
||||
db.session.rollback()
|
||||
user = User.query.filter_by(id=data.user_id).first()
|
||||
shared_server = SharedServer(
|
||||
osid=data.id,
|
||||
user_id=current_user.id,
|
||||
server_owner=user.username,
|
||||
servergroup_id=gid,
|
||||
@@ -388,14 +392,14 @@ class ServerModule(sg.ServerGroupPluginModule):
|
||||
"""
|
||||
shared_server = SharedServer.query.filter_by(
|
||||
name=server.name, user_id=current_user.id,
|
||||
servergroup_id=gid).first()
|
||||
servergroup_id=gid, osid=server.id).first()
|
||||
|
||||
if shared_server is None:
|
||||
ServerModule.create_shared_server(server, gid)
|
||||
|
||||
shared_server = SharedServer.query.filter_by(
|
||||
name=server.name, user_id=current_user.id,
|
||||
servergroup_id=gid).first()
|
||||
servergroup_id=gid, osid=server.id).first()
|
||||
|
||||
return shared_server
|
||||
|
||||
@@ -546,7 +550,9 @@ class ServerNode(PGChildNodeView):
|
||||
if server.tunnel_password is not None else False,
|
||||
errmsg=errmsg,
|
||||
user_name=server.username,
|
||||
shared=server.shared
|
||||
shared=server.shared,
|
||||
is_kerberos_conn=bool(server.kerberos_conn),
|
||||
gss_authenticated=manager.gss_authenticated
|
||||
)
|
||||
)
|
||||
|
||||
@@ -613,11 +619,13 @@ class ServerNode(PGChildNodeView):
|
||||
if server.tunnel_password is not None else False,
|
||||
errmsg=errmsg,
|
||||
shared=server.shared,
|
||||
user_name=server.username
|
||||
user_name=server.username,
|
||||
is_kerberos_conn=bool(server.kerberos_conn),
|
||||
gss_authenticated=manager.gss_authenticated
|
||||
),
|
||||
)
|
||||
|
||||
def delete_shared_server(self, server_name, gid):
|
||||
def delete_shared_server(self, server_name, gid, osid):
|
||||
"""
|
||||
Delete the shared server
|
||||
:param server_name:
|
||||
@@ -625,7 +633,8 @@ class ServerNode(PGChildNodeView):
|
||||
"""
|
||||
try:
|
||||
shared_server = SharedServer.query.filter_by(name=server_name,
|
||||
servergroup_id=gid)
|
||||
servergroup_id=gid,
|
||||
osid=osid)
|
||||
for s in shared_server:
|
||||
get_driver(PG_DEFAULT_DRIVER).delete_manager(s.id)
|
||||
db.session.delete(s)
|
||||
@@ -661,7 +670,7 @@ class ServerNode(PGChildNodeView):
|
||||
get_driver(PG_DEFAULT_DRIVER).delete_manager(s.id)
|
||||
db.session.delete(s)
|
||||
db.session.commit()
|
||||
self.delete_shared_server(server_name, gid)
|
||||
self.delete_shared_server(server_name, gid, sid)
|
||||
QueryHistory.clear_history(current_user.id, sid)
|
||||
|
||||
except Exception as e:
|
||||
@@ -719,7 +728,8 @@ class ServerNode(PGChildNodeView):
|
||||
'tunnel_username': 'tunnel_username',
|
||||
'tunnel_authentication': 'tunnel_authentication',
|
||||
'tunnel_identity_file': 'tunnel_identity_file',
|
||||
'shared': 'shared'
|
||||
'shared': 'shared',
|
||||
'kerberos_conn': 'kerberos_conn',
|
||||
}
|
||||
|
||||
disp_lbl = {
|
||||
@@ -818,7 +828,7 @@ class ServerNode(PGChildNodeView):
|
||||
if 'shared' in data and not data['shared']:
|
||||
# Delete the shared server from DB if server
|
||||
# owner uncheck shared property
|
||||
self.delete_shared_server(server.name, gid)
|
||||
self.delete_shared_server(server.name, gid, server.id)
|
||||
if arg == 'sslcompression':
|
||||
value = 1 if value else 0
|
||||
self._update_server_details(server, sharedserver,
|
||||
@@ -983,7 +993,10 @@ class ServerNode(PGChildNodeView):
|
||||
'tunnel_username': tunnel_username,
|
||||
'tunnel_identity_file': server.tunnel_identity_file
|
||||
if server.tunnel_identity_file else None,
|
||||
'tunnel_authentication': tunnel_authentication
|
||||
'tunnel_authentication': tunnel_authentication,
|
||||
'kerberos_conn': bool(server.kerberos_conn),
|
||||
'gss_authenticated': manager.gss_authenticated,
|
||||
'gss_encrypted': manager.gss_encrypted
|
||||
}
|
||||
|
||||
return ajax_response(response)
|
||||
@@ -1070,7 +1083,8 @@ class ServerNode(PGChildNodeView):
|
||||
tunnel_authentication=data.get('tunnel_authentication', 0),
|
||||
tunnel_identity_file=data.get('tunnel_identity_file', None),
|
||||
shared=data.get('shared', None),
|
||||
passfile=data.get('passfile', None)
|
||||
passfile=data.get('passfile', None),
|
||||
kerberos_conn=1 if data.get('kerberos_conn', False) else 0,
|
||||
)
|
||||
db.session.add(server)
|
||||
db.session.commit()
|
||||
@@ -1152,7 +1166,10 @@ class ServerNode(PGChildNodeView):
|
||||
else 'pg',
|
||||
version=manager.version
|
||||
if manager and manager.version
|
||||
else None
|
||||
else None,
|
||||
is_kerberos_conn=bool(server.kerberos_conn),
|
||||
gss_authenticated=manager.gss_authenticated if
|
||||
manager and manager.gss_authenticated else False
|
||||
)
|
||||
)
|
||||
|
||||
@@ -1346,7 +1363,8 @@ class ServerNode(PGChildNodeView):
|
||||
except Exception as e:
|
||||
current_app.logger.exception(e)
|
||||
return internal_server_error(errormsg=str(e))
|
||||
if 'password' not in data:
|
||||
if 'password' not in data and (server.kerberos_conn is False or
|
||||
server.kerberos_conn is None):
|
||||
conn_passwd = getattr(conn, 'password', None)
|
||||
if conn_passwd is None and not server.save_password and \
|
||||
server.passfile is None and server.service is None:
|
||||
@@ -1398,6 +1416,9 @@ class ServerNode(PGChildNodeView):
|
||||
"Could not connect to server(#{0}) - '{1}'.\nError: {2}"
|
||||
.format(server.id, server.name, errmsg)
|
||||
)
|
||||
if errmsg.find('Ticket expired') != -1:
|
||||
return internal_server_error(errmsg)
|
||||
|
||||
return self.get_response_for_password(server, 401, True,
|
||||
True, errmsg)
|
||||
else:
|
||||
@@ -1465,6 +1486,8 @@ class ServerNode(PGChildNodeView):
|
||||
'is_password_saved': bool(server.save_password),
|
||||
'is_tunnel_password_saved': True
|
||||
if server.tunnel_password is not None else False,
|
||||
'is_kerberos_conn': bool(server.kerberos_conn),
|
||||
'gss_authenticated': manager.gss_authenticated
|
||||
}
|
||||
)
|
||||
|
||||
@@ -1477,6 +1500,13 @@ class ServerNode(PGChildNodeView):
|
||||
|
||||
# Release Connection
|
||||
manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(sid)
|
||||
# Check if any psql terminal is running for the current disconnecting
|
||||
# server. If any terminate the psql tool connection.
|
||||
if 'sid_soid_mapping' in current_app.config and str(sid) in \
|
||||
current_app.config['sid_soid_mapping']:
|
||||
if str(sid) in current_app.config['sid_soid_mapping']:
|
||||
for i in current_app.config['sid_soid_mapping'][str(sid)]:
|
||||
sio.emit('disconnect-psql', namespace='/pty', to=i)
|
||||
|
||||
status = manager.release()
|
||||
|
||||
@@ -1878,7 +1908,7 @@ class ServerNode(PGChildNodeView):
|
||||
if server.shared and server.user_id != current_user.id:
|
||||
shared_server = SharedServer.query.filter_by(
|
||||
name=server.name, user_id=current_user.id,
|
||||
servergroup_id=gid).first()
|
||||
servergroup_id=gid, osid=server.id).first()
|
||||
|
||||
if shared_server is None:
|
||||
return make_json_response(
|
||||
|
||||
@@ -490,6 +490,7 @@ class DatabaseView(PGChildNodeView):
|
||||
did, errmsg
|
||||
)
|
||||
)
|
||||
|
||||
return internal_server_error(errmsg)
|
||||
else:
|
||||
current_app.logger.info(
|
||||
|
||||
@@ -405,7 +405,7 @@ class CastView(PGChildNodeView, SchemaDiffObjectCompare):
|
||||
if not status:
|
||||
return internal_server_error(errormsg=res)
|
||||
|
||||
# we need oid to to add object in tree at browser, below sql will
|
||||
# we need oid to add object in tree at browser, below sql will
|
||||
# gives the same
|
||||
last_system_oid = 0 if self.blueprint.show_system_objects else \
|
||||
self.datlastsysoid
|
||||
|
||||
@@ -189,12 +189,7 @@ define('pgadmin.node.language', [
|
||||
});
|
||||
}
|
||||
return res;
|
||||
}, disabled: function(m) {
|
||||
if (m.isNew()) {
|
||||
return m.get('template_list').indexOf(m.get('name')) != -1;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
}, disabled: 'isDisabled',
|
||||
readonly: function(m) {return !m.isNew();},
|
||||
},{
|
||||
id: 'laninl', label: gettext('Inline function'), type: 'text', control: 'node-ajax-options',
|
||||
@@ -214,12 +209,7 @@ define('pgadmin.node.language', [
|
||||
});
|
||||
}
|
||||
return res;
|
||||
}, disabled: function(m) {
|
||||
if (m.isNew()) {
|
||||
return m.get('template_list').indexOf(m.get('name')) != -1;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
}, disabled: 'isDisabled',
|
||||
readonly: function(m) {return !m.isNew();},
|
||||
},{
|
||||
id: 'lanval', label: gettext('Validator function'), type: 'text', control: 'node-ajax-options',
|
||||
@@ -239,12 +229,7 @@ define('pgadmin.node.language', [
|
||||
});
|
||||
}
|
||||
return res;
|
||||
}, disabled: function(m) {
|
||||
if (m.isNew()) {
|
||||
return m.get('template_list').indexOf(m.get('name')) != -1;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
}, disabled: 'isDisabled',
|
||||
readonly: function(m) {return !m.isNew();},
|
||||
}, {
|
||||
id: 'lanacl', label: gettext('Privileges'), type: 'collection',
|
||||
@@ -292,6 +277,12 @@ define('pgadmin.node.language', [
|
||||
|
||||
return null;
|
||||
},
|
||||
isDisabled: function(m){
|
||||
if (m.isNew()) {
|
||||
return m.get('template_list').indexOf(m.get('name')) != -1;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
}),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -630,7 +630,7 @@ It may have been removed by another user.
|
||||
errormsg=res
|
||||
)
|
||||
|
||||
# we need oid to to add object in tree at browser,
|
||||
# we need oid to add object in tree at browser,
|
||||
# below sql will gives the same
|
||||
SQL = render_template(
|
||||
"/".join([self.template_path, 'sql/oid.sql']),
|
||||
|
||||
@@ -490,7 +490,7 @@ class CollationView(PGChildNodeView, SchemaDiffObjectCompare):
|
||||
if not status:
|
||||
return internal_server_error(errormsg=res)
|
||||
|
||||
# We need oid to to add object in tree at browser
|
||||
# We need oid to add object in tree at browser
|
||||
SQL = render_template(
|
||||
"/".join([self.template_path, self._OID_SQL]), data=data
|
||||
)
|
||||
@@ -598,7 +598,7 @@ class CollationView(PGChildNodeView, SchemaDiffObjectCompare):
|
||||
if not status:
|
||||
return internal_server_error(errormsg=res)
|
||||
|
||||
# We need oid to to add object in tree at browser
|
||||
# We need oid to add object in tree at browser
|
||||
SQL = render_template("/".join([self.template_path,
|
||||
self._OID_SQL]), coid=coid)
|
||||
|
||||
|
||||
@@ -590,7 +590,7 @@ AND relkind != 'c'))"""
|
||||
if not status:
|
||||
return internal_server_error(errormsg=res)
|
||||
|
||||
# We need oid to to add object in tree at browser, below sql will
|
||||
# We need oid to add object in tree at browser, below sql will
|
||||
# gives the same
|
||||
SQL = render_template("/".join([self.template_path,
|
||||
self._OID_SQL]),
|
||||
|
||||
@@ -418,7 +418,7 @@ class FtsParserView(PGChildNodeView, SchemaDiffObjectCompare):
|
||||
if not status:
|
||||
return internal_server_error(errormsg=res)
|
||||
|
||||
# we need fts_parser id to to add object in tree at browser,
|
||||
# we need fts_parser id to add object in tree at browser,
|
||||
# below sql will give the same
|
||||
sql = render_template(
|
||||
"/".join([self.template_path, self._PROPERTIES_SQL]),
|
||||
|
||||
@@ -389,7 +389,7 @@ class FtsTemplateView(PGChildNodeView, SchemaDiffObjectCompare):
|
||||
if not status:
|
||||
return internal_server_error(errormsg=res)
|
||||
|
||||
# we need fts_template id to to add object in tree at browser,
|
||||
# we need fts_template id to add object in tree at browser,
|
||||
# below sql will give the same
|
||||
sql = render_template(
|
||||
"/".join([self.template_path, self._PROPERTIES_SQL]),
|
||||
|
||||
@@ -823,9 +823,9 @@ class TableView(BaseTableView, DataTypeReader, SchemaDiffTableCompare):
|
||||
if 'relacl' in data:
|
||||
data['relacl'] = parse_priv_to_db(data['relacl'], self.acl)
|
||||
|
||||
# Parse & format columns
|
||||
data = column_utils.parse_format_columns(data)
|
||||
data = TableView.check_and_convert_name_to_string(data)
|
||||
# Parse & format columns
|
||||
data = column_utils.parse_format_columns(data)
|
||||
data = TableView.check_and_convert_name_to_string(data)
|
||||
|
||||
# 'coll_inherits' is Array but it comes as string from browser
|
||||
# We will convert it again to list
|
||||
@@ -937,7 +937,7 @@ class TableView(BaseTableView, DataTypeReader, SchemaDiffTableCompare):
|
||||
if not status:
|
||||
return internal_server_error(errormsg=new_scid)
|
||||
|
||||
# we need oid to to add object in tree at browser
|
||||
# we need oid to add object in tree at browser
|
||||
sql = render_template(
|
||||
"/".join([self.table_template_path, self._OID_SQL]),
|
||||
scid=new_scid, data=data
|
||||
|
||||
@@ -413,7 +413,7 @@ class ColumnsView(PGChildNodeView, DataTypeReader):
|
||||
if not status:
|
||||
return internal_server_error(errormsg=res)
|
||||
|
||||
# we need oid to to add object in tree at browser
|
||||
# we need oid to add object in tree at browser
|
||||
SQL = render_template(
|
||||
"/".join([self.template_path, 'get_position.sql']),
|
||||
tid=tid, data=data
|
||||
|
||||
@@ -600,12 +600,7 @@ define('pgadmin.node.column', [
|
||||
},{
|
||||
id: 'seqstart', label: gettext('Start'), type: 'int',
|
||||
mode: ['properties', 'create', 'edit'], group: gettext('Constraints'),
|
||||
disabled: function(m) {
|
||||
let isIdentity = m.get('attidentity');
|
||||
if(!_.isUndefined(isIdentity) && !_.isNull(isIdentity) && !_.isEmpty(isIdentity))
|
||||
return false;
|
||||
return true;
|
||||
}, deps: ['attidentity', 'colconstype'],
|
||||
disabled: 'isIdentityColumn', deps: ['attidentity', 'colconstype'],
|
||||
visible: 'isTypeIdentity',
|
||||
},{
|
||||
id: 'seqmin', label: gettext('Minimum'), type: 'int',
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
|
||||
ALTER COLUMN "col__1_$%{}[]()&*^!@""'`\/#" SET DEFAULT 'changed default value';
|
||||
|
||||
GRANT SELECT("col__1_$%{}[]()&*^!@""'`\/#") ON testschema."table_2_$%{}[]()&*^!@""'`\/#" TO PUBLIC;
|
||||
@@ -0,0 +1,11 @@
|
||||
-- Column: testschema."table_2_$%{}[]()&*^!@""'`\/#"."col__1_$%{}[]()&*^!@""'`\/#"
|
||||
|
||||
-- ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#" DROP COLUMN "col__1_$%{}[]()&*^!@""'`\/#";
|
||||
|
||||
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
|
||||
ADD COLUMN "col__1_$%{}[]()&*^!@""'`\/#" text COLLATE pg_catalog."default" DEFAULT 'changed default value'::text;
|
||||
|
||||
COMMENT ON COLUMN testschema."table_2_$%{}[]()&*^!@""'`\/#"."col__1_$%{}[]()&*^!@""'`\/#"
|
||||
IS 'test comment';
|
||||
|
||||
GRANT SELECT("col__1_$%{}[]()&*^!@""'`\/#") ON testschema."table_2_$%{}[]()&*^!@""'`\/#" TO PUBLIC;
|
||||
@@ -0,0 +1,7 @@
|
||||
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
|
||||
ALTER COLUMN "col__2_$%{}[]()&*^!@""'`\/#" TYPE time(6) with time zone ;
|
||||
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
|
||||
ALTER COLUMN "col__2_$%{}[]()&*^!@""'`\/#" SET NOT NULL;
|
||||
|
||||
COMMENT ON COLUMN testschema."table_2_$%{}[]()&*^!@""'`\/#"."col__2_$%{}[]()&*^!@""'`\/#"
|
||||
IS 'test comment modification';
|
||||
@@ -0,0 +1,9 @@
|
||||
-- Column: testschema."table_2_$%{}[]()&*^!@""'`\/#"."col__2_$%{}[]()&*^!@""'`\/#"
|
||||
|
||||
-- ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#" DROP COLUMN "col__2_$%{}[]()&*^!@""'`\/#";
|
||||
|
||||
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
|
||||
ADD COLUMN "col__2_$%{}[]()&*^!@""'`\/#" time(6) with time zone NOT NULL DEFAULT now();
|
||||
|
||||
COMMENT ON COLUMN testschema."table_2_$%{}[]()&*^!@""'`\/#"."col__2_$%{}[]()&*^!@""'`\/#"
|
||||
IS 'test comment modification';
|
||||
@@ -0,0 +1,3 @@
|
||||
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
|
||||
ALTER COLUMN "col__3_$%{}[]()&*^!@""'`\/#"
|
||||
SET (n_distinct=2);
|
||||
@@ -0,0 +1,13 @@
|
||||
-- Column: testschema."table_2_$%{}[]()&*^!@""'`\/#"."col__3_$%{}[]()&*^!@""'`\/#"
|
||||
|
||||
-- ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#" DROP COLUMN "col__3_$%{}[]()&*^!@""'`\/#";
|
||||
|
||||
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
|
||||
ADD COLUMN "col__3_$%{}[]()&*^!@""'`\/#" integer[] NOT NULL;
|
||||
|
||||
COMMENT ON COLUMN testschema."table_2_$%{}[]()&*^!@""'`\/#"."col__3_$%{}[]()&*^!@""'`\/#"
|
||||
IS 'comment';
|
||||
|
||||
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
|
||||
ALTER COLUMN "col__3_$%{}[]()&*^!@""'`\/#"
|
||||
SET (n_distinct=2);
|
||||
@@ -1,5 +1,5 @@
|
||||
ALTER TABLE testschema."table_2_$%{}[]()&*^!@""'`\/#"
|
||||
ADD COLUMN "col_2_$%{}[]()&*^!@""'`\/#" character varying(50, None) COLLATE pg_catalog."C" DEFAULT None;
|
||||
ADD COLUMN "col_2_$%{}[]()&*^!@""'`\/#" character varying(50) COLLATE pg_catalog."C";
|
||||
|
||||
COMMENT ON COLUMN testschema."table_2_$%{}[]()&*^!@""'`\/#"."col_2_$%{}[]()&*^!@""'`\/#"
|
||||
IS 'Comment for create';
|
||||
IS 'Comment for create';
|
||||