stages/authenticator_validate: add ability to select multiple configuration stages which the user can choose
closes #1843 Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
		| @ -13,8 +13,8 @@ class AuthenticatorValidateStageSerializer(StageSerializer): | ||||
|  | ||||
|     def validate_not_configured_action(self, value): | ||||
|         """Ensure that a configuration stage is set when not_configured_action is configure""" | ||||
|         configuration_stage = self.initial_data.get("configuration_stage") | ||||
|         if value == NotConfiguredAction.CONFIGURE and configuration_stage is None: | ||||
|         configuration_stages = self.initial_data.get("configuration_stages") | ||||
|         if value == NotConfiguredAction.CONFIGURE and configuration_stages is None: | ||||
|             raise ValidationError( | ||||
|                 ( | ||||
|                     'When "Not configured action" is set to "Configure", ' | ||||
| @ -29,7 +29,7 @@ class AuthenticatorValidateStageSerializer(StageSerializer): | ||||
|         fields = StageSerializer.Meta.fields + [ | ||||
|             "not_configured_action", | ||||
|             "device_classes", | ||||
|             "configuration_stage", | ||||
|             "configuration_stages", | ||||
|         ] | ||||
|  | ||||
|  | ||||
| @ -38,5 +38,5 @@ class AuthenticatorValidateStageViewSet(UsedByMixin, ModelViewSet): | ||||
|  | ||||
|     queryset = AuthenticatorValidateStage.objects.all() | ||||
|     serializer_class = AuthenticatorValidateStageSerializer | ||||
|     filterset_fields = ["name", "not_configured_action", "configuration_stage"] | ||||
|     filterset_fields = ["name", "not_configured_action", "configuration_stages"] | ||||
|     ordering = ["name"] | ||||
|  | ||||
| @ -0,0 +1,44 @@ | ||||
| # Generated by Django 4.0.1 on 2022-01-05 22:09 | ||||
|  | ||||
| from django.apps.registry import Apps | ||||
| from django.db import migrations, models | ||||
| from django.db.backends.base.schema import BaseDatabaseSchemaEditor | ||||
|  | ||||
|  | ||||
| def migrate_configuration_stage(apps: Apps, schema_editor: BaseDatabaseSchemaEditor): | ||||
|     db_alias = schema_editor.connection.alias | ||||
|     AuthenticatorValidateStage = apps.get_model( | ||||
|         "authentik_stages_authenticator_validate", "AuthenticatorValidateStage" | ||||
|     ) | ||||
|  | ||||
|     for stage in AuthenticatorValidateStage.objects.using(db_alias).all(): | ||||
|         if stage.configuration_stage: | ||||
|             stage.configuration_stages.set([stage.configuration_stage]) | ||||
|             stage.save() | ||||
|  | ||||
|  | ||||
| class Migration(migrations.Migration): | ||||
|  | ||||
|     dependencies = [ | ||||
|         ("authentik_flows", "0021_auto_20211227_2103"), | ||||
|         ("authentik_stages_authenticator_validate", "0009_default_stage"), | ||||
|     ] | ||||
|  | ||||
|     operations = [ | ||||
|         migrations.AddField( | ||||
|             model_name="authenticatorvalidatestage", | ||||
|             name="configuration_stages", | ||||
|             field=models.ManyToManyField( | ||||
|                 blank=True, | ||||
|                 default=None, | ||||
|                 help_text="Stages used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again.", | ||||
|                 related_name="+", | ||||
|                 to="authentik_flows.Stage", | ||||
|             ), | ||||
|         ), | ||||
|         migrations.RunPython(migrate_configuration_stage), | ||||
|         migrations.RemoveField( | ||||
|             model_name="authenticatorvalidatestage", | ||||
|             name="configuration_stage", | ||||
|         ), | ||||
|     ] | ||||
| @ -38,16 +38,14 @@ class AuthenticatorValidateStage(Stage): | ||||
|         choices=NotConfiguredAction.choices, default=NotConfiguredAction.SKIP | ||||
|     ) | ||||
|  | ||||
|     configuration_stage = models.ForeignKey( | ||||
|     configuration_stages = models.ManyToManyField( | ||||
|         Stage, | ||||
|         null=True, | ||||
|         blank=True, | ||||
|         default=None, | ||||
|         on_delete=models.SET_DEFAULT, | ||||
|         related_name="+", | ||||
|         help_text=_( | ||||
|             ( | ||||
|                 "Stage used to configure Authenticator when user doesn't have any compatible " | ||||
|                 "Stages used to configure Authenticator when user doesn't have any compatible " | ||||
|                 "devices. After this configuration Stage passes, the user is not prompted again." | ||||
|             ) | ||||
|         ), | ||||
|  | ||||
| @ -1,10 +1,12 @@ | ||||
| """Authenticator Validation""" | ||||
| from django.http import HttpRequest, HttpResponse | ||||
| from django_otp import devices_for_user | ||||
| from rest_framework.fields import CharField, IntegerField, JSONField, ListField | ||||
| from rest_framework.fields import CharField, IntegerField, JSONField, ListField, UUIDField | ||||
| from rest_framework.serializers import ValidationError | ||||
| from structlog.stdlib import get_logger | ||||
|  | ||||
| from authentik.core.api.utils import PassiveSerializer | ||||
| from authentik.core.models import User | ||||
| from authentik.events.models import Event, EventAction | ||||
| from authentik.events.utils import cleanse_dict, sanitize_dict | ||||
| from authentik.flows.challenge import ChallengeResponse, ChallengeTypes, WithUserInfoChallenge | ||||
| @ -26,6 +28,18 @@ from authentik.stages.authenticator_webauthn.models import WebAuthnDevice | ||||
| from authentik.stages.password.stage import PLAN_CONTEXT_METHOD, PLAN_CONTEXT_METHOD_ARGS | ||||
|  | ||||
| LOGGER = get_logger() | ||||
| SESSION_STAGES = "goauthentik.io/stages/authenticator_validate/stages" | ||||
| SESSION_SELECTED_STAGE = "goauthentik.io/stages/authenticator_validate/selected_stage" | ||||
| SESSION_DEVICE_CHALLENGES = "goauthentik.io/stages/authenticator_validate/device_challenges" | ||||
|  | ||||
|  | ||||
| class SelectableStageSerializer(PassiveSerializer): | ||||
|     """Serializer for stages which can be selected by users""" | ||||
|  | ||||
|     pk = UUIDField() | ||||
|     name = CharField() | ||||
|     verbose_name = CharField() | ||||
|     meta_model_name = CharField() | ||||
|  | ||||
|  | ||||
| class AuthenticatorValidationChallenge(WithUserInfoChallenge): | ||||
| @ -33,12 +47,14 @@ class AuthenticatorValidationChallenge(WithUserInfoChallenge): | ||||
|  | ||||
|     device_challenges = ListField(child=DeviceChallenge()) | ||||
|     component = CharField(default="ak-stage-authenticator-validate") | ||||
|     configuration_stages = ListField(child=SelectableStageSerializer()) | ||||
|  | ||||
|  | ||||
| class AuthenticatorValidationChallengeResponse(ChallengeResponse): | ||||
|     """Challenge used for Code-based and WebAuthn authenticators""" | ||||
|  | ||||
|     selected_challenge = DeviceChallenge(required=False) | ||||
|     selected_stage = CharField(required=False) | ||||
|  | ||||
|     code = CharField(required=False) | ||||
|     webauthn = JSONField(required=False) | ||||
| @ -84,6 +100,15 @@ class AuthenticatorValidationChallengeResponse(ChallengeResponse): | ||||
|         select_challenge(self.stage.request, devices.first()) | ||||
|         return challenge | ||||
|  | ||||
|     def validate_selected_stage(self, stage_pk: str) -> str: | ||||
|         """Check that the selected stage is valid""" | ||||
|         stages = self.stage.request.session.get(SESSION_STAGES, []) | ||||
|         if not any(str(stage.pk) == stage_pk for stage in stages): | ||||
|             raise ValidationError("Selected stage is invalid") | ||||
|         LOGGER.debug("Setting selected stage to ", stage=stage_pk) | ||||
|         self.stage.request.session[SESSION_SELECTED_STAGE] = stage_pk | ||||
|         return stage_pk | ||||
|  | ||||
|     def validate(self, attrs: dict): | ||||
|         # Checking if the given data is from a valid device class is done above | ||||
|         # Here we only check if the any data was sent at all | ||||
| @ -164,7 +189,7 @@ class AuthenticatorValidateStageView(ChallengeStageView): | ||||
|             else: | ||||
|                 LOGGER.debug("No pending user, continuing") | ||||
|                 return self.executor.stage_ok() | ||||
|         self.request.session["device_challenges"] = challenges | ||||
|         self.request.session[SESSION_DEVICE_CHALLENGES] = challenges | ||||
|  | ||||
|         # No allowed devices | ||||
|         if len(challenges) < 1: | ||||
| @ -175,35 +200,71 @@ class AuthenticatorValidateStageView(ChallengeStageView): | ||||
|                 LOGGER.debug("Authenticator not configured, denying") | ||||
|                 return self.executor.stage_invalid() | ||||
|             if stage.not_configured_action == NotConfiguredAction.CONFIGURE: | ||||
|                 if not stage.configuration_stage: | ||||
|                     Event.new( | ||||
|                         EventAction.CONFIGURATION_ERROR, | ||||
|                         message=( | ||||
|                             "Authenticator validation stage is set to configure user " | ||||
|                             "but no configuration flow is set." | ||||
|                         ), | ||||
|                         stage=self, | ||||
|                     ).from_http(self.request).set_user(user).save() | ||||
|                     return self.executor.stage_invalid() | ||||
|                 LOGGER.debug("Authenticator not configured, sending user to configure") | ||||
|                 # Because the foreign key to stage.configuration_stage points to | ||||
|                 # a base stage class, we need to do another lookup | ||||
|                 stage = Stage.objects.get_subclass(pk=stage.configuration_stage.pk) | ||||
|                 # plan.insert inserts at 1 index, so when stage_ok pops 0, | ||||
|                 # the configuration stage is next | ||||
|                 self.executor.plan.insert_stage(stage) | ||||
|                 return self.executor.stage_ok() | ||||
|                 LOGGER.debug("Authenticator not configured, forcing configure") | ||||
|                 return self.prepare_stages(user) | ||||
|         return super().get(request, *args, **kwargs) | ||||
|  | ||||
|     def get_challenge(self) -> AuthenticatorValidationChallenge: | ||||
|         challenges = self.request.session.get("device_challenges") | ||||
|         if not challenges: | ||||
|             LOGGER.debug("Authenticator Validation stage ran without challenges") | ||||
|     def prepare_stages(self, user: User, *args, **kwargs) -> HttpResponse: | ||||
|         """Check how the user can configure themselves. If no stages are set, return an error. | ||||
|         If a single stage is set, insert that stage directly. If multiple are selected, include | ||||
|         them in the challenge.""" | ||||
|         stage: AuthenticatorValidateStage = self.executor.current_stage | ||||
|         if not stage.configuration_stages.exists(): | ||||
|             Event.new( | ||||
|                 EventAction.CONFIGURATION_ERROR, | ||||
|                 message=( | ||||
|                     "Authenticator validation stage is set to configure user " | ||||
|                     "but no configuration flow is set." | ||||
|                 ), | ||||
|                 stage=self, | ||||
|             ).from_http(self.request).set_user(user).save() | ||||
|             return self.executor.stage_invalid() | ||||
|         if stage.configuration_stages.count() == 1: | ||||
|             self.request.session[SESSION_SELECTED_STAGE] = stage.configuration_stages.first() | ||||
|             LOGGER.debug( | ||||
|                 "Single stage configured, auto-selecting", | ||||
|                 stage=self.request.session[SESSION_SELECTED_STAGE], | ||||
|             ) | ||||
|         stages = Stage.objects.filter(pk__in=stage.configuration_stages.all()).select_subclasses() | ||||
|         self.request.session[SESSION_STAGES] = stages | ||||
|         return super().get(self.request, *args, **kwargs) | ||||
|  | ||||
|     def post(self, request: HttpRequest, *args, **kwargs) -> HttpResponse: | ||||
|         if ( | ||||
|             SESSION_SELECTED_STAGE in self.request.session | ||||
|             and self.executor.current_stage.not_configured_action == NotConfiguredAction.CONFIGURE | ||||
|         ): | ||||
|             LOGGER.debug("Got selected stage in session, running that") | ||||
|             stage_pk = self.request.session.get(SESSION_SELECTED_STAGE) | ||||
|             # Because the foreign key to stage.configuration_stage points to | ||||
|             # a base stage class, we need to do another lookup | ||||
|             stage = Stage.objects.get_subclass(pk=stage_pk) | ||||
|             # plan.insert inserts at 1 index, so when stage_ok pops 0, | ||||
|             # the configuration stage is next | ||||
|             self.executor.plan.insert_stage(stage) | ||||
|             return self.executor.stage_ok() | ||||
|         return super().post(request, *args, **kwargs) | ||||
|  | ||||
|     def get_challenge(self) -> AuthenticatorValidationChallenge: | ||||
|         challenges = self.request.session.get(SESSION_DEVICE_CHALLENGES, []) | ||||
|         stages = self.request.session.get(SESSION_STAGES, []) | ||||
|         stage_challenges = [] | ||||
|         for stage in stages: | ||||
|             serializer = SelectableStageSerializer( | ||||
|                 data={ | ||||
|                     "pk": stage.pk, | ||||
|                     "name": stage.name, | ||||
|                     "verbose_name": str(stage._meta.verbose_name), | ||||
|                     "meta_model_name": f"{stage._meta.app_label}.{stage._meta.model_name}", | ||||
|                 } | ||||
|             ) | ||||
|             serializer.is_valid() | ||||
|             stage_challenges.append(serializer.data) | ||||
|         return AuthenticatorValidationChallenge( | ||||
|             data={ | ||||
|                 "type": ChallengeTypes.NATIVE.value, | ||||
|                 "device_challenges": challenges, | ||||
|                 "configuration_stages": stage_challenges, | ||||
|             } | ||||
|         ) | ||||
|  | ||||
|  | ||||
| @ -43,8 +43,8 @@ class AuthenticatorValidateStageTests(FlowTestCase): | ||||
|         stage = AuthenticatorValidateStage.objects.create( | ||||
|             name="foo", | ||||
|             not_configured_action=NotConfiguredAction.CONFIGURE, | ||||
|             configuration_stage=conf_stage, | ||||
|         ) | ||||
|         stage.configuration_stages.set([conf_stage]) | ||||
|         flow = Flow.objects.create(name="test", slug="test", title="test") | ||||
|         FlowStageBinding.objects.create(target=flow, stage=conf_stage, order=0) | ||||
|         FlowStageBinding.objects.create(target=flow, stage=stage, order=1) | ||||
|  | ||||
							
								
								
									
										69
									
								
								schema.yml
									
									
									
									
									
								
							
							
						
						
									
										69
									
								
								schema.yml
									
									
									
									
									
								
							| @ -15045,10 +15045,14 @@ paths: | ||||
|       description: AuthenticatorValidateStage Viewset | ||||
|       parameters: | ||||
|       - in: query | ||||
|         name: configuration_stage | ||||
|         name: configuration_stages | ||||
|         schema: | ||||
|           type: string | ||||
|           format: uuid | ||||
|           type: array | ||||
|           items: | ||||
|             type: string | ||||
|             format: uuid | ||||
|         explode: true | ||||
|         style: form | ||||
|       - in: query | ||||
|         name: name | ||||
|         schema: | ||||
| @ -19826,11 +19830,12 @@ components: | ||||
|           items: | ||||
|             $ref: '#/components/schemas/DeviceClassesEnum' | ||||
|           description: Device classes which can be used to authenticate | ||||
|         configuration_stage: | ||||
|           type: string | ||||
|           format: uuid | ||||
|           nullable: true | ||||
|           description: Stage used to configure Authenticator when user doesn't have | ||||
|         configuration_stages: | ||||
|           type: array | ||||
|           items: | ||||
|             type: string | ||||
|             format: uuid | ||||
|           description: Stages used to configure Authenticator when user doesn't have | ||||
|             any compatible devices. After this configuration Stage passes, the user | ||||
|             is not prompted again. | ||||
|       required: | ||||
| @ -19858,11 +19863,12 @@ components: | ||||
|           items: | ||||
|             $ref: '#/components/schemas/DeviceClassesEnum' | ||||
|           description: Device classes which can be used to authenticate | ||||
|         configuration_stage: | ||||
|           type: string | ||||
|           format: uuid | ||||
|           nullable: true | ||||
|           description: Stage used to configure Authenticator when user doesn't have | ||||
|         configuration_stages: | ||||
|           type: array | ||||
|           items: | ||||
|             type: string | ||||
|             format: uuid | ||||
|           description: Stages used to configure Authenticator when user doesn't have | ||||
|             any compatible devices. After this configuration Stage passes, the user | ||||
|             is not prompted again. | ||||
|       required: | ||||
| @ -19892,7 +19898,12 @@ components: | ||||
|           type: array | ||||
|           items: | ||||
|             $ref: '#/components/schemas/DeviceChallenge' | ||||
|         configuration_stages: | ||||
|           type: array | ||||
|           items: | ||||
|             $ref: '#/components/schemas/SelectableStage' | ||||
|       required: | ||||
|       - configuration_stages | ||||
|       - device_challenges | ||||
|       - pending_user | ||||
|       - pending_user_avatar | ||||
| @ -19907,6 +19918,9 @@ components: | ||||
|           default: ak-stage-authenticator-validate | ||||
|         selected_challenge: | ||||
|           $ref: '#/components/schemas/DeviceChallengeRequest' | ||||
|         selected_stage: | ||||
|           type: string | ||||
|           minLength: 1 | ||||
|         code: | ||||
|           type: string | ||||
|           minLength: 1 | ||||
| @ -26677,11 +26691,12 @@ components: | ||||
|           items: | ||||
|             $ref: '#/components/schemas/DeviceClassesEnum' | ||||
|           description: Device classes which can be used to authenticate | ||||
|         configuration_stage: | ||||
|           type: string | ||||
|           format: uuid | ||||
|           nullable: true | ||||
|           description: Stage used to configure Authenticator when user doesn't have | ||||
|         configuration_stages: | ||||
|           type: array | ||||
|           items: | ||||
|             type: string | ||||
|             format: uuid | ||||
|           description: Stages used to configure Authenticator when user doesn't have | ||||
|             any compatible devices. After this configuration Stage passes, the user | ||||
|             is not prompted again. | ||||
|     PatchedCaptchaStageRequest: | ||||
| @ -30017,6 +30032,24 @@ components: | ||||
|       - direct | ||||
|       - cached | ||||
|       type: string | ||||
|     SelectableStage: | ||||
|       type: object | ||||
|       description: Serializer for stages which can be selected by users | ||||
|       properties: | ||||
|         pk: | ||||
|           type: string | ||||
|           format: uuid | ||||
|         name: | ||||
|           type: string | ||||
|         verbose_name: | ||||
|           type: string | ||||
|         meta_model_name: | ||||
|           type: string | ||||
|       required: | ||||
|       - meta_model_name | ||||
|       - name | ||||
|       - pk | ||||
|       - verbose_name | ||||
|     ServiceConnection: | ||||
|       type: object | ||||
|       description: ServiceConnection Serializer | ||||
|  | ||||
| @ -67,7 +67,7 @@ export class AuthenticatorValidateStage | ||||
|         return this._selectedDeviceChallenge; | ||||
|     } | ||||
|  | ||||
|     submit(payload: AuthenticatorValidationChallengeResponseRequest): Promise<void> { | ||||
|     submit(payload: AuthenticatorValidationChallengeResponseRequest): Promise<boolean> { | ||||
|         return this.host?.submit(payload) || Promise.resolve(); | ||||
|     } | ||||
|  | ||||
| @ -140,7 +140,7 @@ export class AuthenticatorValidateStage | ||||
|     } | ||||
|  | ||||
|     renderDevicePicker(): TemplateResult { | ||||
|         return html` <ul> | ||||
|         return html`<ul> | ||||
|             ${this.challenge?.deviceChallenges.map((challenges) => { | ||||
|                 return html`<li> | ||||
|                     <button | ||||
| @ -157,6 +157,30 @@ export class AuthenticatorValidateStage | ||||
|         </ul>`; | ||||
|     } | ||||
|  | ||||
|     renderStagePicker(): TemplateResult { | ||||
|         return html`<ul> | ||||
|             ${this.challenge?.configurationStages.map((stage) => { | ||||
|                 return html`<li> | ||||
|                     <button | ||||
|                         class="pf-c-button authenticator-button" | ||||
|                         type="button" | ||||
|                         @click=${() => { | ||||
|                             this.submit({ | ||||
|                                 component: this.challenge.component || "", | ||||
|                                 selectedStage: stage.pk, | ||||
|                             }); | ||||
|                         }} | ||||
|                     > | ||||
|                         <div class="right"> | ||||
|                             <p>${stage.name}</p> | ||||
|                             <small>${stage.verboseName}</small> | ||||
|                         </div> | ||||
|                     </button> | ||||
|                 </li>`; | ||||
|             })} | ||||
|         </ul>`; | ||||
|     } | ||||
|  | ||||
|     renderDeviceChallenge(): TemplateResult { | ||||
|         if (!this.selectedDeviceChallenge) { | ||||
|             return html``; | ||||
| @ -242,6 +266,9 @@ export class AuthenticatorValidateStage | ||||
|                               ${this.selectedDeviceChallenge | ||||
|                                   ? "" | ||||
|                                   : html`<p>${t`Select an authentication method.`}</p>`} | ||||
|                               ${this.challenge.configurationStages.length > 0 | ||||
|                                   ? this.renderStagePicker() | ||||
|                                   : html``} | ||||
|                           </form> | ||||
|                           ${this.renderDevicePicker()} | ||||
|                       </div> | ||||
|  | ||||
| @ -959,8 +959,12 @@ msgid "Configuration flow" | ||||
| msgstr "Ablauf der Konfiguration" | ||||
|  | ||||
| #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts | ||||
| msgid "Configuration stage" | ||||
| msgstr "Konfiguration Stufe" | ||||
| #~ msgid "Configuration stage" | ||||
| #~ msgstr "Konfiguration Stufe" | ||||
|  | ||||
| #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts | ||||
| msgid "Configuration stages" | ||||
| msgstr "" | ||||
|  | ||||
| #~ msgid "Configure WebAuthn" | ||||
| #~ msgstr "Konfiguriere WebAuthn" | ||||
| @ -4410,8 +4414,8 @@ msgid "Stage type" | ||||
| msgstr "Phasen Typ" | ||||
|  | ||||
| #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts | ||||
| msgid "Stage used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again." | ||||
| msgstr "Phase zum Konfigurieren von Authenticator, wenn der Benutzer keine kompatiblen Geräte hat. Nach Ablauf dieser Konfigurationsphase wird der Benutzer nicht erneut aufgefordert." | ||||
| #~ msgid "Stage used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again." | ||||
| #~ msgstr "Phase zum Konfigurieren von Authenticator, wenn der Benutzer keine kompatiblen Geräte hat. Nach Ablauf dieser Konfigurationsphase wird der Benutzer nicht erneut aufgefordert." | ||||
|  | ||||
| #: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts | ||||
| msgid "Stage used to configure a TOTP authenticator (i.e. Authy/Google Authenticator)." | ||||
| @ -4470,6 +4474,10 @@ msgstr "Phasen" | ||||
| msgid "Stages are single steps of a Flow that a user is guided through. A stage can only be executed from within a flow." | ||||
| msgstr "Phasen sind einzelne Schritte eines Flows, durch die ein Benutzer geführt wird. Eine Phase kann nur innerhalb eines Flows ausgeführt werden." | ||||
|  | ||||
| #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts | ||||
| msgid "Stages used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again." | ||||
| msgstr "" | ||||
|  | ||||
| #: src/pages/outposts/ServiceConnectionListPage.ts | ||||
| msgid "State" | ||||
| msgstr "Zustand" | ||||
| @ -5935,6 +5943,10 @@ msgstr "Wenn diese Option aktiviert ist, wird die Einladung nach ihrer Benutzung | ||||
| msgid "When enabled, user fields are matched regardless of their casing." | ||||
| msgstr "Wenn diese Option aktiviert ist, werden Benutzerfelder unabhängig von ihrem Format abgeglichen." | ||||
|  | ||||
| #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts | ||||
| msgid "When multiple stages are selected, the user can choose which one they want to enroll." | ||||
| msgstr "" | ||||
|  | ||||
| #: src/pages/stages/identification/IdentificationStageForm.ts | ||||
| msgid "When selected, a password field is shown on the same page instead of a separate page. This prevents username enumeration attacks." | ||||
| msgstr "Wenn diese Option ausgewählt ist, wird ein Passwortfeld auf derselben Seite statt auf einer separaten Seite angezeigt. Dadurch werden Angriffe auf die Aufzählung von Benutzernamen verhindert." | ||||
|  | ||||
| @ -950,8 +950,12 @@ msgid "Configuration flow" | ||||
| msgstr "Flujo de configuración" | ||||
|  | ||||
| #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts | ||||
| msgid "Configuration stage" | ||||
| msgstr "Etapa de configuración" | ||||
| #~ msgid "Configuration stage" | ||||
| #~ msgstr "Etapa de configuración" | ||||
|  | ||||
| #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts | ||||
| msgid "Configuration stages" | ||||
| msgstr "" | ||||
|  | ||||
| #~ msgid "Configure WebAuthn" | ||||
| #~ msgstr "Configurar WebAuthn" | ||||
| @ -4403,8 +4407,8 @@ msgid "Stage type" | ||||
| msgstr "Tipo de escenario" | ||||
|  | ||||
| #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts | ||||
| msgid "Stage used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again." | ||||
| msgstr "Etapa utilizada para configurar Authenticator cuando el usuario no tiene ningún dispositivo compatible. Una vez superada esta etapa de configuración, no se volverá a preguntar al usuario." | ||||
| #~ msgid "Stage used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again." | ||||
| #~ msgstr "Etapa utilizada para configurar Authenticator cuando el usuario no tiene ningún dispositivo compatible. Una vez superada esta etapa de configuración, no se volverá a preguntar al usuario." | ||||
|  | ||||
| #: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts | ||||
| msgid "Stage used to configure a TOTP authenticator (i.e. Authy/Google Authenticator)." | ||||
| @ -4463,6 +4467,10 @@ msgstr "Etapas" | ||||
| msgid "Stages are single steps of a Flow that a user is guided through. A stage can only be executed from within a flow." | ||||
| msgstr "Las etapas son pasos individuales de un flujo por los que se guía al usuario. Una etapa solo se puede ejecutar desde dentro de un flujo." | ||||
|  | ||||
| #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts | ||||
| msgid "Stages used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again." | ||||
| msgstr "" | ||||
|  | ||||
| #: src/pages/outposts/ServiceConnectionListPage.ts | ||||
| msgid "State" | ||||
| msgstr "Estado" | ||||
| @ -5928,6 +5936,10 @@ msgstr "Cuando se habilita, la invitación se eliminará después de su uso." | ||||
| msgid "When enabled, user fields are matched regardless of their casing." | ||||
| msgstr "Cuando se habilita, los campos de usuario coinciden independientemente de su carcasa." | ||||
|  | ||||
| #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts | ||||
| msgid "When multiple stages are selected, the user can choose which one they want to enroll." | ||||
| msgstr "" | ||||
|  | ||||
| #: src/pages/stages/identification/IdentificationStageForm.ts | ||||
| msgid "When selected, a password field is shown on the same page instead of a separate page. This prevents username enumeration attacks." | ||||
| msgstr "Cuando se selecciona, se muestra un campo de contraseña en la misma página en lugar de en una página separada. Esto evita ataques de enumeración de nombres de usuario." | ||||
|  | ||||
| @ -947,8 +947,12 @@ msgid "Configuration flow" | ||||
| msgstr "Przepływ konfiguracji" | ||||
|  | ||||
| #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts | ||||
| msgid "Configuration stage" | ||||
| msgstr "Etap konfiguracji" | ||||
| #~ msgid "Configuration stage" | ||||
| #~ msgstr "Etap konfiguracji" | ||||
|  | ||||
| #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts | ||||
| msgid "Configuration stages" | ||||
| msgstr "" | ||||
|  | ||||
| #~ msgid "Configure WebAuthn" | ||||
| #~ msgstr "Skonfiguruj WebAuthn" | ||||
| @ -4400,8 +4404,8 @@ msgid "Stage type" | ||||
| msgstr "Typ etapu" | ||||
|  | ||||
| #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts | ||||
| msgid "Stage used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again." | ||||
| msgstr "Etap używany do konfiguracji uwierzytelniacza, gdy użytkownik nie ma żadnych kompatybilnych urządzeń. Po zakończeniu tego etapu konfiguracji użytkownik nie jest ponownie pytany." | ||||
| #~ msgid "Stage used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again." | ||||
| #~ msgstr "Etap używany do konfiguracji uwierzytelniacza, gdy użytkownik nie ma żadnych kompatybilnych urządzeń. Po zakończeniu tego etapu konfiguracji użytkownik nie jest ponownie pytany." | ||||
|  | ||||
| #: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts | ||||
| msgid "Stage used to configure a TOTP authenticator (i.e. Authy/Google Authenticator)." | ||||
| @ -4460,6 +4464,10 @@ msgstr "Etapy" | ||||
| msgid "Stages are single steps of a Flow that a user is guided through. A stage can only be executed from within a flow." | ||||
| msgstr "Etapy to pojedyncze kroki przepływu, przez które prowadzony jest użytkownik. Etap można wykonać tylko z przepływu." | ||||
|  | ||||
| #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts | ||||
| msgid "Stages used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again." | ||||
| msgstr "" | ||||
|  | ||||
| #: src/pages/outposts/ServiceConnectionListPage.ts | ||||
| msgid "State" | ||||
| msgstr "Stan" | ||||
| @ -5925,6 +5933,10 @@ msgstr "Po włączeniu zaproszenie zostanie usunięte po użyciu." | ||||
| msgid "When enabled, user fields are matched regardless of their casing." | ||||
| msgstr "Po włączeniu pola użytkownika są dopasowywane niezależnie od wielkości liter." | ||||
|  | ||||
| #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts | ||||
| msgid "When multiple stages are selected, the user can choose which one they want to enroll." | ||||
| msgstr "" | ||||
|  | ||||
| #: src/pages/stages/identification/IdentificationStageForm.ts | ||||
| msgid "When selected, a password field is shown on the same page instead of a separate page. This prevents username enumeration attacks." | ||||
| msgstr "Po wybraniu pole hasła jest wyświetlane na tej samej stronie zamiast na osobnej stronie. Zapobiega to atakom polegającym na wyliczaniu nazw użytkowników." | ||||
|  | ||||
| @ -950,8 +950,12 @@ msgid "Configuration flow" | ||||
| msgstr "Yapılandırma akışı" | ||||
|  | ||||
| #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts | ||||
| msgid "Configuration stage" | ||||
| msgstr "Yapılandırma aşamasında" | ||||
| #~ msgid "Configuration stage" | ||||
| #~ msgstr "Yapılandırma aşamasında" | ||||
|  | ||||
| #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts | ||||
| msgid "Configuration stages" | ||||
| msgstr "" | ||||
|  | ||||
| #~ msgid "Configure WebAuthn" | ||||
| #~ msgstr "WebAuthn'i Yapılandır" | ||||
| @ -4405,8 +4409,8 @@ msgid "Stage type" | ||||
| msgstr "Aşama türü" | ||||
|  | ||||
| #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts | ||||
| msgid "Stage used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again." | ||||
| msgstr "Kullanıcının uyumlu bir aygıtı olmadığında Kimlik Doğrulayıcısı'nı yapılandırmak için kullanılan Aşama. Bu yapılandırma Stage geçtikten sonra kullanıcıya yeniden istenmez." | ||||
| #~ msgid "Stage used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again." | ||||
| #~ msgstr "Kullanıcının uyumlu bir aygıtı olmadığında Kimlik Doğrulayıcısı'nı yapılandırmak için kullanılan Aşama. Bu yapılandırma Stage geçtikten sonra kullanıcıya yeniden istenmez." | ||||
|  | ||||
| #: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts | ||||
| msgid "Stage used to configure a TOTP authenticator (i.e. Authy/Google Authenticator)." | ||||
| @ -4465,6 +4469,10 @@ msgstr "Aşamalar" | ||||
| msgid "Stages are single steps of a Flow that a user is guided through. A stage can only be executed from within a flow." | ||||
| msgstr "Aşamalar, bir Akış'ın kullanıcının yönlendirildiği tek adımlardır. Bir aşama yalnızca bir akış içinden yürütülebilir." | ||||
|  | ||||
| #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts | ||||
| msgid "Stages used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again." | ||||
| msgstr "" | ||||
|  | ||||
| #: src/pages/outposts/ServiceConnectionListPage.ts | ||||
| msgid "State" | ||||
| msgstr "Eyalet" | ||||
| @ -5930,6 +5938,10 @@ msgstr "Etkinleştirildiğinde, davetiye kullanımdan sonra silinir." | ||||
| msgid "When enabled, user fields are matched regardless of their casing." | ||||
| msgstr "Etkinleştirildiğinde, kullanıcı alanları muhafazası ne olursa olsun eşleştirilir." | ||||
|  | ||||
| #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts | ||||
| msgid "When multiple stages are selected, the user can choose which one they want to enroll." | ||||
| msgstr "" | ||||
|  | ||||
| #: src/pages/stages/identification/IdentificationStageForm.ts | ||||
| msgid "When selected, a password field is shown on the same page instead of a separate page. This prevents username enumeration attacks." | ||||
| msgstr "Seçildiğinde, ayrı bir sayfa yerine aynı sayfada bir parola alanı gösterilir. Bu, kullanıcı adı numaralandırma saldırılarını engeller." | ||||
|  | ||||
| @ -948,8 +948,12 @@ msgid "Configuration flow" | ||||
| msgstr "配置流程" | ||||
|  | ||||
| #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts | ||||
| msgid "Configuration stage" | ||||
| msgstr "配置阶段" | ||||
| #~ msgid "Configuration stage" | ||||
| #~ msgstr "配置阶段" | ||||
|  | ||||
| #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts | ||||
| msgid "Configuration stages" | ||||
| msgstr "" | ||||
|  | ||||
| #~ msgid "Configure WebAuthn" | ||||
| #~ msgstr "配置 WebAuthn" | ||||
| @ -4401,8 +4405,8 @@ msgid "Stage type" | ||||
| msgstr "阶段类型" | ||||
|  | ||||
| #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts | ||||
| msgid "Stage used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again." | ||||
| msgstr "Stage 用于在用户没有任何兼容设备时配置身份验证器。此配置 Stage 通过后,不会再次提示用户。" | ||||
| #~ msgid "Stage used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again." | ||||
| #~ msgstr "Stage 用于在用户没有任何兼容设备时配置身份验证器。此配置 Stage 通过后,不会再次提示用户。" | ||||
|  | ||||
| #: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts | ||||
| msgid "Stage used to configure a TOTP authenticator (i.e. Authy/Google Authenticator)." | ||||
| @ -4461,6 +4465,10 @@ msgstr "阶段" | ||||
| msgid "Stages are single steps of a Flow that a user is guided through. A stage can only be executed from within a flow." | ||||
| msgstr "阶段是引导用户完成的流程的单个步骤。阶段只能在流程内部执行。" | ||||
|  | ||||
| #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts | ||||
| msgid "Stages used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again." | ||||
| msgstr "" | ||||
|  | ||||
| #: src/pages/outposts/ServiceConnectionListPage.ts | ||||
| msgid "State" | ||||
| msgstr "状态" | ||||
| @ -5926,6 +5934,10 @@ msgstr "启用后,邀请将在使用后被删除。" | ||||
| msgid "When enabled, user fields are matched regardless of their casing." | ||||
| msgstr "启用后,无论用户字段大小写如何,都将匹配用户字段。" | ||||
|  | ||||
| #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts | ||||
| msgid "When multiple stages are selected, the user can choose which one they want to enroll." | ||||
| msgstr "" | ||||
|  | ||||
| #: src/pages/stages/identification/IdentificationStageForm.ts | ||||
| msgid "When selected, a password field is shown on the same page instead of a separate page. This prevents username enumeration attacks." | ||||
| msgstr "选中后,密码字段将显示在同一页面上,而不是单独的页面上。这样可以防止用户名枚举攻击。" | ||||
|  | ||||
| @ -948,8 +948,12 @@ msgid "Configuration flow" | ||||
| msgstr "配置流程" | ||||
|  | ||||
| #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts | ||||
| msgid "Configuration stage" | ||||
| msgstr "配置阶段" | ||||
| #~ msgid "Configuration stage" | ||||
| #~ msgstr "配置阶段" | ||||
|  | ||||
| #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts | ||||
| msgid "Configuration stages" | ||||
| msgstr "" | ||||
|  | ||||
| #~ msgid "Configure WebAuthn" | ||||
| #~ msgstr "配置 WebAuthn" | ||||
| @ -4401,8 +4405,8 @@ msgid "Stage type" | ||||
| msgstr "阶段类型" | ||||
|  | ||||
| #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts | ||||
| msgid "Stage used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again." | ||||
| msgstr "Stage 用于在用户没有任何兼容设备时配置身份验证器。此配置 Stage 通过后,不会再次提示用户。" | ||||
| #~ msgid "Stage used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again." | ||||
| #~ msgstr "Stage 用于在用户没有任何兼容设备时配置身份验证器。此配置 Stage 通过后,不会再次提示用户。" | ||||
|  | ||||
| #: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts | ||||
| msgid "Stage used to configure a TOTP authenticator (i.e. Authy/Google Authenticator)." | ||||
| @ -4461,6 +4465,10 @@ msgstr "阶段" | ||||
| msgid "Stages are single steps of a Flow that a user is guided through. A stage can only be executed from within a flow." | ||||
| msgstr "阶段是引导用户完成的流程的单个步骤。阶段只能在流程内部执行。" | ||||
|  | ||||
| #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts | ||||
| msgid "Stages used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again." | ||||
| msgstr "" | ||||
|  | ||||
| #: src/pages/outposts/ServiceConnectionListPage.ts | ||||
| msgid "State" | ||||
| msgstr "州" | ||||
| @ -5926,6 +5934,10 @@ msgstr "启用后,邀请将在使用后被删除。" | ||||
| msgid "When enabled, user fields are matched regardless of their casing." | ||||
| msgstr "启用后,无论用户字段大小写如何,都将匹配用户字段。" | ||||
|  | ||||
| #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts | ||||
| msgid "When multiple stages are selected, the user can choose which one they want to enroll." | ||||
| msgstr "" | ||||
|  | ||||
| #: src/pages/stages/identification/IdentificationStageForm.ts | ||||
| msgid "When selected, a password field is shown on the same page instead of a separate page. This prevents username enumeration attacks." | ||||
| msgstr "选中后,密码字段将显示在同一页面上,而不是单独的页面上。这样可以防止用户名枚举攻击。" | ||||
|  | ||||
| @ -948,8 +948,12 @@ msgid "Configuration flow" | ||||
| msgstr "配置流程" | ||||
|  | ||||
| #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts | ||||
| msgid "Configuration stage" | ||||
| msgstr "配置阶段" | ||||
| #~ msgid "Configuration stage" | ||||
| #~ msgstr "配置阶段" | ||||
|  | ||||
| #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts | ||||
| msgid "Configuration stages" | ||||
| msgstr "" | ||||
|  | ||||
| #~ msgid "Configure WebAuthn" | ||||
| #~ msgstr "配置 WebAuthn" | ||||
| @ -4401,8 +4405,8 @@ msgid "Stage type" | ||||
| msgstr "阶段类型" | ||||
|  | ||||
| #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts | ||||
| msgid "Stage used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again." | ||||
| msgstr "Stage 用于在用户没有任何兼容设备时配置身份验证器。此配置 Stage 通过后,不会再次提示用户。" | ||||
| #~ msgid "Stage used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again." | ||||
| #~ msgstr "Stage 用于在用户没有任何兼容设备时配置身份验证器。此配置 Stage 通过后,不会再次提示用户。" | ||||
|  | ||||
| #: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts | ||||
| msgid "Stage used to configure a TOTP authenticator (i.e. Authy/Google Authenticator)." | ||||
| @ -4461,6 +4465,10 @@ msgstr "阶段" | ||||
| msgid "Stages are single steps of a Flow that a user is guided through. A stage can only be executed from within a flow." | ||||
| msgstr "阶段是引导用户完成的流程的单个步骤。阶段只能在流程内部执行。" | ||||
|  | ||||
| #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts | ||||
| msgid "Stages used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again." | ||||
| msgstr "" | ||||
|  | ||||
| #: src/pages/outposts/ServiceConnectionListPage.ts | ||||
| msgid "State" | ||||
| msgstr "州" | ||||
| @ -5926,6 +5934,10 @@ msgstr "启用后,邀请将在使用后被删除。" | ||||
| msgid "When enabled, user fields are matched regardless of their casing." | ||||
| msgstr "启用后,无论用户字段大小写如何,都将匹配用户字段。" | ||||
|  | ||||
| #: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts | ||||
| msgid "When multiple stages are selected, the user can choose which one they want to enroll." | ||||
| msgstr "" | ||||
|  | ||||
| #: src/pages/stages/identification/IdentificationStageForm.ts | ||||
| msgid "When selected, a password field is shown on the same page instead of a separate page. This prevents username enumeration attacks." | ||||
| msgstr "选中后,密码字段将显示在同一页面上,而不是单独的页面上。这样可以防止用户名枚举攻击。" | ||||
|  | ||||
| @ -25,14 +25,14 @@ export class AuthenticatorValidateStageForm extends ModelForm<AuthenticatorValid | ||||
|                 stageUuid: pk, | ||||
|             }) | ||||
|             .then((stage) => { | ||||
|                 this.showConfigurationStage = | ||||
|                 this.showConfigurationStages = | ||||
|                     stage.notConfiguredAction === NotConfiguredActionEnum.Configure; | ||||
|                 return stage; | ||||
|             }); | ||||
|     } | ||||
|  | ||||
|     @property({ type: Boolean }) | ||||
|     showConfigurationStage = true; | ||||
|     showConfigurationStages = true; | ||||
|  | ||||
|     getSuccessMessage(): string { | ||||
|         if (this.instance) { | ||||
| @ -136,9 +136,9 @@ export class AuthenticatorValidateStageForm extends ModelForm<AuthenticatorValid | ||||
|                                     target.selectedOptions[0].value === | ||||
|                                     NotConfiguredActionEnum.Configure | ||||
|                                 ) { | ||||
|                                     this.showConfigurationStage = true; | ||||
|                                     this.showConfigurationStages = true; | ||||
|                                 } else { | ||||
|                                     this.showConfigurationStage = false; | ||||
|                                     this.showConfigurationStages = false; | ||||
|                                 } | ||||
|                             }} | ||||
|                         > | ||||
| @ -165,21 +165,13 @@ export class AuthenticatorValidateStageForm extends ModelForm<AuthenticatorValid | ||||
|                             </option> | ||||
|                         </select> | ||||
|                     </ak-form-element-horizontal> | ||||
|                     ${this.showConfigurationStage | ||||
|                     ${this.showConfigurationStages | ||||
|                         ? html` | ||||
|                               <ak-form-element-horizontal | ||||
|                                   label=${t`Configuration stage`} | ||||
|                                   ?required=${true} | ||||
|                                   name="configurationStage" | ||||
|                                   label=${t`Configuration stages`} | ||||
|                                   name="configurationStages" | ||||
|                               > | ||||
|                                   <select class="pf-c-form-control"> | ||||
|                                       <option | ||||
|                                           value="" | ||||
|                                           ?selected=${this.instance?.configurationStage === | ||||
|                                           undefined} | ||||
|                                       > | ||||
|                                           --------- | ||||
|                                       </option> | ||||
|                                   <select class="pf-c-form-control" multiple> | ||||
|                                       ${until( | ||||
|                                           new StagesApi(DEFAULT_CONFIG) | ||||
|                                               .stagesAllList({ | ||||
| @ -187,9 +179,11 @@ export class AuthenticatorValidateStageForm extends ModelForm<AuthenticatorValid | ||||
|                                               }) | ||||
|                                               .then((stages) => { | ||||
|                                                   return stages.results.map((stage) => { | ||||
|                                                       const selected = | ||||
|                                                           this.instance?.configurationStage === | ||||
|                                                           stage.pk; | ||||
|                                                       const selected = Array.from( | ||||
|                                                           this.instance?.configurationStages || [], | ||||
|                                                       ).some((su) => { | ||||
|                                                           return su == stage.pk; | ||||
|                                                       }); | ||||
|                                                       return html`<option | ||||
|                                                           value=${ifDefined(stage.pk)} | ||||
|                                                           ?selected=${selected} | ||||
| @ -202,7 +196,10 @@ export class AuthenticatorValidateStageForm extends ModelForm<AuthenticatorValid | ||||
|                                       )} | ||||
|                                   </select> | ||||
|                                   <p class="pf-c-form__helper-text"> | ||||
|                                       ${t`Stage used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again.`} | ||||
|                                       ${t`Stages used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again.`} | ||||
|                                   </p> | ||||
|                                   <p class="pf-c-form__helper-text"> | ||||
|                                       ${t`When multiple stages are selected, the user can choose which one they want to enroll.`} | ||||
|                                   </p> | ||||
|                               </ak-form-element-horizontal> | ||||
|                           ` | ||||
|  | ||||
| @ -153,7 +153,7 @@ export class IdentificationStageForm extends ModelForm<IdentificationStage, stri | ||||
|                         ?required=${true} | ||||
|                         name="sources" | ||||
|                     > | ||||
|                         <select name="users" class="pf-c-form-control" multiple> | ||||
|                         <select class="pf-c-form-control" multiple> | ||||
|                             ${until( | ||||
|                                 new SourcesApi(DEFAULT_CONFIG) | ||||
|                                     .sourcesAllList({}) | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 Jens Langhammer
					Jens Langhammer