flows: add API to clear cache

Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
Jens Langhammer 2021-03-23 10:37:41 +01:00
parent b6d797fc78
commit 6961089425
8 changed files with 76 additions and 89 deletions

View file

@ -1,20 +0,0 @@
{% extends base_template|default:"generic/form.html" %}
{% load authentik_utils %}
{% load i18n %}
{% block above_form %}
<h1>
{% trans form.title %}
</h1>
{% endblock %}
{% block beneath_form %}
<p>
{% trans form.body %}
</p>
{% endblock %}
{% block action %}
{% trans 'Confirm' %}
{% endblock %}

View file

@ -10,7 +10,6 @@ from authentik.admin.views import (
groups,
outposts,
outposts_service_connections,
overview,
policies,
policies_bindings,
property_mappings,
@ -25,16 +24,6 @@ from authentik.admin.views import (
from authentik.providers.saml.views.metadata import MetadataImportView
urlpatterns = [
path(
"overview/cache/flow/",
overview.FlowCacheClearView.as_view(),
name="overview-clear-flow-cache",
),
path(
"overview/cache/policy/",
overview.PolicyCacheClearView.as_view(),
name="overview-clear-policy-cache",
),
# Applications
path(
"applications/create/",

View file

@ -1,47 +0,0 @@
"""authentik administration overview"""
from django.contrib.messages.views import SuccessMessageMixin
from django.core.cache import cache
from django.http.request import HttpRequest
from django.http.response import HttpResponse
from django.utils.translation import gettext as _
from django.views.generic import FormView
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()
class PolicyCacheClearView(AdminRequiredMixin, SuccessMessageMixin, FormView):
"""View to clear Policy cache"""
form_class = PolicyCacheClearForm
success_url = "/"
template_name = "generic/form_non_model.html"
success_message = _("Successfully cleared Policy cache")
def post(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
keys = cache.keys("policy_*")
cache.delete_many(keys)
LOGGER.debug("Cleared Policy cache", keys=len(keys))
# Also delete user application cache
keys = cache.keys(user_app_cache_key("*"))
cache.delete_many(keys)
return super().post(request, *args, **kwargs)
class FlowCacheClearView(AdminRequiredMixin, SuccessMessageMixin, FormView):
"""View to clear Flow cache"""
form_class = FlowCacheClearForm
success_url = "/"
template_name = "generic/form_non_model.html"
success_message = _("Successfully cleared Flow cache")
def post(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
keys = cache.keys("flow_*")
cache.delete_many(keys)
LOGGER.debug("Cleared flow cache", keys=len(keys))
return super().post(request, *args, **kwargs)

View file

@ -3,10 +3,10 @@ from dataclasses import dataclass
from django.core.cache import cache
from django.db.models import Model
from django.http.response import JsonResponse
from django.http.response import HttpResponseBadRequest, JsonResponse
from django.shortcuts import get_object_or_404
from drf_yasg2 import openapi
from drf_yasg2.utils import swagger_auto_schema
from drf_yasg2.utils import no_body, swagger_auto_schema, unset
from guardian.shortcuts import get_objects_for_user
from rest_framework.decorators import action
from rest_framework.exceptions import PermissionDenied
@ -19,6 +19,7 @@ from rest_framework.serializers import (
SerializerMethodField,
)
from rest_framework.viewsets import ModelViewSet
from structlog.stdlib import get_logger
from authentik.core.api.utils import CacheSerializer
from authentik.flows.models import Flow
@ -26,6 +27,8 @@ from authentik.flows.planner import cache_key
from authentik.flows.transfer.common import DataclassEncoder
from authentik.flows.transfer.exporter import FlowExporter
LOGGER = get_logger()
class FlowSerializer(ModelSerializer):
"""Flow Serializer"""
@ -88,10 +91,24 @@ class FlowViewSet(ModelViewSet):
@swagger_auto_schema(responses={200: CacheSerializer(many=False)})
@action(detail=False)
def cached(self, request: Request) -> Response:
def cache_info(self, request: Request) -> Response:
"""Info about cached flows"""
return Response(data={"count": len(cache.keys("flow_*"))})
@swagger_auto_schema(
request_body=no_body,
responses={204: "Successfully cleared cache", 400: "Bad request"},
)
@action(detail=False, methods=["POST"])
def cache_clear(self, request: Request) -> Response:
"""Clear flow cache"""
if not request.user.is_superuser:
return HttpResponseBadRequest()
keys = cache.keys("flow_*")
cache.delete_many(keys)
LOGGER.debug("Cleared flow cache", keys=len(keys))
return Response(status=204)
@swagger_auto_schema(
responses={
"200": openapi.Response(

View file

@ -1,8 +1,9 @@
"""policy API Views"""
from django.core.cache import cache
from django.core.exceptions import ObjectDoesNotExist
from django.http.response import HttpResponseBadRequest
from django.urls import reverse
from drf_yasg2.utils import swagger_auto_schema
from drf_yasg2.utils import no_body, swagger_auto_schema
from rest_framework import mixins
from rest_framework.decorators import action
from rest_framework.request import Request
@ -13,7 +14,9 @@ from rest_framework.serializers import (
SerializerMethodField,
)
from rest_framework.viewsets import GenericViewSet, ModelViewSet
from structlog.stdlib import get_logger
from authentik.core.api.applications import user_app_cache_key
from authentik.core.api.utils import (
CacheSerializer,
MetaNameSerializer,
@ -23,6 +26,8 @@ from authentik.lib.templatetags.authentik_utils import verbose_name
from authentik.lib.utils.reflection import all_subclasses
from authentik.policies.models import Policy, PolicyBinding, PolicyBindingModel
LOGGER = get_logger()
class PolicyBindingModelForeignKey(PrimaryKeyRelatedField):
"""rest_framework PrimaryKeyRelatedField which resolves
@ -139,10 +144,27 @@ class PolicyViewSet(
@swagger_auto_schema(responses={200: CacheSerializer(many=False)})
@action(detail=False)
def cached(self, request: Request) -> Response:
def cache_info(self, request: Request) -> Response:
"""Info about cached policies"""
return Response(data={"count": len(cache.keys("policy_*"))})
@swagger_auto_schema(
request_body=no_body,
responses={204: "Successfully cleared cache", 400: "Bad request"},
)
@action(detail=False, methods=["POST"])
def cache_clear(self, request: Request) -> Response:
"""Clear policy cache"""
if not request.user.is_superuser:
return HttpResponseBadRequest()
keys = cache.keys("policy_*")
cache.delete_many(keys)
LOGGER.debug("Cleared Policy cache", keys=len(keys))
# Also delete user application cache
keys = cache.keys(user_app_cache_key("*"))
cache.delete_many(keys)
return Response(status=204)
class PolicyBindingSerializer(ModelSerializer):
"""PolicyBinding Serializer"""

View file

@ -2878,9 +2878,22 @@ paths:
tags:
- flows
parameters: []
/flows/instances/cached/:
/flows/instances/cache_clear/:
post:
operationId: flows_instances_cache_clear
description: Clear flow cache
parameters: []
responses:
'204':
description: Successfully cleared cache
'400':
description: Bad request
tags:
- flows
parameters: []
/flows/instances/cache_info/:
get:
operationId: flows_instances_cached
operationId: flows_instances_cache_info
description: Info about cached flows
parameters:
- name: flow_uuid
@ -4116,9 +4129,22 @@ paths:
tags:
- policies
parameters: []
/policies/all/cached/:
/policies/all/cache_clear/:
post:
operationId: policies_all_cache_clear
description: Clear policy cache
parameters: []
responses:
'204':
description: Successfully cleared cache
'400':
description: Bad request
tags:
- policies
parameters: []
/policies/all/cache_info/:
get:
operationId: policies_all_cached
operationId: policies_all_cache_info
description: Info about cached policies
parameters:
- name: bindings__isnull

View file

@ -9,7 +9,7 @@ import { DEFAULT_CONFIG } from "../../../api/Config";
export class FlowCacheStatusCard extends AdminStatusCard<number> {
getPrimaryValue(): Promise<number> {
return new FlowsApi(DEFAULT_CONFIG).flowsInstancesCached({}).then((value) => {
return new FlowsApi(DEFAULT_CONFIG).flowsInstancesCacheInfo({}).then((value) => {
return value.count || 0;
});
}

View file

@ -10,7 +10,7 @@ import { DEFAULT_CONFIG } from "../../../api/Config";
export class PolicyCacheStatusCard extends AdminStatusCard<number> {
getPrimaryValue(): Promise<number> {
return new PoliciesApi(DEFAULT_CONFIG).policiesAllCached({}).then((value) => {
return new PoliciesApi(DEFAULT_CONFIG).policiesAllCacheInfo({}).then((value) => {
return value.count || 0;
});
}