flows: Stage ui_user_settings -> staticmethod with context as argument

This commit is contained in:
Jens Langhammer 2020-06-28 10:31:26 +02:00
parent 8c36ab89e8
commit 9d03c4c7d2
5 changed files with 26 additions and 20 deletions

View File

@ -16,10 +16,10 @@ register = template.Library()
# pylint: disable=unused-argument
def user_stages(context: RequestContext) -> List[UIUserSettings]:
"""Return list of all stages which apply to user"""
_all_stages: Iterable[Stage] = Stage.objects.all().select_subclasses()
_all_stages: Iterable[Stage] = Stage.__subclasses__()
matching_stages: List[UIUserSettings] = []
for stage in _all_stages:
user_settings = stage.ui_user_settings
user_settings = stage.ui_user_settings(context)
if not user_settings:
continue
matching_stages.append(user_settings)

View File

@ -13,5 +13,5 @@ class PassbookFlowsConfig(AppConfig):
verbose_name = "passbook Flows"
def ready(self):
"""Load policy cache clearing signals"""
"""Flow signals that clear the cache"""
import_module("passbook.flows.signals")

View File

@ -7,6 +7,7 @@ from django.http import HttpRequest
from django.utils.translation import gettext_lazy as _
from model_utils.managers import InheritanceManager
from structlog import get_logger
from django.template.context import RequestContext
from passbook.core.types import UIUserSettings
from passbook.lib.utils.reflection import class_to_path
@ -15,6 +16,13 @@ from passbook.policies.models import PolicyBindingModel
LOGGER = get_logger()
class NotConfiguredAction(models.TextChoices):
"""Decides how the FlowExecutor should proceed when a stage isn't configured"""
SKIP = "skip"
# CONFIGURE = "configure"
class FlowDesignation(models.TextChoices):
"""Designation of what a Flow should be used for. At a later point, this
should be replaced by a database entry."""
@ -25,7 +33,7 @@ class FlowDesignation(models.TextChoices):
ENROLLMENT = "enrollment"
UNRENOLLMENT = "unenrollment"
RECOVERY = "recovery"
PASSWORD_CHANGE = "password_change" # nosec # noqa
USER_SETTINGS = "user_settings"
class Stage(models.Model):
@ -40,8 +48,8 @@ class Stage(models.Model):
type = ""
form = ""
@property
def ui_user_settings(self) -> Optional[UIUserSettings]:
@staticmethod
def ui_user_settings(context: RequestContext) -> Optional[UIUserSettings]:
"""Entrypoint to integrate with User settings. Can either return None if no
user settings are available, or an instanace of UIUserSettings."""
return None

View File

@ -7,6 +7,12 @@ from structlog import get_logger
LOGGER = get_logger()
def delete_cache_prefix(prefix: str) -> int:
"""Delete keys prefixed with `prefix` and return count of deleted keys."""
keys = cache.keys(prefix)
cache.delete_many(keys)
return len(keys)
@receiver(post_save)
# pylint: disable=unused-argument
def invalidate_flow_cache(sender, instance, **_):
@ -15,17 +21,14 @@ def invalidate_flow_cache(sender, instance, **_):
from passbook.flows.planner import cache_key
if isinstance(instance, Flow):
LOGGER.debug("Invalidating Flow cache", flow=instance)
cache.delete(f"{cache_key(instance)}*")
total = delete_cache_prefix(f"{cache_key(instance)}*")
LOGGER.debug("Invalidating Flow cache", flow=instance, len=total)
if isinstance(instance, FlowStageBinding):
LOGGER.debug("Invalidating Flow cache from FlowStageBinding", binding=instance)
cache.delete(f"{cache_key(instance.flow)}*")
total = delete_cache_prefix(f"{cache_key(instance.flow)}*")
LOGGER.debug("Invalidating Flow cache from FlowStageBinding", binding=instance, len=total)
if isinstance(instance, Stage):
LOGGER.debug("Invalidating Flow cache from Stage", stage=instance)
total = 0
for binding in FlowStageBinding.objects.filter(stage=instance):
prefix = cache_key(binding.flow)
keys = cache.keys(f"{prefix}*")
total += len(keys)
cache.delete_many(keys)
LOGGER.debug("Deleted keys", len=total)
total += delete_cache_prefix(f"{prefix}*")
LOGGER.debug("Invalidating Flow cache from Stage", stage=instance, len=total)

View File

@ -36,11 +36,6 @@ urlpatterns = [
ToDefaultFlow.as_view(designation=FlowDesignation.UNRENOLLMENT),
name="default-unenrollment",
),
path(
"-/default/password_change/",
ToDefaultFlow.as_view(designation=FlowDesignation.PASSWORD_CHANGE),
name="default-password-change",
),
path("b/<slug:flow_slug>/", FlowExecutorView.as_view(), name="flow-executor"),
path(
"<slug:flow_slug>/", FlowExecutorShellView.as_view(), name="flow-executor-shell"