Compare commits

..

29 Commits

Author SHA1 Message Date
00c1e17b52 Merge branch 'main' into web/add-command-palette
Signed-off-by: Jens Langhammer <jens@goauthentik.io>

# Conflicts:
#	web/package-lock.json
#	web/package.json
#	web/src/admin/AdminInterface/AdminInterface.ts
2025-06-14 02:17:24 +02:00
3c2ce40afd web/admin: Text and Textarea Fields that "hide" their contents until prompted (#15024)
* web: Add InvalidationFlow to Radius Provider dialogues

## What

- Bugfix: adds the InvalidationFlow to the Radius Provider dialogues
  - Repairs: `{"invalidation_flow":["This field is required."]}` message, which was *not* propagated
    to the Notification.
- Nitpick: Pretties `?foo=${true}` expressions: `s/\?([^=]+)=\$\{true\}/\1/`

## Note

Yes, I know I'm going to have to do more magic when we harmonize the forms, and no, I didn't add the
Property Mappings to the wizard, and yes, I know I'm going to have pain with the *new* version of
the wizard. But this is a serious bug; you can't make Radius servers with *either* of the current
dialogues at the moment.

* This (temporary) change is needed to prevent the unit tests from failing.

\# What

\# Why

\# How

\# Designs

\# Test Steps

\# Other Notes

* Revert "This (temporary) change is needed to prevent the unit tests from failing."

This reverts commit dddde09be5.

* web/admin: Provide `hidden` text and textarea components

## Details

This commit provides two new elements (technically, since they're API-unaware), one for `<input
type="text">`, and one for `<textarea>`, that provide for the ability to create fields that are (or
can be) hidden. A new boolean attribute, `revealed`, shows the state of the component (the content
is therefore *not* revealed by default).

It also includes a third new element, `ak-visibility-toggle`, that creates a hide/show toggle with
all the right icons, styling, and eventing.  It's straightforward, and isolating it improved the
DX of everything that uses that feature by quite a bit.

Storybook stories (with autodoc documentation) have been provided for `ak-hidden-text-input`,
`ak-hidden-textarea-input`, and `ak-visibility-toggle`.

## Maintenance Notice

As a maintenance detail, the field `ak-private-text` has been renamed `ak-secret-text` to reflect
its usage, and the places where it was used have all been changed to reflect that update.

* web/component: embed styling (for now) to handle the lightDom/shadowDom/slot conflicts in HorizontalLightComponent and HorizontalFormElement

* Comments and Types. I really shouldn't have to catch this stuff with my eyeballs.

* fix typo

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2025-06-14 01:48:34 +02:00
2aceed285e providers/rac: fixes prompt data not being merged with connection_settings (#15037)
* Fixes line that pulls in prompt data

* fallback to old settings

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
Co-authored-by: Jens Langhammer <jens@goauthentik.io>
2025-06-13 18:54:20 +02:00
81e5fef667 website/docs: also hide the postgres pool_options setting (#15023) 2025-06-13 13:36:52 +00:00
7aa6593760 blueprints: sort schema items (#15022) 2025-06-13 13:34:49 +00:00
c40a17beb9 website: bump the build group in /website with 6 updates (#15027)
Bumps the build group in /website with 6 updates:

| Package | From | To |
| --- | --- | --- |
| [@swc/core-darwin-arm64](https://github.com/swc-project/swc) | `1.12.0` | `1.12.1` |
| [@swc/core-linux-arm64-gnu](https://github.com/swc-project/swc) | `1.12.0` | `1.12.1` |
| [@swc/core-linux-x64-gnu](https://github.com/swc-project/swc) | `1.12.0` | `1.12.1` |
| [@swc/html-darwin-arm64](https://github.com/swc-project/swc) | `1.12.0` | `1.12.1` |
| [@swc/html-linux-arm64-gnu](https://github.com/swc-project/swc) | `1.12.0` | `1.12.1` |
| [@swc/html-linux-x64-gnu](https://github.com/swc-project/swc) | `1.12.0` | `1.12.1` |


Updates `@swc/core-darwin-arm64` from 1.12.0 to 1.12.1
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.12.0...v1.12.1)

Updates `@swc/core-linux-arm64-gnu` from 1.12.0 to 1.12.1
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.12.0...v1.12.1)

Updates `@swc/core-linux-x64-gnu` from 1.12.0 to 1.12.1
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.12.0...v1.12.1)

Updates `@swc/html-darwin-arm64` from 1.12.0 to 1.12.1
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.12.0...v1.12.1)

Updates `@swc/html-linux-arm64-gnu` from 1.12.0 to 1.12.1
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.12.0...v1.12.1)

Updates `@swc/html-linux-x64-gnu` from 1.12.0 to 1.12.1
- [Release notes](https://github.com/swc-project/swc/releases)
- [Changelog](https://github.com/swc-project/swc/blob/main/CHANGELOG.md)
- [Commits](https://github.com/swc-project/swc/compare/v1.12.0...v1.12.1)

---
updated-dependencies:
- dependency-name: "@swc/core-darwin-arm64"
  dependency-version: 1.12.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@swc/core-linux-arm64-gnu"
  dependency-version: 1.12.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@swc/core-linux-x64-gnu"
  dependency-version: 1.12.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@swc/html-darwin-arm64"
  dependency-version: 1.12.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@swc/html-linux-arm64-gnu"
  dependency-version: 1.12.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@swc/html-linux-x64-gnu"
  dependency-version: 1.12.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-13 14:44:06 +02:00
335c9fbc10 core: bump astral-sh/uv from 0.7.12 to 0.7.13 (#15028)
Bumps [astral-sh/uv](https://github.com/astral-sh/uv) from 0.7.12 to 0.7.13.
- [Release notes](https://github.com/astral-sh/uv/releases)
- [Changelog](https://github.com/astral-sh/uv/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/uv/compare/0.7.12...0.7.13)

---
updated-dependencies:
- dependency-name: astral-sh/uv
  dependency-version: 0.7.13
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-13 14:44:04 +02:00
51b53caf61 core: bump twilio from 9.6.2 to 9.6.3 (#15029)
Bumps [twilio](https://github.com/twilio/twilio-python) from 9.6.2 to 9.6.3.
- [Release notes](https://github.com/twilio/twilio-python/releases)
- [Changelog](https://github.com/twilio/twilio-python/blob/main/CHANGES.md)
- [Commits](https://github.com/twilio/twilio-python/compare/9.6.2...9.6.3)

---
updated-dependencies:
- dependency-name: twilio
  dependency-version: 9.6.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-13 14:44:01 +02:00
989100a900 core: bump sentry-sdk from 2.29.1 to 2.30.0 (#15030)
Bumps [sentry-sdk](https://github.com/getsentry/sentry-python) from 2.29.1 to 2.30.0.
- [Release notes](https://github.com/getsentry/sentry-python/releases)
- [Changelog](https://github.com/getsentry/sentry-python/blob/master/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-python/compare/2.29.1...2.30.0)

---
updated-dependencies:
- dependency-name: sentry-sdk
  dependency-version: 2.30.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-13 14:43:58 +02:00
8e1531d051 core: bump kubernetes from 32.0.1 to 33.1.0 (#15031)
Bumps [kubernetes](https://github.com/kubernetes-client/python) from 32.0.1 to 33.1.0.
- [Release notes](https://github.com/kubernetes-client/python/releases)
- [Changelog](https://github.com/kubernetes-client/python/blob/v33.1.0/CHANGELOG.md)
- [Commits](https://github.com/kubernetes-client/python/compare/v32.0.1...v33.1.0)

---
updated-dependencies:
- dependency-name: kubernetes
  dependency-version: 33.1.0
  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>
2025-06-13 14:43:22 +02:00
f6f37d6d92 core, web: update translations (#15026)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2025-06-13 02:21:16 +02:00
5b6ca70f22 web: bump the sentry group across 1 directory with 2 updates (#15025)
Bumps the sentry group with 2 updates in the /web directory: [@sentry/browser](https://github.com/getsentry/sentry-javascript) and @spotlightjs/spotlight.


Updates `@sentry/browser` from 9.28.0 to 9.28.1
- [Release notes](https://github.com/getsentry/sentry-javascript/releases)
- [Changelog](https://github.com/getsentry/sentry-javascript/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/getsentry/sentry-javascript/compare/9.28.0...9.28.1)

Updates `@spotlightjs/spotlight` from 2.13.3 to 3.0.0

---
updated-dependencies:
- dependency-name: "@sentry/browser"
  dependency-version: 9.28.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: sentry
- dependency-name: "@spotlightjs/spotlight"
  dependency-version: 3.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: sentry
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-13 02:09:40 +02:00
a74674c3d6 translate: Updates for file web/xliff/en.xlf in zh_CN (#15018)
Translate web/xliff/en.xlf in zh_CN

100% translated source file: 'web/xliff/en.xlf'
on 'zh_CN'.

Co-authored-by: transifex-integration[bot] <43880903+transifex-integration[bot]@users.noreply.github.com>
2025-06-13 02:08:55 +02:00
f46984dec4 lifecycle/aws: bump aws-cdk from 2.1018.0 to 2.1018.1 in /lifecycle/aws (#15016)
Bumps [aws-cdk](https://github.com/aws/aws-cdk-cli/tree/HEAD/packages/aws-cdk) from 2.1018.0 to 2.1018.1.
- [Release notes](https://github.com/aws/aws-cdk-cli/releases)
- [Commits](https://github.com/aws/aws-cdk-cli/commits/aws-cdk@v2.1018.1/packages/aws-cdk)

---
updated-dependencies:
- dependency-name: aws-cdk
  dependency-version: 2.1018.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-13 02:08:34 +02:00
c7963e4af7 website: bump postcss from 8.5.4 to 8.5.5 in /website (#15013)
Bumps [postcss](https://github.com/postcss/postcss) from 8.5.4 to 8.5.5.
- [Release notes](https://github.com/postcss/postcss/releases)
- [Changelog](https://github.com/postcss/postcss/blob/main/CHANGELOG.md)
- [Commits](https://github.com/postcss/postcss/compare/8.5.4...8.5.5)

---
updated-dependencies:
- dependency-name: postcss
  dependency-version: 8.5.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-13 02:08:21 +02:00
6e30b11974 website: bump @types/node from 24.0.0 to 24.0.1 in /website (#15014)
Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 24.0.0 to 24.0.1.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 24.0.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-06-13 02:08:11 +02:00
13bd4069e4 core: fix transaction test case (#15021)
* move patched ct to root

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

* use our transaction test case as base

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

* fix...?

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

* well apparently that works

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

---------

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-13 01:48:26 +02:00
cba8e84bbe fix accent color
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-03-17 03:18:50 +01:00
d313fd7fb4 set dark theme
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-03-17 03:10:02 +01:00
102811508f fix z-index
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-03-17 03:09:53 +01:00
16b3ca3715 web: add command palette
Adds [Ninja Keys](https://github.com/ssleptsov/ninja-keys) (MIT License) to the Admin Interface.
This is a trivial demo. Start the UI and begin by pressing CMD-K or CTRL-K in the Admin Interface.

- Because a lot of the Create and Update operations are accessible as activations-on-modals rather
  than navigable components in their own right, we don't have a way to encode commands like "Start
  the Application Wizard" or "Add a new Policy."
- Our search isn't very quick, so "Edit Application Foo" would have intolerable delays while we
  looked up a list of applications that could be edited.
- The `icon` feature is relatively difficult to exploit because it's a web component and its inner
  styles are inacessible.
- There seem to be cases where the modal-popup and charts conflict.

If we want to move forward with this, we have the challenge of finding activation means for the
various Create and Edit features, and whether or not Search can be meaningfully integrated into the
results.

It would also be nifty if the User and Admin palettes treated each other as peers; you could just go
"CMD-K My User Page" and it would just *take* you there, and "CMD-K Admin Applications" to go back,
creating an illusion of seamlessness.
2024-03-15 15:21:51 -07:00
8b4e0361c4 Merge branch 'main' into dev
* main:
  web: clean up and remove redundant alias '@goauthentik/app' (#8889)
  web/admin: fix markdown table rendering (#8908)
2024-03-14 10:35:46 -07:00
22cb5b7379 Merge branch 'main' into dev
* main:
  web: bump chromedriver from 122.0.5 to 122.0.6 in /tests/wdio (#8902)
  web: bump vite-tsconfig-paths from 4.3.1 to 4.3.2 in /web (#8903)
  core: bump google.golang.org/protobuf from 1.32.0 to 1.33.0 (#8901)
  web: provide InstallID on EnterpriseListPage (#8898)
2024-03-14 08:14:43 -07:00
2d0117d096 Merge branch 'main' into dev
* main:
  api: capabilities: properly set can_save_media when s3 is enabled (#8896)
  web: bump the rollup group in /web with 3 updates (#8891)
  core: bump pydantic from 2.6.3 to 2.6.4 (#8892)
  core: bump twilio from 9.0.0 to 9.0.1 (#8893)
2024-03-13 14:05:11 -07:00
035bda4eac Merge branch 'main' into dev
* main:
  Update _envoy_istio.md (#8888)
  website/docs: new landing page for Providers (#8879)
  web: bump the sentry group in /web with 1 update (#8881)
  web: bump chromedriver from 122.0.4 to 122.0.5 in /tests/wdio (#8884)
  web: bump the eslint group in /tests/wdio with 2 updates (#8883)
  web: bump the eslint group in /web with 2 updates (#8885)
  website: bump @types/react from 18.2.64 to 18.2.65 in /website (#8886)
2024-03-12 13:31:35 -07:00
50906214e5 Merge branch 'main' into dev
* main:
  web: upgrade to lit 3 (#8781)
2024-03-11 11:03:04 -07:00
e505f274b6 Merge branch 'main' into dev
* main:
  web: fix esbuild issue with style sheets (#8856)
2024-03-11 10:28:05 -07:00
fe52f44dca Merge branch 'main' into dev
* main:
  tenants: really ensure default tenant cannot be deleted (#8875)
  core: bump github.com/go-openapi/runtime from 0.27.2 to 0.28.0 (#8867)
  core: bump pytest from 8.0.2 to 8.1.1 (#8868)
  core: bump github.com/go-openapi/strfmt from 0.22.2 to 0.23.0 (#8869)
  core: bump bandit from 1.7.7 to 1.7.8 (#8870)
  core: bump packaging from 23.2 to 24.0 (#8871)
  core: bump ruff from 0.3.1 to 0.3.2 (#8873)
  web: bump the wdio group in /tests/wdio with 3 updates (#8865)
  core: bump requests-oauthlib from 1.3.1 to 1.4.0 (#8866)
  core: bump uvicorn from 0.27.1 to 0.28.0 (#8872)
  core: bump django-filter from 23.5 to 24.1 (#8874)
2024-03-11 10:27:43 -07:00
3146e5a50f web: fix esbuild issue with style sheets
Getting ESBuild, Lit, and Storybook to all agree on how to read and parse stylesheets is a serious
pain. This fix better identifies the value types (instances) being passed from various sources in
the repo to the three *different* kinds of style processors we're using (the native one, the
polyfill one, and whatever the heck Storybook does internally).

Falling back to using older CSS instantiating techniques one era at a time seems to do the trick.
It's ugly, but in the face of the aggressive styling we use to avoid Flashes of Unstyled Content
(FLoUC), it's the logic with which we're left.

In standard mode, the following warning appears on the console when running a Flow:

```
Autofocus processing was blocked because a document already has a focused element.
```

In compatibility mode, the following **error** appears on the console when running a Flow:

```
crawler-inject.js:1106 Uncaught TypeError: Failed to execute 'observe' on 'MutationObserver': parameter 1 is not of type 'Node'.
    at initDomMutationObservers (crawler-inject.js:1106:18)
    at crawler-inject.js:1114:24
    at Array.forEach (<anonymous>)
    at initDomMutationObservers (crawler-inject.js:1114:10)
    at crawler-inject.js:1549:1
initDomMutationObservers @ crawler-inject.js:1106
(anonymous) @ crawler-inject.js:1114
initDomMutationObservers @ crawler-inject.js:1114
(anonymous) @ crawler-inject.js:1549
```

Despite this error, nothing seems to be broken and flows work as anticipated.
2024-03-08 14:15:55 -08:00
45 changed files with 7604 additions and 6538 deletions

View File

@ -75,7 +75,7 @@ RUN --mount=type=secret,id=GEOIPUPDATE_ACCOUNT_ID \
/bin/sh -c "GEOIPUPDATE_LICENSE_KEY_FILE=/run/secrets/GEOIPUPDATE_LICENSE_KEY /usr/bin/entry.sh || echo 'Failed to get GeoIP database, disabling'; exit 0"
# Stage 4: Download uv
FROM ghcr.io/astral-sh/uv:0.7.12 AS uv
FROM ghcr.io/astral-sh/uv:0.7.13 AS uv
# Stage 5: Base python image
FROM ghcr.io/goauthentik/fips-python:3.13.4-slim-bookworm-fips AS python-base

View File

@ -134,7 +134,7 @@ class Command(BaseCommand):
"id": {"type": "string"},
"state": {
"type": "string",
"enum": [s.value for s in BlueprintEntryDesiredState],
"enum": sorted([s.value for s in BlueprintEntryDesiredState]),
"default": "present",
},
"conditions": {"type": "array", "items": {"type": "boolean"}},
@ -205,7 +205,7 @@ class Command(BaseCommand):
"type": "object",
"required": ["permission"],
"properties": {
"permission": {"type": "string", "enum": perms},
"permission": {"type": "string", "enum": sorted(perms)},
"user": {"type": "integer"},
"role": {"type": "string"},
},

View File

@ -47,7 +47,7 @@ class MetaModelRegistry:
models = apps.get_models()
for _, value in self.models.items():
models.append(value)
return models
return sorted(models, key=str)
def get_model(self, app_label: str, model_id: str) -> type[Model]:
"""Get model checks if any virtual models are registered, and falls back

View File

@ -1,11 +1,9 @@
"""Websocket tests"""
from dataclasses import asdict
from unittest.mock import patch
from channels.routing import URLRouter
from channels.testing import WebsocketCommunicator
from django.contrib.contenttypes.models import ContentType
from django.test import TransactionTestCase
from authentik import __version__
@ -16,12 +14,6 @@ from authentik.providers.proxy.models import ProxyProvider
from authentik.root import websocket
def patched__get_ct_cached(app_label, codename):
"""Caches `ContentType` instances like its `QuerySet` does."""
return ContentType.objects.get(app_label=app_label, permission__codename=codename)
@patch("guardian.shortcuts._get_ct_cached", patched__get_ct_cached)
class TestOutpostWS(TransactionTestCase):
"""Websocket tests"""

View File

@ -20,6 +20,9 @@ from authentik.lib.utils.time import timedelta_from_string
from authentik.policies.engine import PolicyEngine
from authentik.policies.views import PolicyAccessView
from authentik.providers.rac.models import ConnectionToken, Endpoint, RACProvider
from authentik.stages.prompt.stage import PLAN_CONTEXT_PROMPT
PLAN_CONNECTION_SETTINGS = "connection_settings"
class RACStartView(PolicyAccessView):
@ -109,10 +112,15 @@ class RACFinalStage(RedirectStage):
return super().dispatch(request, *args, **kwargs)
def get_challenge(self, *args, **kwargs) -> RedirectChallenge:
settings = self.executor.plan.context.get(PLAN_CONNECTION_SETTINGS)
if not settings:
settings = self.executor.plan.context.get(PLAN_CONTEXT_PROMPT, {}).get(
PLAN_CONNECTION_SETTINGS
)
token = ConnectionToken.objects.create(
provider=self.provider,
endpoint=self.endpoint,
settings=self.executor.plan.context.get("connection_settings", {}),
settings=settings or {},
session=self.request.session["authenticatedsession"],
expires=now() + timedelta_from_string(self.provider.connection_expiry),
expiring=True,

View File

@ -3,21 +3,38 @@
import os
from argparse import ArgumentParser
from unittest import TestCase
from unittest.mock import patch
import pytest
from django.conf import settings
from django.contrib.contenttypes.models import ContentType
from django.test.runner import DiscoverRunner
from structlog.stdlib import get_logger
from authentik.lib.config import CONFIG
from authentik.lib.sentry import sentry_init
from authentik.root.signals import post_startup, pre_startup, startup
from tests.e2e.utils import get_docker_tag
# globally set maxDiff to none to show full assert error
TestCase.maxDiff = None
def get_docker_tag() -> str:
"""Get docker-tag based off of CI variables"""
env_pr_branch = "GITHUB_HEAD_REF"
default_branch = "GITHUB_REF"
branch_name = os.environ.get(default_branch, "main")
if os.environ.get(env_pr_branch, "") != "":
branch_name = os.environ[env_pr_branch]
branch_name = branch_name.replace("refs/heads/", "").replace("/", "-")
return f"gh-{branch_name}"
def patched__get_ct_cached(app_label, codename):
"""Caches `ContentType` instances like its `QuerySet` does."""
return ContentType.objects.get(app_label=app_label, permission__codename=codename)
class PytestTestRunner(DiscoverRunner): # pragma: no cover
"""Runs pytest to discover and run tests."""
@ -149,8 +166,9 @@ class PytestTestRunner(DiscoverRunner): # pragma: no cover
return 1
self.logger.info("Running tests", test_files=self.args)
try:
return pytest.main(self.args)
except Exception as e:
self.logger.error("Error running tests", error=str(e), test_files=self.args)
return 1
with patch("guardian.shortcuts._get_ct_cached", patched__get_ct_cached):
try:
return pytest.main(self.args)
except Exception as e:
self.logger.error("Error running tests", error=str(e), test_files=self.args)
return 1

File diff suppressed because it is too large Load Diff

View File

@ -9,7 +9,7 @@
"version": "0.0.0",
"license": "MIT",
"devDependencies": {
"aws-cdk": "^2.1018.0",
"aws-cdk": "^2.1018.1",
"cross-env": "^7.0.3"
},
"engines": {
@ -17,9 +17,9 @@
}
},
"node_modules/aws-cdk": {
"version": "2.1018.0",
"resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1018.0.tgz",
"integrity": "sha512-sppVsNtFJTW4wawS/PBudHCSNHb8xwaZ2WX1mpsfwaPNyTWm0eSUVJsRbRiRBu9O/Us8pgrd4woUjfM1lgD7Kw==",
"version": "2.1018.1",
"resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1018.1.tgz",
"integrity": "sha512-kFPRox5kSm+ktJ451o0ng9rD+60p5Kt1CZIWw8kXnvqbsxN2xv6qbmyWSXw7sGVXVwqrRKVj+71/JeDr+LMAZw==",
"dev": true,
"license": "Apache-2.0",
"bin": {

View File

@ -10,7 +10,7 @@
"node": ">=20"
},
"devDependencies": {
"aws-cdk": "^2.1018.0",
"aws-cdk": "^2.1018.1",
"cross-env": "^7.0.3"
}
}

View File

@ -40,7 +40,7 @@ dependencies = [
"gunicorn==23.0.0",
"jsonpatch==1.33",
"jwcrypto==1.5.6",
"kubernetes==32.0.1",
"kubernetes==33.1.0",
"ldap3==2.9.1",
"lxml==5.4.0",
"msgraph-sdk==1.33.0",
@ -56,13 +56,13 @@ dependencies = [
"pyyaml==6.0.2",
"requests-oauthlib==2.0.0",
"scim2-filter-parser==0.7.0",
"sentry-sdk==2.29.1",
"sentry-sdk==2.30.0",
"service-identity==24.2.0",
"setproctitle==1.3.6",
"structlog==25.4.0",
"swagger-spec-validator==3.0.4",
"tenant-schemas-celery==3.0.0",
"twilio==9.6.2",
"twilio==9.6.3",
"ua-parser==1.0.1",
"unidecode==1.4.0",
"urllib3<3",

View File

@ -2,7 +2,6 @@
from dataclasses import asdict
from time import sleep
from unittest.mock import patch
from guardian.shortcuts import assign_perm
from ldap3 import ALL, ALL_ATTRIBUTES, ALL_OPERATIONAL_ATTRIBUTES, SUBTREE, Connection, Server
@ -16,12 +15,10 @@ from authentik.flows.models import Flow
from authentik.lib.generators import generate_id
from authentik.outposts.apps import MANAGED_OUTPOST
from authentik.outposts.models import Outpost, OutpostConfig, OutpostType
from authentik.outposts.tests.test_ws import patched__get_ct_cached
from authentik.providers.ldap.models import APIAccessMode, LDAPProvider
from tests.e2e.utils import SeleniumTestCase, retry
@patch("guardian.shortcuts._get_ct_cached", patched__get_ct_cached)
class TestProviderLDAP(SeleniumTestCase):
"""LDAP and Outpost e2e tests"""

View File

@ -6,7 +6,6 @@ from json import loads
from sys import platform
from time import sleep
from unittest.case import skip, skipUnless
from unittest.mock import patch
from channels.testing import ChannelsLiveServerTestCase
from jwt import decode
@ -18,12 +17,10 @@ from authentik.flows.models import Flow
from authentik.lib.generators import generate_id
from authentik.outposts.models import DockerServiceConnection, Outpost, OutpostConfig, OutpostType
from authentik.outposts.tasks import outpost_connection_discovery
from authentik.outposts.tests.test_ws import patched__get_ct_cached
from authentik.providers.proxy.models import ProxyProvider
from tests.e2e.utils import SeleniumTestCase, retry
@patch("guardian.shortcuts._get_ct_cached", patched__get_ct_cached)
class TestProviderProxy(SeleniumTestCase):
"""Proxy and Outpost e2e tests"""

View File

@ -4,7 +4,6 @@ from json import loads
from pathlib import Path
from time import sleep
from unittest import skip
from unittest.mock import patch
from selenium.webdriver.common.by import By
@ -13,12 +12,10 @@ from authentik.core.models import Application
from authentik.flows.models import Flow
from authentik.lib.generators import generate_id
from authentik.outposts.models import Outpost, OutpostType
from authentik.outposts.tests.test_ws import patched__get_ct_cached
from authentik.providers.proxy.models import ProxyMode, ProxyProvider
from tests.e2e.utils import SeleniumTestCase, retry
@patch("guardian.shortcuts._get_ct_cached", patched__get_ct_cached)
class TestProviderProxyForward(SeleniumTestCase):
"""Proxy and Outpost e2e tests"""

View File

@ -2,7 +2,6 @@
from dataclasses import asdict
from time import sleep
from unittest.mock import patch
from pyrad.client import Client
from pyrad.dictionary import Dictionary
@ -13,12 +12,10 @@ from authentik.core.models import Application, User
from authentik.flows.models import Flow
from authentik.lib.generators import generate_id, generate_key
from authentik.outposts.models import Outpost, OutpostConfig, OutpostType
from authentik.outposts.tests.test_ws import patched__get_ct_cached
from authentik.providers.radius.models import RadiusProvider
from tests.e2e.utils import SeleniumTestCase, retry
@patch("guardian.shortcuts._get_ct_cached", patched__get_ct_cached)
class TestProviderRadius(SeleniumTestCase):
"""Radius Outpost e2e tests"""

View File

@ -1,7 +1,6 @@
"""authentik e2e testing utilities"""
import json
import os
import socket
from collections.abc import Callable
from functools import lru_cache, wraps
@ -37,22 +36,12 @@ from authentik.core.api.users import UserSerializer
from authentik.core.models import User
from authentik.core.tests.utils import create_test_admin_user
from authentik.lib.generators import generate_id
from authentik.root.test_runner import get_docker_tag
IS_CI = "CI" in environ
RETRIES = int(environ.get("RETRIES", "3")) if IS_CI else 1
def get_docker_tag() -> str:
"""Get docker-tag based off of CI variables"""
env_pr_branch = "GITHUB_HEAD_REF"
default_branch = "GITHUB_REF"
branch_name = os.environ.get(default_branch, "main")
if os.environ.get(env_pr_branch, "") != "":
branch_name = os.environ[env_pr_branch]
branch_name = branch_name.replace("refs/heads/", "").replace("/", "-")
return f"gh-{branch_name}"
def get_local_ip() -> str:
"""Get the local machine's IP"""
hostname = socket.gethostname()

24
uv.lock generated
View File

@ -301,7 +301,7 @@ requires-dist = [
{ name = "gunicorn", specifier = "==23.0.0" },
{ name = "jsonpatch", specifier = "==1.33" },
{ name = "jwcrypto", specifier = "==1.5.6" },
{ name = "kubernetes", specifier = "==32.0.1" },
{ name = "kubernetes", specifier = "==33.1.0" },
{ name = "ldap3", specifier = "==2.9.1" },
{ name = "lxml", specifier = "==5.4.0" },
{ name = "msgraph-sdk", specifier = "==1.33.0" },
@ -317,13 +317,13 @@ requires-dist = [
{ name = "pyyaml", specifier = "==6.0.2" },
{ name = "requests-oauthlib", specifier = "==2.0.0" },
{ name = "scim2-filter-parser", specifier = "==0.7.0" },
{ name = "sentry-sdk", specifier = "==2.29.1" },
{ name = "sentry-sdk", specifier = "==2.30.0" },
{ name = "service-identity", specifier = "==24.2.0" },
{ name = "setproctitle", specifier = "==1.3.6" },
{ name = "structlog", specifier = "==25.4.0" },
{ name = "swagger-spec-validator", specifier = "==3.0.4" },
{ name = "tenant-schemas-celery", specifier = "==3.0.0" },
{ name = "twilio", specifier = "==9.6.2" },
{ name = "twilio", specifier = "==9.6.3" },
{ name = "ua-parser", specifier = "==1.0.1" },
{ name = "unidecode", specifier = "==1.4.0" },
{ name = "urllib3", specifier = "<3" },
@ -1772,7 +1772,7 @@ wheels = [
[[package]]
name = "kubernetes"
version = "32.0.1"
version = "33.1.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "certifi" },
@ -1787,9 +1787,9 @@ dependencies = [
{ name = "urllib3" },
{ name = "websocket-client" },
]
sdist = { url = "https://files.pythonhosted.org/packages/b7/e8/0598f0e8b4af37cd9b10d8b87386cf3173cb8045d834ab5f6ec347a758b3/kubernetes-32.0.1.tar.gz", hash = "sha256:42f43d49abd437ada79a79a16bd48a604d3471a117a8347e87db693f2ba0ba28", size = 946691, upload-time = "2025-02-18T21:06:34.148Z" }
sdist = { url = "https://files.pythonhosted.org/packages/ae/52/19ebe8004c243fdfa78268a96727c71e08f00ff6fe69a301d0b7fcbce3c2/kubernetes-33.1.0.tar.gz", hash = "sha256:f64d829843a54c251061a8e7a14523b521f2dc5c896cf6d65ccf348648a88993", size = 1036779, upload-time = "2025-06-09T21:57:58.521Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/08/10/9f8af3e6f569685ce3af7faab51c8dd9d93b9c38eba339ca31c746119447/kubernetes-32.0.1-py2.py3-none-any.whl", hash = "sha256:35282ab8493b938b08ab5526c7ce66588232df00ef5e1dbe88a419107dc10998", size = 1988070, upload-time = "2025-02-18T21:06:31.391Z" },
{ url = "https://files.pythonhosted.org/packages/89/43/d9bebfc3db7dea6ec80df5cb2aad8d274dd18ec2edd6c4f21f32c237cbbb/kubernetes-33.1.0-py2.py3-none-any.whl", hash = "sha256:544de42b24b64287f7e0aa9513c93cb503f7f40eea39b20f66810011a86eabc5", size = 1941335, upload-time = "2025-06-09T21:57:56.327Z" },
]
[[package]]
@ -2931,15 +2931,15 @@ wheels = [
[[package]]
name = "sentry-sdk"
version = "2.29.1"
version = "2.30.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "certifi" },
{ name = "urllib3" },
]
sdist = { url = "https://files.pythonhosted.org/packages/22/67/d552a5f8e5a6a56b2feea6529e2d8ccd54349084c84176d5a1f7295044bc/sentry_sdk-2.29.1.tar.gz", hash = "sha256:8d4a0206b95fa5fe85e5e7517ed662e3888374bdc342c00e435e10e6d831aa6d", size = 325518, upload-time = "2025-05-19T14:27:38.512Z" }
sdist = { url = "https://files.pythonhosted.org/packages/04/4c/af31e0201b48469786ddeb1bf6fd3dfa3a291cc613a0fe6a60163a7535f9/sentry_sdk-2.30.0.tar.gz", hash = "sha256:436369b02afef7430efb10300a344fb61a11fe6db41c2b11f41ee037d2dd7f45", size = 326767, upload-time = "2025-06-12T10:34:34.733Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/f0/e5/da07b0bd832cefd52d16f2b9bbbe31624d57552602c06631686b93ccb1bd/sentry_sdk-2.29.1-py2.py3-none-any.whl", hash = "sha256:90862fe0616ded4572da6c9dadb363121a1ae49a49e21c418f0634e9d10b4c19", size = 341553, upload-time = "2025-05-19T14:27:36.882Z" },
{ url = "https://files.pythonhosted.org/packages/5a/99/31ac6faaae33ea698086692638f58d14f121162a8db0039e68e94135e7f1/sentry_sdk-2.30.0-py2.py3-none-any.whl", hash = "sha256:59391db1550662f746ea09b483806a631c3ae38d6340804a1a4c0605044f6877", size = 343149, upload-time = "2025-06-12T10:34:32.896Z" },
]
[[package]]
@ -3151,7 +3151,7 @@ wheels = [
[[package]]
name = "twilio"
version = "9.6.2"
version = "9.6.3"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "aiohttp" },
@ -3159,9 +3159,9 @@ dependencies = [
{ name = "pyjwt" },
{ name = "requests" },
]
sdist = { url = "https://files.pythonhosted.org/packages/fa/c9/441a07f6552f2b504812501d56c41bd85b02afeef6c23ab8baf41ed6c70e/twilio-9.6.2.tar.gz", hash = "sha256:5da13bb497e39ece34cb9f2b3bc911f3288928612748f7688b3bda262c2767a1", size = 1041300, upload-time = "2025-05-29T12:25:04.59Z" }
sdist = { url = "https://files.pythonhosted.org/packages/fb/af/1b401bc4cfd3eb41c7e2a98d0040d2bcfd2ad3217f3163401121179b3fb3/twilio-9.6.3.tar.gz", hash = "sha256:16a8c2ab9550343c25c8a195f31db9e230d9b341eca31ebdd301109910fd9730", size = 1041494, upload-time = "2025-06-12T10:40:55.63Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/67/91/382e83e5d205a7ae4325b66d40cd2fa6ce85526f2ed8fc553265e19abbe4/twilio-9.6.2-py2.py3-none-any.whl", hash = "sha256:8d4af6f42850734a921857df42940f7fed84e3e4a508d0d6bef5b9fb7dc08357", size = 1909253, upload-time = "2025-05-29T12:25:02.521Z" },
{ url = "https://files.pythonhosted.org/packages/c9/35/d61a3581eb223e5e1fc0add1c397d7bb60014b22790e8f89aa5eb4e41e04/twilio-9.6.3-py2.py3-none-any.whl", hash = "sha256:a9b2cf11b0718394f12c43585ca25b9094f12b82ff975f1561fcec7f0f6f49b2", size = 1909549, upload-time = "2025-06-12T10:40:53.67Z" },
]
[[package]]

201
web/package-lock.json generated
View File

@ -31,8 +31,8 @@
"@open-wc/lit-helpers": "^0.7.0",
"@patternfly/elements": "^4.1.0",
"@patternfly/patternfly": "^4.224.2",
"@sentry/browser": "^9.28.0",
"@spotlightjs/spotlight": "^2.13.3",
"@sentry/browser": "^9.28.1",
"@spotlightjs/spotlight": "^3.0.0",
"@webcomponents/webcomponentsjs": "^2.8.0",
"base64-js": "^1.5.1",
"change-case": "^5.4.4",
@ -51,6 +51,7 @@
"lit": "^3.2.0",
"md-front-matter": "^1.0.4",
"mermaid": "^11.6.0",
"ninja-keys": "^1.2.2",
"rapidoc": "^9.3.8",
"react": "^19.1.0",
"react-dom": "^19.1.0",
@ -2587,6 +2588,57 @@
"@lit/reactive-element": "^1.0.0 || ^2.0.0"
}
},
"node_modules/@material/mwc-icon": {
"version": "0.25.3",
"resolved": "https://registry.npmjs.org/@material/mwc-icon/-/mwc-icon-0.25.3.tgz",
"integrity": "sha512-36076AWZIRSr8qYOLjuDDkxej/HA0XAosrj7TS1ZeLlUBnLUtbDtvc1S7KSa0hqez7ouzOqGaWK24yoNnTa2OA==",
"deprecated": "MWC beta is longer supported. Please upgrade to @material/web",
"license": "Apache-2.0",
"dependencies": {
"lit": "^2.0.0",
"tslib": "^2.0.1"
}
},
"node_modules/@material/mwc-icon/node_modules/@lit/reactive-element": {
"version": "1.6.3",
"resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.6.3.tgz",
"integrity": "sha512-QuTgnG52Poic7uM1AN5yJ09QMe0O28e10XzSvWDz02TJiiKee4stsiownEIadWm8nYzyDAyT+gKzUoZmiWQtsQ==",
"license": "BSD-3-Clause",
"dependencies": {
"@lit-labs/ssr-dom-shim": "^1.0.0"
}
},
"node_modules/@material/mwc-icon/node_modules/lit": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/lit/-/lit-2.8.0.tgz",
"integrity": "sha512-4Sc3OFX9QHOJaHbmTMk28SYgVxLN3ePDjg7hofEft2zWlehFL3LiAuapWc4U/kYwMYJSh2hTCPZ6/LIC7ii0MA==",
"license": "BSD-3-Clause",
"dependencies": {
"@lit/reactive-element": "^1.6.0",
"lit-element": "^3.3.0",
"lit-html": "^2.8.0"
}
},
"node_modules/@material/mwc-icon/node_modules/lit-element": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/lit-element/-/lit-element-3.3.3.tgz",
"integrity": "sha512-XbeRxmTHubXENkV4h8RIPyr8lXc+Ff28rkcQzw3G6up2xg5E8Zu1IgOWIwBLEQsu3cOVFqdYwiVi0hv0SlpqUA==",
"license": "BSD-3-Clause",
"dependencies": {
"@lit-labs/ssr-dom-shim": "^1.1.0",
"@lit/reactive-element": "^1.3.0",
"lit-html": "^2.8.0"
}
},
"node_modules/@material/mwc-icon/node_modules/lit-html": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/lit-html/-/lit-html-2.8.0.tgz",
"integrity": "sha512-o9t+MQM3P4y7M7yNzqAyjp7z+mQGa4NS4CxiyLqFPyFWyc4O+nodLrkrxSaCTrla6M5YOLaT3RpbbqjszB5g3Q==",
"license": "BSD-3-Clause",
"dependencies": {
"@types/trusted-types": "^2.0.2"
}
},
"node_modules/@mdx-js/mdx": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.1.0.tgz",
@ -4478,75 +4530,75 @@
"dev": true
},
"node_modules/@sentry-internal/browser-utils": {
"version": "9.28.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-9.28.0.tgz",
"integrity": "sha512-SqntPnIXudP3FoKj4mQ1BVPC1RNzo4CGtAxJnLpbIUpdT/khJVM6Q59zrGl2MgZ7URZCI986L5jXihQeferf6g==",
"version": "9.28.1",
"resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-9.28.1.tgz",
"integrity": "sha512-P/FEZkT7UqTw9P/2n/Y4Aa1OtGP6dnCvyqzPPkjiRdVa7Ep7S5ElBJloGv7077TLLBtAfCsEUVRlM1F6/jQoaA==",
"license": "MIT",
"dependencies": {
"@sentry/core": "9.28.0"
"@sentry/core": "9.28.1"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@sentry-internal/feedback": {
"version": "9.28.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-9.28.0.tgz",
"integrity": "sha512-z2jShmVENsesmDnShEOv841Saw0zXe1tX6GHNgkK9f6NrUMbL970JvGKByBFTffhQH6uQ0WeNPnXJ5L/YKnfDg==",
"version": "9.28.1",
"resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-9.28.1.tgz",
"integrity": "sha512-HOk/c26D3nlClO/xEefev8fIJzRA621PFQvNFPu/y0Z5HujEqSmIsrff0cXszPPYD95h4Mwk63E0ZYdspdeXcw==",
"license": "MIT",
"dependencies": {
"@sentry/core": "9.28.0"
"@sentry/core": "9.28.1"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@sentry-internal/replay": {
"version": "9.28.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-9.28.0.tgz",
"integrity": "sha512-BVGVBlmcpJdT55d/vywjfK1u6zMC5ycjJBxU1wUCNgCU3cSKRDBnvmYgk/+Ay23bFryT28Q4hM1p5qBBAOfxjQ==",
"version": "9.28.1",
"resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-9.28.1.tgz",
"integrity": "sha512-Tv9pkfAX+1bmhxF42TL0c4uTiK2+rp5LMYEPdz6JBfpfvG/Z1unPGsuB7fQmHYKyfHBQJmi92DZV+smljm7w/g==",
"license": "MIT",
"dependencies": {
"@sentry-internal/browser-utils": "9.28.0",
"@sentry/core": "9.28.0"
"@sentry-internal/browser-utils": "9.28.1",
"@sentry/core": "9.28.1"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@sentry-internal/replay-canvas": {
"version": "9.28.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-9.28.0.tgz",
"integrity": "sha512-Bv4mbtUrRV3p6PpFQPseLv3+Uaen+3AlfX02Z6QHY1sMa4lpt+U8OHfRGLprnzb6Rarw6fK2LNVL5rnV9LNMwA==",
"version": "9.28.1",
"resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-9.28.1.tgz",
"integrity": "sha512-RtkogfcIpXLFCyV8CTnXmVTH2QauT/KwmUAXBbeOz3rRWsM19yjN1moHrsjxn7OdjTv+D4qWSCA8Ka1aKSpr7g==",
"license": "MIT",
"dependencies": {
"@sentry-internal/replay": "9.28.0",
"@sentry/core": "9.28.0"
"@sentry-internal/replay": "9.28.1",
"@sentry/core": "9.28.1"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@sentry/browser": {
"version": "9.28.0",
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-9.28.0.tgz",
"integrity": "sha512-ttqiv3D9sIB43nZnJTTln1nXw1p4C5BDSh+sHmGUOiqdCH6ND3HByDITYMYIOz1lACSISTT4V+MEpqx0V25Tlw==",
"version": "9.28.1",
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-9.28.1.tgz",
"integrity": "sha512-XAS46iQSq8lXTnv9udQP025JTf3PwSVRE9ePJVQhx25QBWxedqGhEOv5qqX9b1Ijf8KiZYXXhBWMQxBBXVzUaw==",
"license": "MIT",
"dependencies": {
"@sentry-internal/browser-utils": "9.28.0",
"@sentry-internal/feedback": "9.28.0",
"@sentry-internal/replay": "9.28.0",
"@sentry-internal/replay-canvas": "9.28.0",
"@sentry/core": "9.28.0"
"@sentry-internal/browser-utils": "9.28.1",
"@sentry-internal/feedback": "9.28.1",
"@sentry-internal/replay": "9.28.1",
"@sentry-internal/replay-canvas": "9.28.1",
"@sentry/core": "9.28.1"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@sentry/core": {
"version": "9.28.0",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-9.28.0.tgz",
"integrity": "sha512-vzD9xhg9S864jxfCpq77feCE4y7iP2cZYsNMoTupl1vTUlmXlhp7XgF832fEMjEZq4vrPhaqCNsde7Sc3PAbaQ==",
"version": "9.28.1",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-9.28.1.tgz",
"integrity": "sha512-6q59r/71MeE+4StkvwdKAAyhBBNpWcii0HeiWBZ3l1gaFYQlb6bChjZJRZmxSzF5dnvkdF4duQbAC3JmjeIbPA==",
"license": "MIT",
"engines": {
"node": ">=18"
@ -4717,15 +4769,15 @@
}
},
"node_modules/@spotlightjs/overlay": {
"version": "2.15.1",
"resolved": "https://registry.npmjs.org/@spotlightjs/overlay/-/overlay-2.15.1.tgz",
"integrity": "sha512-5TpHWFRiTm8rrNINOQs9iFsqVnguFGHU1cK/bmhrysNzts4tYQT9d+kWvl++GlItKezIPbu5xPD9VoapO30cyw==",
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@spotlightjs/overlay/-/overlay-3.0.0.tgz",
"integrity": "sha512-0b03WtsykqpcOKmjDRnRZf0GGfaEB6ZHGctLZZxFK4NHTDBNJ6BaQZjunr4XU35kKR5BT2OFp5E/DPKluih0Hg==",
"license": "Apache-2.0"
},
"node_modules/@spotlightjs/sidecar": {
"version": "1.11.3",
"resolved": "https://registry.npmjs.org/@spotlightjs/sidecar/-/sidecar-1.11.3.tgz",
"integrity": "sha512-2FNZjnvJH71pAsYlJA/LIaEZ0jdtjqrlD58F/xJ5ZhI7z6US5zIqE7DMrqaK/tvObFam71CyCncKHRG6M0l6Cg==",
"version": "1.11.4",
"resolved": "https://registry.npmjs.org/@spotlightjs/sidecar/-/sidecar-1.11.4.tgz",
"integrity": "sha512-8uDJNhvt6uVNvIoBltjRBqb0a//SxkKoyPACtNjq9k9qMYSfFhE0RVtgqnJNBineXeJfxzK5uvzeG/X7pEhYeQ==",
"license": "Apache-2.0",
"dependencies": {
"@jridgewell/trace-mapping": "^0.3.25",
@ -4741,21 +4793,21 @@
}
},
"node_modules/@spotlightjs/spotlight": {
"version": "2.13.3",
"resolved": "https://registry.npmjs.org/@spotlightjs/spotlight/-/spotlight-2.13.3.tgz",
"integrity": "sha512-wDnXJaSVexPC/+blgXXx2AYCk7S+5lT4TCJmu0HZAVtYd2sDgNub/wAOitsKYxvpRtIQnPe55IlvL4r1X7goSg==",
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@spotlightjs/spotlight/-/spotlight-3.0.0.tgz",
"integrity": "sha512-dkMineYpONLUmkHh7gvBhjf34ES8a08KDQXNem9/0JzAMy/bXSDlC95sqkX9wDfKWjq2rJKYjJulNtCuGHDaeA==",
"license": "Apache-2.0",
"dependencies": {
"@sentry/node": "^8.49.0",
"@spotlightjs/overlay": "2.15.1",
"@spotlightjs/sidecar": "1.11.3",
"@spotlightjs/overlay": "3.0.0",
"@spotlightjs/sidecar": "1.11.4",
"import-meta-resolve": "^4.1.0"
},
"bin": {
"spotlight": "bin/run.js"
},
"engines": {
"node": ">=18"
"node": ">=20"
}
},
"node_modules/@stencil/core": {
@ -16940,6 +16992,12 @@
"integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
"dev": true
},
"node_modules/hotkeys-js": {
"version": "3.8.7",
"resolved": "https://registry.npmjs.org/hotkeys-js/-/hotkeys-js-3.8.7.tgz",
"integrity": "sha512-ckAx3EkUr5XjDwjEHDorHxRO2Kb7z6Z2Sxul4MbBkN8Nho7XDslQsgMJT+CiJ5Z4TgRxxvKHEpuLE3imzqy4Lg==",
"license": "MIT"
},
"node_modules/html-escaper": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
@ -17143,9 +17201,9 @@
}
},
"node_modules/import-in-the-middle": {
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.13.2.tgz",
"integrity": "sha512-Yjp9X7s2eHSXvZYQ0aye6UvwYPrVB5C2k47fuXjFKnYinAByaDZjh4t9MT2wEga9775n6WaIqyHnQhBxYtX2mg==",
"version": "1.14.0",
"resolved": "https://registry.npmjs.org/import-in-the-middle/-/import-in-the-middle-1.14.0.tgz",
"integrity": "sha512-g5zLT0HaztRJWysayWYiUq/7E5H825QIiecMD2pI5QO7Wzr847l6GDvPvmZaDIdrDtS2w7qRczywxiK6SL5vRw==",
"license": "Apache-2.0",
"dependencies": {
"acorn": "^8.14.0",
@ -21632,6 +21690,57 @@
"integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
"dev": true
},
"node_modules/ninja-keys": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/ninja-keys/-/ninja-keys-1.2.2.tgz",
"integrity": "sha512-ylo8jzKowi3XBHkgHRjBJaKQkl32WRLr7kRiA0ajiku11vHRDJ2xANtTScR5C7XlDwKEOYvUPesCKacUeeLAYw==",
"license": "MIT",
"dependencies": {
"@material/mwc-icon": "0.25.3",
"hotkeys-js": "3.8.7",
"lit": "2.2.6"
}
},
"node_modules/ninja-keys/node_modules/@lit/reactive-element": {
"version": "1.6.3",
"resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.6.3.tgz",
"integrity": "sha512-QuTgnG52Poic7uM1AN5yJ09QMe0O28e10XzSvWDz02TJiiKee4stsiownEIadWm8nYzyDAyT+gKzUoZmiWQtsQ==",
"license": "BSD-3-Clause",
"dependencies": {
"@lit-labs/ssr-dom-shim": "^1.0.0"
}
},
"node_modules/ninja-keys/node_modules/lit": {
"version": "2.2.6",
"resolved": "https://registry.npmjs.org/lit/-/lit-2.2.6.tgz",
"integrity": "sha512-K2vkeGABfSJSfkhqHy86ujchJs3NR9nW1bEEiV+bXDkbiQ60Tv5GUausYN2mXigZn8lC1qXuc46ArQRKYmumZw==",
"license": "BSD-3-Clause",
"dependencies": {
"@lit/reactive-element": "^1.3.0",
"lit-element": "^3.2.0",
"lit-html": "^2.2.0"
}
},
"node_modules/ninja-keys/node_modules/lit-element": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/lit-element/-/lit-element-3.3.3.tgz",
"integrity": "sha512-XbeRxmTHubXENkV4h8RIPyr8lXc+Ff28rkcQzw3G6up2xg5E8Zu1IgOWIwBLEQsu3cOVFqdYwiVi0hv0SlpqUA==",
"license": "BSD-3-Clause",
"dependencies": {
"@lit-labs/ssr-dom-shim": "^1.1.0",
"@lit/reactive-element": "^1.3.0",
"lit-html": "^2.8.0"
}
},
"node_modules/ninja-keys/node_modules/lit-html": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/lit-html/-/lit-html-2.8.0.tgz",
"integrity": "sha512-o9t+MQM3P4y7M7yNzqAyjp7z+mQGa4NS4CxiyLqFPyFWyc4O+nodLrkrxSaCTrla6M5YOLaT3RpbbqjszB5g3Q==",
"license": "BSD-3-Clause",
"dependencies": {
"@types/trusted-types": "^2.0.2"
}
},
"node_modules/node-abort-controller": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz",

View File

@ -102,8 +102,8 @@
"@open-wc/lit-helpers": "^0.7.0",
"@patternfly/elements": "^4.1.0",
"@patternfly/patternfly": "^4.224.2",
"@sentry/browser": "^9.28.0",
"@spotlightjs/spotlight": "^2.13.3",
"@sentry/browser": "^9.28.1",
"@spotlightjs/spotlight": "^3.0.0",
"@webcomponents/webcomponentsjs": "^2.8.0",
"base64-js": "^1.5.1",
"change-case": "^5.4.4",
@ -122,6 +122,7 @@
"lit": "^3.2.0",
"md-front-matter": "^1.0.4",
"mermaid": "^11.6.0",
"ninja-keys": "^1.2.2",
"rapidoc": "^9.3.8",
"react": "^19.1.0",
"react-dom": "^19.1.0",

View File

@ -0,0 +1,172 @@
import { navigate } from "@goauthentik/elements/router/RouterOutlet";
import { INinjaAction } from "ninja-keys/dist/interfaces/ininja-action.js";
import { msg } from "@lit/localize";
export const adminCommands: INinjaAction[] = [
{
id: msg("Overview"),
title: msg("Dashboard"),
handler: () => navigate("/administration/overview"),
section: msg("Dashboards"),
},
{
handler: () => navigate("/administration/dashboard/users"),
id: msg("User Statistics"),
title: msg("User Statistics"),
icon: '<i class="pf-icon pf-icon-user"></i>',
section: msg("Dashboards"),
},
{
handler: () => navigate("/administration/system-tasks"),
id: msg("System Tasks"),
title: msg("System Tasks"),
section: msg("Dashboards"),
},
{
handler: () => navigate("/core/applications"),
id: msg("Applications"),
title: msg("Applications"),
section: msg("Applications"),
},
{
handler: () => navigate("/core/providers"),
id: msg("Providers"),
title: msg("Providers"),
section: msg("Applications"),
},
{
handler: () => navigate("/outpost/outposts"),
id: msg("Outposts"),
title: msg("Outposts"),
section: msg("Applications"),
},
{
handler: () => navigate("/events/log"),
id: msg("Logs"),
title: msg("Logs"),
section: msg("Events"),
},
{
handler: () => navigate("/events/rules"),
id: msg("Notification Rules"),
title: msg("Notification Rules"),
section: msg("Events"),
},
{
handler: () => navigate("/events/transports"),
id: msg("Notification Transports"),
title: msg("Notification Transports"),
section: msg("Events"),
},
{
handler: () => navigate("/policy/policies"),
id: msg("Policies"),
title: msg("Policies"),
section: msg("Customization"),
},
{
handler: () => navigate("/core/property-mappings"),
id: msg("Property Mappings"),
title: msg("Property Mappings"),
section: msg("Customization"),
},
{
handler: () => navigate("/blueprints/instances"),
id: msg("Blueprints"),
title: msg("Blueprints"),
section: msg("Customization"),
},
{
handler: () => navigate("/policy/reputation"),
id: msg("Reputation scores"),
title: msg("Reputation scores"),
section: msg("Customization"),
},
{
handler: () => navigate("/flow/flows"),
id: msg("Flows"),
title: msg("Flows"),
section: msg("Flows"),
},
{
handler: () => navigate("/flow/stages"),
id: msg("Stages"),
title: msg("Stages"),
section: msg("Flows"),
},
{
handler: () => navigate("/flow/stages/prompts"),
id: msg("Prompts"),
title: msg("Prompts"),
section: msg("Flows"),
},
{
handler: () => navigate("/identity/users"),
id: msg("Users"),
title: msg("Users"),
section: msg("Directory"),
},
{
handler: () => navigate("/identity/groups"),
id: msg("Groups"),
title: msg("Groups"),
section: msg("Directory"),
},
{
handler: () => navigate("/identity/roles"),
id: msg("Roles"),
title: msg("Roles"),
section: msg("Directory"),
},
{
handler: () => navigate("/core/sources"),
id: msg("Federation and Social login"),
title: msg("Federation and Social login"),
section: msg("Directory"),
},
{
handler: () => navigate("/core/tokens"),
id: msg("Tokens and App passwords"),
title: msg("Tokens and App passwords"),
section: msg("Directory"),
},
{
handler: () => navigate("/flow/stages/invitations"),
id: msg("Invitations"),
title: msg("Invitations"),
section: msg("Directory"),
},
{
handler: () => navigate("/core/brands"),
id: msg("Brands"),
title: msg("Brands"),
section: msg("System"),
},
{
handler: () => navigate("/crypto/certificates"),
id: msg("Certificates"),
title: msg("Certificates"),
section: msg("System"),
},
{
handler: () => navigate("/outpost/integrations"),
id: msg("Outpost Integrations"),
title: msg("Outpost Integrations"),
section: msg("System"),
},
{
handler: () => navigate("/admin/settings"),
id: msg("Settings"),
title: msg("Settings"),
section: msg("System"),
},
{
handler: () => window.location.assign("/if/user/"),
id: msg("User interface"),
title: msg("Go to my User page"),
},
];

View File

@ -1,5 +1,6 @@
import "#admin/AdminInterface/AboutModal";
import type { AboutModal } from "#admin/AdminInterface/AboutModal";
import { adminCommands } from "#admin/AdminInterface/AdminCommands";
import { ROUTES } from "#admin/Routes";
import { EVENT_API_DRAWER_TOGGLE, EVENT_NOTIFICATION_DRAWER_TOGGLE } from "#common/constants";
import { configureSentry } from "#common/sentry/index";
@ -21,6 +22,7 @@ import { getURLParam, updateURLParams } from "#elements/router/RouteMatch";
import "#elements/router/RouterOutlet";
import "#elements/sidebar/Sidebar";
import "#elements/sidebar/SidebarItem";
import "ninja-keys";
import { CSSResult, TemplateResult, css, html, nothing } from "lit";
import { customElement, eventOptions, property, query } from "lit/decorators.js";
@ -119,6 +121,10 @@ export class AdminInterface extends WithCapabilitiesConfig(AuthenticatedInterfac
.pf-c-drawer__panel {
z-index: var(--pf-global--ZIndex--xl);
}
ninja-keys {
--ninja-z-index: 99999;
--ninja-accent-color: var(--ak-accent);
}
`,
];
@ -190,6 +196,11 @@ export class AdminInterface extends WithCapabilitiesConfig(AuthenticatedInterfac
};
return html` <ak-locale-context>
<ninja-keys
.data=${adminCommands}
noAutoLoadMdicons
class="${this.activeTheme === UiThemeEnum.Dark ? "dark" : ""}"
></ninja-keys>
<div class="pf-c-page">
<ak-page-navbar ?open=${this.sidebarOpen} @sidebar-toggle=${this.sidebarListener}>
<ak-version-banner></ak-version-banner>

View File

@ -1,5 +1,5 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import "@goauthentik/components/ak-private-textarea-input.js";
import "@goauthentik/components/ak-secret-textarea-input.js";
import "@goauthentik/elements/CodeMirror";
import "@goauthentik/elements/forms/HorizontalFormElement";
import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
@ -46,7 +46,7 @@ export class CertificateKeyPairForm extends ModelForm<CertificateKeyPair, string
required
/>
</ak-form-element-horizontal>
<ak-private-textarea-input
<ak-secret-textarea-input
label=${msg("Certificate")}
name="certificateData"
input-hint="code"
@ -54,8 +54,8 @@ export class CertificateKeyPairForm extends ModelForm<CertificateKeyPair, string
required
?revealed=${this.instance === undefined}
help=${msg("PEM-encoded Certificate data.")}
></ak-private-textarea-input>
<ak-private-textarea-input
></ak-secret-textarea-input>
<ak-secret-textarea-input
label=${msg("Private Key")}
name="keyData"
input-hint="code"
@ -63,7 +63,7 @@ export class CertificateKeyPairForm extends ModelForm<CertificateKeyPair, string
help=${msg(
"Optional Private Key. If this is set, you can use this keypair for encryption.",
)}
></ak-private-textarea-input>`;
></ak-secret-textarea-input>`;
}
}

View File

@ -1,6 +1,6 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { EVENT_REFRESH_ENTERPRISE } from "@goauthentik/common/constants";
import "@goauthentik/components/ak-private-textarea-input.js";
import "@goauthentik/components/ak-secret-textarea-input.js";
import "@goauthentik/elements/CodeMirror";
import "@goauthentik/elements/forms/HorizontalFormElement";
import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
@ -62,13 +62,13 @@ export class EnterpriseLicenseForm extends ModelForm<License, string> {
value="${ifDefined(this.installID)}"
/>
</ak-form-element-horizontal>
<ak-private-textarea-input
<ak-secret-textarea-input
name="key"
?revealed=${this.instance === undefined}
label=${msg("License key")}
input-hint="code"
>
</ak-private-textarea-input>`;
</ak-secret-textarea-input>`;
}
}

View File

@ -7,8 +7,8 @@ import {
UserMatchingModeToLabel,
} from "@goauthentik/admin/sources/oauth/utils";
import { DEFAULT_CONFIG, config } from "@goauthentik/common/api/config";
import "@goauthentik/components/ak-private-text-input.js";
import "@goauthentik/components/ak-private-textarea-input.js";
import "@goauthentik/components/ak-secret-text-input.js";
import "@goauthentik/components/ak-secret-textarea-input.js";
import "@goauthentik/components/ak-switch-input";
import "@goauthentik/components/ak-text-input";
import "@goauthentik/components/ak-textarea-input";
@ -248,22 +248,22 @@ export class KerberosSourceForm extends WithCapabilitiesConfig(BaseSourceForm<Ke
value=${ifDefined(this.instance?.syncPrincipal)}
help=${msg("Principal used to authenticate to the KDC for syncing.")}
></ak-text-input>
<ak-private-text-input
<ak-secret-text-input
name="syncPassword"
label=${msg("Sync password")}
?revealed=${this.instance === undefined}
help=${msg(
"Password used to authenticate to the KDC for syncing. Optional if Sync keytab or Sync credentials cache is provided.",
)}
></ak-private-text-input>
<ak-private-textarea-input
></ak-secret-text-input>
<ak-secret-textarea-input
name="syncKeytab"
label=${msg("Sync keytab")}
?revealed=${this.instance === undefined}
help=${msg(
"Keytab used to authenticate to the KDC for syncing. Optional if Sync password or Sync credentials cache is provided. Must be base64 encoded or in the form TYPE:residual.",
)}
></ak-private-textarea-input>
></ak-secret-textarea-input>
<ak-text-input
name="syncCcache"
label=${msg("Sync credentials cache")}
@ -285,14 +285,14 @@ export class KerberosSourceForm extends WithCapabilitiesConfig(BaseSourceForm<Ke
"Force the use of a specific server name for SPNEGO. Must be in the form HTTP@domain",
)}
></ak-text-input>
<ak-private-textarea-input
<ak-secret-textarea-input
name="spnegoKeytab"
label=${msg("SPNEGO keytab")}
?revealed=${this.instance === undefined}
help=${msg(
"Keytab used for SPNEGO. Optional if SPNEGO credentials cache is provided. Must be base64 encoded or in the form TYPE:residual.",
)}
></ak-private-textarea-input>
></ak-secret-textarea-input>
<ak-text-input
name="spnegoCcache"
label=${msg("SPNEGO credentials cache")}

View File

@ -2,7 +2,7 @@ import "@goauthentik/admin/common/ak-crypto-certificate-search";
import { placeholderHelperText } from "@goauthentik/admin/helperText";
import { BaseSourceForm } from "@goauthentik/admin/sources/BaseSourceForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import "@goauthentik/components/ak-private-text-input.js";
import "@goauthentik/components/ak-secret-text-input.js";
import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js";
import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement";
@ -260,11 +260,11 @@ export class LDAPSourceForm extends BaseSourceForm<LDAPSource> {
class="pf-c-form-control"
/>
</ak-form-element-horizontal>
<ak-private-text-input
<ak-secret-text-input
label=${msg("Bind Password")}
name="bindPassword"
?revealed=${this.instance === undefined}
></ak-private-text-input>
></ak-secret-text-input>
<ak-form-element-horizontal label=${msg("Base DN")} required name="baseDn">
<input
type="text"

View File

@ -8,8 +8,8 @@ import {
UserMatchingModeToLabel,
} from "@goauthentik/admin/sources/oauth/utils";
import { DEFAULT_CONFIG, config } from "@goauthentik/common/api/config";
import "@goauthentik/components/ak-private-textarea-input.js";
import "@goauthentik/components/ak-radio-input";
import "@goauthentik/components/ak-secret-textarea-input.js";
import "@goauthentik/elements/CodeMirror";
import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror";
import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js";
@ -441,14 +441,14 @@ export class OAuthSourceForm extends WithCapabilitiesConfig(BaseSourceForm<OAuth
/>
<p class="pf-c-form__helper-text">${msg("Also known as Client ID.")}</p>
</ak-form-element-horizontal>
<ak-private-textarea-input
<ak-secret-textarea-input
label=${msg("Consumer secret")}
name="consumerSecret"
input-hint="code"
help=${msg("Also known as Client Secret.")}
required
?revealed=${this.instance === undefined}
></ak-private-textarea-input>
></ak-secret-textarea-input>
<ak-form-element-horizontal label=${msg("Scopes")} name="additionalScopes">
<input
type="text"

View File

@ -1,7 +1,7 @@
import { RenderFlowOption } from "@goauthentik/admin/flows/utils";
import { BaseStageForm } from "@goauthentik/admin/stages/BaseStageForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import "@goauthentik/components/ak-private-text-input.js";
import "@goauthentik/components/ak-secret-text-input.js";
import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement";
import "@goauthentik/elements/forms/SearchSelect";
@ -95,13 +95,13 @@ export class AuthenticatorDuoStageForm extends BaseStageForm<AuthenticatorDuoSta
required
/>
</ak-form-element-horizontal>
<ak-private-text-input
<ak-secret-text-input
name="clientSecret"
label=${msg("Secret key")}
input-hint="code"
required
?revealed=${this.instance === undefined}
></ak-private-text-input>
></ak-secret-text-input>
</div>
</ak-form-group>
<ak-form-group>
@ -125,12 +125,12 @@ export class AuthenticatorDuoStageForm extends BaseStageForm<AuthenticatorDuoSta
spellcheck="false"
/>
</ak-form-element-horizontal>
<ak-private-text-input
<ak-secret-text-input
name="adminSecretKey"
label=${msg("Secret key")}
input-hint="code"
?revealed=${this.instance === undefined}
></ak-private-text-input>
></ak-secret-text-input>
</div>
</ak-form-group>
<ak-form-group expanded>

View File

@ -1,7 +1,7 @@
import { RenderFlowOption } from "@goauthentik/admin/flows/utils";
import { BaseStageForm } from "@goauthentik/admin/stages/BaseStageForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import "@goauthentik/components/ak-private-text-input.js";
import "@goauthentik/components/ak-secret-text-input.js";
import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement";
import "@goauthentik/elements/forms/Radio";
@ -77,11 +77,11 @@ export class AuthenticatorEmailStageForm extends BaseStageForm<AuthenticatorEmai
/>
</ak-form-element-horizontal>
<ak-private-text-input
<ak-secret-text-input
name="password"
label=${msg("SMTP Password")}
?revealed=${this.instance === undefined}
></ak-private-text-input>
></ak-secret-text-input>
<ak-form-element-horizontal name="useTls">
<label class="pf-c-switch">

View File

@ -1,7 +1,7 @@
import { BaseStageForm } from "@goauthentik/admin/stages/BaseStageForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import "@goauthentik/components/ak-number-input";
import "@goauthentik/components/ak-private-text-input.js";
import "@goauthentik/components/ak-secret-text-input.js";
import "@goauthentik/components/ak-switch-input";
import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement";
@ -70,7 +70,7 @@ export class CaptchaStageForm extends BaseStageForm<CaptchaStage> {
</p>
</ak-form-element-horizontal>
<ak-private-text-input
<ak-secret-text-input
name="privateKey"
label=${msg("Private Key")}
input-hint="code"
@ -79,7 +79,7 @@ export class CaptchaStageForm extends BaseStageForm<CaptchaStage> {
help=${msg(
"Private key, acquired from https://www.google.com/recaptcha/intro/v3.html.",
)}
></ak-private-text-input>
></ak-secret-text-input>
<ak-switch-input
name="interactive"

View File

@ -1,6 +1,6 @@
import { BaseStageForm } from "@goauthentik/admin/stages/BaseStageForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import "@goauthentik/components/ak-private-text-input.js";
import "@goauthentik/components/ak-secret-text-input.js";
import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement";
import "@goauthentik/elements/utils/TimeDeltaHelp";
@ -73,11 +73,11 @@ export class EmailStageForm extends BaseStageForm<EmailStage> {
class="pf-c-form-control"
/>
</ak-form-element-horizontal>
<ak-private-text-input
<ak-secret-text-input
label=${msg("SMTP Password")}
name="password"
?revealed=${this.instance === undefined}
></ak-private-text-input>
></ak-secret-text-input>
<ak-form-element-horizontal name="useTls">
<label class="pf-c-switch">
<input

View File

@ -1,4 +1,4 @@
import { AKElement } from "@goauthentik/elements/Base";
import { AKElement, type AKElementProps } from "@goauthentik/elements/Base";
import "@goauthentik/elements/forms/HorizontalFormElement.js";
import { TemplateResult, html, nothing } from "lit";
@ -6,6 +6,19 @@ import { property } from "lit/decorators.js";
type HelpType = TemplateResult | typeof nothing;
export interface HorizontalLightComponentProps<T> extends AKElementProps {
name: string;
label?: string;
required?: boolean;
help?: string;
bighelp?: TemplateResult | TemplateResult[];
hidden?: boolean;
invalid?: boolean;
errorMessages?: string[];
value?: T;
inputHint?: string;
}
export class HorizontalLightComponent<T> extends AKElement {
// Render into the lightDOM. This effectively erases the shadowDOM nature of this component, but
// we're not actually using that and, for the meantime, we need the form handlers to be able to
@ -18,37 +31,81 @@ export class HorizontalLightComponent<T> extends AKElement {
return this;
}
/**
* The name attribute for the form element
* @property
* @attribute
*/
@property({ type: String, reflect: true })
name!: string;
/**
* The label for the input control
* @property
* @attribute
*/
@property({ type: String, reflect: true })
label = "";
/**
* @property
* @attribute
*/
@property({ type: Boolean, reflect: true })
required = false;
/**
* Help text to display below the form element. Optional
* @property
* @attribute
*/
@property({ type: String, reflect: true })
help = "";
/**
* Extended help content. Optional. Expects to be a TemplateResult
* @property
*/
@property({ type: Object })
bighelp?: TemplateResult | TemplateResult[];
/**
* @property
* @attribute
*/
@property({ type: Boolean, reflect: true })
hidden = false;
/**
* @property
* @attribute
*/
@property({ type: Boolean, reflect: true })
invalid = false;
/**
* @property
*/
@property({ attribute: false })
errorMessages: string[] = [];
/**
* @attribute
* @property
*/
@property({ attribute: false })
value?: T;
/**
* Input hint.
* - `code`: uses a monospace font and disables spellcheck & autocomplete
* @property
* @attribute
*/
@property({ type: String, attribute: "input-hint" })
inputHint = "";
renderControl() {
protected renderControl() {
throw new Error("Must be implemented in a subclass");
}

View File

@ -0,0 +1,159 @@
import { bound } from "#elements/decorators/bound";
import { msg } from "@lit/localize";
import { css, html } from "lit";
import { customElement, property, query } from "lit/decorators.js";
import { classMap } from "lit/directives/class-map.js";
import { ifDefined } from "lit/directives/if-defined.js";
import {
HorizontalLightComponent,
HorizontalLightComponentProps,
} from "./HorizontalLightComponent";
import "./ak-visibility-toggle.js";
import type { VisibilityToggleProps } from "./ak-visibility-toggle.js";
type BaseProps = HorizontalLightComponentProps<string> &
Pick<VisibilityToggleProps, "showMessage" | "hideMessage">;
export interface AkHiddenTextInputProps extends BaseProps {
revealed: boolean;
placeholder?: string;
}
export type InputLike = HTMLTextAreaElement | HTMLInputElement;
/**
* @element ak-hidden-text-input
* @class AkHiddenTextInput
*
* A text-input field with a visibility control, so you can show/hide sensitive fields.
*
* ## CSS Parts
* @csspart container - The main container div
* @csspart input - The input element
* @csspart toggle - The visibility toggle button
*
*/
@customElement("ak-hidden-text-input")
export class AkHiddenTextInput<T extends InputLike = HTMLInputElement>
extends HorizontalLightComponent<string>
implements AkHiddenTextInputProps
{
public static get styles() {
return [
css`
main {
display: flex;
}
`,
];
}
/**
* @property
* @attribute
*/
@property({ type: String, reflect: true })
public value = "";
/**
* @property
* @attribute
*/
@property({ type: Boolean, reflect: true })
public revealed = false;
/**
* Text for when the input has no set value
*
* @property
* @attribute
*/
@property({ type: String })
public placeholder?: string;
/**
* Specify kind of help the browser should try to provide
*
* @property
* @attribute
*/
@property({ type: String })
public autocomplete?: "none" | AutoFill;
/**
* @property
* @attribute
*/
@property({ type: String, attribute: "show-message" })
public showMessage = msg("Show field content");
/**
* @property
* @attribute
*/
@property({ type: String, attribute: "hide-message" })
public hideMessage = msg("Hide field content");
@query("#main > input")
protected inputField!: T;
@bound
private handleToggleVisibility() {
this.revealed = !this.revealed;
// Maintain focus on input after toggle
this.updateComplete.then(() => {
if (this.inputField && document.activeElement === this) {
this.inputField.focus();
}
});
}
// TODO: Because of the peculiarities of how HorizontalLightComponent works, keeping its content
// in the LightDom so the inner components actually inherit styling, the normal `css` options
// aren't available. Embedding styles is bad styling, and we'll fix it in the next style
// refresh.
protected renderInputField(setValue: (ev: InputEvent) => void, code: boolean) {
return html` <input
style="flex: 1 1 auto; min-width: 0;"
part="input"
type=${this.revealed ? "text" : "password"}
@input=${setValue}
value=${ifDefined(this.value)}
placeholder=${ifDefined(this.placeholder)}
class="${classMap({
"pf-c-form-control": true,
"pf-m-monospace": code,
})}"
spellcheck=${code ? "false" : "true"}
?required=${this.required}
/>`;
}
protected override renderControl() {
const code = this.inputHint === "code";
const setValue = (ev: InputEvent) => {
this.value = (ev.target as T).value;
};
return html` <div style="display: flex; gap: 0.25rem">
${this.renderInputField(setValue, code)}
<!-- -->
<ak-visibility-toggle
part="toggle"
style="flex: 0 0 auto; align-self: flex-start"
?open=${this.revealed}
show-message=${this.showMessage}
hide-message=${this.hideMessage}
@click=${() => (this.revealed = !this.revealed)}
></ak-visibility-toggle>
</div>`;
}
}
declare global {
interface HTMLElementTagNameMap {
"ak-hidden-text-input": AkHiddenTextInput;
}
}

View File

@ -0,0 +1,128 @@
import { css, html } from "lit";
import { customElement, property, query } from "lit/decorators.js";
import { classMap } from "lit/directives/class-map.js";
import { ifDefined } from "lit/directives/if-defined.js";
import { AkHiddenTextInput, type AkHiddenTextInputProps } from "./ak-hidden-text-input.js";
export interface AkHiddenTextAreaInputProps extends AkHiddenTextInputProps {
/**
* Number of visible text lines (rows)
*/
rows?: number;
/**
* Number of visible character width (cols)
*/
cols?: number;
/**
* How the textarea can be resized
*/
resize?: "none" | "both" | "horizontal" | "vertical";
/**
* Whether text should wrap
*/
wrap?: "soft" | "hard" | "off";
}
/**
* @element ak-hidden-text-input
* @class AkHiddenTextInput
*
* A text-input field with a visibility control, so you can show/hide sensitive fields.
*
* ## CSS Parts
* @csspart container - The main container div
* @csspart input - The input element
* @csspart toggle - The visibility toggle button
*
*/
@customElement("ak-hidden-textarea-input")
export class AkHiddenTextAreaInput
extends AkHiddenTextInput<HTMLTextAreaElement>
implements AkHiddenTextAreaInputProps
{
/* These are mostly just forwarded to the textarea component. */
/**
* @property
* @attribute
*/
@property({ type: Number })
rows?: number = 4;
/**
* @property
* @attribute
*/
@property({ type: Number })
cols?: number;
/**
* @property
* @attribute
*
* You want `resize=true` so that the resize value is visible in the component tag, activating
* the CSS associated with these values.
*/
@property({ type: String, reflect: true })
resize?: "none" | "both" | "horizontal" | "vertical" = "vertical";
/**
* @property
* @attribute
*/
@property({ type: String })
wrap?: "soft" | "hard" | "off" = "soft";
@query("#main > textarea")
protected inputField!: HTMLTextAreaElement;
get displayValue() {
const value = this.value ?? "";
if (this.revealed) {
return value;
}
return value
.split("\n")
.reduce((acc: string[], line: string) => [...acc, "*".repeat(line.length)], [])
.join("\n");
}
// TODO: Because of the peculiarities of how HorizontalLightComponent works, keeping its content
// in the LightDom so the inner components actually inherit styling, the normal `css` options
// aren't available. Embedding styles is bad styling, and we'll fix it in the next style
// refresh.
protected override renderInputField(setValue: (ev: InputEvent) => void, code: boolean) {
const wrap = this.revealed ? this.wrap : "soft";
return html`
<textarea
style="flex: 1 1 auto; min-width: 0;"
part="textarea"
@input=${setValue}
placeholder=${ifDefined(this.placeholder)}
rows=${ifDefined(this.rows)}
cols=${ifDefined(this.cols)}
wrap=${ifDefined(wrap)}
class=${classMap({
"pf-c-form-control": true,
"pf-m-monospace": code,
})}
spellcheck=${code ? "false" : "true"}
?required=${this.required}
>
${this.displayValue}</textarea
>
`;
}
}
declare global {
interface HTMLElementTagNameMap {
"ak-hidden-textarea-input": AkHiddenTextAreaInput;
}
}

View File

@ -8,8 +8,8 @@ import { ifDefined } from "lit/directives/if-defined.js";
import { HorizontalLightComponent } from "./HorizontalLightComponent";
@customElement("ak-private-text-input")
export class AkPrivateTextInput extends HorizontalLightComponent<string> {
@customElement("ak-secret-text-input")
export class AkSecretTextInput extends HorizontalLightComponent<string> {
@property({ type: String, reflect: true })
public value = "";
@ -23,7 +23,7 @@ export class AkPrivateTextInput extends HorizontalLightComponent<string> {
this.revealed = true;
}
#renderPrivateInput() {
#renderSecretInput() {
return html`<div class="pf-c-form__horizontal-group" @click=${() => this.#onReveal()}>
<input
class="pf-c-form-control"
@ -60,14 +60,14 @@ export class AkPrivateTextInput extends HorizontalLightComponent<string> {
}
public override renderControl() {
return this.revealed ? this.renderVisibleInput() : this.#renderPrivateInput();
return this.revealed ? this.renderVisibleInput() : this.#renderSecretInput();
}
}
export default AkPrivateTextInput;
export default AkSecretTextInput;
declare global {
interface HTMLElementTagNameMap {
"ak-private-text-input": AkPrivateTextInput;
"ak-secret-text-input": AkSecretTextInput;
}
}

View File

@ -5,10 +5,10 @@ import { customElement, property } from "lit/decorators.js";
import { classMap } from "lit/directives/class-map.js";
import { ifDefined } from "lit/directives/if-defined.js";
import { AkPrivateTextInput } from "./ak-private-text-input.js";
import { AkSecretTextInput } from "./ak-secret-text-input.js";
@customElement("ak-private-textarea-input")
export class AkPrivateTextAreaInput extends AkPrivateTextInput {
@customElement("ak-secret-textarea-input")
export class AkSecretTextAreaInput extends AkSecretTextInput {
protected override renderVisibleInput() {
const code = this.inputHint === "code";
const setValue = (ev: InputEvent) => {
@ -34,10 +34,10 @@ export class AkPrivateTextAreaInput extends AkPrivateTextInput {
}
}
export default AkPrivateTextAreaInput;
export default AkSecretTextAreaInput;
declare global {
interface HTMLElementTagNameMap {
"ak-private-textarea-input": AkPrivateTextAreaInput;
"ak-secret-textarea-input": AkSecretTextAreaInput;
}
}

View File

@ -0,0 +1,89 @@
import { AKElement } from "@goauthentik/elements/Base.js";
import { msg } from "@lit/localize";
import { html } from "lit";
import { customElement, property } from "lit/decorators.js";
import PFButton from "@patternfly/patternfly/components/Button/button.css";
import PFBase from "@patternfly/patternfly/patternfly-base.css";
export interface VisibilityToggleProps {
open: boolean;
disabled: boolean;
showMessage: string;
hideMessage: string;
}
/**
* @component ak-visibility-toggle
* @class VisibilityToggle
*
* A straightforward two-state iconic button we use in a few places as way of telling users to hide
* or show something secret, such as a password or private key. Expects the client to manage its
* state.
*
* @events
* - click: when the toggle is clicked.
*/
@customElement("ak-visibility-toggle")
export class VisibilityToggle extends AKElement implements VisibilityToggleProps {
static get styles() {
return [PFBase, PFButton];
}
/**
* @property
* @attribute
*/
@property({ type: Boolean, reflect: true })
open = false;
/**
* @property
* @attribute
*/
@property({ type: Boolean, reflect: true })
disabled = false;
/**
* @property
* @attribute
*/
@property({ type: String, attribute: "show-message" })
showMessage = msg("Show field content");
/**
* @property
* @attribute
*/
@property({ type: String, attribute: "hide-message" })
hideMessage = msg("Hide field content");
render() {
const [label, icon] = this.open
? [this.hideMessage, "fa-eye"]
: [this.showMessage, "fa-eye-slash"];
const onClick = (ev: PointerEvent) => {
ev.stopPropagation();
this.dispatchEvent(new PointerEvent(ev.type, ev));
};
return html`<button
aria-label=${label}
title=${label}
@click=${onClick}
?disabled=${this.disabled}
class="pf-c-button pf-m-control"
type="button"
>
<i class="fas ${icon}" aria-hidden="true"></i>
</button>`;
}
}
declare global {
interface HTMLElementTagNameMap {
"ak-visibility-toggle": VisibilityToggle;
}
}

View File

@ -0,0 +1,93 @@
import type { Meta, StoryObj } from "@storybook/web-components";
import { html, nothing } from "lit";
import { ifDefined } from "lit/directives/if-defined.js";
import "../ak-hidden-text-input";
import { type AkHiddenTextInput, type AkHiddenTextInputProps } from "../ak-hidden-text-input.js";
const metadata: Meta<AkHiddenTextInputProps> = {
title: "Components / <ak-hidden-text-input>",
component: "ak-hidden-text-input",
tags: ["autodocs"],
parameters: {
docs: {
description: {
component: `
# Hidden Text Input Component
A text-input field with a visibility control, so you can show/hide sensitive fields.
`,
},
},
layout: "padded",
},
argTypes: {
label: {
control: "text",
description: "Label text for the input field",
},
value: {
control: "text",
description: "Current value of the input",
},
revealed: {
control: "boolean",
description: "Whether the text is currently visible",
},
placeholder: {
control: "text",
description: "Placeholder text for the input",
},
required: {
control: "boolean",
description: "Whether the input is required",
},
inputHint: {
control: "select",
options: ["text", "code"],
description: "Input type hint for styling and behavior",
},
showMessage: {
control: "text",
description: "Custom message for show action",
},
hideMessage: {
control: "text",
description: "Custom message for hide action",
},
},
};
export default metadata;
type Story = StoryObj<AkHiddenTextInput>;
const Template: Story = {
args: {
label: "Hidden Text Input",
value: "",
revealed: false,
},
render: (args) => html`
<ak-hidden-text-input
label=${ifDefined(args.label)}
value=${ifDefined(args.value)}
?revealed=${args.revealed}
placeholder=${ifDefined(args.placeholder)}
?required=${args.required}
input-hint=${ifDefined(args.inputHint)}
show-message=${ifDefined(args.showMessage)}
hide-message=${ifDefined(args.hideMessage)}
></ak-hidden-text-input>
`,
};
export const Password: Story = {
...Template,
args: {
label: "Password",
placeholder: "Enter your password",
required: true,
},
};

View File

@ -0,0 +1,140 @@
import type { Meta, StoryObj } from "@storybook/web-components";
import { html, nothing } from "lit";
import { ifDefined } from "lit/directives/if-defined.js";
import "../ak-hidden-textarea-input";
import {
type AkHiddenTextAreaInput,
type AkHiddenTextAreaInputProps,
} from "../ak-hidden-textarea-input.js";
const metadata: Meta<AkHiddenTextAreaInputProps> = {
title: "Components / <ak-hidden-textarea-input>",
component: "ak-hidden-textarea-input",
tags: ["autodocs"],
parameters: {
docs: {
description: {
component: `
# Hidden Textarea Input Component
A textarea input field with a visibility control, so you can show/hide sensitive fields.
`,
},
},
layout: "padded",
},
argTypes: {
label: {
control: "text",
description: "Label text for the input field",
},
value: {
control: "text",
description: "Current value of the input",
},
revealed: {
control: "boolean",
description: "Whether the text is currently visible",
},
placeholder: {
control: "text",
description: "Placeholder text for the input",
},
required: {
control: "boolean",
description: "Whether the input is required",
},
inputHint: {
control: "select",
options: ["text", "code"],
description: "Input type hint for styling and behavior",
},
showMessage: {
control: "text",
description: "Custom message for show action",
},
hideMessage: {
control: "text",
description: "Custom message for hide action",
},
rows: {
control: { type: "number", min: 1, max: 50 },
description: "Number of visible text lines",
},
cols: {
control: { type: "number", min: 10, max: 200 },
description: "Number of visible character width",
},
resize: {
control: "select",
options: ["none", "both", "horizontal", "vertical"],
description: "How the textarea can be resized",
},
wrap: {
control: "select",
options: ["soft", "hard", "off"],
description: "Text wrapping behavior",
},
},
};
export default metadata;
type Story = StoryObj<AkHiddenTextAreaInput>;
const Template: Story = {
args: {
label: "Hidden Textarea Input",
value: "",
revealed: false,
rows: 4,
},
render: (args) => html`
<ak-hidden-textarea-input
label=${ifDefined(args.label)}
value=${ifDefined(args.value)}
?revealed=${args.revealed}
placeholder=${ifDefined(args.placeholder)}
rows=${ifDefined(args.rows)}
cols=${ifDefined(args.cols)}
resize=${ifDefined(args.resize)}
wrap=${ifDefined(args.wrap)}
?required=${args.required}
input-hint=${ifDefined(args.inputHint)}
show-message=${ifDefined(args.showMessage)}
hide-message=${ifDefined(args.hideMessage)}
></ak-hidden-textarea-input>
`,
};
export const SslCertificate: Story = {
...Template,
args: {
label: "SSL Certificate",
value: `-----BEGIN CERTIFICATE-----
MIIDXTCCAkWgAwIBAgIJAKoK/heBjcOuMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQwHhcNMTcwNTEwMTk0MDA2WhcNMTgwNTEwMTk0MDA2WjBF
MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50
ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMB4XDTE3MDUxMDE5NDAwNloXDTE4MDUxMDE5
NDAwNlowRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUxITAfBgNV
BAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBALdUlNS31SzxwoFShahGfjHj6GgpcVbzL1Siq0Pqnf82T6M2
EDuneMLzAgMBAAECggEBAJkPFn6jeMHyiq0Pqnf82T6M2EDuneMLzAgMBAAECggE
BAJkPFn6jeMHyiq0Pqnf82T6M2EDuneMLzAgMBAAECggEBAJkPFn6jeMHyiq0Pqn
f82T6M2EDuneMLzAgMBAAECggEBAJkPFn6jeMHyiq0Pqnf82T6M2EDuneMLzAgM
BAAECggEBAJkPFn6jeMHyiq0Pqnf82T6M2EDuneMLzAgMBAAECggEBAJkPFn6jeM
Hyiq0Pqnf82T6M2EDuneMLzAgMBAAECggEBAJkPFn6jeMHyiq0Pqnf82T6M2EDu
neMLzAgMBAAECggEBAJkPFn6jeMHyiq0Pqnf82T6M2EDuneMLzAgMBAAECggEBAJ
kPFn6jeMHyiq0Pqnf82T6M2EDuneMLzAgMBAAE=
-----END CERTIFICATE-----`,
inputHint: "code",
rows: 15,
resize: "vertical",
showMessage: "Show certificate content",
hideMessage: "Hide certificate content",
autocomplete: "off",
},
};

View File

@ -0,0 +1,121 @@
import type { Meta, StoryObj } from "@storybook/web-components";
import { html, nothing } from "lit";
import { ifDefined } from "lit/directives/if-defined.js";
import "../ak-visibility-toggle";
import { type VisibilityToggle, type VisibilityToggleProps } from "../ak-visibility-toggle.js";
const metadata: Meta<VisibilityToggleProps> = {
title: "Elements/<ak-visibility-toggle>",
component: "ak-visibility-toggle",
tags: ["autodocs"],
parameters: {
docs: {
description: {
component: `
# Visibility Toggle Component
A straightforward two-state iconic button for toggling the visibility of sensitive content such as passwords, private keys, or other secret information.
- Use for sensitive content that users might want to temporarily reveal
- There are default hide/show messages for screen readers, but they can be overridden
- Clients always handle the state
- The \`open\` state is false by default; we assume you want sensitive content hidden at start
`,
},
},
layout: "padded",
},
argTypes: {
open: {
control: "boolean",
description: "Whether the toggle is in the 'show' state (true) or 'hide' state (false)",
},
showMessage: {
control: "text",
description:
'Message for screen readers when in hide state (default: "Show field content")',
},
hideMessage: {
control: "text",
description:
'Message for screen readers when in show state (default: "Hide field content")',
},
disabled: {
control: "boolean",
description: "Whether the button should be disabled (for demo purposes)",
},
},
};
export default metadata;
type Story = StoryObj<VisibilityToggle>;
const Template: Story = {
args: {
open: false,
showMessage: "Show field content",
hideMessage: "Hide field content",
},
render: (args) => html`
<ak-visibility-toggle
?open=${args.open}
show-message=${ifDefined(args.showMessage)}
hide-message=${ifDefined(args.hideMessage)}
@click=${(e: Event) => {
const target = e.target as VisibilityToggle;
target.open = !target.open;
// In a real application, you would also toggle the visibility
// of the associated content here
}}
></ak-visibility-toggle>
`,
};
// Password field integration example
export const PasswordFieldExample: Story = {
args: {
showMessage: "Reveal password",
hideMessage: "Conceal password",
},
render: () => {
let isVisible = false;
const toggleVisibility = (e: Event) => {
isVisible = !isVisible;
const toggle = e.target as VisibilityToggle;
const passwordField = document.querySelector("#demo-password") as HTMLInputElement;
toggle.open = isVisible;
if (passwordField) {
passwordField.type = isVisible ? "text" : "password";
}
};
return html`
<div style="display: flex; flex-direction: column; gap: 1rem; max-width: 300px;">
<label for="demo-password" style="font-weight: bold;">Password:</label>
<div style="display: flex; align-items: center; gap: 0.5rem;">
<input
id="demo-password"
type="password"
value="supersecretpassword123"
style="flex: 1; padding: 0.5rem; border: 1px solid #ccc; border-radius: 4px;"
readonly
/>
<ak-visibility-toggle
?open=${isVisible}
show-message="Show password"
hide-message="Hide password"
@click=${toggleVisibility}
></ak-visibility-toggle>
</div>
<p style="font-size: 0.875rem; color: #666;">
Click the eye icon to toggle password visibility
</p>
</div>
`;
},
};

View File

@ -16,8 +16,12 @@ import { property } from "lit/decorators.js";
import { UiThemeEnum } from "@goauthentik/api";
export interface AKElementProps {
activeTheme: ResolvedUITheme;
}
@localized()
export class AKElement extends LitElement {
export class AKElement extends LitElement implements AKElementProps {
//#region Static Properties
public static styles?: Array<CSSResult | CSSModule>;

View File

@ -1,4 +1,4 @@
<?xml version="1.0" ?><xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
<?xml version="1.0"?><xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
<file target-language="zh-Hans" source-language="en" original="lit-localize-inputs" datatype="plaintext">
<body>
<trans-unit id="s4caed5b7a7e5d89b">
@ -596,9 +596,9 @@
</trans-unit>
<trans-unit id="saa0e2675da69651b">
<source>The URL &quot;<x id="0" equiv-text="${this.url}"/>&quot; was not found.</source>
<target>未找到 URL &quot;
<x id="0" equiv-text="${this.url}"/>&quot;。</target>
<source>The URL "<x id="0" equiv-text="${this.url}"/>" was not found.</source>
<target>未找到 URL "
<x id="0" equiv-text="${this.url}"/>"。</target>
</trans-unit>
<trans-unit id="s58cd9c2fe836d9c6">
@ -1709,8 +1709,8 @@
</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 &quot;fa-test&quot;.</source>
<target>输入完整 URL、相对路径或者使用 'fa://fa-test' 来使用 Font Awesome 图标 &quot;fa-test&quot;。</target>
<source>Either input a full URL, a relative path, or use 'fa://fa-test' to use the Font Awesome icon "fa-test".</source>
<target>输入完整 URL、相对路径或者使用 'fa://fa-test' 来使用 Font Awesome 图标 "fa-test"。</target>
</trans-unit>
<trans-unit id="s0410779cb47de312">
@ -3762,10 +3762,10 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit>
<trans-unit id="sa95a538bfbb86111">
<source>Are you sure you want to update <x id="0" equiv-text="${this.objectLabel}"/> &quot;<x id="1" equiv-text="${this.obj?.name}"/>&quot;?</source>
<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>您确定要更新
<x id="0" equiv-text="${this.objectLabel}"/>&quot;
<x id="1" equiv-text="${this.obj?.name}"/>&quot; 吗?</target>
<x id="0" equiv-text="${this.objectLabel}"/>"
<x id="1" equiv-text="${this.obj?.name}"/>" 吗?</target>
</trans-unit>
<trans-unit id="sc92d7cfb6ee1fec6">
@ -4831,7 +4831,7 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit>
<trans-unit id="sdf1d8edef27236f0">
<source>A &quot;roaming&quot; authenticator, like a YubiKey</source>
<source>A "roaming" authenticator, like a YubiKey</source>
<target>像 YubiKey 这样的“漫游”身份验证器</target>
</trans-unit>
@ -5190,7 +5190,7 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit>
<trans-unit id="s1608b2f94fa0dbd4">
<source>If set to a duration above 0, the user will have the option to choose to &quot;stay signed in&quot;, which will extend their session by the time specified here.</source>
<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>
<target>如果设置时长大于 0用户可以选择“保持登录”选项这将使用户的会话延长此处设置的时间。</target>
</trans-unit>
@ -7466,7 +7466,7 @@ Bindings to groups/users are checked against the user of the event.</source>
<target>成功创建用户并添加到组 <x id="0" equiv-text="${this.group.name}"/></target>
</trans-unit>
<trans-unit id="s824e0943a7104668">
<source>This user will be added to the group &quot;<x id="0" equiv-text="${this.targetGroup.name}"/>&quot;.</source>
<source>This user will be added to the group "<x id="0" equiv-text="${this.targetGroup.name}"/>".</source>
<target>此用户将会被添加到组 &amp;quot;<x id="0" equiv-text="${this.targetGroup.name}"/>&amp;quot;。</target>
</trans-unit>
<trans-unit id="s62e7f6ed7d9cb3ca">
@ -8748,7 +8748,7 @@ Bindings to groups/users are checked against the user of the event.</source>
<target>同步组</target>
</trans-unit>
<trans-unit id="s2d5f69929bb7221d">
<source><x id="0" equiv-text="${p.name}"/> (&quot;<x id="1" equiv-text="${p.fieldKey}"/>&quot;, of type <x id="2" equiv-text="${p.type}"/>)</source>
<source><x id="0" equiv-text="${p.name}"/> ("<x id="1" equiv-text="${p.fieldKey}"/>", of type <x id="2" equiv-text="${p.type}"/>)</source>
<target><x id="0" equiv-text="${p.name}"/>&amp;quot;<x id="1" equiv-text="${p.fieldKey}"/>&amp;quot;,类型为 <x id="2" equiv-text="${p.type}"/></target>
</trans-unit>
<trans-unit id="s25bacc19d98b444e">
@ -8996,8 +8996,8 @@ Bindings to groups/users are checked against the user of the event.</source>
<target>授权流程成功后有效的重定向 URI。还可以在此处为隐式流程指定任何来源。</target>
</trans-unit>
<trans-unit id="s4c49d27de60a532b">
<source>To allow any redirect URI, set the mode to Regex and the value to &quot;.*&quot;. Be aware of the possible security implications this can have.</source>
<target>要允许任何重定向 URI请设置模式为正则表达式并将此值设置为 &quot;.*&quot;。请注意这可能带来的安全影响。</target>
<source>To allow any redirect URI, set the mode to Regex and the value to ".*". Be aware of the possible security implications this can have.</source>
<target>要允许任何重定向 URI请设置模式为正则表达式并将此值设置为 ".*"。请注意这可能带来的安全影响。</target>
</trans-unit>
<trans-unit id="sa52bf79fe1ccb13e">
<source>Federated OIDC Sources</source>
@ -9750,7 +9750,7 @@ Bindings to groups/users are checked against the user of the event.</source>
<target>在 authorization_code 令牌请求流程期间,如何执行身份验证</target>
</trans-unit>
<trans-unit id="s844baf19a6c4a9b4">
<source>Enable &quot;Remember me on this device&quot;</source>
<source>Enable "Remember me on this device"</source>
<target>启用“在此设备上记住我”</target>
</trans-unit>
<trans-unit id="sfa72bca733f40692">
@ -9883,4 +9883,4 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
</body>
</file>
</xliff>
</xliff>

View File

@ -661,12 +661,6 @@
<source>Apps with most usage</source>
<target>使用率最高的应用</target>
</trans-unit>
<trans-unit id="sda5e1499f93146ad">
<source><x id="0" equiv-text="${ago}"/> days ago</source>
<target>
<x id="0" equiv-text="${ago}"/>天前</target>
</trans-unit>
<trans-unit id="s51ea3a244c781b1f">
<source>Objects created</source>
@ -6118,21 +6112,11 @@ Bindings to groups/users are checked against the user of the event.</source>
<source>Download Private key</source>
<target>下载私钥</target>
</trans-unit>
<trans-unit id="s3a5fec3d73ac9edc">
<source>Create Certificate-Key Pair</source>
<target>创建证书密钥对</target>
</trans-unit>
<trans-unit id="s45cb501abd43ba52">
<source>Generate</source>
<target>生成</target>
</trans-unit>
<trans-unit id="sf9bddaf910f4eea5">
<source>Generate Certificate-Key Pair</source>
<target>生成证书密钥对</target>
</trans-unit>
<trans-unit id="see2bcbc11bb91960">
<source>Successfully updated instance.</source>
@ -7533,10 +7517,6 @@ Bindings to groups/users are checked against the user of the event.</source>
<source>Configure SCIM Provider</source>
<target>配置 SCIM 提供程序</target>
</trans-unit>
<trans-unit id="s7513372fe60f6387">
<source>Event volume</source>
<target>事件容量</target>
</trans-unit>
<trans-unit id="s3271da6c18c25b18">
<source>Connection settings.</source>
<target>连接设置。</target>
@ -9888,6 +9868,18 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s04bb32ec9f359507">
<source>Additional Group DN</source>
<target>额外的组 DN</target>
</trans-unit>
<trans-unit id="sb7af25ce6e30d61a">
<source>The currently selected policy engine mode is <x id="0" equiv-text="${policyEngineMode.label}"/>:</source>
<target>当前所选策略引擎模式为 <x id="0" equiv-text="${policyEngineMode.label}"/></target>
</trans-unit>
<trans-unit id="se1d2545eda4b1600">
<source>Import Existing Certificate-Key Pair</source>
<target>导入已有的证书密钥对</target>
</trans-unit>
<trans-unit id="sb3d5c0a0501669df">
<source>Generate New Certificate-Key Pair</source>
<target>生成新的证书密钥对</target>
</trans-unit>
</body>
</file>

View File

@ -1,15 +1,10 @@
Create a `http_top.conf` file in your nginx `conf.d` directory (`/nginx/conf.d/`) with the following content:
```nginx
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
# Upgrade WebSocket if requested, otherwise use keepalive
map $http_upgrade $connection_upgrade_keepalive {
default upgrade;
'' '';
}
```
Use the following nginx template:
```nginx
server {
# SSL and VHost configuration
listen 443 ssl http2;
@ -25,13 +20,13 @@ server {
proxy_buffer_size 32k;
location / {
# Put your proxy_pass to your application here, and all the other statements you'll need.
# Put your proxy_pass to your application here, and all the other statements you'll need
# proxy_pass http://localhost:5000;
# proxy_set_header Host $host;
# proxy_set_header ...
# Support for websocket
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Connection $connection_upgrade_keepalive;
##############################
# authentik-specific config

View File

@ -72,7 +72,7 @@ To check if your config has been applied correctly, you can run the following co
- `AUTHENTIK_POSTGRESQL__PASSWORD`: Database password, defaults to the environment variable `POSTGRES_PASSWORD`
{/* TODO: Temporarily deactivated feature, see https://github.com/goauthentik/authentik/issues/14320 */}
{/* - `AUTHENTIK_POSTGRESQL__USE_POOL`: Use a [connection pool](https://docs.djangoproject.com/en/stable/ref/databases/#connection-pool) for PostgreSQL connections. Defaults to `false`. :ak-version[2025.4] */}
- `AUTHENTIK_POSTGRESQL__POOL_OPTIONS`: Extra configuration to pass to the [ConnectionPool object](https://www.psycopg.org/psycopg3/docs/api/pool.html#psycopg_pool.ConnectionPool) when it is created. Must be a base64-encoded JSON dictionary. Ignored when `USE_POOL` is set to `false`. :ak-version[2025.4]
{/* - `AUTHENTIK_POSTGRESQL__POOL_OPTIONS`: Extra configuration to pass to the [ConnectionPool object](https://www.psycopg.org/psycopg3/docs/api/pool.html#psycopg_pool.ConnectionPool) when it is created. Must be a base64-encoded JSON dictionary. Ignored when `USE_POOL` is set to `false`. :ak-version[2025.4] */}
- `AUTHENTIK_POSTGRESQL__USE_PGBOUNCER`: Adjust configuration to support connection to PgBouncer. Deprecated, see below
- `AUTHENTIK_POSTGRESQL__USE_PGPOOL`: Adjust configuration to support connection to Pgpool. Deprecated, see below
- `AUTHENTIK_POSTGRESQL__SSLMODE`: Strictness of ssl verification. Defaults to `"verify-ca"`

View File

@ -19,11 +19,11 @@
"@goauthentik/docusaurus-config": "^1.1.0",
"@goauthentik/tsconfig": "^1.0.4",
"@mdx-js/react": "^3.1.0",
"@swc/html-linux-x64-gnu": "1.12.0",
"@swc/html-linux-x64-gnu": "1.12.1",
"clsx": "^2.1.1",
"docusaurus-plugin-openapi-docs": "^4.4.0",
"docusaurus-theme-openapi-docs": "^4.4.0",
"postcss": "^8.5.4",
"postcss": "^8.5.5",
"prism-react-renderer": "^2.4.1",
"react": "^18.3.1",
"react-before-after-slider-component": "^1.1.8",
@ -42,7 +42,7 @@
"@goauthentik/tsconfig": "^1.0.4",
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
"@types/lodash": "^4.17.17",
"@types/node": "^24.0.0",
"@types/node": "^24.0.1",
"@types/postman-collection": "^3.5.11",
"@types/react": "^18.3.22",
"@types/semver": "^7.7.0",
@ -64,12 +64,12 @@
"@rspack/binding-darwin-arm64": "1.3.15",
"@rspack/binding-linux-arm64-gnu": "1.3.15",
"@rspack/binding-linux-x64-gnu": "1.3.15",
"@swc/core-darwin-arm64": "1.12.0",
"@swc/core-linux-arm64-gnu": "1.12.0",
"@swc/core-linux-x64-gnu": "1.12.0",
"@swc/html-darwin-arm64": "1.12.0",
"@swc/html-linux-arm64-gnu": "1.12.0",
"@swc/html-linux-x64-gnu": "1.12.0",
"@swc/core-darwin-arm64": "1.12.1",
"@swc/core-linux-arm64-gnu": "1.12.1",
"@swc/core-linux-x64-gnu": "1.12.1",
"@swc/html-darwin-arm64": "1.12.1",
"@swc/html-linux-arm64-gnu": "1.12.1",
"@swc/html-linux-x64-gnu": "1.12.1",
"lightningcss-darwin-arm64": "1.30.1",
"lightningcss-linux-arm64-gnu": "1.30.1",
"lightningcss-linux-x64-gnu": "1.30.1"
@ -5592,9 +5592,9 @@
}
},
"node_modules/@swc/core-darwin-arm64": {
"version": "1.12.0",
"resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.12.0.tgz",
"integrity": "sha512-usLr8kC80GDv3pwH2zoEaS279kxtWY0MY3blbMFw7zA8fAjqxa8IDxm3WcgyNLNWckWn4asFfguEwz/Weem3nA==",
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.12.1.tgz",
"integrity": "sha512-nUjWVcJ3YS2N40ZbKwYO2RJ4+o2tWYRzNOcIQp05FqW0+aoUCVMdAUUzQinPDynfgwVshDAXCKemY8X7nN5MaA==",
"cpu": [
"arm64"
],
@ -5640,9 +5640,9 @@
}
},
"node_modules/@swc/core-linux-arm64-gnu": {
"version": "1.12.0",
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.12.0.tgz",
"integrity": "sha512-Al0x33gUVxNY5tutEYpSyv7mze6qQS1ONa0HEwoRxcK9WXsX0NHLTiOSGZoCUS1SsXM37ONlbA6/Bsp1MQyP+g==",
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.12.1.tgz",
"integrity": "sha512-BxJDIJPq1+aCh9UsaSAN6wo3tuln8UhNXruOrzTI8/ElIig/3sAueDM6Eq7GvZSGGSA7ljhNATMJ0elD7lFatQ==",
"cpu": [
"arm64"
],
@ -5672,9 +5672,9 @@
}
},
"node_modules/@swc/core-linux-x64-gnu": {
"version": "1.12.0",
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.12.0.tgz",
"integrity": "sha512-ltIvqNi7H0c5pRawyqjeYSKEIfZP4vv/datT3mwT6BW7muJtd1+KIDCPFLMIQ4wm/h76YQwPocsin3fzmnFdNA==",
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.12.1.tgz",
"integrity": "sha512-CrYnV8SZIgArQ9LKH0xEF95PKXzX9WkRSc5j55arOSBeDCeDUQk1Bg/iKdnDiuj5HC1hZpvzwMzSBJjv+Z70jA==",
"cpu": [
"x64"
],
@ -5830,9 +5830,9 @@
}
},
"node_modules/@swc/html-darwin-arm64": {
"version": "1.12.0",
"resolved": "https://registry.npmjs.org/@swc/html-darwin-arm64/-/html-darwin-arm64-1.12.0.tgz",
"integrity": "sha512-okpx8G7xGSPiSekxS4FQu3aR8k+q8nZJCfVKzanQxdZUaCm7YDVUci2Unqp9TvpgZJRA0GOWs1U3QMu2vdr0sQ==",
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@swc/html-darwin-arm64/-/html-darwin-arm64-1.12.1.tgz",
"integrity": "sha512-vbCqYgBBdoxlsnUe/G6irBJ69LUOrlLVXgdxWxDSZ3YcbnpVmwi5YEeaRvqf4vNzZ/nzBMd4DYl6KK2Qsi0prw==",
"cpu": [
"arm64"
],
@ -5878,9 +5878,9 @@
}
},
"node_modules/@swc/html-linux-arm64-gnu": {
"version": "1.12.0",
"resolved": "https://registry.npmjs.org/@swc/html-linux-arm64-gnu/-/html-linux-arm64-gnu-1.12.0.tgz",
"integrity": "sha512-ImZLbghifCPqQhwbEprv2zojieD0j/RGJ+tkNpJ6DyGqcf5qVFfPgGDe/WDPEHCMbJlAodvp1iKTdLSAdTfaLg==",
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@swc/html-linux-arm64-gnu/-/html-linux-arm64-gnu-1.12.1.tgz",
"integrity": "sha512-KbqPLtsPVt0/kjp7sUT1APfEtNQUqMam3S0RzJkvuMz9jB2F9DREvj5EG+DPnx2s/kxnDm4sh9vM2sG2xNHErQ==",
"cpu": [
"arm64"
],
@ -5910,9 +5910,9 @@
}
},
"node_modules/@swc/html-linux-x64-gnu": {
"version": "1.12.0",
"resolved": "https://registry.npmjs.org/@swc/html-linux-x64-gnu/-/html-linux-x64-gnu-1.12.0.tgz",
"integrity": "sha512-IVFXgsyn0/8e9nfVrQXAdGDFboom0nls7KSOJ/+oXMmdK917wrnYLDt7M4DyRT2c+xJmMxgR6tyaTW8KLAl02w==",
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/@swc/html-linux-x64-gnu/-/html-linux-x64-gnu-1.12.1.tgz",
"integrity": "sha512-9QNCTgCZtyQVifLXqDTW7v4lgaC11v0/iL9OhsSZ19ycJrBmnxBmZtDIbuQrXAIzE1GD8mMOK/GLey2IeceoDQ==",
"cpu": [
"x64"
],
@ -6615,9 +6615,9 @@
"license": "MIT"
},
"node_modules/@types/node": {
"version": "24.0.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.0.tgz",
"integrity": "sha512-yZQa2zm87aRVcqDyH5+4Hv9KYgSdgwX1rFnGvpbzMaC7YAljmhBET93TPiTd3ObwTL+gSpIzPKg5BqVxdCvxKg==",
"version": "24.0.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.1.tgz",
"integrity": "sha512-MX4Zioh39chHlDJbKmEgydJDS3tspMP/lnQC67G3SWsTnb9NeYVWOjkxpOSy4oMfPs4StcWHwBrvUb4ybfnuaw==",
"license": "MIT",
"dependencies": {
"undici-types": "~7.8.0"
@ -20672,9 +20672,9 @@
}
},
"node_modules/postcss": {
"version": "8.5.4",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.4.tgz",
"integrity": "sha512-QSa9EBe+uwlGTFmHsPKokv3B/oEMQZxfqW0QqNCyhpa6mB1afzulwn8hihglqAb2pOw+BJgNlmXQ8la2VeHB7w==",
"version": "8.5.5",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.5.tgz",
"integrity": "sha512-d/jtm+rdNT8tpXuHY5MMtcbJFBkhXE6593XVR9UoGCH8jSFGci7jGvMGH5RYd5PBJW+00NZQt6gf7CbagJCrhg==",
"funding": [
{
"type": "opencollective",

View File

@ -37,7 +37,7 @@
"clsx": "^2.1.1",
"docusaurus-plugin-openapi-docs": "^4.4.0",
"docusaurus-theme-openapi-docs": "^4.4.0",
"postcss": "^8.5.4",
"postcss": "^8.5.5",
"prism-react-renderer": "^2.4.1",
"react": "^18.3.1",
"react-before-after-slider-component": "^1.1.8",
@ -56,7 +56,7 @@
"@goauthentik/tsconfig": "^1.0.4",
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
"@types/lodash": "^4.17.17",
"@types/node": "^24.0.0",
"@types/node": "^24.0.1",
"@types/postman-collection": "^3.5.11",
"@types/react": "^18.3.22",
"@types/semver": "^7.7.0",
@ -75,12 +75,12 @@
"@rspack/binding-darwin-arm64": "1.3.15",
"@rspack/binding-linux-arm64-gnu": "1.3.15",
"@rspack/binding-linux-x64-gnu": "1.3.15",
"@swc/core-darwin-arm64": "1.12.0",
"@swc/core-linux-arm64-gnu": "1.12.0",
"@swc/core-linux-x64-gnu": "1.12.0",
"@swc/html-darwin-arm64": "1.12.0",
"@swc/html-linux-arm64-gnu": "1.12.0",
"@swc/html-linux-x64-gnu": "1.12.0",
"@swc/core-darwin-arm64": "1.12.1",
"@swc/core-linux-arm64-gnu": "1.12.1",
"@swc/core-linux-x64-gnu": "1.12.1",
"@swc/html-darwin-arm64": "1.12.1",
"@swc/html-linux-arm64-gnu": "1.12.1",
"@swc/html-linux-x64-gnu": "1.12.1",
"lightningcss-darwin-arm64": "1.30.1",
"lightningcss-linux-arm64-gnu": "1.30.1",
"lightningcss-linux-x64-gnu": "1.30.1"