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:
Jens L 2022-09-21 09:58:23 +02:00 committed by GitHub
parent 909a7772dc
commit 1583d53e54
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 4980 additions and 3452 deletions

View File

@ -1,21 +1,17 @@
"""Flow API Views""" """Flow API Views"""
from dataclasses import dataclass
from django.core.cache import cache from django.core.cache import cache
from django.db.models import Model
from django.http import HttpResponse from django.http import HttpResponse
from django.http.response import HttpResponseBadRequest from django.http.response import HttpResponseBadRequest
from django.urls import reverse from django.urls import reverse
from django.utils.translation import gettext as _ from django.utils.translation import gettext as _
from drf_spectacular.types import OpenApiTypes from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import OpenApiResponse, extend_schema 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.decorators import action
from rest_framework.fields import ReadOnlyField from rest_framework.fields import ReadOnlyField
from rest_framework.parsers import MultiPartParser from rest_framework.parsers import MultiPartParser
from rest_framework.request import Request from rest_framework.request import Request
from rest_framework.response import Response 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 rest_framework.viewsets import ModelViewSet
from structlog.stdlib import get_logger from structlog.stdlib import get_logger
@ -29,6 +25,7 @@ from authentik.core.api.utils import (
FileUploadSerializer, FileUploadSerializer,
LinkSerializer, LinkSerializer,
) )
from authentik.flows.api.flows_diagram import FlowDiagram, FlowDiagramSerializer
from authentik.flows.exceptions import FlowNonApplicableException from authentik.flows.exceptions import FlowNonApplicableException
from authentik.flows.models import Flow from authentik.flows.models import Flow
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER, FlowPlanner, cache_key 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): class FlowViewSet(UsedByMixin, ModelViewSet):
"""Flow Viewset""" """Flow Viewset"""
@ -208,89 +181,9 @@ class FlowViewSet(UsedByMixin, ModelViewSet):
# pylint: disable=unused-argument # pylint: disable=unused-argument
def diagram(self, request: Request, slug: str) -> Response: def diagram(self, request: Request, slug: str) -> Response:
"""Return diagram for flow with slug `slug`, in the format used by flowchart.js""" """Return diagram for flow with slug `slug`, in the format used by flowchart.js"""
flow = self.get_object() diagram = FlowDiagram(self.get_object(), request.user)
header = [ output = diagram.build()
DiagramElement("st", "start", "Start"), return Response({"diagram": output})
]
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})
@permission_required("authentik_flows.change_flow") @permission_required("authentik_flows.change_flow")
@extend_schema( @extend_schema(

View File

@ -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])

View File

@ -9,22 +9,20 @@ from authentik.policies.dummy.models import DummyPolicy
from authentik.policies.models import PolicyBinding from authentik.policies.models import PolicyBinding
from authentik.stages.dummy.models import DummyStage from authentik.stages.dummy.models import DummyStage
DIAGRAM_EXPECTED = """st=>start: Start DIAGRAM_EXPECTED = """graph TD
stage_0=>operation: Stage (Dummy Stage) --> flow_start[["Flow
dummy1 test-default-context"]]
stage_1_policy_0=>condition: Policy (Dummy Policy) --> stage_0(["Stage (Dummy Stage)
test dummy1"])
stage_1=>operation: Stage (Dummy Stage) stage_1_policy_0 --Policy passed--> stage_1(["Stage (Dummy Stage)
dummy2 dummy2"])
e=>end: End|future stage_0 --> stage_1_policy_0{{"Policy (Dummy Policy)
st(right)->stage_0 dummy2-policy"}}
stage_0(bottom)->stage_1_policy_0 stage_1 --> done[["End of the flow"]]"""
stage_1_policy_0(yes, right)->stage_1 DIAGRAM_SHORT_EXPECTED = """graph TD
stage_1_policy_0(no, bottom)->e --> flow_start[["Flow
stage_1(bottom)->e""" test-default-context"]]
DIAGRAM_SHORT_EXPECTED = """st=>start: Start flow_start --> done[["End of the flow"]]"""
e=>end: End|future
st(right)->e"""
class TestFlowsAPI(APITestCase): class TestFlowsAPI(APITestCase):
@ -55,7 +53,9 @@ class TestFlowsAPI(APITestCase):
slug="test-default-context", slug="test-default-context",
designation=FlowDesignation.AUTHENTICATION, 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( FlowStageBinding.objects.create(
target=flow, stage=DummyStage.objects.create(name="dummy1"), order=0 target=flow, stage=DummyStage.objects.create(name="dummy1"), order=0

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \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" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -268,89 +268,89 @@ msgstr ""
msgid "Certificate-Key Pairs" msgid "Certificate-Key Pairs"
msgstr "" msgstr ""
#: authentik/events/models.py:294 #: authentik/events/models.py:300
msgid "Event" msgid "Event"
msgstr "" msgstr ""
#: authentik/events/models.py:295 #: authentik/events/models.py:301
msgid "Events" msgid "Events"
msgstr "" msgstr ""
#: authentik/events/models.py:301 #: authentik/events/models.py:307
msgid "authentik inbuilt notifications" msgid "authentik inbuilt notifications"
msgstr "" msgstr ""
#: authentik/events/models.py:302 #: authentik/events/models.py:308
msgid "Generic Webhook" msgid "Generic Webhook"
msgstr "" msgstr ""
#: authentik/events/models.py:303 #: authentik/events/models.py:309
msgid "Slack Webhook (Slack/Discord)" msgid "Slack Webhook (Slack/Discord)"
msgstr "" msgstr ""
#: authentik/events/models.py:304 #: authentik/events/models.py:310
msgid "Email" msgid "Email"
msgstr "" msgstr ""
#: authentik/events/models.py:322 #: authentik/events/models.py:328
msgid "" msgid ""
"Only send notification once, for example when sending a webhook into a chat " "Only send notification once, for example when sending a webhook into a chat "
"channel." "channel."
msgstr "" msgstr ""
#: authentik/events/models.py:380 #: authentik/events/models.py:388
msgid "Severity" msgid "Severity"
msgstr "" msgstr ""
#: authentik/events/models.py:385 #: authentik/events/models.py:393
msgid "Dispatched for user" msgid "Dispatched for user"
msgstr "" msgstr ""
#: authentik/events/models.py:468 #: authentik/events/models.py:476
msgid "Notification Transport" msgid "Notification Transport"
msgstr "" msgstr ""
#: authentik/events/models.py:469 #: authentik/events/models.py:477
msgid "Notification Transports" msgid "Notification Transports"
msgstr "" msgstr ""
#: authentik/events/models.py:475 #: authentik/events/models.py:483
msgid "Notice" msgid "Notice"
msgstr "" msgstr ""
#: authentik/events/models.py:476 #: authentik/events/models.py:484
msgid "Warning" msgid "Warning"
msgstr "" msgstr ""
#: authentik/events/models.py:477 #: authentik/events/models.py:485
msgid "Alert" msgid "Alert"
msgstr "" msgstr ""
#: authentik/events/models.py:503 #: authentik/events/models.py:511
msgid "Notification" msgid "Notification"
msgstr "" msgstr ""
#: authentik/events/models.py:504 #: authentik/events/models.py:512
msgid "Notifications" msgid "Notifications"
msgstr "" msgstr ""
#: authentik/events/models.py:524 #: authentik/events/models.py:532
msgid "Controls which severity level the created notifications will have." msgid "Controls which severity level the created notifications will have."
msgstr "" msgstr ""
#: authentik/events/models.py:550 #: authentik/events/models.py:558
msgid "Notification Rule" msgid "Notification Rule"
msgstr "" msgstr ""
#: authentik/events/models.py:551 #: authentik/events/models.py:559
msgid "Notification Rules" msgid "Notification Rules"
msgstr "" msgstr ""
#: authentik/events/models.py:572 #: authentik/events/models.py:580
msgid "Notification Webhook Mapping" msgid "Notification Webhook Mapping"
msgstr "" msgstr ""
#: authentik/events/models.py:573 #: authentik/events/models.py:581
msgid "Notification Webhook Mappings" msgid "Notification Webhook Mappings"
msgstr "" msgstr ""
@ -358,19 +358,48 @@ msgstr ""
msgid "Task has not been run yet." msgid "Task has not been run yet."
msgstr "" 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 #, python-format
msgid "Policy (%(type)s)" msgid "Policy (%(type)s)"
msgstr "" 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 #, python-format
msgid "Stage (%(type)s)" msgid "Stage (%(type)s)"
msgstr "" msgstr ""
#: authentik/flows/api/flows.py:380 #: authentik/flows/api/flows_diagram.py:145
#, python-format #: authentik/flows/api/flows_diagram.py:179
msgid "Flow not applicable to current user/request: %(messages)s" 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 "" msgstr ""
#: authentik/flows/exceptions.py:17 #: authentik/flows/exceptions.py:17
@ -399,10 +428,6 @@ msgstr ""
msgid "Configure what should happen when a flow denies access to a user." msgid "Configure what should happen when a flow denies access to a user."
msgstr "" msgstr ""
#: authentik/flows/models.py:178
msgid "Flow"
msgstr ""
#: authentik/flows/models.py:179 #: authentik/flows/models.py:179
msgid "Flows" msgid "Flows"
msgstr "" msgstr ""
@ -1328,19 +1353,19 @@ msgstr ""
msgid "SAML Sources" msgid "SAML Sources"
msgstr "" msgstr ""
#: authentik/stages/authenticator_duo/models.py:80 #: authentik/stages/authenticator_duo/models.py:81
msgid "Duo Authenticator Setup Stage" msgid "Duo Authenticator Setup Stage"
msgstr "" msgstr ""
#: authentik/stages/authenticator_duo/models.py:81 #: authentik/stages/authenticator_duo/models.py:82
msgid "Duo Authenticator Setup Stages" msgid "Duo Authenticator Setup Stages"
msgstr "" msgstr ""
#: authentik/stages/authenticator_duo/models.py:105 #: authentik/stages/authenticator_duo/models.py:106
msgid "Duo Device" msgid "Duo Device"
msgstr "" msgstr ""
#: authentik/stages/authenticator_duo/models.py:106 #: authentik/stages/authenticator_duo/models.py:107
msgid "Duo Devices" msgid "Duo Devices"
msgstr "" msgstr ""

1463
web/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -85,6 +85,7 @@
"@types/chart.js": "^2.9.37", "@types/chart.js": "^2.9.37",
"@types/codemirror": "5.60.5", "@types/codemirror": "5.60.5",
"@types/grecaptcha": "^3.0.4", "@types/grecaptcha": "^3.0.4",
"@types/mermaid": "^9.1.0",
"@typescript-eslint/eslint-plugin": "^5.38.0", "@typescript-eslint/eslint-plugin": "^5.38.0",
"@typescript-eslint/parser": "^5.38.0", "@typescript-eslint/parser": "^5.38.0",
"@webcomponents/webcomponentsjs": "^2.6.0", "@webcomponents/webcomponentsjs": "^2.6.0",
@ -100,9 +101,9 @@
"eslint-config-google": "^0.14.0", "eslint-config-google": "^0.14.0",
"eslint-plugin-custom-elements": "0.0.6", "eslint-plugin-custom-elements": "0.0.6",
"eslint-plugin-lit": "^1.6.1", "eslint-plugin-lit": "^1.6.1",
"flowchart.js": "^1.17.1",
"fuse.js": "^6.6.2", "fuse.js": "^6.6.2",
"lit": "^2.3.1", "lit": "^2.3.1",
"mermaid": "^9.1.7",
"moment": "^2.29.4", "moment": "^2.29.4",
"prettier": "^2.7.1", "prettier": "^2.7.1",
"pyright": "^1.1.272", "pyright": "^1.1.272",

View File

@ -2,10 +2,11 @@ import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { EVENT_REFRESH } from "@goauthentik/common/constants"; import { EVENT_REFRESH } from "@goauthentik/common/constants";
import { AKElement } from "@goauthentik/elements/Base"; import { AKElement } from "@goauthentik/elements/Base";
import "@goauthentik/elements/EmptyState"; 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 { customElement, property } from "lit/decorators.js";
import { unsafeHTML } from "lit/directives/unsafe-html.js";
import { FlowsApi } from "@goauthentik/api"; import { FlowsApi } from "@goauthentik/api";
@ -35,34 +36,37 @@ export class FlowDiagram extends AKElement {
@property({ attribute: false }) @property({ attribute: false })
diagram?: string; diagram?: string;
@property()
fontColour: string = FONT_COLOUR_DARK_MODE;
@property()
fill: string = FILL_DARK_MODE;
handlerBound = false; handlerBound = false;
createRenderRoot(): Element | ShadowRoot {
return this;
}
get isInViewport(): boolean { get isInViewport(): boolean {
const rect = this.getBoundingClientRect(); const rect = this.getBoundingClientRect();
return !(rect.x + rect.y + rect.width + rect.height === 0); return !(rect.x + rect.y + rect.width + rect.height === 0);
} }
static get styles(): CSSResult[] {
return [
css`
:host {
display: flex;
justify-content: center;
}
`,
];
}
constructor() { constructor() {
super(); super();
const matcher = window.matchMedia("(prefers-color-scheme: light)"); const matcher = window.matchMedia("(prefers-color-scheme: light)");
const handler = (ev?: MediaQueryListEvent) => { const handler = (ev?: MediaQueryListEvent) => {
if (ev?.matches || matcher.matches) { console.log("setting config");
this.fontColour = FONT_COLOUR_LIGHT_MODE; mermaid.initialize({
this.fill = FILL_LIGHT_MODE; logLevel: "error",
} else { startOnLoad: false,
this.fontColour = FONT_COLOUR_DARK_MODE; theme: ev?.matches || matcher.matches ? "default" : "dark",
this.fill = FILL_DARK_MODE; flowchart: {
} curve: "linear",
},
});
this.requestUpdate(); this.requestUpdate();
}; };
matcher.addEventListener("change", handler); matcher.addEventListener("change", handler);
@ -93,18 +97,9 @@ export class FlowDiagram extends AKElement {
console.debug(`authentik/flow/diagram: failed to remove element ${el}`); console.debug(`authentik/flow/diagram: failed to remove element ${el}`);
} }
}); });
if (this.diagram) { if (!this.diagram) {
const diagram = FlowChart.parse(this.diagram); return html`<ak-empty-state ?loading=${true}></ak-empty-state>`;
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``;
} }
return html`<ak-empty-state ?loading=${true}></ak-empty-state>`; return html`${unsafeHTML(mermaid.render("graph", this.diagram))}`;
} }
} }

View File

@ -83,7 +83,7 @@ export class FlowViewPage extends AKElement {
<div <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" 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"> <div class="pf-c-card__body">
<dl class="pf-c-description-list"> <dl class="pf-c-description-list">
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
@ -104,7 +104,7 @@ export class FlowViewPage extends AKElement {
</ak-flow-form> </ak-flow-form>
<button <button
slot="trigger" slot="trigger"
class="pf-c-button pf-m-secondary" class="pf-c-button pf-m-block pf-m-secondary"
> >
${t`Edit`} ${t`Edit`}
</button> </button>
@ -119,7 +119,7 @@ export class FlowViewPage extends AKElement {
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text"> <div class="pf-c-description-list__text">
<button <button
class="pf-c-button pf-m-primary" class="pf-c-button pf-m-block pf-m-primary"
@click=${() => { @click=${() => {
const finalURL = `${ const finalURL = `${
window.location.origin window.location.origin
@ -132,7 +132,7 @@ export class FlowViewPage extends AKElement {
${t`Normal`} ${t`Normal`}
</button> </button>
<button <button
class="pf-c-button pf-m-secondary" class="pf-c-button pf-m-block pf-m-secondary"
@click=${() => { @click=${() => {
new FlowsApi(DEFAULT_CONFIG) new FlowsApi(DEFAULT_CONFIG)
.flowsInstancesExecuteRetrieve({ .flowsInstancesExecuteRetrieve({
@ -151,7 +151,7 @@ export class FlowViewPage extends AKElement {
${t`with current user`} ${t`with current user`}
</button> </button>
<button <button
class="pf-c-button pf-m-secondary" class="pf-c-button pf-m-block pf-m-secondary"
@click=${() => { @click=${() => {
new FlowsApi(DEFAULT_CONFIG) new FlowsApi(DEFAULT_CONFIG)
.flowsInstancesExecuteRetrieve({ .flowsInstancesExecuteRetrieve({
@ -187,7 +187,7 @@ export class FlowViewPage extends AKElement {
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text"> <div class="pf-c-description-list__text">
<a <a
class="pf-c-button pf-m-secondary" class="pf-c-button pf-m-block pf-m-secondary"
href=${this.flow.exportUrl} href=${this.flow.exportUrl}
> >
${t`Export`} ${t`Export`}

File diff suppressed because it is too large Load Diff

View File

@ -646,6 +646,10 @@ msgstr "Auto-detect (based on your browser)"
msgid "Automate and template configuration within authentik." msgid "Automate and template configuration within authentik."
msgstr "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 #: src/user/UserInterface.ts
msgid "Avatar image" msgid "Avatar image"
msgstr "Avatar image" msgstr "Avatar image"
@ -2471,6 +2475,7 @@ msgstr "Forgot password?"
msgid "Forgot username or password?" msgid "Forgot username or password?"
msgstr "Forgot username or password?" msgstr "Forgot username or password?"
#: src/elements/forms/ModalForm.ts
#: src/elements/forms/ModalForm.ts #: src/elements/forms/ModalForm.ts
#: src/elements/wizard/FormWizardPage.ts #: src/elements/wizard/FormWizardPage.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." msgid "No additional setup is required."
msgstr "No additional setup is required." msgstr "No additional setup is required."
#: src/elements/forms/ModalForm.ts
#: src/elements/forms/ModalForm.ts #: src/elements/forms/ModalForm.ts
#: src/elements/wizard/FormWizardPage.ts #: src/elements/wizard/FormWizardPage.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" msgid "Or"
msgstr "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/BoundStagesList.ts
#: src/admin/flows/StageBindingForm.ts #: src/admin/flows/StageBindingForm.ts
#: src/admin/policies/BoundPoliciesList.ts #: src/admin/policies/BoundPoliciesList.ts
@ -4152,8 +4162,12 @@ msgid "Path"
msgstr "Path" msgstr "Path"
#: src/admin/stages/user_write/UserWriteStageForm.ts #: 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 "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."
#: 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/ldap/LDAPSourceForm.ts
#: src/admin/sources/oauth/OAuthSourceForm.ts #: src/admin/sources/oauth/OAuthSourceForm.ts
@ -4588,10 +4602,13 @@ msgid "Regular user"
msgstr "Regular user" msgstr "Regular user"
#: src/admin/applications/ApplicationViewPage.ts #: src/admin/applications/ApplicationViewPage.ts
#: src/admin/flows/FlowViewPage.ts
msgid "Related" msgid "Related"
msgstr "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
#: src/admin/providers/saml/SAMLProviderViewPage.ts #: src/admin/providers/saml/SAMLProviderViewPage.ts
msgid "Related objects" 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." 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." 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 #: src/admin/outposts/ServiceConnectionListPage.ts
msgid "State" msgid "State"
msgstr "State" msgstr "State"
@ -5582,6 +5603,10 @@ msgstr "Successfully imported flow."
msgid "Successfully imported provider." msgid "Successfully imported provider."
msgstr "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 #: src/admin/users/UserResetEmailForm.ts
msgid "Successfully sent email." msgid "Successfully sent email."
msgstr "Successfully sent email." msgstr "Successfully sent email."

View File

@ -640,6 +640,10 @@ msgstr "Detección automática (según su navegador)"
msgid "Automate and template configuration within authentik." msgid "Automate and template configuration within authentik."
msgstr "" msgstr ""
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Automatic import"
msgstr ""
#: src/user/UserInterface.ts #: src/user/UserInterface.ts
msgid "Avatar image" msgid "Avatar image"
msgstr "Imagen de avatar" msgstr "Imagen de avatar"
@ -2426,6 +2430,7 @@ msgstr "¿Has olvidado tu contraseña"
msgid "Forgot username or password?" msgid "Forgot username or password?"
msgstr "¿Olvidó su nombre de usuario" msgstr "¿Olvidó su nombre de usuario"
#: src/elements/forms/ModalForm.ts
#: src/elements/forms/ModalForm.ts #: src/elements/forms/ModalForm.ts
#: src/elements/wizard/FormWizardPage.ts #: src/elements/wizard/FormWizardPage.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." msgid "No additional setup is required."
msgstr "No se requiere ninguna configuración adicional." msgstr "No se requiere ninguna configuración adicional."
#: src/elements/forms/ModalForm.ts
#: src/elements/forms/ModalForm.ts #: src/elements/forms/ModalForm.ts
#: src/elements/wizard/FormWizardPage.ts #: src/elements/wizard/FormWizardPage.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" msgid "Or"
msgstr "" msgstr ""
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Or manually import"
msgstr ""
#: src/admin/flows/BoundStagesList.ts #: src/admin/flows/BoundStagesList.ts
#: src/admin/flows/StageBindingForm.ts #: src/admin/flows/StageBindingForm.ts
#: src/admin/policies/BoundPoliciesList.ts #: src/admin/policies/BoundPoliciesList.ts
@ -4081,9 +4091,13 @@ msgid "Path"
msgstr "" msgstr ""
#: src/admin/stages/user_write/UserWriteStageForm.ts #: 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 "" 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/ldap/LDAPSourceForm.ts
#: src/admin/sources/oauth/OAuthSourceForm.ts #: src/admin/sources/oauth/OAuthSourceForm.ts
#: src/admin/sources/plex/PlexSourceForm.ts #: src/admin/sources/plex/PlexSourceForm.ts
@ -4507,10 +4521,13 @@ msgid "Regular user"
msgstr "Usuario habitual" msgstr "Usuario habitual"
#: src/admin/applications/ApplicationViewPage.ts #: src/admin/applications/ApplicationViewPage.ts
#: src/admin/flows/FlowViewPage.ts
msgid "Related" msgid "Related"
msgstr "Relacionado" msgstr "Relacionado"
#: src/admin/flows/FlowViewPage.ts
msgid "Related actions"
msgstr ""
#: src/admin/providers/saml/SAMLProviderViewPage.ts #: src/admin/providers/saml/SAMLProviderViewPage.ts
#: src/admin/providers/saml/SAMLProviderViewPage.ts #: src/admin/providers/saml/SAMLProviderViewPage.ts
msgid "Related objects" 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." 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 "" msgstr ""
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Start automatic import"
msgstr ""
#: src/admin/outposts/ServiceConnectionListPage.ts #: src/admin/outposts/ServiceConnectionListPage.ts
msgid "State" msgid "State"
msgstr "Estado" msgstr "Estado"
@ -5470,6 +5491,10 @@ msgstr "El flujo se importó correctamente."
msgid "Successfully imported provider." msgid "Successfully imported provider."
msgstr "El proveedor se importó correctamente." msgstr "El proveedor se importó correctamente."
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Successfully imported {0} devices."
msgstr ""
#: src/admin/users/UserResetEmailForm.ts #: src/admin/users/UserResetEmailForm.ts
msgid "Successfully sent email." msgid "Successfully sent email."
msgstr "El correo electrónico se envió correctamente." msgstr "El correo electrónico se envió correctamente."

View File

@ -646,6 +646,10 @@ msgstr ""
msgid "Automate and template configuration within authentik." msgid "Automate and template configuration within authentik."
msgstr "" msgstr ""
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Automatic import"
msgstr ""
#: src/user/UserInterface.ts #: src/user/UserInterface.ts
msgid "Avatar image" msgid "Avatar image"
msgstr "Image d'avatar" msgstr "Image d'avatar"
@ -2451,6 +2455,7 @@ msgstr "Mot de passe oublié ?"
msgid "Forgot username or password?" msgid "Forgot username or password?"
msgstr "Mot de passe ou nom d'utilisateur oublié ?" msgstr "Mot de passe ou nom d'utilisateur oublié ?"
#: src/elements/forms/ModalForm.ts
#: src/elements/forms/ModalForm.ts #: src/elements/forms/ModalForm.ts
#: src/elements/wizard/FormWizardPage.ts #: src/elements/wizard/FormWizardPage.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." msgid "No additional setup is required."
msgstr "" msgstr ""
#: src/elements/forms/ModalForm.ts
#: src/elements/forms/ModalForm.ts #: src/elements/forms/ModalForm.ts
#: src/elements/wizard/FormWizardPage.ts #: src/elements/wizard/FormWizardPage.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" msgid "Or"
msgstr "" msgstr ""
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Or manually import"
msgstr ""
#: src/admin/flows/BoundStagesList.ts #: src/admin/flows/BoundStagesList.ts
#: src/admin/flows/StageBindingForm.ts #: src/admin/flows/StageBindingForm.ts
#: src/admin/policies/BoundPoliciesList.ts #: src/admin/policies/BoundPoliciesList.ts
@ -4117,9 +4127,13 @@ msgid "Path"
msgstr "" msgstr ""
#: src/admin/stages/user_write/UserWriteStageForm.ts #: 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 "" 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/ldap/LDAPSourceForm.ts
#: src/admin/sources/oauth/OAuthSourceForm.ts #: src/admin/sources/oauth/OAuthSourceForm.ts
#: src/admin/sources/plex/PlexSourceForm.ts #: src/admin/sources/plex/PlexSourceForm.ts
@ -4550,10 +4564,13 @@ msgid "Regular user"
msgstr "Utilisateur normal" msgstr "Utilisateur normal"
#: src/admin/applications/ApplicationViewPage.ts #: src/admin/applications/ApplicationViewPage.ts
#: src/admin/flows/FlowViewPage.ts
msgid "Related" msgid "Related"
msgstr "Lié" msgstr "Lié"
#: src/admin/flows/FlowViewPage.ts
msgid "Related actions"
msgstr ""
#: src/admin/providers/saml/SAMLProviderViewPage.ts #: src/admin/providers/saml/SAMLProviderViewPage.ts
#: src/admin/providers/saml/SAMLProviderViewPage.ts #: src/admin/providers/saml/SAMLProviderViewPage.ts
msgid "Related objects" 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." 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 "" msgstr ""
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Start automatic import"
msgstr ""
#: src/admin/outposts/ServiceConnectionListPage.ts #: src/admin/outposts/ServiceConnectionListPage.ts
msgid "State" msgid "State"
msgstr "État" msgstr "État"
@ -5531,6 +5552,10 @@ msgstr "Flux importé avec succès"
msgid "Successfully imported provider." msgid "Successfully imported provider."
msgstr "Fournisseur importé avec succès" msgstr "Fournisseur importé avec succès"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Successfully imported {0} devices."
msgstr ""
#: src/admin/users/UserResetEmailForm.ts #: src/admin/users/UserResetEmailForm.ts
msgid "Successfully sent email." msgid "Successfully sent email."
msgstr "Email envoyé avec succès" msgstr "Email envoyé avec succès"

View File

@ -640,6 +640,10 @@ msgstr "Automatycznie wykryj (na podstawie Twojej przeglądarki)"
msgid "Automate and template configuration within authentik." msgid "Automate and template configuration within authentik."
msgstr "" msgstr ""
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Automatic import"
msgstr ""
#: src/user/UserInterface.ts #: src/user/UserInterface.ts
msgid "Avatar image" msgid "Avatar image"
msgstr "Obraz awatara" msgstr "Obraz awatara"
@ -2423,6 +2427,7 @@ msgstr "Zapomniałeś hasła?"
msgid "Forgot username or password?" msgid "Forgot username or password?"
msgstr "Zapomniałeś nazwy użytkownika lub hasła?" msgstr "Zapomniałeś nazwy użytkownika lub hasła?"
#: src/elements/forms/ModalForm.ts
#: src/elements/forms/ModalForm.ts #: src/elements/forms/ModalForm.ts
#: src/elements/wizard/FormWizardPage.ts #: src/elements/wizard/FormWizardPage.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." msgid "No additional setup is required."
msgstr "Nie jest wymagana żadna dodatkowa konfiguracja." msgstr "Nie jest wymagana żadna dodatkowa konfiguracja."
#: src/elements/forms/ModalForm.ts
#: src/elements/forms/ModalForm.ts #: src/elements/forms/ModalForm.ts
#: src/elements/wizard/FormWizardPage.ts #: src/elements/wizard/FormWizardPage.ts
#: src/elements/wizard/FormWizardPage.ts #: src/elements/wizard/FormWizardPage.ts
@ -3928,6 +3934,10 @@ msgstr "Opcjonalnie ustaw wartość „FriendlyName” atrybutu asercji."
msgid "Or" msgid "Or"
msgstr "" msgstr ""
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Or manually import"
msgstr ""
#: src/admin/flows/BoundStagesList.ts #: src/admin/flows/BoundStagesList.ts
#: src/admin/flows/StageBindingForm.ts #: src/admin/flows/StageBindingForm.ts
#: src/admin/policies/BoundPoliciesList.ts #: src/admin/policies/BoundPoliciesList.ts
@ -4078,9 +4088,13 @@ msgid "Path"
msgstr "" msgstr ""
#: src/admin/stages/user_write/UserWriteStageForm.ts #: 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 "" 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/ldap/LDAPSourceForm.ts
#: src/admin/sources/oauth/OAuthSourceForm.ts #: src/admin/sources/oauth/OAuthSourceForm.ts
#: src/admin/sources/plex/PlexSourceForm.ts #: src/admin/sources/plex/PlexSourceForm.ts
@ -4504,10 +4518,13 @@ msgid "Regular user"
msgstr "Zwykły użytkownik" msgstr "Zwykły użytkownik"
#: src/admin/applications/ApplicationViewPage.ts #: src/admin/applications/ApplicationViewPage.ts
#: src/admin/flows/FlowViewPage.ts
msgid "Related" msgid "Related"
msgstr "Związane z" 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
#: src/admin/providers/saml/SAMLProviderViewPage.ts #: src/admin/providers/saml/SAMLProviderViewPage.ts
msgid "Related objects" 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." 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 "" msgstr ""
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Start automatic import"
msgstr ""
#: src/admin/outposts/ServiceConnectionListPage.ts #: src/admin/outposts/ServiceConnectionListPage.ts
msgid "State" msgid "State"
msgstr "Stan" msgstr "Stan"
@ -5467,6 +5488,10 @@ msgstr "Pomyślnie zaimportowano przepływ."
msgid "Successfully imported provider." msgid "Successfully imported provider."
msgstr "Pomyślnie zaimportowano dostawcę." msgstr "Pomyślnie zaimportowano dostawcę."
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Successfully imported {0} devices."
msgstr ""
#: src/admin/users/UserResetEmailForm.ts #: src/admin/users/UserResetEmailForm.ts
msgid "Successfully sent email." msgid "Successfully sent email."
msgstr "Pomyślnie wysłano e-mail." msgstr "Pomyślnie wysłano e-mail."

View File

@ -638,6 +638,10 @@ msgstr ""
msgid "Automate and template configuration within authentik." msgid "Automate and template configuration within authentik."
msgstr "" msgstr ""
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Automatic import"
msgstr ""
#: src/user/UserInterface.ts #: src/user/UserInterface.ts
msgid "Avatar image" msgid "Avatar image"
msgstr "" msgstr ""
@ -2457,6 +2461,7 @@ msgstr ""
msgid "Forgot username or password?" msgid "Forgot username or password?"
msgstr "" msgstr ""
#: src/elements/forms/ModalForm.ts
#: src/elements/forms/ModalForm.ts #: src/elements/forms/ModalForm.ts
#: src/elements/wizard/FormWizardPage.ts #: src/elements/wizard/FormWizardPage.ts
#: src/elements/wizard/FormWizardPage.ts #: src/elements/wizard/FormWizardPage.ts
@ -3676,6 +3681,7 @@ msgstr ""
msgid "No additional setup is required." msgid "No additional setup is required."
msgstr "" msgstr ""
#: src/elements/forms/ModalForm.ts
#: src/elements/forms/ModalForm.ts #: src/elements/forms/ModalForm.ts
#: src/elements/wizard/FormWizardPage.ts #: src/elements/wizard/FormWizardPage.ts
#: src/elements/wizard/FormWizardPage.ts #: src/elements/wizard/FormWizardPage.ts
@ -3980,6 +3986,10 @@ msgstr ""
msgid "Or" msgid "Or"
msgstr "" msgstr ""
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Or manually import"
msgstr ""
#: src/admin/flows/BoundStagesList.ts #: src/admin/flows/BoundStagesList.ts
#: src/admin/flows/StageBindingForm.ts #: src/admin/flows/StageBindingForm.ts
#: src/admin/policies/BoundPoliciesList.ts #: src/admin/policies/BoundPoliciesList.ts
@ -4134,9 +4144,13 @@ msgid "Path"
msgstr "" msgstr ""
#: src/admin/stages/user_write/UserWriteStageForm.ts #: 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 "" 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/ldap/LDAPSourceForm.ts
#: src/admin/sources/oauth/OAuthSourceForm.ts #: src/admin/sources/oauth/OAuthSourceForm.ts
#: src/admin/sources/plex/PlexSourceForm.ts #: src/admin/sources/plex/PlexSourceForm.ts
@ -4568,10 +4582,13 @@ msgid "Regular user"
msgstr "" msgstr ""
#: src/admin/applications/ApplicationViewPage.ts #: src/admin/applications/ApplicationViewPage.ts
#: src/admin/flows/FlowViewPage.ts
msgid "Related" msgid "Related"
msgstr "" msgstr ""
#: src/admin/flows/FlowViewPage.ts
msgid "Related actions"
msgstr ""
#: src/admin/providers/saml/SAMLProviderViewPage.ts #: src/admin/providers/saml/SAMLProviderViewPage.ts
#: src/admin/providers/saml/SAMLProviderViewPage.ts #: src/admin/providers/saml/SAMLProviderViewPage.ts
msgid "Related objects" 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." 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 "" msgstr ""
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Start automatic import"
msgstr ""
#: src/admin/outposts/ServiceConnectionListPage.ts #: src/admin/outposts/ServiceConnectionListPage.ts
msgid "State" msgid "State"
msgstr "" msgstr ""
@ -5562,6 +5583,10 @@ msgstr ""
msgid "Successfully imported provider." msgid "Successfully imported provider."
msgstr "" msgstr ""
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Successfully imported {0} devices."
msgstr ""
#: src/admin/users/UserResetEmailForm.ts #: src/admin/users/UserResetEmailForm.ts
msgid "Successfully sent email." msgid "Successfully sent email."
msgstr "" msgstr ""

View File

@ -640,6 +640,10 @@ msgstr "Otomatik algıla (tarayıcınıza göre)"
msgid "Automate and template configuration within authentik." msgid "Automate and template configuration within authentik."
msgstr "" msgstr ""
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Automatic import"
msgstr ""
#: src/user/UserInterface.ts #: src/user/UserInterface.ts
msgid "Avatar image" msgid "Avatar image"
msgstr "Avatar resmi" msgstr "Avatar resmi"
@ -2426,6 +2430,7 @@ msgstr "Parolanı mi unuttun?"
msgid "Forgot username or password?" msgid "Forgot username or password?"
msgstr "Kullanıcı adı veya parolayı mı unuttunuz?" msgstr "Kullanıcı adı veya parolayı mı unuttunuz?"
#: src/elements/forms/ModalForm.ts
#: src/elements/forms/ModalForm.ts #: src/elements/forms/ModalForm.ts
#: src/elements/wizard/FormWizardPage.ts #: src/elements/wizard/FormWizardPage.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." msgid "No additional setup is required."
msgstr "Ek kurulum gerekmez." msgstr "Ek kurulum gerekmez."
#: src/elements/forms/ModalForm.ts
#: src/elements/forms/ModalForm.ts #: src/elements/forms/ModalForm.ts
#: src/elements/wizard/FormWizardPage.ts #: src/elements/wizard/FormWizardPage.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" msgid "Or"
msgstr "" msgstr ""
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Or manually import"
msgstr ""
#: src/admin/flows/BoundStagesList.ts #: src/admin/flows/BoundStagesList.ts
#: src/admin/flows/StageBindingForm.ts #: src/admin/flows/StageBindingForm.ts
#: src/admin/policies/BoundPoliciesList.ts #: src/admin/policies/BoundPoliciesList.ts
@ -4083,9 +4093,13 @@ msgid "Path"
msgstr "" msgstr ""
#: src/admin/stages/user_write/UserWriteStageForm.ts #: 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 "" 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/ldap/LDAPSourceForm.ts
#: src/admin/sources/oauth/OAuthSourceForm.ts #: src/admin/sources/oauth/OAuthSourceForm.ts
#: src/admin/sources/plex/PlexSourceForm.ts #: src/admin/sources/plex/PlexSourceForm.ts
@ -4509,10 +4523,13 @@ msgid "Regular user"
msgstr "Düzenli kullanıcı" msgstr "Düzenli kullanıcı"
#: src/admin/applications/ApplicationViewPage.ts #: src/admin/applications/ApplicationViewPage.ts
#: src/admin/flows/FlowViewPage.ts
msgid "Related" msgid "Related"
msgstr "İlgili" msgstr "İlgili"
#: src/admin/flows/FlowViewPage.ts
msgid "Related actions"
msgstr ""
#: src/admin/providers/saml/SAMLProviderViewPage.ts #: src/admin/providers/saml/SAMLProviderViewPage.ts
#: src/admin/providers/saml/SAMLProviderViewPage.ts #: src/admin/providers/saml/SAMLProviderViewPage.ts
msgid "Related objects" 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." 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 "" msgstr ""
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Start automatic import"
msgstr ""
#: src/admin/outposts/ServiceConnectionListPage.ts #: src/admin/outposts/ServiceConnectionListPage.ts
msgid "State" msgid "State"
msgstr "Eyalet" msgstr "Eyalet"
@ -5472,6 +5493,10 @@ msgstr "Akış başarıyla aktarıldı."
msgid "Successfully imported provider." msgid "Successfully imported provider."
msgstr "Sağlayıcı başarıyla içe aktarıldı." 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 #: src/admin/users/UserResetEmailForm.ts
msgid "Successfully sent email." msgid "Successfully sent email."
msgstr "Başarıyla e-posta gönderildi." msgstr "Başarıyla e-posta gönderildi."

View File

@ -638,6 +638,10 @@ msgstr "自动检测(基于您的浏览器)"
msgid "Automate and template configuration within authentik." msgid "Automate and template configuration within authentik."
msgstr "" msgstr ""
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Automatic import"
msgstr ""
#: src/user/UserInterface.ts #: src/user/UserInterface.ts
msgid "Avatar image" msgid "Avatar image"
msgstr "头像图片" msgstr "头像图片"
@ -2414,6 +2418,7 @@ msgstr "忘记密码了吗?"
msgid "Forgot username or password?" msgid "Forgot username or password?"
msgstr "忘记用户名或密码?" msgstr "忘记用户名或密码?"
#: src/elements/forms/ModalForm.ts
#: src/elements/forms/ModalForm.ts #: src/elements/forms/ModalForm.ts
#: src/elements/wizard/FormWizardPage.ts #: src/elements/wizard/FormWizardPage.ts
#: src/elements/wizard/FormWizardPage.ts #: src/elements/wizard/FormWizardPage.ts
@ -3617,6 +3622,7 @@ msgstr "没有可用的额外数据。"
msgid "No additional setup is required." msgid "No additional setup is required."
msgstr "无需进行额外设置。" msgstr "无需进行额外设置。"
#: src/elements/forms/ModalForm.ts
#: src/elements/forms/ModalForm.ts #: src/elements/forms/ModalForm.ts
#: src/elements/wizard/FormWizardPage.ts #: src/elements/wizard/FormWizardPage.ts
#: src/elements/wizard/FormWizardPage.ts #: src/elements/wizard/FormWizardPage.ts
@ -3910,6 +3916,10 @@ msgstr "可选,设置断言属性的 'FriendlyName' 值。"
msgid "Or" msgid "Or"
msgstr "" msgstr ""
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Or manually import"
msgstr ""
#: src/admin/flows/BoundStagesList.ts #: src/admin/flows/BoundStagesList.ts
#: src/admin/flows/StageBindingForm.ts #: src/admin/flows/StageBindingForm.ts
#: src/admin/policies/BoundPoliciesList.ts #: src/admin/policies/BoundPoliciesList.ts
@ -4056,9 +4066,13 @@ msgid "Path"
msgstr "" msgstr ""
#: src/admin/stages/user_write/UserWriteStageForm.ts #: 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 "" 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/ldap/LDAPSourceForm.ts
#: src/admin/sources/oauth/OAuthSourceForm.ts #: src/admin/sources/oauth/OAuthSourceForm.ts
#: src/admin/sources/plex/PlexSourceForm.ts #: src/admin/sources/plex/PlexSourceForm.ts
@ -4479,10 +4493,13 @@ msgid "Regular user"
msgstr "普通用户" msgstr "普通用户"
#: src/admin/applications/ApplicationViewPage.ts #: src/admin/applications/ApplicationViewPage.ts
#: src/admin/flows/FlowViewPage.ts
msgid "Related" msgid "Related"
msgstr "相关" msgstr "相关"
#: src/admin/flows/FlowViewPage.ts
msgid "Related actions"
msgstr ""
#: src/admin/providers/saml/SAMLProviderViewPage.ts #: src/admin/providers/saml/SAMLProviderViewPage.ts
#: src/admin/providers/saml/SAMLProviderViewPage.ts #: src/admin/providers/saml/SAMLProviderViewPage.ts
msgid "Related objects" 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." 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 "当用户没有任何兼容的设备时,用来配置身份验证器的阶段。此阶段通过后,将不再请求此用户。" msgstr "当用户没有任何兼容的设备时,用来配置身份验证器的阶段。此阶段通过后,将不再请求此用户。"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Start automatic import"
msgstr ""
#: src/admin/outposts/ServiceConnectionListPage.ts #: src/admin/outposts/ServiceConnectionListPage.ts
msgid "State" msgid "State"
msgstr "状态" msgstr "状态"
@ -5436,6 +5457,10 @@ msgstr "已成功导入流程。"
msgid "Successfully imported provider." msgid "Successfully imported provider."
msgstr "已成功导入提供程序。" msgstr "已成功导入提供程序。"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Successfully imported {0} devices."
msgstr ""
#: src/admin/users/UserResetEmailForm.ts #: src/admin/users/UserResetEmailForm.ts
msgid "Successfully sent email." msgid "Successfully sent email."
msgstr "已成功发送电子邮件。" msgstr "已成功发送电子邮件。"

View File

@ -640,6 +640,10 @@ msgstr "自动检测(基于您的浏览器)"
msgid "Automate and template configuration within authentik." msgid "Automate and template configuration within authentik."
msgstr "" msgstr ""
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Automatic import"
msgstr ""
#: src/user/UserInterface.ts #: src/user/UserInterface.ts
msgid "Avatar image" msgid "Avatar image"
msgstr "Avatar image" msgstr "Avatar image"
@ -2417,6 +2421,7 @@ msgstr "忘记密码了吗?"
msgid "Forgot username or password?" msgid "Forgot username or password?"
msgstr "忘记用户名或密码?" msgstr "忘记用户名或密码?"
#: src/elements/forms/ModalForm.ts
#: src/elements/forms/ModalForm.ts #: src/elements/forms/ModalForm.ts
#: src/elements/wizard/FormWizardPage.ts #: src/elements/wizard/FormWizardPage.ts
#: src/elements/wizard/FormWizardPage.ts #: src/elements/wizard/FormWizardPage.ts
@ -3621,6 +3626,7 @@ msgstr "没有其他可用数据。"
msgid "No additional setup is required." msgid "No additional setup is required."
msgstr "无需进行其他设置。" msgstr "无需进行其他设置。"
#: src/elements/forms/ModalForm.ts
#: src/elements/forms/ModalForm.ts #: src/elements/forms/ModalForm.ts
#: src/elements/wizard/FormWizardPage.ts #: src/elements/wizard/FormWizardPage.ts
#: src/elements/wizard/FormWizardPage.ts #: src/elements/wizard/FormWizardPage.ts
@ -3915,6 +3921,10 @@ msgstr "(可选)设置 “断言” 属性的'友好名称'值。"
msgid "Or" msgid "Or"
msgstr "" msgstr ""
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Or manually import"
msgstr ""
#: src/admin/flows/BoundStagesList.ts #: src/admin/flows/BoundStagesList.ts
#: src/admin/flows/StageBindingForm.ts #: src/admin/flows/StageBindingForm.ts
#: src/admin/policies/BoundPoliciesList.ts #: src/admin/policies/BoundPoliciesList.ts
@ -4061,9 +4071,13 @@ msgid "Path"
msgstr "" msgstr ""
#: src/admin/stages/user_write/UserWriteStageForm.ts #: 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 "" 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/ldap/LDAPSourceForm.ts
#: src/admin/sources/oauth/OAuthSourceForm.ts #: src/admin/sources/oauth/OAuthSourceForm.ts
#: src/admin/sources/plex/PlexSourceForm.ts #: src/admin/sources/plex/PlexSourceForm.ts
@ -4485,10 +4499,13 @@ msgid "Regular user"
msgstr "普通用户" msgstr "普通用户"
#: src/admin/applications/ApplicationViewPage.ts #: src/admin/applications/ApplicationViewPage.ts
#: src/admin/flows/FlowViewPage.ts
msgid "Related" msgid "Related"
msgstr "相关" msgstr "相关"
#: src/admin/flows/FlowViewPage.ts
msgid "Related actions"
msgstr ""
#: src/admin/providers/saml/SAMLProviderViewPage.ts #: src/admin/providers/saml/SAMLProviderViewPage.ts
#: src/admin/providers/saml/SAMLProviderViewPage.ts #: src/admin/providers/saml/SAMLProviderViewPage.ts
msgid "Related objects" 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." 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 "当用户没有任何兼容的设备时,用来配置身份验证器的阶段。此阶段通过后,将不再请求此用户。" msgstr "当用户没有任何兼容的设备时,用来配置身份验证器的阶段。此阶段通过后,将不再请求此用户。"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Start automatic import"
msgstr ""
#: src/admin/outposts/ServiceConnectionListPage.ts #: src/admin/outposts/ServiceConnectionListPage.ts
msgid "State" msgid "State"
msgstr "州" msgstr "州"
@ -5443,6 +5464,10 @@ msgstr "已成功导入流程。"
msgid "Successfully imported provider." msgid "Successfully imported provider."
msgstr "已成功导入提供程序。" msgstr "已成功导入提供程序。"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Successfully imported {0} devices."
msgstr ""
#: src/admin/users/UserResetEmailForm.ts #: src/admin/users/UserResetEmailForm.ts
msgid "Successfully sent email." msgid "Successfully sent email."
msgstr "已成功发送电子邮件。" msgstr "已成功发送电子邮件。"

View File

@ -640,6 +640,10 @@ msgstr "自动检测(基于您的浏览器)"
msgid "Automate and template configuration within authentik." msgid "Automate and template configuration within authentik."
msgstr "" msgstr ""
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Automatic import"
msgstr ""
#: src/user/UserInterface.ts #: src/user/UserInterface.ts
msgid "Avatar image" msgid "Avatar image"
msgstr "Avatar image" msgstr "Avatar image"
@ -2417,6 +2421,7 @@ msgstr "忘记密码了吗?"
msgid "Forgot username or password?" msgid "Forgot username or password?"
msgstr "忘记用户名或密码?" msgstr "忘记用户名或密码?"
#: src/elements/forms/ModalForm.ts
#: src/elements/forms/ModalForm.ts #: src/elements/forms/ModalForm.ts
#: src/elements/wizard/FormWizardPage.ts #: src/elements/wizard/FormWizardPage.ts
#: src/elements/wizard/FormWizardPage.ts #: src/elements/wizard/FormWizardPage.ts
@ -3621,6 +3626,7 @@ msgstr "没有其他可用数据。"
msgid "No additional setup is required." msgid "No additional setup is required."
msgstr "无需进行其他设置。" msgstr "无需进行其他设置。"
#: src/elements/forms/ModalForm.ts
#: src/elements/forms/ModalForm.ts #: src/elements/forms/ModalForm.ts
#: src/elements/wizard/FormWizardPage.ts #: src/elements/wizard/FormWizardPage.ts
#: src/elements/wizard/FormWizardPage.ts #: src/elements/wizard/FormWizardPage.ts
@ -3915,6 +3921,10 @@ msgstr "(可选)设置 “断言” 属性的'友好名称'值。"
msgid "Or" msgid "Or"
msgstr "" msgstr ""
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Or manually import"
msgstr ""
#: src/admin/flows/BoundStagesList.ts #: src/admin/flows/BoundStagesList.ts
#: src/admin/flows/StageBindingForm.ts #: src/admin/flows/StageBindingForm.ts
#: src/admin/policies/BoundPoliciesList.ts #: src/admin/policies/BoundPoliciesList.ts
@ -4061,9 +4071,13 @@ msgid "Path"
msgstr "" msgstr ""
#: src/admin/stages/user_write/UserWriteStageForm.ts #: 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 "" 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/ldap/LDAPSourceForm.ts
#: src/admin/sources/oauth/OAuthSourceForm.ts #: src/admin/sources/oauth/OAuthSourceForm.ts
#: src/admin/sources/plex/PlexSourceForm.ts #: src/admin/sources/plex/PlexSourceForm.ts
@ -4485,10 +4499,13 @@ msgid "Regular user"
msgstr "普通用户" msgstr "普通用户"
#: src/admin/applications/ApplicationViewPage.ts #: src/admin/applications/ApplicationViewPage.ts
#: src/admin/flows/FlowViewPage.ts
msgid "Related" msgid "Related"
msgstr "相关" msgstr "相关"
#: src/admin/flows/FlowViewPage.ts
msgid "Related actions"
msgstr ""
#: src/admin/providers/saml/SAMLProviderViewPage.ts #: src/admin/providers/saml/SAMLProviderViewPage.ts
#: src/admin/providers/saml/SAMLProviderViewPage.ts #: src/admin/providers/saml/SAMLProviderViewPage.ts
msgid "Related objects" 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." 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 "当用户没有任何兼容的设备时,用来配置身份验证器的阶段。此阶段通过后,将不再请求此用户。" msgstr "当用户没有任何兼容的设备时,用来配置身份验证器的阶段。此阶段通过后,将不再请求此用户。"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Start automatic import"
msgstr ""
#: src/admin/outposts/ServiceConnectionListPage.ts #: src/admin/outposts/ServiceConnectionListPage.ts
msgid "State" msgid "State"
msgstr "州" msgstr "州"
@ -5443,6 +5464,10 @@ msgstr "已成功导入流程。"
msgid "Successfully imported provider." msgid "Successfully imported provider."
msgstr "已成功导入提供程序。" msgstr "已成功导入提供程序。"
#: src/admin/stages/authenticator_duo/DuoDeviceImportForm.ts
msgid "Successfully imported {0} devices."
msgstr ""
#: src/admin/users/UserResetEmailForm.ts #: src/admin/users/UserResetEmailForm.ts
msgid "Successfully sent email." msgid "Successfully sent email."
msgstr "已成功发送电子邮件。" msgstr "已成功发送电子邮件。"