Update SQLAlchemy, Flask, Flask-SQLAlchemy, and other packages to current versions. #5901
- Update Flask, Flask-SQLAlchemy, Flask-Babel, Flask-Security-Too, Flask-SocketIO, pytz, psutil, SQLAlchemy, bcrypt, cryptography, eventlet, Authlib, requests python packages - Remove pinned dnspython, Werkzeug packages from requirements.txtpull/5956/head
parent
294282c7ca
commit
292d76b39e
|
|
@ -60,7 +60,7 @@ _create_python_virtualenv() {
|
||||||
pip3 install wheel
|
pip3 install wheel
|
||||||
|
|
||||||
# Install the requirements
|
# Install the requirements
|
||||||
pip3 install --no-cache-dir --no-binary psycopg2 -r "${SOURCEDIR}/requirements.txt"
|
pip3 install --no-cache-dir --no-binary psycopg -r "${SOURCEDIR}/requirements.txt"
|
||||||
|
|
||||||
# Fixup the paths in the venv activation scripts
|
# Fixup the paths in the venv activation scripts
|
||||||
sed -i 's/VIRTUAL_ENV=.*/VIRTUAL_ENV="\/usr\/pgadmin4\/venv"/g' venv/bin/activate
|
sed -i 's/VIRTUAL_ENV=.*/VIRTUAL_ENV="\/usr\/pgadmin4\/venv"/g' venv/bin/activate
|
||||||
|
|
|
||||||
|
|
@ -8,56 +8,46 @@
|
||||||
#
|
#
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
Flask==2.0.3; python_version <= '3.6'
|
Flask==2.2.*
|
||||||
Flask==2.1.*; python_version >= '3.7'
|
|
||||||
Flask-Gravatar==0.*
|
Flask-Gravatar==0.*
|
||||||
Flask-Login==0.*
|
Flask-Login==0.*
|
||||||
Flask-Mail==0.*
|
Flask-Mail==0.*
|
||||||
Flask-Migrate==4.*
|
Flask-Migrate==4.*
|
||||||
dnspython==2.2.1
|
|
||||||
greenlet==1.1.2; python_version <= '3.10'
|
greenlet==1.1.2; python_version <= '3.10'
|
||||||
Flask-SQLAlchemy==2.5.*
|
Flask-SQLAlchemy==3.0.*
|
||||||
Flask-WTF==1.0.1
|
Flask-WTF==1.0.1
|
||||||
Flask-Compress==1.*
|
Flask-Compress==1.*
|
||||||
Flask-Paranoid==0.*
|
Flask-Paranoid==0.*
|
||||||
Flask-Babel==2.*
|
Flask-Babel==3.0.*
|
||||||
Flask-Security-Too==4.1.*
|
Flask-Security-Too==5.1.*
|
||||||
Flask-SocketIO<=5.2.0
|
Flask-SocketIO==5.3.*
|
||||||
WTForms==3.*
|
WTForms==3.0.*
|
||||||
passlib==1.*
|
passlib==1.*
|
||||||
pytz==2021.*
|
pytz==2022.*
|
||||||
speaklater3==1.*
|
speaklater3==1.*
|
||||||
sqlparse==0.*
|
sqlparse==0.*
|
||||||
psutil==5.9.3
|
psutil==5.9.*
|
||||||
psycopg2==2.9.*; python_version < '3.7'
|
psycopg[c]==3.1.*
|
||||||
psycopg[c]==3.1.*; python_version >= '3.7'
|
|
||||||
python-dateutil==2.*
|
python-dateutil==2.*
|
||||||
SQLAlchemy==1.4.44; python_version <= '3.6'
|
SQLAlchemy==2.*
|
||||||
SQLAlchemy==1.4.*; python_version >= '3.7'
|
bcrypt==4.0.*
|
||||||
bcrypt==3.*
|
cryptography==39.0.*
|
||||||
cryptography==3.*
|
pyOpenSSL>=23.* # required by cryptography
|
||||||
sshtunnel==0.*
|
sshtunnel==0.*
|
||||||
ldap3==2.*
|
ldap3==2.*
|
||||||
gssapi==1.7.*; python_version <= '3.6'
|
gssapi==1.8.*
|
||||||
gssapi==1.8.*; python_version >= '3.7'
|
eventlet==0.33.3
|
||||||
eventlet==0.33.0
|
|
||||||
httpagentparser==1.9.*
|
httpagentparser==1.9.*
|
||||||
user-agents==2.2.0
|
user-agents==2.2.0
|
||||||
pywinpty==1.1.*; sys_platform=="win32"
|
pywinpty==1.1.*; sys_platform=="win32"
|
||||||
Authlib==0.15.*; python_version <= '3.6'
|
Authlib==1.2.*
|
||||||
Authlib==1.1.*; python_version >= '3.7'
|
requests==2.28.*
|
||||||
requests==2.25.*
|
|
||||||
pyotp==2.*
|
pyotp==2.*
|
||||||
qrcode==7.*
|
qrcode==7.*
|
||||||
Pillow==8.4.*; python_version <= '3.6'
|
Pillow==9.*
|
||||||
Pillow==9.*; python_version >= '3.7'
|
boto3==1.26.*
|
||||||
boto3==1.23.*; python_version <= '3.6'
|
botocore==1.29.*
|
||||||
boto3==1.26.*; python_version >= '3.7'
|
|
||||||
botocore==1.26.*; python_version <= '3.6'
|
|
||||||
botocore==1.29.*; python_version >= '3.7'
|
|
||||||
urllib3==1.26.*
|
urllib3==1.26.*
|
||||||
Werkzeug==2.0.3; python_version <= '3.6'
|
|
||||||
Werkzeug==2.1.2; python_version >= '3.7'
|
|
||||||
azure-mgmt-rdbms==10.1.0
|
azure-mgmt-rdbms==10.1.0
|
||||||
azure-mgmt-resource==21.0.0
|
azure-mgmt-resource==21.0.0
|
||||||
azure-mgmt-subscription==3.0.0
|
azure-mgmt-subscription==3.0.0
|
||||||
|
|
|
||||||
|
|
@ -859,80 +859,8 @@ AUTO_DISCOVER_SERVERS = True
|
||||||
#############################################################################
|
#############################################################################
|
||||||
SERVER_HEARTBEAT_TIMEOUT = 30 # In seconds
|
SERVER_HEARTBEAT_TIMEOUT = 30 # In seconds
|
||||||
|
|
||||||
##########################################################################
|
#############################################################################
|
||||||
# Local config settings
|
# Patch the default config with custom config and other manipulations
|
||||||
##########################################################################
|
#############################################################################
|
||||||
# User configs loaded from config_local, config_distro etc.
|
from pgadmin.evaluate_config import evaluate_and_patch_config
|
||||||
user_config_settings = {}
|
locals().update(evaluate_and_patch_config(locals()))
|
||||||
|
|
||||||
|
|
||||||
# Function to Extract settings from config_local, config_distro etc.
|
|
||||||
def get_variables_from_module(module_name):
|
|
||||||
module = globals().get(module_name, None)
|
|
||||||
variables = {}
|
|
||||||
if module:
|
|
||||||
variables = {key: value for key, value in module.__dict__.items()
|
|
||||||
if not (key.startswith('__') or key.startswith('_'))}
|
|
||||||
return variables
|
|
||||||
|
|
||||||
|
|
||||||
# Load distribution-specific config overrides
|
|
||||||
try:
|
|
||||||
import config_distro
|
|
||||||
config_distro_settings = get_variables_from_module('config_distro')
|
|
||||||
user_config_settings.update(config_distro_settings)
|
|
||||||
except ImportError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# Load local config overrides
|
|
||||||
try:
|
|
||||||
import config_local
|
|
||||||
config_local_settings = get_variables_from_module('config_local')
|
|
||||||
user_config_settings.update(config_local_settings)
|
|
||||||
except ImportError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# Load system config overrides. We do this last, so that the sysadmin can
|
|
||||||
# override anything they want from a config file that's in a protected system
|
|
||||||
# directory and away from pgAdmin to avoid invalidating signatures.
|
|
||||||
system_config_dir = '/etc/pgadmin'
|
|
||||||
if sys.platform.startswith('win32'):
|
|
||||||
system_config_dir = os.environ['CommonProgramFiles'] + '/pgadmin'
|
|
||||||
elif sys.platform.startswith('darwin'):
|
|
||||||
system_config_dir = '/Library/Preferences/pgadmin'
|
|
||||||
|
|
||||||
if os.path.exists(system_config_dir + '/config_system.py'):
|
|
||||||
try:
|
|
||||||
sys.path.insert(0, system_config_dir)
|
|
||||||
import config_system
|
|
||||||
config_system_settings = get_variables_from_module('config_system')
|
|
||||||
user_config_settings.update(config_system_settings)
|
|
||||||
except ImportError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
# Update settings for 'LOG_FILE', 'SQLITE_PATH', 'SESSION_DB_PATH',
|
|
||||||
# 'AZURE_CREDENTIAL_CACHE_DIR', 'KERBEROS_CCACHE_DIR', 'STORAGE_DIR'
|
|
||||||
# of DATA_DIR is user defined
|
|
||||||
data_dir_dependent_settings = ['LOG_FILE', 'SQLITE_PATH', 'SESSION_DB_PATH',
|
|
||||||
'AZURE_CREDENTIAL_CACHE_DIR',
|
|
||||||
'KERBEROS_CCACHE_DIR', 'STORAGE_DIR']
|
|
||||||
|
|
||||||
if 'DATA_DIR' in user_config_settings:
|
|
||||||
for setting in data_dir_dependent_settings:
|
|
||||||
if setting not in user_config_settings:
|
|
||||||
data_dir = user_config_settings['DATA_DIR']
|
|
||||||
file_dir_name = os.path.basename(locals().get(setting))
|
|
||||||
locals().update({setting: os.path.join(data_dir, file_dir_name)})
|
|
||||||
|
|
||||||
# Finally update config user configs
|
|
||||||
locals().update(user_config_settings)
|
|
||||||
|
|
||||||
# Override DEFAULT_SERVER value from environment variable.
|
|
||||||
if 'PGADMIN_CONFIG_DEFAULT_SERVER' in os.environ:
|
|
||||||
DEFAULT_SERVER = os.environ['PGADMIN_CONFIG_DEFAULT_SERVER']
|
|
||||||
|
|
||||||
# Disable USER_INACTIVITY_TIMEOUT when SERVER_MODE=False
|
|
||||||
if not SERVER_MODE:
|
|
||||||
USER_INACTIVITY_TIMEOUT = 0
|
|
||||||
# Enable PSQL in Desktop Mode.
|
|
||||||
ENABLE_PSQL = True
|
|
||||||
|
|
|
||||||
|
|
@ -123,9 +123,9 @@ def upgrade():
|
||||||
|
|
||||||
if version < 11:
|
if version < 11:
|
||||||
# get metadata from current connection
|
# get metadata from current connection
|
||||||
meta = sa.MetaData(bind=op.get_bind())
|
meta = sa.MetaData()
|
||||||
# define table representation
|
# define table representation
|
||||||
meta.reflect(only=('role',))
|
meta.reflect(op.get_bind(), only=('role',))
|
||||||
role_table = sa.Table('role', meta)
|
role_table = sa.Table('role', meta)
|
||||||
|
|
||||||
op.execute(
|
op.execute(
|
||||||
|
|
@ -166,9 +166,9 @@ def upgrade():
|
||||||
'value': security_password_salt}])
|
'value': security_password_salt}])
|
||||||
|
|
||||||
# get metadata from current connection
|
# get metadata from current connection
|
||||||
meta = sa.MetaData(bind=op.get_bind())
|
meta = sa.MetaData()
|
||||||
# define table representation
|
# define table representation
|
||||||
meta.reflect(only=('version',))
|
meta.reflect(op.get_bind(), only=('version',))
|
||||||
version_table = sa.Table('version', meta)
|
version_table = sa.Table('version', meta)
|
||||||
|
|
||||||
op.execute(
|
op.execute(
|
||||||
|
|
|
||||||
|
|
@ -35,9 +35,9 @@ def upgrade():
|
||||||
['username', 'auth_source'])
|
['username', 'auth_source'])
|
||||||
|
|
||||||
# For internal email is a user name, so update the existing records.
|
# For internal email is a user name, so update the existing records.
|
||||||
meta = sa.MetaData(bind=op.get_bind())
|
meta = sa.MetaData()
|
||||||
# define table representation
|
# define table representation
|
||||||
meta.reflect(only=('user',))
|
meta.reflect(op.get_bind(), only=('user',))
|
||||||
user_table = sa.Table('user', meta)
|
user_table = sa.Table('user', meta)
|
||||||
|
|
||||||
op.execute(
|
op.execute(
|
||||||
|
|
|
||||||
|
|
@ -27,9 +27,9 @@ depends_on = None
|
||||||
|
|
||||||
def upgrade():
|
def upgrade():
|
||||||
# get metadata from current connection
|
# get metadata from current connection
|
||||||
meta = sa.MetaData(bind=op.get_bind())
|
meta = sa.MetaData()
|
||||||
# define table representation
|
# define table representation
|
||||||
meta.reflect(only=('server',))
|
meta.reflect(op.get_bind(), only=('server',))
|
||||||
server_table = sa.Table('server', meta)
|
server_table = sa.Table('server', meta)
|
||||||
op.execute(
|
op.execute(
|
||||||
server_table.update().where(server_table.c.connect_timeout == 0 or
|
server_table.update().where(server_table.c.connect_timeout == 0 or
|
||||||
|
|
|
||||||
|
|
@ -29,9 +29,9 @@ def upgrade():
|
||||||
op.add_column('user', sa.Column('fs_uniquifier', sa.String(),
|
op.add_column('user', sa.Column('fs_uniquifier', sa.String(),
|
||||||
nullable=True))
|
nullable=True))
|
||||||
|
|
||||||
meta = sa.MetaData(bind=op.get_bind())
|
meta = sa.MetaData()
|
||||||
# define table representation
|
# define table representation
|
||||||
meta.reflect(only=('user',))
|
meta.reflect(op.get_bind(), only=('user',))
|
||||||
user_table = sa.Table('user', meta)
|
user_table = sa.Table('user', meta)
|
||||||
|
|
||||||
op.execute(
|
op.execute(
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,9 @@ def upgrade():
|
||||||
# If password is already exists for any existing server then change the
|
# If password is already exists for any existing server then change the
|
||||||
# save_password column to 1 (True) else set 0
|
# save_password column to 1 (True) else set 0
|
||||||
# get metadata from current connection
|
# get metadata from current connection
|
||||||
meta = sa.MetaData(bind=op.get_bind())
|
meta = sa.MetaData()
|
||||||
# define table representation
|
# define table representation
|
||||||
meta.reflect(only=('server',))
|
meta.reflect(op.get_bind(), only=('server',))
|
||||||
server_table = sa.Table('server', meta)
|
server_table = sa.Table('server', meta)
|
||||||
|
|
||||||
op.execute(
|
op.execute(
|
||||||
|
|
|
||||||
|
|
@ -50,18 +50,18 @@ def migrate_connection_params(table_name):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
# define table representation
|
# define table representation
|
||||||
meta = sa.MetaData(bind=op.get_bind())
|
meta = sa.MetaData()
|
||||||
meta.reflect(only=(table_name,))
|
meta.reflect(op.get_bind(), only=(table_name,))
|
||||||
server_table = sa.Table(table_name, meta)
|
server_table = sa.Table(table_name, meta)
|
||||||
|
|
||||||
# Create a select statement
|
# Create a select statement
|
||||||
stmt = sa.select([
|
stmt = sa.select(
|
||||||
server_table.columns.id, server_table.columns.ssl_mode,
|
server_table.columns.id, server_table.columns.ssl_mode,
|
||||||
server_table.columns.sslcert, server_table.columns.sslkey,
|
server_table.columns.sslcert, server_table.columns.sslkey,
|
||||||
server_table.columns.sslrootcert, server_table.columns.sslcrl,
|
server_table.columns.sslrootcert, server_table.columns.sslcrl,
|
||||||
server_table.columns.sslcompression, server_table.columns.hostaddr,
|
server_table.columns.sslcompression, server_table.columns.hostaddr,
|
||||||
server_table.columns.passfile, server_table.columns.connect_timeout
|
server_table.columns.passfile, server_table.columns.connect_timeout
|
||||||
])
|
)
|
||||||
|
|
||||||
# Fetch the data from the server table
|
# Fetch the data from the server table
|
||||||
results = op.get_bind().execute(stmt).fetchall()
|
results = op.get_bind().execute(stmt).fetchall()
|
||||||
|
|
|
||||||
|
|
@ -114,7 +114,8 @@ def upgrade():
|
||||||
current_app.config['SECURITY_PASSWORD_SALT'] = current_salt
|
current_app.config['SECURITY_PASSWORD_SALT'] = current_salt
|
||||||
current_app.config['SECRET_KEY'] = secret_key
|
current_app.config['SECRET_KEY'] = secret_key
|
||||||
user_datastore = SQLAlchemyUserDatastore(db, User, Role)
|
user_datastore = SQLAlchemyUserDatastore(db, User, Role)
|
||||||
Security(current_app, user_datastore, register_blueprint=False)
|
Security(current_app.app_context().app, user_datastore,
|
||||||
|
register_blueprint=False)
|
||||||
else:
|
else:
|
||||||
current_app.config['SECURITY_PASSWORD_SALT'] = current_salt
|
current_app.config['SECURITY_PASSWORD_SALT'] = current_salt
|
||||||
current_app.config['SECRET_KEY'] = secret_key
|
current_app.config['SECRET_KEY'] = secret_key
|
||||||
|
|
|
||||||
|
|
@ -40,10 +40,6 @@ if (3, 10) > sys.version_info > (3, 8) and os.name == 'posix':
|
||||||
# This was causing issue in psycopg3
|
# This was causing issue in psycopg3
|
||||||
from eventlet import hubs
|
from eventlet import hubs
|
||||||
hubs.use_hub("poll")
|
hubs.use_hub("poll")
|
||||||
# Ref: https://github.com/miguelgrinberg/python-socketio/issues/567
|
|
||||||
# Resolve BigAnimal API issue
|
|
||||||
import selectors
|
|
||||||
selectors.DefaultSelector = selectors.PollSelector
|
|
||||||
|
|
||||||
import config
|
import config
|
||||||
import setup
|
import setup
|
||||||
|
|
@ -101,7 +97,6 @@ if not os.path.isfile(config.SQLITE_PATH):
|
||||||
# it can be imported
|
# it can be imported
|
||||||
##########################################################################
|
##########################################################################
|
||||||
app = create_app()
|
app = create_app()
|
||||||
app.debug = False
|
|
||||||
app.config['sessions'] = dict()
|
app.config['sessions'] = dict()
|
||||||
|
|
||||||
if setup_db_required:
|
if setup_db_required:
|
||||||
|
|
@ -163,22 +158,6 @@ def main():
|
||||||
setattr(sys, _name,
|
setattr(sys, _name,
|
||||||
open(os.devnull, 'r' if _name == 'stdin' else 'w'))
|
open(os.devnull, 'r' if _name == 'stdin' else 'w'))
|
||||||
|
|
||||||
# Build Javascript files when DEBUG
|
|
||||||
if config.DEBUG:
|
|
||||||
from pgadmin.utils.javascript.javascript_bundler import \
|
|
||||||
JavascriptBundler, JsState
|
|
||||||
app.debug = True
|
|
||||||
|
|
||||||
javascript_bundler = JavascriptBundler()
|
|
||||||
javascript_bundler.bundle()
|
|
||||||
if javascript_bundler.report() == JsState.NONE:
|
|
||||||
app.logger.error(
|
|
||||||
"Unable to generate javascript.\n"
|
|
||||||
"To run the app ensure that yarn install command runs "
|
|
||||||
"successfully"
|
|
||||||
)
|
|
||||||
raise RuntimeError("No generated javascript, aborting")
|
|
||||||
|
|
||||||
# Output a startup message if we're not under the runtime and startup.
|
# Output a startup message if we're not under the runtime and startup.
|
||||||
# If we're under WSGI, we don't need to worry about this
|
# If we're under WSGI, we don't need to worry about this
|
||||||
if not app.PGADMIN_RUNTIME:
|
if not app.PGADMIN_RUNTIME:
|
||||||
|
|
@ -213,19 +192,19 @@ def main():
|
||||||
app.run(
|
app.run(
|
||||||
host=config.DEFAULT_SERVER,
|
host=config.DEFAULT_SERVER,
|
||||||
port=config.EFFECTIVE_SERVER_PORT,
|
port=config.EFFECTIVE_SERVER_PORT,
|
||||||
|
debug=config.DEBUG,
|
||||||
use_reloader=(
|
use_reloader=(
|
||||||
(not app.PGADMIN_RUNTIME) and app.debug and
|
(not app.PGADMIN_RUNTIME) and
|
||||||
os.environ.get("WERKZEUG_RUN_MAIN") is not None
|
os.environ.get("WERKZEUG_RUN_MAIN") is not None
|
||||||
),
|
),
|
||||||
threaded=config.THREADED_MODE
|
threaded=config.THREADED_MODE
|
||||||
)
|
)
|
||||||
else:
|
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
|
|
||||||
try:
|
try:
|
||||||
socketio.run(
|
socketio.run(
|
||||||
app,
|
app,
|
||||||
|
debug=config.DEBUG,
|
||||||
|
allow_unsafe_werkzeug=True,
|
||||||
host=config.DEFAULT_SERVER,
|
host=config.DEFAULT_SERVER,
|
||||||
port=config.EFFECTIVE_SERVER_PORT,
|
port=config.EFFECTIVE_SERVER_PORT,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -299,9 +299,6 @@ def create_app(app_name=None):
|
||||||
# Initialise i18n
|
# Initialise i18n
|
||||||
babel = Babel(app)
|
babel = Babel(app)
|
||||||
|
|
||||||
app.logger.debug('Available translations: %s' % babel.list_translations())
|
|
||||||
|
|
||||||
@babel.localeselector
|
|
||||||
def get_locale():
|
def get_locale():
|
||||||
"""Get the language for the user."""
|
"""Get the language for the user."""
|
||||||
language = 'en'
|
language = 'en'
|
||||||
|
|
@ -335,6 +332,7 @@ def create_app(app_name=None):
|
||||||
|
|
||||||
return language
|
return language
|
||||||
|
|
||||||
|
babel.init_app(app, locale_selector=get_locale)
|
||||||
##########################################################################
|
##########################################################################
|
||||||
# Setup authentication
|
# Setup authentication
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
@ -456,21 +454,18 @@ def create_app(app_name=None):
|
||||||
# Run migration for the first time i.e. create database
|
# Run migration for the first time i.e. create database
|
||||||
# If version not available, user must have aborted. Tables are not
|
# If version not available, user must have aborted. Tables are not
|
||||||
# created and so its an empty db
|
# created and so its an empty db
|
||||||
try:
|
if get_version() == -1:
|
||||||
if get_version() == -1:
|
db_upgrade(app)
|
||||||
db_upgrade(app)
|
else:
|
||||||
else:
|
schema_version = get_version()
|
||||||
schema_version = get_version()
|
|
||||||
|
|
||||||
# Run migration if current schema version is greater than
|
# Run migration if current schema version is greater than
|
||||||
# the schema version stored in version table.
|
# the schema version stored in version table.
|
||||||
if CURRENT_SCHEMA_VERSION > schema_version:
|
if CURRENT_SCHEMA_VERSION > schema_version:
|
||||||
db_upgrade(app)
|
db_upgrade(app)
|
||||||
# Update schema version to the latest
|
# Update schema version to the latest
|
||||||
set_version(CURRENT_SCHEMA_VERSION)
|
set_version(CURRENT_SCHEMA_VERSION)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
except Exception as e:
|
|
||||||
app.logger.error(e)
|
|
||||||
|
|
||||||
# Run the migration as per specified by the user.
|
# Run the migration as per specified by the user.
|
||||||
if config.CONFIG_DATABASE_URI is not None and \
|
if config.CONFIG_DATABASE_URI is not None and \
|
||||||
|
|
@ -719,7 +714,9 @@ def create_app(app_name=None):
|
||||||
svr_superuser, svr_port, svr_discovery_id,
|
svr_superuser, svr_port, svr_discovery_id,
|
||||||
svr_comment)
|
svr_comment)
|
||||||
|
|
||||||
except Exception:
|
except Exception as e:
|
||||||
|
print(str(e))
|
||||||
|
db.session.rollback()
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@user_logged_in.connect_via(app)
|
@user_logged_in.connect_via(app)
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ def login():
|
||||||
Entry point for all the authentication sources.
|
Entry point for all the authentication sources.
|
||||||
The user input will be validated and authenticated.
|
The user input will be validated and authenticated.
|
||||||
"""
|
"""
|
||||||
form = _security.login_form()
|
form = _security.forms.get('login_form').cls(request.form)
|
||||||
if OAUTH2 in config.AUTHENTICATION_SOURCES \
|
if OAUTH2 in config.AUTHENTICATION_SOURCES \
|
||||||
and 'oauth2_button' in request.form:
|
and 'oauth2_button' in request.form:
|
||||||
# Sending empty form as oauth2 does not require form attribute
|
# Sending empty form as oauth2 does not require form attribute
|
||||||
|
|
@ -173,7 +173,7 @@ def login():
|
||||||
if 'auth_obj' in session:
|
if 'auth_obj' in session:
|
||||||
session.pop('auth_obj')
|
session.pop('auth_obj')
|
||||||
flash(msg, 'danger')
|
flash(msg, 'danger')
|
||||||
form_class = _security.login_form
|
form_class = _security.forms.get('login_form').cls
|
||||||
form = form_class()
|
form = form_class()
|
||||||
|
|
||||||
return _security.render_template(
|
return _security.render_template(
|
||||||
|
|
|
||||||
|
|
@ -177,7 +177,7 @@ class KerberosAuthentication(BaseAuthentication):
|
||||||
negotiate = False
|
negotiate = False
|
||||||
headers = Headers()
|
headers = Headers()
|
||||||
authorization = request.headers.get("Authorization", None)
|
authorization = request.headers.get("Authorization", None)
|
||||||
form_class = _security.login_form
|
form_class = _security.forms.get('login_form').cls
|
||||||
req_json = request.get_json(silent=True)
|
req_json = request.get_json(silent=True)
|
||||||
|
|
||||||
if req_json:
|
if req_json:
|
||||||
|
|
|
||||||
|
|
@ -7,13 +7,12 @@
|
||||||
#
|
#
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
from config import PG_DEFAULT_DRIVER
|
|
||||||
from pgadmin.utils.route import BaseTestGenerator
|
from pgadmin.utils.route import BaseTestGenerator
|
||||||
from regression.python_test_utils import test_utils as utils
|
from regression.python_test_utils import test_utils as utils
|
||||||
from . import utils as servers_utils
|
from . import utils as servers_utils
|
||||||
from unittest.mock import patch, MagicMock
|
from unittest.mock import patch, MagicMock
|
||||||
import json
|
import json
|
||||||
from PG_DEFAULT_DRIVER import OperationalError
|
from psycopg import OperationalError
|
||||||
|
|
||||||
|
|
||||||
class ServersSSHConnectTestCase(BaseTestGenerator):
|
class ServersSSHConnectTestCase(BaseTestGenerator):
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ from abc import abstractmethod
|
||||||
|
|
||||||
import flask
|
import flask
|
||||||
from flask import render_template, current_app
|
from flask import render_template, current_app
|
||||||
from flask.views import View, MethodViewType
|
from flask.views import View, MethodView
|
||||||
from flask_babel import gettext
|
from flask_babel import gettext
|
||||||
|
|
||||||
from config import PG_DEFAULT_DRIVER
|
from config import PG_DEFAULT_DRIVER
|
||||||
|
|
@ -140,7 +140,7 @@ class PGChildModule():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class NodeView(View, metaclass=MethodViewType):
|
class NodeView(View, metaclass=type(MethodView)):
|
||||||
"""
|
"""
|
||||||
A PostgreSQL Object has so many operaions/functions apart from CRUD
|
A PostgreSQL Object has so many operaions/functions apart from CRUD
|
||||||
(Create, Read, Update, Delete):
|
(Create, Read, Update, Delete):
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,98 @@
|
||||||
|
##########################################################################
|
||||||
|
#
|
||||||
|
# pgAdmin 4 - PostgreSQL Tools
|
||||||
|
#
|
||||||
|
# Copyright (C) 2013 - 2023, The pgAdmin Development Team
|
||||||
|
# This software is released under the PostgreSQL Licence
|
||||||
|
#
|
||||||
|
##########################################################################
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# User configs loaded from config_local, config_distro etc.
|
||||||
|
custom_config_settings = {}
|
||||||
|
|
||||||
|
|
||||||
|
# Function to Extract settings from config_local, config_distro etc.
|
||||||
|
def get_variables_from_module(module_name):
|
||||||
|
module = globals().get(module_name, None)
|
||||||
|
variables = {}
|
||||||
|
if module:
|
||||||
|
variables = {key: value for key, value in module.__dict__.items()
|
||||||
|
if not (key.startswith('__') or key.startswith('_'))}
|
||||||
|
return variables
|
||||||
|
|
||||||
|
|
||||||
|
# Load distribution-specific config overrides
|
||||||
|
try:
|
||||||
|
import config_distro
|
||||||
|
config_distro_settings = get_variables_from_module('config_distro')
|
||||||
|
custom_config_settings.update(config_distro_settings)
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Load local config overrides
|
||||||
|
try:
|
||||||
|
import config_local
|
||||||
|
config_local_settings = get_variables_from_module('config_local')
|
||||||
|
custom_config_settings.update(config_local_settings)
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Load system config overrides. We do this last, so that the sysadmin can
|
||||||
|
# override anything they want from a config file that's in a protected system
|
||||||
|
# directory and away from pgAdmin to avoid invalidating signatures.
|
||||||
|
system_config_dir = '/etc/pgadmin'
|
||||||
|
if sys.platform.startswith('win32'):
|
||||||
|
system_config_dir = os.environ['CommonProgramFiles'] + '/pgadmin'
|
||||||
|
elif sys.platform.startswith('darwin'):
|
||||||
|
system_config_dir = '/Library/Preferences/pgadmin'
|
||||||
|
|
||||||
|
if os.path.exists(system_config_dir + '/config_system.py'):
|
||||||
|
try:
|
||||||
|
sys.path.insert(0, system_config_dir)
|
||||||
|
import config_system
|
||||||
|
config_system_settings = get_variables_from_module('config_system')
|
||||||
|
custom_config_settings.update(config_system_settings)
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def evaluate_and_patch_config(config: dict) -> dict:
|
||||||
|
# Update settings for 'LOG_FILE', 'SQLITE_PATH', 'SESSION_DB_PATH',
|
||||||
|
# 'AZURE_CREDENTIAL_CACHE_DIR', 'KERBEROS_CCACHE_DIR', 'STORAGE_DIR'
|
||||||
|
# of DATA_DIR is user defined
|
||||||
|
data_dir_dependent_settings = \
|
||||||
|
['LOG_FILE', 'SQLITE_PATH', 'SESSION_DB_PATH',
|
||||||
|
'AZURE_CREDENTIAL_CACHE_DIR', 'KERBEROS_CCACHE_DIR', 'STORAGE_DIR']
|
||||||
|
|
||||||
|
if 'DATA_DIR' in custom_config_settings:
|
||||||
|
for setting in data_dir_dependent_settings:
|
||||||
|
if setting not in custom_config_settings:
|
||||||
|
data_dir = custom_config_settings['DATA_DIR']
|
||||||
|
file_dir_name = os.path.basename(config.get(setting))
|
||||||
|
config.update(
|
||||||
|
{setting: os.path.join(data_dir, file_dir_name)})
|
||||||
|
|
||||||
|
# To use psycopg3 driver, need to specify +psycopg in conn URI
|
||||||
|
if 'CONFIG_DATABASE_URI' in custom_config_settings:
|
||||||
|
db_uri = custom_config_settings['CONFIG_DATABASE_URI']
|
||||||
|
if db_uri.startswith('postgresql:'):
|
||||||
|
custom_config_settings['CONFIG_DATABASE_URI'] = \
|
||||||
|
'postgresql+psycopg:{0}'.format(db_uri[db_uri.find(':') + 1:])
|
||||||
|
|
||||||
|
# Finally update config user configs
|
||||||
|
config.update(custom_config_settings)
|
||||||
|
|
||||||
|
# Override DEFAULT_SERVER value from environment variable.
|
||||||
|
if 'PGADMIN_CONFIG_DEFAULT_SERVER' in os.environ:
|
||||||
|
config['DEFAULT_SERVER'] = os.environ['PGADMIN_CONFIG_DEFAULT_SERVER']
|
||||||
|
|
||||||
|
# Disable USER_INACTIVITY_TIMEOUT when SERVER_MODE=False
|
||||||
|
if not config.get('SERVER_MODE'):
|
||||||
|
config['USER_INACTIVITY_TIMEOUT'] = 0
|
||||||
|
# Enable PSQL in Desktop Mode.
|
||||||
|
config['ENABLE_PSQL'] = True
|
||||||
|
|
||||||
|
return config
|
||||||
|
|
@ -73,25 +73,6 @@ class PgAdminDbBinaryString(types.TypeDecorator):
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
class PgAdminJSONString(types.TypeDecorator):
|
|
||||||
"""
|
|
||||||
This function is used to return a string representing a json object from
|
|
||||||
an object and vise versa.
|
|
||||||
"""
|
|
||||||
|
|
||||||
impl = types.String
|
|
||||||
|
|
||||||
def process_bind_param(self, value, dialect):
|
|
||||||
if value is not None:
|
|
||||||
value = json.dumps(value)
|
|
||||||
return value
|
|
||||||
|
|
||||||
def process_result_value(self, value, dialect):
|
|
||||||
if value is not None:
|
|
||||||
value = json.loads(value)
|
|
||||||
return value
|
|
||||||
|
|
||||||
|
|
||||||
class Version(db.Model):
|
class Version(db.Model):
|
||||||
"""Version numbers for reference/upgrade purposes"""
|
"""Version numbers for reference/upgrade purposes"""
|
||||||
__tablename__ = 'version'
|
__tablename__ = 'version'
|
||||||
|
|
@ -218,7 +199,7 @@ class Server(db.Model):
|
||||||
shared = db.Column(db.Boolean(), nullable=False)
|
shared = db.Column(db.Boolean(), nullable=False)
|
||||||
kerberos_conn = db.Column(db.Boolean(), nullable=False, default=0)
|
kerberos_conn = db.Column(db.Boolean(), nullable=False, default=0)
|
||||||
cloud_status = db.Column(db.Integer(), nullable=False, default=0)
|
cloud_status = db.Column(db.Integer(), nullable=False, default=0)
|
||||||
connection_params = db.Column(MutableDict.as_mutable(PgAdminJSONString))
|
connection_params = db.Column(MutableDict.as_mutable(types.JSON))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def serialize(self):
|
def serialize(self):
|
||||||
|
|
@ -458,7 +439,7 @@ class SharedServer(db.Model):
|
||||||
tunnel_identity_file = db.Column(db.String(64), nullable=True)
|
tunnel_identity_file = db.Column(db.String(64), nullable=True)
|
||||||
tunnel_password = db.Column(PgAdminDbBinaryString())
|
tunnel_password = db.Column(PgAdminDbBinaryString())
|
||||||
shared = db.Column(db.Boolean(), nullable=False)
|
shared = db.Column(db.Boolean(), nullable=False)
|
||||||
connection_params = db.Column(MutableDict.as_mutable(PgAdminJSONString))
|
connection_params = db.Column(MutableDict.as_mutable(types.JSON))
|
||||||
|
|
||||||
|
|
||||||
class Macros(db.Model):
|
class Macros(db.Model):
|
||||||
|
|
|
||||||
|
|
@ -304,7 +304,7 @@ def panel(trans_id):
|
||||||
params['bgcolor'] = None
|
params['bgcolor'] = None
|
||||||
params['fgcolor'] = None
|
params['fgcolor'] = None
|
||||||
|
|
||||||
s = Server.query.filter_by(id=params['sid']).first()
|
s = Server.query.filter_by(id=int(params['sid'])).first()
|
||||||
if s.shared and s.user_id != current_user.id:
|
if s.shared and s.user_id != current_user.id:
|
||||||
# Import here to avoid circular dependency
|
# Import here to avoid circular dependency
|
||||||
from pgadmin.browser.server_groups.servers import ServerModule
|
from pgadmin.browser.server_groups.servers import ServerModule
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ from flask import render_template, request, \
|
||||||
Response, abort, current_app, session
|
Response, abort, current_app, session
|
||||||
from flask_babel import gettext as _
|
from flask_babel import gettext as _
|
||||||
from flask_security import login_required, roles_required, current_user
|
from flask_security import login_required, roles_required, current_user
|
||||||
from flask_security.utils import encrypt_password
|
from flask_security.utils import hash_password
|
||||||
from werkzeug.exceptions import InternalServerError
|
from werkzeug.exceptions import InternalServerError
|
||||||
|
|
||||||
import config
|
import config
|
||||||
|
|
@ -438,7 +438,7 @@ def validate_password(data, new_data):
|
||||||
'confirmPassword' in data and data['confirmPassword'] != ""):
|
'confirmPassword' in data and data['confirmPassword'] != ""):
|
||||||
|
|
||||||
if data['newPassword'] == data['confirmPassword']:
|
if data['newPassword'] == data['confirmPassword']:
|
||||||
new_data['password'] = encrypt_password(data['newPassword'])
|
new_data['password'] = hash_password(data['newPassword'])
|
||||||
else:
|
else:
|
||||||
raise InternalServerError(_("Passwords do not match."))
|
raise InternalServerError(_("Passwords do not match."))
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -279,7 +279,7 @@ class ManagedSessionInterface(SessionInterface):
|
||||||
self.manager = manager
|
self.manager = manager
|
||||||
|
|
||||||
def open_session(self, app, request):
|
def open_session(self, app, request):
|
||||||
cookie_val = request.cookies.get(app.session_cookie_name)
|
cookie_val = request.cookies.get(app.config['SESSION_COOKIE_NAME'])
|
||||||
|
|
||||||
if not cookie_val or '!' not in cookie_val:
|
if not cookie_val or '!' not in cookie_val:
|
||||||
return self.manager.new_session()
|
return self.manager.new_session()
|
||||||
|
|
@ -296,7 +296,8 @@ class ManagedSessionInterface(SessionInterface):
|
||||||
if not session:
|
if not session:
|
||||||
self.manager.remove(session.sid)
|
self.manager.remove(session.sid)
|
||||||
if session.modified:
|
if session.modified:
|
||||||
response.delete_cookie(app.session_cookie_name, domain=domain)
|
response.delete_cookie(app.config['SESSION_COOKIE_NAME'],
|
||||||
|
domain=domain)
|
||||||
return
|
return
|
||||||
|
|
||||||
if not session.modified:
|
if not session.modified:
|
||||||
|
|
@ -310,7 +311,7 @@ class ManagedSessionInterface(SessionInterface):
|
||||||
|
|
||||||
cookie_exp = self.get_expiration_time(app, session)
|
cookie_exp = self.get_expiration_time(app, session)
|
||||||
response.set_cookie(
|
response.set_cookie(
|
||||||
app.session_cookie_name,
|
app.config['SESSION_COOKIE_NAME'],
|
||||||
'%s!%s' % (session.sid, session.hmac_digest),
|
'%s!%s' % (session.sid, session.hmac_digest),
|
||||||
expires=cookie_exp,
|
expires=cookie_exp,
|
||||||
secure=config.SESSION_COOKIE_SECURE,
|
secure=config.SESSION_COOKIE_SECURE,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue