core: cache applications API

This commit is contained in:
Jens Langhammer 2021-01-16 22:27:36 +01:00
parent 60f52f102a
commit aad3b43ac3
4 changed files with 24 additions and 7 deletions

View file

@ -9,6 +9,7 @@ from structlog.stdlib import get_logger
from authentik.admin.forms.overview import FlowCacheClearForm, PolicyCacheClearForm
from authentik.admin.mixins import AdminRequiredMixin
from authentik.core.api.applications import user_app_cache_key
LOGGER = get_logger()
@ -26,6 +27,9 @@ class PolicyCacheClearView(AdminRequiredMixin, SuccessMessageMixin, FormView):
keys = cache.keys("policy_*")
cache.delete_many(keys)
LOGGER.debug("Cleared Policy cache", keys=len(keys))
# Also delete user application cache
keys = user_app_cache_key("*")
cache.delete_many(keys)
return super().post(request, *args, **kwargs)

View file

@ -1,4 +1,5 @@
"""Application API Views"""
from django.core.cache import cache
from django.db.models import QuerySet
from django.http.response import Http404
from guardian.shortcuts import get_objects_for_user
@ -18,6 +19,11 @@ from authentik.events.models import EventAction
from authentik.policies.engine import PolicyEngine
def user_app_cache_key(user_pk: str) -> str:
"""Cache key where application list for user is saved"""
return f"user_app_cache_{user_pk}"
class ApplicationSerializer(ModelSerializer):
"""Application Serializer"""
@ -72,12 +78,15 @@ class ApplicationViewSet(ModelViewSet):
"""Custom list method that checks Policy based access instead of guardian"""
queryset = self._filter_queryset_for_list(self.get_queryset())
self.paginate_queryset(queryset)
allowed_applications = []
for application in queryset:
engine = PolicyEngine(application, self.request.user, self.request)
engine.build()
if engine.passing:
allowed_applications.append(application)
allowed_applications = cache.get(user_app_cache_key(self.request.user.pk))
if not allowed_applications:
allowed_applications = []
for application in queryset:
engine = PolicyEngine(application, self.request.user, self.request)
engine.build()
if engine.passing:
allowed_applications.append(application)
cache.set(user_app_cache_key(self.request.user.pk), allowed_applications)
serializer = self.get_serializer(allowed_applications, many=True)
return self.get_paginated_response(serializer.data)

View file

@ -20,7 +20,6 @@ UPDATE_TRIGGERING_MODELS = (
@receiver(post_save)
# pylint: disable=unused-argument
def post_save_update(sender, instance: Model, **_):
"""If an Outpost is saved, Ensure that token is created/updated

View file

@ -4,6 +4,8 @@ from django.db.models.signals import post_save
from django.dispatch import receiver
from structlog.stdlib import get_logger
from authentik.core.api.applications import user_app_cache_key
LOGGER = get_logger()
@ -23,3 +25,6 @@ def invalidate_policy_cache(sender, instance, **_):
total += len(keys)
cache.delete_many(keys)
LOGGER.debug("Invalidating policy cache", policy=instance, keys=total)
# Also delete user application cache
keys = user_app_cache_key("*")
cache.delete_many(keys)