Compare commits
	
		
			5 Commits
		
	
	
		
			dependabot
			...
			version-20
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 8543e140ef | |||
| e2cf578afd | |||
| 0ce9fd9b2e | |||
| d17ad65435 | |||
| 01529d3894 | 
| @ -1,5 +1,6 @@ | ||||
| """authentik consent stage""" | ||||
| from typing import Optional | ||||
| from uuid import uuid4 | ||||
|  | ||||
| from django.http import HttpRequest, HttpResponse | ||||
| from django.utils.timezone import now | ||||
| @ -20,7 +21,8 @@ from authentik.stages.consent.models import ConsentMode, ConsentStage, UserConse | ||||
| PLAN_CONTEXT_CONSENT_TITLE = "consent_title" | ||||
| PLAN_CONTEXT_CONSENT_HEADER = "consent_header" | ||||
| PLAN_CONTEXT_CONSENT_PERMISSIONS = "consent_permissions" | ||||
| PLAN_CONTEXT_CONSNET_EXTRA_PERMISSIONS = "consent_additional_permissions" | ||||
| PLAN_CONTEXT_CONSENT_EXTRA_PERMISSIONS = "consent_additional_permissions" | ||||
| SESSION_KEY_CONSENT_TOKEN = "authentik/stages/consent/token"  # nosec | ||||
|  | ||||
|  | ||||
| class ConsentChallenge(WithUserInfoChallenge): | ||||
| @ -30,12 +32,14 @@ class ConsentChallenge(WithUserInfoChallenge): | ||||
|     permissions = PermissionSerializer(many=True) | ||||
|     additional_permissions = PermissionSerializer(many=True) | ||||
|     component = CharField(default="ak-stage-consent") | ||||
|     token = CharField(required=True) | ||||
|  | ||||
|  | ||||
| class ConsentChallengeResponse(ChallengeResponse): | ||||
|     """Consent challenge response, any valid response request is valid""" | ||||
|  | ||||
|     component = CharField(default="ak-stage-consent") | ||||
|     token = CharField(required=True) | ||||
|  | ||||
|  | ||||
| class ConsentStageView(ChallengeStageView): | ||||
| @ -44,12 +48,15 @@ class ConsentStageView(ChallengeStageView): | ||||
|     response_class = ConsentChallengeResponse | ||||
|  | ||||
|     def get_challenge(self) -> Challenge: | ||||
|         token = str(uuid4()) | ||||
|         self.request.session[SESSION_KEY_CONSENT_TOKEN] = token | ||||
|         data = { | ||||
|             "type": ChallengeTypes.NATIVE.value, | ||||
|             "permissions": self.executor.plan.context.get(PLAN_CONTEXT_CONSENT_PERMISSIONS, []), | ||||
|             "additional_permissions": self.executor.plan.context.get( | ||||
|                 PLAN_CONTEXT_CONSNET_EXTRA_PERMISSIONS, [] | ||||
|                 PLAN_CONTEXT_CONSENT_EXTRA_PERMISSIONS, [] | ||||
|             ), | ||||
|             "token": token, | ||||
|         } | ||||
|         if PLAN_CONTEXT_CONSENT_TITLE in self.executor.plan.context: | ||||
|             data["title"] = self.executor.plan.context[PLAN_CONTEXT_CONSENT_TITLE] | ||||
| @ -85,14 +92,14 @@ class ConsentStageView(ChallengeStageView): | ||||
|  | ||||
|         if consent: | ||||
|             perms = self.executor.plan.context.get(PLAN_CONTEXT_CONSENT_PERMISSIONS, []) | ||||
|             allowed_perms = set(consent.permissions.split(" ")) | ||||
|             allowed_perms = set(consent.permissions.split(" ") if consent.permissions != "" else []) | ||||
|             requested_perms = set(x["id"] for x in perms) | ||||
|  | ||||
|             if allowed_perms != requested_perms: | ||||
|                 self.executor.plan.context[PLAN_CONTEXT_CONSENT_PERMISSIONS] = [ | ||||
|                     x for x in perms if x["id"] in allowed_perms | ||||
|                 ] | ||||
|                 self.executor.plan.context[PLAN_CONTEXT_CONSNET_EXTRA_PERMISSIONS] = [ | ||||
|                 self.executor.plan.context[PLAN_CONTEXT_CONSENT_EXTRA_PERMISSIONS] = [ | ||||
|                     x for x in perms if x["id"] in requested_perms.difference(allowed_perms) | ||||
|                 ] | ||||
|                 return super().get(request, *args, **kwargs) | ||||
| @ -102,13 +109,15 @@ class ConsentStageView(ChallengeStageView): | ||||
|         return super().get(request, *args, **kwargs) | ||||
|  | ||||
|     def challenge_valid(self, response: ChallengeResponse) -> HttpResponse: | ||||
|         if response.data["token"] != self.request.session[SESSION_KEY_CONSENT_TOKEN]: | ||||
|             return self.get(self.request) | ||||
|         current_stage: ConsentStage = self.executor.current_stage | ||||
|         if PLAN_CONTEXT_APPLICATION not in self.executor.plan.context: | ||||
|             return self.executor.stage_ok() | ||||
|         application = self.executor.plan.context[PLAN_CONTEXT_APPLICATION] | ||||
|         permissions = self.executor.plan.context.get( | ||||
|             PLAN_CONTEXT_CONSENT_PERMISSIONS, [] | ||||
|         ) + self.executor.plan.context.get(PLAN_CONTEXT_CONSNET_EXTRA_PERMISSIONS, []) | ||||
|         ) + self.executor.plan.context.get(PLAN_CONTEXT_CONSENT_EXTRA_PERMISSIONS, []) | ||||
|         permissions_string = " ".join(x["id"] for x in permissions) | ||||
|         # Make this StageView work when injected, in which case `current_stage` is an instance | ||||
|         # of the base class, and we don't save any consent, as it is assumed to be a one-time | ||||
| @ -116,18 +125,14 @@ class ConsentStageView(ChallengeStageView): | ||||
|         if not isinstance(current_stage, ConsentStage): | ||||
|             return self.executor.stage_ok() | ||||
|         # Since we only get here when no consent exists, we can create it without update | ||||
|         consent = UserConsent( | ||||
|             user=self.request.user, | ||||
|             application=application, | ||||
|             permissions=permissions_string, | ||||
|         ) | ||||
|         if current_stage.mode == ConsentMode.PERMANENT: | ||||
|             UserConsent.objects.create( | ||||
|                 user=self.request.user, | ||||
|                 application=application, | ||||
|                 expiring=False, | ||||
|                 permissions=permissions_string, | ||||
|             ) | ||||
|             consent.expiring = False | ||||
|         if current_stage.mode == ConsentMode.EXPIRING: | ||||
|             UserConsent.objects.create( | ||||
|                 user=self.request.user, | ||||
|                 application=application, | ||||
|                 expires=now() + timedelta_from_string(current_stage.consent_expire_in), | ||||
|                 permissions=permissions_string, | ||||
|             ) | ||||
|             consent.expires = now() + timedelta_from_string(current_stage.consent_expire_in) | ||||
|         consent.save() | ||||
|         return self.executor.stage_ok() | ||||
|  | ||||
| @ -1,5 +1,6 @@ | ||||
| """consent tests""" | ||||
| from time import sleep | ||||
| from uuid import uuid4 | ||||
|  | ||||
| from django.urls import reverse | ||||
|  | ||||
| @ -14,7 +15,10 @@ from authentik.flows.tests import FlowTestCase | ||||
| from authentik.flows.views.executor import SESSION_KEY_PLAN | ||||
| from authentik.lib.generators import generate_id | ||||
| from authentik.stages.consent.models import ConsentMode, ConsentStage, UserConsent | ||||
| from authentik.stages.consent.stage import PLAN_CONTEXT_CONSENT_PERMISSIONS | ||||
| from authentik.stages.consent.stage import ( | ||||
|     PLAN_CONTEXT_CONSENT_PERMISSIONS, | ||||
|     SESSION_KEY_CONSENT_TOKEN, | ||||
| ) | ||||
|  | ||||
|  | ||||
| class TestConsentStage(FlowTestCase): | ||||
| @ -37,10 +41,13 @@ class TestConsentStage(FlowTestCase): | ||||
|         plan = FlowPlan(flow_pk=flow.pk.hex, bindings=[binding], markers=[StageMarker()]) | ||||
|         session = self.client.session | ||||
|         session[SESSION_KEY_PLAN] = plan | ||||
|         session[SESSION_KEY_CONSENT_TOKEN] = str(uuid4()) | ||||
|         session.save() | ||||
|         response = self.client.post( | ||||
|             reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}), | ||||
|             {}, | ||||
|             { | ||||
|                 "token": session[SESSION_KEY_CONSENT_TOKEN], | ||||
|             }, | ||||
|         ) | ||||
|         # pylint: disable=no-member | ||||
|         self.assertEqual(response.status_code, 200) | ||||
| @ -62,10 +69,13 @@ class TestConsentStage(FlowTestCase): | ||||
|         ) | ||||
|         session = self.client.session | ||||
|         session[SESSION_KEY_PLAN] = plan | ||||
|         session[SESSION_KEY_CONSENT_TOKEN] = str(uuid4()) | ||||
|         session.save() | ||||
|         response = self.client.post( | ||||
|             reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}), | ||||
|             {}, | ||||
|             { | ||||
|                 "token": session[SESSION_KEY_CONSENT_TOKEN], | ||||
|             }, | ||||
|         ) | ||||
|         self.assertEqual(response.status_code, 200) | ||||
|         self.assertStageRedirects(response, reverse("authentik_core:root-redirect")) | ||||
| @ -96,7 +106,7 @@ class TestConsentStage(FlowTestCase): | ||||
|             {}, | ||||
|         ) | ||||
|         self.assertEqual(response.status_code, 200) | ||||
|         self.assertStageResponse( | ||||
|         raw_res = self.assertStageResponse( | ||||
|             response, | ||||
|             flow, | ||||
|             self.user, | ||||
| @ -105,7 +115,9 @@ class TestConsentStage(FlowTestCase): | ||||
|         ) | ||||
|         response = self.client.post( | ||||
|             reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}), | ||||
|             {}, | ||||
|             { | ||||
|                 "token": raw_res["token"], | ||||
|             }, | ||||
|         ) | ||||
|         self.assertEqual(response.status_code, 200) | ||||
|         self.assertStageRedirects(response, reverse("authentik_core:root-redirect")) | ||||
| @ -144,7 +156,7 @@ class TestConsentStage(FlowTestCase): | ||||
|             {}, | ||||
|         ) | ||||
|         self.assertEqual(response.status_code, 200) | ||||
|         self.assertStageResponse( | ||||
|         raw_res = self.assertStageResponse( | ||||
|             response, | ||||
|             flow, | ||||
|             self.user, | ||||
| @ -155,7 +167,9 @@ class TestConsentStage(FlowTestCase): | ||||
|         ) | ||||
|         response = self.client.post( | ||||
|             reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}), | ||||
|             {}, | ||||
|             { | ||||
|                 "token": raw_res["token"], | ||||
|             }, | ||||
|         ) | ||||
|         self.assertEqual(response.status_code, 200) | ||||
|         self.assertStageRedirects(response, reverse("authentik_core:root-redirect")) | ||||
| @ -187,7 +201,7 @@ class TestConsentStage(FlowTestCase): | ||||
|             {}, | ||||
|         ) | ||||
|         self.assertEqual(response.status_code, 200) | ||||
|         self.assertStageResponse( | ||||
|         raw_res = self.assertStageResponse( | ||||
|             response, | ||||
|             flow, | ||||
|             self.user, | ||||
| @ -200,7 +214,9 @@ class TestConsentStage(FlowTestCase): | ||||
|         ) | ||||
|         response = self.client.post( | ||||
|             reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}), | ||||
|             {}, | ||||
|             { | ||||
|                 "token": raw_res["token"], | ||||
|             }, | ||||
|         ) | ||||
|         self.assertEqual(response.status_code, 200) | ||||
|         self.assertStageRedirects(response, reverse("authentik_core:root-redirect")) | ||||
| @ -209,3 +225,70 @@ class TestConsentStage(FlowTestCase): | ||||
|                 user=self.user, application=self.application, permissions="foo bar" | ||||
|             ).exists() | ||||
|         ) | ||||
|  | ||||
|     def test_permanent_same(self): | ||||
|         """Test permanent consent from user""" | ||||
|         self.client.force_login(self.user) | ||||
|         flow = create_test_flow(FlowDesignation.AUTHENTICATION) | ||||
|         stage = ConsentStage.objects.create(name=generate_id(), mode=ConsentMode.PERMANENT) | ||||
|         binding = FlowStageBinding.objects.create(target=flow, stage=stage, order=2) | ||||
|  | ||||
|         plan = FlowPlan( | ||||
|             flow_pk=flow.pk.hex, | ||||
|             bindings=[binding], | ||||
|             markers=[StageMarker()], | ||||
|             context={ | ||||
|                 PLAN_CONTEXT_APPLICATION: self.application, | ||||
|             }, | ||||
|         ) | ||||
|         session = self.client.session | ||||
|         session[SESSION_KEY_PLAN] = plan | ||||
|         session.save() | ||||
|  | ||||
|         # First, consent with a single permission | ||||
|         response = self.client.get( | ||||
|             reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}), | ||||
|             {}, | ||||
|         ) | ||||
|         self.assertEqual(response.status_code, 200) | ||||
|         raw_res = self.assertStageResponse( | ||||
|             response, | ||||
|             flow, | ||||
|             self.user, | ||||
|             permissions=[], | ||||
|             additional_permissions=[], | ||||
|         ) | ||||
|         response = self.client.post( | ||||
|             reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}), | ||||
|             { | ||||
|                 "token": raw_res["token"], | ||||
|             }, | ||||
|         ) | ||||
|         self.assertEqual(response.status_code, 200) | ||||
|         self.assertStageRedirects(response, reverse("authentik_core:root-redirect")) | ||||
|         self.assertTrue( | ||||
|             UserConsent.objects.filter( | ||||
|                 user=self.user, application=self.application, permissions="" | ||||
|             ).exists() | ||||
|         ) | ||||
|  | ||||
|         # Request again with the same perms | ||||
|         plan = FlowPlan( | ||||
|             flow_pk=flow.pk.hex, | ||||
|             bindings=[binding], | ||||
|             markers=[StageMarker()], | ||||
|             context={ | ||||
|                 PLAN_CONTEXT_APPLICATION: self.application, | ||||
|                 PLAN_CONTEXT_CONSENT_PERMISSIONS: [], | ||||
|             }, | ||||
|         ) | ||||
|         session = self.client.session | ||||
|         session[SESSION_KEY_PLAN] = plan | ||||
|         session.save() | ||||
|  | ||||
|         response = self.client.get( | ||||
|             reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}), | ||||
|             {}, | ||||
|         ) | ||||
|         self.assertEqual(response.status_code, 200) | ||||
|         self.assertStageResponse(response, component="xak-flow-redirect") | ||||
|  | ||||
							
								
								
									
										816
									
								
								schema.yml
									
									
									
									
									
								
							
							
						
						
									
										816
									
								
								schema.yml
									
									
									
									
									
								
							| @ -179,6 +179,32 @@ paths: | ||||
|           $ref: '#/components/schemas/ValidationError' | ||||
|         '403': | ||||
|           $ref: '#/components/schemas/GenericError' | ||||
|   /authenticators/admin/all/: | ||||
|     get: | ||||
|       operationId: authenticators_admin_all_list | ||||
|       description: Get all devices for current user | ||||
|       parameters: | ||||
|       - in: query | ||||
|         name: user | ||||
|         schema: | ||||
|           type: integer | ||||
|       tags: | ||||
|       - authenticators | ||||
|       security: | ||||
|       - authentik: [] | ||||
|       responses: | ||||
|         '200': | ||||
|           content: | ||||
|             application/json: | ||||
|               schema: | ||||
|                 type: array | ||||
|                 items: | ||||
|                   $ref: '#/components/schemas/Device' | ||||
|           description: '' | ||||
|         '400': | ||||
|           $ref: '#/components/schemas/ValidationError' | ||||
|         '403': | ||||
|           $ref: '#/components/schemas/GenericError' | ||||
|   /authenticators/admin/duo/: | ||||
|     get: | ||||
|       operationId: authenticators_admin_duo_list | ||||
| @ -407,6 +433,30 @@ paths: | ||||
|           $ref: '#/components/schemas/ValidationError' | ||||
|         '403': | ||||
|           $ref: '#/components/schemas/GenericError' | ||||
|     post: | ||||
|       operationId: authenticators_admin_sms_create | ||||
|       description: Viewset for sms authenticator devices (for admins) | ||||
|       tags: | ||||
|       - authenticators | ||||
|       requestBody: | ||||
|         content: | ||||
|           application/json: | ||||
|             schema: | ||||
|               $ref: '#/components/schemas/SMSDeviceRequest' | ||||
|         required: true | ||||
|       security: | ||||
|       - authentik: [] | ||||
|       responses: | ||||
|         '201': | ||||
|           content: | ||||
|             application/json: | ||||
|               schema: | ||||
|                 $ref: '#/components/schemas/SMSDevice' | ||||
|           description: '' | ||||
|         '400': | ||||
|           $ref: '#/components/schemas/ValidationError' | ||||
|         '403': | ||||
|           $ref: '#/components/schemas/GenericError' | ||||
|   /authenticators/admin/sms/{id}/: | ||||
|     get: | ||||
|       operationId: authenticators_admin_sms_retrieve | ||||
| @ -433,6 +483,88 @@ paths: | ||||
|           $ref: '#/components/schemas/ValidationError' | ||||
|         '403': | ||||
|           $ref: '#/components/schemas/GenericError' | ||||
|     put: | ||||
|       operationId: authenticators_admin_sms_update | ||||
|       description: Viewset for sms authenticator devices (for admins) | ||||
|       parameters: | ||||
|       - in: path | ||||
|         name: id | ||||
|         schema: | ||||
|           type: integer | ||||
|         description: A unique integer value identifying this SMS Device. | ||||
|         required: true | ||||
|       tags: | ||||
|       - authenticators | ||||
|       requestBody: | ||||
|         content: | ||||
|           application/json: | ||||
|             schema: | ||||
|               $ref: '#/components/schemas/SMSDeviceRequest' | ||||
|         required: true | ||||
|       security: | ||||
|       - authentik: [] | ||||
|       responses: | ||||
|         '200': | ||||
|           content: | ||||
|             application/json: | ||||
|               schema: | ||||
|                 $ref: '#/components/schemas/SMSDevice' | ||||
|           description: '' | ||||
|         '400': | ||||
|           $ref: '#/components/schemas/ValidationError' | ||||
|         '403': | ||||
|           $ref: '#/components/schemas/GenericError' | ||||
|     patch: | ||||
|       operationId: authenticators_admin_sms_partial_update | ||||
|       description: Viewset for sms authenticator devices (for admins) | ||||
|       parameters: | ||||
|       - in: path | ||||
|         name: id | ||||
|         schema: | ||||
|           type: integer | ||||
|         description: A unique integer value identifying this SMS Device. | ||||
|         required: true | ||||
|       tags: | ||||
|       - authenticators | ||||
|       requestBody: | ||||
|         content: | ||||
|           application/json: | ||||
|             schema: | ||||
|               $ref: '#/components/schemas/PatchedSMSDeviceRequest' | ||||
|       security: | ||||
|       - authentik: [] | ||||
|       responses: | ||||
|         '200': | ||||
|           content: | ||||
|             application/json: | ||||
|               schema: | ||||
|                 $ref: '#/components/schemas/SMSDevice' | ||||
|           description: '' | ||||
|         '400': | ||||
|           $ref: '#/components/schemas/ValidationError' | ||||
|         '403': | ||||
|           $ref: '#/components/schemas/GenericError' | ||||
|     delete: | ||||
|       operationId: authenticators_admin_sms_destroy | ||||
|       description: Viewset for sms authenticator devices (for admins) | ||||
|       parameters: | ||||
|       - in: path | ||||
|         name: id | ||||
|         schema: | ||||
|           type: integer | ||||
|         description: A unique integer value identifying this SMS Device. | ||||
|         required: true | ||||
|       tags: | ||||
|       - authenticators | ||||
|       security: | ||||
|       - authentik: [] | ||||
|       responses: | ||||
|         '204': | ||||
|           description: No response body | ||||
|         '400': | ||||
|           $ref: '#/components/schemas/ValidationError' | ||||
|         '403': | ||||
|           $ref: '#/components/schemas/GenericError' | ||||
|   /authenticators/admin/static/: | ||||
|     get: | ||||
|       operationId: authenticators_admin_static_list | ||||
| @ -481,6 +613,30 @@ paths: | ||||
|           $ref: '#/components/schemas/ValidationError' | ||||
|         '403': | ||||
|           $ref: '#/components/schemas/GenericError' | ||||
|     post: | ||||
|       operationId: authenticators_admin_static_create | ||||
|       description: Viewset for static authenticator devices (for admins) | ||||
|       tags: | ||||
|       - authenticators | ||||
|       requestBody: | ||||
|         content: | ||||
|           application/json: | ||||
|             schema: | ||||
|               $ref: '#/components/schemas/StaticDeviceRequest' | ||||
|         required: true | ||||
|       security: | ||||
|       - authentik: [] | ||||
|       responses: | ||||
|         '201': | ||||
|           content: | ||||
|             application/json: | ||||
|               schema: | ||||
|                 $ref: '#/components/schemas/StaticDevice' | ||||
|           description: '' | ||||
|         '400': | ||||
|           $ref: '#/components/schemas/ValidationError' | ||||
|         '403': | ||||
|           $ref: '#/components/schemas/GenericError' | ||||
|   /authenticators/admin/static/{id}/: | ||||
|     get: | ||||
|       operationId: authenticators_admin_static_retrieve | ||||
| @ -507,6 +663,88 @@ paths: | ||||
|           $ref: '#/components/schemas/ValidationError' | ||||
|         '403': | ||||
|           $ref: '#/components/schemas/GenericError' | ||||
|     put: | ||||
|       operationId: authenticators_admin_static_update | ||||
|       description: Viewset for static authenticator devices (for admins) | ||||
|       parameters: | ||||
|       - in: path | ||||
|         name: id | ||||
|         schema: | ||||
|           type: integer | ||||
|         description: A unique integer value identifying this static device. | ||||
|         required: true | ||||
|       tags: | ||||
|       - authenticators | ||||
|       requestBody: | ||||
|         content: | ||||
|           application/json: | ||||
|             schema: | ||||
|               $ref: '#/components/schemas/StaticDeviceRequest' | ||||
|         required: true | ||||
|       security: | ||||
|       - authentik: [] | ||||
|       responses: | ||||
|         '200': | ||||
|           content: | ||||
|             application/json: | ||||
|               schema: | ||||
|                 $ref: '#/components/schemas/StaticDevice' | ||||
|           description: '' | ||||
|         '400': | ||||
|           $ref: '#/components/schemas/ValidationError' | ||||
|         '403': | ||||
|           $ref: '#/components/schemas/GenericError' | ||||
|     patch: | ||||
|       operationId: authenticators_admin_static_partial_update | ||||
|       description: Viewset for static authenticator devices (for admins) | ||||
|       parameters: | ||||
|       - in: path | ||||
|         name: id | ||||
|         schema: | ||||
|           type: integer | ||||
|         description: A unique integer value identifying this static device. | ||||
|         required: true | ||||
|       tags: | ||||
|       - authenticators | ||||
|       requestBody: | ||||
|         content: | ||||
|           application/json: | ||||
|             schema: | ||||
|               $ref: '#/components/schemas/PatchedStaticDeviceRequest' | ||||
|       security: | ||||
|       - authentik: [] | ||||
|       responses: | ||||
|         '200': | ||||
|           content: | ||||
|             application/json: | ||||
|               schema: | ||||
|                 $ref: '#/components/schemas/StaticDevice' | ||||
|           description: '' | ||||
|         '400': | ||||
|           $ref: '#/components/schemas/ValidationError' | ||||
|         '403': | ||||
|           $ref: '#/components/schemas/GenericError' | ||||
|     delete: | ||||
|       operationId: authenticators_admin_static_destroy | ||||
|       description: Viewset for static authenticator devices (for admins) | ||||
|       parameters: | ||||
|       - in: path | ||||
|         name: id | ||||
|         schema: | ||||
|           type: integer | ||||
|         description: A unique integer value identifying this static device. | ||||
|         required: true | ||||
|       tags: | ||||
|       - authenticators | ||||
|       security: | ||||
|       - authentik: [] | ||||
|       responses: | ||||
|         '204': | ||||
|           description: No response body | ||||
|         '400': | ||||
|           $ref: '#/components/schemas/ValidationError' | ||||
|         '403': | ||||
|           $ref: '#/components/schemas/GenericError' | ||||
|   /authenticators/admin/totp/: | ||||
|     get: | ||||
|       operationId: authenticators_admin_totp_list | ||||
| @ -555,6 +793,30 @@ paths: | ||||
|           $ref: '#/components/schemas/ValidationError' | ||||
|         '403': | ||||
|           $ref: '#/components/schemas/GenericError' | ||||
|     post: | ||||
|       operationId: authenticators_admin_totp_create | ||||
|       description: Viewset for totp authenticator devices (for admins) | ||||
|       tags: | ||||
|       - authenticators | ||||
|       requestBody: | ||||
|         content: | ||||
|           application/json: | ||||
|             schema: | ||||
|               $ref: '#/components/schemas/TOTPDeviceRequest' | ||||
|         required: true | ||||
|       security: | ||||
|       - authentik: [] | ||||
|       responses: | ||||
|         '201': | ||||
|           content: | ||||
|             application/json: | ||||
|               schema: | ||||
|                 $ref: '#/components/schemas/TOTPDevice' | ||||
|           description: '' | ||||
|         '400': | ||||
|           $ref: '#/components/schemas/ValidationError' | ||||
|         '403': | ||||
|           $ref: '#/components/schemas/GenericError' | ||||
|   /authenticators/admin/totp/{id}/: | ||||
|     get: | ||||
|       operationId: authenticators_admin_totp_retrieve | ||||
| @ -581,6 +843,88 @@ paths: | ||||
|           $ref: '#/components/schemas/ValidationError' | ||||
|         '403': | ||||
|           $ref: '#/components/schemas/GenericError' | ||||
|     put: | ||||
|       operationId: authenticators_admin_totp_update | ||||
|       description: Viewset for totp authenticator devices (for admins) | ||||
|       parameters: | ||||
|       - in: path | ||||
|         name: id | ||||
|         schema: | ||||
|           type: integer | ||||
|         description: A unique integer value identifying this TOTP device. | ||||
|         required: true | ||||
|       tags: | ||||
|       - authenticators | ||||
|       requestBody: | ||||
|         content: | ||||
|           application/json: | ||||
|             schema: | ||||
|               $ref: '#/components/schemas/TOTPDeviceRequest' | ||||
|         required: true | ||||
|       security: | ||||
|       - authentik: [] | ||||
|       responses: | ||||
|         '200': | ||||
|           content: | ||||
|             application/json: | ||||
|               schema: | ||||
|                 $ref: '#/components/schemas/TOTPDevice' | ||||
|           description: '' | ||||
|         '400': | ||||
|           $ref: '#/components/schemas/ValidationError' | ||||
|         '403': | ||||
|           $ref: '#/components/schemas/GenericError' | ||||
|     patch: | ||||
|       operationId: authenticators_admin_totp_partial_update | ||||
|       description: Viewset for totp authenticator devices (for admins) | ||||
|       parameters: | ||||
|       - in: path | ||||
|         name: id | ||||
|         schema: | ||||
|           type: integer | ||||
|         description: A unique integer value identifying this TOTP device. | ||||
|         required: true | ||||
|       tags: | ||||
|       - authenticators | ||||
|       requestBody: | ||||
|         content: | ||||
|           application/json: | ||||
|             schema: | ||||
|               $ref: '#/components/schemas/PatchedTOTPDeviceRequest' | ||||
|       security: | ||||
|       - authentik: [] | ||||
|       responses: | ||||
|         '200': | ||||
|           content: | ||||
|             application/json: | ||||
|               schema: | ||||
|                 $ref: '#/components/schemas/TOTPDevice' | ||||
|           description: '' | ||||
|         '400': | ||||
|           $ref: '#/components/schemas/ValidationError' | ||||
|         '403': | ||||
|           $ref: '#/components/schemas/GenericError' | ||||
|     delete: | ||||
|       operationId: authenticators_admin_totp_destroy | ||||
|       description: Viewset for totp authenticator devices (for admins) | ||||
|       parameters: | ||||
|       - in: path | ||||
|         name: id | ||||
|         schema: | ||||
|           type: integer | ||||
|         description: A unique integer value identifying this TOTP device. | ||||
|         required: true | ||||
|       tags: | ||||
|       - authenticators | ||||
|       security: | ||||
|       - authentik: [] | ||||
|       responses: | ||||
|         '204': | ||||
|           description: No response body | ||||
|         '400': | ||||
|           $ref: '#/components/schemas/ValidationError' | ||||
|         '403': | ||||
|           $ref: '#/components/schemas/GenericError' | ||||
|   /authenticators/admin/webauthn/: | ||||
|     get: | ||||
|       operationId: authenticators_admin_webauthn_list | ||||
| @ -629,6 +973,30 @@ paths: | ||||
|           $ref: '#/components/schemas/ValidationError' | ||||
|         '403': | ||||
|           $ref: '#/components/schemas/GenericError' | ||||
|     post: | ||||
|       operationId: authenticators_admin_webauthn_create | ||||
|       description: Viewset for WebAuthn authenticator devices (for admins) | ||||
|       tags: | ||||
|       - authenticators | ||||
|       requestBody: | ||||
|         content: | ||||
|           application/json: | ||||
|             schema: | ||||
|               $ref: '#/components/schemas/WebAuthnDeviceRequest' | ||||
|         required: true | ||||
|       security: | ||||
|       - authentik: [] | ||||
|       responses: | ||||
|         '201': | ||||
|           content: | ||||
|             application/json: | ||||
|               schema: | ||||
|                 $ref: '#/components/schemas/WebAuthnDevice' | ||||
|           description: '' | ||||
|         '400': | ||||
|           $ref: '#/components/schemas/ValidationError' | ||||
|         '403': | ||||
|           $ref: '#/components/schemas/GenericError' | ||||
|   /authenticators/admin/webauthn/{id}/: | ||||
|     get: | ||||
|       operationId: authenticators_admin_webauthn_retrieve | ||||
| @ -655,6 +1023,88 @@ paths: | ||||
|           $ref: '#/components/schemas/ValidationError' | ||||
|         '403': | ||||
|           $ref: '#/components/schemas/GenericError' | ||||
|     put: | ||||
|       operationId: authenticators_admin_webauthn_update | ||||
|       description: Viewset for WebAuthn authenticator devices (for admins) | ||||
|       parameters: | ||||
|       - in: path | ||||
|         name: id | ||||
|         schema: | ||||
|           type: integer | ||||
|         description: A unique integer value identifying this WebAuthn Device. | ||||
|         required: true | ||||
|       tags: | ||||
|       - authenticators | ||||
|       requestBody: | ||||
|         content: | ||||
|           application/json: | ||||
|             schema: | ||||
|               $ref: '#/components/schemas/WebAuthnDeviceRequest' | ||||
|         required: true | ||||
|       security: | ||||
|       - authentik: [] | ||||
|       responses: | ||||
|         '200': | ||||
|           content: | ||||
|             application/json: | ||||
|               schema: | ||||
|                 $ref: '#/components/schemas/WebAuthnDevice' | ||||
|           description: '' | ||||
|         '400': | ||||
|           $ref: '#/components/schemas/ValidationError' | ||||
|         '403': | ||||
|           $ref: '#/components/schemas/GenericError' | ||||
|     patch: | ||||
|       operationId: authenticators_admin_webauthn_partial_update | ||||
|       description: Viewset for WebAuthn authenticator devices (for admins) | ||||
|       parameters: | ||||
|       - in: path | ||||
|         name: id | ||||
|         schema: | ||||
|           type: integer | ||||
|         description: A unique integer value identifying this WebAuthn Device. | ||||
|         required: true | ||||
|       tags: | ||||
|       - authenticators | ||||
|       requestBody: | ||||
|         content: | ||||
|           application/json: | ||||
|             schema: | ||||
|               $ref: '#/components/schemas/PatchedWebAuthnDeviceRequest' | ||||
|       security: | ||||
|       - authentik: [] | ||||
|       responses: | ||||
|         '200': | ||||
|           content: | ||||
|             application/json: | ||||
|               schema: | ||||
|                 $ref: '#/components/schemas/WebAuthnDevice' | ||||
|           description: '' | ||||
|         '400': | ||||
|           $ref: '#/components/schemas/ValidationError' | ||||
|         '403': | ||||
|           $ref: '#/components/schemas/GenericError' | ||||
|     delete: | ||||
|       operationId: authenticators_admin_webauthn_destroy | ||||
|       description: Viewset for WebAuthn authenticator devices (for admins) | ||||
|       parameters: | ||||
|       - in: path | ||||
|         name: id | ||||
|         schema: | ||||
|           type: integer | ||||
|         description: A unique integer value identifying this WebAuthn Device. | ||||
|         required: true | ||||
|       tags: | ||||
|       - authenticators | ||||
|       security: | ||||
|       - authentik: [] | ||||
|       responses: | ||||
|         '204': | ||||
|           description: No response body | ||||
|         '400': | ||||
|           $ref: '#/components/schemas/ValidationError' | ||||
|         '403': | ||||
|           $ref: '#/components/schemas/GenericError' | ||||
|   /authenticators/all/: | ||||
|     get: | ||||
|       operationId: authenticators_all_list | ||||
| @ -1601,6 +2051,22 @@ paths: | ||||
|       operationId: core_applications_list | ||||
|       description: Custom list method that checks Policy based access instead of guardian | ||||
|       parameters: | ||||
|       - in: query | ||||
|         name: group | ||||
|         schema: | ||||
|           type: string | ||||
|       - in: query | ||||
|         name: meta_description | ||||
|         schema: | ||||
|           type: string | ||||
|       - in: query | ||||
|         name: meta_launch_url | ||||
|         schema: | ||||
|           type: string | ||||
|       - in: query | ||||
|         name: meta_publisher | ||||
|         schema: | ||||
|           type: string | ||||
|       - in: query | ||||
|         name: name | ||||
|         schema: | ||||
| @ -5403,7 +5869,7 @@ paths: | ||||
|   /flows/instances/{slug}/export/: | ||||
|     get: | ||||
|       operationId: flows_instances_export_retrieve | ||||
|       description: Export flow to .akflow file | ||||
|       description: Export flow to .yaml file | ||||
|       parameters: | ||||
|       - in: path | ||||
|         name: slug | ||||
| @ -5547,7 +6013,7 @@ paths: | ||||
|   /flows/instances/import_flow/: | ||||
|     post: | ||||
|       operationId: flows_instances_import_flow_create | ||||
|       description: Import flow from .akflow file | ||||
|       description: Import flow from .yaml file | ||||
|       tags: | ||||
|       - flows | ||||
|       requestBody: | ||||
| @ -5564,6 +6030,215 @@ paths: | ||||
|           description: Bad request | ||||
|         '403': | ||||
|           $ref: '#/components/schemas/GenericError' | ||||
|   /managed/blueprints/: | ||||
|     get: | ||||
|       operationId: managed_blueprints_list | ||||
|       description: Blueprint instances | ||||
|       parameters: | ||||
|       - in: query | ||||
|         name: name | ||||
|         schema: | ||||
|           type: string | ||||
|       - name: ordering | ||||
|         required: false | ||||
|         in: query | ||||
|         description: Which field to use when ordering the results. | ||||
|         schema: | ||||
|           type: string | ||||
|       - name: page | ||||
|         required: false | ||||
|         in: query | ||||
|         description: A page number within the paginated result set. | ||||
|         schema: | ||||
|           type: integer | ||||
|       - name: page_size | ||||
|         required: false | ||||
|         in: query | ||||
|         description: Number of results to return per page. | ||||
|         schema: | ||||
|           type: integer | ||||
|       - in: query | ||||
|         name: path | ||||
|         schema: | ||||
|           type: string | ||||
|       - name: search | ||||
|         required: false | ||||
|         in: query | ||||
|         description: A search term. | ||||
|         schema: | ||||
|           type: string | ||||
|       tags: | ||||
|       - managed | ||||
|       security: | ||||
|       - authentik: [] | ||||
|       responses: | ||||
|         '200': | ||||
|           content: | ||||
|             application/json: | ||||
|               schema: | ||||
|                 $ref: '#/components/schemas/PaginatedBlueprintInstanceList' | ||||
|           description: '' | ||||
|         '400': | ||||
|           $ref: '#/components/schemas/ValidationError' | ||||
|         '403': | ||||
|           $ref: '#/components/schemas/GenericError' | ||||
|     post: | ||||
|       operationId: managed_blueprints_create | ||||
|       description: Blueprint instances | ||||
|       tags: | ||||
|       - managed | ||||
|       requestBody: | ||||
|         content: | ||||
|           application/json: | ||||
|             schema: | ||||
|               $ref: '#/components/schemas/BlueprintInstanceRequest' | ||||
|         required: true | ||||
|       security: | ||||
|       - authentik: [] | ||||
|       responses: | ||||
|         '201': | ||||
|           content: | ||||
|             application/json: | ||||
|               schema: | ||||
|                 $ref: '#/components/schemas/BlueprintInstance' | ||||
|           description: '' | ||||
|         '400': | ||||
|           $ref: '#/components/schemas/ValidationError' | ||||
|         '403': | ||||
|           $ref: '#/components/schemas/GenericError' | ||||
|   /managed/blueprints/{instance_uuid}/: | ||||
|     get: | ||||
|       operationId: managed_blueprints_retrieve | ||||
|       description: Blueprint instances | ||||
|       parameters: | ||||
|       - in: path | ||||
|         name: instance_uuid | ||||
|         schema: | ||||
|           type: string | ||||
|           format: uuid | ||||
|         description: A UUID string identifying this Blueprint Instance. | ||||
|         required: true | ||||
|       tags: | ||||
|       - managed | ||||
|       security: | ||||
|       - authentik: [] | ||||
|       responses: | ||||
|         '200': | ||||
|           content: | ||||
|             application/json: | ||||
|               schema: | ||||
|                 $ref: '#/components/schemas/BlueprintInstance' | ||||
|           description: '' | ||||
|         '400': | ||||
|           $ref: '#/components/schemas/ValidationError' | ||||
|         '403': | ||||
|           $ref: '#/components/schemas/GenericError' | ||||
|     put: | ||||
|       operationId: managed_blueprints_update | ||||
|       description: Blueprint instances | ||||
|       parameters: | ||||
|       - in: path | ||||
|         name: instance_uuid | ||||
|         schema: | ||||
|           type: string | ||||
|           format: uuid | ||||
|         description: A UUID string identifying this Blueprint Instance. | ||||
|         required: true | ||||
|       tags: | ||||
|       - managed | ||||
|       requestBody: | ||||
|         content: | ||||
|           application/json: | ||||
|             schema: | ||||
|               $ref: '#/components/schemas/BlueprintInstanceRequest' | ||||
|         required: true | ||||
|       security: | ||||
|       - authentik: [] | ||||
|       responses: | ||||
|         '200': | ||||
|           content: | ||||
|             application/json: | ||||
|               schema: | ||||
|                 $ref: '#/components/schemas/BlueprintInstance' | ||||
|           description: '' | ||||
|         '400': | ||||
|           $ref: '#/components/schemas/ValidationError' | ||||
|         '403': | ||||
|           $ref: '#/components/schemas/GenericError' | ||||
|     patch: | ||||
|       operationId: managed_blueprints_partial_update | ||||
|       description: Blueprint instances | ||||
|       parameters: | ||||
|       - in: path | ||||
|         name: instance_uuid | ||||
|         schema: | ||||
|           type: string | ||||
|           format: uuid | ||||
|         description: A UUID string identifying this Blueprint Instance. | ||||
|         required: true | ||||
|       tags: | ||||
|       - managed | ||||
|       requestBody: | ||||
|         content: | ||||
|           application/json: | ||||
|             schema: | ||||
|               $ref: '#/components/schemas/PatchedBlueprintInstanceRequest' | ||||
|       security: | ||||
|       - authentik: [] | ||||
|       responses: | ||||
|         '200': | ||||
|           content: | ||||
|             application/json: | ||||
|               schema: | ||||
|                 $ref: '#/components/schemas/BlueprintInstance' | ||||
|           description: '' | ||||
|         '400': | ||||
|           $ref: '#/components/schemas/ValidationError' | ||||
|         '403': | ||||
|           $ref: '#/components/schemas/GenericError' | ||||
|     delete: | ||||
|       operationId: managed_blueprints_destroy | ||||
|       description: Blueprint instances | ||||
|       parameters: | ||||
|       - in: path | ||||
|         name: instance_uuid | ||||
|         schema: | ||||
|           type: string | ||||
|           format: uuid | ||||
|         description: A UUID string identifying this Blueprint Instance. | ||||
|         required: true | ||||
|       tags: | ||||
|       - managed | ||||
|       security: | ||||
|       - authentik: [] | ||||
|       responses: | ||||
|         '204': | ||||
|           description: No response body | ||||
|         '400': | ||||
|           $ref: '#/components/schemas/ValidationError' | ||||
|         '403': | ||||
|           $ref: '#/components/schemas/GenericError' | ||||
|   /managed/blueprints/available/: | ||||
|     get: | ||||
|       operationId: managed_blueprints_available_list | ||||
|       description: Get blueprints | ||||
|       tags: | ||||
|       - managed | ||||
|       security: | ||||
|       - authentik: [] | ||||
|       responses: | ||||
|         '200': | ||||
|           content: | ||||
|             application/json: | ||||
|               schema: | ||||
|                 type: array | ||||
|                 items: | ||||
|                   type: string | ||||
|           description: '' | ||||
|         '400': | ||||
|           $ref: '#/components/schemas/ValidationError' | ||||
|         '403': | ||||
|           $ref: '#/components/schemas/GenericError' | ||||
|   /oauth2/authorization_codes/: | ||||
|     get: | ||||
|       operationId: oauth2_authorization_codes_list | ||||
| @ -7679,12 +8354,12 @@ paths: | ||||
|           enum: | ||||
|           - authentik.admin | ||||
|           - authentik.api | ||||
|           - authentik.blueprints | ||||
|           - authentik.core | ||||
|           - authentik.crypto | ||||
|           - authentik.events | ||||
|           - authentik.flows | ||||
|           - authentik.lib | ||||
|           - authentik.managed | ||||
|           - authentik.outposts | ||||
|           - authentik.policies | ||||
|           - authentik.policies.dummy | ||||
| @ -19141,7 +19816,7 @@ components: | ||||
|       - authentik.stages.user_logout | ||||
|       - authentik.stages.user_write | ||||
|       - authentik.tenants | ||||
|       - authentik.managed | ||||
|       - authentik.blueprints | ||||
|       - authentik.core | ||||
|       type: string | ||||
|     AppleChallengeResponseRequest: | ||||
| @ -20187,6 +20862,60 @@ components: | ||||
|       - POST | ||||
|       - POST_AUTO | ||||
|       type: string | ||||
|     BlueprintInstance: | ||||
|       type: object | ||||
|       description: Info about a single blueprint instance file | ||||
|       properties: | ||||
|         name: | ||||
|           type: string | ||||
|         path: | ||||
|           type: string | ||||
|         context: | ||||
|           type: object | ||||
|           additionalProperties: {} | ||||
|         last_applied: | ||||
|           type: string | ||||
|           format: date-time | ||||
|           readOnly: true | ||||
|         status: | ||||
|           $ref: '#/components/schemas/BlueprintInstanceStatusEnum' | ||||
|         enabled: | ||||
|           type: boolean | ||||
|       required: | ||||
|       - context | ||||
|       - last_applied | ||||
|       - name | ||||
|       - path | ||||
|       - status | ||||
|     BlueprintInstanceRequest: | ||||
|       type: object | ||||
|       description: Info about a single blueprint instance file | ||||
|       properties: | ||||
|         name: | ||||
|           type: string | ||||
|           minLength: 1 | ||||
|         path: | ||||
|           type: string | ||||
|           minLength: 1 | ||||
|         context: | ||||
|           type: object | ||||
|           additionalProperties: {} | ||||
|         status: | ||||
|           $ref: '#/components/schemas/BlueprintInstanceStatusEnum' | ||||
|         enabled: | ||||
|           type: boolean | ||||
|       required: | ||||
|       - context | ||||
|       - name | ||||
|       - path | ||||
|       - status | ||||
|     BlueprintInstanceStatusEnum: | ||||
|       enum: | ||||
|       - successful | ||||
|       - warning | ||||
|       - error | ||||
|       - unknown | ||||
|       type: string | ||||
|     Cache: | ||||
|       type: object | ||||
|       description: Generic cache stats for an object | ||||
| @ -20523,11 +21252,14 @@ components: | ||||
|           type: array | ||||
|           items: | ||||
|             $ref: '#/components/schemas/Permission' | ||||
|         token: | ||||
|           type: string | ||||
|       required: | ||||
|       - additional_permissions | ||||
|       - pending_user | ||||
|       - pending_user_avatar | ||||
|       - permissions | ||||
|       - token | ||||
|       - type | ||||
|     ConsentChallengeResponseRequest: | ||||
|       type: object | ||||
| @ -20537,6 +21269,11 @@ components: | ||||
|           type: string | ||||
|           minLength: 1 | ||||
|           default: ak-stage-consent | ||||
|         token: | ||||
|           type: string | ||||
|           minLength: 1 | ||||
|       required: | ||||
|       - token | ||||
|     ConsentStage: | ||||
|       type: object | ||||
|       description: ConsentStage Serializer | ||||
| @ -20742,7 +21479,10 @@ components: | ||||
|         type: | ||||
|           type: string | ||||
|           readOnly: true | ||||
|         confirmed: | ||||
|           type: boolean | ||||
|       required: | ||||
|       - confirmed | ||||
|       - meta_model_name | ||||
|       - name | ||||
|       - pk | ||||
| @ -24096,6 +24836,41 @@ components: | ||||
|       required: | ||||
|       - pagination | ||||
|       - results | ||||
|     PaginatedBlueprintInstanceList: | ||||
|       type: object | ||||
|       properties: | ||||
|         pagination: | ||||
|           type: object | ||||
|           properties: | ||||
|             next: | ||||
|               type: number | ||||
|             previous: | ||||
|               type: number | ||||
|             count: | ||||
|               type: number | ||||
|             current: | ||||
|               type: number | ||||
|             total_pages: | ||||
|               type: number | ||||
|             start_index: | ||||
|               type: number | ||||
|             end_index: | ||||
|               type: number | ||||
|           required: | ||||
|           - next | ||||
|           - previous | ||||
|           - count | ||||
|           - current | ||||
|           - total_pages | ||||
|           - start_index | ||||
|           - end_index | ||||
|         results: | ||||
|           type: array | ||||
|           items: | ||||
|             $ref: '#/components/schemas/BlueprintInstance' | ||||
|       required: | ||||
|       - pagination | ||||
|       - results | ||||
|     PaginatedCaptchaStageList: | ||||
|       type: object | ||||
|       properties: | ||||
| @ -27003,6 +27778,23 @@ components: | ||||
|           minLength: 1 | ||||
|           description: If any of the user's device has been used within this threshold, | ||||
|             this stage will be skipped | ||||
|     PatchedBlueprintInstanceRequest: | ||||
|       type: object | ||||
|       description: Info about a single blueprint instance file | ||||
|       properties: | ||||
|         name: | ||||
|           type: string | ||||
|           minLength: 1 | ||||
|         path: | ||||
|           type: string | ||||
|           minLength: 1 | ||||
|         context: | ||||
|           type: object | ||||
|           additionalProperties: {} | ||||
|         status: | ||||
|           $ref: '#/components/schemas/BlueprintInstanceStatusEnum' | ||||
|         enabled: | ||||
|           type: boolean | ||||
|     PatchedCaptchaStageRequest: | ||||
|       type: object | ||||
|       description: CaptchaStage Serializer | ||||
| @ -30822,13 +31614,6 @@ components: | ||||
|           maxLength: 16 | ||||
|       required: | ||||
|       - token | ||||
|     StatusEnum: | ||||
|       enum: | ||||
|       - SUCCESSFUL | ||||
|       - WARNING | ||||
|       - ERROR | ||||
|       - UNKNOWN | ||||
|       type: string | ||||
|     SubModeEnum: | ||||
|       enum: | ||||
|       - hashed_user_id | ||||
| @ -30937,7 +31722,7 @@ components: | ||||
|           type: string | ||||
|           format: date-time | ||||
|         status: | ||||
|           $ref: '#/components/schemas/StatusEnum' | ||||
|           $ref: '#/components/schemas/TaskStatusEnum' | ||||
|         messages: | ||||
|           type: array | ||||
|           items: {} | ||||
| @ -30947,6 +31732,13 @@ components: | ||||
|       - task_description | ||||
|       - task_finish_timestamp | ||||
|       - task_name | ||||
|     TaskStatusEnum: | ||||
|       enum: | ||||
|       - SUCCESSFUL | ||||
|       - WARNING | ||||
|       - ERROR | ||||
|       - UNKNOWN | ||||
|       type: string | ||||
|     Tenant: | ||||
|       type: object | ||||
|       description: Tenant Serializer | ||||
|  | ||||
							
								
								
									
										14
									
								
								web/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										14
									
								
								web/package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -21,7 +21,7 @@ | ||||
|                 "@codemirror/legacy-modes": "^6.1.0", | ||||
|                 "@formatjs/intl-listformat": "^7.0.3", | ||||
|                 "@fortawesome/fontawesome-free": "^6.1.1", | ||||
|                 "@goauthentik/api": "^2022.7.2-1657137907", | ||||
|                 "@goauthentik/api": "^2022.7.3-1659304078", | ||||
|                 "@jackfranklin/rollup-plugin-markdown": "^0.4.0", | ||||
|                 "@lingui/cli": "^3.14.0", | ||||
|                 "@lingui/core": "^3.14.0", | ||||
| @ -1922,9 +1922,9 @@ | ||||
|             } | ||||
|         }, | ||||
|         "node_modules/@goauthentik/api": { | ||||
|             "version": "2022.7.2-1657137907", | ||||
|             "resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2022.7.2-1657137907.tgz", | ||||
|             "integrity": "sha512-dNyoxWOhLpBMFY3u5v0DiWnqzbEApru87Dkl09i9tgAq5TEjENZbE5xsZO8IpjoZJ8rb8uYqFXyBgVLK9mBvgw==" | ||||
|             "version": "2022.7.3-1659304078", | ||||
|             "resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2022.7.3-1659304078.tgz", | ||||
|             "integrity": "sha512-dWvWB7mlhEZtbFJPVsUCK8Pyxb2lTJhOFmG6oAPVFI0k+TN9HGjY+0FSD+wto+Y9fWq6rPo4lZLaPVJluaA0WA==" | ||||
|         }, | ||||
|         "node_modules/@humanwhocodes/config-array": { | ||||
|             "version": "0.9.2", | ||||
| @ -10384,9 +10384,9 @@ | ||||
|             "integrity": "sha512-J/3yg2AIXc9wznaVqpHVX3Wa5jwKovVF0AMYSnbmcXTiL3PpRPfF58pzWucCwEiCJBp+hCNRLWClTomD8SseKg==" | ||||
|         }, | ||||
|         "@goauthentik/api": { | ||||
|             "version": "2022.7.2-1657137907", | ||||
|             "resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2022.7.2-1657137907.tgz", | ||||
|             "integrity": "sha512-dNyoxWOhLpBMFY3u5v0DiWnqzbEApru87Dkl09i9tgAq5TEjENZbE5xsZO8IpjoZJ8rb8uYqFXyBgVLK9mBvgw==" | ||||
|             "version": "2022.7.3-1659304078", | ||||
|             "resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2022.7.3-1659304078.tgz", | ||||
|             "integrity": "sha512-dWvWB7mlhEZtbFJPVsUCK8Pyxb2lTJhOFmG6oAPVFI0k+TN9HGjY+0FSD+wto+Y9fWq6rPo4lZLaPVJluaA0WA==" | ||||
|         }, | ||||
|         "@humanwhocodes/config-array": { | ||||
|             "version": "0.9.2", | ||||
|  | ||||
| @ -64,7 +64,7 @@ | ||||
|         "@codemirror/legacy-modes": "^6.1.0", | ||||
|         "@formatjs/intl-listformat": "^7.0.3", | ||||
|         "@fortawesome/fontawesome-free": "^6.1.1", | ||||
|         "@goauthentik/api": "^2022.7.2-1657137907", | ||||
|         "@goauthentik/api": "^2022.7.3-1659304078", | ||||
|         "@jackfranklin/rollup-plugin-markdown": "^0.4.0", | ||||
|         "@lingui/cli": "^3.14.0", | ||||
|         "@lingui/core": "^3.14.0", | ||||
|  | ||||
| @ -32,6 +32,7 @@ export class UserConsentList extends Table<UserConsent> { | ||||
|         return [ | ||||
|             new TableColumn(t`Application`, "application"), | ||||
|             new TableColumn(t`Expires`, "expires"), | ||||
|             new TableColumn(t`Permissions`, "permissions"), | ||||
|         ]; | ||||
|     } | ||||
|  | ||||
| @ -58,6 +59,10 @@ export class UserConsentList extends Table<UserConsent> { | ||||
|     } | ||||
|  | ||||
|     row(item: UserConsent): TemplateResult[] { | ||||
|         return [html`${item.application.name}`, html`${item.expires?.toLocaleString()}`]; | ||||
|         return [ | ||||
|             html`${item.application.name}`, | ||||
|             html`${item.expires?.toLocaleString()}`, | ||||
|             html`${item.permissions || "-"}`, | ||||
|         ]; | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -23,17 +23,19 @@ export function readFileAsync(file: Blob) { | ||||
|     }); | ||||
| } | ||||
|  | ||||
| export type KeyUnknown = { | ||||
|     [key: string]: unknown; | ||||
| }; | ||||
|  | ||||
| export class BaseStage<Tin, Tout> extends LitElement { | ||||
|     host!: StageHost; | ||||
|  | ||||
|     @property({ attribute: false }) | ||||
|     challenge!: Tin; | ||||
|  | ||||
|     async submitForm(e: Event): Promise<boolean> { | ||||
|     async submitForm(e: Event, defaults?: KeyUnknown): Promise<boolean> { | ||||
|         e.preventDefault(); | ||||
|         const object: { | ||||
|             [key: string]: unknown; | ||||
|         } = {}; | ||||
|         const object: KeyUnknown = defaults || {}; | ||||
|         const form = new FormData(this.shadowRoot?.querySelector("form") || undefined); | ||||
|  | ||||
|         for await (const [key, value] of form.entries()) { | ||||
|  | ||||
| @ -107,7 +107,9 @@ export class ConsentStage extends BaseStage<ConsentChallenge, ConsentChallengeRe | ||||
|                 <form | ||||
|                     class="pf-c-form" | ||||
|                     @submit=${(e: Event) => { | ||||
|                         this.submitForm(e); | ||||
|                         this.submitForm(e, { | ||||
|                             token: this.challenge.token, | ||||
|                         }); | ||||
|                     }} | ||||
|                 > | ||||
|                     <ak-form-static | ||||
|  | ||||
| @ -7,7 +7,7 @@ import { t } from "@lingui/macro"; | ||||
|  | ||||
| import { customElement } from "lit/decorators.js"; | ||||
|  | ||||
| import { SourcesApi, StatusEnum } from "@goauthentik/api"; | ||||
| import { SourcesApi, TaskStatusEnum } from "@goauthentik/api"; | ||||
|  | ||||
| interface LDAPSyncStats { | ||||
|     healthy: number; | ||||
| @ -50,7 +50,7 @@ export class LDAPSyncStatusChart extends AKChart<LDAPSyncStats> { | ||||
|                     }); | ||||
|  | ||||
|                     health.forEach((task) => { | ||||
|                         if (task.status !== StatusEnum.Successful) { | ||||
|                         if (task.status !== TaskStatusEnum.Successful) { | ||||
|                             sourceKey = "failed"; | ||||
|                         } | ||||
|                         const now = new Date().getTime(); | ||||
|  | ||||
| @ -24,7 +24,7 @@ import PFPage from "@patternfly/patternfly/components/Page/page.css"; | ||||
| import PFGrid from "@patternfly/patternfly/layouts/Grid/grid.css"; | ||||
| import PFBase from "@patternfly/patternfly/patternfly-base.css"; | ||||
|  | ||||
| import { LDAPSource, SourcesApi, StatusEnum } from "@goauthentik/api"; | ||||
| import { LDAPSource, SourcesApi, TaskStatusEnum } from "@goauthentik/api"; | ||||
|  | ||||
| @customElement("ak-source-ldap-view") | ||||
| export class LDAPSourceViewPage extends LitElement { | ||||
| @ -145,9 +145,9 @@ export class LDAPSourceViewPage extends LitElement { | ||||
|                                         return html`<ul class="pf-c-list"> | ||||
|                                             ${tasks.map((task) => { | ||||
|                                                 let header = ""; | ||||
|                                                 if (task.status === StatusEnum.Warning) { | ||||
|                                                 if (task.status === TaskStatusEnum.Warning) { | ||||
|                                                     header = t`Task finished with warnings`; | ||||
|                                                 } else if (task.status === StatusEnum.Error) { | ||||
|                                                 } else if (task.status === TaskStatusEnum.Error) { | ||||
|                                                     header = t`Task finished with errors`; | ||||
|                                                 } else { | ||||
|                                                     header = t`Last sync: ${task.taskFinishTimestamp.toLocaleString()}`; | ||||
|  | ||||
| @ -14,7 +14,7 @@ import { customElement, property } from "lit/decorators.js"; | ||||
|  | ||||
| import PFDescriptionList from "@patternfly/patternfly/components/DescriptionList/description-list.css"; | ||||
|  | ||||
| import { AdminApi, StatusEnum, Task } from "@goauthentik/api"; | ||||
| import { AdminApi, Task, TaskStatusEnum } from "@goauthentik/api"; | ||||
|  | ||||
| @customElement("ak-system-task-list") | ||||
| export class SystemTaskListPage extends TablePage<Task> { | ||||
| @ -67,11 +67,11 @@ export class SystemTaskListPage extends TablePage<Task> { | ||||
|  | ||||
|     taskStatus(task: Task): TemplateResult { | ||||
|         switch (task.status) { | ||||
|             case StatusEnum.Successful: | ||||
|             case TaskStatusEnum.Successful: | ||||
|                 return html`<ak-label color=${PFColor.Green}>${t`Successful`}</ak-label>`; | ||||
|             case StatusEnum.Warning: | ||||
|             case TaskStatusEnum.Warning: | ||||
|                 return html`<ak-label color=${PFColor.Orange}>${t`Warning`}</ak-label>`; | ||||
|             case StatusEnum.Error: | ||||
|             case TaskStatusEnum.Error: | ||||
|                 return html`<ak-label color=${PFColor.Red}>${t`Error`}</ak-label>`; | ||||
|             default: | ||||
|                 return html`<ak-label color=${PFColor.Grey}>${t`Unknown`}</ak-label>`; | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	