
* rename consent permission Signed-off-by: Jens Langhammer <jens@goauthentik.io> * the user version Signed-off-by: Jens Langhammer <jens@goauthentik.io> t Signed-off-by: Jens Langhammer <jens@goauthentik.io> * initial role Signed-off-by: Jens Langhammer <jens@goauthentik.io> * start form Signed-off-by: Jens Langhammer <jens@goauthentik.io> * some minor table refactoring Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix user, add assign Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add roles ui Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix backend Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add assign API for roles Signed-off-by: Jens Langhammer <jens@goauthentik.io> * start adding toggle buttons Signed-off-by: Jens Langhammer <jens@goauthentik.io> * start view page Signed-off-by: Jens Langhammer <jens@goauthentik.io> * exclude add_ permission for per-object perms Signed-off-by: Jens Langhammer <jens@goauthentik.io> * small cleanup Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add permission list for roles Signed-off-by: Jens Langhammer <jens@goauthentik.io> * make sidebar update Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix page header not re-rendering? Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fixup Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add search Signed-off-by: Jens Langhammer <jens@goauthentik.io> * show first category in table groupBy except when its empty Signed-off-by: Jens Langhammer <jens@goauthentik.io> * make model and object PK optional but required together Signed-off-by: Jens Langhammer <jens@goauthentik.io> * allow for setting global perms Signed-off-by: Jens Langhammer <jens@goauthentik.io> * exclude non-authentik permissions Signed-off-by: Jens Langhammer <jens@goauthentik.io> * exclude models which aren't allowed (base models etc) Signed-off-by: Jens Langhammer <jens@goauthentik.io> * ensure all models have verbose_name set, exclude some more internal objects Signed-off-by: Jens Langhammer <jens@goauthentik.io> * lint fix Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix role perm assign Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add unasign for global perms Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add meta changes Signed-off-by: Jens Langhammer <jens@goauthentik.io> * clear modal state after submit Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add roles to our group Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix duplicate url names Signed-off-by: Jens Langhammer <jens@goauthentik.io> * make recursive group query more usable Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add name field to role itself and move group creation to signal Signed-off-by: Jens Langhammer <jens@goauthentik.io> * start sync Signed-off-by: Jens Langhammer <jens@goauthentik.io> * move rbac stuff to separate django app Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix lint and such Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix go Signed-off-by: Jens Langhammer <jens@goauthentik.io> * update Signed-off-by: Jens Langhammer <jens@goauthentik.io> * start API changes Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add more API tests Signed-off-by: Jens Langhammer <jens@goauthentik.io> * make admin interface not require superuser for now, improve error handling Signed-off-by: Jens Langhammer <jens@goauthentik.io> * replace some IsAdminUser where applicable Signed-off-by: Jens Langhammer <jens@goauthentik.io> * migrate flow inspector perms to actual permission Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix license not being a serializermodel Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add permission modal to models without view page Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add additional permissions to assign/unassign permissions Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add action to unassign user permissions Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add permissions tab to remaining view pages Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix flow inspector permission check Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix codecov config? Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add more API tests Signed-off-by: Jens Langhammer <jens@goauthentik.io> * ensure viewsets have an order set Signed-off-by: Jens Langhammer <jens@goauthentik.io> * hopefully the last api name change Signed-off-by: Jens Langhammer <jens@goauthentik.io> * make perm modal less confusing Signed-off-by: Jens Langhammer <jens@goauthentik.io> * start user view permission page Signed-off-by: Jens Langhammer <jens@goauthentik.io> * only make delete bulk form expandable if usedBy is set Signed-off-by: Jens Langhammer <jens@goauthentik.io> * expand permission tables Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add more things Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add user global permission table Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix lint Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix tests' url names Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add tests for assign perms Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add unassign tests Signed-off-by: Jens Langhammer <jens@goauthentik.io> * rebuild permissions Signed-off-by: Jens Langhammer <jens@goauthentik.io> * prevent assigning/unassigning permissions to internal service accounts Signed-off-by: Jens Langhammer <jens@goauthentik.io> * only enable default api browser in debug Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix role object permissions showing duplicate Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix role link on role object permissions table Signed-off-by: Jens Langhammer <jens@goauthentik.io> * fix object permission modal having duplicate close buttons Signed-off-by: Jens Langhammer <jens@goauthentik.io> * return error if user has no global perm and no object perms also improve error display on table Signed-off-by: Jens Langhammer <jens@goauthentik.io> * small optimisation Signed-off-by: Jens Langhammer <jens@goauthentik.io> * optimise even more Signed-off-by: Jens Langhammer <jens@goauthentik.io> * update locale Signed-off-by: Jens Langhammer <jens@goauthentik.io> * add system permission for non-object permissions Signed-off-by: Jens Langhammer <jens@goauthentik.io> * allow access to admin interface based on perm Signed-off-by: Jens Langhammer <jens@goauthentik.io> * clean Signed-off-by: Jens Langhammer <jens@goauthentik.io> * don't exclude base models Signed-off-by: Jens Langhammer <jens@goauthentik.io> --------- Signed-off-by: Jens Langhammer <jens@goauthentik.io>
135 lines
4.7 KiB
Python
135 lines
4.7 KiB
Python
"""Tasks API"""
|
|
from importlib import import_module
|
|
|
|
from django.contrib import messages
|
|
from django.http.response import Http404
|
|
from django.utils.translation import gettext_lazy as _
|
|
from drf_spectacular.types import OpenApiTypes
|
|
from drf_spectacular.utils import OpenApiParameter, OpenApiResponse, extend_schema
|
|
from rest_framework.decorators import action
|
|
from rest_framework.fields import (
|
|
CharField,
|
|
ChoiceField,
|
|
DateTimeField,
|
|
ListField,
|
|
SerializerMethodField,
|
|
)
|
|
from rest_framework.request import Request
|
|
from rest_framework.response import Response
|
|
from rest_framework.viewsets import ViewSet
|
|
from structlog.stdlib import get_logger
|
|
|
|
from authentik.api.decorators import permission_required
|
|
from authentik.core.api.utils import PassiveSerializer
|
|
from authentik.events.monitored_tasks import TaskInfo, TaskResultStatus
|
|
from authentik.rbac.permissions import HasPermission
|
|
|
|
LOGGER = get_logger()
|
|
|
|
|
|
class TaskSerializer(PassiveSerializer):
|
|
"""Serialize TaskInfo and TaskResult"""
|
|
|
|
task_name = CharField()
|
|
task_description = CharField()
|
|
task_finish_timestamp = DateTimeField(source="finish_time")
|
|
task_duration = SerializerMethodField()
|
|
|
|
status = ChoiceField(
|
|
source="result.status.name",
|
|
choices=[(x.name, x.name) for x in TaskResultStatus],
|
|
)
|
|
messages = ListField(source="result.messages")
|
|
|
|
def get_task_duration(self, instance: TaskInfo) -> int:
|
|
"""Get the duration a task took to run"""
|
|
return max(instance.finish_timestamp - instance.start_timestamp, 0)
|
|
|
|
def to_representation(self, instance: TaskInfo):
|
|
"""When a new version of authentik adds fields to TaskInfo,
|
|
the API will fail with an AttributeError, as the classes
|
|
are pickled in cache. In that case, just delete the info"""
|
|
try:
|
|
return super().to_representation(instance)
|
|
# pylint: disable=broad-except
|
|
except Exception: # pragma: no cover
|
|
if isinstance(self.instance, list):
|
|
for inst in self.instance:
|
|
inst.delete()
|
|
else:
|
|
self.instance.delete()
|
|
return {}
|
|
|
|
|
|
class TaskViewSet(ViewSet):
|
|
"""Read-only view set that returns all background tasks"""
|
|
|
|
permission_classes = [HasPermission("authentik_rbac.view_system_tasks")]
|
|
serializer_class = TaskSerializer
|
|
|
|
@extend_schema(
|
|
responses={
|
|
200: TaskSerializer(many=False),
|
|
404: OpenApiResponse(description="Task not found"),
|
|
},
|
|
parameters=[
|
|
OpenApiParameter(
|
|
"id",
|
|
type=OpenApiTypes.STR,
|
|
location=OpenApiParameter.PATH,
|
|
required=True,
|
|
),
|
|
],
|
|
)
|
|
def retrieve(self, request: Request, pk=None) -> Response:
|
|
"""Get a single system task"""
|
|
task = TaskInfo.by_name(pk)
|
|
if not task:
|
|
raise Http404
|
|
return Response(TaskSerializer(task, many=False).data)
|
|
|
|
@extend_schema(responses={200: TaskSerializer(many=True)})
|
|
def list(self, request: Request) -> Response:
|
|
"""List system tasks"""
|
|
tasks = sorted(TaskInfo.all().values(), key=lambda task: task.task_name)
|
|
return Response(TaskSerializer(tasks, many=True).data)
|
|
|
|
@permission_required(None, ["authentik_rbac.run_system_tasks"])
|
|
@extend_schema(
|
|
request=OpenApiTypes.NONE,
|
|
responses={
|
|
204: OpenApiResponse(description="Task retried successfully"),
|
|
404: OpenApiResponse(description="Task not found"),
|
|
500: OpenApiResponse(description="Failed to retry task"),
|
|
},
|
|
parameters=[
|
|
OpenApiParameter(
|
|
"id",
|
|
type=OpenApiTypes.STR,
|
|
location=OpenApiParameter.PATH,
|
|
required=True,
|
|
),
|
|
],
|
|
)
|
|
@action(detail=True, methods=["post"])
|
|
def retry(self, request: Request, pk=None) -> Response:
|
|
"""Retry task"""
|
|
task = TaskInfo.by_name(pk)
|
|
if not task:
|
|
raise Http404
|
|
try:
|
|
task_module = import_module(task.task_call_module)
|
|
task_func = getattr(task_module, task.task_call_func)
|
|
LOGGER.debug("Running task", task=task_func)
|
|
task_func.delay(*task.task_call_args, **task.task_call_kwargs)
|
|
messages.success(
|
|
self.request,
|
|
_("Successfully re-scheduled Task %(name)s!" % {"name": task.task_name}),
|
|
)
|
|
return Response(status=204)
|
|
except (ImportError, AttributeError): # pragma: no cover
|
|
LOGGER.warning("Failed to run task, remove state", task=task)
|
|
# if we get an import error, the module path has probably changed
|
|
task.delete()
|
|
return Response(status=500)
|