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 # pylint: disable=unused-argument
def user_stages(context: RequestContext) -> List[UIUserSettings]: def user_stages(context: RequestContext) -> List[UIUserSettings]:
"""Return list of all stages which apply to user""" """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] = [] matching_stages: List[UIUserSettings] = []
for stage in _all_stages: for stage in _all_stages:
user_settings = stage.ui_user_settings user_settings = stage.ui_user_settings(context)
if not user_settings: if not user_settings:
continue continue
matching_stages.append(user_settings) matching_stages.append(user_settings)

View file

@ -13,5 +13,5 @@ class PassbookFlowsConfig(AppConfig):
verbose_name = "passbook Flows" verbose_name = "passbook Flows"
def ready(self): def ready(self):
"""Load policy cache clearing signals""" """Flow signals that clear the cache"""
import_module("passbook.flows.signals") 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 django.utils.translation import gettext_lazy as _
from model_utils.managers import InheritanceManager from model_utils.managers import InheritanceManager
from structlog import get_logger from structlog import get_logger
from django.template.context import RequestContext
from passbook.core.types import UIUserSettings from passbook.core.types import UIUserSettings
from passbook.lib.utils.reflection import class_to_path from passbook.lib.utils.reflection import class_to_path
@ -15,6 +16,13 @@ from passbook.policies.models import PolicyBindingModel
LOGGER = get_logger() 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): class FlowDesignation(models.TextChoices):
"""Designation of what a Flow should be used for. At a later point, this """Designation of what a Flow should be used for. At a later point, this
should be replaced by a database entry.""" should be replaced by a database entry."""
@ -25,7 +33,7 @@ class FlowDesignation(models.TextChoices):
ENROLLMENT = "enrollment" ENROLLMENT = "enrollment"
UNRENOLLMENT = "unenrollment" UNRENOLLMENT = "unenrollment"
RECOVERY = "recovery" RECOVERY = "recovery"
PASSWORD_CHANGE = "password_change" # nosec # noqa USER_SETTINGS = "user_settings"
class Stage(models.Model): class Stage(models.Model):
@ -40,8 +48,8 @@ class Stage(models.Model):
type = "" type = ""
form = "" form = ""
@property @staticmethod
def ui_user_settings(self) -> Optional[UIUserSettings]: def ui_user_settings(context: RequestContext) -> Optional[UIUserSettings]:
"""Entrypoint to integrate with User settings. Can either return None if no """Entrypoint to integrate with User settings. Can either return None if no
user settings are available, or an instanace of UIUserSettings.""" user settings are available, or an instanace of UIUserSettings."""
return None return None

View file

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

View file

@ -36,11 +36,6 @@ urlpatterns = [
ToDefaultFlow.as_view(designation=FlowDesignation.UNRENOLLMENT), ToDefaultFlow.as_view(designation=FlowDesignation.UNRENOLLMENT),
name="default-unenrollment", 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("b/<slug:flow_slug>/", FlowExecutorView.as_view(), name="flow-executor"),
path( path(
"<slug:flow_slug>/", FlowExecutorShellView.as_view(), name="flow-executor-shell" "<slug:flow_slug>/", FlowExecutorShellView.as_view(), name="flow-executor-shell"