diff --git a/requirements.txt b/requirements.txt index 044286cb0..8336c017a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,9 +8,8 @@ # ############################################################################### -Flask==2.3.*; python_version > '3.7' +Flask==3.0.*; python_version > '3.7' Flask==2.2.*; python_version <= '3.7' -Flask-Gravatar==0.* Flask-Login==0.* Flask-Mail==0.* Flask-Migrate==4.* @@ -23,13 +22,13 @@ Flask-Compress==1.* Flask-Paranoid==0.* Flask-Babel==4.0.*; python_version > '3.7' Flask-Babel==3.1.*; python_version <= '3.7' -Flask-Security-Too==5.3.*; python_version > '3.7' +Flask-Security-Too==5.4.*; python_version > '3.7' Flask-Security-Too==5.1.*; python_version <= '3.7' Flask-SocketIO==5.3.* WTForms==3.1.*; python_version > '3.7' WTForms==3.0.*; python_version <= '3.7' passlib==1.* -pytz==2023.* +pytz==2024.* speaklater3==1.* sqlparse==0.* psutil==5.9.* @@ -45,7 +44,8 @@ eventlet==0.34.2 httpagentparser==1.9.* user-agents==2.2.0 pywinpty==2.0.*; sys_platform=="win32" -Authlib==1.2.* +Authlib==1.2.*; python_version > '3.7' +Authlib==1.3.*; python_version <= '3.7' pyotp==2.* qrcode==7.* boto3==1.33.* @@ -55,11 +55,12 @@ azure-mgmt-resource==23.0.1 azure-mgmt-subscription==3.1.1 azure-identity==1.15.0 google-api-python-client==2.* -google-auth-oauthlib==1.1.0 +google-auth-oauthlib==1.2.0 keyring==24.*; python_version > '3.7' keyring==23.*; python_version <= '3.7' -Werkzeug==2.3.*; python_version > '3.7' +Werkzeug==3.0.*; python_version > '3.7' Werkzeug==2.2.3; python_version <= '3.7' -typer[all]==0.9.* +typer[all]==0.12.* setuptools==69.*; python_version >= '3.12' jsonformatter~=0.3.2 +libgravatar==1.0.* \ No newline at end of file diff --git a/web/pgadmin/__init__.py b/web/pgadmin/__init__.py index 9f49e8214..49b8edbda 100644 --- a/web/pgadmin/__init__.py +++ b/web/pgadmin/__init__.py @@ -505,7 +505,9 @@ def create_app(app_name=None): '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 + 'SECURITY_EMAIL_VALIDATOR_ARGS': config.SECURITY_EMAIL_VALIDATOR_ARGS, + # Disable CSRF for unauthenticated endpoints + 'SECURITY_CSRF_IGNORE_UNAUTH_ENDPOINTS': True })) app.config.update(dict({ @@ -519,7 +521,12 @@ def create_app(app_name=None): security.init_app(app, user_datastore) # register custom unauthorised handler. - app.login_manager.unauthorized_handler(pga_unauthorised) + if sys.version_info < (3, 8): + app.login_manager.unauthorized_handler(pga_unauthorised) + else: + # Flask-Security-Too > 5.4.* requires custom unauth handeler + # to be registeres with it. + security.unauthn_handler(pga_unauthorised) # Set the permanent session lifetime to the specified value in config file. app.permanent_session_lifetime = timedelta( diff --git a/web/pgadmin/browser/__init__.py b/web/pgadmin/browser/__init__.py index 78cfc88de..017a791b8 100644 --- a/web/pgadmin/browser/__init__.py +++ b/web/pgadmin/browser/__init__.py @@ -27,8 +27,8 @@ import keyring from flask import current_app, render_template, url_for, make_response, \ flash, Response, request, after_this_request, redirect, session from flask_babel import gettext -from flask_gravatar import Gravatar -from flask_login import current_user, login_required +from libgravatar import Gravatar +from flask_security import current_user, login_required from flask_login.utils import login_url from flask_security.changeable import send_password_changed_notice from flask_security.decorators import anonymous_user_required @@ -360,24 +360,27 @@ def _get_supported_browser(): return browser_name, browser_known, version +@blueprint.add_app_template_filter +def gravatar(username): + """ + This function adds a template filter which + returns gravatar image for user. + :return: gravatar image + """ + g = Gravatar(username) + return g.get_image( + size=100, + rating='g', + default='retro' + ) + + @blueprint.route("/") @pgCSRFProtect.exempt @login_required @mfa_required def index(): """Render and process the main browser window.""" - # Register Gravatar module with the app only if required - if config.SHOW_GRAVATAR_IMAGE: - Gravatar( - current_app, - size=100, - rating='g', - default='retro', - force_default=False, - force_lower=True, - use_ssl=True, - base_url=None - ) # Check the browser is a supported version # NOTE: If the checks here are updated, make sure the supported versions diff --git a/web/pgadmin/utils/csrf.py b/web/pgadmin/utils/csrf.py index 4ad5cf739..65e45baf7 100644 --- a/web/pgadmin/utils/csrf.py +++ b/web/pgadmin/utils/csrf.py @@ -25,7 +25,8 @@ class _PGCSRFProtect(CSRFProtect): exempt_views = [ 'flask.app.', - 'flask.scaffold.send_static_file', + 'flask.scaffold.send_static_file', # For Flask 2.* + 'flask.blueprints.send_static_file', 'flask_security.views.login', 'flask_security.views.logout', 'pgadmin.tools.translations',