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:
parent
9070df6c26
commit
2ccab75021
|
@ -13,8 +13,8 @@ class AuthenticatorValidateStageSerializer(StageSerializer):
|
||||||
|
|
||||||
def validate_not_configured_action(self, value):
|
def validate_not_configured_action(self, value):
|
||||||
"""Ensure that a configuration stage is set when not_configured_action is configure"""
|
"""Ensure that a configuration stage is set when not_configured_action is configure"""
|
||||||
configuration_stage = self.initial_data.get("configuration_stage")
|
configuration_stages = self.initial_data.get("configuration_stages")
|
||||||
if value == NotConfiguredAction.CONFIGURE and configuration_stage is None:
|
if value == NotConfiguredAction.CONFIGURE and configuration_stages is None:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
(
|
(
|
||||||
'When "Not configured action" is set to "Configure", '
|
'When "Not configured action" is set to "Configure", '
|
||||||
|
@ -29,7 +29,7 @@ class AuthenticatorValidateStageSerializer(StageSerializer):
|
||||||
fields = StageSerializer.Meta.fields + [
|
fields = StageSerializer.Meta.fields + [
|
||||||
"not_configured_action",
|
"not_configured_action",
|
||||||
"device_classes",
|
"device_classes",
|
||||||
"configuration_stage",
|
"configuration_stages",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -38,5 +38,5 @@ class AuthenticatorValidateStageViewSet(UsedByMixin, ModelViewSet):
|
||||||
|
|
||||||
queryset = AuthenticatorValidateStage.objects.all()
|
queryset = AuthenticatorValidateStage.objects.all()
|
||||||
serializer_class = AuthenticatorValidateStageSerializer
|
serializer_class = AuthenticatorValidateStageSerializer
|
||||||
filterset_fields = ["name", "not_configured_action", "configuration_stage"]
|
filterset_fields = ["name", "not_configured_action", "configuration_stages"]
|
||||||
ordering = ["name"]
|
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
|
choices=NotConfiguredAction.choices, default=NotConfiguredAction.SKIP
|
||||||
)
|
)
|
||||||
|
|
||||||
configuration_stage = models.ForeignKey(
|
configuration_stages = models.ManyToManyField(
|
||||||
Stage,
|
Stage,
|
||||||
null=True,
|
|
||||||
blank=True,
|
blank=True,
|
||||||
default=None,
|
default=None,
|
||||||
on_delete=models.SET_DEFAULT,
|
|
||||||
related_name="+",
|
related_name="+",
|
||||||
help_text=_(
|
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."
|
"devices. After this configuration Stage passes, the user is not prompted again."
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
"""Authenticator Validation"""
|
"""Authenticator Validation"""
|
||||||
from django.http import HttpRequest, HttpResponse
|
from django.http import HttpRequest, HttpResponse
|
||||||
from django_otp import devices_for_user
|
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 rest_framework.serializers import ValidationError
|
||||||
from structlog.stdlib import get_logger
|
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.models import Event, EventAction
|
||||||
from authentik.events.utils import cleanse_dict, sanitize_dict
|
from authentik.events.utils import cleanse_dict, sanitize_dict
|
||||||
from authentik.flows.challenge import ChallengeResponse, ChallengeTypes, WithUserInfoChallenge
|
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
|
from authentik.stages.password.stage import PLAN_CONTEXT_METHOD, PLAN_CONTEXT_METHOD_ARGS
|
||||||
|
|
||||||
LOGGER = get_logger()
|
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):
|
class AuthenticatorValidationChallenge(WithUserInfoChallenge):
|
||||||
|
@ -33,12 +47,14 @@ class AuthenticatorValidationChallenge(WithUserInfoChallenge):
|
||||||
|
|
||||||
device_challenges = ListField(child=DeviceChallenge())
|
device_challenges = ListField(child=DeviceChallenge())
|
||||||
component = CharField(default="ak-stage-authenticator-validate")
|
component = CharField(default="ak-stage-authenticator-validate")
|
||||||
|
configuration_stages = ListField(child=SelectableStageSerializer())
|
||||||
|
|
||||||
|
|
||||||
class AuthenticatorValidationChallengeResponse(ChallengeResponse):
|
class AuthenticatorValidationChallengeResponse(ChallengeResponse):
|
||||||
"""Challenge used for Code-based and WebAuthn authenticators"""
|
"""Challenge used for Code-based and WebAuthn authenticators"""
|
||||||
|
|
||||||
selected_challenge = DeviceChallenge(required=False)
|
selected_challenge = DeviceChallenge(required=False)
|
||||||
|
selected_stage = CharField(required=False)
|
||||||
|
|
||||||
code = CharField(required=False)
|
code = CharField(required=False)
|
||||||
webauthn = JSONField(required=False)
|
webauthn = JSONField(required=False)
|
||||||
|
@ -84,6 +100,15 @@ class AuthenticatorValidationChallengeResponse(ChallengeResponse):
|
||||||
select_challenge(self.stage.request, devices.first())
|
select_challenge(self.stage.request, devices.first())
|
||||||
return challenge
|
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):
|
def validate(self, attrs: dict):
|
||||||
# Checking if the given data is from a valid device class is done above
|
# 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
|
# Here we only check if the any data was sent at all
|
||||||
|
@ -164,7 +189,7 @@ class AuthenticatorValidateStageView(ChallengeStageView):
|
||||||
else:
|
else:
|
||||||
LOGGER.debug("No pending user, continuing")
|
LOGGER.debug("No pending user, continuing")
|
||||||
return self.executor.stage_ok()
|
return self.executor.stage_ok()
|
||||||
self.request.session["device_challenges"] = challenges
|
self.request.session[SESSION_DEVICE_CHALLENGES] = challenges
|
||||||
|
|
||||||
# No allowed devices
|
# No allowed devices
|
||||||
if len(challenges) < 1:
|
if len(challenges) < 1:
|
||||||
|
@ -175,7 +200,16 @@ class AuthenticatorValidateStageView(ChallengeStageView):
|
||||||
LOGGER.debug("Authenticator not configured, denying")
|
LOGGER.debug("Authenticator not configured, denying")
|
||||||
return self.executor.stage_invalid()
|
return self.executor.stage_invalid()
|
||||||
if stage.not_configured_action == NotConfiguredAction.CONFIGURE:
|
if stage.not_configured_action == NotConfiguredAction.CONFIGURE:
|
||||||
if not stage.configuration_stage:
|
LOGGER.debug("Authenticator not configured, forcing configure")
|
||||||
|
return self.prepare_stages(user)
|
||||||
|
return super().get(request, *args, **kwargs)
|
||||||
|
|
||||||
|
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(
|
Event.new(
|
||||||
EventAction.CONFIGURATION_ERROR,
|
EventAction.CONFIGURATION_ERROR,
|
||||||
message=(
|
message=(
|
||||||
|
@ -185,25 +219,52 @@ class AuthenticatorValidateStageView(ChallengeStageView):
|
||||||
stage=self,
|
stage=self,
|
||||||
).from_http(self.request).set_user(user).save()
|
).from_http(self.request).set_user(user).save()
|
||||||
return self.executor.stage_invalid()
|
return self.executor.stage_invalid()
|
||||||
LOGGER.debug("Authenticator not configured, sending user to configure")
|
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
|
# Because the foreign key to stage.configuration_stage points to
|
||||||
# a base stage class, we need to do another lookup
|
# a base stage class, we need to do another lookup
|
||||||
stage = Stage.objects.get_subclass(pk=stage.configuration_stage.pk)
|
stage = Stage.objects.get_subclass(pk=stage_pk)
|
||||||
# plan.insert inserts at 1 index, so when stage_ok pops 0,
|
# plan.insert inserts at 1 index, so when stage_ok pops 0,
|
||||||
# the configuration stage is next
|
# the configuration stage is next
|
||||||
self.executor.plan.insert_stage(stage)
|
self.executor.plan.insert_stage(stage)
|
||||||
return self.executor.stage_ok()
|
return self.executor.stage_ok()
|
||||||
return super().get(request, *args, **kwargs)
|
return super().post(request, *args, **kwargs)
|
||||||
|
|
||||||
def get_challenge(self) -> AuthenticatorValidationChallenge:
|
def get_challenge(self) -> AuthenticatorValidationChallenge:
|
||||||
challenges = self.request.session.get("device_challenges")
|
challenges = self.request.session.get(SESSION_DEVICE_CHALLENGES, [])
|
||||||
if not challenges:
|
stages = self.request.session.get(SESSION_STAGES, [])
|
||||||
LOGGER.debug("Authenticator Validation stage ran without challenges")
|
stage_challenges = []
|
||||||
return self.executor.stage_invalid()
|
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(
|
return AuthenticatorValidationChallenge(
|
||||||
data={
|
data={
|
||||||
"type": ChallengeTypes.NATIVE.value,
|
"type": ChallengeTypes.NATIVE.value,
|
||||||
"device_challenges": challenges,
|
"device_challenges": challenges,
|
||||||
|
"configuration_stages": stage_challenges,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -43,8 +43,8 @@ class AuthenticatorValidateStageTests(FlowTestCase):
|
||||||
stage = AuthenticatorValidateStage.objects.create(
|
stage = AuthenticatorValidateStage.objects.create(
|
||||||
name="foo",
|
name="foo",
|
||||||
not_configured_action=NotConfiguredAction.CONFIGURE,
|
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")
|
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=conf_stage, order=0)
|
||||||
FlowStageBinding.objects.create(target=flow, stage=stage, order=1)
|
FlowStageBinding.objects.create(target=flow, stage=stage, order=1)
|
||||||
|
|
53
schema.yml
53
schema.yml
|
@ -15045,10 +15045,14 @@ paths:
|
||||||
description: AuthenticatorValidateStage Viewset
|
description: AuthenticatorValidateStage Viewset
|
||||||
parameters:
|
parameters:
|
||||||
- in: query
|
- in: query
|
||||||
name: configuration_stage
|
name: configuration_stages
|
||||||
schema:
|
schema:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
type: string
|
type: string
|
||||||
format: uuid
|
format: uuid
|
||||||
|
explode: true
|
||||||
|
style: form
|
||||||
- in: query
|
- in: query
|
||||||
name: name
|
name: name
|
||||||
schema:
|
schema:
|
||||||
|
@ -19826,11 +19830,12 @@ components:
|
||||||
items:
|
items:
|
||||||
$ref: '#/components/schemas/DeviceClassesEnum'
|
$ref: '#/components/schemas/DeviceClassesEnum'
|
||||||
description: Device classes which can be used to authenticate
|
description: Device classes which can be used to authenticate
|
||||||
configuration_stage:
|
configuration_stages:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
type: string
|
type: string
|
||||||
format: uuid
|
format: uuid
|
||||||
nullable: true
|
description: Stages used to configure Authenticator when user doesn't have
|
||||||
description: Stage used to configure Authenticator when user doesn't have
|
|
||||||
any compatible devices. After this configuration Stage passes, the user
|
any compatible devices. After this configuration Stage passes, the user
|
||||||
is not prompted again.
|
is not prompted again.
|
||||||
required:
|
required:
|
||||||
|
@ -19858,11 +19863,12 @@ components:
|
||||||
items:
|
items:
|
||||||
$ref: '#/components/schemas/DeviceClassesEnum'
|
$ref: '#/components/schemas/DeviceClassesEnum'
|
||||||
description: Device classes which can be used to authenticate
|
description: Device classes which can be used to authenticate
|
||||||
configuration_stage:
|
configuration_stages:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
type: string
|
type: string
|
||||||
format: uuid
|
format: uuid
|
||||||
nullable: true
|
description: Stages used to configure Authenticator when user doesn't have
|
||||||
description: Stage used to configure Authenticator when user doesn't have
|
|
||||||
any compatible devices. After this configuration Stage passes, the user
|
any compatible devices. After this configuration Stage passes, the user
|
||||||
is not prompted again.
|
is not prompted again.
|
||||||
required:
|
required:
|
||||||
|
@ -19892,7 +19898,12 @@ components:
|
||||||
type: array
|
type: array
|
||||||
items:
|
items:
|
||||||
$ref: '#/components/schemas/DeviceChallenge'
|
$ref: '#/components/schemas/DeviceChallenge'
|
||||||
|
configuration_stages:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
$ref: '#/components/schemas/SelectableStage'
|
||||||
required:
|
required:
|
||||||
|
- configuration_stages
|
||||||
- device_challenges
|
- device_challenges
|
||||||
- pending_user
|
- pending_user
|
||||||
- pending_user_avatar
|
- pending_user_avatar
|
||||||
|
@ -19907,6 +19918,9 @@ components:
|
||||||
default: ak-stage-authenticator-validate
|
default: ak-stage-authenticator-validate
|
||||||
selected_challenge:
|
selected_challenge:
|
||||||
$ref: '#/components/schemas/DeviceChallengeRequest'
|
$ref: '#/components/schemas/DeviceChallengeRequest'
|
||||||
|
selected_stage:
|
||||||
|
type: string
|
||||||
|
minLength: 1
|
||||||
code:
|
code:
|
||||||
type: string
|
type: string
|
||||||
minLength: 1
|
minLength: 1
|
||||||
|
@ -26677,11 +26691,12 @@ components:
|
||||||
items:
|
items:
|
||||||
$ref: '#/components/schemas/DeviceClassesEnum'
|
$ref: '#/components/schemas/DeviceClassesEnum'
|
||||||
description: Device classes which can be used to authenticate
|
description: Device classes which can be used to authenticate
|
||||||
configuration_stage:
|
configuration_stages:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
type: string
|
type: string
|
||||||
format: uuid
|
format: uuid
|
||||||
nullable: true
|
description: Stages used to configure Authenticator when user doesn't have
|
||||||
description: Stage used to configure Authenticator when user doesn't have
|
|
||||||
any compatible devices. After this configuration Stage passes, the user
|
any compatible devices. After this configuration Stage passes, the user
|
||||||
is not prompted again.
|
is not prompted again.
|
||||||
PatchedCaptchaStageRequest:
|
PatchedCaptchaStageRequest:
|
||||||
|
@ -30017,6 +30032,24 @@ components:
|
||||||
- direct
|
- direct
|
||||||
- cached
|
- cached
|
||||||
type: string
|
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:
|
ServiceConnection:
|
||||||
type: object
|
type: object
|
||||||
description: ServiceConnection Serializer
|
description: ServiceConnection Serializer
|
||||||
|
|
|
@ -67,7 +67,7 @@ export class AuthenticatorValidateStage
|
||||||
return this._selectedDeviceChallenge;
|
return this._selectedDeviceChallenge;
|
||||||
}
|
}
|
||||||
|
|
||||||
submit(payload: AuthenticatorValidationChallengeResponseRequest): Promise<void> {
|
submit(payload: AuthenticatorValidationChallengeResponseRequest): Promise<boolean> {
|
||||||
return this.host?.submit(payload) || Promise.resolve();
|
return this.host?.submit(payload) || Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +140,7 @@ export class AuthenticatorValidateStage
|
||||||
}
|
}
|
||||||
|
|
||||||
renderDevicePicker(): TemplateResult {
|
renderDevicePicker(): TemplateResult {
|
||||||
return html` <ul>
|
return html`<ul>
|
||||||
${this.challenge?.deviceChallenges.map((challenges) => {
|
${this.challenge?.deviceChallenges.map((challenges) => {
|
||||||
return html`<li>
|
return html`<li>
|
||||||
<button
|
<button
|
||||||
|
@ -157,6 +157,30 @@ export class AuthenticatorValidateStage
|
||||||
</ul>`;
|
</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 {
|
renderDeviceChallenge(): TemplateResult {
|
||||||
if (!this.selectedDeviceChallenge) {
|
if (!this.selectedDeviceChallenge) {
|
||||||
return html``;
|
return html``;
|
||||||
|
@ -242,6 +266,9 @@ export class AuthenticatorValidateStage
|
||||||
${this.selectedDeviceChallenge
|
${this.selectedDeviceChallenge
|
||||||
? ""
|
? ""
|
||||||
: html`<p>${t`Select an authentication method.`}</p>`}
|
: html`<p>${t`Select an authentication method.`}</p>`}
|
||||||
|
${this.challenge.configurationStages.length > 0
|
||||||
|
? this.renderStagePicker()
|
||||||
|
: html``}
|
||||||
</form>
|
</form>
|
||||||
${this.renderDevicePicker()}
|
${this.renderDevicePicker()}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -959,8 +959,12 @@ msgid "Configuration flow"
|
||||||
msgstr "Ablauf der Konfiguration"
|
msgstr "Ablauf der Konfiguration"
|
||||||
|
|
||||||
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
|
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
|
||||||
msgid "Configuration stage"
|
#~ msgid "Configuration stage"
|
||||||
msgstr "Konfiguration Stufe"
|
#~ msgstr "Konfiguration Stufe"
|
||||||
|
|
||||||
|
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
|
||||||
|
msgid "Configuration stages"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Configure WebAuthn"
|
#~ msgid "Configure WebAuthn"
|
||||||
#~ msgstr "Konfiguriere WebAuthn"
|
#~ msgstr "Konfiguriere WebAuthn"
|
||||||
|
@ -4410,8 +4414,8 @@ msgid "Stage type"
|
||||||
msgstr "Phasen Typ"
|
msgstr "Phasen Typ"
|
||||||
|
|
||||||
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
|
#: 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."
|
#~ 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."
|
#~ 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
|
#: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
|
||||||
msgid "Stage used to configure a TOTP authenticator (i.e. Authy/Google Authenticator)."
|
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."
|
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."
|
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
|
#: src/pages/outposts/ServiceConnectionListPage.ts
|
||||||
msgid "State"
|
msgid "State"
|
||||||
msgstr "Zustand"
|
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."
|
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."
|
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
|
#: 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."
|
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."
|
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"
|
msgstr "Flujo de configuración"
|
||||||
|
|
||||||
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
|
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
|
||||||
msgid "Configuration stage"
|
#~ msgid "Configuration stage"
|
||||||
msgstr "Etapa de configuración"
|
#~ msgstr "Etapa de configuración"
|
||||||
|
|
||||||
|
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
|
||||||
|
msgid "Configuration stages"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Configure WebAuthn"
|
#~ msgid "Configure WebAuthn"
|
||||||
#~ msgstr "Configurar WebAuthn"
|
#~ msgstr "Configurar WebAuthn"
|
||||||
|
@ -4403,8 +4407,8 @@ msgid "Stage type"
|
||||||
msgstr "Tipo de escenario"
|
msgstr "Tipo de escenario"
|
||||||
|
|
||||||
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
|
#: 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."
|
#~ 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."
|
#~ 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
|
#: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
|
||||||
msgid "Stage used to configure a TOTP authenticator (i.e. Authy/Google Authenticator)."
|
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."
|
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."
|
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
|
#: src/pages/outposts/ServiceConnectionListPage.ts
|
||||||
msgid "State"
|
msgid "State"
|
||||||
msgstr "Estado"
|
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."
|
msgid "When enabled, user fields are matched regardless of their casing."
|
||||||
msgstr "Cuando se habilita, los campos de usuario coinciden independientemente de su carcasa."
|
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
|
#: 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."
|
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."
|
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"
|
msgstr "Przepływ konfiguracji"
|
||||||
|
|
||||||
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
|
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
|
||||||
msgid "Configuration stage"
|
#~ msgid "Configuration stage"
|
||||||
msgstr "Etap konfiguracji"
|
#~ msgstr "Etap konfiguracji"
|
||||||
|
|
||||||
|
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
|
||||||
|
msgid "Configuration stages"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Configure WebAuthn"
|
#~ msgid "Configure WebAuthn"
|
||||||
#~ msgstr "Skonfiguruj WebAuthn"
|
#~ msgstr "Skonfiguruj WebAuthn"
|
||||||
|
@ -4400,8 +4404,8 @@ msgid "Stage type"
|
||||||
msgstr "Typ etapu"
|
msgstr "Typ etapu"
|
||||||
|
|
||||||
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
|
#: 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."
|
#~ 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."
|
#~ 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
|
#: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
|
||||||
msgid "Stage used to configure a TOTP authenticator (i.e. Authy/Google Authenticator)."
|
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."
|
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."
|
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
|
#: src/pages/outposts/ServiceConnectionListPage.ts
|
||||||
msgid "State"
|
msgid "State"
|
||||||
msgstr "Stan"
|
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."
|
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."
|
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
|
#: 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."
|
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."
|
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ışı"
|
msgstr "Yapılandırma akışı"
|
||||||
|
|
||||||
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
|
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
|
||||||
msgid "Configuration stage"
|
#~ msgid "Configuration stage"
|
||||||
msgstr "Yapılandırma aşamasında"
|
#~ msgstr "Yapılandırma aşamasında"
|
||||||
|
|
||||||
|
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
|
||||||
|
msgid "Configuration stages"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Configure WebAuthn"
|
#~ msgid "Configure WebAuthn"
|
||||||
#~ msgstr "WebAuthn'i Yapılandır"
|
#~ msgstr "WebAuthn'i Yapılandır"
|
||||||
|
@ -4405,8 +4409,8 @@ msgid "Stage type"
|
||||||
msgstr "Aşama türü"
|
msgstr "Aşama türü"
|
||||||
|
|
||||||
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
|
#: 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."
|
#~ 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."
|
#~ 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
|
#: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
|
||||||
msgid "Stage used to configure a TOTP authenticator (i.e. Authy/Google Authenticator)."
|
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."
|
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."
|
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
|
#: src/pages/outposts/ServiceConnectionListPage.ts
|
||||||
msgid "State"
|
msgid "State"
|
||||||
msgstr "Eyalet"
|
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."
|
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."
|
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
|
#: 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."
|
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."
|
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 "配置流程"
|
msgstr "配置流程"
|
||||||
|
|
||||||
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
|
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
|
||||||
msgid "Configuration stage"
|
#~ msgid "Configuration stage"
|
||||||
msgstr "配置阶段"
|
#~ msgstr "配置阶段"
|
||||||
|
|
||||||
|
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
|
||||||
|
msgid "Configuration stages"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Configure WebAuthn"
|
#~ msgid "Configure WebAuthn"
|
||||||
#~ msgstr "配置 WebAuthn"
|
#~ msgstr "配置 WebAuthn"
|
||||||
|
@ -4401,8 +4405,8 @@ msgid "Stage type"
|
||||||
msgstr "阶段类型"
|
msgstr "阶段类型"
|
||||||
|
|
||||||
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
|
#: 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."
|
#~ 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 通过后,不会再次提示用户。"
|
#~ msgstr "Stage 用于在用户没有任何兼容设备时配置身份验证器。此配置 Stage 通过后,不会再次提示用户。"
|
||||||
|
|
||||||
#: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
|
#: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
|
||||||
msgid "Stage used to configure a TOTP authenticator (i.e. Authy/Google Authenticator)."
|
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."
|
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 "阶段是引导用户完成的流程的单个步骤。阶段只能在流程内部执行。"
|
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
|
#: src/pages/outposts/ServiceConnectionListPage.ts
|
||||||
msgid "State"
|
msgid "State"
|
||||||
msgstr "状态"
|
msgstr "状态"
|
||||||
|
@ -5926,6 +5934,10 @@ msgstr "启用后,邀请将在使用后被删除。"
|
||||||
msgid "When enabled, user fields are matched regardless of their casing."
|
msgid "When enabled, user fields are matched regardless of their casing."
|
||||||
msgstr "启用后,无论用户字段大小写如何,都将匹配用户字段。"
|
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
|
#: 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."
|
msgid "When selected, a password field is shown on the same page instead of a separate page. This prevents username enumeration attacks."
|
||||||
msgstr "选中后,密码字段将显示在同一页面上,而不是单独的页面上。这样可以防止用户名枚举攻击。"
|
msgstr "选中后,密码字段将显示在同一页面上,而不是单独的页面上。这样可以防止用户名枚举攻击。"
|
||||||
|
|
|
@ -948,8 +948,12 @@ msgid "Configuration flow"
|
||||||
msgstr "配置流程"
|
msgstr "配置流程"
|
||||||
|
|
||||||
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
|
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
|
||||||
msgid "Configuration stage"
|
#~ msgid "Configuration stage"
|
||||||
msgstr "配置阶段"
|
#~ msgstr "配置阶段"
|
||||||
|
|
||||||
|
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
|
||||||
|
msgid "Configuration stages"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Configure WebAuthn"
|
#~ msgid "Configure WebAuthn"
|
||||||
#~ msgstr "配置 WebAuthn"
|
#~ msgstr "配置 WebAuthn"
|
||||||
|
@ -4401,8 +4405,8 @@ msgid "Stage type"
|
||||||
msgstr "阶段类型"
|
msgstr "阶段类型"
|
||||||
|
|
||||||
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
|
#: 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."
|
#~ 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 通过后,不会再次提示用户。"
|
#~ msgstr "Stage 用于在用户没有任何兼容设备时配置身份验证器。此配置 Stage 通过后,不会再次提示用户。"
|
||||||
|
|
||||||
#: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
|
#: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
|
||||||
msgid "Stage used to configure a TOTP authenticator (i.e. Authy/Google Authenticator)."
|
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."
|
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 "阶段是引导用户完成的流程的单个步骤。阶段只能在流程内部执行。"
|
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
|
#: src/pages/outposts/ServiceConnectionListPage.ts
|
||||||
msgid "State"
|
msgid "State"
|
||||||
msgstr "州"
|
msgstr "州"
|
||||||
|
@ -5926,6 +5934,10 @@ msgstr "启用后,邀请将在使用后被删除。"
|
||||||
msgid "When enabled, user fields are matched regardless of their casing."
|
msgid "When enabled, user fields are matched regardless of their casing."
|
||||||
msgstr "启用后,无论用户字段大小写如何,都将匹配用户字段。"
|
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
|
#: 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."
|
msgid "When selected, a password field is shown on the same page instead of a separate page. This prevents username enumeration attacks."
|
||||||
msgstr "选中后,密码字段将显示在同一页面上,而不是单独的页面上。这样可以防止用户名枚举攻击。"
|
msgstr "选中后,密码字段将显示在同一页面上,而不是单独的页面上。这样可以防止用户名枚举攻击。"
|
||||||
|
|
|
@ -948,8 +948,12 @@ msgid "Configuration flow"
|
||||||
msgstr "配置流程"
|
msgstr "配置流程"
|
||||||
|
|
||||||
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
|
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
|
||||||
msgid "Configuration stage"
|
#~ msgid "Configuration stage"
|
||||||
msgstr "配置阶段"
|
#~ msgstr "配置阶段"
|
||||||
|
|
||||||
|
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
|
||||||
|
msgid "Configuration stages"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#~ msgid "Configure WebAuthn"
|
#~ msgid "Configure WebAuthn"
|
||||||
#~ msgstr "配置 WebAuthn"
|
#~ msgstr "配置 WebAuthn"
|
||||||
|
@ -4401,8 +4405,8 @@ msgid "Stage type"
|
||||||
msgstr "阶段类型"
|
msgstr "阶段类型"
|
||||||
|
|
||||||
#: src/pages/stages/authenticator_validate/AuthenticatorValidateStageForm.ts
|
#: 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."
|
#~ 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 通过后,不会再次提示用户。"
|
#~ msgstr "Stage 用于在用户没有任何兼容设备时配置身份验证器。此配置 Stage 通过后,不会再次提示用户。"
|
||||||
|
|
||||||
#: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
|
#: src/pages/stages/authenticator_totp/AuthenticatorTOTPStageForm.ts
|
||||||
msgid "Stage used to configure a TOTP authenticator (i.e. Authy/Google Authenticator)."
|
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."
|
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 "阶段是引导用户完成的流程的单个步骤。阶段只能在流程内部执行。"
|
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
|
#: src/pages/outposts/ServiceConnectionListPage.ts
|
||||||
msgid "State"
|
msgid "State"
|
||||||
msgstr "州"
|
msgstr "州"
|
||||||
|
@ -5926,6 +5934,10 @@ msgstr "启用后,邀请将在使用后被删除。"
|
||||||
msgid "When enabled, user fields are matched regardless of their casing."
|
msgid "When enabled, user fields are matched regardless of their casing."
|
||||||
msgstr "启用后,无论用户字段大小写如何,都将匹配用户字段。"
|
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
|
#: 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."
|
msgid "When selected, a password field is shown on the same page instead of a separate page. This prevents username enumeration attacks."
|
||||||
msgstr "选中后,密码字段将显示在同一页面上,而不是单独的页面上。这样可以防止用户名枚举攻击。"
|
msgstr "选中后,密码字段将显示在同一页面上,而不是单独的页面上。这样可以防止用户名枚举攻击。"
|
||||||
|
|
|
@ -25,14 +25,14 @@ export class AuthenticatorValidateStageForm extends ModelForm<AuthenticatorValid
|
||||||
stageUuid: pk,
|
stageUuid: pk,
|
||||||
})
|
})
|
||||||
.then((stage) => {
|
.then((stage) => {
|
||||||
this.showConfigurationStage =
|
this.showConfigurationStages =
|
||||||
stage.notConfiguredAction === NotConfiguredActionEnum.Configure;
|
stage.notConfiguredAction === NotConfiguredActionEnum.Configure;
|
||||||
return stage;
|
return stage;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@property({ type: Boolean })
|
@property({ type: Boolean })
|
||||||
showConfigurationStage = true;
|
showConfigurationStages = true;
|
||||||
|
|
||||||
getSuccessMessage(): string {
|
getSuccessMessage(): string {
|
||||||
if (this.instance) {
|
if (this.instance) {
|
||||||
|
@ -136,9 +136,9 @@ export class AuthenticatorValidateStageForm extends ModelForm<AuthenticatorValid
|
||||||
target.selectedOptions[0].value ===
|
target.selectedOptions[0].value ===
|
||||||
NotConfiguredActionEnum.Configure
|
NotConfiguredActionEnum.Configure
|
||||||
) {
|
) {
|
||||||
this.showConfigurationStage = true;
|
this.showConfigurationStages = true;
|
||||||
} else {
|
} else {
|
||||||
this.showConfigurationStage = false;
|
this.showConfigurationStages = false;
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@ -165,21 +165,13 @@ export class AuthenticatorValidateStageForm extends ModelForm<AuthenticatorValid
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</ak-form-element-horizontal>
|
</ak-form-element-horizontal>
|
||||||
${this.showConfigurationStage
|
${this.showConfigurationStages
|
||||||
? html`
|
? html`
|
||||||
<ak-form-element-horizontal
|
<ak-form-element-horizontal
|
||||||
label=${t`Configuration stage`}
|
label=${t`Configuration stages`}
|
||||||
?required=${true}
|
name="configurationStages"
|
||||||
name="configurationStage"
|
|
||||||
>
|
>
|
||||||
<select class="pf-c-form-control">
|
<select class="pf-c-form-control" multiple>
|
||||||
<option
|
|
||||||
value=""
|
|
||||||
?selected=${this.instance?.configurationStage ===
|
|
||||||
undefined}
|
|
||||||
>
|
|
||||||
---------
|
|
||||||
</option>
|
|
||||||
${until(
|
${until(
|
||||||
new StagesApi(DEFAULT_CONFIG)
|
new StagesApi(DEFAULT_CONFIG)
|
||||||
.stagesAllList({
|
.stagesAllList({
|
||||||
|
@ -187,9 +179,11 @@ export class AuthenticatorValidateStageForm extends ModelForm<AuthenticatorValid
|
||||||
})
|
})
|
||||||
.then((stages) => {
|
.then((stages) => {
|
||||||
return stages.results.map((stage) => {
|
return stages.results.map((stage) => {
|
||||||
const selected =
|
const selected = Array.from(
|
||||||
this.instance?.configurationStage ===
|
this.instance?.configurationStages || [],
|
||||||
stage.pk;
|
).some((su) => {
|
||||||
|
return su == stage.pk;
|
||||||
|
});
|
||||||
return html`<option
|
return html`<option
|
||||||
value=${ifDefined(stage.pk)}
|
value=${ifDefined(stage.pk)}
|
||||||
?selected=${selected}
|
?selected=${selected}
|
||||||
|
@ -202,7 +196,10 @@ export class AuthenticatorValidateStageForm extends ModelForm<AuthenticatorValid
|
||||||
)}
|
)}
|
||||||
</select>
|
</select>
|
||||||
<p class="pf-c-form__helper-text">
|
<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>
|
</p>
|
||||||
</ak-form-element-horizontal>
|
</ak-form-element-horizontal>
|
||||||
`
|
`
|
||||||
|
|
|
@ -153,7 +153,7 @@ export class IdentificationStageForm extends ModelForm<IdentificationStage, stri
|
||||||
?required=${true}
|
?required=${true}
|
||||||
name="sources"
|
name="sources"
|
||||||
>
|
>
|
||||||
<select name="users" class="pf-c-form-control" multiple>
|
<select class="pf-c-form-control" multiple>
|
||||||
${until(
|
${until(
|
||||||
new SourcesApi(DEFAULT_CONFIG)
|
new SourcesApi(DEFAULT_CONFIG)
|
||||||
.sourcesAllList({})
|
.sourcesAllList({})
|
||||||
|
|
Reference in New Issue