restart front
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
This commit is contained in:
		@ -1,3 +1,6 @@
 | 
				
			|||||||
 | 
					from django_filters.filters import BooleanFilter
 | 
				
			||||||
 | 
					from django_filters.filterset import FilterSet
 | 
				
			||||||
 | 
					from rest_framework.fields import ReadOnlyField
 | 
				
			||||||
from rest_framework.mixins import (
 | 
					from rest_framework.mixins import (
 | 
				
			||||||
    ListModelMixin,
 | 
					    ListModelMixin,
 | 
				
			||||||
    RetrieveModelMixin,
 | 
					    RetrieveModelMixin,
 | 
				
			||||||
@ -11,6 +14,9 @@ from authentik.tenants.utils import get_current_tenant
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TaskSerializer(ModelSerializer):
 | 
					class TaskSerializer(ModelSerializer):
 | 
				
			||||||
 | 
					    rel_obj_app_label = ReadOnlyField(source="rel_obj_content_type.app_label")
 | 
				
			||||||
 | 
					    rel_obj_model = ReadOnlyField(source="rel_obj_content_type.model")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    messages = LogEventSerializer(many=True, source="_messages")
 | 
					    messages = LogEventSerializer(many=True, source="_messages")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
@ -21,7 +27,8 @@ class TaskSerializer(ModelSerializer):
 | 
				
			|||||||
            "actor_name",
 | 
					            "actor_name",
 | 
				
			||||||
            "state",
 | 
					            "state",
 | 
				
			||||||
            "mtime",
 | 
					            "mtime",
 | 
				
			||||||
            "rel_obj_content_type",
 | 
					            "rel_obj_app_label",
 | 
				
			||||||
 | 
					            "rel_obj_model",
 | 
				
			||||||
            "rel_obj_id",
 | 
					            "rel_obj_id",
 | 
				
			||||||
            "uid",
 | 
					            "uid",
 | 
				
			||||||
            "messages",
 | 
					            "messages",
 | 
				
			||||||
@ -29,6 +36,23 @@ class TaskSerializer(ModelSerializer):
 | 
				
			|||||||
        ]
 | 
					        ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class TaskFilter(FilterSet):
 | 
				
			||||||
 | 
					    rel_obj_id__isnull = BooleanFilter("rel_obj_id", "isnull")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class Meta:
 | 
				
			||||||
 | 
					        model = Task
 | 
				
			||||||
 | 
					        fields = (
 | 
				
			||||||
 | 
					            "queue_name",
 | 
				
			||||||
 | 
					            "actor_name",
 | 
				
			||||||
 | 
					            "state",
 | 
				
			||||||
 | 
					            "rel_obj_content_type__app_label",
 | 
				
			||||||
 | 
					            "rel_obj_content_type__model",
 | 
				
			||||||
 | 
					            "rel_obj_id",
 | 
				
			||||||
 | 
					            "rel_obj_id__isnull",
 | 
				
			||||||
 | 
					            "aggregated_status",
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TaskViewSet(
 | 
					class TaskViewSet(
 | 
				
			||||||
    RetrieveModelMixin,
 | 
					    RetrieveModelMixin,
 | 
				
			||||||
    ListModelMixin,
 | 
					    ListModelMixin,
 | 
				
			||||||
@ -41,16 +65,16 @@ class TaskViewSet(
 | 
				
			|||||||
        "queue_name",
 | 
					        "queue_name",
 | 
				
			||||||
        "actor_name",
 | 
					        "actor_name",
 | 
				
			||||||
        "state",
 | 
					        "state",
 | 
				
			||||||
 | 
					        "rel_obj_app_label",
 | 
				
			||||||
 | 
					        "rel_obj_model",
 | 
				
			||||||
 | 
					        "rel_obj_id",
 | 
				
			||||||
        "_uid",
 | 
					        "_uid",
 | 
				
			||||||
        "aggregated_status",
 | 
					        "aggregated_status",
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    filterset_fields = (
 | 
					    filterset_class = TaskFilter
 | 
				
			||||||
        "queue_name",
 | 
					 | 
				
			||||||
        "actor_name",
 | 
					 | 
				
			||||||
        "state",
 | 
					 | 
				
			||||||
        "aggregated_status",
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    ordering = ("-mtime",)
 | 
					    ordering = ("-mtime",)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_queryset(self):
 | 
					    def get_queryset(self):
 | 
				
			||||||
        return Task.objects.filter(tenant=get_current_tenant())
 | 
					        return Task.objects.select_related("rel_obj_content_type").filter(
 | 
				
			||||||
 | 
					            tenant=get_current_tenant()
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
				
			|||||||
@ -1,9 +1,12 @@
 | 
				
			|||||||
 | 
					from django_filters.filters import BooleanFilter
 | 
				
			||||||
 | 
					from django_filters.filterset import FilterSet
 | 
				
			||||||
from dramatiq.actor import Actor
 | 
					from dramatiq.actor import Actor
 | 
				
			||||||
from dramatiq.broker import get_broker
 | 
					from dramatiq.broker import get_broker
 | 
				
			||||||
from dramatiq.errors import ActorNotFound
 | 
					from dramatiq.errors import ActorNotFound
 | 
				
			||||||
from drf_spectacular.types import OpenApiTypes
 | 
					from drf_spectacular.types import OpenApiTypes
 | 
				
			||||||
from drf_spectacular.utils import OpenApiResponse, extend_schema
 | 
					from drf_spectacular.utils import OpenApiResponse, extend_schema
 | 
				
			||||||
from rest_framework.decorators import action
 | 
					from rest_framework.decorators import action
 | 
				
			||||||
 | 
					from rest_framework.fields import ReadOnlyField
 | 
				
			||||||
from rest_framework.mixins import (
 | 
					from rest_framework.mixins import (
 | 
				
			||||||
    ListModelMixin,
 | 
					    ListModelMixin,
 | 
				
			||||||
    RetrieveModelMixin,
 | 
					    RetrieveModelMixin,
 | 
				
			||||||
@ -20,19 +23,25 @@ from authentik.tasks.schedules.models import Schedule
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ScheduleSerializer(ModelSerializer):
 | 
					class ScheduleSerializer(ModelSerializer):
 | 
				
			||||||
 | 
					    rel_obj_app_label = ReadOnlyField(source="rel_obj_content_type.app_label")
 | 
				
			||||||
 | 
					    rel_obj_model = ReadOnlyField(source="rel_obj_content_type.model")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    description = SerializerMethodField()
 | 
					    description = SerializerMethodField()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
        model = Schedule
 | 
					        model = Schedule
 | 
				
			||||||
        fields = [
 | 
					        fields = (
 | 
				
			||||||
            "id",
 | 
					            "id",
 | 
				
			||||||
            "uid",
 | 
					            "uid",
 | 
				
			||||||
            "actor_name",
 | 
					            "actor_name",
 | 
				
			||||||
 | 
					            "rel_obj_app_label",
 | 
				
			||||||
 | 
					            "rel_obj_model",
 | 
				
			||||||
 | 
					            "rel_obj_id",
 | 
				
			||||||
            "crontab",
 | 
					            "crontab",
 | 
				
			||||||
            "paused",
 | 
					            "paused",
 | 
				
			||||||
            "next_run",
 | 
					            "next_run",
 | 
				
			||||||
            "description",
 | 
					            "description",
 | 
				
			||||||
        ]
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_description(self, instance: Schedule) -> str | None:
 | 
					    def get_description(self, instance: Schedule) -> str | None:
 | 
				
			||||||
        if instance.rel_obj:
 | 
					        if instance.rel_obj:
 | 
				
			||||||
@ -43,22 +52,48 @@ class ScheduleSerializer(ModelSerializer):
 | 
				
			|||||||
            actor: Actor = get_broker().get_actor(instance.actor_name)
 | 
					            actor: Actor = get_broker().get_actor(instance.actor_name)
 | 
				
			||||||
        except ActorNotFound:
 | 
					        except ActorNotFound:
 | 
				
			||||||
            return "FIXME this shouldn't happen"
 | 
					            return "FIXME this shouldn't happen"
 | 
				
			||||||
 | 
					        if not actor.fn.__doc__:
 | 
				
			||||||
 | 
					            return "no doc"
 | 
				
			||||||
        return actor.fn.__doc__.strip()
 | 
					        return actor.fn.__doc__.strip()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ScheduleFilter(FilterSet):
 | 
				
			||||||
 | 
					    rel_obj_id__isnull = BooleanFilter("rel_obj_id", "isnull")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    class Meta:
 | 
				
			||||||
 | 
					        model = Schedule
 | 
				
			||||||
 | 
					        fields = (
 | 
				
			||||||
 | 
					            "actor_name",
 | 
				
			||||||
 | 
					            "rel_obj_content_type__app_label",
 | 
				
			||||||
 | 
					            "rel_obj_content_type__model",
 | 
				
			||||||
 | 
					            "rel_obj_id",
 | 
				
			||||||
 | 
					            "rel_obj_id__isnull",
 | 
				
			||||||
 | 
					            "paused",
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ScheduleViewSet(
 | 
					class ScheduleViewSet(
 | 
				
			||||||
    RetrieveModelMixin,
 | 
					    RetrieveModelMixin,
 | 
				
			||||||
    UpdateModelMixin,
 | 
					    UpdateModelMixin,
 | 
				
			||||||
    ListModelMixin,
 | 
					    ListModelMixin,
 | 
				
			||||||
    GenericViewSet,
 | 
					    GenericViewSet,
 | 
				
			||||||
):
 | 
					):
 | 
				
			||||||
    queryset = Schedule.objects.all()
 | 
					    queryset = Schedule.objects.select_related("rel_obj_content_type").all()
 | 
				
			||||||
    serializer_class = ScheduleSerializer
 | 
					    serializer_class = ScheduleSerializer
 | 
				
			||||||
    search_fields = (
 | 
					    search_fields = (
 | 
				
			||||||
        "id",
 | 
					        "id",
 | 
				
			||||||
        "uid",
 | 
					        "uid",
 | 
				
			||||||
 | 
					        "actor_name",
 | 
				
			||||||
 | 
					        "rel_obj_content_type__app_label",
 | 
				
			||||||
 | 
					        "rel_obj_content_type__model",
 | 
				
			||||||
 | 
					        "rel_obj_id",
 | 
				
			||||||
 | 
					        "description",
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    filterset_class = ScheduleFilter
 | 
				
			||||||
 | 
					    ordering = (
 | 
				
			||||||
 | 
					        "next_run",
 | 
				
			||||||
 | 
					        "uid",
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    ordering = ("next_run", "uid")
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @permission_required("authentik_tasks_schedules.send_schedule")
 | 
					    @permission_required("authentik_tasks_schedules.send_schedule")
 | 
				
			||||||
    @extend_schema(
 | 
					    @extend_schema(
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					# Generated by Django 5.1.10 on 2025-06-11 12:57
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import pgtrigger.compiler
 | 
				
			||||||
 | 
					import pgtrigger.migrations
 | 
				
			||||||
 | 
					from django.db import migrations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Migration(migrations.Migration):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    dependencies = [
 | 
				
			||||||
 | 
					        ("authentik_tasks_schedules", "0001_initial"),
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    operations = [
 | 
				
			||||||
 | 
					        pgtrigger.migrations.AddTrigger(
 | 
				
			||||||
 | 
					            model_name="schedule",
 | 
				
			||||||
 | 
					            trigger=pgtrigger.compiler.Trigger(
 | 
				
			||||||
 | 
					                name="set_next_run_on_paused",
 | 
				
			||||||
 | 
					                sql=pgtrigger.compiler.UpsertTriggerSql(
 | 
				
			||||||
 | 
					                    condition='WHEN (NEW."paused" AND NOT OLD."paused")',
 | 
				
			||||||
 | 
					                    func="\n                    NEW.next_run = to_timestamp(0);\n                    RETURN NEW;\n                ",
 | 
				
			||||||
 | 
					                    hash="7fe580a86de70723522cfcbac712785984000f92",
 | 
				
			||||||
 | 
					                    operation="UPDATE",
 | 
				
			||||||
 | 
					                    pgid="pgtrigger_set_next_run_on_paused_95c6d",
 | 
				
			||||||
 | 
					                    table="authentik_tasks_schedules_schedule",
 | 
				
			||||||
 | 
					                    when="BEFORE",
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					        ),
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
@ -1,6 +1,7 @@
 | 
				
			|||||||
import pickle  # nosec
 | 
					import pickle  # nosec
 | 
				
			||||||
from uuid import uuid4
 | 
					from uuid import uuid4
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import pgtrigger
 | 
				
			||||||
from cron_converter import Cron
 | 
					from cron_converter import Cron
 | 
				
			||||||
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
 | 
					from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
 | 
				
			||||||
from django.contrib.contenttypes.models import ContentType
 | 
					from django.contrib.contenttypes.models import ContentType
 | 
				
			||||||
@ -55,6 +56,18 @@ class Schedule(SerializerModel):
 | 
				
			|||||||
            ("send_schedule", _("Manually trigger a schedule")),
 | 
					            ("send_schedule", _("Manually trigger a schedule")),
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
        indexes = (models.Index(fields=("rel_obj_content_type", "rel_obj_id")),)
 | 
					        indexes = (models.Index(fields=("rel_obj_content_type", "rel_obj_id")),)
 | 
				
			||||||
 | 
					        triggers = (
 | 
				
			||||||
 | 
					            pgtrigger.Trigger(
 | 
				
			||||||
 | 
					                name="set_next_run_on_paused",
 | 
				
			||||||
 | 
					                operation=pgtrigger.Update,
 | 
				
			||||||
 | 
					                when=pgtrigger.Before,
 | 
				
			||||||
 | 
					                condition=pgtrigger.Q(new__paused=True) & pgtrigger.Q(old__paused=False),
 | 
				
			||||||
 | 
					                func="""
 | 
				
			||||||
 | 
					                    NEW.next_run = to_timestamp(0);
 | 
				
			||||||
 | 
					                    RETURN NEW;
 | 
				
			||||||
 | 
					                """,
 | 
				
			||||||
 | 
					            ),
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def __str__(self):
 | 
					    def __str__(self):
 | 
				
			||||||
        return self.uid
 | 
					        return self.uid
 | 
				
			||||||
 | 
				
			|||||||
@ -15878,6 +15878,14 @@
 | 
				
			|||||||
        "model_authentik_tasks_schedules.schedule": {
 | 
					        "model_authentik_tasks_schedules.schedule": {
 | 
				
			||||||
            "type": "object",
 | 
					            "type": "object",
 | 
				
			||||||
            "properties": {
 | 
					            "properties": {
 | 
				
			||||||
 | 
					                "rel_obj_id": {
 | 
				
			||||||
 | 
					                    "type": [
 | 
				
			||||||
 | 
					                        "string",
 | 
				
			||||||
 | 
					                        "null"
 | 
				
			||||||
 | 
					                    ],
 | 
				
			||||||
 | 
					                    "minLength": 1,
 | 
				
			||||||
 | 
					                    "title": "Rel obj id"
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
                "crontab": {
 | 
					                "crontab": {
 | 
				
			||||||
                    "type": "string",
 | 
					                    "type": "string",
 | 
				
			||||||
                    "minLength": 1,
 | 
					                    "minLength": 1,
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										72
									
								
								schema.yml
									
									
									
									
									
								
							
							
						
						
									
										72
									
								
								schema.yml
									
									
									
									
									
								
							@ -40441,6 +40441,10 @@ paths:
 | 
				
			|||||||
    get:
 | 
					    get:
 | 
				
			||||||
      operationId: tasks_schedules_list
 | 
					      operationId: tasks_schedules_list
 | 
				
			||||||
      parameters:
 | 
					      parameters:
 | 
				
			||||||
 | 
					      - in: query
 | 
				
			||||||
 | 
					        name: actor_name
 | 
				
			||||||
 | 
					        schema:
 | 
				
			||||||
 | 
					          type: string
 | 
				
			||||||
      - name: ordering
 | 
					      - name: ordering
 | 
				
			||||||
        required: false
 | 
					        required: false
 | 
				
			||||||
        in: query
 | 
					        in: query
 | 
				
			||||||
@ -40459,6 +40463,26 @@ paths:
 | 
				
			|||||||
        description: Number of results to return per page.
 | 
					        description: Number of results to return per page.
 | 
				
			||||||
        schema:
 | 
					        schema:
 | 
				
			||||||
          type: integer
 | 
					          type: integer
 | 
				
			||||||
 | 
					      - in: query
 | 
				
			||||||
 | 
					        name: paused
 | 
				
			||||||
 | 
					        schema:
 | 
				
			||||||
 | 
					          type: boolean
 | 
				
			||||||
 | 
					      - in: query
 | 
				
			||||||
 | 
					        name: rel_obj_content_type__app_label
 | 
				
			||||||
 | 
					        schema:
 | 
				
			||||||
 | 
					          type: string
 | 
				
			||||||
 | 
					      - in: query
 | 
				
			||||||
 | 
					        name: rel_obj_content_type__model
 | 
				
			||||||
 | 
					        schema:
 | 
				
			||||||
 | 
					          type: string
 | 
				
			||||||
 | 
					      - in: query
 | 
				
			||||||
 | 
					        name: rel_obj_id
 | 
				
			||||||
 | 
					        schema:
 | 
				
			||||||
 | 
					          type: string
 | 
				
			||||||
 | 
					      - in: query
 | 
				
			||||||
 | 
					        name: rel_obj_id__isnull
 | 
				
			||||||
 | 
					        schema:
 | 
				
			||||||
 | 
					          type: boolean
 | 
				
			||||||
      - name: search
 | 
					      - name: search
 | 
				
			||||||
        required: false
 | 
					        required: false
 | 
				
			||||||
        in: query
 | 
					        in: query
 | 
				
			||||||
@ -40668,6 +40692,22 @@ paths:
 | 
				
			|||||||
        name: queue_name
 | 
					        name: queue_name
 | 
				
			||||||
        schema:
 | 
					        schema:
 | 
				
			||||||
          type: string
 | 
					          type: string
 | 
				
			||||||
 | 
					      - in: query
 | 
				
			||||||
 | 
					        name: rel_obj_content_type__app_label
 | 
				
			||||||
 | 
					        schema:
 | 
				
			||||||
 | 
					          type: string
 | 
				
			||||||
 | 
					      - in: query
 | 
				
			||||||
 | 
					        name: rel_obj_content_type__model
 | 
				
			||||||
 | 
					        schema:
 | 
				
			||||||
 | 
					          type: string
 | 
				
			||||||
 | 
					      - in: query
 | 
				
			||||||
 | 
					        name: rel_obj_id
 | 
				
			||||||
 | 
					        schema:
 | 
				
			||||||
 | 
					          type: string
 | 
				
			||||||
 | 
					      - in: query
 | 
				
			||||||
 | 
					        name: rel_obj_id__isnull
 | 
				
			||||||
 | 
					        schema:
 | 
				
			||||||
 | 
					          type: boolean
 | 
				
			||||||
      - name: search
 | 
					      - name: search
 | 
				
			||||||
        required: false
 | 
					        required: false
 | 
				
			||||||
        in: query
 | 
					        in: query
 | 
				
			||||||
@ -54942,6 +54982,10 @@ components:
 | 
				
			|||||||
    PatchedScheduleRequest:
 | 
					    PatchedScheduleRequest:
 | 
				
			||||||
      type: object
 | 
					      type: object
 | 
				
			||||||
      properties:
 | 
					      properties:
 | 
				
			||||||
 | 
					        rel_obj_id:
 | 
				
			||||||
 | 
					          type: string
 | 
				
			||||||
 | 
					          nullable: true
 | 
				
			||||||
 | 
					          minLength: 1
 | 
				
			||||||
        crontab:
 | 
					        crontab:
 | 
				
			||||||
          type: string
 | 
					          type: string
 | 
				
			||||||
          minLength: 1
 | 
					          minLength: 1
 | 
				
			||||||
@ -58883,6 +58927,16 @@ components:
 | 
				
			|||||||
          type: string
 | 
					          type: string
 | 
				
			||||||
          readOnly: true
 | 
					          readOnly: true
 | 
				
			||||||
          description: Dramatiq actor to call
 | 
					          description: Dramatiq actor to call
 | 
				
			||||||
 | 
					        rel_obj_app_label:
 | 
				
			||||||
 | 
					          type: string
 | 
				
			||||||
 | 
					          readOnly: true
 | 
				
			||||||
 | 
					        rel_obj_model:
 | 
				
			||||||
 | 
					          type: string
 | 
				
			||||||
 | 
					          title: Python model class name
 | 
				
			||||||
 | 
					          readOnly: true
 | 
				
			||||||
 | 
					        rel_obj_id:
 | 
				
			||||||
 | 
					          type: string
 | 
				
			||||||
 | 
					          nullable: true
 | 
				
			||||||
        crontab:
 | 
					        crontab:
 | 
				
			||||||
          type: string
 | 
					          type: string
 | 
				
			||||||
          description: When to schedule tasks
 | 
					          description: When to schedule tasks
 | 
				
			||||||
@ -58903,10 +58957,16 @@ components:
 | 
				
			|||||||
      - description
 | 
					      - description
 | 
				
			||||||
      - id
 | 
					      - id
 | 
				
			||||||
      - next_run
 | 
					      - next_run
 | 
				
			||||||
 | 
					      - rel_obj_app_label
 | 
				
			||||||
 | 
					      - rel_obj_model
 | 
				
			||||||
      - uid
 | 
					      - uid
 | 
				
			||||||
    ScheduleRequest:
 | 
					    ScheduleRequest:
 | 
				
			||||||
      type: object
 | 
					      type: object
 | 
				
			||||||
      properties:
 | 
					      properties:
 | 
				
			||||||
 | 
					        rel_obj_id:
 | 
				
			||||||
 | 
					          type: string
 | 
				
			||||||
 | 
					          nullable: true
 | 
				
			||||||
 | 
					          minLength: 1
 | 
				
			||||||
        crontab:
 | 
					        crontab:
 | 
				
			||||||
          type: string
 | 
					          type: string
 | 
				
			||||||
          minLength: 1
 | 
					          minLength: 1
 | 
				
			||||||
@ -59849,9 +59909,13 @@ components:
 | 
				
			|||||||
          type: string
 | 
					          type: string
 | 
				
			||||||
          format: date-time
 | 
					          format: date-time
 | 
				
			||||||
          description: Task last modified time
 | 
					          description: Task last modified time
 | 
				
			||||||
        rel_obj_content_type:
 | 
					        rel_obj_app_label:
 | 
				
			||||||
          type: integer
 | 
					          type: string
 | 
				
			||||||
          nullable: true
 | 
					          readOnly: true
 | 
				
			||||||
 | 
					        rel_obj_model:
 | 
				
			||||||
 | 
					          type: string
 | 
				
			||||||
 | 
					          title: Python model class name
 | 
				
			||||||
 | 
					          readOnly: true
 | 
				
			||||||
        rel_obj_id:
 | 
					        rel_obj_id:
 | 
				
			||||||
          type: string
 | 
					          type: string
 | 
				
			||||||
          nullable: true
 | 
					          nullable: true
 | 
				
			||||||
@ -59868,6 +59932,8 @@ components:
 | 
				
			|||||||
      - actor_name
 | 
					      - actor_name
 | 
				
			||||||
      - aggregated_status
 | 
					      - aggregated_status
 | 
				
			||||||
      - messages
 | 
					      - messages
 | 
				
			||||||
 | 
					      - rel_obj_app_label
 | 
				
			||||||
 | 
					      - rel_obj_model
 | 
				
			||||||
      - uid
 | 
					      - uid
 | 
				
			||||||
    Tenant:
 | 
					    Tenant:
 | 
				
			||||||
      type: object
 | 
					      type: object
 | 
				
			||||||
 | 
				
			|||||||
@ -16,10 +16,10 @@ export const ROUTES: Route[] = [
 | 
				
			|||||||
        await import("@goauthentik/admin/admin-overview/DashboardUserPage");
 | 
					        await import("@goauthentik/admin/admin-overview/DashboardUserPage");
 | 
				
			||||||
        return html`<ak-admin-dashboard-users></ak-admin-dashboard-users>`;
 | 
					        return html`<ak-admin-dashboard-users></ak-admin-dashboard-users>`;
 | 
				
			||||||
    }),
 | 
					    }),
 | 
				
			||||||
    // new Route(new RegExp("^/administration/system-tasks$"), async () => {
 | 
					    new Route(new RegExp("^/administration/system-tasks$"), async () => {
 | 
				
			||||||
    //     await import("@goauthentik/admin/system-tasks/SystemTaskListPage");
 | 
					        await import("@goauthentik/admin/system-tasks/SystemTasksPage");
 | 
				
			||||||
    //     return html`<ak-system-task-list></ak-system-task-list>`;
 | 
					        return html`<ak-system-tasks></ak-system-tasks>`;
 | 
				
			||||||
    // }),
 | 
					    }),
 | 
				
			||||||
    new Route(new RegExp("^/core/providers$"), async () => {
 | 
					    new Route(new RegExp("^/core/providers$"), async () => {
 | 
				
			||||||
        await import("@goauthentik/admin/providers/ProviderListPage");
 | 
					        await import("@goauthentik/admin/providers/ProviderListPage");
 | 
				
			||||||
        return html`<ak-provider-list></ak-provider-list>`;
 | 
					        return html`<ak-provider-list></ak-provider-list>`;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,8 +1,8 @@
 | 
				
			|||||||
 | 
					import { formatElapsedTime } from "#common/temporal";
 | 
				
			||||||
import "@goauthentik/admin/system-tasks/ScheduleForm";
 | 
					import "@goauthentik/admin/system-tasks/ScheduleForm";
 | 
				
			||||||
import "@goauthentik/admin/system-tasks/TaskList";
 | 
					import "@goauthentik/admin/system-tasks/TaskList";
 | 
				
			||||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
 | 
					import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
 | 
				
			||||||
import { EVENT_REFRESH } from "@goauthentik/common/constants";
 | 
					import { EVENT_REFRESH } from "@goauthentik/common/constants";
 | 
				
			||||||
import { getRelativeTime } from "@goauthentik/common/utils";
 | 
					 | 
				
			||||||
import "@goauthentik/elements/buttons/ActionButton";
 | 
					import "@goauthentik/elements/buttons/ActionButton";
 | 
				
			||||||
import "@goauthentik/elements/buttons/SpinnerButton";
 | 
					import "@goauthentik/elements/buttons/SpinnerButton";
 | 
				
			||||||
import "@goauthentik/elements/forms/DeleteBulkForm";
 | 
					import "@goauthentik/elements/forms/DeleteBulkForm";
 | 
				
			||||||
@ -31,16 +31,42 @@ export class ScheduleList extends Table<Schedule> {
 | 
				
			|||||||
    @property()
 | 
					    @property()
 | 
				
			||||||
    order = "next_run";
 | 
					    order = "next_run";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @property()
 | 
				
			||||||
 | 
					    relObjAppLabel?: string;
 | 
				
			||||||
 | 
					    @property()
 | 
				
			||||||
 | 
					    relObjModel?: string;
 | 
				
			||||||
 | 
					    @property()
 | 
				
			||||||
 | 
					    relObjId?: string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @property()
 | 
				
			||||||
 | 
					    showOnlyStandalone: boolean = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    static get styles(): CSSResult[] {
 | 
					    static get styles(): CSSResult[] {
 | 
				
			||||||
        return super.styles.concat(PFDescriptionList);
 | 
					        return super.styles.concat(PFDescriptionList);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async apiEndpoint(): Promise<PaginatedResponse<Schedule>> {
 | 
					    async apiEndpoint(): Promise<PaginatedResponse<Schedule>> {
 | 
				
			||||||
 | 
					        const relObjIdIsnull =
 | 
				
			||||||
 | 
					            typeof this.relObjId !== "undefined"
 | 
				
			||||||
 | 
					                ? undefined
 | 
				
			||||||
 | 
					                : this.showOnlyStandalone
 | 
				
			||||||
 | 
					                  ? true
 | 
				
			||||||
 | 
					                  : undefined;
 | 
				
			||||||
        return new TasksApi(DEFAULT_CONFIG).tasksSchedulesList({
 | 
					        return new TasksApi(DEFAULT_CONFIG).tasksSchedulesList({
 | 
				
			||||||
            ...(await this.defaultEndpointConfig()),
 | 
					            ...(await this.defaultEndpointConfig()),
 | 
				
			||||||
 | 
					            relObjContentTypeAppLabel: this.relObjAppLabel,
 | 
				
			||||||
 | 
					            relObjContentTypeModel: this.relObjModel,
 | 
				
			||||||
 | 
					            relObjId: this.relObjId,
 | 
				
			||||||
 | 
					            relObjIdIsnull,
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #toggleShowOnlyStandalone = () => {
 | 
				
			||||||
 | 
					        this.showOnlyStandalone = !this.showOnlyStandalone;
 | 
				
			||||||
 | 
					        this.page = 1;
 | 
				
			||||||
 | 
					        return this.fetch();
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    columns(): TableColumn[] {
 | 
					    columns(): TableColumn[] {
 | 
				
			||||||
        return [
 | 
					        return [
 | 
				
			||||||
            new TableColumn(msg("Schedule"), "actor_name"),
 | 
					            new TableColumn(msg("Schedule"), "actor_name"),
 | 
				
			||||||
@ -50,6 +76,35 @@ export class ScheduleList extends Table<Schedule> {
 | 
				
			|||||||
        ];
 | 
					        ];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    renderToolbarAfter(): TemplateResult {
 | 
				
			||||||
 | 
					        if (this.relObjId !== undefined) {
 | 
				
			||||||
 | 
					            return html``;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return html` 
 | 
				
			||||||
 | 
					            <div class="pf-c-toolbar__group pf-m-filter-group">
 | 
				
			||||||
 | 
					                <div class="pf-c-toolbar__item pf-m-search-filter">
 | 
				
			||||||
 | 
					                    <div class="pf-c-input-group">
 | 
				
			||||||
 | 
					                        <label class="pf-c-switch">
 | 
				
			||||||
 | 
					                            <input
 | 
				
			||||||
 | 
					                                class="pf-c-switch__input"
 | 
				
			||||||
 | 
					                                type="checkbox"
 | 
				
			||||||
 | 
					                                ?checked=${this.showOnlyStandalone}
 | 
				
			||||||
 | 
					                                @change=${this.#toggleShowOnlyStandalone}
 | 
				
			||||||
 | 
					                            />
 | 
				
			||||||
 | 
					                            <span class="pf-c-switch__toggle">
 | 
				
			||||||
 | 
					                                <span class="pf-c-switch__toggle-icon">
 | 
				
			||||||
 | 
					                                    <i class="fas fa-check" aria - hidden="true"> </i>
 | 
				
			||||||
 | 
					                                </span>
 | 
				
			||||||
 | 
					                            </span>
 | 
				
			||||||
 | 
					                            <span class="pf-c-switch__label">
 | 
				
			||||||
 | 
					                                ${msg("Show only standalone schedules")}
 | 
				
			||||||
 | 
					                            </span>
 | 
				
			||||||
 | 
					                        </label>
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            </div>`;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    row(item: Schedule): TemplateResult[] {
 | 
					    row(item: Schedule): TemplateResult[] {
 | 
				
			||||||
        return [
 | 
					        return [
 | 
				
			||||||
            html`<div>${item.description}</div>
 | 
					            html`<div>${item.description}</div>
 | 
				
			||||||
@ -59,7 +114,7 @@ export class ScheduleList extends Table<Schedule> {
 | 
				
			|||||||
                ${item.paused
 | 
					                ${item.paused
 | 
				
			||||||
                    ? html`Paused`
 | 
					                    ? html`Paused`
 | 
				
			||||||
                    : html`
 | 
					                    : html`
 | 
				
			||||||
                          <div>${getRelativeTime(item.nextRun)}</div>
 | 
					                          <div>${formatElapsedTime(item.nextRun)}</div>
 | 
				
			||||||
                          <small>${item.nextRun.toLocaleString()}</small>
 | 
					                          <small>${item.nextRun.toLocaleString()}</small>
 | 
				
			||||||
                      `}
 | 
					                      `}
 | 
				
			||||||
            `,
 | 
					            `,
 | 
				
			||||||
@ -101,7 +156,11 @@ export class ScheduleList extends Table<Schedule> {
 | 
				
			|||||||
        return html` <td role="cell" colspan="3">
 | 
					        return html` <td role="cell" colspan="3">
 | 
				
			||||||
            <div class="pf-c-table__expandable-row-content">
 | 
					            <div class="pf-c-table__expandable-row-content">
 | 
				
			||||||
                <div class="pf-c-content">
 | 
					                <div class="pf-c-content">
 | 
				
			||||||
                    <ak-task-list .schedule=${item}></ak-task-list>
 | 
					                    <ak-task-list
 | 
				
			||||||
 | 
					                        .relObjAppLabel="authentik_tasks_schedules"
 | 
				
			||||||
 | 
					                        .relObjModel="schedule"
 | 
				
			||||||
 | 
					                        .relObjId="${item.id}"
 | 
				
			||||||
 | 
					                    ></ak-task-list>
 | 
				
			||||||
                </div>
 | 
					                </div>
 | 
				
			||||||
            </div>
 | 
					            </div>
 | 
				
			||||||
        </td>`;
 | 
					        </td>`;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,163 +0,0 @@
 | 
				
			|||||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
 | 
					 | 
				
			||||||
import { EVENT_REFRESH } from "@goauthentik/common/constants";
 | 
					 | 
				
			||||||
import { formatElapsedTime } from "@goauthentik/common/temporal";
 | 
					 | 
				
			||||||
import { PFColor } from "@goauthentik/elements/Label";
 | 
					 | 
				
			||||||
import "@goauthentik/elements/buttons/ActionButton";
 | 
					 | 
				
			||||||
import "@goauthentik/elements/buttons/SpinnerButton";
 | 
					 | 
				
			||||||
import "@goauthentik/elements/events/LogViewer";
 | 
					 | 
				
			||||||
import { PaginatedResponse } from "@goauthentik/elements/table/Table";
 | 
					 | 
				
			||||||
import { TableColumn } from "@goauthentik/elements/table/Table";
 | 
					 | 
				
			||||||
import { TablePage } from "@goauthentik/elements/table/TablePage";
 | 
					 | 
				
			||||||
import "@patternfly/elements/pf-tooltip/pf-tooltip.js";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import { msg, str } from "@lit/localize";
 | 
					 | 
				
			||||||
import { CSSResult, TemplateResult, html } from "lit";
 | 
					 | 
				
			||||||
import { customElement, property } from "lit/decorators.js";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import PFDescriptionList from "@patternfly/patternfly/components/DescriptionList/description-list.css";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import { EventsApi, SystemTask, SystemTaskStatusEnum } from "@goauthentik/api";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
@customElement("ak-system-task-list")
 | 
					 | 
				
			||||||
export class SystemTaskListPage extends TablePage<SystemTask> {
 | 
					 | 
				
			||||||
    pageTitle(): string {
 | 
					 | 
				
			||||||
        return msg("System Tasks");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    pageDescription(): string {
 | 
					 | 
				
			||||||
        return msg("Long-running operations which authentik executes in the background.");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    pageIcon(): string {
 | 
					 | 
				
			||||||
        return "pf-icon pf-icon-automation";
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    expandable = true;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    searchEnabled(): boolean {
 | 
					 | 
				
			||||||
        return true;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @property()
 | 
					 | 
				
			||||||
    order = "name";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    static get styles(): CSSResult[] {
 | 
					 | 
				
			||||||
        return super.styles.concat(PFDescriptionList);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    async apiEndpoint(): Promise<PaginatedResponse<SystemTask>> {
 | 
					 | 
				
			||||||
        return new EventsApi(DEFAULT_CONFIG).eventsSystemTasksList(
 | 
					 | 
				
			||||||
            await this.defaultEndpointConfig(),
 | 
					 | 
				
			||||||
        );
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    columns(): TableColumn[] {
 | 
					 | 
				
			||||||
        return [
 | 
					 | 
				
			||||||
            new TableColumn(msg("Identifier"), "name"),
 | 
					 | 
				
			||||||
            new TableColumn(msg("Description")),
 | 
					 | 
				
			||||||
            new TableColumn(msg("Last run")),
 | 
					 | 
				
			||||||
            new TableColumn(msg("Status"), "status"),
 | 
					 | 
				
			||||||
            new TableColumn(msg("Actions")),
 | 
					 | 
				
			||||||
        ];
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    taskStatus(task: SystemTask): TemplateResult {
 | 
					 | 
				
			||||||
        switch (task.status) {
 | 
					 | 
				
			||||||
            case SystemTaskStatusEnum.Successful:
 | 
					 | 
				
			||||||
                return html`<ak-label color=${PFColor.Green}>${msg("Successful")}</ak-label>`;
 | 
					 | 
				
			||||||
            case SystemTaskStatusEnum.Warning:
 | 
					 | 
				
			||||||
                return html`<ak-label color=${PFColor.Orange}>${msg("Warning")}</ak-label>`;
 | 
					 | 
				
			||||||
            case SystemTaskStatusEnum.Error:
 | 
					 | 
				
			||||||
                return html`<ak-label color=${PFColor.Red}>${msg("Error")}</ak-label>`;
 | 
					 | 
				
			||||||
            default:
 | 
					 | 
				
			||||||
                return html`<ak-label color=${PFColor.Grey}>${msg("Unknown")}</ak-label>`;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    renderExpanded(item: SystemTask): TemplateResult {
 | 
					 | 
				
			||||||
        return html` <td role="cell" colspan="3">
 | 
					 | 
				
			||||||
                <div class="pf-c-table__expandable-row-content">
 | 
					 | 
				
			||||||
                    <dl class="pf-c-description-list pf-m-horizontal">
 | 
					 | 
				
			||||||
                        <div class="pf-c-description-list__group">
 | 
					 | 
				
			||||||
                            <dt class="pf-c-description-list__term">
 | 
					 | 
				
			||||||
                                <span class="pf-c-description-list__text">${msg("Duration")}</span>
 | 
					 | 
				
			||||||
                            </dt>
 | 
					 | 
				
			||||||
                            <dd class="pf-c-description-list__description">
 | 
					 | 
				
			||||||
                                <div class="pf-c-description-list__text">
 | 
					 | 
				
			||||||
                                    ${msg(str`${item.duration.toFixed(2)} seconds`)}
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </dd>
 | 
					 | 
				
			||||||
                        </div>
 | 
					 | 
				
			||||||
                        <div class="pf-c-description-list__group">
 | 
					 | 
				
			||||||
                            <dt class="pf-c-description-list__term">
 | 
					 | 
				
			||||||
                                <span class="pf-c-description-list__text">${msg("Expiry")}</span>
 | 
					 | 
				
			||||||
                            </dt>
 | 
					 | 
				
			||||||
                            <dd class="pf-c-description-list__description">
 | 
					 | 
				
			||||||
                                <div class="pf-c-description-list__text">
 | 
					 | 
				
			||||||
                                    ${item.expiring
 | 
					 | 
				
			||||||
                                        ? html`
 | 
					 | 
				
			||||||
                                              <pf-tooltip
 | 
					 | 
				
			||||||
                                                  position="top"
 | 
					 | 
				
			||||||
                                                  content=${(
 | 
					 | 
				
			||||||
                                                      item.expires || new Date()
 | 
					 | 
				
			||||||
                                                  ).toLocaleString()}
 | 
					 | 
				
			||||||
                                              >
 | 
					 | 
				
			||||||
                                                  ${formatElapsedTime(item.expires || new Date())}
 | 
					 | 
				
			||||||
                                              </pf-tooltip>
 | 
					 | 
				
			||||||
                                          `
 | 
					 | 
				
			||||||
                                        : msg("-")}
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </dd>
 | 
					 | 
				
			||||||
                        </div>
 | 
					 | 
				
			||||||
                        <div class="pf-c-description-list__group">
 | 
					 | 
				
			||||||
                            <dt class="pf-c-description-list__term">
 | 
					 | 
				
			||||||
                                <span class="pf-c-description-list__text">${msg("Messages")}</span>
 | 
					 | 
				
			||||||
                            </dt>
 | 
					 | 
				
			||||||
                            <dd class="pf-c-description-list__description">
 | 
					 | 
				
			||||||
                                <div class="pf-c-description-list__text">
 | 
					 | 
				
			||||||
                                    <ak-log-viewer .logs=${item?.messages}></ak-log-viewer>
 | 
					 | 
				
			||||||
                                </div>
 | 
					 | 
				
			||||||
                            </dd>
 | 
					 | 
				
			||||||
                        </div>
 | 
					 | 
				
			||||||
                    </dl>
 | 
					 | 
				
			||||||
                </div>
 | 
					 | 
				
			||||||
            </td>
 | 
					 | 
				
			||||||
            <td></td>
 | 
					 | 
				
			||||||
            <td></td>`;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    row(item: SystemTask): TemplateResult[] {
 | 
					 | 
				
			||||||
        return [
 | 
					 | 
				
			||||||
            html`<pre>${item.name}${item.uid ? `:${item.uid}` : ""}</pre>`,
 | 
					 | 
				
			||||||
            html`${item.description}`,
 | 
					 | 
				
			||||||
            html`<div>${formatElapsedTime(item.finishTimestamp)}</div>
 | 
					 | 
				
			||||||
                <small>${item.finishTimestamp.toLocaleString()}</small>`,
 | 
					 | 
				
			||||||
            this.taskStatus(item),
 | 
					 | 
				
			||||||
            html`<ak-action-button
 | 
					 | 
				
			||||||
                class="pf-m-plain"
 | 
					 | 
				
			||||||
                .apiRequest=${() => {
 | 
					 | 
				
			||||||
                    return new EventsApi(DEFAULT_CONFIG)
 | 
					 | 
				
			||||||
                        .eventsSystemTasksRunCreate({
 | 
					 | 
				
			||||||
                            uuid: item.uuid,
 | 
					 | 
				
			||||||
                        })
 | 
					 | 
				
			||||||
                        .then(() => {
 | 
					 | 
				
			||||||
                            this.dispatchEvent(
 | 
					 | 
				
			||||||
                                new CustomEvent(EVENT_REFRESH, {
 | 
					 | 
				
			||||||
                                    bubbles: true,
 | 
					 | 
				
			||||||
                                    composed: true,
 | 
					 | 
				
			||||||
                                }),
 | 
					 | 
				
			||||||
                            );
 | 
					 | 
				
			||||||
                        });
 | 
					 | 
				
			||||||
                }}
 | 
					 | 
				
			||||||
            >
 | 
					 | 
				
			||||||
                <pf-tooltip position="top" content=${msg("Restart task")}>
 | 
					 | 
				
			||||||
                    <i class="fas fa-redo" aria-hidden="true"></i>
 | 
					 | 
				
			||||||
                </pf-tooltip>
 | 
					 | 
				
			||||||
            </ak-action-button>`,
 | 
					 | 
				
			||||||
        ];
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
declare global {
 | 
					 | 
				
			||||||
    interface HTMLElementTagNameMap {
 | 
					 | 
				
			||||||
        "ak-system-task-list": SystemTaskListPage;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@ -62,7 +62,7 @@ export class SystemTasksPage extends AKElement {
 | 
				
			|||||||
                </section>
 | 
					                </section>
 | 
				
			||||||
                <section
 | 
					                <section
 | 
				
			||||||
                    slot="page-tasks"
 | 
					                    slot="page-tasks"
 | 
				
			||||||
                    data-tab-title="${msg("One-off tasks")}"
 | 
					                    data-tab-title="${msg("Tasks")}"
 | 
				
			||||||
                    class="pf-c-page__main-section pf-m-no-padding-mobile"
 | 
					                    class="pf-c-page__main-section pf-m-no-padding-mobile"
 | 
				
			||||||
                >
 | 
					                >
 | 
				
			||||||
                    <div class="pf-l-grid pf-m-gutter">
 | 
					                    <div class="pf-l-grid pf-m-gutter">
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
 | 
					import { formatElapsedTime } from "#common/temporal";
 | 
				
			||||||
import "@goauthentik/admin/rbac/ObjectPermissionModal";
 | 
					import "@goauthentik/admin/rbac/ObjectPermissionModal";
 | 
				
			||||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
 | 
					import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
 | 
				
			||||||
import { getRelativeTime } from "@goauthentik/common/utils";
 | 
					 | 
				
			||||||
import { PFColor } from "@goauthentik/elements/Label";
 | 
					import { PFColor } from "@goauthentik/elements/Label";
 | 
				
			||||||
import "@goauthentik/elements/buttons/SpinnerButton";
 | 
					import "@goauthentik/elements/buttons/SpinnerButton";
 | 
				
			||||||
import "@goauthentik/elements/events/LogViewer";
 | 
					import "@goauthentik/elements/events/LogViewer";
 | 
				
			||||||
@ -16,7 +16,7 @@ import { customElement, property } from "lit/decorators.js";
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import PFDescriptionList from "@patternfly/patternfly/components/DescriptionList/description-list.css";
 | 
					import PFDescriptionList from "@patternfly/patternfly/components/DescriptionList/description-list.css";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { Schedule, Task, TasksApi, TasksTasksListStateEnum } from "@goauthentik/api";
 | 
					import { Task, TasksApi, TasksTasksListStateEnum } from "@goauthentik/api";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@customElement("ak-task-list")
 | 
					@customElement("ak-task-list")
 | 
				
			||||||
export class TaskList extends Table<Task> {
 | 
					export class TaskList extends Table<Task> {
 | 
				
			||||||
@ -24,7 +24,14 @@ export class TaskList extends Table<Task> {
 | 
				
			|||||||
    clearOnRefresh = true;
 | 
					    clearOnRefresh = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property()
 | 
					    @property()
 | 
				
			||||||
    schedule: Schedule | undefined;
 | 
					    relObjAppLabel?: string;
 | 
				
			||||||
 | 
					    @property()
 | 
				
			||||||
 | 
					    relObjModel?: string;
 | 
				
			||||||
 | 
					    @property()
 | 
				
			||||||
 | 
					    relObjId?: string;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @property()
 | 
				
			||||||
 | 
					    showOnlyStandalone: boolean = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    searchEnabled(): boolean {
 | 
					    searchEnabled(): boolean {
 | 
				
			||||||
        return true;
 | 
					        return true;
 | 
				
			||||||
@ -38,14 +45,27 @@ export class TaskList extends Table<Task> {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async apiEndpoint(): Promise<PaginatedResponse<Task>> {
 | 
					    async apiEndpoint(): Promise<PaginatedResponse<Task>> {
 | 
				
			||||||
        const excludeScheduled = this.schedule === undefined;
 | 
					        const relObjIdIsnull =
 | 
				
			||||||
 | 
					            typeof this.relObjId !== "undefined"
 | 
				
			||||||
 | 
					                ? undefined
 | 
				
			||||||
 | 
					                : this.showOnlyStandalone
 | 
				
			||||||
 | 
					                  ? true
 | 
				
			||||||
 | 
					                  : undefined;
 | 
				
			||||||
        return new TasksApi(DEFAULT_CONFIG).tasksTasksList({
 | 
					        return new TasksApi(DEFAULT_CONFIG).tasksTasksList({
 | 
				
			||||||
            ...(await this.defaultEndpointConfig()),
 | 
					            ...(await this.defaultEndpointConfig()),
 | 
				
			||||||
            excludeScheduled: excludeScheduled,
 | 
					            relObjContentTypeAppLabel: this.relObjAppLabel,
 | 
				
			||||||
            scheduleUid: this.schedule?.uid,
 | 
					            relObjContentTypeModel: this.relObjModel,
 | 
				
			||||||
 | 
					            relObjId: this.relObjId,
 | 
				
			||||||
 | 
					            relObjIdIsnull,
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    #toggleShowOnlyStandalone = () => {
 | 
				
			||||||
 | 
					        this.showOnlyStandalone = !this.showOnlyStandalone;
 | 
				
			||||||
 | 
					        this.page = 1;
 | 
				
			||||||
 | 
					        return this.fetch();
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    columns(): TableColumn[] {
 | 
					    columns(): TableColumn[] {
 | 
				
			||||||
        return [
 | 
					        return [
 | 
				
			||||||
            new TableColumn(msg("Task"), "actor_name"),
 | 
					            new TableColumn(msg("Task"), "actor_name"),
 | 
				
			||||||
@ -56,6 +76,37 @@ export class TaskList extends Table<Task> {
 | 
				
			|||||||
        ];
 | 
					        ];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    renderToolbarAfter(): TemplateResult {
 | 
				
			||||||
 | 
					        console.log("task show standalone");
 | 
				
			||||||
 | 
					        console.log(this.showOnlyStandalone);
 | 
				
			||||||
 | 
					        if (this.relObjId !== undefined) {
 | 
				
			||||||
 | 
					            return html``;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return html` 
 | 
				
			||||||
 | 
					            <div class="pf-c-toolbar__group pf-m-filter-group">
 | 
				
			||||||
 | 
					                <div class="pf-c-toolbar__item pf-m-search-filter">
 | 
				
			||||||
 | 
					                    <div class="pf-c-input-group">
 | 
				
			||||||
 | 
					                        <label class="pf-c-switch">
 | 
				
			||||||
 | 
					                            <input
 | 
				
			||||||
 | 
					                                class="pf-c-switch__input"
 | 
				
			||||||
 | 
					                                type="checkbox"
 | 
				
			||||||
 | 
					                                ?checked=${this.showOnlyStandalone}
 | 
				
			||||||
 | 
					                                @change=${this.#toggleShowOnlyStandalone}
 | 
				
			||||||
 | 
					                            />
 | 
				
			||||||
 | 
					                            <span class="pf-c-switch__toggle">
 | 
				
			||||||
 | 
					                                <span class="pf-c-switch__toggle-icon">
 | 
				
			||||||
 | 
					                                    <i class="fas fa-check" aria - hidden="true"> </i>
 | 
				
			||||||
 | 
					                                </span>
 | 
				
			||||||
 | 
					                            </span>
 | 
				
			||||||
 | 
					                            <span class="pf-c-switch__label">
 | 
				
			||||||
 | 
					                                ${msg("Show only standalone tasks")}
 | 
				
			||||||
 | 
					                            </span>
 | 
				
			||||||
 | 
					                        </label>
 | 
				
			||||||
 | 
					                    </div>
 | 
				
			||||||
 | 
					                </div>
 | 
				
			||||||
 | 
					            </div>`;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    taskState(task: Task): TemplateResult {
 | 
					    taskState(task: Task): TemplateResult {
 | 
				
			||||||
        switch (task.state) {
 | 
					        switch (task.state) {
 | 
				
			||||||
            case TasksTasksListStateEnum.Queued:
 | 
					            case TasksTasksListStateEnum.Queued:
 | 
				
			||||||
@ -74,9 +125,9 @@ export class TaskList extends Table<Task> {
 | 
				
			|||||||
    row(item: Task): TemplateResult[] {
 | 
					    row(item: Task): TemplateResult[] {
 | 
				
			||||||
        return [
 | 
					        return [
 | 
				
			||||||
            html`<div>${item.actorName}</div>
 | 
					            html`<div>${item.actorName}</div>
 | 
				
			||||||
                <small>${item.uid}</small>`,
 | 
					                <small>${item.uid.replace(new RegExp("^authentik."), "")}</small>`,
 | 
				
			||||||
            html`${item.queueName}`,
 | 
					            html`${item.queueName}`,
 | 
				
			||||||
            html`<div>${getRelativeTime(item.mtime)}</div>
 | 
					            html`<div>${formatElapsedTime(item.mtime || new Date())}</div>
 | 
				
			||||||
                <small>${item.mtime.toLocaleString()}</small>`,
 | 
					                <small>${item.mtime.toLocaleString()}</small>`,
 | 
				
			||||||
            this.taskState(item),
 | 
					            this.taskState(item),
 | 
				
			||||||
            html``,
 | 
					            html``,
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user