diff --git a/authentik/core/api/applications.py b/authentik/core/api/applications.py index 8acf6f78b..ffc1c1e74 100644 --- a/authentik/core/api/applications.py +++ b/authentik/core/api/applications.py @@ -29,6 +29,7 @@ from structlog.stdlib import get_logger from authentik.admin.api.metrics import CoordinateSerializer, get_events_per_1h from authentik.api.decorators import permission_required from authentik.core.api.providers import ProviderSerializer +from authentik.core.api.used_by import UsedByMixin from authentik.core.models import Application, User from authentik.events.models import EventAction from authentik.policies.api.exec import PolicyTestResultSerializer @@ -73,7 +74,7 @@ class ApplicationSerializer(ModelSerializer): } -class ApplicationViewSet(ModelViewSet): +class ApplicationViewSet(UsedByMixin, ModelViewSet): """Application Viewset""" queryset = Application.objects.all() diff --git a/authentik/core/api/authenticated_sessions.py b/authentik/core/api/authenticated_sessions.py index c3cdb69a7..55989fa04 100644 --- a/authentik/core/api/authenticated_sessions.py +++ b/authentik/core/api/authenticated_sessions.py @@ -11,6 +11,7 @@ from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import GenericViewSet from ua_parser import user_agent_parser +from authentik.core.api.used_by import UsedByMixin from authentik.core.models import AuthenticatedSession from authentik.events.geo import GEOIP_READER, GeoIPDict @@ -92,6 +93,7 @@ class AuthenticatedSessionSerializer(ModelSerializer): class AuthenticatedSessionViewSet( mixins.RetrieveModelMixin, mixins.DestroyModelMixin, + UsedByMixin, mixins.ListModelMixin, GenericViewSet, ): diff --git a/authentik/core/api/groups.py b/authentik/core/api/groups.py index de30d1ee4..d003d9fd2 100644 --- a/authentik/core/api/groups.py +++ b/authentik/core/api/groups.py @@ -5,6 +5,7 @@ from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet from rest_framework_guardian.filters import ObjectPermissionsFilter +from authentik.core.api.used_by import UsedByMixin from authentik.core.api.utils import is_dict from authentik.core.models import Group @@ -20,7 +21,7 @@ class GroupSerializer(ModelSerializer): fields = ["pk", "name", "is_superuser", "parent", "users", "attributes"] -class GroupViewSet(ModelViewSet): +class GroupViewSet(UsedByMixin, ModelViewSet): """Group Viewset""" queryset = Group.objects.all() diff --git a/authentik/core/api/propertymappings.py b/authentik/core/api/propertymappings.py index 4eff31150..2593dc089 100644 --- a/authentik/core/api/propertymappings.py +++ b/authentik/core/api/propertymappings.py @@ -14,6 +14,7 @@ from rest_framework.serializers import ModelSerializer, SerializerMethodField from rest_framework.viewsets import GenericViewSet from authentik.api.decorators import permission_required +from authentik.core.api.used_by import UsedByMixin from authentik.core.api.utils import ( MetaNameSerializer, PassiveSerializer, @@ -65,6 +66,7 @@ class PropertyMappingSerializer(ManagedSerializer, ModelSerializer, MetaNameSeri class PropertyMappingViewSet( mixins.RetrieveModelMixin, mixins.DestroyModelMixin, + UsedByMixin, mixins.ListModelMixin, GenericViewSet, ): diff --git a/authentik/core/api/providers.py b/authentik/core/api/providers.py index 86e210736..3c489e641 100644 --- a/authentik/core/api/providers.py +++ b/authentik/core/api/providers.py @@ -9,6 +9,7 @@ from rest_framework.response import Response from rest_framework.serializers import ModelSerializer, SerializerMethodField from rest_framework.viewsets import GenericViewSet +from authentik.core.api.used_by import UsedByMixin from authentik.core.api.utils import MetaNameSerializer, TypeCreateSerializer from authentik.core.models import Provider from authentik.lib.utils.reflection import all_subclasses @@ -48,6 +49,7 @@ class ProviderSerializer(ModelSerializer, MetaNameSerializer): class ProviderViewSet( mixins.RetrieveModelMixin, mixins.DestroyModelMixin, + UsedByMixin, mixins.ListModelMixin, GenericViewSet, ): diff --git a/authentik/core/api/sources.py b/authentik/core/api/sources.py index 4ee717ed3..97f966cf9 100644 --- a/authentik/core/api/sources.py +++ b/authentik/core/api/sources.py @@ -10,6 +10,7 @@ from rest_framework.serializers import ModelSerializer, SerializerMethodField from rest_framework.viewsets import GenericViewSet from structlog.stdlib import get_logger +from authentik.core.api.used_by import UsedByMixin from authentik.core.api.utils import MetaNameSerializer, TypeCreateSerializer from authentik.core.models import Source from authentik.core.types import UserSettingSerializer @@ -52,6 +53,7 @@ class SourceSerializer(ModelSerializer, MetaNameSerializer): class SourceViewSet( mixins.RetrieveModelMixin, mixins.DestroyModelMixin, + UsedByMixin, mixins.ListModelMixin, GenericViewSet, ): diff --git a/authentik/core/api/tokens.py b/authentik/core/api/tokens.py index 9ef14ac9b..10d74ec6b 100644 --- a/authentik/core/api/tokens.py +++ b/authentik/core/api/tokens.py @@ -9,6 +9,7 @@ from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet from authentik.api.decorators import permission_required +from authentik.core.api.used_by import UsedByMixin from authentik.core.api.users import UserSerializer from authentik.core.api.utils import PassiveSerializer from authentik.core.models import Token, TokenIntents @@ -43,7 +44,7 @@ class TokenViewSerializer(PassiveSerializer): key = CharField(read_only=True) -class TokenViewSet(ModelViewSet): +class TokenViewSet(UsedByMixin, ModelViewSet): """Token Viewset""" lookup_field = "identifier" diff --git a/authentik/core/api/used_by.py b/authentik/core/api/used_by.py new file mode 100644 index 000000000..b1143d989 --- /dev/null +++ b/authentik/core/api/used_by.py @@ -0,0 +1,102 @@ +"""used_by mixin""" +from enum import Enum +from inspect import getmembers + +from django.db.models.base import Model +from django.db.models.deletion import SET_DEFAULT, SET_NULL +from django.db.models.manager import Manager +from drf_spectacular.utils import extend_schema +from guardian.shortcuts import get_objects_for_user +from rest_framework.decorators import action +from rest_framework.fields import CharField, ChoiceField +from rest_framework.request import Request +from rest_framework.response import Response + +from authentik.core.api.utils import PassiveSerializer + + +class DeleteAction(Enum): + """Which action a delete will have on a used object""" + + CASCADE = "cascade" + CASCADE_MANY = "cascade_many" + SET_NULL = "set_null" + SET_DEFAULT = "set_default" + + +class UsedBySerializer(PassiveSerializer): + """A list of all objects referencing the queried object""" + + app = CharField() + model_name = CharField() + pk = CharField() + name = CharField() + action = ChoiceField(choices=[(x.name, x.name) for x in DeleteAction]) + + +def get_delete_action(manager: Manager) -> str: + """Get the delete action from the Foreign key, falls back to cascade""" + if hasattr(manager, "field"): + if manager.field.remote_field.on_delete.__name__ == SET_NULL.__name__: + return DeleteAction.SET_NULL.name + if manager.field.remote_field.on_delete.__name__ == SET_DEFAULT.__name__: + return DeleteAction.SET_DEFAULT.name + if hasattr(manager, "source_field"): + return DeleteAction.CASCADE_MANY.name + return DeleteAction.CASCADE.name + + +class UsedByMixin: + """Mixin to add a used_by endpoint to return a list of all objects using this object""" + + @extend_schema( + responses={200: UsedBySerializer(many=True)}, + ) + @action(detail=True, pagination_class=None, filter_backends=[]) + # pylint: disable=invalid-name, unused-argument, too-many-locals + def used_by(self, request: Request, *args, **kwargs) -> Response: + """Get a list of all objects that use this object""" + # pyright: reportGeneralTypeIssues=false + model: Model = self.get_object() + used_by = [] + shadows = [] + for attr_name, manager in getmembers(model, lambda x: isinstance(x, Manager)): + if attr_name == "objects": # pragma: no cover + continue + manager: Manager + if manager.model._meta.abstract: + continue + app = manager.model._meta.app_label + model_name = manager.model._meta.model_name + delete_action = get_delete_action(manager) + + # To make sure we only apply shadows when there are any objects, + # but so we only apply them once, have a simple flag for the first object + first_object = True + + for obj in get_objects_for_user( + request.user, f"{app}.view_{model_name}", manager + ).all(): + # Only merge shadows on first object + if first_object: + shadows += getattr( + manager.model._meta, "authentik_used_by_shadows", [] + ) + first_object = False + serializer = UsedBySerializer( + data={ + "app": app, + "model_name": model_name, + "pk": str(obj.pk), + "name": str(obj), + "action": delete_action, + } + ) + serializer.is_valid() + used_by.append(serializer.data) + # Check the shadows map and remove anything that should be shadowed + for idx, user in enumerate(used_by): + full_model_name = f"{user['app']}.{user['model_name']}" + if full_model_name in shadows: + del used_by[idx] + return Response(used_by) diff --git a/authentik/core/api/users.py b/authentik/core/api/users.py index 566a8d39a..379958bd5 100644 --- a/authentik/core/api/users.py +++ b/authentik/core/api/users.py @@ -25,6 +25,7 @@ from rest_framework_guardian.filters import ObjectPermissionsFilter from authentik.admin.api.metrics import CoordinateSerializer, get_events_per_1h from authentik.api.decorators import permission_required from authentik.core.api.groups import GroupSerializer +from authentik.core.api.used_by import UsedByMixin from authentik.core.api.utils import LinkSerializer, PassiveSerializer, is_dict from authentik.core.middleware import ( SESSION_IMPERSONATE_ORIGINAL_USER, @@ -131,7 +132,7 @@ class UsersFilter(FilterSet): fields = ["username", "name", "is_active", "is_superuser", "attributes"] -class UserViewSet(ModelViewSet): +class UserViewSet(UsedByMixin, ModelViewSet): """User Viewset""" queryset = User.objects.none() diff --git a/authentik/core/models.py b/authentik/core/models.py index a262fe2b4..677627d64 100644 --- a/authentik/core/models.py +++ b/authentik/core/models.py @@ -5,6 +5,7 @@ from typing import Any, Optional, Type from urllib.parse import urlencode from uuid import uuid4 +import django.db.models.options as options from django.conf import settings from django.contrib.auth.models import AbstractUser from django.contrib.auth.models import UserManager as DjangoUserManager @@ -41,6 +42,9 @@ GRAVATAR_URL = "https://secure.gravatar.com" DEFAULT_AVATAR = static("dist/assets/images/user_default.png") +options.DEFAULT_NAMES = options.DEFAULT_NAMES + ("authentik_used_by_shadows",) + + def default_token_duration(): """Default duration a Token is valid""" return now() + timedelta(minutes=30) diff --git a/authentik/crypto/api.py b/authentik/crypto/api.py index e7b54cb68..a74914404 100644 --- a/authentik/crypto/api.py +++ b/authentik/crypto/api.py @@ -1,10 +1,11 @@ """Crypto API Views""" -import django_filters from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.serialization import load_pem_private_key from cryptography.x509 import load_pem_x509_certificate from django.http.response import HttpResponse from django.utils.translation import gettext_lazy as _ +from django_filters import FilterSet +from django_filters.filters import BooleanFilter from drf_spectacular.types import OpenApiTypes from drf_spectacular.utils import OpenApiParameter, OpenApiResponse, extend_schema from rest_framework.decorators import action @@ -20,6 +21,7 @@ from rest_framework.serializers import ModelSerializer, ValidationError from rest_framework.viewsets import ModelViewSet from authentik.api.decorators import permission_required +from authentik.core.api.used_by import UsedByMixin from authentik.core.api.utils import PassiveSerializer from authentik.crypto.builder import CertificateBuilder from authentik.crypto.models import CertificateKeyPair @@ -100,10 +102,10 @@ class CertificateGenerationSerializer(PassiveSerializer): validity_days = IntegerField(initial=365) -class CertificateKeyPairFilter(django_filters.FilterSet): +class CertificateKeyPairFilter(FilterSet): """Filter for certificates""" - has_key = django_filters.BooleanFilter( + has_key = BooleanFilter( label="Only return certificate-key pairs with keys", method="filter_has_key" ) @@ -117,7 +119,7 @@ class CertificateKeyPairFilter(django_filters.FilterSet): fields = ["name"] -class CertificateKeyPairViewSet(ModelViewSet): +class CertificateKeyPairViewSet(UsedByMixin, ModelViewSet): """CertificateKeyPair Viewset""" queryset = CertificateKeyPair.objects.all() diff --git a/authentik/crypto/tests.py b/authentik/crypto/tests.py index af9764078..22d800651 100644 --- a/authentik/crypto/tests.py +++ b/authentik/crypto/tests.py @@ -4,10 +4,14 @@ import datetime from django.test import TestCase from django.urls import reverse +from authentik.core.api.used_by import DeleteAction from authentik.core.models import User from authentik.crypto.api import CertificateKeyPairSerializer from authentik.crypto.builder import CertificateBuilder from authentik.crypto.models import CertificateKeyPair +from authentik.flows.models import Flow +from authentik.providers.oauth2.generators import generate_client_secret +from authentik.providers.oauth2.models import OAuth2Provider class TestCrypto(TestCase): @@ -91,3 +95,35 @@ class TestCrypto(TestCase): ) self.assertEqual(200, response.status_code) self.assertIn("Content-Disposition", response) + + def test_used_by(self): + """Test used_by endpoint""" + self.client.force_login(User.objects.get(username="akadmin")) + keypair = CertificateKeyPair.objects.first() + provider = OAuth2Provider.objects.create( + name="test", + client_id="test", + client_secret=generate_client_secret(), + authorization_flow=Flow.objects.first(), + redirect_uris="http://localhost", + rsa_key=CertificateKeyPair.objects.first(), + ) + response = self.client.get( + reverse( + "authentik_api:certificatekeypair-used-by", + kwargs={"pk": keypair.pk}, + ) + ) + self.assertEqual(200, response.status_code) + self.assertJSONEqual( + response.content.decode(), + [ + { + "app": "authentik_providers_oauth2", + "model_name": "oauth2provider", + "pk": str(provider.pk), + "name": str(provider), + "action": DeleteAction.SET_NULL.name, + } + ], + ) diff --git a/authentik/events/api/notification.py b/authentik/events/api/notification.py index 07b2ac49e..2162e021f 100644 --- a/authentik/events/api/notification.py +++ b/authentik/events/api/notification.py @@ -7,6 +7,7 @@ from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import GenericViewSet from authentik.api.authorization import OwnerFilter, OwnerPermissions +from authentik.core.api.used_by import UsedByMixin from authentik.events.api.event import EventSerializer from authentik.events.models import Notification @@ -35,6 +36,7 @@ class NotificationViewSet( mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, + UsedByMixin, mixins.ListModelMixin, GenericViewSet, ): diff --git a/authentik/events/api/notification_rule.py b/authentik/events/api/notification_rule.py index fbe0788c3..253a53ab4 100644 --- a/authentik/events/api/notification_rule.py +++ b/authentik/events/api/notification_rule.py @@ -3,6 +3,7 @@ from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet from authentik.core.api.groups import GroupSerializer +from authentik.core.api.used_by import UsedByMixin from authentik.events.models import NotificationRule @@ -24,7 +25,7 @@ class NotificationRuleSerializer(ModelSerializer): ] -class NotificationRuleViewSet(ModelViewSet): +class NotificationRuleViewSet(UsedByMixin, ModelViewSet): """NotificationRule Viewset""" queryset = NotificationRule.objects.all() diff --git a/authentik/events/api/notification_transport.py b/authentik/events/api/notification_transport.py index 05b857e87..3b34e8287 100644 --- a/authentik/events/api/notification_transport.py +++ b/authentik/events/api/notification_transport.py @@ -9,6 +9,7 @@ from rest_framework.serializers import ModelSerializer, Serializer from rest_framework.viewsets import ModelViewSet from authentik.api.decorators import permission_required +from authentik.core.api.used_by import UsedByMixin from authentik.events.models import ( Notification, NotificationSeverity, @@ -52,7 +53,7 @@ class NotificationTransportTestSerializer(Serializer): raise NotImplementedError -class NotificationTransportViewSet(ModelViewSet): +class NotificationTransportViewSet(UsedByMixin, ModelViewSet): """NotificationTransport Viewset""" queryset = NotificationTransport.objects.all() diff --git a/authentik/flows/api/bindings.py b/authentik/flows/api/bindings.py index 4a1f93a49..74b97ca99 100644 --- a/authentik/flows/api/bindings.py +++ b/authentik/flows/api/bindings.py @@ -2,6 +2,7 @@ from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet +from authentik.core.api.used_by import UsedByMixin from authentik.flows.api.stages import StageSerializer from authentik.flows.models import FlowStageBinding @@ -27,7 +28,7 @@ class FlowStageBindingSerializer(ModelSerializer): ] -class FlowStageBindingViewSet(ModelViewSet): +class FlowStageBindingViewSet(UsedByMixin, ModelViewSet): """FlowStageBinding Viewset""" queryset = FlowStageBinding.objects.all() diff --git a/authentik/flows/api/flows.py b/authentik/flows/api/flows.py index 4515da098..97fda014c 100644 --- a/authentik/flows/api/flows.py +++ b/authentik/flows/api/flows.py @@ -24,6 +24,7 @@ from rest_framework.viewsets import ModelViewSet from structlog.stdlib import get_logger from authentik.api.decorators import permission_required +from authentik.core.api.used_by import UsedByMixin from authentik.core.api.utils import CacheSerializer, LinkSerializer from authentik.flows.exceptions import FlowNonApplicableException from authentik.flows.models import Flow @@ -94,7 +95,7 @@ class DiagramElement: return f"{self.identifier}=>{self.type}: {self.rest}" -class FlowViewSet(ModelViewSet): +class FlowViewSet(UsedByMixin, ModelViewSet): """Flow Viewset""" queryset = Flow.objects.all() diff --git a/authentik/flows/api/stages.py b/authentik/flows/api/stages.py index 0b83dbf8b..3ed2e4d0b 100644 --- a/authentik/flows/api/stages.py +++ b/authentik/flows/api/stages.py @@ -11,6 +11,7 @@ from rest_framework.serializers import ModelSerializer, SerializerMethodField from rest_framework.viewsets import GenericViewSet from structlog.stdlib import get_logger +from authentik.core.api.used_by import UsedByMixin from authentik.core.api.utils import MetaNameSerializer, TypeCreateSerializer from authentik.core.types import UserSettingSerializer from authentik.flows.api.flows import FlowSerializer @@ -49,6 +50,7 @@ class StageSerializer(ModelSerializer, MetaNameSerializer): class StageViewSet( mixins.RetrieveModelMixin, mixins.DestroyModelMixin, + UsedByMixin, mixins.ListModelMixin, GenericViewSet, ): diff --git a/authentik/flows/models.py b/authentik/flows/models.py index f5e02aa0c..6e9663882 100644 --- a/authentik/flows/models.py +++ b/authentik/flows/models.py @@ -72,7 +72,7 @@ class Stage(SerializerModel): def __str__(self): if hasattr(self, "__in_memory_type"): return f"In-memory Stage {getattr(self, '__in_memory_type')}" - return self.name + return f"Stage {self.name}" def in_memory_stage(view: Type["StageView"]) -> Stage: @@ -212,7 +212,7 @@ class FlowStageBinding(SerializerModel, PolicyBindingModel): return FlowStageBindingSerializer def __str__(self) -> str: - return f"{self.target} #{self.order}" + return f"Flow-stage binding #{self.order} to {self.target}" class Meta: diff --git a/authentik/outposts/api/outposts.py b/authentik/outposts/api/outposts.py index 604bd8189..4cf47d907 100644 --- a/authentik/outposts/api/outposts.py +++ b/authentik/outposts/api/outposts.py @@ -11,6 +11,7 @@ from rest_framework.serializers import JSONField, ModelSerializer, ValidationErr from rest_framework.viewsets import ModelViewSet from authentik.core.api.providers import ProviderSerializer +from authentik.core.api.used_by import UsedByMixin from authentik.core.api.utils import PassiveSerializer, is_dict from authentik.core.models import Provider from authentik.outposts.api.service_connections import ServiceConnectionSerializer @@ -95,7 +96,7 @@ class OutpostHealthSerializer(PassiveSerializer): version_outdated = BooleanField(read_only=True) -class OutpostViewSet(ModelViewSet): +class OutpostViewSet(UsedByMixin, ModelViewSet): """Outpost Viewset""" queryset = Outpost.objects.all() diff --git a/authentik/outposts/api/service_connections.py b/authentik/outposts/api/service_connections.py index 8f2b04bd1..566ed7dd6 100644 --- a/authentik/outposts/api/service_connections.py +++ b/authentik/outposts/api/service_connections.py @@ -14,6 +14,7 @@ from rest_framework.response import Response from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import GenericViewSet, ModelViewSet +from authentik.core.api.used_by import UsedByMixin from authentik.core.api.utils import ( MetaNameSerializer, PassiveSerializer, @@ -55,6 +56,7 @@ class ServiceConnectionStateSerializer(PassiveSerializer): class ServiceConnectionViewSet( mixins.RetrieveModelMixin, mixins.DestroyModelMixin, + UsedByMixin, mixins.ListModelMixin, GenericViewSet, ): @@ -105,7 +107,7 @@ class DockerServiceConnectionSerializer(ServiceConnectionSerializer): ] -class DockerServiceConnectionViewSet(ModelViewSet): +class DockerServiceConnectionViewSet(UsedByMixin, ModelViewSet): """DockerServiceConnection Viewset""" queryset = DockerServiceConnection.objects.all() @@ -139,7 +141,7 @@ class KubernetesServiceConnectionSerializer(ServiceConnectionSerializer): fields = ServiceConnectionSerializer.Meta.fields + ["kubeconfig"] -class KubernetesServiceConnectionViewSet(ModelViewSet): +class KubernetesServiceConnectionViewSet(UsedByMixin, ModelViewSet): """KubernetesServiceConnection Viewset""" queryset = KubernetesServiceConnection.objects.all() diff --git a/authentik/policies/api/bindings.py b/authentik/policies/api/bindings.py index 3a4ad831e..62603834e 100644 --- a/authentik/policies/api/bindings.py +++ b/authentik/policies/api/bindings.py @@ -11,6 +11,7 @@ from rest_framework.viewsets import ModelViewSet from structlog.stdlib import get_logger from authentik.core.api.groups import GroupSerializer +from authentik.core.api.used_by import UsedByMixin from authentik.core.api.users import UserSerializer from authentik.policies.api.policies import PolicySerializer from authentik.policies.models import PolicyBinding, PolicyBindingModel @@ -99,7 +100,7 @@ class PolicyBindingSerializer(ModelSerializer): return data -class PolicyBindingViewSet(ModelViewSet): +class PolicyBindingViewSet(UsedByMixin, ModelViewSet): """PolicyBinding Viewset""" queryset = ( diff --git a/authentik/policies/api/policies.py b/authentik/policies/api/policies.py index 1f08cc6ec..6be8b36b6 100644 --- a/authentik/policies/api/policies.py +++ b/authentik/policies/api/policies.py @@ -14,6 +14,7 @@ from structlog.stdlib import get_logger from authentik.api.decorators import permission_required from authentik.core.api.applications import user_app_cache_key +from authentik.core.api.used_by import UsedByMixin from authentik.core.api.utils import ( CacheSerializer, MetaNameSerializer, @@ -79,6 +80,7 @@ class PolicySerializer(ModelSerializer, MetaNameSerializer): class PolicyViewSet( mixins.RetrieveModelMixin, mixins.DestroyModelMixin, + UsedByMixin, mixins.ListModelMixin, GenericViewSet, ): diff --git a/authentik/policies/dummy/api.py b/authentik/policies/dummy/api.py index 66d837063..789d18de4 100644 --- a/authentik/policies/dummy/api.py +++ b/authentik/policies/dummy/api.py @@ -1,6 +1,7 @@ """Dummy Policy API Views""" from rest_framework.viewsets import ModelViewSet +from authentik.core.api.used_by import UsedByMixin from authentik.policies.api.policies import PolicySerializer from authentik.policies.dummy.models import DummyPolicy @@ -13,7 +14,7 @@ class DummyPolicySerializer(PolicySerializer): fields = PolicySerializer.Meta.fields + ["result", "wait_min", "wait_max"] -class DummyPolicyViewSet(ModelViewSet): +class DummyPolicyViewSet(UsedByMixin, ModelViewSet): """Dummy Viewset""" queryset = DummyPolicy.objects.all() diff --git a/authentik/policies/event_matcher/api.py b/authentik/policies/event_matcher/api.py index 0dda645f1..9e998bb53 100644 --- a/authentik/policies/event_matcher/api.py +++ b/authentik/policies/event_matcher/api.py @@ -1,6 +1,7 @@ """Event Matcher Policy API""" from rest_framework.viewsets import ModelViewSet +from authentik.core.api.used_by import UsedByMixin from authentik.policies.api.policies import PolicySerializer from authentik.policies.event_matcher.models import EventMatcherPolicy @@ -17,7 +18,7 @@ class EventMatcherPolicySerializer(PolicySerializer): ] -class EventMatcherPolicyViewSet(ModelViewSet): +class EventMatcherPolicyViewSet(UsedByMixin, ModelViewSet): """Event Matcher Policy Viewset""" queryset = EventMatcherPolicy.objects.all() diff --git a/authentik/policies/expiry/api.py b/authentik/policies/expiry/api.py index 70f12a62d..e83ac2fbf 100644 --- a/authentik/policies/expiry/api.py +++ b/authentik/policies/expiry/api.py @@ -1,6 +1,7 @@ """Password Expiry Policy API Views""" from rest_framework.viewsets import ModelViewSet +from authentik.core.api.used_by import UsedByMixin from authentik.policies.api.policies import PolicySerializer from authentik.policies.expiry.models import PasswordExpiryPolicy @@ -13,7 +14,7 @@ class PasswordExpiryPolicySerializer(PolicySerializer): fields = PolicySerializer.Meta.fields + ["days", "deny_only"] -class PasswordExpiryPolicyViewSet(ModelViewSet): +class PasswordExpiryPolicyViewSet(UsedByMixin, ModelViewSet): """Password Expiry Viewset""" queryset = PasswordExpiryPolicy.objects.all() diff --git a/authentik/policies/expression/api.py b/authentik/policies/expression/api.py index d4975e097..26a39ff1f 100644 --- a/authentik/policies/expression/api.py +++ b/authentik/policies/expression/api.py @@ -1,6 +1,7 @@ """Expression Policy API""" from rest_framework.viewsets import ModelViewSet +from authentik.core.api.used_by import UsedByMixin from authentik.policies.api.policies import PolicySerializer from authentik.policies.expression.evaluator import PolicyEvaluator from authentik.policies.expression.models import ExpressionPolicy @@ -20,7 +21,7 @@ class ExpressionPolicySerializer(PolicySerializer): fields = PolicySerializer.Meta.fields + ["expression"] -class ExpressionPolicyViewSet(ModelViewSet): +class ExpressionPolicyViewSet(UsedByMixin, ModelViewSet): """Source Viewset""" queryset = ExpressionPolicy.objects.all() diff --git a/authentik/policies/hibp/api.py b/authentik/policies/hibp/api.py index 66acd8877..86cbfdb95 100644 --- a/authentik/policies/hibp/api.py +++ b/authentik/policies/hibp/api.py @@ -1,6 +1,7 @@ """Source API Views""" from rest_framework.viewsets import ModelViewSet +from authentik.core.api.used_by import UsedByMixin from authentik.policies.api.policies import PolicySerializer from authentik.policies.hibp.models import HaveIBeenPwendPolicy @@ -13,7 +14,7 @@ class HaveIBeenPwendPolicySerializer(PolicySerializer): fields = PolicySerializer.Meta.fields + ["password_field", "allowed_count"] -class HaveIBeenPwendPolicyViewSet(ModelViewSet): +class HaveIBeenPwendPolicyViewSet(UsedByMixin, ModelViewSet): """Source Viewset""" queryset = HaveIBeenPwendPolicy.objects.all() diff --git a/authentik/policies/password/api.py b/authentik/policies/password/api.py index f0171095c..fc11a1c6d 100644 --- a/authentik/policies/password/api.py +++ b/authentik/policies/password/api.py @@ -1,6 +1,7 @@ """Password Policy API Views""" from rest_framework.viewsets import ModelViewSet +from authentik.core.api.used_by import UsedByMixin from authentik.policies.api.policies import PolicySerializer from authentik.policies.password.models import PasswordPolicy @@ -21,7 +22,7 @@ class PasswordPolicySerializer(PolicySerializer): ] -class PasswordPolicyViewSet(ModelViewSet): +class PasswordPolicyViewSet(UsedByMixin, ModelViewSet): """Password Policy Viewset""" queryset = PasswordPolicy.objects.all() diff --git a/authentik/policies/reputation/api.py b/authentik/policies/reputation/api.py index f10d690e0..e3bf747be 100644 --- a/authentik/policies/reputation/api.py +++ b/authentik/policies/reputation/api.py @@ -3,6 +3,7 @@ from rest_framework import mixins from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import GenericViewSet, ModelViewSet +from authentik.core.api.used_by import UsedByMixin from authentik.policies.api.policies import PolicySerializer from authentik.policies.reputation.models import ( IPReputation, @@ -23,7 +24,7 @@ class ReputationPolicySerializer(PolicySerializer): ] -class ReputationPolicyViewSet(ModelViewSet): +class ReputationPolicyViewSet(UsedByMixin, ModelViewSet): """Reputation Policy Viewset""" queryset = ReputationPolicy.objects.all() @@ -46,6 +47,7 @@ class IPReputationSerializer(ModelSerializer): class IPReputationViewSet( mixins.RetrieveModelMixin, mixins.DestroyModelMixin, + UsedByMixin, mixins.ListModelMixin, GenericViewSet, ): @@ -74,6 +76,7 @@ class UserReputationSerializer(ModelSerializer): class UserReputationViewSet( mixins.RetrieveModelMixin, mixins.DestroyModelMixin, + UsedByMixin, mixins.ListModelMixin, GenericViewSet, ): diff --git a/authentik/providers/ldap/api.py b/authentik/providers/ldap/api.py index d9900f3c5..5c10eb6ea 100644 --- a/authentik/providers/ldap/api.py +++ b/authentik/providers/ldap/api.py @@ -4,6 +4,7 @@ from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet from authentik.core.api.providers import ProviderSerializer +from authentik.core.api.used_by import UsedByMixin from authentik.providers.ldap.models import LDAPProvider @@ -19,7 +20,7 @@ class LDAPProviderSerializer(ProviderSerializer): ] -class LDAPProviderViewSet(ModelViewSet): +class LDAPProviderViewSet(UsedByMixin, ModelViewSet): """LDAPProvider Viewset""" queryset = LDAPProvider.objects.all() diff --git a/authentik/providers/oauth2/api/provider.py b/authentik/providers/oauth2/api/provider.py index 9d1b3bb98..daa099bd1 100644 --- a/authentik/providers/oauth2/api/provider.py +++ b/authentik/providers/oauth2/api/provider.py @@ -11,6 +11,7 @@ from rest_framework.serializers import ValidationError from rest_framework.viewsets import ModelViewSet from authentik.core.api.providers import ProviderSerializer +from authentik.core.api.used_by import UsedByMixin from authentik.core.api.utils import PassiveSerializer from authentik.core.models import Provider from authentik.providers.oauth2.models import JWTAlgorithms, OAuth2Provider @@ -61,7 +62,7 @@ class OAuth2ProviderSetupURLs(PassiveSerializer): logout = ReadOnlyField() -class OAuth2ProviderViewSet(ModelViewSet): +class OAuth2ProviderViewSet(UsedByMixin, ModelViewSet): """OAuth2Provider Viewset""" queryset = OAuth2Provider.objects.all() diff --git a/authentik/providers/oauth2/api/scope.py b/authentik/providers/oauth2/api/scope.py index 6ddc12310..20aaf06dc 100644 --- a/authentik/providers/oauth2/api/scope.py +++ b/authentik/providers/oauth2/api/scope.py @@ -2,6 +2,7 @@ from rest_framework.viewsets import ModelViewSet from authentik.core.api.propertymappings import PropertyMappingSerializer +from authentik.core.api.used_by import UsedByMixin from authentik.providers.oauth2.models import ScopeMapping @@ -17,7 +18,7 @@ class ScopeMappingSerializer(PropertyMappingSerializer): ] -class ScopeMappingViewSet(ModelViewSet): +class ScopeMappingViewSet(UsedByMixin, ModelViewSet): """ScopeMapping Viewset""" queryset = ScopeMapping.objects.all() diff --git a/authentik/providers/oauth2/api/tokens.py b/authentik/providers/oauth2/api/tokens.py index 3ff200da8..8d77ff4ce 100644 --- a/authentik/providers/oauth2/api/tokens.py +++ b/authentik/providers/oauth2/api/tokens.py @@ -10,6 +10,7 @@ from rest_framework.filters import OrderingFilter, SearchFilter from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import GenericViewSet +from authentik.core.api.used_by import UsedByMixin from authentik.core.api.users import UserSerializer from authentik.core.api.utils import MetaNameSerializer from authentik.providers.oauth2.api.provider import OAuth2ProviderSerializer @@ -57,6 +58,7 @@ class RefreshTokenModelSerializer(ExpiringBaseGrantModelSerializer): class AuthorizationCodeViewSet( mixins.RetrieveModelMixin, mixins.DestroyModelMixin, + UsedByMixin, mixins.ListModelMixin, GenericViewSet, ): @@ -82,6 +84,7 @@ class AuthorizationCodeViewSet( class RefreshTokenViewSet( mixins.RetrieveModelMixin, mixins.DestroyModelMixin, + UsedByMixin, mixins.ListModelMixin, GenericViewSet, ): diff --git a/authentik/providers/oauth2/migrations/0014_alter_oauth2provider_rsa_key.py b/authentik/providers/oauth2/migrations/0014_alter_oauth2provider_rsa_key.py new file mode 100644 index 000000000..5376b9ea8 --- /dev/null +++ b/authentik/providers/oauth2/migrations/0014_alter_oauth2provider_rsa_key.py @@ -0,0 +1,26 @@ +# Generated by Django 3.2.3 on 2021-06-09 21:52 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("authentik_crypto", "0002_create_self_signed_kp"), + ("authentik_providers_oauth2", "0013_alter_authorizationcode_nonce"), + ] + + operations = [ + migrations.AlterField( + model_name="oauth2provider", + name="rsa_key", + field=models.ForeignKey( + help_text="Key used to sign the tokens. Only required when JWT Algorithm is set to RS256.", + null=True, + on_delete=django.db.models.deletion.SET_NULL, + to="authentik_crypto.certificatekeypair", + verbose_name="RSA Key", + ), + ), + ] diff --git a/authentik/providers/oauth2/models.py b/authentik/providers/oauth2/models.py index 30f84cf5e..a9b82bf84 100644 --- a/authentik/providers/oauth2/models.py +++ b/authentik/providers/oauth2/models.py @@ -215,8 +215,7 @@ class OAuth2Provider(Provider): rsa_key = models.ForeignKey( CertificateKeyPair, verbose_name=_("RSA Key"), - on_delete=models.CASCADE, - blank=True, + on_delete=models.SET_NULL, null=True, help_text=_( "Key used to sign the tokens. Only required when JWT Algorithm is set to RS256." diff --git a/authentik/providers/proxy/api.py b/authentik/providers/proxy/api.py index 3d3075bdd..5665e68b0 100644 --- a/authentik/providers/proxy/api.py +++ b/authentik/providers/proxy/api.py @@ -8,6 +8,7 @@ from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet from authentik.core.api.providers import ProviderSerializer +from authentik.core.api.used_by import UsedByMixin from authentik.core.api.utils import PassiveSerializer from authentik.providers.oauth2.views.provider import ProviderInfoView from authentik.providers.proxy.models import ProxyMode, ProxyProvider @@ -76,7 +77,7 @@ class ProxyProviderSerializer(ProviderSerializer): ] -class ProxyProviderViewSet(ModelViewSet): +class ProxyProviderViewSet(UsedByMixin, ModelViewSet): """ProxyProvider Viewset""" queryset = ProxyProvider.objects.all() diff --git a/authentik/providers/proxy/models.py b/authentik/providers/proxy/models.py index 9672d9f31..c1fbe7ec9 100644 --- a/authentik/providers/proxy/models.py +++ b/authentik/providers/proxy/models.py @@ -167,3 +167,4 @@ class ProxyProvider(OutpostModel, OAuth2Provider): verbose_name = _("Proxy Provider") verbose_name_plural = _("Proxy Providers") + authentik_used_by_shadows = ["authentik_providers_oauth2.oauth2provider"] diff --git a/authentik/providers/saml/api.py b/authentik/providers/saml/api.py index 52fbe2061..0806b8959 100644 --- a/authentik/providers/saml/api.py +++ b/authentik/providers/saml/api.py @@ -21,6 +21,7 @@ from structlog.stdlib import get_logger from authentik.api.decorators import permission_required from authentik.core.api.propertymappings import PropertyMappingSerializer from authentik.core.api.providers import ProviderSerializer +from authentik.core.api.used_by import UsedByMixin from authentik.core.api.utils import PassiveSerializer from authentik.core.models import Provider from authentik.flows.models import Flow, FlowDesignation @@ -75,7 +76,7 @@ class SAMLProviderImportSerializer(PassiveSerializer): file = FileField() -class SAMLProviderViewSet(ModelViewSet): +class SAMLProviderViewSet(UsedByMixin, ModelViewSet): """SAMLProvider Viewset""" queryset = SAMLProvider.objects.all() @@ -166,7 +167,7 @@ class SAMLPropertyMappingSerializer(PropertyMappingSerializer): ] -class SAMLPropertyMappingViewSet(ModelViewSet): +class SAMLPropertyMappingViewSet(UsedByMixin, ModelViewSet): """SAMLPropertyMapping Viewset""" queryset = SAMLPropertyMapping.objects.all() diff --git a/authentik/sources/ldap/api.py b/authentik/sources/ldap/api.py index 9196186f3..5113da93b 100644 --- a/authentik/sources/ldap/api.py +++ b/authentik/sources/ldap/api.py @@ -10,6 +10,7 @@ from rest_framework.viewsets import ModelViewSet from authentik.admin.api.tasks import TaskSerializer from authentik.core.api.propertymappings import PropertyMappingSerializer from authentik.core.api.sources import SourceSerializer +from authentik.core.api.used_by import UsedByMixin from authentik.events.monitored_tasks import TaskInfo from authentik.sources.ldap.models import LDAPPropertyMapping, LDAPSource @@ -41,7 +42,7 @@ class LDAPSourceSerializer(SourceSerializer): extra_kwargs = {"bind_password": {"write_only": True}} -class LDAPSourceViewSet(ModelViewSet): +class LDAPSourceViewSet(UsedByMixin, ModelViewSet): """LDAP Source Viewset""" queryset = LDAPSource.objects.all() @@ -75,7 +76,7 @@ class LDAPPropertyMappingSerializer(PropertyMappingSerializer): ] -class LDAPPropertyMappingViewSet(ModelViewSet): +class LDAPPropertyMappingViewSet(UsedByMixin, ModelViewSet): """LDAP PropertyMapping Viewset""" queryset = LDAPPropertyMapping.objects.all() diff --git a/authentik/sources/oauth/api/source.py b/authentik/sources/oauth/api/source.py index 8899cfc89..f0af31661 100644 --- a/authentik/sources/oauth/api/source.py +++ b/authentik/sources/oauth/api/source.py @@ -9,6 +9,7 @@ from rest_framework.serializers import ValidationError from rest_framework.viewsets import ModelViewSet from authentik.core.api.sources import SourceSerializer +from authentik.core.api.used_by import UsedByMixin from authentik.core.api.utils import PassiveSerializer from authentik.sources.oauth.models import OAuthSource from authentik.sources.oauth.types.manager import MANAGER @@ -78,7 +79,7 @@ class OAuthSourceSerializer(SourceSerializer): extra_kwargs = {"consumer_secret": {"write_only": True}} -class OAuthSourceViewSet(ModelViewSet): +class OAuthSourceViewSet(UsedByMixin, ModelViewSet): """Source Viewset""" queryset = OAuthSource.objects.all() diff --git a/authentik/sources/oauth/api/source_connection.py b/authentik/sources/oauth/api/source_connection.py index c7e1d036b..8c18b5bea 100644 --- a/authentik/sources/oauth/api/source_connection.py +++ b/authentik/sources/oauth/api/source_connection.py @@ -6,6 +6,7 @@ from rest_framework.viewsets import GenericViewSet from authentik.api.authorization import OwnerFilter, OwnerPermissions from authentik.core.api.sources import SourceSerializer +from authentik.core.api.used_by import UsedByMixin from authentik.sources.oauth.models import UserOAuthSourceConnection @@ -26,6 +27,7 @@ class UserOAuthSourceConnectionViewSet( mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, + UsedByMixin, mixins.ListModelMixin, GenericViewSet, ): diff --git a/authentik/sources/plex/api.py b/authentik/sources/plex/api.py index 00200982a..02ce89fd3 100644 --- a/authentik/sources/plex/api.py +++ b/authentik/sources/plex/api.py @@ -14,6 +14,7 @@ from structlog.stdlib import get_logger from authentik.api.decorators import permission_required from authentik.core.api.sources import SourceSerializer +from authentik.core.api.used_by import UsedByMixin from authentik.core.api.utils import PassiveSerializer from authentik.flows.challenge import RedirectChallenge from authentik.flows.views import to_stage_response @@ -42,7 +43,7 @@ class PlexTokenRedeemSerializer(PassiveSerializer): plex_token = CharField() -class PlexSourceViewSet(ModelViewSet): +class PlexSourceViewSet(UsedByMixin, ModelViewSet): """Plex source Viewset""" queryset = PlexSource.objects.all() diff --git a/authentik/sources/saml/api.py b/authentik/sources/saml/api.py index 81cbcf8fb..063970f8c 100644 --- a/authentik/sources/saml/api.py +++ b/authentik/sources/saml/api.py @@ -7,6 +7,7 @@ from rest_framework.response import Response from rest_framework.viewsets import ModelViewSet from authentik.core.api.sources import SourceSerializer +from authentik.core.api.used_by import UsedByMixin from authentik.providers.saml.api import SAMLMetadataSerializer from authentik.sources.saml.models import SAMLSource from authentik.sources.saml.processors.metadata import MetadataProcessor @@ -33,7 +34,7 @@ class SAMLSourceSerializer(SourceSerializer): ] -class SAMLSourceViewSet(ModelViewSet): +class SAMLSourceViewSet(UsedByMixin, ModelViewSet): """SAMLSource Viewset""" queryset = SAMLSource.objects.all() diff --git a/authentik/stages/authenticator_duo/api.py b/authentik/stages/authenticator_duo/api.py index fe69a1ace..4e02f5966 100644 --- a/authentik/stages/authenticator_duo/api.py +++ b/authentik/stages/authenticator_duo/api.py @@ -12,6 +12,7 @@ from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import GenericViewSet, ModelViewSet, ReadOnlyModelViewSet from authentik.api.authorization import OwnerFilter, OwnerPermissions +from authentik.core.api.used_by import UsedByMixin from authentik.flows.api.stages import StageSerializer from authentik.stages.authenticator_duo.models import AuthenticatorDuoStage, DuoDevice from authentik.stages.authenticator_duo.stage import ( @@ -37,7 +38,7 @@ class AuthenticatorDuoStageSerializer(StageSerializer): } -class AuthenticatorDuoStageViewSet(ModelViewSet): +class AuthenticatorDuoStageViewSet(UsedByMixin, ModelViewSet): """AuthenticatorDuoStage Viewset""" queryset = AuthenticatorDuoStage.objects.all() @@ -78,6 +79,7 @@ class DuoDeviceViewSet( mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, + UsedByMixin, mixins.ListModelMixin, GenericViewSet, ): diff --git a/authentik/stages/authenticator_static/api.py b/authentik/stages/authenticator_static/api.py index d0fdea081..4b6498ea5 100644 --- a/authentik/stages/authenticator_static/api.py +++ b/authentik/stages/authenticator_static/api.py @@ -8,6 +8,7 @@ from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import GenericViewSet, ModelViewSet, ReadOnlyModelViewSet from authentik.api.authorization import OwnerFilter, OwnerPermissions +from authentik.core.api.used_by import UsedByMixin from authentik.flows.api.stages import StageSerializer from authentik.stages.authenticator_static.models import AuthenticatorStaticStage @@ -21,7 +22,7 @@ class AuthenticatorStaticStageSerializer(StageSerializer): fields = StageSerializer.Meta.fields + ["configure_flow", "token_count"] -class AuthenticatorStaticStageViewSet(ModelViewSet): +class AuthenticatorStaticStageViewSet(UsedByMixin, ModelViewSet): """AuthenticatorStaticStage Viewset""" queryset = AuthenticatorStaticStage.objects.all() @@ -52,6 +53,7 @@ class StaticDeviceViewSet( mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, + UsedByMixin, mixins.ListModelMixin, GenericViewSet, ): diff --git a/authentik/stages/authenticator_totp/api.py b/authentik/stages/authenticator_totp/api.py index 52689de37..3c9a95f7b 100644 --- a/authentik/stages/authenticator_totp/api.py +++ b/authentik/stages/authenticator_totp/api.py @@ -8,6 +8,7 @@ from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import GenericViewSet, ModelViewSet, ReadOnlyModelViewSet from authentik.api.authorization import OwnerFilter, OwnerPermissions +from authentik.core.api.used_by import UsedByMixin from authentik.flows.api.stages import StageSerializer from authentik.stages.authenticator_totp.models import AuthenticatorTOTPStage @@ -21,7 +22,7 @@ class AuthenticatorTOTPStageSerializer(StageSerializer): fields = StageSerializer.Meta.fields + ["configure_flow", "digits"] -class AuthenticatorTOTPStageViewSet(ModelViewSet): +class AuthenticatorTOTPStageViewSet(UsedByMixin, ModelViewSet): """AuthenticatorTOTPStage Viewset""" queryset = AuthenticatorTOTPStage.objects.all() @@ -45,6 +46,7 @@ class TOTPDeviceViewSet( mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, + UsedByMixin, mixins.ListModelMixin, GenericViewSet, ): diff --git a/authentik/stages/authenticator_validate/api.py b/authentik/stages/authenticator_validate/api.py index 4a51aabb3..32fb88a49 100644 --- a/authentik/stages/authenticator_validate/api.py +++ b/authentik/stages/authenticator_validate/api.py @@ -2,6 +2,7 @@ from rest_framework.serializers import ValidationError from rest_framework.viewsets import ModelViewSet +from authentik.core.api.used_by import UsedByMixin from authentik.flows.api.stages import StageSerializer from authentik.flows.models import NotConfiguredAction from authentik.stages.authenticator_validate.models import AuthenticatorValidateStage @@ -32,7 +33,7 @@ class AuthenticatorValidateStageSerializer(StageSerializer): ] -class AuthenticatorValidateStageViewSet(ModelViewSet): +class AuthenticatorValidateStageViewSet(UsedByMixin, ModelViewSet): """AuthenticatorValidateStage Viewset""" queryset = AuthenticatorValidateStage.objects.all() diff --git a/authentik/stages/authenticator_webauthn/api.py b/authentik/stages/authenticator_webauthn/api.py index 9f9314bf8..9f95be3f5 100644 --- a/authentik/stages/authenticator_webauthn/api.py +++ b/authentik/stages/authenticator_webauthn/api.py @@ -7,6 +7,7 @@ from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import GenericViewSet, ModelViewSet, ReadOnlyModelViewSet from authentik.api.authorization import OwnerFilter, OwnerPermissions +from authentik.core.api.used_by import UsedByMixin from authentik.flows.api.stages import StageSerializer from authentik.stages.authenticator_webauthn.models import ( AuthenticateWebAuthnStage, @@ -23,7 +24,7 @@ class AuthenticateWebAuthnStageSerializer(StageSerializer): fields = StageSerializer.Meta.fields + ["configure_flow"] -class AuthenticateWebAuthnStageViewSet(ModelViewSet): +class AuthenticateWebAuthnStageViewSet(UsedByMixin, ModelViewSet): """AuthenticateWebAuthnStage Viewset""" queryset = AuthenticateWebAuthnStage.objects.all() @@ -44,6 +45,7 @@ class WebAuthnDeviceViewSet( mixins.RetrieveModelMixin, mixins.UpdateModelMixin, mixins.DestroyModelMixin, + UsedByMixin, mixins.ListModelMixin, GenericViewSet, ): diff --git a/authentik/stages/captcha/api.py b/authentik/stages/captcha/api.py index fb425e42f..5623533ce 100644 --- a/authentik/stages/captcha/api.py +++ b/authentik/stages/captcha/api.py @@ -1,6 +1,7 @@ """CaptchaStage API Views""" from rest_framework.viewsets import ModelViewSet +from authentik.core.api.used_by import UsedByMixin from authentik.flows.api.stages import StageSerializer from authentik.stages.captcha.models import CaptchaStage @@ -15,7 +16,7 @@ class CaptchaStageSerializer(StageSerializer): extra_kwargs = {"private_key": {"write_only": True}} -class CaptchaStageViewSet(ModelViewSet): +class CaptchaStageViewSet(UsedByMixin, ModelViewSet): """CaptchaStage Viewset""" queryset = CaptchaStage.objects.all() diff --git a/authentik/stages/consent/api.py b/authentik/stages/consent/api.py index edd067921..609156600 100644 --- a/authentik/stages/consent/api.py +++ b/authentik/stages/consent/api.py @@ -6,6 +6,7 @@ from rest_framework.filters import OrderingFilter, SearchFilter from rest_framework.viewsets import GenericViewSet, ModelViewSet from authentik.core.api.applications import ApplicationSerializer +from authentik.core.api.used_by import UsedByMixin from authentik.core.api.users import UserSerializer from authentik.flows.api.stages import StageSerializer from authentik.stages.consent.models import ConsentStage, UserConsent @@ -20,7 +21,7 @@ class ConsentStageSerializer(StageSerializer): fields = StageSerializer.Meta.fields + ["mode", "consent_expire_in"] -class ConsentStageViewSet(ModelViewSet): +class ConsentStageViewSet(UsedByMixin, ModelViewSet): """ConsentStage Viewset""" queryset = ConsentStage.objects.all() @@ -42,6 +43,7 @@ class UserConsentSerializer(StageSerializer): class UserConsentViewSet( mixins.RetrieveModelMixin, mixins.DestroyModelMixin, + UsedByMixin, mixins.ListModelMixin, GenericViewSet, ): diff --git a/authentik/stages/deny/api.py b/authentik/stages/deny/api.py index 89c1d6e08..b6a9fcd20 100644 --- a/authentik/stages/deny/api.py +++ b/authentik/stages/deny/api.py @@ -1,6 +1,7 @@ """deny Stage API Views""" from rest_framework.viewsets import ModelViewSet +from authentik.core.api.used_by import UsedByMixin from authentik.flows.api.stages import StageSerializer from authentik.stages.deny.models import DenyStage @@ -14,7 +15,7 @@ class DenyStageSerializer(StageSerializer): fields = StageSerializer.Meta.fields -class DenyStageViewSet(ModelViewSet): +class DenyStageViewSet(UsedByMixin, ModelViewSet): """DenyStage Viewset""" queryset = DenyStage.objects.all() diff --git a/authentik/stages/dummy/api.py b/authentik/stages/dummy/api.py index 02e1c9463..4447ec134 100644 --- a/authentik/stages/dummy/api.py +++ b/authentik/stages/dummy/api.py @@ -1,6 +1,7 @@ """DummyStage API Views""" from rest_framework.viewsets import ModelViewSet +from authentik.core.api.used_by import UsedByMixin from authentik.flows.api.stages import StageSerializer from authentik.stages.dummy.models import DummyStage @@ -14,7 +15,7 @@ class DummyStageSerializer(StageSerializer): fields = StageSerializer.Meta.fields -class DummyStageViewSet(ModelViewSet): +class DummyStageViewSet(UsedByMixin, ModelViewSet): """DummyStage Viewset""" queryset = DummyStage.objects.all() diff --git a/authentik/stages/email/api.py b/authentik/stages/email/api.py index e13d9584f..90dfd2c6d 100644 --- a/authentik/stages/email/api.py +++ b/authentik/stages/email/api.py @@ -6,6 +6,7 @@ from rest_framework.response import Response from rest_framework.serializers import ValidationError from rest_framework.viewsets import ModelViewSet +from authentik.core.api.used_by import UsedByMixin from authentik.core.api.utils import TypeCreateSerializer from authentik.flows.api.stages import StageSerializer from authentik.stages.email.models import EmailStage, get_template_choices @@ -46,7 +47,7 @@ class EmailStageSerializer(StageSerializer): extra_kwargs = {"password": {"write_only": True}} -class EmailStageViewSet(ModelViewSet): +class EmailStageViewSet(UsedByMixin, ModelViewSet): """EmailStage Viewset""" queryset = EmailStage.objects.all() diff --git a/authentik/stages/identification/api.py b/authentik/stages/identification/api.py index e2b44ce54..54e9bc8ca 100644 --- a/authentik/stages/identification/api.py +++ b/authentik/stages/identification/api.py @@ -1,6 +1,7 @@ """Identification Stage API Views""" from rest_framework.viewsets import ModelViewSet +from authentik.core.api.used_by import UsedByMixin from authentik.flows.api.stages import StageSerializer from authentik.stages.identification.models import IdentificationStage @@ -22,7 +23,7 @@ class IdentificationStageSerializer(StageSerializer): ] -class IdentificationStageViewSet(ModelViewSet): +class IdentificationStageViewSet(UsedByMixin, ModelViewSet): """IdentificationStage Viewset""" queryset = IdentificationStage.objects.all() diff --git a/authentik/stages/invitation/api.py b/authentik/stages/invitation/api.py index fc5c508d3..ff6a720e2 100644 --- a/authentik/stages/invitation/api.py +++ b/authentik/stages/invitation/api.py @@ -3,6 +3,7 @@ from rest_framework.fields import JSONField from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet +from authentik.core.api.used_by import UsedByMixin from authentik.core.api.users import UserSerializer from authentik.core.api.utils import is_dict from authentik.flows.api.stages import StageSerializer @@ -20,7 +21,7 @@ class InvitationStageSerializer(StageSerializer): ] -class InvitationStageViewSet(ModelViewSet): +class InvitationStageViewSet(UsedByMixin, ModelViewSet): """InvitationStage Viewset""" queryset = InvitationStage.objects.all() @@ -45,7 +46,7 @@ class InvitationSerializer(ModelSerializer): ] -class InvitationViewSet(ModelViewSet): +class InvitationViewSet(UsedByMixin, ModelViewSet): """Invitation Viewset""" queryset = Invitation.objects.all() diff --git a/authentik/stages/password/api.py b/authentik/stages/password/api.py index 48499663e..30a376590 100644 --- a/authentik/stages/password/api.py +++ b/authentik/stages/password/api.py @@ -1,6 +1,7 @@ """PasswordStage API Views""" from rest_framework.viewsets import ModelViewSet +from authentik.core.api.used_by import UsedByMixin from authentik.flows.api.stages import StageSerializer from authentik.stages.password.models import PasswordStage @@ -18,7 +19,7 @@ class PasswordStageSerializer(StageSerializer): ] -class PasswordStageViewSet(ModelViewSet): +class PasswordStageViewSet(UsedByMixin, ModelViewSet): """PasswordStage Viewset""" queryset = PasswordStage.objects.all() diff --git a/authentik/stages/prompt/api.py b/authentik/stages/prompt/api.py index a318ff646..dc5d3b4e6 100644 --- a/authentik/stages/prompt/api.py +++ b/authentik/stages/prompt/api.py @@ -3,6 +3,7 @@ from rest_framework.serializers import CharField, ModelSerializer from rest_framework.validators import UniqueValidator from rest_framework.viewsets import ModelViewSet +from authentik.core.api.used_by import UsedByMixin from authentik.flows.api.stages import StageSerializer from authentik.stages.prompt.models import Prompt, PromptStage @@ -21,7 +22,7 @@ class PromptStageSerializer(StageSerializer): ] -class PromptStageViewSet(ModelViewSet): +class PromptStageViewSet(UsedByMixin, ModelViewSet): """PromptStage Viewset""" queryset = PromptStage.objects.all() @@ -48,7 +49,7 @@ class PromptSerializer(ModelSerializer): ] -class PromptViewSet(ModelViewSet): +class PromptViewSet(UsedByMixin, ModelViewSet): """Prompt Viewset""" queryset = Prompt.objects.all().prefetch_related("promptstage_set") diff --git a/authentik/stages/user_delete/api.py b/authentik/stages/user_delete/api.py index 195fdcca7..8ab224b44 100644 --- a/authentik/stages/user_delete/api.py +++ b/authentik/stages/user_delete/api.py @@ -1,6 +1,7 @@ """User Delete Stage API Views""" from rest_framework.viewsets import ModelViewSet +from authentik.core.api.used_by import UsedByMixin from authentik.flows.api.stages import StageSerializer from authentik.stages.user_delete.models import UserDeleteStage @@ -14,7 +15,7 @@ class UserDeleteStageSerializer(StageSerializer): fields = StageSerializer.Meta.fields -class UserDeleteStageViewSet(ModelViewSet): +class UserDeleteStageViewSet(UsedByMixin, ModelViewSet): """UserDeleteStage Viewset""" queryset = UserDeleteStage.objects.all() diff --git a/authentik/stages/user_login/api.py b/authentik/stages/user_login/api.py index 55ff8a00c..b55f9779c 100644 --- a/authentik/stages/user_login/api.py +++ b/authentik/stages/user_login/api.py @@ -1,6 +1,7 @@ """Login Stage API Views""" from rest_framework.viewsets import ModelViewSet +from authentik.core.api.used_by import UsedByMixin from authentik.flows.api.stages import StageSerializer from authentik.stages.user_login.models import UserLoginStage @@ -16,7 +17,7 @@ class UserLoginStageSerializer(StageSerializer): ] -class UserLoginStageViewSet(ModelViewSet): +class UserLoginStageViewSet(UsedByMixin, ModelViewSet): """UserLoginStage Viewset""" queryset = UserLoginStage.objects.all() diff --git a/authentik/stages/user_logout/api.py b/authentik/stages/user_logout/api.py index 89017e3b9..d361bcfea 100644 --- a/authentik/stages/user_logout/api.py +++ b/authentik/stages/user_logout/api.py @@ -1,6 +1,7 @@ """Logout Stage API Views""" from rest_framework.viewsets import ModelViewSet +from authentik.core.api.used_by import UsedByMixin from authentik.flows.api.stages import StageSerializer from authentik.stages.user_logout.models import UserLogoutStage @@ -14,7 +15,7 @@ class UserLogoutStageSerializer(StageSerializer): fields = StageSerializer.Meta.fields -class UserLogoutStageViewSet(ModelViewSet): +class UserLogoutStageViewSet(UsedByMixin, ModelViewSet): """UserLogoutStage Viewset""" queryset = UserLogoutStage.objects.all() diff --git a/authentik/stages/user_write/api.py b/authentik/stages/user_write/api.py index f1dadc769..5acaa6ae1 100644 --- a/authentik/stages/user_write/api.py +++ b/authentik/stages/user_write/api.py @@ -1,6 +1,7 @@ """User Write Stage API Views""" from rest_framework.viewsets import ModelViewSet +from authentik.core.api.used_by import UsedByMixin from authentik.flows.api.stages import StageSerializer from authentik.stages.user_write.models import UserWriteStage @@ -14,7 +15,7 @@ class UserWriteStageSerializer(StageSerializer): fields = StageSerializer.Meta.fields -class UserWriteStageViewSet(ModelViewSet): +class UserWriteStageViewSet(UsedByMixin, ModelViewSet): """UserWriteStage Viewset""" queryset = UserWriteStage.objects.all() diff --git a/authentik/tenants/api.py b/authentik/tenants/api.py index 4a40453ac..3e85257e5 100644 --- a/authentik/tenants/api.py +++ b/authentik/tenants/api.py @@ -8,6 +8,7 @@ from rest_framework.response import Response from rest_framework.serializers import ModelSerializer from rest_framework.viewsets import ModelViewSet +from authentik.core.api.used_by import UsedByMixin from authentik.core.api.utils import PassiveSerializer from authentik.lib.config import CONFIG from authentik.tenants.models import Tenant @@ -56,7 +57,7 @@ class CurrentTenantSerializer(PassiveSerializer): flow_unenrollment = CharField(source="flow_unenrollment.slug", required=False) -class TenantViewSet(ModelViewSet): +class TenantViewSet(UsedByMixin, ModelViewSet): """Tenant Viewset""" queryset = Tenant.objects.all() diff --git a/authentik/tenants/models.py b/authentik/tenants/models.py index c777ff283..1c1da4e5a 100644 --- a/authentik/tenants/models.py +++ b/authentik/tenants/models.py @@ -41,7 +41,9 @@ class Tenant(models.Model): ) def __str__(self) -> str: - return self.domain + if self.default: + return "Default tenant" + return f"Tenant {self.domain}" class Meta: diff --git a/pyproject.toml b/pyproject.toml index a4a3056ad..f3601d61d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,6 +9,7 @@ force_grid_wrap = 0 use_parentheses = true line_length = 88 src_paths = ["authentik", "tests", "lifecycle"] +force_to_top = "*" [tool.coverage.run] source = ["authentik"] diff --git a/schema.yml b/schema.yml index 8cf6ca3a3..03ff271a0 100644 --- a/schema.yml +++ b/schema.yml @@ -664,6 +664,35 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/authenticators/duo/{id}/used_by/: + get: + operationId: authenticators_duo_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this Duo Device. + required: true + tags: + - authenticators + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/authenticators/static/: get: operationId: authenticators_static_list @@ -837,6 +866,35 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/authenticators/static/{id}/used_by/: + get: + operationId: authenticators_static_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this static device. + required: true + tags: + - authenticators + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/authenticators/totp/: get: operationId: authenticators_totp_list @@ -1010,6 +1068,35 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/authenticators/totp/{id}/used_by/: + get: + operationId: authenticators_totp_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this TOTP device. + required: true + tags: + - authenticators + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/authenticators/webauthn/: get: operationId: authenticators_webauthn_list @@ -1183,6 +1270,35 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/authenticators/webauthn/{id}/used_by/: + get: + operationId: authenticators_webauthn_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this WebAuthn Device. + required: true + tags: + - authenticators + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/core/applications/: get: operationId: core_applications_list @@ -1519,6 +1635,35 @@ paths: description: Bad request '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/core/applications/{slug}/used_by/: + get: + operationId: core_applications_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: slug + schema: + type: string + description: Internal application name, used in URLs. + required: true + tags: + - core + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/core/authenticated_sessions/: get: operationId: core_authenticated_sessions_list @@ -1627,6 +1772,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/core/authenticated_sessions/{uuid}/used_by/: + get: + operationId: core_authenticated_sessions_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + description: A UUID string identifying this authenticated session. + required: true + tags: + - core + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/core/groups/: get: operationId: core_groups_list @@ -1839,6 +2014,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/core/groups/{group_uuid}/used_by/: + get: + operationId: core_groups_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: group_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this group. + required: true + tags: + - core + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/core/tenants/: get: operationId: core_tenants_list @@ -2043,6 +2248,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/core/tenants/{tenant_uuid}/used_by/: + get: + operationId: core_tenants_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: tenant_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Tenant. + required: true + tags: + - core + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/core/tenants/current/: get: operationId: core_tenants_current_retrieve @@ -2280,6 +2515,34 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/core/tokens/{identifier}/used_by/: + get: + operationId: core_tokens_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: identifier + schema: + type: string + required: true + tags: + - core + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/core/tokens/{identifier}/view_key/: get: operationId: core_tokens_view_key_retrieve @@ -2411,6 +2674,35 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/core/user_consent/{id}/used_by/: + get: + operationId: core_user_consent_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this User Consent. + required: true + tags: + - core + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/core/users/: get: operationId: core_users_list @@ -2692,6 +2984,35 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/core/users/{id}/used_by/: + get: + operationId: core_users_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this User. + required: true + tags: + - core + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/core/users/me/: get: operationId: core_users_me_retrieve @@ -2925,6 +3246,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/crypto/certificatekeypairs/{kp_uuid}/used_by/: + get: + operationId: crypto_certificatekeypairs_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: kp_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Certificate-Key Pair. + required: true + tags: + - crypto + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/crypto/certificatekeypairs/{kp_uuid}/view_certificate/: get: operationId: crypto_certificatekeypairs_view_certificate_retrieve @@ -3419,6 +3770,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/events/notifications/{uuid}/used_by/: + get: + operationId: events_notifications_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Notification. + required: true + tags: + - events + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/events/rules/: get: operationId: events_rules_list @@ -3623,6 +4004,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/events/rules/{pbm_uuid}/used_by/: + get: + operationId: events_rules_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: pbm_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Notification Rule. + required: true + tags: + - events + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/events/transports/: get: operationId: events_transports_list @@ -3859,6 +4270,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/events/transports/{uuid}/used_by/: + get: + operationId: events_transports_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Notification Transport. + required: true + tags: + - events + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/flows/bindings/: get: operationId: flows_bindings_list @@ -4111,6 +4552,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/flows/bindings/{fsb_uuid}/used_by/: + get: + operationId: flows_bindings_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: fsb_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Flow Stage Binding. + required: true + tags: + - flows + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/flows/executor/{flow_slug}/: get: operationId: flows_executor_get @@ -4563,6 +5034,35 @@ paths: description: Bad request '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/flows/instances/{slug}/used_by/: + get: + operationId: flows_instances_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: slug + schema: + type: string + description: Visible in the URL. + required: true + tags: + - flows + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/flows/instances/cache_clear/: post: operationId: flows_instances_cache_clear_create @@ -4722,6 +5222,35 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/oauth2/authorization_codes/{id}/used_by/: + get: + operationId: oauth2_authorization_codes_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this Authorization Code. + required: true + tags: + - oauth2 + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/oauth2/refresh_tokens/: get: operationId: oauth2_refresh_tokens_list @@ -4824,6 +5353,35 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/oauth2/refresh_tokens/{id}/used_by/: + get: + operationId: oauth2_refresh_tokens_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this OAuth2 Token. + required: true + tags: + - oauth2 + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/outposts/instances/: get: operationId: outposts_instances_list @@ -5078,6 +5636,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/outposts/instances/{uuid}/used_by/: + get: + operationId: outposts_instances_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + description: A UUID string identifying this outpost. + required: true + tags: + - outposts + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/outposts/instances/default_settings/: get: operationId: outposts_instances_default_settings_retrieve @@ -5370,6 +5958,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/outposts/service_connections/all/{uuid}/used_by/: + get: + operationId: outposts_service_connections_all_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Outpost Service-Connection. + required: true + tags: + - outposts + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/outposts/service_connections/all/types/: get: operationId: outposts_service_connections_all_types_list @@ -5596,6 +6214,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/outposts/service_connections/docker/{uuid}/used_by/: + get: + operationId: outposts_service_connections_docker_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Docker Service-Connection. + required: true + tags: + - outposts + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/outposts/service_connections/kubernetes/: get: operationId: outposts_service_connections_kubernetes_list @@ -5800,6 +6448,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/outposts/service_connections/kubernetes/{uuid}/used_by/: + get: + operationId: outposts_service_connections_kubernetes_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Kubernetes Service-Connection. + required: true + tags: + - outposts + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/policies/all/: get: operationId: policies_all_list @@ -5944,6 +6622,36 @@ paths: description: Invalid parameters '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/policies/all/{policy_uuid}/used_by/: + get: + operationId: policies_all_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: policy_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Policy. + required: true + tags: + - policies + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/policies/all/cache_clear/: post: operationId: policies_all_cache_clear_create @@ -6228,6 +6936,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/policies/bindings/{policy_binding_uuid}/used_by/: + get: + operationId: policies_bindings_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: policy_binding_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Policy Binding. + required: true + tags: + - policies + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/policies/dummy/: get: operationId: policies_dummy_list @@ -6430,6 +7168,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/policies/dummy/{policy_uuid}/used_by/: + get: + operationId: policies_dummy_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: policy_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Dummy Policy. + required: true + tags: + - policies + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/policies/event_matcher/: get: operationId: policies_event_matcher_list @@ -6632,6 +7400,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/policies/event_matcher/{policy_uuid}/used_by/: + get: + operationId: policies_event_matcher_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: policy_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Event Matcher Policy. + required: true + tags: + - policies + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/policies/expression/: get: operationId: policies_expression_list @@ -6836,6 +7634,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/policies/expression/{policy_uuid}/used_by/: + get: + operationId: policies_expression_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: policy_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Expression Policy. + required: true + tags: + - policies + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/policies/haveibeenpwned/: get: operationId: policies_haveibeenpwned_list @@ -7038,6 +7866,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/policies/haveibeenpwned/{policy_uuid}/used_by/: + get: + operationId: policies_haveibeenpwned_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: policy_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Have I Been Pwned Policy. + required: true + tags: + - policies + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/policies/password/: get: operationId: policies_password_list @@ -7242,6 +8100,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/policies/password/{policy_uuid}/used_by/: + get: + operationId: policies_password_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: policy_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Password Policy. + required: true + tags: + - policies + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/policies/password_expiry/: get: operationId: policies_password_expiry_list @@ -7446,6 +8334,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/policies/password_expiry/{policy_uuid}/used_by/: + get: + operationId: policies_password_expiry_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: policy_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Password Expiry Policy. + required: true + tags: + - policies + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/policies/reputation/: get: operationId: policies_reputation_list @@ -7648,6 +8566,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/policies/reputation/{policy_uuid}/used_by/: + get: + operationId: policies_reputation_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: policy_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Reputation Policy. + required: true + tags: + - policies + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/policies/reputation/ips/: get: operationId: policies_reputation_ips_list @@ -7750,6 +8698,35 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/policies/reputation/ips/{id}/used_by/: + get: + operationId: policies_reputation_ips_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this ip reputation. + required: true + tags: + - policies + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/policies/reputation/users/: get: operationId: policies_reputation_users_list @@ -7852,6 +8829,35 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/policies/reputation/users/{id}/used_by/: + get: + operationId: policies_reputation_users_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this user reputation. + required: true + tags: + - policies + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/propertymappings/all/: get: operationId: propertymappings_all_list @@ -7996,6 +9002,36 @@ paths: description: Invalid parameters '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/propertymappings/all/{pm_uuid}/used_by/: + get: + operationId: propertymappings_all_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: pm_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Property Mapping. + required: true + tags: + - propertymappings + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/propertymappings/all/types/: get: operationId: propertymappings_all_types_list @@ -8222,6 +9258,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/propertymappings/ldap/{pm_uuid}/used_by/: + get: + operationId: propertymappings_ldap_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: pm_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this LDAP Property Mapping. + required: true + tags: + - propertymappings + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/propertymappings/saml/: get: operationId: propertymappings_saml_list @@ -8426,6 +9492,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/propertymappings/saml/{pm_uuid}/used_by/: + get: + operationId: propertymappings_saml_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: pm_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this SAML Property Mapping. + required: true + tags: + - propertymappings + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/propertymappings/scope/: get: operationId: propertymappings_scope_list @@ -8630,6 +9726,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/propertymappings/scope/{pm_uuid}/used_by/: + get: + operationId: propertymappings_scope_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: pm_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Scope Mapping. + required: true + tags: + - propertymappings + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/providers/all/: get: operationId: providers_all_list @@ -8728,6 +9854,35 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/providers/all/{id}/used_by/: + get: + operationId: providers_all_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this provider. + required: true + tags: + - providers + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/providers/all/types/: get: operationId: providers_all_types_list @@ -8950,6 +10105,35 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/providers/ldap/{id}/used_by/: + get: + operationId: providers_ldap_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this LDAP Provider. + required: true + tags: + - providers + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/providers/oauth2/: get: operationId: providers_oauth2_list @@ -9179,6 +10363,35 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/providers/oauth2/{id}/used_by/: + get: + operationId: providers_oauth2_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this OAuth2/OpenID Provider. + required: true + tags: + - providers + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/providers/proxy/: get: operationId: providers_proxy_list @@ -9379,6 +10592,35 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/providers/proxy/{id}/used_by/: + get: + operationId: providers_proxy_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this Proxy Provider. + required: true + tags: + - providers + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/providers/saml/: get: operationId: providers_saml_list @@ -9613,6 +10855,35 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/providers/saml/{id}/used_by/: + get: + operationId: providers_saml_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this SAML Provider. + required: true + tags: + - providers + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/providers/saml/import_metadata/: post: operationId: providers_saml_import_metadata_create @@ -9897,6 +11168,35 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/sources/all/{slug}/used_by/: + get: + operationId: sources_all_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: slug + schema: + type: string + description: Internal source name, used in URLs. + required: true + tags: + - sources + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/sources/all/types/: get: operationId: sources_all_types_list @@ -10170,6 +11470,35 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/sources/ldap/{slug}/used_by/: + get: + operationId: sources_ldap_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: slug + schema: + type: string + description: Internal source name, used in URLs. + required: true + tags: + - sources + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/sources/oauth/: get: operationId: sources_oauth_list @@ -10370,6 +11699,35 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/sources/oauth/{slug}/used_by/: + get: + operationId: sources_oauth_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: slug + schema: + type: string + description: Internal source name, used in URLs. + required: true + tags: + - sources + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/sources/oauth/source_types/: get: operationId: sources_oauth_source_types_list @@ -10565,6 +11923,35 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/sources/oauth_user_connections/{id}/used_by/: + get: + operationId: sources_oauth_user_connections_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: id + schema: + type: integer + description: A unique integer value identifying this User OAuth Source Connection. + required: true + tags: + - sources + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/sources/plex/: get: operationId: sources_plex_list @@ -10765,6 +12152,35 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/sources/plex/{slug}/used_by/: + get: + operationId: sources_plex_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: slug + schema: + type: string + description: Internal source name, used in URLs. + required: true + tags: + - sources + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/sources/plex/redeem_token/: post: operationId: sources_plex_redeem_token_create @@ -11032,6 +12448,35 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/sources/saml/{slug}/used_by/: + get: + operationId: sources_saml_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: slug + schema: + type: string + description: Internal source name, used in URLs. + required: true + tags: + - sources + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/stages/all/: get: operationId: stages_all_list @@ -11132,6 +12577,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/stages/all/{stage_uuid}/used_by/: + get: + operationId: stages_all_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: stage_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this stage. + required: true + tags: + - stages + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/stages/all/types/: get: operationId: stages_all_types_list @@ -11406,6 +12881,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/stages/authenticator/duo/{stage_uuid}/used_by/: + get: + operationId: stages_authenticator_duo_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: stage_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Duo Authenticator Setup Stage. + required: true + tags: + - stages + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/stages/authenticator/static/: get: operationId: stages_authenticator_static_list @@ -11610,6 +13115,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/stages/authenticator/static/{stage_uuid}/used_by/: + get: + operationId: stages_authenticator_static_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: stage_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Static Authenticator Stage. + required: true + tags: + - stages + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/stages/authenticator/totp/: get: operationId: stages_authenticator_totp_list @@ -11814,6 +13349,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/stages/authenticator/totp/{stage_uuid}/used_by/: + get: + operationId: stages_authenticator_totp_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: stage_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this TOTP Authenticator Setup Stage. + required: true + tags: + - stages + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/stages/authenticator/validate/: get: operationId: stages_authenticator_validate_list @@ -12018,6 +13583,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/stages/authenticator/validate/{stage_uuid}/used_by/: + get: + operationId: stages_authenticator_validate_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: stage_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Authenticator Validation Stage. + required: true + tags: + - stages + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/stages/authenticator/webauthn/: get: operationId: stages_authenticator_webauthn_list @@ -12222,6 +13817,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/stages/authenticator/webauthn/{stage_uuid}/used_by/: + get: + operationId: stages_authenticator_webauthn_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: stage_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this WebAuthn Authenticator Setup Stage. + required: true + tags: + - stages + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/stages/captcha/: get: operationId: stages_captcha_list @@ -12426,6 +14051,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/stages/captcha/{stage_uuid}/used_by/: + get: + operationId: stages_captcha_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: stage_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Captcha Stage. + required: true + tags: + - stages + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/stages/consent/: get: operationId: stages_consent_list @@ -12630,6 +14285,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/stages/consent/{stage_uuid}/used_by/: + get: + operationId: stages_consent_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: stage_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Consent Stage. + required: true + tags: + - stages + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/stages/deny/: get: operationId: stages_deny_list @@ -12834,6 +14519,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/stages/deny/{stage_uuid}/used_by/: + get: + operationId: stages_deny_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: stage_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Deny Stage. + required: true + tags: + - stages + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/stages/dummy/: get: operationId: stages_dummy_list @@ -13038,6 +14753,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/stages/dummy/{stage_uuid}/used_by/: + get: + operationId: stages_dummy_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: stage_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Dummy Stage. + required: true + tags: + - stages + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/stages/email/: get: operationId: stages_email_list @@ -13242,6 +14987,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/stages/email/{stage_uuid}/used_by/: + get: + operationId: stages_email_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: stage_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Email Stage. + required: true + tags: + - stages + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/stages/email/templates/: get: operationId: stages_email_templates_list @@ -13468,6 +15243,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/stages/identification/{stage_uuid}/used_by/: + get: + operationId: stages_identification_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: stage_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Identification Stage. + required: true + tags: + - stages + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/stages/invitation/invitations/: get: operationId: stages_invitation_invitations_list @@ -13679,6 +15484,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/stages/invitation/invitations/{invite_uuid}/used_by/: + get: + operationId: stages_invitation_invitations_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: invite_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Invitation. + required: true + tags: + - stages + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/stages/invitation/stages/: get: operationId: stages_invitation_stages_list @@ -13883,6 +15718,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/stages/invitation/stages/{stage_uuid}/used_by/: + get: + operationId: stages_invitation_stages_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: stage_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Invitation Stage. + required: true + tags: + - stages + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/stages/password/: get: operationId: stages_password_list @@ -14087,6 +15952,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/stages/password/{stage_uuid}/used_by/: + get: + operationId: stages_password_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: stage_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Password Stage. + required: true + tags: + - stages + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/stages/prompt/prompts/: get: operationId: stages_prompt_prompts_list @@ -14319,6 +16214,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/stages/prompt/prompts/{prompt_uuid}/used_by/: + get: + operationId: stages_prompt_prompts_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: prompt_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Prompt. + required: true + tags: + - stages + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/stages/prompt/stages/: get: operationId: stages_prompt_stages_list @@ -14523,6 +16448,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/stages/prompt/stages/{stage_uuid}/used_by/: + get: + operationId: stages_prompt_stages_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: stage_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this Prompt Stage. + required: true + tags: + - stages + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/stages/user_delete/: get: operationId: stages_user_delete_list @@ -14727,6 +16682,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/stages/user_delete/{stage_uuid}/used_by/: + get: + operationId: stages_user_delete_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: stage_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this User Delete Stage. + required: true + tags: + - stages + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/stages/user_login/: get: operationId: stages_user_login_list @@ -14931,6 +16916,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/stages/user_login/{stage_uuid}/used_by/: + get: + operationId: stages_user_login_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: stage_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this User Login Stage. + required: true + tags: + - stages + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/stages/user_logout/: get: operationId: stages_user_logout_list @@ -15135,6 +17150,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/stages/user_logout/{stage_uuid}/used_by/: + get: + operationId: stages_user_logout_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: stage_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this User Logout Stage. + required: true + tags: + - stages + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' /api/v2beta/stages/user_write/: get: operationId: stages_user_write_list @@ -15339,6 +17384,36 @@ paths: $ref: '#/components/schemas/ValidationError' '403': $ref: '#/components/schemas/GenericError' + /api/v2beta/stages/user_write/{stage_uuid}/used_by/: + get: + operationId: stages_user_write_used_by_list + description: Get a list of all objects that use this object + parameters: + - in: path + name: stage_uuid + schema: + type: string + format: uuid + description: A UUID string identifying this User Write Stage. + required: true + tags: + - stages + security: + - authentik: [] + - cookieAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/UsedBy' + description: '' + '400': + $ref: '#/components/schemas/ValidationError' + '403': + $ref: '#/components/schemas/GenericError' components: schemas: AccessDeniedChallenge: @@ -15362,33 +17437,6 @@ components: type: string required: - type - ActionEnum: - enum: - - login - - login_failed - - logout - - user_write - - suspicious_request - - password_set - - secret_view - - invitation_used - - authorize_application - - source_linked - - impersonation_started - - impersonation_ended - - policy_execution - - policy_exception - - property_mapping_exception - - system_task_execution - - system_task_exception - - configuration_error - - model_created - - model_updated - - model_deleted - - email_sent - - update_available - - custom_ - type: string App: type: object description: Serialize Application info @@ -17076,7 +19124,7 @@ components: readOnly: true action: allOf: - - $ref: '#/components/schemas/ActionEnum' + - $ref: '#/components/schemas/EventMatcherPolicyActionEnum' description: Match created events with this action type. When left empty, all action types will be matched. client_ip: @@ -17094,6 +19142,33 @@ components: - pk - verbose_name - verbose_name_plural + EventMatcherPolicyActionEnum: + enum: + - login + - login_failed + - logout + - user_write + - suspicious_request + - password_set + - secret_view + - invitation_used + - authorize_application + - source_linked + - impersonation_started + - impersonation_ended + - policy_execution + - policy_exception + - property_mapping_exception + - system_task_execution + - system_task_exception + - configuration_error + - model_created + - model_updated + - model_deleted + - email_sent + - update_available + - custom_ + type: string EventMatcherPolicyRequest: type: object description: Event Matcher Policy Serializer @@ -17107,7 +19182,7 @@ components: will be logged. By default, only execution errors are logged. action: allOf: - - $ref: '#/components/schemas/ActionEnum' + - $ref: '#/components/schemas/EventMatcherPolicyActionEnum' description: Match created events with this action type. When left empty, all action types will be matched. client_ip: @@ -22199,7 +24274,7 @@ components: will be logged. By default, only execution errors are logged. action: allOf: - - $ref: '#/components/schemas/ActionEnum' + - $ref: '#/components/schemas/EventMatcherPolicyActionEnum' description: Match created events with this action type. When left empty, all action types will be matched. client_ip: @@ -25448,6 +27523,33 @@ components: required: - challenge - name + UsedBy: + type: object + description: A list of all objects referencing the queried object + properties: + app: + type: string + model_name: + type: string + pk: + type: string + name: + type: string + action: + $ref: '#/components/schemas/UsedByActionEnum' + required: + - action + - app + - model_name + - name + - pk + UsedByActionEnum: + enum: + - CASCADE + - CASCADE_MANY + - SET_NULL + - SET_DEFAULT + type: string User: type: object description: User Serializer diff --git a/web/src/elements/forms/DeleteForm.ts b/web/src/elements/forms/DeleteForm.ts index 27c436c14..724070b1b 100644 --- a/web/src/elements/forms/DeleteForm.ts +++ b/web/src/elements/forms/DeleteForm.ts @@ -1,20 +1,30 @@ import { t } from "@lingui/macro"; -import { customElement, html, property, TemplateResult } from "lit-element"; +import { CSSResult, customElement, html, property, TemplateResult } from "lit-element"; import { EVENT_REFRESH } from "../../constants"; import { ModalButton } from "../buttons/ModalButton"; import { MessageLevel } from "../messages/Message"; import { showMessage } from "../messages/MessageContainer"; import "../buttons/SpinnerButton"; +import { UsedBy, UsedByActionEnum } from "authentik-api"; +import PFList from "@patternfly/patternfly/components/List/list.css"; +import { until } from "lit-html/directives/until"; @customElement("ak-forms-delete") export class DeleteForm extends ModalButton { + static get styles(): CSSResult[] { + return super.styles.concat(PFList); + } + @property({attribute: false}) obj?: Record; @property() objectLabel?: string; + @property({attribute: false}) + usedBy?: () => Promise; + @property({attribute: false}) delete!: () => Promise; @@ -69,6 +79,40 @@ export class DeleteForm extends ModalButton {

+ ${this.usedBy ? until(this.usedBy().then(usedBy => { + if (usedBy.length < 1) { + return html``; + } + return html` +
+
+

+ ${t`The following objects use ${objName} `} +

+
    + ${usedBy.map(ub => { + let consequence = ""; + switch (ub.action) { + case UsedByActionEnum.Cascade: + consequence = t`object will be DELETED`; + break; + case UsedByActionEnum.CascadeMany: + consequence = t`connecting object will be deleted`; + break; + case UsedByActionEnum.SetDefault: + consequence = t`reference will be reset to default value`; + break; + case UsedByActionEnum.SetNull: + consequence = t`reference will be set to an empty value`; + break; + } + return html`
  • ${t`${ub.name} (${consequence})`}
  • `; + })} +
+
+
+ `; + })) : html``}