web: Replace lingui.js with lit-localize (#5761)
* \#\# Details
web: replace lingui with lit/localize
\#\# Changes
This rather massive shift replaces the lingui and `t()` syntax with lit-localize, XLIFF, and the `msg()`
syntax used by lit-localize. 90% of this work was mechanized; simple perl scripts found and replaced
all uses of `t()` with the appropriate corresponding syntax for `msg()` and `msg(str())`.
The XLIFF files were auto-generated from the PO files. They have not been audited, and they should be
checked over by professional translators. The actual _strings_ have not been changed, but as this was
a mechanized change there is always the possibility of mis-translation-- not by the translator, but by
the script.
* web: revise lit/localize: fix two installation issues.
* web: revise localization
TL;DR:
- Replaced all of Lingui's `t()` syntax with `msg()` syntax.
- Mechanically (i.e with a script) converted all of the PO files to XLIFF files
- Refactored the localization code to be a bit smarter:
- the function `getBestMatchLocale` takes the locale lists and a requested locale, and returns the
first match of:
- The locale's code exactly matches the requested locale
- The locale code exactly matches the prefix of the requested locale (i.e the "en" part of "en-US")
- the locale code's prefix exactly matches the prefix of the requested locale
This function is passed to lit-locate's `loadLocale()`.
- `activateLocale()` just calls `loadLocale()` now.
- `autodetectLanguage` searches the following, and picks the first that returns a valid locale
object, before passing it to `loadLocale()`:
- The User's settings
- A `?locale=` component found in `window.location.search`
- The `window.navigator.language` field
- English
The `msg()` only runs when it's run. This seems obvious, but it means that you cannot cache
strings at load time; they must be kept inside functions that are re-run so that the `msg()` engine
can look up the strings in the preferred language of the user at that moment.
You can use thunks-of-strings if you really need them that way.
* Including the 'xliff-converter' in case anyone wants to review it.
* The xliff-converter is tagged as 'xliff-converter', but has been
deleted.
\#\# Details
- Resolves #5171
\#\# Changes
\#\#\# New Features
- Adds a "Add an Application" to the LibraryView if there are no applications and the user is an administrator.
\#\#\# Breaking Changes
- Adds breaking change which causes \<issue\>.
\#\# Checklist
- [ ] Local tests pass (`ak test authentik/`)
- [ ] The code has been formatted (`make lint-fix`)
If an API change has been made
- [ ] The API schema has been updated (`make gen-build`)
If changes to the frontend have been made
- [ ] The code has been formatted (`make web`)
- [ ] The translation files have been updated (`make i18n-extract`)
If applicable
- [ ] The documentation has been updated
- [ ] The documentation has been formatted (`make website`)
* web: fix redundant locales for zh suite.
* web: prettier pass for locale update
* web: localization moderization
Changed the names of the lit-localize commands to make it clear they're
part of the localization effort, and not just "build" and "extract".
* update transifex config
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* fix package lock?
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* use build not compile
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* web: conversion to lit-localize
The CI produced a list of problems that I hadn't caught earlier,
due to a typo ("localize build" is correct, "localize compile" is
not) I had left in package.json. They were minor and linty, but
it was still wise to fix them.
* web: replace lingui with lit/locale
This commit fixes some minor linting issues that were hidden by a typo in package.json. The
issues were not apparently problematic from a Javascript point of view, but they pointed
to sloppy thinking in the progression of types through the system, so I cleaned them
up and formalized the types from LocaleModule to AkLocale.
* web: replace lingui with lit/localize
One problem that has repeatedly come up is that localize's templates do not produce
JavaScript that conforms with our shop style. I've replaced `build-locale` with
a two-step that builds the locale *and* ensures that it conforms to the shop style
via `prettier` every time.
* web: replace lingui with lit-locale
This commit applies the most recent bundle of translations to the
new lit-locale aspect component. It also revises the algorithm
for *finding* the correct locale, replacing the complex fall-back
with some rather straightforward regular expressions.
In the case of Chinese, the fallback comes at the end of the
selection list, which may not be, er, politically valuable
(since Taiwan and Hong Kong come before, being exceptions that
need to be tested). If we need a different order for presentation,
that'll be a future feature.
* web: replace lingui with lit/locale
Well, that was embarassing.
---------
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-06-02 15:08:36 +00:00
<?xml version="1.0" encoding="utf-8"?>
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
<file target-language="de" source-language="en" original="lit-localize-inputs" datatype="plaintext">
<body>
<trans-unit id="s4caed5b7a7e5d89b">
<source>English</source>
<target>Englisch</target>
</trans-unit>
<trans-unit id="s75a27f43413e02c5">
<source>French</source>
<target>Französisch</target>
</trans-unit>
<trans-unit id="s9d2d00982edafabb">
<source>Turkish</source>
<target>Türkisch</target>
</trans-unit>
<trans-unit id="sf1868dc19e3917bb">
<source>Spanish</source>
<target>Spanisch</target>
</trans-unit>
<trans-unit id="s03f49e598ffb11cc">
<source>Polish</source>
<target>Polnisch</target>
</trans-unit>
<trans-unit id="s4660da32fb311ac0">
<source>Taiwanese Mandarin</source>
<target>Taiwanesisches Mandarin</target>
</trans-unit>
<trans-unit id="s354e0a9f146d2869">
<source>Chinese (simplified)</source>
<target>Chinesisch (vereinfacht)</target>
</trans-unit>
<trans-unit id="se3e6af2ce24d80e8">
<source>Chinese (traditional)</source>
<target>Chinesisch (traditionell)</target>
</trans-unit>
<trans-unit id="s63e71d20d1eaca93">
<source>German</source>
<target>Deutsch</target>
</trans-unit>
<trans-unit id="s49730f3d5751a433">
<source>Loading...</source>
<target>Laden...</target>
</trans-unit>
<trans-unit id="sf1e9d421f35b51e5">
<source>Application</source>
<target>Anwendung</target>
</trans-unit>
<trans-unit id="s310d8757ce319673">
<source>Logins</source>
<target>Anmeldungen</target>
</trans-unit>
<trans-unit id="sa50a6326530d8a0d">
<source>Show less</source>
<target>Zeige weniger</target>
</trans-unit>
<trans-unit id="sb2c57b2d347203dd">
<source>Show more</source>
<target>Zeig mehr</target>
</trans-unit>
<trans-unit id="s6238f519db67980d">
<source>UID</source>
<target>UID</target>
</trans-unit>
<trans-unit id="sef49aec68fd1dc66">
<source>Name</source>
<target>Name</target>
</trans-unit>
<trans-unit id="sf9f2c719a04066ec">
<source>App</source>
<target>App</target>
</trans-unit>
<trans-unit id="sda796c87fa97ed4d">
<source>Model Name</source>
<target>Modellname</target>
</trans-unit>
<trans-unit id="s79e8cc71a5975b04">
<source>Message</source>
<target>Nachricht</target>
</trans-unit>
<trans-unit id="sbbc53e0e54d7946f">
<source>Subject</source>
<target>Betreff</target>
</trans-unit>
<trans-unit id="sa6ab5184d6315895">
<source>From</source>
<target>Von</target>
</trans-unit>
<trans-unit id="s09353907b5c79284">
<source>To</source>
<target>Zu</target>
</trans-unit>
<trans-unit id="s63e03c70f67ebf9c">
<source>Context</source>
<target>Kontext</target>
</trans-unit>
<trans-unit id="sa48f81f001b893d2">
<source>User</source>
<target>Benutzer</target>
</trans-unit>
<trans-unit id="s119498d4e4cf59a6">
<source>Affected model:</source>
<target>Betroffenes Modell:</target>
</trans-unit>
<trans-unit id="sa3660d505e7011e0">
<source>Authorized application:</source>
<target>Autorisierte Applikation:</target>
</trans-unit>
<trans-unit id="s95a032ae86881bf5">
<source>Using flow</source>
<target>Nutze Ablauf</target>
</trans-unit>
<trans-unit id="scb5c9a7cc4ccd68d">
<source>Email info:</source>
<target>E-Mail-Info:</target>
</trans-unit>
<trans-unit id="s677f1b675fc21bb1">
<source>Secret:</source>
<target>Geheimnis:</target>
</trans-unit>
<trans-unit id="sd947d57c9a9b7108">
<source>Open issue on GitHub...</source>
<target>Offenes Problem auf GitHub...</target>
</trans-unit>
<trans-unit id="sa6905be242387f36">
<source>Exception</source>
<target>Ausnahme</target>
</trans-unit>
<trans-unit id="s6ab73c998850c5ab">
<source>Expression</source>
<target>Ausdruck</target>
</trans-unit>
<trans-unit id="s50ebe627b4bc7d02">
<source>Binding</source>
<target>Verknüpfung</target>
</trans-unit>
<trans-unit id="s3c6de3f257e0c912">
<source>Request</source>
<target>Anfrage</target>
</trans-unit>
<trans-unit id="s730182ad28374cda">
<source>Object</source>
<target>Objekt</target>
</trans-unit>
<trans-unit id="s890e983a7be64da4">
<source>Result</source>
<target>Ergebnis</target>
</trans-unit>
<trans-unit id="sd3a853f63f45dcb0">
<source>Passing</source>
<target>Erlauben</target>
</trans-unit>
<trans-unit id="sbdeedc1c60306b35">
<source>Messages</source>
<target>Nachrichten</target>
</trans-unit>
<trans-unit id="s0a5401d4419f9958">
<source>Using source</source>
<target>Quelle verwenden</target>
</trans-unit>
<trans-unit id="s14622ee6de586485">
<source>Attempted to log in as <x id="0" equiv-text="${this.event.context.username}"/></source>
<target>Loginversuch als
<x id="0" equiv-text="${this.event.context.username}"/></target>
</trans-unit>
<trans-unit id="sb07bf992e3d00664">
<source>No additional data available.</source>
<target>Keine weiteren Daten vorhanden.</target>
</trans-unit>
<trans-unit id="s09810653c832e935">
<source>Click to change value</source>
<target>Klicken Sie, um den Wert zu ändern</target>
</trans-unit>
<trans-unit id="sfefce784ec55868f">
<source>Select an object.</source>
<target>Wählen Sie ein Objekt aus.</target>
</trans-unit>
<trans-unit id="s04ceadb276bbe149">
<source>Loading options...</source>
</trans-unit>
<trans-unit id="sfe629863ba1338c2">
<source>Connection error, reconnecting...</source>
<target>Verbindungsfehler, erneuter Verbindungsaufbau...</target>
</trans-unit>
<trans-unit id="sc8da3cc71de63832">
<source>Login</source>
<target>Anmeldung</target>
</trans-unit>
<trans-unit id="sb4564c127ab8b921">
<source>Failed login</source>
<target>Fehlgeschlagene Anmeldung</target>
</trans-unit>
<trans-unit id="s67749057edb2586b">
<source>Logout</source>
<target>Abmelden</target>
</trans-unit>
<trans-unit id="s7e537ad68d7c16e1">
<source>User was written to</source>
<target>Benutzer wurde geschrieben nach</target>
</trans-unit>
<trans-unit id="sa0e0bdd7e244416b">
<source>Suspicious request</source>
<target>Verdächtige Anfrage</target>
</trans-unit>
<trans-unit id="s7bda44013984fc48">
<source>Password set</source>
<target>Passwort festgelegt</target>
</trans-unit>
<trans-unit id="sa1b41e334ad89d94">
<source>Secret was viewed</source>
<target>Geheimnis wurde angesehen</target>
</trans-unit>
<trans-unit id="s92ca679592a36b35">
<source>Secret was rotated</source>
<target>Geheimnis wurde rotiert</target>
</trans-unit>
<trans-unit id="s8a1d9403ca90989b">
<source>Invitation used</source>
<target>Einladung verwendet</target>
</trans-unit>
<trans-unit id="s5f496533610103f2">
<source>Application authorized</source>
<target>Anwendung authorisiert</target>
</trans-unit>
<trans-unit id="sdc9e222be9612939">
<source>Source linked</source>
<target>Quelle verknüpft</target>
</trans-unit>
<trans-unit id="sb1c91762ae3a9bee">
<source>Impersonation started</source>
<target>Identitätswechsel gestarted</target>
</trans-unit>
<trans-unit id="s9c73bd29b279d26b">
<source>Impersonation ended</source>
<target>Identitätswechsel beenden</target>
</trans-unit>
<trans-unit id="s1cd264012278c047">
<source>Flow execution</source>
<target>Ablauf-Ausführung</target>
</trans-unit>
<trans-unit id="s32f04d33924ce8ad">
<source>Policy execution</source>
<target>Richtlinien-Ausführung</target>
</trans-unit>
<trans-unit id="sb6d7128df5978cee">
<source>Policy exception</source>
<target>Richtlinien-Ausnahme</target>
</trans-unit>
<trans-unit id="s77f572257f69a8db">
<source>Property Mapping exception</source>
<target>Ausnahme der Eigenschaftszuordnung</target>
</trans-unit>
<trans-unit id="s2543cffd6ebb6803">
<source>System task execution</source>
<target>Ausführung von Systemtasks</target>
</trans-unit>
<trans-unit id="se2f258b996f7279c">
<source>System task exception</source>
<target>Systemtask-Ausnahme</target>
</trans-unit>
<trans-unit id="s81eff3409d572a21">
<source>General system exception</source>
<target>Allgemeine Systemausnahme</target>
</trans-unit>
<trans-unit id="sf8f49cdbf0036343">
<source>Configuration error</source>
<target>Fehler bei der Konfiguration</target>
</trans-unit>
<trans-unit id="s9c6f61dc47bc4f0a">
<source>Model created</source>
<target>Modell erstellt</target>
</trans-unit>
<trans-unit id="s47a4983a2c6bb749">
<source>Model updated</source>
<target>Modell aktualisiert</target>
</trans-unit>
<trans-unit id="sc9f69360b58706c7">
<source>Model deleted</source>
<target>Modell gelöscht</target>
</trans-unit>
<trans-unit id="sa266303caf1bd27f">
<source>Email sent</source>
<target>E-Mail gesendet</target>
</trans-unit>
<trans-unit id="s6c410fedda2a575f">
<source>Update available</source>
<target>Update verfügbar</target>
</trans-unit>
<trans-unit id="s02240309358f557c">
<source>Unknown severity</source>
</trans-unit>
<trans-unit id="sf1ec4acb8d744ed9">
<source>Alert</source>
<target>Alarm</target>
</trans-unit>
<trans-unit id="s9117fb5195e75151">
<source>Notice</source>
<target>Hinweis</target>
</trans-unit>
<trans-unit id="s34be76c6b1eadbef">
<source>Warning</source>
<target>Warnung</target>
</trans-unit>
<trans-unit id="sf45a0d2f00bcc6ff">
<source>no tabs defined</source>
<target>Keine Registerkarten definiert</target>
</trans-unit>
<trans-unit id="s04c5a637328c9b67">
<source><x id="0" equiv-text="${this.pages?.startIndex}"/> - <x id="1" equiv-text="${this.pages?.endIndex}"/> of <x id="2" equiv-text="${this.pages?.count}"/></source>
<target>
<x id="0" equiv-text="${this.pages?.startIndex}"/>-
<x id="1" equiv-text="${this.pages?.endIndex}"/>von
<x id="2" equiv-text="${this.pages?.count}"/></target>
</trans-unit>
<trans-unit id="s6a89bb10338369b4">
<source>Go to previous page</source>
<target>Zurück zur vorherigen Seite</target>
</trans-unit>
<trans-unit id="s7edad99c6b7bfe88">
<source>Go to next page</source>
<target>Weiter zur nächsten Seite</target>
</trans-unit>
<trans-unit id="sffa721bb6aa3128d">
<source>Search...</source>
<target>Suche...</target>
</trans-unit>
<trans-unit id="sb59d68ed12d46377">
<source>Loading</source>
<target>Wird geladen</target>
</trans-unit>
<trans-unit id="s7bc8c327f1f7c82c">
<source>No objects found.</source>
<target>Keine Objekte gefunden.</target>
</trans-unit>
<trans-unit id="sfd44ce578f643145">
<source>Failed to fetch objects.</source>
</trans-unit>
<trans-unit id="s7b7163270e57e8b4">
<source>Refresh</source>
<target>Aktualisieren</target>
</trans-unit>
<trans-unit id="s909e876731a8febb">
<source>Select all rows</source>
<target>Wählen Sie alle Zeilen aus</target>
</trans-unit>
<trans-unit id="sa442044b586ec8bf">
<source>Action</source>
<target>Aktion</target>
</trans-unit>
<trans-unit id="s02839b01844d6ca8">
<source>Creation Date</source>
<target>Erstellungsdatum</target>
</trans-unit>
<trans-unit id="s4d00f1de1c82281b">
<source>Client IP</source>
<target>Client-IP</target>
</trans-unit>
<trans-unit id="s2152f3482784705f">
<source>Recent events</source>
</trans-unit>
<trans-unit id="sc35581d9c1cd67ff">
<source>On behalf of <x id="0" equiv-text="${item.user.on_behalf_of.username}"/></source>
<target>Im Namen von
<x id="0" equiv-text="${item.user.on_behalf_of.username}"/></target>
</trans-unit>
<trans-unit id="saf63a04c86018698">
<source>-</source>
<target>-</target>
</trans-unit>
<trans-unit id="s1b448a4ea79d4eef">
<source>No Events found.</source>
<target>Keine Ereignisse gefunden.</target>
</trans-unit>
<trans-unit id="s50911ec1c8aee99a">
<source>No matching events could be found.</source>
<target>Es konnten keine passenden Ereignisse gefunden werden.</target>
</trans-unit>
<trans-unit id="s113c05ef9996ca4b">
<source>Embedded outpost is not configured correctly.</source>
<target>Der System-Outpost ist nicht richtig konfiguriert.</target>
</trans-unit>
<trans-unit id="seb5ba88f21937c98">
<source>Check outposts.</source>
<target>Outposts prüfen</target>
</trans-unit>
<trans-unit id="sd0bc94e11935ee5a">
<source>HTTPS is not detected correctly</source>
<target>HTTPS wird nicht korrekt erkannt</target>
</trans-unit>
<trans-unit id="s40bf151b56a64f51">
<source>Server and client are further than 5 seconds apart.</source>
<target>Server und Client sind mehr als 5 Sekunden voneinander entfernt.</target>
</trans-unit>
<trans-unit id="s091d3d07b5b3076f">
<source>OK</source>
<target>OK</target>
</trans-unit>
<trans-unit id="sae486938be80729c">
<source>Everything is ok.</source>
<target>Alles funktioniert.</target>
</trans-unit>
<trans-unit id="sea91c57b3d3969fe">
<source>System status</source>
<target>Systemzustand</target>
</trans-unit>
<trans-unit id="scefe482c547fb3f3">
<source>Based on <x id="0" equiv-text="${value.versionCurrent}"/></source>
</trans-unit>
<trans-unit id="s68a50b1ee6efee7b">
<source><x id="0" equiv-text="${value.versionLatest}"/> is available!</source>
<target>
<x id="0" equiv-text="${value.versionLatest}"/>ist verfügbar!</target>
</trans-unit>
<trans-unit id="s713d147e1761d0f0">
<source>Up-to-date!</source>
<target>Aktuell!</target>
</trans-unit>
<trans-unit id="sf4122b220926be97">
<source>Version</source>
<target>Version</target>
</trans-unit>
<trans-unit id="s0a63a8be0b2b422c">
<source>Workers</source>
<target>Arbeiter</target>
</trans-unit>
<trans-unit id="s341ab68d4130de20">
<source>No workers connected. Background tasks will not run.</source>
<target>Keine Worker verbunden. Hintergrundaufgaben werden nicht ausgeführt.</target>
</trans-unit>
<trans-unit id="s2ed8eb02525a920a">
<source><x id="0" equiv-text="${ago}"/> hour(s) ago</source>
</trans-unit>
<trans-unit id="s1f1c857c0c4250e4">
<source><x id="0" equiv-text="${ago}"/> day(s) ago</source>
</trans-unit>
<trans-unit id="s11bc220e8fa9d797">
<source>Authorizations</source>
<target>Berechtigungen</target>
</trans-unit>
<trans-unit id="s3ef3c252ada78076">
<source>Failed Logins</source>
<target>Fehlgeschlagene Anmeldungen</target>
</trans-unit>
<trans-unit id="sc2f1e5dd74c1b7df">
<source>Successful Logins</source>
<target>Erfolgreiche Anmeldungen</target>
</trans-unit>
<trans-unit id="s0382d73823585617">
<source><x id="0" equiv-text="${this.errorMessage}"/>: <x id="1" equiv-text="${e.toString()}"/></source>
<target>
<x id="0" equiv-text="${this.errorMessage}"/>:
<x id="1" equiv-text="${e.toString()}"/></target>
</trans-unit>
<trans-unit id="s2ceb11be2290bb1b">
<source>Cancel</source>
<target>Abbrechen</target>
</trans-unit>
<trans-unit id="se085f35c8a9203a1">
<source>LDAP Source</source>
<target>LDAP Quelle</target>
</trans-unit>
<trans-unit id="s477de089b505a6ea">
<source>SCIM Provider</source>
</trans-unit>
<trans-unit id="s8a75e83497a183a2">
<source>Healthy</source>
</trans-unit>
<trans-unit id="sfeb82261bcf99edd">
<source>Healthy outposts</source>
<target>Intakte Outposts</target>
</trans-unit>
<trans-unit id="saae1c70e168b45b4">
<source>Admin</source>
<target>Admin</target>
</trans-unit>
<trans-unit id="s0a11c2ffb8309d1a">
<source>Not found</source>
<target>Nicht gefunden</target>
</trans-unit>
<trans-unit id="saa0e2675da69651b">
<source>The URL "<x id="0" equiv-text="${this.url}"/>" was not found.</source>
<target>Die URL "
<x id="0" equiv-text="${this.url}"/>" wurde nicht gefunden.</target>
</trans-unit>
<trans-unit id="s58cd9c2fe836d9c6">
<source>Return home</source>
<target>Zurück zum Home</target>
</trans-unit>
<trans-unit id="s41e035c4bb8d15f2">
<source>General system status</source>
<target>Allgemeiner Systemzustand</target>
</trans-unit>
<trans-unit id="s6dfd15978586d05f">
<source>Welcome, <x id="0" equiv-text="${name}"/>.</source>
<target>Willkommen,
<x id="0" equiv-text="${name}"/>!</target>
</trans-unit>
<trans-unit id="sc381422c585b867f">
<source>Quick actions</source>
<target>Schnellaktionen</target>
</trans-unit>
<trans-unit id="sfd13ca8ebd857c2e">
<source>Create a new application</source>
<target>Erstelle eine neue Anwendung</target>
</trans-unit>
<trans-unit id="s079d388d3cbfa54f">
<source>Check the logs</source>
<target>Logs überprüfen</target>
</trans-unit>
<trans-unit id="sed8d4c3fd5f60e1f">
<source>Explore integrations</source>
<target>Integrationen erkunden</target>
</trans-unit>
<trans-unit id="sfffb0d0958bfbc42">
<source>Manage users</source>
</trans-unit>
<trans-unit id="s8763a33c3d46aaf5">
<source>Outpost status</source>
<target>Outpost Status</target>
</trans-unit>
<trans-unit id="scc286303aa9c6cb0">
<source>Sync status</source>
<target>Status synchronisieren</target>
</trans-unit>
<trans-unit id="sbdc4a833de9ca502">
<source>Logins and authorizations over the last week (per 8 hours)</source>
</trans-unit>
<trans-unit id="s6e09a19aa3952509">
<source>Apps with most usage</source>
<target>Meistgenutzte Apps</target>
</trans-unit>
<trans-unit id="sda5e1499f93146ad">
<source><x id="0" equiv-text="${ago}"/> days ago</source>
<target>vor
<x id="0" equiv-text="${ago}"/>Tagen</target>
</trans-unit>
<trans-unit id="s51ea3a244c781b1f">
<source>Objects created</source>
<target>Objekte erstellt</target>
</trans-unit>
<trans-unit id="sfbadb77fbc61efb8">
<source>Users created per day in the last month</source>
<target>Benutzer, die im letzten Monat pro Tag erstellt wurden</target>
</trans-unit>
<trans-unit id="sb0669da3df95837c">
<source>Logins per day in the last month</source>
<target>Anmeldungen pro Tag im letzten Monat</target>
</trans-unit>
<trans-unit id="s835da49b4dc83a51">
<source>Failed Logins per day in the last month</source>
<target>Fehlgeschlagene Anmeldungen pro Tag im letzten Monat</target>
</trans-unit>
<trans-unit id="s5f4586bc1e2740e6">
<source>Clear search</source>
<target>Sucheingabe löschen</target>
</trans-unit>
<trans-unit id="s3b34d9930e33bd46">
<source>System Tasks</source>
<target>Systemoperationen</target>
</trans-unit>
<trans-unit id="saaa3abe03c7260f9">
<source>Long-running operations which authentik executes in the background.</source>
<target>Langlaufende Operationen, die Authentik im Hintergrund ausführt.</target>
</trans-unit>
<trans-unit id="s7468e87263dfff7e">
<source>Identifier</source>
<target>Kennung</target>
</trans-unit>
<trans-unit id="s63d894b1ddb06289">
<source>Description</source>
<target>Beschreibung</target>
</trans-unit>
<trans-unit id="sa9b2a245441557dc">
<source>Last run</source>
<target>Letzter Lauf</target>
</trans-unit>
<trans-unit id="sad3e3c8146fc920f">
<source>Status</source>
<target>Status</target>
</trans-unit>
<trans-unit id="s8af61807443f32a4">
<source>Actions</source>
<target>Aktionen</target>
</trans-unit>
<trans-unit id="sbe9a51f29a4a2c5b">
<source>Successful</source>
<target>Erfolgreich</target>
</trans-unit>
<trans-unit id="s5f343a43e7ea9f91">
<source>Error</source>
<target>Fehler</target>
</trans-unit>
<trans-unit id="sc592307ea80f16b9">
<source>Unknown</source>
<target>Unbekannt</target>
</trans-unit>
<trans-unit id="s92921878e886e36d">
<source>Duration</source>
</trans-unit>
<trans-unit id="se7e1ababbc4868b8">
<source><x id="0" equiv-text="${item.taskDuration.toFixed(2)}"/> seconds</source>
</trans-unit>
<trans-unit id="sc25edca57df81461">
<source>Authentication</source>
<target>Authentifizierung</target>
</trans-unit>
<trans-unit id="s6dfb7283452f78fe">
<source>Authorization</source>
<target>Autorisierung</target>
</trans-unit>
<trans-unit id="sddcfc6ab24e3a6ed">
<source>Enrollment</source>
<target>Registrierung</target>
</trans-unit>
<trans-unit id="s1fc9c70610c4c67d">
<source>Invalidation</source>
<target>Invalidierung</target>
</trans-unit>
<trans-unit id="s6ac670086eb137c6">
<source>Recovery</source>
<target>Wiederherstellung</target>
</trans-unit>
<trans-unit id="sdf22dcf939c27cc7">
<source>Stage Configuration</source>
<target>Phasen Konfiguration</target>
</trans-unit>
<trans-unit id="s6d5bce4321f57cda">
<source>Unenrollment</source>
<target>Abmeldung</target>
</trans-unit>
<trans-unit id="sde2bb5418562c5b2">
<source>Unknown designation</source>
</trans-unit>
<trans-unit id="sb9834316ffd4ae3e">
<source>Stacked</source>
<target>Gestapelt</target>
</trans-unit>
<trans-unit id="s12146091b2b539a3">
<source>Content left</source>
<target>Inhalt links</target>
</trans-unit>
<trans-unit id="sa800871782eba1ac">
<source>Content right</source>
<target>Inhalt rechts</target>
</trans-unit>
<trans-unit id="sb4e50ca3cffdbc10">
<source>Sidebar left</source>
<target>Sidebar links</target>
</trans-unit>
<trans-unit id="s745a55f9abf9f2e5">
<source>Sidebar right</source>
<target>Sidebar rechts</target>
</trans-unit>
<trans-unit id="sb3182a87ded1bc91">
<source>Unknown layout</source>
</trans-unit>
<trans-unit id="sdfd22a21660f6002">
<source>Successfully updated provider.</source>
<target>Provider erfolgreich aktualisiert.</target>
</trans-unit>
<trans-unit id="s457c639088c547c5">
<source>Successfully created provider.</source>
<target>Anbieter erfolgreich erstellt.</target>
</trans-unit>
<trans-unit id="sff69c1a637f899a6">
<source>Bind flow</source>
<target>Ablauf-Verknüpfung</target>
</trans-unit>
<trans-unit id="s319040353f479853">
<source>Flow used for users to authenticate.</source>
</trans-unit>
<trans-unit id="sbc80eab557fbf782">
<source>Search group</source>
<target>Suchgruppe</target>
</trans-unit>
<trans-unit id="s04b7f8d6aaef3756">
<source>Users in the selected group can do search queries. If no group is selected, no LDAP Searches are allowed.</source>
<target>Benutzer in der ausgewählten Gruppe können Suchanfragen stellen. Wenn keine Gruppe ausgewählt ist, sind keine LDAP-Suchen zulässig.</target>
</trans-unit>
<trans-unit id="se5973e7c8ba0fc71">
<source>Bind mode</source>
<target>Bindungsmodus</target>
</trans-unit>
<trans-unit id="s8915e64b8b999bfe">
<source>Cached binding</source>
</trans-unit>
<trans-unit id="s842d690eb3c11762">
<source>Flow is executed and session is cached in memory. Flow is executed when session expires</source>
</trans-unit>
<trans-unit id="s6a66759749bf31ed">
<source>Direct binding</source>
</trans-unit>
<trans-unit id="se0adaf83627104fb">
<source>Always execute the configured bind flow to authenticate the user</source>
</trans-unit>
<trans-unit id="scef3f4ad80abbd22">
<source>Configure how the outpost authenticates requests.</source>
<target>Konfigurieren Sie, wie der Außenposten Anfragen authentifiziert.</target>
</trans-unit>
<trans-unit id="sbcae51a6f06e53d4">
<source>Search mode</source>
<target>Suchmodus</target>
</trans-unit>
<trans-unit id="s9065fcccd837a679">
<source>Cached querying</source>
</trans-unit>
<trans-unit id="s30d0d0e6c626a234">
<source>The outpost holds all users and groups in-memory and will refresh every 5 Minutes</source>
</trans-unit>
<trans-unit id="sffc14b8200a9f938">
<source>Direct querying</source>
</trans-unit>
<trans-unit id="sdce4680288083fe3">
<source>Always returns the latest data, but slower than cached querying</source>
</trans-unit>
<trans-unit id="s8b87df5664de7eb8">
<source>Configure how the outpost queries the core authentik server's users.</source>
<target>Konfigurieren Sie, wie der Outpost die Benutzer des Core-Authentik-Servers abfragt.</target>
</trans-unit>
<trans-unit id="sfe388f0313f52da2">
<source>Protocol settings</source>
<target>Protokolleinstellungen</target>
</trans-unit>
<trans-unit id="s55d731be1ef66efe">
<source>Base DN</source>
<target>Base DN</target>
</trans-unit>
<trans-unit id="s0b15ff11a0049cfd">
<source>LDAP DN under which bind requests and search requests can be made.</source>
<target>LDAP DN, unter dem Bind-Requests und Suchanfragen gestellt werden können.</target>
</trans-unit>
<trans-unit id="sb157267c85fdff30">
<source>Certificate</source>
<target>Zertifikat</target>
</trans-unit>
<trans-unit id="sac43cb9690260b86">
<source>UID start number</source>
<target>UID-Startnummer</target>
</trans-unit>
<trans-unit id="s60edbcfac8ed1f90">
<source>The start for uidNumbers, this number is added to the user.Pk to make sure that the numbers aren't too low for POSIX users. Default is 2000 to ensure that we don't collide with local users uidNumber</source>
<target>Der Anfang für uidNumbers, diese Zahl wird zu user.Pk hinzugefügt, um sicherzustellen, dass die Zahlen für POSIX-Benutzer nicht zu niedrig sind. Standardwert ist 2000, um sicherzustellen, dass wir nicht mit lokalen Benutzer kollidieren</target>
</trans-unit>
<trans-unit id="s5acb607b40356974">
<source>GID start number</source>
<target>GID-Startnummer</target>
</trans-unit>
<trans-unit id="s1c8e9816dcae6d9c">
<source>The start for gidNumbers, this number is added to a number generated from the group.Pk to make sure that the numbers aren't too low for POSIX groups. Default is 4000 to ensure that we don't collide with local groups or users primary groups gidNumber</source>
<target>Der Anfang für gidNumbers, diese Zahl wird zu einer aus der group.Pk generierten Zahl addiert, um sicherzustellen, dass die Zahlen für POSIX-Gruppen nicht zu niedrig sind. Der Standardwert ist 4000, um sicherzustellen, dass wir nicht mit lokalen Gruppen oder primären Benutzergruppen kollidieren.</target>
</trans-unit>
<trans-unit id="s2236dc563c2dbf76">
<source>(Format: hours=-1;minutes=-2;seconds=-3).</source>
<target>(Format: hours=-1;minutes=-2;seconds=-3).</target>
</trans-unit>
<trans-unit id="sbec40ef4e6f139b7">
<source>(Format: hours=1;minutes=2;seconds=3).</source>
<target>(Format: hours=-1;minutes=-2;seconds=-3).</target>
</trans-unit>
<trans-unit id="sbb8ad22c83d375b1">
<source>The following keywords are supported:</source>
</trans-unit>
<trans-unit id="sbb3243352661428f">
<source>Authentication flow</source>
<target>Authentifizierungsablauf</target>
</trans-unit>
<trans-unit id="sa72a3bd1e7e89926">
<source>Flow used when a user access this provider and is not authenticated.</source>
</trans-unit>
<trans-unit id="s62f7c59b0606a8d6">
<source>Authorization flow</source>
<target>Autorisierungsablauf</target>
</trans-unit>
<trans-unit id="sfbaeb0de54fbfdbb">
<source>Flow used when authorizing this provider.</source>
<target>Flow der zur Authorisierung des Anbieter verwendet wird.</target>
</trans-unit>
<trans-unit id="sc8de93a7dc0d78ba">
<source>Client type</source>
<target>Clienttyp</target>
</trans-unit>
<trans-unit id="s399cc2d67d92e957">
<source>Confidential</source>
<target>Vertraulich</target>
</trans-unit>
<trans-unit id="s95f09b229a0a0bb0">
<source>Confidential clients are capable of maintaining the confidentiality of their credentials such as client secrets</source>
</trans-unit>
<trans-unit id="sdd1ff479d04ac140">
<source>Public</source>
<target>Öffentlich</target>
</trans-unit>
<trans-unit id="s51c6b8403c2dc5d9">
<source>Public clients are incapable of maintaining the confidentiality and should use methods like PKCE. </source>
</trans-unit>
<trans-unit id="s4d00e5de1c8213b7">
<source>Client ID</source>
<target>Client ID</target>
</trans-unit>
<trans-unit id="s03fb3fa232f0434a">
<source>Client Secret</source>
<target>Client Geheimnis</target>
</trans-unit>
<trans-unit id="sde0ad51b14f77cf6">
<source>Redirect URIs/Origins (RegEx)</source>
<target>Redirect URIs/Origins (RegEx)</target>
</trans-unit>
<trans-unit id="s7f9eb9c8bd26e8fd">
<source>Valid redirect URLs after a successful authorization flow. Also specify any origins here for Implicit flows.</source>
<target>Gültige Umleitungs-URLs nach einem erfolgreichen Autorisierungsablauf. Geben Sie hier auch alle Ursprünge für implizite Flüsse an.</target>
</trans-unit>
<trans-unit id="s2a369bc2febb5d55">
<source>If no explicit redirect URIs are specified, the first successfully used redirect URI will be saved.</source>
<target>Wenn keine expliziten Umleitungs-URIs angegeben sind, wird die erste erfolgreich verwendete Umleitungs-URI gespeichert.</target>
</trans-unit>
<trans-unit id="sa8384c9c26731f83">
<source>To allow any redirect URI, set this value to ".*". Be aware of the possible security implications this can have.</source>
</trans-unit>
<trans-unit id="s55787f4dfcdce52b">
<source>Signing Key</source>
<target>Signaturschlüssel</target>
</trans-unit>
<trans-unit id="sc6c57419ad3a01a8">
<source>Key used to sign the tokens.</source>
<target>Schlüssel zum Signieren der Token.</target>
</trans-unit>
<trans-unit id="s124f93a61ee772d6">
<source>Advanced protocol settings</source>
<target>Erweiterte Protokolleinstellungen</target>
</trans-unit>
<trans-unit id="s926e0ecf124fb01a">
<source>Access code validity</source>
<target>Gültigkeit des Zugangsschlüssels</target>
</trans-unit>
<trans-unit id="sa578033f134a83b6">
<source>Configure how long access codes are valid for.</source>
<target>Konfiguriere, wie lange Zugangsschlüssel gültig sind.</target>
</trans-unit>
<trans-unit id="sbea3db12fd799210">
<source>Access Token validity</source>
</trans-unit>
<trans-unit id="s72559845d38bf688">
<source>Configure how long access tokens are valid for.</source>
<target>Konfiguriere, wie lange Zugangstoken gültig sind.</target>
</trans-unit>
<trans-unit id="s821f6014c1a435b9">
<source>Refresh Token validity</source>
</trans-unit>
<trans-unit id="s00c2db16ea9bc263">
<source>Configure how long refresh tokens are valid for.</source>
</trans-unit>
<trans-unit id="s2e3ef41a0edd8608">
<source>Scopes</source>
<target>Umfang</target>
</trans-unit>
<trans-unit id="s3a3fae99373ce56b">
<source>Select which scopes can be used by the client. The client still has to specify the scope to access the data.</source>
<target>Wählen Sie aus, welche Bereiche vom Client verwendet werden können. Der Client muss noch den Bereich für den Zugriff auf die Daten angeben.</target>
</trans-unit>
<trans-unit id="sffd2e553143d1b0e">
<source>Hold control/command to select multiple items.</source>
<target>Halten Sie die Strg-/Befehlstaste gedrückt, um mehrere Elemente auszuwählen.</target>
</trans-unit>
<trans-unit id="s26bf2730430efbea">
<source>Subject mode</source>
<target>Betreffmodus</target>
</trans-unit>
<trans-unit id="sccc47f82044453f9">
<source>Based on the User's hashed ID</source>
</trans-unit>
<trans-unit id="sbd5be4fb7442a34c">
<source>Based on the User's ID</source>
</trans-unit>
<trans-unit id="sc9cf9ecaf9e5d67e">
<source>Based on the User's UUID</source>
</trans-unit>
<trans-unit id="s4291727352c4f295">
<source>Based on the User's username</source>
</trans-unit>
<trans-unit id="sd62cfc27ad4aa33b">
<source>Based on the User's Email</source>
</trans-unit>
<trans-unit id="s55eb75bedf96be0f">
<source>This is recommended over the UPN mode.</source>
</trans-unit>
<trans-unit id="sf80e9547166117e6">
<source>Based on the User's UPN</source>
</trans-unit>
<trans-unit id="sde949d0ef44572eb">
<source>Requires the user to have a 'upn' attribute set, and falls back to hashed user ID. Use this mode only if you have different UPN and Mail domains.</source>
</trans-unit>
<trans-unit id="s9f23ed1799b4d49a">
<source>Configure what data should be used as unique User Identifier. For most cases, the default should be fine.</source>
<target>Konfigurieren Sie, welche Daten als eindeutige Benutzerkennung verwendet werden sollen. In den meisten Fällen sollte die Standardeinstellung in Ordnung sein.</target>
</trans-unit>
<trans-unit id="s17d1e337f6c11c1e">
<source>Include claims in id_token</source>
<target>Ansprüche in id_token berücksichtigen</target>
</trans-unit>
<trans-unit id="sbf41e0db12834133">
<source>Include User claims from scopes in the id_token, for applications that don't access the userinfo endpoint.</source>
<target>Schließen Sie Benutzeransprüche aus Bereichen in das id_token ein, für Anwendungen, die nicht auf den userinfo-Endpunkt zugreifen.</target>
</trans-unit>
<trans-unit id="s850a58c683682809">
<source>Issuer mode</source>
<target>Ausstellermodus</target>
</trans-unit>
<trans-unit id="sde56783222b527d6">
<source>Each provider has a different issuer, based on the application slug</source>
</trans-unit>
<trans-unit id="s8d32d7b9e8ca60b1">
<source>Same identifier is used for all providers</source>
<target>Für alle Anbieter wird dieselbe Kennung verwendet</target>
</trans-unit>
<trans-unit id="s37d9155b9f4cc7bd">
<source>Configure how the issuer field of the ID Token should be filled.</source>
<target>Konfigurieren Sie, wie der Flow-Executor mit einer ungültigen Antwort auf eine Abfrage umgehen soll.</target>
</trans-unit>
<trans-unit id="se2adaf0371ffcd65">
<source>Machine-to-Machine authentication settings</source>
<target>Machine-to-Machine-Authentifizierungseinstellungen</target>
</trans-unit>
<trans-unit id="s33318837e6c54a9b">
<source>Trusted OIDC Sources</source>
<target>Trusted OIDC Sources</target>
</trans-unit>
<trans-unit id="s22e566052f7bec81">
<source>JWTs signed by certificates configured in the selected sources can be used to authenticate to this provider.</source>
</trans-unit>
<trans-unit id="s072c6d12d3d37501">
<source>HTTP-Basic Username Key</source>
<target>HTTP-Basic Benutzername Schlüssel</target>
</trans-unit>
<trans-unit id="sb2bb6f93773a4594">
<source>User/Group Attribute used for the user part of the HTTP-Basic Header. If not set, the user's Email address is used.</source>
<target>Benutzer-/Gruppenattribut, das für den Benutzerteil des HTTP-Basic-Headers verwendet wird. Wenn nicht festgelegt, wird die E-Mail-Adresse des Benutzers verwendet.</target>
</trans-unit>
<trans-unit id="s70f6471de355b98c">
<source>HTTP-Basic Password Key</source>
<target>HTTP-Basic Passwort Schlüssel</target>
</trans-unit>
<trans-unit id="sf4de1644dcdb53d5">
<source>User/Group Attribute used for the password part of the HTTP-Basic Header.</source>
<target>Nutzer-/Gruppe-Attribut wird für den Passwort-Teil im HTTP-Basic Header verwendet.</target>
</trans-unit>
<trans-unit id="sb8dd788adf7b907b">
<source>Proxy</source>
<target>Proxy</target>
</trans-unit>
<trans-unit id="s7489f76224f8120d">
<source>Forward auth (single application)</source>
<target>Forward Auth (einzelne Anwendung)</target>
</trans-unit>
<trans-unit id="s25d0cd75377daf75">
<source>Forward auth (domain level)</source>
<target>Authentifizierung weiterleiten (Domänenebene)</target>
</trans-unit>
<trans-unit id="s93574c03953f25dd">
<source>This provider will behave like a transparent reverse-proxy, except requests must be authenticated. If your upstream application uses HTTPS, make sure to connect to the outpost using HTTPS as well.</source>
<target>Dieser Anbieter verhält sich wie ein transparenter Reverse-Proxy, außer dass Anforderungen authentifiziert werden müssen. Wenn Ihre Upstream-Anwendung HTTPS verwendet, stellen Sie sicher, dass Sie sich auch über HTTPS mit dem Outpost verbinden.</target>
</trans-unit>
<trans-unit id="sa29b5680cfafacc8">
<source>External host</source>
<target>Externer Host</target>
</trans-unit>
<trans-unit id="s764bccb30868bf62">
<source>The external URL you'll access the application at. Include any non-standard port.</source>
<target>Die externe URL, unter der Sie auf die Anwendung zugreifen. Schließen Sie alle Nicht-Standard-Ports ein.</target>
</trans-unit>
<trans-unit id="scb317851cbcc6b12">
<source>Internal host</source>
<target>Interner Host</target>
</trans-unit>
<trans-unit id="sf05e384059a0a7c1">
<source>Upstream host that the requests are forwarded to.</source>
<target>Upstream-Host, an den die Anfragen weitergeleitet werden.</target>
</trans-unit>
<trans-unit id="s3d34068a31cab30b">
<source>Internal host SSL Validation</source>
<target>Interne Host-SSL-Validierung</target>
</trans-unit>
<trans-unit id="s4a26798e1c3c37dd">
<source>Validate SSL Certificates of upstream servers.</source>
<target>SSL-Zertifikate der Upstream-Server prüfen.</target>
</trans-unit>
<trans-unit id="s44c90273f08fb718">
<source>Use this provider with nginx's auth_request or traefik's forwardAuth. Only a single provider is required per root domain. You can't do per-application authorization, but you don't have to create a provider for each application.</source>
<target>Verwenden Sie diesen Anbieter mit auth_request von nginx oder forwardAuth von traefik. Pro Root-Domain wird nur ein einziger Anbieter benötigt. Sie können keine Autorisierung pro Anwendung vornehmen, aber Sie müssen nicht für jede Anwendung einen Anbieter erstellen.</target>
</trans-unit>
<trans-unit id="sf55d28d4dff0e41b">
<source>An example setup can look like this:</source>
<target>Ein Beispiel-Setup kann so aussehen:</target>
</trans-unit>
<trans-unit id="sb4a1d1c19438e929">
<source>authentik running on auth.example.com</source>
<target>Authentik läuft auf auth.example.com</target>
</trans-unit>
<trans-unit id="s68f935c9ca792016">
<source>app1 running on app1.example.com</source>
<target>app1 läuft auf app1.example.com</target>
</trans-unit>
<trans-unit id="sf813a72d8fadd765">
<source>In this case, you'd set the Authentication URL to auth.example.com and Cookie domain to example.com.</source>
<target>In diesem Fall würden Sie die Authentifizierungs-URL auf auth.example.com und die Cookie-Domain auf example.com setzen.</target>
</trans-unit>
<trans-unit id="s31d15c6f16951464">
<source>Authentication URL</source>
<target>URL zur Authentifizierung</target>
</trans-unit>
<trans-unit id="sa03fe48e892df2d8">
<source>The external URL you'll authenticate at. The authentik core server should be reachable under this URL.</source>
<target>Die externe URL, bei der Sie sich authentifizieren. Unter dieser URL sollte der Authentik Core Server erreichbar sein.</target>
</trans-unit>
<trans-unit id="s7def067ed3ad3ad9">
<source>Cookie domain</source>
<target>Cookie-Domain</target>
</trans-unit>
<trans-unit id="s211b75e868072162">
<source>Set this to the domain you wish the authentication to be valid for. Must be a parent domain of the URL above. If you're running applications as app1.domain.tld, app2.domain.tld, set this to 'domain.tld'.</source>
<target>Stellen Sie dies auf die Domäne ein, für die die Authentifizierung gültig sein soll. Muss eine übergeordnete Domain der obigen URL sein. Wenn Sie Anwendungen als app1.domain.tld, app2.domain.tld ausführen, setzen Sie dies auf „domain.tld“.</target>
</trans-unit>
<trans-unit id="s2345170f7e272668">
<source>Unknown proxy mode</source>
</trans-unit>
<trans-unit id="s7c10976de6411844">
<source>Token validity</source>
<target>Token-Gültigkeit</target>
</trans-unit>
<trans-unit id="s3e87ce98ba3c4d80">
<source>Configure how long tokens are valid for.</source>
<target>Konfigurieren Sie, wie lange Token gültig sind.</target>
</trans-unit>
<trans-unit id="sd539548ca4c71619">
<source>Additional scopes</source>
<target>Zusätzliche Scopes</target>
</trans-unit>
<trans-unit id="s8f12575f694e85a2">
<source>Additional scope mappings, which are passed to the proxy.</source>
<target>Zusätzliche Bereichszuordnungen, die an den Proxy übergeben werden.</target>
</trans-unit>
<trans-unit id="s93cea6ca1f93349d">
<source>Unauthenticated URLs</source>
<target>Nicht authentifizierte URLs</target>
</trans-unit>
<trans-unit id="sc4508175bf6b09dd">
<source>Unauthenticated Paths</source>
<target>Nicht authentifizierte Pfade</target>
</trans-unit>
<trans-unit id="sc9fc206433f67588">
<source>Regular expressions for which authentication is not required. Each new line is interpreted as a new expression.</source>
<target>Reguläre Ausdrücke, für die keine Authentifizierung erforderlich ist. Jede neue Zeile wird als neuer Ausdruck interpretiert.</target>
</trans-unit>
<trans-unit id="sd503fabef9691134">
<source>When using proxy or forward auth (single application) mode, the requested URL Path is checked against the regular expressions. When using forward auth (domain mode), the full requested URL including scheme and host is matched against the regular expressions.</source>
<target>Bei Verwendung des Proxy- oder Forward-Authentifizierungsmodus (Einzelanwendung) wird der angeforderte URL-Pfad mit den regulären Ausdrücken verglichen. Bei Verwendung von Forward Auth (Domänenmodus) wird die vollständige angeforderte URL einschließlich Schema und Host mit den regulären Ausdrücken abgeglichen.</target>
</trans-unit>
<trans-unit id="sb488dee0be434f7e">
<source>Authentication settings</source>
</trans-unit>
<trans-unit id="s23cee624c735f266">
<source>Intercept header authentication</source>
</trans-unit>
<trans-unit id="sc007cca5af67eae0">
<source>When enabled, authentik will intercept the Authorization header to authenticate the request.</source>
</trans-unit>
<trans-unit id="s36e630ba56617556">
<source>Send HTTP-Basic Authentication</source>
</trans-unit>
<trans-unit id="s9d5796a4b9b7560e">
<source>Send a custom HTTP-Basic Authentication header based on values from authentik.</source>
</trans-unit>
<trans-unit id="s11204eeb1e27ea8f">
<source>ACS URL</source>
<target>ACS URL</target>
</trans-unit>
<trans-unit id="sb7a30abc1dcf6c36">
<source>Issuer</source>
<target>Aussteller</target>
</trans-unit>
<trans-unit id="sf54c562d8a10ce77">
<source>Also known as EntityID.</source>
<target>Auch bekannt als EntityID.</target>
</trans-unit>
<trans-unit id="s991b750e2d5c4234">
<source>Service Provider Binding</source>
<target>Service Anbieter Bindung</target>
</trans-unit>
<trans-unit id="sd8f220c999726151">
<source>Redirect</source>
<target>Umleiten</target>
</trans-unit>
<trans-unit id="sb357ea19a722d827">
<source>Post</source>
<target>Post</target>
</trans-unit>
<trans-unit id="s4e28e2899e08a5f8">
<source>Determines how authentik sends the response back to the Service Provider.</source>
<target>Legt fest, wie authentik die Antwort an den Service Provider zurücksendet.</target>
</trans-unit>
<trans-unit id="sd5a4b41c6c883b03">
<source>Audience</source>
<target>Zielgruppe</target>
</trans-unit>
<trans-unit id="sc741d9ebe07ad103">
<source>Signing Certificate</source>
<target>Signierzertifikat</target>
</trans-unit>
<trans-unit id="sd6c3ddb62de0e8f7">
<source>Certificate used to sign outgoing Responses going to the Service Provider.</source>
<target>Zertifikat, das zum Signieren ausgehender Antworten an den Dienstanbieter verwendet wird.</target>
</trans-unit>
<trans-unit id="s5be3b0567172e415">
<source>Verification Certificate</source>
<target>Zertifikat zur Überprüfung</target>
</trans-unit>
<trans-unit id="s7c27e113f90a89e0">
<source>When selected, incoming assertion's Signatures will be validated against this certificate. To allow unsigned Requests, leave on default.</source>
<target>Wenn diese Option ausgewählt ist, werden die Signaturen eingehender Behauptungen anhand dieses Zertifikats validiert. Um nicht signierte Anfragen zuzulassen, belassen Sie die Standardeinstellung.</target>
</trans-unit>
<trans-unit id="se6d950402810c34f">
<source>Property mappings</source>
<target>Eigenschaftszuordnung(en)</target>
</trans-unit>
<trans-unit id="s1a2797874b7fe852">
<source>NameID Property Mapping</source>
<target>Name ID Eigenschaft</target>
</trans-unit>
<trans-unit id="s256b8452664ccae4">
<source>Configure how the NameID value will be created. When left empty, the NameIDPolicy of the incoming request will be respected.</source>
<target>Konfigurieren Sie, wie der NameID-Wert erstellt wird. Wenn es leer gelassen wird, wird die NameIDPolicy der eingehenden Anfrage respektiert.</target>
</trans-unit>
<trans-unit id="s9f91cc8bcfabb40f">
<source>Assertion valid not before</source>
<target>SAML Assertion nicht gültig vor</target>
</trans-unit>
<trans-unit id="s733f83ff9d50da30">
<source>Configure the maximum allowed time drift for an assertion.</source>
<target>Konfigurieren Sie die maximal zulässige Zeitdrift für eine 'Assertion'</target>
</trans-unit>
<trans-unit id="s2af5754090898640">
<source>Assertion valid not on or after</source>
<target>SAML Assertion gilt nicht am oder danach</target>
</trans-unit>
<trans-unit id="s43c1f927936f0a02">
<source>Assertion not valid on or after current time + this value.</source>
<target>Behauptung nicht gültig am oder nach dem aktuellen Zeitpunkt + diesem Wert.</target>
</trans-unit>
<trans-unit id="sad8550b8731518d8">
<source>Session valid not on or after</source>
<target>Session gültig nicht am oder nach</target>
</trans-unit>
<trans-unit id="s0dd00fbaba08748a">
<source>Session not valid on or after current time + this value.</source>
</trans-unit>
<trans-unit id="s2a0f60e74b478804">
<source>Digest algorithm</source>
<target>Digest-Algorithmus</target>
</trans-unit>
<trans-unit id="s693d975d38ff0214">
<source>Signature algorithm</source>
<target>Signaturalgorithmus</target>
</trans-unit>
<trans-unit id="sd1a5560fde6f2271">
<source>Successfully imported provider.</source>
<target>Anbieter erfolgreich importiert.</target>
</trans-unit>
<trans-unit id="s252a52330d32b900">
<source>Metadata</source>
<target>Metadaten</target>
</trans-unit>
<trans-unit id="s7181a5504472e856">
<source>Apply changes</source>
</trans-unit>
<trans-unit id="s5e8250fb85d64c23">
<source>Close</source>
<target>Schließen</target>
</trans-unit>
<trans-unit id="sad59707375956ad2">
<source>Finish</source>
<target>Fertig</target>
</trans-unit>
<trans-unit id="sc16e00a7a8b2fde2">
<source>Back</source>
<target>Zurück</target>
</trans-unit>
<trans-unit id="sd5903cc8de68b3fc">
<source>No form found</source>
<target>Kein Formular gefunden</target>
</trans-unit>
<trans-unit id="s45935843b1b5b496">
<source>Form didn't return a promise for submitting</source>
<target>Das Formular hat keinen Wert zum Absenden zurückgegeben</target>
</trans-unit>
<trans-unit id="s74475586afc1fb0f">
<source>Select type</source>
<target>Wählen Sie einen Typen.</target>
</trans-unit>
<trans-unit id="s0b3bf19b31dd6bac">
<source>Try the new application wizard</source>
</trans-unit>
<trans-unit id="sa18e1c6e0e6f16cc">
<source>The new application wizard greatly simplifies the steps required to create applications and providers.</source>
</trans-unit>
<trans-unit id="s01ef54f5d7c6ed47">
<source>Try it now</source>
</trans-unit>
<trans-unit id="s382a2aa3984474dd">
<source>Create</source>
<target>Erstellen</target>
</trans-unit>
<trans-unit id="s58d1eb482059da12">
<source>New provider</source>
<target>Neuer Anbieter</target>
</trans-unit>
<trans-unit id="sa661ea7d7a50f2e9">
<source>Create a new provider.</source>
<target>Neuen Anbieter erstellen.</target>
</trans-unit>
<trans-unit id="s5d6af4c100ad321b">
<source>Create <x id="0" equiv-text="${type.name}"/></source>
<target>
<x id="0" equiv-text="${type.name}"/>erstellen</target>
</trans-unit>
<trans-unit id="sb95baab425322600">
<source>Shared secret</source>
</trans-unit>
<trans-unit id="s9e9316a6b0c16231">
<source>Client Networks</source>
</trans-unit>
<trans-unit id="s7f2dcf01f7a8c0b7">
<source>List of CIDRs (comma-seperated) that clients can connect from. A more specific
CIDR will match before a looser one. Clients connecting from a non-specified CIDR
will be dropped.</source>
</trans-unit>
<trans-unit id="s61eacb19db252f5e">
<source>URL</source>
</trans-unit>
<trans-unit id="sb21f33b039c86322">
<source>SCIM base url, usually ends in /v2.</source>
</trans-unit>
<trans-unit id="se68398e3c2c760b2">
<source>Token</source>
<target>Token</target>
</trans-unit>
<trans-unit id="s33ed903c210a6209">
<source>Token to authenticate with. Currently only bearer authentication is supported.</source>
</trans-unit>
<trans-unit id="sfc8bb104e2c05af8">
<source>User filtering</source>
</trans-unit>
<trans-unit id="sc0d0890fbd46ef62">
<source>Exclude service accounts</source>
</trans-unit>
<trans-unit id="s98b1cb8fb62909ec">
<source>Group</source>
<target>Gruppe</target>
</trans-unit>
<trans-unit id="s23ab136ad85f0ad2">
<source>Only sync users within the selected group.</source>
</trans-unit>
<trans-unit id="sfdedc3b0b2b7ce3d">
<source>Attribute mapping</source>
</trans-unit>
<trans-unit id="saf794c74c9ea731e">
<source>User Property Mappings</source>
<target>Benutzereigenschaftszuordnungen</target>
</trans-unit>
<trans-unit id="s019555b5a442aa00">
<source>Property mappings used to user mapping.</source>
</trans-unit>
<trans-unit id="s7cb9aa9ee1783f00">
<source>Group Property Mappings</source>
<target>Gruppeneigenschaftszuordnungen</target>
</trans-unit>
<trans-unit id="sa319e3bf44c85963">
<source>Property mappings used to group creation.</source>
<target>Für die Gruppenerstellung verwendete Eigenschaftszuordnungen.</target>
</trans-unit>
<trans-unit id="se09ab93d69f7f45b">
<source>Not used by any other object.</source>
<target>Von keinem anderen Objekt verwendet.</target>
</trans-unit>
<trans-unit id="s10922bd0ac765562">
<source>object will be DELETED</source>
<target>Objekt wird GELÖSCHT</target>
</trans-unit>
<trans-unit id="sf3981f36525b0dbd">
<source>connection will be deleted</source>
<target>Verbindung wird gelöscht</target>
</trans-unit>
<trans-unit id="s93cf77a59db53395">
<source>reference will be reset to default value</source>
<target>Referenz wird auf den Standardwert zurückgesetzt</target>
</trans-unit>
<trans-unit id="s3e211d29fa10f843">
<source>reference will be set to an empty value</source>
<target>Referenz wird auf einen leeren Wert gesetzt</target>
</trans-unit>
<trans-unit id="s55fa598b754cc3cc">
<source><x id="0" equiv-text="${ub.name}"/> (<x id="1" equiv-text="${consequence}"/>)</source>
<target>
<x id="0" equiv-text="${ub.name}"/>(
<x id="1" equiv-text="${consequence}"/>)</target>
</trans-unit>
<trans-unit id="s09240e07b5b8d640">
<source>ID</source>
<target>ID</target>
</trans-unit>
<trans-unit id="se33b158a1ec02a09">
<source>Successfully deleted <x id="0" equiv-text="${this.objects.length} ${this.objectLabel}"/></source>
</trans-unit>
<trans-unit id="sf6eb148db23d19de">
<source>Failed to delete <x id="0" equiv-text="${this.objectLabel}"/>: <x id="1" equiv-text="${e.toString()}"/></source>
<target>Löschen von
<x id="0" equiv-text="${this.objectLabel}"/>fehlgeschlagen:
<x id="1" equiv-text="${e.toString()}"/></target>
</trans-unit>
<trans-unit id="s039b6434e8a75560">
<source>Delete <x id="0" equiv-text="${this.objectLabel}"/></source>
<target>
<x id="0" equiv-text="${this.objectLabel}"/>löschen</target>
</trans-unit>
<trans-unit id="s5819a49638f6d7cb">
<source>Are you sure you want to delete <x id="0" equiv-text="${this.objects.length} ${this.objectLabel}"/>?</source>
</trans-unit>
<trans-unit id="sdc673e73b5c13aea">
<source>Delete</source>
<target>Löschen</target>
</trans-unit>
<trans-unit id="sb0b86b8ca6ab13bd">
<source>Providers</source>
<target>Anbieter</target>
</trans-unit>
<trans-unit id="s3ffa320128991a45">
<source>Provide support for protocols like SAML and OAuth to assigned applications.</source>
<target>Stellen Unterstützung für Protokolle wie SAML und OAuth für zugewiesene Anwendungen bereit.</target>
</trans-unit>
<trans-unit id="sd2223afb7d6b100d">
<source>Type</source>
<target>Typ</target>
</trans-unit>
<trans-unit id="s10929ca568ae10bc">
<source>Provider(s)</source>
<target>Anbieter</target>
</trans-unit>
<trans-unit id="sb2b3b281954752c4">
<source>Assigned to application </source>
<target>Zugewiesen an Anwendung</target>
</trans-unit>
<trans-unit id="sa6c0ba4910c7ad7f">
<source>Assigned to application (backchannel) </source>
</trans-unit>
<trans-unit id="s97f5e0c138eae172">
<source>Warning: Provider not assigned to any application.</source>
<target>Warnung: Provider ist keiner Applikation zugewiesen</target>
</trans-unit>
<trans-unit id="s8b0432eecbd8b034">
<source>Update</source>
<target>Aktualisieren</target>
</trans-unit>
<trans-unit id="sc9175cb129fdc306">
<source>Update <x id="0" equiv-text="${item.verboseName}"/></source>
<target>Aktualisiere
<x id="0" equiv-text="${item.verboseName}"/></target>
</trans-unit>
<trans-unit id="s398f6ba74ba8943a">
<source>Select providers to add to application</source>
</trans-unit>
<trans-unit id="sf9aee319a006c9b4">
<source>Add</source>
<target>Hinzufügen</target>
</trans-unit>
<trans-unit id="sa90b7809586c35ce">
<source>Either input a full URL, a relative path, or use 'fa://fa-test' to use the Font Awesome icon "fa-test".</source>
<target>Geben Sie entweder eine vollständige URL oder einen relativen Pfad ein oder geben Sie 'fa://fa-test' ein, um das Font Awesome-Icon "fa-test" zu verwenden</target>
</trans-unit>
<trans-unit id="s0410779cb47de312">
<source>Path template for users created. Use placeholders like `%(slug)s` to insert the source slug.</source>
</trans-unit>
<trans-unit id="s58fd2aafa4261c55">
<source>Successfully updated application.</source>
<target>Anwendung erfolgreich aktualisiert.</target>
</trans-unit>
<trans-unit id="s9222ca30ae7786e4">
<source>Successfully created application.</source>
<target>Anwendung erfolgreich erstellt.</target>
</trans-unit>
<trans-unit id="s03907d7a66c6164e">
<source>Application's display Name.</source>
<target>Anzeigename der Applikation</target>
</trans-unit>
<trans-unit id="s91f70424f5d5d23e">
<source>Slug</source>
<target>Slug</target>
</trans-unit>
<trans-unit id="sdae55084f6cb2662">
<source>Optionally enter a group name. Applications with identical groups are shown grouped together.</source>
<target>Geben Sie optional einen Gruppennamen ein. Anwendungen in gleicher Gruppe werden gruppiert angezeigt.</target>
</trans-unit>
<trans-unit id="s7f5869b3d14d7cbc">
<source>Provider</source>
<target>Schnittstellen</target>
</trans-unit>
<trans-unit id="s350a616ff5e145ec">
<source>Select a provider that this application should use.</source>
</trans-unit>
<trans-unit id="s4c6534a118f52fdd">
<source>Select backchannel providers which augment the functionality of the main provider.</source>
</trans-unit>
<trans-unit id="s0639662111324466">
<source>Policy engine mode</source>
<target>Richtlinien-Engine-Modus</target>
</trans-unit>
<trans-unit id="s1a0e95458b44d7f8">
<source>Any policy must match to grant access</source>
</trans-unit>
<trans-unit id="s7fc1ace65486dc25">
<source>All policies must match to grant access</source>
</trans-unit>
<trans-unit id="s8be4abc7ca71da6c">
<source>UI settings</source>
<target>UI-Einstellungen</target>
</trans-unit>
<trans-unit id="s427f788ff333f45b">
<source>Launch URL</source>
<target>Start URL</target>
</trans-unit>
<trans-unit id="s992f8d1a776e763c">
<source>If left empty, authentik will try to extract the launch URL based on the selected provider.</source>
<target>Wenn diese Option leer bleibt, versucht authentik, die Start-URL auf der Grundlage des ausgewählten Anbieters zu extrahieren.</target>
</trans-unit>
<trans-unit id="s2348f46ebf436671">
<source>Open in new tab</source>
</trans-unit>
<trans-unit id="s8655c52824caac63">
<source>If checked, the launch URL will open in a new browser tab or window from the user's application library.</source>
</trans-unit>
<trans-unit id="s068d4dd16d9106d0">
<source>Icon</source>
<target>Symbol</target>
</trans-unit>
<trans-unit id="s67e20cd8018d7e3c">
<source>Currently set to:</source>
<target>Aktuell eingestellt auf:</target>
</trans-unit>
<trans-unit id="s80e6d6fe5ad458d3">
<source>Clear icon</source>
<target>Symbol zurücksetzen</target>
</trans-unit>
<trans-unit id="s6d3b4d0561ba1cff">
<source>Publisher</source>
<target>Herausgeber</target>
</trans-unit>
<trans-unit id="sa8c45b6b92a8ba1f">
<source>Create Application</source>
<target>Anwendung erstellen</target>
</trans-unit>
<trans-unit id="s3d197283cb019b5a">
<source>Overview</source>
<target>Übersicht</target>
</trans-unit>
<trans-unit id="s6c3daaac4eed12f9">
<source>Changelog</source>
<target>Versionsverlauf</target>
</trans-unit>
<trans-unit id="s05e395ff60af047b">
<source>Warning: Provider is not used by any Outpost.</source>
<target>Warnung: Der Anbieter wird von keinem Outpost verwendet.</target>
</trans-unit>
<trans-unit id="sccbfc4dec0c8d80c">
<source>Assigned to application</source>
<target>Zugewiesen an Anwendung</target>
</trans-unit>
<trans-unit id="s2d46e3a9ee8e0e7e">
<source>Update LDAP Provider</source>
<target>Aktualisieren Sie den LDAP-Anbieter</target>
</trans-unit>
<trans-unit id="s64ef2a6c2dd1d3d1">
<source>Edit</source>
<target>Bearbeiten</target>
</trans-unit>
<trans-unit id="saf24e253b3b006d4">
<source>How to connect</source>
<target>So verbinden Sie sich</target>
</trans-unit>
<trans-unit id="s02b3fade1795d03f">
<source>Connect to the LDAP Server on port 389:</source>
<target>Verbindung zum LDAP Server auf Port 389:</target>
</trans-unit>
<trans-unit id="sa00cf67b54c44c71">
<source>Check the IP of the Kubernetes service, or</source>
<target>IP des Kubernetes-Service überprüfen, oder</target>
</trans-unit>
<trans-unit id="s28f270859c5f4d51">
<source>The Host IP of the docker host</source>
<target>Die Host-IP des Docker-Hosts</target>
</trans-unit>
<trans-unit id="sb7794c2910b1a9ec">
<source>Bind DN</source>
<target>Bind DN</target>
</trans-unit>
<trans-unit id="s5694f9421c428227">
<source>Bind Password</source>
<target>Bind Password</target>
</trans-unit>
<trans-unit id="s086e1bbe7c97ea16">
<source>Search base</source>
<target>Suchbasis</target>
</trans-unit>
<trans-unit id="s417b90913e05bc17">
<source>Preview</source>
</trans-unit>
<trans-unit id="s17f3eaf3b07ece26">
<source>Warning: Provider is not used by an Application.</source>
<target>Warnung: Der Anbieter wird nicht von einer Anwendung verwendet.</target>
</trans-unit>
<trans-unit id="s56806e9f63efa298">
<source>Redirect URIs</source>
<target>URIs weiterleiten</target>
</trans-unit>
<trans-unit id="sdbc08adee233f180">
<source>Update OAuth2 Provider</source>
<target>Aktualisieren Sie den OAuth2-Anbieter</target>
</trans-unit>
<trans-unit id="s9d96eb5ca93e6473">
<source>OpenID Configuration URL</source>
<target>OpenID-Konfigurations-URL</target>
</trans-unit>
<trans-unit id="s74f809a69e030351">
<source>OpenID Configuration Issuer</source>
<target>OpenID-Konfigurations-Aussteller</target>
</trans-unit>
<trans-unit id="s028be8989873f001">
<source>Authorize URL</source>
<target>Autorisiere URL</target>
</trans-unit>
<trans-unit id="sebda1d54a3f9f967">
<source>Token URL</source>
<target>Token URL</target>
</trans-unit>
<trans-unit id="s2fc3eb68c7ced3af">
<source>Userinfo URL</source>
<target>Benutzerinfo-URL</target>
</trans-unit>
<trans-unit id="s145483489b87a622">
<source>Logout URL</source>
<target>Abmelde-URL</target>
</trans-unit>
<trans-unit id="s59f5eda30a904b75">
<source>JWKS URL</source>
<target>JWKS URL</target>
</trans-unit>
<trans-unit id="s453b0c150a7ca58e">
<source>Example JWT payload (for currently authenticated user)</source>
</trans-unit>
<trans-unit id="sc6e8a34361c7c272">
<source>Forward auth (domain-level)</source>
<target>Authentifizierung weiterleiten (Domänenebene)</target>
</trans-unit>
<trans-unit id="s6df42b3072a2d7e9">
<source>Nginx (Ingress)</source>
<target>Nginx (Ingress)</target>
</trans-unit>
<trans-unit id="s8e01a852c1db8d29">
<source>Nginx (Proxy Manager)</source>
<target>Nginx (Proxy-Manager)</target>
</trans-unit>
<trans-unit id="sabebdc7fa6a5bddb">
<source>Nginx (standalone)</source>
<target>Nginx (eigenständig)</target>
</trans-unit>
<trans-unit id="s5d9f93f1fe1c19d3">
<source>Traefik (Ingress)</source>
<target>Traefik (Ingress)</target>
</trans-unit>
<trans-unit id="se2b62f7e9017965e">
<source>Traefik (Compose)</source>
<target>Traefik (Compose)</target>
</trans-unit>
<trans-unit id="s4c4c504a48c3b7bd">
<source>Traefik (Standalone)</source>
<target>Traefik (eigenständig)</target>
</trans-unit>
<trans-unit id="s7ba9677d069e5f02">
<source>Caddy (Standalone)</source>
</trans-unit>
<trans-unit id="s4a1e774ab25aa232">
<source>Internal Host</source>
<target>Interner Host</target>
</trans-unit>
<trans-unit id="sc9c3578cce3cf7a8">
<source>External Host</source>
<target>Externer Host</target>
</trans-unit>
<trans-unit id="s7a141f1b61074fbe">
<source>Basic-Auth</source>
<target>Basic-Auth</target>
</trans-unit>
<trans-unit id="scb489a1a173ac3f0">
<source>Yes</source>
<target>Ja</target>
</trans-unit>
<trans-unit id="s37cbecaec58e2192">
<source>Mode</source>
<target>Modus</target>
</trans-unit>
<trans-unit id="s4e474b9e2e737dd1">
<source>Update Proxy Provider</source>
<target>Proxy-Anbieter aktualisieren</target>
</trans-unit>
<trans-unit id="s37eb2f1b6e3c19c2">
<source>Protocol Settings</source>
<target>Protokolleinstellungen</target>
</trans-unit>
<trans-unit id="s5116b89f7db1fbec">
<source>Allowed Redirect URIs</source>
<target>Erlaubte Weiterleitungs-URIs</target>
</trans-unit>
<trans-unit id="saeff3596e1ac31b6">
<source>Setup</source>
<target>Einrichtung</target>
</trans-unit>
<trans-unit id="s1b783856ab4aaaf3">
<source>No additional setup is required.</source>
<target>Keine weitere Einrichtung benötigt.</target>
</trans-unit>
<trans-unit id="s09b671b120443043">
<source>Update Radius Provider</source>
</trans-unit>
<trans-unit id="sd3386a2ef42e80b9">
<source>Download</source>
<target>Download</target>
</trans-unit>
<trans-unit id="sf417c13d7a0f7995">
<source>Copy download URL</source>
<target>Download URL kopieren</target>
</trans-unit>
<trans-unit id="sc1cfce89ebcf1bf9">
<source>Download signing certificate</source>
<target>Signierzertifikat herunterladen</target>
</trans-unit>
<trans-unit id="s2c0de3d35a7bc784">
<source>Related objects</source>
<target>Verwandte Objekte</target>
</trans-unit>
<trans-unit id="s803b0621006085be">
<source>Update SAML Provider</source>
<target>Aktualisieren Sie den SAML-Anbieter</target>
</trans-unit>
<trans-unit id="s44b1f042790cd1a2">
<source>SAML Configuration</source>
</trans-unit>
<trans-unit id="sba999428083abce3">
<source>EntityID/Issuer</source>
</trans-unit>
<trans-unit id="scd2984ee5552643a">
<source>SSO URL (Post)</source>
</trans-unit>
<trans-unit id="saa79b47f60c66458">
<source>SSO URL (Redirect)</source>
</trans-unit>
<trans-unit id="s2da51a6287118ba8">
<source>SSO URL (IdP-initiated Login)</source>
</trans-unit>
<trans-unit id="s0a57e911e457302b">
<source>SLO URL (Post)</source>
</trans-unit>
<trans-unit id="s1e7308bb1ca323e1">
<source>SLO URL (Redirect)</source>
</trans-unit>
<trans-unit id="sd2c58d7c6dddc515">
<source>SAML Metadata</source>
<target>SAML-Metadaten</target>
</trans-unit>
<trans-unit id="s382b702673776873">
<source>Example SAML attributes</source>
</trans-unit>
<trans-unit id="sea3bfc143ced73db">
<source>NameID attribute</source>
</trans-unit>
<trans-unit id="s2f0f6691de0b0388">
<source>Warning: Provider is not assigned to an application as backchannel provider.</source>
</trans-unit>
<trans-unit id="sc6c575c5ff64cdb1">
<source>Update SCIM Provider</source>
</trans-unit>
<trans-unit id="sbecf8dc03c978d15">
<source>Run sync again</source>
<target>Synchronisation erneut ausführen</target>
</trans-unit>
<trans-unit id="sc2cedfb22488ccb2">
<source>Modern applications, APIs and Single-page applications.</source>
</trans-unit>
<trans-unit id="sc3259eb55cf91e8c">
<source>LDAP</source>
<target>LDAP</target>
</trans-unit>
<trans-unit id="sffd5481034a1bd41">
<source>Provide an LDAP interface for applications and users to authenticate against.</source>
</trans-unit>
<trans-unit id="s0c9670f429e74283">
<source>New application</source>
</trans-unit>
<trans-unit id="s6ba50bb0842ba1e2">
<source>Applications</source>
<target>Anwendungen</target>
</trans-unit>
<trans-unit id="s96b2fefc550e4b1c">
<source>Provider Type</source>
<target>Anbietertyp</target>
</trans-unit>
<trans-unit id="sd20f6cd02c90867f">
<source>Application(s)</source>
<target>Anwendung(en)</target>
</trans-unit>
<trans-unit id="sb564f81eb057342e">
<source>Application Icon</source>
<target>Anwendungs-Symbol</target>
</trans-unit>
<trans-unit id="sa347e31efbb60be2">
<source>Update Application</source>
<target>Anwendung aktualisieren</target>
</trans-unit>
<trans-unit id="sd9b556a84ae25690">
<source>Successfully sent test-request.</source>
<target>Testanfrage erfolgreich gesendet.</target>
</trans-unit>
<trans-unit id="s5deac600e329de1b">
<source>Log messages</source>
<target>Logeinträge</target>
</trans-unit>
<trans-unit id="s3feea7b49673bef2">
<source>No log messages.</source>
<target>Keine Logeinträge.</target>
</trans-unit>
<trans-unit id="sa45a194b58837e4f">
<source>Active</source>
<target>Aktiv</target>
</trans-unit>
<trans-unit id="s58c867aac77b9158">
<source>Last login</source>
<target>Letzte Anmeldung</target>
</trans-unit>
<trans-unit id="s3e3bb9e7cb1de4fd">
<source>Select users to add</source>
<target>Wählen Sie die hinzuzufügenden Benutzer aus</target>
</trans-unit>
<trans-unit id="s75d5ff5dd8d3c6d2">
<source>Successfully updated group.</source>
<target>Gruppe erfolgreich aktualisiert.</target>
</trans-unit>
<trans-unit id="s3079ca1184e77573">
<source>Successfully created group.</source>
<target>Gruppe erfolgreich erstellt.</target>
</trans-unit>
<trans-unit id="s63cb05541b294335">
<source>Is superuser</source>
<target>Ist Admin</target>
</trans-unit>
<trans-unit id="s29315e374008d0c5">
<source>Users added to this group will be superusers.</source>
<target>Benutzer dieser Gruppe werden als Superuser hinzugefügt.</target>
</trans-unit>
<trans-unit id="s4eb514ebcb80553d">
<source>Parent</source>
<target>Übergeordnet</target>
</trans-unit>
<trans-unit id="s16b9446e3a70e1f4">
<source>Attributes</source>
<target>Attribute</target>
</trans-unit>
<trans-unit id="sec97cdaf7af8648b">
<source>Set custom attributes using YAML or JSON.</source>
<target>Selbstdefinierte Attribute können mittels YAML oder JSON festgelegt werden.</target>
</trans-unit>
<trans-unit id="s1e36813d3504ed48">
<source>Successfully updated binding.</source>
<target>Bindung erfolgreich aktualisiert.</target>
</trans-unit>
<trans-unit id="s1bf56ee106e9e711">
<source>Successfully created binding.</source>
<target>Bindung erfolgreich erstellt.</target>
</trans-unit>
<trans-unit id="s042baf59902a711f">
<source>Policy</source>
<target>Richtlinie</target>
</trans-unit>
<trans-unit id="s5f5bf4ef2bd93c04">
<source>Group mappings can only be checked if a user is already logged in when trying to access this source.</source>
<target>Gruppenzuordnungen können nur überprüft werden, wenn der Benutzer beim Zugriff auf diese Quelle bereits angemeldet ist.</target>
</trans-unit>
<trans-unit id="s6c607d74bdfe9f36">
<source>User mappings can only be checked if a user is already logged in when trying to access this source.</source>
<target>Benutzerzuordnungen können nur überprüft werden, wenn der Benutzer beim Zugriff auf diese Quelle bereits angemeldet ist.</target>
</trans-unit>
<trans-unit id="s965c503c3e42fdfe">
<source>Enabled</source>
<target>Aktiviert</target>
</trans-unit>
<trans-unit id="s6b85380416964890">
<source>Negate result</source>
<target>Ergebnis verneinen</target>
</trans-unit>
<trans-unit id="s3bfa0258999fb629">
<source>Negates the outcome of the binding. Messages are unaffected.</source>
<target>Negiert das Ergebnis der Bindung. Nachrichten sind nicht betroffen.</target>
</trans-unit>
<trans-unit id="s2ba5f4d8f3bd7c57">
<source>Order</source>
<target>Reihenfolge</target>
</trans-unit>
<trans-unit id="se1e040b55319a0e8">
<source>Timeout</source>
<target>Zeitlimit</target>
</trans-unit>
<trans-unit id="s29ec5e7889f4787f">
<source>Successfully updated policy.</source>
<target>Richtlinie erfolgreich aktualisiert.</target>
</trans-unit>
<trans-unit id="sfc400b2d71e49d28">
<source>Successfully created policy.</source>
<target>Richtlinie erfolgreich erstellt.</target>
</trans-unit>
<trans-unit id="safc0e0656d572f4e">
<source>A policy used for testing. Always returns the same result as specified below after waiting a random duration.</source>
<target>Eine Richtlinie, die zum Testen verwendet wird. Gibt nach einer zufälligen Wartezeit immer das unten angegeben Ergebnis zurück.</target>
</trans-unit>
<trans-unit id="s9ffa1ac03ce6fd20">
<source>Execution logging</source>
<target>Ausführungsprotokollierung</target>
</trans-unit>
<trans-unit id="saf31b3c610036ed6">
<source>When this option is enabled, all executions of this policy will be logged. By default, only execution errors are logged.</source>
<target>Wenn diese Option aktiviert ist, werden alle Ausführungen dieser Richtlinie protokolliert. Standardmäßig werden nur Ausführungsfehler protokolliert.</target>
</trans-unit>
<trans-unit id="sa879d5ce584875cf">
<source>Policy-specific settings</source>
<target>Richtlinienspezifische Einstellungen</target>
</trans-unit>
<trans-unit id="s838418d1a0815157">
<source>Pass policy?</source>
<target>Pass-Richtlinie?</target>
</trans-unit>
<trans-unit id="sd8c5339b82b71507">
<source>Wait (min)</source>
<target>Wartezeit (min.)</target>
</trans-unit>
<trans-unit id="sda4e78c19f5b6f35">
<source>The policy takes a random time to execute. This controls the minimum time it will take.</source>
<target>Die Ausführung der Richtlinie dauert eine zufällige Zeit. Dies steuert die Mindestzeit, die dafür benötigt wird.</target>
</trans-unit>
<trans-unit id="s1d30ff9ba938e68d">
<source>Wait (max)</source>
<target>Wartezeit (max.)</target>
</trans-unit>
<trans-unit id="s303b5e552246e613">
<source>Matches an event against a set of criteria. If any of the configured values match, the policy passes.</source>
<target>Gleicht ein Ereignis mit einer Reihe von Kriterien ab. Wenn einer der konfigurierten Werte übereinstimmt, wird die Richtlinie bestanden.</target>
</trans-unit>
<trans-unit id="s890810efbe103cbc">
<source>Match created events with this action type. When left empty, all action types will be matched.</source>
<target>Ordnen Sie erstellte Ereignisse diesem Aktionstyp zu. Wenn es leer gelassen wird, werden alle Aktionstypen abgeglichen.</target>
</trans-unit>
<trans-unit id="sfab527528ea64618">
<source>Matches Event's Client IP (strict matching, for network matching use an Expression Policy.</source>
<target>Stimmt mit der Client-IP des Ereignisses überein (strenge Übereinstimmung, verwenden Sie für die Netzwerkübereinstimmung eine Ausdrucksrichtlinie.</target>
</trans-unit>
<trans-unit id="s5a15a8f39c699273">
<source>Match events created by selected application. When left empty, all applications are matched.</source>
<target>Übereinstimmungsereignisse, die von der ausgewählten Anwendung erstellt wurden. Wenn es leer gelassen wird, werden alle Anwendungen abgeglichen.</target>
</trans-unit>
<trans-unit id="s5a13f4bbe004503f">
<source>Checks if the request's user's password has been changed in the last x days, and denys based on settings.</source>
<target>Überprüft, ob das Passwort des Benutzers der Anfrage in den letzten x Tagen geändert wurde, und lehnt es basierend auf den Einstellungen ab.</target>
</trans-unit>
<trans-unit id="sfad8af8ce38104a3">
<source>Maximum age (in days)</source>
<target>Höchstalter (in Tagen)</target>
</trans-unit>
<trans-unit id="s9307f3dbb07a73b5">
<source>Only fail the policy, don't invalidate user's password</source>
</trans-unit>
<trans-unit id="scea1f16238093e35">
<source>Executes the python snippet to determine whether to allow or deny a request.</source>
<target>Führt das Python-Snippet aus, um zu bestimmen, ob eine Anfrage zugelassen oder abgelehnt werden soll.</target>
</trans-unit>
<trans-unit id="sabd1bc9fb7da71e7">
<source>Expression using Python.</source>
<target>Ausdruck mit Python.</target>
</trans-unit>
<trans-unit id="s8d08843f397d9e81">
<source>See documentation for a list of all variables.</source>
<target>Eine Liste aller Variablen finden Sie in der Dokumentation.</target>
</trans-unit>
<trans-unit id="se2cc93bd2647baec">
<source>Static rules</source>
</trans-unit>
<trans-unit id="sc96dd9d2e7b05fc5">
<source>Minimum length</source>
<target>Mindestlänge</target>
</trans-unit>
<trans-unit id="s33d48fb745f4d4ae">
<source>Minimum amount of Uppercase Characters</source>
<target>Mindestanzahl an Großbuchstaben</target>
</trans-unit>
<trans-unit id="s883b544e2b4aa3b5">
<source>Minimum amount of Lowercase Characters</source>
<target>Mindestanzahl an Kleinbuchstaben</target>
</trans-unit>
<trans-unit id="s43be3ce2439ffe9c">
<source>Minimum amount of Digits</source>
<target>Mindestanzahl von Ziffern</target>
</trans-unit>
<trans-unit id="sb3651834cca86735">
<source>Minimum amount of Symbols Characters</source>
<target>Mindestanzahl an Sonderzeichen</target>
</trans-unit>
<trans-unit id="sc2f116c0ea77d58a">
<source>Error message</source>
<target>Fehlermeldung</target>
</trans-unit>
<trans-unit id="s21d0e290c51a8ef9">
<source>Symbol charset</source>
<target>Symbolzeichensatz</target>
</trans-unit>
<trans-unit id="s545d99afa61e4095">
<source>Characters which are considered as symbols.</source>
<target>Zeichen, die als Symbole betrachtet werden.</target>
</trans-unit>
<trans-unit id="s1293ad87acc7a609">
<source>HaveIBeenPwned settings</source>
</trans-unit>
<trans-unit id="sdf4e1c6a2f072600">
<source>Allowed count</source>
<target>Erlaubte Anzahl</target>
</trans-unit>
<trans-unit id="scd8062ff5e1326d8">
<source>Allow up to N occurrences in the HIBP database.</source>
<target>Erlaube bis zu N Einträge in der HIBP Datenbank.</target>
</trans-unit>
<trans-unit id="s3fd219b045193507">
<source>zxcvbn settings</source>
</trans-unit>
<trans-unit id="s28d84abfbaf555ea">
<source>Score threshold</source>
</trans-unit>
<trans-unit id="s7b3148ffba9f4527">
<source>If the password's score is less than or equal this value, the policy will fail.</source>
</trans-unit>
<trans-unit id="sd6cd7ce2310a73a4">
<source>Checks the value from the policy request against several rules, mostly used to ensure password strength.</source>
<target>Überprüft den Wert aus der Richtlinienanforderung anhand mehrerer Regeln, die hauptsächlich zur Gewährleistung der Kennwortstärke verwendet werden.</target>
</trans-unit>
<trans-unit id="s2a957e843960b604">
<source>Password field</source>
<target>Passwortfeld</target>
</trans-unit>
<trans-unit id="se8a81c75b6e30a33">
<source>Field key to check, field keys defined in Prompt stages are available.</source>
<target>Zu prüfender Feldschlüssel, die in den Aufforderungsstufen definierten Feldschlüssel sind verfügbar.</target>
</trans-unit>
<trans-unit id="s2f8c4cf12350a36c">
<source>Check static rules</source>
</trans-unit>
<trans-unit id="sd75a9a71309fb387">
<source>Check haveibeenpwned.com</source>
</trans-unit>
<trans-unit id="se5cb18408df3284e">
<source>For more info see:</source>
</trans-unit>
<trans-unit id="scef7abb8456b06d6">
<source>Check zxcvbn</source>
</trans-unit>
<trans-unit id="sdfdb58cd232b363d">
<source>Password strength estimator created by Dropbox, see:</source>
</trans-unit>
<trans-unit id="s40b034801fcb843b">
<source>Allows/denys requests based on the users and/or the IPs reputation.</source>
<target>Erlaubt/verweigert Anfragen auf der Grundlage der Reputation der Nutzer und/oder der IPs.</target>
</trans-unit>
<trans-unit id="scf4afecb0f1e69b2">
<source>Invalid login attempts will decrease the score for the client's IP, and the
username they are attempting to login as, by one.</source>
</trans-unit>
<trans-unit id="s8323a9af28e10502">
<source>The policy passes when the reputation score is below the threshold, and
doesn't pass when either or both of the selected options are equal or above the threshold.</source>
</trans-unit>
<trans-unit id="s1828fbfc2c56379c">
<source>Check IP</source>
<target>IP prüfen</target>
</trans-unit>
<trans-unit id="s4751df77cfd8a5f9">
<source>Check Username</source>
<target>Benutzername prüfen</target>
</trans-unit>
<trans-unit id="se19cc57dd8675498">
<source>Threshold</source>
<target>Schwellwert</target>
</trans-unit>
<trans-unit id="sdbccb39a658f0e45">
<source>New policy</source>
<target>Neue Richtlinie</target>
</trans-unit>
<trans-unit id="sf693300708a40d2c">
<source>Create a new policy.</source>
<target>Neue Richtlinie erstellen.</target>
</trans-unit>
<trans-unit id="s5b1fb0d4c0daeba8">
<source>Create Binding</source>
<target>Verknüpfung erstellen</target>
</trans-unit>
<trans-unit id="s9fb28be12e2c6317">
<source>Superuser</source>
<target>Administrator</target>
</trans-unit>
<trans-unit id="s9f5a5f23312798f0">
<source>Members</source>
<target>Mitglieder</target>
</trans-unit>
<trans-unit id="s7eb3d239e0b491ab">
<source>Select groups to add user to</source>
<target>Wählen Sie Gruppen aus, denen Benutzer hinzugefügt werden sollen</target>
</trans-unit>
<trans-unit id="sec5cdfa358f9dbf7">
<source>Warning: Adding the user to the selected group(s) will give them superuser permissions.</source>
</trans-unit>
<trans-unit id="scab2900019953050">
<source>Successfully updated user.</source>
<target>Benutzer erfolgreich aktualisiert.</target>
</trans-unit>
<trans-unit id="s9c3c272944dcfca3">
<source>Successfully created user.</source>
<target>Nutzer erfolgreich erstellt.</target>
</trans-unit>
<trans-unit id="s03f42eea72154959">
<source>Username</source>
<target>Anmeldename</target>
</trans-unit>
<trans-unit id="s5a802e46a033c8af">
<source>User's primary identifier. 150 characters or fewer.</source>
</trans-unit>
<trans-unit id="sd34be0d0fcb39971">
<source>User's display name.</source>
<target>Anzeigename</target>
</trans-unit>
<trans-unit id="sd1f44f1a8bc20e67">
<source>Email</source>
<target>E-Mail</target>
</trans-unit>
<trans-unit id="sbe3b416a356f1c91">
<source>Is active</source>
<target>Ist aktiv</target>
</trans-unit>
<trans-unit id="s35fac2e5677d55cd">
<source>Designates whether this user should be treated as active. Unselect this instead of deleting accounts.</source>
<target>Legt fest, ob dieser Benutzer als aktiv behandelt werden soll. Deaktivieren Sie dies, anstatt Konten zu löschen</target>
</trans-unit>
<trans-unit id="s2e532e19ed477a56">
<source>Path</source>
</trans-unit>
<trans-unit id="s67560d7e37d984c3">
<source>Policy / User / Group</source>
<target>Richtlinie / Benutzer / Gruppe</target>
</trans-unit>
<trans-unit id="s030ac0829bb50a49">
<source>Policy <x id="0" equiv-text="${item.policyObj?.name}"/></source>
<target>Richtlinie
<x id="0" equiv-text="${item.policyObj?.name}"/></target>
</trans-unit>
<trans-unit id="s2a64d2dca3da9b0e">
<source>Group <x id="0" equiv-text="${item.groupObj?.name}"/></source>
<target>Gruppe
<x id="0" equiv-text="${item.groupObj?.name}"/></target>
</trans-unit>
<trans-unit id="se5dc026819a32ff8">
<source>User <x id="0" equiv-text="${item.userObj?.name}"/></source>
<target>Benutzer
<x id="0" equiv-text="${item.userObj?.name}"/></target>
</trans-unit>
<trans-unit id="s50c312bea93b6925">
<source>Edit Policy</source>
<target>Richtlinie bearbeiten</target>
</trans-unit>
<trans-unit id="s0b55a57f473ab8af">
<source>Update Group</source>
<target>Gruppe aktualisieren</target>
</trans-unit>
<trans-unit id="s494e1ed913d9351a">
<source>Edit Group</source>
<target>Gruppe bearbeiten</target>
</trans-unit>
<trans-unit id="sad130c2d925fb7bf">
<source>Update User</source>
<target>Benutzer ändern</target>
</trans-unit>
<trans-unit id="s5cd31f4a88adf180">
<source>Edit User</source>
<target>Benutzer bearbeiten</target>
</trans-unit>
<trans-unit id="se291dfd2a59d7842">
<source>Policy binding(s)</source>
<target>Richtlinienbindung(en)</target>
</trans-unit>
<trans-unit id="s7e87ab366c199345">
<source>Update Binding</source>
<target>Bindung aktualisieren</target>
</trans-unit>
<trans-unit id="s40b80eb4cc1f0e0c">
<source>Edit Binding</source>
<target>Verknüpfung bearbeiten</target>
</trans-unit>
<trans-unit id="sbad5b96fb855ef36">
<source>No Policies bound.</source>
<target>Keine Richtlinien verknüpft.</target>
</trans-unit>
<trans-unit id="sc15d60377cc8aaac">
<source>No policies are currently bound to this object.</source>
<target>Aktuell sind keine Richtlinien mit diesem Objekt verknüpft.</target>
</trans-unit>
<trans-unit id="sddb040c47daae56b">
<source>Bind existing policy</source>
</trans-unit>
<trans-unit id="saa855c61e0403fe6">
<source>Warning: Application is not used by any Outpost.</source>
<target>Warnung: Die Anwendung wird von keinem Outpost verwendet.</target>
</trans-unit>
<trans-unit id="sb6cbd4f92ebaf5d8">
<source>Related</source>
<target>Verwandt</target>
</trans-unit>
<trans-unit id="sc92ea8fbf9ba06a7">
<source>Backchannel Providers</source>
</trans-unit>
<trans-unit id="sd71081c23d1cd38b">
<source>Check access</source>
<target>Zugang prüfen</target>
</trans-unit>
<trans-unit id="s42cbd8dca939a9c7">
<source>Check</source>
<target>Prüfung</target>
</trans-unit>
<trans-unit id="sf22f7f8a9309b4ed">
<source>Check Application access</source>
<target>Anwendungszugriff überprüfen</target>
</trans-unit>
<trans-unit id="s2474e7fb1aec9f05">
<source>Test</source>
<target>Testen</target>
</trans-unit>
<trans-unit id="s512957aa09384646">
<source>Launch</source>
<target>Starten</target>
</trans-unit>
<trans-unit id="sed02f831e653deb3">
<source>Logins over the last week (per 8 hours)</source>
</trans-unit>
<trans-unit id="s2b1bc31276c4c477">
<source>Policy / Group / User Bindings</source>
<target>Richtlinien / Gruppen / Nutzerverknüpfungen</target>
</trans-unit>
<trans-unit id="s473f0143efa3f706">
<source>These policies control which users can access this application.</source>
<target>Diese Richtlinien steuern, welche Benutzer auf diese Anwendung zugreifen können.</target>
</trans-unit>
<trans-unit id="s24875d5475e82526">
<source>Successfully updated source.</source>
<target>Quelle erfolgreich aktualisiert</target>
</trans-unit>
<trans-unit id="s60d891ed3ee9ebc5">
<source>Successfully created source.</source>
<target>Quelle erfolgreich erstellt.</target>
</trans-unit>
<trans-unit id="s8af7239354f7e7b6">
<source>Sync users</source>
<target>Benutzer synchronisieren</target>
</trans-unit>
<trans-unit id="sd80b0b8aeae3abe3">
<source>User password writeback</source>
<target>Rückschreiben des Benutzerkennworts</target>
</trans-unit>
<trans-unit id="s2b952e9dc99cbded">
<source>Login password is synced from LDAP into authentik automatically. Enable this option only to write password changes in authentik back to LDAP.</source>
<target>Das Login-Passwort wird automatisch von LDAP in Authentik synchronisiert. Aktivieren Sie diese Option nur, um Passwortänderungen in Authentik zurück in LDAP zu schreiben.</target>
</trans-unit>
<trans-unit id="saf7ce4165a1025f6">
<source>Sync groups</source>
<target>Gruppen synchronisieren</target>
</trans-unit>
<trans-unit id="s2035f889f576bca6">
<source>Connection settings</source>
<target>Verbindungseinstellungen</target>
</trans-unit>
<trans-unit id="s0a72e65aef45b1e8">
<source>Server URI</source>
<target>Server URI</target>
</trans-unit>
<trans-unit id="sa599dbe5776897ad">
<source>Specify multiple server URIs by separating them with a comma.</source>
<target>Geben Sie mehrere Server-URIs an, indem Sie sie durch ein Komma trennen.</target>
</trans-unit>
<trans-unit id="se36b55dfcf5dc80b">
<source>Enable StartTLS</source>
<target>Aktiviere StartTLS</target>
</trans-unit>
<trans-unit id="s33683c3b1dbaf264">
<source>To use SSL instead, use 'ldaps://' and disable this option.</source>
<target>Um stattdessen SSL zu verwenden, verwenden Sie 'ldaps://' und deaktivieren Sie diese Option.</target>
</trans-unit>
<trans-unit id="s2221fef80f4753a2">
<source>TLS Verification Certificate</source>
<target>TLS-Verifizierungszertifikat</target>
</trans-unit>
<trans-unit id="sb8c13bd58191cea2">
<source>When connecting to an LDAP Server with TLS, certificates are not checked by default. Specify a keypair to validate the remote certificate.</source>
<target>Bei der Verbindung zu einem LDAP-Server mit TLS werden Zertifikate standardmäßig nicht geprüft. Geben Sie ein Schlüsselpaar an, um das Remote-Zertifikat zu validieren.</target>
</trans-unit>
<trans-unit id="sb7684e2910a33a1f">
<source>Bind CN</source>
<target>Bind CN</target>
</trans-unit>
<trans-unit id="s3de6db803012016a">
<source>LDAP Attribute mapping</source>
<target>LDAP-Attributzuordnung</target>
</trans-unit>
<trans-unit id="s7c05ee41d634aa45">
<source>Property mappings used to user creation.</source>
<target>Für die Benutzererstellung verwendete Eigenschaftszuordnungen.</target>
</trans-unit>
<trans-unit id="s94333971a07803b9">
<source>Additional settings</source>
<target>Weitere Einstellungen</target>
</trans-unit>
<trans-unit id="sd14a19a19d507f9e">
<source>Parent group for all the groups imported from LDAP.</source>
<target>Übergeordnete Gruppe für alle aus LDAP importierten Gruppen.</target>
</trans-unit>
<trans-unit id="sfbc59ff17a73503d">
<source>User path</source>
</trans-unit>
<trans-unit id="sd18170637295bace">
<source>Addition User DN</source>
<target>Zusatz Benutzer-DN</target>
</trans-unit>
<trans-unit id="s9ae089fd248e72db">
<source>Additional user DN, prepended to the Base DN.</source>
<target>Zusätzlicher Benutzer-DN, dem Basis-DN vorangestellt.</target>
</trans-unit>
<trans-unit id="s5944355d69db1fb8">
<source>Addition Group DN</source>
<target>Zusatz Gruppen-DN</target>
</trans-unit>
<trans-unit id="sfae9f4ea5749a36b">
<source>Additional group DN, prepended to the Base DN.</source>
<target>Zusätzlicher Gruppen-DN, dem Basis-DN vorangestellt.</target>
</trans-unit>
<trans-unit id="s66ffc06300964849">
<source>User object filter</source>
<target>Benutzerobjektfilter</target>
</trans-unit>
<trans-unit id="s1c2a173db0e1ec61">
<source>Consider Objects matching this filter to be Users.</source>
<target>Betrachten Sie Objekte, die diesem Filter entsprechen, als Benutzer.</target>
</trans-unit>
<trans-unit id="s2ec94a7c7f5bcd1b">
<source>Group object filter</source>
<target>Gruppenobjektfilter</target>
</trans-unit>
<trans-unit id="saf5eb7596b3a355b">
<source>Consider Objects matching this filter to be Groups.</source>
<target>Betrachten Sie Objekte, die diesem Filter entsprechen, als Gruppen.</target>
</trans-unit>
<trans-unit id="sf325a4adba4d6278">
<source>Group membership field</source>
<target>Gruppenmitgliedschaftsfeld</target>
</trans-unit>
<trans-unit id="s76768bebabb7d543">
<source>Field which contains members of a group. Note that if using the "memberUid" field, the value is assumed to contain a relative distinguished name. e.g. 'memberUid=some-user' instead of 'memberUid=cn=some-user,ou=groups,...'</source>
<target>Feld, das Mitglieder einer Gruppe enthält. Beachten Sie, dass bei Verwendung des Felds „memberUid“ davon ausgegangen wird, dass der Wert einen relativ definierten Namen enthält. z.B. 'memberUid=some-user' statt 'memberUid=cn=some-user,ou=groups,...'</target>
</trans-unit>
<trans-unit id="s026555347e589f0e">
<source>Object uniqueness field</source>
<target>Feld für die Eindeutigkeit des Objekts</target>
</trans-unit>
<trans-unit id="s24211f319e5b7e98">
<source>Field which contains a unique Identifier.</source>
<target>Feld das eine einzigartige Kennung beinhaltet</target>
</trans-unit>
<trans-unit id="s900b0d85b872d134">
<source>Link users on unique identifier</source>
<target>Verknüpfen Sie Benutzer mit einer eindeutigen Kennung</target>
</trans-unit>
<trans-unit id="s6c70a73265e14521">
<source>Link to a user with identical email address. Can have security implications when a source doesn't validate email addresses</source>
<target>Link zu einem Benutzer mit identischer E-Mail-Adresse. Kann Auswirkungen auf die Sicherheit haben, wenn eine Quelle E-Mail-Adressen nicht validiert</target>
</trans-unit>
<trans-unit id="s995535e7af30d754">
<source>Use the user's email address, but deny enrollment when the email address already exists</source>
</trans-unit>
<trans-unit id="s542ecb4130f6cea5">
<source>Link to a user with identical username. Can have security implications when a username is used with another source</source>
</trans-unit>
<trans-unit id="s2a1debf34e5aeba4">
<source>Use the user's username, but deny enrollment when the username already exists</source>
</trans-unit>
<trans-unit id="s81ce0d54727f42d2">
<source>Unknown user matching mode</source>
</trans-unit>
<trans-unit id="sd04376c4216c921f">
<source>URL settings</source>
<target>URL-Einstellungen</target>
</trans-unit>
<trans-unit id="s872d0e88ab34ed83">
<source>Authorization URL</source>
<target>Autorisierungs-URL</target>
</trans-unit>
<trans-unit id="see3ff55262fd6500">
<source>URL the user is redirect to to consent the authorization.</source>
<target>URL, zu der Benutzer weitergeleitet werden um die Authorisierung zu bestätigen.</target>
</trans-unit>
<trans-unit id="sb932dead79567c7b">
<source>Access token URL</source>
<target>Zugangstoken-URL</target>
</trans-unit>
<trans-unit id="s88b8a2892635a2fc">
<source>URL used by authentik to retrieve tokens.</source>
<target>URL, die von Authentik zum Abrufen von Token verwendet wird.</target>
</trans-unit>
<trans-unit id="s69bd313dd12fc2f3">
<source>Profile URL</source>
<target>Profil URL</target>
</trans-unit>
<trans-unit id="sa8d83cd8023e8e4d">
<source>URL used by authentik to get user information.</source>
<target>URL, die von Authentik verwendet wird, um Benutzerinformationen zu erhalten.</target>
</trans-unit>
<trans-unit id="sc7707b3ba3a2a7ca">
<source>Request token URL</source>
<target>Token-URL anfordern</target>
</trans-unit>
<trans-unit id="s3926da5b20cdf3b6">
<source>URL used to request the initial token. This URL is only required for OAuth 1.</source>
<target>URL, die zur Anforderung des anfänglichen Tokens verwendet wird. Diese URL ist nur für OAuth 1 erforderlich</target>
</trans-unit>
<trans-unit id="s199b55513a739f43">
<source>OIDC Well-known URL</source>
<target>OIDC Well-known URL</target>
</trans-unit>
<trans-unit id="s8b149b30b5b523ef">
<source>OIDC well-known configuration URL. Can be used to automatically configure the URLs above.</source>
<target>Bekannte OIDC-Konfigurations-URL. Kann verwendet werden, um die obigen URLs automatisch zu konfigurieren.</target>
</trans-unit>
<trans-unit id="s9db2c836ade1339c">
<source>OIDC JWKS URL</source>
<target>OIDC JWKS URL</target>
</trans-unit>
<trans-unit id="s4b2a1b657c160f5b">
<source>JSON Web Key URL. Keys from the URL will be used to validate JWTs from this source.</source>
</trans-unit>
<trans-unit id="s2df0b65125600de9">
<source>OIDC JWKS</source>
<target>OIDC JWKS</target>
</trans-unit>
<trans-unit id="s02de8d9e8583b480">
<source>Raw JWKS data.</source>
</trans-unit>
<trans-unit id="s81a87652ade099e4">
<source>User matching mode</source>
<target>Benutzer-Matching-Modus</target>
</trans-unit>
<trans-unit id="s485c05d34eb00415">
<source>Delete currently set icon.</source>
<target>Lösche das aktuell festgelegte Symbol.</target>
</trans-unit>
<trans-unit id="se8987bdfb35e46b2">
<source>Consumer key</source>
<target>Schlüssel</target>
</trans-unit>
<trans-unit id="sabaf0061f7e41b0b">
<source>Consumer secret</source>
<target>Geheimniss</target>
</trans-unit>
<trans-unit id="sa61966cd83b4924c">
<source>Additional scopes to be passed to the OAuth Provider, separated by space. To replace existing scopes, prefix with *.</source>
</trans-unit>
<trans-unit id="s1cc0e66dbd2b5502">
<source>Flow settings</source>
<target>Ablauf-Einstellungen</target>
</trans-unit>
<trans-unit id="sfe6977a3aea3ee6e">
<source>Flow to use when authenticating existing users.</source>
<target>Flow der zur Authorisierung bereits ersteller Nutzer verwendet wird</target>
</trans-unit>
<trans-unit id="s2801a48ceac691b3">
<source>Enrollment flow</source>
<target>Registrierungsablauf</target>
</trans-unit>
<trans-unit id="s5d0a14d29ebad561">
<source>Flow to use when enrolling new users.</source>
<target>Flow der zum Anlegen bereits neuer Nutzer verwendet wird</target>
</trans-unit>
<trans-unit id="s91f389c796720a81">
<source>Load servers</source>
<target>Server laden</target>
</trans-unit>
<trans-unit id="s24f405197ede5ebb">
<source>Re-authenticate with plex</source>
<target>Mit Plex erneut authentifizieren</target>
</trans-unit>
<trans-unit id="sc297b2e13c28ecf9">
<source>Allow friends to authenticate via Plex, even if you don't share any servers</source>
<target>Freunden erlauben sich via Plex zu authentifizieren, auch wenn keine Server geteilt werden.</target>
</trans-unit>
<trans-unit id="sfee91e08b8b47477">
<source>Allowed servers</source>
<target>Erlaubte Server</target>
</trans-unit>
<trans-unit id="s216eb300543edd91">
<source>Select which server a user has to be a member of to be allowed to authenticate.</source>
<target>Wählen Sie aus, bei welchem Server ein Benutzer Mitglied sein muss, um sich authentifizieren zu dürfen.</target>
</trans-unit>
<trans-unit id="s31d7f3ba04d306a5">
<source>SSO URL</source>
<target>SSO URL</target>
</trans-unit>
<trans-unit id="s1d9d6c5b424fdc1f">
<source>URL that the initial Login request is sent to.</source>
<target>URL, an die die erste Login-Anfrage gesendet wird.</target>
</trans-unit>
<trans-unit id="sd94db2b8c85d10a6">
<source>SLO URL</source>
<target>SLO URL</target>
</trans-unit>
<trans-unit id="sc764ddf60b5149de">
<source>Optional URL if the IDP supports Single-Logout.</source>
<target>Optionale URL, falls der IDP Einmalabmeldung (SLO) unterstützt.</target>
</trans-unit>
<trans-unit id="se7430794fa89005a">
<source>Also known as Entity ID. Defaults the Metadata URL.</source>
<target>Auch bekannt als Entity ID. Standardmäßig wird die Metadaten-URL verwendet.</target>
</trans-unit>
<trans-unit id="s5615bb595ad6ded6">
<source>Binding Type</source>
<target>Verknüpfungstyp</target>
</trans-unit>
<trans-unit id="sa2e4d6830226d3ec">
<source>Redirect binding</source>
<target>Bindings umleiten</target>
</trans-unit>
<trans-unit id="s6f96a78d81ef277c">
<source>Post-auto binding</source>
</trans-unit>
<trans-unit id="sc2c70fd56f5d0b48">
<source>Post binding but the request is automatically sent and the user doesn't have to confirm.</source>
</trans-unit>
<trans-unit id="s968c90258dcf7562">
<source>Post binding</source>
<target>POST Bindung</target>
</trans-unit>
<trans-unit id="se10bbf4cf861c81b">
<source>Signing keypair</source>
<target>Schlüsselpaar signieren</target>
</trans-unit>
<trans-unit id="s838ed611b533b19e">
<source>Keypair which is used to sign outgoing requests. Leave empty to disable signing.</source>
<target>Schlüsselpaar, das zum Signieren ausgehender Anfragen verwendet wird. Leer lassen, um das Signieren zu deaktivieren.</target>
</trans-unit>
<trans-unit id="s39c8c0bf4d927c9f">
<source> Allow IDP-initiated logins</source>
<target>IDP-initiierte Anmeldungen zulassen</target>
</trans-unit>
<trans-unit id="s65d507f1513c2f03">
<source>Allows authentication flows initiated by the IdP. This can be a security risk, as no validation of the request ID is done.</source>
<target>Ermöglicht vom IdP initiierte Authentifizierungsströmen. Dies kann ein Sicherheitsrisiko darstellen, da keine Validierung der Anfrage-ID erfolgt.</target>
</trans-unit>
<trans-unit id="s297a2075bd7e40db">
<source>NameID Policy</source>
<target>NameID Richtlinie</target>
</trans-unit>
<trans-unit id="s004e9a2c90f23900">
<source>Persistent</source>
<target>Persistent</target>
</trans-unit>
<trans-unit id="s38887b94b3320533">
<source>Email address</source>
<target>E-Mail-Adresse</target>
</trans-unit>
<trans-unit id="s2d34c87f67f66c6a">
<source>Windows</source>
<target>Fenster</target>
</trans-unit>
<trans-unit id="s1665454e31e14941">
<source>X509 Subject</source>
<target>X509 Betreff</target>
</trans-unit>
<trans-unit id="s0c3ac7f9383a8cfd">
<source>Transient</source>
<target>Vorübergehend</target>
</trans-unit>
<trans-unit id="s20a0ce62823bfa97">
<source>Delete temporary users after</source>
<target>Temporäre Benutzer danach löschen</target>
</trans-unit>
<trans-unit id="s3198c384c2f68b08">
<source>Time offset when temporary users should be deleted. This only applies if your IDP uses the NameID Format 'transient', and the user doesn't log out manually.</source>
</trans-unit>
<trans-unit id="sb32e9c1faa0b8673">
<source>Pre-authentication flow</source>
<target>Vor-Authentifizierungs Ablauf</target>
</trans-unit>
<trans-unit id="sa3c1f6ac5e63a70f">
<source>Flow used before authentication.</source>
<target>Flow der vor Authorisierung verwendet wird</target>
</trans-unit>
<trans-unit id="se12969ade44cd2b6">
<source>New source</source>
<target>Neue Quelle</target>
</trans-unit>
<trans-unit id="s19b09f4fc72175d1">
<source>Create a new source.</source>
<target>Neue Quelle erstellen.</target>
</trans-unit>
<trans-unit id="s6152026c364ad974">
<source>Sources of identities, which can either be synced into authentik's database, or can be used by users to authenticate and enroll themselves.</source>
<target>Identitätsquellen, die entweder mit der Datenbank von authentik synchronisiert oder von Benutzern verwendet werden können, um sich selbst zu authentifizieren und zu registrieren.</target>
</trans-unit>
<trans-unit id="s0a0ca63b967f1630">
<source>Source(s)</source>
<target>Quellen</target>
</trans-unit>
<trans-unit id="s66722bc2ea775e05">
<source>Disabled</source>
<target>Deaktiviert</target>
</trans-unit>
<trans-unit id="s4ff2c202b4e5bdc5">
<source>Built-in</source>
<target>Eingebaut</target>
</trans-unit>
<trans-unit id="s52b500138a2d2b8a">
<source>Update LDAP Source</source>
<target>Aktualisieren Sie die LDAP-Quelle</target>
</trans-unit>
<trans-unit id="s31a2d43bc1cf1790">
<source>Not synced yet.</source>
<target>Noch nicht synchronisiert.</target>
</trans-unit>
<trans-unit id="s388ee787bbf2271b">
<source>Task finished with warnings</source>
<target>Aufgabe mit Warnungen beendet</target>
</trans-unit>
<trans-unit id="s949826fad0fe0909">
<source>Task finished with errors</source>
<target>Aufgabe mit Fehlern beendet</target>
</trans-unit>
<trans-unit id="sbedb77365a066648">
<source>Last sync: <x id="0" equiv-text="${task.taskFinishTimestamp.toLocaleString()}"/></source>
<target>Letzte Synchronisierung:
<x id="0" equiv-text="${task.taskFinishTimestamp.toLocaleString()}"/></target>
</trans-unit>
<trans-unit id="sf3fec8353106ac2f">
<source>OAuth Source <x id="0" equiv-text="${this.source.name}"/></source>
</trans-unit>
<trans-unit id="se09d055771f3a11d">
<source>Generic OpenID Connect</source>
<target>Generisches OpenID Connect</target>
</trans-unit>
<trans-unit id="s5c1dc164c89ac13e">
<source>Unknown provider type</source>
</trans-unit>
<trans-unit id="s355b21b89ce5d9c5">
<source>Details</source>
<target>Details</target>
</trans-unit>
<trans-unit id="s01088b6625d2443b">
<source>Callback URL</source>
<target>Callback URL</target>
</trans-unit>
<trans-unit id="sb6d5146d5efb3058">
<source>Access Key</source>
<target>Zugangsschlüssel</target>
</trans-unit>
<trans-unit id="s065604a41e9d1584">
<source>Update OAuth Source</source>
<target>OAuth-Quelle aktualisieren</target>
</trans-unit>
<trans-unit id="s7b576aa71acb36a6">
<source>Diagram</source>
<target>Diagramm</target>
</trans-unit>
<trans-unit id="s587ba266269297ab">
<source>Policy Bindings</source>
<target>Regelwerk Bindungen</target>
</trans-unit>
<trans-unit id="s2feae323f46479f8">
<source>These bindings control which users can access this source.
You can only use policies here as access is checked before the user is authenticated.</source>
</trans-unit>
<trans-unit id="se17fcb1f159ee382">
<source>Update Plex Source</source>
<target>Aktualisieren Sie die Plex-Quelle</target>
</trans-unit>
<trans-unit id="saa10777250a6deca">
<source>Update SAML Source</source>
<target>Aktualisieren Sie die SAML-Quelle</target>
</trans-unit>
<trans-unit id="s643d8f2e5e5e930d">
<source>Successfully updated mapping.</source>
<target>Zuordnung erfolgreich aktualisiert.</target>
</trans-unit>
<trans-unit id="sffeef5b119d8625c">
<source>Successfully created mapping.</source>
<target>Verknüpfung erfolgreich erstellt.</target>
</trans-unit>
<trans-unit id="s1c33d22492029aba">
<source>Object field</source>
<target>Objektfeld</target>
</trans-unit>
<trans-unit id="s06df3c3b6a503da8">
<source>Field of the user object this value is written to.</source>
<target>Feld des Benutzerobjekts, in das dieser Wert geschrieben wird.</target>
</trans-unit>
<trans-unit id="sd39c5e998efecf93">
<source>SAML Attribute Name</source>
<target>SAML-Attributsname</target>
</trans-unit>
<trans-unit id="scf2790cf3ad89283">
<source>Attribute name used for SAML Assertions. Can be a URN OID, a schema reference, or a any other string. If this property mapping is used for NameID Property, this field is discarded.</source>
<target>Der für die SAML Assertion verwendete Attributname. Kann eine URN OID, eine Schemareferenz oder eine beliebige andere Zeichenfolge sein. Wenn diese Eigenschaftszuordnung für die NameID-Eigenschaft verwendet wird, wird dieses Feld verworfen.</target>
</trans-unit>
<trans-unit id="sab6d24c5ec8dc361">
<source>Friendly Name</source>
<target>Name</target>
</trans-unit>
<trans-unit id="s9f8aac89fe318acc">
<source>Optionally set the 'FriendlyName' value of the Assertion attribute.</source>
<target>Legen Sie optional den Wert „FriendlyName“ des Assertion-Attributs fest.</target>
</trans-unit>
<trans-unit id="s851c108679653d2a">
<source>Scope name</source>
<target>Bereichsname</target>
</trans-unit>
<trans-unit id="s23fd4411419fca06">
<source>Scope which the client can specify to access these properties.</source>
<target>Gültigkeitsbereich, den der Client angeben kann, um auf diese Eigenschaften zuzugreifen.</target>
</trans-unit>
<trans-unit id="s7754f0e34f27fb6e">
<source>Description shown to the user when consenting. If left empty, the user won't be informed.</source>
<target>Beschreibung, die Benutzer sehen, wenn sie Einwilligen. Falls leer gelassen, werden Benutzer nicht informiert.</target>
</trans-unit>
<trans-unit id="sb6c3bf5489d7556e">
<source>Example context data</source>
</trans-unit>
<trans-unit id="s4a697f0b36c4fe83">
<source>Active Directory User</source>
</trans-unit>
<trans-unit id="s9277b90db38e1983">
<source>Active Directory Group</source>
</trans-unit>
<trans-unit id="sc2e03590269d5a10">
<source>New property mapping</source>
<target>Neue Eigenschaft</target>
</trans-unit>
<trans-unit id="s713e8666ed70f8b3">
<source>Create a new property mapping.</source>
<target>Neue Eigenschaftszuordnung erstellen.</target>
</trans-unit>
<trans-unit id="sce106606ae84d46f">
<source>Property Mappings</source>
<target>Eigenschaften</target>
</trans-unit>
<trans-unit id="s271a7e04ff9865b1">
<source>Control how authentik exposes and interprets information.</source>
<target>Kontrollieren Sie, wie authentik Informationen offenlegt und interpretiert.</target>
</trans-unit>
<trans-unit id="s59dc0eda07f9e2b6">
<source>Property Mapping(s)</source>
<target>Eigenschaftszuordnung(en)</target>
</trans-unit>
<trans-unit id="sa57c393736e2732c">
<source>Test Property Mapping</source>
<target>Eigenschaftszuordnung testen</target>
</trans-unit>
<trans-unit id="sc39fb3ff3753d5ab">
<source>Hide managed mappings</source>
<target>Verwaltete Zuordnungen ausblenden</target>
</trans-unit>
<trans-unit id="s476ffc07e6d66f18">
<source>Successfully updated token.</source>
<target>Token erfolgreich aktualisiert.</target>
</trans-unit>
<trans-unit id="s93c1e5fbe8184895">
<source>Successfully created token.</source>
<target>Token erfolgreich erstellt.</target>
</trans-unit>
<trans-unit id="s5fc4269c2addee61">
<source>Unique identifier the token is referenced by.</source>
<target>Einzigartige Kennung zur Referenzierung des Token.</target>
</trans-unit>
<trans-unit id="sb8bc2b8376c96a6b">
<source>Intent</source>
<target>Zweck</target>
</trans-unit>
<trans-unit id="sbd34d118bcb1aaf2">
<source>API Token</source>
<target>API Token</target>
</trans-unit>
<trans-unit id="se31d92bea7f3a186">
<source>Used to access the API programmatically</source>
</trans-unit>
<trans-unit id="sfd586951c75eb291">
<source>App password.</source>
</trans-unit>
<trans-unit id="s59bf194136d0d13a">
<source>Used to login using a flow executor</source>
</trans-unit>
<trans-unit id="s1b14062c44e5ef45">
<source>Expiring</source>
<target>Ablaufend</target>
</trans-unit>
<trans-unit id="safcc54b2aedb1a17">
<source>If this is selected, the token will expire. Upon expiration, the token will be rotated.</source>
<target>Wenn dies ausgewählt ist, läuft das Token ab. Nach Ablauf wird der Token rotiert.</target>
</trans-unit>
<trans-unit id="s4165cd175bc4c0c4">
<source>Expires on</source>
<target>Läuft ab am</target>
</trans-unit>
<trans-unit id="s1cd198d689c66e4b">
<source>API Access</source>
<target>API Zugriff</target>
</trans-unit>
<trans-unit id="sf29883ac9ec43085">
<source>App password</source>
<target>App Passwort</target>
</trans-unit>
<trans-unit id="sfe211545fd02f73e">
<source>Verification</source>
<target>Überprüfung</target>
</trans-unit>
<trans-unit id="sd73b202ec04eefd9">
<source>Unknown intent</source>
</trans-unit>
<trans-unit id="s78fd8c03f8c967f3">
<source>Tokens</source>
<target>Tokens</target>
</trans-unit>
<trans-unit id="sdcc7b2c109ce9775">
<source>Tokens are used throughout authentik for Email validation stages, Recovery keys and API access.</source>
<target>Token werden bei authentik für E-Mail-Validierungsphasen, Wiederherstellungsschlüssel und API-Zugriff verwendet.</target>
</trans-unit>
<trans-unit id="sf71dba2c30283a54">
<source>Expires?</source>
<target>Läuft ab?</target>
</trans-unit>
<trans-unit id="sc7be80a7f8ec597e">
<source>Expiry date</source>
<target>Ablaufdatum</target>
</trans-unit>
<trans-unit id="s71dcd9cf808449aa">
<source>Token(s)</source>
<target>Token(s)</target>
</trans-unit>
<trans-unit id="sb15e8daacf26bdfc">
<source>Create Token</source>
<target>Token erstellen</target>
</trans-unit>
<trans-unit id="s8d7ecd944ebe834b">
<source>Token is managed by authentik.</source>
<target>Token wird von Authentik verwaltet.</target>
</trans-unit>
<trans-unit id="sd1288ca57e221cf9">
<source>Update Token</source>
<target>Token aktualisieren</target>
</trans-unit>
<trans-unit id="s41706a202b6c40f1">
<source>Domain</source>
<target>Domain</target>
</trans-unit>
<trans-unit id="se74ce42d41e392ba">
<source>Matching is done based on domain suffix, so if you enter domain.tld, foo.domain.tld will still match.</source>
<target>Der Abgleich erfolgt basierend auf dem Domänensuffix. Wenn Sie also domain.tld eingeben, wird foo.domain.tld immer noch übereinstimmen.</target>
</trans-unit>
<trans-unit id="s11326fd2590f4e5e">
<source>Default</source>
<target>Standard</target>
</trans-unit>
<trans-unit id="sc19838ca8c135c1b">
<source>Branding settings</source>
<target>Branding-Einstellungen</target>
</trans-unit>
<trans-unit id="s99f110d27e30b289">
<source>Title</source>
<target>Titel</target>
</trans-unit>
<trans-unit id="sab6bad52985c6676">
<source>Branding shown in page title and several other places.</source>
<target>Das Branding wird im Seitentitel und an mehreren anderen Stellen angezeigt.</target>
</trans-unit>
<trans-unit id="s4f1af2b48a5e249a">
<source>Logo</source>
<target>Logo</target>
</trans-unit>
<trans-unit id="sd6b8b4156f7df696">
<source>Icon shown in sidebar/header and flow executor.</source>
<target>Bild, das in der Seitenleiste/dem Header und in Abläufen zu sehen ist.</target>
</trans-unit>
<trans-unit id="s3626433940124897">
<source>Favicon</source>
<target>Favicon</target>
</trans-unit>
<trans-unit id="se99efc0873031976">
<source>Icon shown in the browser tab.</source>
<target>Symbol im Browsertab.</target>
</trans-unit>
<trans-unit id="s10356fd921037fbf">
<source>Default flows</source>
<target>Standardabläufe</target>
</trans-unit>
<trans-unit id="sd216b08bafb297ee">
<source>Flow used to authenticate users. If left empty, the first applicable flow sorted by the slug is used.</source>
<target>Ablauf zur Authentifizierung von Benutzern. Wenn es leer gelassen wird, wird der erste anwendbare Fluss, sortiert nach dem Slug, verwendet.</target>
</trans-unit>
<trans-unit id="s35e6e60e83a8c003">
<source>Invalidation flow</source>
<target>Ablauf der Invalidierung</target>
</trans-unit>
<trans-unit id="s7989db5f4819af89">
<source>Flow used to logout. If left empty, the first applicable flow sorted by the slug is used.</source>
<target>Ablauf, der zum Abmelden genutzt wird. Wenn keiner angegeben ist, wird der erste anwendbare Ablauf, sortiert nach Slug, verwendet.</target>
</trans-unit>
<trans-unit id="sfeb779d4ccbc5a0e">
<source>Recovery flow</source>
<target>Wiederherstellungsfluss</target>
</trans-unit>
<trans-unit id="s1c2fd8097e14a608">
<source>Recovery flow. If left empty, the first applicable flow sorted by the slug is used.</source>
<target>Wiederherstellungsfluss. Wenn es leer gelassen wird, wird der erste anwendbare Fluss, sortiert nach dem Slug, verwendet.</target>
</trans-unit>
<trans-unit id="s836aa192b30c21da">
<source>Unenrollment flow</source>
<target>Ablauf der Abmeldung</target>
</trans-unit>
<trans-unit id="s081d3c4b47a6ff83">
<source>If set, users are able to unenroll themselves using this flow. If no flow is set, option is not shown.</source>
<target>Wenn festgelegt, können sich Benutzer mit diesem Ablauf selbst abmelden. Wenn kein Ablauf eingestellt ist, wird die Option nicht angezeigt.</target>
</trans-unit>
<trans-unit id="secbfd13bdae95a59">
<source>User settings flow</source>
<target>Ablauf für Benutzereinstellungen</target>
</trans-unit>
<trans-unit id="s523160b433311521">
<source>If set, users are able to configure details of their profile.</source>
<target>Wenn aktiviert, können Nutzer Profildetails selbstständig ändern.</target>
</trans-unit>
<trans-unit id="s134177568525dbc8">
<source>Device code flow</source>
</trans-unit>
<trans-unit id="s7b298427bdea81ae">
<source>If set, the OAuth Device Code profile can be used, and the selected flow will be used to enter the code.</source>
</trans-unit>
<trans-unit id="s7f4e4054fbe132e1">
<source>Other global settings</source>
<target>Weitere globale Einstellungen</target>
</trans-unit>
<trans-unit id="sbadde673052efc02">
<source>Web Certificate</source>
<target>Web-Zertifikat</target>
</trans-unit>
<trans-unit id="s84c5a011acd608c9">
<source>Event retention</source>
<target>Ereignisspeicherung</target>
</trans-unit>
<trans-unit id="s2536ac8d32d2e63f">
<source>Duration after which events will be deleted from the database.</source>
<target>Dauer, nach der ein Ereignis aus der Datenbank gelöscht wird.</target>
</trans-unit>
<trans-unit id="s7b1fba26d245cb1c">
<source>When using an external logging solution for archiving, this can be set to "minutes=5".</source>
<target>Falls eine externe Protokollierlösung zum archivieren genutzt wird, könnte dies auf „minutes=5“ gesetzt werden.</target>
</trans-unit>
<trans-unit id="s44536d20bb5c8257">
<source>This setting only affects new Events, as the expiration is saved per-event.</source>
<target>Diese Einstellung betrifft nur neue Ereignisse, da die Ablaufzeit für jedes Ereignis gespeichert wird.</target>
</trans-unit>
<trans-unit id="s164be9a7537b99f6">
<source>Configure visual settings and defaults for different domains.</source>
<target>Konfiguriere visuelle Einstellungen und Standards für verschiedene Domains.</target>
</trans-unit>
<trans-unit id="s4802636d55022ed3">
<source>Default?</source>
<target>Standard?</target>
</trans-unit>
<trans-unit id="s8cb7bb82e96d5d77">
<source>Policies</source>
<target>Richtlinien</target>
</trans-unit>
<trans-unit id="sec1808532fe107b9">
<source>Allow users to use Applications based on properties, enforce Password Criteria and selectively apply Stages.</source>
<target>Erlauben Sie Benutzern die Verwendung von Anwendungen auf der Grundlage von Eigenschaften, erzwingen Sie Passwortkriterien und wende ausgewählte Stages an.</target>
</trans-unit>
<trans-unit id="se16ac750b81fa93d">
<source>Assigned to <x id="0" equiv-text="${item.boundTo}"/> object(s).</source>
<target>Zugewiesen zu
<x id="0" equiv-text="${item.boundTo}"/>Objekt(en).</target>
</trans-unit>
<trans-unit id="s5a48d5171e1a1522">
<source>Warning: Policy is not assigned.</source>
<target>Warnung: Keine Richtlinie zugewiesen</target>
</trans-unit>
<trans-unit id="s544142ce35050751">
<source>Test Policy</source>
<target>Testrichtlinie</target>
</trans-unit>
<trans-unit id="s00c8354318addfa0">
<source>Policy / Policies</source>
<target>Richtlinie / Richtlinien</target>
</trans-unit>
<trans-unit id="s76da2c978dcc5ef4">
<source>Successfully cleared policy cache</source>
<target>Richtlinien-Cache erfolgreich geleert</target>
</trans-unit>
<trans-unit id="sa717841a602fe7d8">
<source>Failed to delete policy cache</source>
<target>Richtlinienpuffer löschen fehlgeschlagen</target>
</trans-unit>
<trans-unit id="s3ed5607ad78d4224">
<source>Clear cache</source>
<target>Cache löschen</target>
</trans-unit>
<trans-unit id="s1b07757762cda372">
<source>Clear Policy cache</source>
<target>Löschen Sie den Richtlinien-Cache</target>
</trans-unit>
<trans-unit id="s15b46b78edebb20a">
<source>Are you sure you want to clear the policy cache? This will cause all policies to be re-evaluated on their next usage.</source>
</trans-unit>
<trans-unit id="s62ddcbaaa91d120d">
<source>Reputation scores</source>
<target>Reputation Punkte</target>
</trans-unit>
<trans-unit id="sd080b2370aa82967">
<source>Reputation for IP and user identifiers. Scores are decreased for each failed login and increased for each successful login.</source>
<target>Reputation für IP und Benutzerkennungen. Die Punktzahl wird für jede fehlgeschlagene Anmeldung verringert und für jede erfolgreiche Anmeldung erhöht.</target>
</trans-unit>
<trans-unit id="s09242207b5b8f83c">
<source>IP</source>
<target>IP</target>
</trans-unit>
<trans-unit id="s7d684b6257284e55">
<source>Score</source>
<target>Punkt(e)</target>
</trans-unit>
<trans-unit id="s10d2dbc4613397f0">
<source>Updated</source>
<target>Aktualisiert</target>
</trans-unit>
<trans-unit id="sa33d061d2ade20aa">
<source>Reputation</source>
<target>Reputation</target>
</trans-unit>
<trans-unit id="s9f26843287bb592d">
<source>Groups</source>
<target>Gruppen</target>
</trans-unit>
<trans-unit id="s4dcb9288f7e9e4d7">
<source>Group users together and give them permissions based on the membership.</source>
<target>Gruppieren Sie Benutzer und erteilen Sie ihnen Berechtigungen basierend auf der Mitgliedschaft.</target>
</trans-unit>
<trans-unit id="s62f93cfcb45d5a06">
<source>Superuser privileges?</source>
<target>Administrationsrechte?</target>
</trans-unit>
<trans-unit id="s9fdda7ea4642306c">
<source>Group(s)</source>
<target>Gruppe(n)</target>
</trans-unit>
<trans-unit id="s416a540b16275f2e">
<source>Create Group</source>
<target>Gruppe erstellen</target>
</trans-unit>
<trans-unit id="s7c5774fad9d050ce">
<source>Create group</source>
<target>Gruppe erstellen</target>
</trans-unit>
<trans-unit id="s2a12e0b5527ff99a">
<source>Enabling this toggle will create a group named after the user, with the user as member.</source>
<target>Durch Aktivieren dieses Schalters wird eine nach dem Benutzer benannte Gruppe mit dem Benutzer als Mitglied erstellt.</target>
</trans-unit>
<trans-unit id="s6b6e6eb037aef7da">
<source>Use the username and password below to authenticate. The password can be retrieved later on the Tokens page.</source>
<target>Verwenden Sie den Benutzernamen und das Passwort unten, um sich zu authentifizieren. Das Passwort kann später auf der Seite Tokens abgerufen werden.</target>
</trans-unit>
<trans-unit id="sf6e1665c7022a1f8">
<source>Password</source>
<target>Passwort</target>
</trans-unit>
<trans-unit id="sbb57cd8a3ed12915">
<source>Valid for 360 days, after which the password will automatically rotate. You can copy the password from the Token List.</source>
<target>Gültig für 360 Tage, danach rotiert das Passwort automatisch. Sie können das Passwort aus der Token-Liste kopieren.</target>
</trans-unit>
<trans-unit id="s4414164d120de61a">
<source>The following objects use <x id="0" equiv-text="${objName}"/></source>
<target>Die folgenden Objekte verwenden
<x id="0" equiv-text="${objName}"/></target>
</trans-unit>
<trans-unit id="s92e241c9f3c101a2">
<source>connecting object will be deleted</source>
<target>Verbindungsobjekt wird gelöscht</target>
</trans-unit>
<trans-unit id="se6a13beff646557b">
<source>Successfully updated <x id="0" equiv-text="${this.objectLabel} ${this.obj?.name}"/></source>
</trans-unit>
<trans-unit id="s14401ff4a0cba208">
<source>Failed to update <x id="0" equiv-text="${this.objectLabel}"/>: <x id="1" equiv-text="${e.toString()}"/></source>
<target>Aktualisieren von
<x id="0" equiv-text="${this.objectLabel}"/>fehlgeschlagen:
<x id="1" equiv-text="${e.toString()}"/></target>
</trans-unit>
<trans-unit id="sa95a538bfbb86111">
<source>Are you sure you want to update <x id="0" equiv-text="${this.objectLabel}"/> "<x id="1" equiv-text="${this.obj?.name}"/>"?</source>
<target>Sind Sie sicher, dass Sie
<x id="0" equiv-text="${this.objectLabel}"/>"
<x id="1" equiv-text="${this.obj?.name}"/>" aktualisieren wollen?</target>
</trans-unit>
<trans-unit id="sc92d7cfb6ee1fec6">
<source>Successfully updated password.</source>
<target>Passwort erfolgreich aktualisiert.</target>
</trans-unit>
<trans-unit id="se5498954255620b4">
<source>Successfully sent email.</source>
<target>E-Mail erfolgreich gesendet.</target>
</trans-unit>
<trans-unit id="s44ea4e9a81ce730d">
<source>Email stage</source>
<target>E-Mail-Stufe</target>
</trans-unit>
<trans-unit id="sdb53ccdd6174e6e3">
<source>Successfully added user(s).</source>
</trans-unit>
<trans-unit id="s306a35df5d0d38bb">
<source>Users to add</source>
</trans-unit>
<trans-unit id="s7d499be3b781a3ca">
<source>User(s)</source>
<target>Benutzer</target>
</trans-unit>
<trans-unit id="s7220fcf4fec4e0df">
<source>Remove Users(s)</source>
</trans-unit>
<trans-unit id="s5d7748b1d2363478">
<source>Are you sure you want to remove the selected users from the group <x id="0" equiv-text="${this.targetGroup?.name}"/>?</source>
</trans-unit>
<trans-unit id="sea4f08110bb8f15d">
<source>Remove</source>
</trans-unit>
<trans-unit id="sf466142da6a65052">
<source>Impersonate</source>
<target>Identitätswechsel</target>
</trans-unit>
<trans-unit id="s58888ef1ee9b5bb8">
<source>User status</source>
<target>Benutzerstatus</target>
</trans-unit>
<trans-unit id="sf9e61f4f8e90f0f1">
<source>Change status</source>
<target>Status ändern</target>
</trans-unit>
<trans-unit id="sf56998949bdf6b33">
<source>Deactivate</source>
<target>Deaktivieren</target>
</trans-unit>
<trans-unit id="s3794c596ee7964ad">
<source>Update password</source>
<target>Passwort ändern</target>
</trans-unit>
<trans-unit id="sce8d867ca5f35304">
<source>Set password</source>
<target>Passwort festlegen</target>
</trans-unit>
<trans-unit id="s0ae3395d8f48e624">
<source>Successfully generated recovery link</source>
<target>Erfolgreich generierter Wiederherstellungslink</target>
</trans-unit>
<trans-unit id="s8ca0dbaec5d48563">
<source>No recovery flow is configured.</source>
<target>Es ist kein Wiederherstellungsablauf konfiguriert.</target>
</trans-unit>
<trans-unit id="sb69119c9f0547bed">
<source>Copy recovery link</source>
<target>Wiederherstellungslink kopieren</target>
</trans-unit>
<trans-unit id="s7fa236d26b798301">
<source>Send link</source>
<target>Link senden</target>
</trans-unit>
<trans-unit id="sa9dbe2fb284e26fe">
<source>Send recovery link to user</source>
<target>Wiederherstellungslink an Benutzer senden</target>
</trans-unit>
<trans-unit id="s03fd2c252ad7972a">
<source>Email recovery link</source>
<target>E-Mail-Wiederherstellungslink</target>
</trans-unit>
<trans-unit id="sd7fa99e4d82b374a">
<source>Recovery link cannot be emailed, user has no email address saved.</source>
<target>Der Wiederherstellungslink kann nicht per E-Mail gesendet werden, der Benutzer hat keine E-Mail-Adresse gespeichert.</target>
</trans-unit>
<trans-unit id="s720594461542943f">
<source>Add User</source>
<target>Benutzer hinzufügen</target>
</trans-unit>
<trans-unit id="s4c41f3f4c23e8eaa">
<source>Warning: This group is configured with superuser access. Added users will have superuser access.</source>
</trans-unit>
<trans-unit id="scee721983b1c28d0">
<source>Add existing user</source>
<target>Bestehenden Benutzer hinzufügen</target>
</trans-unit>
<trans-unit id="sd600334ec2c39b74">
<source>Create user</source>
</trans-unit>
<trans-unit id="s53ad3455d9523b54">
<source>Create User</source>
<target>Benutzer erstellen</target>
</trans-unit>
<trans-unit id="s06c163334767a381">
<source>Create Service account</source>
<target>Internes Konto erstellen</target>
</trans-unit>
<trans-unit id="sc744f3691efe310d">
<source>Hide service-accounts</source>
<target>Interne Konten ausblenden</target>
</trans-unit>
<trans-unit id="secdb4b4c4e66aa38">
<source>Group Info</source>
<target>Gruppeninformationen</target>
</trans-unit>
<trans-unit id="s005053d82b712e0a">
<source>Notes</source>
</trans-unit>
<trans-unit id="s634448e4942cf452">
<source>Edit the notes attribute of this group to add notes here.</source>
</trans-unit>
<trans-unit id="s586d6bd2eca2da93">
<source>Users</source>
<target>Benutzer</target>
</trans-unit>
<trans-unit id="sca7cfe2bef51b2a5">
<source>Root</source>
</trans-unit>
<trans-unit id="s3616cc78631f5893">
<source>Warning: You're about to delete the user you're logged in as (<x id="0" equiv-text="${shouldShowWarning.username}"/>). Proceed at your own risk.</source>
<target>Warnung: Sie sind im Begriff, den Benutzer zu löschen, als den Sie angemeldet sind (
<x id="0" equiv-text="${shouldShowWarning.username}"/>). Fahren Sie auf eigene Gefahr fort.</target>
</trans-unit>
<trans-unit id="s510c7add9e24c306">
<source>Hide deactivated user</source>
</trans-unit>
<trans-unit id="s94055b4eb957dc8f">
<source>User folders</source>
</trans-unit>
<trans-unit id="sa982875b258fea07">
<source>Successfully added user to group(s).</source>
</trans-unit>
<trans-unit id="s1bd5920d8adf2bd5">
<source>Groups to add</source>
</trans-unit>
<trans-unit id="s5f71fa3c53828e30">
<source>Remove from Group(s)</source>
</trans-unit>
<trans-unit id="sb4c9ed2a487b238f">
<source>Are you sure you want to remove user <x id="0" equiv-text="${this.targetUser?.username}"/> from the following groups?</source>
</trans-unit>
<trans-unit id="s964f6725aeb7662f">
<source>Add Group</source>
<target>Gruppe hinzufügen</target>
</trans-unit>
<trans-unit id="s65ca2f256ea09c11">
<source>Add to existing group</source>
<target>Zu bestehender Gruppe hinzufügen</target>
</trans-unit>
<trans-unit id="s505fbbdcbc6aa921">
<source>Add new group</source>
<target>Neue Gruppe hinzufügen</target>
</trans-unit>
<trans-unit id="s506beb486fa41241">
<source>Application authorizations</source>
<target>Applikationsgenehmigungen</target>
</trans-unit>
<trans-unit id="s7301a7069b7bc83e">
<source>Revoked?</source>
<target>Widerrufen?</target>
</trans-unit>
<trans-unit id="sd924045605feea63">
<source>Expires</source>
<target>Läuft ab</target>
</trans-unit>
<trans-unit id="s1c8916418c334935">
<source>ID Token</source>
<target>ID-Token</target>
</trans-unit>
<trans-unit id="s90760e5e02e95dfe">
<source>Refresh Tokens(s)</source>
</trans-unit>
<trans-unit id="s1b88fa3df4423292">
<source>Last IP</source>
<target>Letzte IP</target>
</trans-unit>
<trans-unit id="se63f9d833700af49">
<source>Session(s)</source>
<target>Sitzung(en)</target>
</trans-unit>
<trans-unit id="sf679b7a62808287e">
<source>Expiry</source>
<target>Ablaufdatum</target>
</trans-unit>
<trans-unit id="sde1907073fd96017">
<source>(Current session)</source>
</trans-unit>
<trans-unit id="se8dca0132c66ae03">
<source>Permissions</source>
</trans-unit>
<trans-unit id="s76881c01b6a3a8c7">
<source>Consent(s)</source>
<target>Einwilligung(en)</target>
</trans-unit>
<trans-unit id="sea2f00b34b385a43">
<source>Successfully updated device.</source>
<target>Gerät erfolgreich aktualisiert.</target>
</trans-unit>
<trans-unit id="s858e7ac4b3cf955f">
<source>Static tokens</source>
<target>Statische Token</target>
</trans-unit>
<trans-unit id="sfcfcf85a57eea78a">
<source>TOTP Device</source>
<target>TOTP-Gerät</target>
</trans-unit>
<trans-unit id="s6a406aecb2c0e5c5">
<source>Enroll</source>
<target>Registrieren</target>
</trans-unit>
<trans-unit id="sa0b01f479f40c52d">
<source>Device(s)</source>
<target>Gerät(e)</target>
</trans-unit>
<trans-unit id="sabb56f74492e7e96">
<source>Update Device</source>
<target>Gerät aktualisieren</target>
</trans-unit>
<trans-unit id="sf05c700a1250824e">
<source>Confirmed</source>
</trans-unit>
<trans-unit id="s64a33dcdaf90af26">
<source>User Info</source>
<target>Benutzerinformation</target>
</trans-unit>
<trans-unit id="sc44bae5cde0083fa">
<source>Actions over the last week (per 8 hours)</source>
<target>Aktionen der letzten Woche (pro 8 Stunden)</target>
</trans-unit>
<trans-unit id="sb57dbcda1929c642">
<source>Edit the notes attribute of this user to add notes here.</source>
</trans-unit>
<trans-unit id="s5c18cae48b93138c">
<source>Sessions</source>
<target>Sitzungen</target>
</trans-unit>
<trans-unit id="s27586544c447d9e3">
<source>User events</source>
<target>Benutzerereignisse</target>
</trans-unit>
<trans-unit id="s4d31797d81e9cea3">
<source>Explicit Consent</source>
<target>Explizite Einwilligung</target>
</trans-unit>
<trans-unit id="sb6770fa90be6d8b3">
<source>OAuth Refresh Tokens</source>
</trans-unit>
<trans-unit id="s28b3de1561da72b3">
<source>MFA Authenticators</source>
</trans-unit>
<trans-unit id="s7a322c89298dd27c">
<source>Successfully updated invitation.</source>
<target>Einladung erfolgreich aktualisiert.</target>
</trans-unit>
<trans-unit id="sc554339ffc7b04e7">
<source>Successfully created invitation.</source>
<target>Integration erfolgreich erstellt.</target>
</trans-unit>
<trans-unit id="sfcebd18506f1e535">
<source>Flow</source>
<target>Ablauf</target>
</trans-unit>
<trans-unit id="sa84a7fd11ba85e88">
<source>When selected, the invite will only be usable with the flow. By default the invite is accepted on all flows with invitation stages.</source>
</trans-unit>
<trans-unit id="s7520286c8419a266">
<source>Optional data which is loaded into the flow's 'prompt_data' context variable. YAML or JSON.</source>
<target>Optionale Daten, die in die Kontextvariable „prompt_data“ des Flows geladen werden. YAML oder JSON.</target>
</trans-unit>
<trans-unit id="sb8795b799c70776a">
<source>Single use</source>
<target>Einmalbenutzung</target>
</trans-unit>
<trans-unit id="sf232d42142eacc23">
<source>When enabled, the invitation will be deleted after usage.</source>
<target>Wenn diese Option aktiviert ist, wird die Einladung nach ihrer Benutzung gelöscht.</target>
</trans-unit>
<trans-unit id="sa4a8086275475714">
<source>Select an enrollment flow</source>
<target>Registrierungsablauf wählen</target>
</trans-unit>
<trans-unit id="s839cb09cb2193da9">
<source>Link to use the invitation.</source>
<target>Einladungslink</target>
</trans-unit>
<trans-unit id="s8226f48cb1a80997">
<source>Invitations</source>
<target>Einladungen</target>
</trans-unit>
<trans-unit id="s57448f10eb973100">
<source>Create Invitation Links to enroll Users, and optionally force specific attributes of their account.</source>
<target>Erstelle Einladungslinks um Benutzer zu registrieren und optional spezifische Attribute zu deren Konto hinzuzufügen.</target>
</trans-unit>
<trans-unit id="s4aee34a672e5cfc0">
<source>Created by</source>
<target>Erstellt von</target>
</trans-unit>
<trans-unit id="sd5ba2d61ee4796fe">
<source>Invitation(s)</source>
<target>Einladung(en)</target>
</trans-unit>
<trans-unit id="s96dcf7ec8342c335">
<source>Invitation not limited to any flow, and can be used with any enrollment flow.</source>
</trans-unit>
<trans-unit id="s1b42b49e7b392013">
<source>Update Invitation</source>
<target>Einladung aktualisieren</target>
</trans-unit>
<trans-unit id="s38c72e1cf120b8d8">
<source>Create Invitation</source>
<target>Einladung erstellen</target>
</trans-unit>
<trans-unit id="s802826db4e2c852e">
<source>Warning: No invitation stage is bound to any flow. Invitations will not work as expected.</source>
<target>Warnung: Keine Einladungsphase ist an einen Ablauf gebunden. Einladungen funktionieren nicht wie erwartet.</target>
</trans-unit>
<trans-unit id="s2f995efbb1e46b18">
<source>Auto-detect (based on your browser)</source>
<target>Automatische Erkennung (basierend auf Ihrem Browser)</target>
</trans-unit>
<trans-unit id="s296fbffaaa7c910a">
<source>Required.</source>
<target>Erforderlich</target>
</trans-unit>
<trans-unit id="s81ecf2d4386b8e84">
<source>Continue</source>
<target>Weiter</target>
</trans-unit>
<trans-unit id="s8b2b2a43fcf688a3">
<source>Successfully updated prompt.</source>
<target>Eingabeaufforderung erfolgreich aktualisiert.</target>
</trans-unit>
<trans-unit id="s5572ac4d2208f5ec">
<source>Successfully created prompt.</source>
<target>Eingabeaufforderung erfolgreich erstellt.</target>
</trans-unit>
<trans-unit id="s54e7a23a95d99649">
<source>Text: Simple Text input</source>
<target>Text: Einfaches Texteingabefeld</target>
</trans-unit>
<trans-unit id="s63e54b86e2a2cc43">
<source>Text Area: Multiline text input</source>
</trans-unit>
<trans-unit id="s12de1c06a1e18cc5">
<source>Text (read-only): Simple Text input, but cannot be edited.</source>
<target>Text (read-only): Einfaches Texteingabefeld, nicht editierbar</target>
</trans-unit>
<trans-unit id="s4e5646b23e41231f">
<source>Text Area (read-only): Multiline text input, but cannot be edited.</source>
</trans-unit>
<trans-unit id="s1e4c3de6e12cd87b">
<source>Username: Same as Text input, but checks for and prevents duplicate usernames.</source>
<target>Benutzername: Wie bei der Texteingabe, prüft jedoch auf doppelte Benutzernamen und verhindert diese.</target>
</trans-unit>
<trans-unit id="s5462c7f56ed65e6c">
<source>Email: Text field with Email type.</source>
<target>E-Mail: Textfeld mit E-Mail-Typ.</target>
</trans-unit>
<trans-unit id="s1c5574968b29ab1c">
<source>Password: Masked input, multiple inputs of this type on the same prompt need to be identical.</source>
</trans-unit>
<trans-unit id="sbbb97b1c63507dc0">
<source>Number</source>
<target>Nummer</target>
</trans-unit>
<trans-unit id="sdae649fae731e838">
<source>Checkbox</source>
<target>Checkbox</target>
</trans-unit>
<trans-unit id="s34edeb18f887161d">
<source>Radio Button Group (fixed choice)</source>
</trans-unit>
<trans-unit id="s57730b6870e8916c">
<source>Dropdown (fixed choice)</source>
</trans-unit>
<trans-unit id="sac8252732f2edb19">
<source>Date</source>
<target>Datum</target>
</trans-unit>
<trans-unit id="s45960273852a61b2">
<source>Date Time</source>
<target>Zeitlicher Termin</target>
</trans-unit>
<trans-unit id="sd1f81284eeb7b503">
<source>File</source>
<target>Datei</target>
</trans-unit>
<trans-unit id="s21e3c227cc2c5873">
<source>Separator: Static Separator Line</source>
<target>Trennzeichen: Statische Trennungslinie</target>
</trans-unit>
<trans-unit id="s706af57c1af42c6d">
<source>Hidden: Hidden field, can be used to insert data into form.</source>
<target>Versteckt: Verstecktes Feld, kann zum Einfügen von Daten in das Formular verwendet werden.</target>
</trans-unit>
<trans-unit id="s40e2c72dae905a50">
<source>Static: Static value, displayed as-is.</source>
<target>Statisch: Statischer Wert, wird so angezeigt, wie er ist.</target>
</trans-unit>
<trans-unit id="sdd4bd4224c4e943d">
<source>authentik: Locale: Displays a list of locales authentik supports.</source>
<target>authentik: Gebietsschema: Zeigt eine Liste von Gebietsschemas, die Authentik unterstützt.</target>
</trans-unit>
<trans-unit id="saf84e7732a9e1336">
<source>Preview errors</source>
</trans-unit>
<trans-unit id="sb71ace8e9b35c749">
<source>Data preview</source>
</trans-unit>
<trans-unit id="s4d53f4b7ff33bedd">
<source>Unique name of this field, used for selecting fields in prompt stages.</source>
</trans-unit>
<trans-unit id="s3b58f8d2155ae90c">
<source>Field Key</source>
<target>Schlüsselfeld</target>
</trans-unit>
<trans-unit id="s2b088ba65eb69b7e">
<source>Name of the form field, also used to store the value.</source>
<target>Name des Formularfelds, das auch zum Speichern des Werts verwendet wird.</target>
</trans-unit>
<trans-unit id="s662fcb3761ad9df7">
<source>When used in conjunction with a User Write stage, use attributes.foo to write attributes.</source>
<target>Bei Verwendung in Verbindung mit einer User Write-Phase verwenden Sie attributes.foo zum Schreiben von Attributen.</target>
</trans-unit>
<trans-unit id="s5590dbf7e425789d">
<source>Label</source>
<target>Beschriftung</target>
</trans-unit>
<trans-unit id="s0c135eba6017d94f">
<source>Label shown next to/above the prompt.</source>
<target>Beschriftung neben/über der Eingabeaufforderung</target>
</trans-unit>
<trans-unit id="sae5d87e99fe081e0">
<source>Required</source>
<target>Erforderlich</target>
</trans-unit>
<trans-unit id="s37dbfe2133b74d2d">
<source>Interpret placeholder as expression</source>
<target>Platzhalter aus Ausdruck interpretieren</target>
</trans-unit>
<trans-unit id="s4a953e6234cb4808">
<source>When checked, the placeholder will be evaluated in the same way a property mapping is.
If the evaluation fails, the placeholder itself is returned.</source>
</trans-unit>
<trans-unit id="sf90be97cb08f3d5a">
<source>Placeholder</source>
<target>Platzhalter</target>
</trans-unit>
<trans-unit id="sf76ead4c4708dd06">
<source>Optionally provide a short hint that describes the expected input value.
When creating a fixed choice field, enable interpreting as expression and return a
list to return multiple choices.</source>
</trans-unit>
<trans-unit id="saa7ba2057bd524a1">
<source>Interpret initial value as expression</source>
</trans-unit>
<trans-unit id="sd60415c7666859f0">
<source>When checked, the initial value will be evaluated in the same way a property mapping is.
If the evaluation fails, the initial value itself is returned.</source>
</trans-unit>
<trans-unit id="sa9c7044d9fd1f3e6">
<source>Initial value</source>
</trans-unit>
<trans-unit id="seab35681cbf36755">
<source>Optionally pre-fill the input with an initial value.
When creating a fixed choice field, enable interpreting as expression and
return a list to return multiple default choices.</source>
</trans-unit>
<trans-unit id="s72c1c17a9bdc76ad">
<source>Help text</source>
<target>Hilfetext</target>
</trans-unit>
<trans-unit id="s584d1c38ad20d560">
<source>Any HTML can be used.</source>
<target>Jedes HTML kann verwendet werden.</target>
</trans-unit>
<trans-unit id="s2be6121210e2a2f8">
<source>Prompts</source>
<target>Eingabeaufforderungen</target>
</trans-unit>
<trans-unit id="s42fc6f4b64eff5d9">
<source>Single Prompts that can be used for Prompt Stages.</source>
<target>Einzelne Eingabeaufforderungen, die für Eingabeaufforderungsphasen verwendet werden können.</target>
</trans-unit>
<trans-unit id="s42a1ebe17efda727">
<source>Field</source>
<target>Feld</target>
</trans-unit>
<trans-unit id="s41b105819b67ee7a">
<source>Stages</source>
<target>Phasen</target>
</trans-unit>
<trans-unit id="sec7443a45fd141e5">
<source>Prompt(s)</source>
<target>Eingabeaufforderung(en)</target>
</trans-unit>
<trans-unit id="scc733ba98740038a">
<source>Update Prompt</source>
<target>Aktualisierungsaufforderung</target>
</trans-unit>
<trans-unit id="s61b6f3e6bc59c6dd">
<source>Create Prompt</source>
<target>Eingabeaufforderung erstellen</target>
</trans-unit>
<trans-unit id="sff5bb7742c2896c8">
<source>Target</source>
<target>Ziel</target>
</trans-unit>
<trans-unit id="sae5da213b7f896ed">
<source>Stage</source>
<target>Phase</target>
</trans-unit>
<trans-unit id="s0a61796c1956d32c">
<source>Evaluate when flow is planned</source>
</trans-unit>
<trans-unit id="sf533f13321fee530">
<source>Evaluate policies during the Flow planning process.</source>
</trans-unit>
<trans-unit id="s6336fa345e96dde9">
<source>Evaluate when stage is run</source>
</trans-unit>
<trans-unit id="sff3b708e23bb96b2">
<source>Evaluate policies before the Stage is present to the user.</source>
<target>Werten Sie Richtlinien aus, bevor die Phase dem Benutzer angezeigt wird.</target>
</trans-unit>
<trans-unit id="s0dc46deb8f181baf">
<source>Invalid response behavior</source>
</trans-unit>
<trans-unit id="seb0805249661d15b">
<source>Returns the error message and a similar challenge to the executor</source>
</trans-unit>
<trans-unit id="sd891d8463d0ebace">
<source>Restarts the flow from the beginning</source>
</trans-unit>
<trans-unit id="s6b9a1dd402750a8a">
<source>Restarts the flow from the beginning, while keeping the flow context</source>
</trans-unit>
<trans-unit id="sbc88fb27a4c3b894">
<source>Configure how the flow executor should handle an invalid response to a challenge given by this bound stage.</source>
</trans-unit>
<trans-unit id="s916b32ac64ea2b05">
<source>Successfully updated stage.</source>
<target>Phase erfolgreich aktualisiert.</target>
</trans-unit>
<trans-unit id="s14c8f36e180d6bbc">
<source>Successfully created stage.</source>
<target>Phase erfolgreich erstellt.</target>
</trans-unit>
<trans-unit id="sf22a28f83cc45fcc">
<source>Stage used to configure a duo-based authenticator. This stage should be used for configuration flows.</source>
<target>Phase, die zum Konfigurieren eines Duo-basierten Authentifikators verwendet wird. Diese Phase sollte für Konfigurationsabläufe verwendet werden.</target>
</trans-unit>
<trans-unit id="s5adafce329aaa853">
<source>Authenticator type name</source>
</trans-unit>
<trans-unit id="s23e6a57201fba25e">
<source>Display name of this authenticator, used by users when they enroll an authenticator.</source>
</trans-unit>
<trans-unit id="s276d751eb7a186cc">
<source>API Hostname</source>
<target>API Hostname</target>
</trans-unit>
<trans-unit id="s5b6b6e2cb884d59f">
<source>Duo Auth API</source>
<target>Duo Auth API</target>
</trans-unit>
<trans-unit id="s240ff02ce3a53dee">
<source>Integration key</source>
<target>Integrationsschlüssel</target>
</trans-unit>
<trans-unit id="s56fd9ed596c724fa">
<source>Secret key</source>
<target>Geheimer Schlüssel</target>
</trans-unit>
<trans-unit id="s88870d7e499e848b">
<source>Duo Admin API (optional)</source>
<target>Duo Admin API (optional)</target>
</trans-unit>
<trans-unit id="s7f13f4a2d0370cf6">
<source>When using a Duo MFA, Access or Beyond plan, an Admin API application can be created.
This will allow authentik to import devices automatically.</source>
</trans-unit>
<trans-unit id="s9a34d1520e320465">
<source>Stage-specific settings</source>
<target>Phasenspezifische Einstellungen</target>
</trans-unit>
<trans-unit id="s0dfc6838c9d07677">
<source>Configuration flow</source>
<target>Ablauf der Konfiguration</target>
</trans-unit>
<trans-unit id="sebf44d2471b608ad">
<source>Flow used by an authenticated user to configure this Stage. If empty, user will not be able to configure this stage.</source>
<target>Ablauf der von einem authentifizierten Benutzer verwendet wird, um diese Phase zu konfigurieren. Wenn leer, kann der Benutzer diese Phase nicht konfigurieren.</target>
</trans-unit>
<trans-unit id="s3baf512851453712">
<source>Twilio Account SID</source>
<target>Twilio Konto SID</target>
</trans-unit>
<trans-unit id="sa738ce390bc24875">
<source>Get this value from https://console.twilio.com</source>
<target>Holen Sie sich diesen Wert von https://console.twilio.com</target>
</trans-unit>
<trans-unit id="sa7b56a80ab1801f0">
<source>Twilio Auth Token</source>
<target>Twilio Authentifizierungs Token</target>
</trans-unit>
<trans-unit id="sfe99a8caa70232ab">
<source>Authentication Type</source>
<target>Authentifizierungsart</target>
</trans-unit>
<trans-unit id="safd0363143a46a91">
<source>Basic Auth</source>
<target>Basic Auth</target>
</trans-unit>
<trans-unit id="sd06b47084fec0ec5">
<source>Bearer Token</source>
<target>Bearer Token</target>
</trans-unit>
<trans-unit id="sb1751a1411d6874f">
<source>External API URL</source>
<target>Externe API URL</target>
</trans-unit>
<trans-unit id="sbdc1176ff9f93da2">
<source>This is the full endpoint to send POST requests to.</source>
<target>Dies ist der vollständige Endpunkt, an den POST-Anforderungen gesendet werden.</target>
</trans-unit>
<trans-unit id="s51da4de00984fe51">
<source>API Auth Username</source>
<target>API Auth Benutzername</target>
</trans-unit>
<trans-unit id="s293ab4331c1dd387">
<source>This is the username to be used with basic auth or the token when used with bearer token</source>
<target>Dies ist der Benutzername, der mit Basic Auth verwendet werden soll, oder das Token, wenn es mit Bearer-Token verwendet wird</target>
</trans-unit>
<trans-unit id="s634d041fd954ab20">
<source>API Auth password</source>
<target>API Auth Passwort</target>
</trans-unit>
<trans-unit id="sb635ad3c2e357d3c">
<source>This is the password to be used with basic auth</source>
<target>Dies ist das Passwort, das mit der Basisauthentifizierung verwendet werden soll</target>
</trans-unit>
<trans-unit id="sa92398dba8b12d85">
<source>Mapping</source>
</trans-unit>
<trans-unit id="s38162f615710c7b4">
<source>Modify the payload sent to the custom provider.</source>
</trans-unit>
<trans-unit id="s5e830ae7688d1219">
<source>Stage used to configure an SMS-based TOTP authenticator.</source>
<target>Phase, die zum Konfigurieren eines SMS-basierten TOTP-Authentifikators verwendet wird.</target>
</trans-unit>
<trans-unit id="s0d5d05bf3d122ced">
<source>Twilio</source>
<target>Twilio</target>
</trans-unit>
<trans-unit id="sc3c74f5273df459a">
<source>Generic</source>
<target>Generisch</target>
</trans-unit>
<trans-unit id="sbbb2180b6aed196e">
<source>From number</source>
<target>Von Nummer</target>
</trans-unit>
<trans-unit id="sc647dcb91f6958dd">
<source>Number the SMS will be sent from.</source>
<target>Nummer, von der die SMS gesendet wird</target>
</trans-unit>
<trans-unit id="s0ae0072614320ae2">
<source>Hash phone number</source>
<target>Hash-Telefonnummer</target>
</trans-unit>
<trans-unit id="s9ca3310e1999fd5b">
<source>If enabled, only a hash of the phone number will be saved. This can be done for data-protection reasons. Devices created from a stage with this enabled cannot be used with the authenticator validation stage.</source>
</trans-unit>
<trans-unit id="s128e7f5f34bfa155">
<source>Stage used to configure a static authenticator (i.e. static tokens). This stage should be used for configuration flows.</source>
<target>Phase, die zum Konfigurieren eines statischen Authentifikators (d. h. statischer Token) verwendet wird. Diese Phase sollte für Konfigurationsabläufe verwendet werden</target>
</trans-unit>
<trans-unit id="sabf67834e35dede5">
<source>Token count</source>
<target>Token Count</target>
</trans-unit>
<trans-unit id="sc5a4711395ffb043">
<source>Stage used to configure a TOTP authenticator (i.e. Authy/Google Authenticator).</source>
<target>Phase zum Konfigurieren eines TOTP-Authentifikators (z. B. Authy/Google Authenticator)</target>
</trans-unit>
<trans-unit id="s9d8ad4b85287131f">
<source>Digits</source>
<target>Ziffern</target>
</trans-unit>
<trans-unit id="sc04e92d753742189">
<source>6 digits, widely compatible</source>
<target>6 Ziffern, weitestgehend kompatibel</target>
</trans-unit>
<trans-unit id="sdc70195469e83e3f">
<source>8 digits, not compatible with apps like Google Authenticator</source>
<target>8 Ziffern, nicht kompatibel mit Anwendungen wie Google Authenticator</target>
</trans-unit>
<trans-unit id="s0e15f678445dfc45">
<source>Stage used to validate any authenticator. This stage should be used during authentication or authorization flows.</source>
<target>Phase, die verwendet wird, um einen beliebigen Authentifikator zu validieren. Diese Phase sollte während Authentifizierungs- oder Autorisierungsabläufen verwendet werden.</target>
</trans-unit>
<trans-unit id="s73c13e5a6f5e38a3">
<source>Device classes</source>
<target>Geräteklassen</target>
</trans-unit>
<trans-unit id="s97d1b0070f50c07f">
<source>Static Tokens</source>
<target>Statische Token</target>
</trans-unit>
<trans-unit id="sb8168ae309c66abc">
<source>TOTP Authenticators</source>
<target>TOTP-Authentifikatoren</target>
</trans-unit>
<trans-unit id="sde47e4d8b9b21b59">
<source>WebAuthn Authenticators</source>
<target>WebAuthn-Authentifikatoren</target>
</trans-unit>
<trans-unit id="s8da88a8a5750bce1">
<source>Duo Authenticators</source>
<target>Duo-Authentifikatoren</target>
</trans-unit>
<trans-unit id="s4d182bae8a578010">
<source>SMS-based Authenticators</source>
<target>SMS-basierte Authentifikatoren</target>
</trans-unit>
<trans-unit id="sd8d9451f86502d1a">
<source>Device classes which can be used to authenticate.</source>
<target>Geräteklassen, die zur Authentifizierung verwendet werden können.</target>
</trans-unit>
<trans-unit id="se2e9f5a32c93e5f7">
<source>Last validation threshold</source>
<target>Letzte Validierungsschwelle</target>
</trans-unit>
<trans-unit id="s951281efc92b03fc">
<source>If any of the devices user of the types selected above have been used within this duration, this stage will be skipped.</source>
<target>Wenn eines der oben ausgewählten Geräte innerhalb dieser Zeitspanne benutzt wurde, wird dieser Schritt übersprungen.</target>
</trans-unit>
<trans-unit id="s681074b6c1f19c08">
<source>Not configured action</source>
<target>Nicht konfigurierte Aktion</target>
</trans-unit>
<trans-unit id="sa2c29dc5ed47b26d">
<source>Force the user to configure an authenticator</source>
<target>Benutzer auffordern einen Authenticator einzurichten</target>
</trans-unit>
<trans-unit id="sa30c58514a3dc0fb">
<source>Deny the user access</source>
<target>Dem Benutzer den Zugang verweigern</target>
</trans-unit>
<trans-unit id="s1e0de9c4f66dc371">
<source>WebAuthn User verification</source>
</trans-unit>
<trans-unit id="sdb7b2173869822bc">
<source>User verification must occur.</source>
<target>Die Benutzerüberprüfung muss erfolgen.</target>
</trans-unit>
<trans-unit id="s7683363cdf78cf31">
<source>User verification is preferred if available, but not required.</source>
<target>Die Benutzerüberprüfung wird bevorzugt, falls verfügbar, aber nicht erforderlich.</target>
</trans-unit>
<trans-unit id="scb43f5faeb6a7ca9">
<source>User verification should not occur.</source>
<target>Die Benutzerüberprüfung sollte nicht stattfinden.</target>
</trans-unit>
<trans-unit id="scae166352a31032c">
<source>Configuration stages</source>
<target>Konfiguration Stufen</target>
</trans-unit>
<trans-unit id="s6941a67f0038ba4c">
<source>Stages used to configure Authenticator when user doesn't have any compatible devices. After this configuration Stage passes, the user is not prompted again.</source>
<target>Stufen zur Konfiguration des Authenticators, wenn der Benutzer keine kompatiblen Geräte besitzt. Nachdem diese Konfigurationsstufe abgeschlossen ist, wird der Benutzer nicht mehr dazu aufgefordert.</target>
</trans-unit>
<trans-unit id="s7e5af9c6ba6f5cc6">
<source>When multiple stages are selected, the user can choose which one they want to enroll.</source>
<target>Wenn mehrere Stufen ausgewählt sind, kann der Benutzer wählen, welche er registrieren möchte.</target>
</trans-unit>
<trans-unit id="s34b23ebbac9f6ab9">
<source>User verification</source>
<target>Benutzerüberprüfung</target>
</trans-unit>
<trans-unit id="s9ea472b555374771">
<source>Resident key requirement</source>
<target>Resident-Key-Anforderung</target>
</trans-unit>
<trans-unit id="s5fbaeb14f42815e5">
<source>Authenticator Attachment</source>
<target>Authenticator-Anhang</target>
</trans-unit>
<trans-unit id="s502d2473587032e1">
<source>No preference is sent</source>
<target>Keine Präferenz wird gesendet</target>
</trans-unit>
<trans-unit id="s60cc554fde2676cb">
<source>A non-removable authenticator, like TouchID or Windows Hello</source>
<target>Ein nicht abnehmbarer Authentifikator, wie TouchID oder Windows Hello</target>
</trans-unit>
<trans-unit id="sdf1d8edef27236f0">
<source>A "roaming" authenticator, like a YubiKey</source>
<target>Ein "Roaming"-Authentifikator, wie ein YubiKey</target>
</trans-unit>
<trans-unit id="sfffba7b23d8fb40c">
<source>This stage checks the user's current session against the Google reCaptcha (or compatible) service.</source>
</trans-unit>
<trans-unit id="sfd1af96798dd8a5f">
<source>Public Key</source>
<target>Öffentlicher Schlüssel</target>
</trans-unit>
<trans-unit id="sf339673f0f76a8bd">
<source>Public key, acquired from https://www.google.com/recaptcha/intro/v3.html.</source>
<target>Öffentlicher Schlüssel, erworben von https://www.google.com/recaptcha/intro/v3.html.</target>
</trans-unit>
<trans-unit id="s83d0f62ad1731a03">
<source>Private Key</source>
<target>Privater Schlüssel</target>
</trans-unit>
<trans-unit id="s892d2731a6f22e59">
<source>Private key, acquired from https://www.google.com/recaptcha/intro/v3.html.</source>
<target>Privater Schlüssel, erworben von https://www.google.com/recaptcha/intro/v3.html.</target>
</trans-unit>
<trans-unit id="scb6620fcd5bff04c">
<source>Advanced settings</source>
<target>Erweiterte Einstellungen</target>
</trans-unit>
<trans-unit id="s39e436de1dc4df4f">
<source>JS URL</source>
</trans-unit>
<trans-unit id="s170b705c55ecb2ae">
<source>URL to fetch JavaScript from, defaults to recaptcha. Can be replaced with any compatible alternative.</source>
</trans-unit>
<trans-unit id="s275021658614ce9e">
<source>API URL</source>
<target>API URL</target>
</trans-unit>
<trans-unit id="sc8a79fddea3ab4a9">
<source>URL used to validate captcha response, defaults to recaptcha. Can be replaced with any compatible alternative.</source>
</trans-unit>
<trans-unit id="s1cd617e7bbe278d0">
<source>Prompt for the user's consent. The consent can either be permanent or expire in a defined amount of time.</source>
<target>Abfrage zur Einwilligung von Benutzern. Die Einwilligung kann entweder permanent gelten oder in einer bestimmten Zeit ablaufen.</target>
</trans-unit>
<trans-unit id="s26513c9dd154f041">
<source>Always require consent</source>
<target>Immer nach Zustimmung fragen</target>
</trans-unit>
<trans-unit id="s8ce8bdc9cc9c8604">
<source>Consent given last indefinitely</source>
<target>Einwilligung gilt unbegrenzt</target>
</trans-unit>
<trans-unit id="sb986f15fa9b17805">
<source>Consent expires.</source>
<target>Einwilligung erlischt.</target>
</trans-unit>
<trans-unit id="s6f328f2d8382d998">
<source>Consent expires in</source>
<target>Einwilligung erlischt in</target>
</trans-unit>
<trans-unit id="se0c660020d9cf5b7">
<source>Offset after which consent expires.</source>
</trans-unit>
<trans-unit id="s22b10ed263b96194">
<source>Dummy stage used for testing. Shows a simple continue button and always passes.</source>
<target>Dummy-Stage zum Testen verwendet. Zeigt eine einfache Schaltfläche zum Fortfahren und besteht immer.</target>
</trans-unit>
<trans-unit id="sdb861d9906f18ac2">
<source>Throw error?</source>
</trans-unit>
<trans-unit id="s31ebc5431d677f5d">
<source>SMTP Host</source>
<target>SMTP Server</target>
</trans-unit>
<trans-unit id="s289fce7e694b98ac">
<source>SMTP Port</source>
<target>SMTP Port</target>
</trans-unit>
<trans-unit id="se4a9da0295597e73">
<source>SMTP Username</source>
<target>SMTP Benutzername</target>
</trans-unit>
<trans-unit id="s593db2c00d6516a2">
<source>SMTP Password</source>
<target>SMTP Passwort</target>
</trans-unit>
<trans-unit id="s0d4268408182491d">
<source>Use TLS</source>
<target>TLS verwenden</target>
</trans-unit>
<trans-unit id="s480c6c40a248f7d2">
<source>Use SSL</source>
<target>SSL verwenden</target>
</trans-unit>
<trans-unit id="sc1feadd25659c94d">
<source>From address</source>
<target>Absenderadresse</target>
</trans-unit>
<trans-unit id="sa248e1021d2c27b5">
<source>Verify the user's email address by sending them a one-time-link. Can also be used for recovery to verify the user's authenticity.</source>
<target>Überprüfen Sie die E-Mail-Adresse des Benutzers, indem Sie ihm einen einmaligen Link senden. Kann auch für die Wiederherstellung verwendet werden, um die Authentizität des Benutzers zu überprüfen.</target>
</trans-unit>
<trans-unit id="s87b7e3bc944c728c">
<source>Activate pending user on success</source>
<target>Aktiviere ausstehenden Benutzer bei Erfolg</target>
</trans-unit>
<trans-unit id="s9e9c8d99f4c26baf">
<source>When a user returns from the email successfully, their account will be activated.</source>
<target>Wenn ein Benutzer erfolgreich von der E-Mail zurückkehrt, wird sein Konto aktiviert</target>
</trans-unit>
<trans-unit id="s618d4e53f455c834">
<source>Use global settings</source>
<target>Verwende globale Einstellungen</target>
</trans-unit>
<trans-unit id="sae1e1a59d22609c4">
<source>When enabled, global Email connection settings will be used and connection settings below will be ignored.</source>
<target>Wenn diese Option aktiviert ist, werden die globalen E-Mail Verbindungseinstellungen benutzt und die unten angegebenen Einstellungen ignoriert</target>
</trans-unit>
<trans-unit id="sb1fe947f9ad27b9d">
<source>Token expiry</source>
<target>Ablauf des Tokens</target>
</trans-unit>
<trans-unit id="s1c6ba8d100453392">
<source>Time in minutes the token sent is valid.</source>
<target>Zeit in Minuten wie lange der verschickte Token gültig ist</target>
</trans-unit>
<trans-unit id="se47baf2fd16b9d2b">
<source>Template</source>
<target>Schablone</target>
</trans-unit>
<trans-unit id="s4af8a3ce5a600855">
<source>Let the user identify themselves with their username or Email address.</source>
<target>Lassen Sie den Benutzer sich mit seinem Benutzernamen oder seiner E-Mail-Adresse identifizieren.</target>
</trans-unit>
<trans-unit id="s592ab7d2bc1b8973">
<source>User fields</source>
<target>Benutzerfelder</target>
</trans-unit>
<trans-unit id="s61e48919db20538a">
<source>UPN</source>
<target>UPN</target>
</trans-unit>
<trans-unit id="s4cdae7635e757555">
<source>Fields a user can identify themselves with. If no fields are selected, the user will only be able to use sources.</source>
<target>Felder, mit denen sich ein Benutzer identifizieren kann. Wenn keine Felder ausgewählt sind, kann der Benutzer nur Quellen verwenden.</target>
</trans-unit>
<trans-unit id="s3380d7cbcebe50f6">
<source>Password stage</source>
<target>Passwort-Phase</target>
</trans-unit>
<trans-unit id="s08c91cb1a2cd3d97">
<source>When selected, a password field is shown on the same page instead of a separate page. This prevents username enumeration attacks.</source>
<target>Wenn diese Option ausgewählt ist, wird ein Passwortfeld auf derselben Seite statt auf einer separaten Seite angezeigt. Dadurch werden Angriffe auf die Aufzählung von Benutzernamen verhindert.</target>
</trans-unit>
<trans-unit id="sd97d8d0906e6cc47">
<source>Case insensitive matching</source>
<target>Abgleich ohne Berücksichtigung der Groß-/Kleinschreibung</target>
</trans-unit>
<trans-unit id="s8aaad223e954f9ca">
<source>When enabled, user fields are matched regardless of their casing.</source>
<target>Wenn diese Option aktiviert ist, werden Benutzerfelder unabhängig von ihrem Format abgeglichen.</target>
</trans-unit>
<trans-unit id="sbab723b98dcfe23f">
<source>Show matched user</source>
<target>Passenden Benutzer anzeigen</target>
</trans-unit>
<trans-unit id="se50a08ab71bb96ed">
<source>When a valid username/email has been entered, and this option is enabled, the user's username and avatar will be shown. Otherwise, the text that the user entered will be shown.</source>
<target>Sofern eine gültige E-Mailadresse oder Benutzername angegeben wurde und diese Option aktiviert ist, wird das Profilbild und der Benutzername des Benutzers angezeigt. Ansonsten wird der vom Benutzer eingegebene Text angezeigt.</target>
</trans-unit>
<trans-unit id="s0295ce5d6f635d75">
<source>Source settings</source>
</trans-unit>
<trans-unit id="s91e3a47599412f51">
<source>Sources</source>
<target>Quellen</target>
</trans-unit>
<trans-unit id="s17a679298216aca9">
<source>Select sources should be shown for users to authenticate with. This only affects web-based sources, not LDAP.</source>
<target>Es sollten ausgewählte Quellen angezeigt werden, mit denen sich Benutzer authentifizieren können. Dies betrifft nur webbasierte Quellen, nicht LDAP.</target>
</trans-unit>
<trans-unit id="sa41aee3ae04c9216">
<source>Show sources' labels</source>
<target>Bezeichnungen der Quellen anzeigen</target>
</trans-unit>
<trans-unit id="s54cd35e6224ba65d">
<source>By default, only icons are shown for sources. Enable this to show their full names.</source>
<target>Standardmäßig werden für Quellen nur Symbole angezeigt. Aktiviere diese Option, um den vollständigen Namen anzuzeigen.</target>
</trans-unit>
<trans-unit id="s9ee20003cb116abf">
<source>Passwordless flow</source>
<target>Passwortloser Ablauf</target>
</trans-unit>
<trans-unit id="s0c8c4d2bb0a9162a">
<source>Optional passwordless flow, which is linked at the bottom of the page. When configured, users can use this flow to authenticate with a WebAuthn authenticator, without entering any details.</source>
<target>Optionaler passwortloser Ablauf, der unten auf der Seite verlinkt ist. Nach der Konfiguration können Benutzer diesen Ablauf verwenden, um sich mit einem WebAuthn-Authentifikator zu authentifizieren, ohne Details einzugeben.</target>
</trans-unit>
<trans-unit id="s01a3a7f48ee4edaf">
<source>Optional enrollment flow, which is linked at the bottom of the page.</source>
<target>Optionaler Anmeldevorgang, der unten auf der Seite verlinkt ist.</target>
</trans-unit>
<trans-unit id="s82188c9542510212">
<source>Optional recovery flow, which is linked at the bottom of the page.</source>
<target>Optionaler Wiederherstellungsablauf, der unten auf der Seite verlinkt ist.</target>
</trans-unit>
<trans-unit id="s3e59b8b2debf0209">
<source>This stage can be included in enrollment flows to accept invitations.</source>
<target>Diese Phase kann in Registrierungsabläufe aufgenommen werden, um Einladungen anzunehmen.</target>
</trans-unit>
<trans-unit id="s79ad406777feab1f">
<source>Continue flow without invitation</source>
<target>Ablauf mit Einladung fortsetzen</target>
</trans-unit>
<trans-unit id="s61ccefd661ac2296">
<source>If this flag is set, this Stage will jump to the next Stage when no Invitation is given. By default this Stage will cancel the Flow when no invitation is given.</source>
<target>Wenn dieses Flag gesetzt ist, springt diese Stufe zur nächsten Stufe, wenn keine Einladung gegeben wird. Standardmäßig bricht diese Phase den Flow ab, wenn keine Einladung gegeben wird.</target>
</trans-unit>
<trans-unit id="sdc30bddeda2f0225">
<source>Validate the user's password against the selected backend(s).</source>
<target>Validieren Sie das Passwort des Benutzers mit den ausgewählten Backends.</target>
</trans-unit>
<trans-unit id="sb8d4f44a1d5b9a14">
<source>Backends</source>
<target>Backends</target>
</trans-unit>
<trans-unit id="sba42248f3f27955c">
<source>User database + standard password</source>
<target>Benutzer Datenbank + Standardpasswort</target>
</trans-unit>
<trans-unit id="s3330adb3f0922f7b">
<source>User database + app passwords</source>
<target>Benutzer Datenbank + Applikations Passwort</target>
</trans-unit>
<trans-unit id="sc10db51c9bb77d5c">
<source>User database + LDAP password</source>
<target>Benutzer Datenbank + LDAP Passwort</target>
</trans-unit>
<trans-unit id="sd35ae4be63df1f9f">
<source>Selection of backends to test the password against.</source>
<target>Auswahl der Backends, mit denen das Kennwort getestet werden soll.</target>
</trans-unit>
<trans-unit id="s482ae78809a6822b">
<source>Flow used by an authenticated user to configure their password. If empty, user will not be able to configure change their password.</source>
<target>Ablauf, der von einem authentifizierten Benutzer verwendet wird, um sein Passwort zu konfigurieren. Wenn leer, kann der Benutzer sein Passwort nicht ändern.</target>
</trans-unit>
<trans-unit id="s77994108c886b965">
<source>Failed attempts before cancel</source>
<target>Fehlgeschlagene Versuche vor Abbruch</target>
</trans-unit>
<trans-unit id="sa9020b93c3bd7235">
<source>How many attempts a user has before the flow is canceled. To lock the user out, use a reputation policy and a user_write stage.</source>
<target>Anzahl der Versuche, die Benutzer haben, bevor der Ablauf abgebrochen wird. Um Benutzer auszuschließen kann eine Reputations-Richtlinie und eine user_write-Stufe genutzt werden.</target>
</trans-unit>
<trans-unit id="s5170f9ef331949c0">
<source>Show arbitrary input fields to the user, for example during enrollment. Data is saved in the flow context under the 'prompt_data' variable.</source>
<target>Zeigen Sie dem Benutzer beliebige Eingabefelder, beispielsweise während der Registrierung. Daten werden im Flow-Kontext unter der Variablen „prompt_data“ gespeichert.</target>
</trans-unit>
<trans-unit id="s36cb242ac90353bc">
<source>Fields</source>
<target>Felder</target>
</trans-unit>
<trans-unit id="s2d5f69929bb7221d">
<source><x id="0" equiv-text="${prompt.name}"/> ("<x id="1" equiv-text="${prompt.fieldKey}"/>", of type <x id="2" equiv-text="${prompt.type}"/>)</source>
<target>
<x id="0" equiv-text="${prompt.name}"/>("
<x id="1" equiv-text="${prompt.fieldKey}"/>", vom Typ
<x id="2" equiv-text="${prompt.type}"/>)</target>
</trans-unit>
<trans-unit id="s3b7b519444181264">
<source>Validation Policies</source>
<target>Validierungsrichtlinien</target>
</trans-unit>
<trans-unit id="s59691290a232c687">
<source>Selected policies are executed when the stage is submitted to validate the data.</source>
<target>Ausgewählte Richtlinien werden ausgeführt, wenn die Stufe zur Validierung der Daten übermittelt wird.</target>
</trans-unit>
<trans-unit id="sbf4ef82e04772a4e">
<source>Delete the currently pending user. CAUTION, this stage does not ask for confirmation. Use a consent stage to ensure the user is aware of their actions.</source>
</trans-unit>
<trans-unit id="s8cc920e6a8430a0d">
<source>Log the currently pending user in.</source>
<target>Melden Sie den aktuell ausstehenden Benutzer an.</target>
</trans-unit>
<trans-unit id="sb85ffe141d7c229d">
<source>Session duration</source>
<target>Sessionsdauer</target>
</trans-unit>
<trans-unit id="sece294cd51a85745">
<source>Determines how long a session lasts. Default of 0 seconds means that the sessions lasts until the browser is closed.</source>
<target>Legt fest, wie lange eine Sitzung dauert. Der Standardwert von 0 Sekunden bedeutet, dass die Sitzungen dauern, bis der Browser geschlossen wird.</target>
</trans-unit>
<trans-unit id="sf7949fbbab2eb566">
<source>Different browsers handle session cookies differently, and might not remove them even when the browser is closed.</source>
</trans-unit>
<trans-unit id="s53bbc3ae4b5fa1d0">
<source>See here.</source>
</trans-unit>
<trans-unit id="s2512334108f06a5a">
<source>Stay signed in offset</source>
</trans-unit>
<trans-unit id="s1608b2f94fa0dbd4">
<source>If set to a duration above 0, the user will have the option to choose to "stay signed in", which will extend their session by the time specified here.</source>
</trans-unit>
<trans-unit id="s542a71bb8f41e057">
<source>Terminate other sessions</source>
</trans-unit>
<trans-unit id="sa920231366378c90">
<source>When enabled, all previous sessions of the user will be terminated.</source>
</trans-unit>
<trans-unit id="sfee06600c15082a9">
<source>Remove the user from the current session.</source>
<target>Entfernen Sie den Benutzer aus der aktuellen Sitzung.</target>
</trans-unit>
<trans-unit id="s927398c400970760">
<source>Write any data from the flow's context's 'prompt_data' to the currently pending user. If no user
is pending, a new user is created, and data is written to them.</source>
</trans-unit>
<trans-unit id="sb379d861cbed0b47">
<source>Never create users</source>
</trans-unit>
<trans-unit id="s81d673755a86a4f0">
<source>When no user is present in the flow context, the stage will fail.</source>
</trans-unit>
<trans-unit id="s9940e3f073fbdbd4">
<source>Create users when required</source>
</trans-unit>
<trans-unit id="s5414356cc10e80fe">
<source>When no user is present in the the flow context, a new user is created.</source>
</trans-unit>
<trans-unit id="s57337099d96ce6d2">
<source>Always create new users</source>
<target>Immer neuen Benutzer erzeugen</target>
</trans-unit>
<trans-unit id="se80dd66f23b4fc39">
<source>Create a new user even if a user is in the flow context.</source>
</trans-unit>
<trans-unit id="sed3512fe4560c7f4">
<source>Create users as inactive</source>
<target>Benutzer als inaktiv anlegen</target>
</trans-unit>
<trans-unit id="s9193ef1a39a6c872">
<source>Mark newly created users as inactive.</source>
<target>Neu erstellte Benutzer als inaktiv markieren.</target>
</trans-unit>
<trans-unit id="s89d1847b5e4ad225">
<source>User path template</source>
</trans-unit>
<trans-unit id="s18269e3889d6fa54">
<source>Path new users will be created under. If left blank, the default path will be used.</source>
</trans-unit>
<trans-unit id="sc1cb0eef9ed94e6a">
<source>Newly created users are added to this group, if a group is selected.</source>
<target>Neu erstellte Benutzer werden dieser Gruppe hinzugefügt, wenn eine Gruppe ausgewählt ist.</target>
</trans-unit>
<trans-unit id="sd8417b41ca27bc8f">
<source>New stage</source>
<target>Neue Stufe</target>
</trans-unit>
<trans-unit id="s293801033f9fc0d0">
<source>Create a new stage.</source>
<target>Neue Stufe erstellen.</target>
</trans-unit>
<trans-unit id="s71633a67e0d7c0e4">
<source>Successfully imported device.</source>
</trans-unit>
<trans-unit id="s7d61705dfb120d7b">
<source>The user in authentik this device will be assigned to.</source>
</trans-unit>
<trans-unit id="s5eaf1d304e03ed4b">
<source>Duo User ID</source>
<target>Duo User ID</target>
</trans-unit>
<trans-unit id="s003847d8bc01c676">
<source>The user ID in Duo, can be found in the URL after clicking on a user.</source>
</trans-unit>
<trans-unit id="sbbc806ea3987c781">
<source>Automatic import</source>
</trans-unit>
<trans-unit id="s77299a9d3dd932cd">
<source>Successfully imported <x id="0" equiv-text="${res.count}"/> devices.</source>
</trans-unit>
<trans-unit id="s6a615f6165ef01c9">
<source>Start automatic import</source>
</trans-unit>
<trans-unit id="s9f83d7768aea548a">
<source>Or manually import</source>
</trans-unit>
<trans-unit id="sddc8efe94cb8c210">
<source>Stages are single steps of a Flow that a user is guided through. A stage can only be executed from within a flow.</source>
<target>Phasen sind einzelne Schritte eines Flows, durch die ein Benutzer geführt wird. Eine Phase kann nur innerhalb eines Flows ausgeführt werden.</target>
</trans-unit>
<trans-unit id="sb69a4b0acd0895f2">
<source>Flows</source>
<target>Abläufe</target>
</trans-unit>
<trans-unit id="s0eaf755fa88c8d97">
<source>Stage(s)</source>
<target>Phase(n)</target>
</trans-unit>
<trans-unit id="s3914cb410fca44d4">
<source>Import</source>
<target>Importieren</target>
</trans-unit>
<trans-unit id="s8a67b33a0d70d322">
<source>Import Duo device</source>
<target>Duo Gerät importieren</target>
</trans-unit>
<trans-unit id="s48cf8fd56b1237ed">
<source>Successfully updated flow.</source>
<target>Ablauf erfolgreich aktualisiert.</target>
</trans-unit>
<trans-unit id="sc3e0c240b159fbce">
<source>Successfully created flow.</source>
<target>Ablauf erfolgreich erstellt.</target>
</trans-unit>
<trans-unit id="s925936f647ae52cc">
<source>Shown as the Title in Flow pages.</source>
<target>Wird als Titel auf den Ablaufseiten angezeigt.</target>
</trans-unit>
<trans-unit id="s50719dda8f90abf4">
<source>Visible in the URL.</source>
<target>Sichtbar in der URL</target>
</trans-unit>
<trans-unit id="s0f4c6540c30bd8b4">
<source>Designation</source>
<target>Bezeichnung</target>
</trans-unit>
<trans-unit id="sb25d9afe10941425">
<source>Decides what this Flow is used for. For example, the Authentication flow is redirect to when an un-authenticated user visits authentik.</source>
<target>Entscheidet, wofür dieser Flow verwendet wird. Beispielsweise wird der Authentifizierungsablauf umgeleitet, wenn ein nicht authentifizierter Benutzer authentik besucht.</target>
</trans-unit>
<trans-unit id="sb36e4c05244278c1">
<source>No requirement</source>
</trans-unit>
<trans-unit id="s7b105164d209f670">
<source>Require authentication</source>
</trans-unit>
<trans-unit id="s239c2a351cde6d39">
<source>Require no authentication.</source>
</trans-unit>
<trans-unit id="s98beadfeeb3acb66">
<source>Require superuser.</source>
</trans-unit>
<trans-unit id="sfad9279cc42c6b61">
<source>Required authentication level for this flow.</source>
</trans-unit>
<trans-unit id="sb56674c9ea4f0588">
<source>Behavior settings</source>
</trans-unit>
<trans-unit id="sb6d7d58cb0a1544e">
<source>Compatibility mode</source>
<target>Kompatibilitätsmodus</target>
</trans-unit>
<trans-unit id="s14ace18ccf4fb86d">
<source>Increases compatibility with password managers and mobile devices.</source>
</trans-unit>
<trans-unit id="scfbc2f1396ee8550">
<source>Denied action</source>
</trans-unit>
<trans-unit id="sff38031cf061e3ae">
<source>Will follow the ?next parameter if set, otherwise show a message</source>
</trans-unit>
<trans-unit id="s936bf4342b182ad4">
<source>Will either follow the ?next parameter or redirect to the default interface</source>
</trans-unit>
<trans-unit id="s22b0e8c5277dd5a9">
<source>Will notify the user the flow isn't applicable</source>
</trans-unit>
<trans-unit id="s2eeca5cfc99ef19b">
<source>Decides the response when a policy denies access to this flow for a user.</source>
</trans-unit>
<trans-unit id="sbaf20067de176c90">
<source>Appearance settings</source>
</trans-unit>
<trans-unit id="s2e4818861000b13f">
<source>Layout</source>
<target>Aufbau</target>
</trans-unit>
<trans-unit id="s1efbfc3937d565bd">
<source>Background</source>
<target>Hintergrund</target>
</trans-unit>
<trans-unit id="s374abf1a54d87b67">
<source>Background shown during execution.</source>
<target>Hintergrund während der Ausführung.</target>
</trans-unit>
<trans-unit id="s3ebf4c166058afce">
<source>Clear background</source>
</trans-unit>
<trans-unit id="sb24755ea94bef31d">
<source>Delete currently set background image.</source>
<target>Aktuelles Hintergrundbild löschen</target>
</trans-unit>
<trans-unit id="sb904f23f17b60c3a">
<source>Successfully imported flow.</source>
<target>Ablauf erfolgreich importiert.</target>
</trans-unit>
<trans-unit id="s344c4a2a48997e18">
<source>.yaml files, which can be found on goauthentik.io and can be exported by authentik.</source>
</trans-unit>
<trans-unit id="sc816360d6f5a1eeb">
<source>Flows describe a chain of Stages to authenticate, enroll or recover a user. Stages are chosen based on policies applied to them.</source>
<target>Abläufe beschreiben eine Kette von Phasen zum Authentifizieren, Registrieren oder Wiederherstellen eines Benutzers. Phasen werden basierend auf den auf sie angewendeten Richtlinien ausgewählt.</target>
</trans-unit>
<trans-unit id="s6f857299d5db1ecf">
<source>Flow(s)</source>
<target>Ablauf/Abläufe</target>
</trans-unit>
<trans-unit id="s9e830cbc0b42a514">
<source>Update Flow</source>
<target>Ablauf aktualisieren</target>
</trans-unit>
<trans-unit id="s2f1bcfcc5cae94c3">
<source>Create Flow</source>
<target>Ablauf erstellen</target>
</trans-unit>
<trans-unit id="s832282d415294df4">
<source>Import Flow</source>
<target>Ablauf importieren</target>
</trans-unit>
<trans-unit id="s098237f7ccb4dc4a">
<source>Successfully cleared flow cache</source>
<target>Der Ablauf-Cache wurde erfolgreich geleert</target>
</trans-unit>
<trans-unit id="s59572c1be31a812e">
<source>Failed to delete flow cache</source>
<target>Ablaufpuffer löschen fehlgeschlagen</target>
</trans-unit>
<trans-unit id="sa2b727168b090d34">
<source>Clear Flow cache</source>
<target>Flow-Cache löschen</target>
</trans-unit>
<trans-unit id="sf12d588a76ba7e51">
<source>Are you sure you want to clear the flow cache?
This will cause all flows to be re-evaluated on their next usage.</source>
</trans-unit>
<trans-unit id="sbe47a5bdeec19ab0">
<source>Stage binding(s)</source>
<target>Phasen Bindung(en)</target>
</trans-unit>
<trans-unit id="sfa88f413e287bb0f">
<source>Stage type</source>
<target>Phasen Typ</target>
</trans-unit>
<trans-unit id="s04440099d97c0bef">
<source>Edit Stage</source>
<target>Stufe bearbeiten</target>
</trans-unit>
<trans-unit id="s980270d0fab7ecb3">
<source>Update Stage binding</source>
<target>Phasenbindung aktualisieren</target>
</trans-unit>
<trans-unit id="sfe938c1585e0bf68">
<source>These bindings control if this stage will be applied to the flow.</source>
<target>Diese Bindungen steuern, ob diese Stufe auf den Ablauf angewendet wird.</target>
</trans-unit>
<trans-unit id="sfac6f995c7670559">
<source>No Stages bound</source>
<target>Keine Phasen verknüpft.</target>
</trans-unit>
<trans-unit id="s955c1fec1c6fb970">
<source>No stages are currently bound to this flow.</source>
<target>Aktuell sind keine Phasen mit diesem Ablauf verknüpft.</target>
</trans-unit>
<trans-unit id="s9a393a04eaf1eb0e">
<source>Create Stage binding</source>
<target>Stage Bindung erstellen</target>
</trans-unit>
<trans-unit id="s207e8b106806d7e4">
<source>Bind stage</source>
<target>Phasen-Verknüpfung</target>
</trans-unit>
<trans-unit id="scc2e420c54dc8089">
<source>Bind existing stage</source>
</trans-unit>
<trans-unit id="s30d1f50f476c3f48">
<source>Flow Overview</source>
<target>Ablauf Übersicht</target>
</trans-unit>
<trans-unit id="s77099d752f1ab773">
<source>Related actions</source>
</trans-unit>
<trans-unit id="sd07866d9f38b2c50">
<source>Execute flow</source>
<target>Ablauf ausführen</target>
</trans-unit>
<trans-unit id="s9ff3121d30f88d52">
<source>Normal</source>
<target>Normal</target>
</trans-unit>
<trans-unit id="s6e4c997a101b6abf">
<source>with current user</source>
<target>mit aktuellem Nutzer</target>
</trans-unit>
<trans-unit id="s8ecdbff1a7329b64">
<source>with inspector</source>
<target>mit Inspektor</target>
</trans-unit>
<trans-unit id="s3576aead3e68c5c9">
<source>Export flow</source>
<target>Ablauf exportieren</target>
</trans-unit>
<trans-unit id="s293aa6a6446fb153">
<source>Export</source>
<target>Exportieren</target>
</trans-unit>
<trans-unit id="se2c3cbf2ed1403f1">
<source>Stage Bindings</source>
<target>Phasen Bindungen</target>
</trans-unit>
<trans-unit id="s78c08391ffbfb8c0">
<source>These bindings control which users can access this flow.</source>
<target>Diese Bindungen steuern, welche Benutzer auf diesen Ablauf zugreifen können.</target>
</trans-unit>
<trans-unit id="sc1a1ff47c058bb09">
<source>Event Log</source>
<target>Ereignisprotokoll</target>
</trans-unit>
<trans-unit id="s65d67612999165e9">
<source>Event <x id="0" equiv-text="${this.event.pk}"/></source>
<target>Ereignis
<x id="0" equiv-text="${this.event.pk}"/></target>
</trans-unit>
<trans-unit id="s455de2f740b073fd">
<source>Event info</source>
<target>Ereignisinfo</target>
</trans-unit>
<trans-unit id="sb41b2cfbbc52565b">
<source>Created</source>
</trans-unit>
<trans-unit id="s037bc6d25a03c3c8">
<source>Successfully updated transport.</source>
<target>Zustellungsart erfolgreich aktualisiert.</target>
</trans-unit>
<trans-unit id="s1575a15cee001915">
<source>Successfully created transport.</source>
<target>Zustellungsart erfolgreich erstellt.</target>
</trans-unit>
<trans-unit id="s4acf840bc792c3ae">
<source>Local (notifications will be created within authentik)</source>
<target>Lokal (Benachrichtigungen werden innerhalb von authentik erstellt)</target>
</trans-unit>
<trans-unit id="sede0abbf2b612812">
<source>Webhook (generic)</source>
<target>Webhook (generic)</target>
</trans-unit>
<trans-unit id="s76f5dca6404a1210">
<source>Webhook (Slack/Discord)</source>
<target>Webhook (Slack/Discord)</target>
</trans-unit>
<trans-unit id="s6873bdbfa24615fb">
<source>Webhook URL</source>
<target>Webhook URL</target>
</trans-unit>
<trans-unit id="s25ec2846f6b88214">
<source>Webhook Mapping</source>
<target>Webhook Zuordnung</target>
</trans-unit>
<trans-unit id="sca2879d96f58a39c">
<source>Send once</source>
<target>Einmal senden</target>
</trans-unit>
<trans-unit id="s2430e000b7cfefd0">
<source>Only send notification once, for example when sending a webhook into a chat channel.</source>
<target>Benachrichtigung nur einmal senden, z. B. beim Senden eines Webhooks in einen Chat-Kanal</target>
</trans-unit>
<trans-unit id="s819509c33a7534ac">
<source>Notification Transports</source>
<target>Mitteilungszustellungsarten</target>
</trans-unit>
<trans-unit id="s57072ffb92b6c9c8">
<source>Define how notifications are sent to users, like Email or Webhook.</source>
<target>Definieren Sie, wie Benachrichtigungen an Benutzer gesendet werden, z. B. E-Mail oder Webhook.</target>
</trans-unit>
<trans-unit id="s624256f8a4bb4c89">
<source>Notification transport(s)</source>
<target>Mitteilungszustellungsart(en)</target>
</trans-unit>
<trans-unit id="sac1332e6f421526e">
<source>Update Notification Transport</source>
<target>Mitteilungszustellungsart aktualisieren</target>
</trans-unit>
<trans-unit id="s6b5002c605b39d6d">
<source>Create Notification Transport</source>
<target>Mitteilungszustellungsart erstellen</target>
</trans-unit>
<trans-unit id="s0a39e4f61ccafacb">
<source>Successfully updated rule.</source>
<target>Regel erfolgreich aktualisiert.</target>
</trans-unit>
<trans-unit id="s72e102414fec81a4">
<source>Successfully created rule.</source>
<target>Regel erfolgreich erstellt.</target>
</trans-unit>
<trans-unit id="sa55ee64c5c51df0f">
<source>Select the group of users which the alerts are sent to. If no group is selected the rule is disabled.</source>
</trans-unit>
<trans-unit id="sffa171e11d4ae513">
<source>Transports</source>
<target>Zustellungsarten</target>
</trans-unit>
<trans-unit id="s7b18721be331241e">
<source>Select which transports should be used to notify the user. If none are selected, the notification will only be shown in the authentik UI.</source>
<target>Wählen Sie, welche Zustellungsart genutzt werden soll um Benutzer zu benachrichtigen. Wenn keine gewählt wurde, werden Benachrichtigungen nur in der Authentik-Oberfläche angezeigt.</target>
</trans-unit>
<trans-unit id="scd0cfe87af6f2ff2">
<source>Severity</source>
<target>Schweregrad</target>
</trans-unit>
<trans-unit id="s98c3bdf4fd5cdf65">
<source>Notification Rules</source>
<target>Benachrichtigungsregeln</target>
</trans-unit>
<trans-unit id="s107bf77afb93c9b8">
<source>Send notifications whenever a specific Event is created and matched by policies.</source>
<target>Senden Sie Benachrichtigungen, wenn ein bestimmtes Ereignis erstellt und mit Richtlinien abgeglichen wird.</target>
</trans-unit>
<trans-unit id="sf3f9a0feaf083207">
<source>Sent to group</source>
<target>An Gruppe gesendet</target>
</trans-unit>
<trans-unit id="sc92ed9d5e01d3f24">
<source>Notification rule(s)</source>
<target>Benachrichtigungsregel(n)</target>
</trans-unit>
<trans-unit id="s5140d157642d7362">
<source>None (rule disabled)</source>
<target>Keine (Regel deaktiviert)</target>
</trans-unit>
<trans-unit id="sd1146418b344f81f">
<source>Update Notification Rule</source>
<target>Benachrichtigungsregel aktualisieren</target>
</trans-unit>
<trans-unit id="sbbc1de43ab6c1f76">
<source>Create Notification Rule</source>
<target>Benachrichtigungsregel erstellen</target>
</trans-unit>
<trans-unit id="s5795b310ab271d20">
<source>These bindings control upon which events this rule triggers.
Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s90c3b62194fe8508">
<source>Outpost Deployment Info</source>
<target>Outpost-Installationsinfo</target>
</trans-unit>
<trans-unit id="s35f9df7668d5fa79">
<source>View deployment documentation</source>
<target>Installationsdokumentation anzeigen</target>
</trans-unit>
<trans-unit id="sad09c62cb4ebae68">
<source>Click to copy token</source>
<target>Token kopieren</target>
</trans-unit>
<trans-unit id="s0e03fe2dc5b9164b">
<source>If your authentik Instance is using a self-signed certificate, set this value.</source>
<target>Wenn Ihre authentik-Instanz ein selbstsigniertes Zertifikat verwendet, setzen Sie diesen Wert.</target>
</trans-unit>
<trans-unit id="sc21032b0d37882a0">
<source>If your authentik_host setting does not match the URL you want to login with, add this setting.</source>
<target>Wenn Ihre authentik_host-Einstellung nicht der URL entspricht, mit der Sie sich anmelden, fügen Sie diese Einstellung hinzu.</target>
</trans-unit>
<trans-unit id="s6f270e1668c036e9">
<source>Successfully updated outpost.</source>
<target>Outpost erfolgreich aktualisiert.</target>
</trans-unit>
<trans-unit id="s79aed8154d7c472c">
<source>Successfully created outpost.</source>
<target>Outpost erfolgreich erstellt.</target>
</trans-unit>
<trans-unit id="s8afc8c5aafb392d3">
<source>Radius</source>
</trans-unit>
<trans-unit id="s03970aa76a09982d">
<source>Integration</source>
<target>Integration</target>
</trans-unit>
<trans-unit id="s9c29565c5ae1cc92">
<source>Selecting an integration enables the management of the outpost by authentik.</source>
<target>Die Auswahl einer Integration ermöglicht die Verwaltung des Outposts durch Authentik.</target>
</trans-unit>
<trans-unit id="s554ce268e9727e79">
<source>You can only select providers that match the type of the outpost.</source>
<target>Sie können nur Anbieter auswählen, die zum Typ des Outposts passen.</target>
</trans-unit>
<trans-unit id="sf9b1c0661a02d9f9">
<source>Configuration</source>
<target>Konfiguration</target>
</trans-unit>
<trans-unit id="s3abecf1e778c9625">
<source>See more here:</source>
</trans-unit>
<trans-unit id="s74cb3d66f6a668e1">
<source>Documentation</source>
</trans-unit>
<trans-unit id="saa8939ac88a76f98">
<source>Last seen</source>
</trans-unit>
<trans-unit id="s1ac2653a6492b435">
<source><x id="0" equiv-text="${this.outpostHealth.version}"/>, should be <x id="1" equiv-text="${this.outpostHealth.versionShould}"/></source>
<target>"
<x id="0" equiv-text="${this.outpostHealth.version}"/>", sollte "
<x id="1" equiv-text="${this.outpostHealth.versionShould}"/>" sein</target>
</trans-unit>
<trans-unit id="s1e176e35c828318c">
<source>Hostname</source>
</trans-unit>
<trans-unit id="s322e34cfcba47155">
<source>Not available</source>
<target>Nicht verfügbar</target>
</trans-unit>
<trans-unit id="s02b632a9ac24a824">
<source>Last seen: <x id="0" equiv-text="${this.outpostHealth.lastSeen?.toLocaleTimeString()}"/></source>
<target>Überprüft:
<x id="0" equiv-text="${this.outpostHealth.lastSeen?.toLocaleTimeString()}"/></target>
</trans-unit>
<trans-unit id="sa43153d53ae65063">
<source>Unknown type</source>
</trans-unit>
<trans-unit id="s5e169e1bac20b4a6">
<source>Outposts</source>
<target>Outposts</target>
</trans-unit>
<trans-unit id="s8802553bc57617ee">
<source>Outposts are deployments of authentik components to support different environments and protocols, like reverse proxies.</source>
<target>Outposts sind Installationen von authentik-Komponenten, die Unterstützung für unterschiedliche Umgebungen und Protokolle wie Reverse Proxies bereitsstellen.</target>
</trans-unit>
<trans-unit id="s84d7d6ebbedcb586">
<source>Health and Version</source>
<target>Zustand und Version</target>
</trans-unit>
<trans-unit id="s9bf48a89367282cd">
<source>Warning: authentik Domain is not configured, authentication will not work.</source>
<target>Warnung: authentik-Domain ist nicht konfiguriert. Authentifizierungen werden nicht funktionieren.</target>
</trans-unit>
<trans-unit id="sbf5f4c5ba679e847">
<source>Logging in via <x id="0" equiv-text="${item.config.authentik_host}"/>.</source>
<target>Anmelden über
<x id="0" equiv-text="${item.config.authentik_host}"/>.</target>
</trans-unit>
<trans-unit id="s59b6028f19d15cda">
<source>No integration active</source>
<target>Keine Integrationen aktiv</target>
</trans-unit>
<trans-unit id="s9bd59e0ea70a3e4a">
<source>Update Outpost</source>
<target>Outpost aktualisieren</target>
</trans-unit>
<trans-unit id="sc8f286ac783c385d">
<source>View Deployment Info</source>
<target>Installationsinfo anzeigen</target>
</trans-unit>
<trans-unit id="s9ee92717d7f63247">
<source>Detailed health (one instance per column, data is cached so may be out of date)</source>
</trans-unit>
<trans-unit id="s1d49ec5030447643">
<source>Outpost(s)</source>
<target>Outpost(s)</target>
</trans-unit>
<trans-unit id="s1a2f8f4b3861583b">
<source>Create Outpost</source>
<target>Außenposten erstellen</target>
</trans-unit>
<trans-unit id="sdc1ef94016f0d855">
<source>Successfully updated integration.</source>
<target>Integration erfolgreich aktualisiert.</target>
</trans-unit>
<trans-unit id="sc2a1a40a1b4b0170">
<source>Successfully created integration.</source>
<target>Integration erfolgreich erstellt.</target>
</trans-unit>
<trans-unit id="se9b1fec72ffd8f48">
<source>Local</source>
<target>Lokal</target>
</trans-unit>
<trans-unit id="sc1231049879b8d33">
<source>If enabled, use the local connection. Required Docker socket/Kubernetes Integration.</source>
<target>Nutze, wenn aktiviert, die lokale Verbindung. Benötigt Docker socket/Kubernetes Integration.</target>
</trans-unit>
<trans-unit id="s13de04774ff0f210">
<source>Docker URL</source>
<target>Docker URL</target>
</trans-unit>
<trans-unit id="sa7fcf026bd25f231">
<source>Can be in the format of 'unix://' when connecting to a local docker daemon, using 'ssh://' to connect via SSH, or 'https://:2376' when connecting to a remote system.</source>
<target>Kann das Format 'unix://' haben, wenn eine Verbindung zu einem lokalen Docker-Daemon hergestellt wird, oder 'ssh://', wenn eine Verbindung über SSH hergestellt wird, oder 'https://:2376', wenn eine Verbindung zu einem entfernten System hergestellt wird.</target>
</trans-unit>
<trans-unit id="saf1d289e3137c2ea">
<source>CA which the endpoint's Certificate is verified against. Can be left empty for no validation.</source>
<target>CA, anhand derer das Zertifikat des Endpunkts überprüft wird. Kann leer gelassen werden, um keine Validierung durchzuführen.</target>
</trans-unit>
<trans-unit id="s0f2e070d38cd36df">
<source>TLS Authentication Certificate/SSH Keypair</source>
<target>TLS-Authentifizierungszertifikat/SSH-Schlüsselpaar</target>
</trans-unit>
<trans-unit id="s2f58bb9905d2b76f">
<source>Certificate/Key used for authentication. Can be left empty for no authentication.</source>
<target>Zertifikat/Schlüssel für die Authentifizierung. Kann leer gelassen werden, wenn keine Authentifizierung erfolgt.</target>
</trans-unit>
<trans-unit id="s8b33660e2ed7212c">
<source>When connecting via SSH, this keypair is used for authentication.</source>
<target>Bei Verbindung via SSH wird dieses Schlüsselpaar zur Authentifizierung genutzt.</target>
</trans-unit>
<trans-unit id="sa668bd79645c3e06">
<source>Kubeconfig</source>
<target>Kubeconfig</target>
</trans-unit>
<trans-unit id="sa85cfb884c17d85d">
<source>Verify Kubernetes API SSL Certificate</source>
</trans-unit>
<trans-unit id="se78364ee913ae2bd">
<source>New outpost integration</source>
<target>Neue Outpost-Integration</target>
</trans-unit>
<trans-unit id="s68d69ad0271c8ef6">
<source>Create a new outpost integration.</source>
<target>Neue Outpost-Integration erstellen.</target>
</trans-unit>
<trans-unit id="sae239213b7c70376">
<source>State</source>
<target>Zustand</target>
</trans-unit>
<trans-unit id="sb96629f50f2e7fab">
<source>Unhealthy</source>
<target>Defekt</target>
</trans-unit>
<trans-unit id="sa8e255492bb6ae0d">
<source>Outpost integration(s)</source>
<target>Outpostintegration(en)</target>
</trans-unit>
<trans-unit id="s9d18948d25c68d66">
<source>Successfully generated certificate-key pair.</source>
<target>Zertifikat-Schlüsselpaar erfolgreich generiert.</target>
</trans-unit>
<trans-unit id="sd4ac926e4ebb1cd7">
<source>Common Name</source>
<target>Gemeinsamer Name</target>
</trans-unit>
<trans-unit id="s592425143c4f5834">
<source>Subject-alt name</source>
<target>SAN</target>
</trans-unit>
<trans-unit id="se9d0f12f95b14095">
<source>Optional, comma-separated SubjectAlt Names.</source>
<target>Optionale, durch Kommas getrennte SubjectAlt-Namen</target>
</trans-unit>
<trans-unit id="s7609ee54e8a7b05a">
<source>Validity days</source>
<target>Gültigkeitstage</target>
</trans-unit>
<trans-unit id="s4c24b2baa377e870">
<source>Successfully updated certificate-key pair.</source>
<target>Zertifikat-Schlüsselpaar erfolgreich aktualisiert.</target>
</trans-unit>
<trans-unit id="s122f308b5f198ba7">
<source>Successfully created certificate-key pair.</source>
<target>Zertifikat-Schlüsselpaar erfolgreich erstellt.</target>
</trans-unit>
<trans-unit id="s08a8716c214a0efb">
<source>PEM-encoded Certificate data.</source>
<target>PEM-codierte Zertifikatsdaten.</target>
</trans-unit>
<trans-unit id="s6e612e5a6a359bbb">
<source>Optional Private Key. If this is set, you can use this keypair for encryption.</source>
<target>Optionaler privater Schlüssel. Wenn dies eingestellt ist, können Sie dieses Schlüsselpaar für die Verschlüsselung verwenden.</target>
</trans-unit>
<trans-unit id="s27ac7a47b390e3cb">
<source>Certificate-Key Pairs</source>
<target>Zertifikat-Schlüsselpaare</target>
</trans-unit>
<trans-unit id="sb72ebab438cb2983">
<source>Import certificates of external providers or create certificates to sign requests with.</source>
<target>Importieren Sie Zertifikate externer Anbieter oder erstellen Sie Zertifikate zum Signieren von Anfragen.</target>
</trans-unit>
<trans-unit id="s4b5af7736aedd6c1">
<source>Private key available?</source>
<target>Privater Schlüssel vorhanden?</target>
</trans-unit>
<trans-unit id="s1d6e16d86961c782">
<source>Certificate-Key Pair(s)</source>
<target>Zertifikat Schlüsselpaar(e)</target>
</trans-unit>
<trans-unit id="sc1ce2f758935ff48">
<source>Managed by authentik</source>
<target>Verwaltet durch Authentik</target>
</trans-unit>
<trans-unit id="sf53a78d889b6c775">
<source>Managed by authentik (Discovered)</source>
<target>Verwaltet von authentik (Discovered)</target>
</trans-unit>
<trans-unit id="sef50d248448e0df1">
<source>Yes (<x id="0" equiv-text="${item.privateKeyType?.toUpperCase()}"/>)</source>
<target>Ja (
<x id="0" equiv-text="${item.privateKeyType?.toUpperCase()}"/>)</target>
</trans-unit>
<trans-unit id="s09205907b5b56cda">
<source>No</source>
<target>Nein</target>
</trans-unit>
<trans-unit id="s33aa05f435c29753">
<source>Update Certificate-Key Pair</source>
<target>Aktualisieren Sie das Zertifikatschlüsselpaar</target>
</trans-unit>
<trans-unit id="seffdf887fed7f668">
<source>Certificate Fingerprint (SHA1)</source>
<target>Zertifikat-Fingerabdruck (SHA1)</target>
</trans-unit>
<trans-unit id="sdd6b8b56a811080e">
<source>Certificate Fingerprint (SHA256)</source>
<target>Zertifikat-Fingerabdruck (SHA256)</target>
</trans-unit>
<trans-unit id="s2a2d3e7c379e9518">
<source>Certificate Subject</source>
<target>Zertifikat Betreff</target>
</trans-unit>
<trans-unit id="s351246c52548086a">
<source>Download Certificate</source>
<target>Zertifikat herunterladen</target>
</trans-unit>
<trans-unit id="s47bd537a3bcebf19">
<source>Download Private key</source>
<target>Privaten Schlüssel herunterladen</target>
</trans-unit>
<trans-unit id="s3a5fec3d73ac9edc">
<source>Create Certificate-Key Pair</source>
<target>Zertifikat-Schlüsselpaar generieren</target>
</trans-unit>
<trans-unit id="s45cb501abd43ba52">
<source>Generate</source>
<target>Generiere</target>
</trans-unit>
<trans-unit id="sf9bddaf910f4eea5">
<source>Generate Certificate-Key Pair</source>
<target>Zertifikat-Schlüsselpaar generieren</target>
</trans-unit>
<trans-unit id="see2bcbc11bb91960">
<source>Successfully updated instance.</source>
</trans-unit>
<trans-unit id="s9e51d6de369f320b">
<source>Successfully created instance.</source>
</trans-unit>
<trans-unit id="s92e91071c6a45eb4">
<source>Disabled blueprints are never applied.</source>
</trans-unit>
<trans-unit id="sf63c89c0604c288f">
<source>Local path</source>
</trans-unit>
<trans-unit id="sd6422f7004036cdd">
<source>OCI Registry</source>
</trans-unit>
<trans-unit id="se2d65e13768468e0">
<source>Internal</source>
</trans-unit>
<trans-unit id="scbb7d3154da629f3">
<source>OCI URL, in the format of oci://registry.domain.tld/path/to/manifest.</source>
</trans-unit>
<trans-unit id="s0195c0df7294228a">
<source>See more about OCI support here:</source>
</trans-unit>
<trans-unit id="sfae395b94a5a0040">
<source>Blueprint</source>
</trans-unit>
<trans-unit id="s7e1342d37124b65b">
<source>Configure the blueprint context, used for templating.</source>
</trans-unit>
<trans-unit id="s6ec8c9d11310300a">
<source>Orphaned</source>
</trans-unit>
<trans-unit id="saab79cd956ee56a9">
<source>Blueprints</source>
</trans-unit>
<trans-unit id="s6835db03209b4f94">
<source>Automate and template configuration within authentik.</source>
</trans-unit>
<trans-unit id="s23de62f931f7d754">
<source>Last applied</source>
</trans-unit>
<trans-unit id="s2708cac1f4942708">
<source>Blueprint(s)</source>
</trans-unit>
<trans-unit id="s880b8b70b22f9977">
<source>Update Blueprint</source>
</trans-unit>
<trans-unit id="sef3d102324bf8561">
<source>Create Blueprint Instance</source>
</trans-unit>
<trans-unit id="s32a3efa23718e713">
<source>API Requests</source>
<target>API Anfragen</target>
</trans-unit>
<trans-unit id="sddb3b0176f437721">
<source>Open API Browser</source>
<target>API-Browser öffnen</target>
</trans-unit>
<trans-unit id="s5be3c6d61cd9182f">
<source>Notifications</source>
<target>Benachrichtigungen</target>
</trans-unit>
<trans-unit id="sa3438c7bb4e9cce8">
<source><x id="0" equiv-text="${this.unread}"/> unread</source>
<target>
<x id="0" equiv-text="${this.unread}"/>ungelesen</target>
</trans-unit>
<trans-unit id="s6e6e737601f44b2c">
<source>Successfully cleared notifications</source>
<target>Benachrichtigungen erfolgreich gelöscht</target>
</trans-unit>
<trans-unit id="s8cda828dac449ea5">
<source>Clear all</source>
<target>Alles löschen</target>
</trans-unit>
<trans-unit id="s4207178ba0b99418">
<source>A newer version of the frontend is available.</source>
<target>Eine neuere Version des Frontends ist verfügbar.</target>
</trans-unit>
<trans-unit id="s96b3cddf33e1c853">
web: refactor sidebar capabilities for categorical subsections (#7482)
* web: break circular dependency between AKElement & Interface.
This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.
I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.
* web: fix broken typescript references
This built... and then it didn't? Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.
* web: rollback dependabot's upgrade of context
The most frustrating part of this is that I RAN THIS, dammit, with the updated
context and the current Wizard, and it finished the End-to-End tests without
complaint.
* Due for amendment
* Revert "Due for amendment"
This reverts commit 829ad5d3f214fa163958593636b28300d010da42.
* web: refactor sidebar capabilities for categorical subsections
The project "Change Admin UI lists to have sublists per type" requires some initial changes to the
UI to facilitate this request. The AdminSidebar is the principle target of this project, and it is
embedded in the AdminInterface. To facilitate editing the AdminSidebar as an independent entity,
AdminInterface has been moved into its own folder and the AdminSidebar extracted as a standalone Web
Component. This removes, oh, about half the code from AdminInterface. A little cleanup with
`classMap` was also committed.
The rollup config was adjusted to find the new AdminInterface location.
The Sidebar uses the global `config: Config` object to check for Enterprise capabilities. Rather
than plumb all the way down through the Interface => AdminInterface -> AdminSidebar, I chose to make
provide an alternative way of reaching the `config` object, as a *context*. Other configuration
objects (Me, UiConfig, Tenant) interfaces will be contextualized as demand warrants.
Demand will warrant. Just not yet. <sup>1</sup>
The Sidebar has been refactored only slightly; the renderers are entirely the same as they were
prior to extraction. What has been changed is the source of information: when we retrieve the
current version we story *only* the information, and use type information to ensure that the version
we store is the version we care about. The same is true of `impersonation`; we care only about the
name of the person being impersonated being present, so we don't store anything else.
Fetches have been moved from `firstUpdated` to the constructor. No reason to have the sidebar
render twice if the network returns before the render is scheduled.
Because the path used to identify the user being impersonated has changed, the `str()` references in
the XLIFF files had to be adjusted. **This change is to a variable only and does not require
translation.**
---
<sup>1</sup> The code is littered with checks to `me()?`, `uiConfig?`, `config?`, etc. In the
*context* of being logged in as an administrator those should never be in doubt. I intend to make
our interfaces not have any doubt.
* Function to help generate sizing solutions across Javascript and CSS.
* web: refactor sidebar capabilities for categorical subsections
Move open/close logic into the ak-admin-sidebar itself.
This commit removes the responsibility for opening/closing the sidebar from the interface parent
code and places it inside the sidebar entirely. Since the Django invocation passes none of the
properties ak-interface-admin is capable of receiving, this seems like a safe operation.
The sidebar now assumes the responsibility for hooking up the window event listeners for open/close
and resize.
On connection to the DOM, and on resize, the sidebar checks to see if the viewport width meets the
criteria for a behavioral change (slide-overlay vs slide-push), and on slide-push automatically
opens the sidebar on the assumption that there's plenty of room. In order to support more dynamic
styling going forward, I've substituted the 1280px with 80rem, which is the same, but allows for
some better styling if someone with older eyes needs to "zoom in" on the whole thing with a larger
font size.
The hide/show code involves "reaching up" to touch the host's classList. There's a comment
indicating that this is a slightly fragile thing to do, but in a well-known way.
2023-11-20 18:24:59 +00:00
<source>You're currently impersonating <x id="0" equiv-text="${this.impersonation}"/>. Click to stop.</source>
web: Replace lingui.js with lit-localize (#5761)
* \#\# Details
web: replace lingui with lit/localize
\#\# Changes
This rather massive shift replaces the lingui and `t()` syntax with lit-localize, XLIFF, and the `msg()`
syntax used by lit-localize. 90% of this work was mechanized; simple perl scripts found and replaced
all uses of `t()` with the appropriate corresponding syntax for `msg()` and `msg(str())`.
The XLIFF files were auto-generated from the PO files. They have not been audited, and they should be
checked over by professional translators. The actual _strings_ have not been changed, but as this was
a mechanized change there is always the possibility of mis-translation-- not by the translator, but by
the script.
* web: revise lit/localize: fix two installation issues.
* web: revise localization
TL;DR:
- Replaced all of Lingui's `t()` syntax with `msg()` syntax.
- Mechanically (i.e with a script) converted all of the PO files to XLIFF files
- Refactored the localization code to be a bit smarter:
- the function `getBestMatchLocale` takes the locale lists and a requested locale, and returns the
first match of:
- The locale's code exactly matches the requested locale
- The locale code exactly matches the prefix of the requested locale (i.e the "en" part of "en-US")
- the locale code's prefix exactly matches the prefix of the requested locale
This function is passed to lit-locate's `loadLocale()`.
- `activateLocale()` just calls `loadLocale()` now.
- `autodetectLanguage` searches the following, and picks the first that returns a valid locale
object, before passing it to `loadLocale()`:
- The User's settings
- A `?locale=` component found in `window.location.search`
- The `window.navigator.language` field
- English
The `msg()` only runs when it's run. This seems obvious, but it means that you cannot cache
strings at load time; they must be kept inside functions that are re-run so that the `msg()` engine
can look up the strings in the preferred language of the user at that moment.
You can use thunks-of-strings if you really need them that way.
* Including the 'xliff-converter' in case anyone wants to review it.
* The xliff-converter is tagged as 'xliff-converter', but has been
deleted.
\#\# Details
- Resolves #5171
\#\# Changes
\#\#\# New Features
- Adds a "Add an Application" to the LibraryView if there are no applications and the user is an administrator.
\#\#\# Breaking Changes
- Adds breaking change which causes \<issue\>.
\#\# Checklist
- [ ] Local tests pass (`ak test authentik/`)
- [ ] The code has been formatted (`make lint-fix`)
If an API change has been made
- [ ] The API schema has been updated (`make gen-build`)
If changes to the frontend have been made
- [ ] The code has been formatted (`make web`)
- [ ] The translation files have been updated (`make i18n-extract`)
If applicable
- [ ] The documentation has been updated
- [ ] The documentation has been formatted (`make website`)
* web: fix redundant locales for zh suite.
* web: prettier pass for locale update
* web: localization moderization
Changed the names of the lit-localize commands to make it clear they're
part of the localization effort, and not just "build" and "extract".
* update transifex config
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* fix package lock?
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* use build not compile
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* web: conversion to lit-localize
The CI produced a list of problems that I hadn't caught earlier,
due to a typo ("localize build" is correct, "localize compile" is
not) I had left in package.json. They were minor and linty, but
it was still wise to fix them.
* web: replace lingui with lit/locale
This commit fixes some minor linting issues that were hidden by a typo in package.json. The
issues were not apparently problematic from a Javascript point of view, but they pointed
to sloppy thinking in the progression of types through the system, so I cleaned them
up and formalized the types from LocaleModule to AkLocale.
* web: replace lingui with lit/localize
One problem that has repeatedly come up is that localize's templates do not produce
JavaScript that conforms with our shop style. I've replaced `build-locale` with
a two-step that builds the locale *and* ensures that it conforms to the shop style
via `prettier` every time.
* web: replace lingui with lit-locale
This commit applies the most recent bundle of translations to the
new lit-locale aspect component. It also revises the algorithm
for *finding* the correct locale, replacing the complex fall-back
with some rather straightforward regular expressions.
In the case of Chinese, the fallback comes at the end of the
selection list, which may not be, er, politically valuable
(since Taiwan and Hong Kong come before, being exceptions that
need to be tested). If we need a different order for presentation,
that'll be a future feature.
* web: replace lingui with lit/locale
Well, that was embarassing.
---------
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-06-02 15:08:36 +00:00
<target>Sie geben sich gerade als
web: refactor sidebar capabilities for categorical subsections (#7482)
* web: break circular dependency between AKElement & Interface.
This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.
I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.
* web: fix broken typescript references
This built... and then it didn't? Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.
* web: rollback dependabot's upgrade of context
The most frustrating part of this is that I RAN THIS, dammit, with the updated
context and the current Wizard, and it finished the End-to-End tests without
complaint.
* Due for amendment
* Revert "Due for amendment"
This reverts commit 829ad5d3f214fa163958593636b28300d010da42.
* web: refactor sidebar capabilities for categorical subsections
The project "Change Admin UI lists to have sublists per type" requires some initial changes to the
UI to facilitate this request. The AdminSidebar is the principle target of this project, and it is
embedded in the AdminInterface. To facilitate editing the AdminSidebar as an independent entity,
AdminInterface has been moved into its own folder and the AdminSidebar extracted as a standalone Web
Component. This removes, oh, about half the code from AdminInterface. A little cleanup with
`classMap` was also committed.
The rollup config was adjusted to find the new AdminInterface location.
The Sidebar uses the global `config: Config` object to check for Enterprise capabilities. Rather
than plumb all the way down through the Interface => AdminInterface -> AdminSidebar, I chose to make
provide an alternative way of reaching the `config` object, as a *context*. Other configuration
objects (Me, UiConfig, Tenant) interfaces will be contextualized as demand warrants.
Demand will warrant. Just not yet. <sup>1</sup>
The Sidebar has been refactored only slightly; the renderers are entirely the same as they were
prior to extraction. What has been changed is the source of information: when we retrieve the
current version we story *only* the information, and use type information to ensure that the version
we store is the version we care about. The same is true of `impersonation`; we care only about the
name of the person being impersonated being present, so we don't store anything else.
Fetches have been moved from `firstUpdated` to the constructor. No reason to have the sidebar
render twice if the network returns before the render is scheduled.
Because the path used to identify the user being impersonated has changed, the `str()` references in
the XLIFF files had to be adjusted. **This change is to a variable only and does not require
translation.**
---
<sup>1</sup> The code is littered with checks to `me()?`, `uiConfig?`, `config?`, etc. In the
*context* of being logged in as an administrator those should never be in doubt. I intend to make
our interfaces not have any doubt.
* Function to help generate sizing solutions across Javascript and CSS.
* web: refactor sidebar capabilities for categorical subsections
Move open/close logic into the ak-admin-sidebar itself.
This commit removes the responsibility for opening/closing the sidebar from the interface parent
code and places it inside the sidebar entirely. Since the Django invocation passes none of the
properties ak-interface-admin is capable of receiving, this seems like a safe operation.
The sidebar now assumes the responsibility for hooking up the window event listeners for open/close
and resize.
On connection to the DOM, and on resize, the sidebar checks to see if the viewport width meets the
criteria for a behavioral change (slide-overlay vs slide-push), and on slide-push automatically
opens the sidebar on the assumption that there's plenty of room. In order to support more dynamic
styling going forward, I've substituted the 1280px with 80rem, which is the same, but allows for
some better styling if someone with older eyes needs to "zoom in" on the whole thing with a larger
font size.
The hide/show code involves "reaching up" to touch the host's classList. There's a comment
indicating that this is a slightly fragile thing to do, but in a well-known way.
2023-11-20 18:24:59 +00:00
<x id="0" equiv-text="${this.impersonation}"/>aus. Klicken Sie zum Stoppen.</target>
web: Replace lingui.js with lit-localize (#5761)
* \#\# Details
web: replace lingui with lit/localize
\#\# Changes
This rather massive shift replaces the lingui and `t()` syntax with lit-localize, XLIFF, and the `msg()`
syntax used by lit-localize. 90% of this work was mechanized; simple perl scripts found and replaced
all uses of `t()` with the appropriate corresponding syntax for `msg()` and `msg(str())`.
The XLIFF files were auto-generated from the PO files. They have not been audited, and they should be
checked over by professional translators. The actual _strings_ have not been changed, but as this was
a mechanized change there is always the possibility of mis-translation-- not by the translator, but by
the script.
* web: revise lit/localize: fix two installation issues.
* web: revise localization
TL;DR:
- Replaced all of Lingui's `t()` syntax with `msg()` syntax.
- Mechanically (i.e with a script) converted all of the PO files to XLIFF files
- Refactored the localization code to be a bit smarter:
- the function `getBestMatchLocale` takes the locale lists and a requested locale, and returns the
first match of:
- The locale's code exactly matches the requested locale
- The locale code exactly matches the prefix of the requested locale (i.e the "en" part of "en-US")
- the locale code's prefix exactly matches the prefix of the requested locale
This function is passed to lit-locate's `loadLocale()`.
- `activateLocale()` just calls `loadLocale()` now.
- `autodetectLanguage` searches the following, and picks the first that returns a valid locale
object, before passing it to `loadLocale()`:
- The User's settings
- A `?locale=` component found in `window.location.search`
- The `window.navigator.language` field
- English
The `msg()` only runs when it's run. This seems obvious, but it means that you cannot cache
strings at load time; they must be kept inside functions that are re-run so that the `msg()` engine
can look up the strings in the preferred language of the user at that moment.
You can use thunks-of-strings if you really need them that way.
* Including the 'xliff-converter' in case anyone wants to review it.
* The xliff-converter is tagged as 'xliff-converter', but has been
deleted.
\#\# Details
- Resolves #5171
\#\# Changes
\#\#\# New Features
- Adds a "Add an Application" to the LibraryView if there are no applications and the user is an administrator.
\#\#\# Breaking Changes
- Adds breaking change which causes \<issue\>.
\#\# Checklist
- [ ] Local tests pass (`ak test authentik/`)
- [ ] The code has been formatted (`make lint-fix`)
If an API change has been made
- [ ] The API schema has been updated (`make gen-build`)
If changes to the frontend have been made
- [ ] The code has been formatted (`make web`)
- [ ] The translation files have been updated (`make i18n-extract`)
If applicable
- [ ] The documentation has been updated
- [ ] The documentation has been formatted (`make website`)
* web: fix redundant locales for zh suite.
* web: prettier pass for locale update
* web: localization moderization
Changed the names of the lit-localize commands to make it clear they're
part of the localization effort, and not just "build" and "extract".
* update transifex config
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* fix package lock?
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* use build not compile
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* web: conversion to lit-localize
The CI produced a list of problems that I hadn't caught earlier,
due to a typo ("localize build" is correct, "localize compile" is
not) I had left in package.json. They were minor and linty, but
it was still wise to fix them.
* web: replace lingui with lit/locale
This commit fixes some minor linting issues that were hidden by a typo in package.json. The
issues were not apparently problematic from a Javascript point of view, but they pointed
to sloppy thinking in the progression of types through the system, so I cleaned them
up and formalized the types from LocaleModule to AkLocale.
* web: replace lingui with lit/localize
One problem that has repeatedly come up is that localize's templates do not produce
JavaScript that conforms with our shop style. I've replaced `build-locale` with
a two-step that builds the locale *and* ensures that it conforms to the shop style
via `prettier` every time.
* web: replace lingui with lit-locale
This commit applies the most recent bundle of translations to the
new lit-locale aspect component. It also revises the algorithm
for *finding* the correct locale, replacing the complex fall-back
with some rather straightforward regular expressions.
In the case of Chinese, the fallback comes at the end of the
selection list, which may not be, er, politically valuable
(since Taiwan and Hong Kong come before, being exceptions that
need to be tested). If we need a different order for presentation,
that'll be a future feature.
* web: replace lingui with lit/locale
Well, that was embarassing.
---------
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-06-02 15:08:36 +00:00
</trans-unit>
<trans-unit id="s7031e6928c44cedd">
<source>User interface</source>
<target>Benutzeroberfläche</target>
</trans-unit>
<trans-unit id="s8849ece8c65e3a18">
<source>Dashboards</source>
<target>Dashboards</target>
</trans-unit>
<trans-unit id="sc265a3e29e1206e4">
<source>Events</source>
<target>Events</target>
</trans-unit>
<trans-unit id="s4f1ad6b48a5df506">
<source>Logs</source>
<target>Logs</target>
</trans-unit>
<trans-unit id="s1823625e6f831d73">
<source>Customisation</source>
<target>Anpassung</target>
</trans-unit>
<trans-unit id="sc0829ee663ced008">
<source>Directory</source>
<target>Verzeichnis</target>
</trans-unit>
<trans-unit id="sa81e2cdaf6921adc">
<source>System</source>
<target>System</target>
</trans-unit>
<trans-unit id="s5515a897ae98bed9">
<source>Certificates</source>
<target>Zertifikate</target>
</trans-unit>
<trans-unit id="s6b79e73ca77148a0">
<source>Outpost Integrations</source>
<target>Outpostintegrationen</target>
</trans-unit>
<trans-unit id="sab85321d3b0840b7">
<source>API request failed</source>
<target>API Anfrage fehlgeschlagen</target>
</trans-unit>
<trans-unit id="sa3599457b9418bc5">
<source>User's avatar</source>
<target>Avatar des Benutzers</target>
</trans-unit>
<trans-unit id="s9bd9ba84819493d4">
<source>Something went wrong! Please try again later.</source>
<target>Etwas ist schiefgelaufen. Bitte probiere es später wieder</target>
</trans-unit>
<trans-unit id="s4090dd0c0e45988b">
<source>Request ID</source>
</trans-unit>
<trans-unit id="s4d7fe7be1c49896c">
<source>You may close this page now.</source>
</trans-unit>
<trans-unit id="sf8c76d5fb408de7b">
<source>You're about to be redirect to the following URL.</source>
<target>Sie werden gleich zur folgenden URL weitergeleitet</target>
</trans-unit>
<trans-unit id="s197420b40df164f8">
<source>Follow redirect</source>
<target>Weiterleitung folgen</target>
</trans-unit>
<trans-unit id="sa11e92683c5860c7">
<source>Request has been denied.</source>
<target>Anfrage wurde verweigert</target>
</trans-unit>
<trans-unit id="s8939f574b096054a">
<source>Not you?</source>
<target>Nicht Sie?</target>
</trans-unit>
<trans-unit id="sc4eedb434536bdb4">
<source>Need an account?</source>
<target>Wird ein Konto gebraucht?</target>
</trans-unit>
<trans-unit id="s38f774cd7e9b9dad">
<source>Sign up.</source>
<target>Registrieren.</target>
</trans-unit>
<trans-unit id="sa03aa46068460c95">
<source>Forgot username or password?</source>
<target>Benutzername oder Passwort vergessen?</target>
</trans-unit>
<trans-unit id="s4a87445f3108db7c">
<source>Select one of the sources below to login.</source>
<target>Wählen Sie eine der folgenden Quellen aus, um sich anzumelden.</target>
</trans-unit>
<trans-unit id="s091d5407b5b32e84">
<source>Or</source>
</trans-unit>
<trans-unit id="se5fd752dbbc3cd28">
<source>Use a security key</source>
<target>Verwenden Sie einen Sicherheitsschlüssel</target>
</trans-unit>
<trans-unit id="s670ad066cc0e50a3">
<source>Login to continue to <x id="0" equiv-text="${this.challenge.applicationPre}"/>.</source>
<target>Anmelden um mit
<x id="0" equiv-text="${this.challenge.applicationPre}"/>fortzufahren.</target>
</trans-unit>
<trans-unit id="scf5ce91bfba10a61">
<source>Please enter your password</source>
<target>Bitte geben Sie Ihr Passwort ein</target>
</trans-unit>
<trans-unit id="s85366fac18679f28">
<source>Forgot password?</source>
<target>Passwort vergessen?</target>
</trans-unit>
<trans-unit id="s14c552fb0a4c0186">
<source>Application requires following permissions:</source>
<target>Anwendung benötigt die folgenden Berechtigungen:</target>
</trans-unit>
<trans-unit id="s7073489bb01b3c24">
<source>Application already has access to the following permissions:</source>
</trans-unit>
<trans-unit id="s98dc556f8bf707dc">
<source>Application requires following new permissions:</source>
</trans-unit>
<trans-unit id="sbd19064fc3f405c1">
<source>Check your Inbox for a verification email.</source>
<target>Prüfen Sie Ihren Posteingang auf eine Bestätigungsmail.</target>
</trans-unit>
<trans-unit id="s8aff572e64b7936b">
<source>Send Email again.</source>
<target>E-Mail erneut senden.</target>
</trans-unit>
<trans-unit id="sdc323c6af4ae9f01">
<source>Successfully copied TOTP Config.</source>
<target>TOTP Config erfolgreich kopiert</target>
</trans-unit>
<trans-unit id="s3687049d1af562c4">
<source>Copy</source>
<target>Kopieren</target>
</trans-unit>
<trans-unit id="s3643189d1abbb7f4">
<source>Code</source>
<target>Code</target>
</trans-unit>
<trans-unit id="sfe1c86b42ba13376">
<source>Please enter your TOTP Code</source>
<target>Bitte geben Sie Ihren TOTP-Code ein.</target>
</trans-unit>
<trans-unit id="sc2ec367e3108fe65">
<source>Duo activation QR code</source>
</trans-unit>
<trans-unit id="sc5668cb23167e9bb">
<source>Alternatively, if your current device has Duo installed, click on this link:</source>
<target>Alternativ kannst Du auch auf diesen Link klicken, wenn Du Duo auf Deinem Gerät installiert hast:</target>
</trans-unit>
<trans-unit id="s721d94ae700b5dfd">
<source>Duo activation</source>
<target>Duo-Aktivierung</target>
</trans-unit>
<trans-unit id="s708d9a4a0db0be8f">
<source>Check status</source>
<target>Status überprüfen</target>
</trans-unit>
<trans-unit id="s31fba571065f2c87">
<source>Make sure to keep these tokens in a safe place.</source>
<target>Bewahren Sie diese Tokens an einem sicheren Ort auf.</target>
</trans-unit>
<trans-unit id="sc0a0c87d5c556c38">
<source>Phone number</source>
<target>Telefonnummer</target>
</trans-unit>
<trans-unit id="s04c1210202f48dc9">
<source>Please enter your Phone number.</source>
<target>Bitte geben Sie Ihre Telefonnummer ein.</target>
</trans-unit>
<trans-unit id="seb0c08d9f233bbfe">
<source>Please enter the code you received via SMS</source>
</trans-unit>
<trans-unit id="s2b7dbba348234a36">
<source>A code has been sent to you via SMS.</source>
<target>Ihnen wurde ein Code per SMS gesendet.</target>
</trans-unit>
<trans-unit id="sa84adff85b5e505c">
<source>Open your two-factor authenticator app to view your authentication code.</source>
</trans-unit>
<trans-unit id="s7abc9d08b0f70fd6">
<source>Static token</source>
<target>Statische Token</target>
</trans-unit>
<trans-unit id="s844fea0bfb10a72a">
<source>Authentication code</source>
</trans-unit>
<trans-unit id="s3cd84e82e83e35ad">
<source>Please enter your code</source>
</trans-unit>
<trans-unit id="s18b910437b73e8e8">
<source>Return to device picker</source>
<target>Zurück zur Geräteauswahl</target>
</trans-unit>
<trans-unit id="sbcf8604929b6a27a">
<source>Sending Duo push notification</source>
</trans-unit>
<trans-unit id="s3b68883dda2682ed">
<source>Assertions is empty</source>
<target>SAML Assertion ist leer</target>
</trans-unit>
<trans-unit id="sbbb7318812d64e51">
<source>Error when creating credential: <x id="0" equiv-text="${err}"/></source>
<target>Fehler beim Erstellen der Anmeldedaten:
<x id="0" equiv-text="${err}"/></target>
</trans-unit>
<trans-unit id="sfe199b2564b66054">
<source>Error when validating assertion on server: <x id="0" equiv-text="${err}"/></source>
<target>Fehler beim Validieren der Assertion auf dem Server:
<x id="0" equiv-text="${err}"/></target>
</trans-unit>
<trans-unit id="se409d01b52c4e12f">
<source>Retry authentication</source>
<target>Authentifizierung erneut versuchen</target>
</trans-unit>
<trans-unit id="s8d857061510fe794">
<source>Duo push-notifications</source>
<target>Duo Push-Benachrichtigungen</target>
</trans-unit>
<trans-unit id="s47490298c17b753a">
<source>Receive a push notification on your device.</source>
<target>Erhalten Sie eine Push-Benachrichtigung auf Ihrem Gerät.</target>
</trans-unit>
<trans-unit id="s16bc281dce5685e8">
<source>Authenticator</source>
<target>Authentifikator</target>
</trans-unit>
<trans-unit id="sdefec5401bf67eba">
<source>Use a security key to prove your identity.</source>
<target>Verwenden Sie einen Sicherheitsschlüssel, um Ihre Identität nachzuweisen</target>
</trans-unit>
<trans-unit id="sd6a025d66f2637d1">
<source>Traditional authenticator</source>
<target>Traditioneller Authentifikator</target>
</trans-unit>
<trans-unit id="sb25e689e00c61829">
<source>Use a code-based authenticator.</source>
<target>Verwenden Sie einen Code-basierten Authentifikator</target>
</trans-unit>
<trans-unit id="s9e568afec3810bfe">
<source>Recovery keys</source>
<target>Wiederherstellungsschlüssel</target>
</trans-unit>
<trans-unit id="sb17e8c70f9a05c77">
<source>In case you can't access any other method.</source>
<target>Falls Sie auf keine andere Methode zugreifen können.</target>
</trans-unit>
<trans-unit id="s97f2dc19fa556a6a">
<source>SMS</source>
<target>SMS</target>
</trans-unit>
<trans-unit id="s0e516232f2ab4e04">
<source>Tokens sent via SMS.</source>
<target>Per SMS versendete Token.</target>
</trans-unit>
<trans-unit id="s6ae0d087036e6d6d">
<source>Select an authentication method.</source>
<target>Wählen Sie eine Authentifizierungsmethode aus.</target>
</trans-unit>
<trans-unit id="sac17f177f884e238">
<source>Stay signed in?</source>
<target>Eingeloggt bleiben?</target>
</trans-unit>
<trans-unit id="s859b2e00391da380">
<source>Select Yes to reduce the number of times you're asked to sign in.</source>
<target>Wähle 'Ja' um die Anzahl der Anmeldeaufforderungen zu reduzieren.</target>
</trans-unit>
<trans-unit id="s420d2cdedcaf8cd0">
<source>Authenticating with Plex...</source>
<target>Authentifizierung mit Plex...</target>
</trans-unit>
<trans-unit id="s2ddbebcb8a49b005">
<source>Waiting for authentication...</source>
</trans-unit>
<trans-unit id="sb15fe7b9d09bb419">
<source>If no Plex popup opens, click the button below.</source>
</trans-unit>
<trans-unit id="sbc625b4c669b9ce8">
<source>Open login</source>
</trans-unit>
<trans-unit id="sd766cdc29b25ff95">
<source>Authenticating with Apple...</source>
<target>Authentifizierung mit Apple...</target>
</trans-unit>
<trans-unit id="s2c8189544e3ea679">
<source>Retry</source>
<target>Erneut versuchen</target>
</trans-unit>
<trans-unit id="sc1589121ae2f5f92">
<source>Enter the code shown on your device.</source>
</trans-unit>
<trans-unit id="s67664f8ee9aea98d">
<source>Please enter your Code</source>
<target>Bitte geben Sie Ihren Code ein</target>
</trans-unit>
<trans-unit id="s455a8fc21077e7f9">
<source>You've successfully authenticated your device.</source>
</trans-unit>
<trans-unit id="s3ab772345f78aee0">
<source>Flow inspector</source>
<target>Ablauf-Inspektor</target>
</trans-unit>
<trans-unit id="s502884e1977b2c06">
<source>Next stage</source>
<target>Nächste Phase</target>
</trans-unit>
<trans-unit id="sb3fa80ccfa97ee54">
<source>Stage name</source>
<target>Phasenname</target>
</trans-unit>
<trans-unit id="sbea3c1e4f2fd623d">
<source>Stage kind</source>
<target>Art der Phase</target>
</trans-unit>
<trans-unit id="s2bc8aa1740d3da34">
<source>Stage object</source>
<target>Phasen Objekt</target>
</trans-unit>
<trans-unit id="sc3e1c4f1fff8e1ca">
<source>This flow is completed.</source>
<target>Dieser Ablauf ist abgeschlossen.</target>
</trans-unit>
<trans-unit id="s342eccabf83c9bde">
<source>Plan history</source>
<target>History</target>
</trans-unit>
<trans-unit id="sb2f307e79d20bb56">
<source>Current plan context</source>
<target>Aktueller Plankontext</target>
</trans-unit>
<trans-unit id="sa13e6c8310000e30">
<source>Session ID</source>
<target>Sitzungs-ID</target>
</trans-unit>
<trans-unit id="s6fe64b4625517333">
<source>Powered by authentik</source>
<target>Erstellt durch Authentik</target>
</trans-unit>
<trans-unit id="sdf34a5599d66f85c">
<source>Background image</source>
<target>Hintergrundbild</target>
</trans-unit>
<trans-unit id="s7fa4e5e409d43573">
<source>Error creating credential: <x id="0" equiv-text="${err}"/></source>
<target>Fehler beim Erstellen der Anmeldedaten:
<x id="0" equiv-text="${err}"/></target>
</trans-unit>
<trans-unit id="s9d95f09deb601f34">
<source>Server validation of credential failed: <x id="0" equiv-text="${err}"/></source>
<target>Servervalidierung der Anmeldedaten fehlgeschlagen:
<x id="0" equiv-text="${err}"/></target>
</trans-unit>
<trans-unit id="s6c8f05e3be04f62a">
<source>Register device</source>
<target>Gerät registrieren</target>
</trans-unit>
<trans-unit id="s3fb39fc45e840f78">
<source>Refer to documentation</source>
</trans-unit>
<trans-unit id="sc741dfb09d3395f0">
<source>No Applications available.</source>
<target>Keine Anwendungen vorhanden.</target>
</trans-unit>
<trans-unit id="sf34026321b35315c">
<source>Either no applications are defined, or you don’ t have access to any.</source>
</trans-unit>
<trans-unit id="s1cf2298d92c327a6">
<source>My Applications</source>
<target>Meine Anwendungen</target>
</trans-unit>
<trans-unit id="s2656433a3b1f7e86">
<source>My applications</source>
<target>Meine Anwendungen</target>
</trans-unit>
<trans-unit id="s06c92148da82be0d">
<source>Change your password</source>
<target>Ändern Sie Ihr Passwort</target>
</trans-unit>
<trans-unit id="sff50532a2d85e32e">
<source>Change password</source>
<target>Password ändern</target>
</trans-unit>
<trans-unit id="saf63d34c8601dd41">
<source><x id="0" equiv-text="${prompt.label}"/></source>
<target>
<x id="0" equiv-text="${prompt.label}"/>
</target>
</trans-unit>
<trans-unit id="s33f85f24c0f5f008">
<source>Save</source>
<target>Speichern</target>
</trans-unit>
<trans-unit id="s045c3b86aae073c1">
<source>Delete account</source>
<target>Account löschen</target>
</trans-unit>
<trans-unit id="s4a6aa26413287069">
<source>Successfully updated details</source>
<target>Details erfolgreich aktualisiert.</target>
</trans-unit>
<trans-unit id="s6fcd9b5a87ceccd6">
<source>Open settings</source>
<target>Einstellungen öffnen</target>
</trans-unit>
<trans-unit id="s8c05cccd470f6b5f">
<source>No settings flow configured.</source>
<target>Kein Ablauf für Einstellungen konfiguriert.</target>
</trans-unit>
<trans-unit id="sb546eb04425e07fa">
<source>Update details</source>
<target>Angaben aktualisieren</target>
</trans-unit>
<trans-unit id="s30205d424e710818">
<source>Successfully disconnected source</source>
<target>Quelle erfolgreich getrennt</target>
</trans-unit>
<trans-unit id="s67dedada007d4067">
<source>Failed to disconnected source: <x id="0" equiv-text="${exc}"/></source>
<target>Quelle konnte nicht getrennt werden:
<x id="0" equiv-text="${exc}"/></target>
</trans-unit>
<trans-unit id="sd2208cd1a767644b">
<source>Disconnect</source>
<target>Verbindung trennen</target>
</trans-unit>
<trans-unit id="s7a4f059aaa029719">
<source>Connect</source>
<target>Verbinden</target>
</trans-unit>
<trans-unit id="sababff57115130a0">
<source>Error: unsupported source settings: <x id="0" equiv-text="${source.component}"/></source>
<target>Fehler: nicht unterstützte Quelleinstellungen:
<x id="0" equiv-text="${source.component}"/></target>
</trans-unit>
<trans-unit id="sd1031bddc66dc495">
<source>Connect your user account to the services listed below, to allow you to login using the service instead of traditional credentials.</source>
<target>Verknüpfen Sie Ihr Konto mit einem der unten aufgeführten Dienste, um das Anmelden mit dem Dienst, anstatt der üblichen Anmeldedaten zu ermöglichen.</target>
</trans-unit>
<trans-unit id="s7968dbed9b106c29">
<source>No services available.</source>
<target>Keine Dienste verfügbar.</target>
</trans-unit>
<trans-unit id="s3a135682bd30bdbb">
<source>Create App password</source>
<target>App Passwort erstellen</target>
</trans-unit>
<trans-unit id="s588796ee929a2e4c">
<source>User details</source>
<target>Nutzerdetails</target>
</trans-unit>
<trans-unit id="s332a5235948c1a1d">
<source>Consent</source>
<target>Einwilligung</target>
</trans-unit>
<trans-unit id="sff945d3f59b93c5e">
<source>MFA Devices</source>
<target>Multifaktor-Authentifzierungs Geräte</target>
</trans-unit>
<trans-unit id="sc54aafeea9c9bab0">
<source>Connected services</source>
<target>Verknüpfte Dienste</target>
</trans-unit>
<trans-unit id="sc6b4ebd37b7a91c7">
<source>Tokens and App passwords</source>
<target>Tokens und App Passwörter</target>
</trans-unit>
<trans-unit id="sba65ae54d6585c1a">
<source>Unread notifications</source>
<target>Ungelesene Benachrichtigungen</target>
</trans-unit>
<trans-unit id="s5599c62bb78c631f">
<source>Admin interface</source>
<target>Admin Interface</target>
</trans-unit>
<trans-unit id="s1298e361e40ee1c5">
<source>Stop impersonation</source>
<target>Beenden Sie den Identitätswechsel</target>
</trans-unit>
<trans-unit id="s6abff64e7ff7fde9">
<source>Avatar image</source>
<target>Profilbild</target>
</trans-unit>
<trans-unit id="sbf9c5c5a8e5efad4">
<source>Failed</source>
</trans-unit>
<trans-unit id="se4cd073c125382af">
<source>Unsynced / N/A</source>
</trans-unit>
<trans-unit id="s21b3058faf874368">
<source>Outdated outposts</source>
<target>Obsolete Outposts</target>
</trans-unit>
<trans-unit id="s51f92b6fa76656ca">
<source>Unhealthy outposts</source>
<target>Defekte Outposts</target>
</trans-unit>
<trans-unit id="s0fbf6dc6a1966408">
<source>Next</source>
<target>Weiter</target>
</trans-unit>
<trans-unit id="s4409ada9c5c2a7f8">
<source>Inactive</source>
<target>Inaktiv</target>
</trans-unit>
<trans-unit id="s7ec7036b249f4f22">
<source>Regular user</source>
<target>Regelmäßiger Benutzer</target>
</trans-unit>
<trans-unit id="s27976e94b05c6970">
<source>Activate</source>
<target>Aktivieren</target>
</trans-unit>
2023-06-12 13:41:44 +00:00
<trans-unit id="s1024166475850a65">
<source>Use Server URI for SNI verification</source>
</trans-unit>
<trans-unit id="se65beb94fffc3c4b">
<source>Required for servers using TLS 1.3+</source>
</trans-unit>
<trans-unit id="s5506b35a1bceb141">
<source>Client certificate keypair to authenticate against the LDAP Server's Certificate.</source>
</trans-unit>
<trans-unit id="s4647b2c92638d6fd">
<source>The certificate for the above configured Base DN. As a fallback, the provider uses a self-signed certificate.</source>
</trans-unit>
<trans-unit id="scd247ffad6e04ac0">
<source>TLS Server name</source>
</trans-unit>
<trans-unit id="s2acef4f6ba39bf11">
<source>DNS name for which the above configured certificate should be used. The certificate cannot be detected based on the base DN, as the SSL/TLS negotiation happens before such data is exchanged.</source>
</trans-unit>
<trans-unit id="s000ee3e634868b3c">
<source>TLS Client authentication certificate</source>
2023-06-13 13:41:48 +00:00
</trans-unit>
<trans-unit id="s5da52af9b083c29a">
<source>Model</source>
</trans-unit>
<trans-unit id="s3ba9b8aeb686d9f7">
<source>Match events created by selected model. When left empty, all models are matched.</source>
2023-06-20 10:09:13 +00:00
</trans-unit>
<trans-unit id="s254d527e3a53dbb7">
<source>Code-based MFA Support</source>
</trans-unit>
<trans-unit id="s1889ba2eaeec2f1e">
<source>When enabled, code-based multi-factor authentication can be used by appending a semicolon and the TOTP code to the password. This should only be enabled if all users that will bind to this provider have a TOTP device configured, as otherwise a password may incorrectly be rejected if it contains a semicolon.</source>
2023-07-17 15:57:08 +00:00
</trans-unit>
<trans-unit id="s9f9492d30a96b9c6">
<source>User type</source>
</trans-unit>
<trans-unit id="s0e427111d750cc02">
<source>Successfully updated license.</source>
</trans-unit>
<trans-unit id="s06ae64e621f302eb">
<source>Successfully created license.</source>
</trans-unit>
<trans-unit id="s2905c425adae99bd">
<source>Install ID</source>
</trans-unit>
<trans-unit id="sb18ec434a8a3aafb">
<source>License key</source>
</trans-unit>
<trans-unit id="s2e109263b73c12d5">
<source>Licenses</source>
</trans-unit>
<trans-unit id="sd49099e9522635f4">
<source>License(s)</source>
</trans-unit>
<trans-unit id="s3be1d90ffa46b7f1">
<source>Enterprise is in preview.</source>
</trans-unit>
<trans-unit id="sd22bd01bdf28c548">
<source>Cumulative license expiry</source>
</trans-unit>
<trans-unit id="sdeb6cee42435dd07">
<source>Update License</source>
</trans-unit>
<trans-unit id="s7df5b92a3f93544f">
<source>Warning: The current user count has exceeded the configured licenses.</source>
</trans-unit>
<trans-unit id="s0141f42936495787">
<source>Click here for more info.</source>
</trans-unit>
<trans-unit id="s7be2df39f727faa2">
<source>Enterprise</source>
</trans-unit>
<trans-unit id="s9ce7cc01fb9b5b53">
<source>Manage enterprise licenses</source>
2023-07-21 16:23:51 +00:00
</trans-unit>
<trans-unit id="sf9ebf11ac2645820">
<source>No licenses found.</source>
</trans-unit>
<trans-unit id="sa1db89262360550b">
<source>Send us feedback!</source>
</trans-unit>
<trans-unit id="s4015746f55a8d89f">
<source>Get a license</source>
</trans-unit>
<trans-unit id="sb2cbd06f8e25b47e">
<source>Go to Customer Portal</source>
</trans-unit>
<trans-unit id="sf58825457d61c429">
<source>Forecast internal users</source>
</trans-unit>
<trans-unit id="sde9a3f41977ec1f8">
2023-08-23 11:20:42 +00:00
<source>Estimated user count one year from now based on <x id="0" equiv-text="${this.forecast?.internalUsers}"/> current internal users and <x id="1" equiv-text="${this.forecast?.forecastedInternalUsers}"/> forecasted internal users.</source>
2023-07-21 16:23:51 +00:00
</trans-unit>
<trans-unit id="s4557b6b9da258643">
<source>Forecast external users</source>
</trans-unit>
<trans-unit id="sf52479d6daa0a4a8">
<source>Estimated user count one year from now based on <x id="0" equiv-text="${this.forecast?.externalUsers}"/> current external users and <x id="1" equiv-text="${this.forecast?.forecastedExternalUsers}"/> forecasted external users.</source>
</trans-unit>
<trans-unit id="s6196153c4b0c1ea0">
<source>Install</source>
</trans-unit>
<trans-unit id="s0285b4bd69130fa3">
<source>Install License</source>
2023-07-28 12:25:56 +00:00
</trans-unit>
<trans-unit id="scef2eb6a2bfe3110">
<source>Internal users might be users such as company employees, which will get access to the full Enterprise feature set.</source>
</trans-unit>
<trans-unit id="sf66389b04fcc219c">
<source>External users might be external consultants or B2C customers. These users don't get access to enterprise features.</source>
</trans-unit>
<trans-unit id="s77e8668a27dbc402">
<source>Service accounts should be used for machine-to-machine authentication or other automations.</source>
</trans-unit>
<trans-unit id="s28cbd874ba450b4e">
<source>Less details</source>
</trans-unit>
<trans-unit id="s8fa26f65aed77c96">
<source>More details</source>
2023-07-31 17:35:09 +00:00
</trans-unit>
<trans-unit id="s08df8d0a773a3ea0">
<source>Remove item</source>
</trans-unit>
<trans-unit id="s364c4f177a2f8322">
<source>Open API drawer</source>
</trans-unit>
<trans-unit id="s9ba989e69344ff29">
<source>Open Notification drawer</source>
</trans-unit>
<trans-unit id="s14bf17e2a1a2c381">
<source>Restart task</source>
</trans-unit>
<trans-unit id="s19409e8712ddd369">
<source>Add provider</source>
</trans-unit>
<trans-unit id="s1f7698c061c208c9">
<source>Open</source>
</trans-unit>
<trans-unit id="scc3487e74c5a3e89">
<source>Copy token</source>
</trans-unit>
<trans-unit id="s424f57afae0caac4">
<source>Add users</source>
</trans-unit>
<trans-unit id="sd9f67fbf3f86efcf">
<source>Add group</source>
</trans-unit>
<trans-unit id="s254a9a23dc1635df">
<source>Import devices</source>
</trans-unit>
<trans-unit id="sc4fdeccf14be5378">
<source>Execute</source>
</trans-unit>
<trans-unit id="s3b3c333481944862">
<source>Show details</source>
</trans-unit>
<trans-unit id="sb8f855b49234b81b">
<source>Apply</source>
</trans-unit>
<trans-unit id="s9d8b8aa2b404c2c8">
<source>Settings</source>
</trans-unit>
<trans-unit id="s7cfe12cd14df9950">
<source>Sign out</source>
2023-08-17 21:48:05 +00:00
</trans-unit>
<trans-unit id="s7caa8f7edb920909">
<source>The number of tokens generated whenever this stage is used. Every token generated per stage execution will be attached to a single static device.</source>
</trans-unit>
<trans-unit id="s4aacc4e0277c1042">
<source>Token length</source>
</trans-unit>
<trans-unit id="s6931695c4f563bc4">
<source>The length of the individual generated tokens. Can be increased to improve security.</source>
2023-08-23 11:20:42 +00:00
</trans-unit>
<trans-unit id="s0dd031b58ed4017c">
<source>Internal: <x id="0" equiv-text="${item.internalUsers}"/></source>
</trans-unit>
<trans-unit id="s57b07e524f8f5c2a">
<source>External: <x id="0" equiv-text="${item.externalUsers}"/></source>
2023-08-30 18:10:36 +00:00
</trans-unit>
<trans-unit id="s7f68101a50f526ee">
<source>Statically deny the flow. To use this stage effectively, disable *Evaluate when flow is planned* on the respective binding.</source>
2023-09-02 16:59:17 +00:00
</trans-unit>
<trans-unit id="s911a27022aba349f">
<source>Create and bind Policy</source>
</trans-unit>
<trans-unit id="sb1a4e9b288e2f005">
<source>Federation and Social login</source>
</trans-unit>
<trans-unit id="s6f367f5604d5056d">
<source>Create and bind Stage</source>
</trans-unit>
<trans-unit id="s1a65ee08832fbfe2">
<source>Flows and Stages</source>
2023-09-15 11:12:38 +00:00
</trans-unit>
<trans-unit id="s4ba4473f3d4ec896">
<source>New version available</source>
</trans-unit>
<trans-unit id="s6b1ed7507f26cb4a">
<source>Failure result</source>
</trans-unit>
<trans-unit id="s2e422519ed38f7d8">
<source>Pass</source>
</trans-unit>
<trans-unit id="s81a45c4fd11e8e1a">
<source>Don't pass</source>
</trans-unit>
<trans-unit id="s95b73e0f4e47eb9a">
<source>Result used when policy execution fails.</source>
</trans-unit>
<trans-unit id="s6a3cf855140b9511">
<source>Required: User verification must occur.</source>
</trans-unit>
<trans-unit id="sc498a3b05cfe2b08">
<source>Preferred: User verification is preferred if available, but not required.</source>
</trans-unit>
<trans-unit id="s9d2239d2b0402795">
<source>Discouraged: User verification should not occur.</source>
</trans-unit>
<trans-unit id="s428b7859907f6db2">
<source>Required: The authenticator MUST create a dedicated credential. If it cannot, the RP is prepared for an error to occur</source>
</trans-unit>
<trans-unit id="s33e3766d4a02b042">
<source>Preferred: The authenticator can create and store a dedicated credential, but if it doesn't that's alright too</source>
</trans-unit>
<trans-unit id="sfb852dd507c25c24">
<source>Discouraged: The authenticator should not create a dedicated credential</source>
2023-09-25 10:43:24 +00:00
</trans-unit>
<trans-unit id="s028d385389b5aac0">
<source>Lock the user out of this system</source>
</trans-unit>
<trans-unit id="sd2122c514f0778b5">
<source>Allow the user to log in and use this system</source>
</trans-unit>
<trans-unit id="s43fe853bf219a9b8">
<source>Temporarily assume the identity of this user</source>
</trans-unit>
<trans-unit id="se28b5f3fcadaeeb1">
<source>Enter a new password for this user</source>
</trans-unit>
<trans-unit id="s6f5bb31e2733ecd5">
<source>Create a link for this user to reset their password</source>
</trans-unit>
<trans-unit id="s67ac11d47f1ce794">
<source>WebAuthn requires this page to be accessed via HTTPS.</source>
</trans-unit>
<trans-unit id="se9e9e1d6799b86a5">
<source>WebAuthn not supported by browser.</source>
2023-10-08 22:08:16 +00:00
</trans-unit>
<trans-unit id="sff0ac1ace2d90709">
<source>Use this provider with nginx's auth_request or traefik's forwardAuth. Each application/domain needs its own provider. Additionally, on each domain, /outpost.goauthentik.io must be routed to the outpost (when using a managed outpost, this is done for you).</source>
</trans-unit>
<trans-unit id="scb58b8a60cad8762">
<source>Default relay state</source>
</trans-unit>
<trans-unit id="s6827a456c9dfc6ee">
<source>When using IDP-initiated logins, the relay state will be set to this value.</source>
2023-10-12 12:00:45 +00:00
</trans-unit>
<trans-unit id="s01794c0ee3629c1b">
<source>Flow Info</source>
2023-10-12 13:12:46 +00:00
</trans-unit>
<trans-unit id="s24bce955914b1f0a">
<source>Stage used to configure a WebAuthn authenticator (i.e. Yubikey, FaceID/Windows Hello).</source>
2023-10-12 19:33:45 +00:00
</trans-unit>
web: Application wizard v2 with tests (#7004)
* A lot of comments about forms.
* Adding comments to the wizard.
* Broke out the text input into a single renderer. Still works as required.
* web: Legibility in the ApplicationForm.
This is a pretty good result. By using the LightDOM setting, this
provides the existing Authentik form manager with access to the
ak-form-horizontal-element components without having to do any
cross-border magic. It's not ideal, and it shows up just how badly
we've got patternfly splattered everywhere, but the actual results
are remarkable. The patterns for text, switch, radio, textarea,
file, and even select are smaller and easier here.
I'm still noodling on what an unspread search-select element would
look like. It's just dependency injection, so it ought to be as
straightforward as that.
* web: Marking down the start of the 'components' library.
* web: Baby steps
I become frustrated with my inability to make any progress on this project, so I decided to reach
for a tool that I consider highly reliable but also incredibly time-consuming and boring: test
driven development.
In this case, I wrote a story about how I wanted to see the first page rendered: just put the HTML
tag, completely unadorned, that will handle the first page of the wizard. Then, add an event handler
that will send the updated content to some parent object, since what we really want is to
orchestrate the state of the user's input with a centralized location. Then, rather than fiddling
with the attributes and properties of the various pages, I wanted them to be able to "look up" the
values they want, much as we'd expect a standalone form to be able to pull its values from the
server, so I added a context object that receives the update event and incorporates the new
knowledge about the state of the process into itself.
The result is surprisingly satisfying: the first page renders cleanly, displays the content that we
want, and as we fiddle with, we can *watch in real time* as the results of the context are updated
and retransmitted to all receiving objects. And the sending object gets the results so it
re-renders, but it ends up looking the same as it was before the render.
* Now, it's starting to look like a complete package. The LDAP method is working, but there is a bug:
the radio is sending the wrong value !?!?!?. Track that down, dammit. The search wrappers now resend
their events as standard `input` events, and that actually seems to work well; the browser is
decorating it with the right target, with the right `name` attribute, and since we have good
definitions of the `value` as a string (the real value of any search object is its UUID4), that
works quite well. Added search wrappers for CoreGroup and CryptoCertificate (CertificateKeyPairs),
and the latter has flags for "use the first one if it's the only one" and "allow the display of
keyless certificates."
Not sure why `state()` is blocking the transmission of typing information from the typed element
to the context handler, but it's a bug in the typechecker, and it's not a problem so far.
* Now, it's starting to look like a complete package. The LDAP method is working, but there is a bug:
the radio is sending the wrong value !?!?!?. Track that down, dammit. The search wrappers now resend
their events as standard `input` events, and that actually seems to work well; the browser is
decorating it with the right target, with the right `name` attribute, and since we have good
definitions of the `value` as a string (the real value of any search object is its UUID4), that
works quite well. Added search wrappers for CoreGroup and CryptoCertificate (CertificateKeyPairs),
and the latter has flags for "use the first one if it's the only one" and "allow the display of
keyless certificates."
Not sure why `state()` is blocking the transmission of typing information from the typed element
to the context handler, but it's a bug in the typechecker, and it's not a problem so far.
* web: tracked down that weirld bug with the radio.
Because radio inputs are actually multiples, the events handling for
radio is... wonky. If we want our `<ak-radio>` component to be a
unitary event dispatcher, saying "This is the element selected," we
needed to do more than what was currently being handled.
I've intercepted the events that we care about and have placed
them into a controller that dictates both the setting and the
re-render of the component. This makes it "controlled" (to use the
Angular/React/Vue) language and depends on Lit's reactiveElement
lifecycle to work, rather than trust the browser, but the browser's
experience with respect to the `<input type=radio` is pretty bad:
both input elements fire events, one for "losing selection" and
one for "gaining selection". That can be very confusing to handle,
so we funnel them down in our aggregate radio element to a single
event, "selection changed".
As a quality-of-life measure, I've also set the label to be
unselectable; this means that a click on the label will trigger the
selection event, and a long click will not disable selection or
confuse the selection event generator.
* web: now passing the precommit phase
* web: a HACK for Storybook to inject the "use light theme" flag into the body.
This isn't really a very good hack; what it does is say that every story is
responsible for hacking its theme into the parent. This is very annoying, but
it does mean that we can at least show our components in the best light.
* web: ak-application-wizard-authentication-by-oauth, and many fixes!
1. Fixed `eventEmitter` so that if the detail object is a scalar, it will not attempt to "objectify"
it. This was causing a bug where retrofitting the eventEmitter to some older components resulted
in a detail of "some" being translated into ['s', 'o', 'm', 'e']. Not what is wanted.
2. Removed the "transitional form" from the existing components; they had a two-step where the web
component class was just a wrapper around an independent rendering function. While this worked,
it was only to make the case that they *were* independent rendering objects and could be
supported with the right web component framework. We're halfway there now; the last step will be
to transform the horizontal-element and various input CSS into componentized CSS, the way
Patternfly-Elements is currently doing.
3. Fixed the `help` field so that it could take a string or a TemplateResult, and if the latter,
don't bother wrapping it in the helper text functionality; just let it be its own thing. This
supports the multi-line help of redirectURI as well as the `ak-utils-time-delta` capability.
4. Transform Oauth2ProviderForm to use the new components, to the best of our ability. Also used
the `provider = this.wizard.provider` and `provider = this.instance` syntax to make the render
function *completely portable*; it's the exact same text that is dropped into...
5. The complete `ak-application-wizard-authentication-by-oauth` component. They're so similar part
of me wonders if I could push them both out to a common reference, or a collection of common
references. Both components use the PropertyMapping and Sources, and both use the same
collection of searches (Crypto, Flow).
6. A Storybook for `ak-application-wizard-authentication-by-oauth`, showing the works working.
7. New mocks for `authorizationFlow`, `propertyMappings`, and `hasJWKs`.
This sequence has revealed a bug in the radio control. (It's always the radio control.) If the
default doesn't match the current setting, the radio control doesn't behave as expected; it won't
change when you fully expect that it should. I'll investigate how to harmonize those tomorrow.
* web: Converted our toggle groups to a more streamlined implementation.
* web: one more toggle group.
* initial api and schema
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* separate blueprint importer from yaml parsing
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* cleanup
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* web: Replace ad-hoc toggle control with ak-toggle-group
This commit replaces various ad-hoc implementations of the Patternfly Toggle Group HTML with a web
component that encapsulates all of the needed behavior and exposes a single API with a single event
handler, return the value of the option clicked.
The results are: Lots of visual clutter is eliminated. A single link of:
```
<div class="pf-c-toggle-group__item">
<button
class="pf-c-toggle-group__button ${this.mode === ProxyMode.Proxy
? "pf-m-selected"
: ""}"
type="button"
@click=${() => {
this.mode = ProxyMode.Proxy;
}}>
<span class="pf-c-toggle-group__text">${msg("Proxy")}</span>
</button>
</div>
<div class="pf-c-divider pf-m-vertical" role="separator"></div>
```
Now looks like:
```
<option value=${ProxyMode.Proxy}>${msg("Proxy")}</option>
```
This also means that the three pages that used the Patternfly Toggle Group could eliminate all of
their Patternfly PFToggleGroup needs, as well as the `justify-content: center` extension, which also
eliminated the `css` import.
The savings aren't as spectacular as I'd hoped: removed 178 lines, but added 123; total savings 55
lines of code. I still count this a win: we need never write another toggle component again, and
any bugs, extensions or features we may want to add can be centralized or forked without risking the
whole edifice.
* web: minor code formatting issue.
* add new "must_created" state to blueprints to prevent overwriting objects
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* web: adding a storybook for the ak-toggle-group component
* Bugs found by CI/CD.
* web: Replace ad-hoc search for CryptoCertificateKeyPairs with ak-crypto-certeficate-search
This commit replaces various ad-hoc implementations of `search-select` for CryptoCertificateKeyPairs
with a web component that encapsulates all of the needed behavior and exposes a single API.
The results are: Lots of visual clutter is eliminated. A single search of:
```HTML
<ak-search-select
.fetchObjects=${async (query?: string): Promise<CertificateKeyPair[]> => {
const args: CryptoCertificatekeypairsListRequest = {
ordering: "name",
hasKey: true,
includeDetails: false,
};
if (query !== undefined) {
args.search = query;
}
const certificates = await new CryptoApi(
DEFAULT_CONFIG,
).cryptoCertificatekeypairsList(args);
return certificates.results;
}}
.renderElement=${(item: CertificateKeyPair): string => {
return item.name;
}}
.value=${(item: CertificateKeyPair | undefined): string | undefined => {
return item?.pk;
}}
.selected=${(item: CertificateKeyPair): boolean => {
return this.instance?.tlsVerification === item.pk;
}}
?blankable=${true}
>
</ak-search-select>
```
Now looks like:
```HTML
<ak-crypto-certificate-search certificate=${this.instance?.tlsVerification}>
</ak-crypto-certificate-search>
```
There are three searches that do not require there to be a valid key with the certificate; these are
supported with the boolean property `nokey`; likewise, there is one search (in SAMLProviderForm)
that states that if there is no current certificate in the SAMLProvider and only one certificate can
be found in the Authentik database, use that one; this is supported with the boolean property
`singleton`.
These changes replace 382 lines of object-oriented invocations with 36 lines of declarative
configuration, and 98 lines for the class. Overall, the code for "find a crypto certificate" has
been reduced by 46%.
Suggestions for a better word than `singleton` are welcome!
* web: display tests for CryptoCertificateKeypair search
This adds a Storybook for the CryptoCertificateKeypair search, including
a mock fetch of the data. In the course of running the tests, we discovered
that including the SearchSelect _class_ won't include the customElement declaration
unless you include the whole file! Other bugs found: including the CSS from
Storybook is different from that of LitElement native, so much so that the
adapter needed to be included. FlowSearch had a similar bug. The problem
only manifests when building via Webpack (which Storybook uses) and not
Rollup, but we should support both in distribution.
* Fixed behavioral problem with the radio; the `if` there was
preventing the radio from reflecting the default correctly.
The observed behavior was that the radio wouldn't "activate"
until the item selected during the render pass was clicked on
first.
* Proxy Provider done.
* web: Tactical change. Put all the variants on the second page; it's
a longer list, but it's also easier to manage than all those
required sub-options.
* Rounding out the catalog.
* web: SAML Manual Configuration
Added a 'design document' that just kinda describes what I'm trying
to do, in case I don't get this done by Friday Aug 11, 2023.
I had two tables doing the same thing, so I merged them and then
wrote a few map/filters to specialize them for those two use cases.
Along the way I had to fiddle with the ESLint settings so that
underscore-prefixed unused variables would be ignored.
I cleaned up the visual appeal of the forms in the LDAP application.
I was copy/pasting the "handleProviderEvent" function, so I pulled
it out into ApplicationWizardProviderPageBase. Not so much a matter
of abstraction as just disliking that kind of duplication; it served
no purpose.
* Added SAML Story to Storybook.
* Web: This is coming together amazingly well. Like, almost too well.
* web: 80% of the way there
This commit includes the first three pages of the wizard, the
completion of the wizard framework with evented handling, and control
over progression.
Some shortcomings of this design have become evident: it isn't
possible to communicate between the steps' wrappers, as they are
POJOs without access to the context. An imperative decision-making
process has to be inserted in the orchestration layer,
which is kinda annoying.
But it looks good and it behaves correctly, to the extent that I've
given it behavior. It's an excellent foundation.
* Linting.
* web: application wizard
Found where the hook for form validity should go. Excellent! Now I just need to incorporate
that basic validation into the business logic and we're good to go.
* Turns out that was one layer too many; the topmost component was fine for
maintaining the context.
* It looks like my brilliant strategy has hit a snag.
The idea is simple. Let's start with this picture:
```
<application-wizard .steps=${[... a collection of step objects ...]}>
<wizard-main .steps=${(steps from above)}>
<application-current-panel>
<current-form>
```
- ApplicationWizard has a Context for the ApplicationProviderPair (or whatever it's going to be).
This context does not know about the steps; it just knows about: the "application" object, the
"provider" object, and a discriminator to know *which* provider the user has selected.
- ApplicationWizard has Steps that, among other things, provides Panels for:
- Application
- Pick Provider
- Configure Provider
- Submit ApplicationProviderPair to the back-end
- The WizardFrame renders the CurrentPanel for the CurrentStep
The CurrentPanel gets its data from the ApplicationWizard in the form of a Context. It then sends
messages (events) to ApplicationWizard about the contents of each field as the user is filling out
the form, so that the ApplicationWizard can record those in the ApplicationProviderPair for later
submission.
When a CurrentForm is valid, the ApplicationWizard updates the Steps object to show that the "Next
button" on the Wizard is now available.
In this way, the user can progress through the system. When they get to the last page, we can
provide in the ApplicationWizard with the means to submit the form and/or send the user back to
the page with the validation failure.
Problem: The context is being updated in real-time, which is triggering re-renders of the form. This
leads to focus problems as the fields that are not yet valid are triggering "focus grab" behavior.
This is a classic problem with "controlled" inputs. What we really want is for the CurrentPanel to
not re-render at all, but to behave like a normal, uncontrolled form, and let the browser do most of
the work. We still want the [Next] button to enable when the form is valid enough to permit that.
---
Other details: I've ripped out a lot of Jen's work, which is probably a mistake. It's still
preserved elsewhere. I've also cleaned up the various wizardly things to try and look organized.
It *looks* like it should work, it just... doesn't. Not yet.
* Late addition: I had an inspiration about how to reduce the way
reactivity broke focus by, basically, removing the reactivity and
managing the first-time-through lifecycle to prevent the update
from causing refocus. It works well! Now I just need to test it.
* This application fixes the bug with respect to the wizard-level context being updated incorrectly.
Understandings:
- To use uncontrolled inputs, which I prefer, the context object should not be a state or property
at the level of consumers; it should not automatically re-render with every keystroke, i.e. "The
React Way." We're using Web Components, [client-side
validation](https://developer.mozilla.org/en-US/docs/Learn/Forms/Form_validation) exists on the
platform already, and live-validation is problematic for any number of reasons.
- The trade-off is that it is now necessary to re-render the target page of the wizard de-novo, but
that's not really as big a deal as it sounds. Lit is ready to do that... and then nothing else
until we request a change-of-page. Excellent.
- The top level context *must* be a state, but it's better if it's a state never actually used by
the top-level context container. The debate about whether or not to make that container a dumb one
(`<slot></slot>`) or to merge it with the top-level object continues; here, I've merged it with
the top-level wizard object, but that object does not refer to the state variable being managed in
its render pass, so changes to it do not cause a re-render of the whole wizard. The purpose of the
top-level page is to manage the *steps*, not the *content of any step*. A step may change
dynamically based on the content of a step, but that's the same thing as *which step*. Lesson:
always know what your state is *about*.
- Deep merging is a complex subject, but here it's appropriate to our needs.
* web: Application Wizard
This commit combines a working (but very unpolished) version of the Application Wizard with Jen's
code for the CoreTransactionApplicationRequest, resulting in a successful round trip.
It fixes a number of bugs with the way ContextProducer decorators were being processed, such that
they just weren't working with our current configuration (although they did work fine in Storybook);
consumers didn't need to be fixed.
It also *removes* the steps-aware context from the Wizard.
That *may* be a mistake. To re-iterate, the `WizardFrame` provides the chrome for a Wizard: the
button bar div, the breadcrumbs div, the header div, and it takes the steps object as its source of
truth for all of the content. The `WizardContent` part of the application has two parts: The
`WizardMain`, which wraps the frame and supplies the context for all the `WizardPanels`, and the
`WizardPanels` themselves, which are dependent on a context from `WizardMain` for the data that
populates each panel. YAGNI right now that the panels need to know anything about the steps, and the
`WizardMain` can just pass a fresh `.steps` object to the `WizardFrame` when they need updating.
Using props drilling may make more sense here.
It certainy does *not* make sense for the panels. They need to be renderable on-demand, and they
need to make sense of what they're rendering on-demand, so the function is
```
(panel code) => (context) => (rendered panel)
```
(Yes, that's curried notation. Deal.)
* This commit includes the first WDIO test for the ApplicationWizard. It doesn't do much right now, but
it does log in and navigate to the wizard successfully.
* web: completed test for single application, provided new programming language to make it easier to write tests.
* Almost there.
Missing: The validation is currently not working as expected, and I cannot get the backend
to give me meaningful data helping us "go back" to the field that wasn't valid. I really
don't want to put all the meaningful validation on the front-end; that's the road to -
perdition, the back-end must be usable by people less assiduous than we are.
Also: Need to make the button bar work better; maybe each panel can provide a custom button
bar if one is needed?
* web: Test harness
We have an end-to-end test harness that includes a trivially correct DSL for "This is what a user would do, do this":
```
const deleteProvider = (theSlug) => ([
["button", '>>>ak-sidebar-item a[href="#/core/providers"]'],
["deletebox", `>>>a[href="#/core/applications/${theSlug}"]`],
["button", '>>>ak-forms-delete-bulk button[slot="trigger"]'],
["button", '>>>ak-forms-delete-bulk div[role="dialog"] ak-spinner-button'],
]);
```
It's now possible to target individual sequences of events this way. With a little creativity, we could have standalone functions that take parameters for our calls and just do them, without too much struggle.
* web: Revised navigation
After working with the navigation for awhile, I realized that it's a poor map; what I really wanted was
a controller/view pair, where events flow up to the controller and then messages on "what to draw" flow
down to the view. It work quite well, and the wizard frame is smaller and smarter for it.
I've also moved the WDIO-driven tests into the 'tests' folder, because it (a) makes more sense to put
them there, and (b) it prevents any confusion about who's in charge of node_modules.
* web: Simplify, simplify, simplify
Sort-of.
This commit changes the way the "wizard step coordinator" layer works, giving the
wizard writer much more power over button bar. It still assumes there are only
three actions the wizard frame wants to commit: next, back, and close. This empowers
the steps themselves to re-arrange their buttons and describe the rules through which
transitions occur.
* web: resetting the form is not working yet...
I vehemently dislike the object-oriented "reset" command; every wizard should start with
an absolutely fresh copy of the data upon entry. Refactoring the wizard to re-build its
content from the inside is the correct way to go, but I don't have a good mental image
of how to make the ModalButton and the component it invokes interact cleanly, which
frustrates the hell out of me.
* web: reset
As I said, I greatly dislike having to be dependent upon "resets"; I prefer my
data to be de novo going into a "new" transaction. That said, we work with
what we've got; I've created an event generated by the wizard that says the
modal just closed; anything wrapping and implementing the wizard can then
capture that event and reset the data. I've also added a pair of functions
that create the two states (what step, what form data) anew, so that resetting
is as trivial as initializing (and is exactly the same, code-wise).
* web: Without error handling, this is complete, but I still need @BeryJu (Jens)
for help with the SAML Upload (it doesn't appear to be correctly handled?) and
the error handling.
* web: revise tests for wizard
This commit replaces the previous WDIO instance with a more formal and straightforward process using
the [pageobjects](https://martinfowler.com/bliki/PageObject.html). In this form, every major
component has its own test suite, and a test is a sequence of exercises of those components.
A test then becomes something as straightforward as:
```
await LoginPage.open();
await LoginPage.login("ken@goauthentik.io", "eat10bugs");
expect(await UserLibraryPage.pageHeader).toHaveText("My Applications");
await UserLibraryPage.goToAdmin();
expect(await AdminOverviewPage.pageHeader).toHaveText("Welcome, ");
await AdminOverviewPage.openApplicationsListPage();
expect(await ApplicationsListPage.pageHeader).toHaveText("Applications");
ApplicationsListPage.startCreateApplicationWizard();
await ApplicationWizard.app.name.setValue(`Test application ${newId}`);
await ApplicationWizard.nextButton.click();
await (await ApplicationWizard.getProviderType("ldapprovider")).click();
await ApplicationWizard.nextButton.click();
await ApplicationWizard.ldap.setBindFlow("default-authentication-flow");
await ApplicationWizard.nextButton.click();
await expect(await ApplicationWizard.commitMessage).toHaveText(
"Your application has been saved"
);
```
Whether or not there's another layer of DSL in there or not, this is a pretty nice idiom for
maintaining tests.
* web: updating with forms and fixes for eslint complaints.
* web/add webdriverIO testing layer
This commit adds WebdriverIO as an end-to-end solution to unit testing. WebdriverIO can be run both
locally and remotely, supports strong integration with web components, and is generally robust for
use in pipelines. I'll confess to working through a tutorial on how to do this for web components,
and this is just chapter 2 (I think there are 5 or so chapters...).
There's a makefile, with help! If you just run `make` it tells you:
```
Specify a command. The choices are:
help Show this help
node_modules Runs `npm install` to prepare this feature
precommit Run the precommit: spell check all comments, eslint with sonarJS, prettier-write
test-good-login Test that we can log into the server. Requires a running instance of the server.
test-bad-login Test that bad usernames and passwords create appropriate error messages
```
... because Makefiles are documentation, and documentation belongs in Makefiles.
I've chosen to go with a PageObject-oriented low-level DSL; what that means is that for each major
components (a page, a form, a wizard), there's a class that provides human-readable names for
human-interactable and human-viewable objects on the page. The LoginPage object, for example, has
selectors for the username, password, submit button, and the failure alert; accessing those allows
us to test for items as expected., and to write a DSL for "a good login" that's as straightforward
as:
```
await LoginPage.open();
await LoginPage.login("ken@goauthentik.io", "eat10bugs");
await expect(UserLibraryPage.pageHeader).toHaveText("My applications");
```
There was a *lot* of messing around with the LoginPage to get the username and password into the
system. For example, I had to do this with all the `waitForClickable` and `waitForEnable` because
we both keep the buttons inaccessible until the form has something and we "black out" the page (put
a darkening filter over it) while accessing the flow, meaning there was a race condition such that
the test would attempt to interact with the username or password field before it was accessible.
But this works now, which is very nice.
``` JavaScript
get inputUsername() {
return $('>>>input[name="uidField"]');
}
get btnSubmit() {
return $('>>>button[type="submit"]');
}
async username(username: string) {
await this.inputUsername.waitForClickable();
await this.inputUsername.setValue(username);
await this.btnSubmit.waitForEnabled();
await this.btnSubmit.click();
}
```
The bells & whistles of *Prettier*, *Eslint*, and *Codespell* have also been enabled. I do like my
guardrails.
* web/adding tests: added comments and cleaned up some administrative features.
* web/test: changed the name of one test to reflect it's 'good' status
* core/allow alternative postgres credentials
This commit allows the `dev-reset` command in the Makefile to pick up and use credentials from the
`.env` file if they are present, or fallback to the defaults provided if they are not. This is the
only place in the Makefile where the database credentials are used directly against postgresql
binaries. The syntax was tested with bash, zsh, and csh, and did not fail under those.
The `$${:-}` syntax is a combination of a Makefile idiom for "Pass a single `$` to the environment
where this command will be executed," and the shell expresion `${VARIABLE:-default}` means
"dereference the environment variable; if it is undefined, used the default value provided."
* Re-arrange sequence to avoid recursive make.
Nothing wrong with recursive make; it just wasn't essential
here. `migrate` is just a build target, not a task.
* Cleanup according to the Usage:
checkmake [options] <makefile>...
checkmake -h | --help
checkmake --version
checkmake --list-rules Makefile linting tool.
* core: added 'help' to the Makefile
* get postgres config from authentik config loader
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* don't set -x by default
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* sort help
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* update help strings
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* web: test LDAP wizard sequence
* web: improve testing by adding test admin user via blueprint
* This commit continues the application wizard buildout. In this commit are the following changes:
- Added SCIM to the list of available providers
- Fixed ForwardProxy so that its mode is set correctly. (This is a special case in the committer;
I'm unhappy with that.)
- Fixed the commit messages so that:
- icons are set correctly (Success, Danger, Working)
- icons are colored correctly according to state
- commit message includes a `data-commit-state` field so tests can find it!
- Merged the application wizard tests into a single test pass
- Isolated common parts of the application wizard tests to reduce unnecessary repetition. All
application tests are the same until you reach the provider section anyway.
- Fixed the unit tests so they're finding the right error messages and are enabled to display them
correctly.
- Moved the test Form handlers into their own folder so they're not cluttering up the Pages folder.
* web: add radius to application wizard
This commit continues the application wizard buildout. In this commit are the following changes:
- Fixed a width-setting bug in the Makefile `make help` feature (i.e "automate that stuff!")
- Added Radius to the list of providers we can offer via the wizard
- Added `launchUrl` and `UI Settings` to features of the application page the wizard can find
- Changed 'SAML Manual Configuration' to just say "SAML Configuration"
- Modified `ak-form-group` to take and honor the `aria-label` property (which in turn makes it
easier to target specific forms with unit testing)
- Reduced the log level for wdio to 'warn'; 'info' was super-spammy and not helpful. It can be put
back with `--logLevel info` from the command line.
* fix blueprints
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* update package name
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* add dependabot
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* prettier run
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* add basic CI
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* remove hooks
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* web: application wizard refactor & completion
This commit refactors the various components of the Wizard and ApplicationWizard, creating a much
more maintainable and satisfying Wizard experience for both developers (i.e, *me* and *Jens* so
far), and for the customer.
The Wizard base has been refactored into three components:
**AkWizardController**
The `AkWizardController` provides the event listenters for the wizard; it hooks them up, recevies the
events, and forwards them to the wizard. It unwraps the event objects and forwards the relevant
messages contained in the events. It knows of three event categories:
- Navigation requests (move to a different step)
- Update requests (the current step has updated the business content)
- Close requests (close or cancel the wizard).
**ak-wizard-frame**
The `ak-wizard-frame` is the ModalButton interface. It provides the Header, Breadcrumbs (nee`
"navigation block"), Buttons, and a DIV into which the main content is rendered.
**AkWizard**
`AkWizard` is an *incomplete* implementation of the wizard. It's meant to be inherited by a child
class, which will implement the rest. It extends `AKElement`. It provides the basic content needed,
such as steps, currentStep (as an index), an accessor for the step itself, an accessor for the
frame, and the interface to the `AkWizardController`.
**ApplicationWizard**
The `ApplicationWizard` itself has been refactored to accommodate these changes. It inherits from
`AkWizard` and provides the business logic for what to do when a form updates, some custom logic for
preventing moving through the wizard when the forms are incomplete, and a persistence layer for
filling out different providers in the same session. It's simplified a *lot*.
The types specified for `AkWizard` are pretty nifty, I think. I could wish the types being passed
via the custom events were more robust, but [strongly typed custom
events](https://github.com/lit/lit-element/issues/808) turn out to be quite the pain in the, er,
neck. As it is, the `precommit` pass did very good at preventing the worst disasters.
The steps themselves were re-written as objects so that they could take advantage of their `valid`
and `disabled` states and provide more meaningful buttons and labels. I think it's a solid
compromise, and it moved a lot of display logic out of the core `handleUpdate()` business method.
The tests, such as they are, are passing.
* Added comment describing new test.
* web: ensuring copy from `main` is canon
* web: fixes after merge
* web: laying the groundwork for future expansion
This commit is a hodge-podge of updates and changes to the web. Functional changes:
- Makefile: Fixed a bug in the `help` section that prevented the WIDTH from being accurately
calculated if `help` was included rather than in-lined.
- ESLint: Modified the "unused vars" rule so that variables starting with an underline are not
considered by the rule. This allows for elided variables in event handlers. It's not a perfect
solution-- a better one would be to use Typescript's function-specialization typing, but there are
too many places where we elide or ignore some variables in a function's usage that switching over
to specialization would be a huge lift.
- locale: It turns out, lit-locale does its own context management. We don't need to have a context
at all in this space, and that's one less listener we need to attach t othe DOM.
- ModalButton: A small thing, but using `nothing` instead of "html``" allows lit better control over
rendering and reduces the number of actual renders of the page.
- FormGroup: Provided a means to modify the aria-label, rather than stick with the just the word
"Details." Specializing this field will both help users of screen readers in the future, and will
allow test suites to find specific form groups now.
- RadioButton: provide a more consistent interface to the RadioButton. First, we dispatch the
events to the outside world, and we set the value locally so that the current `Form.ts` continues
to behave as expected. We also prevent the "button lost value" event from propagating; this
presents a unified select-like interface to users of the RadioButtonGroup. The current value
semantics are preserved; other clients of the RadioButton do not see a change in behavior.
- EventEmitter: If the custom event detail is *not* an object, do not use the object-like semantics
for forwarding it; just send it as-is.
- Comments: In the course of laying the groundwork for the application wizard, I throw a LOT of
comments into the code, describing APIs, interfaces, class and function signatures, to better
document the behavior inside and as signposts for future work.
* web: permit arrays to be sent in custom events without interpolation.
* actually use assignValue or rather serializeFieldRecursive
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* web: eslint & prettier fixes, plus small aesthetic differences.
* Restoring this file. Not sure where it disappears to.
* fix label in dark mode
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* SCIM Manuel -> SCIM
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* fix lint errors
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* web: better converter configuration, CSS repair, and forward-domain-proxy
1. Forward Domain Proxy. I wasn't sure if this method was appropriate for the wizard,
but Jens says it is. I've added it.
2. In the process of doing so, I decided that the Provider.converter field was overly
complexified; I tried too hard to reduce the number of functions I needed to define,
but in the process outsourced some of the logic of converting the Wizard's dataset
into a property typed request to the `commit` phase, which was inappropriate. All
of the logic about a provider, aside from its display, should be here with the code
that distinguishes between providers. This commit makes it so.
3. Small CSS fix: the fields inherited from the Proxy provider forms had some unexpected
CSS which was causing a bit of a weird indent. That has been rectified.
* web: running pre-commit after merge.
* web: ensure the applications wizard tests finish after current changes
* prettier has opinions.
* web: application wizard spit & polish
The "ApplicationWizardHint" now correctly uses the localstorage and allows the user to navigate back
and see the message after it's been hidden, so that it will always be available during the test
phase.
The ApplicationList's old "Create Application Form" button has been restored for the purposes of the
test phase.
The ApplicationWizard is now available on both the ApplicationList and ProviderList pages.
Tana and I discussed the microcopy, putting a stronger second-person "You can do..." twist onto the
language, to give the user the sense of empowerment.
The ShowHintController now has both "hide" and "show" operations, to support the hint restoration.
* web: updated storybook stories for the wizard, illustration how "a simple wizard" is configured in source code and tested with storybook.
* web: I hate getting spanked by prettier.
* web: sometimes I wish I had lower standards
Anyway, this was a very stupid bug, because by definition function
definition arguments don't have uses, they're being defined, not
implemented. Fixed, conf fixed to compensate, and consequences
conquered.
* move context from labs to main
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* Revert "move context from labs to main"
This reverts commit 3718ee69048966d26b1c357a7d2653fbb3ab613b.
* web: reify the data loop
I was very unhappy with the "update this dot-path" mechanism I was using earlier; it was hard
for me to read and understand what was happening, and I wrote the darned thing. I decided instead
to go with a hard substitution model; each phase of the wizard is responsible for updating the
*entire* payload, mostly by creating a new payload and substituting the field value associated
with the event.
On the receiver, we have to do that *again* to handle the swapping of providers when the user
chooses one and then another. It looks clunky, and it is, but it's *legible*; a junior dev
could understand what it's doing, and that's the goal.
* Revert "web: reify the data loop"
This reverts commit 09fedcacf02a90a021ce9e18c0eb4bec1ef48302.
* web: revert the 'lit' to 'lit-labs' for task and context.
---------
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-10-18 19:43:37 +00:00
<<<<<<< HEAD
<trans-unit id="s1cffe58249b04669">
<source>Internal application name used in URLs.</source>
</trans-unit>
<trans-unit id="sb3d4f79d9d8b71e5">
<source>Submit</source>
</trans-unit>
<trans-unit id="se2b29e6cfe59414c">
<source>UI Settings</source>
</trans-unit>
<trans-unit id="s836148f721d8913b">
<source>Transparent Reverse Proxy</source>
</trans-unit>
<trans-unit id="s945a6b94361ee45b">
<source>For transparent reverse proxies with required authentication</source>
</trans-unit>
<trans-unit id="s40830ec037f34626">
<source>Configure SAML provider manually</source>
</trans-unit>
<trans-unit id="sea9fc40dfd1d18b1">
<source>Configure RADIUS provider manually</source>
</trans-unit>
<trans-unit id="sa1b0052ae095b9b3">
<source>Configure SCIM provider manually</source>
</trans-unit>
<trans-unit id="s15831fa50a116545">
<source>Saving Application...</source>
</trans-unit>
<trans-unit id="s823abdb61543a826">
<source>Authentik was unable to save this application:</source>
</trans-unit>
<trans-unit id="s848288f8c2265aad">
<source>Your application has been saved</source>
</trans-unit>
<trans-unit id="s67d858051b34c38b">
<source>Method's display Name.</source>
</trans-unit>
<trans-unit id="h10ef80d434185070">
<source>Use this provider with nginx's <x id="0" equiv-text="<code>"/>auth_request<x id="1" equiv-text="</code>"/> or traefik's
<x id="2" equiv-text="<code>"/>forwardAuth<x id="3" equiv-text="</code>"/>. Each application/domain needs its own provider.
Additionally, on each domain, <x id="4" equiv-text="<code>"/>/outpost.goauthentik.io<x id="5" equiv-text="</code>"/> must be
routed to the outpost (when using a managed outpost, this is done for you).</source>
</trans-unit>
2023-10-12 19:33:45 +00:00
<trans-unit id="sd18b18f91b804c3f">
<source>Custom attributes</source>
</trans-unit>
<trans-unit id="s71c5d51d5a357dbd">
<source>Don't show this message again.</source>
2023-10-16 15:31:50 +00:00
</trans-unit>
<trans-unit id="s3e99ea082ca5ade9">
<source>Failed to fetch</source>
</trans-unit>
<trans-unit id="s98327528f00365a7">
<source>Failed to fetch data.</source>
</trans-unit>
<trans-unit id="sf485014051ad0cf7">
<source>Successfully assigned permission.</source>
</trans-unit>
<trans-unit id="sca7fed2bef53cb99">
<source>Role</source>
</trans-unit>
<trans-unit id="sc92c1a54034e21cc">
<source>Assign</source>
</trans-unit>
<trans-unit id="scd84d10ee9137070">
<source>Assign permission to role</source>
</trans-unit>
<trans-unit id="s5ee6f1b84e9ebc69">
<source>Assign to new role</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-16 15:31:50 +00:00
<trans-unit id="s4afb26a8fae257e9">
<source>Directly assigned</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-16 15:31:50 +00:00
<trans-unit id="sd8051c26e155f043">
<source>Assign permission to user</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-16 15:31:50 +00:00
<trans-unit id="sf79f8681e5ffaee2">
<source>Assign to new user</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-16 15:31:50 +00:00
<trans-unit id="saabeb4cab074b0b9">
<source>User Object Permissions</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-16 15:31:50 +00:00
<trans-unit id="s8489d5559dda260c">
<source>Role Object Permissions</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-16 15:31:50 +00:00
<trans-unit id="s6b2beba7ab637e9e">
<source>Roles</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-16 15:31:50 +00:00
<trans-unit id="s96d2bb4be3f5e8aa">
<source>Select roles to grant this groups' users' permissions from the selected roles.</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-16 15:31:50 +00:00
<trans-unit id="sb37880a2a7288ef0">
<source>Update Permissions</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-16 15:31:50 +00:00
<trans-unit id="se9c07cf256774d81">
<source>Editing is disabled for managed tokens</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-16 15:31:50 +00:00
<trans-unit id="s78ab26da7f067de8">
<source>Select permissions to grant</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-16 15:31:50 +00:00
<trans-unit id="sdeb90bfd8a80b86b">
<source>Permissions to add</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-16 15:31:50 +00:00
<trans-unit id="s36247910d67421e1">
<source>Select permissions</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-16 15:31:50 +00:00
<trans-unit id="s67e136af8fc1107b">
<source>Assign permission</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-16 15:31:50 +00:00
<trans-unit id="sb923723d27df40ba">
<source>Permission(s)</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-16 15:31:50 +00:00
<trans-unit id="sc5fb00b25c7f5a02">
<source>Permission</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-16 15:31:50 +00:00
<trans-unit id="s1455753daa00f1bc">
<source>User doesn't have view permission so description cannot be retrieved.</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-16 15:31:50 +00:00
<trans-unit id="sa3a3e09b88ed9791">
<source>Assigned permissions</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-16 15:31:50 +00:00
<trans-unit id="s9cc631505c17b028">
<source>Assigned global permissions</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-16 15:31:50 +00:00
<trans-unit id="s8f85a0e678846080">
<source>Assigned object permissions</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-16 15:31:50 +00:00
<trans-unit id="s9103a949a3963aa9">
<source>Successfully updated role.</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-16 15:31:50 +00:00
<trans-unit id="sdf87c5661b31359e">
<source>Successfully created role.</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-16 15:31:50 +00:00
<trans-unit id="s3484b1e6d0b5335f">
<source>Manage roles which grant permissions to objects within authentik.</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-16 15:31:50 +00:00
<trans-unit id="s259de999919316db">
<source>Role(s)</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-16 15:31:50 +00:00
<trans-unit id="s2ffad156e8332f04">
<source>Update Role</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-16 15:31:50 +00:00
<trans-unit id="sc5f923729564fbf3">
<source>Create Role</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-16 15:31:50 +00:00
<trans-unit id="s14bfa8fd1bec8889">
<source>Role doesn't have view permission so description cannot be retrieved.</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-16 15:31:50 +00:00
<trans-unit id="s7e796fe83982863f">
<source>Role <x id="0" equiv-text="${this._role?.name || ""}"/></source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-16 15:31:50 +00:00
<trans-unit id="s526e2c66bd51ff5f">
<source>Role Info</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
web: Application wizard v2 with tests (#7004)
* A lot of comments about forms.
* Adding comments to the wizard.
* Broke out the text input into a single renderer. Still works as required.
* web: Legibility in the ApplicationForm.
This is a pretty good result. By using the LightDOM setting, this
provides the existing Authentik form manager with access to the
ak-form-horizontal-element components without having to do any
cross-border magic. It's not ideal, and it shows up just how badly
we've got patternfly splattered everywhere, but the actual results
are remarkable. The patterns for text, switch, radio, textarea,
file, and even select are smaller and easier here.
I'm still noodling on what an unspread search-select element would
look like. It's just dependency injection, so it ought to be as
straightforward as that.
* web: Marking down the start of the 'components' library.
* web: Baby steps
I become frustrated with my inability to make any progress on this project, so I decided to reach
for a tool that I consider highly reliable but also incredibly time-consuming and boring: test
driven development.
In this case, I wrote a story about how I wanted to see the first page rendered: just put the HTML
tag, completely unadorned, that will handle the first page of the wizard. Then, add an event handler
that will send the updated content to some parent object, since what we really want is to
orchestrate the state of the user's input with a centralized location. Then, rather than fiddling
with the attributes and properties of the various pages, I wanted them to be able to "look up" the
values they want, much as we'd expect a standalone form to be able to pull its values from the
server, so I added a context object that receives the update event and incorporates the new
knowledge about the state of the process into itself.
The result is surprisingly satisfying: the first page renders cleanly, displays the content that we
want, and as we fiddle with, we can *watch in real time* as the results of the context are updated
and retransmitted to all receiving objects. And the sending object gets the results so it
re-renders, but it ends up looking the same as it was before the render.
* Now, it's starting to look like a complete package. The LDAP method is working, but there is a bug:
the radio is sending the wrong value !?!?!?. Track that down, dammit. The search wrappers now resend
their events as standard `input` events, and that actually seems to work well; the browser is
decorating it with the right target, with the right `name` attribute, and since we have good
definitions of the `value` as a string (the real value of any search object is its UUID4), that
works quite well. Added search wrappers for CoreGroup and CryptoCertificate (CertificateKeyPairs),
and the latter has flags for "use the first one if it's the only one" and "allow the display of
keyless certificates."
Not sure why `state()` is blocking the transmission of typing information from the typed element
to the context handler, but it's a bug in the typechecker, and it's not a problem so far.
* Now, it's starting to look like a complete package. The LDAP method is working, but there is a bug:
the radio is sending the wrong value !?!?!?. Track that down, dammit. The search wrappers now resend
their events as standard `input` events, and that actually seems to work well; the browser is
decorating it with the right target, with the right `name` attribute, and since we have good
definitions of the `value` as a string (the real value of any search object is its UUID4), that
works quite well. Added search wrappers for CoreGroup and CryptoCertificate (CertificateKeyPairs),
and the latter has flags for "use the first one if it's the only one" and "allow the display of
keyless certificates."
Not sure why `state()` is blocking the transmission of typing information from the typed element
to the context handler, but it's a bug in the typechecker, and it's not a problem so far.
* web: tracked down that weirld bug with the radio.
Because radio inputs are actually multiples, the events handling for
radio is... wonky. If we want our `<ak-radio>` component to be a
unitary event dispatcher, saying "This is the element selected," we
needed to do more than what was currently being handled.
I've intercepted the events that we care about and have placed
them into a controller that dictates both the setting and the
re-render of the component. This makes it "controlled" (to use the
Angular/React/Vue) language and depends on Lit's reactiveElement
lifecycle to work, rather than trust the browser, but the browser's
experience with respect to the `<input type=radio` is pretty bad:
both input elements fire events, one for "losing selection" and
one for "gaining selection". That can be very confusing to handle,
so we funnel them down in our aggregate radio element to a single
event, "selection changed".
As a quality-of-life measure, I've also set the label to be
unselectable; this means that a click on the label will trigger the
selection event, and a long click will not disable selection or
confuse the selection event generator.
* web: now passing the precommit phase
* web: a HACK for Storybook to inject the "use light theme" flag into the body.
This isn't really a very good hack; what it does is say that every story is
responsible for hacking its theme into the parent. This is very annoying, but
it does mean that we can at least show our components in the best light.
* web: ak-application-wizard-authentication-by-oauth, and many fixes!
1. Fixed `eventEmitter` so that if the detail object is a scalar, it will not attempt to "objectify"
it. This was causing a bug where retrofitting the eventEmitter to some older components resulted
in a detail of "some" being translated into ['s', 'o', 'm', 'e']. Not what is wanted.
2. Removed the "transitional form" from the existing components; they had a two-step where the web
component class was just a wrapper around an independent rendering function. While this worked,
it was only to make the case that they *were* independent rendering objects and could be
supported with the right web component framework. We're halfway there now; the last step will be
to transform the horizontal-element and various input CSS into componentized CSS, the way
Patternfly-Elements is currently doing.
3. Fixed the `help` field so that it could take a string or a TemplateResult, and if the latter,
don't bother wrapping it in the helper text functionality; just let it be its own thing. This
supports the multi-line help of redirectURI as well as the `ak-utils-time-delta` capability.
4. Transform Oauth2ProviderForm to use the new components, to the best of our ability. Also used
the `provider = this.wizard.provider` and `provider = this.instance` syntax to make the render
function *completely portable*; it's the exact same text that is dropped into...
5. The complete `ak-application-wizard-authentication-by-oauth` component. They're so similar part
of me wonders if I could push them both out to a common reference, or a collection of common
references. Both components use the PropertyMapping and Sources, and both use the same
collection of searches (Crypto, Flow).
6. A Storybook for `ak-application-wizard-authentication-by-oauth`, showing the works working.
7. New mocks for `authorizationFlow`, `propertyMappings`, and `hasJWKs`.
This sequence has revealed a bug in the radio control. (It's always the radio control.) If the
default doesn't match the current setting, the radio control doesn't behave as expected; it won't
change when you fully expect that it should. I'll investigate how to harmonize those tomorrow.
* web: Converted our toggle groups to a more streamlined implementation.
* web: one more toggle group.
* initial api and schema
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* separate blueprint importer from yaml parsing
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* cleanup
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* web: Replace ad-hoc toggle control with ak-toggle-group
This commit replaces various ad-hoc implementations of the Patternfly Toggle Group HTML with a web
component that encapsulates all of the needed behavior and exposes a single API with a single event
handler, return the value of the option clicked.
The results are: Lots of visual clutter is eliminated. A single link of:
```
<div class="pf-c-toggle-group__item">
<button
class="pf-c-toggle-group__button ${this.mode === ProxyMode.Proxy
? "pf-m-selected"
: ""}"
type="button"
@click=${() => {
this.mode = ProxyMode.Proxy;
}}>
<span class="pf-c-toggle-group__text">${msg("Proxy")}</span>
</button>
</div>
<div class="pf-c-divider pf-m-vertical" role="separator"></div>
```
Now looks like:
```
<option value=${ProxyMode.Proxy}>${msg("Proxy")}</option>
```
This also means that the three pages that used the Patternfly Toggle Group could eliminate all of
their Patternfly PFToggleGroup needs, as well as the `justify-content: center` extension, which also
eliminated the `css` import.
The savings aren't as spectacular as I'd hoped: removed 178 lines, but added 123; total savings 55
lines of code. I still count this a win: we need never write another toggle component again, and
any bugs, extensions or features we may want to add can be centralized or forked without risking the
whole edifice.
* web: minor code formatting issue.
* add new "must_created" state to blueprints to prevent overwriting objects
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* web: adding a storybook for the ak-toggle-group component
* Bugs found by CI/CD.
* web: Replace ad-hoc search for CryptoCertificateKeyPairs with ak-crypto-certeficate-search
This commit replaces various ad-hoc implementations of `search-select` for CryptoCertificateKeyPairs
with a web component that encapsulates all of the needed behavior and exposes a single API.
The results are: Lots of visual clutter is eliminated. A single search of:
```HTML
<ak-search-select
.fetchObjects=${async (query?: string): Promise<CertificateKeyPair[]> => {
const args: CryptoCertificatekeypairsListRequest = {
ordering: "name",
hasKey: true,
includeDetails: false,
};
if (query !== undefined) {
args.search = query;
}
const certificates = await new CryptoApi(
DEFAULT_CONFIG,
).cryptoCertificatekeypairsList(args);
return certificates.results;
}}
.renderElement=${(item: CertificateKeyPair): string => {
return item.name;
}}
.value=${(item: CertificateKeyPair | undefined): string | undefined => {
return item?.pk;
}}
.selected=${(item: CertificateKeyPair): boolean => {
return this.instance?.tlsVerification === item.pk;
}}
?blankable=${true}
>
</ak-search-select>
```
Now looks like:
```HTML
<ak-crypto-certificate-search certificate=${this.instance?.tlsVerification}>
</ak-crypto-certificate-search>
```
There are three searches that do not require there to be a valid key with the certificate; these are
supported with the boolean property `nokey`; likewise, there is one search (in SAMLProviderForm)
that states that if there is no current certificate in the SAMLProvider and only one certificate can
be found in the Authentik database, use that one; this is supported with the boolean property
`singleton`.
These changes replace 382 lines of object-oriented invocations with 36 lines of declarative
configuration, and 98 lines for the class. Overall, the code for "find a crypto certificate" has
been reduced by 46%.
Suggestions for a better word than `singleton` are welcome!
* web: display tests for CryptoCertificateKeypair search
This adds a Storybook for the CryptoCertificateKeypair search, including
a mock fetch of the data. In the course of running the tests, we discovered
that including the SearchSelect _class_ won't include the customElement declaration
unless you include the whole file! Other bugs found: including the CSS from
Storybook is different from that of LitElement native, so much so that the
adapter needed to be included. FlowSearch had a similar bug. The problem
only manifests when building via Webpack (which Storybook uses) and not
Rollup, but we should support both in distribution.
* Fixed behavioral problem with the radio; the `if` there was
preventing the radio from reflecting the default correctly.
The observed behavior was that the radio wouldn't "activate"
until the item selected during the render pass was clicked on
first.
* Proxy Provider done.
* web: Tactical change. Put all the variants on the second page; it's
a longer list, but it's also easier to manage than all those
required sub-options.
* Rounding out the catalog.
* web: SAML Manual Configuration
Added a 'design document' that just kinda describes what I'm trying
to do, in case I don't get this done by Friday Aug 11, 2023.
I had two tables doing the same thing, so I merged them and then
wrote a few map/filters to specialize them for those two use cases.
Along the way I had to fiddle with the ESLint settings so that
underscore-prefixed unused variables would be ignored.
I cleaned up the visual appeal of the forms in the LDAP application.
I was copy/pasting the "handleProviderEvent" function, so I pulled
it out into ApplicationWizardProviderPageBase. Not so much a matter
of abstraction as just disliking that kind of duplication; it served
no purpose.
* Added SAML Story to Storybook.
* Web: This is coming together amazingly well. Like, almost too well.
* web: 80% of the way there
This commit includes the first three pages of the wizard, the
completion of the wizard framework with evented handling, and control
over progression.
Some shortcomings of this design have become evident: it isn't
possible to communicate between the steps' wrappers, as they are
POJOs without access to the context. An imperative decision-making
process has to be inserted in the orchestration layer,
which is kinda annoying.
But it looks good and it behaves correctly, to the extent that I've
given it behavior. It's an excellent foundation.
* Linting.
* web: application wizard
Found where the hook for form validity should go. Excellent! Now I just need to incorporate
that basic validation into the business logic and we're good to go.
* Turns out that was one layer too many; the topmost component was fine for
maintaining the context.
* It looks like my brilliant strategy has hit a snag.
The idea is simple. Let's start with this picture:
```
<application-wizard .steps=${[... a collection of step objects ...]}>
<wizard-main .steps=${(steps from above)}>
<application-current-panel>
<current-form>
```
- ApplicationWizard has a Context for the ApplicationProviderPair (or whatever it's going to be).
This context does not know about the steps; it just knows about: the "application" object, the
"provider" object, and a discriminator to know *which* provider the user has selected.
- ApplicationWizard has Steps that, among other things, provides Panels for:
- Application
- Pick Provider
- Configure Provider
- Submit ApplicationProviderPair to the back-end
- The WizardFrame renders the CurrentPanel for the CurrentStep
The CurrentPanel gets its data from the ApplicationWizard in the form of a Context. It then sends
messages (events) to ApplicationWizard about the contents of each field as the user is filling out
the form, so that the ApplicationWizard can record those in the ApplicationProviderPair for later
submission.
When a CurrentForm is valid, the ApplicationWizard updates the Steps object to show that the "Next
button" on the Wizard is now available.
In this way, the user can progress through the system. When they get to the last page, we can
provide in the ApplicationWizard with the means to submit the form and/or send the user back to
the page with the validation failure.
Problem: The context is being updated in real-time, which is triggering re-renders of the form. This
leads to focus problems as the fields that are not yet valid are triggering "focus grab" behavior.
This is a classic problem with "controlled" inputs. What we really want is for the CurrentPanel to
not re-render at all, but to behave like a normal, uncontrolled form, and let the browser do most of
the work. We still want the [Next] button to enable when the form is valid enough to permit that.
---
Other details: I've ripped out a lot of Jen's work, which is probably a mistake. It's still
preserved elsewhere. I've also cleaned up the various wizardly things to try and look organized.
It *looks* like it should work, it just... doesn't. Not yet.
* Late addition: I had an inspiration about how to reduce the way
reactivity broke focus by, basically, removing the reactivity and
managing the first-time-through lifecycle to prevent the update
from causing refocus. It works well! Now I just need to test it.
* This application fixes the bug with respect to the wizard-level context being updated incorrectly.
Understandings:
- To use uncontrolled inputs, which I prefer, the context object should not be a state or property
at the level of consumers; it should not automatically re-render with every keystroke, i.e. "The
React Way." We're using Web Components, [client-side
validation](https://developer.mozilla.org/en-US/docs/Learn/Forms/Form_validation) exists on the
platform already, and live-validation is problematic for any number of reasons.
- The trade-off is that it is now necessary to re-render the target page of the wizard de-novo, but
that's not really as big a deal as it sounds. Lit is ready to do that... and then nothing else
until we request a change-of-page. Excellent.
- The top level context *must* be a state, but it's better if it's a state never actually used by
the top-level context container. The debate about whether or not to make that container a dumb one
(`<slot></slot>`) or to merge it with the top-level object continues; here, I've merged it with
the top-level wizard object, but that object does not refer to the state variable being managed in
its render pass, so changes to it do not cause a re-render of the whole wizard. The purpose of the
top-level page is to manage the *steps*, not the *content of any step*. A step may change
dynamically based on the content of a step, but that's the same thing as *which step*. Lesson:
always know what your state is *about*.
- Deep merging is a complex subject, but here it's appropriate to our needs.
* web: Application Wizard
This commit combines a working (but very unpolished) version of the Application Wizard with Jen's
code for the CoreTransactionApplicationRequest, resulting in a successful round trip.
It fixes a number of bugs with the way ContextProducer decorators were being processed, such that
they just weren't working with our current configuration (although they did work fine in Storybook);
consumers didn't need to be fixed.
It also *removes* the steps-aware context from the Wizard.
That *may* be a mistake. To re-iterate, the `WizardFrame` provides the chrome for a Wizard: the
button bar div, the breadcrumbs div, the header div, and it takes the steps object as its source of
truth for all of the content. The `WizardContent` part of the application has two parts: The
`WizardMain`, which wraps the frame and supplies the context for all the `WizardPanels`, and the
`WizardPanels` themselves, which are dependent on a context from `WizardMain` for the data that
populates each panel. YAGNI right now that the panels need to know anything about the steps, and the
`WizardMain` can just pass a fresh `.steps` object to the `WizardFrame` when they need updating.
Using props drilling may make more sense here.
It certainy does *not* make sense for the panels. They need to be renderable on-demand, and they
need to make sense of what they're rendering on-demand, so the function is
```
(panel code) => (context) => (rendered panel)
```
(Yes, that's curried notation. Deal.)
* This commit includes the first WDIO test for the ApplicationWizard. It doesn't do much right now, but
it does log in and navigate to the wizard successfully.
* web: completed test for single application, provided new programming language to make it easier to write tests.
* Almost there.
Missing: The validation is currently not working as expected, and I cannot get the backend
to give me meaningful data helping us "go back" to the field that wasn't valid. I really
don't want to put all the meaningful validation on the front-end; that's the road to -
perdition, the back-end must be usable by people less assiduous than we are.
Also: Need to make the button bar work better; maybe each panel can provide a custom button
bar if one is needed?
* web: Test harness
We have an end-to-end test harness that includes a trivially correct DSL for "This is what a user would do, do this":
```
const deleteProvider = (theSlug) => ([
["button", '>>>ak-sidebar-item a[href="#/core/providers"]'],
["deletebox", `>>>a[href="#/core/applications/${theSlug}"]`],
["button", '>>>ak-forms-delete-bulk button[slot="trigger"]'],
["button", '>>>ak-forms-delete-bulk div[role="dialog"] ak-spinner-button'],
]);
```
It's now possible to target individual sequences of events this way. With a little creativity, we could have standalone functions that take parameters for our calls and just do them, without too much struggle.
* web: Revised navigation
After working with the navigation for awhile, I realized that it's a poor map; what I really wanted was
a controller/view pair, where events flow up to the controller and then messages on "what to draw" flow
down to the view. It work quite well, and the wizard frame is smaller and smarter for it.
I've also moved the WDIO-driven tests into the 'tests' folder, because it (a) makes more sense to put
them there, and (b) it prevents any confusion about who's in charge of node_modules.
* web: Simplify, simplify, simplify
Sort-of.
This commit changes the way the "wizard step coordinator" layer works, giving the
wizard writer much more power over button bar. It still assumes there are only
three actions the wizard frame wants to commit: next, back, and close. This empowers
the steps themselves to re-arrange their buttons and describe the rules through which
transitions occur.
* web: resetting the form is not working yet...
I vehemently dislike the object-oriented "reset" command; every wizard should start with
an absolutely fresh copy of the data upon entry. Refactoring the wizard to re-build its
content from the inside is the correct way to go, but I don't have a good mental image
of how to make the ModalButton and the component it invokes interact cleanly, which
frustrates the hell out of me.
* web: reset
As I said, I greatly dislike having to be dependent upon "resets"; I prefer my
data to be de novo going into a "new" transaction. That said, we work with
what we've got; I've created an event generated by the wizard that says the
modal just closed; anything wrapping and implementing the wizard can then
capture that event and reset the data. I've also added a pair of functions
that create the two states (what step, what form data) anew, so that resetting
is as trivial as initializing (and is exactly the same, code-wise).
* web: Without error handling, this is complete, but I still need @BeryJu (Jens)
for help with the SAML Upload (it doesn't appear to be correctly handled?) and
the error handling.
* web: revise tests for wizard
This commit replaces the previous WDIO instance with a more formal and straightforward process using
the [pageobjects](https://martinfowler.com/bliki/PageObject.html). In this form, every major
component has its own test suite, and a test is a sequence of exercises of those components.
A test then becomes something as straightforward as:
```
await LoginPage.open();
await LoginPage.login("ken@goauthentik.io", "eat10bugs");
expect(await UserLibraryPage.pageHeader).toHaveText("My Applications");
await UserLibraryPage.goToAdmin();
expect(await AdminOverviewPage.pageHeader).toHaveText("Welcome, ");
await AdminOverviewPage.openApplicationsListPage();
expect(await ApplicationsListPage.pageHeader).toHaveText("Applications");
ApplicationsListPage.startCreateApplicationWizard();
await ApplicationWizard.app.name.setValue(`Test application ${newId}`);
await ApplicationWizard.nextButton.click();
await (await ApplicationWizard.getProviderType("ldapprovider")).click();
await ApplicationWizard.nextButton.click();
await ApplicationWizard.ldap.setBindFlow("default-authentication-flow");
await ApplicationWizard.nextButton.click();
await expect(await ApplicationWizard.commitMessage).toHaveText(
"Your application has been saved"
);
```
Whether or not there's another layer of DSL in there or not, this is a pretty nice idiom for
maintaining tests.
* web: updating with forms and fixes for eslint complaints.
* web/add webdriverIO testing layer
This commit adds WebdriverIO as an end-to-end solution to unit testing. WebdriverIO can be run both
locally and remotely, supports strong integration with web components, and is generally robust for
use in pipelines. I'll confess to working through a tutorial on how to do this for web components,
and this is just chapter 2 (I think there are 5 or so chapters...).
There's a makefile, with help! If you just run `make` it tells you:
```
Specify a command. The choices are:
help Show this help
node_modules Runs `npm install` to prepare this feature
precommit Run the precommit: spell check all comments, eslint with sonarJS, prettier-write
test-good-login Test that we can log into the server. Requires a running instance of the server.
test-bad-login Test that bad usernames and passwords create appropriate error messages
```
... because Makefiles are documentation, and documentation belongs in Makefiles.
I've chosen to go with a PageObject-oriented low-level DSL; what that means is that for each major
components (a page, a form, a wizard), there's a class that provides human-readable names for
human-interactable and human-viewable objects on the page. The LoginPage object, for example, has
selectors for the username, password, submit button, and the failure alert; accessing those allows
us to test for items as expected., and to write a DSL for "a good login" that's as straightforward
as:
```
await LoginPage.open();
await LoginPage.login("ken@goauthentik.io", "eat10bugs");
await expect(UserLibraryPage.pageHeader).toHaveText("My applications");
```
There was a *lot* of messing around with the LoginPage to get the username and password into the
system. For example, I had to do this with all the `waitForClickable` and `waitForEnable` because
we both keep the buttons inaccessible until the form has something and we "black out" the page (put
a darkening filter over it) while accessing the flow, meaning there was a race condition such that
the test would attempt to interact with the username or password field before it was accessible.
But this works now, which is very nice.
``` JavaScript
get inputUsername() {
return $('>>>input[name="uidField"]');
}
get btnSubmit() {
return $('>>>button[type="submit"]');
}
async username(username: string) {
await this.inputUsername.waitForClickable();
await this.inputUsername.setValue(username);
await this.btnSubmit.waitForEnabled();
await this.btnSubmit.click();
}
```
The bells & whistles of *Prettier*, *Eslint*, and *Codespell* have also been enabled. I do like my
guardrails.
* web/adding tests: added comments and cleaned up some administrative features.
* web/test: changed the name of one test to reflect it's 'good' status
* core/allow alternative postgres credentials
This commit allows the `dev-reset` command in the Makefile to pick up and use credentials from the
`.env` file if they are present, or fallback to the defaults provided if they are not. This is the
only place in the Makefile where the database credentials are used directly against postgresql
binaries. The syntax was tested with bash, zsh, and csh, and did not fail under those.
The `$${:-}` syntax is a combination of a Makefile idiom for "Pass a single `$` to the environment
where this command will be executed," and the shell expresion `${VARIABLE:-default}` means
"dereference the environment variable; if it is undefined, used the default value provided."
* Re-arrange sequence to avoid recursive make.
Nothing wrong with recursive make; it just wasn't essential
here. `migrate` is just a build target, not a task.
* Cleanup according to the Usage:
checkmake [options] <makefile>...
checkmake -h | --help
checkmake --version
checkmake --list-rules Makefile linting tool.
* core: added 'help' to the Makefile
* get postgres config from authentik config loader
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* don't set -x by default
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* sort help
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* update help strings
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* web: test LDAP wizard sequence
* web: improve testing by adding test admin user via blueprint
* This commit continues the application wizard buildout. In this commit are the following changes:
- Added SCIM to the list of available providers
- Fixed ForwardProxy so that its mode is set correctly. (This is a special case in the committer;
I'm unhappy with that.)
- Fixed the commit messages so that:
- icons are set correctly (Success, Danger, Working)
- icons are colored correctly according to state
- commit message includes a `data-commit-state` field so tests can find it!
- Merged the application wizard tests into a single test pass
- Isolated common parts of the application wizard tests to reduce unnecessary repetition. All
application tests are the same until you reach the provider section anyway.
- Fixed the unit tests so they're finding the right error messages and are enabled to display them
correctly.
- Moved the test Form handlers into their own folder so they're not cluttering up the Pages folder.
* web: add radius to application wizard
This commit continues the application wizard buildout. In this commit are the following changes:
- Fixed a width-setting bug in the Makefile `make help` feature (i.e "automate that stuff!")
- Added Radius to the list of providers we can offer via the wizard
- Added `launchUrl` and `UI Settings` to features of the application page the wizard can find
- Changed 'SAML Manual Configuration' to just say "SAML Configuration"
- Modified `ak-form-group` to take and honor the `aria-label` property (which in turn makes it
easier to target specific forms with unit testing)
- Reduced the log level for wdio to 'warn'; 'info' was super-spammy and not helpful. It can be put
back with `--logLevel info` from the command line.
* fix blueprints
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* update package name
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* add dependabot
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* prettier run
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* add basic CI
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* remove hooks
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* web: application wizard refactor & completion
This commit refactors the various components of the Wizard and ApplicationWizard, creating a much
more maintainable and satisfying Wizard experience for both developers (i.e, *me* and *Jens* so
far), and for the customer.
The Wizard base has been refactored into three components:
**AkWizardController**
The `AkWizardController` provides the event listenters for the wizard; it hooks them up, recevies the
events, and forwards them to the wizard. It unwraps the event objects and forwards the relevant
messages contained in the events. It knows of three event categories:
- Navigation requests (move to a different step)
- Update requests (the current step has updated the business content)
- Close requests (close or cancel the wizard).
**ak-wizard-frame**
The `ak-wizard-frame` is the ModalButton interface. It provides the Header, Breadcrumbs (nee`
"navigation block"), Buttons, and a DIV into which the main content is rendered.
**AkWizard**
`AkWizard` is an *incomplete* implementation of the wizard. It's meant to be inherited by a child
class, which will implement the rest. It extends `AKElement`. It provides the basic content needed,
such as steps, currentStep (as an index), an accessor for the step itself, an accessor for the
frame, and the interface to the `AkWizardController`.
**ApplicationWizard**
The `ApplicationWizard` itself has been refactored to accommodate these changes. It inherits from
`AkWizard` and provides the business logic for what to do when a form updates, some custom logic for
preventing moving through the wizard when the forms are incomplete, and a persistence layer for
filling out different providers in the same session. It's simplified a *lot*.
The types specified for `AkWizard` are pretty nifty, I think. I could wish the types being passed
via the custom events were more robust, but [strongly typed custom
events](https://github.com/lit/lit-element/issues/808) turn out to be quite the pain in the, er,
neck. As it is, the `precommit` pass did very good at preventing the worst disasters.
The steps themselves were re-written as objects so that they could take advantage of their `valid`
and `disabled` states and provide more meaningful buttons and labels. I think it's a solid
compromise, and it moved a lot of display logic out of the core `handleUpdate()` business method.
The tests, such as they are, are passing.
* Added comment describing new test.
* web: ensuring copy from `main` is canon
* web: fixes after merge
* web: laying the groundwork for future expansion
This commit is a hodge-podge of updates and changes to the web. Functional changes:
- Makefile: Fixed a bug in the `help` section that prevented the WIDTH from being accurately
calculated if `help` was included rather than in-lined.
- ESLint: Modified the "unused vars" rule so that variables starting with an underline are not
considered by the rule. This allows for elided variables in event handlers. It's not a perfect
solution-- a better one would be to use Typescript's function-specialization typing, but there are
too many places where we elide or ignore some variables in a function's usage that switching over
to specialization would be a huge lift.
- locale: It turns out, lit-locale does its own context management. We don't need to have a context
at all in this space, and that's one less listener we need to attach t othe DOM.
- ModalButton: A small thing, but using `nothing` instead of "html``" allows lit better control over
rendering and reduces the number of actual renders of the page.
- FormGroup: Provided a means to modify the aria-label, rather than stick with the just the word
"Details." Specializing this field will both help users of screen readers in the future, and will
allow test suites to find specific form groups now.
- RadioButton: provide a more consistent interface to the RadioButton. First, we dispatch the
events to the outside world, and we set the value locally so that the current `Form.ts` continues
to behave as expected. We also prevent the "button lost value" event from propagating; this
presents a unified select-like interface to users of the RadioButtonGroup. The current value
semantics are preserved; other clients of the RadioButton do not see a change in behavior.
- EventEmitter: If the custom event detail is *not* an object, do not use the object-like semantics
for forwarding it; just send it as-is.
- Comments: In the course of laying the groundwork for the application wizard, I throw a LOT of
comments into the code, describing APIs, interfaces, class and function signatures, to better
document the behavior inside and as signposts for future work.
* web: permit arrays to be sent in custom events without interpolation.
* actually use assignValue or rather serializeFieldRecursive
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* web: eslint & prettier fixes, plus small aesthetic differences.
* Restoring this file. Not sure where it disappears to.
* fix label in dark mode
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* SCIM Manuel -> SCIM
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* fix lint errors
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* web: better converter configuration, CSS repair, and forward-domain-proxy
1. Forward Domain Proxy. I wasn't sure if this method was appropriate for the wizard,
but Jens says it is. I've added it.
2. In the process of doing so, I decided that the Provider.converter field was overly
complexified; I tried too hard to reduce the number of functions I needed to define,
but in the process outsourced some of the logic of converting the Wizard's dataset
into a property typed request to the `commit` phase, which was inappropriate. All
of the logic about a provider, aside from its display, should be here with the code
that distinguishes between providers. This commit makes it so.
3. Small CSS fix: the fields inherited from the Proxy provider forms had some unexpected
CSS which was causing a bit of a weird indent. That has been rectified.
* web: running pre-commit after merge.
* web: ensure the applications wizard tests finish after current changes
* prettier has opinions.
* web: application wizard spit & polish
The "ApplicationWizardHint" now correctly uses the localstorage and allows the user to navigate back
and see the message after it's been hidden, so that it will always be available during the test
phase.
The ApplicationList's old "Create Application Form" button has been restored for the purposes of the
test phase.
The ApplicationWizard is now available on both the ApplicationList and ProviderList pages.
Tana and I discussed the microcopy, putting a stronger second-person "You can do..." twist onto the
language, to give the user the sense of empowerment.
The ShowHintController now has both "hide" and "show" operations, to support the hint restoration.
* web: updated storybook stories for the wizard, illustration how "a simple wizard" is configured in source code and tested with storybook.
* web: I hate getting spanked by prettier.
* web: sometimes I wish I had lower standards
Anyway, this was a very stupid bug, because by definition function
definition arguments don't have uses, they're being defined, not
implemented. Fixed, conf fixed to compensate, and consequences
conquered.
* move context from labs to main
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* Revert "move context from labs to main"
This reverts commit 3718ee69048966d26b1c357a7d2653fbb3ab613b.
* web: reify the data loop
I was very unhappy with the "update this dot-path" mechanism I was using earlier; it was hard
for me to read and understand what was happening, and I wrote the darned thing. I decided instead
to go with a hard substitution model; each phase of the wizard is responsible for updating the
*entire* payload, mostly by creating a new payload and substituting the field value associated
with the event.
On the receiver, we have to do that *again* to handle the swapping of providers when the user
chooses one and then another. It looks clunky, and it is, but it's *legible*; a junior dev
could understand what it's doing, and that's the goal.
* Revert "web: reify the data loop"
This reverts commit 09fedcacf02a90a021ce9e18c0eb4bec1ef48302.
* web: revert the 'lit' to 'lit-labs' for task and context.
---------
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-10-18 19:43:37 +00:00
<trans-unit id="s2da4aa7a9abeb653">
<source>Pseudolocale (for testing)</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-19 12:53:56 +00:00
<trans-unit id="s4bd386db7302bb22">
<source>Create With Wizard</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-19 12:53:56 +00:00
<trans-unit id="s070fdfb03034ca9b">
<source>One hint, 'New Application Wizard', is currently hidden</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-19 12:53:56 +00:00
<trans-unit id="s61bd841e66966325">
<source>External applications that use authentik as an identity provider via protocols like OAuth2 and SAML. All applications are shown here, even ones you cannot access.</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-19 12:53:56 +00:00
<trans-unit id="s1cc306d8e28c4464">
<source>Deny message</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-19 12:53:56 +00:00
<trans-unit id="s6985c401e1100122">
<source>Message shown when this stage is run.</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-19 12:53:56 +00:00
<trans-unit id="s09f0c100d0ad2fec">
<source>Open Wizard</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-19 12:53:56 +00:00
<trans-unit id="sf2ef885f7d0a101d">
<source>Demo Wizard</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-19 12:53:56 +00:00
<trans-unit id="s77505ee5d2e45e53">
<source>Run the demo wizard</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-23 16:48:12 +00:00
<trans-unit id="s4498e890d47a8066">
<source>OAuth2/OIDC (Open Authorization/OpenID Connect)</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-23 16:48:12 +00:00
<trans-unit id="s4f2e195d09e2868c">
<source>LDAP (Lightweight Directory Access Protocol)</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-23 16:48:12 +00:00
<trans-unit id="s7f5bb0c9923315ed">
<source>Forward Auth (Single Application)</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-23 16:48:12 +00:00
<trans-unit id="sf8008d2d6b064b95">
<source>Forward Auth (Domain Level)</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-23 16:48:12 +00:00
<trans-unit id="sfa8a1ffa9fee07d3">
<source>SAML (Security Assertion Markup Language)</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-23 16:48:12 +00:00
<trans-unit id="s848a23972e388662">
<source>RADIUS (Remote Authentication Dial-In User Service)</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-23 16:48:12 +00:00
<trans-unit id="s3e902999ddf7b50e">
<source>SCIM (System for Cross-domain Identity Management)</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-23 16:48:12 +00:00
<trans-unit id="sdc5690be4a342985">
<source>The token has been copied to your clipboard</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-23 16:48:12 +00:00
<trans-unit id="s7f3edfee24690c9f">
<source>The token was displayed because authentik does not have permission to write to the clipboard</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-23 16:48:12 +00:00
<trans-unit id="saf6097bfa25205b8">
<source>A copy of this recovery link has been placed in your clipboard</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-23 16:48:12 +00:00
<trans-unit id="s895514dda9cb9c94">
<source>Create recovery link</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-23 16:48:12 +00:00
<trans-unit id="se5c795faf2c07514">
<source>Create Recovery Link</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2023-10-25 16:25:37 +00:00
<trans-unit id="s84fcddede27b8e2a">
<source>External</source>
2023-10-08 22:08:16 +00:00
</trans-unit>
2023-10-25 16:25:37 +00:00
<trans-unit id="s1a635369edaf4dc3">
<source>Service account</source>
2023-10-16 15:31:50 +00:00
</trans-unit>
2023-10-25 16:25:37 +00:00
<trans-unit id="sff930bf2834e2201">
<source>Service account (internal)</source>
2023-10-16 15:31:50 +00:00
</trans-unit>
2023-10-25 16:25:37 +00:00
<trans-unit id="s66313b45b69cfc88">
<source>Check the release notes</source>
2023-10-16 15:31:50 +00:00
</trans-unit>
2023-10-25 16:25:37 +00:00
<trans-unit id="sb4d7bae2440d9781">
<source>User Statistics</source>
2023-10-16 15:31:50 +00:00
</trans-unit>
2023-10-25 16:25:37 +00:00
<trans-unit id="s0924f51b028233a3">
<source><No name set></source>
2023-10-16 15:31:50 +00:00
</trans-unit>
2023-10-27 09:39:39 +00:00
<trans-unit id="sdc9a6ad1af30572c">
<source>For nginx's auth_request or traefik's forwardAuth</source>
2023-10-16 15:31:50 +00:00
</trans-unit>
2023-10-27 09:39:39 +00:00
<trans-unit id="sfc31264ef7ff86ef">
<source>For nginx's auth_request or traefik's forwardAuth per root domain</source>
2023-10-16 15:31:50 +00:00
</trans-unit>
2023-10-27 09:39:39 +00:00
<trans-unit id="sc615309d10a9228c">
<source>RBAC is in preview.</source>
2023-10-16 15:31:50 +00:00
</trans-unit>
2023-10-27 09:39:39 +00:00
<trans-unit id="s32babfed740fd3c1">
<source>User type used for newly created users.</source>
2023-10-16 15:31:50 +00:00
</trans-unit>
2023-11-06 12:51:41 +00:00
<trans-unit id="s4a34a6be4c68ec87">
<source>Users created</source>
2023-10-16 15:31:50 +00:00
</trans-unit>
2023-11-06 12:51:41 +00:00
<trans-unit id="s275c956687e2e656">
<source>Failed logins</source>
2023-10-16 15:31:50 +00:00
</trans-unit>
2023-11-14 12:05:18 +00:00
<trans-unit id="sb35c08e3a541188f">
<source>Also known as Client ID.</source>
2023-10-16 15:31:50 +00:00
</trans-unit>
2023-11-14 12:05:18 +00:00
<trans-unit id="sd46fd9b647cfea10">
<source>Also known as Client Secret.</source>
2023-10-16 15:31:50 +00:00
</trans-unit>
2023-11-14 12:05:18 +00:00
<trans-unit id="s4476e9c50cfd13f4">
<source>Global status</source>
2023-10-16 15:31:50 +00:00
</trans-unit>
2023-11-14 12:05:18 +00:00
<trans-unit id="sd21a971eea208533">
<source>Vendor</source>
2023-10-16 15:31:50 +00:00
</trans-unit>
2023-11-14 12:05:18 +00:00
<trans-unit id="sadadfe9dfa06d7dd">
<source>No sync status.</source>
2023-10-16 15:31:50 +00:00
</trans-unit>
2023-11-14 12:05:18 +00:00
<trans-unit id="s2b1c81130a65a55b">
<source>Sync currently running.</source>
2023-10-16 15:31:50 +00:00
</trans-unit>
2023-11-14 12:05:18 +00:00
<trans-unit id="sf36170f71cea38c2">
<source>Connectivity</source>
web: Application wizard v2 with tests (#7004)
* A lot of comments about forms.
* Adding comments to the wizard.
* Broke out the text input into a single renderer. Still works as required.
* web: Legibility in the ApplicationForm.
This is a pretty good result. By using the LightDOM setting, this
provides the existing Authentik form manager with access to the
ak-form-horizontal-element components without having to do any
cross-border magic. It's not ideal, and it shows up just how badly
we've got patternfly splattered everywhere, but the actual results
are remarkable. The patterns for text, switch, radio, textarea,
file, and even select are smaller and easier here.
I'm still noodling on what an unspread search-select element would
look like. It's just dependency injection, so it ought to be as
straightforward as that.
* web: Marking down the start of the 'components' library.
* web: Baby steps
I become frustrated with my inability to make any progress on this project, so I decided to reach
for a tool that I consider highly reliable but also incredibly time-consuming and boring: test
driven development.
In this case, I wrote a story about how I wanted to see the first page rendered: just put the HTML
tag, completely unadorned, that will handle the first page of the wizard. Then, add an event handler
that will send the updated content to some parent object, since what we really want is to
orchestrate the state of the user's input with a centralized location. Then, rather than fiddling
with the attributes and properties of the various pages, I wanted them to be able to "look up" the
values they want, much as we'd expect a standalone form to be able to pull its values from the
server, so I added a context object that receives the update event and incorporates the new
knowledge about the state of the process into itself.
The result is surprisingly satisfying: the first page renders cleanly, displays the content that we
want, and as we fiddle with, we can *watch in real time* as the results of the context are updated
and retransmitted to all receiving objects. And the sending object gets the results so it
re-renders, but it ends up looking the same as it was before the render.
* Now, it's starting to look like a complete package. The LDAP method is working, but there is a bug:
the radio is sending the wrong value !?!?!?. Track that down, dammit. The search wrappers now resend
their events as standard `input` events, and that actually seems to work well; the browser is
decorating it with the right target, with the right `name` attribute, and since we have good
definitions of the `value` as a string (the real value of any search object is its UUID4), that
works quite well. Added search wrappers for CoreGroup and CryptoCertificate (CertificateKeyPairs),
and the latter has flags for "use the first one if it's the only one" and "allow the display of
keyless certificates."
Not sure why `state()` is blocking the transmission of typing information from the typed element
to the context handler, but it's a bug in the typechecker, and it's not a problem so far.
* Now, it's starting to look like a complete package. The LDAP method is working, but there is a bug:
the radio is sending the wrong value !?!?!?. Track that down, dammit. The search wrappers now resend
their events as standard `input` events, and that actually seems to work well; the browser is
decorating it with the right target, with the right `name` attribute, and since we have good
definitions of the `value` as a string (the real value of any search object is its UUID4), that
works quite well. Added search wrappers for CoreGroup and CryptoCertificate (CertificateKeyPairs),
and the latter has flags for "use the first one if it's the only one" and "allow the display of
keyless certificates."
Not sure why `state()` is blocking the transmission of typing information from the typed element
to the context handler, but it's a bug in the typechecker, and it's not a problem so far.
* web: tracked down that weirld bug with the radio.
Because radio inputs are actually multiples, the events handling for
radio is... wonky. If we want our `<ak-radio>` component to be a
unitary event dispatcher, saying "This is the element selected," we
needed to do more than what was currently being handled.
I've intercepted the events that we care about and have placed
them into a controller that dictates both the setting and the
re-render of the component. This makes it "controlled" (to use the
Angular/React/Vue) language and depends on Lit's reactiveElement
lifecycle to work, rather than trust the browser, but the browser's
experience with respect to the `<input type=radio` is pretty bad:
both input elements fire events, one for "losing selection" and
one for "gaining selection". That can be very confusing to handle,
so we funnel them down in our aggregate radio element to a single
event, "selection changed".
As a quality-of-life measure, I've also set the label to be
unselectable; this means that a click on the label will trigger the
selection event, and a long click will not disable selection or
confuse the selection event generator.
* web: now passing the precommit phase
* web: a HACK for Storybook to inject the "use light theme" flag into the body.
This isn't really a very good hack; what it does is say that every story is
responsible for hacking its theme into the parent. This is very annoying, but
it does mean that we can at least show our components in the best light.
* web: ak-application-wizard-authentication-by-oauth, and many fixes!
1. Fixed `eventEmitter` so that if the detail object is a scalar, it will not attempt to "objectify"
it. This was causing a bug where retrofitting the eventEmitter to some older components resulted
in a detail of "some" being translated into ['s', 'o', 'm', 'e']. Not what is wanted.
2. Removed the "transitional form" from the existing components; they had a two-step where the web
component class was just a wrapper around an independent rendering function. While this worked,
it was only to make the case that they *were* independent rendering objects and could be
supported with the right web component framework. We're halfway there now; the last step will be
to transform the horizontal-element and various input CSS into componentized CSS, the way
Patternfly-Elements is currently doing.
3. Fixed the `help` field so that it could take a string or a TemplateResult, and if the latter,
don't bother wrapping it in the helper text functionality; just let it be its own thing. This
supports the multi-line help of redirectURI as well as the `ak-utils-time-delta` capability.
4. Transform Oauth2ProviderForm to use the new components, to the best of our ability. Also used
the `provider = this.wizard.provider` and `provider = this.instance` syntax to make the render
function *completely portable*; it's the exact same text that is dropped into...
5. The complete `ak-application-wizard-authentication-by-oauth` component. They're so similar part
of me wonders if I could push them both out to a common reference, or a collection of common
references. Both components use the PropertyMapping and Sources, and both use the same
collection of searches (Crypto, Flow).
6. A Storybook for `ak-application-wizard-authentication-by-oauth`, showing the works working.
7. New mocks for `authorizationFlow`, `propertyMappings`, and `hasJWKs`.
This sequence has revealed a bug in the radio control. (It's always the radio control.) If the
default doesn't match the current setting, the radio control doesn't behave as expected; it won't
change when you fully expect that it should. I'll investigate how to harmonize those tomorrow.
* web: Converted our toggle groups to a more streamlined implementation.
* web: one more toggle group.
* initial api and schema
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* separate blueprint importer from yaml parsing
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* cleanup
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* web: Replace ad-hoc toggle control with ak-toggle-group
This commit replaces various ad-hoc implementations of the Patternfly Toggle Group HTML with a web
component that encapsulates all of the needed behavior and exposes a single API with a single event
handler, return the value of the option clicked.
The results are: Lots of visual clutter is eliminated. A single link of:
```
<div class="pf-c-toggle-group__item">
<button
class="pf-c-toggle-group__button ${this.mode === ProxyMode.Proxy
? "pf-m-selected"
: ""}"
type="button"
@click=${() => {
this.mode = ProxyMode.Proxy;
}}>
<span class="pf-c-toggle-group__text">${msg("Proxy")}</span>
</button>
</div>
<div class="pf-c-divider pf-m-vertical" role="separator"></div>
```
Now looks like:
```
<option value=${ProxyMode.Proxy}>${msg("Proxy")}</option>
```
This also means that the three pages that used the Patternfly Toggle Group could eliminate all of
their Patternfly PFToggleGroup needs, as well as the `justify-content: center` extension, which also
eliminated the `css` import.
The savings aren't as spectacular as I'd hoped: removed 178 lines, but added 123; total savings 55
lines of code. I still count this a win: we need never write another toggle component again, and
any bugs, extensions or features we may want to add can be centralized or forked without risking the
whole edifice.
* web: minor code formatting issue.
* add new "must_created" state to blueprints to prevent overwriting objects
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* web: adding a storybook for the ak-toggle-group component
* Bugs found by CI/CD.
* web: Replace ad-hoc search for CryptoCertificateKeyPairs with ak-crypto-certeficate-search
This commit replaces various ad-hoc implementations of `search-select` for CryptoCertificateKeyPairs
with a web component that encapsulates all of the needed behavior and exposes a single API.
The results are: Lots of visual clutter is eliminated. A single search of:
```HTML
<ak-search-select
.fetchObjects=${async (query?: string): Promise<CertificateKeyPair[]> => {
const args: CryptoCertificatekeypairsListRequest = {
ordering: "name",
hasKey: true,
includeDetails: false,
};
if (query !== undefined) {
args.search = query;
}
const certificates = await new CryptoApi(
DEFAULT_CONFIG,
).cryptoCertificatekeypairsList(args);
return certificates.results;
}}
.renderElement=${(item: CertificateKeyPair): string => {
return item.name;
}}
.value=${(item: CertificateKeyPair | undefined): string | undefined => {
return item?.pk;
}}
.selected=${(item: CertificateKeyPair): boolean => {
return this.instance?.tlsVerification === item.pk;
}}
?blankable=${true}
>
</ak-search-select>
```
Now looks like:
```HTML
<ak-crypto-certificate-search certificate=${this.instance?.tlsVerification}>
</ak-crypto-certificate-search>
```
There are three searches that do not require there to be a valid key with the certificate; these are
supported with the boolean property `nokey`; likewise, there is one search (in SAMLProviderForm)
that states that if there is no current certificate in the SAMLProvider and only one certificate can
be found in the Authentik database, use that one; this is supported with the boolean property
`singleton`.
These changes replace 382 lines of object-oriented invocations with 36 lines of declarative
configuration, and 98 lines for the class. Overall, the code for "find a crypto certificate" has
been reduced by 46%.
Suggestions for a better word than `singleton` are welcome!
* web: display tests for CryptoCertificateKeypair search
This adds a Storybook for the CryptoCertificateKeypair search, including
a mock fetch of the data. In the course of running the tests, we discovered
that including the SearchSelect _class_ won't include the customElement declaration
unless you include the whole file! Other bugs found: including the CSS from
Storybook is different from that of LitElement native, so much so that the
adapter needed to be included. FlowSearch had a similar bug. The problem
only manifests when building via Webpack (which Storybook uses) and not
Rollup, but we should support both in distribution.
* Fixed behavioral problem with the radio; the `if` there was
preventing the radio from reflecting the default correctly.
The observed behavior was that the radio wouldn't "activate"
until the item selected during the render pass was clicked on
first.
* Proxy Provider done.
* web: Tactical change. Put all the variants on the second page; it's
a longer list, but it's also easier to manage than all those
required sub-options.
* Rounding out the catalog.
* web: SAML Manual Configuration
Added a 'design document' that just kinda describes what I'm trying
to do, in case I don't get this done by Friday Aug 11, 2023.
I had two tables doing the same thing, so I merged them and then
wrote a few map/filters to specialize them for those two use cases.
Along the way I had to fiddle with the ESLint settings so that
underscore-prefixed unused variables would be ignored.
I cleaned up the visual appeal of the forms in the LDAP application.
I was copy/pasting the "handleProviderEvent" function, so I pulled
it out into ApplicationWizardProviderPageBase. Not so much a matter
of abstraction as just disliking that kind of duplication; it served
no purpose.
* Added SAML Story to Storybook.
* Web: This is coming together amazingly well. Like, almost too well.
* web: 80% of the way there
This commit includes the first three pages of the wizard, the
completion of the wizard framework with evented handling, and control
over progression.
Some shortcomings of this design have become evident: it isn't
possible to communicate between the steps' wrappers, as they are
POJOs without access to the context. An imperative decision-making
process has to be inserted in the orchestration layer,
which is kinda annoying.
But it looks good and it behaves correctly, to the extent that I've
given it behavior. It's an excellent foundation.
* Linting.
* web: application wizard
Found where the hook for form validity should go. Excellent! Now I just need to incorporate
that basic validation into the business logic and we're good to go.
* Turns out that was one layer too many; the topmost component was fine for
maintaining the context.
* It looks like my brilliant strategy has hit a snag.
The idea is simple. Let's start with this picture:
```
<application-wizard .steps=${[... a collection of step objects ...]}>
<wizard-main .steps=${(steps from above)}>
<application-current-panel>
<current-form>
```
- ApplicationWizard has a Context for the ApplicationProviderPair (or whatever it's going to be).
This context does not know about the steps; it just knows about: the "application" object, the
"provider" object, and a discriminator to know *which* provider the user has selected.
- ApplicationWizard has Steps that, among other things, provides Panels for:
- Application
- Pick Provider
- Configure Provider
- Submit ApplicationProviderPair to the back-end
- The WizardFrame renders the CurrentPanel for the CurrentStep
The CurrentPanel gets its data from the ApplicationWizard in the form of a Context. It then sends
messages (events) to ApplicationWizard about the contents of each field as the user is filling out
the form, so that the ApplicationWizard can record those in the ApplicationProviderPair for later
submission.
When a CurrentForm is valid, the ApplicationWizard updates the Steps object to show that the "Next
button" on the Wizard is now available.
In this way, the user can progress through the system. When they get to the last page, we can
provide in the ApplicationWizard with the means to submit the form and/or send the user back to
the page with the validation failure.
Problem: The context is being updated in real-time, which is triggering re-renders of the form. This
leads to focus problems as the fields that are not yet valid are triggering "focus grab" behavior.
This is a classic problem with "controlled" inputs. What we really want is for the CurrentPanel to
not re-render at all, but to behave like a normal, uncontrolled form, and let the browser do most of
the work. We still want the [Next] button to enable when the form is valid enough to permit that.
---
Other details: I've ripped out a lot of Jen's work, which is probably a mistake. It's still
preserved elsewhere. I've also cleaned up the various wizardly things to try and look organized.
It *looks* like it should work, it just... doesn't. Not yet.
* Late addition: I had an inspiration about how to reduce the way
reactivity broke focus by, basically, removing the reactivity and
managing the first-time-through lifecycle to prevent the update
from causing refocus. It works well! Now I just need to test it.
* This application fixes the bug with respect to the wizard-level context being updated incorrectly.
Understandings:
- To use uncontrolled inputs, which I prefer, the context object should not be a state or property
at the level of consumers; it should not automatically re-render with every keystroke, i.e. "The
React Way." We're using Web Components, [client-side
validation](https://developer.mozilla.org/en-US/docs/Learn/Forms/Form_validation) exists on the
platform already, and live-validation is problematic for any number of reasons.
- The trade-off is that it is now necessary to re-render the target page of the wizard de-novo, but
that's not really as big a deal as it sounds. Lit is ready to do that... and then nothing else
until we request a change-of-page. Excellent.
- The top level context *must* be a state, but it's better if it's a state never actually used by
the top-level context container. The debate about whether or not to make that container a dumb one
(`<slot></slot>`) or to merge it with the top-level object continues; here, I've merged it with
the top-level wizard object, but that object does not refer to the state variable being managed in
its render pass, so changes to it do not cause a re-render of the whole wizard. The purpose of the
top-level page is to manage the *steps*, not the *content of any step*. A step may change
dynamically based on the content of a step, but that's the same thing as *which step*. Lesson:
always know what your state is *about*.
- Deep merging is a complex subject, but here it's appropriate to our needs.
* web: Application Wizard
This commit combines a working (but very unpolished) version of the Application Wizard with Jen's
code for the CoreTransactionApplicationRequest, resulting in a successful round trip.
It fixes a number of bugs with the way ContextProducer decorators were being processed, such that
they just weren't working with our current configuration (although they did work fine in Storybook);
consumers didn't need to be fixed.
It also *removes* the steps-aware context from the Wizard.
That *may* be a mistake. To re-iterate, the `WizardFrame` provides the chrome for a Wizard: the
button bar div, the breadcrumbs div, the header div, and it takes the steps object as its source of
truth for all of the content. The `WizardContent` part of the application has two parts: The
`WizardMain`, which wraps the frame and supplies the context for all the `WizardPanels`, and the
`WizardPanels` themselves, which are dependent on a context from `WizardMain` for the data that
populates each panel. YAGNI right now that the panels need to know anything about the steps, and the
`WizardMain` can just pass a fresh `.steps` object to the `WizardFrame` when they need updating.
Using props drilling may make more sense here.
It certainy does *not* make sense for the panels. They need to be renderable on-demand, and they
need to make sense of what they're rendering on-demand, so the function is
```
(panel code) => (context) => (rendered panel)
```
(Yes, that's curried notation. Deal.)
* This commit includes the first WDIO test for the ApplicationWizard. It doesn't do much right now, but
it does log in and navigate to the wizard successfully.
* web: completed test for single application, provided new programming language to make it easier to write tests.
* Almost there.
Missing: The validation is currently not working as expected, and I cannot get the backend
to give me meaningful data helping us "go back" to the field that wasn't valid. I really
don't want to put all the meaningful validation on the front-end; that's the road to -
perdition, the back-end must be usable by people less assiduous than we are.
Also: Need to make the button bar work better; maybe each panel can provide a custom button
bar if one is needed?
* web: Test harness
We have an end-to-end test harness that includes a trivially correct DSL for "This is what a user would do, do this":
```
const deleteProvider = (theSlug) => ([
["button", '>>>ak-sidebar-item a[href="#/core/providers"]'],
["deletebox", `>>>a[href="#/core/applications/${theSlug}"]`],
["button", '>>>ak-forms-delete-bulk button[slot="trigger"]'],
["button", '>>>ak-forms-delete-bulk div[role="dialog"] ak-spinner-button'],
]);
```
It's now possible to target individual sequences of events this way. With a little creativity, we could have standalone functions that take parameters for our calls and just do them, without too much struggle.
* web: Revised navigation
After working with the navigation for awhile, I realized that it's a poor map; what I really wanted was
a controller/view pair, where events flow up to the controller and then messages on "what to draw" flow
down to the view. It work quite well, and the wizard frame is smaller and smarter for it.
I've also moved the WDIO-driven tests into the 'tests' folder, because it (a) makes more sense to put
them there, and (b) it prevents any confusion about who's in charge of node_modules.
* web: Simplify, simplify, simplify
Sort-of.
This commit changes the way the "wizard step coordinator" layer works, giving the
wizard writer much more power over button bar. It still assumes there are only
three actions the wizard frame wants to commit: next, back, and close. This empowers
the steps themselves to re-arrange their buttons and describe the rules through which
transitions occur.
* web: resetting the form is not working yet...
I vehemently dislike the object-oriented "reset" command; every wizard should start with
an absolutely fresh copy of the data upon entry. Refactoring the wizard to re-build its
content from the inside is the correct way to go, but I don't have a good mental image
of how to make the ModalButton and the component it invokes interact cleanly, which
frustrates the hell out of me.
* web: reset
As I said, I greatly dislike having to be dependent upon "resets"; I prefer my
data to be de novo going into a "new" transaction. That said, we work with
what we've got; I've created an event generated by the wizard that says the
modal just closed; anything wrapping and implementing the wizard can then
capture that event and reset the data. I've also added a pair of functions
that create the two states (what step, what form data) anew, so that resetting
is as trivial as initializing (and is exactly the same, code-wise).
* web: Without error handling, this is complete, but I still need @BeryJu (Jens)
for help with the SAML Upload (it doesn't appear to be correctly handled?) and
the error handling.
* web: revise tests for wizard
This commit replaces the previous WDIO instance with a more formal and straightforward process using
the [pageobjects](https://martinfowler.com/bliki/PageObject.html). In this form, every major
component has its own test suite, and a test is a sequence of exercises of those components.
A test then becomes something as straightforward as:
```
await LoginPage.open();
await LoginPage.login("ken@goauthentik.io", "eat10bugs");
expect(await UserLibraryPage.pageHeader).toHaveText("My Applications");
await UserLibraryPage.goToAdmin();
expect(await AdminOverviewPage.pageHeader).toHaveText("Welcome, ");
await AdminOverviewPage.openApplicationsListPage();
expect(await ApplicationsListPage.pageHeader).toHaveText("Applications");
ApplicationsListPage.startCreateApplicationWizard();
await ApplicationWizard.app.name.setValue(`Test application ${newId}`);
await ApplicationWizard.nextButton.click();
await (await ApplicationWizard.getProviderType("ldapprovider")).click();
await ApplicationWizard.nextButton.click();
await ApplicationWizard.ldap.setBindFlow("default-authentication-flow");
await ApplicationWizard.nextButton.click();
await expect(await ApplicationWizard.commitMessage).toHaveText(
"Your application has been saved"
);
```
Whether or not there's another layer of DSL in there or not, this is a pretty nice idiom for
maintaining tests.
* web: updating with forms and fixes for eslint complaints.
* web/add webdriverIO testing layer
This commit adds WebdriverIO as an end-to-end solution to unit testing. WebdriverIO can be run both
locally and remotely, supports strong integration with web components, and is generally robust for
use in pipelines. I'll confess to working through a tutorial on how to do this for web components,
and this is just chapter 2 (I think there are 5 or so chapters...).
There's a makefile, with help! If you just run `make` it tells you:
```
Specify a command. The choices are:
help Show this help
node_modules Runs `npm install` to prepare this feature
precommit Run the precommit: spell check all comments, eslint with sonarJS, prettier-write
test-good-login Test that we can log into the server. Requires a running instance of the server.
test-bad-login Test that bad usernames and passwords create appropriate error messages
```
... because Makefiles are documentation, and documentation belongs in Makefiles.
I've chosen to go with a PageObject-oriented low-level DSL; what that means is that for each major
components (a page, a form, a wizard), there's a class that provides human-readable names for
human-interactable and human-viewable objects on the page. The LoginPage object, for example, has
selectors for the username, password, submit button, and the failure alert; accessing those allows
us to test for items as expected., and to write a DSL for "a good login" that's as straightforward
as:
```
await LoginPage.open();
await LoginPage.login("ken@goauthentik.io", "eat10bugs");
await expect(UserLibraryPage.pageHeader).toHaveText("My applications");
```
There was a *lot* of messing around with the LoginPage to get the username and password into the
system. For example, I had to do this with all the `waitForClickable` and `waitForEnable` because
we both keep the buttons inaccessible until the form has something and we "black out" the page (put
a darkening filter over it) while accessing the flow, meaning there was a race condition such that
the test would attempt to interact with the username or password field before it was accessible.
But this works now, which is very nice.
``` JavaScript
get inputUsername() {
return $('>>>input[name="uidField"]');
}
get btnSubmit() {
return $('>>>button[type="submit"]');
}
async username(username: string) {
await this.inputUsername.waitForClickable();
await this.inputUsername.setValue(username);
await this.btnSubmit.waitForEnabled();
await this.btnSubmit.click();
}
```
The bells & whistles of *Prettier*, *Eslint*, and *Codespell* have also been enabled. I do like my
guardrails.
* web/adding tests: added comments and cleaned up some administrative features.
* web/test: changed the name of one test to reflect it's 'good' status
* core/allow alternative postgres credentials
This commit allows the `dev-reset` command in the Makefile to pick up and use credentials from the
`.env` file if they are present, or fallback to the defaults provided if they are not. This is the
only place in the Makefile where the database credentials are used directly against postgresql
binaries. The syntax was tested with bash, zsh, and csh, and did not fail under those.
The `$${:-}` syntax is a combination of a Makefile idiom for "Pass a single `$` to the environment
where this command will be executed," and the shell expresion `${VARIABLE:-default}` means
"dereference the environment variable; if it is undefined, used the default value provided."
* Re-arrange sequence to avoid recursive make.
Nothing wrong with recursive make; it just wasn't essential
here. `migrate` is just a build target, not a task.
* Cleanup according to the Usage:
checkmake [options] <makefile>...
checkmake -h | --help
checkmake --version
checkmake --list-rules Makefile linting tool.
* core: added 'help' to the Makefile
* get postgres config from authentik config loader
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* don't set -x by default
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* sort help
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* update help strings
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* web: test LDAP wizard sequence
* web: improve testing by adding test admin user via blueprint
* This commit continues the application wizard buildout. In this commit are the following changes:
- Added SCIM to the list of available providers
- Fixed ForwardProxy so that its mode is set correctly. (This is a special case in the committer;
I'm unhappy with that.)
- Fixed the commit messages so that:
- icons are set correctly (Success, Danger, Working)
- icons are colored correctly according to state
- commit message includes a `data-commit-state` field so tests can find it!
- Merged the application wizard tests into a single test pass
- Isolated common parts of the application wizard tests to reduce unnecessary repetition. All
application tests are the same until you reach the provider section anyway.
- Fixed the unit tests so they're finding the right error messages and are enabled to display them
correctly.
- Moved the test Form handlers into their own folder so they're not cluttering up the Pages folder.
* web: add radius to application wizard
This commit continues the application wizard buildout. In this commit are the following changes:
- Fixed a width-setting bug in the Makefile `make help` feature (i.e "automate that stuff!")
- Added Radius to the list of providers we can offer via the wizard
- Added `launchUrl` and `UI Settings` to features of the application page the wizard can find
- Changed 'SAML Manual Configuration' to just say "SAML Configuration"
- Modified `ak-form-group` to take and honor the `aria-label` property (which in turn makes it
easier to target specific forms with unit testing)
- Reduced the log level for wdio to 'warn'; 'info' was super-spammy and not helpful. It can be put
back with `--logLevel info` from the command line.
* fix blueprints
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* update package name
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* add dependabot
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* prettier run
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* add basic CI
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* remove hooks
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* web: application wizard refactor & completion
This commit refactors the various components of the Wizard and ApplicationWizard, creating a much
more maintainable and satisfying Wizard experience for both developers (i.e, *me* and *Jens* so
far), and for the customer.
The Wizard base has been refactored into three components:
**AkWizardController**
The `AkWizardController` provides the event listenters for the wizard; it hooks them up, recevies the
events, and forwards them to the wizard. It unwraps the event objects and forwards the relevant
messages contained in the events. It knows of three event categories:
- Navigation requests (move to a different step)
- Update requests (the current step has updated the business content)
- Close requests (close or cancel the wizard).
**ak-wizard-frame**
The `ak-wizard-frame` is the ModalButton interface. It provides the Header, Breadcrumbs (nee`
"navigation block"), Buttons, and a DIV into which the main content is rendered.
**AkWizard**
`AkWizard` is an *incomplete* implementation of the wizard. It's meant to be inherited by a child
class, which will implement the rest. It extends `AKElement`. It provides the basic content needed,
such as steps, currentStep (as an index), an accessor for the step itself, an accessor for the
frame, and the interface to the `AkWizardController`.
**ApplicationWizard**
The `ApplicationWizard` itself has been refactored to accommodate these changes. It inherits from
`AkWizard` and provides the business logic for what to do when a form updates, some custom logic for
preventing moving through the wizard when the forms are incomplete, and a persistence layer for
filling out different providers in the same session. It's simplified a *lot*.
The types specified for `AkWizard` are pretty nifty, I think. I could wish the types being passed
via the custom events were more robust, but [strongly typed custom
events](https://github.com/lit/lit-element/issues/808) turn out to be quite the pain in the, er,
neck. As it is, the `precommit` pass did very good at preventing the worst disasters.
The steps themselves were re-written as objects so that they could take advantage of their `valid`
and `disabled` states and provide more meaningful buttons and labels. I think it's a solid
compromise, and it moved a lot of display logic out of the core `handleUpdate()` business method.
The tests, such as they are, are passing.
* Added comment describing new test.
* web: ensuring copy from `main` is canon
* web: fixes after merge
* web: laying the groundwork for future expansion
This commit is a hodge-podge of updates and changes to the web. Functional changes:
- Makefile: Fixed a bug in the `help` section that prevented the WIDTH from being accurately
calculated if `help` was included rather than in-lined.
- ESLint: Modified the "unused vars" rule so that variables starting with an underline are not
considered by the rule. This allows for elided variables in event handlers. It's not a perfect
solution-- a better one would be to use Typescript's function-specialization typing, but there are
too many places where we elide or ignore some variables in a function's usage that switching over
to specialization would be a huge lift.
- locale: It turns out, lit-locale does its own context management. We don't need to have a context
at all in this space, and that's one less listener we need to attach t othe DOM.
- ModalButton: A small thing, but using `nothing` instead of "html``" allows lit better control over
rendering and reduces the number of actual renders of the page.
- FormGroup: Provided a means to modify the aria-label, rather than stick with the just the word
"Details." Specializing this field will both help users of screen readers in the future, and will
allow test suites to find specific form groups now.
- RadioButton: provide a more consistent interface to the RadioButton. First, we dispatch the
events to the outside world, and we set the value locally so that the current `Form.ts` continues
to behave as expected. We also prevent the "button lost value" event from propagating; this
presents a unified select-like interface to users of the RadioButtonGroup. The current value
semantics are preserved; other clients of the RadioButton do not see a change in behavior.
- EventEmitter: If the custom event detail is *not* an object, do not use the object-like semantics
for forwarding it; just send it as-is.
- Comments: In the course of laying the groundwork for the application wizard, I throw a LOT of
comments into the code, describing APIs, interfaces, class and function signatures, to better
document the behavior inside and as signposts for future work.
* web: permit arrays to be sent in custom events without interpolation.
* actually use assignValue or rather serializeFieldRecursive
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* web: eslint & prettier fixes, plus small aesthetic differences.
* Restoring this file. Not sure where it disappears to.
* fix label in dark mode
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* SCIM Manuel -> SCIM
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* fix lint errors
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* web: better converter configuration, CSS repair, and forward-domain-proxy
1. Forward Domain Proxy. I wasn't sure if this method was appropriate for the wizard,
but Jens says it is. I've added it.
2. In the process of doing so, I decided that the Provider.converter field was overly
complexified; I tried too hard to reduce the number of functions I needed to define,
but in the process outsourced some of the logic of converting the Wizard's dataset
into a property typed request to the `commit` phase, which was inappropriate. All
of the logic about a provider, aside from its display, should be here with the code
that distinguishes between providers. This commit makes it so.
3. Small CSS fix: the fields inherited from the Proxy provider forms had some unexpected
CSS which was causing a bit of a weird indent. That has been rectified.
* web: running pre-commit after merge.
* web: ensure the applications wizard tests finish after current changes
* prettier has opinions.
* web: application wizard spit & polish
The "ApplicationWizardHint" now correctly uses the localstorage and allows the user to navigate back
and see the message after it's been hidden, so that it will always be available during the test
phase.
The ApplicationList's old "Create Application Form" button has been restored for the purposes of the
test phase.
The ApplicationWizard is now available on both the ApplicationList and ProviderList pages.
Tana and I discussed the microcopy, putting a stronger second-person "You can do..." twist onto the
language, to give the user the sense of empowerment.
The ShowHintController now has both "hide" and "show" operations, to support the hint restoration.
* web: updated storybook stories for the wizard, illustration how "a simple wizard" is configured in source code and tested with storybook.
* web: I hate getting spanked by prettier.
* web: sometimes I wish I had lower standards
Anyway, this was a very stupid bug, because by definition function
definition arguments don't have uses, they're being defined, not
implemented. Fixed, conf fixed to compensate, and consequences
conquered.
* move context from labs to main
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* Revert "move context from labs to main"
This reverts commit 3718ee69048966d26b1c357a7d2653fbb3ab613b.
* web: reify the data loop
I was very unhappy with the "update this dot-path" mechanism I was using earlier; it was hard
for me to read and understand what was happening, and I wrote the darned thing. I decided instead
to go with a hard substitution model; each phase of the wizard is responsible for updating the
*entire* payload, mostly by creating a new payload and substituting the field value associated
with the event.
On the receiver, we have to do that *again* to handle the swapping of providers when the user
chooses one and then another. It looks clunky, and it is, but it's *legible*; a junior dev
could understand what it's doing, and that's the goal.
* Revert "web: reify the data loop"
This reverts commit 09fedcacf02a90a021ce9e18c0eb4bec1ef48302.
* web: revert the 'lit' to 'lit-labs' for task and context.
---------
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-10-18 19:43:37 +00:00
</trans-unit>
2023-11-15 15:28:56 +00:00
<trans-unit id="sd94e99af8b41ff54">
<source>0: Too guessable: risky password. (guesses &lt; 10^3)</source>
2023-10-19 12:53:56 +00:00
</trans-unit>
2023-11-15 15:28:56 +00:00
<trans-unit id="sc926385d1a624c3a">
<source>1: Very guessable: protection from throttled online attacks. (guesses &lt; 10^6)</source>
2023-10-19 12:53:56 +00:00
</trans-unit>
2023-11-15 15:28:56 +00:00
<trans-unit id="s8aae61c41319602c">
<source>2: Somewhat guessable: protection from unthrottled online attacks. (guesses &lt; 10^8)</source>
2023-10-19 12:53:56 +00:00
</trans-unit>
2023-11-15 15:28:56 +00:00
<trans-unit id="sc1f4b57e722a89d6">
<source>3: Safely unguessable: moderate protection from offline slow-hash scenario. (guesses &lt; 10^10)</source>
2023-10-19 12:53:56 +00:00
</trans-unit>
2023-11-15 15:28:56 +00:00
<trans-unit id="sd47f3d3c9741343d">
<source>4: Very unguessable: strong protection from offline slow-hash scenario. (guesses &gt;= 10^10)</source>
2023-10-19 12:53:56 +00:00
</trans-unit>
2023-11-15 22:14:30 +00:00
<trans-unit id="s3d2a8b86a4f5a810">
<source>Successfully created user and added to group <x id="0" equiv-text="${this.group.name}"/></source>
2023-10-19 12:53:56 +00:00
</trans-unit>
2023-11-16 23:07:21 +00:00
<trans-unit id="s824e0943a7104668">
<source>This user will be added to the group "<x id="0" equiv-text="${this.targetGroup.name}"/>".</source>
2023-10-19 12:53:56 +00:00
</trans-unit>
2023-11-18 00:55:48 +00:00
<trans-unit id="s62e7f6ed7d9cb3ca">
<source>Pretend user exists</source>
2023-10-19 12:53:56 +00:00
</trans-unit>
2023-11-18 00:55:48 +00:00
<trans-unit id="s52bdc80690a9a8dc">
<source>When enabled, the stage will always accept the given user identifier and continue.</source>
2023-10-23 16:48:12 +00:00
</trans-unit>
web/admin: revise wizard form handling (#7331)
* web: break circular dependency between AKElement & Interface.
This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.
I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.
* web: fix broken typescript references
This built... and then it didn't? Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.
* web: extract the form processing from the form submission process
Our forms have a lot of customized value handling, and the function `serializeForm` takes
our input structures and creates a JSON object ready for submission across the wire for
the various models provided by the API.
That function was embedded in the `ak-form` object, but it has no actual dependencies on
the state of that object; aside from identifying the input elements, which is done at the
very start of processing, this large block of code stands alone. Separating out the
"processing the form" from "identifying the form" allows us to customize our form handling
and preserve form information on the client for transactional purposes such as our wizard.
w
* web: multi-select, but there's a styling issue.
* web: provide a closed control for multi-select
This commit creates a new control, using the ak-form-element-horizontal as a *CLOSED*
object, for our multi-select. This control right now is limited to what we expect to
be using in the wizard, but that doesn't mean it can't be smarter in the future.
* web: hung up by a silly spelling error
* web: update the form-handling method
With the `serializeForm` method extracted, it's much easier to examine and parse
every *form* with every keystroke, preserving them against the changes that
happen as the customer navigates the Wizard. With that in place, it became
straightforward to retrofit the "handle changes to the application, to the provider, and to the providerType"
into the three pages of the wizard, and to provide *all* of the form elements in a base class
such that no specialized handling needs to happen to any of the child pages.
Fixed an ugly typo in the oauth2 provider, as well.
* web: wizard should work with multi-select and should reflect default values
(Note: This commit is predicated on both the "Extract serializeForm function from Form.ts" and
"Provide a controlled multi-select input control" PRs.)
The initial attempt at the wizard was woefully naive in its implementation, missing some critical
details along the way. This revision starts off with one stronger assumption: trust that Jens knows
what he's doing, and knew what he was building when he wrote the initial `Form` handler.
The problem with the `Form` handler, and the reason I avoided it, was simply that it does too many
things, especially in its ModelForm variant: it receives a model from the back-end, renders a
(hand-written) form for that model, allows the user to interact with that model, and facilitates
saving it to the back-end again, complete with on-page notifications of success or failure.
The Wizard could not use all of that. It needs to gather the information for *two* models (an
Application and a Provider, plus the ProviderType) and has a new and specialized end-point for a
transaction that allows the committing or roll back of both models to happen simultaneously,
predicated on success or failure respectively.
With "Extract `serializeForm` completed, it was possible to repurpose the forms that already
existed, stripping them down to just their input components, and eventing the entire thing in a
single event loop of "events flow up, data flows down." In this case, the *entire form* is
serialized on a per-event basis and pushed up the to the orchestration layer, which saves them off.
Writing a parent `BasePanel` class that has accessors for `formValues` and `valid` means that the
state of every page is accessible with a simple query. This simplified the `BaseProviderPanel` class
to just specialize the `dispatchUpdate` method to send the wizard update with the new provider
information filled out.
Because the *form* is being treated as the source of truth about the state of a `Partial<Application>`
or `Partial<*Provider>` object, the defaults are now being captured as expected.
Likewise, this simplified the `providerCache` layer which preserves customer input in the event that
the customer starts filling out the wrong provider to a simple conditional clause in the
orchestrator. The Wizard has much fewer smarts because it doesn't (and probably never did) need
them.
Along with the above changes, the following has also been done:
For SAML and SCIM, the providerMappings now works. They weren't being managed as `state` objects,
so they weren't receiving updates when the update event retrieved the information from the back-end.
In order to make clear what's happening, I have extracted the loops from the original definition and
built them as named objects: `propertyMappings`, `pmUserValues`, `pmGroupValues` and so on, which I
then pass into the new multi-select component.
I fixed a really embarrassing typo in Oauth2's "advanced settings" block.
I have extracted the CoreGroup search-select into a custom component.
I deleted the `merge` function. That was a faulty experiment with non-deterministic outcomes, and I
was never happy with it. I'm glad its gone.
I've added a title header to each of the providers, so the user can be sure that they're looking
at the right provider type when they start filling out the form.
I've created a new token, `data-ak-control`, with which we can mark all objects that we can treat as
Authentik value-producing components, the form value of which is available through a `json()`
method. I've added this bit of intelligence to the `serializeForm` function, short-circuiting the
complex processing and putting the "this is the shape of the value we expect from this input" *onto
the input itself*. Which is where it belongs.
* web: add error handling to wizard.
* web: improve error handling in light components
Rather than reproduce the error handling across all of the LightComponents,
I've made a parent class that takes the common fields to distribute between
the ak-form-element-horizontal and the input object itself. This made it
much easier to properly display errors in freeform input fields in the
wizard, as well as working with the routine error handling in Form.ts
* Added the radio control to the list of LightComponents.
* Fix bug where event was recorded twice.
* Fixed merge bug (?) that somehow deleted the Authorization Select block in OAuth2.
* web: prettier had opinions
* web: added error handling and display
* web: bump @lit-labs/context from 0.4.1 to 0.5.1 in /web
Bumps [@lit-labs/context](https://github.com/lit/lit/tree/HEAD/packages/labs/context) from 0.4.1 to 0.5.1.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/labs/context/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/@lit-labs/context@0.5.1/packages/labs/context)
---
updated-dependencies:
- dependency-name: "@lit-labs/context"
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
* web: updated wizard to run with latest package.json configuration
Apparently, there were stale dependencies in package-lock.json that were conflicting
with the requests in our package.json. By running `npm update`, I was able to resolve
the conflict.
I have also removed the default names from the context names collection; they weren't doing
any good, and they permit frictionless renaming of dependencies, which is never a good
idea.
* web: schlepping on the errors messages
During testing, I realized I was unhappy with the error messages. They're not very helpful.
By adding links to navigate back to the place where the error occurred, and providing better
context for what the error could have been, I hope to help the use correct their errors.
* make package the same as main
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-12-06 11:28:19 +00:00
<trans-unit id="scda8dc24b561e205">
<source>There was an error in the application.</source>
2023-10-23 16:48:12 +00:00
</trans-unit>
web/admin: revise wizard form handling (#7331)
* web: break circular dependency between AKElement & Interface.
This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.
I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.
* web: fix broken typescript references
This built... and then it didn't? Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.
* web: extract the form processing from the form submission process
Our forms have a lot of customized value handling, and the function `serializeForm` takes
our input structures and creates a JSON object ready for submission across the wire for
the various models provided by the API.
That function was embedded in the `ak-form` object, but it has no actual dependencies on
the state of that object; aside from identifying the input elements, which is done at the
very start of processing, this large block of code stands alone. Separating out the
"processing the form" from "identifying the form" allows us to customize our form handling
and preserve form information on the client for transactional purposes such as our wizard.
w
* web: multi-select, but there's a styling issue.
* web: provide a closed control for multi-select
This commit creates a new control, using the ak-form-element-horizontal as a *CLOSED*
object, for our multi-select. This control right now is limited to what we expect to
be using in the wizard, but that doesn't mean it can't be smarter in the future.
* web: hung up by a silly spelling error
* web: update the form-handling method
With the `serializeForm` method extracted, it's much easier to examine and parse
every *form* with every keystroke, preserving them against the changes that
happen as the customer navigates the Wizard. With that in place, it became
straightforward to retrofit the "handle changes to the application, to the provider, and to the providerType"
into the three pages of the wizard, and to provide *all* of the form elements in a base class
such that no specialized handling needs to happen to any of the child pages.
Fixed an ugly typo in the oauth2 provider, as well.
* web: wizard should work with multi-select and should reflect default values
(Note: This commit is predicated on both the "Extract serializeForm function from Form.ts" and
"Provide a controlled multi-select input control" PRs.)
The initial attempt at the wizard was woefully naive in its implementation, missing some critical
details along the way. This revision starts off with one stronger assumption: trust that Jens knows
what he's doing, and knew what he was building when he wrote the initial `Form` handler.
The problem with the `Form` handler, and the reason I avoided it, was simply that it does too many
things, especially in its ModelForm variant: it receives a model from the back-end, renders a
(hand-written) form for that model, allows the user to interact with that model, and facilitates
saving it to the back-end again, complete with on-page notifications of success or failure.
The Wizard could not use all of that. It needs to gather the information for *two* models (an
Application and a Provider, plus the ProviderType) and has a new and specialized end-point for a
transaction that allows the committing or roll back of both models to happen simultaneously,
predicated on success or failure respectively.
With "Extract `serializeForm` completed, it was possible to repurpose the forms that already
existed, stripping them down to just their input components, and eventing the entire thing in a
single event loop of "events flow up, data flows down." In this case, the *entire form* is
serialized on a per-event basis and pushed up the to the orchestration layer, which saves them off.
Writing a parent `BasePanel` class that has accessors for `formValues` and `valid` means that the
state of every page is accessible with a simple query. This simplified the `BaseProviderPanel` class
to just specialize the `dispatchUpdate` method to send the wizard update with the new provider
information filled out.
Because the *form* is being treated as the source of truth about the state of a `Partial<Application>`
or `Partial<*Provider>` object, the defaults are now being captured as expected.
Likewise, this simplified the `providerCache` layer which preserves customer input in the event that
the customer starts filling out the wrong provider to a simple conditional clause in the
orchestrator. The Wizard has much fewer smarts because it doesn't (and probably never did) need
them.
Along with the above changes, the following has also been done:
For SAML and SCIM, the providerMappings now works. They weren't being managed as `state` objects,
so they weren't receiving updates when the update event retrieved the information from the back-end.
In order to make clear what's happening, I have extracted the loops from the original definition and
built them as named objects: `propertyMappings`, `pmUserValues`, `pmGroupValues` and so on, which I
then pass into the new multi-select component.
I fixed a really embarrassing typo in Oauth2's "advanced settings" block.
I have extracted the CoreGroup search-select into a custom component.
I deleted the `merge` function. That was a faulty experiment with non-deterministic outcomes, and I
was never happy with it. I'm glad its gone.
I've added a title header to each of the providers, so the user can be sure that they're looking
at the right provider type when they start filling out the form.
I've created a new token, `data-ak-control`, with which we can mark all objects that we can treat as
Authentik value-producing components, the form value of which is available through a `json()`
method. I've added this bit of intelligence to the `serializeForm` function, short-circuiting the
complex processing and putting the "this is the shape of the value we expect from this input" *onto
the input itself*. Which is where it belongs.
* web: add error handling to wizard.
* web: improve error handling in light components
Rather than reproduce the error handling across all of the LightComponents,
I've made a parent class that takes the common fields to distribute between
the ak-form-element-horizontal and the input object itself. This made it
much easier to properly display errors in freeform input fields in the
wizard, as well as working with the routine error handling in Form.ts
* Added the radio control to the list of LightComponents.
* Fix bug where event was recorded twice.
* Fixed merge bug (?) that somehow deleted the Authorization Select block in OAuth2.
* web: prettier had opinions
* web: added error handling and display
* web: bump @lit-labs/context from 0.4.1 to 0.5.1 in /web
Bumps [@lit-labs/context](https://github.com/lit/lit/tree/HEAD/packages/labs/context) from 0.4.1 to 0.5.1.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/labs/context/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/@lit-labs/context@0.5.1/packages/labs/context)
---
updated-dependencies:
- dependency-name: "@lit-labs/context"
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
* web: updated wizard to run with latest package.json configuration
Apparently, there were stale dependencies in package-lock.json that were conflicting
with the requests in our package.json. By running `npm update`, I was able to resolve
the conflict.
I have also removed the default names from the context names collection; they weren't doing
any good, and they permit frictionless renaming of dependencies, which is never a good
idea.
* web: schlepping on the errors messages
During testing, I realized I was unhappy with the error messages. They're not very helpful.
By adding links to navigate back to the place where the error occurred, and providing better
context for what the error could have been, I hope to help the use correct their errors.
* make package the same as main
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-12-06 11:28:19 +00:00
<trans-unit id="sdaca9c2c0361ed3a">
<source>Review the application.</source>
2023-10-23 16:48:12 +00:00
</trans-unit>
web/admin: revise wizard form handling (#7331)
* web: break circular dependency between AKElement & Interface.
This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.
I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.
* web: fix broken typescript references
This built... and then it didn't? Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.
* web: extract the form processing from the form submission process
Our forms have a lot of customized value handling, and the function `serializeForm` takes
our input structures and creates a JSON object ready for submission across the wire for
the various models provided by the API.
That function was embedded in the `ak-form` object, but it has no actual dependencies on
the state of that object; aside from identifying the input elements, which is done at the
very start of processing, this large block of code stands alone. Separating out the
"processing the form" from "identifying the form" allows us to customize our form handling
and preserve form information on the client for transactional purposes such as our wizard.
w
* web: multi-select, but there's a styling issue.
* web: provide a closed control for multi-select
This commit creates a new control, using the ak-form-element-horizontal as a *CLOSED*
object, for our multi-select. This control right now is limited to what we expect to
be using in the wizard, but that doesn't mean it can't be smarter in the future.
* web: hung up by a silly spelling error
* web: update the form-handling method
With the `serializeForm` method extracted, it's much easier to examine and parse
every *form* with every keystroke, preserving them against the changes that
happen as the customer navigates the Wizard. With that in place, it became
straightforward to retrofit the "handle changes to the application, to the provider, and to the providerType"
into the three pages of the wizard, and to provide *all* of the form elements in a base class
such that no specialized handling needs to happen to any of the child pages.
Fixed an ugly typo in the oauth2 provider, as well.
* web: wizard should work with multi-select and should reflect default values
(Note: This commit is predicated on both the "Extract serializeForm function from Form.ts" and
"Provide a controlled multi-select input control" PRs.)
The initial attempt at the wizard was woefully naive in its implementation, missing some critical
details along the way. This revision starts off with one stronger assumption: trust that Jens knows
what he's doing, and knew what he was building when he wrote the initial `Form` handler.
The problem with the `Form` handler, and the reason I avoided it, was simply that it does too many
things, especially in its ModelForm variant: it receives a model from the back-end, renders a
(hand-written) form for that model, allows the user to interact with that model, and facilitates
saving it to the back-end again, complete with on-page notifications of success or failure.
The Wizard could not use all of that. It needs to gather the information for *two* models (an
Application and a Provider, plus the ProviderType) and has a new and specialized end-point for a
transaction that allows the committing or roll back of both models to happen simultaneously,
predicated on success or failure respectively.
With "Extract `serializeForm` completed, it was possible to repurpose the forms that already
existed, stripping them down to just their input components, and eventing the entire thing in a
single event loop of "events flow up, data flows down." In this case, the *entire form* is
serialized on a per-event basis and pushed up the to the orchestration layer, which saves them off.
Writing a parent `BasePanel` class that has accessors for `formValues` and `valid` means that the
state of every page is accessible with a simple query. This simplified the `BaseProviderPanel` class
to just specialize the `dispatchUpdate` method to send the wizard update with the new provider
information filled out.
Because the *form* is being treated as the source of truth about the state of a `Partial<Application>`
or `Partial<*Provider>` object, the defaults are now being captured as expected.
Likewise, this simplified the `providerCache` layer which preserves customer input in the event that
the customer starts filling out the wrong provider to a simple conditional clause in the
orchestrator. The Wizard has much fewer smarts because it doesn't (and probably never did) need
them.
Along with the above changes, the following has also been done:
For SAML and SCIM, the providerMappings now works. They weren't being managed as `state` objects,
so they weren't receiving updates when the update event retrieved the information from the back-end.
In order to make clear what's happening, I have extracted the loops from the original definition and
built them as named objects: `propertyMappings`, `pmUserValues`, `pmGroupValues` and so on, which I
then pass into the new multi-select component.
I fixed a really embarrassing typo in Oauth2's "advanced settings" block.
I have extracted the CoreGroup search-select into a custom component.
I deleted the `merge` function. That was a faulty experiment with non-deterministic outcomes, and I
was never happy with it. I'm glad its gone.
I've added a title header to each of the providers, so the user can be sure that they're looking
at the right provider type when they start filling out the form.
I've created a new token, `data-ak-control`, with which we can mark all objects that we can treat as
Authentik value-producing components, the form value of which is available through a `json()`
method. I've added this bit of intelligence to the `serializeForm` function, short-circuiting the
complex processing and putting the "this is the shape of the value we expect from this input" *onto
the input itself*. Which is where it belongs.
* web: add error handling to wizard.
* web: improve error handling in light components
Rather than reproduce the error handling across all of the LightComponents,
I've made a parent class that takes the common fields to distribute between
the ak-form-element-horizontal and the input object itself. This made it
much easier to properly display errors in freeform input fields in the
wizard, as well as working with the routine error handling in Form.ts
* Added the radio control to the list of LightComponents.
* Fix bug where event was recorded twice.
* Fixed merge bug (?) that somehow deleted the Authorization Select block in OAuth2.
* web: prettier had opinions
* web: added error handling and display
* web: bump @lit-labs/context from 0.4.1 to 0.5.1 in /web
Bumps [@lit-labs/context](https://github.com/lit/lit/tree/HEAD/packages/labs/context) from 0.4.1 to 0.5.1.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/labs/context/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/@lit-labs/context@0.5.1/packages/labs/context)
---
updated-dependencies:
- dependency-name: "@lit-labs/context"
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
* web: updated wizard to run with latest package.json configuration
Apparently, there were stale dependencies in package-lock.json that were conflicting
with the requests in our package.json. By running `npm update`, I was able to resolve
the conflict.
I have also removed the default names from the context names collection; they weren't doing
any good, and they permit frictionless renaming of dependencies, which is never a good
idea.
* web: schlepping on the errors messages
During testing, I realized I was unhappy with the error messages. They're not very helpful.
By adding links to navigate back to the place where the error occurred, and providing better
context for what the error could have been, I hope to help the use correct their errors.
* make package the same as main
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-12-06 11:28:19 +00:00
<trans-unit id="sb50000a8fada5672">
<source>There was an error in the provider.</source>
2023-10-23 16:48:12 +00:00
</trans-unit>
web/admin: revise wizard form handling (#7331)
* web: break circular dependency between AKElement & Interface.
This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.
I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.
* web: fix broken typescript references
This built... and then it didn't? Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.
* web: extract the form processing from the form submission process
Our forms have a lot of customized value handling, and the function `serializeForm` takes
our input structures and creates a JSON object ready for submission across the wire for
the various models provided by the API.
That function was embedded in the `ak-form` object, but it has no actual dependencies on
the state of that object; aside from identifying the input elements, which is done at the
very start of processing, this large block of code stands alone. Separating out the
"processing the form" from "identifying the form" allows us to customize our form handling
and preserve form information on the client for transactional purposes such as our wizard.
w
* web: multi-select, but there's a styling issue.
* web: provide a closed control for multi-select
This commit creates a new control, using the ak-form-element-horizontal as a *CLOSED*
object, for our multi-select. This control right now is limited to what we expect to
be using in the wizard, but that doesn't mean it can't be smarter in the future.
* web: hung up by a silly spelling error
* web: update the form-handling method
With the `serializeForm` method extracted, it's much easier to examine and parse
every *form* with every keystroke, preserving them against the changes that
happen as the customer navigates the Wizard. With that in place, it became
straightforward to retrofit the "handle changes to the application, to the provider, and to the providerType"
into the three pages of the wizard, and to provide *all* of the form elements in a base class
such that no specialized handling needs to happen to any of the child pages.
Fixed an ugly typo in the oauth2 provider, as well.
* web: wizard should work with multi-select and should reflect default values
(Note: This commit is predicated on both the "Extract serializeForm function from Form.ts" and
"Provide a controlled multi-select input control" PRs.)
The initial attempt at the wizard was woefully naive in its implementation, missing some critical
details along the way. This revision starts off with one stronger assumption: trust that Jens knows
what he's doing, and knew what he was building when he wrote the initial `Form` handler.
The problem with the `Form` handler, and the reason I avoided it, was simply that it does too many
things, especially in its ModelForm variant: it receives a model from the back-end, renders a
(hand-written) form for that model, allows the user to interact with that model, and facilitates
saving it to the back-end again, complete with on-page notifications of success or failure.
The Wizard could not use all of that. It needs to gather the information for *two* models (an
Application and a Provider, plus the ProviderType) and has a new and specialized end-point for a
transaction that allows the committing or roll back of both models to happen simultaneously,
predicated on success or failure respectively.
With "Extract `serializeForm` completed, it was possible to repurpose the forms that already
existed, stripping them down to just their input components, and eventing the entire thing in a
single event loop of "events flow up, data flows down." In this case, the *entire form* is
serialized on a per-event basis and pushed up the to the orchestration layer, which saves them off.
Writing a parent `BasePanel` class that has accessors for `formValues` and `valid` means that the
state of every page is accessible with a simple query. This simplified the `BaseProviderPanel` class
to just specialize the `dispatchUpdate` method to send the wizard update with the new provider
information filled out.
Because the *form* is being treated as the source of truth about the state of a `Partial<Application>`
or `Partial<*Provider>` object, the defaults are now being captured as expected.
Likewise, this simplified the `providerCache` layer which preserves customer input in the event that
the customer starts filling out the wrong provider to a simple conditional clause in the
orchestrator. The Wizard has much fewer smarts because it doesn't (and probably never did) need
them.
Along with the above changes, the following has also been done:
For SAML and SCIM, the providerMappings now works. They weren't being managed as `state` objects,
so they weren't receiving updates when the update event retrieved the information from the back-end.
In order to make clear what's happening, I have extracted the loops from the original definition and
built them as named objects: `propertyMappings`, `pmUserValues`, `pmGroupValues` and so on, which I
then pass into the new multi-select component.
I fixed a really embarrassing typo in Oauth2's "advanced settings" block.
I have extracted the CoreGroup search-select into a custom component.
I deleted the `merge` function. That was a faulty experiment with non-deterministic outcomes, and I
was never happy with it. I'm glad its gone.
I've added a title header to each of the providers, so the user can be sure that they're looking
at the right provider type when they start filling out the form.
I've created a new token, `data-ak-control`, with which we can mark all objects that we can treat as
Authentik value-producing components, the form value of which is available through a `json()`
method. I've added this bit of intelligence to the `serializeForm` function, short-circuiting the
complex processing and putting the "this is the shape of the value we expect from this input" *onto
the input itself*. Which is where it belongs.
* web: add error handling to wizard.
* web: improve error handling in light components
Rather than reproduce the error handling across all of the LightComponents,
I've made a parent class that takes the common fields to distribute between
the ak-form-element-horizontal and the input object itself. This made it
much easier to properly display errors in freeform input fields in the
wizard, as well as working with the routine error handling in Form.ts
* Added the radio control to the list of LightComponents.
* Fix bug where event was recorded twice.
* Fixed merge bug (?) that somehow deleted the Authorization Select block in OAuth2.
* web: prettier had opinions
* web: added error handling and display
* web: bump @lit-labs/context from 0.4.1 to 0.5.1 in /web
Bumps [@lit-labs/context](https://github.com/lit/lit/tree/HEAD/packages/labs/context) from 0.4.1 to 0.5.1.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/labs/context/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/@lit-labs/context@0.5.1/packages/labs/context)
---
updated-dependencies:
- dependency-name: "@lit-labs/context"
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
* web: updated wizard to run with latest package.json configuration
Apparently, there were stale dependencies in package-lock.json that were conflicting
with the requests in our package.json. By running `npm update`, I was able to resolve
the conflict.
I have also removed the default names from the context names collection; they weren't doing
any good, and they permit frictionless renaming of dependencies, which is never a good
idea.
* web: schlepping on the errors messages
During testing, I realized I was unhappy with the error messages. They're not very helpful.
By adding links to navigate back to the place where the error occurred, and providing better
context for what the error could have been, I hope to help the use correct their errors.
* make package the same as main
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-12-06 11:28:19 +00:00
<trans-unit id="s21f95eaf151d4ce3">
<source>Review the provider.</source>
2023-10-23 16:48:12 +00:00
</trans-unit>
web/admin: revise wizard form handling (#7331)
* web: break circular dependency between AKElement & Interface.
This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.
I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.
* web: fix broken typescript references
This built... and then it didn't? Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.
* web: extract the form processing from the form submission process
Our forms have a lot of customized value handling, and the function `serializeForm` takes
our input structures and creates a JSON object ready for submission across the wire for
the various models provided by the API.
That function was embedded in the `ak-form` object, but it has no actual dependencies on
the state of that object; aside from identifying the input elements, which is done at the
very start of processing, this large block of code stands alone. Separating out the
"processing the form" from "identifying the form" allows us to customize our form handling
and preserve form information on the client for transactional purposes such as our wizard.
w
* web: multi-select, but there's a styling issue.
* web: provide a closed control for multi-select
This commit creates a new control, using the ak-form-element-horizontal as a *CLOSED*
object, for our multi-select. This control right now is limited to what we expect to
be using in the wizard, but that doesn't mean it can't be smarter in the future.
* web: hung up by a silly spelling error
* web: update the form-handling method
With the `serializeForm` method extracted, it's much easier to examine and parse
every *form* with every keystroke, preserving them against the changes that
happen as the customer navigates the Wizard. With that in place, it became
straightforward to retrofit the "handle changes to the application, to the provider, and to the providerType"
into the three pages of the wizard, and to provide *all* of the form elements in a base class
such that no specialized handling needs to happen to any of the child pages.
Fixed an ugly typo in the oauth2 provider, as well.
* web: wizard should work with multi-select and should reflect default values
(Note: This commit is predicated on both the "Extract serializeForm function from Form.ts" and
"Provide a controlled multi-select input control" PRs.)
The initial attempt at the wizard was woefully naive in its implementation, missing some critical
details along the way. This revision starts off with one stronger assumption: trust that Jens knows
what he's doing, and knew what he was building when he wrote the initial `Form` handler.
The problem with the `Form` handler, and the reason I avoided it, was simply that it does too many
things, especially in its ModelForm variant: it receives a model from the back-end, renders a
(hand-written) form for that model, allows the user to interact with that model, and facilitates
saving it to the back-end again, complete with on-page notifications of success or failure.
The Wizard could not use all of that. It needs to gather the information for *two* models (an
Application and a Provider, plus the ProviderType) and has a new and specialized end-point for a
transaction that allows the committing or roll back of both models to happen simultaneously,
predicated on success or failure respectively.
With "Extract `serializeForm` completed, it was possible to repurpose the forms that already
existed, stripping them down to just their input components, and eventing the entire thing in a
single event loop of "events flow up, data flows down." In this case, the *entire form* is
serialized on a per-event basis and pushed up the to the orchestration layer, which saves them off.
Writing a parent `BasePanel` class that has accessors for `formValues` and `valid` means that the
state of every page is accessible with a simple query. This simplified the `BaseProviderPanel` class
to just specialize the `dispatchUpdate` method to send the wizard update with the new provider
information filled out.
Because the *form* is being treated as the source of truth about the state of a `Partial<Application>`
or `Partial<*Provider>` object, the defaults are now being captured as expected.
Likewise, this simplified the `providerCache` layer which preserves customer input in the event that
the customer starts filling out the wrong provider to a simple conditional clause in the
orchestrator. The Wizard has much fewer smarts because it doesn't (and probably never did) need
them.
Along with the above changes, the following has also been done:
For SAML and SCIM, the providerMappings now works. They weren't being managed as `state` objects,
so they weren't receiving updates when the update event retrieved the information from the back-end.
In order to make clear what's happening, I have extracted the loops from the original definition and
built them as named objects: `propertyMappings`, `pmUserValues`, `pmGroupValues` and so on, which I
then pass into the new multi-select component.
I fixed a really embarrassing typo in Oauth2's "advanced settings" block.
I have extracted the CoreGroup search-select into a custom component.
I deleted the `merge` function. That was a faulty experiment with non-deterministic outcomes, and I
was never happy with it. I'm glad its gone.
I've added a title header to each of the providers, so the user can be sure that they're looking
at the right provider type when they start filling out the form.
I've created a new token, `data-ak-control`, with which we can mark all objects that we can treat as
Authentik value-producing components, the form value of which is available through a `json()`
method. I've added this bit of intelligence to the `serializeForm` function, short-circuiting the
complex processing and putting the "this is the shape of the value we expect from this input" *onto
the input itself*. Which is where it belongs.
* web: add error handling to wizard.
* web: improve error handling in light components
Rather than reproduce the error handling across all of the LightComponents,
I've made a parent class that takes the common fields to distribute between
the ak-form-element-horizontal and the input object itself. This made it
much easier to properly display errors in freeform input fields in the
wizard, as well as working with the routine error handling in Form.ts
* Added the radio control to the list of LightComponents.
* Fix bug where event was recorded twice.
* Fixed merge bug (?) that somehow deleted the Authorization Select block in OAuth2.
* web: prettier had opinions
* web: added error handling and display
* web: bump @lit-labs/context from 0.4.1 to 0.5.1 in /web
Bumps [@lit-labs/context](https://github.com/lit/lit/tree/HEAD/packages/labs/context) from 0.4.1 to 0.5.1.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/labs/context/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/@lit-labs/context@0.5.1/packages/labs/context)
---
updated-dependencies:
- dependency-name: "@lit-labs/context"
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
* web: updated wizard to run with latest package.json configuration
Apparently, there were stale dependencies in package-lock.json that were conflicting
with the requests in our package.json. By running `npm update`, I was able to resolve
the conflict.
I have also removed the default names from the context names collection; they weren't doing
any good, and they permit frictionless renaming of dependencies, which is never a good
idea.
* web: schlepping on the errors messages
During testing, I realized I was unhappy with the error messages. They're not very helpful.
By adding links to navigate back to the place where the error occurred, and providing better
context for what the error could have been, I hope to help the use correct their errors.
* make package the same as main
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-12-06 11:28:19 +00:00
<trans-unit id="s9fd39a5cb20b4e61">
<source>There was an error</source>
2023-10-23 16:48:12 +00:00
</trans-unit>
web/admin: revise wizard form handling (#7331)
* web: break circular dependency between AKElement & Interface.
This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.
I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.
* web: fix broken typescript references
This built... and then it didn't? Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.
* web: extract the form processing from the form submission process
Our forms have a lot of customized value handling, and the function `serializeForm` takes
our input structures and creates a JSON object ready for submission across the wire for
the various models provided by the API.
That function was embedded in the `ak-form` object, but it has no actual dependencies on
the state of that object; aside from identifying the input elements, which is done at the
very start of processing, this large block of code stands alone. Separating out the
"processing the form" from "identifying the form" allows us to customize our form handling
and preserve form information on the client for transactional purposes such as our wizard.
w
* web: multi-select, but there's a styling issue.
* web: provide a closed control for multi-select
This commit creates a new control, using the ak-form-element-horizontal as a *CLOSED*
object, for our multi-select. This control right now is limited to what we expect to
be using in the wizard, but that doesn't mean it can't be smarter in the future.
* web: hung up by a silly spelling error
* web: update the form-handling method
With the `serializeForm` method extracted, it's much easier to examine and parse
every *form* with every keystroke, preserving them against the changes that
happen as the customer navigates the Wizard. With that in place, it became
straightforward to retrofit the "handle changes to the application, to the provider, and to the providerType"
into the three pages of the wizard, and to provide *all* of the form elements in a base class
such that no specialized handling needs to happen to any of the child pages.
Fixed an ugly typo in the oauth2 provider, as well.
* web: wizard should work with multi-select and should reflect default values
(Note: This commit is predicated on both the "Extract serializeForm function from Form.ts" and
"Provide a controlled multi-select input control" PRs.)
The initial attempt at the wizard was woefully naive in its implementation, missing some critical
details along the way. This revision starts off with one stronger assumption: trust that Jens knows
what he's doing, and knew what he was building when he wrote the initial `Form` handler.
The problem with the `Form` handler, and the reason I avoided it, was simply that it does too many
things, especially in its ModelForm variant: it receives a model from the back-end, renders a
(hand-written) form for that model, allows the user to interact with that model, and facilitates
saving it to the back-end again, complete with on-page notifications of success or failure.
The Wizard could not use all of that. It needs to gather the information for *two* models (an
Application and a Provider, plus the ProviderType) and has a new and specialized end-point for a
transaction that allows the committing or roll back of both models to happen simultaneously,
predicated on success or failure respectively.
With "Extract `serializeForm` completed, it was possible to repurpose the forms that already
existed, stripping them down to just their input components, and eventing the entire thing in a
single event loop of "events flow up, data flows down." In this case, the *entire form* is
serialized on a per-event basis and pushed up the to the orchestration layer, which saves them off.
Writing a parent `BasePanel` class that has accessors for `formValues` and `valid` means that the
state of every page is accessible with a simple query. This simplified the `BaseProviderPanel` class
to just specialize the `dispatchUpdate` method to send the wizard update with the new provider
information filled out.
Because the *form* is being treated as the source of truth about the state of a `Partial<Application>`
or `Partial<*Provider>` object, the defaults are now being captured as expected.
Likewise, this simplified the `providerCache` layer which preserves customer input in the event that
the customer starts filling out the wrong provider to a simple conditional clause in the
orchestrator. The Wizard has much fewer smarts because it doesn't (and probably never did) need
them.
Along with the above changes, the following has also been done:
For SAML and SCIM, the providerMappings now works. They weren't being managed as `state` objects,
so they weren't receiving updates when the update event retrieved the information from the back-end.
In order to make clear what's happening, I have extracted the loops from the original definition and
built them as named objects: `propertyMappings`, `pmUserValues`, `pmGroupValues` and so on, which I
then pass into the new multi-select component.
I fixed a really embarrassing typo in Oauth2's "advanced settings" block.
I have extracted the CoreGroup search-select into a custom component.
I deleted the `merge` function. That was a faulty experiment with non-deterministic outcomes, and I
was never happy with it. I'm glad its gone.
I've added a title header to each of the providers, so the user can be sure that they're looking
at the right provider type when they start filling out the form.
I've created a new token, `data-ak-control`, with which we can mark all objects that we can treat as
Authentik value-producing components, the form value of which is available through a `json()`
method. I've added this bit of intelligence to the `serializeForm` function, short-circuiting the
complex processing and putting the "this is the shape of the value we expect from this input" *onto
the input itself*. Which is where it belongs.
* web: add error handling to wizard.
* web: improve error handling in light components
Rather than reproduce the error handling across all of the LightComponents,
I've made a parent class that takes the common fields to distribute between
the ak-form-element-horizontal and the input object itself. This made it
much easier to properly display errors in freeform input fields in the
wizard, as well as working with the routine error handling in Form.ts
* Added the radio control to the list of LightComponents.
* Fix bug where event was recorded twice.
* Fixed merge bug (?) that somehow deleted the Authorization Select block in OAuth2.
* web: prettier had opinions
* web: added error handling and display
* web: bump @lit-labs/context from 0.4.1 to 0.5.1 in /web
Bumps [@lit-labs/context](https://github.com/lit/lit/tree/HEAD/packages/labs/context) from 0.4.1 to 0.5.1.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/labs/context/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/@lit-labs/context@0.5.1/packages/labs/context)
---
updated-dependencies:
- dependency-name: "@lit-labs/context"
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
* web: updated wizard to run with latest package.json configuration
Apparently, there were stale dependencies in package-lock.json that were conflicting
with the requests in our package.json. By running `npm update`, I was able to resolve
the conflict.
I have also removed the default names from the context names collection; they weren't doing
any good, and they permit frictionless renaming of dependencies, which is never a good
idea.
* web: schlepping on the errors messages
During testing, I realized I was unhappy with the error messages. They're not very helpful.
By adding links to navigate back to the place where the error occurred, and providing better
context for what the error could have been, I hope to help the use correct their errors.
* make package the same as main
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-12-06 11:28:19 +00:00
<trans-unit id="s7a6b3453209e1066">
<source>There was an error creating the application, but no error message was sent. Please review the server logs.</source>
2023-10-23 16:48:12 +00:00
</trans-unit>
web/admin: revise wizard form handling (#7331)
* web: break circular dependency between AKElement & Interface.
This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.
I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.
* web: fix broken typescript references
This built... and then it didn't? Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.
* web: extract the form processing from the form submission process
Our forms have a lot of customized value handling, and the function `serializeForm` takes
our input structures and creates a JSON object ready for submission across the wire for
the various models provided by the API.
That function was embedded in the `ak-form` object, but it has no actual dependencies on
the state of that object; aside from identifying the input elements, which is done at the
very start of processing, this large block of code stands alone. Separating out the
"processing the form" from "identifying the form" allows us to customize our form handling
and preserve form information on the client for transactional purposes such as our wizard.
w
* web: multi-select, but there's a styling issue.
* web: provide a closed control for multi-select
This commit creates a new control, using the ak-form-element-horizontal as a *CLOSED*
object, for our multi-select. This control right now is limited to what we expect to
be using in the wizard, but that doesn't mean it can't be smarter in the future.
* web: hung up by a silly spelling error
* web: update the form-handling method
With the `serializeForm` method extracted, it's much easier to examine and parse
every *form* with every keystroke, preserving them against the changes that
happen as the customer navigates the Wizard. With that in place, it became
straightforward to retrofit the "handle changes to the application, to the provider, and to the providerType"
into the three pages of the wizard, and to provide *all* of the form elements in a base class
such that no specialized handling needs to happen to any of the child pages.
Fixed an ugly typo in the oauth2 provider, as well.
* web: wizard should work with multi-select and should reflect default values
(Note: This commit is predicated on both the "Extract serializeForm function from Form.ts" and
"Provide a controlled multi-select input control" PRs.)
The initial attempt at the wizard was woefully naive in its implementation, missing some critical
details along the way. This revision starts off with one stronger assumption: trust that Jens knows
what he's doing, and knew what he was building when he wrote the initial `Form` handler.
The problem with the `Form` handler, and the reason I avoided it, was simply that it does too many
things, especially in its ModelForm variant: it receives a model from the back-end, renders a
(hand-written) form for that model, allows the user to interact with that model, and facilitates
saving it to the back-end again, complete with on-page notifications of success or failure.
The Wizard could not use all of that. It needs to gather the information for *two* models (an
Application and a Provider, plus the ProviderType) and has a new and specialized end-point for a
transaction that allows the committing or roll back of both models to happen simultaneously,
predicated on success or failure respectively.
With "Extract `serializeForm` completed, it was possible to repurpose the forms that already
existed, stripping them down to just their input components, and eventing the entire thing in a
single event loop of "events flow up, data flows down." In this case, the *entire form* is
serialized on a per-event basis and pushed up the to the orchestration layer, which saves them off.
Writing a parent `BasePanel` class that has accessors for `formValues` and `valid` means that the
state of every page is accessible with a simple query. This simplified the `BaseProviderPanel` class
to just specialize the `dispatchUpdate` method to send the wizard update with the new provider
information filled out.
Because the *form* is being treated as the source of truth about the state of a `Partial<Application>`
or `Partial<*Provider>` object, the defaults are now being captured as expected.
Likewise, this simplified the `providerCache` layer which preserves customer input in the event that
the customer starts filling out the wrong provider to a simple conditional clause in the
orchestrator. The Wizard has much fewer smarts because it doesn't (and probably never did) need
them.
Along with the above changes, the following has also been done:
For SAML and SCIM, the providerMappings now works. They weren't being managed as `state` objects,
so they weren't receiving updates when the update event retrieved the information from the back-end.
In order to make clear what's happening, I have extracted the loops from the original definition and
built them as named objects: `propertyMappings`, `pmUserValues`, `pmGroupValues` and so on, which I
then pass into the new multi-select component.
I fixed a really embarrassing typo in Oauth2's "advanced settings" block.
I have extracted the CoreGroup search-select into a custom component.
I deleted the `merge` function. That was a faulty experiment with non-deterministic outcomes, and I
was never happy with it. I'm glad its gone.
I've added a title header to each of the providers, so the user can be sure that they're looking
at the right provider type when they start filling out the form.
I've created a new token, `data-ak-control`, with which we can mark all objects that we can treat as
Authentik value-producing components, the form value of which is available through a `json()`
method. I've added this bit of intelligence to the `serializeForm` function, short-circuiting the
complex processing and putting the "this is the shape of the value we expect from this input" *onto
the input itself*. Which is where it belongs.
* web: add error handling to wizard.
* web: improve error handling in light components
Rather than reproduce the error handling across all of the LightComponents,
I've made a parent class that takes the common fields to distribute between
the ak-form-element-horizontal and the input object itself. This made it
much easier to properly display errors in freeform input fields in the
wizard, as well as working with the routine error handling in Form.ts
* Added the radio control to the list of LightComponents.
* Fix bug where event was recorded twice.
* Fixed merge bug (?) that somehow deleted the Authorization Select block in OAuth2.
* web: prettier had opinions
* web: added error handling and display
* web: bump @lit-labs/context from 0.4.1 to 0.5.1 in /web
Bumps [@lit-labs/context](https://github.com/lit/lit/tree/HEAD/packages/labs/context) from 0.4.1 to 0.5.1.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/labs/context/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/@lit-labs/context@0.5.1/packages/labs/context)
---
updated-dependencies:
- dependency-name: "@lit-labs/context"
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
* web: updated wizard to run with latest package.json configuration
Apparently, there were stale dependencies in package-lock.json that were conflicting
with the requests in our package.json. By running `npm update`, I was able to resolve
the conflict.
I have also removed the default names from the context names collection; they weren't doing
any good, and they permit frictionless renaming of dependencies, which is never a good
idea.
* web: schlepping on the errors messages
During testing, I realized I was unhappy with the error messages. They're not very helpful.
By adding links to navigate back to the place where the error occurred, and providing better
context for what the error could have been, I hope to help the use correct their errors.
* make package the same as main
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-12-06 11:28:19 +00:00
<trans-unit id="s1a711c19cda48375">
<source>Configure LDAP Provider</source>
2023-10-23 16:48:12 +00:00
</trans-unit>
web/admin: revise wizard form handling (#7331)
* web: break circular dependency between AKElement & Interface.
This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.
I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.
* web: fix broken typescript references
This built... and then it didn't? Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.
* web: extract the form processing from the form submission process
Our forms have a lot of customized value handling, and the function `serializeForm` takes
our input structures and creates a JSON object ready for submission across the wire for
the various models provided by the API.
That function was embedded in the `ak-form` object, but it has no actual dependencies on
the state of that object; aside from identifying the input elements, which is done at the
very start of processing, this large block of code stands alone. Separating out the
"processing the form" from "identifying the form" allows us to customize our form handling
and preserve form information on the client for transactional purposes such as our wizard.
w
* web: multi-select, but there's a styling issue.
* web: provide a closed control for multi-select
This commit creates a new control, using the ak-form-element-horizontal as a *CLOSED*
object, for our multi-select. This control right now is limited to what we expect to
be using in the wizard, but that doesn't mean it can't be smarter in the future.
* web: hung up by a silly spelling error
* web: update the form-handling method
With the `serializeForm` method extracted, it's much easier to examine and parse
every *form* with every keystroke, preserving them against the changes that
happen as the customer navigates the Wizard. With that in place, it became
straightforward to retrofit the "handle changes to the application, to the provider, and to the providerType"
into the three pages of the wizard, and to provide *all* of the form elements in a base class
such that no specialized handling needs to happen to any of the child pages.
Fixed an ugly typo in the oauth2 provider, as well.
* web: wizard should work with multi-select and should reflect default values
(Note: This commit is predicated on both the "Extract serializeForm function from Form.ts" and
"Provide a controlled multi-select input control" PRs.)
The initial attempt at the wizard was woefully naive in its implementation, missing some critical
details along the way. This revision starts off with one stronger assumption: trust that Jens knows
what he's doing, and knew what he was building when he wrote the initial `Form` handler.
The problem with the `Form` handler, and the reason I avoided it, was simply that it does too many
things, especially in its ModelForm variant: it receives a model from the back-end, renders a
(hand-written) form for that model, allows the user to interact with that model, and facilitates
saving it to the back-end again, complete with on-page notifications of success or failure.
The Wizard could not use all of that. It needs to gather the information for *two* models (an
Application and a Provider, plus the ProviderType) and has a new and specialized end-point for a
transaction that allows the committing or roll back of both models to happen simultaneously,
predicated on success or failure respectively.
With "Extract `serializeForm` completed, it was possible to repurpose the forms that already
existed, stripping them down to just their input components, and eventing the entire thing in a
single event loop of "events flow up, data flows down." In this case, the *entire form* is
serialized on a per-event basis and pushed up the to the orchestration layer, which saves them off.
Writing a parent `BasePanel` class that has accessors for `formValues` and `valid` means that the
state of every page is accessible with a simple query. This simplified the `BaseProviderPanel` class
to just specialize the `dispatchUpdate` method to send the wizard update with the new provider
information filled out.
Because the *form* is being treated as the source of truth about the state of a `Partial<Application>`
or `Partial<*Provider>` object, the defaults are now being captured as expected.
Likewise, this simplified the `providerCache` layer which preserves customer input in the event that
the customer starts filling out the wrong provider to a simple conditional clause in the
orchestrator. The Wizard has much fewer smarts because it doesn't (and probably never did) need
them.
Along with the above changes, the following has also been done:
For SAML and SCIM, the providerMappings now works. They weren't being managed as `state` objects,
so they weren't receiving updates when the update event retrieved the information from the back-end.
In order to make clear what's happening, I have extracted the loops from the original definition and
built them as named objects: `propertyMappings`, `pmUserValues`, `pmGroupValues` and so on, which I
then pass into the new multi-select component.
I fixed a really embarrassing typo in Oauth2's "advanced settings" block.
I have extracted the CoreGroup search-select into a custom component.
I deleted the `merge` function. That was a faulty experiment with non-deterministic outcomes, and I
was never happy with it. I'm glad its gone.
I've added a title header to each of the providers, so the user can be sure that they're looking
at the right provider type when they start filling out the form.
I've created a new token, `data-ak-control`, with which we can mark all objects that we can treat as
Authentik value-producing components, the form value of which is available through a `json()`
method. I've added this bit of intelligence to the `serializeForm` function, short-circuiting the
complex processing and putting the "this is the shape of the value we expect from this input" *onto
the input itself*. Which is where it belongs.
* web: add error handling to wizard.
* web: improve error handling in light components
Rather than reproduce the error handling across all of the LightComponents,
I've made a parent class that takes the common fields to distribute between
the ak-form-element-horizontal and the input object itself. This made it
much easier to properly display errors in freeform input fields in the
wizard, as well as working with the routine error handling in Form.ts
* Added the radio control to the list of LightComponents.
* Fix bug where event was recorded twice.
* Fixed merge bug (?) that somehow deleted the Authorization Select block in OAuth2.
* web: prettier had opinions
* web: added error handling and display
* web: bump @lit-labs/context from 0.4.1 to 0.5.1 in /web
Bumps [@lit-labs/context](https://github.com/lit/lit/tree/HEAD/packages/labs/context) from 0.4.1 to 0.5.1.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/labs/context/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/@lit-labs/context@0.5.1/packages/labs/context)
---
updated-dependencies:
- dependency-name: "@lit-labs/context"
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
* web: updated wizard to run with latest package.json configuration
Apparently, there were stale dependencies in package-lock.json that were conflicting
with the requests in our package.json. By running `npm update`, I was able to resolve
the conflict.
I have also removed the default names from the context names collection; they weren't doing
any good, and they permit frictionless renaming of dependencies, which is never a good
idea.
* web: schlepping on the errors messages
During testing, I realized I was unhappy with the error messages. They're not very helpful.
By adding links to navigate back to the place where the error occurred, and providing better
context for what the error could have been, I hope to help the use correct their errors.
* make package the same as main
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-12-06 11:28:19 +00:00
<trans-unit id="s9368e965b5c292ab">
<source>Configure OAuth2/OpenId Provider</source>
2023-10-23 16:48:12 +00:00
</trans-unit>
web/admin: revise wizard form handling (#7331)
* web: break circular dependency between AKElement & Interface.
This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.
I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.
* web: fix broken typescript references
This built... and then it didn't? Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.
* web: extract the form processing from the form submission process
Our forms have a lot of customized value handling, and the function `serializeForm` takes
our input structures and creates a JSON object ready for submission across the wire for
the various models provided by the API.
That function was embedded in the `ak-form` object, but it has no actual dependencies on
the state of that object; aside from identifying the input elements, which is done at the
very start of processing, this large block of code stands alone. Separating out the
"processing the form" from "identifying the form" allows us to customize our form handling
and preserve form information on the client for transactional purposes such as our wizard.
w
* web: multi-select, but there's a styling issue.
* web: provide a closed control for multi-select
This commit creates a new control, using the ak-form-element-horizontal as a *CLOSED*
object, for our multi-select. This control right now is limited to what we expect to
be using in the wizard, but that doesn't mean it can't be smarter in the future.
* web: hung up by a silly spelling error
* web: update the form-handling method
With the `serializeForm` method extracted, it's much easier to examine and parse
every *form* with every keystroke, preserving them against the changes that
happen as the customer navigates the Wizard. With that in place, it became
straightforward to retrofit the "handle changes to the application, to the provider, and to the providerType"
into the three pages of the wizard, and to provide *all* of the form elements in a base class
such that no specialized handling needs to happen to any of the child pages.
Fixed an ugly typo in the oauth2 provider, as well.
* web: wizard should work with multi-select and should reflect default values
(Note: This commit is predicated on both the "Extract serializeForm function from Form.ts" and
"Provide a controlled multi-select input control" PRs.)
The initial attempt at the wizard was woefully naive in its implementation, missing some critical
details along the way. This revision starts off with one stronger assumption: trust that Jens knows
what he's doing, and knew what he was building when he wrote the initial `Form` handler.
The problem with the `Form` handler, and the reason I avoided it, was simply that it does too many
things, especially in its ModelForm variant: it receives a model from the back-end, renders a
(hand-written) form for that model, allows the user to interact with that model, and facilitates
saving it to the back-end again, complete with on-page notifications of success or failure.
The Wizard could not use all of that. It needs to gather the information for *two* models (an
Application and a Provider, plus the ProviderType) and has a new and specialized end-point for a
transaction that allows the committing or roll back of both models to happen simultaneously,
predicated on success or failure respectively.
With "Extract `serializeForm` completed, it was possible to repurpose the forms that already
existed, stripping them down to just their input components, and eventing the entire thing in a
single event loop of "events flow up, data flows down." In this case, the *entire form* is
serialized on a per-event basis and pushed up the to the orchestration layer, which saves them off.
Writing a parent `BasePanel` class that has accessors for `formValues` and `valid` means that the
state of every page is accessible with a simple query. This simplified the `BaseProviderPanel` class
to just specialize the `dispatchUpdate` method to send the wizard update with the new provider
information filled out.
Because the *form* is being treated as the source of truth about the state of a `Partial<Application>`
or `Partial<*Provider>` object, the defaults are now being captured as expected.
Likewise, this simplified the `providerCache` layer which preserves customer input in the event that
the customer starts filling out the wrong provider to a simple conditional clause in the
orchestrator. The Wizard has much fewer smarts because it doesn't (and probably never did) need
them.
Along with the above changes, the following has also been done:
For SAML and SCIM, the providerMappings now works. They weren't being managed as `state` objects,
so they weren't receiving updates when the update event retrieved the information from the back-end.
In order to make clear what's happening, I have extracted the loops from the original definition and
built them as named objects: `propertyMappings`, `pmUserValues`, `pmGroupValues` and so on, which I
then pass into the new multi-select component.
I fixed a really embarrassing typo in Oauth2's "advanced settings" block.
I have extracted the CoreGroup search-select into a custom component.
I deleted the `merge` function. That was a faulty experiment with non-deterministic outcomes, and I
was never happy with it. I'm glad its gone.
I've added a title header to each of the providers, so the user can be sure that they're looking
at the right provider type when they start filling out the form.
I've created a new token, `data-ak-control`, with which we can mark all objects that we can treat as
Authentik value-producing components, the form value of which is available through a `json()`
method. I've added this bit of intelligence to the `serializeForm` function, short-circuiting the
complex processing and putting the "this is the shape of the value we expect from this input" *onto
the input itself*. Which is where it belongs.
* web: add error handling to wizard.
* web: improve error handling in light components
Rather than reproduce the error handling across all of the LightComponents,
I've made a parent class that takes the common fields to distribute between
the ak-form-element-horizontal and the input object itself. This made it
much easier to properly display errors in freeform input fields in the
wizard, as well as working with the routine error handling in Form.ts
* Added the radio control to the list of LightComponents.
* Fix bug where event was recorded twice.
* Fixed merge bug (?) that somehow deleted the Authorization Select block in OAuth2.
* web: prettier had opinions
* web: added error handling and display
* web: bump @lit-labs/context from 0.4.1 to 0.5.1 in /web
Bumps [@lit-labs/context](https://github.com/lit/lit/tree/HEAD/packages/labs/context) from 0.4.1 to 0.5.1.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/labs/context/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/@lit-labs/context@0.5.1/packages/labs/context)
---
updated-dependencies:
- dependency-name: "@lit-labs/context"
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
* web: updated wizard to run with latest package.json configuration
Apparently, there were stale dependencies in package-lock.json that were conflicting
with the requests in our package.json. By running `npm update`, I was able to resolve
the conflict.
I have also removed the default names from the context names collection; they weren't doing
any good, and they permit frictionless renaming of dependencies, which is never a good
idea.
* web: schlepping on the errors messages
During testing, I realized I was unhappy with the error messages. They're not very helpful.
By adding links to navigate back to the place where the error occurred, and providing better
context for what the error could have been, I hope to help the use correct their errors.
* make package the same as main
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-12-06 11:28:19 +00:00
<trans-unit id="sf5cbccdc6254c8dc">
<source>Configure Proxy Provider</source>
2023-10-23 16:48:12 +00:00
</trans-unit>
web/admin: revise wizard form handling (#7331)
* web: break circular dependency between AKElement & Interface.
This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.
I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.
* web: fix broken typescript references
This built... and then it didn't? Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.
* web: extract the form processing from the form submission process
Our forms have a lot of customized value handling, and the function `serializeForm` takes
our input structures and creates a JSON object ready for submission across the wire for
the various models provided by the API.
That function was embedded in the `ak-form` object, but it has no actual dependencies on
the state of that object; aside from identifying the input elements, which is done at the
very start of processing, this large block of code stands alone. Separating out the
"processing the form" from "identifying the form" allows us to customize our form handling
and preserve form information on the client for transactional purposes such as our wizard.
w
* web: multi-select, but there's a styling issue.
* web: provide a closed control for multi-select
This commit creates a new control, using the ak-form-element-horizontal as a *CLOSED*
object, for our multi-select. This control right now is limited to what we expect to
be using in the wizard, but that doesn't mean it can't be smarter in the future.
* web: hung up by a silly spelling error
* web: update the form-handling method
With the `serializeForm` method extracted, it's much easier to examine and parse
every *form* with every keystroke, preserving them against the changes that
happen as the customer navigates the Wizard. With that in place, it became
straightforward to retrofit the "handle changes to the application, to the provider, and to the providerType"
into the three pages of the wizard, and to provide *all* of the form elements in a base class
such that no specialized handling needs to happen to any of the child pages.
Fixed an ugly typo in the oauth2 provider, as well.
* web: wizard should work with multi-select and should reflect default values
(Note: This commit is predicated on both the "Extract serializeForm function from Form.ts" and
"Provide a controlled multi-select input control" PRs.)
The initial attempt at the wizard was woefully naive in its implementation, missing some critical
details along the way. This revision starts off with one stronger assumption: trust that Jens knows
what he's doing, and knew what he was building when he wrote the initial `Form` handler.
The problem with the `Form` handler, and the reason I avoided it, was simply that it does too many
things, especially in its ModelForm variant: it receives a model from the back-end, renders a
(hand-written) form for that model, allows the user to interact with that model, and facilitates
saving it to the back-end again, complete with on-page notifications of success or failure.
The Wizard could not use all of that. It needs to gather the information for *two* models (an
Application and a Provider, plus the ProviderType) and has a new and specialized end-point for a
transaction that allows the committing or roll back of both models to happen simultaneously,
predicated on success or failure respectively.
With "Extract `serializeForm` completed, it was possible to repurpose the forms that already
existed, stripping them down to just their input components, and eventing the entire thing in a
single event loop of "events flow up, data flows down." In this case, the *entire form* is
serialized on a per-event basis and pushed up the to the orchestration layer, which saves them off.
Writing a parent `BasePanel` class that has accessors for `formValues` and `valid` means that the
state of every page is accessible with a simple query. This simplified the `BaseProviderPanel` class
to just specialize the `dispatchUpdate` method to send the wizard update with the new provider
information filled out.
Because the *form* is being treated as the source of truth about the state of a `Partial<Application>`
or `Partial<*Provider>` object, the defaults are now being captured as expected.
Likewise, this simplified the `providerCache` layer which preserves customer input in the event that
the customer starts filling out the wrong provider to a simple conditional clause in the
orchestrator. The Wizard has much fewer smarts because it doesn't (and probably never did) need
them.
Along with the above changes, the following has also been done:
For SAML and SCIM, the providerMappings now works. They weren't being managed as `state` objects,
so they weren't receiving updates when the update event retrieved the information from the back-end.
In order to make clear what's happening, I have extracted the loops from the original definition and
built them as named objects: `propertyMappings`, `pmUserValues`, `pmGroupValues` and so on, which I
then pass into the new multi-select component.
I fixed a really embarrassing typo in Oauth2's "advanced settings" block.
I have extracted the CoreGroup search-select into a custom component.
I deleted the `merge` function. That was a faulty experiment with non-deterministic outcomes, and I
was never happy with it. I'm glad its gone.
I've added a title header to each of the providers, so the user can be sure that they're looking
at the right provider type when they start filling out the form.
I've created a new token, `data-ak-control`, with which we can mark all objects that we can treat as
Authentik value-producing components, the form value of which is available through a `json()`
method. I've added this bit of intelligence to the `serializeForm` function, short-circuiting the
complex processing and putting the "this is the shape of the value we expect from this input" *onto
the input itself*. Which is where it belongs.
* web: add error handling to wizard.
* web: improve error handling in light components
Rather than reproduce the error handling across all of the LightComponents,
I've made a parent class that takes the common fields to distribute between
the ak-form-element-horizontal and the input object itself. This made it
much easier to properly display errors in freeform input fields in the
wizard, as well as working with the routine error handling in Form.ts
* Added the radio control to the list of LightComponents.
* Fix bug where event was recorded twice.
* Fixed merge bug (?) that somehow deleted the Authorization Select block in OAuth2.
* web: prettier had opinions
* web: added error handling and display
* web: bump @lit-labs/context from 0.4.1 to 0.5.1 in /web
Bumps [@lit-labs/context](https://github.com/lit/lit/tree/HEAD/packages/labs/context) from 0.4.1 to 0.5.1.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/labs/context/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/@lit-labs/context@0.5.1/packages/labs/context)
---
updated-dependencies:
- dependency-name: "@lit-labs/context"
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
* web: updated wizard to run with latest package.json configuration
Apparently, there were stale dependencies in package-lock.json that were conflicting
with the requests in our package.json. By running `npm update`, I was able to resolve
the conflict.
I have also removed the default names from the context names collection; they weren't doing
any good, and they permit frictionless renaming of dependencies, which is never a good
idea.
* web: schlepping on the errors messages
During testing, I realized I was unhappy with the error messages. They're not very helpful.
By adding links to navigate back to the place where the error occurred, and providing better
context for what the error could have been, I hope to help the use correct their errors.
* make package the same as main
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-12-06 11:28:19 +00:00
<trans-unit id="sf6d46bb442b77e91">
<source>AdditionalScopes</source>
2023-10-23 16:48:12 +00:00
</trans-unit>
web/admin: revise wizard form handling (#7331)
* web: break circular dependency between AKElement & Interface.
This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.
I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.
* web: fix broken typescript references
This built... and then it didn't? Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.
* web: extract the form processing from the form submission process
Our forms have a lot of customized value handling, and the function `serializeForm` takes
our input structures and creates a JSON object ready for submission across the wire for
the various models provided by the API.
That function was embedded in the `ak-form` object, but it has no actual dependencies on
the state of that object; aside from identifying the input elements, which is done at the
very start of processing, this large block of code stands alone. Separating out the
"processing the form" from "identifying the form" allows us to customize our form handling
and preserve form information on the client for transactional purposes such as our wizard.
w
* web: multi-select, but there's a styling issue.
* web: provide a closed control for multi-select
This commit creates a new control, using the ak-form-element-horizontal as a *CLOSED*
object, for our multi-select. This control right now is limited to what we expect to
be using in the wizard, but that doesn't mean it can't be smarter in the future.
* web: hung up by a silly spelling error
* web: update the form-handling method
With the `serializeForm` method extracted, it's much easier to examine and parse
every *form* with every keystroke, preserving them against the changes that
happen as the customer navigates the Wizard. With that in place, it became
straightforward to retrofit the "handle changes to the application, to the provider, and to the providerType"
into the three pages of the wizard, and to provide *all* of the form elements in a base class
such that no specialized handling needs to happen to any of the child pages.
Fixed an ugly typo in the oauth2 provider, as well.
* web: wizard should work with multi-select and should reflect default values
(Note: This commit is predicated on both the "Extract serializeForm function from Form.ts" and
"Provide a controlled multi-select input control" PRs.)
The initial attempt at the wizard was woefully naive in its implementation, missing some critical
details along the way. This revision starts off with one stronger assumption: trust that Jens knows
what he's doing, and knew what he was building when he wrote the initial `Form` handler.
The problem with the `Form` handler, and the reason I avoided it, was simply that it does too many
things, especially in its ModelForm variant: it receives a model from the back-end, renders a
(hand-written) form for that model, allows the user to interact with that model, and facilitates
saving it to the back-end again, complete with on-page notifications of success or failure.
The Wizard could not use all of that. It needs to gather the information for *two* models (an
Application and a Provider, plus the ProviderType) and has a new and specialized end-point for a
transaction that allows the committing or roll back of both models to happen simultaneously,
predicated on success or failure respectively.
With "Extract `serializeForm` completed, it was possible to repurpose the forms that already
existed, stripping them down to just their input components, and eventing the entire thing in a
single event loop of "events flow up, data flows down." In this case, the *entire form* is
serialized on a per-event basis and pushed up the to the orchestration layer, which saves them off.
Writing a parent `BasePanel` class that has accessors for `formValues` and `valid` means that the
state of every page is accessible with a simple query. This simplified the `BaseProviderPanel` class
to just specialize the `dispatchUpdate` method to send the wizard update with the new provider
information filled out.
Because the *form* is being treated as the source of truth about the state of a `Partial<Application>`
or `Partial<*Provider>` object, the defaults are now being captured as expected.
Likewise, this simplified the `providerCache` layer which preserves customer input in the event that
the customer starts filling out the wrong provider to a simple conditional clause in the
orchestrator. The Wizard has much fewer smarts because it doesn't (and probably never did) need
them.
Along with the above changes, the following has also been done:
For SAML and SCIM, the providerMappings now works. They weren't being managed as `state` objects,
so they weren't receiving updates when the update event retrieved the information from the back-end.
In order to make clear what's happening, I have extracted the loops from the original definition and
built them as named objects: `propertyMappings`, `pmUserValues`, `pmGroupValues` and so on, which I
then pass into the new multi-select component.
I fixed a really embarrassing typo in Oauth2's "advanced settings" block.
I have extracted the CoreGroup search-select into a custom component.
I deleted the `merge` function. That was a faulty experiment with non-deterministic outcomes, and I
was never happy with it. I'm glad its gone.
I've added a title header to each of the providers, so the user can be sure that they're looking
at the right provider type when they start filling out the form.
I've created a new token, `data-ak-control`, with which we can mark all objects that we can treat as
Authentik value-producing components, the form value of which is available through a `json()`
method. I've added this bit of intelligence to the `serializeForm` function, short-circuiting the
complex processing and putting the "this is the shape of the value we expect from this input" *onto
the input itself*. Which is where it belongs.
* web: add error handling to wizard.
* web: improve error handling in light components
Rather than reproduce the error handling across all of the LightComponents,
I've made a parent class that takes the common fields to distribute between
the ak-form-element-horizontal and the input object itself. This made it
much easier to properly display errors in freeform input fields in the
wizard, as well as working with the routine error handling in Form.ts
* Added the radio control to the list of LightComponents.
* Fix bug where event was recorded twice.
* Fixed merge bug (?) that somehow deleted the Authorization Select block in OAuth2.
* web: prettier had opinions
* web: added error handling and display
* web: bump @lit-labs/context from 0.4.1 to 0.5.1 in /web
Bumps [@lit-labs/context](https://github.com/lit/lit/tree/HEAD/packages/labs/context) from 0.4.1 to 0.5.1.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/labs/context/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/@lit-labs/context@0.5.1/packages/labs/context)
---
updated-dependencies:
- dependency-name: "@lit-labs/context"
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
* web: updated wizard to run with latest package.json configuration
Apparently, there were stale dependencies in package-lock.json that were conflicting
with the requests in our package.json. By running `npm update`, I was able to resolve
the conflict.
I have also removed the default names from the context names collection; they weren't doing
any good, and they permit frictionless renaming of dependencies, which is never a good
idea.
* web: schlepping on the errors messages
During testing, I realized I was unhappy with the error messages. They're not very helpful.
By adding links to navigate back to the place where the error occurred, and providing better
context for what the error could have been, I hope to help the use correct their errors.
* make package the same as main
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-12-06 11:28:19 +00:00
<trans-unit id="s2c8c6f89089b31d4">
<source>Configure Radius Provider</source>
2023-10-23 16:48:12 +00:00
</trans-unit>
web/admin: revise wizard form handling (#7331)
* web: break circular dependency between AKElement & Interface.
This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.
I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.
* web: fix broken typescript references
This built... and then it didn't? Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.
* web: extract the form processing from the form submission process
Our forms have a lot of customized value handling, and the function `serializeForm` takes
our input structures and creates a JSON object ready for submission across the wire for
the various models provided by the API.
That function was embedded in the `ak-form` object, but it has no actual dependencies on
the state of that object; aside from identifying the input elements, which is done at the
very start of processing, this large block of code stands alone. Separating out the
"processing the form" from "identifying the form" allows us to customize our form handling
and preserve form information on the client for transactional purposes such as our wizard.
w
* web: multi-select, but there's a styling issue.
* web: provide a closed control for multi-select
This commit creates a new control, using the ak-form-element-horizontal as a *CLOSED*
object, for our multi-select. This control right now is limited to what we expect to
be using in the wizard, but that doesn't mean it can't be smarter in the future.
* web: hung up by a silly spelling error
* web: update the form-handling method
With the `serializeForm` method extracted, it's much easier to examine and parse
every *form* with every keystroke, preserving them against the changes that
happen as the customer navigates the Wizard. With that in place, it became
straightforward to retrofit the "handle changes to the application, to the provider, and to the providerType"
into the three pages of the wizard, and to provide *all* of the form elements in a base class
such that no specialized handling needs to happen to any of the child pages.
Fixed an ugly typo in the oauth2 provider, as well.
* web: wizard should work with multi-select and should reflect default values
(Note: This commit is predicated on both the "Extract serializeForm function from Form.ts" and
"Provide a controlled multi-select input control" PRs.)
The initial attempt at the wizard was woefully naive in its implementation, missing some critical
details along the way. This revision starts off with one stronger assumption: trust that Jens knows
what he's doing, and knew what he was building when he wrote the initial `Form` handler.
The problem with the `Form` handler, and the reason I avoided it, was simply that it does too many
things, especially in its ModelForm variant: it receives a model from the back-end, renders a
(hand-written) form for that model, allows the user to interact with that model, and facilitates
saving it to the back-end again, complete with on-page notifications of success or failure.
The Wizard could not use all of that. It needs to gather the information for *two* models (an
Application and a Provider, plus the ProviderType) and has a new and specialized end-point for a
transaction that allows the committing or roll back of both models to happen simultaneously,
predicated on success or failure respectively.
With "Extract `serializeForm` completed, it was possible to repurpose the forms that already
existed, stripping them down to just their input components, and eventing the entire thing in a
single event loop of "events flow up, data flows down." In this case, the *entire form* is
serialized on a per-event basis and pushed up the to the orchestration layer, which saves them off.
Writing a parent `BasePanel` class that has accessors for `formValues` and `valid` means that the
state of every page is accessible with a simple query. This simplified the `BaseProviderPanel` class
to just specialize the `dispatchUpdate` method to send the wizard update with the new provider
information filled out.
Because the *form* is being treated as the source of truth about the state of a `Partial<Application>`
or `Partial<*Provider>` object, the defaults are now being captured as expected.
Likewise, this simplified the `providerCache` layer which preserves customer input in the event that
the customer starts filling out the wrong provider to a simple conditional clause in the
orchestrator. The Wizard has much fewer smarts because it doesn't (and probably never did) need
them.
Along with the above changes, the following has also been done:
For SAML and SCIM, the providerMappings now works. They weren't being managed as `state` objects,
so they weren't receiving updates when the update event retrieved the information from the back-end.
In order to make clear what's happening, I have extracted the loops from the original definition and
built them as named objects: `propertyMappings`, `pmUserValues`, `pmGroupValues` and so on, which I
then pass into the new multi-select component.
I fixed a really embarrassing typo in Oauth2's "advanced settings" block.
I have extracted the CoreGroup search-select into a custom component.
I deleted the `merge` function. That was a faulty experiment with non-deterministic outcomes, and I
was never happy with it. I'm glad its gone.
I've added a title header to each of the providers, so the user can be sure that they're looking
at the right provider type when they start filling out the form.
I've created a new token, `data-ak-control`, with which we can mark all objects that we can treat as
Authentik value-producing components, the form value of which is available through a `json()`
method. I've added this bit of intelligence to the `serializeForm` function, short-circuiting the
complex processing and putting the "this is the shape of the value we expect from this input" *onto
the input itself*. Which is where it belongs.
* web: add error handling to wizard.
* web: improve error handling in light components
Rather than reproduce the error handling across all of the LightComponents,
I've made a parent class that takes the common fields to distribute between
the ak-form-element-horizontal and the input object itself. This made it
much easier to properly display errors in freeform input fields in the
wizard, as well as working with the routine error handling in Form.ts
* Added the radio control to the list of LightComponents.
* Fix bug where event was recorded twice.
* Fixed merge bug (?) that somehow deleted the Authorization Select block in OAuth2.
* web: prettier had opinions
* web: added error handling and display
* web: bump @lit-labs/context from 0.4.1 to 0.5.1 in /web
Bumps [@lit-labs/context](https://github.com/lit/lit/tree/HEAD/packages/labs/context) from 0.4.1 to 0.5.1.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/labs/context/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/@lit-labs/context@0.5.1/packages/labs/context)
---
updated-dependencies:
- dependency-name: "@lit-labs/context"
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
* web: updated wizard to run with latest package.json configuration
Apparently, there were stale dependencies in package-lock.json that were conflicting
with the requests in our package.json. By running `npm update`, I was able to resolve
the conflict.
I have also removed the default names from the context names collection; they weren't doing
any good, and they permit frictionless renaming of dependencies, which is never a good
idea.
* web: schlepping on the errors messages
During testing, I realized I was unhappy with the error messages. They're not very helpful.
By adding links to navigate back to the place where the error occurred, and providing better
context for what the error could have been, I hope to help the use correct their errors.
* make package the same as main
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-12-06 11:28:19 +00:00
<trans-unit id="sfe906cde5dddc041">
<source>Configure SAML Provider</source>
2023-10-25 16:25:37 +00:00
</trans-unit>
web/admin: revise wizard form handling (#7331)
* web: break circular dependency between AKElement & Interface.
This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.
I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.
* web: fix broken typescript references
This built... and then it didn't? Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.
* web: extract the form processing from the form submission process
Our forms have a lot of customized value handling, and the function `serializeForm` takes
our input structures and creates a JSON object ready for submission across the wire for
the various models provided by the API.
That function was embedded in the `ak-form` object, but it has no actual dependencies on
the state of that object; aside from identifying the input elements, which is done at the
very start of processing, this large block of code stands alone. Separating out the
"processing the form" from "identifying the form" allows us to customize our form handling
and preserve form information on the client for transactional purposes such as our wizard.
w
* web: multi-select, but there's a styling issue.
* web: provide a closed control for multi-select
This commit creates a new control, using the ak-form-element-horizontal as a *CLOSED*
object, for our multi-select. This control right now is limited to what we expect to
be using in the wizard, but that doesn't mean it can't be smarter in the future.
* web: hung up by a silly spelling error
* web: update the form-handling method
With the `serializeForm` method extracted, it's much easier to examine and parse
every *form* with every keystroke, preserving them against the changes that
happen as the customer navigates the Wizard. With that in place, it became
straightforward to retrofit the "handle changes to the application, to the provider, and to the providerType"
into the three pages of the wizard, and to provide *all* of the form elements in a base class
such that no specialized handling needs to happen to any of the child pages.
Fixed an ugly typo in the oauth2 provider, as well.
* web: wizard should work with multi-select and should reflect default values
(Note: This commit is predicated on both the "Extract serializeForm function from Form.ts" and
"Provide a controlled multi-select input control" PRs.)
The initial attempt at the wizard was woefully naive in its implementation, missing some critical
details along the way. This revision starts off with one stronger assumption: trust that Jens knows
what he's doing, and knew what he was building when he wrote the initial `Form` handler.
The problem with the `Form` handler, and the reason I avoided it, was simply that it does too many
things, especially in its ModelForm variant: it receives a model from the back-end, renders a
(hand-written) form for that model, allows the user to interact with that model, and facilitates
saving it to the back-end again, complete with on-page notifications of success or failure.
The Wizard could not use all of that. It needs to gather the information for *two* models (an
Application and a Provider, plus the ProviderType) and has a new and specialized end-point for a
transaction that allows the committing or roll back of both models to happen simultaneously,
predicated on success or failure respectively.
With "Extract `serializeForm` completed, it was possible to repurpose the forms that already
existed, stripping them down to just their input components, and eventing the entire thing in a
single event loop of "events flow up, data flows down." In this case, the *entire form* is
serialized on a per-event basis and pushed up the to the orchestration layer, which saves them off.
Writing a parent `BasePanel` class that has accessors for `formValues` and `valid` means that the
state of every page is accessible with a simple query. This simplified the `BaseProviderPanel` class
to just specialize the `dispatchUpdate` method to send the wizard update with the new provider
information filled out.
Because the *form* is being treated as the source of truth about the state of a `Partial<Application>`
or `Partial<*Provider>` object, the defaults are now being captured as expected.
Likewise, this simplified the `providerCache` layer which preserves customer input in the event that
the customer starts filling out the wrong provider to a simple conditional clause in the
orchestrator. The Wizard has much fewer smarts because it doesn't (and probably never did) need
them.
Along with the above changes, the following has also been done:
For SAML and SCIM, the providerMappings now works. They weren't being managed as `state` objects,
so they weren't receiving updates when the update event retrieved the information from the back-end.
In order to make clear what's happening, I have extracted the loops from the original definition and
built them as named objects: `propertyMappings`, `pmUserValues`, `pmGroupValues` and so on, which I
then pass into the new multi-select component.
I fixed a really embarrassing typo in Oauth2's "advanced settings" block.
I have extracted the CoreGroup search-select into a custom component.
I deleted the `merge` function. That was a faulty experiment with non-deterministic outcomes, and I
was never happy with it. I'm glad its gone.
I've added a title header to each of the providers, so the user can be sure that they're looking
at the right provider type when they start filling out the form.
I've created a new token, `data-ak-control`, with which we can mark all objects that we can treat as
Authentik value-producing components, the form value of which is available through a `json()`
method. I've added this bit of intelligence to the `serializeForm` function, short-circuiting the
complex processing and putting the "this is the shape of the value we expect from this input" *onto
the input itself*. Which is where it belongs.
* web: add error handling to wizard.
* web: improve error handling in light components
Rather than reproduce the error handling across all of the LightComponents,
I've made a parent class that takes the common fields to distribute between
the ak-form-element-horizontal and the input object itself. This made it
much easier to properly display errors in freeform input fields in the
wizard, as well as working with the routine error handling in Form.ts
* Added the radio control to the list of LightComponents.
* Fix bug where event was recorded twice.
* Fixed merge bug (?) that somehow deleted the Authorization Select block in OAuth2.
* web: prettier had opinions
* web: added error handling and display
* web: bump @lit-labs/context from 0.4.1 to 0.5.1 in /web
Bumps [@lit-labs/context](https://github.com/lit/lit/tree/HEAD/packages/labs/context) from 0.4.1 to 0.5.1.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/labs/context/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/@lit-labs/context@0.5.1/packages/labs/context)
---
updated-dependencies:
- dependency-name: "@lit-labs/context"
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
* web: updated wizard to run with latest package.json configuration
Apparently, there were stale dependencies in package-lock.json that were conflicting
with the requests in our package.json. By running `npm update`, I was able to resolve
the conflict.
I have also removed the default names from the context names collection; they weren't doing
any good, and they permit frictionless renaming of dependencies, which is never a good
idea.
* web: schlepping on the errors messages
During testing, I realized I was unhappy with the error messages. They're not very helpful.
By adding links to navigate back to the place where the error occurred, and providing better
context for what the error could have been, I hope to help the use correct their errors.
* make package the same as main
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-12-06 11:28:19 +00:00
<trans-unit id="sb3defbacd01ad972">
<source>Property mappings used for user mapping.</source>
2023-10-25 16:25:37 +00:00
</trans-unit>
web/admin: revise wizard form handling (#7331)
* web: break circular dependency between AKElement & Interface.
This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.
I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.
* web: fix broken typescript references
This built... and then it didn't? Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.
* web: extract the form processing from the form submission process
Our forms have a lot of customized value handling, and the function `serializeForm` takes
our input structures and creates a JSON object ready for submission across the wire for
the various models provided by the API.
That function was embedded in the `ak-form` object, but it has no actual dependencies on
the state of that object; aside from identifying the input elements, which is done at the
very start of processing, this large block of code stands alone. Separating out the
"processing the form" from "identifying the form" allows us to customize our form handling
and preserve form information on the client for transactional purposes such as our wizard.
w
* web: multi-select, but there's a styling issue.
* web: provide a closed control for multi-select
This commit creates a new control, using the ak-form-element-horizontal as a *CLOSED*
object, for our multi-select. This control right now is limited to what we expect to
be using in the wizard, but that doesn't mean it can't be smarter in the future.
* web: hung up by a silly spelling error
* web: update the form-handling method
With the `serializeForm` method extracted, it's much easier to examine and parse
every *form* with every keystroke, preserving them against the changes that
happen as the customer navigates the Wizard. With that in place, it became
straightforward to retrofit the "handle changes to the application, to the provider, and to the providerType"
into the three pages of the wizard, and to provide *all* of the form elements in a base class
such that no specialized handling needs to happen to any of the child pages.
Fixed an ugly typo in the oauth2 provider, as well.
* web: wizard should work with multi-select and should reflect default values
(Note: This commit is predicated on both the "Extract serializeForm function from Form.ts" and
"Provide a controlled multi-select input control" PRs.)
The initial attempt at the wizard was woefully naive in its implementation, missing some critical
details along the way. This revision starts off with one stronger assumption: trust that Jens knows
what he's doing, and knew what he was building when he wrote the initial `Form` handler.
The problem with the `Form` handler, and the reason I avoided it, was simply that it does too many
things, especially in its ModelForm variant: it receives a model from the back-end, renders a
(hand-written) form for that model, allows the user to interact with that model, and facilitates
saving it to the back-end again, complete with on-page notifications of success or failure.
The Wizard could not use all of that. It needs to gather the information for *two* models (an
Application and a Provider, plus the ProviderType) and has a new and specialized end-point for a
transaction that allows the committing or roll back of both models to happen simultaneously,
predicated on success or failure respectively.
With "Extract `serializeForm` completed, it was possible to repurpose the forms that already
existed, stripping them down to just their input components, and eventing the entire thing in a
single event loop of "events flow up, data flows down." In this case, the *entire form* is
serialized on a per-event basis and pushed up the to the orchestration layer, which saves them off.
Writing a parent `BasePanel` class that has accessors for `formValues` and `valid` means that the
state of every page is accessible with a simple query. This simplified the `BaseProviderPanel` class
to just specialize the `dispatchUpdate` method to send the wizard update with the new provider
information filled out.
Because the *form* is being treated as the source of truth about the state of a `Partial<Application>`
or `Partial<*Provider>` object, the defaults are now being captured as expected.
Likewise, this simplified the `providerCache` layer which preserves customer input in the event that
the customer starts filling out the wrong provider to a simple conditional clause in the
orchestrator. The Wizard has much fewer smarts because it doesn't (and probably never did) need
them.
Along with the above changes, the following has also been done:
For SAML and SCIM, the providerMappings now works. They weren't being managed as `state` objects,
so they weren't receiving updates when the update event retrieved the information from the back-end.
In order to make clear what's happening, I have extracted the loops from the original definition and
built them as named objects: `propertyMappings`, `pmUserValues`, `pmGroupValues` and so on, which I
then pass into the new multi-select component.
I fixed a really embarrassing typo in Oauth2's "advanced settings" block.
I have extracted the CoreGroup search-select into a custom component.
I deleted the `merge` function. That was a faulty experiment with non-deterministic outcomes, and I
was never happy with it. I'm glad its gone.
I've added a title header to each of the providers, so the user can be sure that they're looking
at the right provider type when they start filling out the form.
I've created a new token, `data-ak-control`, with which we can mark all objects that we can treat as
Authentik value-producing components, the form value of which is available through a `json()`
method. I've added this bit of intelligence to the `serializeForm` function, short-circuiting the
complex processing and putting the "this is the shape of the value we expect from this input" *onto
the input itself*. Which is where it belongs.
* web: add error handling to wizard.
* web: improve error handling in light components
Rather than reproduce the error handling across all of the LightComponents,
I've made a parent class that takes the common fields to distribute between
the ak-form-element-horizontal and the input object itself. This made it
much easier to properly display errors in freeform input fields in the
wizard, as well as working with the routine error handling in Form.ts
* Added the radio control to the list of LightComponents.
* Fix bug where event was recorded twice.
* Fixed merge bug (?) that somehow deleted the Authorization Select block in OAuth2.
* web: prettier had opinions
* web: added error handling and display
* web: bump @lit-labs/context from 0.4.1 to 0.5.1 in /web
Bumps [@lit-labs/context](https://github.com/lit/lit/tree/HEAD/packages/labs/context) from 0.4.1 to 0.5.1.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/labs/context/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/@lit-labs/context@0.5.1/packages/labs/context)
---
updated-dependencies:
- dependency-name: "@lit-labs/context"
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
* web: updated wizard to run with latest package.json configuration
Apparently, there were stale dependencies in package-lock.json that were conflicting
with the requests in our package.json. By running `npm update`, I was able to resolve
the conflict.
I have also removed the default names from the context names collection; they weren't doing
any good, and they permit frictionless renaming of dependencies, which is never a good
idea.
* web: schlepping on the errors messages
During testing, I realized I was unhappy with the error messages. They're not very helpful.
By adding links to navigate back to the place where the error occurred, and providing better
context for what the error could have been, I hope to help the use correct their errors.
* make package the same as main
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-12-06 11:28:19 +00:00
<trans-unit id="s7ccce0ec8d228db6">
<source>Configure SCIM Provider</source>
2023-10-25 16:25:37 +00:00
</trans-unit>
web/admin: revise wizard form handling (#7331)
* web: break circular dependency between AKElement & Interface.
This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.
I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.
* web: fix broken typescript references
This built... and then it didn't? Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.
* web: extract the form processing from the form submission process
Our forms have a lot of customized value handling, and the function `serializeForm` takes
our input structures and creates a JSON object ready for submission across the wire for
the various models provided by the API.
That function was embedded in the `ak-form` object, but it has no actual dependencies on
the state of that object; aside from identifying the input elements, which is done at the
very start of processing, this large block of code stands alone. Separating out the
"processing the form" from "identifying the form" allows us to customize our form handling
and preserve form information on the client for transactional purposes such as our wizard.
w
* web: multi-select, but there's a styling issue.
* web: provide a closed control for multi-select
This commit creates a new control, using the ak-form-element-horizontal as a *CLOSED*
object, for our multi-select. This control right now is limited to what we expect to
be using in the wizard, but that doesn't mean it can't be smarter in the future.
* web: hung up by a silly spelling error
* web: update the form-handling method
With the `serializeForm` method extracted, it's much easier to examine and parse
every *form* with every keystroke, preserving them against the changes that
happen as the customer navigates the Wizard. With that in place, it became
straightforward to retrofit the "handle changes to the application, to the provider, and to the providerType"
into the three pages of the wizard, and to provide *all* of the form elements in a base class
such that no specialized handling needs to happen to any of the child pages.
Fixed an ugly typo in the oauth2 provider, as well.
* web: wizard should work with multi-select and should reflect default values
(Note: This commit is predicated on both the "Extract serializeForm function from Form.ts" and
"Provide a controlled multi-select input control" PRs.)
The initial attempt at the wizard was woefully naive in its implementation, missing some critical
details along the way. This revision starts off with one stronger assumption: trust that Jens knows
what he's doing, and knew what he was building when he wrote the initial `Form` handler.
The problem with the `Form` handler, and the reason I avoided it, was simply that it does too many
things, especially in its ModelForm variant: it receives a model from the back-end, renders a
(hand-written) form for that model, allows the user to interact with that model, and facilitates
saving it to the back-end again, complete with on-page notifications of success or failure.
The Wizard could not use all of that. It needs to gather the information for *two* models (an
Application and a Provider, plus the ProviderType) and has a new and specialized end-point for a
transaction that allows the committing or roll back of both models to happen simultaneously,
predicated on success or failure respectively.
With "Extract `serializeForm` completed, it was possible to repurpose the forms that already
existed, stripping them down to just their input components, and eventing the entire thing in a
single event loop of "events flow up, data flows down." In this case, the *entire form* is
serialized on a per-event basis and pushed up the to the orchestration layer, which saves them off.
Writing a parent `BasePanel` class that has accessors for `formValues` and `valid` means that the
state of every page is accessible with a simple query. This simplified the `BaseProviderPanel` class
to just specialize the `dispatchUpdate` method to send the wizard update with the new provider
information filled out.
Because the *form* is being treated as the source of truth about the state of a `Partial<Application>`
or `Partial<*Provider>` object, the defaults are now being captured as expected.
Likewise, this simplified the `providerCache` layer which preserves customer input in the event that
the customer starts filling out the wrong provider to a simple conditional clause in the
orchestrator. The Wizard has much fewer smarts because it doesn't (and probably never did) need
them.
Along with the above changes, the following has also been done:
For SAML and SCIM, the providerMappings now works. They weren't being managed as `state` objects,
so they weren't receiving updates when the update event retrieved the information from the back-end.
In order to make clear what's happening, I have extracted the loops from the original definition and
built them as named objects: `propertyMappings`, `pmUserValues`, `pmGroupValues` and so on, which I
then pass into the new multi-select component.
I fixed a really embarrassing typo in Oauth2's "advanced settings" block.
I have extracted the CoreGroup search-select into a custom component.
I deleted the `merge` function. That was a faulty experiment with non-deterministic outcomes, and I
was never happy with it. I'm glad its gone.
I've added a title header to each of the providers, so the user can be sure that they're looking
at the right provider type when they start filling out the form.
I've created a new token, `data-ak-control`, with which we can mark all objects that we can treat as
Authentik value-producing components, the form value of which is available through a `json()`
method. I've added this bit of intelligence to the `serializeForm` function, short-circuiting the
complex processing and putting the "this is the shape of the value we expect from this input" *onto
the input itself*. Which is where it belongs.
* web: add error handling to wizard.
* web: improve error handling in light components
Rather than reproduce the error handling across all of the LightComponents,
I've made a parent class that takes the common fields to distribute between
the ak-form-element-horizontal and the input object itself. This made it
much easier to properly display errors in freeform input fields in the
wizard, as well as working with the routine error handling in Form.ts
* Added the radio control to the list of LightComponents.
* Fix bug where event was recorded twice.
* Fixed merge bug (?) that somehow deleted the Authorization Select block in OAuth2.
* web: prettier had opinions
* web: added error handling and display
* web: bump @lit-labs/context from 0.4.1 to 0.5.1 in /web
Bumps [@lit-labs/context](https://github.com/lit/lit/tree/HEAD/packages/labs/context) from 0.4.1 to 0.5.1.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/labs/context/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/@lit-labs/context@0.5.1/packages/labs/context)
---
updated-dependencies:
- dependency-name: "@lit-labs/context"
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
* web: updated wizard to run with latest package.json configuration
Apparently, there were stale dependencies in package-lock.json that were conflicting
with the requests in our package.json. By running `npm update`, I was able to resolve
the conflict.
I have also removed the default names from the context names collection; they weren't doing
any good, and they permit frictionless renaming of dependencies, which is never a good
idea.
* web: schlepping on the errors messages
During testing, I realized I was unhappy with the error messages. They're not very helpful.
By adding links to navigate back to the place where the error occurred, and providing better
context for what the error could have been, I hope to help the use correct their errors.
* make package the same as main
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-12-06 11:28:19 +00:00
<trans-unit id="sd7728d2b6e1d25e9">
<source>Property mappings used for group creation.</source>
2023-10-25 16:25:37 +00:00
</trans-unit>
2023-12-06 17:06:07 +00:00
<trans-unit id="s7513372fe60f6387">
<source>Event volume</source>
2023-10-25 16:25:37 +00:00
</trans-unit>
2023-12-19 12:32:10 +00:00
<trans-unit id="s047a5f0211fedc72">
<source>Require Outpost (flow can only be executed from an outpost).</source>
2023-10-25 16:25:37 +00:00
</trans-unit>
2023-12-30 20:33:14 +00:00
<trans-unit id="s3271da6c18c25b18">
<source>Connection settings.</source>
2023-10-27 09:39:39 +00:00
</trans-unit>
2023-12-30 20:33:14 +00:00
<trans-unit id="s2f4ca2148183d692">
<source>Successfully updated endpoint.</source>
2023-10-27 09:39:39 +00:00
</trans-unit>
2023-12-30 20:33:14 +00:00
<trans-unit id="s5adee855dbe191d9">
<source>Successfully created endpoint.</source>
2023-10-27 09:39:39 +00:00
</trans-unit>
2023-12-30 20:33:14 +00:00
<trans-unit id="s61e136c0658e27d5">
<source>Protocol</source>
2023-10-27 09:39:39 +00:00
</trans-unit>
2023-12-30 20:33:14 +00:00
<trans-unit id="sa062b019ff0c8809">
<source>RDP</source>
2023-11-06 12:51:41 +00:00
</trans-unit>
2023-12-30 20:33:14 +00:00
<trans-unit id="s97f9bf19fa5b57d1">
<source>SSH</source>
2023-11-06 12:51:41 +00:00
</trans-unit>
2023-12-30 20:33:14 +00:00
<trans-unit id="s7c100119e9ffcc32">
<source>VNC</source>
2023-11-14 12:05:18 +00:00
</trans-unit>
2023-12-30 20:33:14 +00:00
<trans-unit id="s6b05f9d8801fc14f">
<source>Host</source>
2023-11-14 12:05:18 +00:00
</trans-unit>
2023-12-30 20:33:14 +00:00
<trans-unit id="sb474f652a2c2fc76">
<source>Hostname/IP to connect to.</source>
2023-11-14 12:05:18 +00:00
</trans-unit>
2023-12-30 20:33:14 +00:00
<trans-unit id="s8276649077e8715c">
<source>Endpoint(s)</source>
2023-11-14 12:05:18 +00:00
</trans-unit>
2023-12-30 20:33:14 +00:00
<trans-unit id="sf1dabfe0fe8a75ad">
<source>Update Endpoint</source>
2023-11-14 12:05:18 +00:00
</trans-unit>
2023-12-30 20:33:14 +00:00
<trans-unit id="s008496c7716b9812">
<source>These bindings control which users will have access to this endpoint. Users must also have access to the application.</source>
2023-11-14 12:05:18 +00:00
</trans-unit>
2023-12-30 20:33:14 +00:00
<trans-unit id="s38e7cd1a24e70faa">
<source>Create Endpoint</source>
2023-11-14 12:05:18 +00:00
</trans-unit>
2023-12-30 20:33:14 +00:00
<trans-unit id="s4770c10e5b1c028c">
<source>RAC is in preview.</source>
2023-11-15 15:28:56 +00:00
</trans-unit>
2023-12-30 20:33:14 +00:00
<trans-unit id="s168565f5ac74a89f">
<source>Update RAC Provider</source>
2023-11-15 15:28:56 +00:00
</trans-unit>
2023-12-30 20:33:14 +00:00
<trans-unit id="s8465a2caa2d9ea5d">
<source>Endpoints</source>
2023-11-15 15:28:56 +00:00
</trans-unit>
2023-12-30 20:33:14 +00:00
<trans-unit id="s9857d883d8eb98fc">
<source>General settings</source>
2023-11-15 15:28:56 +00:00
</trans-unit>
2023-12-30 20:33:14 +00:00
<trans-unit id="sd2066881798a1b96">
<source>RDP settings</source>
2023-11-15 15:28:56 +00:00
</trans-unit>
2023-12-30 20:33:14 +00:00
<trans-unit id="sb864dc36a463a155">
<source>Ignore server certificate</source>
2023-11-15 22:14:30 +00:00
</trans-unit>
2023-12-30 20:33:14 +00:00
<trans-unit id="s20366a8d1eaaca54">
<source>Enable wallpaper</source>
2023-11-16 23:07:21 +00:00
</trans-unit>
2023-12-30 20:33:14 +00:00
<trans-unit id="s1e44c5350ef7598c">
<source>Enable font-smoothing</source>
2023-11-18 00:55:48 +00:00
</trans-unit>
2023-12-30 20:33:14 +00:00
<trans-unit id="s04ff5d6ae711e6d6">
<source>Enable full window dragging</source>
2023-11-18 00:55:48 +00:00
</trans-unit>
2023-12-30 20:33:14 +00:00
<trans-unit id="s663ccbfdf27e8dd0">
<source>Network binding</source>
web/admin: revise wizard form handling (#7331)
* web: break circular dependency between AKElement & Interface.
This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.
I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.
* web: fix broken typescript references
This built... and then it didn't? Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.
* web: extract the form processing from the form submission process
Our forms have a lot of customized value handling, and the function `serializeForm` takes
our input structures and creates a JSON object ready for submission across the wire for
the various models provided by the API.
That function was embedded in the `ak-form` object, but it has no actual dependencies on
the state of that object; aside from identifying the input elements, which is done at the
very start of processing, this large block of code stands alone. Separating out the
"processing the form" from "identifying the form" allows us to customize our form handling
and preserve form information on the client for transactional purposes such as our wizard.
w
* web: multi-select, but there's a styling issue.
* web: provide a closed control for multi-select
This commit creates a new control, using the ak-form-element-horizontal as a *CLOSED*
object, for our multi-select. This control right now is limited to what we expect to
be using in the wizard, but that doesn't mean it can't be smarter in the future.
* web: hung up by a silly spelling error
* web: update the form-handling method
With the `serializeForm` method extracted, it's much easier to examine and parse
every *form* with every keystroke, preserving them against the changes that
happen as the customer navigates the Wizard. With that in place, it became
straightforward to retrofit the "handle changes to the application, to the provider, and to the providerType"
into the three pages of the wizard, and to provide *all* of the form elements in a base class
such that no specialized handling needs to happen to any of the child pages.
Fixed an ugly typo in the oauth2 provider, as well.
* web: wizard should work with multi-select and should reflect default values
(Note: This commit is predicated on both the "Extract serializeForm function from Form.ts" and
"Provide a controlled multi-select input control" PRs.)
The initial attempt at the wizard was woefully naive in its implementation, missing some critical
details along the way. This revision starts off with one stronger assumption: trust that Jens knows
what he's doing, and knew what he was building when he wrote the initial `Form` handler.
The problem with the `Form` handler, and the reason I avoided it, was simply that it does too many
things, especially in its ModelForm variant: it receives a model from the back-end, renders a
(hand-written) form for that model, allows the user to interact with that model, and facilitates
saving it to the back-end again, complete with on-page notifications of success or failure.
The Wizard could not use all of that. It needs to gather the information for *two* models (an
Application and a Provider, plus the ProviderType) and has a new and specialized end-point for a
transaction that allows the committing or roll back of both models to happen simultaneously,
predicated on success or failure respectively.
With "Extract `serializeForm` completed, it was possible to repurpose the forms that already
existed, stripping them down to just their input components, and eventing the entire thing in a
single event loop of "events flow up, data flows down." In this case, the *entire form* is
serialized on a per-event basis and pushed up the to the orchestration layer, which saves them off.
Writing a parent `BasePanel` class that has accessors for `formValues` and `valid` means that the
state of every page is accessible with a simple query. This simplified the `BaseProviderPanel` class
to just specialize the `dispatchUpdate` method to send the wizard update with the new provider
information filled out.
Because the *form* is being treated as the source of truth about the state of a `Partial<Application>`
or `Partial<*Provider>` object, the defaults are now being captured as expected.
Likewise, this simplified the `providerCache` layer which preserves customer input in the event that
the customer starts filling out the wrong provider to a simple conditional clause in the
orchestrator. The Wizard has much fewer smarts because it doesn't (and probably never did) need
them.
Along with the above changes, the following has also been done:
For SAML and SCIM, the providerMappings now works. They weren't being managed as `state` objects,
so they weren't receiving updates when the update event retrieved the information from the back-end.
In order to make clear what's happening, I have extracted the loops from the original definition and
built them as named objects: `propertyMappings`, `pmUserValues`, `pmGroupValues` and so on, which I
then pass into the new multi-select component.
I fixed a really embarrassing typo in Oauth2's "advanced settings" block.
I have extracted the CoreGroup search-select into a custom component.
I deleted the `merge` function. That was a faulty experiment with non-deterministic outcomes, and I
was never happy with it. I'm glad its gone.
I've added a title header to each of the providers, so the user can be sure that they're looking
at the right provider type when they start filling out the form.
I've created a new token, `data-ak-control`, with which we can mark all objects that we can treat as
Authentik value-producing components, the form value of which is available through a `json()`
method. I've added this bit of intelligence to the `serializeForm` function, short-circuiting the
complex processing and putting the "this is the shape of the value we expect from this input" *onto
the input itself*. Which is where it belongs.
* web: add error handling to wizard.
* web: improve error handling in light components
Rather than reproduce the error handling across all of the LightComponents,
I've made a parent class that takes the common fields to distribute between
the ak-form-element-horizontal and the input object itself. This made it
much easier to properly display errors in freeform input fields in the
wizard, as well as working with the routine error handling in Form.ts
* Added the radio control to the list of LightComponents.
* Fix bug where event was recorded twice.
* Fixed merge bug (?) that somehow deleted the Authorization Select block in OAuth2.
* web: prettier had opinions
* web: added error handling and display
* web: bump @lit-labs/context from 0.4.1 to 0.5.1 in /web
Bumps [@lit-labs/context](https://github.com/lit/lit/tree/HEAD/packages/labs/context) from 0.4.1 to 0.5.1.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/labs/context/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/@lit-labs/context@0.5.1/packages/labs/context)
---
updated-dependencies:
- dependency-name: "@lit-labs/context"
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
* web: updated wizard to run with latest package.json configuration
Apparently, there were stale dependencies in package-lock.json that were conflicting
with the requests in our package.json. By running `npm update`, I was able to resolve
the conflict.
I have also removed the default names from the context names collection; they weren't doing
any good, and they permit frictionless renaming of dependencies, which is never a good
idea.
* web: schlepping on the errors messages
During testing, I realized I was unhappy with the error messages. They're not very helpful.
By adding links to navigate back to the place where the error occurred, and providing better
context for what the error could have been, I hope to help the use correct their errors.
* make package the same as main
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-12-06 11:28:19 +00:00
</trans-unit>
2023-12-30 20:33:14 +00:00
<trans-unit id="sb108a06693c67753">
<source>No binding</source>
web/admin: revise wizard form handling (#7331)
* web: break circular dependency between AKElement & Interface.
This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.
I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.
* web: fix broken typescript references
This built... and then it didn't? Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.
* web: extract the form processing from the form submission process
Our forms have a lot of customized value handling, and the function `serializeForm` takes
our input structures and creates a JSON object ready for submission across the wire for
the various models provided by the API.
That function was embedded in the `ak-form` object, but it has no actual dependencies on
the state of that object; aside from identifying the input elements, which is done at the
very start of processing, this large block of code stands alone. Separating out the
"processing the form" from "identifying the form" allows us to customize our form handling
and preserve form information on the client for transactional purposes such as our wizard.
w
* web: multi-select, but there's a styling issue.
* web: provide a closed control for multi-select
This commit creates a new control, using the ak-form-element-horizontal as a *CLOSED*
object, for our multi-select. This control right now is limited to what we expect to
be using in the wizard, but that doesn't mean it can't be smarter in the future.
* web: hung up by a silly spelling error
* web: update the form-handling method
With the `serializeForm` method extracted, it's much easier to examine and parse
every *form* with every keystroke, preserving them against the changes that
happen as the customer navigates the Wizard. With that in place, it became
straightforward to retrofit the "handle changes to the application, to the provider, and to the providerType"
into the three pages of the wizard, and to provide *all* of the form elements in a base class
such that no specialized handling needs to happen to any of the child pages.
Fixed an ugly typo in the oauth2 provider, as well.
* web: wizard should work with multi-select and should reflect default values
(Note: This commit is predicated on both the "Extract serializeForm function from Form.ts" and
"Provide a controlled multi-select input control" PRs.)
The initial attempt at the wizard was woefully naive in its implementation, missing some critical
details along the way. This revision starts off with one stronger assumption: trust that Jens knows
what he's doing, and knew what he was building when he wrote the initial `Form` handler.
The problem with the `Form` handler, and the reason I avoided it, was simply that it does too many
things, especially in its ModelForm variant: it receives a model from the back-end, renders a
(hand-written) form for that model, allows the user to interact with that model, and facilitates
saving it to the back-end again, complete with on-page notifications of success or failure.
The Wizard could not use all of that. It needs to gather the information for *two* models (an
Application and a Provider, plus the ProviderType) and has a new and specialized end-point for a
transaction that allows the committing or roll back of both models to happen simultaneously,
predicated on success or failure respectively.
With "Extract `serializeForm` completed, it was possible to repurpose the forms that already
existed, stripping them down to just their input components, and eventing the entire thing in a
single event loop of "events flow up, data flows down." In this case, the *entire form* is
serialized on a per-event basis and pushed up the to the orchestration layer, which saves them off.
Writing a parent `BasePanel` class that has accessors for `formValues` and `valid` means that the
state of every page is accessible with a simple query. This simplified the `BaseProviderPanel` class
to just specialize the `dispatchUpdate` method to send the wizard update with the new provider
information filled out.
Because the *form* is being treated as the source of truth about the state of a `Partial<Application>`
or `Partial<*Provider>` object, the defaults are now being captured as expected.
Likewise, this simplified the `providerCache` layer which preserves customer input in the event that
the customer starts filling out the wrong provider to a simple conditional clause in the
orchestrator. The Wizard has much fewer smarts because it doesn't (and probably never did) need
them.
Along with the above changes, the following has also been done:
For SAML and SCIM, the providerMappings now works. They weren't being managed as `state` objects,
so they weren't receiving updates when the update event retrieved the information from the back-end.
In order to make clear what's happening, I have extracted the loops from the original definition and
built them as named objects: `propertyMappings`, `pmUserValues`, `pmGroupValues` and so on, which I
then pass into the new multi-select component.
I fixed a really embarrassing typo in Oauth2's "advanced settings" block.
I have extracted the CoreGroup search-select into a custom component.
I deleted the `merge` function. That was a faulty experiment with non-deterministic outcomes, and I
was never happy with it. I'm glad its gone.
I've added a title header to each of the providers, so the user can be sure that they're looking
at the right provider type when they start filling out the form.
I've created a new token, `data-ak-control`, with which we can mark all objects that we can treat as
Authentik value-producing components, the form value of which is available through a `json()`
method. I've added this bit of intelligence to the `serializeForm` function, short-circuiting the
complex processing and putting the "this is the shape of the value we expect from this input" *onto
the input itself*. Which is where it belongs.
* web: add error handling to wizard.
* web: improve error handling in light components
Rather than reproduce the error handling across all of the LightComponents,
I've made a parent class that takes the common fields to distribute between
the ak-form-element-horizontal and the input object itself. This made it
much easier to properly display errors in freeform input fields in the
wizard, as well as working with the routine error handling in Form.ts
* Added the radio control to the list of LightComponents.
* Fix bug where event was recorded twice.
* Fixed merge bug (?) that somehow deleted the Authorization Select block in OAuth2.
* web: prettier had opinions
* web: added error handling and display
* web: bump @lit-labs/context from 0.4.1 to 0.5.1 in /web
Bumps [@lit-labs/context](https://github.com/lit/lit/tree/HEAD/packages/labs/context) from 0.4.1 to 0.5.1.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/labs/context/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/@lit-labs/context@0.5.1/packages/labs/context)
---
updated-dependencies:
- dependency-name: "@lit-labs/context"
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
* web: updated wizard to run with latest package.json configuration
Apparently, there were stale dependencies in package-lock.json that were conflicting
with the requests in our package.json. By running `npm update`, I was able to resolve
the conflict.
I have also removed the default names from the context names collection; they weren't doing
any good, and they permit frictionless renaming of dependencies, which is never a good
idea.
* web: schlepping on the errors messages
During testing, I realized I was unhappy with the error messages. They're not very helpful.
By adding links to navigate back to the place where the error occurred, and providing better
context for what the error could have been, I hope to help the use correct their errors.
* make package the same as main
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-12-06 11:28:19 +00:00
</trans-unit>
2023-12-30 20:33:14 +00:00
<trans-unit id="s5aab90c74f1233b8">
<source>Bind ASN</source>
web/admin: revise wizard form handling (#7331)
* web: break circular dependency between AKElement & Interface.
This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.
I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.
* web: fix broken typescript references
This built... and then it didn't? Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.
* web: extract the form processing from the form submission process
Our forms have a lot of customized value handling, and the function `serializeForm` takes
our input structures and creates a JSON object ready for submission across the wire for
the various models provided by the API.
That function was embedded in the `ak-form` object, but it has no actual dependencies on
the state of that object; aside from identifying the input elements, which is done at the
very start of processing, this large block of code stands alone. Separating out the
"processing the form" from "identifying the form" allows us to customize our form handling
and preserve form information on the client for transactional purposes such as our wizard.
w
* web: multi-select, but there's a styling issue.
* web: provide a closed control for multi-select
This commit creates a new control, using the ak-form-element-horizontal as a *CLOSED*
object, for our multi-select. This control right now is limited to what we expect to
be using in the wizard, but that doesn't mean it can't be smarter in the future.
* web: hung up by a silly spelling error
* web: update the form-handling method
With the `serializeForm` method extracted, it's much easier to examine and parse
every *form* with every keystroke, preserving them against the changes that
happen as the customer navigates the Wizard. With that in place, it became
straightforward to retrofit the "handle changes to the application, to the provider, and to the providerType"
into the three pages of the wizard, and to provide *all* of the form elements in a base class
such that no specialized handling needs to happen to any of the child pages.
Fixed an ugly typo in the oauth2 provider, as well.
* web: wizard should work with multi-select and should reflect default values
(Note: This commit is predicated on both the "Extract serializeForm function from Form.ts" and
"Provide a controlled multi-select input control" PRs.)
The initial attempt at the wizard was woefully naive in its implementation, missing some critical
details along the way. This revision starts off with one stronger assumption: trust that Jens knows
what he's doing, and knew what he was building when he wrote the initial `Form` handler.
The problem with the `Form` handler, and the reason I avoided it, was simply that it does too many
things, especially in its ModelForm variant: it receives a model from the back-end, renders a
(hand-written) form for that model, allows the user to interact with that model, and facilitates
saving it to the back-end again, complete with on-page notifications of success or failure.
The Wizard could not use all of that. It needs to gather the information for *two* models (an
Application and a Provider, plus the ProviderType) and has a new and specialized end-point for a
transaction that allows the committing or roll back of both models to happen simultaneously,
predicated on success or failure respectively.
With "Extract `serializeForm` completed, it was possible to repurpose the forms that already
existed, stripping them down to just their input components, and eventing the entire thing in a
single event loop of "events flow up, data flows down." In this case, the *entire form* is
serialized on a per-event basis and pushed up the to the orchestration layer, which saves them off.
Writing a parent `BasePanel` class that has accessors for `formValues` and `valid` means that the
state of every page is accessible with a simple query. This simplified the `BaseProviderPanel` class
to just specialize the `dispatchUpdate` method to send the wizard update with the new provider
information filled out.
Because the *form* is being treated as the source of truth about the state of a `Partial<Application>`
or `Partial<*Provider>` object, the defaults are now being captured as expected.
Likewise, this simplified the `providerCache` layer which preserves customer input in the event that
the customer starts filling out the wrong provider to a simple conditional clause in the
orchestrator. The Wizard has much fewer smarts because it doesn't (and probably never did) need
them.
Along with the above changes, the following has also been done:
For SAML and SCIM, the providerMappings now works. They weren't being managed as `state` objects,
so they weren't receiving updates when the update event retrieved the information from the back-end.
In order to make clear what's happening, I have extracted the loops from the original definition and
built them as named objects: `propertyMappings`, `pmUserValues`, `pmGroupValues` and so on, which I
then pass into the new multi-select component.
I fixed a really embarrassing typo in Oauth2's "advanced settings" block.
I have extracted the CoreGroup search-select into a custom component.
I deleted the `merge` function. That was a faulty experiment with non-deterministic outcomes, and I
was never happy with it. I'm glad its gone.
I've added a title header to each of the providers, so the user can be sure that they're looking
at the right provider type when they start filling out the form.
I've created a new token, `data-ak-control`, with which we can mark all objects that we can treat as
Authentik value-producing components, the form value of which is available through a `json()`
method. I've added this bit of intelligence to the `serializeForm` function, short-circuiting the
complex processing and putting the "this is the shape of the value we expect from this input" *onto
the input itself*. Which is where it belongs.
* web: add error handling to wizard.
* web: improve error handling in light components
Rather than reproduce the error handling across all of the LightComponents,
I've made a parent class that takes the common fields to distribute between
the ak-form-element-horizontal and the input object itself. This made it
much easier to properly display errors in freeform input fields in the
wizard, as well as working with the routine error handling in Form.ts
* Added the radio control to the list of LightComponents.
* Fix bug where event was recorded twice.
* Fixed merge bug (?) that somehow deleted the Authorization Select block in OAuth2.
* web: prettier had opinions
* web: added error handling and display
* web: bump @lit-labs/context from 0.4.1 to 0.5.1 in /web
Bumps [@lit-labs/context](https://github.com/lit/lit/tree/HEAD/packages/labs/context) from 0.4.1 to 0.5.1.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/labs/context/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/@lit-labs/context@0.5.1/packages/labs/context)
---
updated-dependencies:
- dependency-name: "@lit-labs/context"
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
* web: updated wizard to run with latest package.json configuration
Apparently, there were stale dependencies in package-lock.json that were conflicting
with the requests in our package.json. By running `npm update`, I was able to resolve
the conflict.
I have also removed the default names from the context names collection; they weren't doing
any good, and they permit frictionless renaming of dependencies, which is never a good
idea.
* web: schlepping on the errors messages
During testing, I realized I was unhappy with the error messages. They're not very helpful.
By adding links to navigate back to the place where the error occurred, and providing better
context for what the error could have been, I hope to help the use correct their errors.
* make package the same as main
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-12-06 11:28:19 +00:00
</trans-unit>
2023-12-30 20:33:14 +00:00
<trans-unit id="s488303b048afe83b">
<source>Bind ASN and Network</source>
web/admin: revise wizard form handling (#7331)
* web: break circular dependency between AKElement & Interface.
This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.
I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.
* web: fix broken typescript references
This built... and then it didn't? Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.
* web: extract the form processing from the form submission process
Our forms have a lot of customized value handling, and the function `serializeForm` takes
our input structures and creates a JSON object ready for submission across the wire for
the various models provided by the API.
That function was embedded in the `ak-form` object, but it has no actual dependencies on
the state of that object; aside from identifying the input elements, which is done at the
very start of processing, this large block of code stands alone. Separating out the
"processing the form" from "identifying the form" allows us to customize our form handling
and preserve form information on the client for transactional purposes such as our wizard.
w
* web: multi-select, but there's a styling issue.
* web: provide a closed control for multi-select
This commit creates a new control, using the ak-form-element-horizontal as a *CLOSED*
object, for our multi-select. This control right now is limited to what we expect to
be using in the wizard, but that doesn't mean it can't be smarter in the future.
* web: hung up by a silly spelling error
* web: update the form-handling method
With the `serializeForm` method extracted, it's much easier to examine and parse
every *form* with every keystroke, preserving them against the changes that
happen as the customer navigates the Wizard. With that in place, it became
straightforward to retrofit the "handle changes to the application, to the provider, and to the providerType"
into the three pages of the wizard, and to provide *all* of the form elements in a base class
such that no specialized handling needs to happen to any of the child pages.
Fixed an ugly typo in the oauth2 provider, as well.
* web: wizard should work with multi-select and should reflect default values
(Note: This commit is predicated on both the "Extract serializeForm function from Form.ts" and
"Provide a controlled multi-select input control" PRs.)
The initial attempt at the wizard was woefully naive in its implementation, missing some critical
details along the way. This revision starts off with one stronger assumption: trust that Jens knows
what he's doing, and knew what he was building when he wrote the initial `Form` handler.
The problem with the `Form` handler, and the reason I avoided it, was simply that it does too many
things, especially in its ModelForm variant: it receives a model from the back-end, renders a
(hand-written) form for that model, allows the user to interact with that model, and facilitates
saving it to the back-end again, complete with on-page notifications of success or failure.
The Wizard could not use all of that. It needs to gather the information for *two* models (an
Application and a Provider, plus the ProviderType) and has a new and specialized end-point for a
transaction that allows the committing or roll back of both models to happen simultaneously,
predicated on success or failure respectively.
With "Extract `serializeForm` completed, it was possible to repurpose the forms that already
existed, stripping them down to just their input components, and eventing the entire thing in a
single event loop of "events flow up, data flows down." In this case, the *entire form* is
serialized on a per-event basis and pushed up the to the orchestration layer, which saves them off.
Writing a parent `BasePanel` class that has accessors for `formValues` and `valid` means that the
state of every page is accessible with a simple query. This simplified the `BaseProviderPanel` class
to just specialize the `dispatchUpdate` method to send the wizard update with the new provider
information filled out.
Because the *form* is being treated as the source of truth about the state of a `Partial<Application>`
or `Partial<*Provider>` object, the defaults are now being captured as expected.
Likewise, this simplified the `providerCache` layer which preserves customer input in the event that
the customer starts filling out the wrong provider to a simple conditional clause in the
orchestrator. The Wizard has much fewer smarts because it doesn't (and probably never did) need
them.
Along with the above changes, the following has also been done:
For SAML and SCIM, the providerMappings now works. They weren't being managed as `state` objects,
so they weren't receiving updates when the update event retrieved the information from the back-end.
In order to make clear what's happening, I have extracted the loops from the original definition and
built them as named objects: `propertyMappings`, `pmUserValues`, `pmGroupValues` and so on, which I
then pass into the new multi-select component.
I fixed a really embarrassing typo in Oauth2's "advanced settings" block.
I have extracted the CoreGroup search-select into a custom component.
I deleted the `merge` function. That was a faulty experiment with non-deterministic outcomes, and I
was never happy with it. I'm glad its gone.
I've added a title header to each of the providers, so the user can be sure that they're looking
at the right provider type when they start filling out the form.
I've created a new token, `data-ak-control`, with which we can mark all objects that we can treat as
Authentik value-producing components, the form value of which is available through a `json()`
method. I've added this bit of intelligence to the `serializeForm` function, short-circuiting the
complex processing and putting the "this is the shape of the value we expect from this input" *onto
the input itself*. Which is where it belongs.
* web: add error handling to wizard.
* web: improve error handling in light components
Rather than reproduce the error handling across all of the LightComponents,
I've made a parent class that takes the common fields to distribute between
the ak-form-element-horizontal and the input object itself. This made it
much easier to properly display errors in freeform input fields in the
wizard, as well as working with the routine error handling in Form.ts
* Added the radio control to the list of LightComponents.
* Fix bug where event was recorded twice.
* Fixed merge bug (?) that somehow deleted the Authorization Select block in OAuth2.
* web: prettier had opinions
* web: added error handling and display
* web: bump @lit-labs/context from 0.4.1 to 0.5.1 in /web
Bumps [@lit-labs/context](https://github.com/lit/lit/tree/HEAD/packages/labs/context) from 0.4.1 to 0.5.1.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/labs/context/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/@lit-labs/context@0.5.1/packages/labs/context)
---
updated-dependencies:
- dependency-name: "@lit-labs/context"
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
* web: updated wizard to run with latest package.json configuration
Apparently, there were stale dependencies in package-lock.json that were conflicting
with the requests in our package.json. By running `npm update`, I was able to resolve
the conflict.
I have also removed the default names from the context names collection; they weren't doing
any good, and they permit frictionless renaming of dependencies, which is never a good
idea.
* web: schlepping on the errors messages
During testing, I realized I was unhappy with the error messages. They're not very helpful.
By adding links to navigate back to the place where the error occurred, and providing better
context for what the error could have been, I hope to help the use correct their errors.
* make package the same as main
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-12-06 11:28:19 +00:00
</trans-unit>
2023-12-30 20:33:14 +00:00
<trans-unit id="s3268dcfe0c8234dc">
<source>Bind ASN, Network and IP</source>
web/admin: revise wizard form handling (#7331)
* web: break circular dependency between AKElement & Interface.
This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.
I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.
* web: fix broken typescript references
This built... and then it didn't? Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.
* web: extract the form processing from the form submission process
Our forms have a lot of customized value handling, and the function `serializeForm` takes
our input structures and creates a JSON object ready for submission across the wire for
the various models provided by the API.
That function was embedded in the `ak-form` object, but it has no actual dependencies on
the state of that object; aside from identifying the input elements, which is done at the
very start of processing, this large block of code stands alone. Separating out the
"processing the form" from "identifying the form" allows us to customize our form handling
and preserve form information on the client for transactional purposes such as our wizard.
w
* web: multi-select, but there's a styling issue.
* web: provide a closed control for multi-select
This commit creates a new control, using the ak-form-element-horizontal as a *CLOSED*
object, for our multi-select. This control right now is limited to what we expect to
be using in the wizard, but that doesn't mean it can't be smarter in the future.
* web: hung up by a silly spelling error
* web: update the form-handling method
With the `serializeForm` method extracted, it's much easier to examine and parse
every *form* with every keystroke, preserving them against the changes that
happen as the customer navigates the Wizard. With that in place, it became
straightforward to retrofit the "handle changes to the application, to the provider, and to the providerType"
into the three pages of the wizard, and to provide *all* of the form elements in a base class
such that no specialized handling needs to happen to any of the child pages.
Fixed an ugly typo in the oauth2 provider, as well.
* web: wizard should work with multi-select and should reflect default values
(Note: This commit is predicated on both the "Extract serializeForm function from Form.ts" and
"Provide a controlled multi-select input control" PRs.)
The initial attempt at the wizard was woefully naive in its implementation, missing some critical
details along the way. This revision starts off with one stronger assumption: trust that Jens knows
what he's doing, and knew what he was building when he wrote the initial `Form` handler.
The problem with the `Form` handler, and the reason I avoided it, was simply that it does too many
things, especially in its ModelForm variant: it receives a model from the back-end, renders a
(hand-written) form for that model, allows the user to interact with that model, and facilitates
saving it to the back-end again, complete with on-page notifications of success or failure.
The Wizard could not use all of that. It needs to gather the information for *two* models (an
Application and a Provider, plus the ProviderType) and has a new and specialized end-point for a
transaction that allows the committing or roll back of both models to happen simultaneously,
predicated on success or failure respectively.
With "Extract `serializeForm` completed, it was possible to repurpose the forms that already
existed, stripping them down to just their input components, and eventing the entire thing in a
single event loop of "events flow up, data flows down." In this case, the *entire form* is
serialized on a per-event basis and pushed up the to the orchestration layer, which saves them off.
Writing a parent `BasePanel` class that has accessors for `formValues` and `valid` means that the
state of every page is accessible with a simple query. This simplified the `BaseProviderPanel` class
to just specialize the `dispatchUpdate` method to send the wizard update with the new provider
information filled out.
Because the *form* is being treated as the source of truth about the state of a `Partial<Application>`
or `Partial<*Provider>` object, the defaults are now being captured as expected.
Likewise, this simplified the `providerCache` layer which preserves customer input in the event that
the customer starts filling out the wrong provider to a simple conditional clause in the
orchestrator. The Wizard has much fewer smarts because it doesn't (and probably never did) need
them.
Along with the above changes, the following has also been done:
For SAML and SCIM, the providerMappings now works. They weren't being managed as `state` objects,
so they weren't receiving updates when the update event retrieved the information from the back-end.
In order to make clear what's happening, I have extracted the loops from the original definition and
built them as named objects: `propertyMappings`, `pmUserValues`, `pmGroupValues` and so on, which I
then pass into the new multi-select component.
I fixed a really embarrassing typo in Oauth2's "advanced settings" block.
I have extracted the CoreGroup search-select into a custom component.
I deleted the `merge` function. That was a faulty experiment with non-deterministic outcomes, and I
was never happy with it. I'm glad its gone.
I've added a title header to each of the providers, so the user can be sure that they're looking
at the right provider type when they start filling out the form.
I've created a new token, `data-ak-control`, with which we can mark all objects that we can treat as
Authentik value-producing components, the form value of which is available through a `json()`
method. I've added this bit of intelligence to the `serializeForm` function, short-circuiting the
complex processing and putting the "this is the shape of the value we expect from this input" *onto
the input itself*. Which is where it belongs.
* web: add error handling to wizard.
* web: improve error handling in light components
Rather than reproduce the error handling across all of the LightComponents,
I've made a parent class that takes the common fields to distribute between
the ak-form-element-horizontal and the input object itself. This made it
much easier to properly display errors in freeform input fields in the
wizard, as well as working with the routine error handling in Form.ts
* Added the radio control to the list of LightComponents.
* Fix bug where event was recorded twice.
* Fixed merge bug (?) that somehow deleted the Authorization Select block in OAuth2.
* web: prettier had opinions
* web: added error handling and display
* web: bump @lit-labs/context from 0.4.1 to 0.5.1 in /web
Bumps [@lit-labs/context](https://github.com/lit/lit/tree/HEAD/packages/labs/context) from 0.4.1 to 0.5.1.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/labs/context/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/@lit-labs/context@0.5.1/packages/labs/context)
---
updated-dependencies:
- dependency-name: "@lit-labs/context"
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
* web: updated wizard to run with latest package.json configuration
Apparently, there were stale dependencies in package-lock.json that were conflicting
with the requests in our package.json. By running `npm update`, I was able to resolve
the conflict.
I have also removed the default names from the context names collection; they weren't doing
any good, and they permit frictionless renaming of dependencies, which is never a good
idea.
* web: schlepping on the errors messages
During testing, I realized I was unhappy with the error messages. They're not very helpful.
By adding links to navigate back to the place where the error occurred, and providing better
context for what the error could have been, I hope to help the use correct their errors.
* make package the same as main
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-12-06 11:28:19 +00:00
</trans-unit>
2023-12-30 20:33:14 +00:00
<trans-unit id="s226381aca231644f">
<source>Configure if sessions created by this stage should be bound to the Networks they were created in.</source>
web/admin: revise wizard form handling (#7331)
* web: break circular dependency between AKElement & Interface.
This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.
I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.
* web: fix broken typescript references
This built... and then it didn't? Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.
* web: extract the form processing from the form submission process
Our forms have a lot of customized value handling, and the function `serializeForm` takes
our input structures and creates a JSON object ready for submission across the wire for
the various models provided by the API.
That function was embedded in the `ak-form` object, but it has no actual dependencies on
the state of that object; aside from identifying the input elements, which is done at the
very start of processing, this large block of code stands alone. Separating out the
"processing the form" from "identifying the form" allows us to customize our form handling
and preserve form information on the client for transactional purposes such as our wizard.
w
* web: multi-select, but there's a styling issue.
* web: provide a closed control for multi-select
This commit creates a new control, using the ak-form-element-horizontal as a *CLOSED*
object, for our multi-select. This control right now is limited to what we expect to
be using in the wizard, but that doesn't mean it can't be smarter in the future.
* web: hung up by a silly spelling error
* web: update the form-handling method
With the `serializeForm` method extracted, it's much easier to examine and parse
every *form* with every keystroke, preserving them against the changes that
happen as the customer navigates the Wizard. With that in place, it became
straightforward to retrofit the "handle changes to the application, to the provider, and to the providerType"
into the three pages of the wizard, and to provide *all* of the form elements in a base class
such that no specialized handling needs to happen to any of the child pages.
Fixed an ugly typo in the oauth2 provider, as well.
* web: wizard should work with multi-select and should reflect default values
(Note: This commit is predicated on both the "Extract serializeForm function from Form.ts" and
"Provide a controlled multi-select input control" PRs.)
The initial attempt at the wizard was woefully naive in its implementation, missing some critical
details along the way. This revision starts off with one stronger assumption: trust that Jens knows
what he's doing, and knew what he was building when he wrote the initial `Form` handler.
The problem with the `Form` handler, and the reason I avoided it, was simply that it does too many
things, especially in its ModelForm variant: it receives a model from the back-end, renders a
(hand-written) form for that model, allows the user to interact with that model, and facilitates
saving it to the back-end again, complete with on-page notifications of success or failure.
The Wizard could not use all of that. It needs to gather the information for *two* models (an
Application and a Provider, plus the ProviderType) and has a new and specialized end-point for a
transaction that allows the committing or roll back of both models to happen simultaneously,
predicated on success or failure respectively.
With "Extract `serializeForm` completed, it was possible to repurpose the forms that already
existed, stripping them down to just their input components, and eventing the entire thing in a
single event loop of "events flow up, data flows down." In this case, the *entire form* is
serialized on a per-event basis and pushed up the to the orchestration layer, which saves them off.
Writing a parent `BasePanel` class that has accessors for `formValues` and `valid` means that the
state of every page is accessible with a simple query. This simplified the `BaseProviderPanel` class
to just specialize the `dispatchUpdate` method to send the wizard update with the new provider
information filled out.
Because the *form* is being treated as the source of truth about the state of a `Partial<Application>`
or `Partial<*Provider>` object, the defaults are now being captured as expected.
Likewise, this simplified the `providerCache` layer which preserves customer input in the event that
the customer starts filling out the wrong provider to a simple conditional clause in the
orchestrator. The Wizard has much fewer smarts because it doesn't (and probably never did) need
them.
Along with the above changes, the following has also been done:
For SAML and SCIM, the providerMappings now works. They weren't being managed as `state` objects,
so they weren't receiving updates when the update event retrieved the information from the back-end.
In order to make clear what's happening, I have extracted the loops from the original definition and
built them as named objects: `propertyMappings`, `pmUserValues`, `pmGroupValues` and so on, which I
then pass into the new multi-select component.
I fixed a really embarrassing typo in Oauth2's "advanced settings" block.
I have extracted the CoreGroup search-select into a custom component.
I deleted the `merge` function. That was a faulty experiment with non-deterministic outcomes, and I
was never happy with it. I'm glad its gone.
I've added a title header to each of the providers, so the user can be sure that they're looking
at the right provider type when they start filling out the form.
I've created a new token, `data-ak-control`, with which we can mark all objects that we can treat as
Authentik value-producing components, the form value of which is available through a `json()`
method. I've added this bit of intelligence to the `serializeForm` function, short-circuiting the
complex processing and putting the "this is the shape of the value we expect from this input" *onto
the input itself*. Which is where it belongs.
* web: add error handling to wizard.
* web: improve error handling in light components
Rather than reproduce the error handling across all of the LightComponents,
I've made a parent class that takes the common fields to distribute between
the ak-form-element-horizontal and the input object itself. This made it
much easier to properly display errors in freeform input fields in the
wizard, as well as working with the routine error handling in Form.ts
* Added the radio control to the list of LightComponents.
* Fix bug where event was recorded twice.
* Fixed merge bug (?) that somehow deleted the Authorization Select block in OAuth2.
* web: prettier had opinions
* web: added error handling and display
* web: bump @lit-labs/context from 0.4.1 to 0.5.1 in /web
Bumps [@lit-labs/context](https://github.com/lit/lit/tree/HEAD/packages/labs/context) from 0.4.1 to 0.5.1.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/labs/context/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/@lit-labs/context@0.5.1/packages/labs/context)
---
updated-dependencies:
- dependency-name: "@lit-labs/context"
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
* web: updated wizard to run with latest package.json configuration
Apparently, there were stale dependencies in package-lock.json that were conflicting
with the requests in our package.json. By running `npm update`, I was able to resolve
the conflict.
I have also removed the default names from the context names collection; they weren't doing
any good, and they permit frictionless renaming of dependencies, which is never a good
idea.
* web: schlepping on the errors messages
During testing, I realized I was unhappy with the error messages. They're not very helpful.
By adding links to navigate back to the place where the error occurred, and providing better
context for what the error could have been, I hope to help the use correct their errors.
* make package the same as main
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-12-06 11:28:19 +00:00
</trans-unit>
2023-12-30 20:33:14 +00:00
<trans-unit id="s2555a1f20f3fd93e">
<source>GeoIP binding</source>
web/admin: revise wizard form handling (#7331)
* web: break circular dependency between AKElement & Interface.
This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.
I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.
* web: fix broken typescript references
This built... and then it didn't? Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.
* web: extract the form processing from the form submission process
Our forms have a lot of customized value handling, and the function `serializeForm` takes
our input structures and creates a JSON object ready for submission across the wire for
the various models provided by the API.
That function was embedded in the `ak-form` object, but it has no actual dependencies on
the state of that object; aside from identifying the input elements, which is done at the
very start of processing, this large block of code stands alone. Separating out the
"processing the form" from "identifying the form" allows us to customize our form handling
and preserve form information on the client for transactional purposes such as our wizard.
w
* web: multi-select, but there's a styling issue.
* web: provide a closed control for multi-select
This commit creates a new control, using the ak-form-element-horizontal as a *CLOSED*
object, for our multi-select. This control right now is limited to what we expect to
be using in the wizard, but that doesn't mean it can't be smarter in the future.
* web: hung up by a silly spelling error
* web: update the form-handling method
With the `serializeForm` method extracted, it's much easier to examine and parse
every *form* with every keystroke, preserving them against the changes that
happen as the customer navigates the Wizard. With that in place, it became
straightforward to retrofit the "handle changes to the application, to the provider, and to the providerType"
into the three pages of the wizard, and to provide *all* of the form elements in a base class
such that no specialized handling needs to happen to any of the child pages.
Fixed an ugly typo in the oauth2 provider, as well.
* web: wizard should work with multi-select and should reflect default values
(Note: This commit is predicated on both the "Extract serializeForm function from Form.ts" and
"Provide a controlled multi-select input control" PRs.)
The initial attempt at the wizard was woefully naive in its implementation, missing some critical
details along the way. This revision starts off with one stronger assumption: trust that Jens knows
what he's doing, and knew what he was building when he wrote the initial `Form` handler.
The problem with the `Form` handler, and the reason I avoided it, was simply that it does too many
things, especially in its ModelForm variant: it receives a model from the back-end, renders a
(hand-written) form for that model, allows the user to interact with that model, and facilitates
saving it to the back-end again, complete with on-page notifications of success or failure.
The Wizard could not use all of that. It needs to gather the information for *two* models (an
Application and a Provider, plus the ProviderType) and has a new and specialized end-point for a
transaction that allows the committing or roll back of both models to happen simultaneously,
predicated on success or failure respectively.
With "Extract `serializeForm` completed, it was possible to repurpose the forms that already
existed, stripping them down to just their input components, and eventing the entire thing in a
single event loop of "events flow up, data flows down." In this case, the *entire form* is
serialized on a per-event basis and pushed up the to the orchestration layer, which saves them off.
Writing a parent `BasePanel` class that has accessors for `formValues` and `valid` means that the
state of every page is accessible with a simple query. This simplified the `BaseProviderPanel` class
to just specialize the `dispatchUpdate` method to send the wizard update with the new provider
information filled out.
Because the *form* is being treated as the source of truth about the state of a `Partial<Application>`
or `Partial<*Provider>` object, the defaults are now being captured as expected.
Likewise, this simplified the `providerCache` layer which preserves customer input in the event that
the customer starts filling out the wrong provider to a simple conditional clause in the
orchestrator. The Wizard has much fewer smarts because it doesn't (and probably never did) need
them.
Along with the above changes, the following has also been done:
For SAML and SCIM, the providerMappings now works. They weren't being managed as `state` objects,
so they weren't receiving updates when the update event retrieved the information from the back-end.
In order to make clear what's happening, I have extracted the loops from the original definition and
built them as named objects: `propertyMappings`, `pmUserValues`, `pmGroupValues` and so on, which I
then pass into the new multi-select component.
I fixed a really embarrassing typo in Oauth2's "advanced settings" block.
I have extracted the CoreGroup search-select into a custom component.
I deleted the `merge` function. That was a faulty experiment with non-deterministic outcomes, and I
was never happy with it. I'm glad its gone.
I've added a title header to each of the providers, so the user can be sure that they're looking
at the right provider type when they start filling out the form.
I've created a new token, `data-ak-control`, with which we can mark all objects that we can treat as
Authentik value-producing components, the form value of which is available through a `json()`
method. I've added this bit of intelligence to the `serializeForm` function, short-circuiting the
complex processing and putting the "this is the shape of the value we expect from this input" *onto
the input itself*. Which is where it belongs.
* web: add error handling to wizard.
* web: improve error handling in light components
Rather than reproduce the error handling across all of the LightComponents,
I've made a parent class that takes the common fields to distribute between
the ak-form-element-horizontal and the input object itself. This made it
much easier to properly display errors in freeform input fields in the
wizard, as well as working with the routine error handling in Form.ts
* Added the radio control to the list of LightComponents.
* Fix bug where event was recorded twice.
* Fixed merge bug (?) that somehow deleted the Authorization Select block in OAuth2.
* web: prettier had opinions
* web: added error handling and display
* web: bump @lit-labs/context from 0.4.1 to 0.5.1 in /web
Bumps [@lit-labs/context](https://github.com/lit/lit/tree/HEAD/packages/labs/context) from 0.4.1 to 0.5.1.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/labs/context/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/@lit-labs/context@0.5.1/packages/labs/context)
---
updated-dependencies:
- dependency-name: "@lit-labs/context"
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
* web: updated wizard to run with latest package.json configuration
Apparently, there were stale dependencies in package-lock.json that were conflicting
with the requests in our package.json. By running `npm update`, I was able to resolve
the conflict.
I have also removed the default names from the context names collection; they weren't doing
any good, and they permit frictionless renaming of dependencies, which is never a good
idea.
* web: schlepping on the errors messages
During testing, I realized I was unhappy with the error messages. They're not very helpful.
By adding links to navigate back to the place where the error occurred, and providing better
context for what the error could have been, I hope to help the use correct their errors.
* make package the same as main
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-12-06 11:28:19 +00:00
</trans-unit>
2023-12-30 20:33:14 +00:00
<trans-unit id="s3d63c78f93c9a92e">
<source>Bind Continent</source>
web/admin: revise wizard form handling (#7331)
* web: break circular dependency between AKElement & Interface.
This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.
I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.
* web: fix broken typescript references
This built... and then it didn't? Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.
* web: extract the form processing from the form submission process
Our forms have a lot of customized value handling, and the function `serializeForm` takes
our input structures and creates a JSON object ready for submission across the wire for
the various models provided by the API.
That function was embedded in the `ak-form` object, but it has no actual dependencies on
the state of that object; aside from identifying the input elements, which is done at the
very start of processing, this large block of code stands alone. Separating out the
"processing the form" from "identifying the form" allows us to customize our form handling
and preserve form information on the client for transactional purposes such as our wizard.
w
* web: multi-select, but there's a styling issue.
* web: provide a closed control for multi-select
This commit creates a new control, using the ak-form-element-horizontal as a *CLOSED*
object, for our multi-select. This control right now is limited to what we expect to
be using in the wizard, but that doesn't mean it can't be smarter in the future.
* web: hung up by a silly spelling error
* web: update the form-handling method
With the `serializeForm` method extracted, it's much easier to examine and parse
every *form* with every keystroke, preserving them against the changes that
happen as the customer navigates the Wizard. With that in place, it became
straightforward to retrofit the "handle changes to the application, to the provider, and to the providerType"
into the three pages of the wizard, and to provide *all* of the form elements in a base class
such that no specialized handling needs to happen to any of the child pages.
Fixed an ugly typo in the oauth2 provider, as well.
* web: wizard should work with multi-select and should reflect default values
(Note: This commit is predicated on both the "Extract serializeForm function from Form.ts" and
"Provide a controlled multi-select input control" PRs.)
The initial attempt at the wizard was woefully naive in its implementation, missing some critical
details along the way. This revision starts off with one stronger assumption: trust that Jens knows
what he's doing, and knew what he was building when he wrote the initial `Form` handler.
The problem with the `Form` handler, and the reason I avoided it, was simply that it does too many
things, especially in its ModelForm variant: it receives a model from the back-end, renders a
(hand-written) form for that model, allows the user to interact with that model, and facilitates
saving it to the back-end again, complete with on-page notifications of success or failure.
The Wizard could not use all of that. It needs to gather the information for *two* models (an
Application and a Provider, plus the ProviderType) and has a new and specialized end-point for a
transaction that allows the committing or roll back of both models to happen simultaneously,
predicated on success or failure respectively.
With "Extract `serializeForm` completed, it was possible to repurpose the forms that already
existed, stripping them down to just their input components, and eventing the entire thing in a
single event loop of "events flow up, data flows down." In this case, the *entire form* is
serialized on a per-event basis and pushed up the to the orchestration layer, which saves them off.
Writing a parent `BasePanel` class that has accessors for `formValues` and `valid` means that the
state of every page is accessible with a simple query. This simplified the `BaseProviderPanel` class
to just specialize the `dispatchUpdate` method to send the wizard update with the new provider
information filled out.
Because the *form* is being treated as the source of truth about the state of a `Partial<Application>`
or `Partial<*Provider>` object, the defaults are now being captured as expected.
Likewise, this simplified the `providerCache` layer which preserves customer input in the event that
the customer starts filling out the wrong provider to a simple conditional clause in the
orchestrator. The Wizard has much fewer smarts because it doesn't (and probably never did) need
them.
Along with the above changes, the following has also been done:
For SAML and SCIM, the providerMappings now works. They weren't being managed as `state` objects,
so they weren't receiving updates when the update event retrieved the information from the back-end.
In order to make clear what's happening, I have extracted the loops from the original definition and
built them as named objects: `propertyMappings`, `pmUserValues`, `pmGroupValues` and so on, which I
then pass into the new multi-select component.
I fixed a really embarrassing typo in Oauth2's "advanced settings" block.
I have extracted the CoreGroup search-select into a custom component.
I deleted the `merge` function. That was a faulty experiment with non-deterministic outcomes, and I
was never happy with it. I'm glad its gone.
I've added a title header to each of the providers, so the user can be sure that they're looking
at the right provider type when they start filling out the form.
I've created a new token, `data-ak-control`, with which we can mark all objects that we can treat as
Authentik value-producing components, the form value of which is available through a `json()`
method. I've added this bit of intelligence to the `serializeForm` function, short-circuiting the
complex processing and putting the "this is the shape of the value we expect from this input" *onto
the input itself*. Which is where it belongs.
* web: add error handling to wizard.
* web: improve error handling in light components
Rather than reproduce the error handling across all of the LightComponents,
I've made a parent class that takes the common fields to distribute between
the ak-form-element-horizontal and the input object itself. This made it
much easier to properly display errors in freeform input fields in the
wizard, as well as working with the routine error handling in Form.ts
* Added the radio control to the list of LightComponents.
* Fix bug where event was recorded twice.
* Fixed merge bug (?) that somehow deleted the Authorization Select block in OAuth2.
* web: prettier had opinions
* web: added error handling and display
* web: bump @lit-labs/context from 0.4.1 to 0.5.1 in /web
Bumps [@lit-labs/context](https://github.com/lit/lit/tree/HEAD/packages/labs/context) from 0.4.1 to 0.5.1.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/labs/context/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/@lit-labs/context@0.5.1/packages/labs/context)
---
updated-dependencies:
- dependency-name: "@lit-labs/context"
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
* web: updated wizard to run with latest package.json configuration
Apparently, there were stale dependencies in package-lock.json that were conflicting
with the requests in our package.json. By running `npm update`, I was able to resolve
the conflict.
I have also removed the default names from the context names collection; they weren't doing
any good, and they permit frictionless renaming of dependencies, which is never a good
idea.
* web: schlepping on the errors messages
During testing, I realized I was unhappy with the error messages. They're not very helpful.
By adding links to navigate back to the place where the error occurred, and providing better
context for what the error could have been, I hope to help the use correct their errors.
* make package the same as main
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-12-06 11:28:19 +00:00
</trans-unit>
2023-12-30 20:33:14 +00:00
<trans-unit id="s395d5863b3a259b5">
<source>Bind Continent and Country</source>
web/admin: revise wizard form handling (#7331)
* web: break circular dependency between AKElement & Interface.
This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.
I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.
* web: fix broken typescript references
This built... and then it didn't? Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.
* web: extract the form processing from the form submission process
Our forms have a lot of customized value handling, and the function `serializeForm` takes
our input structures and creates a JSON object ready for submission across the wire for
the various models provided by the API.
That function was embedded in the `ak-form` object, but it has no actual dependencies on
the state of that object; aside from identifying the input elements, which is done at the
very start of processing, this large block of code stands alone. Separating out the
"processing the form" from "identifying the form" allows us to customize our form handling
and preserve form information on the client for transactional purposes such as our wizard.
w
* web: multi-select, but there's a styling issue.
* web: provide a closed control for multi-select
This commit creates a new control, using the ak-form-element-horizontal as a *CLOSED*
object, for our multi-select. This control right now is limited to what we expect to
be using in the wizard, but that doesn't mean it can't be smarter in the future.
* web: hung up by a silly spelling error
* web: update the form-handling method
With the `serializeForm` method extracted, it's much easier to examine and parse
every *form* with every keystroke, preserving them against the changes that
happen as the customer navigates the Wizard. With that in place, it became
straightforward to retrofit the "handle changes to the application, to the provider, and to the providerType"
into the three pages of the wizard, and to provide *all* of the form elements in a base class
such that no specialized handling needs to happen to any of the child pages.
Fixed an ugly typo in the oauth2 provider, as well.
* web: wizard should work with multi-select and should reflect default values
(Note: This commit is predicated on both the "Extract serializeForm function from Form.ts" and
"Provide a controlled multi-select input control" PRs.)
The initial attempt at the wizard was woefully naive in its implementation, missing some critical
details along the way. This revision starts off with one stronger assumption: trust that Jens knows
what he's doing, and knew what he was building when he wrote the initial `Form` handler.
The problem with the `Form` handler, and the reason I avoided it, was simply that it does too many
things, especially in its ModelForm variant: it receives a model from the back-end, renders a
(hand-written) form for that model, allows the user to interact with that model, and facilitates
saving it to the back-end again, complete with on-page notifications of success or failure.
The Wizard could not use all of that. It needs to gather the information for *two* models (an
Application and a Provider, plus the ProviderType) and has a new and specialized end-point for a
transaction that allows the committing or roll back of both models to happen simultaneously,
predicated on success or failure respectively.
With "Extract `serializeForm` completed, it was possible to repurpose the forms that already
existed, stripping them down to just their input components, and eventing the entire thing in a
single event loop of "events flow up, data flows down." In this case, the *entire form* is
serialized on a per-event basis and pushed up the to the orchestration layer, which saves them off.
Writing a parent `BasePanel` class that has accessors for `formValues` and `valid` means that the
state of every page is accessible with a simple query. This simplified the `BaseProviderPanel` class
to just specialize the `dispatchUpdate` method to send the wizard update with the new provider
information filled out.
Because the *form* is being treated as the source of truth about the state of a `Partial<Application>`
or `Partial<*Provider>` object, the defaults are now being captured as expected.
Likewise, this simplified the `providerCache` layer which preserves customer input in the event that
the customer starts filling out the wrong provider to a simple conditional clause in the
orchestrator. The Wizard has much fewer smarts because it doesn't (and probably never did) need
them.
Along with the above changes, the following has also been done:
For SAML and SCIM, the providerMappings now works. They weren't being managed as `state` objects,
so they weren't receiving updates when the update event retrieved the information from the back-end.
In order to make clear what's happening, I have extracted the loops from the original definition and
built them as named objects: `propertyMappings`, `pmUserValues`, `pmGroupValues` and so on, which I
then pass into the new multi-select component.
I fixed a really embarrassing typo in Oauth2's "advanced settings" block.
I have extracted the CoreGroup search-select into a custom component.
I deleted the `merge` function. That was a faulty experiment with non-deterministic outcomes, and I
was never happy with it. I'm glad its gone.
I've added a title header to each of the providers, so the user can be sure that they're looking
at the right provider type when they start filling out the form.
I've created a new token, `data-ak-control`, with which we can mark all objects that we can treat as
Authentik value-producing components, the form value of which is available through a `json()`
method. I've added this bit of intelligence to the `serializeForm` function, short-circuiting the
complex processing and putting the "this is the shape of the value we expect from this input" *onto
the input itself*. Which is where it belongs.
* web: add error handling to wizard.
* web: improve error handling in light components
Rather than reproduce the error handling across all of the LightComponents,
I've made a parent class that takes the common fields to distribute between
the ak-form-element-horizontal and the input object itself. This made it
much easier to properly display errors in freeform input fields in the
wizard, as well as working with the routine error handling in Form.ts
* Added the radio control to the list of LightComponents.
* Fix bug where event was recorded twice.
* Fixed merge bug (?) that somehow deleted the Authorization Select block in OAuth2.
* web: prettier had opinions
* web: added error handling and display
* web: bump @lit-labs/context from 0.4.1 to 0.5.1 in /web
Bumps [@lit-labs/context](https://github.com/lit/lit/tree/HEAD/packages/labs/context) from 0.4.1 to 0.5.1.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/labs/context/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/@lit-labs/context@0.5.1/packages/labs/context)
---
updated-dependencies:
- dependency-name: "@lit-labs/context"
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
* web: updated wizard to run with latest package.json configuration
Apparently, there were stale dependencies in package-lock.json that were conflicting
with the requests in our package.json. By running `npm update`, I was able to resolve
the conflict.
I have also removed the default names from the context names collection; they weren't doing
any good, and they permit frictionless renaming of dependencies, which is never a good
idea.
* web: schlepping on the errors messages
During testing, I realized I was unhappy with the error messages. They're not very helpful.
By adding links to navigate back to the place where the error occurred, and providing better
context for what the error could have been, I hope to help the use correct their errors.
* make package the same as main
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-12-06 11:28:19 +00:00
</trans-unit>
2023-12-30 20:33:14 +00:00
<trans-unit id="s625ea0c32b4b136c">
<source>Bind Continent, Country and City</source>
web/admin: revise wizard form handling (#7331)
* web: break circular dependency between AKElement & Interface.
This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.
I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.
* web: fix broken typescript references
This built... and then it didn't? Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.
* web: extract the form processing from the form submission process
Our forms have a lot of customized value handling, and the function `serializeForm` takes
our input structures and creates a JSON object ready for submission across the wire for
the various models provided by the API.
That function was embedded in the `ak-form` object, but it has no actual dependencies on
the state of that object; aside from identifying the input elements, which is done at the
very start of processing, this large block of code stands alone. Separating out the
"processing the form" from "identifying the form" allows us to customize our form handling
and preserve form information on the client for transactional purposes such as our wizard.
w
* web: multi-select, but there's a styling issue.
* web: provide a closed control for multi-select
This commit creates a new control, using the ak-form-element-horizontal as a *CLOSED*
object, for our multi-select. This control right now is limited to what we expect to
be using in the wizard, but that doesn't mean it can't be smarter in the future.
* web: hung up by a silly spelling error
* web: update the form-handling method
With the `serializeForm` method extracted, it's much easier to examine and parse
every *form* with every keystroke, preserving them against the changes that
happen as the customer navigates the Wizard. With that in place, it became
straightforward to retrofit the "handle changes to the application, to the provider, and to the providerType"
into the three pages of the wizard, and to provide *all* of the form elements in a base class
such that no specialized handling needs to happen to any of the child pages.
Fixed an ugly typo in the oauth2 provider, as well.
* web: wizard should work with multi-select and should reflect default values
(Note: This commit is predicated on both the "Extract serializeForm function from Form.ts" and
"Provide a controlled multi-select input control" PRs.)
The initial attempt at the wizard was woefully naive in its implementation, missing some critical
details along the way. This revision starts off with one stronger assumption: trust that Jens knows
what he's doing, and knew what he was building when he wrote the initial `Form` handler.
The problem with the `Form` handler, and the reason I avoided it, was simply that it does too many
things, especially in its ModelForm variant: it receives a model from the back-end, renders a
(hand-written) form for that model, allows the user to interact with that model, and facilitates
saving it to the back-end again, complete with on-page notifications of success or failure.
The Wizard could not use all of that. It needs to gather the information for *two* models (an
Application and a Provider, plus the ProviderType) and has a new and specialized end-point for a
transaction that allows the committing or roll back of both models to happen simultaneously,
predicated on success or failure respectively.
With "Extract `serializeForm` completed, it was possible to repurpose the forms that already
existed, stripping them down to just their input components, and eventing the entire thing in a
single event loop of "events flow up, data flows down." In this case, the *entire form* is
serialized on a per-event basis and pushed up the to the orchestration layer, which saves them off.
Writing a parent `BasePanel` class that has accessors for `formValues` and `valid` means that the
state of every page is accessible with a simple query. This simplified the `BaseProviderPanel` class
to just specialize the `dispatchUpdate` method to send the wizard update with the new provider
information filled out.
Because the *form* is being treated as the source of truth about the state of a `Partial<Application>`
or `Partial<*Provider>` object, the defaults are now being captured as expected.
Likewise, this simplified the `providerCache` layer which preserves customer input in the event that
the customer starts filling out the wrong provider to a simple conditional clause in the
orchestrator. The Wizard has much fewer smarts because it doesn't (and probably never did) need
them.
Along with the above changes, the following has also been done:
For SAML and SCIM, the providerMappings now works. They weren't being managed as `state` objects,
so they weren't receiving updates when the update event retrieved the information from the back-end.
In order to make clear what's happening, I have extracted the loops from the original definition and
built them as named objects: `propertyMappings`, `pmUserValues`, `pmGroupValues` and so on, which I
then pass into the new multi-select component.
I fixed a really embarrassing typo in Oauth2's "advanced settings" block.
I have extracted the CoreGroup search-select into a custom component.
I deleted the `merge` function. That was a faulty experiment with non-deterministic outcomes, and I
was never happy with it. I'm glad its gone.
I've added a title header to each of the providers, so the user can be sure that they're looking
at the right provider type when they start filling out the form.
I've created a new token, `data-ak-control`, with which we can mark all objects that we can treat as
Authentik value-producing components, the form value of which is available through a `json()`
method. I've added this bit of intelligence to the `serializeForm` function, short-circuiting the
complex processing and putting the "this is the shape of the value we expect from this input" *onto
the input itself*. Which is where it belongs.
* web: add error handling to wizard.
* web: improve error handling in light components
Rather than reproduce the error handling across all of the LightComponents,
I've made a parent class that takes the common fields to distribute between
the ak-form-element-horizontal and the input object itself. This made it
much easier to properly display errors in freeform input fields in the
wizard, as well as working with the routine error handling in Form.ts
* Added the radio control to the list of LightComponents.
* Fix bug where event was recorded twice.
* Fixed merge bug (?) that somehow deleted the Authorization Select block in OAuth2.
* web: prettier had opinions
* web: added error handling and display
* web: bump @lit-labs/context from 0.4.1 to 0.5.1 in /web
Bumps [@lit-labs/context](https://github.com/lit/lit/tree/HEAD/packages/labs/context) from 0.4.1 to 0.5.1.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/labs/context/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/@lit-labs/context@0.5.1/packages/labs/context)
---
updated-dependencies:
- dependency-name: "@lit-labs/context"
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
* web: updated wizard to run with latest package.json configuration
Apparently, there were stale dependencies in package-lock.json that were conflicting
with the requests in our package.json. By running `npm update`, I was able to resolve
the conflict.
I have also removed the default names from the context names collection; they weren't doing
any good, and they permit frictionless renaming of dependencies, which is never a good
idea.
* web: schlepping on the errors messages
During testing, I realized I was unhappy with the error messages. They're not very helpful.
By adding links to navigate back to the place where the error occurred, and providing better
context for what the error could have been, I hope to help the use correct their errors.
* make package the same as main
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-12-06 11:28:19 +00:00
</trans-unit>
2023-12-30 20:33:14 +00:00
<trans-unit id="s4bc7a1a88961be90">
<source>Configure if sessions created by this stage should be bound to their GeoIP-based location</source>
web/admin: revise wizard form handling (#7331)
* web: break circular dependency between AKElement & Interface.
This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.
I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.
* web: fix broken typescript references
This built... and then it didn't? Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.
* web: extract the form processing from the form submission process
Our forms have a lot of customized value handling, and the function `serializeForm` takes
our input structures and creates a JSON object ready for submission across the wire for
the various models provided by the API.
That function was embedded in the `ak-form` object, but it has no actual dependencies on
the state of that object; aside from identifying the input elements, which is done at the
very start of processing, this large block of code stands alone. Separating out the
"processing the form" from "identifying the form" allows us to customize our form handling
and preserve form information on the client for transactional purposes such as our wizard.
w
* web: multi-select, but there's a styling issue.
* web: provide a closed control for multi-select
This commit creates a new control, using the ak-form-element-horizontal as a *CLOSED*
object, for our multi-select. This control right now is limited to what we expect to
be using in the wizard, but that doesn't mean it can't be smarter in the future.
* web: hung up by a silly spelling error
* web: update the form-handling method
With the `serializeForm` method extracted, it's much easier to examine and parse
every *form* with every keystroke, preserving them against the changes that
happen as the customer navigates the Wizard. With that in place, it became
straightforward to retrofit the "handle changes to the application, to the provider, and to the providerType"
into the three pages of the wizard, and to provide *all* of the form elements in a base class
such that no specialized handling needs to happen to any of the child pages.
Fixed an ugly typo in the oauth2 provider, as well.
* web: wizard should work with multi-select and should reflect default values
(Note: This commit is predicated on both the "Extract serializeForm function from Form.ts" and
"Provide a controlled multi-select input control" PRs.)
The initial attempt at the wizard was woefully naive in its implementation, missing some critical
details along the way. This revision starts off with one stronger assumption: trust that Jens knows
what he's doing, and knew what he was building when he wrote the initial `Form` handler.
The problem with the `Form` handler, and the reason I avoided it, was simply that it does too many
things, especially in its ModelForm variant: it receives a model from the back-end, renders a
(hand-written) form for that model, allows the user to interact with that model, and facilitates
saving it to the back-end again, complete with on-page notifications of success or failure.
The Wizard could not use all of that. It needs to gather the information for *two* models (an
Application and a Provider, plus the ProviderType) and has a new and specialized end-point for a
transaction that allows the committing or roll back of both models to happen simultaneously,
predicated on success or failure respectively.
With "Extract `serializeForm` completed, it was possible to repurpose the forms that already
existed, stripping them down to just their input components, and eventing the entire thing in a
single event loop of "events flow up, data flows down." In this case, the *entire form* is
serialized on a per-event basis and pushed up the to the orchestration layer, which saves them off.
Writing a parent `BasePanel` class that has accessors for `formValues` and `valid` means that the
state of every page is accessible with a simple query. This simplified the `BaseProviderPanel` class
to just specialize the `dispatchUpdate` method to send the wizard update with the new provider
information filled out.
Because the *form* is being treated as the source of truth about the state of a `Partial<Application>`
or `Partial<*Provider>` object, the defaults are now being captured as expected.
Likewise, this simplified the `providerCache` layer which preserves customer input in the event that
the customer starts filling out the wrong provider to a simple conditional clause in the
orchestrator. The Wizard has much fewer smarts because it doesn't (and probably never did) need
them.
Along with the above changes, the following has also been done:
For SAML and SCIM, the providerMappings now works. They weren't being managed as `state` objects,
so they weren't receiving updates when the update event retrieved the information from the back-end.
In order to make clear what's happening, I have extracted the loops from the original definition and
built them as named objects: `propertyMappings`, `pmUserValues`, `pmGroupValues` and so on, which I
then pass into the new multi-select component.
I fixed a really embarrassing typo in Oauth2's "advanced settings" block.
I have extracted the CoreGroup search-select into a custom component.
I deleted the `merge` function. That was a faulty experiment with non-deterministic outcomes, and I
was never happy with it. I'm glad its gone.
I've added a title header to each of the providers, so the user can be sure that they're looking
at the right provider type when they start filling out the form.
I've created a new token, `data-ak-control`, with which we can mark all objects that we can treat as
Authentik value-producing components, the form value of which is available through a `json()`
method. I've added this bit of intelligence to the `serializeForm` function, short-circuiting the
complex processing and putting the "this is the shape of the value we expect from this input" *onto
the input itself*. Which is where it belongs.
* web: add error handling to wizard.
* web: improve error handling in light components
Rather than reproduce the error handling across all of the LightComponents,
I've made a parent class that takes the common fields to distribute between
the ak-form-element-horizontal and the input object itself. This made it
much easier to properly display errors in freeform input fields in the
wizard, as well as working with the routine error handling in Form.ts
* Added the radio control to the list of LightComponents.
* Fix bug where event was recorded twice.
* Fixed merge bug (?) that somehow deleted the Authorization Select block in OAuth2.
* web: prettier had opinions
* web: added error handling and display
* web: bump @lit-labs/context from 0.4.1 to 0.5.1 in /web
Bumps [@lit-labs/context](https://github.com/lit/lit/tree/HEAD/packages/labs/context) from 0.4.1 to 0.5.1.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/labs/context/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/@lit-labs/context@0.5.1/packages/labs/context)
---
updated-dependencies:
- dependency-name: "@lit-labs/context"
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
* web: updated wizard to run with latest package.json configuration
Apparently, there were stale dependencies in package-lock.json that were conflicting
with the requests in our package.json. By running `npm update`, I was able to resolve
the conflict.
I have also removed the default names from the context names collection; they weren't doing
any good, and they permit frictionless renaming of dependencies, which is never a good
idea.
* web: schlepping on the errors messages
During testing, I realized I was unhappy with the error messages. They're not very helpful.
By adding links to navigate back to the place where the error occurred, and providing better
context for what the error could have been, I hope to help the use correct their errors.
* make package the same as main
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-12-06 11:28:19 +00:00
</trans-unit>
2023-12-30 20:33:14 +00:00
<trans-unit id="sa06cd519ff151b6d">
<source>RAC</source>
web/admin: revise wizard form handling (#7331)
* web: break circular dependency between AKElement & Interface.
This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.
I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.
* web: fix broken typescript references
This built... and then it didn't? Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.
* web: extract the form processing from the form submission process
Our forms have a lot of customized value handling, and the function `serializeForm` takes
our input structures and creates a JSON object ready for submission across the wire for
the various models provided by the API.
That function was embedded in the `ak-form` object, but it has no actual dependencies on
the state of that object; aside from identifying the input elements, which is done at the
very start of processing, this large block of code stands alone. Separating out the
"processing the form" from "identifying the form" allows us to customize our form handling
and preserve form information on the client for transactional purposes such as our wizard.
w
* web: multi-select, but there's a styling issue.
* web: provide a closed control for multi-select
This commit creates a new control, using the ak-form-element-horizontal as a *CLOSED*
object, for our multi-select. This control right now is limited to what we expect to
be using in the wizard, but that doesn't mean it can't be smarter in the future.
* web: hung up by a silly spelling error
* web: update the form-handling method
With the `serializeForm` method extracted, it's much easier to examine and parse
every *form* with every keystroke, preserving them against the changes that
happen as the customer navigates the Wizard. With that in place, it became
straightforward to retrofit the "handle changes to the application, to the provider, and to the providerType"
into the three pages of the wizard, and to provide *all* of the form elements in a base class
such that no specialized handling needs to happen to any of the child pages.
Fixed an ugly typo in the oauth2 provider, as well.
* web: wizard should work with multi-select and should reflect default values
(Note: This commit is predicated on both the "Extract serializeForm function from Form.ts" and
"Provide a controlled multi-select input control" PRs.)
The initial attempt at the wizard was woefully naive in its implementation, missing some critical
details along the way. This revision starts off with one stronger assumption: trust that Jens knows
what he's doing, and knew what he was building when he wrote the initial `Form` handler.
The problem with the `Form` handler, and the reason I avoided it, was simply that it does too many
things, especially in its ModelForm variant: it receives a model from the back-end, renders a
(hand-written) form for that model, allows the user to interact with that model, and facilitates
saving it to the back-end again, complete with on-page notifications of success or failure.
The Wizard could not use all of that. It needs to gather the information for *two* models (an
Application and a Provider, plus the ProviderType) and has a new and specialized end-point for a
transaction that allows the committing or roll back of both models to happen simultaneously,
predicated on success or failure respectively.
With "Extract `serializeForm` completed, it was possible to repurpose the forms that already
existed, stripping them down to just their input components, and eventing the entire thing in a
single event loop of "events flow up, data flows down." In this case, the *entire form* is
serialized on a per-event basis and pushed up the to the orchestration layer, which saves them off.
Writing a parent `BasePanel` class that has accessors for `formValues` and `valid` means that the
state of every page is accessible with a simple query. This simplified the `BaseProviderPanel` class
to just specialize the `dispatchUpdate` method to send the wizard update with the new provider
information filled out.
Because the *form* is being treated as the source of truth about the state of a `Partial<Application>`
or `Partial<*Provider>` object, the defaults are now being captured as expected.
Likewise, this simplified the `providerCache` layer which preserves customer input in the event that
the customer starts filling out the wrong provider to a simple conditional clause in the
orchestrator. The Wizard has much fewer smarts because it doesn't (and probably never did) need
them.
Along with the above changes, the following has also been done:
For SAML and SCIM, the providerMappings now works. They weren't being managed as `state` objects,
so they weren't receiving updates when the update event retrieved the information from the back-end.
In order to make clear what's happening, I have extracted the loops from the original definition and
built them as named objects: `propertyMappings`, `pmUserValues`, `pmGroupValues` and so on, which I
then pass into the new multi-select component.
I fixed a really embarrassing typo in Oauth2's "advanced settings" block.
I have extracted the CoreGroup search-select into a custom component.
I deleted the `merge` function. That was a faulty experiment with non-deterministic outcomes, and I
was never happy with it. I'm glad its gone.
I've added a title header to each of the providers, so the user can be sure that they're looking
at the right provider type when they start filling out the form.
I've created a new token, `data-ak-control`, with which we can mark all objects that we can treat as
Authentik value-producing components, the form value of which is available through a `json()`
method. I've added this bit of intelligence to the `serializeForm` function, short-circuiting the
complex processing and putting the "this is the shape of the value we expect from this input" *onto
the input itself*. Which is where it belongs.
* web: add error handling to wizard.
* web: improve error handling in light components
Rather than reproduce the error handling across all of the LightComponents,
I've made a parent class that takes the common fields to distribute between
the ak-form-element-horizontal and the input object itself. This made it
much easier to properly display errors in freeform input fields in the
wizard, as well as working with the routine error handling in Form.ts
* Added the radio control to the list of LightComponents.
* Fix bug where event was recorded twice.
* Fixed merge bug (?) that somehow deleted the Authorization Select block in OAuth2.
* web: prettier had opinions
* web: added error handling and display
* web: bump @lit-labs/context from 0.4.1 to 0.5.1 in /web
Bumps [@lit-labs/context](https://github.com/lit/lit/tree/HEAD/packages/labs/context) from 0.4.1 to 0.5.1.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/labs/context/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/@lit-labs/context@0.5.1/packages/labs/context)
---
updated-dependencies:
- dependency-name: "@lit-labs/context"
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
* web: updated wizard to run with latest package.json configuration
Apparently, there were stale dependencies in package-lock.json that were conflicting
with the requests in our package.json. By running `npm update`, I was able to resolve
the conflict.
I have also removed the default names from the context names collection; they weren't doing
any good, and they permit frictionless renaming of dependencies, which is never a good
idea.
* web: schlepping on the errors messages
During testing, I realized I was unhappy with the error messages. They're not very helpful.
By adding links to navigate back to the place where the error occurred, and providing better
context for what the error could have been, I hope to help the use correct their errors.
* make package the same as main
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-12-06 11:28:19 +00:00
</trans-unit>
2023-12-30 20:33:14 +00:00
<trans-unit id="s28b99b59541f54ca">
<source>Connection failed after <x id="0" equiv-text="${this.connectionAttempt}"/> attempts.</source>
web/admin: revise wizard form handling (#7331)
* web: break circular dependency between AKElement & Interface.
This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.
I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.
* web: fix broken typescript references
This built... and then it didn't? Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.
* web: extract the form processing from the form submission process
Our forms have a lot of customized value handling, and the function `serializeForm` takes
our input structures and creates a JSON object ready for submission across the wire for
the various models provided by the API.
That function was embedded in the `ak-form` object, but it has no actual dependencies on
the state of that object; aside from identifying the input elements, which is done at the
very start of processing, this large block of code stands alone. Separating out the
"processing the form" from "identifying the form" allows us to customize our form handling
and preserve form information on the client for transactional purposes such as our wizard.
w
* web: multi-select, but there's a styling issue.
* web: provide a closed control for multi-select
This commit creates a new control, using the ak-form-element-horizontal as a *CLOSED*
object, for our multi-select. This control right now is limited to what we expect to
be using in the wizard, but that doesn't mean it can't be smarter in the future.
* web: hung up by a silly spelling error
* web: update the form-handling method
With the `serializeForm` method extracted, it's much easier to examine and parse
every *form* with every keystroke, preserving them against the changes that
happen as the customer navigates the Wizard. With that in place, it became
straightforward to retrofit the "handle changes to the application, to the provider, and to the providerType"
into the three pages of the wizard, and to provide *all* of the form elements in a base class
such that no specialized handling needs to happen to any of the child pages.
Fixed an ugly typo in the oauth2 provider, as well.
* web: wizard should work with multi-select and should reflect default values
(Note: This commit is predicated on both the "Extract serializeForm function from Form.ts" and
"Provide a controlled multi-select input control" PRs.)
The initial attempt at the wizard was woefully naive in its implementation, missing some critical
details along the way. This revision starts off with one stronger assumption: trust that Jens knows
what he's doing, and knew what he was building when he wrote the initial `Form` handler.
The problem with the `Form` handler, and the reason I avoided it, was simply that it does too many
things, especially in its ModelForm variant: it receives a model from the back-end, renders a
(hand-written) form for that model, allows the user to interact with that model, and facilitates
saving it to the back-end again, complete with on-page notifications of success or failure.
The Wizard could not use all of that. It needs to gather the information for *two* models (an
Application and a Provider, plus the ProviderType) and has a new and specialized end-point for a
transaction that allows the committing or roll back of both models to happen simultaneously,
predicated on success or failure respectively.
With "Extract `serializeForm` completed, it was possible to repurpose the forms that already
existed, stripping them down to just their input components, and eventing the entire thing in a
single event loop of "events flow up, data flows down." In this case, the *entire form* is
serialized on a per-event basis and pushed up the to the orchestration layer, which saves them off.
Writing a parent `BasePanel` class that has accessors for `formValues` and `valid` means that the
state of every page is accessible with a simple query. This simplified the `BaseProviderPanel` class
to just specialize the `dispatchUpdate` method to send the wizard update with the new provider
information filled out.
Because the *form* is being treated as the source of truth about the state of a `Partial<Application>`
or `Partial<*Provider>` object, the defaults are now being captured as expected.
Likewise, this simplified the `providerCache` layer which preserves customer input in the event that
the customer starts filling out the wrong provider to a simple conditional clause in the
orchestrator. The Wizard has much fewer smarts because it doesn't (and probably never did) need
them.
Along with the above changes, the following has also been done:
For SAML and SCIM, the providerMappings now works. They weren't being managed as `state` objects,
so they weren't receiving updates when the update event retrieved the information from the back-end.
In order to make clear what's happening, I have extracted the loops from the original definition and
built them as named objects: `propertyMappings`, `pmUserValues`, `pmGroupValues` and so on, which I
then pass into the new multi-select component.
I fixed a really embarrassing typo in Oauth2's "advanced settings" block.
I have extracted the CoreGroup search-select into a custom component.
I deleted the `merge` function. That was a faulty experiment with non-deterministic outcomes, and I
was never happy with it. I'm glad its gone.
I've added a title header to each of the providers, so the user can be sure that they're looking
at the right provider type when they start filling out the form.
I've created a new token, `data-ak-control`, with which we can mark all objects that we can treat as
Authentik value-producing components, the form value of which is available through a `json()`
method. I've added this bit of intelligence to the `serializeForm` function, short-circuiting the
complex processing and putting the "this is the shape of the value we expect from this input" *onto
the input itself*. Which is where it belongs.
* web: add error handling to wizard.
* web: improve error handling in light components
Rather than reproduce the error handling across all of the LightComponents,
I've made a parent class that takes the common fields to distribute between
the ak-form-element-horizontal and the input object itself. This made it
much easier to properly display errors in freeform input fields in the
wizard, as well as working with the routine error handling in Form.ts
* Added the radio control to the list of LightComponents.
* Fix bug where event was recorded twice.
* Fixed merge bug (?) that somehow deleted the Authorization Select block in OAuth2.
* web: prettier had opinions
* web: added error handling and display
* web: bump @lit-labs/context from 0.4.1 to 0.5.1 in /web
Bumps [@lit-labs/context](https://github.com/lit/lit/tree/HEAD/packages/labs/context) from 0.4.1 to 0.5.1.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/labs/context/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/@lit-labs/context@0.5.1/packages/labs/context)
---
updated-dependencies:
- dependency-name: "@lit-labs/context"
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
* web: updated wizard to run with latest package.json configuration
Apparently, there were stale dependencies in package-lock.json that were conflicting
with the requests in our package.json. By running `npm update`, I was able to resolve
the conflict.
I have also removed the default names from the context names collection; they weren't doing
any good, and they permit frictionless renaming of dependencies, which is never a good
idea.
* web: schlepping on the errors messages
During testing, I realized I was unhappy with the error messages. They're not very helpful.
By adding links to navigate back to the place where the error occurred, and providing better
context for what the error could have been, I hope to help the use correct their errors.
* make package the same as main
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-12-06 11:28:19 +00:00
</trans-unit>
2023-12-30 20:33:14 +00:00
<trans-unit id="s7c7d956418e1c8c8">
<source>Re-connecting in <x id="0" equiv-text="${Math.max(1, delay / 1000)}"/> second(s).</source>
web/admin: revise wizard form handling (#7331)
* web: break circular dependency between AKElement & Interface.
This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.
I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.
* web: fix broken typescript references
This built... and then it didn't? Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.
* web: extract the form processing from the form submission process
Our forms have a lot of customized value handling, and the function `serializeForm` takes
our input structures and creates a JSON object ready for submission across the wire for
the various models provided by the API.
That function was embedded in the `ak-form` object, but it has no actual dependencies on
the state of that object; aside from identifying the input elements, which is done at the
very start of processing, this large block of code stands alone. Separating out the
"processing the form" from "identifying the form" allows us to customize our form handling
and preserve form information on the client for transactional purposes such as our wizard.
w
* web: multi-select, but there's a styling issue.
* web: provide a closed control for multi-select
This commit creates a new control, using the ak-form-element-horizontal as a *CLOSED*
object, for our multi-select. This control right now is limited to what we expect to
be using in the wizard, but that doesn't mean it can't be smarter in the future.
* web: hung up by a silly spelling error
* web: update the form-handling method
With the `serializeForm` method extracted, it's much easier to examine and parse
every *form* with every keystroke, preserving them against the changes that
happen as the customer navigates the Wizard. With that in place, it became
straightforward to retrofit the "handle changes to the application, to the provider, and to the providerType"
into the three pages of the wizard, and to provide *all* of the form elements in a base class
such that no specialized handling needs to happen to any of the child pages.
Fixed an ugly typo in the oauth2 provider, as well.
* web: wizard should work with multi-select and should reflect default values
(Note: This commit is predicated on both the "Extract serializeForm function from Form.ts" and
"Provide a controlled multi-select input control" PRs.)
The initial attempt at the wizard was woefully naive in its implementation, missing some critical
details along the way. This revision starts off with one stronger assumption: trust that Jens knows
what he's doing, and knew what he was building when he wrote the initial `Form` handler.
The problem with the `Form` handler, and the reason I avoided it, was simply that it does too many
things, especially in its ModelForm variant: it receives a model from the back-end, renders a
(hand-written) form for that model, allows the user to interact with that model, and facilitates
saving it to the back-end again, complete with on-page notifications of success or failure.
The Wizard could not use all of that. It needs to gather the information for *two* models (an
Application and a Provider, plus the ProviderType) and has a new and specialized end-point for a
transaction that allows the committing or roll back of both models to happen simultaneously,
predicated on success or failure respectively.
With "Extract `serializeForm` completed, it was possible to repurpose the forms that already
existed, stripping them down to just their input components, and eventing the entire thing in a
single event loop of "events flow up, data flows down." In this case, the *entire form* is
serialized on a per-event basis and pushed up the to the orchestration layer, which saves them off.
Writing a parent `BasePanel` class that has accessors for `formValues` and `valid` means that the
state of every page is accessible with a simple query. This simplified the `BaseProviderPanel` class
to just specialize the `dispatchUpdate` method to send the wizard update with the new provider
information filled out.
Because the *form* is being treated as the source of truth about the state of a `Partial<Application>`
or `Partial<*Provider>` object, the defaults are now being captured as expected.
Likewise, this simplified the `providerCache` layer which preserves customer input in the event that
the customer starts filling out the wrong provider to a simple conditional clause in the
orchestrator. The Wizard has much fewer smarts because it doesn't (and probably never did) need
them.
Along with the above changes, the following has also been done:
For SAML and SCIM, the providerMappings now works. They weren't being managed as `state` objects,
so they weren't receiving updates when the update event retrieved the information from the back-end.
In order to make clear what's happening, I have extracted the loops from the original definition and
built them as named objects: `propertyMappings`, `pmUserValues`, `pmGroupValues` and so on, which I
then pass into the new multi-select component.
I fixed a really embarrassing typo in Oauth2's "advanced settings" block.
I have extracted the CoreGroup search-select into a custom component.
I deleted the `merge` function. That was a faulty experiment with non-deterministic outcomes, and I
was never happy with it. I'm glad its gone.
I've added a title header to each of the providers, so the user can be sure that they're looking
at the right provider type when they start filling out the form.
I've created a new token, `data-ak-control`, with which we can mark all objects that we can treat as
Authentik value-producing components, the form value of which is available through a `json()`
method. I've added this bit of intelligence to the `serializeForm` function, short-circuiting the
complex processing and putting the "this is the shape of the value we expect from this input" *onto
the input itself*. Which is where it belongs.
* web: add error handling to wizard.
* web: improve error handling in light components
Rather than reproduce the error handling across all of the LightComponents,
I've made a parent class that takes the common fields to distribute between
the ak-form-element-horizontal and the input object itself. This made it
much easier to properly display errors in freeform input fields in the
wizard, as well as working with the routine error handling in Form.ts
* Added the radio control to the list of LightComponents.
* Fix bug where event was recorded twice.
* Fixed merge bug (?) that somehow deleted the Authorization Select block in OAuth2.
* web: prettier had opinions
* web: added error handling and display
* web: bump @lit-labs/context from 0.4.1 to 0.5.1 in /web
Bumps [@lit-labs/context](https://github.com/lit/lit/tree/HEAD/packages/labs/context) from 0.4.1 to 0.5.1.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/labs/context/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/@lit-labs/context@0.5.1/packages/labs/context)
---
updated-dependencies:
- dependency-name: "@lit-labs/context"
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
* web: updated wizard to run with latest package.json configuration
Apparently, there were stale dependencies in package-lock.json that were conflicting
with the requests in our package.json. By running `npm update`, I was able to resolve
the conflict.
I have also removed the default names from the context names collection; they weren't doing
any good, and they permit frictionless renaming of dependencies, which is never a good
idea.
* web: schlepping on the errors messages
During testing, I realized I was unhappy with the error messages. They're not very helpful.
By adding links to navigate back to the place where the error occurred, and providing better
context for what the error could have been, I hope to help the use correct their errors.
* make package the same as main
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-12-06 11:28:19 +00:00
</trans-unit>
2023-12-30 20:33:14 +00:00
<trans-unit id="sfc003381f593d943">
<source>Connecting...</source>
web/admin: revise wizard form handling (#7331)
* web: break circular dependency between AKElement & Interface.
This commit changes the way the root node of the web application shell is
discovered by child components, such that the base class shared by both
no longer results in a circular dependency between the two models.
I've run this in isolation and have seen no failures of discovery; the identity
token exists as soon as the Interface is constructed and is found by every item
on the page.
* web: fix broken typescript references
This built... and then it didn't? Anyway, the current fix is to
provide type information the AkInterface for the data that consumers
require.
* web: extract the form processing from the form submission process
Our forms have a lot of customized value handling, and the function `serializeForm` takes
our input structures and creates a JSON object ready for submission across the wire for
the various models provided by the API.
That function was embedded in the `ak-form` object, but it has no actual dependencies on
the state of that object; aside from identifying the input elements, which is done at the
very start of processing, this large block of code stands alone. Separating out the
"processing the form" from "identifying the form" allows us to customize our form handling
and preserve form information on the client for transactional purposes such as our wizard.
w
* web: multi-select, but there's a styling issue.
* web: provide a closed control for multi-select
This commit creates a new control, using the ak-form-element-horizontal as a *CLOSED*
object, for our multi-select. This control right now is limited to what we expect to
be using in the wizard, but that doesn't mean it can't be smarter in the future.
* web: hung up by a silly spelling error
* web: update the form-handling method
With the `serializeForm` method extracted, it's much easier to examine and parse
every *form* with every keystroke, preserving them against the changes that
happen as the customer navigates the Wizard. With that in place, it became
straightforward to retrofit the "handle changes to the application, to the provider, and to the providerType"
into the three pages of the wizard, and to provide *all* of the form elements in a base class
such that no specialized handling needs to happen to any of the child pages.
Fixed an ugly typo in the oauth2 provider, as well.
* web: wizard should work with multi-select and should reflect default values
(Note: This commit is predicated on both the "Extract serializeForm function from Form.ts" and
"Provide a controlled multi-select input control" PRs.)
The initial attempt at the wizard was woefully naive in its implementation, missing some critical
details along the way. This revision starts off with one stronger assumption: trust that Jens knows
what he's doing, and knew what he was building when he wrote the initial `Form` handler.
The problem with the `Form` handler, and the reason I avoided it, was simply that it does too many
things, especially in its ModelForm variant: it receives a model from the back-end, renders a
(hand-written) form for that model, allows the user to interact with that model, and facilitates
saving it to the back-end again, complete with on-page notifications of success or failure.
The Wizard could not use all of that. It needs to gather the information for *two* models (an
Application and a Provider, plus the ProviderType) and has a new and specialized end-point for a
transaction that allows the committing or roll back of both models to happen simultaneously,
predicated on success or failure respectively.
With "Extract `serializeForm` completed, it was possible to repurpose the forms that already
existed, stripping them down to just their input components, and eventing the entire thing in a
single event loop of "events flow up, data flows down." In this case, the *entire form* is
serialized on a per-event basis and pushed up the to the orchestration layer, which saves them off.
Writing a parent `BasePanel` class that has accessors for `formValues` and `valid` means that the
state of every page is accessible with a simple query. This simplified the `BaseProviderPanel` class
to just specialize the `dispatchUpdate` method to send the wizard update with the new provider
information filled out.
Because the *form* is being treated as the source of truth about the state of a `Partial<Application>`
or `Partial<*Provider>` object, the defaults are now being captured as expected.
Likewise, this simplified the `providerCache` layer which preserves customer input in the event that
the customer starts filling out the wrong provider to a simple conditional clause in the
orchestrator. The Wizard has much fewer smarts because it doesn't (and probably never did) need
them.
Along with the above changes, the following has also been done:
For SAML and SCIM, the providerMappings now works. They weren't being managed as `state` objects,
so they weren't receiving updates when the update event retrieved the information from the back-end.
In order to make clear what's happening, I have extracted the loops from the original definition and
built them as named objects: `propertyMappings`, `pmUserValues`, `pmGroupValues` and so on, which I
then pass into the new multi-select component.
I fixed a really embarrassing typo in Oauth2's "advanced settings" block.
I have extracted the CoreGroup search-select into a custom component.
I deleted the `merge` function. That was a faulty experiment with non-deterministic outcomes, and I
was never happy with it. I'm glad its gone.
I've added a title header to each of the providers, so the user can be sure that they're looking
at the right provider type when they start filling out the form.
I've created a new token, `data-ak-control`, with which we can mark all objects that we can treat as
Authentik value-producing components, the form value of which is available through a `json()`
method. I've added this bit of intelligence to the `serializeForm` function, short-circuiting the
complex processing and putting the "this is the shape of the value we expect from this input" *onto
the input itself*. Which is where it belongs.
* web: add error handling to wizard.
* web: improve error handling in light components
Rather than reproduce the error handling across all of the LightComponents,
I've made a parent class that takes the common fields to distribute between
the ak-form-element-horizontal and the input object itself. This made it
much easier to properly display errors in freeform input fields in the
wizard, as well as working with the routine error handling in Form.ts
* Added the radio control to the list of LightComponents.
* Fix bug where event was recorded twice.
* Fixed merge bug (?) that somehow deleted the Authorization Select block in OAuth2.
* web: prettier had opinions
* web: added error handling and display
* web: bump @lit-labs/context from 0.4.1 to 0.5.1 in /web
Bumps [@lit-labs/context](https://github.com/lit/lit/tree/HEAD/packages/labs/context) from 0.4.1 to 0.5.1.
- [Release notes](https://github.com/lit/lit/releases)
- [Changelog](https://github.com/lit/lit/blob/main/packages/labs/context/CHANGELOG.md)
- [Commits](https://github.com/lit/lit/commits/@lit-labs/context@0.5.1/packages/labs/context)
---
updated-dependencies:
- dependency-name: "@lit-labs/context"
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
* web: updated wizard to run with latest package.json configuration
Apparently, there were stale dependencies in package-lock.json that were conflicting
with the requests in our package.json. By running `npm update`, I was able to resolve
the conflict.
I have also removed the default names from the context names collection; they weren't doing
any good, and they permit frictionless renaming of dependencies, which is never a good
idea.
* web: schlepping on the errors messages
During testing, I realized I was unhappy with the error messages. They're not very helpful.
By adding links to navigate back to the place where the error occurred, and providing better
context for what the error could have been, I hope to help the use correct their errors.
* make package the same as main
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
---------
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-12-06 11:28:19 +00:00
</trans-unit>
2023-12-30 20:33:14 +00:00
<trans-unit id="s31aa94a0b3c7edb2">
<source>Select endpoint to connect to</source>
2023-12-06 17:06:07 +00:00
</trans-unit>
2023-12-30 20:33:14 +00:00
<trans-unit id="sa2ea0fcd3ffa80e0">
<source>Connection expiry</source>
2023-12-08 01:52:59 +00:00
</trans-unit>
2023-12-30 20:33:14 +00:00
<trans-unit id="s6dd297c217729828">
<source>Determines how long a session lasts before being disconnected and requiring re-authorization.</source>
2023-12-08 01:52:59 +00:00
</trans-unit>
2024-01-04 15:18:12 +00:00
<trans-unit id="scc7f34824150bfb8">
<source>Provider require enterprise.</source>
</trans-unit>
<trans-unit id="s31f1afc1bfe1cb3a">
<source>Learn more</source>
2024-01-08 17:27:09 +00:00
</trans-unit>
<trans-unit id="sc39f6abf0daedb0f">
<source>Maximum concurrent connections</source>
</trans-unit>
<trans-unit id="s62418cbcd2a25498">
<source>Maximum concurrent allowed connections to this endpoint. Can be set to -1 to disable the limit.</source>
2024-01-09 15:38:09 +00:00
</trans-unit>
2024-01-03 11:22:25 +00:00
<trans-unit id="s744401846fea6e76">
<source>Brand</source>
2023-12-08 01:52:59 +00:00
</trans-unit>
2024-01-03 11:22:25 +00:00
<trans-unit id="sab21e1f62676b56c">
<source>Successfully updated brand.</source>
2023-12-08 01:52:59 +00:00
</trans-unit>
2024-01-03 11:22:25 +00:00
<trans-unit id="sa43e43fd3a23e22d">
<source>Successfully created brand.</source>
2023-12-08 01:52:59 +00:00
</trans-unit>
2024-01-03 11:22:25 +00:00
<trans-unit id="s41b3f9b4c98aabd9">
<source>Use this brand for each domain that doesn't have a dedicated brand.</source>
2023-12-08 01:52:59 +00:00
</trans-unit>
2024-01-03 11:22:25 +00:00
<trans-unit id="s17260b71484b307f">
<source>Set custom attributes using YAML or JSON. Any attributes set here will be inherited by users, if the request is handled by this brand.</source>
2023-12-08 01:52:59 +00:00
</trans-unit>
2024-01-03 11:22:25 +00:00
<trans-unit id="s79fc990a2b58f27f">
<source>Brands</source>
2023-12-08 01:52:59 +00:00
</trans-unit>
2024-01-03 11:22:25 +00:00
<trans-unit id="s02774bc46a167346">
<source>Brand(s)</source>
2023-12-08 01:52:59 +00:00
</trans-unit>
2024-01-03 11:22:25 +00:00
<trans-unit id="s801bf3d03f4a3ff1">
<source>Update Brand</source>
2023-12-08 01:52:59 +00:00
</trans-unit>
2024-01-03 11:22:25 +00:00
<trans-unit id="s5c3efec5330e0000">
<source>Create Brand</source>
2023-12-08 01:52:59 +00:00
</trans-unit>
2024-01-03 11:22:25 +00:00
<trans-unit id="sa9d13ce9e83aac17">
<source>To let a user directly reset a their password, configure a recovery flow on the currently active brand.</source>
2023-12-08 01:52:59 +00:00
</trans-unit>
2024-01-09 15:38:09 +00:00
<trans-unit id="s94d61907ee22a8c1">
<source>Korean</source>
</trans-unit>
<trans-unit id="s95d56e58f816d211">
<source>Dutch</source>
</trans-unit>
2024-01-03 11:22:25 +00:00
<trans-unit id="s6709b81e1ed4e39f">
<source>The current brand must have a recovery flow configured to use a recovery link</source>
2023-12-08 01:52:59 +00:00
</trans-unit>
2024-01-03 11:22:25 +00:00
<trans-unit id="s634e2fd82c397576">
<source>Successfully updated settings.</source>
2023-12-08 01:52:59 +00:00
</trans-unit>
2024-01-03 11:22:25 +00:00
<trans-unit id="sb8e4edaea6f1d935">
<source>Avatars</source>
2023-12-08 01:52:59 +00:00
</trans-unit>
2024-01-03 11:22:25 +00:00
<trans-unit id="s945856050217c828">
<source>Configure how authentik should show avatars for users. The following values can be set:</source>
2023-12-08 01:52:59 +00:00
</trans-unit>
2024-01-03 11:22:25 +00:00
<trans-unit id="sf4ef4c8ce713f775">
<source>Disables per-user avatars and just shows a 1x1 pixel transparent picture</source>
2023-12-08 01:52:59 +00:00
</trans-unit>
2024-01-03 11:22:25 +00:00
<trans-unit id="s5446842a7e4a963b">
<source>Uses gravatar with the user's email address</source>
2023-12-08 01:52:59 +00:00
</trans-unit>
2024-01-03 11:22:25 +00:00
<trans-unit id="s35363b9e1cc2abd3">
<source>Generated avatars based on the user's name</source>
2023-12-08 01:52:59 +00:00
</trans-unit>
2024-01-03 11:22:25 +00:00
<trans-unit id="s48110ca292cad513">
<source>Any URL: If you want to use images hosted on another server, you can set any URL. Additionally, these placeholders can be used:</source>
2023-12-08 01:52:59 +00:00
</trans-unit>
2024-01-03 11:22:25 +00:00
<trans-unit id="sbe1dfda044bdc93b">
<source>The user's username</source>
2023-12-08 01:52:59 +00:00
</trans-unit>
2024-01-03 11:22:25 +00:00
<trans-unit id="s653f257c9c2d4dc5">
<source>The email address, md5 hashed</source>
2023-12-08 01:52:59 +00:00
</trans-unit>
2024-01-03 11:22:25 +00:00
<trans-unit id="s9c9183cd80916b4f">
<source>The user's UPN, if set (otherwise an empty string)</source>
2023-12-08 01:52:59 +00:00
</trans-unit>
2024-01-03 11:22:25 +00:00
<trans-unit id="h4963ed14d7e239a9">
<source>An attribute path like
<x id="0" equiv-text="<code>"/>attributes.something.avatar<x id="1" equiv-text="</code>"/>, which can be used in
combination with the file field to allow users to upload custom
avatars for themselves.</source>
2023-12-08 01:52:59 +00:00
</trans-unit>
2024-01-03 11:22:25 +00:00
<trans-unit id="s4c80c34a67a6f1c9">
<source>Multiple values can be set, comma-separated, and authentik will fallback to the next mode when no avatar could be found.</source>
2023-12-08 01:52:59 +00:00
</trans-unit>
2024-01-03 11:22:25 +00:00
<trans-unit id="h2fafcc3ebafea2f8">
<source>For example, setting this to <x id="0" equiv-text="<code>"/>gravatar,initials<x id="1" equiv-text="</code>"/> will
attempt to get an avatar from Gravatar, and if the user has not
configured on there, it will fallback to a generated avatar.</source>
2023-12-08 01:52:59 +00:00
</trans-unit>
2024-01-03 11:22:25 +00:00
<trans-unit id="s078ffec0257621c0">
<source>Enable the ability for users to change their name.</source>
2023-12-08 01:52:59 +00:00
</trans-unit>
2024-01-03 11:22:25 +00:00
<trans-unit id="s5fc6c14d106f40d3">
<source>Enable the ability for users to change their email.</source>
2023-12-08 01:52:59 +00:00
</trans-unit>
2024-01-03 11:22:25 +00:00
<trans-unit id="s6d816a95ca43a99d">
<source>Enable the ability for users to change their username.</source>
2023-12-08 01:52:59 +00:00
</trans-unit>
2024-01-03 11:22:25 +00:00
<trans-unit id="s57b52b60ed5e2bc7">
<source>Footer links</source>
2023-12-08 01:52:59 +00:00
</trans-unit>
2024-01-03 11:22:25 +00:00
<trans-unit id="s7349802b2f7f99c2">
<source>This option configures the footer links on the flow executor pages. It must be a valid JSON list and can be used as follows:</source>
2023-12-08 01:52:59 +00:00
</trans-unit>
2024-01-03 11:22:25 +00:00
<trans-unit id="s166b59f3cc5d8ec3">
<source>GDPR compliance</source>
2023-12-08 01:52:59 +00:00
</trans-unit>
2024-01-03 11:22:25 +00:00
<trans-unit id="sb8b23770f899e5bb">
<source>When enabled, all the events caused by a user will be deleted upon the user's deletion.</source>
2023-12-08 01:52:59 +00:00
</trans-unit>
2024-01-03 11:22:25 +00:00
<trans-unit id="s29501761df0fe837">
<source>Impersonation</source>
2023-12-08 01:52:59 +00:00
</trans-unit>
2024-01-03 11:22:25 +00:00
<trans-unit id="s8f503553d8432487">
<source>Globally enable/disable impersonation.</source>
2023-12-20 08:45:34 +00:00
</trans-unit>
2024-01-03 11:22:25 +00:00
<trans-unit id="see1eb81c1f734079">
<source>System settings</source>
2024-01-15 22:40:45 +00:00
</trans-unit>
2024-01-16 04:50:09 +00:00
<trans-unit id="s5faec5eb5faf62ac">
<source>Allow users to change name</source>
2024-01-15 22:40:45 +00:00
</trans-unit>
2024-01-16 04:50:09 +00:00
<trans-unit id="s456d88f3679190fd">
<source>Allow users to change email</source>
2024-01-15 22:40:45 +00:00
</trans-unit>
2024-01-16 04:50:09 +00:00
<trans-unit id="s628e414bb2367057">
<source>Allow users to change username</source>
2023-06-12 13:41:44 +00:00
</trans-unit>
web: Replace lingui.js with lit-localize (#5761)
* \#\# Details
web: replace lingui with lit/localize
\#\# Changes
This rather massive shift replaces the lingui and `t()` syntax with lit-localize, XLIFF, and the `msg()`
syntax used by lit-localize. 90% of this work was mechanized; simple perl scripts found and replaced
all uses of `t()` with the appropriate corresponding syntax for `msg()` and `msg(str())`.
The XLIFF files were auto-generated from the PO files. They have not been audited, and they should be
checked over by professional translators. The actual _strings_ have not been changed, but as this was
a mechanized change there is always the possibility of mis-translation-- not by the translator, but by
the script.
* web: revise lit/localize: fix two installation issues.
* web: revise localization
TL;DR:
- Replaced all of Lingui's `t()` syntax with `msg()` syntax.
- Mechanically (i.e with a script) converted all of the PO files to XLIFF files
- Refactored the localization code to be a bit smarter:
- the function `getBestMatchLocale` takes the locale lists and a requested locale, and returns the
first match of:
- The locale's code exactly matches the requested locale
- The locale code exactly matches the prefix of the requested locale (i.e the "en" part of "en-US")
- the locale code's prefix exactly matches the prefix of the requested locale
This function is passed to lit-locate's `loadLocale()`.
- `activateLocale()` just calls `loadLocale()` now.
- `autodetectLanguage` searches the following, and picks the first that returns a valid locale
object, before passing it to `loadLocale()`:
- The User's settings
- A `?locale=` component found in `window.location.search`
- The `window.navigator.language` field
- English
The `msg()` only runs when it's run. This seems obvious, but it means that you cannot cache
strings at load time; they must be kept inside functions that are re-run so that the `msg()` engine
can look up the strings in the preferred language of the user at that moment.
You can use thunks-of-strings if you really need them that way.
* Including the 'xliff-converter' in case anyone wants to review it.
* The xliff-converter is tagged as 'xliff-converter', but has been
deleted.
\#\# Details
- Resolves #5171
\#\# Changes
\#\#\# New Features
- Adds a "Add an Application" to the LibraryView if there are no applications and the user is an administrator.
\#\#\# Breaking Changes
- Adds breaking change which causes \<issue\>.
\#\# Checklist
- [ ] Local tests pass (`ak test authentik/`)
- [ ] The code has been formatted (`make lint-fix`)
If an API change has been made
- [ ] The API schema has been updated (`make gen-build`)
If changes to the frontend have been made
- [ ] The code has been formatted (`make web`)
- [ ] The translation files have been updated (`make i18n-extract`)
If applicable
- [ ] The documentation has been updated
- [ ] The documentation has been formatted (`make website`)
* web: fix redundant locales for zh suite.
* web: prettier pass for locale update
* web: localization moderization
Changed the names of the lit-localize commands to make it clear they're
part of the localization effort, and not just "build" and "extract".
* update transifex config
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* fix package lock?
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* use build not compile
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
* web: conversion to lit-localize
The CI produced a list of problems that I hadn't caught earlier,
due to a typo ("localize build" is correct, "localize compile" is
not) I had left in package.json. They were minor and linty, but
it was still wise to fix them.
* web: replace lingui with lit/locale
This commit fixes some minor linting issues that were hidden by a typo in package.json. The
issues were not apparently problematic from a Javascript point of view, but they pointed
to sloppy thinking in the progression of types through the system, so I cleaned them
up and formalized the types from LocaleModule to AkLocale.
* web: replace lingui with lit/localize
One problem that has repeatedly come up is that localize's templates do not produce
JavaScript that conforms with our shop style. I've replaced `build-locale` with
a two-step that builds the locale *and* ensures that it conforms to the shop style
via `prettier` every time.
* web: replace lingui with lit-locale
This commit applies the most recent bundle of translations to the
new lit-locale aspect component. It also revises the algorithm
for *finding* the correct locale, replacing the complex fall-back
with some rather straightforward regular expressions.
In the case of Chinese, the fallback comes at the end of the
selection list, which may not be, er, politically valuable
(since Taiwan and Hong Kong come before, being exceptions that
need to be tested). If we need a different order for presentation,
that'll be a future feature.
* web: replace lingui with lit/locale
Well, that was embarassing.
---------
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-06-02 15:08:36 +00:00
</body>
</file>
</xliff>