Commit graph

2224 commits

Author SHA1 Message Date
Ken Sternberg 6df83e4259
web/admin: fix html error on oauth2 provider page (#7384)
* 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.

* \# Details

Extra `>` symbol screwed up the reading of the rest of the component.  Unfortunately,
too many fields in an input are optional, so it was easy for this bug to bypass any
checks by the validators.  I should have caught it myself, though.
2023-10-30 15:35:37 -07:00
Jens Langhammer 8e72fcab59
release: 2023.10.2 2023-10-28 21:43:54 +02:00
Jens L 41d372a340
web/admin: fix @change handler for ak-radio elements (#7348)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-27 16:28:18 +02:00
Jens L ae4d5a30f2
web/admin: fix role form reacting to enter (#7330)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-27 11:39:39 +02:00
Jens Langhammer 64c38909ff
release: 2023.10.1 2023-10-26 20:06:05 +02:00
Jens Langhammer ed46fd629e
release: 2023.10.0 2023-10-26 16:51:57 +02:00
Jens L 28053059ff
stages/user_write: allow setting user type when creating new user (#7293)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-26 14:33:29 +02:00
dependabot[bot] 3f5d5e0408
web: bump fuse.js from 6.6.2 to 7.0.0 in /web (#7307)
Bumps [fuse.js](https://github.com/krisk/Fuse) from 6.6.2 to 7.0.0.
- [Release notes](https://github.com/krisk/Fuse/releases)
- [Changelog](https://github.com/krisk/Fuse/blob/main/CHANGELOG.md)
- [Commits](https://github.com/krisk/Fuse/compare/v6.6.2...v7.0.0)

---
updated-dependencies:
- dependency-name: fuse.js
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-26 12:29:25 +02:00
Ken Sternberg a52e4a3262
web: extract form processing (#7298)
* 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
2023-10-25 14:39:50 -07:00
Jens L f6118ec876
web/admin: add preview banner to RBAC pages (#7295)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-25 20:15:28 +02:00
Marc 'risson' Schmitt 488420eeb6 web: fix typo in traefik name
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2023-10-25 18:55:37 +02:00
Jens L a8f066eb51
web/admin: disable wizard banner for now (#7294)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-25 18:30:58 +02:00
Jens L 7673e5a297
web/admin: small fixes (#7292)
* show user type better on admin interface

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix rendering for backchannel in app form

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix missing trailing slash in admin redirect

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-25 18:25:37 +02:00
Ken Sternberg e3ac774a18
web: 3 fixes for small typos, annoyances, and improvements (#7249)
I'm conducting a more comprehensive survey of the UI in order to get a more holistic idea of the
changes that should be implemented.  Along the way, I'm finding a few small details that annoy me.
Here are three.

It goes to "User statistics."  I have changed both the text of the link and the page to read "User
Statistics" (it's a title, it should be capitalized).

Give people warning when you're about to take them out of the system, especially if you're opening a
new tab along the way.

Just a thing I spotted along the way.
2023-10-23 10:48:16 -07:00
Jens L 75aedb4d3f
web/admin: small wizard fixes (#7259) 2023-10-23 18:48:12 +02:00
Ken Sternberg 9582cd4599
web: break circular dependency between AKElement & Interface. (#7165)
* 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.
2023-10-20 14:26:57 -07:00
Ken Sternberg cc781cad00
web/admin: improve user email button labels (#7233)
* web: isolate clipboard handling

We would like to use the clipboard for more than just the token copy button.  This commit
enables that by separating the "Write to Clipboard" and "Write to Notifications" routines
into separate functions, putting "writeToClipboard" into the utilities collection, and
clarifying what happens when a custom presses the TokenCopy button.

* web: break out the recovery link logic into a standalone function

UserViewPage and UserLinkPage have the same functionality to request to view a
link with which a user may access an account recovery flow.  The language and
error messages were different on both of those pages.  This commit harmonizes
the language by making the request a standalone function.  It also exploits the
breakout of the "write to clipboard" commit to write the link to the clipboard,
and to inform the user that the clipboard has been written to, when possible.

* web: parity between UserViewPage and UserListPage

Since the UserListPage's "accordion" view has an offer to "Email
the recovery link" to the user, it seemed appropriate to grant the
same capability to the UserListPage.

* web: harmonize the CSS.

After a bit of messing around, I have also ensured that the gap between the buttons is
the same in all cases, that in the columnar display the buttons are of uniform width,
and that the buttons have the same next:

- "Set Password"
- "View Recovery Link"
- "Email Recovery Link"

NOTE: This commit is contingent upon the PR for [isolate clipboard
handling](https://github.com/goauthentik/authentik/pull/7229) to
be accepted, as it relies on the clipboard handler for the "write
link to clipboard" feature.

* web: ensure the existence of the user

Every `...render()` method in the UserViewPage class has a preamble
guard clause:

```
    if (!this.user) {
        return html``;
    }
```

With this clause, it should not be necessary to repeatedly check
the type of `this.user` throughout the rest of the method, but the
nominal type is `User?`, which means that functions called from
within the method need to be protected against `undefined` failure.
By creating a new variable with the type after the guard clause,
we ensure the type is `User` (no question!) and can safely use it
without those checks.

Along the way, I replaced the empty html with `nothing` and corrected
(mostly by removing) the return types.

References:

- [Lit-HTML: Prefer `nothing` over empty html or other falsey walues](https://lit.dev/docs/api/templates/#nothing)
- [TypeScript: Type annotations on return types are rarely
necessary](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#:~:text=Return%20Type%20Annotations&text=Much%20like%20variable%20type%20annotations,example%20doesn't%20change%20anything.)

* web: accepting suggested label change
2023-10-20 10:01:18 -07:00
Jens L 63426bc9a8
sources/oauth: include default JWKS URLs for OAuth sources (#6992)
* sources/oauth: include default JWKS URLs for OAuth sources

makes it easier to use pre-defined types like github, google, azure with JWT M2M instead of needing to create a generic OAuth Source

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix error

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-20 16:54:03 +02:00
Ken Sternberg 20e003656a
web: fix bad comment that was confusing lit-analyze (#7234)
The old comment was left over from a previous revision of the wizard, and
blocked lit-analyze's ability to understand the Modal's `slot="trigger"`
declaration.
2023-10-20 11:17:24 +02:00
Ken Sternberg 7e536515c6
web: isolate clipboard handling (#7229)
We would like to use the clipboard for more than just the token copy button.  This commit
enables that by separating the "Write to Clipboard" and "Write to Notifications" routines
into separate functions, putting "writeToClipboard" into the utilities collection, and
clarifying what happens when a custom presses the TokenCopy button.
2023-10-19 16:26:02 -07:00
Jens L 92d170d065
web/flows: update flow background (#7232)
* web/flows: update flow background

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* Optimised images with calibre/image-actions

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2023-10-19 23:53:27 +02:00
Jens L 41464aec18
web/admin: fix prompt form and codemirror mode (#7231)
* web/admin: fix extra curly brace

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* also fix form rendering

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix codemirror alignment

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* use enum for codemirror mode to prevent invalid mode

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-19 23:53:04 +02:00
Jens L 4686796543
web/admin: decrease wizard hint padding (#7227)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-19 17:59:08 +02:00
Jens L acad3c4d5c
core/rbac: fix missing field when removing perm, add delete from object page (#7226)
* make object permissions deletable from the object page

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix error when removing object permissions form user/role page

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* upgrade translation

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-19 14:53:56 +02:00
Ken Sternberg 3a7283c670
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 3718ee6904.

* 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 09fedcacf0.

* 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 12:43:37 -07:00
Jens L 8aafa06259
providers/radius: TOTP MFA support (#7217)
* move CheckPasswordMFA to flow executor

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add mfa support field to radius

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-18 19:43:36 +02:00
Samir Musali a60f3b4b81
stage/deny: add custom message (#7144)
* stage/deny: add message

* add migration, tests and schema update

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add form

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-10-18 17:13:33 +02:00
Jens Langhammer c7182bf513
Revert "web: Updates to the Context and Tasks libraries from lit. (#7168)"
This reverts commit 15be83c06c.
2023-10-18 11:22:00 +02:00
Ken Sternberg 15be83c06c
web: Updates to the Context and Tasks libraries from lit. (#7168)
* Updates to the Context and Tasks libraries from lit.

* web: fix for bad merge

* Still trying to solve that f*&!ing merge bug.

* fix build

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* Updates to the Context and Tasks libraries from lit.

* web: fix for bad merge

* Still trying to solve that f*&!ing merge bug.

* fix build

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-10-17 21:35:11 +02:00
Ken Sternberg 9e568e1e85
web: the return of pseudolocalization (#7190)
* web: the return of pseudolocalization

The move to lit-locale lost the ability to automagically pseudolocalize the UI, a useful
utility for checking that additions to the UI have been properly cataloged as
translation targets.  This short script (barely 40 lines) digs deep into the lit-localize
toolkit and produces a pretranslated translation bundle in the target format folder.

* Linted, prettied, and commented.
2023-10-16 13:54:43 -07:00
Jens L e28babb0b8
core: Initial RBAC (#6806)
* rename consent permission

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* the user version

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

t

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* initial role

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* start form

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* some minor table refactoring

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix user, add assign

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add roles ui

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix backend

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add assign API for roles

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* start adding toggle buttons

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* start view page

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* exclude add_ permission for per-object perms

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* small cleanup

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add permission list for roles

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* make sidebar update

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix page header not re-rendering?

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fixup

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add search

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* show first category in table groupBy except when its empty

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* make model and object PK optional but required together

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* allow for setting global perms

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* exclude non-authentik permissions

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* exclude models which aren't allowed (base models etc)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* ensure all models have verbose_name set, exclude some more internal objects

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* lint fix

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix role perm assign

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add unasign for global perms

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add meta changes

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* clear modal state after submit

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add roles to our group

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix duplicate url names

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* make recursive group query more usable

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add name field to role itself and move group creation to signal

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* start sync

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* move rbac stuff to separate django app

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix lint and such

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix go

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* update

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* start API changes

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add more API tests

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* make admin interface not require superuser for now, improve error handling

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* replace some IsAdminUser where applicable

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* migrate flow inspector perms to actual permission

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix license not being a serializermodel

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add permission modal to models without view page

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add additional permissions to assign/unassign permissions

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add action to unassign user permissions

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add permissions tab to remaining view pages

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix flow inspector permission check

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix codecov config?

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add more API tests

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* ensure viewsets have an order set

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* hopefully the last api name change

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* make perm modal less confusing

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* start user view permission page

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* only make delete bulk form expandable if usedBy is set

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* expand permission tables

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add more things

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add user global permission table

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix lint

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix tests' url names

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add tests for assign perms

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add unassign tests

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* rebuild permissions

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* prevent assigning/unassigning permissions to internal service accounts

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* only enable default api browser in debug

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix role object permissions showing duplicate

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix role link on role object permissions table

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix object permission modal having duplicate close buttons

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* return error if user has no global perm and no object perms

also improve error display on table

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* small optimisation

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* optimise even more

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* update locale

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* add system permission for non-object permissions

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* allow access to admin interface based on perm

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* clean

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* don't exclude base models

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-16 17:31:50 +02:00
Jens L 41bb1ca707
providers/scim: remove preview (#7166)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-13 19:03:13 +02:00
Ken Sternberg 9d18bc545f
web: change 'Attributes' to 'Custom attributes' on Invitation Field (#7145)
Everywhere else, the label "Attributes" refers to the dictionary field that our
core models have and use as a JSON repository for key/value pairs that don't need
the full model's awareness or management.  Using the same label here, where the
term refers to the context data of the invitation itself, may confuse people,
so we've changed the label to signal its difference.
2023-10-12 12:33:45 -07:00
Ken Sternberg 21e5441f92
web: patternfly hints as ak-web-component (#7120)
* web: patternfly hints as ak-web-component

Patternfly 5's "Hints" React Component, but ported to web components.
The discovery that CSS Custom Properties are still available in
child components, even if they're within independent ShadowDOMs,
made this fairly easy to port from Handlebars to Lit-HTML.  Moving
the definitions into `:host` and the applications into the root DIV
of the component made duplicating the Patternfly 5 structure
straightforward.

Despite the [Patternfly
Elements]documentation](https://patternflyelements.org/docs/develop/create/),
there's a lot to Patternfly Elements that isn't well documented,
such as their slot controller, which near as I can tell just makes
it easy to determine if a slot with the given name is actually being
used by the client code, but it's hard to tell why, other than that it
provides an easy way to determine if some CSS should be included.

* Pre-commit fixes.

* web: fix some issues with styling found while testing.

* web: separated the "with Title" and "without Title" stories.

* Added footer story, fixed some CSS.

* web: hint controller

Add the `ShowHintController`.  This ReactiveController takes a token
in its constructor, and looks in LocalStorage for that token and
an associated value.  If that value is not `undefined`, it sets the
field `this.host.showHint` to the value found.

It also provides a `render()` method that provides an `ak-hint-footer`
with a checkbox and the "Don't show this message again," and responds
to clicks on the checkbox by setting the `this.hint.showHint` and
LocalStorage values to "false".

An example web component using it has been supplied.

* web: support dark mode for hints.

This was nifty.  Still not entirely sure about the `theme="dark"`
rippling through the product, but in this case it works quite well.
All it took was defining the alternative dark mode values in a CSS
entry, `:host([theme="dark"]) { ... }` and exploiting Patternfly's
already intensely atomized CSS Custom Properties properly.

* web: revise colors to use more of the Authentik dark-mode style.

* Update web/src/components/ak-hint/ak-hint.ts

Signed-off-by: Jens L. <jens@beryju.org>

* remove any

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens L. <jens@beryju.org>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L <jens@goauthentik.io>
2023-10-12 10:44:15 -07:00
Jens L b503379319
web: fix form default submit handler (#7122)
* web/elements: rename renderInlineForm to renderForm set submit handler to empty function

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix all kinds of forms not using the form inheritance correctly

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-12 15:12:46 +02:00
Jens L d1f2e7c0cd
web/admin: add additional Flow info (#7155)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-12 14:00:45 +02:00
Jens L 6f3fc22c9b
providers/saml: add default RelayState value for IDP-initiated requests (#7100)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-09 00:08:16 +02:00
Ken Sternberg 6792bf8876
web: package up horizontal elements into their own components (#7053)
* 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: package up horizontal elements into their own components.

This commit introduces a number of "components."  Jens has this idiom:

```
   <ak-form-element-horizontal label=${msg("Name")} name="name" ?required=${true}>
       <input
           type="text"
           value="${ifDefined(this.instance?.name)}"
           class="pf-c-form-control"
           required
       />
   </ak-form-element-horizontal>
```

It's a very web-oriented idiom in that it's built out of two building blocks, the "element-horizontal" descriptor,
and the input object itself.  This idiom is repeated a lot throughout the code.  As an alternative, let's wrap
everything into an inheritable interface:

```
  <ak-text-input
      name="name"
      label=${msg("Name")}
      value="${ifDefined(this.instance?.name)}
      required
  >
  </ak-text-input>
```

This preserves all the information of the above, makes it much clearer what kind of interaction we're having
(sometimes the `type=` information in an input is lost or easily missed), and while it does require you know
that there are provided components rather than the pair of layout-behavior as in the original it also gives
the developer more precision over the look and feel of the components.

*Right now* these components are placed into the LightDOM, as they are in the existing source code, because
the Form handler has a need to be able to "peer into" the "element-horizontal" component to find the values
of the input objects.  In a future revision I hope to place the burden of type/value processing onto the
input objects themselves such that the form handler will need only look for the `.value` of the associated
input control.

Other fixes:

- update the FlowSearch() such that it actually emits an input event when its value changes.
- Disable the storybook shortcuts; on Chrome, at least, they get confused with simple inputs
- Fix an issue with precommit to not scan any Python with ESLint!  :-)

* web: provide storybook stories for the components

This commit provides storybook stories for the ak-horizontal-element wrappers.  A few
bugs were found along the way, including one rather nasty one from Radio where we
were still getting the "set/unset" pair in the wrong order, so I had to knuckle down
and fix the event handler properly.

* web: test oauth2 provider "guinea pig" for new components

I used the Oauth2 provider page as my experiment in seeing if the
horizontal-element wrappers could be used instead of the raw wrappers
themselves, and I wanted to make sure a test existed that asserts
that filling out THAT form in the ProvidersList and ProvidersForm
didn't break anything.

This commit updates the WDIO tests to do just that; the test is
simple, but it does exercise the `name` field of the Provider,
something not needed in the Wizard because it's set automatically
based on the Application name, and it even asserts that the new
Provider exists in the list of available Providers when it's done.

* web: making sure ESlint and Prettier are happy

* "fix" lint

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-10-04 13:07:52 -07:00
Jens L 03287936e9
web/flows: fix plex login not opening new tab on mobile safari (#7050)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-03 15:32:48 +02:00
Jens L a0f607b5ac
web/flows: bottom-align about text on flows page (#7051)
* web/flows: bottom-align about text on flows page

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* fix a bunch of typos

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-03 14:10:10 +02:00
Ken Sternberg 3b171a02b7
web: laying the groundwork for future expansion (#7045)
* 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>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2023-10-02 13:33:27 -07:00
Jens L 86939937cf
web/admin: use <pre> for order field on bound elements (#7031)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-10-02 16:57:21 +02:00
Marc 'risson' Schmitt 9c3ff1d71b web: locales: rename fr_FR to fr to match transifex
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2023-10-02 13:31:21 +02:00
Marc 'risson' Schmitt d55c0c1c2d web/admin: invitation stage: default "continue without invitation" to false
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2023-09-29 18:40:12 +02:00
Jens L 8e39ad2cda
web/user: fix incorrect link to admin interface (#6993) 2023-09-26 19:51:45 +02:00
Jens L 3e81824388
core: prevent self-impersonation (#6885)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-26 12:04:40 +02:00
Jens L ce1a071d16
web/user: fix unenrollment flow not being shown (#6972)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-25 16:59:45 +02:00
Jens L 80e86c52e7
web/flows: improve WebAuthn error messages (#6957)
* web/flows: improve WebAuthn error messages

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* include localhost

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2023-09-25 12:43:24 +02:00
Ken Sternberg 671b7156ed
web: improve testability (#6952)
web/improve testability

This is a trio of small hacks that allow the E2E tests to find several components
on the page while the test is running:

- Add a `data-managed-for` field to SearchSelect's positioned elements. If a search
  has a `name` field, it will be reflected here, allowing tests to find specific
  instances of the dropdown elements.
- Add a forwarder to the search select wrappers we use for our SearchSelect.
- Added aria details to the UserLibrary header to make it easy to identify.
2023-09-22 09:04:30 -07:00
Ken Sternberg 42c3cfa65d
web/admin: user details few tooltip buttons (#6899)
* Web: Detangling some circular dependencies in Admin and User

Admin, User, and Flow should not dependend upon each other, at least
not in a circular way.  If Admin and User depend on Flow, that's
fine, but Flow should not correspondingly depend upon elements of
either; if they have something in common, let's put them in
`@goauthentik/common` or find some other smart place to store them.

This commit refactors the intentToLabel and actionToLabel functions
into `@goauthentik/common/labels` and converts them to static tables
for maintenance purposes.

* web: "Consistency is the hobgoblin of small minds" - Ralph Waldo Emerson

* web: I found these confusing to look at, so I added comments.

* web: remove admin-to-user component reference(s)

There was only one: AppIcon.  This has been moved to `components`.

Touching the LibraryApplications page triggered a cyclomatic
complexity check.  Extracting the expansion block and streamlining
the class and style declarations with lit directives helped.

* web: remove admin from elements

This commit removes the two references from `elements` to `admin`: the list of UserEvents and a
reference to the FlowSearch type, used by the Forms manager to decide how to extract a value.
For FlowSearch, a different convention for detecting the type was implemented (instances of the
object have a unique fieldname for the value holder).  UserEvents and ObjectChangelog have been
moved to `components` as they're clearly dependent upon the API.

This defers work on removing Admin from Components, as that is (again) references going the
wrong way, but that can happen later.

* web: remove admin-to-user component reference(s) (#6856)

There was only one: AppIcon.  This has been moved to `components`.

Touching the LibraryApplications page triggered a cyclomatic
complexity check.  Extracting the expansion block and streamlining
the class and style declarations with lit directives helped.

* This was supposed to be merged.

* web: remove `./element`⇢`./user` references

The offender here is UserDevicesList, which despite being in `elements` is only
used by the admin/user/UserViewPage.  The problem is that UserDevicesList,
despite being in `admin`, inherits from `user`, so moving it would have created
a new admin⇢user reference, and the whole point of this exercise is to get rid
of references that point "up" from the foundational pieces to the views, or
that refer to components in sibling applications.

After examining UserDevicesList, I realized that *every feature* of MFADevicesList
had been overridden: the rows, the columns, the toolbar, and the endpoint all had
custom overrides.  Nothing was left of MFADevicesList after that.   Even the
property that the web component used had been completely changed.  The only thing
they had in common was that they both inherited from `Table<Device>`.

Refactoring UserDevicesList so that it inherited directly from `Table<Device>` and
then moving it into `./admin/users` was the obvious and correct step.

Both used the same label table, so that went into the `common/labels` folder.

Along the way, I cleaned up a few minor details. Just little things, like the repeated invocation
of:

```
new AuthenticatorsApi(DEFAULT_CONFIG).authenticatorAdminMETHODDestroy({ id: device.pk });
```

This is repeated five times, once for each Method.  By creating these:

```
        const api = new AuthenticatorsApi(DEFAULT_CONFIG);
        const id = { id: device.pk };
```

The method invocation could be just `api.authenticatorsMETHODDestroy(id)`, which is easier on the
eyes.  See the MFADevicesPage for the full example.

Similarly,

```
return [
   new TableColumn(msg("Name"), ""),
   new TableColumn(msg("Type"), ""),
   new TableColumn("")
];
   ```

is more straightforward as:

```
const headers = [msg("Name"), msg("Type"), ""];
return headers.map((th) => new TableColumn(th, ""));
```

We've labeled what we're working with, and web developers ought to know that `th` is the HTML code
for `table header`.

I've had to alter what files are scanned in pre-commit mode; it doesn't handle renamed files very well,
and at the moment a file that is renamed is not scanned, as its "new" name is not straightforwardly
displayed, not even by `git porcelain`.

* web: make the table of column headers look like a table

* web: detangle `common` from `elements`.

And just like that, `common` no longer has a reference to `elements`.   I don't mind this little bit of
code duplication if it removes a cycle.  What it does point out is that there are bits of `common` that
are predicated on the presence of the browser, and that there are bits of `elements` that, if they rely
on `common`, can't be disentangled from the application as a whole.  Which seems to me that we have two
different things going on in common: things about an application, and things about elements that are
independent of the application.

I'll think about those later.

```
$ rg 'import.*@goauthentik' ./common/ | perl -ne 'm{"(@goauthentik[^"]*)"} && print "$1\n"' | sort | cut -d '/' -f1-2 | uniq | sort
@goauthentik/api
@goauthentik/common
$
```

* web: odd bug; merge-related?  Gonna investigate.

* web: build failure thanks to local cache; fixed

* web: detangle `components` from `admin`.

This was the last inappropriate reference: something from `./components` referencing something in
`./admin`, in this case the `ak-event-info` component.  Used by both Users and Admin, moving it
into `./components` was the obvious correct step.

`ak-event-info` is a lookup table relating specific events in the event log to rich, textual
representations; in the special case of model changes and email info, even more rich content is
available in a dl/dt format. I've tableized the model changes and email info renderer, and I've
extracted every event's textual representation into its own method, converting the `switch/case`
rendering statement into a `switch/case` dispatch switch. This has the virtue of isolating each
unique case and making the dispatch switch short and coherent.

The conversion was done mechanistically; I gave the refactorer (Tide, in this case) instructions to
duplicate the switch block and then convert every case into a method with a name patterned on the
`case`. Going back to the original switch block, it was easy to duplicate the pattern matching and
convert it into a dispatch switch.

And with this, there are zero cycles in the references between the different "packageable" sections
of the UI.  The only thing left to do is figure out how to redistribute `./elements` and `./components`
in a way that makes sense for each.

* Changed function name from 'emailMessageBody' to 'githubIssueMessageBody' to better reflect its usage.

* web: added comments about length and purpose of githubIssueMessageBody.

* Update web/src/common/labels.ts

Co-authored-by: Jens L. <jens@goauthentik.io>
Signed-off-by: Ken Sternberg <133134217+kensternberg-authentik@users.noreply.github.com>

* Unwanted change.

* web/add tooltip buttons to user details page

This commit wraps the command buttons on the UserDetailsPage with tooltips providing greater copy
explaining what each button does. It also ensures that every button is a minimum of 11ems in width
(The longest phrase, 'Reset Password', results in a width of 10.75ems; this makes them all
consistent.)

The technique for giving the `ak-action-button` objects a mininum width uses the CSS `::part()`
syntax, which is new. CanIUse shows that it's at 95.3% of global usage; our weak points remain Opera
Mini and UC Browser for Android.

Oh, and IE. But the various Powers That Be™ agree we're no longer tracking or caring about IE.

* I added some text, so it's my responibility to add the language files.

* fix text

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* rework

Signed-off-by: Jens Langhammer <jens@goauthentik.io>

* web: enforce a max-width on the container for the buttons so that they don't look funky on ultrawide monitors.

* wbe: re-ran and confirmed prettier.

---------

Signed-off-by: Ken Sternberg <133134217+kensternberg-authentik@users.noreply.github.com>
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens L. <jens@goauthentik.io>
2023-09-18 10:27:13 -07:00