auth-plugins: remove the in-object cache that cauused invalidation failures.

We use now proper dogepile cache which gets purged on settings change.
This commit is contained in:
RhodeCode Admin 2023-02-02 09:42:19 +01:00
parent 83e86c7943
commit 159c758565
2 changed files with 47 additions and 39 deletions

View file

@ -18,14 +18,17 @@
# RhodeCode Enterprise Edition, including its added features, Support services,
# and proprietary license terms, please see https://rhodecode.com/licenses/
import time
import logging
from pyramid.exceptions import ConfigurationError
from zope.interface import implementer
from rhodecode.authentication.interface import IAuthnPluginRegistry
from rhodecode.lib.utils2 import safe_str
from rhodecode.model.settings import SettingsModel
from rhodecode.lib.utils2 import safe_str
from rhodecode.lib.statsd_client import StatsdClient
from rhodecode.lib import rc_cache
log = logging.getLogger(__name__)
@ -38,7 +41,6 @@ class AuthenticationPluginRegistry(object):
def __init__(self, settings):
self._plugins = {}
self._plugins_for_auth = None
self._fallback_plugin = settings.get(self.fallback_plugin_key, None)
def add_authn_plugin(self, config, plugin):
@ -64,44 +66,56 @@ class AuthenticationPluginRegistry(object):
if plugin.uid == plugin_uid:
return plugin
def invalidate_plugins_for_auth(self):
log.debug('Invalidating cached plugins for authentication')
self._plugins_for_auth = None
def get_plugins_for_authentication(self):
def get_plugins_for_authentication(self, cache=True):
"""
Returns a list of plugins which should be consulted when authenticating
a user. It only returns plugins which are enabled and active.
Additionally it includes the fallback plugin from the INI file, if
`rhodecode.auth_plugin_fallback` is set to a plugin ID.
"""
if self._plugins_for_auth is not None:
return self._plugins_for_auth
plugins = []
cache_namespace_uid = 'cache_auth_plugins'
region = rc_cache.get_or_create_region('cache_general', cache_namespace_uid)
# Add all enabled and active plugins to the list. We iterate over the
# auth_plugins setting from DB because it also represents the ordering.
enabled_plugins = SettingsModel().get_auth_plugins()
raw_settings = SettingsModel().get_all_settings(cache=True)
for plugin_id in enabled_plugins:
plugin = self.get_plugin(plugin_id)
if plugin is not None and plugin.is_active(
plugin_cached_settings=raw_settings):
@region.conditional_cache_on_arguments(condition=cache)
def _get_auth_plugins(name, key, fallback_plugin):
plugins = []
# inject settings into plugin, we can re-use the DB fetched settings here
plugin._settings = plugin._propagate_settings(raw_settings)
plugins.append(plugin)
# Add all enabled and active plugins to the list. We iterate over the
# auth_plugins setting from DB because it also represents the ordering.
enabled_plugins = SettingsModel().get_auth_plugins()
raw_settings = SettingsModel().get_all_settings(cache=False)
for plugin_id in enabled_plugins:
plugin = self.get_plugin(plugin_id)
if plugin is not None and plugin.is_active(
plugin_cached_settings=raw_settings):
# Add the fallback plugin from ini file.
if self._fallback_plugin:
log.warn(
'Using fallback authentication plugin from INI file: "%s"',
self._fallback_plugin)
plugin = self.get_plugin(self._fallback_plugin)
if plugin is not None and plugin not in plugins:
plugin._settings = plugin._propagate_settings(raw_settings)
plugins.append(plugin)
# inject settings into plugin, we can re-use the DB fetched settings here
plugin._settings = plugin._propagate_settings(raw_settings)
plugins.append(plugin)
# Add the fallback plugin from ini file.
if fallback_plugin:
log.warn(
'Using fallback authentication plugin from INI file: "%s"',
fallback_plugin)
plugin = self.get_plugin(fallback_plugin)
if plugin is not None and plugin not in plugins:
plugin._settings = plugin._propagate_settings(raw_settings)
plugins.append(plugin)
return plugins
start = time.time()
plugins = _get_auth_plugins('rhodecode_auth_plugins', 'v1', self._fallback_plugin)
compute_time = time.time() - start
log.debug('cached method:%s took %.4fs', _get_auth_plugins.func_name, compute_time)
statsd = StatsdClient.statsd
if statsd:
elapsed_time_ms = round(1000.0 * compute_time) # use ms only
statsd.timing("rhodecode_auth_plugins_timing.histogram", elapsed_time_ms,
use_decimals=False)
return plugins
self._plugins_for_auth = plugins
return self._plugins_for_auth

View file

@ -218,16 +218,9 @@ class SettingsModel(BaseModel):
return region, cache_key
def invalidate_settings_cache(self):
from rhodecode.authentication.base import get_authn_registry
region, cache_key = self.get_cache_region()
log.debug('Invalidation cache region %s for cache_key: %s', region, cache_key)
region.invalidate()
registry = get_current_registry()
if registry:
authn_registry = get_authn_registry(registry)
if authn_registry:
authn_registry.invalidate_plugins_for_auth()
def get_all_settings(self, cache=False, from_request=True):
# defines if we use GLOBAL, or PER_REPO
@ -260,6 +253,7 @@ class SettingsModel(BaseModel):
start = time.time()
result = _get_all_settings('rhodecode_settings', cache_key)
compute_time = time.time() - start
log.debug('cached method:%s took %.4fs', _get_all_settings.func_name, compute_time)
statsd = StatsdClient.statsd
if statsd: