mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
Revert "Update SQLAlchemy, Flask, Flask-SQLAlchemy, and other packages to current versions. #5901"
This reverts commit 31818bb67a.
This commit is contained in:
@@ -8,45 +8,56 @@
|
|||||||
#
|
#
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
Flask==2.2.*
|
Flask==2.0.3; python_version <= '3.6'
|
||||||
|
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==3.0.*
|
Flask-SQLAlchemy==2.5.*
|
||||||
Flask-WTF==1.0.1
|
Flask-WTF==1.0.1
|
||||||
Flask-Compress==1.*
|
Flask-Compress==1.*
|
||||||
Flask-Paranoid==0.*
|
Flask-Paranoid==0.*
|
||||||
Flask-Babel==3.0.*
|
Flask-Babel==2.*
|
||||||
Flask-Security-Too==5.1.*
|
Flask-Security-Too==4.1.*
|
||||||
Flask-SocketIO==5.3.*
|
Flask-SocketIO<=5.2.0
|
||||||
WTForms==3.0.*
|
WTForms==3.*
|
||||||
passlib==1.*
|
passlib==1.*
|
||||||
pytz==2022.*
|
pytz==2021.*
|
||||||
speaklater3==1.*
|
speaklater3==1.*
|
||||||
sqlparse==0.*
|
sqlparse==0.*
|
||||||
psutil==5.9.*
|
psutil==5.9.3
|
||||||
psycopg[c]==3.1.*
|
psycopg2==2.9.*; python_version < '3.7'
|
||||||
|
psycopg[c]==3.1.*; python_version >= '3.7'
|
||||||
python-dateutil==2.*
|
python-dateutil==2.*
|
||||||
SQLAlchemy==2.*
|
SQLAlchemy==1.4.44; python_version <= '3.6'
|
||||||
bcrypt==4.0.*
|
SQLAlchemy==1.4.*; python_version >= '3.7'
|
||||||
cryptography==39.0.*
|
bcrypt==3.*
|
||||||
|
cryptography==3.*
|
||||||
sshtunnel==0.*
|
sshtunnel==0.*
|
||||||
ldap3==2.*
|
ldap3==2.*
|
||||||
gssapi==1.8.*
|
gssapi==1.7.*; python_version <= '3.6'
|
||||||
eventlet==0.33.3
|
gssapi==1.8.*; python_version >= '3.7'
|
||||||
|
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==1.2.*
|
Authlib==0.15.*; python_version <= '3.6'
|
||||||
requests==2.28.*
|
Authlib==1.1.*; python_version >= '3.7'
|
||||||
|
requests==2.25.*
|
||||||
pyotp==2.*
|
pyotp==2.*
|
||||||
qrcode==7.*
|
qrcode==7.*
|
||||||
Pillow==9.*
|
Pillow==8.4.*; python_version <= '3.6'
|
||||||
boto3==1.26.*
|
Pillow==9.*; python_version >= '3.7'
|
||||||
botocore==1.29.*
|
boto3==1.23.*; python_version <= '3.6'
|
||||||
|
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,8 +859,80 @@ AUTO_DISCOVER_SERVERS = True
|
|||||||
#############################################################################
|
#############################################################################
|
||||||
SERVER_HEARTBEAT_TIMEOUT = 30 # In seconds
|
SERVER_HEARTBEAT_TIMEOUT = 30 # In seconds
|
||||||
|
|
||||||
#############################################################################
|
##########################################################################
|
||||||
# Patch the default config with custom config and other manipulations
|
# Local config settings
|
||||||
#############################################################################
|
##########################################################################
|
||||||
from pgadmin.evaluate_config import evaluate_and_patch_config
|
# User configs loaded from config_local, config_distro etc.
|
||||||
locals().update(evaluate_and_patch_config(locals()))
|
user_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')
|
||||||
|
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()
|
meta = sa.MetaData(bind=op.get_bind())
|
||||||
# define table representation
|
# define table representation
|
||||||
meta.reflect(op.get_bind(), only=('role',))
|
meta.reflect(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()
|
meta = sa.MetaData(bind=op.get_bind())
|
||||||
# define table representation
|
# define table representation
|
||||||
meta.reflect(op.get_bind(), only=('version',))
|
meta.reflect(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()
|
meta = sa.MetaData(bind=op.get_bind())
|
||||||
# define table representation
|
# define table representation
|
||||||
meta.reflect(op.get_bind(), only=('user',))
|
meta.reflect(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()
|
meta = sa.MetaData(bind=op.get_bind())
|
||||||
# define table representation
|
# define table representation
|
||||||
meta.reflect(op.get_bind(), only=('server',))
|
meta.reflect(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()
|
meta = sa.MetaData(bind=op.get_bind())
|
||||||
# define table representation
|
# define table representation
|
||||||
meta.reflect(op.get_bind(), only=('user',))
|
meta.reflect(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()
|
meta = sa.MetaData(bind=op.get_bind())
|
||||||
# define table representation
|
# define table representation
|
||||||
meta.reflect(op.get_bind(), only=('server',))
|
meta.reflect(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()
|
meta = sa.MetaData(bind=op.get_bind())
|
||||||
meta.reflect(op.get_bind(), only=(table_name,))
|
meta.reflect(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,8 +114,7 @@ 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.app_context().app, user_datastore,
|
Security(current_app, user_datastore, register_blueprint=False)
|
||||||
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,6 +40,10 @@ 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
|
||||||
@@ -97,6 +101,7 @@ 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:
|
||||||
@@ -158,6 +163,22 @@ 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:
|
||||||
@@ -192,19 +213,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
|
(not app.PGADMIN_RUNTIME) and app.debug 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,6 +299,9 @@ 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'
|
||||||
@@ -332,7 +335,6 @@ def create_app(app_name=None):
|
|||||||
|
|
||||||
return language
|
return language
|
||||||
|
|
||||||
babel.init_app(app, locale_selector=get_locale)
|
|
||||||
##########################################################################
|
##########################################################################
|
||||||
# Setup authentication
|
# Setup authentication
|
||||||
##########################################################################
|
##########################################################################
|
||||||
@@ -454,18 +456,21 @@ 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
|
||||||
if get_version() == -1:
|
try:
|
||||||
db_upgrade(app)
|
if get_version() == -1:
|
||||||
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)
|
db_upgrade(app)
|
||||||
# Update schema version to the latest
|
else:
|
||||||
set_version(CURRENT_SCHEMA_VERSION)
|
schema_version = get_version()
|
||||||
db.session.commit()
|
|
||||||
|
# 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)
|
||||||
|
# Update schema version to the latest
|
||||||
|
set_version(CURRENT_SCHEMA_VERSION)
|
||||||
|
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 \
|
||||||
@@ -714,9 +719,7 @@ 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 as e:
|
except Exception:
|
||||||
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.forms.get('login_form').cls(request.form)
|
form = _security.login_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.forms.get('login_form').cls
|
form_class = _security.login_form
|
||||||
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.forms.get('login_form').cls
|
form_class = _security.login_form
|
||||||
req_json = request.get_json(silent=True)
|
req_json = request.get_json(silent=True)
|
||||||
|
|
||||||
if req_json:
|
if req_json:
|
||||||
|
|||||||
@@ -7,12 +7,13 @@
|
|||||||
#
|
#
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
|
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 psycopg import OperationalError
|
from PG_DEFAULT_DRIVER 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, MethodView
|
from flask.views import View, MethodViewType
|
||||||
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=type(MethodView)):
|
class NodeView(View, metaclass=MethodViewType):
|
||||||
"""
|
"""
|
||||||
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):
|
||||||
|
|||||||
@@ -1,98 +0,0 @@
|
|||||||
##########################################################################
|
|
||||||
#
|
|
||||||
# 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,6 +73,25 @@ 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'
|
||||||
@@ -199,7 +218,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(types.JSON))
|
connection_params = db.Column(MutableDict.as_mutable(PgAdminJSONString))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def serialize(self):
|
def serialize(self):
|
||||||
@@ -439,7 +458,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(types.JSON))
|
connection_params = db.Column(MutableDict.as_mutable(PgAdminJSONString))
|
||||||
|
|
||||||
|
|
||||||
class Macros(db.Model):
|
class Macros(db.Model):
|
||||||
|
|||||||
@@ -126,7 +126,7 @@ def initialize_target(self, utils, close_debugger_instance=True):
|
|||||||
|
|
||||||
|
|
||||||
async def start_listener(self, utils, db_utils):
|
async def start_listener(self, utils, db_utils):
|
||||||
response = self.tester.post(
|
response = self.tester.get(
|
||||||
'debugger/start_listener/' + str(self.trans_id),
|
'debugger/start_listener/' + str(self.trans_id),
|
||||||
content_type='application/json')
|
content_type='application/json')
|
||||||
if response.status_code != 200:
|
if response.status_code != 200:
|
||||||
|
|||||||
@@ -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=int(params['sid'])).first()
|
s = Server.query.filter_by(id=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 hash_password
|
from flask_security.utils import encrypt_password
|
||||||
from werkzeug.exceptions import InternalServerError
|
from werkzeug.exceptions import InternalServerError
|
||||||
|
|
||||||
import config
|
import config
|
||||||
@@ -437,7 +437,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'] = hash_password(data['newPassword'])
|
new_data['password'] = encrypt_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.config['SESSION_COOKIE_NAME'])
|
cookie_val = request.cookies.get(app.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,8 +296,7 @@ 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.config['SESSION_COOKIE_NAME'],
|
response.delete_cookie(app.session_cookie_name, domain=domain)
|
||||||
domain=domain)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
if not session.modified:
|
if not session.modified:
|
||||||
@@ -311,7 +310,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.config['SESSION_COOKIE_NAME'],
|
app.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,
|
||||||
|
|||||||
Reference in New Issue
Block a user