web: use mermaidjs (#3623)
* flows: move flow diagram logic to separate file Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * idk Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * make web component work Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * remove subgraph for now Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * cleanup Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * add denied connection Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * fix Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * wrong list Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * fix tests Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * use custom styles Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * i18n Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * fix typing issues, make diagram centered Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * fix tests Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> * fix lint Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org> Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
parent
909a7772dc
commit
1583d53e54
|
@ -1,21 +1,17 @@
|
|||
"""Flow API Views"""
|
||||
from dataclasses import dataclass
|
||||
|
||||
from django.core.cache import cache
|
||||
from django.db.models import Model
|
||||
from django.http import HttpResponse
|
||||
from django.http.response import HttpResponseBadRequest
|
||||
from django.urls import reverse
|
||||
from django.utils.translation import gettext as _
|
||||
from drf_spectacular.types import OpenApiTypes
|
||||
from drf_spectacular.utils import OpenApiResponse, extend_schema
|
||||
from guardian.shortcuts import get_objects_for_user
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.fields import ReadOnlyField
|
||||
from rest_framework.parsers import MultiPartParser
|
||||
from rest_framework.request import Request
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.serializers import CharField, ModelSerializer, Serializer, SerializerMethodField
|
||||
from rest_framework.serializers import ModelSerializer, SerializerMethodField
|
||||
from rest_framework.viewsets import ModelViewSet
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
|
@ -29,6 +25,7 @@ from authentik.core.api.utils import (
|
|||
FileUploadSerializer,
|
||||
LinkSerializer,
|
||||
)
|
||||
from authentik.flows.api.flows_diagram import FlowDiagram, FlowDiagramSerializer
|
||||
from authentik.flows.exceptions import FlowNonApplicableException
|
||||
from authentik.flows.models import Flow
|
||||
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER, FlowPlanner, cache_key
|
||||
|
@ -80,30 +77,6 @@ class FlowSerializer(ModelSerializer):
|
|||
}
|
||||
|
||||
|
||||
class FlowDiagramSerializer(Serializer):
|
||||
"""response of the flow's diagram action"""
|
||||
|
||||
diagram = CharField(read_only=True)
|
||||
|
||||
def create(self, validated_data: dict) -> Model:
|
||||
raise NotImplementedError
|
||||
|
||||
def update(self, instance: Model, validated_data: dict) -> Model:
|
||||
raise NotImplementedError
|
||||
|
||||
|
||||
@dataclass
|
||||
class DiagramElement:
|
||||
"""Single element used in a diagram"""
|
||||
|
||||
identifier: str
|
||||
type: str
|
||||
rest: str
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"{self.identifier}=>{self.type}: {self.rest}"
|
||||
|
||||
|
||||
class FlowViewSet(UsedByMixin, ModelViewSet):
|
||||
"""Flow Viewset"""
|
||||
|
||||
|
@ -208,89 +181,9 @@ class FlowViewSet(UsedByMixin, ModelViewSet):
|
|||
# pylint: disable=unused-argument
|
||||
def diagram(self, request: Request, slug: str) -> Response:
|
||||
"""Return diagram for flow with slug `slug`, in the format used by flowchart.js"""
|
||||
flow = self.get_object()
|
||||
header = [
|
||||
DiagramElement("st", "start", "Start"),
|
||||
]
|
||||
body: list[DiagramElement] = []
|
||||
footer = []
|
||||
# Collect all elements we need
|
||||
# First, policies bound to the flow itself
|
||||
for p_index, policy_binding in enumerate(
|
||||
get_objects_for_user(request.user, "authentik_policies.view_policybinding")
|
||||
.filter(target=flow)
|
||||
.exclude(policy__isnull=True)
|
||||
.order_by("order")
|
||||
):
|
||||
body.append(
|
||||
DiagramElement(
|
||||
f"flow_policy_{p_index}",
|
||||
"condition",
|
||||
_("Policy (%(type)s)" % {"type": policy_binding.policy._meta.verbose_name})
|
||||
+ "\n"
|
||||
+ policy_binding.policy.name,
|
||||
)
|
||||
)
|
||||
# Collect all stages
|
||||
for s_index, stage_binding in enumerate(
|
||||
get_objects_for_user(request.user, "authentik_flows.view_flowstagebinding")
|
||||
.filter(target=flow)
|
||||
.order_by("order")
|
||||
):
|
||||
# First all policies bound to stages since they execute before stages
|
||||
for p_index, policy_binding in enumerate(
|
||||
get_objects_for_user(request.user, "authentik_policies.view_policybinding")
|
||||
.filter(target=stage_binding)
|
||||
.exclude(policy__isnull=True)
|
||||
.order_by("order")
|
||||
):
|
||||
body.append(
|
||||
DiagramElement(
|
||||
f"stage_{s_index}_policy_{p_index}",
|
||||
"condition",
|
||||
_("Policy (%(type)s)" % {"type": policy_binding.policy._meta.verbose_name})
|
||||
+ "\n"
|
||||
+ policy_binding.policy.name,
|
||||
)
|
||||
)
|
||||
body.append(
|
||||
DiagramElement(
|
||||
f"stage_{s_index}",
|
||||
"operation",
|
||||
_("Stage (%(type)s)" % {"type": stage_binding.stage._meta.verbose_name})
|
||||
+ "\n"
|
||||
+ stage_binding.stage.name,
|
||||
)
|
||||
)
|
||||
# If the 2nd last element is a policy, we need to have an item to point to
|
||||
# for a negative case
|
||||
body.append(
|
||||
DiagramElement("e", "end", "End|future"),
|
||||
)
|
||||
if len(body) == 1:
|
||||
footer.append("st(right)->e")
|
||||
else:
|
||||
# Actual diagram flow
|
||||
footer.append(f"st(right)->{body[0].identifier}")
|
||||
for index in range(len(body) - 1):
|
||||
element: DiagramElement = body[index]
|
||||
if element.type == "condition":
|
||||
# Policy passes, link policy yes to next stage
|
||||
footer.append(f"{element.identifier}(yes, right)->{body[index + 1].identifier}")
|
||||
# For policies bound to the flow itself, if they deny,
|
||||
# the flow doesn't get executed, hence directly to the end
|
||||
if element.identifier.startswith("flow_policy_"):
|
||||
footer.append(f"{element.identifier}(no, bottom)->e")
|
||||
else:
|
||||
# Policy doesn't pass, go to stage after next stage
|
||||
no_element = body[index + 1]
|
||||
if no_element.type != "end":
|
||||
no_element = body[index + 2]
|
||||
footer.append(f"{element.identifier}(no, bottom)->{no_element.identifier}")
|
||||
elif element.type == "operation":
|
||||
footer.append(f"{element.identifier}(bottom)->{body[index + 1].identifier}")
|
||||
diagram = "\n".join([str(x) for x in header + body + footer])
|
||||
return Response({"diagram": diagram})
|
||||
diagram = FlowDiagram(self.get_object(), request.user)
|
||||
output = diagram.build()
|
||||
return Response({"diagram": output})
|
||||
|
||||
@permission_required("authentik_flows.change_flow")
|
||||
@extend_schema(
|
||||
|
|
|
@ -0,0 +1,206 @@
|
|||
"""Flows Diagram API"""
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Optional
|
||||
|
||||
from django.utils.translation import gettext as _
|
||||
from guardian.shortcuts import get_objects_for_user
|
||||
from rest_framework.serializers import CharField
|
||||
|
||||
from authentik.core.api.utils import PassiveSerializer
|
||||
from authentik.core.models import User
|
||||
from authentik.flows.models import Flow, FlowStageBinding
|
||||
|
||||
|
||||
@dataclass
|
||||
class DiagramElement:
|
||||
"""Single element used in a diagram"""
|
||||
|
||||
identifier: str
|
||||
description: str
|
||||
action: Optional[str] = None
|
||||
source: Optional[list["DiagramElement"]] = None
|
||||
|
||||
style: list[str] = field(default_factory=lambda: ["[", "]"])
|
||||
|
||||
def __str__(self) -> str:
|
||||
element = f'{self.identifier}{self.style[0]}"{self.description}"{self.style[1]}'
|
||||
if self.action is not None:
|
||||
if self.action != "":
|
||||
element = f"--{self.action}--> {element}"
|
||||
else:
|
||||
element = f"--> {element}"
|
||||
if self.source:
|
||||
source_element = []
|
||||
for source in self.source:
|
||||
source_element.append(f"{source.identifier} {element}")
|
||||
return "\n".join(source_element)
|
||||
return element
|
||||
|
||||
|
||||
class FlowDiagramSerializer(PassiveSerializer):
|
||||
"""response of the flow's diagram action"""
|
||||
|
||||
diagram = CharField(read_only=True)
|
||||
|
||||
|
||||
class FlowDiagram:
|
||||
"""Generate flow chart fow a flow"""
|
||||
|
||||
flow: Flow
|
||||
user: User
|
||||
|
||||
def __init__(self, flow: Flow, user: User) -> None:
|
||||
self.flow = flow
|
||||
self.user = user
|
||||
|
||||
def get_flow_policies(self, parent_elements: list[DiagramElement]) -> list[DiagramElement]:
|
||||
"""Collect all policies bound to the flow"""
|
||||
elements = []
|
||||
for p_index, policy_binding in enumerate(
|
||||
get_objects_for_user(self.user, "authentik_policies.view_policybinding")
|
||||
.filter(target=self.flow)
|
||||
.exclude(policy__isnull=True)
|
||||
.order_by("order")
|
||||
):
|
||||
element = DiagramElement(
|
||||
f"flow_policy_{p_index}",
|
||||
_("Policy (%(type)s)" % {"type": policy_binding.policy._meta.verbose_name})
|
||||
+ "\n"
|
||||
+ policy_binding.policy.name,
|
||||
_("Binding %(order)d" % {"order": policy_binding.order}),
|
||||
parent_elements,
|
||||
style=["{{", "}}"],
|
||||
)
|
||||
elements.append(element)
|
||||
return elements
|
||||
|
||||
def get_stage_policies(
|
||||
self,
|
||||
stage_index: int,
|
||||
stage_binding: FlowStageBinding,
|
||||
parent_elements: list[DiagramElement],
|
||||
) -> list[DiagramElement]:
|
||||
"""First all policies bound to stages since they execute before stages"""
|
||||
elements = []
|
||||
for p_index, policy_binding in enumerate(
|
||||
get_objects_for_user(self.user, "authentik_policies.view_policybinding")
|
||||
.filter(target=stage_binding)
|
||||
.exclude(policy__isnull=True)
|
||||
.order_by("order")
|
||||
):
|
||||
element = DiagramElement(
|
||||
f"stage_{stage_index}_policy_{p_index}",
|
||||
_("Policy (%(type)s)" % {"type": policy_binding.policy._meta.verbose_name})
|
||||
+ "\n"
|
||||
+ policy_binding.policy.name,
|
||||
"",
|
||||
parent_elements,
|
||||
style=["{{", "}}"],
|
||||
)
|
||||
elements.append(element)
|
||||
return elements
|
||||
|
||||
def get_stages(self, parent_elements: list[DiagramElement]) -> list[str | DiagramElement]:
|
||||
"""Collect all stages"""
|
||||
elements = []
|
||||
stages = []
|
||||
for s_index, stage_binding in enumerate(
|
||||
get_objects_for_user(self.user, "authentik_flows.view_flowstagebinding")
|
||||
.filter(target=self.flow)
|
||||
.order_by("order")
|
||||
):
|
||||
stage_policies = self.get_stage_policies(s_index, stage_binding, parent_elements)
|
||||
elements.extend(stage_policies)
|
||||
|
||||
action = ""
|
||||
if len(stage_policies) > 0:
|
||||
action = _("Policy passed")
|
||||
|
||||
element = DiagramElement(
|
||||
f"stage_{s_index}",
|
||||
_("Stage (%(type)s)" % {"type": stage_binding.stage._meta.verbose_name})
|
||||
+ "\n"
|
||||
+ stage_binding.stage.name,
|
||||
action,
|
||||
stage_policies,
|
||||
style=["([", "])"],
|
||||
)
|
||||
stages.append(element)
|
||||
|
||||
parent_elements = [element]
|
||||
|
||||
# This adds connections for policy denies, but retroactively, as we can't really
|
||||
# look ahead
|
||||
# Check if we have a stage behind us and if it has any sources
|
||||
if s_index > 0:
|
||||
last_stage: DiagramElement = stages[s_index - 1]
|
||||
if last_stage.source and len(last_stage.source) > 0:
|
||||
# If it has any sources, add a connection from each of that stage's sources
|
||||
# to this stage
|
||||
for source in last_stage.source:
|
||||
elements.append(
|
||||
DiagramElement(
|
||||
element.identifier,
|
||||
element.description,
|
||||
_("Policy denied"),
|
||||
[source],
|
||||
style=element.style,
|
||||
)
|
||||
)
|
||||
|
||||
if len(stages) > 0:
|
||||
elements.append(
|
||||
DiagramElement(
|
||||
"done",
|
||||
_("End of the flow"),
|
||||
"",
|
||||
[stages[-1]],
|
||||
style=["[[", "]]"],
|
||||
),
|
||||
)
|
||||
return stages + elements
|
||||
|
||||
def build(self) -> str:
|
||||
"""Build flowchart"""
|
||||
all_elements = [
|
||||
"graph TD",
|
||||
]
|
||||
|
||||
pre_flow_policies_element = DiagramElement(
|
||||
"flow_pre", _("Pre-flow policies"), style=["[[", "]]"]
|
||||
)
|
||||
flow_policies = self.get_flow_policies([pre_flow_policies_element])
|
||||
if len(flow_policies) > 0:
|
||||
all_elements.append(pre_flow_policies_element)
|
||||
all_elements.extend(flow_policies)
|
||||
all_elements.append(
|
||||
DiagramElement(
|
||||
"done",
|
||||
_("End of the flow"),
|
||||
_("Policy denied"),
|
||||
flow_policies,
|
||||
)
|
||||
)
|
||||
|
||||
flow_element = DiagramElement(
|
||||
"flow_start",
|
||||
_("Flow") + "\n" + self.flow.name,
|
||||
"",
|
||||
source=flow_policies,
|
||||
style=["[[", "]]"],
|
||||
)
|
||||
all_elements.append(flow_element)
|
||||
|
||||
stages = self.get_stages([flow_element])
|
||||
all_elements.extend(stages)
|
||||
if len(stages) < 1:
|
||||
all_elements.append(
|
||||
DiagramElement(
|
||||
"done",
|
||||
_("End of the flow"),
|
||||
"",
|
||||
[flow_element],
|
||||
style=["[[", "]]"],
|
||||
),
|
||||
)
|
||||
return "\n".join([str(x) for x in all_elements])
|
|
@ -9,22 +9,20 @@ from authentik.policies.dummy.models import DummyPolicy
|
|||
from authentik.policies.models import PolicyBinding
|
||||
from authentik.stages.dummy.models import DummyStage
|
||||
|
||||
DIAGRAM_EXPECTED = """st=>start: Start
|
||||
stage_0=>operation: Stage (Dummy Stage)
|
||||
dummy1
|
||||
stage_1_policy_0=>condition: Policy (Dummy Policy)
|
||||
test
|
||||
stage_1=>operation: Stage (Dummy Stage)
|
||||
dummy2
|
||||
e=>end: End|future
|
||||
st(right)->stage_0
|
||||
stage_0(bottom)->stage_1_policy_0
|
||||
stage_1_policy_0(yes, right)->stage_1
|
||||
stage_1_policy_0(no, bottom)->e
|
||||
stage_1(bottom)->e"""
|
||||
DIAGRAM_SHORT_EXPECTED = """st=>start: Start
|
||||
e=>end: End|future
|
||||
st(right)->e"""
|
||||
DIAGRAM_EXPECTED = """graph TD
|
||||
--> flow_start[["Flow
|
||||
test-default-context"]]
|
||||
--> stage_0(["Stage (Dummy Stage)
|
||||
dummy1"])
|
||||
stage_1_policy_0 --Policy passed--> stage_1(["Stage (Dummy Stage)
|
||||
dummy2"])
|
||||
stage_0 --> stage_1_policy_0{{"Policy (Dummy Policy)
|
||||
dummy2-policy"}}
|
||||
stage_1 --> done[["End of the flow"]]"""
|
||||
DIAGRAM_SHORT_EXPECTED = """graph TD
|
||||
--> flow_start[["Flow
|
||||
test-default-context"]]
|
||||
flow_start --> done[["End of the flow"]]"""
|
||||
|
||||
|
||||
class TestFlowsAPI(APITestCase):
|
||||
|
@ -55,7 +53,9 @@ class TestFlowsAPI(APITestCase):
|
|||
slug="test-default-context",
|
||||
designation=FlowDesignation.AUTHENTICATION,
|
||||
)
|
||||
false_policy = DummyPolicy.objects.create(name="test", result=False, wait_min=1, wait_max=2)
|
||||
false_policy = DummyPolicy.objects.create(
|
||||
name="dummy2-policy", result=False, wait_min=1, wait_max=2
|
||||
)
|
||||
|
||||
FlowStageBinding.objects.create(
|
||||
target=flow, stage=DummyStage.objects.create(name="dummy1"), order=0
|
||||
|
|
|
@ -8,7 +8,7 @@ msgid ""
|
|||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2022-09-16 21:25+0000\n"
|
||||
"POT-Creation-Date: 2022-09-20 22:16+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
|
@ -268,89 +268,89 @@ msgstr ""
|
|||
msgid "Certificate-Key Pairs"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:294
|
||||
#: authentik/events/models.py:300
|
||||
msgid "Event"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:295
|
||||
#: authentik/events/models.py:301
|
||||
msgid "Events"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:301
|
||||
#: authentik/events/models.py:307
|
||||
msgid "authentik inbuilt notifications"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:302
|
||||
#: authentik/events/models.py:308
|
||||
msgid "Generic Webhook"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:303
|
||||
#: authentik/events/models.py:309
|
||||
msgid "Slack Webhook (Slack/Discord)"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:304
|
||||
#: authentik/events/models.py:310
|
||||
msgid "Email"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:322
|
||||
#: authentik/events/models.py:328
|
||||
msgid ""
|
||||
"Only send notification once, for example when sending a webhook into a chat "
|
||||
"channel."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:380
|
||||
#: authentik/events/models.py:388
|
||||
msgid "Severity"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:385
|
||||
#: authentik/events/models.py:393
|
||||
msgid "Dispatched for user"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:468
|
||||
#: authentik/events/models.py:476
|
||||
msgid "Notification Transport"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:469
|
||||
#: authentik/events/models.py:477
|
||||
msgid "Notification Transports"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:475
|
||||
#: authentik/events/models.py:483
|
||||
msgid "Notice"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:476
|
||||
#: authentik/events/models.py:484
|
||||
msgid "Warning"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:477
|
||||
#: authentik/events/models.py:485
|
||||
msgid "Alert"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:503
|
||||
#: authentik/events/models.py:511
|
||||
msgid "Notification"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:504
|
||||
#: authentik/events/models.py:512
|
||||
msgid "Notifications"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:524
|
||||
#: authentik/events/models.py:532
|
||||
msgid "Controls which severity level the created notifications will have."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:550
|
||||
#: authentik/events/models.py:558
|
||||
msgid "Notification Rule"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:551
|
||||
#: authentik/events/models.py:559
|
||||
msgid "Notification Rules"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:572
|
||||
#: authentik/events/models.py:580
|
||||
msgid "Notification Webhook Mapping"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py:573
|
||||
#: authentik/events/models.py:581
|
||||
msgid "Notification Webhook Mappings"
|
||||
msgstr ""
|
||||
|
||||
|
@ -358,19 +358,48 @@ msgstr ""
|
|||
msgid "Task has not been run yet."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/flows/api/flows.py:229 authentik/flows/api/flows.py:251
|
||||
#: authentik/flows/api/flows.py:273
|
||||
#, python-format
|
||||
msgid "Flow not applicable to current user/request: %(messages)s"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/flows/api/flows_diagram.py:67
|
||||
#: authentik/flows/api/flows_diagram.py:93
|
||||
#, python-format
|
||||
msgid "Policy (%(type)s)"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/flows/api/flows.py:260
|
||||
#: authentik/flows/api/flows_diagram.py:70
|
||||
#, python-format
|
||||
msgid "Binding %(order)d"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/flows/api/flows_diagram.py:117
|
||||
msgid "Policy passed"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/flows/api/flows_diagram.py:121
|
||||
#, python-format
|
||||
msgid "Stage (%(type)s)"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/flows/api/flows.py:380
|
||||
#, python-format
|
||||
msgid "Flow not applicable to current user/request: %(messages)s"
|
||||
#: authentik/flows/api/flows_diagram.py:145
|
||||
#: authentik/flows/api/flows_diagram.py:179
|
||||
msgid "Policy denied"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/flows/api/flows_diagram.py:154
|
||||
#: authentik/flows/api/flows_diagram.py:178
|
||||
#: authentik/flows/api/flows_diagram.py:199
|
||||
msgid "End of the flow"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/flows/api/flows_diagram.py:169
|
||||
msgid "Pre-flow policies"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/flows/api/flows_diagram.py:186 authentik/flows/models.py:178
|
||||
msgid "Flow"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/flows/exceptions.py:17
|
||||
|
@ -399,10 +428,6 @@ msgstr ""
|
|||
msgid "Configure what should happen when a flow denies access to a user."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/flows/models.py:178
|
||||
msgid "Flow"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/flows/models.py:179
|
||||
msgid "Flows"
|
||||
msgstr ""
|
||||
|
@ -1328,19 +1353,19 @@ msgstr ""
|
|||
msgid "SAML Sources"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/authenticator_duo/models.py:80
|
||||
#: authentik/stages/authenticator_duo/models.py:81
|
||||
msgid "Duo Authenticator Setup Stage"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/authenticator_duo/models.py:81
|
||||
#: authentik/stages/authenticator_duo/models.py:82
|
||||
msgid "Duo Authenticator Setup Stages"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/authenticator_duo/models.py:105
|
||||
#: authentik/stages/authenticator_duo/models.py:106
|
||||
msgid "Duo Device"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/authenticator_duo/models.py:106
|
||||
#: authentik/stages/authenticator_duo/models.py:107
|
||||
msgid "Duo Devices"
|
||||
msgstr ""
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -85,6 +85,7 @@
|
|||
"@types/chart.js": "^2.9.37",
|
||||
"@types/codemirror": "5.60.5",
|
||||
"@types/grecaptcha": "^3.0.4",
|
||||
"@types/mermaid": "^9.1.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.38.0",
|
||||
"@typescript-eslint/parser": "^5.38.0",
|
||||
"@webcomponents/webcomponentsjs": "^2.6.0",
|
||||
|
@ -100,9 +101,9 @@
|
|||
"eslint-config-google": "^0.14.0",
|
||||
"eslint-plugin-custom-elements": "0.0.6",
|
||||
"eslint-plugin-lit": "^1.6.1",
|
||||
"flowchart.js": "^1.17.1",
|
||||
"fuse.js": "^6.6.2",
|
||||
"lit": "^2.3.1",
|
||||
"mermaid": "^9.1.7",
|
||||
"moment": "^2.29.4",
|
||||
"prettier": "^2.7.1",
|
||||
"pyright": "^1.1.272",
|
||||
|
|
|
@ -2,10 +2,11 @@ import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
|||
import { EVENT_REFRESH } from "@goauthentik/common/constants";
|
||||
import { AKElement } from "@goauthentik/elements/Base";
|
||||
import "@goauthentik/elements/EmptyState";
|
||||
import FlowChart from "flowchart.js";
|
||||
import mermaid from "mermaid";
|
||||
|
||||
import { TemplateResult, html } from "lit";
|
||||
import { CSSResult, TemplateResult, css, html } from "lit";
|
||||
import { customElement, property } from "lit/decorators.js";
|
||||
import { unsafeHTML } from "lit/directives/unsafe-html.js";
|
||||
|
||||
import { FlowsApi } from "@goauthentik/api";
|
||||
|
||||
|
@ -35,34 +36,37 @@ export class FlowDiagram extends AKElement {
|
|||
@property({ attribute: false })
|
||||
diagram?: string;
|
||||
|
||||
@property()
|
||||
fontColour: string = FONT_COLOUR_DARK_MODE;
|
||||
|
||||
@property()
|
||||
fill: string = FILL_DARK_MODE;
|
||||
|
||||
handlerBound = false;
|
||||
|
||||
createRenderRoot(): Element | ShadowRoot {
|
||||
return this;
|
||||
}
|
||||
|
||||
get isInViewport(): boolean {
|
||||
const rect = this.getBoundingClientRect();
|
||||
return !(rect.x + rect.y + rect.width + rect.height === 0);
|
||||
}
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
return [
|
||||
css`
|
||||
:host {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
`,
|
||||
];
|
||||
}
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
const matcher = window.matchMedia("(prefers-color-scheme: light)");
|
||||
const handler = (ev?: MediaQueryListEvent) => {
|
||||
if (ev?.matches || matcher.matches) {
|
||||
this.fontColour = FONT_COLOUR_LIGHT_MODE;
|
||||
this.fill = FILL_LIGHT_MODE;
|
||||
} else {
|
||||
this.fontColour = FONT_COLOUR_DARK_MODE;
|
||||
this.fill = FILL_DARK_MODE;
|
||||
}
|
||||
console.log("setting config");
|
||||
mermaid.initialize({
|
||||
logLevel: "error",
|
||||
startOnLoad: false,
|
||||
theme: ev?.matches || matcher.matches ? "default" : "dark",
|
||||
flowchart: {
|
||||
curve: "linear",
|
||||
},
|
||||
});
|
||||
this.requestUpdate();
|
||||
};
|
||||
matcher.addEventListener("change", handler);
|
||||
|
@ -93,18 +97,9 @@ export class FlowDiagram extends AKElement {
|
|||
console.debug(`authentik/flow/diagram: failed to remove element ${el}`);
|
||||
}
|
||||
});
|
||||
if (this.diagram) {
|
||||
const diagram = FlowChart.parse(this.diagram);
|
||||
diagram.drawSVG(this, {
|
||||
"font-color": this.fontColour,
|
||||
"line-color": "#bebebe",
|
||||
"element-color": "#bebebe",
|
||||
"fill": this.fill,
|
||||
"yes-text": "Policy passes",
|
||||
"no-text": "Policy denies",
|
||||
});
|
||||
return html``;
|
||||
if (!this.diagram) {
|
||||
return html`<ak-empty-state ?loading=${true}></ak-empty-state>`;
|
||||
}
|
||||
return html`<ak-empty-state ?loading=${true}></ak-empty-state>`;
|
||||
return html`${unsafeHTML(mermaid.render("graph", this.diagram))}`;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,7 +83,7 @@ export class FlowViewPage extends AKElement {
|
|||
<div
|
||||
class="pf-c-card pf-l-grid__item pf-m-12-col pf-m-2-col-on-xl pf-m-2-col-on-2xl"
|
||||
>
|
||||
<div class="pf-c-card__title">${t`Related`}</div>
|
||||
<div class="pf-c-card__title">${t`Related actions`}</div>
|
||||
<div class="pf-c-card__body">
|
||||
<dl class="pf-c-description-list">
|
||||
<div class="pf-c-description-list__group">
|
||||
|
@ -104,7 +104,7 @@ export class FlowViewPage extends AKElement {
|
|||
</ak-flow-form>
|
||||
<button
|
||||
slot="trigger"
|
||||
class="pf-c-button pf-m-secondary"
|
||||
class="pf-c-button pf-m-block pf-m-secondary"
|
||||
>
|
||||
${t`Edit`}
|
||||
</button>
|
||||
|
@ -119,7 +119,7 @@ export class FlowViewPage extends AKElement {
|
|||
<dd class="pf-c-description-list__description">
|
||||
<div class="pf-c-description-list__text">
|
||||
<button
|
||||
class="pf-c-button pf-m-primary"
|
||||
class="pf-c-button pf-m-block pf-m-primary"
|
||||
@click=${() => {
|
||||
const finalURL = `${
|
||||
window.location.origin
|
||||
|
@ -132,7 +132,7 @@ export class FlowViewPage extends AKElement {
|
|||
${t`Normal`}
|
||||
</button>
|
||||
<button
|
||||
class="pf-c-button pf-m-secondary"
|
||||
class="pf-c-button pf-m-block pf-m-secondary"
|
||||
@click=${() => {
|
||||
new FlowsApi(DEFAULT_CONFIG)
|
||||
.flowsInstancesExecuteRetrieve({
|
||||
|
@ -151,7 +151,7 @@ export class FlowViewPage extends AKElement {
|
|||
${t`with current user`}
|
||||
</button>
|
||||
<button
|
||||
class="pf-c-button pf-m-secondary"
|
||||
class="pf-c-button pf-m-block pf-m-secondary"
|
||||
@click=${() => {
|
||||
new FlowsApi(DEFAULT_CONFIG)
|
||||
.flowsInstancesExecuteRetrieve({
|
||||
|
@ -187,7 +187,7 @@ export class FlowViewPage extends AKElement {
|
|||
<dd class="pf-c-description-list__description">
|
||||
<div class="pf-c-description-list__text">
|
||||
<a
|
||||
class="pf-c-button pf-m-secondary"
|
||||
class="pf-c-button pf-m-block pf-m-secondary"
|
||||
href=${this.flow.exportUrl}
|
||||
>
|
||||
${t`Export`}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -646,6 +646,10 @@ msgstr "Auto-detect (based on your browser)"
|
|||
msgid "Automate and template configuration within authentik."
|
||||
msgstr "Automate and template configuration within authentik."
|
||||
|
||||
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
|
||||
msgid "Automatic import"
|
||||
msgstr "Automatic import"
|
||||
|
||||
#: src/user/UserInterface.ts
|
||||
msgid "Avatar image"
|
||||
msgstr "Avatar image"
|
||||
|
@ -2471,6 +2475,7 @@ msgstr "Forgot password?"
|
|||
msgid "Forgot username or password?"
|
||||
msgstr "Forgot username or password?"
|
||||
|
||||
#: src/elements/forms/ModalForm.ts
|
||||
#: src/elements/forms/ModalForm.ts
|
||||
#: src/elements/wizard/FormWizardPage.ts
|
||||
#: src/elements/wizard/FormWizardPage.ts
|
||||
|
@ -3694,6 +3699,7 @@ msgstr "No additional data available."
|
|||
msgid "No additional setup is required."
|
||||
msgstr "No additional setup is required."
|
||||
|
||||
#: src/elements/forms/ModalForm.ts
|
||||
#: src/elements/forms/ModalForm.ts
|
||||
#: src/elements/wizard/FormWizardPage.ts
|
||||
#: src/elements/wizard/FormWizardPage.ts
|
||||
|
@ -3998,6 +4004,10 @@ msgstr "Optionally set the 'FriendlyName' value of the Assertion attribute."
|
|||
msgid "Or"
|
||||
msgstr "Or"
|
||||
|
||||
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
|
||||
msgid "Or manually import"
|
||||
msgstr "Or manually import"
|
||||
|
||||
#: src/admin/flows/BoundStagesList.ts
|
||||
#: src/admin/flows/StageBindingForm.ts
|
||||
#: src/admin/policies/BoundPoliciesList.ts
|
||||
|
@ -4152,8 +4162,12 @@ msgid "Path"
|
|||
msgstr "Path"
|
||||
|
||||
#: src/admin/stages/user_write/UserWriteStageForm.ts
|
||||
msgid "Path new users will be created under. If left blank, the default path will be used.fo"
|
||||
msgstr "Path new users will be created under. If left blank, the default path will be used.fo"
|
||||
msgid "Path new users will be created under. If left blank, the default path will be used."
|
||||
msgstr "Path new users will be created under. If left blank, the default path will be used."
|
||||
|
||||
#: src/admin/stages/user_write/UserWriteStageForm.ts
|
||||
#~ msgid "Path new users will be created under. If left blank, the default path will be used.fo"
|
||||
#~ msgstr "Path new users will be created under. If left blank, the default path will be used.fo"
|
||||
|
||||
#: src/admin/sources/ldap/LDAPSourceForm.ts
|
||||
#: src/admin/sources/oauth/OAuthSourceForm.ts
|
||||
|
@ -4588,10 +4602,13 @@ msgid "Regular user"
|
|||
msgstr "Regular user"
|
||||
|
||||
#: src/admin/applications/ApplicationViewPage.ts
|
||||
#: src/admin/flows/FlowViewPage.ts
|
||||
msgid "Related"
|
||||
msgstr "Related"
|
||||
|
||||
#: src/admin/flows/FlowViewPage.ts
|
||||
msgid "Related actions"
|
||||
msgstr "Related actions"
|
||||
|
||||
#: src/admin/providers/saml/SAMLProviderViewPage.ts
|
||||
#: src/admin/providers/saml/SAMLProviderViewPage.ts
|
||||
msgid "Related objects"
|
||||
|
@ -5338,6 +5355,10 @@ msgstr "Stages are single steps of a Flow that a user is guided through. A stage
|
|||
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 "Stages used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again."
|
||||
|
||||
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
|
||||
msgid "Start automatic import"
|
||||
msgstr "Start automatic import"
|
||||
|
||||
#: src/admin/outposts/ServiceConnectionListPage.ts
|
||||
msgid "State"
|
||||
msgstr "State"
|
||||
|
@ -5582,6 +5603,10 @@ msgstr "Successfully imported flow."
|
|||
msgid "Successfully imported provider."
|
||||
msgstr "Successfully imported provider."
|
||||
|
||||
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
|
||||
msgid "Successfully imported {0} devices."
|
||||
msgstr "Successfully imported {0} devices."
|
||||
|
||||
#: src/admin/users/UserResetEmailForm.ts
|
||||
msgid "Successfully sent email."
|
||||
msgstr "Successfully sent email."
|
||||
|
|
|
@ -640,6 +640,10 @@ msgstr "Detección automática (según su navegador)"
|
|||
msgid "Automate and template configuration within authentik."
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
|
||||
msgid "Automatic import"
|
||||
msgstr ""
|
||||
|
||||
#: src/user/UserInterface.ts
|
||||
msgid "Avatar image"
|
||||
msgstr "Imagen de avatar"
|
||||
|
@ -2426,6 +2430,7 @@ msgstr "¿Has olvidado tu contraseña"
|
|||
msgid "Forgot username or password?"
|
||||
msgstr "¿Olvidó su nombre de usuario"
|
||||
|
||||
#: src/elements/forms/ModalForm.ts
|
||||
#: src/elements/forms/ModalForm.ts
|
||||
#: src/elements/wizard/FormWizardPage.ts
|
||||
#: src/elements/wizard/FormWizardPage.ts
|
||||
|
@ -3634,6 +3639,7 @@ msgstr "No hay datos adicionales disponibles."
|
|||
msgid "No additional setup is required."
|
||||
msgstr "No se requiere ninguna configuración adicional."
|
||||
|
||||
#: src/elements/forms/ModalForm.ts
|
||||
#: src/elements/forms/ModalForm.ts
|
||||
#: src/elements/wizard/FormWizardPage.ts
|
||||
#: src/elements/wizard/FormWizardPage.ts
|
||||
|
@ -3931,6 +3937,10 @@ msgstr "Si lo desea, defina el valor «FriendlyName» del atributo Assertion."
|
|||
msgid "Or"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
|
||||
msgid "Or manually import"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/flows/BoundStagesList.ts
|
||||
#: src/admin/flows/StageBindingForm.ts
|
||||
#: src/admin/policies/BoundPoliciesList.ts
|
||||
|
@ -4081,9 +4091,13 @@ msgid "Path"
|
|||
msgstr ""
|
||||
|
||||
#: src/admin/stages/user_write/UserWriteStageForm.ts
|
||||
msgid "Path new users will be created under. If left blank, the default path will be used.fo"
|
||||
msgid "Path new users will be created under. If left blank, the default path will be used."
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/stages/user_write/UserWriteStageForm.ts
|
||||
#~ msgid "Path new users will be created under. If left blank, the default path will be used.fo"
|
||||
#~ msgstr ""
|
||||
|
||||
#: src/admin/sources/ldap/LDAPSourceForm.ts
|
||||
#: src/admin/sources/oauth/OAuthSourceForm.ts
|
||||
#: src/admin/sources/plex/PlexSourceForm.ts
|
||||
|
@ -4507,10 +4521,13 @@ msgid "Regular user"
|
|||
msgstr "Usuario habitual"
|
||||
|
||||
#: src/admin/applications/ApplicationViewPage.ts
|
||||
#: src/admin/flows/FlowViewPage.ts
|
||||
msgid "Related"
|
||||
msgstr "Relacionado"
|
||||
|
||||
#: src/admin/flows/FlowViewPage.ts
|
||||
msgid "Related actions"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/providers/saml/SAMLProviderViewPage.ts
|
||||
#: src/admin/providers/saml/SAMLProviderViewPage.ts
|
||||
msgid "Related objects"
|
||||
|
@ -5236,6 +5253,10 @@ msgstr "Las etapas son pasos individuales de un flujo por los que se guía al us
|
|||
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/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
|
||||
msgid "Start automatic import"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/outposts/ServiceConnectionListPage.ts
|
||||
msgid "State"
|
||||
msgstr "Estado"
|
||||
|
@ -5470,6 +5491,10 @@ msgstr "El flujo se importó correctamente."
|
|||
msgid "Successfully imported provider."
|
||||
msgstr "El proveedor se importó correctamente."
|
||||
|
||||
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
|
||||
msgid "Successfully imported {0} devices."
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/users/UserResetEmailForm.ts
|
||||
msgid "Successfully sent email."
|
||||
msgstr "El correo electrónico se envió correctamente."
|
||||
|
|
|
@ -646,6 +646,10 @@ msgstr ""
|
|||
msgid "Automate and template configuration within authentik."
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
|
||||
msgid "Automatic import"
|
||||
msgstr ""
|
||||
|
||||
#: src/user/UserInterface.ts
|
||||
msgid "Avatar image"
|
||||
msgstr "Image d'avatar"
|
||||
|
@ -2451,6 +2455,7 @@ msgstr "Mot de passe oublié ?"
|
|||
msgid "Forgot username or password?"
|
||||
msgstr "Mot de passe ou nom d'utilisateur oublié ?"
|
||||
|
||||
#: src/elements/forms/ModalForm.ts
|
||||
#: src/elements/forms/ModalForm.ts
|
||||
#: src/elements/wizard/FormWizardPage.ts
|
||||
#: src/elements/wizard/FormWizardPage.ts
|
||||
|
@ -3665,6 +3670,7 @@ msgstr "Aucune donnée additionnelle disponible."
|
|||
msgid "No additional setup is required."
|
||||
msgstr ""
|
||||
|
||||
#: src/elements/forms/ModalForm.ts
|
||||
#: src/elements/forms/ModalForm.ts
|
||||
#: src/elements/wizard/FormWizardPage.ts
|
||||
#: src/elements/wizard/FormWizardPage.ts
|
||||
|
@ -3966,6 +3972,10 @@ msgstr "Indiquer la valeur \"FriendlyName\" de l'attribut d'assertion (optionnel
|
|||
msgid "Or"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
|
||||
msgid "Or manually import"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/flows/BoundStagesList.ts
|
||||
#: src/admin/flows/StageBindingForm.ts
|
||||
#: src/admin/policies/BoundPoliciesList.ts
|
||||
|
@ -4117,9 +4127,13 @@ msgid "Path"
|
|||
msgstr ""
|
||||
|
||||
#: src/admin/stages/user_write/UserWriteStageForm.ts
|
||||
msgid "Path new users will be created under. If left blank, the default path will be used.fo"
|
||||
msgid "Path new users will be created under. If left blank, the default path will be used."
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/stages/user_write/UserWriteStageForm.ts
|
||||
#~ msgid "Path new users will be created under. If left blank, the default path will be used.fo"
|
||||
#~ msgstr ""
|
||||
|
||||
#: src/admin/sources/ldap/LDAPSourceForm.ts
|
||||
#: src/admin/sources/oauth/OAuthSourceForm.ts
|
||||
#: src/admin/sources/plex/PlexSourceForm.ts
|
||||
|
@ -4550,10 +4564,13 @@ msgid "Regular user"
|
|||
msgstr "Utilisateur normal"
|
||||
|
||||
#: src/admin/applications/ApplicationViewPage.ts
|
||||
#: src/admin/flows/FlowViewPage.ts
|
||||
msgid "Related"
|
||||
msgstr "Lié"
|
||||
|
||||
#: src/admin/flows/FlowViewPage.ts
|
||||
msgid "Related actions"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/providers/saml/SAMLProviderViewPage.ts
|
||||
#: src/admin/providers/saml/SAMLProviderViewPage.ts
|
||||
msgid "Related objects"
|
||||
|
@ -5289,6 +5306,10 @@ msgstr "Les étapes sont des étapes simples d'un flux au travers duquel un util
|
|||
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/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
|
||||
msgid "Start automatic import"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/outposts/ServiceConnectionListPage.ts
|
||||
msgid "State"
|
||||
msgstr "État"
|
||||
|
@ -5531,6 +5552,10 @@ msgstr "Flux importé avec succès"
|
|||
msgid "Successfully imported provider."
|
||||
msgstr "Fournisseur importé avec succès"
|
||||
|
||||
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
|
||||
msgid "Successfully imported {0} devices."
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/users/UserResetEmailForm.ts
|
||||
msgid "Successfully sent email."
|
||||
msgstr "Email envoyé avec succès"
|
||||
|
|
|
@ -640,6 +640,10 @@ msgstr "Automatycznie wykryj (na podstawie Twojej przeglądarki)"
|
|||
msgid "Automate and template configuration within authentik."
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
|
||||
msgid "Automatic import"
|
||||
msgstr ""
|
||||
|
||||
#: src/user/UserInterface.ts
|
||||
msgid "Avatar image"
|
||||
msgstr "Obraz awatara"
|
||||
|
@ -2423,6 +2427,7 @@ msgstr "Zapomniałeś hasła?"
|
|||
msgid "Forgot username or password?"
|
||||
msgstr "Zapomniałeś nazwy użytkownika lub hasła?"
|
||||
|
||||
#: src/elements/forms/ModalForm.ts
|
||||
#: src/elements/forms/ModalForm.ts
|
||||
#: src/elements/wizard/FormWizardPage.ts
|
||||
#: src/elements/wizard/FormWizardPage.ts
|
||||
|
@ -3631,6 +3636,7 @@ msgstr "Brak dodatkowych danych."
|
|||
msgid "No additional setup is required."
|
||||
msgstr "Nie jest wymagana żadna dodatkowa konfiguracja."
|
||||
|
||||
#: src/elements/forms/ModalForm.ts
|
||||
#: src/elements/forms/ModalForm.ts
|
||||
#: src/elements/wizard/FormWizardPage.ts
|
||||
#: src/elements/wizard/FormWizardPage.ts
|
||||
|
@ -3928,6 +3934,10 @@ msgstr "Opcjonalnie ustaw wartość „FriendlyName” atrybutu asercji."
|
|||
msgid "Or"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
|
||||
msgid "Or manually import"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/flows/BoundStagesList.ts
|
||||
#: src/admin/flows/StageBindingForm.ts
|
||||
#: src/admin/policies/BoundPoliciesList.ts
|
||||
|
@ -4078,9 +4088,13 @@ msgid "Path"
|
|||
msgstr ""
|
||||
|
||||
#: src/admin/stages/user_write/UserWriteStageForm.ts
|
||||
msgid "Path new users will be created under. If left blank, the default path will be used.fo"
|
||||
msgid "Path new users will be created under. If left blank, the default path will be used."
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/stages/user_write/UserWriteStageForm.ts
|
||||
#~ msgid "Path new users will be created under. If left blank, the default path will be used.fo"
|
||||
#~ msgstr ""
|
||||
|
||||
#: src/admin/sources/ldap/LDAPSourceForm.ts
|
||||
#: src/admin/sources/oauth/OAuthSourceForm.ts
|
||||
#: src/admin/sources/plex/PlexSourceForm.ts
|
||||
|
@ -4504,10 +4518,13 @@ msgid "Regular user"
|
|||
msgstr "Zwykły użytkownik"
|
||||
|
||||
#: src/admin/applications/ApplicationViewPage.ts
|
||||
#: src/admin/flows/FlowViewPage.ts
|
||||
msgid "Related"
|
||||
msgstr "Związane z"
|
||||
|
||||
#: src/admin/flows/FlowViewPage.ts
|
||||
msgid "Related actions"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/providers/saml/SAMLProviderViewPage.ts
|
||||
#: src/admin/providers/saml/SAMLProviderViewPage.ts
|
||||
msgid "Related objects"
|
||||
|
@ -5233,6 +5250,10 @@ msgstr "Etapy to pojedyncze kroki przepływu, przez które prowadzony jest użyt
|
|||
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/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
|
||||
msgid "Start automatic import"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/outposts/ServiceConnectionListPage.ts
|
||||
msgid "State"
|
||||
msgstr "Stan"
|
||||
|
@ -5467,6 +5488,10 @@ msgstr "Pomyślnie zaimportowano przepływ."
|
|||
msgid "Successfully imported provider."
|
||||
msgstr "Pomyślnie zaimportowano dostawcę."
|
||||
|
||||
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
|
||||
msgid "Successfully imported {0} devices."
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/users/UserResetEmailForm.ts
|
||||
msgid "Successfully sent email."
|
||||
msgstr "Pomyślnie wysłano e-mail."
|
||||
|
|
|
@ -638,6 +638,10 @@ msgstr ""
|
|||
msgid "Automate and template configuration within authentik."
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
|
||||
msgid "Automatic import"
|
||||
msgstr ""
|
||||
|
||||
#: src/user/UserInterface.ts
|
||||
msgid "Avatar image"
|
||||
msgstr ""
|
||||
|
@ -2457,6 +2461,7 @@ msgstr ""
|
|||
msgid "Forgot username or password?"
|
||||
msgstr ""
|
||||
|
||||
#: src/elements/forms/ModalForm.ts
|
||||
#: src/elements/forms/ModalForm.ts
|
||||
#: src/elements/wizard/FormWizardPage.ts
|
||||
#: src/elements/wizard/FormWizardPage.ts
|
||||
|
@ -3676,6 +3681,7 @@ msgstr ""
|
|||
msgid "No additional setup is required."
|
||||
msgstr ""
|
||||
|
||||
#: src/elements/forms/ModalForm.ts
|
||||
#: src/elements/forms/ModalForm.ts
|
||||
#: src/elements/wizard/FormWizardPage.ts
|
||||
#: src/elements/wizard/FormWizardPage.ts
|
||||
|
@ -3980,6 +3986,10 @@ msgstr ""
|
|||
msgid "Or"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
|
||||
msgid "Or manually import"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/flows/BoundStagesList.ts
|
||||
#: src/admin/flows/StageBindingForm.ts
|
||||
#: src/admin/policies/BoundPoliciesList.ts
|
||||
|
@ -4134,9 +4144,13 @@ msgid "Path"
|
|||
msgstr ""
|
||||
|
||||
#: src/admin/stages/user_write/UserWriteStageForm.ts
|
||||
msgid "Path new users will be created under. If left blank, the default path will be used.fo"
|
||||
msgid "Path new users will be created under. If left blank, the default path will be used."
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/stages/user_write/UserWriteStageForm.ts
|
||||
#~ msgid "Path new users will be created under. If left blank, the default path will be used.fo"
|
||||
#~ msgstr ""
|
||||
|
||||
#: src/admin/sources/ldap/LDAPSourceForm.ts
|
||||
#: src/admin/sources/oauth/OAuthSourceForm.ts
|
||||
#: src/admin/sources/plex/PlexSourceForm.ts
|
||||
|
@ -4568,10 +4582,13 @@ msgid "Regular user"
|
|||
msgstr ""
|
||||
|
||||
#: src/admin/applications/ApplicationViewPage.ts
|
||||
#: src/admin/flows/FlowViewPage.ts
|
||||
msgid "Related"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/flows/FlowViewPage.ts
|
||||
msgid "Related actions"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/providers/saml/SAMLProviderViewPage.ts
|
||||
#: src/admin/providers/saml/SAMLProviderViewPage.ts
|
||||
msgid "Related objects"
|
||||
|
@ -5318,6 +5335,10 @@ msgstr ""
|
|||
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/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
|
||||
msgid "Start automatic import"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/outposts/ServiceConnectionListPage.ts
|
||||
msgid "State"
|
||||
msgstr ""
|
||||
|
@ -5562,6 +5583,10 @@ msgstr ""
|
|||
msgid "Successfully imported provider."
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
|
||||
msgid "Successfully imported {0} devices."
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/users/UserResetEmailForm.ts
|
||||
msgid "Successfully sent email."
|
||||
msgstr ""
|
||||
|
|
|
@ -640,6 +640,10 @@ msgstr "Otomatik algıla (tarayıcınıza göre)"
|
|||
msgid "Automate and template configuration within authentik."
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
|
||||
msgid "Automatic import"
|
||||
msgstr ""
|
||||
|
||||
#: src/user/UserInterface.ts
|
||||
msgid "Avatar image"
|
||||
msgstr "Avatar resmi"
|
||||
|
@ -2426,6 +2430,7 @@ msgstr "Parolanı mi unuttun?"
|
|||
msgid "Forgot username or password?"
|
||||
msgstr "Kullanıcı adı veya parolayı mı unuttunuz?"
|
||||
|
||||
#: src/elements/forms/ModalForm.ts
|
||||
#: src/elements/forms/ModalForm.ts
|
||||
#: src/elements/wizard/FormWizardPage.ts
|
||||
#: src/elements/wizard/FormWizardPage.ts
|
||||
|
@ -3635,6 +3640,7 @@ msgstr "Ek veri yok."
|
|||
msgid "No additional setup is required."
|
||||
msgstr "Ek kurulum gerekmez."
|
||||
|
||||
#: src/elements/forms/ModalForm.ts
|
||||
#: src/elements/forms/ModalForm.ts
|
||||
#: src/elements/wizard/FormWizardPage.ts
|
||||
#: src/elements/wizard/FormWizardPage.ts
|
||||
|
@ -3933,6 +3939,10 @@ msgstr "İsteğe bağlı olarak onaylama özniteliğinin 'FriendlyName' değerin
|
|||
msgid "Or"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
|
||||
msgid "Or manually import"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/flows/BoundStagesList.ts
|
||||
#: src/admin/flows/StageBindingForm.ts
|
||||
#: src/admin/policies/BoundPoliciesList.ts
|
||||
|
@ -4083,9 +4093,13 @@ msgid "Path"
|
|||
msgstr ""
|
||||
|
||||
#: src/admin/stages/user_write/UserWriteStageForm.ts
|
||||
msgid "Path new users will be created under. If left blank, the default path will be used.fo"
|
||||
msgid "Path new users will be created under. If left blank, the default path will be used."
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/stages/user_write/UserWriteStageForm.ts
|
||||
#~ msgid "Path new users will be created under. If left blank, the default path will be used.fo"
|
||||
#~ msgstr ""
|
||||
|
||||
#: src/admin/sources/ldap/LDAPSourceForm.ts
|
||||
#: src/admin/sources/oauth/OAuthSourceForm.ts
|
||||
#: src/admin/sources/plex/PlexSourceForm.ts
|
||||
|
@ -4509,10 +4523,13 @@ msgid "Regular user"
|
|||
msgstr "Düzenli kullanıcı"
|
||||
|
||||
#: src/admin/applications/ApplicationViewPage.ts
|
||||
#: src/admin/flows/FlowViewPage.ts
|
||||
msgid "Related"
|
||||
msgstr "İlgili"
|
||||
|
||||
#: src/admin/flows/FlowViewPage.ts
|
||||
msgid "Related actions"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/providers/saml/SAMLProviderViewPage.ts
|
||||
#: src/admin/providers/saml/SAMLProviderViewPage.ts
|
||||
msgid "Related objects"
|
||||
|
@ -5238,6 +5255,10 @@ msgstr "Aşamalar, bir Akış'ın kullanıcının yönlendirildiği tek adımlar
|
|||
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/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
|
||||
msgid "Start automatic import"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/outposts/ServiceConnectionListPage.ts
|
||||
msgid "State"
|
||||
msgstr "Eyalet"
|
||||
|
@ -5472,6 +5493,10 @@ msgstr "Akış başarıyla aktarıldı."
|
|||
msgid "Successfully imported provider."
|
||||
msgstr "Sağlayıcı başarıyla içe aktarıldı."
|
||||
|
||||
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
|
||||
msgid "Successfully imported {0} devices."
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/users/UserResetEmailForm.ts
|
||||
msgid "Successfully sent email."
|
||||
msgstr "Başarıyla e-posta gönderildi."
|
||||
|
|
|
@ -638,6 +638,10 @@ msgstr "自动检测(基于您的浏览器)"
|
|||
msgid "Automate and template configuration within authentik."
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
|
||||
msgid "Automatic import"
|
||||
msgstr ""
|
||||
|
||||
#: src/user/UserInterface.ts
|
||||
msgid "Avatar image"
|
||||
msgstr "头像图片"
|
||||
|
@ -2414,6 +2418,7 @@ msgstr "忘记密码了吗?"
|
|||
msgid "Forgot username or password?"
|
||||
msgstr "忘记用户名或密码?"
|
||||
|
||||
#: src/elements/forms/ModalForm.ts
|
||||
#: src/elements/forms/ModalForm.ts
|
||||
#: src/elements/wizard/FormWizardPage.ts
|
||||
#: src/elements/wizard/FormWizardPage.ts
|
||||
|
@ -3617,6 +3622,7 @@ msgstr "没有可用的额外数据。"
|
|||
msgid "No additional setup is required."
|
||||
msgstr "无需进行额外设置。"
|
||||
|
||||
#: src/elements/forms/ModalForm.ts
|
||||
#: src/elements/forms/ModalForm.ts
|
||||
#: src/elements/wizard/FormWizardPage.ts
|
||||
#: src/elements/wizard/FormWizardPage.ts
|
||||
|
@ -3910,6 +3916,10 @@ msgstr "可选,设置断言属性的 'FriendlyName' 值。"
|
|||
msgid "Or"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
|
||||
msgid "Or manually import"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/flows/BoundStagesList.ts
|
||||
#: src/admin/flows/StageBindingForm.ts
|
||||
#: src/admin/policies/BoundPoliciesList.ts
|
||||
|
@ -4056,9 +4066,13 @@ msgid "Path"
|
|||
msgstr ""
|
||||
|
||||
#: src/admin/stages/user_write/UserWriteStageForm.ts
|
||||
msgid "Path new users will be created under. If left blank, the default path will be used.fo"
|
||||
msgid "Path new users will be created under. If left blank, the default path will be used."
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/stages/user_write/UserWriteStageForm.ts
|
||||
#~ msgid "Path new users will be created under. If left blank, the default path will be used.fo"
|
||||
#~ msgstr ""
|
||||
|
||||
#: src/admin/sources/ldap/LDAPSourceForm.ts
|
||||
#: src/admin/sources/oauth/OAuthSourceForm.ts
|
||||
#: src/admin/sources/plex/PlexSourceForm.ts
|
||||
|
@ -4479,10 +4493,13 @@ msgid "Regular user"
|
|||
msgstr "普通用户"
|
||||
|
||||
#: src/admin/applications/ApplicationViewPage.ts
|
||||
#: src/admin/flows/FlowViewPage.ts
|
||||
msgid "Related"
|
||||
msgstr "相关"
|
||||
|
||||
#: src/admin/flows/FlowViewPage.ts
|
||||
msgid "Related actions"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/providers/saml/SAMLProviderViewPage.ts
|
||||
#: src/admin/providers/saml/SAMLProviderViewPage.ts
|
||||
msgid "Related objects"
|
||||
|
@ -5202,6 +5219,10 @@ msgstr "阶段是引导用户完成流程的单个步骤。阶段只能在流程
|
|||
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/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
|
||||
msgid "Start automatic import"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/outposts/ServiceConnectionListPage.ts
|
||||
msgid "State"
|
||||
msgstr "状态"
|
||||
|
@ -5436,6 +5457,10 @@ msgstr "已成功导入流程。"
|
|||
msgid "Successfully imported provider."
|
||||
msgstr "已成功导入提供程序。"
|
||||
|
||||
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
|
||||
msgid "Successfully imported {0} devices."
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/users/UserResetEmailForm.ts
|
||||
msgid "Successfully sent email."
|
||||
msgstr "已成功发送电子邮件。"
|
||||
|
|
|
@ -640,6 +640,10 @@ msgstr "自动检测(基于您的浏览器)"
|
|||
msgid "Automate and template configuration within authentik."
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
|
||||
msgid "Automatic import"
|
||||
msgstr ""
|
||||
|
||||
#: src/user/UserInterface.ts
|
||||
msgid "Avatar image"
|
||||
msgstr "Avatar image"
|
||||
|
@ -2417,6 +2421,7 @@ msgstr "忘记密码了吗?"
|
|||
msgid "Forgot username or password?"
|
||||
msgstr "忘记用户名或密码?"
|
||||
|
||||
#: src/elements/forms/ModalForm.ts
|
||||
#: src/elements/forms/ModalForm.ts
|
||||
#: src/elements/wizard/FormWizardPage.ts
|
||||
#: src/elements/wizard/FormWizardPage.ts
|
||||
|
@ -3621,6 +3626,7 @@ msgstr "没有其他可用数据。"
|
|||
msgid "No additional setup is required."
|
||||
msgstr "无需进行其他设置。"
|
||||
|
||||
#: src/elements/forms/ModalForm.ts
|
||||
#: src/elements/forms/ModalForm.ts
|
||||
#: src/elements/wizard/FormWizardPage.ts
|
||||
#: src/elements/wizard/FormWizardPage.ts
|
||||
|
@ -3915,6 +3921,10 @@ msgstr "(可选)设置 “断言” 属性的'友好名称'值。"
|
|||
msgid "Or"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
|
||||
msgid "Or manually import"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/flows/BoundStagesList.ts
|
||||
#: src/admin/flows/StageBindingForm.ts
|
||||
#: src/admin/policies/BoundPoliciesList.ts
|
||||
|
@ -4061,9 +4071,13 @@ msgid "Path"
|
|||
msgstr ""
|
||||
|
||||
#: src/admin/stages/user_write/UserWriteStageForm.ts
|
||||
msgid "Path new users will be created under. If left blank, the default path will be used.fo"
|
||||
msgid "Path new users will be created under. If left blank, the default path will be used."
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/stages/user_write/UserWriteStageForm.ts
|
||||
#~ msgid "Path new users will be created under. If left blank, the default path will be used.fo"
|
||||
#~ msgstr ""
|
||||
|
||||
#: src/admin/sources/ldap/LDAPSourceForm.ts
|
||||
#: src/admin/sources/oauth/OAuthSourceForm.ts
|
||||
#: src/admin/sources/plex/PlexSourceForm.ts
|
||||
|
@ -4485,10 +4499,13 @@ msgid "Regular user"
|
|||
msgstr "普通用户"
|
||||
|
||||
#: src/admin/applications/ApplicationViewPage.ts
|
||||
#: src/admin/flows/FlowViewPage.ts
|
||||
msgid "Related"
|
||||
msgstr "相关"
|
||||
|
||||
#: src/admin/flows/FlowViewPage.ts
|
||||
msgid "Related actions"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/providers/saml/SAMLProviderViewPage.ts
|
||||
#: src/admin/providers/saml/SAMLProviderViewPage.ts
|
||||
msgid "Related objects"
|
||||
|
@ -5209,6 +5226,10 @@ msgstr "阶段是引导用户完成的流程的单个步骤。阶段只能在流
|
|||
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/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
|
||||
msgid "Start automatic import"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/outposts/ServiceConnectionListPage.ts
|
||||
msgid "State"
|
||||
msgstr "州"
|
||||
|
@ -5443,6 +5464,10 @@ msgstr "已成功导入流程。"
|
|||
msgid "Successfully imported provider."
|
||||
msgstr "已成功导入提供程序。"
|
||||
|
||||
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
|
||||
msgid "Successfully imported {0} devices."
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/users/UserResetEmailForm.ts
|
||||
msgid "Successfully sent email."
|
||||
msgstr "已成功发送电子邮件。"
|
||||
|
|
|
@ -640,6 +640,10 @@ msgstr "自动检测(基于您的浏览器)"
|
|||
msgid "Automate and template configuration within authentik."
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
|
||||
msgid "Automatic import"
|
||||
msgstr ""
|
||||
|
||||
#: src/user/UserInterface.ts
|
||||
msgid "Avatar image"
|
||||
msgstr "Avatar image"
|
||||
|
@ -2417,6 +2421,7 @@ msgstr "忘记密码了吗?"
|
|||
msgid "Forgot username or password?"
|
||||
msgstr "忘记用户名或密码?"
|
||||
|
||||
#: src/elements/forms/ModalForm.ts
|
||||
#: src/elements/forms/ModalForm.ts
|
||||
#: src/elements/wizard/FormWizardPage.ts
|
||||
#: src/elements/wizard/FormWizardPage.ts
|
||||
|
@ -3621,6 +3626,7 @@ msgstr "没有其他可用数据。"
|
|||
msgid "No additional setup is required."
|
||||
msgstr "无需进行其他设置。"
|
||||
|
||||
#: src/elements/forms/ModalForm.ts
|
||||
#: src/elements/forms/ModalForm.ts
|
||||
#: src/elements/wizard/FormWizardPage.ts
|
||||
#: src/elements/wizard/FormWizardPage.ts
|
||||
|
@ -3915,6 +3921,10 @@ msgstr "(可选)设置 “断言” 属性的'友好名称'值。"
|
|||
msgid "Or"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
|
||||
msgid "Or manually import"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/flows/BoundStagesList.ts
|
||||
#: src/admin/flows/StageBindingForm.ts
|
||||
#: src/admin/policies/BoundPoliciesList.ts
|
||||
|
@ -4061,9 +4071,13 @@ msgid "Path"
|
|||
msgstr ""
|
||||
|
||||
#: src/admin/stages/user_write/UserWriteStageForm.ts
|
||||
msgid "Path new users will be created under. If left blank, the default path will be used.fo"
|
||||
msgid "Path new users will be created under. If left blank, the default path will be used."
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/stages/user_write/UserWriteStageForm.ts
|
||||
#~ msgid "Path new users will be created under. If left blank, the default path will be used.fo"
|
||||
#~ msgstr ""
|
||||
|
||||
#: src/admin/sources/ldap/LDAPSourceForm.ts
|
||||
#: src/admin/sources/oauth/OAuthSourceForm.ts
|
||||
#: src/admin/sources/plex/PlexSourceForm.ts
|
||||
|
@ -4485,10 +4499,13 @@ msgid "Regular user"
|
|||
msgstr "普通用户"
|
||||
|
||||
#: src/admin/applications/ApplicationViewPage.ts
|
||||
#: src/admin/flows/FlowViewPage.ts
|
||||
msgid "Related"
|
||||
msgstr "相关"
|
||||
|
||||
#: src/admin/flows/FlowViewPage.ts
|
||||
msgid "Related actions"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/providers/saml/SAMLProviderViewPage.ts
|
||||
#: src/admin/providers/saml/SAMLProviderViewPage.ts
|
||||
msgid "Related objects"
|
||||
|
@ -5209,6 +5226,10 @@ msgstr "阶段是引导用户完成的流程的单个步骤。阶段只能在流
|
|||
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/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
|
||||
msgid "Start automatic import"
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/outposts/ServiceConnectionListPage.ts
|
||||
msgid "State"
|
||||
msgstr "州"
|
||||
|
@ -5443,6 +5464,10 @@ msgstr "已成功导入流程。"
|
|||
msgid "Successfully imported provider."
|
||||
msgstr "已成功导入提供程序。"
|
||||
|
||||
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
|
||||
msgid "Successfully imported {0} devices."
|
||||
msgstr ""
|
||||
|
||||
#: src/admin/users/UserResetEmailForm.ts
|
||||
msgid "Successfully sent email."
|
||||
msgstr "已成功发送电子邮件。"
|
||||
|
|
Reference in New Issue