Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 12 additions & 10 deletions web/pgadmin/authenticate/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"""External Authentication Registry."""


import config
from pgadmin.utils.dynamic_registry import create_registry_metaclass


Expand All @@ -19,20 +20,21 @@ def load_modules(cls, app=None):
from . import internal as module
submodules.append(module)

from . import kerberos as module
submodules.append(module)
if config.SERVER_MODE:
from . import kerberos as module
submodules.append(module)

from . import ldap as module
submodules.append(module)
from . import ldap as module
submodules.append(module)

from . import mfa as module
submodules.append(module)
from . import mfa as module
submodules.append(module)

from . import oauth2 as module
submodules.append(module)
from . import oauth2 as module
submodules.append(module)

from . import webserver as module
submodules.append(module)
from . import webserver as module
submodules.append(module)

for module in submodules:
if "init_app" in module.__dict__.keys():
Expand Down
135 changes: 135 additions & 0 deletions web/pgadmin/authenticate/tests/test_auth_gating.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2026, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################

import sys
import unittest
import config
from pgadmin.authenticate.registry import AuthSourceRegistry


class TestAuthSourceRegistryGating(unittest.TestCase):
"""
Test suite for SERVER_MODE gating of external authentication providers in
AuthSourceRegistry.
"""

def setUp(self):
self._orig_server_mode = config.SERVER_MODE
if AuthSourceRegistry._registry:
self._orig_registry = dict(AuthSourceRegistry._registry)
else:
self._orig_registry = {}

if AuthSourceRegistry._objects:
self._orig_objects = dict(AuthSourceRegistry._objects)
else:
self._orig_objects = {}

def tearDown(self):
config.SERVER_MODE = self._orig_server_mode
AuthSourceRegistry._registry = self._orig_registry
AuthSourceRegistry._objects = self._orig_objects

def _unload_external_auth_modules(self):
external_modules = [
'pgadmin.authenticate.kerberos',
'pgadmin.authenticate.ldap',
'pgadmin.authenticate.mfa',
'pgadmin.authenticate.oauth2',
'pgadmin.authenticate.webserver',
]
for mod in external_modules:
sys.modules.pop(mod, None)

def _reset_registry(self):
self._unload_external_auth_modules()
AuthSourceRegistry._registry = dict()
AuthSourceRegistry._objects = dict()

if 'pgadmin.authenticate.internal' in sys.modules:
internal_module = sys.modules['pgadmin.authenticate.internal']
if hasattr(internal_module, 'InternalAuthentication'):
AuthSourceRegistry._registry['internal'] = (
internal_module.InternalAuthentication
)

def test_desktop_mode_gating(self):
"""
Verify that in desktop mode (SERVER_MODE = False), external
authentication provider modules are not imported or registered.
"""
config.SERVER_MODE = False
self._reset_registry()

AuthSourceRegistry.load_modules()

registry_keys = list(AuthSourceRegistry._registry.keys())

# Desktop mode must load 'internal' authentication
self.assertIn('internal', registry_keys)

# External providers must NOT be registered in desktop mode
self.assertNotIn('kerberos', registry_keys)
self.assertNotIn('ldap', registry_keys)
self.assertNotIn('oauth2', registry_keys)
self.assertNotIn('webserver', registry_keys)

# Verify external modules were NOT imported into sys.modules
self.assertNotIn('pgadmin.authenticate.kerberos', sys.modules)
self.assertNotIn('pgadmin.authenticate.ldap', sys.modules)
self.assertNotIn('pgadmin.authenticate.mfa', sys.modules)
self.assertNotIn('pgadmin.authenticate.oauth2', sys.modules)
self.assertNotIn('pgadmin.authenticate.webserver', sys.modules)

def test_server_mode_loading(self):
"""
Verify that in server mode (SERVER_MODE = True), external
authentication provider modules are imported and registered.
"""
config.SERVER_MODE = True
self._reset_registry()

# Dummy Flask-like app stub for init_app if called
class MockLoginManager:
logout_view = None

class MockApp:
def __init__(self):
self.login_manager = MockLoginManager()

def register_blueprint(self, *args, **kwargs):
pass

def register_logout_hook(self, *args, **kwargs):
pass

class Logger:
def warning(self, *args, **kwargs):
pass

logger = Logger()

app = MockApp()
AuthSourceRegistry.load_modules(app)

registry_keys = list(AuthSourceRegistry._registry.keys())

# Server mode must load all providers
self.assertIn('internal', registry_keys)
self.assertIn('kerberos', registry_keys)
self.assertIn('ldap', registry_keys)
self.assertIn('oauth2', registry_keys)
self.assertIn('webserver', registry_keys)

# Verify external modules WERE imported into sys.modules
self.assertIn('pgadmin.authenticate.kerberos', sys.modules)
self.assertIn('pgadmin.authenticate.ldap', sys.modules)
self.assertIn('pgadmin.authenticate.mfa', sys.modules)
self.assertIn('pgadmin.authenticate.oauth2', sys.modules)
self.assertIn('pgadmin.authenticate.webserver', sys.modules)
Loading