VYPR
Moderate severityNVD Advisory· Published May 2, 2024· Updated Feb 13, 2025

The Multi Factor Authentication bypass vulnerability in pgAdmin 4

CVE-2024-4215

Description

pgAdmin <= 8.5 is affected by a multi-factor authentication bypass vulnerability. This vulnerability allows an attacker with knowledge of a legitimate account’s username and password may authenticate to the application and perform sensitive actions within the application, such as managing files and executing SQL queries, regardless of the account’s MFA enrollment status.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
pgadmin4PyPI
< 8.68.6

Affected products

1

Patches

1
f4761f55f7cf

Fixed Multi-Factor Authentication bypass vulnerability (CVE-2024-4215). #7425

https://github.com/pgadmin-org/pgadmin4Khushboo VashiApr 29, 2024via ghsa
35 files changed · +309 271
  • docs/en_US/release_notes_8_6.rst+3 2 modified
    @@ -35,10 +35,11 @@ Bug fixes
       | `Issue #2410 <https://github.com/pgadmin-org/pgadmin4/issues/2410>`_ -  Fixed all input boxes in pgAdmin to show browser auto-fill only where it is relevant.
       | `Issue #7173 <https://github.com/pgadmin-org/pgadmin4/issues/7173>`_ -  Install dbus-python, an in-direct dependency of the Keyring package as a system package for Debian platforms.
       | `Issue #7275 <https://github.com/pgadmin-org/pgadmin4/issues/7275>`_ -  Fixed an issue where debugger was not scrolling automatically on stepping.
    -  | `Issue #7282 <https://github.com/pgadmin-org/pgadmin4/issues/7282>`_ -  Fixed an XSS vulnerability in the /settings/store endpoint.
    +  | `Issue #7282 <https://github.com/pgadmin-org/pgadmin4/issues/7282>`_ -  Fixed an XSS vulnerability in the /settings/store endpoint (CVE-2024-4216).
       | `Issue #7294 <https://github.com/pgadmin-org/pgadmin4/issues/7294>`_ -  Fixed an issue where double dollar quoted code is treated as string in syntax highlighter.
       | `Issue #7317 <https://github.com/pgadmin-org/pgadmin4/issues/7317>`_ -  Fixed an issue where pressing backspace should remove the spaces and not the entire tab width, on enabling 'Use spaces?' in the preferences.
       | `Issue #7334 <https://github.com/pgadmin-org/pgadmin4/issues/7334>`_ -  Fixed an issue where incorrect select/exec scripts were generated for functions/procedures.
       | `Issue #7372 <https://github.com/pgadmin-org/pgadmin4/issues/7372>`_ -  Fixed an issue where connection to the database is not automatically re-established after connectivity drop.
       | `Issue #7384 <https://github.com/pgadmin-org/pgadmin4/issues/7384>`_ -  Fixed an issue when closing the view data second tab; it raises the error that the 'ViewCommand' object has no attribute 'auto_commit'.
    -  | `Issue #7390 <https://github.com/pgadmin-org/pgadmin4/issues/7390>`_ -  Fixed violates check constraint issue when creating a pgAgent schedule.
    \ No newline at end of file
    +  | `Issue #7390 <https://github.com/pgadmin-org/pgadmin4/issues/7390>`_ -  Fixed violates check constraint issue when creating a pgAgent schedule.
    +  | `Issue #7425 <https://github.com/pgadmin-org/pgadmin4/issues/7425>`_ -  Fixed Multi-Factor Authentication bypass vulnerability (CVE-2024-4215).
    \ No newline at end of file
    
  • web/pgadmin/about/__init__.py+4 3 modified
    @@ -11,7 +11,8 @@
     
     from flask import Response, render_template, request
     from flask_babel import gettext
    -from flask_security import current_user, login_required
    +from flask_security import current_user
    +from pgadmin.user_login_check import pga_login_required
     from pgadmin.utils import PgAdminModule
     from pgadmin.utils.menu import MenuItem
     from pgadmin.utils.constants import MIMETYPE_APP_JS
    @@ -53,7 +54,7 @@ def get_exposed_url_endpoints(self):
     # A test page
     ##########################################################################
     @blueprint.route("/", endpoint='index')
    -@login_required
    +@pga_login_required
     def index():
         """Render the about box."""
         info = {}
    @@ -138,7 +139,7 @@ def detect_browser(request):
     
     
     @blueprint.route("/about.js")
    -@login_required
    +@pga_login_required
     def script():
         """render the required javascript"""
         return Response(
    
  • web/pgadmin/authenticate/__init__.py+6 8 modified
    @@ -23,12 +23,10 @@
     from flask_login import current_user
     from flask_socketio import disconnect, ConnectionRefusedError
     
    -
     from pgadmin.model import db, User
    -from pgadmin.utils import PgAdminModule, get_safe_post_login_redirect, \
    -    get_safe_post_logout_redirect
     from pgadmin.utils.constants import KERBEROS, INTERNAL, OAUTH2, LDAP,\
         MessageType
    +import pgadmin.utils as pga_utils
     from pgadmin.authenticate.registry import AuthSourceRegistry
     
     MODULE_NAME = 'authenticate'
    @@ -84,7 +82,7 @@ def wrapped(*args, **kwargs):
         return wrapped
     
     
    -class AuthenticateModule(PgAdminModule):
    +class AuthenticateModule(pga_utils.PgAdminModule):
         def get_exposed_url_endpoints(self):
             return ['authenticate.login']
     
    @@ -135,7 +133,7 @@ def _login():
                               'Administrator.'),
                       MessageType.WARNING)
                 logout_user()
    -            return redirect(get_safe_post_logout_redirect())
    +            return redirect(pga_utils.get_safe_post_logout_redirect())
     
         # Validate the user
         if not auth_obj.validate():
    @@ -161,7 +159,7 @@ def _login():
                         flash_login_attempt_error = None
                     flash(error, MessageType.WARNING)
     
    -        return redirect(get_safe_post_logout_redirect())
    +        return redirect(pga_utils.get_safe_post_logout_redirect())
     
         # Authenticate the user
         status, msg = auth_obj.authenticate()
    @@ -177,7 +175,7 @@ def _login():
                         'authenticate.kerberos_login'), url_for('browser.index')))
     
                 flash(msg, MessageType.ERROR)
    -            return redirect(get_safe_post_logout_redirect())
    +            return redirect(pga_utils.get_safe_post_logout_redirect())
     
             session['auth_source_manager'] = current_auth_obj
     
    @@ -187,7 +185,7 @@ def _login():
     
             if 'auth_obj' in session:
                 session.pop('auth_obj')
    -        return redirect(get_safe_post_login_redirect())
    +        return redirect(pga_utils.get_safe_post_login_redirect())
     
         elif isinstance(msg, Response):
             return msg
    
  • web/pgadmin/authenticate/kerberos.py+3 3 modified
    @@ -18,7 +18,7 @@
         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
    +from pgadmin.user_login_check import pga_login_required
     
     import config
     from pgadmin.model import User
    @@ -97,7 +97,7 @@ def kerberos_logout():
         @blueprint.route("/update_ticket",
                          endpoint="update_ticket", methods=["GET"])
         @pgCSRFProtect.exempt
    -    @login_required
    +    @pga_login_required
         def kerberos_update_ticket():
             """
             Update the kerberos ticket.
    @@ -127,7 +127,7 @@ def kerberos_update_ticket():
         @blueprint.route("/validate_ticket",
                          endpoint="validate_ticket", methods=["GET"])
         @pgCSRFProtect.exempt
    -    @login_required
    +    @pga_login_required
         def kerberos_validate_ticket():
             """
             Return the kerberos ticket lifetime left after getting the
    
  • web/pgadmin/authenticate/mfa/utils.py+3 3 modified
    @@ -13,7 +13,7 @@
     
     from flask import url_for, session, request, redirect
     from flask_login.utils import login_url
    -from flask_security import current_user
    +from flask_security import current_user, login_required
     
     import config
     from pgadmin.model import UserMFA, db
    @@ -279,7 +279,7 @@ def get_next_url():
             registration_url = url_for('mfa.register')
     
             if next_url.startswith(registration_url):
    -            return url('browser.index')
    +            return url_for('browser.index')
     
             return next_url
     
    @@ -290,8 +290,8 @@ def redirect_to_mfa_registration():
             return redirect(login_url("mfa.register", next_url=get_next_url()))
     
         @wraps(wrapped)
    +    @login_required
         def inner(*args, **kwargs):
    -
             def execute_func():
                 session['mfa_authenticated'] = True
                 return wrapped(*args, **kwargs)
    
  • web/pgadmin/browser/__init__.py+9 8 modified
    @@ -28,7 +28,7 @@
         flash, Response, request, after_this_request, redirect, session
     from flask_babel import gettext
     from libgravatar import Gravatar
    -from flask_security import current_user, login_required
    +from flask_security import current_user
     from flask_login.utils import login_url
     from flask_security.changeable import send_password_changed_notice
     from flask_security.decorators import anonymous_user_required
    @@ -64,6 +64,8 @@
     from pgadmin.authenticate import AuthSourceManager
     from pgadmin.utils.exception import CryptKeyMissing
     
    +from pgadmin.user_login_check import pga_login_required
    +
     try:
         from flask_security.views import default_render_json
     except ImportError as e:
    @@ -377,8 +379,7 @@ def gravatar(username):
     
     @blueprint.route("/")
     @pgCSRFProtect.exempt
    -@login_required
    -@mfa_required
    +@pga_login_required
     def index():
         """Render and process the main browser window."""
     
    @@ -471,7 +472,7 @@ def get_shared_storage_list():
     
     @blueprint.route("/js/utils.js")
     @pgCSRFProtect.exempt
    -@login_required
    +@pga_login_required
     def utils():
         layout = get_setting('Browser/Layout', default='')
         snippets = []
    @@ -592,7 +593,7 @@ def exposed_urls():
     
     @blueprint.route("/js/error.js")
     @pgCSRFProtect.exempt
    -@login_required
    +@pga_login_required
     def error_js():
         return make_response(
             render_template('browser/js/error.js', _=gettext),
    @@ -609,7 +610,7 @@ def messages_js():
     
     @blueprint.route("/browser.css")
     @pgCSRFProtect.exempt
    -@login_required
    +@pga_login_required
     def browser_css():
         """Render and return CSS snippets from the nodes and modules."""
         snippets = []
    @@ -624,7 +625,7 @@ def browser_css():
     
     
     @blueprint.route("/nodes/", endpoint="nodes")
    -@login_required
    +@pga_login_required
     def get_nodes():
         """Build a list of treeview nodes from the child nodes."""
         nodes = []
    @@ -931,7 +932,7 @@ def set_master_password():
         @blueprint.route("/change_password", endpoint="change_password",
                          methods=['GET', 'POST'])
         @pgCSRFProtect.exempt
    -    @login_required
    +    @pga_login_required
         def change_password():
             """View function which handles a change password request."""
     
    
  • web/pgadmin/browser/server_groups/__init__.py+13 12 modified
    @@ -14,7 +14,8 @@
     
     from flask import request, jsonify, render_template
     from flask_babel import gettext
    -from flask_security import current_user, login_required
    +from flask_security import current_user
    +from pgadmin.user_login_check import pga_login_required
     from pgadmin.browser import BrowserPluginModule
     from pgadmin.browser.utils import NodeView
     from pgadmin.utils.ajax import make_json_response, gone, \
    @@ -162,7 +163,7 @@ class ServerGroupView(NodeView):
         parent_ids = []
         ids = [{'type': 'int', 'id': 'gid'}]
     
    -    @login_required
    +    @pga_login_required
         def list(self):
             res = []
     
    @@ -176,7 +177,7 @@ def list(self):
     
             return ajax_response(response=res, status=200)
     
    -    @login_required
    +    @pga_login_required
         def delete(self, gid):
             """Delete a server group node in the settings database"""
     
    @@ -232,7 +233,7 @@ def delete(self, gid):
     
             return make_json_response(result=request.form)
     
    -    @login_required
    +    @pga_login_required
         def update(self, gid):
             """Update the server-group properties"""
     
    @@ -281,7 +282,7 @@ def update(self, gid):
                 )
             )
     
    -    @login_required
    +    @pga_login_required
         def properties(self, gid):
             """Update the server-group properties"""
     
    @@ -299,7 +300,7 @@ def properties(self, gid):
                     status=200
                 )
     
    -    @login_required
    +    @pga_login_required
         def create(self):
             """Creates new server-group """
             data = request.form if request.form else json.loads(
    @@ -349,23 +350,23 @@ def create(self):
                     success=0,
                     errormsg=gettext('No server group name was specified'))
     
    -    @login_required
    +    @pga_login_required
         def sql(self, gid):
             return make_json_response(status=422)
     
    -    @login_required
    +    @pga_login_required
         def modified_sql(self, gid):
             return make_json_response(status=422)
     
    -    @login_required
    +    @pga_login_required
         def statistics(self, gid):
             return make_json_response(status=422)
     
    -    @login_required
    +    @pga_login_required
         def dependencies(self, gid):
             return make_json_response(status=422)
     
    -    @login_required
    +    @pga_login_required
         def dependents(self, gid):
             return make_json_response(status=422)
     
    @@ -394,7 +395,7 @@ def get_all_server_groups():
                     groups.append(group)
             return groups
     
    -    @login_required
    +    @pga_login_required
         def nodes(self, gid=None):
             """Return a JSON document listing the server groups for the user"""
             nodes = []
    
  • web/pgadmin/browser/server_groups/servers/__init__.py+15 14 modified
    @@ -13,7 +13,8 @@
     from flask import render_template, request, make_response, jsonify, \
         current_app, url_for, session
     from flask_babel import gettext
    -from flask_security import current_user, login_required
    +from flask_security import current_user
    +from pgadmin.user_login_check import pga_login_required
     from psycopg.conninfo import make_conninfo, conninfo_to_dict
     
     from pgadmin.browser.server_groups.servers.types import ServerType
    @@ -218,7 +219,7 @@ def get_servers(self, all_servers, hide_shared_server, gid):
     
             return servers
     
    -    @login_required
    +    @pga_login_required
         def get_nodes(self, gid):
             """Return a JSON document listing the server groups for the user"""
     
    @@ -564,7 +565,7 @@ def update_connection_parameter(self, data, server):
     
                 data['connection_params'] = existing_conn_params
     
    -    @login_required
    +    @pga_login_required
         def nodes(self, gid):
             res = []
             """
    @@ -650,7 +651,7 @@ def nodes(self, gid):
     
             return make_json_response(result=res)
     
    -    @login_required
    +    @pga_login_required
         def node(self, gid, sid):
             """Return a JSON document listing the server groups for the user"""
             server = Server.query.filter_by(id=sid).first()
    @@ -733,7 +734,7 @@ def delete_shared_server(self, server_name, gid, osid):
                     success=0,
                     errormsg=e.message)
     
    -    @login_required
    +    @pga_login_required
         def delete(self, gid, sid):
             """Delete a server node in the settings database."""
             servers = Server.query.filter_by(user_id=current_user.id, id=sid)
    @@ -783,7 +784,7 @@ def delete(self, gid, sid):
             return make_json_response(success=1,
                                       info=gettext("Server deleted"))
     
    -    @login_required
    +    @pga_login_required
         def update(self, gid, sid):
             """Update the server settings"""
             server = Server.query.filter_by(id=sid).first()
    @@ -988,7 +989,7 @@ def _server_modify_disallowed_when_connected(
                             ).format(disp_lbl[arg])
                         )
     
    -    @login_required
    +    @pga_login_required
         def list(self, gid):
             """
             Return list of attributes of all servers.
    @@ -1035,7 +1036,7 @@ def list(self, gid):
                 response=res
             )
     
    -    @login_required
    +    @pga_login_required
         def properties(self, gid, sid):
             """Return list of attributes of a server"""
     
    @@ -1154,7 +1155,7 @@ def update_connection_string(manager, server):
             display_conn_string = make_conninfo(**con_info_ord)
             return display_conn_string
     
    -    @login_required
    +    @pga_login_required
         def create(self, gid):
             """Add a server node to the settings database"""
             required_args = ['name', 'db']
    @@ -1376,15 +1377,15 @@ def create(self, gid):
                     errormsg=str(e)
                 )
     
    -    @login_required
    +    @pga_login_required
         def sql(self, gid, sid):
             return make_json_response(data='')
     
    -    @login_required
    +    @pga_login_required
         def modified_sql(self, gid, sid):
             return make_json_response(data='')
     
    -    @login_required
    +    @pga_login_required
         def statistics(self, gid, sid):
             manager = get_driver(PG_DEFAULT_DRIVER).connection_manager(sid)
             conn = manager.connection()
    @@ -1408,11 +1409,11 @@ def statistics(self, gid, sid):
                 )
             )
     
    -    @login_required
    +    @pga_login_required
         def dependencies(self, gid, sid):
             return make_json_response(data='')
     
    -    @login_required
    +    @pga_login_required
         def dependents(self, gid, sid):
             return make_json_response(data='')
     
    
  • web/pgadmin/dashboard/__init__.py+14 14 modified
    @@ -12,7 +12,7 @@
     from functools import wraps
     from flask import render_template, url_for, Response, g, request
     from flask_babel import gettext
    -from flask_security import login_required
    +from pgadmin.user_login_check import pga_login_required
     import json
     from pgadmin.utils import PgAdminModule
     from pgadmin.utils.ajax import make_response as ajax_response,\
    @@ -314,7 +314,7 @@ def get_error(i_node_type):
     
     
     @blueprint.route("/dashboard.js")
    -@login_required
    +@pga_login_required
     def script():
         """render the required javascript"""
         return Response(
    @@ -330,7 +330,7 @@ def script():
     @blueprint.route('/', endpoint='index')
     @blueprint.route('/<int:sid>', endpoint='get_by_sever_id')
     @blueprint.route('/<int:sid>/<int:did>', endpoint='get_by_database_id')
    -@login_required
    +@pga_login_required
     def index(sid=None, did=None):
         """
         Renders the welcome, server or database dashboard
    @@ -446,7 +446,7 @@ def get_long_running_query_status(activities):
                      endpoint='dashboard_stats_sid')
     @blueprint.route('/dashboard_stats/<int:sid>/<int:did>',
                      endpoint='dashboard_stats_did')
    -@login_required
    +@pga_login_required
     @check_precondition
     def dashboard_stats(sid=None, did=None):
         resp_data = {}
    @@ -478,7 +478,7 @@ def dashboard_stats(sid=None, did=None):
     @blueprint.route(
         '/activity/<int:sid>/<int:did>', endpoint='get_activity_by_database_id'
     )
    -@login_required
    +@pga_login_required
     @check_precondition
     def activity(sid=None, did=None):
         """
    @@ -494,7 +494,7 @@ def activity(sid=None, did=None):
     @blueprint.route(
         '/locks/<int:sid>/<int:did>', endpoint='get_locks_by_database_id'
     )
    -@login_required
    +@pga_login_required
     @check_precondition
     def locks(sid=None, did=None):
         """
    @@ -510,7 +510,7 @@ def locks(sid=None, did=None):
     @blueprint.route(
         '/prepared/<int:sid>/<int:did>', endpoint='get_prepared_by_database_id'
     )
    -@login_required
    +@pga_login_required
     @check_precondition
     def prepared(sid=None, did=None):
         """
    @@ -523,7 +523,7 @@ def prepared(sid=None, did=None):
     
     @blueprint.route('/config/', endpoint='config')
     @blueprint.route('/config/<int:sid>', endpoint='get_config_by_server_id')
    -@login_required
    +@pga_login_required
     @check_precondition
     def config(sid=None):
         """
    @@ -540,7 +540,7 @@ def config(sid=None):
     @blueprint.route(
         '/cancel_query/<int:sid>/<int:did>/<int:pid>', methods=['DELETE']
     )
    -@login_required
    +@pga_login_required
     @check_precondition
     def cancel_query(sid=None, did=None, pid=None):
         """
    @@ -567,7 +567,7 @@ def cancel_query(sid=None, did=None, pid=None):
     @blueprint.route(
         '/terminate_session/<int:sid>/<int:did>/<int:pid>', methods=['DELETE']
     )
    -@login_required
    +@pga_login_required
     @check_precondition
     def terminate_session(sid=None, did=None, pid=None):
         """
    @@ -595,7 +595,7 @@ def terminate_session(sid=None, did=None, pid=None):
                      endpoint='check_system_statistics_sid', methods=['GET'])
     @blueprint.route('check_extension/system_statistics/<int:sid>/<int:did>',
                      endpoint='check_system_statistics_did', methods=['GET'])
    -@login_required
    +@pga_login_required
     @check_precondition
     def check_system_statistics(sid=None, did=None):
         sql = "SELECT * FROM pg_extension WHERE extname = 'system_stats';"
    @@ -620,7 +620,7 @@ def check_system_statistics(sid=None, did=None):
                      endpoint='system_statistics_sid', methods=['GET'])
     @blueprint.route('/system_statistics/<int:sid>/<int:did>',
                      endpoint='system_statistics_did', methods=['GET'])
    -@login_required
    +@pga_login_required
     @check_precondition
     def system_statistics(sid=None, did=None):
         resp_data = {}
    @@ -652,7 +652,7 @@ def system_statistics(sid=None, did=None):
     
     @blueprint.route('/replication_stats/<int:sid>',
                      endpoint='replication_stats', methods=['GET'])
    -@login_required
    +@pga_login_required
     @check_precondition
     def replication_stats(sid=None):
         """
    @@ -676,7 +676,7 @@ def replication_stats(sid=None):
     
     @blueprint.route('/replication_slots/<int:sid>',
                      endpoint='replication_slots', methods=['GET'])
    -@login_required
    +@pga_login_required
     @check_precondition
     def replication_slots(sid=None):
         """
    
  • web/pgadmin/misc/bgprocess/__init__.py+6 6 modified
    @@ -12,7 +12,7 @@
     the long running background-processes.
     """
     from flask import url_for
    -from flask_security import login_required
    +from pgadmin.user_login_check import pga_login_required
     from pgadmin.utils import PgAdminModule
     from pgadmin.utils.ajax import make_response, gone, success_return,\
         make_json_response
    @@ -43,7 +43,7 @@ def get_exposed_url_endpoints(self):
     
     
     @blueprint.route('/', methods=['GET'], endpoint='list')
    -@login_required
    +@pga_login_required
     def index():
         return make_response(response=BatchProcess.list())
     
    @@ -52,7 +52,7 @@ def index():
     @blueprint.route(
         '/<pid>/<int:out>/<int:err>/', methods=['GET'], endpoint='detailed_status'
     )
    -@login_required
    +@pga_login_required
     def status(pid, out=-1, err=-1):
         """
         Check the status of the process running in background.
    @@ -76,7 +76,7 @@ def status(pid, out=-1, err=-1):
     
     
     @blueprint.route('/<pid>', methods=['PUT'], endpoint='acknowledge')
    -@login_required
    +@pga_login_required
     def acknowledge(pid):
         """
         User has acknowledge the process
    @@ -96,7 +96,7 @@ def acknowledge(pid):
     
     @blueprint.route('/update_cloud_details/<pid>', methods=['PUT'],
                      endpoint='update_cloud_details')
    -@login_required
    +@pga_login_required
     def update_cloud_details(pid):
         """
         Update the cloud details and get instance details
    @@ -133,7 +133,7 @@ def update_cloud_details(pid):
     
     
     @blueprint.route('/stop/<pid>', methods=['PUT'], endpoint='stop_process')
    -@login_required
    +@pga_login_required
     def stop_process(pid):
         """
         User has stopped the process
    
  • web/pgadmin/misc/cloud/azure/__init__.py+13 13 modified
    @@ -14,7 +14,7 @@
     from pgadmin.misc.bgprocess.processes import BatchProcess
     from pgadmin import make_json_response
     from pgadmin.utils import PgAdminModule
    -from flask_security import login_required
    +from pgadmin.user_login_check import pga_login_required
     import json
     from flask import session, current_app, request
     from flask_login import current_user
    @@ -59,7 +59,7 @@ def get_exposed_url_endpoints(self):
     
     @blueprint.route('/verify_credentials/',
                      methods=['POST'], endpoint='verify_credentials')
    -@login_required
    +@pga_login_required
     def verify_credentials():
         """Verify Credentials."""
         data = json.loads(request.data)
    @@ -96,7 +96,7 @@ def verify_credentials():
     
     @blueprint.route('/get_azure_verification_codes/',
                      methods=['GET'], endpoint='get_azure_verification_codes')
    -@login_required
    +@pga_login_required
     def get_azure_verification_codes():
         """Get azure code for authentication."""
         azure_auth_code = None
    @@ -110,7 +110,7 @@ def get_azure_verification_codes():
     
     @blueprint.route('/check_cluster_name_availability/',
                      methods=['GET'], endpoint='check_cluster_name_availability')
    -@login_required
    +@pga_login_required
     def check_cluster_name_availability():
         """Check Server Name availability."""
         data = request.args
    @@ -129,7 +129,7 @@ def check_cluster_name_availability():
     
     @blueprint.route('/subscriptions/',
                      methods=['GET'], endpoint='subscriptions')
    -@login_required
    +@pga_login_required
     def get_azure_subscriptions():
         """
         List subscriptions.
    @@ -142,7 +142,7 @@ def get_azure_subscriptions():
     
     @blueprint.route('/resource_groups/<subscription_id>',
                      methods=['GET'], endpoint='resource_groups')
    -@login_required
    +@pga_login_required
     def get_azure_resource_groups(subscription_id):
         """
         Fetch resource groups based on subscription.
    @@ -156,7 +156,7 @@ def get_azure_resource_groups(subscription_id):
     
     @blueprint.route('/regions/<subscription_id>',
                      methods=['GET'], endpoint='regions')
    -@login_required
    +@pga_login_required
     def get_azure_regions(subscription_id):
         """List Regions for Azure."""
         if not subscription_id:
    @@ -169,7 +169,7 @@ def get_azure_regions(subscription_id):
     
     @blueprint.route('/zone_redundant_ha_supported/<region_name>',
                      methods=['GET'], endpoint='zone_redundant_ha_supported')
    -@login_required
    +@pga_login_required
     def is_ha_supported(region_name):
         """Check high availability support in given region."""
         azure = session['azure']['azure_obj']
    @@ -181,7 +181,7 @@ def is_ha_supported(region_name):
     
     @blueprint.route('/availability_zones/<region_name>',
                      methods=['GET'], endpoint='availability_zones')
    -@login_required
    +@pga_login_required
     def get_azure_availability_zones(region_name):
         """List availability zones in given region."""
         if not region_name:
    @@ -194,7 +194,7 @@ def get_azure_availability_zones(region_name):
     
     @blueprint.route('/db_versions/<availability_zone>',
                      methods=['GET'], endpoint='db_versions')
    -@login_required
    +@pga_login_required
     def get_azure_postgresql_server_versions(availability_zone):
         """Get azure postgres database versions."""
         if not availability_zone:
    @@ -208,7 +208,7 @@ def get_azure_postgresql_server_versions(availability_zone):
     
     @blueprint.route('/instance_types/<availability_zone>/<db_version>',
                      methods=['GET'], endpoint='instance_types')
    -@login_required
    +@pga_login_required
     def get_azure_instance_types(availability_zone, db_version):
         """Get instance types for Azure."""
         if not db_version:
    @@ -220,7 +220,7 @@ def get_azure_instance_types(availability_zone, db_version):
     
     @blueprint.route('/storage_types/<availability_zone>/<db_version>',
                      methods=['GET'], endpoint='storage_types')
    -@login_required
    +@pga_login_required
     def list_azure_storage_types(availability_zone, db_version):
         """Get the storage types supported."""
         if not db_version:
    @@ -232,7 +232,7 @@ def list_azure_storage_types(availability_zone, db_version):
     
     @blueprint.route('/clear_session',
                      methods=['GET'], endpoint='clear_session')
    -@login_required
    +@pga_login_required
     def clear_session():
         clear_azure_session()
         return make_json_response(success=1)
    
  • web/pgadmin/misc/cloud/biganimal/__init__.py+11 11 modified
    @@ -14,7 +14,7 @@
     import pickle
     from flask_babel import gettext
     from flask import session, current_app
    -from flask_security import login_required
    +from pgadmin.user_login_check import pga_login_required
     from werkzeug.datastructures import Headers
     from pgadmin.utils import PgAdminModule
     from pgadmin.misc.cloud.utils import _create_server, CloudProcessDesc
    @@ -52,7 +52,7 @@ def get_exposed_url_endpoints(self):
     
     @blueprint.route('/verification_ack/',
                      methods=['GET'], endpoint='verification_ack')
    -@login_required
    +@pga_login_required
     def biganimal_verification_ack():
         """Check the Verification is done or not."""
         biganimal_obj = pickle.loads(session['biganimal']['provider_obj'])
    @@ -65,7 +65,7 @@ def biganimal_verification_ack():
     
     @blueprint.route('/verification/',
                      methods=['GET'], endpoint='verification')
    -@login_required
    +@pga_login_required
     def verification():
         """Verify Credentials."""
         biganimal = BigAnimalProvider()
    @@ -78,7 +78,7 @@ def verification():
     
     @blueprint.route('/projects/',
                      methods=['GET'], endpoint='projects')
    -@login_required
    +@pga_login_required
     def biganimal_projects():
         """Get Providers."""
         biganimal_obj = pickle.loads(session['biganimal']['provider_obj'])
    @@ -88,7 +88,7 @@ def biganimal_projects():
     
     @blueprint.route('/providers/<project_id>',
                      methods=['GET'], endpoint='providers')
    -@login_required
    +@pga_login_required
     def biganimal_providers(project_id):
         """Get Providers."""
         biganimal_obj = pickle.loads(session['biganimal']['provider_obj'])
    @@ -99,7 +99,7 @@ def biganimal_providers(project_id):
     
     @blueprint.route('/regions/',
                      methods=['GET'], endpoint='regions')
    -@login_required
    +@pga_login_required
     def biganimal_regions():
         """Get Regions."""
         biganimal_obj = pickle.loads(session['biganimal']['provider_obj'])
    @@ -110,7 +110,7 @@ def biganimal_regions():
     
     @blueprint.route('/db_types/',
                      methods=['GET'], endpoint='db_types')
    -@login_required
    +@pga_login_required
     def biganimal_db_types():
         """Get Database Types."""
         biganimal_obj = pickle.loads(session['biganimal']['provider_obj'])
    @@ -120,7 +120,7 @@ def biganimal_db_types():
     
     @blueprint.route('/db_versions/<cluster_type>/<pg_type>',
                      methods=['GET'], endpoint='db_versions')
    -@login_required
    +@pga_login_required
     def biganimal_db_versions(cluster_type, pg_type):
         """Get Database Version."""
         biganimal_obj = pickle.loads(session['biganimal']['provider_obj'])
    @@ -130,7 +130,7 @@ def biganimal_db_versions(cluster_type, pg_type):
     
     @blueprint.route('/instance_types/<region_id>/<provider_id>',
                      methods=['GET'], endpoint='instance_types')
    -@login_required
    +@pga_login_required
     def biganimal_instance_types(region_id, provider_id):
         """Get Instance Types."""
         if not region_id or not provider_id:
    @@ -143,7 +143,7 @@ def biganimal_instance_types(region_id, provider_id):
     
     @blueprint.route('/volume_types/<region_id>/<provider_id>',
                      methods=['GET'], endpoint='volume_types')
    -@login_required
    +@pga_login_required
     def biganimal_volume_types(region_id, provider_id):
         """Get Volume Types."""
         if not region_id or not provider_id:
    @@ -155,7 +155,7 @@ def biganimal_volume_types(region_id, provider_id):
     
     @blueprint.route('/volume_properties/<region_id>/<provider_id>/<volume_type>',
                      methods=['GET'], endpoint='volume_properties')
    -@login_required
    +@pga_login_required
     def biganimal_volume_properties(region_id, provider_id, volume_type):
         """Get Volume Properties."""
         if not region_id or not provider_id:
    
  • web/pgadmin/misc/cloud/google/__init__.py+10 10 modified
    @@ -20,7 +20,7 @@
     from pgadmin.misc.bgprocess import BatchProcess
     from pgadmin.misc.cloud.utils import _create_server, CloudProcessDesc
     from pgadmin.utils import PgAdminModule, filename_with_file_manager_path
    -from flask_security import login_required
    +from pgadmin.user_login_check import pga_login_required
     from flask import session, current_app, request
     from flask_babel import gettext as _
     
    @@ -53,14 +53,14 @@ def get_exposed_url_endpoints(self):
     
     
     @blueprint.route("/")
    -@login_required
    +@pga_login_required
     def index():
         return bad_request(errormsg=_("This URL cannot be called directly."))
     
     
     @blueprint.route('/verify_credentials/',
                      methods=['POST'], endpoint='verify_credentials')
    -@login_required
    +@pga_login_required
     def verify_credentials():
         """
         Initiate process of authorisation for google oauth2
    @@ -118,7 +118,7 @@ def verify_credentials():
     @blueprint.route('/callback',
                      methods=['GET'], endpoint='callback')
     @pgCSRFProtect.exempt
    -@login_required
    +@pga_login_required
     def callback():
         """
         Call back function on google authentication response.
    @@ -132,7 +132,7 @@ def callback():
     
     @blueprint.route('/verification_ack',
                      methods=['GET'], endpoint='verification_ack')
    -@login_required
    +@pga_login_required
     def verification_ack():
         """
         Checks for google oauth2 authorisation confirmation
    @@ -151,7 +151,7 @@ def verification_ack():
     
     @blueprint.route('/projects/',
                      methods=['GET'], endpoint='projects')
    -@login_required
    +@pga_login_required
     def get_projects():
         """
         Lists the projects for authorized user
    @@ -165,7 +165,7 @@ def get_projects():
     
     @blueprint.route('/regions/<project_id>',
                      methods=['GET'], endpoint='regions')
    -@login_required
    +@pga_login_required
     def get_regions(project_id):
         """
         Lists regions based on project for authorized user
    @@ -184,7 +184,7 @@ def get_regions(project_id):
     
     @blueprint.route('/availability_zones/<region>',
                      methods=['GET'], endpoint='availability_zones')
    -@login_required
    +@pga_login_required
     def get_availability_zones(region):
         """
         List availability zones for specified region
    @@ -201,7 +201,7 @@ def get_availability_zones(region):
     
     @blueprint.route('/instance_types/<project_id>/<region>/<instance_class>',
                      methods=['GET'], endpoint='instance_types')
    -@login_required
    +@pga_login_required
     def get_instance_types(project_id, region, instance_class):
         """
         List the instances types for specified google project, region &
    @@ -224,7 +224,7 @@ def get_instance_types(project_id, region, instance_class):
     
     @blueprint.route('/database_versions/',
                      methods=['GET'], endpoint='database_versions')
    -@login_required
    +@pga_login_required
     def get_database_versions():
         """
         Lists the postgresql database versions.
    
  • web/pgadmin/misc/cloud/__init__.py+9 8 modified
    @@ -13,7 +13,8 @@
     from flask import Response, url_for
     from flask import render_template, request
     from flask_babel import gettext
    -from flask_security import login_required, current_user
    +from flask_security import current_user
    +from pgadmin.user_login_check import pga_login_required
     
     from pgadmin.utils import PgAdminModule, html
     from pgadmin.utils.ajax import make_json_response,\
    @@ -81,15 +82,15 @@ def register(self, app, options):
     
     
     @blueprint.route("/")
    -@login_required
    +@pga_login_required
     def index():
         return bad_request(
             errormsg=gettext("This URL cannot be called directly.")
         )
     
     
     @blueprint.route("/cloud.js")
    -@login_required
    +@pga_login_required
     def script():
         """render own javascript"""
         res = Response(response=render_template(
    @@ -101,7 +102,7 @@ def script():
     
     @blueprint.route('/clear_cloud_session/',
                      methods=['POST'], endpoint='clear_cloud_session')
    -@login_required
    +@pga_login_required
     def clear_session():
         """Get host IP Address"""
         clear_cloud_session()
    @@ -110,7 +111,7 @@ def clear_session():
     
     @blueprint.route('/get_host_ip/',
                      methods=['GET'], endpoint='get_host_ip')
    -@login_required
    +@pga_login_required
     def get_host_ip():
         """Get host IP Address"""
         ip = get_my_ip()
    @@ -120,7 +121,7 @@ def get_host_ip():
     @blueprint.route(
         '/deploy', methods=['POST'], endpoint='deploy_on_cloud'
     )
    -@login_required
    +@pga_login_required
     def deploy_on_cloud():
         """Deploy on Cloud."""
     
    @@ -219,7 +220,7 @@ def clear_cloud_session(pid=None):
         '/update_cloud_process/<sid>', methods=['GET'],
         endpoint='update_cloud_process'
     )
    -@login_required
    +@pga_login_required
     def update_cloud_process(sid):
         """Update Cloud Server Process"""
         _process = Process.query.filter_by(user_id=current_user.id,
    @@ -233,7 +234,7 @@ def update_cloud_process(sid):
         '/update_cloud_server', methods=['POST'],
         endpoint='update_cloud_server'
     )
    -@login_required
    +@pga_login_required
     def update_cloud_server():
         """Update Cloud Server."""
         server_data = json.loads(request.data)
    
  • web/pgadmin/misc/cloud/rds/__init__.py+5 5 modified
    @@ -16,7 +16,7 @@
     from boto3.session import Session
     from flask_babel import gettext
     from flask import session, current_app, request
    -from flask_security import login_required
    +from pgadmin.user_login_check import pga_login_required
     from werkzeug.datastructures import Headers
     from pgadmin.utils import PgAdminModule
     from pgadmin.misc.cloud.utils import _create_server, CloudProcessDesc
    @@ -48,7 +48,7 @@ def get_exposed_url_endpoints(self):
     
     @blueprint.route('/verify_credentials/',
                      methods=['POST'], endpoint='verify_credentials')
    -@login_required
    +@pga_login_required
     def verify_credentials():
         """Verify Credentials."""
         msg = ''
    @@ -80,7 +80,7 @@ def verify_credentials():
     
     @blueprint.route('/db_instances/',
                      methods=['GET'], endpoint='db_instances')
    -@login_required
    +@pga_login_required
     def get_db_instances():
         """
         Fetch AWS DB Instances based on engine version.
    @@ -116,7 +116,7 @@ def get_db_instances():
     
     @blueprint.route('/db_versions/',
                      methods=['GET'], endpoint='db_versions')
    -@login_required
    +@pga_login_required
     def get_db_versions():
         """GET AWS Database Versions for AWS."""
         if 'aws' not in session:
    @@ -142,7 +142,7 @@ def get_db_versions():
     
     @blueprint.route('/regions/',
                      methods=['GET'], endpoint='regions')
    -@login_required
    +@pga_login_required
     def get_regions():
         """GET Regions for AWS."""
         try:
    
  • web/pgadmin/misc/file_manager/__init__.py+9 9 modified
    @@ -26,7 +26,7 @@
     from flask import render_template, Response, session, request as req, \
         url_for, current_app, send_from_directory
     from flask_babel import gettext
    -from flask_security import login_required
    +from pgadmin.user_login_check import pga_login_required
     from pgadmin.utils import PgAdminModule
     from pgadmin.utils import get_storage_directory
     from pgadmin.utils.ajax import make_json_response, unauthorized, \
    @@ -184,15 +184,15 @@ def register_preferences(self):
     
     
     @blueprint.route("/", endpoint='index')
    -@login_required
    +@pga_login_required
     def index():
         return bad_request(
             errormsg=gettext("This URL cannot be called directly.")
         )
     
     
     @blueprint.route("/utility.js")
    -@login_required
    +@pga_login_required
     def utility():
         """render the required javascript"""
         return Response(response=render_template(
    @@ -204,7 +204,7 @@ def utility():
     @blueprint.route(
         "/init", methods=["POST"], endpoint='init'
     )
    -@login_required
    +@pga_login_required
     def init_filemanager():
         if len(req.data) != 0:
             configs = json.loads(req.data)
    @@ -259,7 +259,7 @@ def init_filemanager():
         "/delete_trans_id/<int:trans_id>",
         methods=["DELETE"], endpoint='delete_trans_id'
     )
    -@login_required
    +@pga_login_required
     def delete_trans_id(trans_id):
         Filemanager.release_transaction(trans_id)
         return make_json_response(
    @@ -270,7 +270,7 @@ def delete_trans_id(trans_id):
     @blueprint.route(
         "/save_last_dir/<int:trans_id>", methods=["POST"], endpoint='save_last_dir'
     )
    -@login_required
    +@pga_login_required
     def save_last_directory_visited(trans_id):
         blueprint.last_directory_visited.set(req.json['path'])
         blueprint.last_storage.set(req.json['storage_folder'])
    @@ -281,7 +281,7 @@ def save_last_directory_visited(trans_id):
         "/save_file_dialog_view/<int:trans_id>", methods=["POST"],
         endpoint='save_file_dialog_view'
     )
    -@login_required
    +@pga_login_required
     def save_file_dialog_view(trans_id):
         blueprint.file_dialog_view.set(req.json['view'])
         return make_json_response(status=200)
    @@ -291,7 +291,7 @@ def save_file_dialog_view(trans_id):
         "/save_show_hidden_file_option/<int:trans_id>", methods=["PUT"],
         endpoint='save_show_hidden_file_option'
     )
    -@login_required
    +@pga_login_required
     def save_show_hidden_file_option(trans_id):
         blueprint.show_hidden_files.set(req.json['show_hidden'])
         return make_json_response(status=200)
    @@ -1108,7 +1108,7 @@ def permission(self, path=None):
         "/filemanager/<int:trans_id>/",
         methods=["POST"], endpoint='filemanager'
     )
    -@login_required
    +@pga_login_required
     def file_manager(trans_id):
         """
         It is the common function for every call which is made
    
  • web/pgadmin/misc/__init__.py+3 3 modified
    @@ -13,7 +13,7 @@
     from flask import render_template, Response, request, current_app
     from flask.helpers import url_for
     from flask_babel import gettext
    -from flask_security import login_required
    +from pgadmin.user_login_check import pga_login_required
     from pathlib import Path
     from pgadmin.utils import PgAdminModule, replace_binary_path, \
         get_binary_path_versions
    @@ -221,7 +221,7 @@ def shutdown():
     @blueprint.route("/validate_binary_path",
                      endpoint="validate_binary_path",
                      methods=["POST"])
    -@login_required
    +@pga_login_required
     def validate_binary_path():
         """
         This function is used to validate the specified utilities path by
    @@ -255,7 +255,7 @@ def validate_binary_path():
     
     @blueprint.route("/upgrade_check", endpoint="upgrade_check",
                      methods=['GET'])
    -@login_required
    +@pga_login_required
     def upgrade_check():
         # Get the current version info from the website, and flash a message if
         # the user is out of date, and the check is enabled.
    
  • web/pgadmin/preferences/__init__.py+6 6 modified
    @@ -16,7 +16,7 @@
     import json
     from flask import render_template, url_for, Response, request, session
     from flask_babel import gettext
    -from flask_security import login_required
    +from pgadmin.user_login_check import pga_login_required
     from pgadmin.utils import PgAdminModule
     from pgadmin.utils.ajax import success_return, \
         make_response as ajax_response, internal_server_error
    @@ -57,7 +57,7 @@ def get_exposed_url_endpoints(self):
     
     
     @blueprint.route("/preferences.js")
    -@login_required
    +@pga_login_required
     def script():
         """render the required javascript"""
         return Response(
    @@ -69,7 +69,7 @@ def script():
     
     @blueprint.route("/", methods=["GET"], endpoint='index')
     @blueprint.route("/<module>/<preference>", endpoint='get_by_name')
    -@login_required
    +@pga_login_required
     def preferences(module=None, preference=None):
         """Fetch all/or requested preferences of pgAdmin IV."""
     
    @@ -162,7 +162,7 @@ def _iterate_categories(pref_d, label, res):
     
     
     @blueprint.route("/get_all", methods=["GET"], endpoint='get_all')
    -@login_required
    +@pga_login_required
     def preferences_s():
         """Fetch all preferences for caching."""
         # Load Preferences
    @@ -220,7 +220,7 @@ def get_data():
     
     
     @blueprint.route("/", methods=["PUT"], endpoint="update")
    -@login_required
    +@pga_login_required
     def save():
         """
         Save a specific preference.
    @@ -296,7 +296,7 @@ def save_pref(data):
     
     
     @blueprint.route("/update", methods=["PUT"], endpoint="update_pref")
    -@login_required
    +@pga_login_required
     def update():
         """
         Update a specific preference.
    
  • web/pgadmin/redirects/__init__.py+2 2 modified
    @@ -8,7 +8,7 @@
     ##########################################################################
     
     from flask import redirect, url_for
    -from flask_security import login_required
    +from pgadmin.user_login_check import pga_login_required
     
     from pgadmin import PgAdminModule
     
    @@ -20,7 +20,7 @@
     
     
     @blueprint.route('/')
    -@login_required
    +@pga_login_required
     def index():
         """Redirect users hitting the root to the browser"""
         return redirect(url_for('browser.index'))
    
  • web/pgadmin/settings/__init__.py+10 10 modified
    @@ -15,7 +15,7 @@
     from flask import Response, request, render_template, url_for, current_app
     from flask_babel import gettext
     from flask_login import current_user
    -from flask_security import login_required
    +from pgadmin.user_login_check import pga_login_required
     from pgadmin.utils import PgAdminModule
     from pgadmin.utils.ajax import make_json_response, bad_request,\
         success_return, internal_server_error
    @@ -80,13 +80,13 @@ def get_setting(setting, default=''):
     
     
     @blueprint.route("/")
    -@login_required
    +@pga_login_required
     def index():
         return bad_request(errormsg=gettext("This URL cannot be called directly."))
     
     
     @blueprint.route("/settings.js")
    -@login_required
    +@pga_login_required
     def script():
         """Render the required Javascript"""
         return Response(response=render_template("settings/settings.js"),
    @@ -96,7 +96,7 @@ def script():
     
     @blueprint.route("/store", methods=['POST'], endpoint='store_bulk')
     @blueprint.route("/store/<setting>/<value>", methods=['PUT'], endpoint='store')
    -@login_required
    +@pga_login_required
     def store(setting=None, value=None):
         """Store a configuration setting, or if this is a POST request and a
         count value is present, store multiple settings at once."""
    @@ -131,7 +131,7 @@ def store(setting=None, value=None):
     
     
     @blueprint.route("/layout", methods=['DELETE'], endpoint='reset_layout')
    -@login_required
    +@pga_login_required
     def reset_layout():
         """Reset configuration setting"""
     
    @@ -162,7 +162,7 @@ def reset_layout():
     
     @blueprint.route("/reset_tree_state", methods=['DELETE'],
                      endpoint='reset_tree_state')
    -@login_required
    +@pga_login_required
     def reset_tree_state():
         """Reset the saved tree state."""
     
    @@ -182,7 +182,7 @@ def reset_tree_state():
     
     @blueprint.route("/save_tree_state/", endpoint="save_tree_state",
                      methods=['POST'])
    -@login_required
    +@pga_login_required
     def save_browser_tree_state():
         """Save the browser tree state."""
         data = request.form if request.form else request.data.decode('utf-8')
    @@ -210,7 +210,7 @@ def save_browser_tree_state():
     
     @blueprint.route("/get_tree_state/", endpoint="get_tree_state",
                      methods=['GET'])
    -@login_required
    +@pga_login_required
     def get_browser_tree_state():
         """Get the browser tree state."""
     
    @@ -228,7 +228,7 @@ def get_browser_tree_state():
     @blueprint.route("/save_file_format_setting/",
                      endpoint="save_file_format_setting",
                      methods=['POST'])
    -@login_required
    +@pga_login_required
     def save_file_format_setting():
         """
         This function save the selected file format.save_file_format_setting
    @@ -247,7 +247,7 @@ def save_file_format_setting():
     @blueprint.route("/get_file_format_setting/",
                      endpoint="get_file_format_setting",
                      methods=['GET'])
    -@login_required
    +@pga_login_required
     def get_file_format_setting():
         """
         This function return the last selected file format
    
  • web/pgadmin/tools/backup/__init__.py+7 6 modified
    @@ -16,7 +16,8 @@
     from flask import render_template, request, current_app, \
         url_for, Response
     from flask_babel import gettext
    -from flask_security import login_required, current_user
    +from flask_security import current_user
    +from pgadmin.user_login_check import pga_login_required
     from pgadmin.misc.bgprocess.processes import BatchProcess, IProcessDesc
     from pgadmin.utils import PgAdminModule, get_storage_directory, html, \
         fs_short_path, document_dir, does_utility_exist, get_server, \
    @@ -177,13 +178,13 @@ def details(self, cmd, args):
     
     
     @blueprint.route("/")
    -@login_required
    +@pga_login_required
     def index():
         return bad_request(errormsg=gettext("This URL cannot be called directly."))
     
     
     @blueprint.route("/backup.js")
    -@login_required
    +@pga_login_required
     def script():
         """render own javascript"""
         return Response(
    @@ -391,7 +392,7 @@ def set_value(key, param, default_value=None, assertion=True):
     @blueprint.route(
         '/job/<int:sid>/object', methods=['POST'], endpoint='create_object_job'
     )
    -@login_required
    +@pga_login_required
     def create_backup_objects_job(sid):
         """
         Args:
    @@ -498,7 +499,7 @@ def create_backup_objects_job(sid):
     @blueprint.route(
         '/utility_exists/<int:sid>/<backup_obj_type>', endpoint='utility_exists'
     )
    -@login_required
    +@pga_login_required
     def check_utility_exists(sid, backup_obj_type):
         """
         This function checks the utility file exist on the given path.
    @@ -540,7 +541,7 @@ def check_utility_exists(sid, backup_obj_type):
     @blueprint.route(
         '/objects/<int:sid>/<int:did>/<int:scid>', endpoint='schema_objects'
     )
    -@login_required
    +@pga_login_required
     def objects(sid, did, scid=None):
         """
         This function returns backup objects
    
  • web/pgadmin/tools/debugger/__init__.py+19 19 modified
    @@ -16,7 +16,7 @@
     
     from flask import render_template, request, current_app
     from flask_babel import gettext
    -from flask_security import login_required
    +from pgadmin.user_login_check import pga_login_required
     from werkzeug.user_agent import UserAgent
     
     from pgadmin.utils import PgAdminModule, \
    @@ -237,7 +237,7 @@ def on_logout(self):
     
     
     @blueprint.route("/", endpoint='index')
    -@login_required
    +@pga_login_required
     def index():
         return bad_request(
             errormsg=gettext("This URL cannot be called directly.")
    @@ -350,7 +350,7 @@ def check_node_type(node_type, fid, trid, conn, ppas_server,
         '/init/<node_type>/<int:sid>/<int:did>/<int:scid>/<int:fid>/<int:trid>',
         methods=['GET'], endpoint='init_for_trigger'
     )
    -@login_required
    +@pga_login_required
     def init_function(node_type, sid, did, scid, fid, trid=None):
         """
         init_function(node_type, sid, did, scid, fid, trid)
    @@ -557,7 +557,7 @@ def check_user_ip_req(r_set, data):
     
     
     @blueprint.route('/direct/<int:trans_id>', methods=['GET'], endpoint='direct')
    -@login_required
    +@pga_login_required
     def direct_new(trans_id):
         de_inst = DebuggerInstance(trans_id)
     
    @@ -769,7 +769,7 @@ def get_search_path(conn):
         methods=['POST'],
         endpoint='initialize_target_for_trigger'
     )
    -@login_required
    +@pga_login_required
     def initialize_target(debug_type, trans_id, sid, did,
                           scid, func_id, tri_id=None):
         """
    @@ -894,7 +894,7 @@ def close(trans_id):
     @blueprint.route(
         '/restart/<int:trans_id>', methods=['GET'], endpoint='restart'
     )
    -@login_required
    +@pga_login_required
     def restart_debugging(trans_id):
         """
         restart_debugging(trans_id)
    @@ -959,7 +959,7 @@ def restart_debugging(trans_id):
         '/start_listener/<int:trans_id>', methods=['POST'],
         endpoint='start_listener'
     )
    -@login_required
    +@pga_login_required
     def start_debugger_listener(trans_id):
         """
         start_debugger_listener(trans_id)
    @@ -1203,7 +1203,7 @@ def get_debugger_arg_val(val_list):
         '/execute_query/<int:trans_id>/<query_type>', methods=['GET'],
         endpoint='execute_query'
     )
    -@login_required
    +@pga_login_required
     def execute_debugger_query(trans_id, query_type):
         """
         execute_debugger_query(trans_id, query_type)
    @@ -1290,7 +1290,7 @@ def execute_debugger_query(trans_id, query_type):
     @blueprint.route(
         '/messages/<int:trans_id>/', methods=["GET"], endpoint='messages'
     )
    -@login_required
    +@pga_login_required
     def messages(trans_id):
         """
         messages(trans_id)
    @@ -1348,7 +1348,7 @@ def messages(trans_id):
         '/start_execution/<int:trans_id>/<int:port_num>', methods=['GET'],
         endpoint='start_execution'
     )
    -@login_required
    +@pga_login_required
     def start_execution(trans_id, port_num):
         """
         start_execution(trans_id, port_num)
    @@ -1424,7 +1424,7 @@ def start_execution(trans_id, port_num):
         '/set_breakpoint/<int:trans_id>/<int:line_no>/<int:set_type>',
         methods=['GET'], endpoint='set_breakpoint'
     )
    -@login_required
    +@pga_login_required
     def set_clear_breakpoint(trans_id, line_no, set_type):
         """
         set_clear_breakpoint(trans_id, line_no, set_type)
    @@ -1525,7 +1525,7 @@ def get_debugger_template_path(de_inst):
         '/clear_all_breakpoint/<int:trans_id>', methods=['POST'],
         endpoint='clear_all_breakpoint'
     )
    -@login_required
    +@pga_login_required
     def clear_all_breakpoint(trans_id):
         """
         clear_all_breakpoint(trans_id)
    @@ -1597,7 +1597,7 @@ def clear_all_breakpoint(trans_id):
         '/deposit_value/<int:trans_id>', methods=['POST'],
         endpoint='deposit_value'
     )
    -@login_required
    +@pga_login_required
     def deposit_parameter_value(trans_id):
         """
         deposit_parameter_value(trans_id)
    @@ -1671,7 +1671,7 @@ def deposit_parameter_value(trans_id):
         '/select_frame/<int:trans_id>/<int:frame_id>', methods=['GET'],
         endpoint='select_frame'
     )
    -@login_required
    +@pga_login_required
     def select_frame(trans_id, frame_id):
         """
         select_frame(trans_id, frame_id)
    @@ -1733,7 +1733,7 @@ def select_frame(trans_id, frame_id):
         '/get_arguments/<int:sid>/<int:did>/<int:scid>/<int:func_id>',
         methods=['GET'], endpoint='get_arguments'
     )
    -@login_required
    +@pga_login_required
     def get_arguments_sqlite(sid, did, scid, func_id):
         """
         get_arguments_sqlite(sid, did, scid, func_id)
    @@ -1818,7 +1818,7 @@ def get_array_string(data, i):
         '/set_arguments/<int:sid>/<int:did>/<int:scid>/<int:func_id>',
         methods=['POST'], endpoint='set_arguments'
     )
    -@login_required
    +@pga_login_required
     def set_arguments_sqlite(sid, did, scid, func_id):
         """
         set_arguments_sqlite(sid, did, scid, func_id)
    @@ -1907,7 +1907,7 @@ def set_arguments_sqlite(sid, did, scid, func_id):
         '/clear_arguments/<int:sid>/<int:did>/<int:scid>/<int:func_id>',
         methods=['POST'], endpoint='clear_arguments'
     )
    -@login_required
    +@pga_login_required
     def clear_arguments_sqlite(sid, did, scid, func_id):
         """
         clear_arguments_sqlite(sid, did, scid, func_id)
    @@ -2052,7 +2052,7 @@ def check_result(result, conn, statusmsg):
         '/poll_end_execution_result/<int:trans_id>/',
         methods=["GET"], endpoint='poll_end_execution_result'
     )
    -@login_required
    +@pga_login_required
     def poll_end_execution_result(trans_id):
         """
         poll_end_execution_result(trans_id)
    @@ -2128,7 +2128,7 @@ def poll_end_execution_result(trans_id):
     @blueprint.route(
         '/poll_result/<int:trans_id>/', methods=["GET"], endpoint='poll_result'
     )
    -@login_required
    +@pga_login_required
     def poll_result(trans_id):
         """
         poll_result(trans_id)
    
  • web/pgadmin/tools/erd/__init__.py+6 6 modified
    @@ -12,7 +12,7 @@
     
     from flask import url_for, request, Response
     from flask import render_template, current_app as app
    -from flask_security import login_required
    +from pgadmin.user_login_check import pga_login_required
     from flask_babel import gettext
     from werkzeug.user_agent import UserAgent
     from pgadmin.utils import PgAdminModule, \
    @@ -431,7 +431,7 @@ def register_preferences(self):
         methods=["POST"],
         endpoint='panel'
     )
    -@login_required
    +@pga_login_required
     def panel(trans_id):
         """
         This method calls index.html to render the erd tool.
    @@ -496,7 +496,7 @@ def panel(trans_id):
         '/initialize/<int:trans_id>/<int:sgid>/<int:sid>/<int:did>',
         methods=["POST"], endpoint='initialize'
     )
    -@login_required
    +@pga_login_required
     def initialize_erd(trans_id, sgid, sid, did):
         """
         This method is responsible for instantiating and initializing
    @@ -551,7 +551,7 @@ def _get_connection(sid, did, trans_id):
     @blueprint.route('/prequisite/<int:trans_id>/<int:sgid>/<int:sid>/<int:did>',
                      methods=["GET"],
                      endpoint='prequisite')
    -@login_required
    +@pga_login_required
     def prequisite(trans_id, sgid, sid, did):
         conn = _get_connection(sid, did, trans_id)
         helper = ERDHelper(trans_id, sid, did)
    @@ -608,7 +608,7 @@ def translate_foreign_keys(tab_fks, tab_data, all_nodes):
     @blueprint.route('/sql/<int:trans_id>/<int:sgid>/<int:sid>/<int:did>',
                      methods=["POST"],
                      endpoint='sql')
    -@login_required
    +@pga_login_required
     def sql(trans_id, sgid, sid, did):
         data = json.loads(request.data)
         with_drop = False
    @@ -687,7 +687,7 @@ def tables(params):
     @blueprint.route('/close/<int:trans_id>/<int:sgid>/<int:sid>/<int:did>',
                      methods=["DELETE"],
                      endpoint='close')
    -@login_required
    +@pga_login_required
     def close(trans_id, sgid, sid, did):
         manager = get_driver(
             PG_DEFAULT_DRIVER).connection_manager(sid)
    
  • web/pgadmin/tools/grant_wizard/__init__.py+7 7 modified
    @@ -13,7 +13,7 @@
     from flask import Response, url_for
     from flask import render_template, request, current_app
     from flask_babel import gettext
    -from flask_security import login_required
    +from pgadmin.user_login_check import pga_login_required
     from urllib.parse import unquote
     
     from pgadmin.browser.server_groups.servers.utils import parse_priv_to_db
    @@ -115,15 +115,15 @@ def wrap(*args, **kwargs):
     
     
     @blueprint.route("/")
    -@login_required
    +@pga_login_required
     def index():
         return bad_request(
             errormsg=gettext("This URL cannot be called directly.")
         )
     
     
     @blueprint.route("/grant_wizard.js")
    -@login_required
    +@pga_login_required
     def script():
         """render own javascript"""
         return Response(response=render_template(
    @@ -135,7 +135,7 @@ def script():
     @blueprint.route(
         '/acl/<int:sid>/<int:did>/', methods=['GET'], endpoint='acl'
     )
    -@login_required
    +@pga_login_required
     @check_precondition
     def acl_list(sid, did):
         """render list of acls"""
    @@ -255,7 +255,7 @@ def get_node_sql_with_type(node_id, node_type, server_prop,
         '/<int:sid>/<int:did>/<int:node_id>/<node_type>/',
         methods=['GET'], endpoint='objects'
     )
    -@login_required
    +@pga_login_required
     @check_precondition
     def properties(sid, did, node_id, node_type):
         """It fetches the properties of object types
    @@ -411,7 +411,7 @@ def set_priv_for_package(server_prop, data, acls):
         '/sql/<int:sid>/<int:did>/',
         methods=['POST'], endpoint='modified_sql'
     )
    -@login_required
    +@pga_login_required
     @check_precondition
     def msql(sid, did):
         """
    @@ -545,7 +545,7 @@ def parse_priv(data, acls, server_prop):
     @blueprint.route(
         '/<int:sid>/<int:did>/', methods=['POST'], endpoint='apply'
     )
    -@login_required
    +@pga_login_required
     @check_precondition
     def save(sid, did):
         """
    
  • web/pgadmin/tools/import_export/__init__.py+7 6 modified
    @@ -14,7 +14,8 @@
     
     from flask import Response, render_template, request, current_app
     from flask_babel import gettext as _
    -from flask_security import login_required, current_user
    +from flask_security import current_user
    +from pgadmin.user_login_check import pga_login_required
     from pgadmin.misc.bgprocess.processes import BatchProcess, IProcessDesc
     from pgadmin.utils import PgAdminModule, get_storage_directory, IS_WIN, \
         does_utility_exist, get_server, filename_with_file_manager_path
    @@ -135,13 +136,13 @@ def details(self, cmd, args):
     
     
     @blueprint.route("/")
    -@login_required
    +@pga_login_required
     def index():
         return bad_request(errormsg=_("This URL cannot be called directly."))
     
     
     @blueprint.route("/js/import_export.js")
    -@login_required
    +@pga_login_required
     def script():
         """render the import/export javascript file"""
         return Response(
    @@ -226,7 +227,7 @@ def _save_import_export_settings(settings):
     
     
     @blueprint.route('/job/<int:sid>', methods=['POST'], endpoint="create_job")
    -@login_required
    +@pga_login_required
     def create_import_export_job(sid):
         """
         Args:
    @@ -358,7 +359,7 @@ def create_import_export_job(sid):
     
     
     @blueprint.route('/get_settings/', methods=['GET'], endpoint='get_settings')
    -@login_required
    +@pga_login_required
     def get_import_export_settings():
         settings = get_setting('import_export_setting', None)
         if settings is None:
    @@ -371,7 +372,7 @@ def get_import_export_settings():
     @blueprint.route(
         '/utility_exists/<int:sid>', endpoint='utility_exists'
     )
    -@login_required
    +@pga_login_required
     def check_utility_exists(sid):
         """
         This function checks the utility file exist on the given path.
    
  • web/pgadmin/tools/import_export_servers/__init__.py+7 6 modified
    @@ -16,7 +16,8 @@
     
     from flask import Response, render_template, request
     from flask_babel import gettext as _
    -from flask_security import login_required, current_user
    +from flask_security import current_user
    +from pgadmin.user_login_check import pga_login_required
     from pgadmin.utils import PgAdminModule
     from pgadmin.utils.ajax import bad_request
     from pgadmin.utils.constants import MIMETYPE_APP_JS
    @@ -54,13 +55,13 @@ def get_exposed_url_endpoints(self):
     
     
     @blueprint.route("/")
    -@login_required
    +@pga_login_required
     def index():
         return bad_request(errormsg=_("This URL cannot be called directly."))
     
     
     @blueprint.route("/js/import_export_servers.js")
    -@login_required
    +@pga_login_required
     def script():
         """render the import/export javascript file"""
         return Response(
    @@ -72,7 +73,7 @@ def script():
     
     
     @blueprint.route('/get_servers', methods=['GET'], endpoint='get_servers')
    -@login_required
    +@pga_login_required
     def get_servers():
         """
         This function is used to get the servers with server groups
    @@ -102,7 +103,7 @@ def get_servers():
     
     
     @blueprint.route('/load_servers', methods=['POST'], endpoint='load_servers')
    -@login_required
    +@pga_login_required
     def load_servers():
         """
         This function is used to load the servers from the json file.
    @@ -167,7 +168,7 @@ def load_servers():
     
     
     @blueprint.route('/save', methods=['POST'], endpoint='save')
    -@login_required
    +@pga_login_required
     def save():
         """
         This function is used to import or export based on the data
    
  • web/pgadmin/tools/maintenance/__init__.py+6 5 modified
    @@ -13,7 +13,8 @@
     
     from flask import url_for, Response, render_template, request, current_app
     from flask_babel import gettext as _
    -from flask_security import login_required, current_user
    +from flask_security import current_user
    +from pgadmin.user_login_check import pga_login_required
     from pgadmin.misc.bgprocess.processes import BatchProcess, IProcessDesc
     from pgadmin.utils import PgAdminModule, html, does_utility_exist, get_server
     from pgadmin.utils.ajax import bad_request, make_json_response
    @@ -122,15 +123,15 @@ def details(self, cmd, args):
     
     
     @blueprint.route("/")
    -@login_required
    +@pga_login_required
     def index():
         return bad_request(
             errormsg=_("This URL cannot be called directly.")
         )
     
     
     @blueprint.route("/js/maintenance.js")
    -@login_required
    +@pga_login_required
     def script():
         """render the maintenance tool of vacuum javascript file"""
         return Response(
    @@ -160,7 +161,7 @@ def get_index_name(data):
     @blueprint.route(
         '/job/<int:sid>/<int:did>', methods=['POST'], endpoint='create_job'
     )
    -@login_required
    +@pga_login_required
     def create_maintenance_job(sid, did):
         """
         Args:
    @@ -252,7 +253,7 @@ def create_maintenance_job(sid, did):
     @blueprint.route(
         '/utility_exists/<int:sid>', endpoint='utility_exists'
     )
    -@login_required
    +@pga_login_required
     def check_utility_exists(sid):
         """
         This function checks the utility file exist on the given path.
    
  • web/pgadmin/tools/psql/__init__.py+4 3 modified
    @@ -19,7 +19,8 @@
     from flask import render_template, copy_current_request_context, \
         current_app as app
     from flask_babel import gettext
    -from flask_security import login_required, current_user
    +from flask_security import current_user
    +from pgadmin.user_login_check import pga_login_required
     from pgadmin.browser.utils import underscore_unescape, underscore_escape
     from pgadmin.utils import PgAdminModule
     from pgadmin.utils.constants import MIMETYPE_APP_JS
    @@ -71,7 +72,7 @@ def get_exposed_url_endpoints(self):
     
     
     @blueprint.route("/psql.js")
    -@login_required
    +@pga_login_required
     def script():
         """render the required javascript"""
         return Response(
    @@ -84,7 +85,7 @@ def script():
     @blueprint.route('/panel/<int:trans_id>',
                      methods=["POST"],
                      endpoint="panel")
    -@login_required
    +@pga_login_required
     def panel(trans_id):
         """
         Return panel template for PSQL tools.
    
  • web/pgadmin/tools/restore/__init__.py+6 5 modified
    @@ -13,7 +13,8 @@
     
     from flask import render_template, request, current_app, Response
     from flask_babel import gettext as _
    -from flask_security import login_required, current_user
    +from flask_security import current_user
    +from pgadmin.user_login_check import pga_login_required
     from pgadmin.misc.bgprocess.processes import BatchProcess, IProcessDesc
     from pgadmin.utils import PgAdminModule, fs_short_path, does_utility_exist, \
         get_server, filename_with_file_manager_path
    @@ -109,13 +110,13 @@ def details(self, cmd, args):
     
     
     @blueprint.route("/")
    -@login_required
    +@pga_login_required
     def index():
         return bad_request(errormsg=_("This URL cannot be called directly."))
     
     
     @blueprint.route("/restore.js")
    -@login_required
    +@pga_login_required
     def script():
         """render own javascript"""
         return Response(
    @@ -350,7 +351,7 @@ def _set_args_param_values(data, manager, server, driver, conn, _file):
     
     
     @blueprint.route('/job/<int:sid>', methods=['POST'], endpoint='create_job')
    -@login_required
    +@pga_login_required
     def create_restore_job(sid):
         """
         Args:
    @@ -410,7 +411,7 @@ def create_restore_job(sid):
     @blueprint.route(
         '/utility_exists/<int:sid>', endpoint='utility_exists'
     )
    -@login_required
    +@pga_login_required
     def check_utility_exists(sid):
         """
         This function checks the utility file exist on the given path.
    
  • web/pgadmin/tools/schema_diff/__init__.py+11 10 modified
    @@ -15,7 +15,8 @@
     
     from flask import Response, session, url_for, request
     from flask import render_template, current_app as app
    -from flask_security import current_user, login_required
    +from flask_security import current_user
    +from pgadmin.user_login_check import pga_login_required
     from flask_babel import gettext
     from pgadmin.utils import PgAdminModule
     from pgadmin.utils.ajax import make_json_response, bad_request, \
    @@ -109,7 +110,7 @@ def register_preferences(self):
     
     
     @blueprint.route("/")
    -@login_required
    +@pga_login_required
     def index():
         return bad_request(
             errormsg=gettext('This URL cannot be requested directly.')
    @@ -193,7 +194,7 @@ def update_session_diff_transaction(trans_id, session_obj, diff_model_obj):
         methods=["GET"],
         endpoint="initialize"
     )
    -@login_required
    +@pga_login_required
     def initialize():
         """
         This function will initialize the schema diff and return the list
    @@ -261,7 +262,7 @@ def close(trans_id):
         methods=["GET"],
         endpoint="servers"
     )
    -@login_required
    +@pga_login_required
     def servers():
         """
         This function will return the list of servers for the specified
    @@ -317,7 +318,7 @@ def servers():
         methods=["GET"],
         endpoint="get_server"
     )
    -@login_required
    +@pga_login_required
     def get_server(sid, did):
         """
         This function will return the server details for the specified
    @@ -354,7 +355,7 @@ def get_server(sid, did):
         methods=["POST"],
         endpoint="connect_server"
     )
    -@login_required
    +@pga_login_required
     def connect_server(sid):
         # Check if server is already connected then no need to reconnect again.
         driver = get_driver(PG_DEFAULT_DRIVER)
    @@ -377,7 +378,7 @@ def connect_server(sid):
         methods=["POST"],
         endpoint="connect_database"
     )
    -@login_required
    +@pga_login_required
     def connect_database(sid, did):
         server = Server.query.filter_by(id=sid).first()
         view = SchemaDiffRegistry.get_node_view('database')
    @@ -389,7 +390,7 @@ def connect_database(sid, did):
         methods=["GET"],
         endpoint="databases"
     )
    -@login_required
    +@pga_login_required
     def databases(sid):
         """
         This function will return the list of databases for the specified
    @@ -426,7 +427,7 @@ def databases(sid):
         methods=["GET"],
         endpoint="schemas"
     )
    -@login_required
    +@pga_login_required
     def schemas(sid, did):
         """
         This function will return the list of schemas for the specified
    @@ -668,7 +669,7 @@ def compare_schema(params):
         methods=["GET"],
         endpoint="ddl_compare"
     )
    -@login_required
    +@pga_login_required
     def ddl_compare(trans_id, source_sid, source_did, source_scid,
                     target_sid, target_did, target_scid, source_oid,
                     target_oid, node_type, comp_status):
    
  • web/pgadmin/tools/search_objects/__init__.py+4 4 modified
    @@ -11,7 +11,7 @@
     
     from flask import request
     from flask_babel import gettext
    -from flask_security import login_required
    +from pgadmin.user_login_check import pga_login_required
     
     from pgadmin.utils import PgAdminModule
     from pgadmin.utils.ajax import make_json_response, bad_request,\
    @@ -54,20 +54,20 @@ def register_preferences(self):
     
     
     @blueprint.route("/", endpoint='index')
    -@login_required
    +@pga_login_required
     def index():
         return bad_request(errormsg=gettext("This URL cannot be called directly."))
     
     
     @blueprint.route("types/<int:sid>/<int:did>", endpoint='types')
    -@login_required
    +@pga_login_required
     def types(sid, did):
         so_obj = SearchObjectsHelper(sid, did, blueprint.show_system_objects())
         return make_json_response(data=so_obj.get_supported_types())
     
     
     @blueprint.route("search/<int:sid>/<int:did>", endpoint='search')
    -@login_required
    +@pga_login_required
     def search(sid, did):
         """
         URL args:
    
  • web/pgadmin/tools/sqleditor/__init__.py+40 39 modified
    @@ -22,7 +22,8 @@
     from flask import Response, url_for, render_template, session, current_app
     from flask import request
     from flask_babel import gettext
    -from flask_security import login_required, current_user
    +from pgadmin.user_login_check import pga_login_required
    +from flask_security import current_user
     from pgadmin.misc.file_manager import Filemanager
     from pgadmin.tools.sqleditor.command import QueryToolCommand, ObjectRegistry, \
         SQLFilter
    @@ -161,15 +162,15 @@ def register_preferences(self):
     
     
     @blueprint.route('/')
    -@login_required
    +@pga_login_required
     def index():
         return bad_request(
             errormsg=gettext('This URL cannot be requested directly.')
         )
     
     
     @blueprint.route("/filter", endpoint='filter')
    -@login_required
    +@pga_login_required
     def show_filter():
         return render_template(MODULE_NAME + '/filter.html')
     
    @@ -180,7 +181,7 @@ def show_filter():
         methods=["PUT", "POST"],
         endpoint="initialize_viewdata"
     )
    -@login_required
    +@pga_login_required
     def initialize_viewdata(trans_id, cmd_type, obj_type, sgid, sid, did, obj_id):
         """
         This method is responsible for creating an asynchronous connection.
    @@ -346,7 +347,7 @@ def panel(trans_id):
         '/initialize/sqleditor/<int:trans_id>/<int:sgid>/<int:sid>',
         methods=["POST"], endpoint='initialize_sqleditor'
     )
    -@login_required
    +@pga_login_required
     def initialize_sqleditor(trans_id, sgid, sid, did=None):
         """
         This method is responsible for instantiating and initializing
    @@ -632,7 +633,7 @@ def close(trans_id):
         '/filter/validate/<int:sid>/<int:did>/<int:obj_id>',
         methods=["PUT", "POST"], endpoint='filter_validate'
     )
    -@login_required
    +@pga_login_required
     def validate_filter(sid, did, obj_id):
         """
         This method is used to validate the sql filter.
    @@ -765,7 +766,7 @@ def check_transaction_status(trans_id, auto_comp=False):
         '/view_data/start/<int:trans_id>',
         methods=["GET"], endpoint='view_data_start'
     )
    -@login_required
    +@pga_login_required
     def start_view_data(trans_id):
         """
         This method is used to execute query using asynchronous connection.
    @@ -864,7 +865,7 @@ def start_view_data(trans_id):
         '/query_tool/start/<int:trans_id>',
         methods=["PUT", "POST"], endpoint='query_tool_start'
     )
    -@login_required
    +@pga_login_required
     def start_query_tool(trans_id):
         """
         This method is used to execute query using asynchronous connection.
    @@ -902,7 +903,7 @@ def extract_sql_from_network_parameters(request_data, request_arguments,
     
     
     @blueprint.route('/poll/<int:trans_id>', methods=["GET"], endpoint='poll')
    -@login_required
    +@pga_login_required
     def poll(trans_id):
         """
         This method polls the result of the asynchronous query and returns
    @@ -1144,7 +1145,7 @@ def poll(trans_id):
         '/fetch/<int:trans_id>/<int:fetch_all>', methods=["GET"],
         endpoint='fetch_all'
     )
    -@login_required
    +@pga_login_required
     def fetch(trans_id, fetch_all=None):
         result = None
         has_more_rows = False
    @@ -1199,7 +1200,7 @@ def fetch(trans_id, fetch_all=None):
         '/fetch_all_from_start/<int:trans_id>/<int:limit>', methods=["GET"],
         endpoint='fetch_all_from_start'
     )
    -@login_required
    +@pga_login_required
     def fetch_all_from_start(trans_id, limit=-1):
         """
         This function is used to fetch all the records from start and reset
    @@ -1330,7 +1331,7 @@ def _check_and_connect(trans_obj):
     @blueprint.route(
         '/save/<int:trans_id>', methods=["PUT", "POST"], endpoint='save'
     )
    -@login_required
    +@pga_login_required
     def save(trans_id):
         """
         This method is used to save the data changes to the server
    @@ -1401,7 +1402,7 @@ def save(trans_id):
         '/filter/inclusive/<int:trans_id>',
         methods=["PUT", "POST"], endpoint='inclusive_filter'
     )
    -@login_required
    +@pga_login_required
     def append_filter_inclusive(trans_id):
         """
         This method is used to append and apply the filter.
    @@ -1456,7 +1457,7 @@ def append_filter_inclusive(trans_id):
         '/filter/exclusive/<int:trans_id>',
         methods=["PUT", "POST"], endpoint='exclusive_filter'
     )
    -@login_required
    +@pga_login_required
     def append_filter_exclusive(trans_id):
         """
         This method is used to append and apply the filter.
    @@ -1512,7 +1513,7 @@ def append_filter_exclusive(trans_id):
         '/filter/remove/<int:trans_id>',
         methods=["PUT", "POST"], endpoint='remove_filter'
     )
    -@login_required
    +@pga_login_required
     def remove_filter(trans_id):
         """
         This method is used to remove the filter.
    @@ -1552,7 +1553,7 @@ def remove_filter(trans_id):
     @blueprint.route(
         '/limit/<int:trans_id>', methods=["PUT", "POST"], endpoint='set_limit'
     )
    -@login_required
    +@pga_login_required
     def set_limit(trans_id):
         """
         This method is used to set the limit for the SQL.
    @@ -1640,7 +1641,7 @@ def _check_and_cancel_transaction(trans_obj, delete_connection, conn, manager):
         '/cancel/<int:trans_id>',
         methods=["PUT", "POST"], endpoint='cancel_transaction'
     )
    -@login_required
    +@pga_login_required
     def cancel_transaction(trans_id):
         """
         This method is used to cancel the running transaction
    @@ -1701,7 +1702,7 @@ def cancel_transaction(trans_id):
         '/object/get/<int:trans_id>',
         methods=["GET"], endpoint='get_object_name'
     )
    -@login_required
    +@pga_login_required
     def get_object_name(trans_id):
         """
         This method is used to get the object name
    @@ -1757,7 +1758,7 @@ def check_and_upgrade_to_qt(trans_id, connect):
         '/auto_commit/<int:trans_id>',
         methods=["PUT", "POST"], endpoint='auto_commit'
     )
    -@login_required
    +@pga_login_required
     def set_auto_commit(trans_id):
         """
         This method is used to set the value for auto commit .
    @@ -1810,7 +1811,7 @@ def set_auto_commit(trans_id):
         '/auto_rollback/<int:trans_id>',
         methods=["PUT", "POST"], endpoint='auto_rollback'
     )
    -@login_required
    +@pga_login_required
     def set_auto_rollback(trans_id):
         """
         This method is used to set the value for auto commit .
    @@ -1863,7 +1864,7 @@ def set_auto_rollback(trans_id):
         '/autocomplete/<int:trans_id>',
         methods=["PUT", "POST"], endpoint='autocomplete'
     )
    -@login_required
    +@pga_login_required
     def auto_complete(trans_id):
         """
         This method implements the autocomplete feature.
    @@ -1923,7 +1924,7 @@ def auto_complete(trans_id):
     
     
     @blueprint.route("/sqleditor.js")
    -@login_required
    +@pga_login_required
     def script():
         """render the required javascript"""
         return Response(
    @@ -1939,7 +1940,7 @@ def script():
     
     
     @blueprint.route('/load_file/', methods=["PUT", "POST"], endpoint='load_file')
    -@login_required
    +@pga_login_required
     def load_file():
         """
         This function gets name of file from request data
    @@ -1993,7 +1994,7 @@ def load_file():
     
     
     @blueprint.route('/save_file/', methods=["PUT", "POST"], endpoint='save_file')
    -@login_required
    +@pga_login_required
     def save_file():
         """
         This function retrieves file_name and data from request.
    @@ -2072,7 +2073,7 @@ def get_file_encoding_of_loaded_file(file_name):
         methods=["POST"],
         endpoint='query_tool_download'
     )
    -@login_required
    +@pga_login_required
     def start_query_download_tool(trans_id):
         (status, error_msg, sync_conn, trans_obj,
          session_obj) = check_transaction_status(trans_id)
    @@ -2151,7 +2152,7 @@ def start_query_download_tool(trans_id):
         methods=["GET"],
         endpoint='connection_status'
     )
    -@login_required
    +@pga_login_required
     def query_tool_status(trans_id):
         """
         The task of this function to return the status of the current connection
    @@ -2208,7 +2209,7 @@ def query_tool_status(trans_id):
         '/filter_dialog/<int:trans_id>',
         methods=["GET"], endpoint='get_filter_data'
     )
    -@login_required
    +@pga_login_required
     def get_filter_data(trans_id):
         """
         This method is used to get all the columns for data sorting dialog.
    @@ -2227,7 +2228,7 @@ def get_filter_data(trans_id):
         '/get_server_connection/<int:sgid>/<int:sid>',
         methods=["GET"], endpoint='_check_server_connection_status'
     )
    -@login_required
    +@pga_login_required
     def _check_server_connection_status(sgid, sid=None):
         """
         This function returns the server connection details
    @@ -2275,7 +2276,7 @@ def _check_server_connection_status(sgid, sid=None):
         '/new_connection_dialog',
         methods=["GET"], endpoint='get_new_connection_servers'
     )
    -@login_required
    +@pga_login_required
     def get_new_connection_data(sgid=None, sid=None):
         """
         This method is used to get required data for get new connection.
    @@ -2331,7 +2332,7 @@ def get_new_connection_data(sgid=None, sid=None):
         '/new_connection_database/<int:sgid>/<int:sid>',
         methods=["GET"], endpoint='get_new_connection_database'
     )
    -@login_required
    +@pga_login_required
     def get_new_connection_database(sgid, sid=None):
         """
         This method is used to get required data for get new connection.
    @@ -2412,7 +2413,7 @@ def get_new_connection_database(sgid, sid=None):
         '/new_connection_user/<int:sgid>/<int:sid>',
         methods=["GET"], endpoint='get_new_connection_user'
     )
    -@login_required
    +@pga_login_required
     def get_new_connection_user(sgid, sid=None):
         """
         This method is used to get required data for get new connection.
    @@ -2478,7 +2479,7 @@ def get_new_connection_user(sgid, sid=None):
         '/new_connection_role/<int:sgid>/<int:sid>',
         methods=["GET"], endpoint='get_new_connection_role'
     )
    -@login_required
    +@pga_login_required
     def get_new_connection_role(sgid, sid=None):
         """
         This method is used to get required data for get new connection.
    @@ -2543,7 +2544,7 @@ def get_new_connection_role(sgid, sid=None):
         methods=["POST"],
         endpoint="connect_server"
     )
    -@login_required
    +@pga_login_required
     def connect_server(sid):
         # Check if server is already connected then no need to reconnect again.
         server = Server.query.filter_by(id=sid).first()
    @@ -2568,7 +2569,7 @@ def connect_server(sid):
         '/filter_dialog/<int:trans_id>',
         methods=["PUT"], endpoint='set_filter_data'
     )
    -@login_required
    +@pga_login_required
     def set_filter_data(trans_id):
         """
         This method is used to update the columns for data sorting dialog.
    @@ -2591,7 +2592,7 @@ def set_filter_data(trans_id):
         '/query_history/<int:trans_id>',
         methods=["POST"], endpoint='add_query_history'
     )
    -@login_required
    +@pga_login_required
     def add_query_history(trans_id):
         """
         This method adds to query history for user/server/database
    @@ -2617,7 +2618,7 @@ def add_query_history(trans_id):
         '/query_history/<int:trans_id>',
         methods=["DELETE"], endpoint='clear_query_history'
     )
    -@login_required
    +@pga_login_required
     def clear_query_history(trans_id):
         """
         This method returns clears history for user/server/database
    @@ -2637,7 +2638,7 @@ def clear_query_history(trans_id):
         '/query_history/<int:trans_id>',
         methods=["GET"], endpoint='get_query_history'
     )
    -@login_required
    +@pga_login_required
     def get_query_history(trans_id):
         """
         This method returns query history for user/server/database
    @@ -2660,7 +2661,7 @@ def get_query_history(trans_id):
         '/get_macros/<int:macro_id>/<int:trans_id>',
         methods=["GET"], endpoint='get_macro'
     )
    -@login_required
    +@pga_login_required
     def macros(trans_id, macro_id=None, json_resp=True):
         """
         This method is used to get all the columns for data sorting dialog.
    @@ -2679,7 +2680,7 @@ def macros(trans_id, macro_id=None, json_resp=True):
         '/set_macros/<int:trans_id>',
         methods=["PUT"], endpoint='set_macros'
     )
    -@login_required
    +@pga_login_required
     def update_macros(trans_id):
         """
         This method is used to get all the columns for data sorting dialog.
    
  • web/pgadmin/tools/sqleditor/utils/macros.py+2 1 modified
    @@ -12,7 +12,8 @@
     import json
     from flask_babel import gettext
     from flask import current_app, request
    -from flask_security import login_required, current_user
    +from pgadmin.user_login_check import pga_login_required
    +from flask_security import current_user
     from pgadmin.utils.ajax import make_response as ajax_response,\
         make_json_response
     from pgadmin.model import db, Macros, UserMacros
    
  • web/pgadmin/tools/user_management/__init__.py+5 4 modified
    @@ -13,7 +13,8 @@
     from flask import render_template, request, \
         Response, abort, current_app, session
     from flask_babel import gettext as _
    -from flask_security import login_required, roles_required, current_user
    +from flask_security import roles_required, current_user
    +from pgadmin.user_login_check import pga_login_required
     from flask_security.utils import hash_password
     from werkzeug.exceptions import InternalServerError
     
    @@ -73,13 +74,13 @@ def get_exposed_url_endpoints(self):
     
     
     @blueprint.route("/")
    -@login_required
    +@pga_login_required
     def index():
         return bad_request(errormsg=_("This URL cannot be called directly."))
     
     
     @blueprint.route("/user_management.js")
    -@login_required
    +@pga_login_required
     def script():
         """render own javascript"""
         return Response(
    @@ -95,7 +96,7 @@ def script():
     
     @blueprint.route("/current_user.js")
     @pgCSRFProtect.exempt
    -@login_required
    +@pga_login_required
     def current_user_info():
         return Response(
             response=render_template(
    
  • web/pgadmin/user_login_check.py+24 0 added
    @@ -0,0 +1,24 @@
    +##########################################################################
    +#
    +# pgAdmin 4 - PostgreSQL Tools
    +#
    +# Copyright (C) 2013 - 2024, The pgAdmin Development Team
    +# This software is released under the PostgreSQL Licence
    +#
    +##########################################################################
    +
    +"""Implements pgAdmin4 User validity."""
    +
    +from functools import wraps
    +from flask_security import login_required
    +
    +
    +def pga_login_required(func):
    +    import pgadmin.authenticate.mfa.utils as mfa_utils
    +
    +    @wraps(func)
    +    @mfa_utils.mfa_required
    +    def wrapper(*args, **kwargs):
    +        return func(*args, **kwargs)
    +
    +    return wrapper
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

6

News mentions

0

No linked articles in our index yet.