Merge pull request #691 from BeryJu/web-intl

This commit is contained in:
Jens L 2021-04-03 21:32:57 +02:00 committed by GitHub
commit e8dc6b259f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
165 changed files with 11779 additions and 2071 deletions

View File

@ -1,10 +1,8 @@
"""authentik api urls""" """authentik api urls"""
from django.urls import include, path from django.urls import include, path
from django.views.i18n import JavaScriptCatalog
from authentik.api.v2.urls import urlpatterns as v2_urls from authentik.api.v2.urls import urlpatterns as v2_urls
urlpatterns = [ urlpatterns = [
path("v2beta/", include(v2_urls)), path("v2beta/", include(v2_urls)),
path("jsi18n/", JavaScriptCatalog.as_view(), name="javascript-catalog"),
] ]

View File

@ -61,23 +61,23 @@ class UserMetricsSerializer(PassiveSerializer):
@swagger_serializer_method(serializer_or_field=CoordinateSerializer(many=True)) @swagger_serializer_method(serializer_or_field=CoordinateSerializer(many=True))
def get_logins_per_1h(self, _): def get_logins_per_1h(self, _):
"""Get successful logins per hour for the last 24 hours""" """Get successful logins per hour for the last 24 hours"""
request = self.context["request"]._request user = self.context["user"]
return get_events_per_1h(action=EventAction.LOGIN, user__pk=request.user.pk) return get_events_per_1h(action=EventAction.LOGIN, user__pk=user.pk)
@swagger_serializer_method(serializer_or_field=CoordinateSerializer(many=True)) @swagger_serializer_method(serializer_or_field=CoordinateSerializer(many=True))
def get_logins_failed_per_1h(self, _): def get_logins_failed_per_1h(self, _):
"""Get failed logins per hour for the last 24 hours""" """Get failed logins per hour for the last 24 hours"""
request = self.context["request"]._request user = self.context["user"]
return get_events_per_1h( return get_events_per_1h(
action=EventAction.LOGIN_FAILED, context__username=request.user.username action=EventAction.LOGIN_FAILED, context__username=user.username
) )
@swagger_serializer_method(serializer_or_field=CoordinateSerializer(many=True)) @swagger_serializer_method(serializer_or_field=CoordinateSerializer(many=True))
def get_authorizations_per_1h(self, _): def get_authorizations_per_1h(self, _):
"""Get failed logins per hour for the last 24 hours""" """Get failed logins per hour for the last 24 hours"""
request = self.context["request"]._request user = self.context["user"]
return get_events_per_1h( return get_events_per_1h(
action=EventAction.AUTHORIZE_APPLICATION, user__pk=request.user.pk action=EventAction.AUTHORIZE_APPLICATION, user__pk=user.pk
) )
@ -109,11 +109,13 @@ class UserViewSet(ModelViewSet):
@permission_required("authentik_core.view_user", ["authentik_events.view_event"]) @permission_required("authentik_core.view_user", ["authentik_events.view_event"])
@swagger_auto_schema(responses={200: UserMetricsSerializer(many=False)}) @swagger_auto_schema(responses={200: UserMetricsSerializer(many=False)})
@action(detail=False, pagination_class=None, filter_backends=[]) @action(detail=True, pagination_class=None, filter_backends=[])
def metrics(self, request: Request) -> Response: # pylint: disable=invalid-name, unused-argument
def metrics(self, request: Request, pk: int) -> Response:
"""User metrics per 1h""" """User metrics per 1h"""
user: User = self.get_object()
serializer = UserMetricsSerializer(True) serializer = UserMetricsSerializer(True)
serializer.context["request"] = request serializer.context["user"] = user
return Response(serializer.data) return Response(serializer.data)
@permission_required("authentik_core.reset_user_password") @permission_required("authentik_core.reset_user_password")

View File

@ -12,8 +12,7 @@
<link rel="shortcut icon" type="image/png" href="{% static 'dist/assets/icons/icon.png' %}?v={{ ak_version }}"> <link rel="shortcut icon" type="image/png" href="{% static 'dist/assets/icons/icon.png' %}?v={{ ak_version }}">
<link rel="stylesheet" type="text/css" href="{% static 'dist/patternfly.min.css' %}?v={{ ak_version }}"> <link rel="stylesheet" type="text/css" href="{% static 'dist/patternfly.min.css' %}?v={{ ak_version }}">
<link rel="stylesheet" type="text/css" href="{% static 'dist/authentik.css' %}?v={{ ak_version }}"> <link rel="stylesheet" type="text/css" href="{% static 'dist/authentik.css' %}?v={{ ak_version }}">
<script src="{% url 'authentik_api:javascript-catalog' %}?v={{ ak_version }}"></script> <script src="{% static 'dist/poly.js' %}?v={{ ak_version }}" type="module"></script>
<script src="{% static 'dist/adoptedStyleSheets.js' %}?v={{ ak_version }}" type="module"></script>
{% block head %} {% block head %}
{% endblock %} {% endblock %}
</head> </head>

View File

@ -1,5 +1,4 @@
"""NotificationTransport API Views""" """NotificationTransport API Views"""
from django.http.response import Http404
from drf_yasg.utils import no_body, swagger_auto_schema from drf_yasg.utils import no_body, swagger_auto_schema
from rest_framework.decorators import action from rest_framework.decorators import action
from rest_framework.fields import CharField, ListField, SerializerMethodField from rest_framework.fields import CharField, ListField, SerializerMethodField
@ -68,10 +67,7 @@ class NotificationTransportViewSet(ModelViewSet):
def test(self, request: Request, pk=None) -> Response: def test(self, request: Request, pk=None) -> Response:
"""Send example notification using selected transport. Requires """Send example notification using selected transport. Requires
Modify permissions.""" Modify permissions."""
transports = self.get_object() transport: NotificationTransport = self.get_object()
if not transports.exists():
raise Http404
transport: NotificationTransport = transports.first()
notification = Notification( notification = Notification(
severity=NotificationSeverity.NOTICE, severity=NotificationSeverity.NOTICE,
body=f"Test Notification from transport {transport.name}", body=f"Test Notification from transport {transport.name}",

View File

@ -109,14 +109,14 @@ class PolicyViewSet(
) )
return Response(TypeCreateSerializer(data, many=True).data) return Response(TypeCreateSerializer(data, many=True).data)
@permission_required("authentik_policies.view_policy_cache") @permission_required(None, ["authentik_policies.view_policy_cache"])
@swagger_auto_schema(responses={200: CacheSerializer(many=False)}) @swagger_auto_schema(responses={200: CacheSerializer(many=False)})
@action(detail=False, pagination_class=None, filter_backends=[]) @action(detail=False, pagination_class=None, filter_backends=[])
def cache_info(self, request: Request) -> Response: def cache_info(self, request: Request) -> Response:
"""Info about cached policies""" """Info about cached policies"""
return Response(data={"count": len(cache.keys("policy_*"))}) return Response(data={"count": len(cache.keys("policy_*"))})
@permission_required("authentik_policies.clear_policy_cache") @permission_required(None, ["authentik_policies.clear_policy_cache"])
@swagger_auto_schema( @swagger_auto_schema(
request_body=no_body, request_body=no_body,
responses={204: "Successfully cleared cache", 400: "Bad request"}, responses={204: "Successfully cleared cache", 400: "Bad request"},

View File

@ -2087,23 +2087,6 @@ paths:
tags: tags:
- core - core
parameters: [] parameters: []
/core/users/metrics/:
get:
operationId: core_users_metrics
description: User metrics per 1h
parameters: []
responses:
'200':
description: ''
schema:
$ref: '#/definitions/UserMetrics'
'403':
description: Authentication credentials were invalid, absent or insufficient.
schema:
$ref: '#/definitions/GenericError'
tags:
- core
parameters: []
/core/users/{id}/: /core/users/{id}/:
get: get:
operationId: core_users_read operationId: core_users_read
@ -2207,6 +2190,33 @@ paths:
description: A unique integer value identifying this User. description: A unique integer value identifying this User.
required: true required: true
type: integer type: integer
/core/users/{id}/metrics/:
get:
operationId: core_users_metrics
description: User metrics per 1h
parameters: []
responses:
'200':
description: ''
schema:
$ref: '#/definitions/UserMetrics'
'403':
description: Authentication credentials were invalid, absent or insufficient.
schema:
$ref: '#/definitions/GenericError'
'404':
description: Object does not exist or caller has insufficient permissions
to access it.
schema:
$ref: '#/definitions/APIException'
tags:
- core
parameters:
- name: id
in: path
description: A unique integer value identifying this User.
required: true
type: integer
/core/users/{id}/recovery/: /core/users/{id}/recovery/:
get: get:
operationId: core_users_recovery operationId: core_users_recovery

27
web/.babelrc Normal file
View File

@ -0,0 +1,27 @@
{
"presets": [
"@babel/env",
"@babel/typescript"
],
"plugins": [
[
"@babel/plugin-proposal-decorators",
{
"decoratorsBeforeExport": true
}
],
[
"@babel/plugin-proposal-class-properties",
{
"loose": true
}
],
[
"@babel/plugin-transform-runtime",
{
"regenerator": true
}
],
"macros"
]
}

3153
web/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -4,51 +4,81 @@
"private": true, "private": true,
"license": "GNU GPLv3", "license": "GNU GPLv3",
"scripts": { "scripts": {
"build": "rollup -c ./rollup.config.js", "extract": "lingui extract",
"watch": "rollup -c -w", "build": "lingui compile && rollup -c ./rollup.config.js",
"watch": "lingui compile && rollup -c -w",
"lint": "eslint . --max-warnings 0", "lint": "eslint . --max-warnings 0",
"lit-analyse": "lit-analyzer src" "lit-analyse": "lit-analyzer src"
}, },
"lingui": {
"sourceLocale": "en",
"locales": ["en", "pseudo-LOCALE"],
"pseudoLocale": "pseudo-LOCALE",
"fallbackLocales": {
"pseudo-LOCALE": "en"
},
"compileNamespace": "ts",
"catalogs": [
{
"path": "src/locales/{locale}",
"include": [
"src"
],
"exclude": [
"**/node_modules/**",
"**/dist/**"
]
}
]
},
"dependencies": { "dependencies": {
"@babel/core": "^7.13.14",
"@babel/plugin-proposal-decorators": "^7.13.5",
"@babel/plugin-transform-runtime": "^7.13.10",
"@babel/preset-env": "^7.13.12",
"@babel/preset-typescript": "^7.13.0",
"@fortawesome/fontawesome-free": "^5.15.3", "@fortawesome/fontawesome-free": "^5.15.3",
"@lingui/cli": "^3.8.2",
"@lingui/core": "^3.8.2",
"@lingui/macro": "^3.8.2",
"@patternfly/patternfly": "^4.96.2", "@patternfly/patternfly": "^4.96.2",
"@polymer/iron-form": "^3.0.1", "@polymer/iron-form": "^3.0.1",
"@polymer/paper-input": "^3.2.1", "@polymer/paper-input": "^3.2.1",
"@rollup/plugin-babel": "^5.3.0",
"@rollup/plugin-replace": "^2.4.2",
"@rollup/plugin-typescript": "^8.2.1",
"@sentry/browser": "^6.2.5", "@sentry/browser": "^6.2.5",
"@sentry/tracing": "^6.2.5", "@sentry/tracing": "^6.2.5",
"@types/chart.js": "^2.9.31", "@types/chart.js": "^2.9.31",
"@types/codemirror": "0.0.108", "@types/codemirror": "0.0.108",
"@types/grecaptcha": "^3.0.1", "@types/grecaptcha": "^3.0.1",
"@typescript-eslint/eslint-plugin": "^4.20.0",
"@typescript-eslint/parser": "^4.20.0",
"authentik-api": "file:api", "authentik-api": "file:api",
"babel-plugin-macros": "^3.0.1",
"base64-js": "^1.5.1", "base64-js": "^1.5.1",
"chart.js": "^2.9.4", "chart.js": "^2.9.4",
"codemirror": "^5.60.0", "codemirror": "^5.60.0",
"construct-style-sheets-polyfill": "^2.4.16", "construct-style-sheets-polyfill": "^2.4.16",
"eslint-config-google": "^0.14.0",
"eslint-plugin-lit": "^1.3.0",
"eslint": "^7.23.0",
"flowchart.js": "^1.15.0", "flowchart.js": "^1.15.0",
"lit-element": "^2.4.0", "lit-element": "^2.4.0",
"lit-html": "^1.3.0", "lit-html": "^1.3.0",
"rapidoc": "^8.4.9", "rapidoc": "^8.4.9",
"rollup": "^2.44.0", "rollup-plugin-commonjs": "^10.1.0",
"rollup-plugin-copy": "^3.4.0", "rollup-plugin-copy": "^3.4.0",
"rollup-plugin-cssimport": "^1.0.2", "rollup-plugin-cssimport": "^1.0.2",
"rollup-plugin-external-globals": "^0.6.1",
"tslib": "^2.1.0",
"webcomponent-qr-code": "^1.0.5",
"yaml": "^1.10.2"
},
"devDependencies": {
"@rollup/plugin-typescript": "^8.2.1",
"@typescript-eslint/eslint-plugin": "^4.20.0",
"@typescript-eslint/parser": "^4.20.0",
"eslint": "^7.23.0",
"eslint-config-google": "^0.14.0",
"eslint-plugin-lit": "^1.3.0",
"rollup-plugin-commonjs": "^10.1.0",
"rollup-plugin-minify-html-literals": "^1.2.6", "rollup-plugin-minify-html-literals": "^1.2.6",
"rollup-plugin-node-resolve": "^5.2.0", "rollup-plugin-node-resolve": "^5.2.0",
"rollup-plugin-sourcemaps": "^0.6.3", "rollup-plugin-sourcemaps": "^0.6.3",
"rollup-plugin-terser": "^7.0.2", "rollup-plugin-terser": "^7.0.2",
"rollup": "^2.44.0",
"ts-lit-plugin": "^1.2.1", "ts-lit-plugin": "^1.2.1",
"typescript": "^4.2.3" "tslib": "^2.1.0",
"typescript": "^4.2.3",
"webcomponent-qr-code": "^1.0.5",
"yaml": "^1.10.2"
} }
} }

View File

@ -5,7 +5,12 @@ import sourcemaps from "rollup-plugin-sourcemaps";
import typescript from "@rollup/plugin-typescript"; import typescript from "@rollup/plugin-typescript";
import cssimport from "rollup-plugin-cssimport"; import cssimport from "rollup-plugin-cssimport";
import copy from "rollup-plugin-copy"; import copy from "rollup-plugin-copy";
import externalGlobals from "rollup-plugin-external-globals"; import babel from "@rollup/plugin-babel";
import replace from "@rollup/plugin-replace";
const extensions = [
".js", ".jsx", ".ts", ".tsx",
];
const resources = [ const resources = [
{ src: "node_modules/rapidoc/dist/rapidoc-min.js", dest: "dist/" }, { src: "node_modules/rapidoc/dist/rapidoc-min.js", dest: "dist/" },
@ -26,6 +31,11 @@ const resources = [
const isProdBuild = process.env.NODE_ENV === "production"; const isProdBuild = process.env.NODE_ENV === "production";
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
function manualChunks(id) { function manualChunks(id) {
if (id.includes("locales")) {
const parts = id.split("/");
const file = parts[parts.length - 1];
return "locale-" + file.replace(".ts", "");
}
if (id.includes("node_modules")) { if (id.includes("node_modules")) {
if (id.includes("codemirror")) { if (id.includes("codemirror")) {
return "vendor-cm"; return "vendor-cm";
@ -67,20 +77,15 @@ export default [
], ],
output: [ output: [
{ {
format: "es", format: "iife",
dir: "dist", file: "dist/poly.js",
sourcemap: true, sourcemap: true,
} }
], ],
plugins: [ plugins: [
cssimport(), cssimport(),
typescript(),
externalGlobals({
django: "django",
}),
resolve({ browser: true }), resolve({ browser: true }),
commonjs(), commonjs(),
sourcemaps(),
isProdBuild && terser(), isProdBuild && terser(),
].filter(p => p), ].filter(p => p),
watch: { watch: {
@ -100,19 +105,23 @@ export default [
], ],
plugins: [ plugins: [
cssimport(), cssimport(),
typescript(), resolve({ extensions, browser: true }),
externalGlobals({
django: "django",
}),
resolve({ browser: true }),
commonjs(), commonjs(),
babel({
extensions,
babelHelpers: "runtime",
include: ["src/**/*"],
}),
replace({
"process.env.NODE_ENV": JSON.stringify(isProdBuild ? "production" : "development"),
preventAssignment: true
}),
sourcemaps(), sourcemaps(),
isProdBuild && terser(), isProdBuild && terser(),
].filter(p => p), ].filter(p => p),
watch: { watch: {
clearScreen: false, clearScreen: false,
}, },
external: ["django"]
}, },
// Flow executor // Flow executor
{ {
@ -127,18 +136,22 @@ export default [
], ],
plugins: [ plugins: [
cssimport(), cssimport(),
typescript(), resolve({ extensions, browser: true }),
externalGlobals({
django: "django"
}),
resolve({ browser: true }),
commonjs(), commonjs(),
babel({
extensions,
babelHelpers: "runtime",
include: ["src/**/*"],
}),
replace({
"process.env.NODE_ENV": JSON.stringify(isProdBuild ? "production" : "development"),
preventAssignment: true
}),
sourcemaps(), sourcemaps(),
isProdBuild && terser(), isProdBuild && terser(),
].filter(p => p), ].filter(p => p),
watch: { watch: {
clearScreen: false, clearScreen: false,
}, },
external: ["django"]
}, },
]; ];

10
web/src/django.d.ts vendored
View File

@ -1,10 +0,0 @@
declare module "django" {
export = django;
}
declare namespace django {
function gettext(name: string): string;
function ngettext(singular: string, plural: string, count: number): string;
function gettext_noop(msgid: string): string;
function pgettext(context: string, msgid: string): string;
function interpolate(fmt: string, obj: unknown, named: boolean): string;
}

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element"; import { CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element";
import PFExpandableSection from "../../node_modules/@patternfly/patternfly/components/ExpandableSection/expandable-section.css"; import PFExpandableSection from "../../node_modules/@patternfly/patternfly/components/ExpandableSection/expandable-section.css";
@ -26,7 +26,7 @@ export class Expand extends LitElement {
<span class="pf-c-expandable-section__toggle-icon"> <span class="pf-c-expandable-section__toggle-icon">
<i class="fas fa-angle-right" aria-hidden="true"></i> <i class="fas fa-angle-right" aria-hidden="true"></i>
</span> </span>
<span class="pf-c-expandable-section__toggle-text">${gettext(this.expanded ? this.textOpen : this.textClosed)}</span> <span class="pf-c-expandable-section__toggle-text">${this.expanded ? t`${this.textOpen}` : t`${this.textClosed}`}</span>
</button> </button>
<slot ?hidden=${!this.expanded} class="pf-c-expandable-section__content"></slot> <slot ?hidden=${!this.expanded} class="pf-c-expandable-section__content"></slot>
</div>`; </div>`;

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { LitElement } from "lit-element"; import { LitElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
@ -15,9 +15,9 @@ export abstract class Page extends LitElement {
<div class="pf-c-content"> <div class="pf-c-content">
<h1> <h1>
<i class="${this.pageIcon()}"></i> <i class="${this.pageIcon()}"></i>
${gettext(this.pageTitle())} ${t`${this.pageTitle()}`}
</h1> </h1>
${description ? html`<p>${gettext(description)}</p>` : html``} ${description ? html`<p>${t`${description}`}</p>` : html``}
</div> </div>
</section> </section>
${this.renderContent()}`; ${this.renderContent()}`;

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element"; import { CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element";
import PFSpinner from "@patternfly/patternfly/components/Spinner/spinner.css"; import PFSpinner from "@patternfly/patternfly/components/Spinner/spinner.css";
@ -22,7 +22,7 @@ export class Spinner extends LitElement {
return html`<span return html`<span
class="pf-c-spinner ${this.size.toString()}" class="pf-c-spinner ${this.size.toString()}"
role="progressbar" role="progressbar"
aria-valuetext="${gettext("Loading...")}"> aria-valuetext="${t`Loading...`}">
<span class="pf-c-spinner__clipper"></span> <span class="pf-c-spinner__clipper"></span>
<span class="pf-c-spinner__lead-ball"></span> <span class="pf-c-spinner__lead-ball"></span>
<span class="pf-c-spinner__tail-ball"></span> <span class="pf-c-spinner__tail-ball"></span>

View File

@ -4,7 +4,7 @@ import PFTabs from "@patternfly/patternfly/components/Tabs/tabs.css";
import PFGlobal from "@patternfly/patternfly/patternfly-base.css"; import PFGlobal from "@patternfly/patternfly/patternfly-base.css";
import AKGlobal from "../authentik.css"; import AKGlobal from "../authentik.css";
import { CURRENT_CLASS } from "../constants"; import { CURRENT_CLASS } from "../constants";
import { gettext } from "django"; import { t } from "@lingui/macro";
@customElement("ak-tabs") @customElement("ak-tabs")
export class Tabs extends LitElement { export class Tabs extends LitElement {
@ -62,7 +62,7 @@ export class Tabs extends LitElement {
const pages = Array.from(this.querySelectorAll("[slot^='page-']")); const pages = Array.from(this.querySelectorAll("[slot^='page-']"));
if (!this.currentPage) { if (!this.currentPage) {
if (pages.length < 1) { if (pages.length < 1) {
return html`<h1>${gettext("no tabs defined")}</h1>`; return html`<h1>${t`no tabs defined`}</h1>`;
} }
this.currentPage = pages[0].attributes.getNamedItem("slot")?.value; this.currentPage = pages[0].attributes.getNamedItem("slot")?.value;
} }

View File

@ -1,4 +1,3 @@
import { gettext } from "django";
import { css, CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element"; import { css, CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import PFBase from "@patternfly/patternfly/patternfly-base.css"; import PFBase from "@patternfly/patternfly/patternfly-base.css";
@ -47,7 +46,7 @@ export class AggregateCard extends LitElement {
return html`<div class="pf-c-card pf-c-card-aggregate"> return html`<div class="pf-c-card pf-c-card-aggregate">
<div class="pf-c-card__header pf-l-flex pf-m-justify-content-space-between"> <div class="pf-c-card__header pf-l-flex pf-m-justify-content-space-between">
<div class="pf-c-card__header-main"> <div class="pf-c-card__header-main">
<i class="${ifDefined(this.icon)}"></i> ${this.header ? gettext(this.header) : ""} <i class="${ifDefined(this.icon)}"></i> ${this.header ? this.header : ""}
</div> </div>
${this.renderHeaderLink()} ${this.renderHeaderLink()}
</div> </div>

View File

@ -1,4 +1,4 @@
import { customElement } from "lit-element"; import { customElement, property } from "lit-element";
import Chart from "chart.js"; import Chart from "chart.js";
import { CoreApi, UserMetrics } from "authentik-api"; import { CoreApi, UserMetrics } from "authentik-api";
import { AKChart } from "./Chart"; import { AKChart } from "./Chart";
@ -7,8 +7,13 @@ import { DEFAULT_CONFIG } from "../../api/Config";
@customElement("ak-charts-user") @customElement("ak-charts-user")
export class UserChart extends AKChart<UserMetrics> { export class UserChart extends AKChart<UserMetrics> {
@property({type: Number})
userId?: number;
apiRequest(): Promise<UserMetrics> { apiRequest(): Promise<UserMetrics> {
return new CoreApi(DEFAULT_CONFIG).coreUsersMetrics(); return new CoreApi(DEFAULT_CONFIG).coreUsersMetrics({
id: this.userId || 0,
});
} }
getDatasets(data: UserMetrics): Chart.ChartDataSets[] { getDatasets(data: UserMetrics): Chart.ChartDataSets[] {

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { customElement, html, property, TemplateResult } from "lit-element"; import { customElement, html, property, TemplateResult } from "lit-element";
import { AKResponse } from "../../api/Client"; import { AKResponse } from "../../api/Client";
import { Table, TableColumn } from "../table/Table"; import { Table, TableColumn } from "../table/Table";
@ -44,10 +44,10 @@ export class ObjectChangelog extends Table<Event> {
columns(): TableColumn[] { columns(): TableColumn[] {
return [ return [
new TableColumn("Action", "action"), new TableColumn(t`Action`, t`action`),
new TableColumn("User", "enabled"), new TableColumn(t`User`, t`enabled`),
new TableColumn("Creation Date", "created"), new TableColumn(t`Creation Date`, t`created`),
new TableColumn("Client IP", "client_ip"), new TableColumn(t`Client IP`, t`client_ip`),
]; ];
} }
@ -56,7 +56,7 @@ export class ObjectChangelog extends Table<Event> {
html`${item.action}`, html`${item.action}`,
html`<div>${item.user?.username}</div> html`<div>${item.user?.username}</div>
${item.user.on_behalf_of ? html`<small> ${item.user.on_behalf_of ? html`<small>
${gettext(`On behalf of ${item.user.on_behalf_of.username}`)} ${t`On behalf of ${item.user.on_behalf_of.username}`}
</small>` : html``}`, </small>` : html``}`,
html`<span>${item.created?.toLocaleString()}</span>`, html`<span>${item.created?.toLocaleString()}</span>`,
html`<span>${item.clientIp}</span>`, html`<span>${item.clientIp}</span>`,
@ -76,9 +76,9 @@ export class ObjectChangelog extends Table<Event> {
} }
renderEmpty(): TemplateResult { renderEmpty(): TemplateResult {
return super.renderEmpty(html`<ak-empty-state header=${gettext("No Events found.")} icon="pf-icon-module"> return super.renderEmpty(html`<ak-empty-state header=${t`No Events found.`} icon="pf-icon-module">
<div slot="body"> <div slot="body">
${gettext("No matching events could be found.")} ${t`No matching events could be found.`}
</div> </div>
</ak-empty-state>`); </ak-empty-state>`);
} }

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { customElement, html, property, TemplateResult } from "lit-element"; import { customElement, html, property, TemplateResult } from "lit-element";
import { EVENT_REFRESH } from "../../constants"; import { EVENT_REFRESH } from "../../constants";
import { ModalButton } from "../buttons/ModalButton"; import { ModalButton } from "../buttons/ModalButton";
@ -37,14 +37,14 @@ export class ConfirmationForm extends ModalButton {
onSuccess(): void { onSuccess(): void {
showMessage({ showMessage({
message: gettext(this.successMessage), message: this.successMessage,
level: MessageLevel.success, level: MessageLevel.success,
}); });
} }
onError(e: Error): void { onError(e: Error): void {
showMessage({ showMessage({
message: gettext(`${this.errorMessage}: ${e.toString()}`), message: t`${this.errorMessage}: ${e.toString()}`,
level: MessageLevel.error, level: MessageLevel.error,
}); });
} }
@ -76,14 +76,14 @@ export class ConfirmationForm extends ModalButton {
this.confirm(); this.confirm();
}} }}
class="pf-m-danger"> class="pf-m-danger">
${gettext(this.action)} ${this.action}
</ak-spinner-button>&nbsp; </ak-spinner-button>&nbsp;
<ak-spinner-button <ak-spinner-button
.callAction=${() => { .callAction=${() => {
this.open = false; this.open = false;
}} }}
class="pf-m-secondary"> class="pf-m-secondary">
${gettext("Cancel")} ${t`Cancel`}
</ak-spinner-button> </ak-spinner-button>
</footer>`; </footer>`;
} }

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { customElement, html, property, TemplateResult } from "lit-element"; import { customElement, html, property, TemplateResult } from "lit-element";
import { EVENT_REFRESH } from "../../constants"; import { EVENT_REFRESH } from "../../constants";
import { ModalButton } from "../buttons/ModalButton"; import { ModalButton } from "../buttons/ModalButton";
@ -35,14 +35,14 @@ export class DeleteForm extends ModalButton {
onSuccess(): void { onSuccess(): void {
showMessage({ showMessage({
message: gettext(`Successfully deleted ${this.objectLabel} ${ this.obj?.name }`), message: t`Successfully deleted ${this.objectLabel} ${ this.obj?.name }`,
level: MessageLevel.success, level: MessageLevel.success,
}); });
} }
onError(e: Error): void { onError(e: Error): void {
showMessage({ showMessage({
message: gettext(`Failed to delete ${this.objectLabel}: ${e.toString()}`), message: t`Failed to delete ${this.objectLabel}: ${e.toString()}`,
level: MessageLevel.error, level: MessageLevel.error,
}); });
} }
@ -51,7 +51,7 @@ export class DeleteForm extends ModalButton {
return html`<section class="pf-c-page__main-section pf-m-light"> return html`<section class="pf-c-page__main-section pf-m-light">
<div class="pf-c-content"> <div class="pf-c-content">
<h1 class="pf-c-title pf-m-2xl"> <h1 class="pf-c-title pf-m-2xl">
${gettext(`Delete ${this.objectLabel}`)} ${t`Delete ${this.objectLabel}`}
</h1> </h1>
</div> </div>
</section> </section>
@ -62,9 +62,7 @@ export class DeleteForm extends ModalButton {
<div class="pf-c-card__body"> <div class="pf-c-card__body">
<form class="pf-c-form pf-m-horizontal"> <form class="pf-c-form pf-m-horizontal">
<p> <p>
${gettext( ${t`Are you sure you want to delete ${this.objectLabel} '${this.obj?.name}'?`}
`Are you sure you want to delete ${this.objectLabel} '${this.obj?.name}'?`
)}
</p> </p>
</form> </form>
</div> </div>
@ -78,14 +76,14 @@ export class DeleteForm extends ModalButton {
this.confirm(); this.confirm();
}} }}
class="pf-m-danger"> class="pf-m-danger">
${gettext("Delete")} ${t`Delete`}
</ak-spinner-button>&nbsp; </ak-spinner-button>&nbsp;
<ak-spinner-button <ak-spinner-button
.callAction=${() => { .callAction=${() => {
this.open = false; this.open = false;
}} }}
class="pf-m-secondary"> class="pf-m-secondary">
${gettext("Cancel")} ${t`Cancel`}
</ak-spinner-button> </ak-spinner-button>
</footer>`; </footer>`;
} }

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { customElement, html, property, TemplateResult } from "lit-element"; import { customElement, html, property, TemplateResult } from "lit-element";
import { EVENT_REFRESH } from "../../constants"; import { EVENT_REFRESH } from "../../constants";
import { ModalButton } from "../buttons/ModalButton"; import { ModalButton } from "../buttons/ModalButton";
@ -66,7 +66,7 @@ export class ModalForm extends ModalButton {
this.open = false; this.open = false;
}} }}
class="pf-m-secondary"> class="pf-m-secondary">
${gettext("Cancel")} ${t`Cancel`}
</ak-spinner-button> </ak-spinner-button>
</footer>`; </footer>`;
} }

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { LitElement, html, customElement, TemplateResult, property, CSSResult, css } from "lit-element"; import { LitElement, html, customElement, TemplateResult, property, CSSResult, css } from "lit-element";
import "./Message"; import "./Message";
import { APIMessage, MessageLevel } from "./Message"; import { APIMessage, MessageLevel } from "./Message";
@ -64,7 +64,7 @@ export class MessageContainer extends LitElement {
if (this.retryDelay > 3000) { if (this.retryDelay > 3000) {
showMessage({ showMessage({
level: MessageLevel.error, level: MessageLevel.error,
message: gettext("Connection error, reconnecting...") message: t`Connection error, reconnecting...`
}); });
} }
setTimeout(() => { setTimeout(() => {

View File

@ -1,5 +1,5 @@
import { Middleware, ResponseContext } from "authentik-api"; import { Middleware, ResponseContext } from "authentik-api";
import { gettext } from "django"; import { t } from "@lingui/macro";
import { MessageLevel } from "./Message"; import { MessageLevel } from "./Message";
import { showMessage } from "./MessageContainer"; import { showMessage } from "./MessageContainer";
@ -9,7 +9,7 @@ export class MessageMiddleware implements Middleware {
if (context.response.status >= 500) { if (context.response.status >= 500) {
showMessage({ showMessage({
level: MessageLevel.error, level: MessageLevel.error,
message: gettext("API request failed"), message: t`API request failed`,
description: `${context.init.method} ${context.url}: ${context.response.status}` description: `${context.init.method} ${context.url}: ${context.response.status}`
}); });
} }

View File

@ -5,7 +5,7 @@ import PFNotificationDrawer from "@patternfly/patternfly/components/Notification
import PFDropdown from "@patternfly/patternfly/components/Dropdown/dropdown.css"; import PFDropdown from "@patternfly/patternfly/components/Dropdown/dropdown.css";
import AKGlobal from "../../authentik.css"; import AKGlobal from "../../authentik.css";
import PFContent from "@patternfly/patternfly/components/Content/content.css"; import PFContent from "@patternfly/patternfly/components/Content/content.css";
import { gettext } from "django"; import { t } from "@lingui/macro";
import { EVENT_API_DRAWER_REFRESH } from "../../constants"; import { EVENT_API_DRAWER_REFRESH } from "../../constants";
export interface RequestInfo { export interface RequestInfo {
@ -71,7 +71,7 @@ export class APIDrawer extends LitElement {
<div class="pf-c-notification-drawer"> <div class="pf-c-notification-drawer">
<div class="pf-c-notification-drawer__header pf-c-content"> <div class="pf-c-notification-drawer__header pf-c-content">
<h1> <h1>
${gettext("API Requests")} ${t`API Requests`}
</h1> </h1>
</div> </div>
<div class="pf-c-notification-drawer__body"> <div class="pf-c-notification-drawer__body">

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { css, CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element"; import { css, CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element";
import { EventsApi, Notification } from "authentik-api"; import { EventsApi, Notification } from "authentik-api";
import { AKResponse } from "../../api/Client"; import { AKResponse } from "../../api/Client";
@ -100,10 +100,10 @@ export class NotificationDrawer extends LitElement {
<div class="pf-c-notification-drawer"> <div class="pf-c-notification-drawer">
<div class="pf-c-notification-drawer__header pf-c-content"> <div class="pf-c-notification-drawer__header pf-c-content">
<h1> <h1>
${gettext("Notifications")} ${t`Notifications`}
</h1> </h1>
<p> <p>
${gettext(`${this.unread} unread`)} ${t`${this.unread} unread`}
</p> </p>
</div> </div>
<div class="pf-c-notification-drawer__body"> <div class="pf-c-notification-drawer__body">

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { customElement, html, property, TemplateResult } from "lit-element"; import { customElement, html, property, TemplateResult } from "lit-element";
import { AKResponse } from "../../api/Client"; import { AKResponse } from "../../api/Client";
import { Table, TableColumn } from "../table/Table"; import { Table, TableColumn } from "../table/Table";
@ -26,9 +26,9 @@ export class UserOAuthCodeList extends Table<ExpiringBaseGrantModel> {
columns(): TableColumn[] { columns(): TableColumn[] {
return [ return [
new TableColumn("Provider", "provider"), new TableColumn(t`Provider`, t`provider`),
new TableColumn("Expires", "expires"), new TableColumn(t`Expires`, t`expires`),
new TableColumn("Scopes", "scope"), new TableColumn(t`Scopes`, t`scope`),
new TableColumn(""), new TableColumn(""),
]; ];
} }
@ -41,14 +41,14 @@ export class UserOAuthCodeList extends Table<ExpiringBaseGrantModel> {
html` html`
<ak-forms-delete <ak-forms-delete
.obj=${item} .obj=${item}
objectLabel=${gettext("Authorization Code")} objectLabel=${t`Authorization Code`}
.delete=${() => { .delete=${() => {
return new Oauth2Api(DEFAULT_CONFIG).oauth2AuthorizationCodesDelete({ return new Oauth2Api(DEFAULT_CONFIG).oauth2AuthorizationCodesDelete({
id: item.pk || 0, id: item.pk || 0,
}); });
}}> }}>
<button slot="trigger" class="pf-c-button pf-m-danger"> <button slot="trigger" class="pf-c-button pf-m-danger">
${gettext("Delete Authorization Code")} ${t`Delete Authorization Code`}
</button> </button>
</ak-forms-delete>`, </ak-forms-delete>`,
]; ];

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { customElement, html, property, TemplateResult } from "lit-element"; import { customElement, html, property, TemplateResult } from "lit-element";
import { AKResponse } from "../../api/Client"; import { AKResponse } from "../../api/Client";
import { Table, TableColumn } from "../table/Table"; import { Table, TableColumn } from "../table/Table";
@ -26,9 +26,9 @@ export class UserOAuthRefreshList extends Table<ExpiringBaseGrantModel> {
columns(): TableColumn[] { columns(): TableColumn[] {
return [ return [
new TableColumn("Provider", "provider"), new TableColumn(t`Provider`, t`provider`),
new TableColumn("Expires", "expires"), new TableColumn(t`Expires`, t`expires`),
new TableColumn("Scopes", "scope"), new TableColumn(t`Scopes`, t`scope`),
new TableColumn(""), new TableColumn(""),
]; ];
} }
@ -41,14 +41,14 @@ export class UserOAuthRefreshList extends Table<ExpiringBaseGrantModel> {
html` html`
<ak-forms-delete <ak-forms-delete
.obj=${item} .obj=${item}
objectLabel=${gettext("Refresh Code")} objectLabel=${t`Refresh Code`}
.delete=${() => { .delete=${() => {
return new Oauth2Api(DEFAULT_CONFIG).oauth2RefreshTokensDelete({ return new Oauth2Api(DEFAULT_CONFIG).oauth2RefreshTokensDelete({
id: item.pk || 0, id: item.pk || 0,
}); });
}}> }}>
<button slot="trigger" class="pf-c-button pf-m-danger"> <button slot="trigger" class="pf-c-button pf-m-danger">
${gettext("Delete Refresh Code")} ${t`Delete Refresh Code`}
</button> </button>
</ak-forms-delete>`, </ak-forms-delete>`,
]; ];

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element"; import { CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element";
import PFEmptyState from "@patternfly/patternfly/components/EmptyState/empty-state.css"; import PFEmptyState from "@patternfly/patternfly/components/EmptyState/empty-state.css";
import PFTitle from "@patternfly/patternfly/components/Title/title.css"; import PFTitle from "@patternfly/patternfly/components/Title/title.css";
@ -18,11 +18,11 @@ export class Router404 extends LitElement {
return html`<div class="pf-c-empty-state pf-m-full-height"> return html`<div class="pf-c-empty-state pf-m-full-height">
<div class="pf-c-empty-state__content"> <div class="pf-c-empty-state__content">
<i class="fas fa-question-circle pf-c-empty-state__icon" aria-hidden="true"></i> <i class="fas fa-question-circle pf-c-empty-state__icon" aria-hidden="true"></i>
<h1 class="pf-c-title pf-m-lg">${gettext("Not found")}</h1> <h1 class="pf-c-title pf-m-lg">${t`Not found`}</h1>
<div class="pf-c-empty-state__body"> <div class="pf-c-empty-state__body">
${gettext(`The URL '${this.url}' was not found.`)} ${t`The URL '${this.url}' was not found.`}
</div> </div>
<a href="#/" class="pf-c-button pf-m-primary" type="button">${gettext("Return home")}</a> <a href="#/" class="pf-c-button pf-m-primary" type="button">${t`Return home`}</a>
</div> </div>
</div>`; </div>`;
} }

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { CSSResult, html, LitElement, property, TemplateResult } from "lit-element"; import { CSSResult, html, LitElement, property, TemplateResult } from "lit-element";
import { AKResponse } from "../../api/Client"; import { AKResponse } from "../../api/Client";
@ -54,7 +54,7 @@ export class TableColumn {
return html` return html`
<button class="pf-c-table__button" @click=${() => this.headerClickHandler(table)}> <button class="pf-c-table__button" @click=${() => this.headerClickHandler(table)}>
<div class="pf-c-table__button-content"> <div class="pf-c-table__button-content">
<span class="pf-c-table__text">${gettext(this.title)}</span> <span class="pf-c-table__text">${this.title}</span>
<span class="pf-c-table__sort-indicator"> <span class="pf-c-table__sort-indicator">
<i class="fas ${this.getSortIndicator(table)}"></i> <i class="fas ${this.getSortIndicator(table)}"></i>
</span> </span>
@ -70,7 +70,7 @@ export class TableColumn {
${this.orderBy ? "pf-c-table__sort " : " "} ${this.orderBy ? "pf-c-table__sort " : " "}
${(table.order === this.orderBy || table.order === `-${this.orderBy}`) ? "pf-m-selected " : ""} ${(table.order === this.orderBy || table.order === `-${this.orderBy}`) ? "pf-m-selected " : ""}
"> ">
${this.orderBy ? this.renderSortable(table) : html`${gettext(this.title)}`} ${this.orderBy ? this.renderSortable(table) : html`${this.title}`}
</th>`; </th>`;
} }
@ -147,7 +147,7 @@ export abstract class Table<T> extends LitElement {
<div class="pf-l-bullseye"> <div class="pf-l-bullseye">
<ak-empty-state <ak-empty-state
?loading="${true}" ?loading="${true}"
header=${gettext("Loading")}> header=${t`Loading`}>
</ak-empty-state> </ak-empty-state>
</div> </div>
</td> </td>
@ -159,7 +159,7 @@ export abstract class Table<T> extends LitElement {
<tr role="row"> <tr role="row">
<td role="cell" colspan="8"> <td role="cell" colspan="8">
<div class="pf-l-bullseye"> <div class="pf-l-bullseye">
${inner ? inner : html`<ak-empty-state header="${gettext("No elements found.")}"></ak-empty-state>`} ${inner ? inner : html`<ak-empty-state header="${t`No elements found.`}"></ak-empty-state>`}
</div> </div>
</td> </td>
</tr> </tr>
@ -218,7 +218,7 @@ export abstract class Table<T> extends LitElement {
return html`<button return html`<button
@click=${() => { this.fetch(); }} @click=${() => { this.fetch(); }}
class="pf-c-button pf-m-primary"> class="pf-c-button pf-m-primary">
${gettext("Refresh")} ${t`Refresh`}
</button>`; </button>`;
} }
@ -253,7 +253,7 @@ export abstract class Table<T> extends LitElement {
<thead> <thead>
<tr role="row"> <tr role="row">
${this.checkbox ? html`<td class="pf-c-table__check" role="cell"> ${this.checkbox ? html`<td class="pf-c-table__check" role="cell">
<input type="checkbox" aria-label=${gettext("Select all rows")} @input=${(ev: InputEvent) => { <input type="checkbox" aria-label=${t`Select all rows`} @input=${(ev: InputEvent) => {
if ((ev.target as HTMLInputElement).checked) { if ((ev.target as HTMLInputElement).checked) {
this.selectedElements = this.data?.results || []; this.selectedElements = this.data?.results || [];
} else { } else {

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { CSSResult } from "lit-element"; import { CSSResult } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
@ -34,9 +34,9 @@ export abstract class TablePage<T> extends Table<T> {
<div class="pf-c-content"> <div class="pf-c-content">
<h1> <h1>
<i class="${this.pageIcon()}"></i> <i class="${this.pageIcon()}"></i>
${gettext(this.pageTitle())} ${t`${this.pageTitle()}`}
</h1> </h1>
${description ? html`<p>${gettext(description)}</p>` : html``} ${description ? html`<p>${t`${description}`}</p>` : html``}
</div> </div>
</section> </section>
<section class="pf-c-page__main-section pf-m-no-padding-mobile"> <section class="pf-c-page__main-section pf-m-no-padding-mobile">

View File

@ -1,6 +1,6 @@
import { CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element"; import { CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element";
import { AKPagination } from "../../api/Client"; import { AKPagination } from "../../api/Client";
import { gettext } from "django"; import { t } from "@lingui/macro";
import PFBase from "@patternfly/patternfly/patternfly-base.css"; import PFBase from "@patternfly/patternfly/patternfly-base.css";
import PFButton from "@patternfly/patternfly/components/Button/button.css"; import PFButton from "@patternfly/patternfly/components/Button/button.css";
import PFPagination from "@patternfly/patternfly/components/Pagination/pagination.css"; import PFPagination from "@patternfly/patternfly/components/Pagination/pagination.css";
@ -25,9 +25,7 @@ export class TablePagination extends LitElement {
<div class="pf-c-options-menu"> <div class="pf-c-options-menu">
<div class="pf-c-options-menu__toggle pf-m-text pf-m-plain"> <div class="pf-c-options-menu__toggle pf-m-text pf-m-plain">
<span class="pf-c-options-menu__toggle-text"> <span class="pf-c-options-menu__toggle-text">
${this.pages?.startIndex} - ${t`${this.pages?.startIndex} - ${this.pages?.endIndex} of ${this.pages?.count}`}
${this.pages?.endIndex} of
${this.pages?.count}
</span> </span>
</div> </div>
</div> </div>
@ -37,7 +35,7 @@ export class TablePagination extends LitElement {
class="pf-c-button pf-m-plain" class="pf-c-button pf-m-plain"
@click=${() => { this.pageChangeHandler(this.pages?.previous || 0); }} @click=${() => { this.pageChangeHandler(this.pages?.previous || 0); }}
?disabled="${(this.pages?.previous || 0) < 1}" ?disabled="${(this.pages?.previous || 0) < 1}"
aria-label="${gettext("Go to previous page")}" aria-label="${t`Go to previous page`}"
> >
<i class="fas fa-angle-left" aria-hidden="true"></i> <i class="fas fa-angle-left" aria-hidden="true"></i>
</button> </button>
@ -47,7 +45,7 @@ export class TablePagination extends LitElement {
class="pf-c-button pf-m-plain" class="pf-c-button pf-m-plain"
@click=${() => { this.pageChangeHandler(this.pages?.next || 0); }} @click=${() => { this.pageChangeHandler(this.pages?.next || 0); }}
?disabled="${(this.pages?.next || 0) <= 0}" ?disabled="${(this.pages?.next || 0) <= 0}"
aria-label="${gettext("Go to next page")}" aria-label="${t`Go to next page`}"
> >
<i class="fas fa-angle-right" aria-hidden="true"></i> <i class="fas fa-angle-right" aria-hidden="true"></i>
</button> </button>

View File

@ -6,6 +6,7 @@ import PFToolbar from "@patternfly/patternfly/components/Toolbar/toolbar.css";
import PFInputGroup from "@patternfly/patternfly/components/InputGroup/input-group.css"; import PFInputGroup from "@patternfly/patternfly/components/InputGroup/input-group.css";
import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css"; import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css";
import AKGlobal from "../../authentik.css"; import AKGlobal from "../../authentik.css";
import { t } from "@lingui/macro";
@customElement("ak-table-search") @customElement("ak-table-search")
export class TableSearch extends LitElement { export class TableSearch extends LitElement {
@ -31,7 +32,7 @@ export class TableSearch extends LitElement {
if (el.value === "") return; if (el.value === "") return;
this.onSearch(el?.value); this.onSearch(el?.value);
}}> }}>
<input class="pf-c-form-control" name="search" type="search" placeholder="Search..." value="${ifDefined(this.value)}" @search=${(ev: Event) => { <input class="pf-c-form-control" name="search" type="search" placeholder=${t`Search...`} value="${ifDefined(this.value)}" @search=${(ev: Event) => {
if (!this.onSearch) return; if (!this.onSearch) return;
this.onSearch((ev.target as HTMLInputElement).value); this.onSearch((ev.target as HTMLInputElement).value);
}}> }}>

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { customElement, html, property, TemplateResult } from "lit-element"; import { customElement, html, property, TemplateResult } from "lit-element";
import { AKResponse } from "../../api/Client"; import { AKResponse } from "../../api/Client";
import { Table, TableColumn } from "../table/Table"; import { Table, TableColumn } from "../table/Table";
@ -26,8 +26,8 @@ export class UserConsentList extends Table<UserConsent> {
columns(): TableColumn[] { columns(): TableColumn[] {
return [ return [
new TableColumn("Application", "application"), new TableColumn(t`Application`, t`application`),
new TableColumn("Expires", "expires"), new TableColumn(t`Expires`, t`expires`),
new TableColumn(""), new TableColumn(""),
]; ];
} }
@ -39,14 +39,14 @@ export class UserConsentList extends Table<UserConsent> {
html` html`
<ak-forms-delete <ak-forms-delete
.obj=${item} .obj=${item}
objectLabel=${gettext("Consent")} objectLabel=${t`Consent`}
.delete=${() => { .delete=${() => {
return new CoreApi(DEFAULT_CONFIG).coreUserConsentDelete({ return new CoreApi(DEFAULT_CONFIG).coreUserConsentDelete({
id: item.pk || 0, id: item.pk || 0,
}); });
}}> }}>
<button slot="trigger" class="pf-c-button pf-m-danger"> <button slot="trigger" class="pf-c-button pf-m-danger">
${gettext("Delete Consent")} ${t`Delete Consent`}
</button> </button>
</ak-forms-delete>`, </ak-forms-delete>`,
]; ];

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { LitElement, html, customElement, property, TemplateResult, CSSResult, css } from "lit-element"; import { LitElement, html, customElement, property, TemplateResult, CSSResult, css } from "lit-element";
import PFLogin from "@patternfly/patternfly/components/Login/login.css"; import PFLogin from "@patternfly/patternfly/components/Login/login.css";
@ -152,11 +152,11 @@ export class FlowExecutor extends LitElement implements StageHost {
type: ChallengeTypeEnum.Shell, type: ChallengeTypeEnum.Shell,
body: `<header class="pf-c-login__main-header"> body: `<header class="pf-c-login__main-header">
<h1 class="pf-c-title pf-m-3xl"> <h1 class="pf-c-title pf-m-3xl">
${gettext("Whoops!")} ${t`Whoops!`}
</h1> </h1>
</header> </header>
<div class="pf-c-login__main-body"> <div class="pf-c-login__main-body">
<h3>${gettext("Something went wrong! Please try again later.")}</h3> <h3>${t`Something went wrong! Please try again later.`}</h3>
<pre class="ak-exception">${error}</pre> <pre class="ak-exception">${error}</pre>
</div>` </div>`
}; };
@ -178,7 +178,7 @@ export class FlowExecutor extends LitElement implements StageHost {
window.location.assign((this.challenge as RedirectChallenge).to); window.location.assign((this.challenge as RedirectChallenge).to);
return html`<ak-empty-state return html`<ak-empty-state
?loading=${true} ?loading=${true}
header=${gettext("Loading")}> header=${t`Loading`}>
</ak-empty-state>`; </ak-empty-state>`;
case ChallengeTypeEnum.Shell: case ChallengeTypeEnum.Shell:
return html`${unsafeHTML((this.challenge as ShellChallenge).body)}`; return html`${unsafeHTML((this.challenge as ShellChallenge).body)}`;
@ -225,7 +225,7 @@ export class FlowExecutor extends LitElement implements StageHost {
if (!this.challenge) { if (!this.challenge) {
return html`<ak-empty-state return html`<ak-empty-state
?loading=${true} ?loading=${true}
header=${gettext("Loading")}> header=${t`Loading`}>
</ak-empty-state>`; </ak-empty-state>`;
} }
return html` return html`
@ -267,7 +267,7 @@ export class FlowExecutor extends LitElement implements StageHost {
</li>`; </li>`;
}))} }))}
${this.config?.brandingTitle != "authentik" ? html` ${this.config?.brandingTitle != "authentik" ? html`
<li><a href="https://goauthentik.io">${gettext("Powered by authentik")}</a></li> <li><a href="https://goauthentik.io">${t`Powered by authentik`}</a></li>
` : html``} ` : html``}
</ul> </ul>
</footer> </footer>

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { css, CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element"; import { css, CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element";
import PFAvatar from "@patternfly/patternfly/components/Avatar/avatar.css"; import PFAvatar from "@patternfly/patternfly/components/Avatar/avatar.css";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
@ -40,7 +40,7 @@ export class FormStatic extends LitElement {
return html` return html`
<div class="form-control-static"> <div class="form-control-static">
<div class="avatar"> <div class="avatar">
<img class="pf-c-avatar" src="${ifDefined(this.userAvatar)}" alt="${gettext("User's avatar")}"> <img class="pf-c-avatar" src="${ifDefined(this.userAvatar)}" alt="${t`User's avatar`}">
${this.user} ${this.user}
</div> </div>
<slot name="link"></slot> <slot name="link"></slot>

View File

@ -8,7 +8,7 @@ import PFForm from "@patternfly/patternfly/components/Form/form.css";
import PFList from "@patternfly/patternfly/components/List/list.css"; import PFList from "@patternfly/patternfly/components/List/list.css";
import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css"; import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css";
import AKGlobal from "../../authentik.css"; import AKGlobal from "../../authentik.css";
import { gettext } from "django"; import { t } from "@lingui/macro";
import "../../elements/EmptyState"; import "../../elements/EmptyState";
@ -30,7 +30,7 @@ export class FlowAccessDenied extends BaseStage {
if (!this.challenge) { if (!this.challenge) {
return html`<ak-empty-state return html`<ak-empty-state
?loading="${true}" ?loading="${true}"
header=${gettext("Loading")}> header=${t`Loading`}>
</ak-empty-state>`; </ak-empty-state>`;
} }
return html`<header class="pf-c-login__main-header"> return html`<header class="pf-c-login__main-header">
@ -43,7 +43,7 @@ export class FlowAccessDenied extends BaseStage {
<div class="pf-c-form__group"> <div class="pf-c-form__group">
<p> <p>
<i class="pf-icon pf-icon-error-circle-o"></i> <i class="pf-icon pf-icon-error-circle-o"></i>
${gettext("Request has been denied.")} ${t`Request has been denied.`}
</p> </p>
${this.challenge?.error_message && ${this.challenge?.error_message &&
html`<hr> html`<hr>

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { css, CSSResult, customElement, html, property, TemplateResult } from "lit-element"; import { css, CSSResult, customElement, html, property, TemplateResult } from "lit-element";
import { WithUserInfoChallenge } from "../../../api/Flows"; import { WithUserInfoChallenge } from "../../../api/Flows";
import PFLogin from "@patternfly/patternfly/components/Login/login.css"; import PFLogin from "@patternfly/patternfly/components/Login/login.css";
@ -47,7 +47,7 @@ export class AuthenticatorStaticStage extends BaseStage {
if (!this.challenge) { if (!this.challenge) {
return html`<ak-empty-state return html`<ak-empty-state
?loading="${true}" ?loading="${true}"
header=${gettext("Loading")}> header=${t`Loading`}>
</ak-empty-state>`; </ak-empty-state>`;
} }
return html`<header class="pf-c-login__main-header"> return html`<header class="pf-c-login__main-header">
@ -62,11 +62,11 @@ export class AuthenticatorStaticStage extends BaseStage {
userAvatar="${this.challenge.pending_user_avatar}" userAvatar="${this.challenge.pending_user_avatar}"
user=${this.challenge.pending_user}> user=${this.challenge.pending_user}>
<div slot="link"> <div slot="link">
<a href="${FlowURLManager.cancel()}">${gettext("Not you?")}</a> <a href="${FlowURLManager.cancel()}">${t`Not you?`}</a>
</div> </div>
</ak-form-static> </ak-form-static>
<ak-form-element <ak-form-element
label="${gettext("Tokens")}" label="${t`Tokens`}"
?required="${true}" ?required="${true}"
class="pf-c-form__group"> class="pf-c-form__group">
<ul class="ak-otp-tokens"> <ul class="ak-otp-tokens">
@ -78,7 +78,7 @@ export class AuthenticatorStaticStage extends BaseStage {
<div class="pf-c-form__group pf-m-action"> <div class="pf-c-form__group pf-m-action">
<button type="submit" class="pf-c-button pf-m-primary pf-m-block"> <button type="submit" class="pf-c-button pf-m-primary pf-m-block">
${gettext("Continue")} ${t`Continue`}
</button> </button>
</div> </div>
</form> </form>

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { CSSResult, customElement, html, property, TemplateResult } from "lit-element"; import { CSSResult, customElement, html, property, TemplateResult } from "lit-element";
import { WithUserInfoChallenge } from "../../../api/Flows"; import { WithUserInfoChallenge } from "../../../api/Flows";
import PFLogin from "@patternfly/patternfly/components/Login/login.css"; import PFLogin from "@patternfly/patternfly/components/Login/login.css";
@ -35,7 +35,7 @@ export class AuthenticatorTOTPStage extends BaseStage {
if (!this.challenge) { if (!this.challenge) {
return html`<ak-empty-state return html`<ak-empty-state
?loading="${true}" ?loading="${true}"
header=${gettext("Loading")}> header=${t`Loading`}>
</ak-empty-state>`; </ak-empty-state>`;
} }
return html`<header class="pf-c-login__main-header"> return html`<header class="pf-c-login__main-header">
@ -50,7 +50,7 @@ export class AuthenticatorTOTPStage extends BaseStage {
userAvatar="${this.challenge.pending_user_avatar}" userAvatar="${this.challenge.pending_user_avatar}"
user=${this.challenge.pending_user}> user=${this.challenge.pending_user}>
<div slot="link"> <div slot="link">
<a href="${FlowURLManager.cancel()}">${gettext("Not you?")}</a> <a href="${FlowURLManager.cancel()}">${t`Not you?`}</a>
</div> </div>
</ak-form-static> </ak-form-static>
<input type="hidden" name="otp_uri" value=${this.challenge.config_url} /> <input type="hidden" name="otp_uri" value=${this.challenge.config_url} />
@ -63,16 +63,16 @@ export class AuthenticatorTOTPStage extends BaseStage {
navigator.clipboard.writeText(this.challenge?.config_url).then(() => { navigator.clipboard.writeText(this.challenge?.config_url).then(() => {
showMessage({ showMessage({
level: MessageLevel.success, level: MessageLevel.success,
message: gettext("Successfully copied TOTP Config.") message: t`Successfully copied TOTP Config.`
}); });
}); });
}}> }}>
<span class="pf-c-button__progress"><i class="fas fa-copy"></i></span> <span class="pf-c-button__progress"><i class="fas fa-copy"></i></span>
${gettext("Copy")} ${t`Copy`}
</button> </button>
</ak-form-element> </ak-form-element>
<ak-form-element <ak-form-element
label="${gettext("Code")}" label="${t`Code`}"
?required="${true}" ?required="${true}"
class="pf-c-form__group" class="pf-c-form__group"
.errors=${(this.challenge?.response_errors || {})["code"]}> .errors=${(this.challenge?.response_errors || {})["code"]}>
@ -81,7 +81,7 @@ export class AuthenticatorTOTPStage extends BaseStage {
name="code" name="code"
inputmode="numeric" inputmode="numeric"
pattern="[0-9]*" pattern="[0-9]*"
placeholder="${gettext("Please enter your TOTP Code")}" placeholder="${t`Please enter your TOTP Code`}"
autofocus="" autofocus=""
autocomplete="one-time-code" autocomplete="one-time-code"
class="pf-c-form-control" class="pf-c-form-control"
@ -90,7 +90,7 @@ export class AuthenticatorTOTPStage extends BaseStage {
<div class="pf-c-form__group pf-m-action"> <div class="pf-c-form__group pf-m-action">
<button type="submit" class="pf-c-button pf-m-primary pf-m-block"> <button type="submit" class="pf-c-button pf-m-primary pf-m-block">
${gettext("Continue")} ${t`Continue`}
</button> </button>
</div> </div>
</form> </form>

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { css, CSSResult, customElement, html, property, TemplateResult } from "lit-element"; import { css, CSSResult, customElement, html, property, TemplateResult } from "lit-element";
import { WithUserInfoChallenge } from "../../../api/Flows"; import { WithUserInfoChallenge } from "../../../api/Flows";
import PFLogin from "@patternfly/patternfly/components/Login/login.css"; import PFLogin from "@patternfly/patternfly/components/Login/login.css";
@ -80,8 +80,8 @@ export class AuthenticatorValidateStage extends BaseStage implements StageHost {
case DeviceClasses.WEBAUTHN: case DeviceClasses.WEBAUTHN:
return html`<i class="fas fa-mobile-alt"></i> return html`<i class="fas fa-mobile-alt"></i>
<div class="right"> <div class="right">
<p>${gettext("Authenticator")}</p> <p>${t`Authenticator`}</p>
<small>${gettext("Use a security key to prove your identity.")}</small> <small>${t`Use a security key to prove your identity.`}</small>
</div>`; </div>`;
case DeviceClasses.TOTP: case DeviceClasses.TOTP:
// TOTP is a bit special, assuming that TOTP is allowed from the backend, // TOTP is a bit special, assuming that TOTP is allowed from the backend,
@ -97,14 +97,14 @@ export class AuthenticatorValidateStage extends BaseStage implements StageHost {
} }
return html`<i class="fas fa-clock"></i> return html`<i class="fas fa-clock"></i>
<div class="right"> <div class="right">
<p>${gettext("Traditional authenticator")}</p> <p>${t`Traditional authenticator`}</p>
<small>${gettext("Use a code-based authenticator.")}</small> <small>${t`Use a code-based authenticator.`}</small>
</div>`; </div>`;
case DeviceClasses.STATIC: case DeviceClasses.STATIC:
return html`<i class="fas fa-key"></i> return html`<i class="fas fa-key"></i>
<div class="right"> <div class="right">
<p>${gettext("Recovery keys")}</p> <p>${t`Recovery keys`}</p>
<small>${gettext("In case you can't access any other method.")}</small> <small>${t`In case you can't access any other method.`}</small>
</div>`; </div>`;
default: default:
break; break;
@ -154,7 +154,7 @@ export class AuthenticatorValidateStage extends BaseStage implements StageHost {
if (!this.challenge) { if (!this.challenge) {
return html`<ak-empty-state return html`<ak-empty-state
?loading="${true}" ?loading="${true}"
header=${gettext("Loading")}> header=${t`Loading`}>
</ak-empty-state>`; </ak-empty-state>`;
} }
// User only has a single device class, so we don't show a picker // User only has a single device class, so we don't show a picker
@ -166,7 +166,7 @@ export class AuthenticatorValidateStage extends BaseStage implements StageHost {
${this.challenge.title} ${this.challenge.title}
</h1> </h1>
${this.selectedDeviceChallenge ? "" : html`<p class="pf-c-login__main-header-desc"> ${this.selectedDeviceChallenge ? "" : html`<p class="pf-c-login__main-header-desc">
${gettext("Select an identification method.")} ${t`Select an identification method.`}
</p>`} </p>`}
</header> </header>
${this.selectedDeviceChallenge ? ${this.selectedDeviceChallenge ?

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { CSSResult, customElement, html, property, TemplateResult } from "lit-element"; import { CSSResult, customElement, html, property, TemplateResult } from "lit-element";
import PFLogin from "@patternfly/patternfly/components/Login/login.css"; import PFLogin from "@patternfly/patternfly/components/Login/login.css";
import PFForm from "@patternfly/patternfly/components/Form/form.css"; import PFForm from "@patternfly/patternfly/components/Form/form.css";
@ -35,7 +35,7 @@ export class AuthenticatorValidateStageWebCode extends BaseStage {
if (!this.challenge) { if (!this.challenge) {
return html`<ak-empty-state return html`<ak-empty-state
?loading="${true}" ?loading="${true}"
header=${gettext("Loading")}> header=${t`Loading`}>
</ak-empty-state>`; </ak-empty-state>`;
} }
return html`<div class="pf-c-login__main-body"> return html`<div class="pf-c-login__main-body">
@ -45,11 +45,11 @@ export class AuthenticatorValidateStageWebCode extends BaseStage {
userAvatar="${this.challenge.pending_user_avatar}" userAvatar="${this.challenge.pending_user_avatar}"
user=${this.challenge.pending_user}> user=${this.challenge.pending_user}>
<div slot="link"> <div slot="link">
<a href="${FlowURLManager.cancel()}">${gettext("Not you?")}</a> <a href="${FlowURLManager.cancel()}">${t`Not you?`}</a>
</div> </div>
</ak-form-static> </ak-form-static>
<ak-form-element <ak-form-element
label="${gettext("Code")}" label="${t`Code`}"
?required="${true}" ?required="${true}"
class="pf-c-form__group" class="pf-c-form__group"
.errors=${(this.challenge?.response_errors || {})["code"]}> .errors=${(this.challenge?.response_errors || {})["code"]}>
@ -58,7 +58,7 @@ export class AuthenticatorValidateStageWebCode extends BaseStage {
name="code" name="code"
inputmode="numeric" inputmode="numeric"
pattern="[0-9]*" pattern="[0-9]*"
placeholder="${gettext("Please enter your TOTP Code")}" placeholder="${t`Please enter your TOTP Code`}"
autofocus="" autofocus=""
autocomplete="one-time-code" autocomplete="one-time-code"
class="pf-c-form-control" class="pf-c-form-control"
@ -68,7 +68,7 @@ export class AuthenticatorValidateStageWebCode extends BaseStage {
<div class="pf-c-form__group pf-m-action"> <div class="pf-c-form__group pf-m-action">
<button type="submit" class="pf-c-button pf-m-primary pf-m-block"> <button type="submit" class="pf-c-button pf-m-primary pf-m-block">
${gettext("Continue")} ${t`Continue`}
</button> </button>
</div> </div>
</form> </form>
@ -81,7 +81,7 @@ export class AuthenticatorValidateStageWebCode extends BaseStage {
if (!this.host) return; if (!this.host) return;
(this.host as AuthenticatorValidateStage).selectedDeviceChallenge = undefined; (this.host as AuthenticatorValidateStage).selectedDeviceChallenge = undefined;
}}> }}>
${gettext("Return to device picker")} ${t`Return to device picker`}
</button> </button>
</li>`: </li>`:
html``} html``}

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { CSSResult, customElement, html, property, TemplateResult } from "lit-element"; import { CSSResult, customElement, html, property, TemplateResult } from "lit-element";
import PFLogin from "@patternfly/patternfly/components/Login/login.css"; import PFLogin from "@patternfly/patternfly/components/Login/login.css";
import PFForm from "@patternfly/patternfly/components/Form/form.css"; import PFForm from "@patternfly/patternfly/components/Form/form.css";
@ -48,10 +48,10 @@ export class AuthenticatorValidateStageWebAuthn extends BaseStage {
publicKey: transformedCredentialRequestOptions, publicKey: transformedCredentialRequestOptions,
}); });
if (!assertion) { if (!assertion) {
throw new Error(gettext("Assertions is empty")); throw new Error(t`Assertions is empty`);
} }
} catch (err) { } catch (err) {
throw new Error(gettext(`Error when creating credential: ${err}`)); throw new Error(t`Error when creating credential: ${err}`);
} }
// we now have an authentication assertion! encode the byte arrays contained // we now have an authentication assertion! encode the byte arrays contained
@ -64,7 +64,7 @@ export class AuthenticatorValidateStageWebAuthn extends BaseStage {
formData.set("webauthn", JSON.stringify(transformedAssertionForServer)); formData.set("webauthn", JSON.stringify(transformedAssertionForServer));
await this.host?.submit(formData); await this.host?.submit(formData);
} catch (err) { } catch (err) {
throw new Error(gettext(`Error when validating assertion on server: ${err}`)); throw new Error(t`Error when validating assertion on server: ${err}`);
} }
} }
@ -78,7 +78,7 @@ export class AuthenticatorValidateStageWebAuthn extends BaseStage {
} }
this.authenticateRunning = true; this.authenticateRunning = true;
this.authenticate().catch((e) => { this.authenticate().catch((e) => {
console.error(gettext(e)); console.error(e);
this.authenticateMessage = e.toString(); this.authenticateMessage = e.toString();
}).finally(() => { }).finally(() => {
this.authenticateRunning = false; this.authenticateRunning = false;
@ -101,7 +101,7 @@ export class AuthenticatorValidateStageWebAuthn extends BaseStage {
<button class="pf-c-button pf-m-primary pf-m-block" @click=${() => { <button class="pf-c-button pf-m-primary pf-m-block" @click=${() => {
this.authenticateWrapper(); this.authenticateWrapper();
}}> }}>
${gettext("Retry authentication")} ${t`Retry authentication`}
</button> </button>
</div>`} </div>`}
</div> </div>
@ -113,7 +113,7 @@ export class AuthenticatorValidateStageWebAuthn extends BaseStage {
if (!this.host) return; if (!this.host) return;
(this.host as AuthenticatorValidateStage).selectedDeviceChallenge = undefined; (this.host as AuthenticatorValidateStage).selectedDeviceChallenge = undefined;
}}> }}>
${gettext("Return to device picker")} ${t`Return to device picker`}
</button> </button>
</li>`: </li>`:
html``} html``}

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { CSSResult, customElement, html, property, TemplateResult } from "lit-element"; import { CSSResult, customElement, html, property, TemplateResult } from "lit-element";
import { WithUserInfoChallenge } from "../../../api/Flows"; import { WithUserInfoChallenge } from "../../../api/Flows";
import PFLogin from "@patternfly/patternfly/components/Login/login.css"; import PFLogin from "@patternfly/patternfly/components/Login/login.css";
@ -54,7 +54,7 @@ export class WebAuthnAuthenticatorRegisterStage extends BaseStage {
throw new Error("Credential is empty"); throw new Error("Credential is empty");
} }
} catch (err) { } catch (err) {
throw new Error(gettext(`Error creating credential: ${err}`)); throw new Error(t`Error creating credential: ${err}`);
} }
// we now have a new credential! We now need to encode the byte arrays // we now have a new credential! We now need to encode the byte arrays
@ -68,7 +68,7 @@ export class WebAuthnAuthenticatorRegisterStage extends BaseStage {
response: newAssertionForServer response: newAssertionForServer
}); });
} catch (err) { } catch (err) {
throw new Error(gettext(`Server validation of credential failed: ${err}`)); throw new Error(t`Server validation of credential failed: ${err}`);
} }
} }
@ -113,7 +113,7 @@ export class WebAuthnAuthenticatorRegisterStage extends BaseStage {
<button class="pf-c-button pf-m-primary pf-m-block" @click=${() => { <button class="pf-c-button pf-m-primary pf-m-block" @click=${() => {
this.registerWrapper(); this.registerWrapper();
}}> }}>
${gettext("Register device")} ${t`Register device`}
</button> </button>
</div>`} </div>`}
</div> </div>

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { CSSResult, customElement, html, property, TemplateResult } from "lit-element"; import { CSSResult, customElement, html, property, TemplateResult } from "lit-element";
import { WithUserInfoChallenge } from "../../../api/Flows"; import { WithUserInfoChallenge } from "../../../api/Flows";
import PFLogin from "@patternfly/patternfly/components/Login/login.css"; import PFLogin from "@patternfly/patternfly/components/Login/login.css";
@ -34,7 +34,7 @@ export class AutosubmitStage extends BaseStage {
if (!this.challenge) { if (!this.challenge) {
return html`<ak-empty-state return html`<ak-empty-state
?loading="${true}" ?loading="${true}"
header=${gettext("Loading")}> header=${t`Loading`}>
</ak-empty-state>`; </ak-empty-state>`;
} }
return html`<header class="pf-c-login__main-header"> return html`<header class="pf-c-login__main-header">
@ -52,7 +52,7 @@ export class AutosubmitStage extends BaseStage {
</ak-empty-state> </ak-empty-state>
<div class="pf-c-form__group pf-m-action"> <div class="pf-c-form__group pf-m-action">
<button type="submit" class="pf-c-button pf-m-primary pf-m-block"> <button type="submit" class="pf-c-button pf-m-primary pf-m-block">
${gettext("Continue")} ${t`Continue`}
</button> </button>
</div> </div>
</form> </form>

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { CSSResult, customElement, html, property, TemplateResult } from "lit-element"; import { CSSResult, customElement, html, property, TemplateResult } from "lit-element";
import { WithUserInfoChallenge } from "../../../api/Flows"; import { WithUserInfoChallenge } from "../../../api/Flows";
import PFLogin from "@patternfly/patternfly/components/Login/login.css"; import PFLogin from "@patternfly/patternfly/components/Login/login.css";
@ -64,7 +64,7 @@ export class CaptchaStage extends BaseStage {
if (!this.challenge) { if (!this.challenge) {
return html`<ak-empty-state return html`<ak-empty-state
?loading="${true}" ?loading="${true}"
header=${gettext("Loading")}> header=${t`Loading`}>
</ak-empty-state>`; </ak-empty-state>`;
} }
return html`<header class="pf-c-login__main-header"> return html`<header class="pf-c-login__main-header">
@ -79,7 +79,7 @@ export class CaptchaStage extends BaseStage {
userAvatar="${this.challenge.pending_user_avatar}" userAvatar="${this.challenge.pending_user_avatar}"
user=${this.challenge.pending_user}> user=${this.challenge.pending_user}>
<div slot="link"> <div slot="link">
<a href="${FlowURLManager.cancel()}">${gettext("Not you?")}</a> <a href="${FlowURLManager.cancel()}">${t`Not you?`}</a>
</div> </div>
</ak-form-static> </ak-form-static>
<div class="ak-loading"> <div class="ak-loading">

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { CSSResult, customElement, html, property, TemplateResult } from "lit-element"; import { CSSResult, customElement, html, property, TemplateResult } from "lit-element";
import { WithUserInfoChallenge } from "../../../api/Flows"; import { WithUserInfoChallenge } from "../../../api/Flows";
import PFLogin from "@patternfly/patternfly/components/Login/login.css"; import PFLogin from "@patternfly/patternfly/components/Login/login.css";
@ -39,7 +39,7 @@ export class ConsentStage extends BaseStage {
if (!this.challenge) { if (!this.challenge) {
return html`<ak-empty-state return html`<ak-empty-state
?loading="${true}" ?loading="${true}"
header=${gettext("Loading")}> header=${t`Loading`}>
</ak-empty-state>`; </ak-empty-state>`;
} }
return html`<header class="pf-c-login__main-header"> return html`<header class="pf-c-login__main-header">
@ -54,14 +54,14 @@ export class ConsentStage extends BaseStage {
userAvatar="${this.challenge.pending_user_avatar}" userAvatar="${this.challenge.pending_user_avatar}"
user=${this.challenge.pending_user}> user=${this.challenge.pending_user}>
<div slot="link"> <div slot="link">
<a href="${FlowURLManager.cancel()}">${gettext("Not you?")}</a> <a href="${FlowURLManager.cancel()}">${t`Not you?`}</a>
</div> </div>
</ak-form-static> </ak-form-static>
<div class="pf-c-form__group"> <div class="pf-c-form__group">
<p id="header-text"> <p id="header-text">
${this.challenge.header_text} ${this.challenge.header_text}
</p> </p>
<p>${gettext("Application requires following permissions")}</p> <p>${t`Application requires following permissions`}</p>
<ul class="pf-c-list" id="permmissions"> <ul class="pf-c-list" id="permmissions">
${(this.challenge.permissions || []).map((permission) => { ${(this.challenge.permissions || []).map((permission) => {
return html`<li data-permission-code="${permission.id}">${permission.name}</li>`; return html`<li data-permission-code="${permission.id}">${permission.name}</li>`;
@ -71,7 +71,7 @@ export class ConsentStage extends BaseStage {
<div class="pf-c-form__group pf-m-action"> <div class="pf-c-form__group pf-m-action">
<button type="submit" class="pf-c-button pf-m-primary pf-m-block"> <button type="submit" class="pf-c-button pf-m-primary pf-m-block">
${gettext("Continue")} ${t`Continue`}
</button> </button>
</div> </div>
</form> </form>

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { CSSResult, customElement, html, property, TemplateResult } from "lit-element"; import { CSSResult, customElement, html, property, TemplateResult } from "lit-element";
import { Challenge } from "../../../api/Flows"; import { Challenge } from "../../../api/Flows";
import PFLogin from "@patternfly/patternfly/components/Login/login.css"; import PFLogin from "@patternfly/patternfly/components/Login/login.css";
@ -26,7 +26,7 @@ export class DummyStage extends BaseStage {
if (!this.challenge) { if (!this.challenge) {
return html`<ak-empty-state return html`<ak-empty-state
?loading="${true}" ?loading="${true}"
header=${gettext("Loading")}> header=${t`Loading`}>
</ak-empty-state>`; </ak-empty-state>`;
} }
return html`<header class="pf-c-login__main-header"> return html`<header class="pf-c-login__main-header">
@ -38,7 +38,7 @@ export class DummyStage extends BaseStage {
<form class="pf-c-form" @submit=${(e: Event) => { this.submitForm(e); }}> <form class="pf-c-form" @submit=${(e: Event) => { this.submitForm(e); }}>
<div class="pf-c-form__group pf-m-action"> <div class="pf-c-form__group pf-m-action">
<button type="submit" class="pf-c-button pf-m-primary pf-m-block"> <button type="submit" class="pf-c-button pf-m-primary pf-m-block">
${gettext("Continue")} ${t`Continue`}
</button> </button>
</div> </div>
</form> </form>

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { CSSResult, customElement, html, property, TemplateResult } from "lit-element"; import { CSSResult, customElement, html, property, TemplateResult } from "lit-element";
import { Challenge } from "authentik-api"; import { Challenge } from "authentik-api";
import PFLogin from "@patternfly/patternfly/components/Login/login.css"; import PFLogin from "@patternfly/patternfly/components/Login/login.css";
@ -27,7 +27,7 @@ export class EmailStage extends BaseStage {
if (!this.challenge) { if (!this.challenge) {
return html`<ak-empty-state return html`<ak-empty-state
?loading="${true}" ?loading="${true}"
header=${gettext("Loading")}> header=${t`Loading`}>
</ak-empty-state>`; </ak-empty-state>`;
} }
return html`<header class="pf-c-login__main-header"> return html`<header class="pf-c-login__main-header">
@ -39,13 +39,13 @@ export class EmailStage extends BaseStage {
<form class="pf-c-form" @submit=${(e: Event) => { this.submitForm(e); }}> <form class="pf-c-form" @submit=${(e: Event) => { this.submitForm(e); }}>
<div class="pf-c-form__group"> <div class="pf-c-form__group">
<p> <p>
${gettext("Check your Emails for a password reset link.")} ${t`Check your Emails for a password reset link.`}
</p> </p>
</div> </div>
<div class="pf-c-form__group pf-m-action"> <div class="pf-c-form__group pf-m-action">
<button type="submit" class="pf-c-button pf-m-primary pf-m-block"> <button type="submit" class="pf-c-button pf-m-primary pf-m-block">
${gettext("Send Email again.")} ${t`Send Email again.`}
</button> </button>
</div> </div>
</form> </form>

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { css, CSSResult, customElement, html, property, TemplateResult } from "lit-element"; import { css, CSSResult, customElement, html, property, TemplateResult } from "lit-element";
import { BaseStage } from "../base"; import { BaseStage } from "../base";
import PFLogin from "@patternfly/patternfly/components/Login/login.css"; import PFLogin from "@patternfly/patternfly/components/Login/login.css";
@ -144,13 +144,13 @@ export class IdentificationStage extends BaseStage {
return html`<div class="pf-c-login__main-footer-band"> return html`<div class="pf-c-login__main-footer-band">
${this.challenge.enroll_url ? html` ${this.challenge.enroll_url ? html`
<p class="pf-c-login__main-footer-band-item"> <p class="pf-c-login__main-footer-band-item">
${gettext("Need an account?")} ${t`Need an account?`}
<a id="enroll" href="${this.challenge.enroll_url}">${gettext("Sign up.")}</a> <a id="enroll" href="${this.challenge.enroll_url}">${t`Sign up.`}</a>
</p>` : html``} </p>` : html``}
${this.challenge.recovery_url ? html` ${this.challenge.recovery_url ? html`
<p class="pf-c-login__main-footer-band-item"> <p class="pf-c-login__main-footer-band-item">
${gettext("Need an account?")} ${t`Need an account?`}
<a id="recovery" href="${this.challenge.recovery_url}">${gettext("Forgot username or password?")}</a> <a id="recovery" href="${this.challenge.recovery_url}">${t`Forgot username or password?`}</a>
</p>` : html``} </p>` : html``}
</div>`; </div>`;
} }
@ -159,7 +159,7 @@ export class IdentificationStage extends BaseStage {
if (!this.challenge) { if (!this.challenge) {
return html`<ak-empty-state return html`<ak-empty-state
?loading="${true}" ?loading="${true}"
header=${gettext("Loading")}> header=${t`Loading`}>
</ak-empty-state>`; </ak-empty-state>`;
} }
return html`<header class="pf-c-login__main-header"> return html`<header class="pf-c-login__main-header">
@ -171,12 +171,12 @@ export class IdentificationStage extends BaseStage {
<form class="pf-c-form" @submit=${(e: Event) => {this.submitForm(e);}}> <form class="pf-c-form" @submit=${(e: Event) => {this.submitForm(e);}}>
${this.challenge.application_pre ? ${this.challenge.application_pre ?
html`<p> html`<p>
${gettext(`Login to continue to ${this.challenge.application_pre}.`)} ${t`Login to continue to ${this.challenge.application_pre}.`}
</p>`: </p>`:
html``} html``}
<ak-form-element <ak-form-element
label="${gettext("Email or Username")}" label="${t`Email or Username`}"
?required="${true}" ?required="${true}"
class="pf-c-form__group" class="pf-c-form__group"
.errors=${(this.challenge?.response_errors || {})["uid_field"]}> .errors=${(this.challenge?.response_errors || {})["uid_field"]}>

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { CSSResult, customElement, html, property, TemplateResult } from "lit-element"; import { CSSResult, customElement, html, property, TemplateResult } from "lit-element";
import { WithUserInfoChallenge } from "../../../api/Flows"; import { WithUserInfoChallenge } from "../../../api/Flows";
import PFLogin from "@patternfly/patternfly/components/Login/login.css"; import PFLogin from "@patternfly/patternfly/components/Login/login.css";
@ -33,7 +33,7 @@ export class PasswordStage extends BaseStage {
if (!this.challenge) { if (!this.challenge) {
return html`<ak-empty-state return html`<ak-empty-state
?loading="${true}" ?loading="${true}"
header=${gettext("Loading")}> header=${t`Loading`}>
</ak-empty-state>`; </ak-empty-state>`;
} }
return html`<header class="pf-c-login__main-header"> return html`<header class="pf-c-login__main-header">
@ -48,18 +48,18 @@ export class PasswordStage extends BaseStage {
userAvatar="${this.challenge.pending_user_avatar}" userAvatar="${this.challenge.pending_user_avatar}"
user=${this.challenge.pending_user}> user=${this.challenge.pending_user}>
<div slot="link"> <div slot="link">
<a href="${FlowURLManager.cancel()}">${gettext("Not you?")}</a> <a href="${FlowURLManager.cancel()}">${t`Not you?`}</a>
</div> </div>
</ak-form-static> </ak-form-static>
<input name="username" autocomplete="username" type="hidden" value="${this.challenge.pending_user}"> <input name="username" autocomplete="username" type="hidden" value="${this.challenge.pending_user}">
<ak-form-element <ak-form-element
label="${gettext("Password")}" label="${t`Password`}"
?required="${true}" ?required="${true}"
class="pf-c-form__group" class="pf-c-form__group"
.errors=${(this.challenge?.response_errors || {})["password"]}> .errors=${(this.challenge?.response_errors || {})["password"]}>
<input type="password" <input type="password"
name="password" name="password"
placeholder="${gettext("Please enter your password")}" placeholder="${t`Please enter your password`}"
autofocus="" autofocus=""
autocomplete="current-password" autocomplete="current-password"
class="pf-c-form-control" class="pf-c-form-control"
@ -69,11 +69,11 @@ export class PasswordStage extends BaseStage {
${this.challenge.recovery_url ? ${this.challenge.recovery_url ?
html`<a href="${this.challenge.recovery_url}"> html`<a href="${this.challenge.recovery_url}">
${gettext("Forgot password?")}</a>` : ""} ${t`Forgot password?`}</a>` : ""}
<div class="pf-c-form__group pf-m-action"> <div class="pf-c-form__group pf-m-action">
<button type="submit" class="pf-c-button pf-m-primary pf-m-block"> <button type="submit" class="pf-c-button pf-m-primary pf-m-block">
${gettext("Continue")} ${t`Continue`}
</button> </button>
</div> </div>
</form> </form>

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { CSSResult, customElement, html, property, TemplateResult } from "lit-element"; import { CSSResult, customElement, html, property, TemplateResult } from "lit-element";
import { unsafeHTML } from "lit-html/directives/unsafe-html"; import { unsafeHTML } from "lit-html/directives/unsafe-html";
import PFLogin from "@patternfly/patternfly/components/Login/login.css"; import PFLogin from "@patternfly/patternfly/components/Login/login.css";
@ -121,7 +121,7 @@ export class PromptStage extends BaseStage {
if (!this.challenge) { if (!this.challenge) {
return html`<ak-empty-state return html`<ak-empty-state
?loading="${true}" ?loading="${true}"
header=${gettext("Loading")}> header=${t`Loading`}>
</ak-empty-state>`; </ak-empty-state>`;
} }
return html`<header class="pf-c-login__main-header"> return html`<header class="pf-c-login__main-header">
@ -142,7 +142,7 @@ export class PromptStage extends BaseStage {
})} })}
<div class="pf-c-form__group pf-m-action"> <div class="pf-c-form__group pf-m-action">
<button type="submit" class="pf-c-button pf-m-primary pf-m-block"> <button type="submit" class="pf-c-button pf-m-primary pf-m-block">
${gettext("Continue")} ${t`Continue`}
</button> </button>
</div> </div>
</form> </form>

View File

@ -4,58 +4,60 @@ import { me } from "../api/Users";
import { SidebarItem } from "../elements/sidebar/Sidebar"; import { SidebarItem } from "../elements/sidebar/Sidebar";
import { ID_REGEX, SLUG_REGEX, UUID_REGEX } from "../elements/router/Route"; import { ID_REGEX, SLUG_REGEX, UUID_REGEX } from "../elements/router/Route";
import { Interface } from "./Interface"; import { Interface } from "./Interface";
import "./locale";
import { t } from "@lingui/macro";
export const SIDEBAR_ITEMS: SidebarItem[] = [ export const SIDEBAR_ITEMS: SidebarItem[] = [
new SidebarItem("Library", "/library"), new SidebarItem(t`Library`, "/library"),
new SidebarItem("Monitor").children( new SidebarItem(t`Monitor`).children(
new SidebarItem("Overview", "/administration/overview"), new SidebarItem(t`Overview`, "/administration/overview"),
new SidebarItem("System Tasks", "/administration/system-tasks"), new SidebarItem(t`System Tasks`, "/administration/system-tasks"),
).when((): Promise<boolean> => { ).when((): Promise<boolean> => {
return me().then(u => u.user.isSuperuser||false); return me().then(u => u.user.isSuperuser||false);
}), }),
new SidebarItem("Resources").children( new SidebarItem(t`Resources`).children(
new SidebarItem("Applications", "/core/applications").activeWhen( new SidebarItem(t`Applications`, "/core/applications").activeWhen(
`^/core/applications/(?<slug>${SLUG_REGEX})$` `^/core/applications/(?<slug>${SLUG_REGEX})$`
), ),
new SidebarItem("Sources", "/core/sources").activeWhen( new SidebarItem(t`Sources`, "/core/sources").activeWhen(
`^/core/sources/(?<slug>${SLUG_REGEX})$`, `^/core/sources/(?<slug>${SLUG_REGEX})$`,
), ),
new SidebarItem("Providers", "/core/providers").activeWhen( new SidebarItem(t`Providers`, "/core/providers").activeWhen(
`^/core/providers/(?<id>${ID_REGEX})$`, `^/core/providers/(?<id>${ID_REGEX})$`,
), ),
new SidebarItem("Outposts", "/outpost/outposts"), new SidebarItem(t`Outposts`, "/outpost/outposts"),
new SidebarItem("Outpost Service Connections", "/outpost/service-connections"), new SidebarItem(t`Outpost Service Connections`, "/outpost/service-connections"),
).when((): Promise<boolean> => { ).when((): Promise<boolean> => {
return me().then(u => u.user.isSuperuser||false); return me().then(u => u.user.isSuperuser||false);
}), }),
new SidebarItem("Events").children( new SidebarItem(t`Events`).children(
new SidebarItem("Logs", "/events/log").activeWhen( new SidebarItem(t`Logs`, "/events/log").activeWhen(
`^/events/log/(?<id>${UUID_REGEX})$` `^/events/log/(?<id>${UUID_REGEX})$`
), ),
new SidebarItem("Notification Rules", "/events/rules"), new SidebarItem(t`Notification Rules`, "/events/rules"),
new SidebarItem("Notification Transports", "/events/transports"), new SidebarItem(t`Notification Transports`, "/events/transports"),
).when((): Promise<boolean> => { ).when((): Promise<boolean> => {
return me().then(u => u.user.isSuperuser || false); return me().then(u => u.user.isSuperuser || false);
}), }),
new SidebarItem("Customisation").children( new SidebarItem(t`Customisation`).children(
new SidebarItem("Policies", "/policy/policies"), new SidebarItem(t`Policies`, "/policy/policies"),
new SidebarItem("Property Mappings", "/core/property-mappings"), new SidebarItem(t`Property Mappings`, "/core/property-mappings"),
).when((): Promise<boolean> => { ).when((): Promise<boolean> => {
return me().then(u => u.user.isSuperuser||false); return me().then(u => u.user.isSuperuser||false);
}), }),
new SidebarItem("Flows").children( new SidebarItem(t`Flows`).children(
new SidebarItem("Flows", "/flow/flows").activeWhen(`^/flow/flows/(?<slug>${SLUG_REGEX})$`), new SidebarItem(t`Flows`, "/flow/flows").activeWhen(`^/flow/flows/(?<slug>${SLUG_REGEX})$`),
new SidebarItem("Stages", "/flow/stages"), new SidebarItem(t`Stages`, "/flow/stages"),
new SidebarItem("Prompts", "/flow/stages/prompts"), new SidebarItem(t`Prompts`, "/flow/stages/prompts"),
new SidebarItem("Invitations", "/flow/stages/invitations"), new SidebarItem(t`Invitations`, "/flow/stages/invitations"),
).when((): Promise<boolean> => { ).when((): Promise<boolean> => {
return me().then(u => u.user.isSuperuser||false); return me().then(u => u.user.isSuperuser||false);
}), }),
new SidebarItem("Identity & Cryptography").children( new SidebarItem(t`Identity & Cryptography`).children(
new SidebarItem("Users", "/identity/users").activeWhen(`^/identity/users/(?<id>${ID_REGEX})$`), new SidebarItem(t`Users`, "/identity/users").activeWhen(`^/identity/users/(?<id>${ID_REGEX})$`),
new SidebarItem("Groups", "/identity/groups"), new SidebarItem(t`Groups`, "/identity/groups"),
new SidebarItem("Certificates", "/crypto/certificates"), new SidebarItem(t`Certificates`, "/crypto/certificates"),
new SidebarItem("Tokens", "/core/tokens"), new SidebarItem(t`Tokens`, "/core/tokens"),
).when((): Promise<boolean> => { ).when((): Promise<boolean> => {
return me().then(u => u.user.isSuperuser||false); return me().then(u => u.user.isSuperuser||false);
}), }),

View File

@ -1,4 +1,3 @@
import "construct-style-sheets-polyfill"; import "./locale";
import "../elements/messages/MessageContainer"; import "../elements/messages/MessageContainer";
import "../flows/FlowExecutor"; import "../flows/FlowExecutor";

View File

@ -13,7 +13,7 @@ import "../elements/notifications/NotificationDrawer";
import "../elements/Banner"; import "../elements/Banner";
import { until } from "lit-html/directives/until"; import { until } from "lit-html/directives/until";
import { me } from "../api/Users"; import { me } from "../api/Users";
import { gettext } from "django"; import { t } from "@lingui/macro";
import { EVENT_NOTIFICATION_TOGGLE, EVENT_SIDEBAR_TOGGLE } from "../constants"; import { EVENT_NOTIFICATION_TOGGLE, EVENT_SIDEBAR_TOGGLE } from "../constants";
export abstract class Interface extends LitElement { export abstract class Interface extends LitElement {
@ -52,9 +52,9 @@ export abstract class Interface extends LitElement {
${until(me().then((u) => { ${until(me().then((u) => {
if (u.original) { if (u.original) {
return html`<ak-banner> return html`<ak-banner>
${gettext(`You're currently impersonating ${u.user.username}.`)} ${t`You're currently impersonating ${u.user.username}.`}
<a href=${`/-/impersonation/end/?back=${window.location.pathname}%23${window.location.hash}`}> <a href=${`/-/impersonation/end/?back=${window.location.pathname}%23${window.location.hash}`}>
${gettext("Stop impersonation")} ${t`Stop impersonation`}
</a> </a>
</ak-banner>`; </ak-banner>`;
} }

View File

@ -7,8 +7,7 @@
<link rel="shortcut icon" type="image/png" href="/static/dist/assets/icons/icon.png"> <link rel="shortcut icon" type="image/png" href="/static/dist/assets/icons/icon.png">
<link rel="stylesheet" type="text/css" href="/static/dist/patternfly-base.css"> <link rel="stylesheet" type="text/css" href="/static/dist/patternfly-base.css">
<link rel="stylesheet" type="text/css" href="/static/dist/authentik.css"> <link rel="stylesheet" type="text/css" href="/static/dist/authentik.css">
<script src="/api/jsi18n/"></script> <script src="/static/dist/poly.js" type="module"></script>
<script src="/static/dist/adoptedStyleSheets.js" type="module"></script>
<script src="/static/dist/AdminInterface.js" type="module"></script> <script src="/static/dist/AdminInterface.js" type="module"></script>
<title>authentik</title> <title>authentik</title>
</head> </head>

View File

@ -7,8 +7,7 @@
<link rel="shortcut icon" type="image/png" href="/static/dist/assets/icons/icon.png"> <link rel="shortcut icon" type="image/png" href="/static/dist/assets/icons/icon.png">
<link rel="stylesheet" type="text/css" href="/static/dist/patternfly-base.css"> <link rel="stylesheet" type="text/css" href="/static/dist/patternfly-base.css">
<link rel="stylesheet" type="text/css" href="/static/dist/authentik.css"> <link rel="stylesheet" type="text/css" href="/static/dist/authentik.css">
<script src="/api/jsi18n/"></script> <script src="/static/dist/poly.js" type="module"></script>
<script src="/static/dist/adoptedStyleSheets.js" type="module"></script>
<script src="/static/dist/FlowInterface.js" type="module"></script> <script src="/static/dist/FlowInterface.js" type="module"></script>
<title>authentik</title> <title>authentik</title>
</head> </head>

View File

@ -0,0 +1,14 @@
import { i18n } from "@lingui/core";
import { en } from "make-plural/plurals";
import { messages as localeEN } from "../locales/en";
import { messages as localeDEBUG } from "../locales/pseudo-LOCALE";
i18n.loadLocaleData("en", { plurals: en });
i18n.loadLocaleData("debug", { plurals: en });
i18n.load("en", localeEN);
i18n.load("debug", localeDEBUG);
i18n.activate("en");
if (window.location.search.includes("debugLocale")) {
i18n.activate("debug");
}

1
web/src/locales/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*.ts

3725
web/src/locales/en.po Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { css, CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element"; import { css, CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element";
import { ifDefined } from "lit-html/directives/if-defined"; import { ifDefined } from "lit-html/directives/if-defined";
import { until } from "lit-html/directives/until"; import { until } from "lit-html/directives/until";
@ -87,7 +87,7 @@ export class LibraryPage extends LitElement {
apps?: AKResponse<Application>; apps?: AKResponse<Application>;
pageTitle(): string { pageTitle(): string {
return gettext("Applications"); return t`Applications`;
} }
static get styles(): CSSResult[] { static get styles(): CSSResult[] {
@ -109,9 +109,9 @@ export class LibraryPage extends LitElement {
return html` <div class="pf-c-empty-state pf-m-full-height"> return html` <div class="pf-c-empty-state pf-m-full-height">
<div class="pf-c-empty-state__content"> <div class="pf-c-empty-state__content">
<i class="fas fa-cubes pf-c-empty-state__icon" aria-hidden="true"></i> <i class="fas fa-cubes pf-c-empty-state__icon" aria-hidden="true"></i>
<h1 class="pf-c-title pf-m-lg">${gettext("No Applications available.")}</h1> <h1 class="pf-c-title pf-m-lg">${t`No Applications available.`}</h1>
<div class="pf-c-empty-state__body"> <div class="pf-c-empty-state__body">
${gettext("Either no applications are defined, or you don't have access to any.")} ${t`Either no applications are defined, or you don't have access to any.`}
</div> </div>
</div> </div>
</div>`; </div>`;
@ -129,7 +129,7 @@ export class LibraryPage extends LitElement {
<div class="pf-c-content"> <div class="pf-c-content">
<h1> <h1>
<i class="pf-icon pf-icon-applications"></i> <i class="pf-icon pf-icon-applications"></i>
${gettext("Applications")} ${t`Applications`}
</h1> </h1>
</div> </div>
</section> </section>

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { CSSResult, customElement, html, LitElement, TemplateResult } from "lit-element"; import { CSSResult, customElement, html, LitElement, TemplateResult } from "lit-element";
import "../../elements/charts/AdminLoginsChart"; import "../../elements/charts/AdminLoginsChart";
@ -28,30 +28,30 @@ export class AdminOverviewPage extends LitElement {
render(): TemplateResult { render(): TemplateResult {
return html`<section class="pf-c-page__main-section pf-m-light"> return html`<section class="pf-c-page__main-section pf-m-light">
<div class="pf-c-content"> <div class="pf-c-content">
<h1>${gettext("System Overview")}</h1> <h1>${t`System Overview`}</h1>
</div> </div>
</section> </section>
<section class="pf-c-page__main-section"> <section class="pf-c-page__main-section">
<div class="pf-l-gallery pf-m-gutter"> <div class="pf-l-gallery pf-m-gutter">
<ak-aggregate-card class="pf-l-gallery__item pf-m-4-col" icon="pf-icon pf-icon-server" header="Logins over the last 24 hours" style="grid-column-end: span 3;grid-row-end: span 2;"> <ak-aggregate-card class="pf-l-gallery__item pf-m-4-col" icon="pf-icon pf-icon-server" header=${t`Logins over the last 24 hours`} style="grid-column-end: span 3;grid-row-end: span 2;">
<ak-charts-admin-login></ak-charts-admin-login> <ak-charts-admin-login></ak-charts-admin-login>
</ak-aggregate-card> </ak-aggregate-card>
<ak-aggregate-card class="pf-l-gallery__item pf-m-4-col" icon="pf-icon pf-icon-server" header="Apps with most usage" style="grid-column-end: span 2;grid-row-end: span 3;"> <ak-aggregate-card class="pf-l-gallery__item pf-m-4-col" icon="pf-icon pf-icon-server" header=${t`Apps with most usage`} style="grid-column-end: span 2;grid-row-end: span 3;">
<ak-top-applications-table></ak-top-applications-table> <ak-top-applications-table></ak-top-applications-table>
</ak-aggregate-card> </ak-aggregate-card>
<ak-admin-status-card-provider class="pf-l-gallery__item pf-m-4-col" icon="pf-icon pf-icon-plugged" header="Providers" headerLink="#/core/providers/"> <ak-admin-status-card-provider class="pf-l-gallery__item pf-m-4-col" icon="pf-icon pf-icon-plugged" header=${t`Providers`} headerLink="#/core/providers/">
</ak-admin-status-card-provider> </ak-admin-status-card-provider>
<ak-admin-status-card-policy-unbound class="pf-l-gallery__item pf-m-4-col" icon="pf-icon pf-icon-infrastructure" header="Policies" headerLink="#/policy/policies"> <ak-admin-status-card-policy-unbound class="pf-l-gallery__item pf-m-4-col" icon="pf-icon pf-icon-infrastructure" header=${t`Policies`} headerLink="#/policy/policies">
</ak-admin-status-card-policy-unbound> </ak-admin-status-card-policy-unbound>
<ak-admin-status-card-user-count class="pf-l-gallery__item pf-m-4-col" icon="pf-icon pf-icon-user" header="Users" headerLink="#/identity/users"> <ak-admin-status-card-user-count class="pf-l-gallery__item pf-m-4-col" icon="pf-icon pf-icon-user" header=${t`Users`} headerLink="#/identity/users">
</ak-admin-status-card-user-count> </ak-admin-status-card-user-count>
<ak-admin-status-version class="pf-l-gallery__item pf-m-4-col" icon="pf-icon pf-icon-bundle" header="Version" headerLink="https://github.com/BeryJu/authentik/releases"> <ak-admin-status-version class="pf-l-gallery__item pf-m-4-col" icon="pf-icon pf-icon-bundle" header=${t`Version`} headerLink="https://github.com/BeryJu/authentik/releases">
</ak-admin-status-version> </ak-admin-status-version>
<ak-admin-status-card-workers class="pf-l-gallery__item pf-m-4-col" icon="pf-icon pf-icon-server" header="Workers"> <ak-admin-status-card-workers class="pf-l-gallery__item pf-m-4-col" icon="pf-icon pf-icon-server" header=${t`Workers`}>
</ak-admin-status-card-workers> </ak-admin-status-card-workers>
<ak-admin-status-card-policy-cache class="pf-l-gallery__item pf-m-4-col" icon="pf-icon pf-icon-server" header="Cached Policies"> <ak-admin-status-card-policy-cache class="pf-l-gallery__item pf-m-4-col" icon="pf-icon pf-icon-server" header=${t`Cached Policies`}>
</ak-admin-status-card-policy-cache> </ak-admin-status-card-policy-cache>
<ak-admin-status-card-flow-cache class="pf-l-gallery__item pf-m-4-col" icon="pf-icon pf-icon-server" header="Cached Flows"> <ak-admin-status-card-flow-cache class="pf-l-gallery__item pf-m-4-col" icon="pf-icon pf-icon-server" header=${t`Cached Flows`}>
</ak-admin-status-card-flow-cache> </ak-admin-status-card-flow-cache>
</div> </div>
</section>`; </section>`;

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element"; import { CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element";
import { EventsApi, EventTopPerUser } from "authentik-api"; import { EventsApi, EventTopPerUser } from "authentik-api";
import PFTable from "@patternfly/patternfly/components/Table/table.css"; import PFTable from "@patternfly/patternfly/components/Table/table.css";
@ -43,8 +43,8 @@ export class TopApplicationsTable extends LitElement {
return html`<table class="pf-c-table pf-m-compact" role="grid"> return html`<table class="pf-c-table pf-m-compact" role="grid">
<thead> <thead>
<tr role="row"> <tr role="row">
<th role="columnheader" scope="col">${gettext("Application")}</th> <th role="columnheader" scope="col">${t`Application`}</th>
<th role="columnheader" scope="col">${gettext("Logins")}</th> <th role="columnheader" scope="col">${t`Logins`}</th>
<th role="columnheader" scope="col"></th> <th role="columnheader" scope="col"></th>
</tr> </tr>
</thead> </thead>

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { customElement, html, TemplateResult } from "lit-element"; import { customElement, html, TemplateResult } from "lit-element";
import { AdminStatus, AdminStatusCard } from "./AdminStatusCard"; import { AdminStatus, AdminStatusCard } from "./AdminStatusCard";
import { FlowsApi } from "authentik-api"; import { FlowsApi } from "authentik-api";
@ -18,7 +18,7 @@ export class FlowCacheStatusCard extends AdminStatusCard<number> {
if (value < 1) { if (value < 1) {
return Promise.resolve<AdminStatus>({ return Promise.resolve<AdminStatus>({
icon: "fa fa-exclamation-triangle pf-m-warning", icon: "fa fa-exclamation-triangle pf-m-warning",
message: gettext("No flows cached."), message: t`No flows cached.`,
}); });
} else { } else {
return Promise.resolve<AdminStatus>({ return Promise.resolve<AdminStatus>({
@ -29,18 +29,18 @@ export class FlowCacheStatusCard extends AdminStatusCard<number> {
renderHeaderLink(): TemplateResult { renderHeaderLink(): TemplateResult {
return html`<ak-forms-confirm return html`<ak-forms-confirm
successMessage="Successfully cleared flow cache" successMessage=${t`Successfully cleared flow cache`}
errorMessage="Failed to delete flow cache" errorMessage=${t`Failed to delete flow cache`}
action="Clear cache" action=${t`Clear cache`}
.onConfirm=${() => { .onConfirm=${() => {
return new FlowsApi(DEFAULT_CONFIG).flowsInstancesCacheClear(); return new FlowsApi(DEFAULT_CONFIG).flowsInstancesCacheClear();
}}> }}>
<span slot="header"> <span slot="header">
${gettext("Clear Flow cache")} ${t`Clear Flow cache`}
</span> </span>
<p slot="body"> <p slot="body">
${gettext(`Are you sure you want to clear the flow cache? ${t`Are you sure you want to clear the flow cache?
This will cause all flows to be re-evaluated on their next usage.`)} This will cause all flows to be re-evaluated on their next usage.`}
</p> </p>
<a slot="trigger"> <a slot="trigger">
<i class="fa fa-trash"> </i> <i class="fa fa-trash"> </i>

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { customElement } from "lit-element"; import { customElement } from "lit-element";
import { TemplateResult, html } from "lit-html"; import { TemplateResult, html } from "lit-html";
import { AdminStatusCard, AdminStatus } from "./AdminStatusCard"; import { AdminStatusCard, AdminStatus } from "./AdminStatusCard";
@ -19,7 +19,7 @@ export class PolicyCacheStatusCard extends AdminStatusCard<number> {
if (value < 1) { if (value < 1) {
return Promise.resolve<AdminStatus>({ return Promise.resolve<AdminStatus>({
icon: "fa fa-exclamation-triangle pf-m-warning", icon: "fa fa-exclamation-triangle pf-m-warning",
message: gettext("No policies cached. Users may experience slow response times."), message: t`No policies cached. Users may experience slow response times.`,
}); });
} else { } else {
return Promise.resolve<AdminStatus>({ return Promise.resolve<AdminStatus>({
@ -30,18 +30,18 @@ export class PolicyCacheStatusCard extends AdminStatusCard<number> {
renderHeaderLink(): TemplateResult { renderHeaderLink(): TemplateResult {
return html`<ak-forms-confirm return html`<ak-forms-confirm
successMessage="Successfully cleared policy cache" successMessage=${t`Successfully cleared policy cache`}
errorMessage="Failed to delete policy cache" errorMessage=${t`Failed to delete policy cache`}
action="Clear cache" action=${t`Clear cache`}
.onConfirm=${() => { .onConfirm=${() => {
return new PoliciesApi(DEFAULT_CONFIG).policiesAllCacheClear(); return new PoliciesApi(DEFAULT_CONFIG).policiesAllCacheClear();
}}> }}>
<span slot="header"> <span slot="header">
${gettext("Clear Policy cache")} ${t`Clear Policy cache`}
</span> </span>
<p slot="body"> <p slot="body">
${gettext(`Are you sure you want to clear the policy cache? ${t`Are you sure you want to clear the policy cache?
This will cause all policies to be re-evaluated on their next usage.`)} This will cause all policies to be re-evaluated on their next usage.`}
</p> </p>
<a slot="trigger"> <a slot="trigger">
<i class="fa fa-trash"> </i> <i class="fa fa-trash"> </i>

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { customElement } from "lit-element"; import { customElement } from "lit-element";
import { PoliciesApi } from "authentik-api"; import { PoliciesApi } from "authentik-api";
import { DEFAULT_CONFIG } from "../../../api/Config"; import { DEFAULT_CONFIG } from "../../../api/Config";
@ -20,7 +20,7 @@ export class PolicyUnboundStatusCard extends AdminStatusCard<number> {
if (value > 0) { if (value > 0) {
return Promise.resolve<AdminStatus>({ return Promise.resolve<AdminStatus>({
icon: "fa fa-exclamation-triangle pf-m-warning", icon: "fa fa-exclamation-triangle pf-m-warning",
message: gettext("Policies without binding exist."), message: t`Policies without binding exist.`,
}); });
} else { } else {
return Promise.resolve<AdminStatus>({ return Promise.resolve<AdminStatus>({

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { customElement } from "lit-element"; import { customElement } from "lit-element";
import { ProvidersApi } from "authentik-api"; import { ProvidersApi } from "authentik-api";
import { DEFAULT_CONFIG } from "../../../api/Config"; import { DEFAULT_CONFIG } from "../../../api/Config";
@ -19,7 +19,7 @@ export class ProviderStatusCard extends AdminStatusCard<number> {
if (value > 0) { if (value > 0) {
return Promise.resolve<AdminStatus>({ return Promise.resolve<AdminStatus>({
icon: "fa fa-exclamation-triangle pf-m-warning", icon: "fa fa-exclamation-triangle pf-m-warning",
message: gettext("Warning: At least one Provider has no application assigned."), message: t`Warning: At least one Provider has no application assigned.`,
}); });
} else { } else {
return Promise.resolve<AdminStatus>({ return Promise.resolve<AdminStatus>({

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { customElement, html, TemplateResult } from "lit-element"; import { customElement, html, TemplateResult } from "lit-element";
import { AdminApi, Version } from "authentik-api"; import { AdminApi, Version } from "authentik-api";
import { DEFAULT_CONFIG } from "../../../api/Config"; import { DEFAULT_CONFIG } from "../../../api/Config";
@ -15,18 +15,18 @@ export class VersionStatusCard extends AdminStatusCard<Version> {
if (value.buildHash) { if (value.buildHash) {
return Promise.resolve<AdminStatus>({ return Promise.resolve<AdminStatus>({
icon: "fa fa-check-circle pf-m-success", icon: "fa fa-check-circle pf-m-success",
message: gettext(`Build hash: ${value.buildHash?.substring(0, 10)}`), message: t`Build hash: ${value.buildHash?.substring(0, 10)}`,
}); });
} }
if (value.outdated) { if (value.outdated) {
return Promise.resolve<AdminStatus>({ return Promise.resolve<AdminStatus>({
icon: "fa fa-exclamation-triangle pf-m-warning", icon: "fa fa-exclamation-triangle pf-m-warning",
message: gettext(`${value.versionLatest} is available!`), message: t`${value.versionLatest} is available!`,
}); });
} }
return Promise.resolve<AdminStatus>({ return Promise.resolve<AdminStatus>({
icon: "fa fa-check-circle pf-m-success", icon: "fa fa-check-circle pf-m-success",
message: gettext("Up-to-date!") message: t`Up-to-date!`
}); });
} }

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { customElement } from "lit-element"; import { customElement } from "lit-element";
import { AdminApi } from "authentik-api"; import { AdminApi } from "authentik-api";
import { DEFAULT_CONFIG } from "../../../api/Config"; import { DEFAULT_CONFIG } from "../../../api/Config";
@ -17,7 +17,7 @@ export class WorkersStatusCard extends AdminStatusCard<number> {
if (value < 1) { if (value < 1) {
return Promise.resolve<AdminStatus>({ return Promise.resolve<AdminStatus>({
icon: "fa fa-exclamation-triangle pf-m-warning", icon: "fa fa-exclamation-triangle pf-m-warning",
message: gettext("No workers connected. Background tasks will not run."), message: t`No workers connected. Background tasks will not run.`,
}); });
} else { } else {
return Promise.resolve<AdminStatus>({ return Promise.resolve<AdminStatus>({

View File

@ -1,5 +1,5 @@
import { CoreApi, Application, ProvidersApi, Provider, ApplicationPolicyEngineModeEnum } from "authentik-api"; import { CoreApi, Application, ProvidersApi, Provider, ApplicationPolicyEngineModeEnum } from "authentik-api";
import { gettext } from "django"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement, property } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../api/Config"; import { DEFAULT_CONFIG } from "../../api/Config";
@ -20,9 +20,9 @@ export class ApplicationForm extends Form<Application> {
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.application) { if (this.application) {
return gettext("Successfully updated application."); return t`Successfully updated application.`;
} else { } else {
return gettext("Successfully created application."); return t`Successfully created application.`;
} }
} }
@ -74,21 +74,21 @@ export class ApplicationForm extends Form<Application> {
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Name")} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.application?.name)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.application?.name)}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${gettext("Application's display Name.")}</p> <p class="pf-c-form__helper-text">${t`Application's display Name.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Slug")} label=${t`Slug`}
?required=${true} ?required=${true}
name="slug"> name="slug">
<input type="text" value="${ifDefined(this.application?.slug)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.application?.slug)}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${gettext("Internal application name, used in URLs.")}</p> <p class="pf-c-form__helper-text">${t`Internal application name, used in URLs.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Provider")} label=${t`Provider`}
name="parent"> name="parent">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value="" ?selected=${this.application?.provider === undefined}>---------</option> <option value="" ?selected=${this.application?.provider === undefined}>---------</option>
@ -98,36 +98,36 @@ export class ApplicationForm extends Form<Application> {
</select> </select>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Policy engine mode")} label=${t`Policy engine mode`}
?required=${true} ?required=${true}
name="policyEngineMode"> name="policyEngineMode">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value=${ApplicationPolicyEngineModeEnum.Any} ?selected=${this.application?.policyEngineMode === ApplicationPolicyEngineModeEnum.Any}> <option value=${ApplicationPolicyEngineModeEnum.Any} ?selected=${this.application?.policyEngineMode === ApplicationPolicyEngineModeEnum.Any}>
${gettext("ANY, any policy must match to grant access.")} ${t`ANY, any policy must match to grant access.`}
</option> </option>
<option value=${ApplicationPolicyEngineModeEnum.All} ?selected=${this.application?.policyEngineMode === ApplicationPolicyEngineModeEnum.All}> <option value=${ApplicationPolicyEngineModeEnum.All} ?selected=${this.application?.policyEngineMode === ApplicationPolicyEngineModeEnum.All}>
${gettext("ALL, all policies must match to grant access.")} ${t`ALL, all policies must match to grant access.`}
</option> </option>
</select> </select>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Launch URL")} label=${t`Launch URL`}
name="launchUrl"> name="launchUrl">
<input type="text" value="${ifDefined(this.application?.launchUrl)}" class="pf-c-form-control"> <input type="text" value="${ifDefined(this.application?.launchUrl)}" class="pf-c-form-control">
<p class="pf-c-form__helper-text">${gettext("If left empty, authentik will try to extract the launch URL based on the selected provider.")}</p> <p class="pf-c-form__helper-text">${t`If left empty, authentik will try to extract the launch URL based on the selected provider.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Icon")} label=${t`Icon`}
name="metaIcon"> name="metaIcon">
<input type="file" value="${ifDefined(this.application?.metaIcon)}" class="pf-c-form-control"> <input type="file" value="${ifDefined(this.application?.metaIcon)}" class="pf-c-form-control">
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Description")} label=${t`Description`}
name="metaDescription"> name="metaDescription">
<textarea class="pf-c-form-control">${ifDefined(this.application?.metaDescription)}</textarea> <textarea class="pf-c-form-control">${ifDefined(this.application?.metaDescription)}</textarea>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Publisher")} label=${t`Publisher`}
name="metaPublisher"> name="metaPublisher">
<input type="text" value="${ifDefined(this.application?.metaPublisher)}" class="pf-c-form-control"> <input type="text" value="${ifDefined(this.application?.metaPublisher)}" class="pf-c-form-control">
</ak-form-element-horizontal> </ak-form-element-horizontal>

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { css, CSSResult, customElement, html, property, TemplateResult } from "lit-element"; import { css, CSSResult, customElement, html, property, TemplateResult } from "lit-element";
import PFAvatar from "@patternfly/patternfly/components/Avatar/avatar.css"; import PFAvatar from "@patternfly/patternfly/components/Avatar/avatar.css";
import { AKResponse } from "../../api/Client"; import { AKResponse } from "../../api/Client";
@ -19,10 +19,10 @@ export class ApplicationListPage extends TablePage<Application> {
return true; return true;
} }
pageTitle(): string { pageTitle(): string {
return gettext("Applications"); return t`Applications`;
} }
pageDescription(): string { pageDescription(): string {
return gettext("External Applications which use authentik as Identity-Provider, utilizing protocols like OAuth2 and SAML."); return t`External Applications which use authentik as Identity-Provider, utilizing protocols like OAuth2 and SAML.`;
} }
pageIcon(): string { pageIcon(): string {
return "pf-icon pf-icon-applications"; return "pf-icon pf-icon-applications";
@ -54,8 +54,8 @@ export class ApplicationListPage extends TablePage<Application> {
columns(): TableColumn[] { columns(): TableColumn[] {
return [ return [
new TableColumn(""), new TableColumn(""),
new TableColumn("Name", "name"), new TableColumn(t`Name`, t`name`),
new TableColumn("Slug", "slug"), new TableColumn(t`Slug`, t`slug`),
new TableColumn("Provider"), new TableColumn("Provider"),
new TableColumn("Provider Type"), new TableColumn("Provider Type"),
new TableColumn(""), new TableColumn(""),
@ -65,7 +65,7 @@ export class ApplicationListPage extends TablePage<Application> {
row(item: Application): TemplateResult[] { row(item: Application): TemplateResult[] {
return [ return [
item.metaIcon ? item.metaIcon ?
html`<img class="app-icon pf-c-avatar" src="${item.metaIcon}" alt="${gettext("Application Icon")}">` : html`<img class="app-icon pf-c-avatar" src="${item.metaIcon}" alt="${t`Application Icon`}">` :
html`<i class="fas fas fa-share-square"></i>`, html`<i class="fas fas fa-share-square"></i>`,
html`<a href="#/core/applications/${item.slug}"> html`<a href="#/core/applications/${item.slug}">
<div> <div>
@ -79,27 +79,27 @@ export class ApplicationListPage extends TablePage<Application> {
html` html`
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> <span slot="submit">
${gettext("Update")} ${t`Update`}
</span> </span>
<span slot="header"> <span slot="header">
${gettext("Update Application")} ${t`Update Application`}
</span> </span>
<ak-application-form slot="form" .application=${item}> <ak-application-form slot="form" .application=${item}>
</ak-application-form> </ak-application-form>
<button slot="trigger" class="pf-c-button pf-m-secondary"> <button slot="trigger" class="pf-c-button pf-m-secondary">
${gettext("Edit")} ${t`Edit`}
</button> </button>
</ak-forms-modal> </ak-forms-modal>
<ak-forms-delete <ak-forms-delete
.obj=${item} .obj=${item}
objectLabel=${gettext("Application")} objectLabel=${t`Application`}
.delete=${() => { .delete=${() => {
return new CoreApi(DEFAULT_CONFIG).coreApplicationsDelete({ return new CoreApi(DEFAULT_CONFIG).coreApplicationsDelete({
slug: item.slug || "" slug: item.slug || ""
}); });
}}> }}>
<button slot="trigger" class="pf-c-button pf-m-danger"> <button slot="trigger" class="pf-c-button pf-m-danger">
${gettext("Delete")} ${t`Delete`}
</button> </button>
</ak-forms-delete>`, </ak-forms-delete>`,
]; ];
@ -109,15 +109,15 @@ export class ApplicationListPage extends TablePage<Application> {
return html` return html`
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> <span slot="submit">
${gettext("Create")} ${t`Create`}
</span> </span>
<span slot="header"> <span slot="header">
${gettext("Create Application")} ${t`Create Application`}
</span> </span>
<ak-application-form slot="form"> <ak-application-form slot="form">
</ak-application-form> </ak-application-form>
<button slot="trigger" class="pf-c-button pf-m-primary"> <button slot="trigger" class="pf-c-button pf-m-primary">
${gettext("Create")} ${t`Create`}
</button> </button>
</ak-forms-modal> </ak-forms-modal>
${super.renderToolbar()} ${super.renderToolbar()}

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { css, CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element"; import { css, CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element";
import "../../elements/Tabs"; import "../../elements/Tabs";
@ -49,13 +49,13 @@ export class ApplicationViewPage extends LitElement {
return html`<section class="pf-c-page__main-section pf-m-light"> return html`<section class="pf-c-page__main-section pf-m-light">
<div class="pf-c-content"> <div class="pf-c-content">
<h1> <h1>
${gettext("Loading...")} ${t`Loading...`}
</h1> </h1>
</div> </div>
</section> </section>
<ak-empty-state <ak-empty-state
?loading="${true}" ?loading="${true}"
header=${gettext("Loading")}> header=${t`Loading`}>
</ak-empty-state>`; </ak-empty-state>`;
} }
return html`<section class="pf-c-page__main-section pf-m-light"> return html`<section class="pf-c-page__main-section pf-m-light">
@ -68,10 +68,10 @@ export class ApplicationViewPage extends LitElement {
</div> </div>
</section> </section>
<ak-tabs> <ak-tabs>
<section slot="page-1" data-tab-title="${gettext("Overview")}" class="pf-c-page__main-section pf-m-no-padding-mobile"> <section slot="page-1" data-tab-title="${t`Overview`}" class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-l-gallery pf-m-gutter"> <div class="pf-l-gallery pf-m-gutter">
<div class="pf-c-card pf-l-gallery__item" style="grid-column-end: span 3;grid-row-end: span 2;"> <div class="pf-c-card pf-l-gallery__item" style="grid-column-end: span 3;grid-row-end: span 2;">
<div class="pf-c-card__title">${gettext("Logins over the last 24 hours")}</div> <div class="pf-c-card__title">${t`Logins over the last 24 hours`}</div>
<div class="pf-c-card__body"> <div class="pf-c-card__body">
${this.application && html` ${this.application && html`
<ak-charts-application-authorize applicationSlug=${this.application.slug}> <ak-charts-application-authorize applicationSlug=${this.application.slug}>
@ -79,13 +79,13 @@ export class ApplicationViewPage extends LitElement {
</div> </div>
</div> </div>
<div class="pf-c-card pf-l-gallery__item"> <div class="pf-c-card pf-l-gallery__item">
<div class="pf-c-card__title">${gettext("Related")}</div> <div class="pf-c-card__title">${t`Related`}</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">
${this.application.provider ? ${this.application.provider ?
html`<div class="pf-c-description-list__group"> html`<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${gettext("Provider")}</span> <span class="pf-c-description-list__text">${t`Provider`}</span>
</dt> </dt>
<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">
@ -100,7 +100,7 @@ export class ApplicationViewPage extends LitElement {
</div> </div>
</div> </div>
<div class="pf-c-card pf-l-gallery__item" style="grid-column-end: span 3;grid-row-end: span 2;"> <div class="pf-c-card pf-l-gallery__item" style="grid-column-end: span 3;grid-row-end: span 2;">
<div class="pf-c-card__title">${gettext("Changelog")}</div> <div class="pf-c-card__title">${t`Changelog`}</div>
<div class="pf-c-card__body"> <div class="pf-c-card__body">
<ak-object-changelog <ak-object-changelog
targetModelPk=${this.application.pk || ""} targetModelPk=${this.application.pk || ""}
@ -111,9 +111,9 @@ export class ApplicationViewPage extends LitElement {
</div> </div>
</div> </div>
</section> </section>
<div slot="page-2" data-tab-title="${gettext("Policy Bindings")}" class="pf-c-page__main-section pf-m-no-padding-mobile"> <div slot="page-2" data-tab-title="${t`Policy Bindings`}" class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-c-card"> <div class="pf-c-card">
<div class="pf-c-card__title">${gettext("These policies control which users can access this application.")}</div> <div class="pf-c-card__title">${t`These policies control which users can access this application.`}</div>
<ak-bound-policies-list .target=${this.application.pk}> <ak-bound-policies-list .target=${this.application.pk}>
</ak-bound-policies-list> </ak-bound-policies-list>
</div> </div>

View File

@ -1,6 +1,6 @@
import { CertificateGeneration, CryptoApi } from "authentik-api"; import { CertificateGeneration, CryptoApi } from "authentik-api";
import { CertificateKeyPair } from "authentik-api/src"; import { CertificateKeyPair } from "authentik-api/src";
import { gettext } from "django"; import { t } from "@lingui/macro";
import { customElement } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../api/Config"; import { DEFAULT_CONFIG } from "../../api/Config";
@ -11,7 +11,7 @@ import "../../elements/forms/HorizontalFormElement";
export class CertificateKeyPairForm extends Form<CertificateGeneration> { export class CertificateKeyPairForm extends Form<CertificateGeneration> {
getSuccessMessage(): string { getSuccessMessage(): string {
return gettext("Successfully generated certificate-key pair."); return t`Successfully generated certificate-key pair.`;
} }
send = (data: CertificateGeneration): Promise<CertificateKeyPair> => { send = (data: CertificateGeneration): Promise<CertificateKeyPair> => {
@ -23,19 +23,19 @@ export class CertificateKeyPairForm extends Form<CertificateGeneration> {
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Common Name")} label=${t`Common Name`}
name="commonName" name="commonName"
?required=${true}> ?required=${true}>
<input type="text" class="pf-c-form-control" required> <input type="text" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Subject-alt name")} label=${t`Subject-alt name`}
name="subjectAltName"> name="subjectAltName">
<input class="pf-c-form-control" type="text"> <input class="pf-c-form-control" type="text">
<p class="pf-c-form__helper-text">${gettext("Optional, comma-separated SubjectAlt Names.")}</p> <p class="pf-c-form__helper-text">${t`Optional, comma-separated SubjectAlt Names.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Validity days")} label=${t`Validity days`}
name="validityDays" name="validityDays"
?required=${true}> ?required=${true}>
<input class="pf-c-form-control" type="number" value="365"> <input class="pf-c-form-control" type="number" value="365">

View File

@ -1,5 +1,5 @@
import { CertificateKeyPair, CryptoApi } from "authentik-api"; import { CertificateKeyPair, CryptoApi } from "authentik-api";
import { gettext } from "django"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement, property } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../api/Config"; import { DEFAULT_CONFIG } from "../../api/Config";
@ -17,9 +17,9 @@ export class CertificateKeyPairForm extends Form<CertificateKeyPair> {
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.keyPair) { if (this.keyPair) {
return gettext("Successfully updated certificate-key pair."); return t`Successfully updated certificate-key pair.`;
} else { } else {
return gettext("Successfully created certificate-key pair."); return t`Successfully created certificate-key pair.`;
} }
} }
@ -39,24 +39,24 @@ export class CertificateKeyPairForm extends Form<CertificateKeyPair> {
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Name")} label=${t`Name`}
name="name" name="name"
?required=${true}> ?required=${true}>
<input type="text" value="${ifDefined(this.keyPair?.name)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.keyPair?.name)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
${this.keyPair ? html`<ak-divider>${gettext("Only change the fields below if you want to overwrite their values.")}</ak-divider>` : html``} ${this.keyPair ? html`<ak-divider>${t`Only change the fields below if you want to overwrite their values.`}</ak-divider>` : html``}
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Certificate")} label=${t`Certificate`}
name="certificateData" name="certificateData"
?required=${true}> ?required=${true}>
<textarea class="pf-c-form-control" required>${ifDefined(this.keyPair?.certificateData)}</textarea> <textarea class="pf-c-form-control" required>${ifDefined(this.keyPair?.certificateData)}</textarea>
<p class="pf-c-form__helper-text">${gettext("PEM-encoded Certificate data.")}</p> <p class="pf-c-form__helper-text">${t`PEM-encoded Certificate data.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
name="keyData" name="keyData"
label=${gettext("Private Key")}> label=${t`Private Key`}>
<textarea class="pf-c-form-control" >${ifDefined(this.keyPair?.keyData)}</textarea> <textarea class="pf-c-form-control" >${ifDefined(this.keyPair?.keyData)}</textarea>
<p class="pf-c-form__helper-text">${gettext("Optional Private Key. If this is set, you can use this keypair for encryption.")}</p> <p class="pf-c-form__helper-text">${t`Optional Private Key. If this is set, you can use this keypair for encryption.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</form>`; </form>`;
} }

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { CSSResult, customElement, html, property, TemplateResult } from "lit-element"; import { CSSResult, customElement, html, property, TemplateResult } from "lit-element";
import { AKResponse } from "../../api/Client"; import { AKResponse } from "../../api/Client";
import { TablePage } from "../../elements/table/TablePage"; import { TablePage } from "../../elements/table/TablePage";
@ -23,10 +23,10 @@ export class CertificateKeyPairListPage extends TablePage<CertificateKeyPair> {
return true; return true;
} }
pageTitle(): string { pageTitle(): string {
return gettext("Certificate-Key Pairs"); return t`Certificate-Key Pairs`;
} }
pageDescription(): string { pageDescription(): string {
return gettext("Import certificates of external providers or create certificates to sign requests with."); return t`Import certificates of external providers or create certificates to sign requests with.`;
} }
pageIcon(): string { pageIcon(): string {
return "pf-icon pf-icon-key"; return "pf-icon pf-icon-key";
@ -50,7 +50,7 @@ export class CertificateKeyPairListPage extends TablePage<CertificateKeyPair> {
columns(): TableColumn[] { columns(): TableColumn[] {
return [ return [
new TableColumn("Name", "name"), new TableColumn(t`Name`, t`name`),
new TableColumn("Private key available?"), new TableColumn("Private key available?"),
new TableColumn("Expiry date"), new TableColumn("Expiry date"),
new TableColumn(""), new TableColumn(""),
@ -60,32 +60,32 @@ export class CertificateKeyPairListPage extends TablePage<CertificateKeyPair> {
row(item: CertificateKeyPair): TemplateResult[] { row(item: CertificateKeyPair): TemplateResult[] {
return [ return [
html`${item.name}`, html`${item.name}`,
html`${gettext(item.privateKeyAvailable ? "Yes" : "No")}`, html`${item.privateKeyAvailable ? t`Yes` : t`No`}`,
html`${item.certExpiry?.toLocaleString()}`, html`${item.certExpiry?.toLocaleString()}`,
html` html`
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> <span slot="submit">
${gettext("Update")} ${t`Update`}
</span> </span>
<span slot="header"> <span slot="header">
${gettext("Update Certificate-Key Pair")} ${t`Update Certificate-Key Pair`}
</span> </span>
<ak-crypto-certificate-form slot="form" .keyPair=${item}> <ak-crypto-certificate-form slot="form" .keyPair=${item}>
</ak-crypto-certificate-form> </ak-crypto-certificate-form>
<button slot="trigger" class="pf-c-button pf-m-secondary"> <button slot="trigger" class="pf-c-button pf-m-secondary">
${gettext("Edit")} ${t`Edit`}
</button> </button>
</ak-forms-modal> </ak-forms-modal>
<ak-forms-delete <ak-forms-delete
.obj=${item} .obj=${item}
objectLabel=${gettext("Certificate-Key Pair")} objectLabel=${t`Certificate-Key Pair`}
.delete=${() => { .delete=${() => {
return new CryptoApi(DEFAULT_CONFIG).cryptoCertificatekeypairsDelete({ return new CryptoApi(DEFAULT_CONFIG).cryptoCertificatekeypairsDelete({
kpUuid: item.pk || "" kpUuid: item.pk || ""
}); });
}}> }}>
<button slot="trigger" class="pf-c-button pf-m-danger"> <button slot="trigger" class="pf-c-button pf-m-danger">
${gettext("Delete")} ${t`Delete`}
</button> </button>
</ak-forms-delete>`, </ak-forms-delete>`,
]; ];
@ -98,7 +98,7 @@ export class CertificateKeyPairListPage extends TablePage<CertificateKeyPair> {
<dl class="pf-c-description-list pf-m-horizontal"> <dl class="pf-c-description-list pf-m-horizontal">
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${gettext("Certificate Fingerprint")}</span> <span class="pf-c-description-list__text">${t`Certificate Fingerprint`}</span>
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">${item.fingerprint}</div> <div class="pf-c-description-list__text">${item.fingerprint}</div>
@ -106,7 +106,7 @@ export class CertificateKeyPairListPage extends TablePage<CertificateKeyPair> {
</div> </div>
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${gettext("Certificate Subjet")}</span> <span class="pf-c-description-list__text">${t`Certificate Subjet`}</span>
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">${item.certSubject}</div> <div class="pf-c-description-list__text">${item.certSubject}</div>
@ -123,28 +123,28 @@ export class CertificateKeyPairListPage extends TablePage<CertificateKeyPair> {
return html` return html`
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> <span slot="submit">
${gettext("Create")} ${t`Create`}
</span> </span>
<span slot="header"> <span slot="header">
${gettext("Create Certificate-Key Pair")} ${t`Create Certificate-Key Pair`}
</span> </span>
<ak-crypto-certificate-form slot="form"> <ak-crypto-certificate-form slot="form">
</ak-crypto-certificate-form> </ak-crypto-certificate-form>
<button slot="trigger" class="pf-c-button pf-m-primary"> <button slot="trigger" class="pf-c-button pf-m-primary">
${gettext("Create")} ${t`Create`}
</button> </button>
</ak-forms-modal> </ak-forms-modal>
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> <span slot="submit">
${gettext("Generate")} ${t`Generate`}
</span> </span>
<span slot="header"> <span slot="header">
${gettext("Generate Certificate-Key Pair")} ${t`Generate Certificate-Key Pair`}
</span> </span>
<ak-crypto-certificate-generate-form slot="form"> <ak-crypto-certificate-generate-form slot="form">
</ak-crypto-certificate-generate-form> </ak-crypto-certificate-generate-form>
<button slot="trigger" class="pf-c-button pf-m-secondary"> <button slot="trigger" class="pf-c-button pf-m-secondary">
${gettext("Generate")} ${t`Generate`}
</button> </button>
</ak-forms-modal> </ak-forms-modal>
${super.renderToolbar()} ${super.renderToolbar()}

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { css, CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element"; import { css, CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element";
import { until } from "lit-html/directives/until"; import { until } from "lit-html/directives/until";
import { FlowsApi } from "authentik-api"; import { FlowsApi } from "authentik-api";
@ -43,7 +43,7 @@ export class EventInfo extends LitElement {
return html`<dl class="pf-c-description-list pf-m-horizontal"> return html`<dl class="pf-c-description-list pf-m-horizontal">
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${gettext("UID")}</span> <span class="pf-c-description-list__text">${t`UID`}</span>
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">${context.pk as string}</div> <div class="pf-c-description-list__text">${context.pk as string}</div>
@ -51,7 +51,7 @@ export class EventInfo extends LitElement {
</div> </div>
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${gettext("Name")}</span> <span class="pf-c-description-list__text">${t`Name`}</span>
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">${context.name as string}</div> <div class="pf-c-description-list__text">${context.name as string}</div>
@ -59,7 +59,7 @@ export class EventInfo extends LitElement {
</div> </div>
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${gettext("App")}</span> <span class="pf-c-description-list__text">${t`App`}</span>
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">${context.app as string}</div> <div class="pf-c-description-list__text">${context.app as string}</div>
@ -67,7 +67,7 @@ export class EventInfo extends LitElement {
</div> </div>
<div class="pf-c-description-list__group"> <div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${gettext("Model Name")}</span> <span class="pf-c-description-list__text">${t`Model Name`}</span>
</dt> </dt>
<dd class="pf-c-description-list__description"> <dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">${context.model_name as string}</div> <div class="pf-c-description-list__text">${context.model_name as string}</div>
@ -79,11 +79,11 @@ export class EventInfo extends LitElement {
defaultResponse(): TemplateResult { defaultResponse(): TemplateResult {
return html`<div class="pf-l-flex"> return html`<div class="pf-l-flex">
<div class="pf-l-flex__item"> <div class="pf-l-flex__item">
<h3>${gettext("Context")}</h3> <h3>${t`Context`}</h3>
<code>${JSON.stringify(this.event?.context, null, 4)}</code> <code>${JSON.stringify(this.event?.context, null, 4)}</code>
</div> </div>
<div class="pf-l-flex__item"> <div class="pf-l-flex__item">
<h3>${gettext("User")}</h3> <h3>${t`User`}</h3>
<code>${JSON.stringify(this.event?.user, null, 4)}</code> <code>${JSON.stringify(this.event?.user, null, 4)}</code>
</div> </div>
</div>`; </div>`;
@ -98,17 +98,17 @@ export class EventInfo extends LitElement {
case "model_updated": case "model_updated":
case "model_deleted": case "model_deleted":
return html` return html`
<h3>${gettext("Affected model:")}</h3> <h3>${t`Affected model:`}</h3>
${this.getModelInfo(this.event.context?.model as EventContext)} ${this.getModelInfo(this.event.context?.model as EventContext)}
`; `;
case "authorize_application": case "authorize_application":
return html`<div class="pf-l-flex"> return html`<div class="pf-l-flex">
<div class="pf-l-flex__item"> <div class="pf-l-flex__item">
<h3>${gettext("Authorized application:")}</h3> <h3>${t`Authorized application:`}</h3>
${this.getModelInfo(this.event.context.authorized_application as EventContext)} ${this.getModelInfo(this.event.context.authorized_application as EventContext)}
</div> </div>
<div class="pf-l-flex__item"> <div class="pf-l-flex__item">
<h3>${gettext("Using flow")}</h3> <h3>${t`Using flow`}</h3>
<span>${until(new FlowsApi(DEFAULT_CONFIG).flowsInstancesList({ <span>${until(new FlowsApi(DEFAULT_CONFIG).flowsInstancesList({
flowUuid: this.event.context.flow as string, flowUuid: this.event.context.flow as string,
}).then(resp => { }).then(resp => {
@ -120,20 +120,20 @@ export class EventInfo extends LitElement {
<ak-expand>${this.defaultResponse()}</ak-expand>`; <ak-expand>${this.defaultResponse()}</ak-expand>`;
case "login_failed": case "login_failed":
return html` return html`
<h3>${gettext(`Attempted to log in as ${this.event.context.username}`)}</h3> <h3>${t`Attempted to log in as ${this.event.context.username}`}</h3>
<ak-expand>${this.defaultResponse()}</ak-expand>`; <ak-expand>${this.defaultResponse()}</ak-expand>`;
case "secret_view": case "secret_view":
return html` return html`
<h3>${gettext("Secret:")}</h3> <h3>${t`Secret:`}</h3>
${this.getModelInfo(this.event.context.secret as EventContext)}`; ${this.getModelInfo(this.event.context.secret as EventContext)}`;
case "property_mapping_exception": case "property_mapping_exception":
return html`<div class="pf-l-flex"> return html`<div class="pf-l-flex">
<div class="pf-l-flex__item"> <div class="pf-l-flex__item">
<h3>${gettext("Exception")}</h3> <h3>${t`Exception`}</h3>
<code>${this.event.context.message || this.event.context.error}</code> <code>${this.event.context.message || this.event.context.error}</code>
</div> </div>
<div class="pf-l-flex__item"> <div class="pf-l-flex__item">
<h3>${gettext("Expression")}</h3> <h3>${t`Expression`}</h3>
<code>${this.event.context.expression}</code> <code>${this.event.context.expression}</code>
</div> </div>
</div> </div>
@ -141,18 +141,18 @@ export class EventInfo extends LitElement {
case "policy_exception": case "policy_exception":
return html`<div class="pf-l-flex"> return html`<div class="pf-l-flex">
<div class="pf-l-flex__item"> <div class="pf-l-flex__item">
<h3>${gettext("Binding")}</h3> <h3>${t`Binding`}</h3>
${this.getModelInfo(this.event.context.binding as EventContext)} ${this.getModelInfo(this.event.context.binding as EventContext)}
</div> </div>
<div class="pf-l-flex__item"> <div class="pf-l-flex__item">
<h3>${gettext("Request")}</h3> <h3>${t`Request`}</h3>
<ul class="pf-c-list"> <ul class="pf-c-list">
<li>${gettext("Object")}: ${this.getModelInfo((this.event.context.request as EventContext).obj as EventContext)}</li> <li>${t`Object`}: ${this.getModelInfo((this.event.context.request as EventContext).obj as EventContext)}</li>
<li><span>${gettext("Context")}: <code>${JSON.stringify((this.event.context.request as EventContext).context, null, 4)}</code></span></li> <li><span>${t`Context`}: <code>${JSON.stringify((this.event.context.request as EventContext).context, null, 4)}</code></span></li>
</ul> </ul>
</div> </div>
<div class="pf-l-flex__item"> <div class="pf-l-flex__item">
<h3>${gettext("Exception")}</h3> <h3>${t`Exception`}</h3>
<code>${this.event.context.message || this.event.context.error}</code> <code>${this.event.context.message || this.event.context.error}</code>
</div> </div>
</div> </div>
@ -160,21 +160,21 @@ export class EventInfo extends LitElement {
case "policy_execution": case "policy_execution":
return html`<div class="pf-l-flex"> return html`<div class="pf-l-flex">
<div class="pf-l-flex__item"> <div class="pf-l-flex__item">
<h3>${gettext("Binding")}</h3> <h3>${t`Binding`}</h3>
${this.getModelInfo(this.event.context.binding as EventContext)} ${this.getModelInfo(this.event.context.binding as EventContext)}
</div> </div>
<div class="pf-l-flex__item"> <div class="pf-l-flex__item">
<h3>${gettext("Request")}</h3> <h3>${t`Request`}</h3>
<ul class="pf-c-list"> <ul class="pf-c-list">
<li>${gettext("Object")}: ${this.getModelInfo((this.event.context.request as EventContext).obj as EventContext)}</li> <li>${t`Object`}: ${this.getModelInfo((this.event.context.request as EventContext).obj as EventContext)}</li>
<li><span>${gettext("Context")}: <code>${JSON.stringify((this.event.context.request as EventContext).context, null, 4)}</code></span></li> <li><span>${t`Context`}: <code>${JSON.stringify((this.event.context.request as EventContext).context, null, 4)}</code></span></li>
</ul> </ul>
</div> </div>
<div class="pf-l-flex__item"> <div class="pf-l-flex__item">
<h3>${gettext("Result")}</h3> <h3>${t`Result`}</h3>
<ul class="pf-c-list"> <ul class="pf-c-list">
<li>${gettext("Passing")}: ${(this.event.context.result as EventContext).passing}</li> <li>${t`Passing`}: ${(this.event.context.result as EventContext).passing}</li>
<li>${gettext("Messages")}: <li>${t`Messages`}:
<ul class="pf-c-list"> <ul class="pf-c-list">
${((this.event.context.result as EventContext).messages as string[]).map(msg => { ${((this.event.context.result as EventContext).messages as string[]).map(msg => {
return html`<li>${msg}</li>`; return html`<li>${msg}</li>`;
@ -189,7 +189,7 @@ export class EventInfo extends LitElement {
return html`<h3>${this.event.context.message}</h3> return html`<h3>${this.event.context.message}</h3>
<ak-expand>${this.defaultResponse()}</ak-expand>`; <ak-expand>${this.defaultResponse()}</ak-expand>`;
case "update_available": case "update_available":
return html`<h3>${gettext("New version available!")}</h3> return html`<h3>${t`New version available!`}</h3>
<a target="_blank" href="https://github.com/BeryJu/authentik/releases/tag/version%2F${this.event.context.new_version}">${this.event.context.new_version}</a> <a target="_blank" href="https://github.com/BeryJu/authentik/releases/tag/version%2F${this.event.context.new_version}">${this.event.context.new_version}</a>
`; `;
// Action types which typically don't record any extra context. // Action types which typically don't record any extra context.
@ -198,7 +198,7 @@ export class EventInfo extends LitElement {
if ("using_source" in this.event.context) { if ("using_source" in this.event.context) {
return html`<div class="pf-l-flex"> return html`<div class="pf-l-flex">
<div class="pf-l-flex__item"> <div class="pf-l-flex__item">
<h3>${gettext("Using source")}</h3> <h3>${t`Using source`}</h3>
${this.getModelInfo(this.event.context.using_source as EventContext)} ${this.getModelInfo(this.event.context.using_source as EventContext)}
</div> </div>
</div>`; </div>`;
@ -206,7 +206,7 @@ export class EventInfo extends LitElement {
return this.defaultResponse(); return this.defaultResponse();
case "logout": case "logout":
if (this.event.context === {}) { if (this.event.context === {}) {
return html`<span>${gettext("No additional data available.")}</span>`; return html`<span>${t`No additional data available.`}</span>`;
} }
return this.defaultResponse(); return this.defaultResponse();
default: default:

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { css, CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element"; import { css, CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element";
import { EventsApi } from "authentik-api"; import { EventsApi } from "authentik-api";
import { DEFAULT_CONFIG } from "../../api/Config"; import { DEFAULT_CONFIG } from "../../api/Config";
@ -37,7 +37,7 @@ export class EventInfoPage extends LitElement {
<div class="pf-c-content"> <div class="pf-c-content">
<h1> <h1>
<i class="pf-icon pf-icon-catalog"></i> <i class="pf-icon pf-icon-catalog"></i>
${gettext(`Event ${this.event?.pk || ""}`)} ${t`Event ${this.event?.pk || ""}`}
</h1> </h1>
</div> </div>
</section> </section>

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { customElement, html, property, TemplateResult } from "lit-element"; import { customElement, html, property, TemplateResult } from "lit-element";
import { Event, EventsApi } from "authentik-api"; import { Event, EventsApi } from "authentik-api";
import { AKResponse } from "../../api/Client"; import { AKResponse } from "../../api/Client";
@ -40,10 +40,10 @@ export class EventListPage extends TablePage<Event> {
columns(): TableColumn[] { columns(): TableColumn[] {
return [ return [
new TableColumn("Action", "action"), new TableColumn(t`Action`, t`action`),
new TableColumn("User", "user"), new TableColumn(t`User`, t`user`),
new TableColumn("Creation Date", "created"), new TableColumn(t`Creation Date`, t`created`),
new TableColumn("Client IP", "client_ip"), new TableColumn(t`Client IP`, t`client_ip`),
]; ];
} }
row(item: EventWithContext): TemplateResult[] { row(item: EventWithContext): TemplateResult[] {
@ -52,7 +52,7 @@ export class EventListPage extends TablePage<Event> {
<small>${item.app}</small>`, <small>${item.app}</small>`,
html`<div>${item.user?.username}</div> html`<div>${item.user?.username}</div>
${item.user.on_behalf_of ? html`<small> ${item.user.on_behalf_of ? html`<small>
${gettext(`On behalf of ${item.user.on_behalf_of.username}`)} ${t`On behalf of ${item.user.on_behalf_of.username}`}
</small>` : html``}`, </small>` : html``}`,
html`<span>${item.created?.toLocaleString()}</span>`, html`<span>${item.created?.toLocaleString()}</span>`,
html`<span>${item.clientIp}</span>`, html`<span>${item.clientIp}</span>`,

View File

@ -1,5 +1,5 @@
import { CoreApi, EventsApi, NotificationRule, NotificationRuleSeverityEnum } from "authentik-api"; import { CoreApi, EventsApi, NotificationRule, NotificationRuleSeverityEnum } from "authentik-api";
import { gettext } from "django"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement, property } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../api/Config"; import { DEFAULT_CONFIG } from "../../api/Config";
@ -16,9 +16,9 @@ export class RuleForm extends Form<NotificationRule> {
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.rule) { if (this.rule) {
return gettext("Successfully updated rule."); return t`Successfully updated rule.`;
} else { } else {
return gettext("Successfully created rule."); return t`Successfully created rule.`;
} }
} }
@ -38,13 +38,13 @@ export class RuleForm extends Form<NotificationRule> {
renderSeverity(): TemplateResult { renderSeverity(): TemplateResult {
return html` return html`
<option value=${NotificationRuleSeverityEnum.Alert} ?selected=${this.rule?.severity === NotificationRuleSeverityEnum.Alert}> <option value=${NotificationRuleSeverityEnum.Alert} ?selected=${this.rule?.severity === NotificationRuleSeverityEnum.Alert}>
${gettext("Alert")} ${t`Alert`}
</option> </option>
<option value=${NotificationRuleSeverityEnum.Warning} ?selected=${this.rule?.severity === NotificationRuleSeverityEnum.Warning}> <option value=${NotificationRuleSeverityEnum.Warning} ?selected=${this.rule?.severity === NotificationRuleSeverityEnum.Warning}>
${gettext("Warning")} ${t`Warning`}
</option> </option>
<option value=${NotificationRuleSeverityEnum.Notice} ?selected=${this.rule?.severity === NotificationRuleSeverityEnum.Notice}> <option value=${NotificationRuleSeverityEnum.Notice} ?selected=${this.rule?.severity === NotificationRuleSeverityEnum.Notice}>
${gettext("Notice")} ${t`Notice`}
</option> </option>
`; `;
} }
@ -52,13 +52,13 @@ export class RuleForm extends Form<NotificationRule> {
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Name")} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.rule?.name)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.rule?.name)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Group")} label=${t`Group`}
name="group"> name="group">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value="" ?selected=${this.rule?.group === undefined}>---------</option> <option value="" ?selected=${this.rule?.group === undefined}>---------</option>
@ -70,7 +70,7 @@ export class RuleForm extends Form<NotificationRule> {
</select> </select>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Transports")} label=${t`Transports`}
?required=${true} ?required=${true}
name="transports"> name="transports">
<select name="users" class="pf-c-form-control" multiple> <select name="users" class="pf-c-form-control" multiple>
@ -83,11 +83,11 @@ export class RuleForm extends Form<NotificationRule> {
}); });
}))} }))}
</select> </select>
<p class="pf-c-form__helper-text">${gettext("Select which transports should be used to notify the user. If none are selected, the notification will only be shown in the authentik UI.")}</p> <p class="pf-c-form__helper-text">${t`Select which transports should be used to notify the user. If none are selected, the notification will only be shown in the authentik UI.`}</p>
<p class="pf-c-form__helper-text">${gettext("Hold control/command to select multiple items.")}</p> <p class="pf-c-form__helper-text">${t`Hold control/command to select multiple items.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Severity")} label=${t`Severity`}
?required=${true} ?required=${true}
name="severity"> name="severity">
<select class="pf-c-form-control"> <select class="pf-c-form-control">

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { customElement, html, property, TemplateResult } from "lit-element"; import { customElement, html, property, TemplateResult } from "lit-element";
import { AKResponse } from "../../api/Client"; import { AKResponse } from "../../api/Client";
import { TablePage } from "../../elements/table/TablePage"; import { TablePage } from "../../elements/table/TablePage";
@ -21,10 +21,10 @@ export class RuleListPage extends TablePage<NotificationRule> {
return true; return true;
} }
pageTitle(): string { pageTitle(): string {
return gettext("Notification Rules"); return t`Notification Rules`;
} }
pageDescription(): string { pageDescription(): string {
return gettext("Send notifications whenever a specific Event is created and matched by policies."); return t`Send notifications whenever a specific Event is created and matched by policies.`;
} }
pageIcon(): string { pageIcon(): string {
return "pf-icon pf-icon-attention-bell"; return "pf-icon pf-icon-attention-bell";
@ -44,9 +44,9 @@ export class RuleListPage extends TablePage<NotificationRule> {
columns(): TableColumn[] { columns(): TableColumn[] {
return [ return [
new TableColumn("Name", "name"), new TableColumn(t`Name`, t`name`),
new TableColumn("Severity", "severity"), new TableColumn(t`Severity`, t`severity`),
new TableColumn("Sent to group", "group"), new TableColumn(t`Sent to group`, t`group`),
new TableColumn(""), new TableColumn(""),
]; ];
} }
@ -55,31 +55,31 @@ export class RuleListPage extends TablePage<NotificationRule> {
return [ return [
html`${item.name}`, html`${item.name}`,
html`${item.severity}`, html`${item.severity}`,
html`${item.group?.name || gettext("None (rule disabled)")}`, html`${item.group?.name || t`None (rule disabled)`}`,
html` html`
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> <span slot="submit">
${gettext("Update")} ${t`Update`}
</span> </span>
<span slot="header"> <span slot="header">
${gettext("Update Notification Rule")} ${t`Update Notification Rule`}
</span> </span>
<ak-event-rule-form slot="form" .rule=${item}> <ak-event-rule-form slot="form" .rule=${item}>
</ak-event-rule-form> </ak-event-rule-form>
<button slot="trigger" class="pf-c-button pf-m-primary"> <button slot="trigger" class="pf-c-button pf-m-primary">
${gettext("Edit")} ${t`Edit`}
</button> </button>
</ak-forms-modal> </ak-forms-modal>
<ak-forms-delete <ak-forms-delete
.obj=${item} .obj=${item}
objectLabel=${gettext("Notification rule")} objectLabel=${t`Notification rule`}
.delete=${() => { .delete=${() => {
return new EventsApi(DEFAULT_CONFIG).eventsRulesDelete({ return new EventsApi(DEFAULT_CONFIG).eventsRulesDelete({
pbmUuid: item.pk || "" pbmUuid: item.pk || ""
}); });
}}> }}>
<button slot="trigger" class="pf-c-button pf-m-danger"> <button slot="trigger" class="pf-c-button pf-m-danger">
${gettext("Delete")} ${t`Delete`}
</button> </button>
</ak-forms-delete>`, </ak-forms-delete>`,
]; ];
@ -89,15 +89,15 @@ export class RuleListPage extends TablePage<NotificationRule> {
return html` return html`
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> <span slot="submit">
${gettext("Create")} ${t`Create`}
</span> </span>
<span slot="header"> <span slot="header">
${gettext("Create Notification Rule")} ${t`Create Notification Rule`}
</span> </span>
<ak-event-rule-form slot="form"> <ak-event-rule-form slot="form">
</ak-event-rule-form> </ak-event-rule-form>
<button slot="trigger" class="pf-c-button pf-m-primary"> <button slot="trigger" class="pf-c-button pf-m-primary">
${gettext("Create")} ${t`Create`}
</button> </button>
</ak-forms-modal> </ak-forms-modal>
${super.renderToolbar()} ${super.renderToolbar()}

View File

@ -1,5 +1,5 @@
import { EventsApi, NotificationTransport, NotificationTransportModeEnum } from "authentik-api"; import { EventsApi, NotificationTransport, NotificationTransportModeEnum } from "authentik-api";
import { gettext } from "django"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement, property } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../api/Config"; import { DEFAULT_CONFIG } from "../../api/Config";
@ -18,9 +18,9 @@ export class TransportForm extends Form<NotificationTransport> {
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.transport) { if (this.transport) {
return gettext("Successfully updated transport."); return t`Successfully updated transport.`;
} else { } else {
return gettext("Successfully created transport."); return t`Successfully created transport.`;
} }
} }
@ -40,13 +40,13 @@ export class TransportForm extends Form<NotificationTransport> {
renderTransportModes(): TemplateResult { renderTransportModes(): TemplateResult {
return html` return html`
<option value=${NotificationTransportModeEnum.Email} ?selected=${this.transport?.mode === NotificationTransportModeEnum.Email}> <option value=${NotificationTransportModeEnum.Email} ?selected=${this.transport?.mode === NotificationTransportModeEnum.Email}>
${gettext("Email")} ${t`Email`}
</option> </option>
<option value=${NotificationTransportModeEnum.Webhook} ?selected=${this.transport?.mode === NotificationTransportModeEnum.Webhook}> <option value=${NotificationTransportModeEnum.Webhook} ?selected=${this.transport?.mode === NotificationTransportModeEnum.Webhook}>
${gettext("Webhook (generic)")} ${t`Webhook (generic)`}
</option> </option>
<option value=${NotificationTransportModeEnum.WebhookSlack} ?selected=${this.transport?.mode === NotificationTransportModeEnum.WebhookSlack}> <option value=${NotificationTransportModeEnum.WebhookSlack} ?selected=${this.transport?.mode === NotificationTransportModeEnum.WebhookSlack}>
${gettext("Webhook (Slack/Discord)")} ${t`Webhook (Slack/Discord)`}
</option> </option>
`; `;
} }
@ -68,13 +68,13 @@ export class TransportForm extends Form<NotificationTransport> {
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Name")} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.transport?.name)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.transport?.name)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Mode")} label=${t`Mode`}
?required=${true} ?required=${true}
name="mode"> name="mode">
<select class="pf-c-form-control" @change=${(ev: Event) => { <select class="pf-c-form-control" @change=${(ev: Event) => {
@ -86,7 +86,7 @@ export class TransportForm extends Form<NotificationTransport> {
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
?hidden=${!this.showWebhook} ?hidden=${!this.showWebhook}
label=${gettext("Webhook URL")} label=${t`Webhook URL`}
name="webhookUrl"> name="webhookUrl">
<input type="text" value="${ifDefined(this.transport?.webhookUrl)}" class="pf-c-form-control"> <input type="text" value="${ifDefined(this.transport?.webhookUrl)}" class="pf-c-form-control">
</ak-form-element-horizontal> </ak-form-element-horizontal>
@ -94,10 +94,10 @@ export class TransportForm extends Form<NotificationTransport> {
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${this.transport?.sendOnce || false}> <input type="checkbox" class="pf-c-check__input" ?checked=${this.transport?.sendOnce || false}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${gettext("Send once")} ${t`Send once`}
</label> </label>
</div> </div>
<p class="pf-c-form__helper-text">${gettext("Only send notification once, for example when sending a webhook into a chat channel.")}</p> <p class="pf-c-form__helper-text">${t`Only send notification once, for example when sending a webhook into a chat channel.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</form>`; </form>`;
} }

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { customElement, html, property, TemplateResult } from "lit-element"; import { customElement, html, property, TemplateResult } from "lit-element";
import { AKResponse } from "../../api/Client"; import { AKResponse } from "../../api/Client";
import { TablePage } from "../../elements/table/TablePage"; import { TablePage } from "../../elements/table/TablePage";
@ -19,10 +19,10 @@ export class TransportListPage extends TablePage<NotificationTransport> {
return true; return true;
} }
pageTitle(): string { pageTitle(): string {
return gettext("Notification Transports"); return t`Notification Transports`;
} }
pageDescription(): string { pageDescription(): string {
return gettext("Define how notifications are sent to users, like Email or Webhook."); return t`Define how notifications are sent to users, like Email or Webhook.`;
} }
pageIcon(): string { pageIcon(): string {
return "pf-icon pf-icon-export"; return "pf-icon pf-icon-export";
@ -42,8 +42,8 @@ export class TransportListPage extends TablePage<NotificationTransport> {
columns(): TableColumn[] { columns(): TableColumn[] {
return [ return [
new TableColumn("Name", "name"), new TableColumn(t`Name`, t`name`),
new TableColumn("Mode", "mode"), new TableColumn(t`Mode`, t`mode`),
new TableColumn(""), new TableColumn(""),
]; ];
} }
@ -59,31 +59,31 @@ export class TransportListPage extends TablePage<NotificationTransport> {
uuid: item.pk || "", uuid: item.pk || "",
}); });
}}> }}>
${gettext("Test")} ${t`Test`}
</ak-action-button> </ak-action-button>
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> <span slot="submit">
${gettext("Update")} ${t`Update`}
</span> </span>
<span slot="header"> <span slot="header">
${gettext("Update Notification Transport")} ${t`Update Notification Transport`}
</span> </span>
<ak-event-transport-form slot="form" .transport=${item}> <ak-event-transport-form slot="form" .transport=${item}>
</ak-event-transport-form> </ak-event-transport-form>
<button slot="trigger" class="pf-c-button pf-m-primary"> <button slot="trigger" class="pf-c-button pf-m-primary">
${gettext("Edit")} ${t`Edit`}
</button> </button>
</ak-forms-modal> </ak-forms-modal>
<ak-forms-delete <ak-forms-delete
.obj=${item} .obj=${item}
objectLabel=${gettext("Notifications Transport")} objectLabel=${t`Notifications Transport`}
.delete=${() => { .delete=${() => {
return new EventsApi(DEFAULT_CONFIG).eventsTransportsDelete({ return new EventsApi(DEFAULT_CONFIG).eventsTransportsDelete({
uuid: item.pk || "" uuid: item.pk || ""
}); });
}}> }}>
<button slot="trigger" class="pf-c-button pf-m-danger"> <button slot="trigger" class="pf-c-button pf-m-danger">
${gettext("Delete")} ${t`Delete`}
</button> </button>
</ak-forms-delete>`, </ak-forms-delete>`,
]; ];
@ -93,15 +93,15 @@ export class TransportListPage extends TablePage<NotificationTransport> {
return html` return html`
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> <span slot="submit">
${gettext("Create")} ${t`Create`}
</span> </span>
<span slot="header"> <span slot="header">
${gettext("Create Notification Transport")} ${t`Create Notification Transport`}
</span> </span>
<ak-event-transport-form slot="form"> <ak-event-transport-form slot="form">
</ak-event-transport-form> </ak-event-transport-form>
<button slot="trigger" class="pf-c-button pf-m-primary"> <button slot="trigger" class="pf-c-button pf-m-primary">
${gettext("Create")} ${t`Create`}
</button> </button>
</ak-forms-modal> </ak-forms-modal>
${super.renderToolbar()} ${super.renderToolbar()}

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { customElement, html, property, TemplateResult } from "lit-element"; import { customElement, html, property, TemplateResult } from "lit-element";
import { AKResponse } from "../../api/Client"; import { AKResponse } from "../../api/Client";
import { Table, TableColumn } from "../../elements/table/Table"; import { Table, TableColumn } from "../../elements/table/Table";
@ -50,10 +50,10 @@ export class BoundStagesList extends Table<FlowStageBinding> {
html` html`
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> <span slot="submit">
${gettext("Update")} ${t`Update`}
</span> </span>
<span slot="header"> <span slot="header">
${gettext(`Update ${item.stageObj?.verboseName}`)} ${t`Update ${item.stageObj?.verboseName}`}
</span> </span>
<ak-proxy-form <ak-proxy-form
slot="form" slot="form"
@ -63,32 +63,32 @@ export class BoundStagesList extends Table<FlowStageBinding> {
type=${ifDefined(item.stageObj?.component)}> type=${ifDefined(item.stageObj?.component)}>
</ak-proxy-form> </ak-proxy-form>
<button slot="trigger" class="pf-c-button pf-m-secondary"> <button slot="trigger" class="pf-c-button pf-m-secondary">
${gettext("Edit Stage")} ${t`Edit Stage`}
</button> </button>
</ak-forms-modal> </ak-forms-modal>
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> <span slot="submit">
${gettext("Update")} ${t`Update`}
</span> </span>
<span slot="header"> <span slot="header">
${gettext("Update Stage binding")} ${t`Update Stage binding`}
</span> </span>
<ak-stage-binding-form slot="form" .fsb=${item}> <ak-stage-binding-form slot="form" .fsb=${item}>
</ak-stage-binding-form> </ak-stage-binding-form>
<button slot="trigger" class="pf-c-button pf-m-secondary"> <button slot="trigger" class="pf-c-button pf-m-secondary">
${gettext("Edit Binding")} ${t`Edit Binding`}
</button> </button>
</ak-forms-modal> </ak-forms-modal>
<ak-forms-delete <ak-forms-delete
.obj=${item} .obj=${item}
objectLabel=${gettext("Stage binding")} objectLabel=${t`Stage binding`}
.delete=${() => { .delete=${() => {
return new FlowsApi(DEFAULT_CONFIG).flowsBindingsDelete({ return new FlowsApi(DEFAULT_CONFIG).flowsBindingsDelete({
fsbUuid: item.pk || "", fsbUuid: item.pk || "",
}); });
}}> }}>
<button slot="trigger" class="pf-c-button pf-m-danger"> <button slot="trigger" class="pf-c-button pf-m-danger">
${gettext("Delete Binding")} ${t`Delete Binding`}
</button> </button>
</ak-forms-delete>`, </ak-forms-delete>`,
]; ];
@ -100,7 +100,7 @@ export class BoundStagesList extends Table<FlowStageBinding> {
<td role="cell" colspan="3"> <td role="cell" colspan="3">
<div class="pf-c-table__expandable-row-content"> <div class="pf-c-table__expandable-row-content">
<div class="pf-c-content"> <div class="pf-c-content">
<p>${gettext("These policies control when this stage will be applied to the flow.")}</p> <p>${t`These policies control when this stage will be applied to the flow.`}</p>
<ak-bound-policies-list .target=${item.policybindingmodelPtrId}> <ak-bound-policies-list .target=${item.policybindingmodelPtrId}>
</ak-bound-policies-list> </ak-bound-policies-list>
</div> </div>
@ -111,22 +111,22 @@ export class BoundStagesList extends Table<FlowStageBinding> {
} }
renderEmpty(): TemplateResult { renderEmpty(): TemplateResult {
return super.renderEmpty(html`<ak-empty-state header=${gettext("No Stages bound")} icon="pf-icon-module"> return super.renderEmpty(html`<ak-empty-state header=${t`No Stages bound`} icon="pf-icon-module">
<div slot="body"> <div slot="body">
${gettext("No stages are currently bound to this flow.")} ${t`No stages are currently bound to this flow.`}
</div> </div>
<div slot="primary"> <div slot="primary">
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> <span slot="submit">
${gettext("Create")} ${t`Create`}
</span> </span>
<span slot="header"> <span slot="header">
${gettext("Create Stage binding")} ${t`Create Stage binding`}
</span> </span>
<ak-stage-binding-form slot="form" targetPk=${ifDefined(this.target)}> <ak-stage-binding-form slot="form" targetPk=${ifDefined(this.target)}>
</ak-stage-binding-form> </ak-stage-binding-form>
<button slot="trigger" class="pf-c-button pf-m-primary"> <button slot="trigger" class="pf-c-button pf-m-primary">
${gettext("Bind stage")} ${t`Bind stage`}
</button> </button>
</ak-forms-modal> </ak-forms-modal>
</div> </div>
@ -137,7 +137,7 @@ export class BoundStagesList extends Table<FlowStageBinding> {
return html` return html`
<ak-dropdown class="pf-c-dropdown"> <ak-dropdown class="pf-c-dropdown">
<button class="pf-m-primary pf-c-dropdown__toggle" type="button"> <button class="pf-m-primary pf-c-dropdown__toggle" type="button">
<span class="pf-c-dropdown__toggle-text">${gettext("Create Stage")}</span> <span class="pf-c-dropdown__toggle-text">${t`Create Stage`}</span>
<i class="fas fa-caret-down pf-c-dropdown__toggle-icon" aria-hidden="true"></i> <i class="fas fa-caret-down pf-c-dropdown__toggle-icon" aria-hidden="true"></i>
</button> </button>
<ul class="pf-c-dropdown__menu" hidden> <ul class="pf-c-dropdown__menu" hidden>
@ -146,10 +146,10 @@ export class BoundStagesList extends Table<FlowStageBinding> {
return html`<li> return html`<li>
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> <span slot="submit">
${gettext("Create")} ${t`Create`}
</span> </span>
<span slot="header"> <span slot="header">
${gettext(`Create ${type.name}`)} ${t`Create ${type.name}`}
</span> </span>
<ak-proxy-form <ak-proxy-form
slot="form" slot="form"
@ -167,15 +167,15 @@ export class BoundStagesList extends Table<FlowStageBinding> {
</ak-dropdown> </ak-dropdown>
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> <span slot="submit">
${gettext("Create")} ${t`Create`}
</span> </span>
<span slot="header"> <span slot="header">
${gettext("Create Stage binding")} ${t`Create Stage binding`}
</span> </span>
<ak-stage-binding-form slot="form" targetPk=${ifDefined(this.target)}> <ak-stage-binding-form slot="form" targetPk=${ifDefined(this.target)}>
</ak-stage-binding-form> </ak-stage-binding-form>
<button slot="trigger" class="pf-c-button pf-m-secondary"> <button slot="trigger" class="pf-c-button pf-m-secondary">
${gettext("Bind stage")} ${t`Bind stage`}
</button> </button>
</ak-forms-modal> </ak-forms-modal>
${super.renderToolbar()} ${super.renderToolbar()}

View File

@ -1,5 +1,5 @@
import { Flow, FlowDesignationEnum, FlowPolicyEngineModeEnum, FlowsApi } from "authentik-api"; import { Flow, FlowDesignationEnum, FlowPolicyEngineModeEnum, FlowsApi } from "authentik-api";
import { gettext } from "django"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement, property } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../api/Config"; import { DEFAULT_CONFIG } from "../../api/Config";
@ -15,9 +15,9 @@ export class FlowForm extends Form<Flow> {
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.flow) { if (this.flow) {
return gettext("Successfully updated flow."); return t`Successfully updated flow.`;
} else { } else {
return gettext("Successfully created flow."); return t`Successfully created flow.`;
} }
} }
@ -48,25 +48,25 @@ export class FlowForm extends Form<Flow> {
renderDesignations(): TemplateResult { renderDesignations(): TemplateResult {
return html` return html`
<option value=${FlowDesignationEnum.Authentication} ?selected=${this.flow?.designation === FlowDesignationEnum.Authentication}> <option value=${FlowDesignationEnum.Authentication} ?selected=${this.flow?.designation === FlowDesignationEnum.Authentication}>
${gettext("Authentication")} ${t`Authentication`}
</option> </option>
<option value=${FlowDesignationEnum.Authorization} ?selected=${this.flow?.designation === FlowDesignationEnum.Authorization}> <option value=${FlowDesignationEnum.Authorization} ?selected=${this.flow?.designation === FlowDesignationEnum.Authorization}>
${gettext("Authorization")} ${t`Authorization`}
</option> </option>
<option value=${FlowDesignationEnum.Enrollment} ?selected=${this.flow?.designation === FlowDesignationEnum.Enrollment}> <option value=${FlowDesignationEnum.Enrollment} ?selected=${this.flow?.designation === FlowDesignationEnum.Enrollment}>
${gettext("Enrollment")} ${t`Enrollment`}
</option> </option>
<option value=${FlowDesignationEnum.Invalidation} ?selected=${this.flow?.designation === FlowDesignationEnum.Invalidation}> <option value=${FlowDesignationEnum.Invalidation} ?selected=${this.flow?.designation === FlowDesignationEnum.Invalidation}>
${gettext("Invalidation")} ${t`Invalidation`}
</option> </option>
<option value=${FlowDesignationEnum.Recovery} ?selected=${this.flow?.designation === FlowDesignationEnum.Recovery}> <option value=${FlowDesignationEnum.Recovery} ?selected=${this.flow?.designation === FlowDesignationEnum.Recovery}>
${gettext("Recovery")} ${t`Recovery`}
</option> </option>
<option value=${FlowDesignationEnum.StageConfiguration} ?selected=${this.flow?.designation === FlowDesignationEnum.StageConfiguration}> <option value=${FlowDesignationEnum.StageConfiguration} ?selected=${this.flow?.designation === FlowDesignationEnum.StageConfiguration}>
${gettext("Stage Configuration")} ${t`Stage Configuration`}
</option> </option>
<option value=${FlowDesignationEnum.Unenrollment} ?selected=${this.flow?.designation === FlowDesignationEnum.Unenrollment}> <option value=${FlowDesignationEnum.Unenrollment} ?selected=${this.flow?.designation === FlowDesignationEnum.Unenrollment}>
${gettext("Unenrollment")} ${t`Unenrollment`}
</option> </option>
`; `;
} }
@ -74,53 +74,53 @@ export class FlowForm extends Form<Flow> {
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Name")} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.flow?.name)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.flow?.name)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Title")} label=${t`Title`}
?required=${true} ?required=${true}
name="title"> name="title">
<input type="text" value="${ifDefined(this.flow?.title)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.flow?.title)}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${gettext("Shown as the Title in Flow pages.")}</p> <p class="pf-c-form__helper-text">${t`Shown as the Title in Flow pages.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Name")} label=${t`Name`}
?required=${true} ?required=${true}
name="slug"> name="slug">
<input type="text" value="${ifDefined(this.flow?.slug)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.flow?.slug)}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${gettext("Visible in the URL.")}</p> <p class="pf-c-form__helper-text">${t`Visible in the URL.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Policy engine mode")} label=${t`Policy engine mode`}
?required=${true} ?required=${true}
name="policyEngineMode"> name="policyEngineMode">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value=${FlowPolicyEngineModeEnum.Any} ?selected=${this.flow?.policyEngineMode === FlowPolicyEngineModeEnum.Any}> <option value=${FlowPolicyEngineModeEnum.Any} ?selected=${this.flow?.policyEngineMode === FlowPolicyEngineModeEnum.Any}>
${gettext("ANY, any policy must match to grant access.")} ${t`ANY, any policy must match to grant access.`}
</option> </option>
<option value=${FlowPolicyEngineModeEnum.All} ?selected=${this.flow?.policyEngineMode === FlowPolicyEngineModeEnum.All}> <option value=${FlowPolicyEngineModeEnum.All} ?selected=${this.flow?.policyEngineMode === FlowPolicyEngineModeEnum.All}>
${gettext("ALL, all policies must match to grant access.")} ${t`ALL, all policies must match to grant access.`}
</option> </option>
</select> </select>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Designation")} label=${t`Designation`}
?required=${true} ?required=${true}
name="designation"> name="designation">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value="" ?selected=${this.flow?.designation === undefined}>---------</option> <option value="" ?selected=${this.flow?.designation === undefined}>---------</option>
${this.renderDesignations()} ${this.renderDesignations()}
</select> </select>
<p class="pf-c-form__helper-text">${gettext("Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik.")}</p> <p class="pf-c-form__helper-text">${t`Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Background")} label=${t`Background`}
name="background"> name="background">
<input type="file" value="${ifDefined(this.flow?.background)}" class="pf-c-form-control"> <input type="file" value="${ifDefined(this.flow?.background)}" class="pf-c-form-control">
<p class="pf-c-form__helper-text">${gettext("Background shown during execution.")}</p> <p class="pf-c-form__helper-text">${t`Background shown during execution.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</form>`; </form>`;
} }

View File

@ -1,5 +1,5 @@
import { Flow, FlowsApi } from "authentik-api"; import { Flow, FlowsApi } from "authentik-api";
import { gettext } from "django"; import { t } from "@lingui/macro";
import { customElement } from "lit-element"; import { customElement } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../api/Config"; import { DEFAULT_CONFIG } from "../../api/Config";
@ -10,7 +10,7 @@ import "../../elements/forms/HorizontalFormElement";
export class FlowImportForm extends Form<Flow> { export class FlowImportForm extends Form<Flow> {
getSuccessMessage(): string { getSuccessMessage(): string {
return gettext("Successfully imported flow."); return t`Successfully imported flow.`;
} }
// eslint-disable-next-line // eslint-disable-next-line
@ -27,10 +27,10 @@ export class FlowImportForm extends Form<Flow> {
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Flow")} label=${t`Flow`}
name="flow"> name="flow">
<input type="file" value="" class="pf-c-form-control"> <input type="file" value="" class="pf-c-form-control">
<p class="pf-c-form__helper-text">${gettext("Background shown during execution.")}</p> <p class="pf-c-form__helper-text">${t`Background shown during execution.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</form>`; </form>`;
} }

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { customElement, html, property, TemplateResult } from "lit-element"; import { customElement, html, property, TemplateResult } from "lit-element";
import { AKResponse } from "../../api/Client"; import { AKResponse } from "../../api/Client";
import { TablePage } from "../../elements/table/TablePage"; import { TablePage } from "../../elements/table/TablePage";
@ -19,10 +19,10 @@ export class FlowListPage extends TablePage<Flow> {
return true; return true;
} }
pageTitle(): string { pageTitle(): string {
return gettext("Flows"); return t`Flows`;
} }
pageDescription(): string { pageDescription(): string {
return gettext("Flows describe a chain of Stages to authenticate, enroll or recover a user. Stages are chosen based on policies applied to them."); return t`Flows describe a chain of Stages to authenticate, enroll or recover a user. Stages are chosen based on policies applied to them.`;
} }
pageIcon(): string { pageIcon(): string {
return "pf-icon pf-icon-process-automation"; return "pf-icon pf-icon-process-automation";
@ -42,9 +42,9 @@ export class FlowListPage extends TablePage<Flow> {
columns(): TableColumn[] { columns(): TableColumn[] {
return [ return [
new TableColumn("Identifier", "slug"), new TableColumn(t`Identifier`, t`slug`),
new TableColumn("Name", "name"), new TableColumn(t`Name`, t`name`),
new TableColumn("Designation", "designation"), new TableColumn(t`Designation`, t`designation`),
new TableColumn("Stages"), new TableColumn("Stages"),
new TableColumn("Policies"), new TableColumn("Policies"),
new TableColumn(""), new TableColumn(""),
@ -63,27 +63,27 @@ export class FlowListPage extends TablePage<Flow> {
html` html`
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> <span slot="submit">
${gettext("Update")} ${t`Update`}
</span> </span>
<span slot="header"> <span slot="header">
${gettext("Update Flow")} ${t`Update Flow`}
</span> </span>
<ak-flow-form slot="form" .flow=${item}> <ak-flow-form slot="form" .flow=${item}>
</ak-flow-form> </ak-flow-form>
<button slot="trigger" class="pf-c-button pf-m-secondary"> <button slot="trigger" class="pf-c-button pf-m-secondary">
${gettext("Edit")} ${t`Edit`}
</button> </button>
</ak-forms-modal> </ak-forms-modal>
<ak-forms-delete <ak-forms-delete
.obj=${item} .obj=${item}
objectLabel=${gettext("Flow")} objectLabel=${t`Flow`}
.delete=${() => { .delete=${() => {
return new FlowsApi(DEFAULT_CONFIG).flowsInstancesDelete({ return new FlowsApi(DEFAULT_CONFIG).flowsInstancesDelete({
slug: item.slug slug: item.slug
}); });
}}> }}>
<button slot="trigger" class="pf-c-button pf-m-danger"> <button slot="trigger" class="pf-c-button pf-m-danger">
${gettext("Delete")} ${t`Delete`}
</button> </button>
</ak-forms-delete> </ak-forms-delete>
<button <button
@ -95,10 +95,10 @@ export class FlowListPage extends TablePage<Flow> {
window.location.assign(`${link.link}?next=/%23${window.location.href}`); window.location.assign(`${link.link}?next=/%23${window.location.href}`);
}); });
}}> }}>
${gettext("Execute")} ${t`Execute`}
</button> </button>
<a class="pf-c-button pf-m-secondary" href="${`${DEFAULT_CONFIG.basePath}/flows/instances/${item.slug}/export/`}"> <a class="pf-c-button pf-m-secondary" href="${`${DEFAULT_CONFIG.basePath}/flows/instances/${item.slug}/export/`}">
${gettext("Export")} ${t`Export`}
</a>`, </a>`,
]; ];
} }
@ -107,28 +107,28 @@ export class FlowListPage extends TablePage<Flow> {
return html` return html`
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> <span slot="submit">
${gettext("Create")} ${t`Create`}
</span> </span>
<span slot="header"> <span slot="header">
${gettext("Create Flow")} ${t`Create Flow`}
</span> </span>
<ak-flow-form slot="form"> <ak-flow-form slot="form">
</ak-flow-form> </ak-flow-form>
<button slot="trigger" class="pf-c-button pf-m-primary"> <button slot="trigger" class="pf-c-button pf-m-primary">
${gettext("Create")} ${t`Create`}
</button> </button>
</ak-forms-modal> </ak-forms-modal>
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> <span slot="submit">
${gettext("Import")} ${t`Import`}
</span> </span>
<span slot="header"> <span slot="header">
${gettext("Import Flow")} ${t`Import Flow`}
</span> </span>
<ak-flow-import-form slot="form"> <ak-flow-import-form slot="form">
</ak-flow-import-form> </ak-flow-import-form>
<button slot="trigger" class="pf-c-button pf-m-primary"> <button slot="trigger" class="pf-c-button pf-m-primary">
${gettext("Import")} ${t`Import`}
</button> </button>
</ak-forms-modal> </ak-forms-modal>
${super.renderToolbar()} ${super.renderToolbar()}

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { css, CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element"; import { css, CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element";
import "../../elements/Tabs"; import "../../elements/Tabs";
@ -59,7 +59,7 @@ export class FlowViewPage extends LitElement {
</div> </div>
</section> </section>
<ak-tabs> <ak-tabs>
<div slot="page-1" data-tab-title="${gettext("Flow Overview")}" class="pf-c-page__main-section pf-m-no-padding-mobile"> <div slot="page-1" data-tab-title="${t`Flow Overview`}" class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-l-gallery pf-m-gutter"> <div class="pf-l-gallery pf-m-gutter">
<div class="pf-c-card pf-l-gallery__item" style="grid-column-end: span 3;grid-row-end: span 2;"> <div class="pf-c-card pf-l-gallery__item" style="grid-column-end: span 3;grid-row-end: span 2;">
<div class="pf-c-card"> <div class="pf-c-card">
@ -70,12 +70,12 @@ export class FlowViewPage extends LitElement {
</div> </div>
</div> </div>
<div class="pf-c-card pf-l-gallery__item"> <div class="pf-c-card pf-l-gallery__item">
<div class="pf-c-card__title">${gettext("Related")}</div> <div class="pf-c-card__title">${t`Related`}</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">
<dt class="pf-c-description-list__term"> <dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${gettext("Execute flow")}</span> <span class="pf-c-description-list__text">${t`Execute flow`}</span>
</dt> </dt>
<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">
@ -88,7 +88,7 @@ export class FlowViewPage extends LitElement {
window.location.assign(`${link.link}?next=/%23${window.location.href}`); window.location.assign(`${link.link}?next=/%23${window.location.href}`);
}); });
}}> }}>
${gettext("Execute")} ${t`Execute`}
</button> </button>
</div> </div>
</dd> </dd>
@ -98,7 +98,7 @@ export class FlowViewPage extends LitElement {
</div> </div>
</div> </div>
</div> </div>
<div slot="page-2" data-tab-title="${gettext("Stage Bindings")}" class="pf-c-page__main-section pf-m-no-padding-mobile"> <div slot="page-2" data-tab-title="${t`Stage Bindings`}" class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-c-card"> <div class="pf-c-card">
<div class="pf-c-card__body"> <div class="pf-c-card__body">
<ak-bound-stages-list .target=${this.flow.pk}> <ak-bound-stages-list .target=${this.flow.pk}>
@ -106,16 +106,16 @@ export class FlowViewPage extends LitElement {
</div> </div>
</div> </div>
</div> </div>
<div slot="page-3" data-tab-title="${gettext("Policy Bindings")}" class="pf-c-page__main-section pf-m-no-padding-mobile"> <div slot="page-3" data-tab-title="${t`Policy Bindings`}" class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-c-card"> <div class="pf-c-card">
<div class="pf-c-card__title">${gettext("These policies control which users can access this flow.")}</div> <div class="pf-c-card__title">${t`These policies control which users can access this flow.`}</div>
<div class="pf-c-card__body"> <div class="pf-c-card__body">
<ak-bound-policies-list .target=${this.flow.policybindingmodelPtrId}> <ak-bound-policies-list .target=${this.flow.policybindingmodelPtrId}>
</ak-bound-policies-list> </ak-bound-policies-list>
</div> </div>
</div> </div>
</div> </div>
<div slot="page-4" data-tab-title="${gettext("Changelog")}" class="pf-c-page__main-section pf-m-no-padding-mobile"> <div slot="page-4" data-tab-title="${t`Changelog`}" class="pf-c-page__main-section pf-m-no-padding-mobile">
<div class="pf-c-card"> <div class="pf-c-card">
<div class="pf-c-card__body"> <div class="pf-c-card__body">
<ak-object-changelog <ak-object-changelog

View File

@ -1,5 +1,5 @@
import { FlowsApi, FlowStageBinding, FlowStageBindingPolicyEngineModeEnum, Stage, StagesApi } from "authentik-api"; import { FlowsApi, FlowStageBinding, FlowStageBindingPolicyEngineModeEnum, Stage, StagesApi } from "authentik-api";
import { gettext } from "django"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement, property } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../api/Config"; import { DEFAULT_CONFIG } from "../../api/Config";
@ -20,9 +20,9 @@ export class StageBindingForm extends Form<FlowStageBinding> {
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.fsb) { if (this.fsb) {
return gettext("Successfully updated binding."); return t`Successfully updated binding.`;
} else { } else {
return gettext("Successfully created binding."); return t`Successfully created binding.`;
} }
} }
@ -71,7 +71,7 @@ export class StageBindingForm extends Form<FlowStageBinding> {
`; `;
} }
return html`<ak-form-element-horizontal return html`<ak-form-element-horizontal
label=${gettext("Target")} label=${t`Target`}
?required=${true} ?required=${true}
name="target"> name="target">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
@ -91,7 +91,7 @@ export class StageBindingForm extends Form<FlowStageBinding> {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
${this.renderTarget()} ${this.renderTarget()}
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Stage")} label=${t`Stage`}
?required=${true} ?required=${true}
name="stage"> name="stage">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
@ -106,36 +106,36 @@ export class StageBindingForm extends Form<FlowStageBinding> {
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${this.fsb?.evaluateOnPlan || true}> <input type="checkbox" class="pf-c-check__input" ?checked=${this.fsb?.evaluateOnPlan || true}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${gettext("Evaluate on plan")} ${t`Evaluate on plan`}
</label> </label>
</div> </div>
<p class="pf-c-form__helper-text">${gettext("Evaluate policies during the Flow planning process. Disable this for input-based policies.")}</p> <p class="pf-c-form__helper-text">${t`Evaluate policies during the Flow planning process. Disable this for input-based policies.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal name="reEvaluatePolicies"> <ak-form-element-horizontal name="reEvaluatePolicies">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${this.fsb?.reEvaluatePolicies || false}> <input type="checkbox" class="pf-c-check__input" ?checked=${this.fsb?.reEvaluatePolicies || false}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${gettext("Re-evaluate policies")} ${t`Re-evaluate policies`}
</label> </label>
</div> </div>
<p class="pf-c-form__helper-text">${gettext("Evaluate policies when the Stage is present to the user.")}</p> <p class="pf-c-form__helper-text">${t`Evaluate policies when the Stage is present to the user.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Order")} label=${t`Order`}
?required=${true} ?required=${true}
name="order"> name="order">
<input type="number" value="${until(this.getOrder(), this.fsb?.order)}" class="pf-c-form-control" required> <input type="number" value="${until(this.getOrder(), this.fsb?.order)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Policy engine mode")} label=${t`Policy engine mode`}
?required=${true} ?required=${true}
name="policyEngineMode"> name="policyEngineMode">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value=${FlowStageBindingPolicyEngineModeEnum.Any} ?selected=${this.fsb?.policyEngineMode === FlowStageBindingPolicyEngineModeEnum.Any}> <option value=${FlowStageBindingPolicyEngineModeEnum.Any} ?selected=${this.fsb?.policyEngineMode === FlowStageBindingPolicyEngineModeEnum.Any}>
${gettext("ANY, any policy must match to grant access.")} ${t`ANY, any policy must match to grant access.`}
</option> </option>
<option value=${FlowStageBindingPolicyEngineModeEnum.All} ?selected=${this.fsb?.policyEngineMode === FlowStageBindingPolicyEngineModeEnum.All}> <option value=${FlowStageBindingPolicyEngineModeEnum.All} ?selected=${this.fsb?.policyEngineMode === FlowStageBindingPolicyEngineModeEnum.All}>
${gettext("ALL, all policies must match to grant access.")} ${t`ALL, all policies must match to grant access.`}
</option> </option>
</select> </select>
</ak-form-element-horizontal> </ak-form-element-horizontal>

View File

@ -1,5 +1,5 @@
import { CoreApi, Group } from "authentik-api"; import { CoreApi, Group } from "authentik-api";
import { gettext } from "django"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement, property } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../api/Config"; import { DEFAULT_CONFIG } from "../../api/Config";
@ -18,9 +18,9 @@ export class GroupForm extends Form<Group> {
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.group) { if (this.group) {
return gettext("Successfully updated group."); return t`Successfully updated group.`;
} else { } else {
return gettext("Successfully created group."); return t`Successfully created group.`;
} }
} }
@ -40,7 +40,7 @@ export class GroupForm extends Form<Group> {
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Name")} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.group?.name)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.group?.name)}" class="pf-c-form-control" required>
@ -49,13 +49,13 @@ export class GroupForm extends Form<Group> {
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${this.group?.isSuperuser || false}> <input type="checkbox" class="pf-c-check__input" ?checked=${this.group?.isSuperuser || false}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${gettext("Is superuser")} ${t`Is superuser`}
</label> </label>
</div> </div>
<p class="pf-c-form__helper-text">${gettext("Users added to this group will be superusers.")}</p> <p class="pf-c-form__helper-text">${t`Users added to this group will be superusers.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Parent")} label=${t`Parent`}
?required=${true} ?required=${true}
name="parent"> name="parent">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
@ -68,7 +68,7 @@ export class GroupForm extends Form<Group> {
</select> </select>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Members")} label=${t`Members`}
?required=${true} ?required=${true}
name="users"> name="users">
<select class="pf-c-form-control" multiple> <select class="pf-c-form-control" multiple>
@ -83,10 +83,10 @@ export class GroupForm extends Form<Group> {
}); });
}))} }))}
</select> </select>
<p class="pf-c-form__helper-text">${gettext("Hold control/command to select multiple items.")}</p> <p class="pf-c-form__helper-text">${t`Hold control/command to select multiple items.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Attributes")} label=${t`Attributes`}
name="attributes"> name="attributes">
<ak-codemirror mode="yaml" value="${YAML.stringify(this.group?.attributes)}"> <ak-codemirror mode="yaml" value="${YAML.stringify(this.group?.attributes)}">
</ak-codemirror> </ak-codemirror>

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { customElement, html, property, TemplateResult } from "lit-element"; import { customElement, html, property, TemplateResult } from "lit-element";
import { AKResponse } from "../../api/Client"; import { AKResponse } from "../../api/Client";
import { TablePage } from "../../elements/table/TablePage"; import { TablePage } from "../../elements/table/TablePage";
@ -18,10 +18,10 @@ export class GroupListPage extends TablePage<Group> {
return true; return true;
} }
pageTitle(): string { pageTitle(): string {
return gettext("Groups"); return t`Groups`;
} }
pageDescription(): string { pageDescription(): string {
return gettext("Group users together and give them permissions based on the membership."); return t`Group users together and give them permissions based on the membership.`;
} }
pageIcon(): string { pageIcon(): string {
return "pf-icon pf-icon-users"; return "pf-icon pf-icon-users";
@ -41,8 +41,8 @@ export class GroupListPage extends TablePage<Group> {
columns(): TableColumn[] { columns(): TableColumn[] {
return [ return [
new TableColumn("Name", "name"), new TableColumn(t`Name`, t`name`),
new TableColumn("Parent", "parent"), new TableColumn(t`Parent`, t`parent`),
new TableColumn("Members"), new TableColumn("Members"),
new TableColumn("Superuser privileges?"), new TableColumn("Superuser privileges?"),
new TableColumn(""), new TableColumn(""),
@ -54,31 +54,31 @@ export class GroupListPage extends TablePage<Group> {
html`${item.name}`, html`${item.name}`,
html`${item.parent || "-"}`, html`${item.parent || "-"}`,
html`${item.users?.keys.length}`, html`${item.users?.keys.length}`,
html`${item.isSuperuser ? "Yes" : "No"}`, html`${item.isSuperuser ? t`Yes` : t`No`}`,
html` html`
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> <span slot="submit">
${gettext("Update")} ${t`Update`}
</span> </span>
<span slot="header"> <span slot="header">
${gettext("Update Group")} ${t`Update Group`}
</span> </span>
<ak-group-form slot="form" .group=${item}> <ak-group-form slot="form" .group=${item}>
</ak-group-form> </ak-group-form>
<button slot="trigger" class="pf-c-button pf-m-secondary"> <button slot="trigger" class="pf-c-button pf-m-secondary">
${gettext("Edit")} ${t`Edit`}
</button> </button>
</ak-forms-modal> </ak-forms-modal>
<ak-forms-delete <ak-forms-delete
.obj=${item} .obj=${item}
objectLabel=${gettext("Group")} objectLabel=${t`Group`}
.delete=${() => { .delete=${() => {
return new CoreApi(DEFAULT_CONFIG).coreGroupsDelete({ return new CoreApi(DEFAULT_CONFIG).coreGroupsDelete({
groupUuid: item.pk || "" groupUuid: item.pk || ""
}); });
}}> }}>
<button slot="trigger" class="pf-c-button pf-m-danger"> <button slot="trigger" class="pf-c-button pf-m-danger">
${gettext("Delete")} ${t`Delete`}
</button> </button>
</ak-forms-delete>`, </ak-forms-delete>`,
]; ];
@ -88,15 +88,15 @@ export class GroupListPage extends TablePage<Group> {
return html` return html`
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> <span slot="submit">
${gettext("Create")} ${t`Create`}
</span> </span>
<span slot="header"> <span slot="header">
${gettext("Create Group")} ${t`Create Group`}
</span> </span>
<ak-group-form slot="form"> <ak-group-form slot="form">
</ak-group-form> </ak-group-form>
<button slot="trigger" class="pf-c-button pf-m-primary"> <button slot="trigger" class="pf-c-button pf-m-primary">
${gettext("Create")} ${t`Create`}
</button> </button>
</ak-forms-modal> </ak-forms-modal>
${super.renderToolbar()} ${super.renderToolbar()}

View File

@ -1,5 +1,5 @@
import { Outpost, OutpostsApi, ProvidersApi } from "authentik-api"; import { Outpost, OutpostsApi, ProvidersApi } from "authentik-api";
import { gettext } from "django"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement, property } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../api/Config"; import { DEFAULT_CONFIG } from "../../api/Config";
@ -18,9 +18,9 @@ export class OutpostForm extends Form<Outpost> {
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.outpost) { if (this.outpost) {
return gettext("Successfully updated outpost."); return t`Successfully updated outpost.`;
} else { } else {
return gettext("Successfully created outpost."); return t`Successfully created outpost.`;
} }
} }
@ -40,21 +40,21 @@ export class OutpostForm extends Form<Outpost> {
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Name")} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.outpost?.name)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.outpost?.name)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Type")} label=${t`Type`}
?required=${true} ?required=${true}
name="type"> name="type">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value="proxy" ?selected=${true}>${gettext("Proxy")}</option>s <option value="proxy" ?selected=${true}>${t`Proxy`}</option>s
</select> </select>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Service connection")} label=${t`Service connection`}
name="serviceConnection"> name="serviceConnection">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value="" ?selected=${this.outpost?.serviceConnection === undefined}>---------</option> <option value="" ?selected=${this.outpost?.serviceConnection === undefined}>---------</option>
@ -66,13 +66,13 @@ export class OutpostForm extends Form<Outpost> {
}); });
}), html``)} }), html``)}
</select> </select>
<p class="pf-c-form__helper-text">${gettext("Selecting a service-connection enables the management of the outpost by authentik.")}</p> <p class="pf-c-form__helper-text">${t`Selecting a service-connection enables the management of the outpost by authentik.`}</p>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
See <a _target="blank" href="https://goauthentik.io/docs/outposts/outposts">documentation</a>. See <a target="_blank" href="https://goauthentik.io/docs/outposts/outposts">documentation</a>.
</p> </p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Providers")} label=${t`Providers`}
?required=${true} ?required=${true}
name="providers"> name="providers">
<select class="pf-c-form-control" multiple> <select class="pf-c-form-control" multiple>
@ -87,7 +87,7 @@ export class OutpostForm extends Form<Outpost> {
}); });
}))} }))}
</select> </select>
<p class="pf-c-form__helper-text">${gettext("Hold control/command to select multiple items.")}</p> <p class="pf-c-form__helper-text">${t`Hold control/command to select multiple items.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
${until(new OutpostsApi(DEFAULT_CONFIG).outpostsOutpostsDefaultSettings({}).then(config => { ${until(new OutpostsApi(DEFAULT_CONFIG).outpostsOutpostsDefaultSettings({}).then(config => {
let fc = config.config; let fc = config.config;
@ -95,7 +95,7 @@ export class OutpostForm extends Form<Outpost> {
fc = this.outpost.config; fc = this.outpost.config;
} }
return html`<ak-form-element-horizontal return html`<ak-form-element-horizontal
label=${gettext("Configuration")} label=${t`Configuration`}
name="config"> name="config">
<ak-codemirror mode="yaml" value="${YAML.stringify(fc)}"></ak-codemirror> <ak-codemirror mode="yaml" value="${YAML.stringify(fc)}"></ak-codemirror>
</ak-form-element-horizontal>`; </ak-form-element-horizontal>`;

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element"; import { CSSResult, customElement, html, LitElement, property, TemplateResult } from "lit-element";
import { until } from "lit-html/directives/until"; import { until } from "lit-html/directives/until";
import { OutpostsApi } from "authentik-api"; import { OutpostsApi } from "authentik-api";
@ -28,7 +28,7 @@ export class OutpostHealth extends LitElement {
return html`<li> return html`<li>
<ul> <ul>
<li role="cell"> <li role="cell">
<i class="fas fa-question-circle"></i>${gettext("Not available")} <i class="fas fa-question-circle"></i>${t`Not available`}
</li> </li>
</ul> </ul>
</li>`; </li>`;
@ -37,13 +37,13 @@ export class OutpostHealth extends LitElement {
return html`<li> return html`<li>
<ul> <ul>
<li role="cell"> <li role="cell">
<i class="fas fa-check pf-m-success"></i>${gettext(`Last seen: ${h.lastSeen?.toLocaleTimeString()}`)} <i class="fas fa-check pf-m-success"></i>${t`Last seen: ${h.lastSeen?.toLocaleTimeString()}`}
</li> </li>
<li role="cell"> <li role="cell">
${h.versionOutdated ? ${h.versionOutdated ?
html`<i class="fas fa-times pf-m-danger"></i> html`<i class="fas fa-times pf-m-danger"></i>
${gettext(`${h.version}, should be ${h.versionShould}`)}` : ${t`${h.version}, should be ${h.versionShould}`}` :
html`<i class="fas fa-check pf-m-success"></i>${gettext(`Version: ${h.version || ""}`)}`} html`<i class="fas fa-check pf-m-success"></i>${t`Version: ${h.version || ""}`}`}
</li> </li>
</ul> </ul>
</li>`; </li>`;

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement, property } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { AKResponse } from "../../api/Client"; import { AKResponse } from "../../api/Client";
@ -40,7 +40,7 @@ export class OutpostListPage extends TablePage<Outpost> {
} }
columns(): TableColumn[] { columns(): TableColumn[] {
return [ return [
new TableColumn("Name", "name"), new TableColumn(t`Name`, t`name`),
new TableColumn("Providers"), new TableColumn("Providers"),
new TableColumn("Health and Version"), new TableColumn("Health and Version"),
new TableColumn(""), new TableColumn(""),
@ -60,39 +60,39 @@ export class OutpostListPage extends TablePage<Outpost> {
html` html`
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> <span slot="submit">
${gettext("Update")} ${t`Update`}
</span> </span>
<span slot="header"> <span slot="header">
${gettext("Update Outpost")} ${t`Update Outpost`}
</span> </span>
<ak-outpost-form slot="form" .outpost=${item}> <ak-outpost-form slot="form" .outpost=${item}>
</ak-outpost-form> </ak-outpost-form>
<button slot="trigger" class="pf-c-button pf-m-secondary"> <button slot="trigger" class="pf-c-button pf-m-secondary">
${gettext("Edit")} ${t`Edit`}
</button> </button>
</ak-forms-modal> </ak-forms-modal>
<ak-forms-delete <ak-forms-delete
.obj=${item} .obj=${item}
objectLabel=${gettext("Outpost")} objectLabel=${t`Outpost`}
.delete=${() => { .delete=${() => {
return new OutpostsApi(DEFAULT_CONFIG).outpostsOutpostsDelete({ return new OutpostsApi(DEFAULT_CONFIG).outpostsOutpostsDelete({
uuid: item.pk || "" uuid: item.pk || ""
}); });
}}> }}>
<button slot="trigger" class="pf-c-button pf-m-danger"> <button slot="trigger" class="pf-c-button pf-m-danger">
${gettext("Delete")} ${t`Delete`}
</button> </button>
</ak-forms-delete> </ak-forms-delete>
<ak-modal-button> <ak-modal-button>
<button slot="trigger" class="pf-c-button pf-m-tertiary"> <button slot="trigger" class="pf-c-button pf-m-tertiary">
${gettext("View Deployment Info")} ${t`View Deployment Info`}
</button> </button>
<div slot="modal"> <div slot="modal">
<div class="pf-c-modal-box__header"> <div class="pf-c-modal-box__header">
<h1 class="pf-c-title pf-m-2xl" id="modal-title">${gettext("Outpost Deployment Info")}</h1> <h1 class="pf-c-title pf-m-2xl" id="modal-title">${t`Outpost Deployment Info`}</h1>
</div> </div>
<div class="pf-c-modal-box__body" id="modal-description"> <div class="pf-c-modal-box__body" id="modal-description">
<p><a href="https://goauthentik.io/docs/outposts/outposts/#deploy">${gettext("View deployment documentation")}</a></p> <p><a href="https://goauthentik.io/docs/outposts/outposts/#deploy">${t`View deployment documentation`}</a></p>
<form class="pf-c-form"> <form class="pf-c-form">
<div class="pf-c-form__group"> <div class="pf-c-form__group">
<label class="pf-c-form__label" for="help-text-simple-form-name"> <label class="pf-c-form__label" for="help-text-simple-form-name">
@ -106,11 +106,11 @@ export class OutpostListPage extends TablePage<Outpost> {
</label> </label>
<div> <div>
<ak-token-copy-button identifier="${ifDefined(item.tokenIdentifier)}"> <ak-token-copy-button identifier="${ifDefined(item.tokenIdentifier)}">
${gettext("Click to copy token")} ${t`Click to copy token`}
</ak-token-copy-button> </ak-token-copy-button>
</div> </div>
</div> </div>
<h3>${gettext("If your authentik Instance is using a self-signed certificate, set this value.")}</h3> <h3>${t`If your authentik Instance is using a self-signed certificate, set this value.`}</h3>
<div class="pf-c-form__group"> <div class="pf-c-form__group">
<label class="pf-c-form__label" for="help-text-simple-form-name"> <label class="pf-c-form__label" for="help-text-simple-form-name">
<span class="pf-c-form__label-text">AUTHENTIK_INSECURE</span> <span class="pf-c-form__label-text">AUTHENTIK_INSECURE</span>
@ -120,7 +120,7 @@ export class OutpostListPage extends TablePage<Outpost> {
</form> </form>
</div> </div>
<footer class="pf-c-modal-box__footer pf-m-align-left"> <footer class="pf-c-modal-box__footer pf-m-align-left">
<a class="pf-c-button pf-m-primary">${gettext("Close")}</a> <a class="pf-c-button pf-m-primary">${t`Close`}</a>
</footer> </footer>
</div> </div>
</ak-modal-button>`, </ak-modal-button>`,
@ -131,15 +131,15 @@ export class OutpostListPage extends TablePage<Outpost> {
return html` return html`
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> <span slot="submit">
${gettext("Create")} ${t`Create`}
</span> </span>
<span slot="header"> <span slot="header">
${gettext("Create Outpost")} ${t`Create Outpost`}
</span> </span>
<ak-outpost-form slot="form"> <ak-outpost-form slot="form">
</ak-outpost-form> </ak-outpost-form>
<button slot="trigger" class="pf-c-button pf-m-primary"> <button slot="trigger" class="pf-c-button pf-m-primary">
${gettext("Create")} ${t`Create`}
</button> </button>
</ak-forms-modal> </ak-forms-modal>
${super.renderToolbar()} ${super.renderToolbar()}

View File

@ -1,5 +1,5 @@
import { CryptoApi, DockerServiceConnection, OutpostsApi } from "authentik-api"; import { CryptoApi, DockerServiceConnection, OutpostsApi } from "authentik-api";
import { gettext } from "django"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement, property } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../api/Config"; import { DEFAULT_CONFIG } from "../../api/Config";
@ -24,9 +24,9 @@ export class ServiceConnectionDockerForm extends Form<DockerServiceConnection> {
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.sc) { if (this.sc) {
return gettext("Successfully updated service-connection."); return t`Successfully updated service-connection.`;
} else { } else {
return gettext("Successfully created service-connection."); return t`Successfully created service-connection.`;
} }
} }
@ -46,7 +46,7 @@ export class ServiceConnectionDockerForm extends Form<DockerServiceConnection> {
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Name")} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.sc?.name)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.sc?.name)}" class="pf-c-form-control" required>
@ -55,20 +55,20 @@ export class ServiceConnectionDockerForm extends Form<DockerServiceConnection> {
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${this.sc?.local || false}> <input type="checkbox" class="pf-c-check__input" ?checked=${this.sc?.local || false}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${gettext("Local")} ${t`Local`}
</label> </label>
</div> </div>
<p class="pf-c-form__helper-text">${gettext("If enabled, use the local connection. Required Docker socket/Kubernetes Integration.")}</p> <p class="pf-c-form__helper-text">${t`If enabled, use the local connection. Required Docker socket/Kubernetes Integration.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Docker URL")} label=${t`Docker URL`}
?required=${true} ?required=${true}
name="url"> name="url">
<input type="text" value="${ifDefined(this.sc?.url)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.sc?.url)}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${gettext("Can be in the format of 'unix://' when connecting to a local docker daemon, or 'https://:2376' when connecting to a remote system.")}</p> <p class="pf-c-form__helper-text">${t`Can be in the format of 'unix://' when connecting to a local docker daemon, or 'https://:2376' when connecting to a remote system.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("TLS Verification Certificate")} label=${t`TLS Verification Certificate`}
?required=${true} ?required=${true}
name="tlsVerification"> name="tlsVerification">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
@ -81,10 +81,10 @@ export class ServiceConnectionDockerForm extends Form<DockerServiceConnection> {
}); });
}))} }))}
</select> </select>
<p class="pf-c-form__helper-text">${gettext("CA which the endpoint's Certificate is verified against. Can be left empty for no validation.")}</p> <p class="pf-c-form__helper-text">${t`CA which the endpoint's Certificate is verified against. Can be left empty for no validation.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("TLS Authentication Certificate")} label=${t`TLS Authentication Certificate`}
?required=${true} ?required=${true}
name="tlsAuthentication"> name="tlsAuthentication">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
@ -97,7 +97,7 @@ export class ServiceConnectionDockerForm extends Form<DockerServiceConnection> {
}); });
}))} }))}
</select> </select>
<p class="pf-c-form__helper-text">${gettext("Certificate/Key used for authentication. Can be left empty for no authentication.")}</p> <p class="pf-c-form__helper-text">${t`Certificate/Key used for authentication. Can be left empty for no authentication.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
</form>`; </form>`;
} }

View File

@ -1,5 +1,5 @@
import { KubernetesServiceConnection, OutpostsApi } from "authentik-api"; import { KubernetesServiceConnection, OutpostsApi } from "authentik-api";
import { gettext } from "django"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement, property } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../api/Config"; import { DEFAULT_CONFIG } from "../../api/Config";
@ -25,9 +25,9 @@ export class ServiceConnectionKubernetesForm extends Form<KubernetesServiceConne
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.sc) { if (this.sc) {
return gettext("Successfully updated service-connection."); return t`Successfully updated service-connection.`;
} else { } else {
return gettext("Successfully created service-connection."); return t`Successfully created service-connection.`;
} }
} }
@ -47,7 +47,7 @@ export class ServiceConnectionKubernetesForm extends Form<KubernetesServiceConne
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Name")} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.sc?.name)}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.sc?.name)}" class="pf-c-form-control" required>
@ -56,13 +56,13 @@ export class ServiceConnectionKubernetesForm extends Form<KubernetesServiceConne
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${this.sc?.local || false}> <input type="checkbox" class="pf-c-check__input" ?checked=${this.sc?.local || false}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${gettext("Local")} ${t`Local`}
</label> </label>
</div> </div>
<p class="pf-c-form__helper-text">${gettext("If enabled, use the local connection. Required Docker socket/Kubernetes Integration.")}</p> <p class="pf-c-form__helper-text">${t`If enabled, use the local connection. Required Docker socket/Kubernetes Integration.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Kubeconfig")} label=${t`Kubeconfig`}
name="kubeconfig"> name="kubeconfig">
<ak-codemirror mode="yaml" value="${YAML.stringify(this.sc?.kubeconfig)}"> <ak-codemirror mode="yaml" value="${YAML.stringify(this.sc?.kubeconfig)}">
</ak-codemirror> </ak-codemirror>

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement, property } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { AKResponse } from "../../api/Client"; import { AKResponse } from "../../api/Client";
@ -45,9 +45,9 @@ export class OutpostServiceConnectionListPage extends TablePage<ServiceConnectio
columns(): TableColumn[] { columns(): TableColumn[] {
return [ return [
new TableColumn("Name", "name"), new TableColumn(t`Name`, t`name`),
new TableColumn("Type"), new TableColumn("Type"),
new TableColumn("Local", "local"), new TableColumn(t`Local`, t`local`),
new TableColumn("State"), new TableColumn("State"),
new TableColumn(""), new TableColumn(""),
]; ];
@ -60,7 +60,7 @@ export class OutpostServiceConnectionListPage extends TablePage<ServiceConnectio
return [ return [
html`${item.name}`, html`${item.name}`,
html`${item.verboseName}`, html`${item.verboseName}`,
html`${item.local ? "Yes" : "No"}`, html`${item.local ? t`Yes` : t`No`}`,
html`${until( html`${until(
new OutpostsApi(DEFAULT_CONFIG).outpostsServiceConnectionsAllState({ new OutpostsApi(DEFAULT_CONFIG).outpostsServiceConnectionsAllState({
uuid: item.pk || "" uuid: item.pk || ""
@ -68,15 +68,15 @@ export class OutpostServiceConnectionListPage extends TablePage<ServiceConnectio
if (state.healthy) { if (state.healthy) {
return html`<i class="fas fa-check pf-m-success"></i> ${state.version}`; return html`<i class="fas fa-check pf-m-success"></i> ${state.version}`;
} }
return html`<i class="fas fa-times pf-m-danger"></i> ${gettext("Unhealthy")}`; return html`<i class="fas fa-times pf-m-danger"></i> ${t`Unhealthy`}`;
}), html`<ak-spinner></ak-spinner>`)}`, }), html`<ak-spinner></ak-spinner>`)}`,
html` html`
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> <span slot="submit">
${gettext("Update")} ${t`Update`}
</span> </span>
<span slot="header"> <span slot="header">
${gettext(`Update ${item.verboseName}`)} ${t`Update ${item.verboseName}`}
</span> </span>
<ak-proxy-form <ak-proxy-form
slot="form" slot="form"
@ -86,19 +86,19 @@ export class OutpostServiceConnectionListPage extends TablePage<ServiceConnectio
type=${ifDefined(item.component)}> type=${ifDefined(item.component)}>
</ak-proxy-form> </ak-proxy-form>
<button slot="trigger" class="pf-c-button pf-m-secondary"> <button slot="trigger" class="pf-c-button pf-m-secondary">
${gettext("Edit")} ${t`Edit`}
</button> </button>
</ak-forms-modal> </ak-forms-modal>
<ak-forms-delete <ak-forms-delete
.obj=${item} .obj=${item}
objectLabel=${gettext("Outpost Service-connection")} objectLabel=${t`Outpost Service-connection`}
.delete=${() => { .delete=${() => {
return new OutpostsApi(DEFAULT_CONFIG).outpostsServiceConnectionsAllDelete({ return new OutpostsApi(DEFAULT_CONFIG).outpostsServiceConnectionsAllDelete({
uuid: item.pk || "" uuid: item.pk || ""
}); });
}}> }}>
<button slot="trigger" class="pf-c-button pf-m-danger"> <button slot="trigger" class="pf-c-button pf-m-danger">
${gettext("Delete")} ${t`Delete`}
</button> </button>
</ak-forms-delete>`, </ak-forms-delete>`,
]; ];
@ -108,7 +108,7 @@ export class OutpostServiceConnectionListPage extends TablePage<ServiceConnectio
return html` return html`
<ak-dropdown class="pf-c-dropdown"> <ak-dropdown class="pf-c-dropdown">
<button class="pf-m-primary pf-c-dropdown__toggle" type="button"> <button class="pf-m-primary pf-c-dropdown__toggle" type="button">
<span class="pf-c-dropdown__toggle-text">${gettext("Create")}</span> <span class="pf-c-dropdown__toggle-text">${t`Create`}</span>
<i class="fas fa-caret-down pf-c-dropdown__toggle-icon" aria-hidden="true"></i> <i class="fas fa-caret-down pf-c-dropdown__toggle-icon" aria-hidden="true"></i>
</button> </button>
<ul class="pf-c-dropdown__menu" hidden> <ul class="pf-c-dropdown__menu" hidden>
@ -117,10 +117,10 @@ export class OutpostServiceConnectionListPage extends TablePage<ServiceConnectio
return html`<li> return html`<li>
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> <span slot="submit">
${gettext("Create")} ${t`Create`}
</span> </span>
<span slot="header"> <span slot="header">
${gettext(`Create ${type.name}`)} ${t`Create ${type.name}`}
</span> </span>
<ak-proxy-form <ak-proxy-form
slot="form" slot="form"

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { customElement, html, property, TemplateResult } from "lit-element"; import { customElement, html, property, TemplateResult } from "lit-element";
import { AKResponse } from "../../api/Client"; import { AKResponse } from "../../api/Client";
import { Table, TableColumn } from "../../elements/table/Table"; import { Table, TableColumn } from "../../elements/table/Table";
@ -36,22 +36,22 @@ export class BoundPoliciesList extends Table<PolicyBinding> {
columns(): TableColumn[] { columns(): TableColumn[] {
return [ return [
new TableColumn("Policy / User / Group"), new TableColumn("Policy / User / Group"),
new TableColumn("Enabled", "enabled"), new TableColumn(t`Enabled`, t`enabled`),
new TableColumn("Order", "order"), new TableColumn(t`Order`, t`order`),
new TableColumn("Timeout", "timeout"), new TableColumn(t`Timeout`, t`timeout`),
new TableColumn(""), new TableColumn(""),
]; ];
} }
getPolicyUserGroupRow(item: PolicyBinding): string { getPolicyUserGroupRow(item: PolicyBinding): string {
if (item.policy) { if (item.policy) {
return gettext(`Policy ${item.policyObj?.name}`); return t`Policy ${item.policyObj?.name}`;
} else if (item.group) { } else if (item.group) {
return gettext(`Group ${item.groupObj?.name}`); return t`Group ${item.groupObj?.name}`;
} else if (item.user) { } else if (item.user) {
return gettext(`User ${item.userObj?.name}`); return t`User ${item.userObj?.name}`;
} else { } else {
return gettext(""); return t`-`;
} }
} }
@ -60,10 +60,10 @@ export class BoundPoliciesList extends Table<PolicyBinding> {
return html` return html`
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> <span slot="submit">
${gettext("Update")} ${t`Update`}
</span> </span>
<span slot="header"> <span slot="header">
${gettext(`Update ${item.policyObj?.name}`)} ${t`Update ${item.policyObj?.name}`}
</span> </span>
<ak-proxy-form <ak-proxy-form
slot="form" slot="form"
@ -73,35 +73,35 @@ export class BoundPoliciesList extends Table<PolicyBinding> {
type=${ifDefined(item.policyObj?.component)}> type=${ifDefined(item.policyObj?.component)}>
</ak-proxy-form> </ak-proxy-form>
<button slot="trigger" class="pf-c-button pf-m-secondary"> <button slot="trigger" class="pf-c-button pf-m-secondary">
${gettext("Edit")} ${t`Edit`}
</button> </button>
</ak-forms-modal>`; </ak-forms-modal>`;
} else if (item.group) { } else if (item.group) {
return html`<ak-forms-modal> return html`<ak-forms-modal>
<span slot="submit"> <span slot="submit">
${gettext("Update")} ${t`Update`}
</span> </span>
<span slot="header"> <span slot="header">
${gettext("Update Group")} ${t`Update Group`}
</span> </span>
<ak-group-form slot="form" .group=${item.groupObj}> <ak-group-form slot="form" .group=${item.groupObj}>
</ak-group-form> </ak-group-form>
<button slot="trigger" class="pf-c-button pf-m-primary"> <button slot="trigger" class="pf-c-button pf-m-primary">
${gettext("Edit Group")} ${t`Edit Group`}
</button> </button>
</ak-forms-modal>`; </ak-forms-modal>`;
} else if (item.user) { } else if (item.user) {
return html`<ak-forms-modal> return html`<ak-forms-modal>
<span slot="submit"> <span slot="submit">
${gettext("Update")} ${t`Update`}
</span> </span>
<span slot="header"> <span slot="header">
${gettext("Update User")} ${t`Update User`}
</span> </span>
<ak-user-form slot="form" .user=${item.userObj}> <ak-user-form slot="form" .user=${item.userObj}>
</ak-user-form> </ak-user-form>
<button slot="trigger" class="pf-m-secondary pf-c-button"> <button slot="trigger" class="pf-m-secondary pf-c-button">
${gettext("Edit")} ${t`Edit`}
</button> </button>
</ak-forms-modal>`; </ak-forms-modal>`;
} else { } else {
@ -112,56 +112,56 @@ export class BoundPoliciesList extends Table<PolicyBinding> {
row(item: PolicyBinding): TemplateResult[] { row(item: PolicyBinding): TemplateResult[] {
return [ return [
html`${this.getPolicyUserGroupRow(item)}`, html`${this.getPolicyUserGroupRow(item)}`,
html`${item.enabled ? "Yes" : "No"}`, html`${item.enabled ? t`Yes` : t`No`}`,
html`${item.order}`, html`${item.order}`,
html`${item.timeout}`, html`${item.timeout}`,
html` html`
${this.getObjectEditButton(item)} ${this.getObjectEditButton(item)}
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> <span slot="submit">
${gettext("Update")} ${t`Update`}
</span> </span>
<span slot="header"> <span slot="header">
${gettext("Update Binding")} ${t`Update Binding`}
</span> </span>
<ak-policy-binding-form slot="form" .binding=${item} targetPk=${ifDefined(this.target)}> <ak-policy-binding-form slot="form" .binding=${item} targetPk=${ifDefined(this.target)}>
</ak-policy-binding-form> </ak-policy-binding-form>
<button slot="trigger" class="pf-c-button pf-m-secondary"> <button slot="trigger" class="pf-c-button pf-m-secondary">
${gettext("Edit Binding")} ${t`Edit Binding`}
</button> </button>
</ak-forms-modal> </ak-forms-modal>
<ak-forms-delete <ak-forms-delete
.obj=${item} .obj=${item}
objectLabel=${gettext("Policy binding")} objectLabel=${t`Policy binding`}
.delete=${() => { .delete=${() => {
return new PoliciesApi(DEFAULT_CONFIG).policiesBindingsDelete({ return new PoliciesApi(DEFAULT_CONFIG).policiesBindingsDelete({
policyBindingUuid: item.pk || "", policyBindingUuid: item.pk || "",
}); });
}}> }}>
<button slot="trigger" class="pf-c-button pf-m-danger"> <button slot="trigger" class="pf-c-button pf-m-danger">
${gettext("Delete Binding")} ${t`Delete Binding`}
</button> </button>
</ak-forms-delete>`, </ak-forms-delete>`,
]; ];
} }
renderEmpty(): TemplateResult { renderEmpty(): TemplateResult {
return super.renderEmpty(html`<ak-empty-state header=${gettext("No Policies bound.")} icon="pf-icon-module"> return super.renderEmpty(html`<ak-empty-state header=${t`No Policies bound.`} icon="pf-icon-module">
<div slot="body"> <div slot="body">
${gettext("No policies are currently bound to this object.")} ${t`No policies are currently bound to this object.`}
</div> </div>
<div slot="primary"> <div slot="primary">
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> <span slot="submit">
${gettext("Create")} ${t`Create`}
</span> </span>
<span slot="header"> <span slot="header">
${gettext("Create Binding")} ${t`Create Binding`}
</span> </span>
<ak-policy-binding-form slot="form" targetPk=${ifDefined(this.target)}> <ak-policy-binding-form slot="form" targetPk=${ifDefined(this.target)}>
</ak-policy-binding-form> </ak-policy-binding-form>
<button slot="trigger" class="pf-c-button pf-m-primary"> <button slot="trigger" class="pf-c-button pf-m-primary">
${gettext("Create Binding")} ${t`Create Binding`}
</button> </button>
</ak-forms-modal> </ak-forms-modal>
</div> </div>
@ -172,7 +172,7 @@ export class BoundPoliciesList extends Table<PolicyBinding> {
return html` return html`
<ak-dropdown class="pf-c-dropdown"> <ak-dropdown class="pf-c-dropdown">
<button class="pf-m-primary pf-c-dropdown__toggle" type="button"> <button class="pf-m-primary pf-c-dropdown__toggle" type="button">
<span class="pf-c-dropdown__toggle-text">${gettext("Create Policy")}</span> <span class="pf-c-dropdown__toggle-text">${t`Create Policy`}</span>
<i class="fas fa-caret-down pf-c-dropdown__toggle-icon" aria-hidden="true"></i> <i class="fas fa-caret-down pf-c-dropdown__toggle-icon" aria-hidden="true"></i>
</button> </button>
<ul class="pf-c-dropdown__menu" hidden> <ul class="pf-c-dropdown__menu" hidden>
@ -181,10 +181,10 @@ export class BoundPoliciesList extends Table<PolicyBinding> {
return html`<li> return html`<li>
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> <span slot="submit">
${gettext("Create")} ${t`Create`}
</span> </span>
<span slot="header"> <span slot="header">
${gettext(`Create ${type.name}`)} ${t`Create ${type.name}`}
</span> </span>
<ak-proxy-form <ak-proxy-form
slot="form" slot="form"
@ -202,15 +202,15 @@ export class BoundPoliciesList extends Table<PolicyBinding> {
</ak-dropdown> </ak-dropdown>
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> <span slot="submit">
${gettext("Create")} ${t`Create`}
</span> </span>
<span slot="header"> <span slot="header">
${gettext("Create Binding")} ${t`Create Binding`}
</span> </span>
<ak-policy-binding-form slot="form" targetPk=${ifDefined(this.target)}> <ak-policy-binding-form slot="form" targetPk=${ifDefined(this.target)}>
</ak-policy-binding-form> </ak-policy-binding-form>
<button slot="trigger" class="pf-c-button pf-m-primary"> <button slot="trigger" class="pf-c-button pf-m-primary">
${gettext("Create Binding")} ${t`Create Binding`}
</button> </button>
</ak-forms-modal> </ak-forms-modal>
${super.renderToolbar()} ${super.renderToolbar()}

View File

@ -1,5 +1,5 @@
import { CoreApi, PoliciesApi, Policy, PolicyBinding } from "authentik-api"; import { CoreApi, PoliciesApi, Policy, PolicyBinding } from "authentik-api";
import { gettext } from "django"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement, property } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../api/Config"; import { DEFAULT_CONFIG } from "../../api/Config";
@ -20,9 +20,9 @@ export class PolicyBindingForm extends Form<PolicyBinding> {
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.binding) { if (this.binding) {
return gettext("Successfully updated binding."); return t`Successfully updated binding.`;
} else { } else {
return gettext("Successfully created binding."); return t`Successfully created binding.`;
} }
} }
@ -72,7 +72,7 @@ export class PolicyBindingForm extends Form<PolicyBinding> {
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Policy")} label=${t`Policy`}
name="policy"> name="policy">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value="" ?selected=${this.binding?.policy === undefined}>---------</option> <option value="" ?selected=${this.binding?.policy === undefined}>---------</option>
@ -84,7 +84,7 @@ export class PolicyBindingForm extends Form<PolicyBinding> {
</select> </select>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Group")} label=${t`Group`}
name="group"> name="group">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value="" ?selected=${this.binding?.group === undefined}>---------</option> <option value="" ?selected=${this.binding?.group === undefined}>---------</option>
@ -98,7 +98,7 @@ export class PolicyBindingForm extends Form<PolicyBinding> {
</select> </select>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("User")} label=${t`User`}
name="user"> name="user">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
<option value="" ?selected=${this.binding?.user === undefined}>---------</option> <option value="" ?selected=${this.binding?.user === undefined}>---------</option>
@ -116,18 +116,18 @@ export class PolicyBindingForm extends Form<PolicyBinding> {
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${this.binding?.enabled || true}> <input type="checkbox" class="pf-c-check__input" ?checked=${this.binding?.enabled || true}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${gettext("Enabled")} ${t`Enabled`}
</label> </label>
</div> </div>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Order")} label=${t`Order`}
?required=${true} ?required=${true}
name="order"> name="order">
<input type="number" value="${until(this.getOrder(), this.binding?.order)}" class="pf-c-form-control" required> <input type="number" value="${until(this.getOrder(), this.binding?.order)}" class="pf-c-form-control" required>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Timeout")} label=${t`Timeout`}
?required=${true} ?required=${true}
name="timeout"> name="timeout">
<input type="number" value="${first(this.binding?.timeout, 30)}" class="pf-c-form-control" required> <input type="number" value="${first(this.binding?.timeout, 30)}" class="pf-c-form-control" required>

View File

@ -1,4 +1,4 @@
import { gettext } from "django"; import { t } from "@lingui/macro";
import { customElement, html, property, TemplateResult } from "lit-element"; import { customElement, html, property, TemplateResult } from "lit-element";
import { AKResponse } from "../../api/Client"; import { AKResponse } from "../../api/Client";
import { TablePage } from "../../elements/table/TablePage"; import { TablePage } from "../../elements/table/TablePage";
@ -29,10 +29,10 @@ export class PolicyListPage extends TablePage<Policy> {
return true; return true;
} }
pageTitle(): string { pageTitle(): string {
return gettext("Policies"); return t`Policies`;
} }
pageDescription(): string { pageDescription(): string {
return gettext("Allow users to use Applications based on properties, enforce Password Criteria and selectively apply Stages."); return t`Allow users to use Applications based on properties, enforce Password Criteria and selectively apply Stages.`;
} }
pageIcon(): string { pageIcon(): string {
return "pf-icon pf-icon-infrastructure"; return "pf-icon pf-icon-infrastructure";
@ -52,7 +52,7 @@ export class PolicyListPage extends TablePage<Policy> {
columns(): TableColumn[] { columns(): TableColumn[] {
return [ return [
new TableColumn("Name", "name"), new TableColumn(t`Name`, t`name`),
new TableColumn("Type"), new TableColumn("Type"),
new TableColumn(""), new TableColumn(""),
]; ];
@ -65,19 +65,19 @@ export class PolicyListPage extends TablePage<Policy> {
${(item.boundTo || 0) > 0 ? ${(item.boundTo || 0) > 0 ?
html`<i class="pf-icon pf-icon-ok"></i> html`<i class="pf-icon pf-icon-ok"></i>
<small> <small>
${gettext(`Assigned to ${item.boundTo} objects.`)} ${t`Assigned to ${item.boundTo} objects.`}
</small>`: </small>`:
html`<i class="pf-icon pf-icon-warning-triangle"></i> html`<i class="pf-icon pf-icon-warning-triangle"></i>
<small>${gettext("Warning: Policy is not assigned.")}</small>`} <small>${t`Warning: Policy is not assigned.`}</small>`}
</div>`, </div>`,
html`${item.verboseName}`, html`${item.verboseName}`,
html` html`
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> <span slot="submit">
${gettext("Update")} ${t`Update`}
</span> </span>
<span slot="header"> <span slot="header">
${gettext(`Update ${item.verboseName}`)} ${t`Update ${item.verboseName}`}
</span> </span>
<ak-proxy-form <ak-proxy-form
slot="form" slot="form"
@ -87,32 +87,32 @@ export class PolicyListPage extends TablePage<Policy> {
type=${ifDefined(item.component)}> type=${ifDefined(item.component)}>
</ak-proxy-form> </ak-proxy-form>
<button slot="trigger" class="pf-c-button pf-m-secondary"> <button slot="trigger" class="pf-c-button pf-m-secondary">
${gettext("Edit")} ${t`Edit`}
</button> </button>
</ak-forms-modal> </ak-forms-modal>
<ak-forms-modal .closeAfterSuccessfulSubmit=${false}> <ak-forms-modal .closeAfterSuccessfulSubmit=${false}>
<span slot="submit"> <span slot="submit">
${gettext("Test")} ${t`Test`}
</span> </span>
<span slot="header"> <span slot="header">
${gettext("Test Policy")} ${t`Test Policy`}
</span> </span>
<ak-policy-test-form slot="form" .policy=${item}> <ak-policy-test-form slot="form" .policy=${item}>
</ak-policy-test-form> </ak-policy-test-form>
<button slot="trigger" class="pf-c-button pf-m-secondary"> <button slot="trigger" class="pf-c-button pf-m-secondary">
${gettext("Test")} ${t`Test`}
</button> </button>
</ak-forms-modal> </ak-forms-modal>
<ak-forms-delete <ak-forms-delete
.obj=${item} .obj=${item}
objectLabel=${gettext("Policy")} objectLabel=${t`Policy`}
.delete=${() => { .delete=${() => {
return new PoliciesApi(DEFAULT_CONFIG).policiesAllDelete({ return new PoliciesApi(DEFAULT_CONFIG).policiesAllDelete({
policyUuid: item.pk || "" policyUuid: item.pk || ""
}); });
}}> }}>
<button slot="trigger" class="pf-c-button pf-m-danger"> <button slot="trigger" class="pf-c-button pf-m-danger">
${gettext("Delete")} ${t`Delete`}
</button> </button>
</ak-forms-delete>`, </ak-forms-delete>`,
]; ];
@ -122,7 +122,7 @@ export class PolicyListPage extends TablePage<Policy> {
return html` return html`
<ak-dropdown class="pf-c-dropdown"> <ak-dropdown class="pf-c-dropdown">
<button class="pf-m-primary pf-c-dropdown__toggle" type="button"> <button class="pf-m-primary pf-c-dropdown__toggle" type="button">
<span class="pf-c-dropdown__toggle-text">${gettext("Create")}</span> <span class="pf-c-dropdown__toggle-text">${t`Create`}</span>
<i class="fas fa-caret-down pf-c-dropdown__toggle-icon" aria-hidden="true"></i> <i class="fas fa-caret-down pf-c-dropdown__toggle-icon" aria-hidden="true"></i>
</button> </button>
<ul class="pf-c-dropdown__menu" hidden> <ul class="pf-c-dropdown__menu" hidden>
@ -131,10 +131,10 @@ export class PolicyListPage extends TablePage<Policy> {
return html`<li> return html`<li>
<ak-forms-modal> <ak-forms-modal>
<span slot="submit"> <span slot="submit">
${gettext("Create")} ${t`Create`}
</span> </span>
<span slot="header"> <span slot="header">
${gettext(`Create ${type.name}`)} ${t`Create ${type.name}`}
</span> </span>
<ak-proxy-form <ak-proxy-form
slot="form" slot="form"

View File

@ -1,5 +1,5 @@
import { CoreApi, PoliciesApi, Policy, PolicyTestResult } from "authentik-api"; import { CoreApi, PoliciesApi, Policy, PolicyTestResult } from "authentik-api";
import { gettext } from "django"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement, property } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../api/Config"; import { DEFAULT_CONFIG } from "../../api/Config";
@ -20,7 +20,7 @@ export class PolicyTestForm extends Form<PolicyTest> {
result?: PolicyTestResult; result?: PolicyTestResult;
getSuccessMessage(): string { getSuccessMessage(): string {
return gettext("Successfully sent test-request."); return t`Successfully sent test-request.`;
} }
send = (data: PolicyTest): Promise<PolicyTestResult> => { send = (data: PolicyTest): Promise<PolicyTestResult> => {
@ -33,15 +33,15 @@ export class PolicyTestForm extends Form<PolicyTest> {
renderResult(): TemplateResult { renderResult(): TemplateResult {
return html` return html`
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Passing")}> label=${t`Passing`}>
<div class="pf-c-form__group-label"> <div class="pf-c-form__group-label">
<div class="c-form__horizontal-group"> <div class="c-form__horizontal-group">
<span class="pf-c-form__label-text">${this.result?.passing ? gettext("Yes") : gettext("No")}</span> <span class="pf-c-form__label-text">${this.result?.passing ? t`Yes` : t`No`}</span>
</div> </div>
</div> </div>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Messages")}> label=${t`Messages`}>
<div class="pf-c-form__group-label"> <div class="pf-c-form__group-label">
<div class="c-form__horizontal-group"> <div class="c-form__horizontal-group">
<ul> <ul>
@ -59,7 +59,7 @@ export class PolicyTestForm extends Form<PolicyTest> {
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("User")} label=${t`User`}
?required=${true} ?required=${true}
name="user"> name="user">
<select class="pf-c-form-control"> <select class="pf-c-form-control">
@ -73,7 +73,7 @@ export class PolicyTestForm extends Form<PolicyTest> {
</select> </select>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Context")} label=${t`Context`}
name="context"> name="context">
<ak-codemirror mode="yaml"> <ak-codemirror mode="yaml">
</ak-codemirror> </ak-codemirror>

View File

@ -1,5 +1,5 @@
import { DummyPolicy, PoliciesApi } from "authentik-api"; import { DummyPolicy, PoliciesApi } from "authentik-api";
import { gettext } from "django"; import { t } from "@lingui/macro";
import { customElement, property } from "lit-element"; import { customElement, property } from "lit-element";
import { html, TemplateResult } from "lit-html"; import { html, TemplateResult } from "lit-html";
import { DEFAULT_CONFIG } from "../../../api/Config"; import { DEFAULT_CONFIG } from "../../../api/Config";
@ -25,9 +25,9 @@ export class DummyPolicyForm extends Form<DummyPolicy> {
getSuccessMessage(): string { getSuccessMessage(): string {
if (this.policy) { if (this.policy) {
return gettext("Successfully updated policy."); return t`Successfully updated policy.`;
} else { } else {
return gettext("Successfully created policy."); return t`Successfully created policy.`;
} }
} }
@ -47,7 +47,7 @@ export class DummyPolicyForm extends Form<DummyPolicy> {
renderForm(): TemplateResult { renderForm(): TemplateResult {
return html`<form class="pf-c-form pf-m-horizontal"> return html`<form class="pf-c-form pf-m-horizontal">
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Name")} label=${t`Name`}
?required=${true} ?required=${true}
name="name"> name="name">
<input type="text" value="${ifDefined(this.policy?.name || "")}" class="pf-c-form-control" required> <input type="text" value="${ifDefined(this.policy?.name || "")}" class="pf-c-form-control" required>
@ -56,34 +56,34 @@ export class DummyPolicyForm extends Form<DummyPolicy> {
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${this.policy?.executionLogging || false}> <input type="checkbox" class="pf-c-check__input" ?checked=${this.policy?.executionLogging || false}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${gettext("Execution logging")} ${t`Execution logging`}
</label> </label>
</div> </div>
<p class="pf-c-form__helper-text">${gettext("When this option is enabled, all executions of this policy will be logged. By default, only execution errors are logged.")}</p> <p class="pf-c-form__helper-text">${t`When this option is enabled, all executions of this policy will be logged. By default, only execution errors are logged.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-group .expanded=${true}> <ak-form-group .expanded=${true}>
<span slot="header"> <span slot="header">
${gettext("Policy-specific settings")} ${t`Policy-specific settings`}
</span> </span>
<div slot="body" class="pf-c-form"> <div slot="body" class="pf-c-form">
<ak-form-element-horizontal name="result"> <ak-form-element-horizontal name="result">
<div class="pf-c-check"> <div class="pf-c-check">
<input type="checkbox" class="pf-c-check__input" ?checked=${this.policy?.result || false}> <input type="checkbox" class="pf-c-check__input" ?checked=${this.policy?.result || false}>
<label class="pf-c-check__label"> <label class="pf-c-check__label">
${gettext("Pass policy?")} ${t`Pass policy?`}
</label> </label>
</div> </div>
<p class="pf-c-form__helper-text">${gettext("When this option is enabled, all executions of this policy will be logged. By default, only execution errors are logged.")}</p> <p class="pf-c-form__helper-text">${t`When this option is enabled, all executions of this policy will be logged. By default, only execution errors are logged.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Wait (min)")} label=${t`Wait (min)`}
?required=${true} ?required=${true}
name="waitMin"> name="waitMin">
<input type="number" value="${first(this.policy?.waitMin, 1)}" class="pf-c-form-control" required> <input type="number" value="${first(this.policy?.waitMin, 1)}" class="pf-c-form-control" required>
<p class="pf-c-form__helper-text">${gettext("The policy takes a random time to execute. This controls the minimum time it will take.")}</p> <p class="pf-c-form__helper-text">${t`The policy takes a random time to execute. This controls the minimum time it will take.`}</p>
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal <ak-form-element-horizontal
label=${gettext("Wait (max)")} label=${t`Wait (max)`}
?required=${true} ?required=${true}
name="waitMax"> name="waitMax">
<input type="number" value="${first(this.policy?.waitMax, 5)}" class="pf-c-form-control" required> <input type="number" value="${first(this.policy?.waitMax, 5)}" class="pf-c-form-control" required>

Some files were not shown because too many files have changed in this diff Show More