Compare commits

..

16 Commits

Author SHA1 Message Date
22412729e2 release: 2025.4.0 2025-04-29 16:16:32 -03:00
a02868a27d website/docs: Release notes 2025.4.0 (#14281)
* remove rc notice and enterprise tag for the span

* Edit sidebar and security.md

* Add api changes and minor fixes

* Fix linting

* fix netlify linter

* Update website/docs/releases/2025/v2025.4.md

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/docs/releases/2025/v2025.4.md

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* remove changelog entries that shouldn't be there

Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>

* Update v2025.4.md

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update v2025.4.md

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* fix linting

---------

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2025-04-29 15:56:28 -03:00
bfbb4a8ebc website/docs: sessions in database (#13507)
Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2025-04-29 15:56:21 -03:00
6c0e827677 website/docs: add LDAP 'Lookup using user attribute' docs (#13966)
* website/docs: add LDAP 'Lookup using user attribute' docs

Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>

* Updated the doc to new template, removed incorrect screenshot, clarified instructions

* Change in group field explanation as per Marc's comment

* Added examples for filters and changed some language.

* Removed additional info link

* fixup

Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>

* Minor formatting changes

* Update website/docs/users-sources/sources/protocols/ldap/index.md

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/docs/users-sources/sources/directory-sync/active-directory/index.md

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/docs/users-sources/sources/directory-sync/active-directory/index.md

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Dewi Roberts <dewi@goauthentik.io>

* Added more information to service account creation and LDAPS testing

* Added examples for fields based on issue #3801

---------

Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>
Signed-off-by: Dewi Roberts <dewi@goauthentik.io>
Co-authored-by: Dewi Roberts <dewi@goauthentik.io>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Dominic R <dominic@sdko.org>
2025-04-29 15:56:13 -03:00
29884cbf81 website/docs: add postgres pool configuration (#14060)
* website/docs: add postgres pool configuration

Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>

* Update website/docs/install-config/configuration/configuration.mdx

Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>

---------

Signed-off-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
2025-04-29 15:56:01 -03:00
0f02985b0c website/docs: docs about initial perms (#14263)
* basic procedural steps

* more questions, more typos

* more typos

* tweaks

* more content, new links

* fixed link

* tweak

* fix things

* more fixes

* yet more fixes

* Apply suggestions from code review

Co-authored-by: Dewi Roberts <dewi@goauthentik.io>
Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/docs/users-sources/access-control/initial_permissions.mdx

Co-authored-by: Dewi Roberts <dewi@goauthentik.io>
Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* dewi's edits

* dominic's edits

* gergo edits and more dominic edits

* one more

* yet one more fix

* final gergo observation

* tweak

---------

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Tana M Berry <tana@goauthentik.io>
Co-authored-by: Dewi Roberts <dewi@goauthentik.io>
2025-04-29 15:55:54 -03:00
2244e026c2 website/docs: Revert "website/docs: revert token_expiry format in example blueprint… (#14280)
Revert "website/docs: revert token_expiry format in example blueprint (#13582)"

This reverts commit 9538cf4690.
2025-04-29 15:55:47 -03:00
429c03021c website/docs: Password Uniqueness Policy (#13686)
* First draft docs for policies/unique_password

* simplify documentation

* fix styling

* Add clarification about when this policy takes effect

* change wording in how it works

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Marcelo Elizeche Landó <marce@melizeche.com>

* Take the user by the hand and tell them where to go

* Improve wording in Configuration options

* add suggestion from PR

Co-authored-by: Dominic R <dominic@sdko.org>
Signed-off-by: Marcelo Elizeche Landó <marce@melizeche.com>

* Update website/docs/customize/policies/unique_password.md

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Apply suggestions from code review

Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Signed-off-by: Marcelo Elizeche Landó <marce@melizeche.com>

* fix linting and wording

* Add instructions for binding

* Remove conf options section, add to sidebar

* Update website/docs/customize/policies/unique_password.md

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

---------

Signed-off-by: Marcelo Elizeche Landó <marce@melizeche.com>
Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Dominic R <dominic@sdko.org>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
2025-04-29 15:55:41 -03:00
f47e8d9d72 docs/website: Update 2025.4 notes (#14272)
Fix styling
2025-04-29 15:55:35 -03:00
3e7d2587c4 website/docs: update 2025.4 release notes (#14251)
* Update release notes for 2025.4

* fix typo

* Add/improve highlights, features and descriptions

* Fix linting and remove API changes

* remove minor changes

* fix linting

* Add helm chart stuff and integrations guide

* fix linting

* Restore SECURITY.md and sidebar.js

* Update website/docs/releases/2025/v2025.4.md

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/docs/releases/2025/v2025.4.md

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/docs/releases/2025/v2025.4.md

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/docs/releases/2025/v2025.4.md

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/docs/releases/2025/v2025.4.md

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/docs/releases/2025/v2025.4.md

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* Update website/docs/releases/2025/v2025.4.md

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* password history - add compliance note

Signed-off-by: Fletcher Heisler <fheisler@users.noreply.github.com>

* Update website/docs/releases/2025/v2025.4.md

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>

* please the linter

* use current version

* add .md

* fix badges

---------

Signed-off-by: Tana M Berry <tanamarieberry@yahoo.com>
Signed-off-by: Fletcher Heisler <fheisler@users.noreply.github.com>
Co-authored-by: Tana M Berry <tanamarieberry@yahoo.com>
Co-authored-by: Fletcher Heisler <fheisler@users.noreply.github.com>
2025-04-29 15:54:55 -03:00
55a38d4a36 rbac: add name to Permissions search (cherry-pick #14269) (#14270)
rbac: add `name` to Permissions search (#14269)

Co-authored-by: Simonyi Gergő <28359278+gergosimonyi@users.noreply.github.com>
2025-04-28 19:04:05 +02:00
6021bb932d web: fix bug that was causing charts to be too tall (cherry-pick #14253) (#14254)
Co-authored-by: Ken Sternberg <133134217+kensternberg-authentik@users.noreply.github.com>
fix bug that was causing charts to be too tall (#14253)
2025-04-28 13:51:49 +02:00
54a5d95717 release: 2025.4.0-rc2 2025-04-25 13:50:44 +02:00
a0a1275452 lifecycle: fix test-all in docker (cherry-pick #14244) (#14246)
Co-authored-by: Marc 'risson' Schmitt <marc.schmitt@risson.space>
fix test-all in docker (#14244)
2025-04-25 13:50:27 +02:00
919aa5df59 core, web: update translations (cherry-pick #14243) (#14245)
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
Co-authored-by: rissson <18313093+rissson@users.noreply.github.com>
2025-04-25 13:39:50 +02:00
cedf7cf683 release: 2025.4.0-rc1 2025-04-25 01:53:53 -03:00
222 changed files with 6846 additions and 10126 deletions

View File

@ -118,15 +118,3 @@ updates:
prefix: "core:" prefix: "core:"
labels: labels:
- dependencies - dependencies
- package-ecosystem: docker-compose
directories:
# - /scripts # Maybe
- /tests/e2e
schedule:
interval: daily
time: "04:00"
open-pull-requests-limit: 10
commit-message:
prefix: "core:"
labels:
- dependencies

View File

@ -70,18 +70,22 @@ jobs:
- name: checkout stable - name: checkout stable
run: | run: |
# Copy current, latest config to local # Copy current, latest config to local
# Temporarly comment the .github backup while migrating to uv
cp authentik/lib/default.yml local.env.yml cp authentik/lib/default.yml local.env.yml
cp -R .github .. # cp -R .github ..
cp -R scripts .. cp -R scripts ..
git checkout $(git tag --sort=version:refname | grep '^version/' | grep -vE -- '-rc[0-9]+$' | tail -n1) git checkout $(git tag --sort=version:refname | grep '^version/' | grep -vE -- '-rc[0-9]+$' | tail -n1)
rm -rf .github/ scripts/ # rm -rf .github/ scripts/
mv ../.github ../scripts . # mv ../.github ../scripts .
rm -rf scripts/
mv ../scripts .
- name: Setup authentik env (stable) - name: Setup authentik env (stable)
uses: ./.github/actions/setup uses: ./.github/actions/setup
with: with:
postgresql_version: ${{ matrix.psql }} postgresql_version: ${{ matrix.psql }}
continue-on-error: true
- name: run migrations to stable - name: run migrations to stable
run: uv run python -m lifecycle.migrate run: poetry run python -m lifecycle.migrate
- name: checkout current code - name: checkout current code
run: | run: |
set -x set -x

View File

@ -16,7 +16,7 @@
], ],
"typescript.preferences.importModuleSpecifier": "non-relative", "typescript.preferences.importModuleSpecifier": "non-relative",
"typescript.preferences.importModuleSpecifierEnding": "index", "typescript.preferences.importModuleSpecifierEnding": "index",
"typescript.tsdk": "./node_modules/typescript/lib", "typescript.tsdk": "./web/node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true, "typescript.enablePromptUseWorkspaceTsdk": true,
"yaml.schemas": { "yaml.schemas": {
"./blueprints/schema.json": "blueprints/**/*.yaml" "./blueprints/schema.json": "blueprints/**/*.yaml"
@ -30,5 +30,7 @@
} }
], ],
"go.testFlags": ["-count=1"], "go.testFlags": ["-count=1"],
"github-actions.workflows.pinned.workflows": [".github/workflows/ci-main.yml"] "github-actions.workflows.pinned.workflows": [
".github/workflows/ci-main.yml"
]
} }

View File

@ -94,7 +94,7 @@ RUN --mount=type=secret,id=GEOIPUPDATE_ACCOUNT_ID \
/bin/sh -c "/usr/bin/entry.sh || echo 'Failed to get GeoIP database, disabling'; exit 0" /bin/sh -c "/usr/bin/entry.sh || echo 'Failed to get GeoIP database, disabling'; exit 0"
# Stage 5: Download uv # Stage 5: Download uv
FROM ghcr.io/astral-sh/uv:0.7.2 AS uv FROM ghcr.io/astral-sh/uv:0.6.16 AS uv
# Stage 6: Base python image # Stage 6: Base python image
FROM ghcr.io/goauthentik/fips-python:3.12.10-slim-bookworm-fips AS python-base FROM ghcr.io/goauthentik/fips-python:3.12.10-slim-bookworm-fips AS python-base

View File

@ -16,7 +16,7 @@ def migrate_custom_css(apps: Apps, schema_editor: BaseDatabaseSchemaEditor):
if not path.exists(): if not path.exists():
return return
css = path.read_text() css = path.read_text()
Brand.objects.using(db_alias).all().update(branding_custom_css=css) Brand.objects.using(db_alias).update(branding_custom_css=css)
class Migration(migrations.Migration): class Migration(migrations.Migration):

File diff suppressed because one or more lines are too long

6
go.mod
View File

@ -21,13 +21,13 @@ require (
github.com/nmcclain/asn1-ber v0.0.0-20170104154839-2661553a0484 github.com/nmcclain/asn1-ber v0.0.0-20170104154839-2661553a0484
github.com/pires/go-proxyproto v0.8.0 github.com/pires/go-proxyproto v0.8.0
github.com/prometheus/client_golang v1.22.0 github.com/prometheus/client_golang v1.22.0
github.com/redis/go-redis/v9 v9.8.0 github.com/redis/go-redis/v9 v9.7.3
github.com/sethvargo/go-envconfig v1.3.0 github.com/sethvargo/go-envconfig v1.2.0
github.com/sirupsen/logrus v1.9.3 github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.9.1 github.com/spf13/cobra v1.9.1
github.com/stretchr/testify v1.10.0 github.com/stretchr/testify v1.10.0
github.com/wwt/guac v1.3.2 github.com/wwt/guac v1.3.2
goauthentik.io/api/v3 v3.2025040.1 goauthentik.io/api/v3 v3.2025024.9
golang.org/x/exp v0.0.0-20230210204819-062eb4c674ab golang.org/x/exp v0.0.0-20230210204819-062eb4c674ab
golang.org/x/oauth2 v0.29.0 golang.org/x/oauth2 v0.29.0
golang.org/x/sync v0.13.0 golang.org/x/sync v0.13.0

12
go.sum
View File

@ -245,14 +245,14 @@ github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ
github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/redis/go-redis/v9 v9.8.0 h1:q3nRvjrlge/6UD7eTu/DSg2uYiU2mCL0G/uzBWqhicI= github.com/redis/go-redis/v9 v9.7.3 h1:YpPyAayJV+XErNsatSElgRZZVCwXX9QzkKYNvO7x0wM=
github.com/redis/go-redis/v9 v9.8.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= github.com/redis/go-redis/v9 v9.7.3/go.mod h1:bGUrSggJ9X9GUmZpZNEOQKaANxSGgOEBRltRTZHSvrA=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sethvargo/go-envconfig v1.3.0 h1:gJs+Fuv8+f05omTpwWIu6KmuseFAXKrIaOZSh8RMt0U= github.com/sethvargo/go-envconfig v1.2.0 h1:q3XkOZWkC+G1sMLCrw9oPGTjYexygLOXDmGUit1ti8Q=
github.com/sethvargo/go-envconfig v1.3.0/go.mod h1:JLd0KFWQYzyENqnEPWWZ49i4vzZo/6nRidxI8YvGiHw= github.com/sethvargo/go-envconfig v1.2.0/go.mod h1:JLd0KFWQYzyENqnEPWWZ49i4vzZo/6nRidxI8YvGiHw=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
@ -290,8 +290,8 @@ go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
goauthentik.io/api/v3 v3.2025040.1 h1:rQEcMNpz84/LPX8LVFteOJuserrd4PnU4k1Iu/wWqhs= goauthentik.io/api/v3 v3.2025024.9 h1:i3tbkyotE32ZpJ729BsPWTuLQUdtZ54Li4aP1amZzsM=
goauthentik.io/api/v3 v3.2025040.1/go.mod h1:zz+mEZg8rY/7eEjkMGWJ2DnGqk+zqxuybGCGrR2O4Kw= goauthentik.io/api/v3 v3.2025024.9/go.mod h1:zz+mEZg8rY/7eEjkMGWJ2DnGqk+zqxuybGCGrR2O4Kw=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=

View File

@ -9,7 +9,7 @@
"version": "0.0.0", "version": "0.0.0",
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"aws-cdk": "^2.1013.0", "aws-cdk": "^2.1012.0",
"cross-env": "^7.0.3" "cross-env": "^7.0.3"
}, },
"engines": { "engines": {
@ -17,9 +17,9 @@
} }
}, },
"node_modules/aws-cdk": { "node_modules/aws-cdk": {
"version": "2.1013.0", "version": "2.1012.0",
"resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1013.0.tgz", "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1012.0.tgz",
"integrity": "sha512-cbq4cOoEIZueMWenGgfI4RujS+AQ9GaMCTlW/3CnvEIhMD8j/tgZx7PTtgMuvwYrRoEeb/wTxgLPgUd5FhsoHA==", "integrity": "sha512-C6jSWkqP0hkY2Cs300VJHjspmTXDTMfB813kwZvRbd/OsKBfTBJBbYU16VoLAp1LVEOnQMf8otSlaSgzVF0X9A==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"bin": { "bin": {

View File

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

Binary file not shown.

View File

@ -12,8 +12,8 @@
# tmassimi, 2024 # tmassimi, 2024
# Marc Schmitt, 2024 # Marc Schmitt, 2024
# albanobattistella <albanobattistella@gmail.com>, 2024 # albanobattistella <albanobattistella@gmail.com>, 2024
# Matteo Piccina <altermatte@gmail.com>, 2025
# Kowalski Dragon (kowalski7cc) <kowalski.7cc@gmail.com>, 2025 # Kowalski Dragon (kowalski7cc) <kowalski.7cc@gmail.com>, 2025
# Matteo Piccina <altermatte@gmail.com>, 2025
# #
#, fuzzy #, fuzzy
msgid "" msgid ""
@ -22,7 +22,7 @@ msgstr ""
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-04-23 09:00+0000\n" "POT-Creation-Date: 2025-04-23 09:00+0000\n"
"PO-Revision-Date: 2022-09-26 16:47+0000\n" "PO-Revision-Date: 2022-09-26 16:47+0000\n"
"Last-Translator: Kowalski Dragon (kowalski7cc) <kowalski.7cc@gmail.com>, 2025\n" "Last-Translator: Matteo Piccina <altermatte@gmail.com>, 2025\n"
"Language-Team: Italian (https://app.transifex.com/authentik/teams/119923/it/)\n" "Language-Team: Italian (https://app.transifex.com/authentik/teams/119923/it/)\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
@ -383,7 +383,7 @@ msgstr "Mappatura delle proprietà"
#: authentik/core/models.py #: authentik/core/models.py
msgid "session data" msgid "session data"
msgstr "dati sessione" msgstr ""
#: authentik/core/models.py #: authentik/core/models.py
msgid "Session" msgid "Session"
@ -509,7 +509,7 @@ msgstr ""
#: authentik/enterprise/policies/unique_password/models.py #: authentik/enterprise/policies/unique_password/models.py
msgid "Number of passwords to check against." msgid "Number of passwords to check against."
msgstr "Numero di password da verificare." msgstr ""
#: authentik/enterprise/policies/unique_password/models.py #: authentik/enterprise/policies/unique_password/models.py
#: authentik/policies/password/models.py #: authentik/policies/password/models.py
@ -519,19 +519,18 @@ msgstr "Password non impostata nel contesto"
#: authentik/enterprise/policies/unique_password/models.py #: authentik/enterprise/policies/unique_password/models.py
msgid "This password has been used previously. Please choose a different one." msgid "This password has been used previously. Please choose a different one."
msgstr "" msgstr ""
"Questa password è già stata utilizzata in precedenza. Scegline una diversa."
#: authentik/enterprise/policies/unique_password/models.py #: authentik/enterprise/policies/unique_password/models.py
msgid "Password Uniqueness Policy" msgid "Password Uniqueness Policy"
msgstr "Politica di unicità della password" msgstr ""
#: authentik/enterprise/policies/unique_password/models.py #: authentik/enterprise/policies/unique_password/models.py
msgid "Password Uniqueness Policies" msgid "Password Uniqueness Policies"
msgstr "Criteri di unicità delle password" msgstr ""
#: authentik/enterprise/policies/unique_password/models.py #: authentik/enterprise/policies/unique_password/models.py
msgid "User Password History" msgid "User Password History"
msgstr "Cronologia password utente" msgstr ""
#: authentik/enterprise/policy.py #: authentik/enterprise/policy.py
msgid "Enterprise required to access this feature." msgid "Enterprise required to access this feature."
@ -2204,7 +2203,7 @@ msgstr "Ruoli"
#: authentik/rbac/models.py #: authentik/rbac/models.py
msgid "Initial Permissions" msgid "Initial Permissions"
msgstr "Permessi Iniziali" msgstr ""
#: authentik/rbac/models.py #: authentik/rbac/models.py
msgid "System permission" msgid "System permission"
@ -2459,9 +2458,6 @@ msgid ""
"attribute. This allows nested group resolution on systems like FreeIPA and " "attribute. This allows nested group resolution on systems like FreeIPA and "
"Active Directory" "Active Directory"
msgstr "" msgstr ""
"Cerca l'appartenenza al gruppo in base a un attributo utente anziché a un "
"attributo di gruppo. Questo consente la risoluzione di gruppi nidificati su "
"sistemi come FreeIPA e Active Directory."
#: authentik/sources/ldap/models.py #: authentik/sources/ldap/models.py
msgid "LDAP Source" msgid "LDAP Source"
@ -2481,19 +2477,19 @@ msgstr "Mappature delle proprietà della sorgente LDAP"
#: authentik/sources/ldap/models.py #: authentik/sources/ldap/models.py
msgid "User LDAP Source Connection" msgid "User LDAP Source Connection"
msgstr "Connessione Sorgente LDAP Utente" msgstr ""
#: authentik/sources/ldap/models.py #: authentik/sources/ldap/models.py
msgid "User LDAP Source Connections" msgid "User LDAP Source Connections"
msgstr "Connessioni Sorgente LDAP Utente" msgstr ""
#: authentik/sources/ldap/models.py #: authentik/sources/ldap/models.py
msgid "Group LDAP Source Connection" msgid "Group LDAP Source Connection"
msgstr "Connessione Sorgente LDAP Gruppo" msgstr ""
#: authentik/sources/ldap/models.py #: authentik/sources/ldap/models.py
msgid "Group LDAP Source Connections" msgid "Group LDAP Source Connections"
msgstr "Connessioni Sorgente LDAP Gruppo" msgstr ""
#: authentik/sources/ldap/signals.py #: authentik/sources/ldap/signals.py
msgid "Password does not match Active Directory Complexity." msgid "Password does not match Active Directory Complexity."
@ -2505,11 +2501,11 @@ msgstr "Nessun token ricevuto."
#: authentik/sources/oauth/models.py #: authentik/sources/oauth/models.py
msgid "HTTP Basic Authentication" msgid "HTTP Basic Authentication"
msgstr "HTTP Basic Authentication" msgstr ""
#: authentik/sources/oauth/models.py #: authentik/sources/oauth/models.py
msgid "Include the client ID and secret as request parameters" msgid "Include the client ID and secret as request parameters"
msgstr "Includi il client ID e il segreto come parametri di richiesta" msgstr ""
#: authentik/sources/oauth/models.py #: authentik/sources/oauth/models.py
msgid "Request Token URL" msgid "Request Token URL"
@ -2556,8 +2552,6 @@ msgid ""
"How to perform authentication during an authorization_code token request " "How to perform authentication during an authorization_code token request "
"flow" "flow"
msgstr "" msgstr ""
"Come eseguire l'autenticazione durante un flusso di richiesta del token "
"authorization_code"
#: authentik/sources/oauth/models.py #: authentik/sources/oauth/models.py
msgid "OAuth Source" msgid "OAuth Source"
@ -3490,9 +3484,6 @@ msgid ""
"Show the user the 'Remember me on this device' toggle, allowing repeat users" "Show the user the 'Remember me on this device' toggle, allowing repeat users"
" to skip straight to entering their password." " to skip straight to entering their password."
msgstr "" msgstr ""
"Mostra all'utente il pulsante \"Ricordami su questo dispositivo\", "
"consentendo agli utenti abituali di passare direttamente all'inserimento "
"della password."
#: authentik/stages/identification/models.py #: authentik/stages/identification/models.py
msgid "Optional enrollment flow, which is linked at the bottom of the page." msgid "Optional enrollment flow, which is linked at the bottom of the page."
@ -3882,11 +3873,11 @@ msgstr ""
#: authentik/tenants/models.py #: authentik/tenants/models.py
msgid "Reputation cannot decrease lower than this value. Zero or negative." msgid "Reputation cannot decrease lower than this value. Zero or negative."
msgstr "La reputazione non può scendere sotto questo valore. Zero o negativo." msgstr ""
#: authentik/tenants/models.py #: authentik/tenants/models.py
msgid "Reputation cannot increase higher than this value. Zero or positive." msgid "Reputation cannot increase higher than this value. Zero or positive."
msgstr "La reputazione non può superare questo valore. Zero o positivo." msgstr ""
#: authentik/tenants/models.py #: authentik/tenants/models.py
msgid "The option configures the footer links on the flow executor pages." msgid "The option configures the footer links on the flow executor pages."

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

538
package-lock.json generated
View File

@ -1,546 +1,12 @@
{ {
"name": "@goauthentik/authentik", "name": "@goauthentik/authentik",
"version": "2025.4.0", "version": "2025.2.1",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@goauthentik/authentik", "name": "@goauthentik/authentik",
"version": "2025.4.0", "version": "2025.2.1"
"devDependencies": {
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
"prettier": "^3.3.3",
"prettier-plugin-organize-imports": "^4.1.0",
"prettier-plugin-packagejson": "^2.5.10",
"typescript": "^5.6.2"
}
},
"node_modules/@babel/code-frame": {
"version": "7.26.2",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz",
"integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/helper-validator-identifier": "^7.25.9",
"js-tokens": "^4.0.0",
"picocolors": "^1.0.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/generator": {
"version": "7.27.0",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz",
"integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/parser": "^7.27.0",
"@babel/types": "^7.27.0",
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.25",
"jsesc": "^3.0.2"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-string-parser": {
"version": "7.25.9",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz",
"integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-validator-identifier": {
"version": "7.25.9",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz",
"integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/parser": {
"version": "7.27.0",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz",
"integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/types": "^7.27.0"
},
"bin": {
"parser": "bin/babel-parser.js"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@babel/template": {
"version": "7.27.0",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz",
"integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.26.2",
"@babel/parser": "^7.27.0",
"@babel/types": "^7.27.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/traverse": {
"version": "7.27.0",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz",
"integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.26.2",
"@babel/generator": "^7.27.0",
"@babel/parser": "^7.27.0",
"@babel/template": "^7.27.0",
"@babel/types": "^7.27.0",
"debug": "^4.3.1",
"globals": "^11.1.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/types": {
"version": "7.27.0",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz",
"integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/helper-string-parser": "^7.25.9",
"@babel/helper-validator-identifier": "^7.25.9"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@jridgewell/gen-mapping": {
"version": "0.3.8",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz",
"integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/set-array": "^1.2.1",
"@jridgewell/sourcemap-codec": "^1.4.10",
"@jridgewell/trace-mapping": "^0.3.24"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/resolve-uri": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/set-array": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
"integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
"integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
"dev": true,
"license": "MIT"
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.25",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
"integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
"node_modules/@pkgr/core": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.2.tgz",
"integrity": "sha512-fdDH1LSGfZdTH2sxdpVMw31BanV28K/Gry0cVFxaNP77neJSkd82mM8ErPNYs9e+0O7SdHBLTDzDgwUuy18RnQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": "^12.20.0 || ^14.18.0 || >=16.0.0"
},
"funding": {
"url": "https://opencollective.com/unts"
}
},
"node_modules/@trivago/prettier-plugin-sort-imports": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-5.2.2.tgz",
"integrity": "sha512-fYDQA9e6yTNmA13TLVSA+WMQRc5Bn/c0EUBditUHNfMMxN7M82c38b1kEggVE3pLpZ0FwkwJkUEKMiOi52JXFA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"@babel/generator": "^7.26.5",
"@babel/parser": "^7.26.7",
"@babel/traverse": "^7.26.7",
"@babel/types": "^7.26.7",
"javascript-natural-sort": "^0.7.1",
"lodash": "^4.17.21"
},
"engines": {
"node": ">18.12"
},
"peerDependencies": {
"@vue/compiler-sfc": "3.x",
"prettier": "2.x - 3.x",
"prettier-plugin-svelte": "3.x",
"svelte": "4.x || 5.x"
},
"peerDependenciesMeta": {
"@vue/compiler-sfc": {
"optional": true
},
"prettier-plugin-svelte": {
"optional": true
},
"svelte": {
"optional": true
}
}
},
"node_modules/debug": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz",
"integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==",
"dev": true,
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/detect-indent": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-7.0.1.tgz",
"integrity": "sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=12.20"
}
},
"node_modules/detect-newline": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-4.0.1.tgz",
"integrity": "sha512-qE3Veg1YXzGHQhlA6jzebZN2qVf6NX+A7m7qlhCGG30dJixrAQhYOsJjsnBjJkCSmuOPpCk30145fr8FV0bzog==",
"dev": true,
"license": "MIT",
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/fdir": {
"version": "6.4.4",
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz",
"integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==",
"dev": true,
"license": "MIT",
"peerDependencies": {
"picomatch": "^3 || ^4"
},
"peerDependenciesMeta": {
"picomatch": {
"optional": true
}
}
},
"node_modules/get-stdin": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz",
"integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/git-hooks-list": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-3.2.0.tgz",
"integrity": "sha512-ZHG9a1gEhUMX1TvGrLdyWb9kDopCBbTnI8z4JgRMYxsijWipgjSEYoPWqBuIB0DnRnvqlQSEeVmzpeuPm7NdFQ==",
"dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/fisker/git-hooks-list?sponsor=1"
}
},
"node_modules/globals": {
"version": "11.12.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
"integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=4"
}
},
"node_modules/is-plain-obj": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz",
"integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/javascript-natural-sort": {
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz",
"integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==",
"dev": true,
"license": "MIT"
},
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
"dev": true,
"license": "MIT"
},
"node_modules/jsesc": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
"integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
"dev": true,
"license": "MIT",
"bin": {
"jsesc": "bin/jsesc"
},
"engines": {
"node": ">=6"
}
},
"node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true,
"license": "MIT"
},
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"dev": true,
"license": "MIT"
},
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
"dev": true,
"license": "ISC"
},
"node_modules/picomatch": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz",
"integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/prettier": {
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz",
"integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==",
"dev": true,
"license": "MIT",
"bin": {
"prettier": "bin/prettier.cjs"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/prettier-plugin-organize-imports": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-4.1.0.tgz",
"integrity": "sha512-5aWRdCgv645xaa58X8lOxzZoiHAldAPChljr/MT0crXVOWTZ+Svl4hIWlz+niYSlO6ikE5UXkN1JrRvIP2ut0A==",
"dev": true,
"license": "MIT",
"peerDependencies": {
"prettier": ">=2.0",
"typescript": ">=2.9",
"vue-tsc": "^2.1.0"
},
"peerDependenciesMeta": {
"vue-tsc": {
"optional": true
}
}
},
"node_modules/prettier-plugin-packagejson": {
"version": "2.5.10",
"resolved": "https://registry.npmjs.org/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.5.10.tgz",
"integrity": "sha512-LUxATI5YsImIVSaaLJlJ3aE6wTD+nvots18U3GuQMJpUyClChaZlQrqx3dBnbhF20OnKWZyx8EgyZypQtBDtgQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"sort-package-json": "2.15.1",
"synckit": "0.9.2"
},
"peerDependencies": {
"prettier": ">= 1.16.0"
},
"peerDependenciesMeta": {
"prettier": {
"optional": true
}
}
},
"node_modules/semver": {
"version": "7.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
"integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
"dev": true,
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/sort-object-keys": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/sort-object-keys/-/sort-object-keys-1.1.3.tgz",
"integrity": "sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==",
"dev": true,
"license": "MIT"
},
"node_modules/sort-package-json": {
"version": "2.15.1",
"resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-2.15.1.tgz",
"integrity": "sha512-9x9+o8krTT2saA9liI4BljNjwAbvUnWf11Wq+i/iZt8nl2UGYnf3TH5uBydE7VALmP7AGwlfszuEeL8BDyb0YA==",
"dev": true,
"license": "MIT",
"dependencies": {
"detect-indent": "^7.0.1",
"detect-newline": "^4.0.0",
"get-stdin": "^9.0.0",
"git-hooks-list": "^3.0.0",
"is-plain-obj": "^4.1.0",
"semver": "^7.6.0",
"sort-object-keys": "^1.1.3",
"tinyglobby": "^0.2.9"
},
"bin": {
"sort-package-json": "cli.js"
}
},
"node_modules/synckit": {
"version": "0.9.2",
"resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz",
"integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@pkgr/core": "^0.1.0",
"tslib": "^2.6.2"
},
"engines": {
"node": "^14.18.0 || >=16.0.0"
},
"funding": {
"url": "https://opencollective.com/unts"
}
},
"node_modules/tinyglobby": {
"version": "0.2.13",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz",
"integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==",
"dev": true,
"license": "MIT",
"dependencies": {
"fdir": "^6.4.4",
"picomatch": "^4.0.2"
},
"engines": {
"node": ">=12.0.0"
},
"funding": {
"url": "https://github.com/sponsors/SuperchupuDev"
}
},
"node_modules/tslib": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
"dev": true,
"license": "0BSD"
},
"node_modules/typescript": {
"version": "5.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"dev": true,
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=14.17"
}
} }
} }
} }

View File

@ -1,15 +1,5 @@
{ {
"name": "@goauthentik/authentik", "name": "@goauthentik/authentik",
"version": "2025.4.0", "version": "2025.4.0",
"private": true, "private": true
"type": "module",
"devDependencies": {
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
"prettier": "^3.3.3",
"prettier-plugin-organize-imports": "^4.1.0",
"prettier-plugin-packagejson": "^2.5.10",
"typescript": "^5.6.2"
},
"workspaces": [],
"prettier": "./packages/prettier-config/index.js"
} }

View File

@ -1,12 +1,12 @@
{ {
"name": "@goauthentik/docusaurus-config", "name": "@goauthentik/docusaurus-config",
"version": "1.0.6", "version": "1.0.5",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@goauthentik/docusaurus-config", "name": "@goauthentik/docusaurus-config",
"version": "1.0.6", "version": "1.0.5",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"deepmerge-ts": "^7.1.5", "deepmerge-ts": "^7.1.5",

View File

@ -1,6 +1,6 @@
{ {
"name": "@goauthentik/docusaurus-config", "name": "@goauthentik/docusaurus-config",
"version": "1.0.6", "version": "1.0.5",
"description": "authentik's Docusaurus config", "description": "authentik's Docusaurus config",
"license": "MIT", "license": "MIT",
"scripts": { "scripts": {

View File

@ -2,3 +2,4 @@
This package contains utility scripts common to all TypeScript and JavaScript packages in the This package contains utility scripts common to all TypeScript and JavaScript packages in the
`@goauthentik` monorepo. `@goauthentik` monorepo.

View File

@ -1,9 +1,8 @@
/** /**
* @file Constants for JavaScript and TypeScript files. * @file Constants for JavaScript and TypeScript files.
*
*/ */
/// <reference types="../../types/global.js" />
/** /**
* The current Node.js environment, defaulting to "development" when not set. * The current Node.js environment, defaulting to "development" when not set.
* *
@ -13,4 +12,6 @@
* ensure that module tree-shaking works correctly. * ensure that module tree-shaking works correctly.
* *
*/ */
export const NodeEnvironment = process.env.NODE_ENV || "development"; export const NodeEnvironment = /** @type {'development' | 'production'} */ (
process.env.NODE_ENV || "development"
);

View File

@ -1,7 +1,4 @@
/// <reference types="./types/global.js" />
export * from "./paths.js"; export * from "./paths.js";
export * from "./constants.js"; export * from "./constants.js";
export * from "./build.js";
export * from "./version.js"; export * from "./version.js";
export * from "./scripting.js"; export * from "./scripting.js";

View File

@ -0,0 +1,19 @@
{
"name": "@goauthentik/monorepo",
"version": "1.0.0",
"description": "Utilities for the authentik monorepo.",
"private": true,
"license": "MIT",
"type": "module",
"exports": {
"./package.json": "./package.json",
".": {
"import": "./index.js",
"types": "./out/index.d.ts"
}
},
"types": "./out/index.d.ts",
"engines": {
"node": ">=20.11"
}
}

View File

@ -0,0 +1,30 @@
import { createRequire } from "node:module";
import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
const __dirname = dirname(fileURLToPath(import.meta.url));
/**
* @typedef {'~authentik'} MonoRepoRoot
*/
/**
* The root of the authentik monorepo.
*/
export const MonoRepoRoot = /** @type {MonoRepoRoot} */ (resolve(__dirname, "..", ".."));
const require = createRequire(import.meta.url);
/**
* Resolve a package name to its location in the monorepo to the single node_modules directory.
* @param {string} packageName
* @returns {string} The resolved path to the package.
* @throws {Error} If the package cannot be resolved.
*/
export function resolvePackage(packageName) {
const packageJSONPath = require.resolve(join(packageName, "package.json"), {
paths: [MonoRepoRoot],
});
return dirname(packageJSONPath);
}

View File

View File

@ -1,6 +1,6 @@
import { execSync } from "node:child_process"; import { execSync } from "node:child_process";
import PackageJSON from "../../../package.json" with { type: "json" }; import PackageJSON from "../../package.json" with { type: "json" };
import { MonoRepoRoot } from "./paths.js"; import { MonoRepoRoot } from "./paths.js";
/** /**

View File

@ -1,28 +0,0 @@
// TypeScript Project Configuration
{
"extends": "./packages/tsconfig/tsconfig.json",
"compilerOptions": {
"baseUrl": "."
},
"watchOptions": {
"excludeDirectories": [
"**/.git", // Git
"**/.yarn", // Yarn
"**/.vscode", // VS Code
"**/.vscode-test-web", // VS Code Web Test
"**/dist", // Distributed build files
"**/out", // Output build files
"**/.drafts", // Drafts
"**/.github", // GitHub
"**/node_modules" // Node modules
]
},
// The root project has no sources of its own. By setting `files` to an empty
// list, TS won't automatically include all sources below root (the default).
"files": [],
"references": [
// Note that references are in the order we want them to be built.
// TODO: Left blank until TypeScript workspaces are complete.
]
}

154
uv.lock generated
View File

@ -13,7 +13,7 @@ wheels = [
[[package]] [[package]]
name = "aiohttp" name = "aiohttp"
version = "3.11.18" version = "3.11.16"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "aiohappyeyeballs" }, { name = "aiohappyeyeballs" },
@ -24,24 +24,24 @@ dependencies = [
{ name = "propcache" }, { name = "propcache" },
{ name = "yarl" }, { name = "yarl" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/63/e7/fa1a8c00e2c54b05dc8cb5d1439f627f7c267874e3f7bb047146116020f9/aiohttp-3.11.18.tar.gz", hash = "sha256:ae856e1138612b7e412db63b7708735cff4d38d0399f6a5435d3dac2669f558a", size = 7678653 } sdist = { url = "https://files.pythonhosted.org/packages/f1/d9/1c4721d143e14af753f2bf5e3b681883e1f24b592c0482df6fa6e33597fa/aiohttp-3.11.16.tar.gz", hash = "sha256:16f8a2c9538c14a557b4d309ed4d0a7c60f0253e8ed7b6c9a2859a7582f8b1b8", size = 7676826 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/b5/d2/5bc436f42bf4745c55f33e1e6a2d69e77075d3e768e3d1a34f96ee5298aa/aiohttp-3.11.18-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:63d71eceb9cad35d47d71f78edac41fcd01ff10cacaa64e473d1aec13fa02df2", size = 706671 }, { url = "https://files.pythonhosted.org/packages/db/38/100d01cbc60553743baf0fba658cb125f8ad674a8a771f765cdc155a890d/aiohttp-3.11.16-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:911a6e91d08bb2c72938bc17f0a2d97864c531536b7832abee6429d5296e5b27", size = 704881 },
{ url = "https://files.pythonhosted.org/packages/fe/d0/2dbabecc4e078c0474abb40536bbde717fb2e39962f41c5fc7a216b18ea7/aiohttp-3.11.18-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d1929da615840969929e8878d7951b31afe0bac883d84418f92e5755d7b49508", size = 466169 }, { url = "https://files.pythonhosted.org/packages/21/ed/b4102bb6245e36591209e29f03fe87e7956e54cb604ee12e20f7eb47f994/aiohttp-3.11.16-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6ac13b71761e49d5f9e4d05d33683bbafef753e876e8e5a7ef26e937dd766713", size = 464564 },
{ url = "https://files.pythonhosted.org/packages/70/84/19edcf0b22933932faa6e0be0d933a27bd173da02dc125b7354dff4d8da4/aiohttp-3.11.18-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7d0aebeb2392f19b184e3fdd9e651b0e39cd0f195cdb93328bd124a1d455cd0e", size = 457554 }, { url = "https://files.pythonhosted.org/packages/3b/e1/a9ab6c47b62ecee080eeb33acd5352b40ecad08fb2d0779bcc6739271745/aiohttp-3.11.16-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fd36c119c5d6551bce374fcb5c19269638f8d09862445f85a5a48596fd59f4bb", size = 456548 },
{ url = "https://files.pythonhosted.org/packages/32/d0/e8d1f034ae5624a0f21e4fb3feff79342ce631f3a4d26bd3e58b31ef033b/aiohttp-3.11.18-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3849ead845e8444f7331c284132ab314b4dac43bfae1e3cf350906d4fff4620f", size = 1690154 }, { url = "https://files.pythonhosted.org/packages/80/ad/216c6f71bdff2becce6c8776f0aa32cb0fa5d83008d13b49c3208d2e4016/aiohttp-3.11.16-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d489d9778522fbd0f8d6a5c6e48e3514f11be81cb0a5954bdda06f7e1594b321", size = 1691749 },
{ url = "https://files.pythonhosted.org/packages/16/de/2f9dbe2ac6f38f8495562077131888e0d2897e3798a0ff3adda766b04a34/aiohttp-3.11.18-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5e8452ad6b2863709f8b3d615955aa0807bc093c34b8e25b3b52097fe421cb7f", size = 1733402 }, { url = "https://files.pythonhosted.org/packages/bd/ea/7df7bcd3f4e734301605f686ffc87993f2d51b7acb6bcc9b980af223f297/aiohttp-3.11.16-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:69a2cbd61788d26f8f1e626e188044834f37f6ae3f937bd9f08b65fc9d7e514e", size = 1736874 },
{ url = "https://files.pythonhosted.org/packages/e0/04/bd2870e1e9aef990d14b6df2a695f17807baf5c85a4c187a492bda569571/aiohttp-3.11.18-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3b8d2b42073611c860a37f718b3d61ae8b4c2b124b2e776e2c10619d920350ec", size = 1783958 }, { url = "https://files.pythonhosted.org/packages/51/41/c7724b9c87a29b7cfd1202ec6446bae8524a751473d25e2ff438bc9a02bf/aiohttp-3.11.16-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd464ba806e27ee24a91362ba3621bfc39dbbb8b79f2e1340201615197370f7c", size = 1786885 },
{ url = "https://files.pythonhosted.org/packages/23/06/4203ffa2beb5bedb07f0da0f79b7d9039d1c33f522e0d1a2d5b6218e6f2e/aiohttp-3.11.18-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40fbf91f6a0ac317c0a07eb328a1384941872f6761f2e6f7208b63c4cc0a7ff6", size = 1695288 }, { url = "https://files.pythonhosted.org/packages/86/b3/f61f8492fa6569fa87927ad35a40c159408862f7e8e70deaaead349e2fba/aiohttp-3.11.16-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ce63ae04719513dd2651202352a2beb9f67f55cb8490c40f056cea3c5c355ce", size = 1698059 },
{ url = "https://files.pythonhosted.org/packages/30/b2/e2285dda065d9f29ab4b23d8bcc81eb881db512afb38a3f5247b191be36c/aiohttp-3.11.18-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:44ff5625413fec55216da5eaa011cf6b0a2ed67a565914a212a51aa3755b0009", size = 1618871 }, { url = "https://files.pythonhosted.org/packages/ce/be/7097cf860a9ce8bbb0e8960704e12869e111abcd3fbd245153373079ccec/aiohttp-3.11.16-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09b00dd520d88eac9d1768439a59ab3d145065c91a8fab97f900d1b5f802895e", size = 1626527 },
{ url = "https://files.pythonhosted.org/packages/57/e0/88f2987885d4b646de2036f7296ebea9268fdbf27476da551c1a7c158bc0/aiohttp-3.11.18-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7f33a92a2fde08e8c6b0c61815521324fc1612f397abf96eed86b8e31618fdb4", size = 1646262 }, { url = "https://files.pythonhosted.org/packages/1d/1d/aaa841c340e8c143a8d53a1f644c2a2961c58cfa26e7b398d6bf75cf5d23/aiohttp-3.11.16-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7f6428fee52d2bcf96a8aa7b62095b190ee341ab0e6b1bcf50c615d7966fd45b", size = 1644036 },
{ url = "https://files.pythonhosted.org/packages/e0/19/4d2da508b4c587e7472a032290b2981f7caeca82b4354e19ab3df2f51d56/aiohttp-3.11.18-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:11d5391946605f445ddafda5eab11caf310f90cdda1fd99865564e3164f5cff9", size = 1677431 }, { url = "https://files.pythonhosted.org/packages/2c/88/59d870f76e9345e2b149f158074e78db457985c2b4da713038d9da3020a8/aiohttp-3.11.16-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:13ceac2c5cdcc3f64b9015710221ddf81c900c5febc505dbd8f810e770011540", size = 1685270 },
{ url = "https://files.pythonhosted.org/packages/eb/ae/047473ea50150a41440f3265f53db1738870b5a1e5406ece561ca61a3bf4/aiohttp-3.11.18-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3cc314245deb311364884e44242e00c18b5896e4fe6d5f942e7ad7e4cb640adb", size = 1637430 }, { url = "https://files.pythonhosted.org/packages/2b/b1/c6686948d4c79c3745595efc469a9f8a43cab3c7efc0b5991be65d9e8cb8/aiohttp-3.11.16-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:fadbb8f1d4140825069db3fedbbb843290fd5f5bc0a5dbd7eaf81d91bf1b003b", size = 1650852 },
{ url = "https://files.pythonhosted.org/packages/11/32/c6d1e3748077ce7ee13745fae33e5cb1dac3e3b8f8787bf738a93c94a7d2/aiohttp-3.11.18-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:0f421843b0f70740772228b9e8093289924359d306530bcd3926f39acbe1adda", size = 1703342 }, { url = "https://files.pythonhosted.org/packages/fe/94/3e42a6916fd3441721941e0f1b8438e1ce2a4c49af0e28e0d3c950c9b3c9/aiohttp-3.11.16-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:6a792ce34b999fbe04a7a71a90c74f10c57ae4c51f65461a411faa70e154154e", size = 1704481 },
{ url = "https://files.pythonhosted.org/packages/c5/1d/a3b57bfdbe285f0d45572d6d8f534fd58761da3e9cbc3098372565005606/aiohttp-3.11.18-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:e220e7562467dc8d589e31c1acd13438d82c03d7f385c9cd41a3f6d1d15807c1", size = 1740600 }, { url = "https://files.pythonhosted.org/packages/b1/6d/6ab5854ff59b27075c7a8c610597d2b6c38945f9a1284ee8758bc3720ff6/aiohttp-3.11.16-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:f4065145bf69de124accdd17ea5f4dc770da0a6a6e440c53f6e0a8c27b3e635c", size = 1735370 },
{ url = "https://files.pythonhosted.org/packages/a5/71/f9cd2fed33fa2b7ce4d412fb7876547abb821d5b5520787d159d0748321d/aiohttp-3.11.18-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ab2ef72f8605046115bc9aa8e9d14fd49086d405855f40b79ed9e5c1f9f4faea", size = 1695131 }, { url = "https://files.pythonhosted.org/packages/73/2a/08a68eec3c99a6659067d271d7553e4d490a0828d588e1daa3970dc2b771/aiohttp-3.11.16-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fa73e8c2656a3653ae6c307b3f4e878a21f87859a9afab228280ddccd7369d71", size = 1697619 },
{ url = "https://files.pythonhosted.org/packages/97/97/d1248cd6d02b9de6aa514793d0dcb20099f0ec47ae71a933290116c070c5/aiohttp-3.11.18-cp312-cp312-win32.whl", hash = "sha256:12a62691eb5aac58d65200c7ae94d73e8a65c331c3a86a2e9670927e94339ee8", size = 412442 }, { url = "https://files.pythonhosted.org/packages/61/d5/fea8dbbfb0cd68fbb56f0ae913270a79422d9a41da442a624febf72d2aaf/aiohttp-3.11.16-cp312-cp312-win32.whl", hash = "sha256:f244b8e541f414664889e2c87cac11a07b918cb4b540c36f7ada7bfa76571ea2", size = 411710 },
{ url = "https://files.pythonhosted.org/packages/33/9a/e34e65506e06427b111e19218a99abf627638a9703f4b8bcc3e3021277ed/aiohttp-3.11.18-cp312-cp312-win_amd64.whl", hash = "sha256:364329f319c499128fd5cd2d1c31c44f234c58f9b96cc57f743d16ec4f3238c8", size = 439444 }, { url = "https://files.pythonhosted.org/packages/33/fb/41cde15fbe51365024550bf77b95a4fc84ef41365705c946da0421f0e1e0/aiohttp-3.11.16-cp312-cp312-win_amd64.whl", hash = "sha256:23a15727fbfccab973343b6d1b7181bfb0b4aa7ae280f36fd2f90f5476805682", size = 438012 },
] ]
[[package]] [[package]]
@ -558,30 +558,30 @@ wheels = [
[[package]] [[package]]
name = "boto3" name = "boto3"
version = "1.37.38" version = "1.37.35"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "botocore" }, { name = "botocore" },
{ name = "jmespath" }, { name = "jmespath" },
{ name = "s3transfer" }, { name = "s3transfer" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/0d/b5/d1c2e8c484cea43891629bbab6ca90ce9ca932586750bc0e786c8f096ccf/boto3-1.37.38.tar.gz", hash = "sha256:88c02910933ab7777597d1ca7c62375f52822e0aa1a8e0c51b2598a547af42b2", size = 111623 } sdist = { url = "https://files.pythonhosted.org/packages/48/5f/e356ecd2f236e6ddc7711eaf3f075c15b13e2d044cfdb47719d49c4ae7dd/boto3-1.37.35.tar.gz", hash = "sha256:751ed599c8fd9ca24896edcd6620e8a32b3db1b68efea3a90126312240e668a2", size = 111640 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/d3/87/8189f22ee798177bc7b40afd13f046442c5f91b699e70a950b42ff447e80/boto3-1.37.38-py3-none-any.whl", hash = "sha256:b6d42803607148804dff82389757827a24ce9271f0583748853934c86310999f", size = 139922 }, { url = "https://files.pythonhosted.org/packages/f6/e4/00958f65ac74ab0a76af33f16c8fdf5726a5c6f0d3c0d0c058ff0dd00fd7/boto3-1.37.35-py3-none-any.whl", hash = "sha256:5a90d674830adbaf86456d6b27a18f5f11378277da5286511fa860d2e7b14261", size = 139922 },
] ]
[[package]] [[package]]
name = "botocore" name = "botocore"
version = "1.37.38" version = "1.37.35"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "jmespath" }, { name = "jmespath" },
{ name = "python-dateutil" }, { name = "python-dateutil" },
{ name = "urllib3" }, { name = "urllib3" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/34/79/4e072e614339727f79afef704e5993b5b4d2667c1671c757cc4deb954744/botocore-1.37.38.tar.gz", hash = "sha256:c3ea386177171f2259b284db6afc971c959ec103fa2115911c4368bea7cbbc5d", size = 13832365 } sdist = { url = "https://files.pythonhosted.org/packages/64/0b/d281d74d53f7d4733402aed7a536275084fa344a2672f7ea4dbc8ebe1f1b/botocore-1.37.35.tar.gz", hash = "sha256:197a9bf8251c45b9d882c405ec0d0ab40c10e2d2a55ee66960185daec4beb6ec", size = 13821053 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/55/1b/93f3504afc7c523dcaa8a8147cfc75421983e30b08d9f93a533929589630/botocore-1.37.38-py3-none-any.whl", hash = "sha256:23b4097780e156a4dcaadfc1ed156ce25cb95b6087d010c4bb7f7f5d9bc9d219", size = 13499391 }, { url = "https://files.pythonhosted.org/packages/22/00/bf9c894f5af8e35b06ecf757d4a95883408e71c48642dc7f8760580584fd/botocore-1.37.35-py3-none-any.whl", hash = "sha256:50839212e90650d0b0fa6b8f7514876bf802f6164f2775f3abcd4d53c98bb73c", size = 13485892 },
] ]
[[package]] [[package]]
@ -1279,28 +1279,26 @@ wheels = [
[[package]] [[package]]
name = "frozenlist" name = "frozenlist"
version = "1.6.0" version = "1.5.0"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/ee/f4/d744cba2da59b5c1d88823cf9e8a6c74e4659e2b27604ed973be2a0bf5ab/frozenlist-1.6.0.tar.gz", hash = "sha256:b99655c32c1c8e06d111e7f41c06c29a5318cb1835df23a45518e02a47c63b68", size = 42831 } sdist = { url = "https://files.pythonhosted.org/packages/8f/ed/0f4cec13a93c02c47ec32d81d11c0c1efbadf4a471e3f3ce7cad366cbbd3/frozenlist-1.5.0.tar.gz", hash = "sha256:81d5af29e61b9c8348e876d442253723928dce6433e0e76cd925cd83f1b4b817", size = 39930 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/9c/8a/289b7d0de2fbac832ea80944d809759976f661557a38bb8e77db5d9f79b7/frozenlist-1.6.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:c5b9e42ace7d95bf41e19b87cec8f262c41d3510d8ad7514ab3862ea2197bfb1", size = 160193 }, { url = "https://files.pythonhosted.org/packages/79/73/fa6d1a96ab7fd6e6d1c3500700963eab46813847f01ef0ccbaa726181dd5/frozenlist-1.5.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:31115ba75889723431aa9a4e77d5f398f5cf976eea3bdf61749731f62d4a4a21", size = 94026 },
{ url = "https://files.pythonhosted.org/packages/19/80/2fd17d322aec7f430549f0669f599997174f93ee17929ea5b92781ec902c/frozenlist-1.6.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ca9973735ce9f770d24d5484dcb42f68f135351c2fc81a7a9369e48cf2998a29", size = 123831 }, { url = "https://files.pythonhosted.org/packages/ab/04/ea8bf62c8868b8eada363f20ff1b647cf2e93377a7b284d36062d21d81d1/frozenlist-1.5.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7437601c4d89d070eac8323f121fcf25f88674627505334654fd027b091db09d", size = 54150 },
{ url = "https://files.pythonhosted.org/packages/99/06/f5812da431273f78c6543e0b2f7de67dfd65eb0a433978b2c9c63d2205e4/frozenlist-1.6.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6ac40ec76041c67b928ca8aaffba15c2b2ee3f5ae8d0cb0617b5e63ec119ca25", size = 121862 }, { url = "https://files.pythonhosted.org/packages/d0/9a/8e479b482a6f2070b26bda572c5e6889bb3ba48977e81beea35b5ae13ece/frozenlist-1.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7948140d9f8ece1745be806f2bfdf390127cf1a763b925c4a805c603df5e697e", size = 51927 },
{ url = "https://files.pythonhosted.org/packages/d0/31/9e61c6b5fc493cf24d54881731204d27105234d09878be1a5983182cc4a5/frozenlist-1.6.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:95b7a8a3180dfb280eb044fdec562f9b461614c0ef21669aea6f1d3dac6ee576", size = 316361 }, { url = "https://files.pythonhosted.org/packages/e3/12/2aad87deb08a4e7ccfb33600871bbe8f0e08cb6d8224371387f3303654d7/frozenlist-1.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:feeb64bc9bcc6b45c6311c9e9b99406660a9c05ca8a5b30d14a78555088b0b3a", size = 282647 },
{ url = "https://files.pythonhosted.org/packages/9d/55/22ca9362d4f0222324981470fd50192be200154d51509ee6eb9baa148e96/frozenlist-1.6.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:c444d824e22da6c9291886d80c7d00c444981a72686e2b59d38b285617cb52c8", size = 307115 }, { url = "https://files.pythonhosted.org/packages/77/f2/07f06b05d8a427ea0060a9cef6e63405ea9e0d761846b95ef3fb3be57111/frozenlist-1.5.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:683173d371daad49cffb8309779e886e59c2f369430ad28fe715f66d08d4ab1a", size = 289052 },
{ url = "https://files.pythonhosted.org/packages/ae/39/4fff42920a57794881e7bb3898dc7f5f539261711ea411b43bba3cde8b79/frozenlist-1.6.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bb52c8166499a8150bfd38478248572c924c003cbb45fe3bcd348e5ac7c000f9", size = 322505 }, { url = "https://files.pythonhosted.org/packages/bd/9f/8bf45a2f1cd4aa401acd271b077989c9267ae8463e7c8b1eb0d3f561b65e/frozenlist-1.5.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7d57d8f702221405a9d9b40f9da8ac2e4a1a8b5285aac6100f3393675f0a85ee", size = 291719 },
{ url = "https://files.pythonhosted.org/packages/55/f2/88c41f374c1e4cf0092a5459e5f3d6a1e17ed274c98087a76487783df90c/frozenlist-1.6.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b35298b2db9c2468106278537ee529719228950a5fdda686582f68f247d1dc6e", size = 322666 }, { url = "https://files.pythonhosted.org/packages/41/d1/1f20fd05a6c42d3868709b7604c9f15538a29e4f734c694c6bcfc3d3b935/frozenlist-1.5.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:30c72000fbcc35b129cb09956836c7d7abf78ab5416595e4857d1cae8d6251a6", size = 267433 },
{ url = "https://files.pythonhosted.org/packages/75/51/034eeb75afdf3fd03997856195b500722c0b1a50716664cde64e28299c4b/frozenlist-1.6.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d108e2d070034f9d57210f22fefd22ea0d04609fc97c5f7f5a686b3471028590", size = 302119 }, { url = "https://files.pythonhosted.org/packages/af/f2/64b73a9bb86f5a89fb55450e97cd5c1f84a862d4ff90d9fd1a73ab0f64a5/frozenlist-1.5.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:000a77d6034fbad9b6bb880f7ec073027908f1b40254b5d6f26210d2dab1240e", size = 283591 },
{ url = "https://files.pythonhosted.org/packages/2b/a6/564ecde55ee633270a793999ef4fd1d2c2b32b5a7eec903b1012cb7c5143/frozenlist-1.6.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4e1be9111cb6756868ac242b3c2bd1f09d9aea09846e4f5c23715e7afb647103", size = 316226 }, { url = "https://files.pythonhosted.org/packages/29/e2/ffbb1fae55a791fd6c2938dd9ea779509c977435ba3940b9f2e8dc9d5316/frozenlist-1.5.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5d7f5a50342475962eb18b740f3beecc685a15b52c91f7d975257e13e029eca9", size = 273249 },
{ url = "https://files.pythonhosted.org/packages/f1/c8/6c0682c32377f402b8a6174fb16378b683cf6379ab4d2827c580892ab3c7/frozenlist-1.6.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:94bb451c664415f02f07eef4ece976a2c65dcbab9c2f1705b7031a3a75349d8c", size = 312788 }, { url = "https://files.pythonhosted.org/packages/2e/6e/008136a30798bb63618a114b9321b5971172a5abddff44a100c7edc5ad4f/frozenlist-1.5.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:87f724d055eb4785d9be84e9ebf0f24e392ddfad00b3fe036e43f489fafc9039", size = 271075 },
{ url = "https://files.pythonhosted.org/packages/b6/b8/10fbec38f82c5d163ca1750bfff4ede69713badf236a016781cf1f10a0f0/frozenlist-1.6.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:d1a686d0b0949182b8faddea596f3fc11f44768d1f74d4cad70213b2e139d821", size = 325914 }, { url = "https://files.pythonhosted.org/packages/ae/f0/4e71e54a026b06724cec9b6c54f0b13a4e9e298cc8db0f82ec70e151f5ce/frozenlist-1.5.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:6e9080bb2fb195a046e5177f10d9d82b8a204c0736a97a153c2466127de87784", size = 285398 },
{ url = "https://files.pythonhosted.org/packages/62/ca/2bf4f3a1bd40cdedd301e6ecfdbb291080d5afc5f9ce350c0739f773d6b9/frozenlist-1.6.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:ea8e59105d802c5a38bdbe7362822c522230b3faba2aa35c0fa1765239b7dd70", size = 305283 }, { url = "https://files.pythonhosted.org/packages/4d/36/70ec246851478b1c0b59f11ef8ade9c482ff447c1363c2bd5fad45098b12/frozenlist-1.5.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9b93d7aaa36c966fa42efcaf716e6b3900438632a626fb09c049f6a2f09fc631", size = 294445 },
{ url = "https://files.pythonhosted.org/packages/09/64/20cc13ccf94abc2a1f482f74ad210703dc78a590d0b805af1c9aa67f76f9/frozenlist-1.6.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:abc4e880a9b920bc5020bf6a431a6bb40589d9bca3975c980495f63632e8382f", size = 319264 }, { url = "https://files.pythonhosted.org/packages/37/e0/47f87544055b3349b633a03c4d94b405956cf2437f4ab46d0928b74b7526/frozenlist-1.5.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:52ef692a4bc60a6dd57f507429636c2af8b6046db8b31b18dac02cbc8f507f7f", size = 280569 },
{ url = "https://files.pythonhosted.org/packages/20/ff/86c6a2bbe98cfc231519f5e6d712a0898488ceac804a917ce014f32e68f6/frozenlist-1.6.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9a79713adfe28830f27a3c62f6b5406c37376c892b05ae070906f07ae4487046", size = 326482 }, { url = "https://files.pythonhosted.org/packages/f9/7c/490133c160fb6b84ed374c266f42800e33b50c3bbab1652764e6e1fc498a/frozenlist-1.5.0-cp312-cp312-win32.whl", hash = "sha256:29d94c256679247b33a3dc96cce0f93cbc69c23bf75ff715919332fdbb6a32b8", size = 44721 },
{ url = "https://files.pythonhosted.org/packages/2f/da/8e381f66367d79adca245d1d71527aac774e30e291d41ef161ce2d80c38e/frozenlist-1.6.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:9a0318c2068e217a8f5e3b85e35899f5a19e97141a45bb925bb357cfe1daf770", size = 318248 }, { url = "https://files.pythonhosted.org/packages/b1/56/4e45136ffc6bdbfa68c29ca56ef53783ef4c2fd395f7cbf99a2624aa9aaa/frozenlist-1.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:8969190d709e7c48ea386db202d708eb94bdb29207a1f269bab1196ce0dcca1f", size = 51329 },
{ url = "https://files.pythonhosted.org/packages/39/24/1a1976563fb476ab6f0fa9fefaac7616a4361dbe0461324f9fd7bf425dbe/frozenlist-1.6.0-cp312-cp312-win32.whl", hash = "sha256:853ac025092a24bb3bf09ae87f9127de9fe6e0c345614ac92536577cf956dfcc", size = 115161 }, { url = "https://files.pythonhosted.org/packages/c6/c8/a5be5b7550c10858fcf9b0ea054baccab474da77d37f1e828ce043a3a5d4/frozenlist-1.5.0-py3-none-any.whl", hash = "sha256:d994863bba198a4a518b467bb971c56e1db3f180a25c6cf7bb1949c267f748c3", size = 11901 },
{ url = "https://files.pythonhosted.org/packages/80/2e/fb4ed62a65f8cd66044706b1013f0010930d8cbb0729a2219561ea075434/frozenlist-1.6.0-cp312-cp312-win_amd64.whl", hash = "sha256:2bdfe2d7e6c9281c6e55523acd6c2bf77963cb422fdc7d142fb0cb6621b66878", size = 120548 },
{ url = "https://files.pythonhosted.org/packages/71/3e/b04a0adda73bd52b390d730071c0d577073d3d26740ee1bad25c3ad0f37b/frozenlist-1.6.0-py3-none-any.whl", hash = "sha256:535eec9987adb04701266b92745d6cdcef2e77669299359c3009c3404dd5d191", size = 12404 },
] ]
[[package]] [[package]]
@ -2160,11 +2158,11 @@ wheels = [
[[package]] [[package]]
name = "packaging" name = "packaging"
version = "25.0" version = "24.2"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727 } sdist = { url = "https://files.pythonhosted.org/packages/d0/63/68dbb6eb2de9cb10ee4c9c14a0148804425e13c4fb20d61cce69f53106da/packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f", size = 163950 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469 }, { url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451 },
] ]
[[package]] [[package]]
@ -2204,16 +2202,16 @@ wheels = [
[[package]] [[package]]
name = "pdoc" name = "pdoc"
version = "15.0.3" version = "15.0.1"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "jinja2" }, { name = "jinja2" },
{ name = "markupsafe" }, { name = "markupsafe" },
{ name = "pygments" }, { name = "pygments" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/9f/e9/66ab0fc39276a1818dea6302858ec9558964d8d9f1c90dd1facfe395d216/pdoc-15.0.3.tar.gz", hash = "sha256:6482d8ebbd40185fea5e6aec2f1592f4be92e93cf6bf70b9e2a00378bbaf3252", size = 155384 } sdist = { url = "https://files.pythonhosted.org/packages/bf/16/1b542af6f18a27de059f722c487a596681127897b6d31f78e46d6e5bf2fe/pdoc-15.0.1.tar.gz", hash = "sha256:3b08382c9d312243ee6c2a1813d0ff517a6ab84d596fa2c6c6b5255b17c3d666", size = 154174 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/dc/37/bc3189471c63c84e15f7dc42d4b712747e9662ffbcfacfc4b6a93e6c3bc6/pdoc-15.0.3-py3-none-any.whl", hash = "sha256:686c921ef2622f166de5f73b7241935a4ddac79c8d10dbfa43def8c1fca86550", size = 145950 }, { url = "https://files.pythonhosted.org/packages/2f/4d/60d856a1b12fbf6ac1539efccfa138e57c6b88675c9867d84bbb46455cc1/pdoc-15.0.1-py3-none-any.whl", hash = "sha256:fd437ab8eb55f9b942226af7865a3801e2fb731665199b74fd9a44737dbe20f9", size = 144186 },
] ]
[[package]] [[package]]
@ -2773,39 +2771,39 @@ wheels = [
[[package]] [[package]]
name = "ruff" name = "ruff"
version = "0.11.6" version = "0.11.5"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/d9/11/bcef6784c7e5d200b8a1f5c2ddf53e5da0efec37e6e5a44d163fb97e04ba/ruff-0.11.6.tar.gz", hash = "sha256:bec8bcc3ac228a45ccc811e45f7eb61b950dbf4cf31a67fa89352574b01c7d79", size = 4010053 } sdist = { url = "https://files.pythonhosted.org/packages/45/71/5759b2a6b2279bb77fe15b1435b89473631c2cd6374d45ccdb6b785810be/ruff-0.11.5.tar.gz", hash = "sha256:cae2e2439cb88853e421901ec040a758960b576126dab520fa08e9de431d1bef", size = 3976488 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/6e/1f/8848b625100ebcc8740c8bac5b5dd8ba97dd4ee210970e98832092c1635b/ruff-0.11.6-py3-none-linux_armv6l.whl", hash = "sha256:d84dcbe74cf9356d1bdb4a78cf74fd47c740bf7bdeb7529068f69b08272239a1", size = 10248105 }, { url = "https://files.pythonhosted.org/packages/23/db/6efda6381778eec7f35875b5cbefd194904832a1153d68d36d6b269d81a8/ruff-0.11.5-py3-none-linux_armv6l.whl", hash = "sha256:2561294e108eb648e50f210671cc56aee590fb6167b594144401532138c66c7b", size = 10103150 },
{ url = "https://files.pythonhosted.org/packages/e0/47/c44036e70c6cc11e6ee24399c2a1e1f1e99be5152bd7dff0190e4b325b76/ruff-0.11.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:9bc583628e1096148011a5d51ff3c836f51899e61112e03e5f2b1573a9b726de", size = 11001494 }, { url = "https://files.pythonhosted.org/packages/44/f2/06cd9006077a8db61956768bc200a8e52515bf33a8f9b671ee527bb10d77/ruff-0.11.5-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ac12884b9e005c12d0bd121f56ccf8033e1614f736f766c118ad60780882a077", size = 10898637 },
{ url = "https://files.pythonhosted.org/packages/ed/5b/170444061650202d84d316e8f112de02d092bff71fafe060d3542f5bc5df/ruff-0.11.6-py3-none-macosx_11_0_arm64.whl", hash = "sha256:f2959049faeb5ba5e3b378709e9d1bf0cab06528b306b9dd6ebd2a312127964a", size = 10352151 }, { url = "https://files.pythonhosted.org/packages/18/f5/af390a013c56022fe6f72b95c86eb7b2585c89cc25d63882d3bfe411ecf1/ruff-0.11.5-py3-none-macosx_11_0_arm64.whl", hash = "sha256:4bfd80a6ec559a5eeb96c33f832418bf0fb96752de0539905cf7b0cc1d31d779", size = 10236012 },
{ url = "https://files.pythonhosted.org/packages/ff/91/f02839fb3787c678e112c8865f2c3e87cfe1744dcc96ff9fc56cfb97dda2/ruff-0.11.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:63c5d4e30d9d0de7fedbfb3e9e20d134b73a30c1e74b596f40f0629d5c28a193", size = 10541951 }, { url = "https://files.pythonhosted.org/packages/b8/ca/b9bf954cfed165e1a0c24b86305d5c8ea75def256707f2448439ac5e0d8b/ruff-0.11.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0947c0a1afa75dcb5db4b34b070ec2bccee869d40e6cc8ab25aca11a7d527794", size = 10415338 },
{ url = "https://files.pythonhosted.org/packages/9e/f3/c09933306096ff7a08abede3cc2534d6fcf5529ccd26504c16bf363989b5/ruff-0.11.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:26a4b9a4e1439f7d0a091c6763a100cef8fbdc10d68593df6f3cfa5abdd9246e", size = 10079195 }, { url = "https://files.pythonhosted.org/packages/d9/4d/2522dde4e790f1b59885283f8786ab0046958dfd39959c81acc75d347467/ruff-0.11.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ad871ff74b5ec9caa66cb725b85d4ef89b53f8170f47c3406e32ef040400b038", size = 9965277 },
{ url = "https://files.pythonhosted.org/packages/e0/0d/a87f8933fccbc0d8c653cfbf44bedda69c9582ba09210a309c066794e2ee/ruff-0.11.6-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b5edf270223dd622218256569636dc3e708c2cb989242262fe378609eccf1308", size = 11698918 }, { url = "https://files.pythonhosted.org/packages/e5/7a/749f56f150eef71ce2f626a2f6988446c620af2f9ba2a7804295ca450397/ruff-0.11.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e6cf918390cfe46d240732d4d72fa6e18e528ca1f60e318a10835cf2fa3dc19f", size = 11541614 },
{ url = "https://files.pythonhosted.org/packages/52/7d/8eac0bd083ea8a0b55b7e4628428203441ca68cd55e0b67c135a4bc6e309/ruff-0.11.6-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:f55844e818206a9dd31ff27f91385afb538067e2dc0beb05f82c293ab84f7d55", size = 12319426 }, { url = "https://files.pythonhosted.org/packages/89/b2/7d9b8435222485b6aac627d9c29793ba89be40b5de11584ca604b829e960/ruff-0.11.5-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:56145ee1478582f61c08f21076dc59153310d606ad663acc00ea3ab5b2125f82", size = 12198873 },
{ url = "https://files.pythonhosted.org/packages/c2/dc/d0c17d875662d0c86fadcf4ca014ab2001f867621b793d5d7eef01b9dcce/ruff-0.11.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d8f782286c5ff562e4e00344f954b9320026d8e3fae2ba9e6948443fafd9ffc", size = 11791012 }, { url = "https://files.pythonhosted.org/packages/00/e0/a1a69ef5ffb5c5f9c31554b27e030a9c468fc6f57055886d27d316dfbabd/ruff-0.11.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e5f66f8f1e8c9fc594cbd66fbc5f246a8d91f916cb9667e80208663ec3728304", size = 11670190 },
{ url = "https://files.pythonhosted.org/packages/f9/f3/81a1aea17f1065449a72509fc7ccc3659cf93148b136ff2a8291c4bc3ef1/ruff-0.11.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:01c63ba219514271cee955cd0adc26a4083df1956d57847978383b0e50ffd7d2", size = 13949947 }, { url = "https://files.pythonhosted.org/packages/05/61/c1c16df6e92975072c07f8b20dad35cd858e8462b8865bc856fe5d6ccb63/ruff-0.11.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:80b4df4d335a80315ab9afc81ed1cff62be112bd165e162b5eed8ac55bfc8470", size = 13902301 },
{ url = "https://files.pythonhosted.org/packages/61/9f/a3e34de425a668284e7024ee6fd41f452f6fa9d817f1f3495b46e5e3a407/ruff-0.11.6-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15adac20ef2ca296dd3d8e2bedc6202ea6de81c091a74661c3666e5c4c223ff6", size = 11471753 }, { url = "https://files.pythonhosted.org/packages/79/89/0af10c8af4363304fd8cb833bd407a2850c760b71edf742c18d5a87bb3ad/ruff-0.11.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3068befab73620b8a0cc2431bd46b3cd619bc17d6f7695a3e1bb166b652c382a", size = 11350132 },
{ url = "https://files.pythonhosted.org/packages/df/c5/4a57a86d12542c0f6e2744f262257b2aa5a3783098ec14e40f3e4b3a354a/ruff-0.11.6-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:4dd6b09e98144ad7aec026f5588e493c65057d1b387dd937d7787baa531d9bc2", size = 10417121 }, { url = "https://files.pythonhosted.org/packages/b9/e1/ecb4c687cbf15164dd00e38cf62cbab238cad05dd8b6b0fc68b0c2785e15/ruff-0.11.5-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:f5da2e710a9641828e09aa98b92c9ebbc60518fdf3921241326ca3e8f8e55b8b", size = 10312937 },
{ url = "https://files.pythonhosted.org/packages/58/3f/a3b4346dff07ef5b862e2ba06d98fcbf71f66f04cf01d375e871382b5e4b/ruff-0.11.6-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:45b2e1d6c0eed89c248d024ea95074d0e09988d8e7b1dad8d3ab9a67017a5b03", size = 10073829 }, { url = "https://files.pythonhosted.org/packages/cf/4f/0e53fe5e500b65934500949361e3cd290c5ba60f0324ed59d15f46479c06/ruff-0.11.5-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:ef39f19cb8ec98cbc762344921e216f3857a06c47412030374fffd413fb8fd3a", size = 9936683 },
{ url = "https://files.pythonhosted.org/packages/93/cc/7ed02e0b86a649216b845b3ac66ed55d8aa86f5898c5f1691797f408fcb9/ruff-0.11.6-py3-none-musllinux_1_2_i686.whl", hash = "sha256:bd40de4115b2ec4850302f1a1d8067f42e70b4990b68838ccb9ccd9f110c5e8b", size = 11076108 }, { url = "https://files.pythonhosted.org/packages/04/a8/8183c4da6d35794ae7f76f96261ef5960853cd3f899c2671961f97a27d8e/ruff-0.11.5-py3-none-musllinux_1_2_i686.whl", hash = "sha256:b2a7cedf47244f431fd11aa5a7e2806dda2e0c365873bda7834e8f7d785ae159", size = 10950217 },
{ url = "https://files.pythonhosted.org/packages/39/5e/5b09840fef0eff1a6fa1dea6296c07d09c17cb6fb94ed5593aa591b50460/ruff-0.11.6-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:77cda2dfbac1ab73aef5e514c4cbfc4ec1fbef4b84a44c736cc26f61b3814cd9", size = 11512366 }, { url = "https://files.pythonhosted.org/packages/26/88/9b85a5a8af21e46a0639b107fcf9bfc31da4f1d263f2fc7fbe7199b47f0a/ruff-0.11.5-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:81be52e7519f3d1a0beadcf8e974715b2dfc808ae8ec729ecfc79bddf8dbb783", size = 11404521 },
{ url = "https://files.pythonhosted.org/packages/6f/4c/1cd5a84a412d3626335ae69f5f9de2bb554eea0faf46deb1f0cb48534042/ruff-0.11.6-py3-none-win32.whl", hash = "sha256:5151a871554be3036cd6e51d0ec6eef56334d74dfe1702de717a995ee3d5b287", size = 10485900 }, { url = "https://files.pythonhosted.org/packages/fc/52/047f35d3b20fd1ae9ccfe28791ef0f3ca0ef0b3e6c1a58badd97d450131b/ruff-0.11.5-py3-none-win32.whl", hash = "sha256:e268da7b40f56e3eca571508a7e567e794f9bfcc0f412c4b607931d3af9c4afe", size = 10320697 },
{ url = "https://files.pythonhosted.org/packages/42/46/8997872bc44d43df986491c18d4418f1caff03bc47b7f381261d62c23442/ruff-0.11.6-py3-none-win_amd64.whl", hash = "sha256:cce85721d09c51f3b782c331b0abd07e9d7d5f775840379c640606d3159cae0e", size = 11558592 }, { url = "https://files.pythonhosted.org/packages/b9/fe/00c78010e3332a6e92762424cf4c1919065707e962232797d0b57fd8267e/ruff-0.11.5-py3-none-win_amd64.whl", hash = "sha256:6c6dc38af3cfe2863213ea25b6dc616d679205732dc0fb673356c2d69608f800", size = 11378665 },
{ url = "https://files.pythonhosted.org/packages/d7/6a/65fecd51a9ca19e1477c3879a7fda24f8904174d1275b419422ac00f6eee/ruff-0.11.6-py3-none-win_arm64.whl", hash = "sha256:3567ba0d07fb170b1b48d944715e3294b77f5b7679e8ba258199a250383ccb79", size = 10682766 }, { url = "https://files.pythonhosted.org/packages/43/7c/c83fe5cbb70ff017612ff36654edfebec4b1ef79b558b8e5fd933bab836b/ruff-0.11.5-py3-none-win_arm64.whl", hash = "sha256:67e241b4314f4eacf14a601d586026a962f4002a475aa702c69980a38087aa4e", size = 10460287 },
] ]
[[package]] [[package]]
name = "s3transfer" name = "s3transfer"
version = "0.11.5" version = "0.11.4"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "botocore" }, { name = "botocore" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/c4/2b/5c9562795c2eb2b5f63536961754760c25bf0f34af93d36aa28dea2fb303/s3transfer-0.11.5.tar.gz", hash = "sha256:8c8aad92784779ab8688a61aefff3e28e9ebdce43142808eaa3f0b0f402f68b7", size = 149107 } sdist = { url = "https://files.pythonhosted.org/packages/0f/ec/aa1a215e5c126fe5decbee2e107468f51d9ce190b9763cb649f76bb45938/s3transfer-0.11.4.tar.gz", hash = "sha256:559f161658e1cf0a911f45940552c696735f5c74e64362e515f333ebed87d679", size = 148419 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/45/39/13402e323666d17850eca87e4cd6ecfcf9fd7809cac9efdcce10272fc29d/s3transfer-0.11.5-py3-none-any.whl", hash = "sha256:757af0f2ac150d3c75bc4177a32355c3862a98d20447b69a0161812992fe0bd4", size = 84782 }, { url = "https://files.pythonhosted.org/packages/86/62/8d3fc3ec6640161a5649b2cddbbf2b9fa39c92541225b33f117c37c5a2eb/s3transfer-0.11.4-py3-none-any.whl", hash = "sha256:ac265fa68318763a03bf2dc4f39d5cbd6a9e178d81cc9483ad27da33637e320d", size = 84412 },
] ]
[[package]] [[package]]
@ -2887,11 +2885,11 @@ wheels = [
[[package]] [[package]]
name = "setuptools" name = "setuptools"
version = "79.0.0" version = "78.1.0"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/7d/19/fecb7e2825616270f34512b3394cdcf6f45a79b5b6d94fdbd86a509e67b5/setuptools-79.0.0.tar.gz", hash = "sha256:9828422e7541213b0aacb6e10bbf9dd8febeaa45a48570e09b6d100e063fc9f9", size = 1367685 } sdist = { url = "https://files.pythonhosted.org/packages/a9/5a/0db4da3bc908df06e5efae42b44e75c81dd52716e10192ff36d0c1c8e379/setuptools-78.1.0.tar.gz", hash = "sha256:18fd474d4a82a5f83dac888df697af65afa82dec7323d09c3e37d1f14288da54", size = 1367827 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/cc/ea/d53f2f8897c46a36df085964d07761ea4c2d1f2cf92019693b6742b7aabb/setuptools-79.0.0-py3-none-any.whl", hash = "sha256:b9ab3a104bedb292323f53797b00864e10e434a3ab3906813a7169e4745b912a", size = 1256065 }, { url = "https://files.pythonhosted.org/packages/54/21/f43f0a1fa8b06b32812e0975981f4677d28e0f3271601dc88ac5a5b83220/setuptools-78.1.0-py3-none-any.whl", hash = "sha256:3e386e96793c8702ae83d17b853fb93d3e09ef82ec62722e61da5cd22376dcd8", size = 1256108 },
] ]
[[package]] [[package]]
@ -3016,7 +3014,7 @@ wheels = [
[[package]] [[package]]
name = "trio" name = "trio"
version = "0.30.0" version = "0.29.0"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "attrs" }, { name = "attrs" },
@ -3026,9 +3024,9 @@ dependencies = [
{ name = "sniffio" }, { name = "sniffio" },
{ name = "sortedcontainers" }, { name = "sortedcontainers" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/01/c1/68d582b4d3a1c1f8118e18042464bb12a7c1b75d64d75111b297687041e3/trio-0.30.0.tar.gz", hash = "sha256:0781c857c0c81f8f51e0089929a26b5bb63d57f927728a5586f7e36171f064df", size = 593776 } sdist = { url = "https://files.pythonhosted.org/packages/a1/47/f62e62a1a6f37909aed0bf8f5d5411e06fa03846cfcb64540cd1180ccc9f/trio-0.29.0.tar.gz", hash = "sha256:ea0d3967159fc130acb6939a0be0e558e364fee26b5deeecc893a6b08c361bdf", size = 588952 }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/69/8e/3f6dfda475ecd940e786defe6df6c500734e686c9cd0a0f8ef6821e9b2f2/trio-0.30.0-py3-none-any.whl", hash = "sha256:3bf4f06b8decf8d3cf00af85f40a89824669e2d033bb32469d34840edcfc22a5", size = 499194 }, { url = "https://files.pythonhosted.org/packages/c9/55/c4d9bea8b3d7937901958f65124123512419ab0eb73695e5f382521abbfb/trio-0.29.0-py3-none-any.whl", hash = "sha256:d8c463f1a9cc776ff63e331aba44c125f423a5a13c684307e828d930e625ba66", size = 492920 },
] ]
[[package]] [[package]]

View File

@ -2,11 +2,15 @@
node_modules node_modules
# don't lint build output (make sure it's set to your correct build folder name) # don't lint build output (make sure it's set to your correct build folder name)
dist dist
out
# don't lint nyc coverage output # don't lint nyc coverage output
coverage coverage
# Import order matters # Import order matters
poly.ts
src/locale-codes.ts src/locale-codes.ts
src/locales/ src/locales/
storybook-static/ storybook-static/
# Prettier breaks the tsconfig file
tsconfig.json
.storybook/css-import-maps* .storybook/css-import-maps*
package.json
packages/**/package.json

846
web/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,44 +1,6 @@
{ {
"name": "@goauthentik/web", "name": "@goauthentik/web",
"version": "0.0.0", "version": "0.0.0",
"license": "MIT",
"private": true,
"scripts": {
"build": "wireit",
"build-locales": "wireit",
"build-locales:build": "wireit",
"build-proxy": "wireit",
"build:sfe": "wireit",
"esbuild:watch": "node scripts/build-web.mjs --watch",
"extract-locales": "wireit",
"format": "wireit",
"lint": "wireit",
"lint:imports": "wireit",
"lint:lockfile": "wireit",
"lint:nightmare": "wireit",
"lint:precommit": "wireit",
"lint:types": "wireit",
"lit-analyse": "wireit",
"postinstall": "bash scripts/patch-spotlight.sh",
"precommit": "wireit",
"prettier": "wireit",
"prettier-check": "wireit",
"pseudolocalize": "wireit",
"storybook": "storybook dev -p 6006",
"storybook:build": "wireit",
"test": "wireit",
"test:e2e": "wireit",
"test:e2e:watch": "wireit",
"test:watch": "wireit",
"tsc": "wireit",
"watch": "run-s build-locales esbuild:watch"
},
"type": "module",
"exports": {
"./package.json": "./package.json",
"./paths": "./paths.js",
"./scripts/*": "./scripts/*.mjs"
},
"dependencies": { "dependencies": {
"@codemirror/lang-css": "^6.3.1", "@codemirror/lang-css": "^6.3.1",
"@codemirror/lang-html": "^6.4.9", "@codemirror/lang-html": "^6.4.9",
@ -50,7 +12,8 @@
"@floating-ui/dom": "^1.6.11", "@floating-ui/dom": "^1.6.11",
"@formatjs/intl-listformat": "^7.5.7", "@formatjs/intl-listformat": "^7.5.7",
"@fortawesome/fontawesome-free": "^6.6.0", "@fortawesome/fontawesome-free": "^6.6.0",
"@goauthentik/api": "^2025.4.0-1746018955", "@goauthentik/api": "^2025.2.4-1745519715",
"@lit-labs/ssr": "3.2.2",
"@lit/context": "^1.1.2", "@lit/context": "^1.1.2",
"@lit/localize": "^0.12.2", "@lit/localize": "^0.12.2",
"@lit/reactive-element": "^2.0.4", "@lit/reactive-element": "^2.0.4",
@ -91,7 +54,6 @@
"remark-gfm": "^4.0.1", "remark-gfm": "^4.0.1",
"remark-mdx-frontmatter": "^5.0.0", "remark-mdx-frontmatter": "^5.0.0",
"style-mod": "^4.1.2", "style-mod": "^4.1.2",
"trusted-types": "^2.0.0",
"ts-pattern": "^5.4.0", "ts-pattern": "^5.4.0",
"unist-util-visit": "^5.0.0", "unist-util-visit": "^5.0.0",
"webcomponent-qr-code": "^1.2.0", "webcomponent-qr-code": "^1.2.0",
@ -100,7 +62,6 @@
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.11.1", "@eslint/js": "^9.11.1",
"@goauthentik/esbuild-plugin-live-reload": "^1.0.4", "@goauthentik/esbuild-plugin-live-reload": "^1.0.4",
"@goauthentik/monorepo": "^1.0.0",
"@goauthentik/prettier-config": "^1.0.4", "@goauthentik/prettier-config": "^1.0.4",
"@goauthentik/tsconfig": "^1.0.4", "@goauthentik/tsconfig": "^1.0.4",
"@hcaptcha/types": "^1.0.4", "@hcaptcha/types": "^1.0.4",
@ -132,13 +93,13 @@
"@wdio/spec-reporter": "^9.1.2", "@wdio/spec-reporter": "^9.1.2",
"chromedriver": "^131.0.1", "chromedriver": "^131.0.1",
"esbuild": "^0.25.0", "esbuild": "^0.25.0",
"esbuild-plugin-copy": "^2.1.1",
"esbuild-plugin-polyfill-node": "^0.3.0", "esbuild-plugin-polyfill-node": "^0.3.0",
"esbuild-plugins-node-modules-polyfill": "^1.7.0", "esbuild-plugins-node-modules-polyfill": "^1.7.0",
"eslint": "^9.11.1", "eslint": "^9.11.1",
"eslint-plugin-lit": "^1.15.0", "eslint-plugin-lit": "^1.15.0",
"eslint-plugin-wc": "^2.1.1", "eslint-plugin-wc": "^2.1.1",
"github-slugger": "^2.0.0", "github-slugger": "^2.0.0",
"glob": "^11.0.0",
"globals": "^15.10.0", "globals": "^15.10.0",
"knip": "^5.30.6", "knip": "^5.30.6",
"lit-analyzer": "^2.0.3", "lit-analyzer": "^2.0.3",
@ -149,6 +110,7 @@
"rollup-plugin-postcss-lit": "^2.1.0", "rollup-plugin-postcss-lit": "^2.1.0",
"storybook": "^8.3.4", "storybook": "^8.3.4",
"storybook-addon-mock": "^5.0.0", "storybook-addon-mock": "^5.0.0",
"syncpack": "^13.0.0",
"turnstile-types": "^1.2.3", "turnstile-types": "^1.2.3",
"typescript": "^5.6.2", "typescript": "^5.6.2",
"typescript-eslint": "^8.8.0", "typescript-eslint": "^8.8.0",
@ -156,6 +118,10 @@
"vite-tsconfig-paths": "^5.0.1", "vite-tsconfig-paths": "^5.0.1",
"wireit": "^0.14.9" "wireit": "^0.14.9"
}, },
"engines": {
"node": ">=20"
},
"license": "MIT",
"optionalDependencies": { "optionalDependencies": {
"@esbuild/darwin-arm64": "^0.24.0", "@esbuild/darwin-arm64": "^0.24.0",
"@esbuild/linux-amd64": "^0.18.11", "@esbuild/linux-amd64": "^0.18.11",
@ -164,6 +130,48 @@
"@rollup/rollup-linux-arm64-gnu": "4.23.0", "@rollup/rollup-linux-arm64-gnu": "4.23.0",
"@rollup/rollup-linux-x64-gnu": "4.23.0" "@rollup/rollup-linux-x64-gnu": "4.23.0"
}, },
"overrides": {
"rapidoc": {
"@apitools/openapi-parser@": "0.0.37"
},
"chromedriver": {
"axios": "^1.8.4"
}
},
"prettier": "@goauthentik/prettier-config",
"private": true,
"scripts": {
"build": "wireit",
"build-locales": "wireit",
"build-locales:build": "wireit",
"build-proxy": "wireit",
"build:sfe": "wireit",
"esbuild:watch": "node scripts/build-web.mjs --watch",
"extract-locales": "wireit",
"format": "wireit",
"lint": "wireit",
"lint:imports": "wireit",
"lint:lockfile": "wireit",
"lint:nightmare": "wireit",
"lint:package": "wireit",
"lint:precommit": "wireit",
"lint:types": "wireit",
"lit-analyse": "wireit",
"postinstall": "bash scripts/patch-spotlight.sh",
"precommit": "wireit",
"prettier": "wireit",
"prettier-check": "wireit",
"pseudolocalize": "wireit",
"storybook": "storybook dev -p 6006",
"storybook:build": "wireit",
"test": "wireit",
"test:e2e": "wireit",
"test:e2e:watch": "wireit",
"test:watch": "wireit",
"tsc": "wireit",
"watch": "run-s build-locales esbuild:watch"
},
"type": "module",
"wireit": { "wireit": {
"build": { "build": {
"#comment": [ "#comment": [
@ -240,7 +248,10 @@
"command": "lit-localize extract" "command": "lit-localize extract"
}, },
"format": { "format": {
"command": "prettier --write ." "command": "prettier --write .",
"dependencies": [
"lint:package"
]
}, },
"format:packages": { "format:packages": {
"dependencies": [ "dependencies": [
@ -279,6 +290,9 @@
"./packages/sfe:lint:lockfile" "./packages/sfe:lint:lockfile"
] ]
}, },
"lint:package": {
"command": "syncpack format -i ' '"
},
"lint:nightmare": { "lint:nightmare": {
"command": "${NODE_RUNNER} ./scripts/eslint.mjs --nightmare", "command": "${NODE_RUNNER} ./scripts/eslint.mjs --nightmare",
"env": { "env": {
@ -309,6 +323,7 @@
"lint:types", "lint:types",
"lint:components", "lint:components",
"lint:spelling", "lint:spelling",
"lint:package",
"lint:lockfile", "lint:lockfile",
"lint:lockfiles", "lint:lockfiles",
"lint:precommit", "lint:precommit",
@ -373,20 +388,8 @@
] ]
} }
}, },
"engines": {
"node": ">=20"
},
"workspaces": [ "workspaces": [
".", ".",
"./packages/*" "./packages/*"
], ]
"prettier": "@goauthentik/prettier-config",
"overrides": {
"rapidoc": {
"@apitools/openapi-parser@": "0.0.37"
},
"chromedriver": {
"axios": "^1.8.4"
}
}
} }

View File

@ -1,11 +1,22 @@
{ {
"name": "@goauthentik/esbuild-plugin-live-reload", "name": "@goauthentik/esbuild-plugin-live-reload",
"version": "1.0.4",
"description": "ESBuild plugin to watch for file changes and trigger client-side reloads.", "description": "ESBuild plugin to watch for file changes and trigger client-side reloads.",
"license": "MIT", "version": "1.0.4",
"private": true, "dependencies": {
"main": "index.js", "find-free-ports": "^3.1.1"
"type": "module", },
"devDependencies": {
"@goauthentik/prettier-config": "^1.0.4",
"@goauthentik/tsconfig": "^1.0.4",
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
"@types/node": "^22.14.1",
"esbuild": "^0.25.0",
"prettier": "^3.3.3",
"typescript": "^5.6.2"
},
"engines": {
"node": ">=20.11"
},
"exports": { "exports": {
"./package.json": "./package.json", "./package.json": "./package.json",
".": { ".": {
@ -21,33 +32,22 @@
"import": "./plugin/index.js" "import": "./plugin/index.js"
} }
}, },
"dependencies": {
"find-free-ports": "^3.1.1"
},
"devDependencies": {
"@goauthentik/prettier-config": "^1.0.4",
"@goauthentik/tsconfig": "^1.0.4",
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
"@types/node": "^22.14.1",
"esbuild": "^0.25.0",
"prettier": "^3.3.3",
"typescript": "^5.6.2"
},
"peerDependencies": {
"esbuild": "^0.25.0"
},
"engines": {
"node": ">=20.11"
},
"types": "./out/index.d.ts",
"files": [ "files": [
"./index.js", "./index.js",
"client/**/*", "client/**/*",
"plugin/**/*", "plugin/**/*",
"out/**/*" "out/**/*"
], ],
"license": "MIT",
"main": "index.js",
"peerDependencies": {
"esbuild": "^0.25.0"
},
"prettier": "@goauthentik/prettier-config", "prettier": "@goauthentik/prettier-config",
"private": true,
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
} },
"type": "module",
"types": "./out/index.d.ts"
} }

View File

@ -1,42 +0,0 @@
/**
* @file Utility functions for building and copying files.
*/
/**
* A source environment variable, which can be a string, number, boolean, null, or undefined.
* @typedef {string | number | boolean | null | undefined} EnvironmentVariable
*/
/**
* A type helper for serializing environment variables.
*
* @template {EnvironmentVariable} T
* @typedef {T extends string ? `"${T}"` : T} JSONify
*/
/**
* Given an object of environment variables, returns a new object with the same keys and values, but
* with the values serialized as strings.
*
* @template {Record<string, EnvironmentVariable>} EnvRecord
* @template {string} [Prefix='process.env.']
*
* @param {EnvRecord} input
* @param {Prefix} [prefix='process.env.']
*
* @returns {{[K in keyof EnvRecord as `${Prefix}${K}`]: JSONify<EnvRecord[K]>}}
*/
export function serializeEnvironmentVars(input, prefix = /** @type {Prefix} */ ("process.env.")) {
/**
* @type {Record<string, string>}
*/
const env = {};
for (const [key, value] of Object.entries(input)) {
const namespaceKey = prefix + key;
env[namespaceKey] = JSON.stringify(value || "");
}
return /** @type {any} */ (env);
}

View File

@ -1,28 +0,0 @@
{
"name": "@goauthentik/monorepo",
"version": "1.0.0",
"description": "Utilities for the authentik monorepo.",
"license": "MIT",
"private": true,
"main": "index.js",
"type": "module",
"exports": {
"./package.json": "./package.json",
".": {
"types": "./out/index.d.ts",
"import": "./index.js"
}
},
"devDependencies": {
"@goauthentik/prettier-config": "^1.0.4",
"@goauthentik/tsconfig": "^1.0.4",
"@types/node": "^22.14.1",
"prettier": "^3.3.3",
"typescript": "^5.6.2"
},
"engines": {
"node": ">=20.11"
},
"types": "./out/index.d.ts",
"prettier": "@goauthentik/prettier-config"
}

View File

@ -1,45 +0,0 @@
import { createRequire } from "node:module";
import { dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
const relativeDirname = dirname(fileURLToPath(import.meta.url));
/**
* @typedef {'~authentik'} MonoRepoRoot
*/
/**
* The root of the authentik monorepo.
*/
// TODO: Revise when this package is moved to the monorepo's `packages/monorepo` directory.
export const MonoRepoRoot = /** @type {MonoRepoRoot} */ (
resolve(relativeDirname, "..", "..", "..")
);
const require = createRequire(import.meta.url);
/**
* Resolve a package name to its location in the monorepo to the single node_modules directory.
* @param {string} packageName
*
* @returns {string} The resolved path to the package.
* @throws {Error} If the package cannot be resolved.
*/
export function resolvePackage(packageName) {
const relativePackageJSONPath = join(packageName, "package.json");
/** @type {string} */
let absolutePackageJSONPath;
try {
absolutePackageJSONPath = require.resolve(relativePackageJSONPath);
} catch (cause) {
const error = new Error(`Failed to resolve package "${packageName}"`);
error.cause = cause;
throw error;
}
return dirname(absolutePackageJSONPath);
}

View File

@ -1,15 +0,0 @@
declare module "process" {
global {
namespace NodeJS {
interface ProcessEnv {
/**
* An environment variable used to determine
* whether Node.js is running in production mode.
*
* @see {@link https://nodejs.org/en/learn/getting-started/nodejs-the-difference-between-development-and-production | The difference between development and production}
*/
NODE_ENV?: "production" | "development";
}
}
}
}

View File

@ -1,78 +0,0 @@
import { dirname, resolve } from "node:path";
import { fileURLToPath } from "node:url";
const relativeDirname = dirname(fileURLToPath(import.meta.url));
//#region Base paths
/**
* @typedef {'@goauthentik/web'} WebPackageIdentifier
*/
/**
* The root of the web package.
*/
export const PackageRoot = /** @type {WebPackageIdentifier} */ (resolve(relativeDirname));
/**
* The name of the distribution directory.
*/
export const DistDirectoryName = "dist";
/**
* Path to the web package's distribution directory.
*
* This is where the built files are located after running the build process.
*/
export const DistDirectory = /** @type {`${WebPackageIdentifier}/${DistDirectoryName}`} */ (
resolve(relativeDirname, DistDirectoryName)
);
//#endregion
//#region Entry points
/**
* @typedef {{ in: string, out: string }} EntryPointTarget
*
* ESBuild entrypoint target.
* Matches the type defined in the ESBuild context.
*/
/**
* Entry points available for building.
*
* @satisfies {Record<string, EntryPointTarget>}
*/
export const EntryPoint = /** @type {const} */ ({
Admin: {
in: resolve(PackageRoot, "src", "admin", "AdminInterface", "index.entrypoint.ts"),
out: resolve(DistDirectory, "admin", "AdminInterface"),
},
User: {
in: resolve(PackageRoot, "src", "user", "index.entrypoint.ts"),
out: resolve(DistDirectory, "user", "UserInterface"),
},
Flow: {
in: resolve(PackageRoot, "src", "flow", "index.entrypoint.ts"),
out: resolve(DistDirectory, "flow", "FlowInterface"),
},
Standalone: {
in: resolve(PackageRoot, "src", "standalone", "api-browser/index.entrypoint.ts"),
out: resolve(DistDirectory, "standalone", "api-browser", "index"),
},
StandaloneLoading: {
in: resolve(PackageRoot, "src", "standalone", "loading/index.entrypoint.ts"),
out: resolve(DistDirectory, "standalone", "loading", "index"),
},
RAC: {
in: resolve(PackageRoot, "src", "rac", "index.entrypoint.ts"),
out: resolve(DistDirectory, "rac", "index"),
},
Polyfill: {
in: resolve(PackageRoot, "src", "polyfill", "index.entrypoint.ts"),
out: resolve(DistDirectory, "poly"),
},
});
//#endregion

View File

@ -4,86 +4,138 @@
* @import { BuildOptions } from "esbuild"; * @import { BuildOptions } from "esbuild";
*/ */
import { liveReloadPlugin } from "@goauthentik/esbuild-plugin-live-reload/plugin"; import { liveReloadPlugin } from "@goauthentik/esbuild-plugin-live-reload/plugin";
import { import { execFileSync } from "child_process";
MonoRepoRoot,
NodeEnvironment,
readBuildIdentifier,
resolvePackage,
serializeEnvironmentVars,
} from "@goauthentik/monorepo";
import { DistDirectory, DistDirectoryName, EntryPoint, PackageRoot } from "@goauthentik/web/paths";
import { deepmerge } from "deepmerge-ts"; import { deepmerge } from "deepmerge-ts";
import esbuild from "esbuild"; import esbuild from "esbuild";
import copy from "esbuild-plugin-copy";
import { polyfillNode } from "esbuild-plugin-polyfill-node"; import { polyfillNode } from "esbuild-plugin-polyfill-node";
import * as fs from "node:fs/promises"; import { copyFileSync, mkdirSync, readFileSync, statSync } from "fs";
import * as path from "node:path"; import { globSync } from "glob";
import * as path from "path";
import { cwd } from "process";
import process from "process";
import { fileURLToPath } from "url";
import { mdxPlugin } from "./esbuild/build-mdx-plugin.mjs"; import { mdxPlugin } from "./esbuild/build-mdx-plugin.mjs";
const logPrefix = "[Build]"; const __dirname = fileURLToPath(new URL(".", import.meta.url));
let authentikProjectRoot = path.join(__dirname, "..", "..");
const definitions = serializeEnvironmentVars({ try {
NODE_ENV: NodeEnvironment, // Use the package.json file in the root folder, as it has the current version information.
CWD: process.cwd(), authentikProjectRoot = execFileSync("git", ["rev-parse", "--show-toplevel"], {
AK_API_BASE_PATH: process.env.AK_API_BASE_PATH, encoding: "utf8",
}); }).replace("\n", "");
} catch (_error) {
// We probably don't have a .git folder, which could happen in container builds.
}
const patternflyPath = resolvePackage("@patternfly/patternfly"); const packageJSONPath = path.join(authentikProjectRoot, "./package.json");
const rootPackage = JSON.parse(readFileSync(packageJSONPath, "utf8"));
const NODE_ENV = process.env.NODE_ENV || "development";
const AK_API_BASE_PATH = process.env.AK_API_BASE_PATH || "";
const environmentVars = new Map([
["NODE_ENV", NODE_ENV],
["CWD", cwd()],
["AK_API_BASE_PATH", AK_API_BASE_PATH],
]);
const definitions = Object.fromEntries(
Array.from(environmentVars).map(([key, value]) => {
return [`process.env.${key}`, JSON.stringify(value)];
}),
);
/** /**
* @type {Readonly<BuildOptions>} * All is magic is just to make sure the assets are copied into the right places. This is a very
* stripped down version of what the rollup-copy-plugin does, without any of the features we don't
* use, and using globSync instead of globby since we already had globSync lying around thanks to
* Typescript. If there's a third argument in an array entry, it's used to replace the internal path
* before concatenating it all together as the destination target.
* @type {Array<[string, string, string?]>}
*/
const assetsFileMappings = [
["node_modules/@patternfly/patternfly/patternfly.min.css", "."],
["node_modules/@patternfly/patternfly/assets/**", ".", "node_modules/@patternfly/patternfly/"],
["src/common/styles/**", "."],
["src/assets/images/**", "./assets/images"],
["./icons/*", "./assets/icons"],
];
/**
* @param {string} filePath
*/
const isFile = (filePath) => statSync(filePath).isFile();
/**
* @param {string} src Source file
* @param {string} dest Destination folder
* @param {string} [strip] Path to strip from the source file
*/
function nameCopyTarget(src, dest, strip) {
const target = path.join(dest, strip ? src.replace(strip, "") : path.parse(src).base);
return [src, target];
}
for (const [source, rawdest, strip] of assetsFileMappings) {
const matchedPaths = globSync(source);
const dest = path.join("dist", rawdest);
const copyTargets = matchedPaths.map((path) => nameCopyTarget(path, dest, strip));
for (const [src, dest] of copyTargets) {
if (isFile(src)) {
mkdirSync(path.dirname(dest), { recursive: true });
copyFileSync(src, dest);
}
}
}
/**
* @typedef {[source: string, destination: string]} EntryPoint
*/
/**
* This starts the definitions used for esbuild: Our targets, our arguments, the function for
* running a build, and three options for building: watching, building, and building the proxy.
* Ordered by largest to smallest interface to build even faster
*
* @type {EntryPoint[]}
*/
const entryPoints = [
["admin/AdminInterface/AdminInterface.ts", "admin"],
["user/UserInterface.ts", "user"],
["flow/FlowInterface.ts", "flow"],
["standalone/api-browser/index.ts", "standalone/api-browser"],
["rac/index.ts", "rac"],
["standalone/loading/index.ts", "standalone/loading"],
["polyfill/poly.ts", "."],
];
/**
* @type {import("esbuild").BuildOptions}
*/ */
const BASE_ESBUILD_OPTIONS = { const BASE_ESBUILD_OPTIONS = {
entryNames: `[dir]/[name]-${readBuildIdentifier()}`,
chunkNames: "[dir]/chunks/[name]-[hash]",
assetNames: "assets/[dir]/[name]-[hash]",
publicPath: path.join("/static", DistDirectoryName),
outdir: DistDirectory,
bundle: true, bundle: true,
write: true, write: true,
sourcemap: true, sourcemap: true,
minify: NodeEnvironment === "production", minify: NODE_ENV === "production",
legalComments: "external",
splitting: true, splitting: true,
treeShaking: true, treeShaking: true,
external: ["*.woff", "*.woff2"], external: ["*.woff", "*.woff2"],
tsconfig: path.resolve(PackageRoot, "tsconfig.build.json"), tsconfig: path.resolve(__dirname, "..", "tsconfig.build.json"),
loader: { loader: {
".css": "text", ".css": "text",
}, },
plugins: [ plugins: [
copy({
assets: [
{
from: path.join(patternflyPath, "patternfly.min.css"),
to: ".",
},
{
from: path.join(patternflyPath, "assets", "**"),
to: "./assets",
},
{
from: path.resolve(PackageRoot, "src", "common", "styles", "**"),
to: ".",
},
{
from: path.resolve(PackageRoot, "src", "assets", "images", "**"),
to: "./assets/images",
},
{
from: path.resolve(PackageRoot, "icons", "*"),
to: "./assets/icons",
},
],
}),
polyfillNode({ polyfillNode({
polyfills: { polyfills: {
path: true, path: true,
}, },
}), }),
mdxPlugin({ mdxPlugin({
root: MonoRepoRoot, root: authentikProjectRoot,
}), }),
], ],
define: definitions, define: definitions,
@ -99,43 +151,69 @@ const BASE_ESBUILD_OPTIONS = {
}, },
}; };
async function cleanDistDirectory() { /**
const timerLabel = `${logPrefix} ♻️ Cleaning previous builds...`; * Creates a version ID for the build.
* @returns {string}
*/
function composeVersionID() {
const { version } = rootPackage;
const buildHash = process.env.GIT_BUILD_HASH;
console.time(timerLabel); if (buildHash) {
return `${version}+${buildHash}`;
}
await fs.rm(DistDirectory, { return version;
recursive: true,
force: true,
});
await fs.mkdir(DistDirectory, {
recursive: true,
});
console.timeEnd(timerLabel);
} }
/** /**
* Creates an ESBuild options, extending the base options with the given overrides. * Build a single entry point.
* *
* @param {BuildOptions} overrides * @param {EntryPoint} buildTarget
* @returns {BuildOptions} * @param {Partial<esbuild.BuildOptions>} [overrides]
* @throws {Error} on build failure
*/ */
export function createESBuildOptions(overrides) { function createEntryPointOptions([source, dest], overrides = {}) {
/** const outdir = path.join(__dirname, "..", "dist", dest);
* @type {BuildOptions}
*/
const mergedOptions = deepmerge(BASE_ESBUILD_OPTIONS, overrides);
return mergedOptions; /**
* @type {esbuild.BuildOptions}
*/
const entryPointConfig = {
entryPoints: [`./src/${source}`],
entryNames: `[dir]/[name]-${composeVersionID()}`,
publicPath: path.join("/static", "dist", dest),
outdir,
};
/**
* @type {esbuild.BuildOptions}
*/
const mergedConfig = deepmerge(BASE_ESBUILD_OPTIONS, entryPointConfig, overrides);
return mergedConfig;
}
/**
* Build all entry points in parallel.
*
* @param {EntryPoint[]} entryPoints
* @returns {Promise<esbuild.BuildResult[]>}
*/
async function buildParallel(entryPoints) {
return Promise.all(
entryPoints.map((entryPoint) => {
return esbuild.build(createEntryPointOptions(entryPoint));
}),
);
} }
function doHelp() { function doHelp() {
console.log(`Build the authentik UI console.log(`Build the authentik UI
options: options:
-w, --watch: Build all interfaces -w, --watch: Build all ${entryPoints.length} interfaces
-p, --proxy: Build only the polyfills and the loading application -p, --proxy: Build only the polyfills and the loading application
-h, --help: This help message -h, --help: This help message
`); `);
@ -144,29 +222,27 @@ function doHelp() {
} }
async function doWatch() { async function doWatch() {
console.group(`${logPrefix} 🤖 Watching entry points`); console.log("Watching all entry points...");
const entryPoints = Object.entries(EntryPoint).map(([entrypointID, target]) => { const buildContexts = await Promise.all(
console.log(entrypointID); entryPoints.map((entryPoint) => {
return esbuild.context(
return target; createEntryPointOptions(entryPoint, {
}); define: definitions,
console.groupEnd();
const buildOptions = createESBuildOptions({
entryPoints,
plugins: [ plugins: [
liveReloadPlugin({ liveReloadPlugin({
relativeRoot: PackageRoot, logPrefix: `Build Observer (${entryPoint[1]})`,
relativeRoot: path.join(__dirname, ".."),
}), }),
], ],
}); }),
);
}),
);
const buildContext = await esbuild.context(buildOptions); await Promise.all(buildContexts.map((context) => context.rebuild()));
await buildContext.rebuild(); await Promise.allSettled(buildContexts.map((context) => context.watch()));
await buildContext.watch();
return /** @type {Promise<void>} */ ( return /** @type {Promise<void>} */ (
new Promise((resolve) => { new Promise((resolve) => {
@ -178,34 +254,15 @@ async function doWatch() {
} }
async function doBuild() { async function doBuild() {
console.group(`${logPrefix} 🚀 Building entry points:`); console.log("Building all entry points");
const entryPoints = Object.entries(EntryPoint).map(([entrypointID, target]) => { return buildParallel(entryPoints);
console.log(entrypointID);
return target;
});
console.groupEnd();
const buildOptions = createESBuildOptions({
entryPoints,
});
await esbuild.build(buildOptions);
console.log("Build complete");
} }
async function doProxy() { async function doProxy() {
const entryPoints = [EntryPoint.StandaloneLoading]; return buildParallel(
entryPoints.filter(([_, dest]) => ["standalone/loading", "."].includes(dest)),
const buildOptions = createESBuildOptions({ );
entryPoints,
});
await esbuild.build(buildOptions);
console.log("Proxy build complete");
} }
async function delegateCommand() { async function delegateCommand() {
@ -227,10 +284,7 @@ async function delegateCommand() {
} }
} }
await cleanDistDirectory() await delegateCommand()
// ---
.then(() =>
delegateCommand()
.then(() => { .then(() => {
console.log("Build complete"); console.log("Build complete");
process.exit(0); process.exit(0);
@ -238,5 +292,4 @@ await cleanDistDirectory()
.catch((error) => { .catch((error) => {
console.error(error); console.error(error);
process.exit(1); process.exit(1);
}), });
);

View File

@ -1,11 +1,11 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { VERSION } from "@goauthentik/common/constants"; import { VERSION } from "@goauthentik/common/constants";
import { globalAK } from "@goauthentik/common/global"; import { globalAK } from "@goauthentik/common/global";
import { DefaultBrand } from "@goauthentik/common/ui/config";
import "@goauthentik/elements/EmptyState"; import "@goauthentik/elements/EmptyState";
import { WithBrandConfig } from "@goauthentik/elements/Interface/brandProvider"; import { WithBrandConfig } from "@goauthentik/elements/Interface/brandProvider";
import { WithLicenseSummary } from "@goauthentik/elements/Interface/licenseSummaryProvider"; import { WithLicenseSummary } from "@goauthentik/elements/Interface/licenseSummaryProvider";
import { ModalButton } from "@goauthentik/elements/buttons/ModalButton"; import { ModalButton } from "@goauthentik/elements/buttons/ModalButton";
import { DefaultBrand } from "@goauthentik/elements/sidebar/SidebarBrand";
import { msg } from "@lit/localize"; import { msg } from "@lit/localize";
import { TemplateResult, css, html } from "lit"; import { TemplateResult, css, html } from "lit";

View File

@ -4,17 +4,13 @@ import { ROUTES } from "@goauthentik/admin/Routes";
import { import {
EVENT_API_DRAWER_TOGGLE, EVENT_API_DRAWER_TOGGLE,
EVENT_NOTIFICATION_DRAWER_TOGGLE, EVENT_NOTIFICATION_DRAWER_TOGGLE,
EVENT_SIDEBAR_TOGGLE,
} from "@goauthentik/common/constants"; } from "@goauthentik/common/constants";
import { configureSentry } from "@goauthentik/common/sentry"; import { configureSentry } from "@goauthentik/common/sentry";
import { me } from "@goauthentik/common/users"; import { me } from "@goauthentik/common/users";
import { WebsocketClient } from "@goauthentik/common/ws"; import { WebsocketClient } from "@goauthentik/common/ws";
import { AuthenticatedInterface } from "@goauthentik/elements/Interface"; import { AuthenticatedInterface } from "@goauthentik/elements/Interface";
import { WithLicenseSummary } from "@goauthentik/elements/Interface/licenseSummaryProvider.js";
import "@goauthentik/elements/ak-locale-context"; import "@goauthentik/elements/ak-locale-context";
import "@goauthentik/elements/banner/EnterpriseStatusBanner"; import "@goauthentik/elements/banner/EnterpriseStatusBanner";
import "@goauthentik/elements/banner/EnterpriseStatusBanner";
import "@goauthentik/elements/banner/VersionBanner";
import "@goauthentik/elements/banner/VersionBanner"; import "@goauthentik/elements/banner/VersionBanner";
import "@goauthentik/elements/messages/MessageContainer"; import "@goauthentik/elements/messages/MessageContainer";
import "@goauthentik/elements/messages/MessageContainer"; import "@goauthentik/elements/messages/MessageContainer";
@ -25,32 +21,25 @@ import "@goauthentik/elements/router/RouterOutlet";
import "@goauthentik/elements/sidebar/Sidebar"; import "@goauthentik/elements/sidebar/Sidebar";
import "@goauthentik/elements/sidebar/SidebarItem"; import "@goauthentik/elements/sidebar/SidebarItem";
import { CSSResult, TemplateResult, css, html, nothing } from "lit"; import { CSSResult, TemplateResult, css, html } from "lit";
import { customElement, property, query, state } from "lit/decorators.js"; import { customElement, property, query, state } from "lit/decorators.js";
import { classMap } from "lit/directives/class-map.js"; import { classMap } from "lit/directives/class-map.js";
import PFButton from "@patternfly/patternfly/components/Button/button.css"; import PFButton from "@patternfly/patternfly/components/Button/button.css";
import PFDrawer from "@patternfly/patternfly/components/Drawer/drawer.css"; import PFDrawer from "@patternfly/patternfly/components/Drawer/drawer.css";
import PFNav from "@patternfly/patternfly/components/Nav/nav.css";
import PFPage from "@patternfly/patternfly/components/Page/page.css"; import PFPage from "@patternfly/patternfly/components/Page/page.css";
import PFBase from "@patternfly/patternfly/patternfly-base.css"; import PFBase from "@patternfly/patternfly/patternfly-base.css";
import { LicenseSummaryStatusEnum, SessionUser, UiThemeEnum } from "@goauthentik/api"; import { SessionUser, UiThemeEnum } from "@goauthentik/api";
import { import "./AdminSidebar";
AdminSidebarEnterpriseEntries,
AdminSidebarEntries,
renderSidebarItems,
} from "./AdminSidebar.js";
if (process.env.NODE_ENV === "development") { if (process.env.NODE_ENV === "development") {
await import("@goauthentik/esbuild-plugin-live-reload/client"); await import("@goauthentik/esbuild-plugin-live-reload/client");
} }
@customElement("ak-interface-admin") @customElement("ak-interface-admin")
export class AdminInterface extends WithLicenseSummary(AuthenticatedInterface) { export class AdminInterface extends AuthenticatedInterface {
//#region Properties
@property({ type: Boolean }) @property({ type: Boolean })
notificationDrawerOpen = getURLParam("notificationDrawerOpen", false); notificationDrawerOpen = getURLParam("notificationDrawerOpen", false);
@ -65,29 +54,12 @@ export class AdminInterface extends WithLicenseSummary(AuthenticatedInterface) {
@query("ak-about-modal") @query("ak-about-modal")
aboutModal?: AboutModal; aboutModal?: AboutModal;
@property({ type: Boolean, reflect: true })
public sidebarOpen: boolean;
#toggleSidebar = () => {
this.sidebarOpen = !this.sidebarOpen;
};
#sidebarMatcher: MediaQueryList;
#sidebarListener = (event: MediaQueryListEvent) => {
this.sidebarOpen = event.matches;
};
//#endregion
//#region Styles
static get styles(): CSSResult[] { static get styles(): CSSResult[] {
return [ return [
PFBase, PFBase,
PFPage, PFPage,
PFButton, PFButton,
PFDrawer, PFDrawer,
PFNav,
css` css`
.pf-c-page__main, .pf-c-page__main,
.pf-c-drawer__content, .pf-c-drawer__content,
@ -95,30 +67,23 @@ export class AdminInterface extends WithLicenseSummary(AuthenticatedInterface) {
z-index: auto !important; z-index: auto !important;
background-color: transparent; background-color: transparent;
} }
.display-none { .display-none {
display: none; display: none;
} }
.pf-c-page { .pf-c-page {
background-color: var(--pf-c-page--BackgroundColor) !important; background-color: var(--pf-c-page--BackgroundColor) !important;
} }
:host([theme="dark"]) {
/* Global page background colour */ /* Global page background colour */
.pf-c-page { :host([theme="dark"]) .pf-c-page {
--pf-c-page--BackgroundColor: var(--ak-dark-background); --pf-c-page--BackgroundColor: var(--ak-dark-background);
} }
} ak-enterprise-status,
ak-version-banner {
ak-page-navbar {
grid-area: header; grid-area: header;
} }
ak-admin-sidebar {
.ak-sidebar {
grid-area: nav; grid-area: nav;
} }
.pf-c-drawer__panel { .pf-c-drawer__panel {
z-index: var(--pf-global--ZIndex--xl); z-index: var(--pf-global--ZIndex--xl);
} }
@ -126,23 +91,10 @@ export class AdminInterface extends WithLicenseSummary(AuthenticatedInterface) {
]; ];
} }
//#endregion
//#region Lifecycle
constructor() { constructor() {
super(); super();
this.ws = new WebsocketClient(); this.ws = new WebsocketClient();
this.#sidebarMatcher = window.matchMedia("(min-width: 1200px)");
this.sidebarOpen = this.#sidebarMatcher.matches;
}
public connectedCallback() {
super.connectedCallback();
window.addEventListener(EVENT_SIDEBAR_TOGGLE, this.#toggleSidebar);
window.addEventListener(EVENT_NOTIFICATION_DRAWER_TOGGLE, () => { window.addEventListener(EVENT_NOTIFICATION_DRAWER_TOGGLE, () => {
this.notificationDrawerOpen = !this.notificationDrawerOpen; this.notificationDrawerOpen = !this.notificationDrawerOpen;
updateURLParams({ updateURLParams({
@ -156,14 +108,6 @@ export class AdminInterface extends WithLicenseSummary(AuthenticatedInterface) {
apiDrawerOpen: this.apiDrawerOpen, apiDrawerOpen: this.apiDrawerOpen,
}); });
}); });
this.#sidebarMatcher.addEventListener("change", this.#sidebarListener);
}
public disconnectedCallback(): void {
super.disconnectedCallback();
window.removeEventListener(EVENT_SIDEBAR_TOGGLE, this.#toggleSidebar);
this.#sidebarMatcher.removeEventListener("change", this.#sidebarListener);
} }
async firstUpdated(): Promise<void> { async firstUpdated(): Promise<void> {
@ -174,7 +118,6 @@ export class AdminInterface extends WithLicenseSummary(AuthenticatedInterface) {
this.user.user.isSuperuser || this.user.user.isSuperuser ||
// TODO: somehow add `access_admin_interface` to the API schema // TODO: somehow add `access_admin_interface` to the API schema
this.user.user.systemPermissions.includes("access_admin_interface"); this.user.user.systemPermissions.includes("access_admin_interface");
if (!canAccessAdmin && this.user.user.pk > 0) { if (!canAccessAdmin && this.user.user.pk > 0) {
window.location.assign("/if/user/"); window.location.assign("/if/user/");
} }
@ -182,14 +125,10 @@ export class AdminInterface extends WithLicenseSummary(AuthenticatedInterface) {
render(): TemplateResult { render(): TemplateResult {
const sidebarClasses = { const sidebarClasses = {
"pf-c-page__sidebar": true,
"pf-m-light": this.activeTheme === UiThemeEnum.Light, "pf-m-light": this.activeTheme === UiThemeEnum.Light,
"pf-m-expanded": this.sidebarOpen,
"pf-m-collapsed": !this.sidebarOpen,
}; };
const drawerOpen = this.notificationDrawerOpen || this.apiDrawerOpen; const drawerOpen = this.notificationDrawerOpen || this.apiDrawerOpen;
const drawerClasses = { const drawerClasses = {
"pf-m-expanded": drawerOpen, "pf-m-expanded": drawerOpen,
"pf-m-collapsed": !drawerOpen, "pf-m-collapsed": !drawerOpen,
@ -197,18 +136,11 @@ export class AdminInterface extends WithLicenseSummary(AuthenticatedInterface) {
return html` <ak-locale-context> return html` <ak-locale-context>
<div class="pf-c-page"> <div class="pf-c-page">
<ak-page-navbar>
<ak-version-banner></ak-version-banner>
<ak-enterprise-status interface="admin"></ak-enterprise-status> <ak-enterprise-status interface="admin"></ak-enterprise-status>
</ak-page-navbar> <ak-version-banner></ak-version-banner>
<ak-admin-sidebar
<ak-sidebar class="${classMap(sidebarClasses)}"> class="pf-c-page__sidebar ${classMap(sidebarClasses)}"
${renderSidebarItems(AdminSidebarEntries)} ></ak-admin-sidebar>
${this.licenseSummary?.status !== LicenseSummaryStatusEnum.Unlicensed
? renderSidebarItems(AdminSidebarEnterpriseEntries)
: nothing}
</ak-sidebar>
<div class="pf-c-page__drawer"> <div class="pf-c-page__drawer">
<div class="pf-c-drawer ${classMap(drawerClasses)}"> <div class="pf-c-drawer ${classMap(drawerClasses)}">
<div class="pf-c-drawer__main"> <div class="pf-c-drawer__main">

View File

@ -1,77 +1,132 @@
import { EVENT_SIDEBAR_TOGGLE } from "@goauthentik/common/constants";
import { me } from "@goauthentik/common/users";
import { AKElement } from "@goauthentik/elements/Base";
import {
CapabilitiesEnum,
WithCapabilitiesConfig,
} from "@goauthentik/elements/Interface/capabilitiesProvider";
import { WithVersion } from "@goauthentik/elements/Interface/versionProvider";
import { ID_REGEX, SLUG_REGEX, UUID_REGEX } from "@goauthentik/elements/router/Route"; import { ID_REGEX, SLUG_REGEX, UUID_REGEX } from "@goauthentik/elements/router/Route";
import { getRootStyle } from "@goauthentik/elements/utils/getRootStyle";
import { spread } from "@open-wc/lit-helpers"; import { spread } from "@open-wc/lit-helpers";
import { msg } from "@lit/localize"; import { msg } from "@lit/localize";
import { TemplateResult, html, nothing } from "lit"; import { TemplateResult, html, nothing } from "lit";
import { repeat } from "lit/directives/repeat.js"; import { customElement, property, state } from "lit/decorators.js";
import { map } from "lit/directives/map.js";
// The second attribute type is of string[] to help with the 'activeWhen' control, which was import { UiThemeEnum } from "@goauthentik/api";
// commonplace and singular enough to merit its own handler. import type { SessionUser, UserSelf } from "@goauthentik/api";
type SidebarEntry = [
@customElement("ak-admin-sidebar")
export class AkAdminSidebar extends WithCapabilitiesConfig(WithVersion(AKElement)) {
@property({ type: Boolean, reflect: true })
open = true;
@state()
impersonation: UserSelf["username"] | null = null;
constructor() {
super();
me().then((user: SessionUser) => {
this.impersonation = user.original ? user.user.username : null;
});
this.toggleOpen = this.toggleOpen.bind(this);
this.checkWidth = this.checkWidth.bind(this);
}
// This has to be a bound method so the event listener can be removed on disconnection as
// needed.
toggleOpen() {
this.open = !this.open;
}
checkWidth() {
// This works just fine, but it assumes that the `--ak-sidebar--minimum-auto-width` is in
// REMs. If that changes, this code will have to be adjusted as well.
const minWidth =
parseFloat(getRootStyle("--ak-sidebar--minimum-auto-width")) *
parseFloat(getRootStyle("font-size"));
this.open = window.innerWidth >= minWidth;
}
connectedCallback() {
super.connectedCallback();
window.addEventListener(EVENT_SIDEBAR_TOGGLE, this.toggleOpen);
window.addEventListener("resize", this.checkWidth);
// After connecting to the DOM, we can now perform this check to see if the sidebar should
// be open by default.
this.checkWidth();
}
// The symmetry (☟, ☝) here is critical in that you want to start adding these handlers after
// connection, and removing them before disconnection.
disconnectedCallback() {
window.removeEventListener(EVENT_SIDEBAR_TOGGLE, this.toggleOpen);
window.removeEventListener("resize", this.checkWidth);
super.disconnectedCallback();
}
render() {
return html`
<ak-sidebar
class="pf-c-page__sidebar ${this.open ? "pf-m-expanded" : "pf-m-collapsed"} ${this
.activeTheme === UiThemeEnum.Light
? "pf-m-light"
: ""}"
>
${this.renderSidebarItems()}
</ak-sidebar>
`;
}
updated() {
// This is permissible as`:host.classList` is not one of the properties Lit uses as a
// scheduling trigger. This sort of shenanigans can trigger an loop, in that it will trigger
// a browser reflow, which may trigger some other styling the application is monitoring,
// triggering a re-render which triggers a browser reflow, ad infinitum. But we've been
// living with that since jQuery, and it's both well-known and fortunately rare.
// eslint-disable-next-line wc/no-self-class
this.classList.remove("pf-m-expanded", "pf-m-collapsed");
// eslint-disable-next-line wc/no-self-class
this.classList.add(this.open ? "pf-m-expanded" : "pf-m-collapsed");
}
renderSidebarItems(): TemplateResult {
// The second attribute type is of string[] to help with the 'activeWhen' control, which was
// commonplace and singular enough to merit its own handler.
type SidebarEntry = [
path: string | null, path: string | null,
label: string, label: string,
attributes?: Record<string, any> | string[] | null, // eslint-disable-line attributes?: Record<string, any> | string[] | null, // eslint-disable-line
children?: SidebarEntry[], children?: SidebarEntry[],
]; ];
/** // prettier-ignore
* Recursively renders a sidebar entry. const sidebarContent: SidebarEntry[] = [
*/
export function renderSidebarItem([
path,
label,
attributes,
children,
]: SidebarEntry): TemplateResult {
const properties = Array.isArray(attributes)
? { ".activeWhen": attributes }
: (attributes ?? {});
if (path) {
properties.path = path;
}
return html`<ak-sidebar-item ${spread(properties)}>
${label ? html`<span slot="label">${label}</span>` : nothing}
${children ? renderSidebarItems(children) : nothing}
</ak-sidebar-item>`;
}
/**
* Recursively renders a collection of sidebar entries.
*/
export function renderSidebarItems(entries: readonly SidebarEntry[]) {
return repeat(entries, ([path, label]) => path || label, renderSidebarItem);
}
// prettier-ignore
export const AdminSidebarEntries: readonly SidebarEntry[] = [
[null, msg("Dashboards"), { "?expanded": true }, [ [null, msg("Dashboards"), { "?expanded": true }, [
["/administration/overview", msg("Overview")], ["/administration/overview", msg("Overview")],
["/administration/dashboard/users", msg("User Statistics")], ["/administration/dashboard/users", msg("User Statistics")],
["/administration/system-tasks", msg("System Tasks")]] ["/administration/system-tasks", msg("System Tasks")]]],
],
[null, msg("Applications"), null, [ [null, msg("Applications"), null, [
["/core/applications", msg("Applications"), [`^/core/applications/(?<slug>${SLUG_REGEX})$`]], ["/core/applications", msg("Applications"), [`^/core/applications/(?<slug>${SLUG_REGEX})$`]],
["/core/providers", msg("Providers"), [`^/core/providers/(?<id>${ID_REGEX})$`]], ["/core/providers", msg("Providers"), [`^/core/providers/(?<id>${ID_REGEX})$`]],
["/outpost/outposts", msg("Outposts")]] ["/outpost/outposts", msg("Outposts")]]],
],
[null, msg("Events"), null, [ [null, msg("Events"), null, [
["/events/log", msg("Logs"), [`^/events/log/(?<id>${UUID_REGEX})$`]], ["/events/log", msg("Logs"), [`^/events/log/(?<id>${UUID_REGEX})$`]],
["/events/rules", msg("Notification Rules")], ["/events/rules", msg("Notification Rules")],
["/events/transports", msg("Notification Transports")]] ["/events/transports", msg("Notification Transports")]]],
],
[null, msg("Customization"), null, [ [null, msg("Customization"), null, [
["/policy/policies", msg("Policies")], ["/policy/policies", msg("Policies")],
["/core/property-mappings", msg("Property Mappings")], ["/core/property-mappings", msg("Property Mappings")],
["/blueprints/instances", msg("Blueprints")], ["/blueprints/instances", msg("Blueprints")],
["/policy/reputation", msg("Reputation scores")]] ["/policy/reputation", msg("Reputation scores")]]],
],
[null, msg("Flows and Stages"), null, [ [null, msg("Flows and Stages"), null, [
["/flow/flows", msg("Flows"), [`^/flow/flows/(?<slug>${SLUG_REGEX})$`]], ["/flow/flows", msg("Flows"), [`^/flow/flows/(?<slug>${SLUG_REGEX})$`]],
["/flow/stages", msg("Stages")], ["/flow/stages", msg("Stages")],
["/flow/stages/prompts", msg("Prompts")]] ["/flow/stages/prompts", msg("Prompts")]]],
],
[null, msg("Directory"), null, [ [null, msg("Directory"), null, [
["/identity/users", msg("Users"), [`^/identity/users/(?<id>${ID_REGEX})$`]], ["/identity/users", msg("Users"), [`^/identity/users/(?<id>${ID_REGEX})$`]],
["/identity/groups", msg("Groups"), [`^/identity/groups/(?<id>${UUID_REGEX})$`]], ["/identity/groups", msg("Groups"), [`^/identity/groups/(?<id>${UUID_REGEX})$`]],
@ -79,19 +134,53 @@ export const AdminSidebarEntries: readonly SidebarEntry[] = [
["/identity/initial-permissions", msg("Initial Permissions"), [`^/identity/initial-permissions/(?<id>${ID_REGEX})$`]], ["/identity/initial-permissions", msg("Initial Permissions"), [`^/identity/initial-permissions/(?<id>${ID_REGEX})$`]],
["/core/sources", msg("Federation and Social login"), [`^/core/sources/(?<slug>${SLUG_REGEX})$`]], ["/core/sources", msg("Federation and Social login"), [`^/core/sources/(?<slug>${SLUG_REGEX})$`]],
["/core/tokens", msg("Tokens and App passwords")], ["/core/tokens", msg("Tokens and App passwords")],
["/flow/stages/invitations", msg("Invitations")]] ["/flow/stages/invitations", msg("Invitations")]]],
],
[null, msg("System"), null, [ [null, msg("System"), null, [
["/core/brands", msg("Brands")], ["/core/brands", msg("Brands")],
["/crypto/certificates", msg("Certificates")], ["/crypto/certificates", msg("Certificates")],
["/outpost/integrations", msg("Outpost Integrations")], ["/outpost/integrations", msg("Outpost Integrations")],
["/admin/settings", msg("Settings")]] ["/admin/settings", msg("Settings")]]],
], ];
];
// prettier-ignore // Typescript requires the type here to correctly type the recursive path
export const AdminSidebarEnterpriseEntries: readonly SidebarEntry[] = [ type SidebarRenderer = (_: SidebarEntry) => TemplateResult;
[null, msg("Enterprise"), null, [
["/enterprise/licenses", msg("Licenses"), null] const renderOneSidebarItem: SidebarRenderer = ([path, label, attributes, children]) => {
], const properties = Array.isArray(attributes)
]] ? { ".activeWhen": attributes }
: (attributes ?? {});
if (path) {
properties.path = path;
}
return html`<ak-sidebar-item ${spread(properties)}>
${label ? html`<span slot="label">${label}</span>` : nothing}
${map(children, renderOneSidebarItem)}
</ak-sidebar-item>`;
};
// prettier-ignore
return html`
${map(sidebarContent, renderOneSidebarItem)}
${this.renderEnterpriseMenu()}
`;
}
renderEnterpriseMenu() {
return this.can(CapabilitiesEnum.IsEnterprise)
? html`
<ak-sidebar-item>
<span slot="label">${msg("Enterprise")}</span>
<ak-sidebar-item path="/enterprise/licenses">
<span slot="label">${msg("Licenses")}</span>
</ak-sidebar-item>
</ak-sidebar-item>
`
: nothing;
}
}
declare global {
interface HTMLElementTagNameMap {
"ak-admin-sidebar": AkAdminSidebar;
}
}

View File

@ -0,0 +1,5 @@
import { AdminInterface } from "./AdminInterface";
import "./AdminInterface";
export { AdminInterface };
export default AdminInterface;

View File

@ -94,13 +94,10 @@ export class AdminOverviewPage extends AdminOverviewBase {
} }
render(): TemplateResult { render(): TemplateResult {
const username = this.user?.user.name || this.user?.user.username; const name = this.user?.user.name ?? this.user?.user.username;
return html` <ak-page-header return html`<ak-page-header description=${msg("General system status")} ?hasIcon=${false}>
header=${msg(str`Welcome, ${username || ""}.`)} <span slot="header"> ${msg(str`Welcome, ${name || ""}.`)} </span>
description=${msg("General system status")}
?hasIcon=${false}
>
</ak-page-header> </ak-page-header>
<section class="pf-c-page__main-section"> <section class="pf-c-page__main-section">
<div class="pf-l-grid pf-m-gutter"> <div class="pf-l-grid pf-m-gutter">

View File

@ -1,4 +1,5 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/components/ak-number-input"; import "@goauthentik/components/ak-number-input";
import "@goauthentik/components/ak-switch-input"; import "@goauthentik/components/ak-switch-input";
import "@goauthentik/components/ak-text-input"; import "@goauthentik/components/ak-text-input";
@ -183,14 +184,20 @@ export class AdminSettingsForm extends Form<SettingsRequest> {
label=${msg("Reputation: lower limit")} label=${msg("Reputation: lower limit")}
required required
name="reputationLowerLimit" name="reputationLowerLimit"
value="${this._settings?.reputationLowerLimit ?? DEFAULT_REPUTATION_LOWER_LIMIT}" value="${first(
this._settings?.reputationLowerLimit,
DEFAULT_REPUTATION_LOWER_LIMIT,
)}"
help=${msg("Reputation cannot decrease lower than this value. Zero or negative.")} help=${msg("Reputation cannot decrease lower than this value. Zero or negative.")}
></ak-number-input> ></ak-number-input>
<ak-number-input <ak-number-input
label=${msg("Reputation: upper limit")} label=${msg("Reputation: upper limit")}
required required
name="reputationUpperLimit" name="reputationUpperLimit"
value="${this._settings?.reputationUpperLimit ?? DEFAULT_REPUTATION_UPPER_LIMIT}" value="${first(
this._settings?.reputationUpperLimit,
DEFAULT_REPUTATION_UPPER_LIMIT,
)}"
help=${msg("Reputation cannot increase higher than this value. Zero or positive.")} help=${msg("Reputation cannot increase higher than this value. Zero or positive.")}
></ak-number-input> ></ak-number-input>
<ak-form-element-horizontal label=${msg("Footer links")} name="footerLinks"> <ak-form-element-horizontal label=${msg("Footer links")} name="footerLinks">
@ -250,7 +257,7 @@ export class AdminSettingsForm extends Form<SettingsRequest> {
label=${msg("Default token length")} label=${msg("Default token length")}
required required
name="defaultTokenLength" name="defaultTokenLength"
value="${this._settings?.defaultTokenLength ?? 60}" value="${first(this._settings?.defaultTokenLength, 60)}"
help=${msg("Default length of generated tokens")} help=${msg("Default length of generated tokens")}
></ak-number-input> ></ak-number-input>
`; `;

View File

@ -83,10 +83,13 @@ export class AdminSettingsPage extends AKElement {
} }
render() { render() {
if (!this.settings) return nothing; if (!this.settings) {
return nothing;
}
return html` return html`
<ak-page-header icon="fa fa-cog" header="${msg("System settings")}"> </ak-page-header> <ak-page-header icon="fa fa-cog" header="" description="">
<span slot="header"> ${msg("System settings")} </span>
</ak-page-header>
<section class="pf-c-page__main-section pf-m-no-padding-mobile pf-l-grid pf-m-gutter"> <section class="pf-c-page__main-section pf-m-no-padding-mobile pf-l-grid pf-m-gutter">
<div class="pf-c-card"> <div class="pf-c-card">
<div class="pf-c-card__body"> <div class="pf-c-card__body">

View File

@ -1,6 +1,7 @@
import "@goauthentik/admin/applications/ProviderSelectModal"; import "@goauthentik/admin/applications/ProviderSelectModal";
import { iconHelperText } from "@goauthentik/admin/helperText"; import { iconHelperText } from "@goauthentik/admin/helperText";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/components/ak-file-input"; import "@goauthentik/components/ak-file-input";
import "@goauthentik/components/ak-radio-input"; import "@goauthentik/components/ak-radio-input";
import "@goauthentik/components/ak-switch-input"; import "@goauthentik/components/ak-switch-input";
@ -193,7 +194,7 @@ export class ApplicationForm extends WithCapabilitiesConfig(ModelForm<Applicatio
></ak-text-input> ></ak-text-input>
<ak-switch-input <ak-switch-input
name="openInNewTab" name="openInNewTab"
?checked=${this.instance?.openInNewTab ?? false} ?checked=${first(this.instance?.openInNewTab, false)}
label=${msg("Open in new tab")} label=${msg("Open in new tab")}
help=${msg( help=${msg(
"If checked, the launch URL will open in a new browser tab or window from the user's application library.", "If checked, the launch URL will open in a new browser tab or window from the user's application library.",
@ -220,7 +221,7 @@ export class ApplicationForm extends WithCapabilitiesConfig(ModelForm<Applicatio
: html` <ak-text-input : html` <ak-text-input
label=${msg("Icon")} label=${msg("Icon")}
name="metaIcon" name="metaIcon"
value=${this.instance?.metaIcon ?? ""} value=${first(this.instance?.metaIcon, "")}
help=${iconHelperText} help=${iconHelperText}
> >
</ak-text-input>`} </ak-text-input>`}

View File

@ -1,4 +1,5 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/CodeMirror"; import "@goauthentik/elements/CodeMirror";
import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror"; import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
@ -59,7 +60,7 @@ export class ApplicationEntitlementForm extends ModelForm<ApplicationEntitlement
return html` <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name"> return html` <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
<input <input
type="text" type="text"
value="${this.instance?.name ?? ""}" value="${first(this.instance?.name, "")}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -71,7 +72,7 @@ export class ApplicationEntitlementForm extends ModelForm<ApplicationEntitlement
> >
<ak-codemirror <ak-codemirror
mode=${CodeMirrorMode.YAML} mode=${CodeMirrorMode.YAML}
value="${YAML.stringify(this.instance?.attributes ?? {})}" value="${YAML.stringify(first(this.instance?.attributes, {}))}"
> >
</ak-codemirror> </ak-codemirror>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">

View File

@ -1,6 +1,7 @@
import { policyOptions } from "@goauthentik/admin/applications/PolicyOptions.js"; import { policyOptions } from "@goauthentik/admin/applications/PolicyOptions.js";
import { ApplicationWizardStep } from "@goauthentik/admin/applications/wizard/ApplicationWizardStep.js"; import { ApplicationWizardStep } from "@goauthentik/admin/applications/wizard/ApplicationWizardStep.js";
import "@goauthentik/admin/applications/wizard/ak-wizard-title.js"; import "@goauthentik/admin/applications/wizard/ak-wizard-title.js";
import { isSlug } from "@goauthentik/common/utils.js";
import { camelToSnake } from "@goauthentik/common/utils.js"; import { camelToSnake } from "@goauthentik/common/utils.js";
import "@goauthentik/components/ak-radio-input"; import "@goauthentik/components/ak-radio-input";
import "@goauthentik/components/ak-slug-input"; import "@goauthentik/components/ak-slug-input";
@ -10,7 +11,6 @@ import { type NavigableButton, type WizardButton } from "@goauthentik/components
import { type KeyUnknown } from "@goauthentik/elements/forms/Form"; import { type KeyUnknown } from "@goauthentik/elements/forms/Form";
import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import { isSlug } from "@goauthentik/elements/router/utils.js";
import { msg } from "@lit/localize"; import { msg } from "@lit/localize";
import { html } from "lit"; import { html } from "lit";

View File

@ -1,5 +1,6 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { docLink } from "@goauthentik/common/global"; import { docLink } from "@goauthentik/common/global";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/components/ak-toggle-group"; import "@goauthentik/components/ak-toggle-group";
import "@goauthentik/elements/CodeMirror"; import "@goauthentik/elements/CodeMirror";
import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror"; import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror";
@ -79,7 +80,7 @@ export class BlueprintForm extends ModelForm<BlueprintInstance, string> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.enabled ?? true} ?checked=${first(this.instance?.enabled, true)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -183,7 +184,7 @@ export class BlueprintForm extends ModelForm<BlueprintInstance, string> {
<ak-form-element-horizontal label=${msg("Context")} name="context"> <ak-form-element-horizontal label=${msg("Context")} name="context">
<ak-codemirror <ak-codemirror
mode=${CodeMirrorMode.YAML} mode=${CodeMirrorMode.YAML}
value="${YAML.stringify(this.instance?.context ?? {})}" value="${YAML.stringify(first(this.instance?.context, {}))}"
> >
</ak-codemirror> </ak-codemirror>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">

View File

@ -1,13 +1,14 @@
import "@goauthentik/admin/common/ak-crypto-certificate-search"; import "@goauthentik/admin/common/ak-crypto-certificate-search";
import "@goauthentik/admin/common/ak-flow-search/ak-flow-search"; import "@goauthentik/admin/common/ak-flow-search/ak-flow-search";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { DefaultBrand } from "@goauthentik/common/ui/config"; import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/CodeMirror"; import "@goauthentik/elements/CodeMirror";
import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror"; import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror";
import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
import "@goauthentik/elements/forms/SearchSelect"; import "@goauthentik/elements/forms/SearchSelect";
import { DefaultBrand } from "@goauthentik/elements/sidebar/SidebarBrand";
import YAML from "yaml"; import YAML from "yaml";
import { msg } from "@lit/localize"; import { msg } from "@lit/localize";
@ -53,7 +54,7 @@ export class BrandForm extends ModelForm<Brand, string> {
return html` <ak-form-element-horizontal label=${msg("Domain")} required name="domain"> return html` <ak-form-element-horizontal label=${msg("Domain")} required name="domain">
<input <input
type="text" type="text"
value="${this.instance?.domain ?? window.location.host}" value="${first(this.instance?.domain, window.location.host)}"
class="pf-c-form-control pf-m-monospace" class="pf-c-form-control pf-m-monospace"
autocomplete="off" autocomplete="off"
spellcheck="false" spellcheck="false"
@ -71,7 +72,7 @@ export class BrandForm extends ModelForm<Brand, string> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?._default ?? false} ?checked=${first(this.instance?._default, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -91,7 +92,10 @@ export class BrandForm extends ModelForm<Brand, string> {
<ak-form-element-horizontal label=${msg("Title")} required name="brandingTitle"> <ak-form-element-horizontal label=${msg("Title")} required name="brandingTitle">
<input <input
type="text" type="text"
value="${this.instance?.brandingTitle ?? DefaultBrand.brandingTitle}" value="${first(
this.instance?.brandingTitle,
DefaultBrand.brandingTitle,
)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -102,7 +106,7 @@ export class BrandForm extends ModelForm<Brand, string> {
<ak-form-element-horizontal label=${msg("Logo")} required name="brandingLogo"> <ak-form-element-horizontal label=${msg("Logo")} required name="brandingLogo">
<input <input
type="text" type="text"
value="${this.instance?.brandingLogo ?? DefaultBrand.brandingLogo}" value="${first(this.instance?.brandingLogo, DefaultBrand.brandingLogo)}"
class="pf-c-form-control pf-m-monospace" class="pf-c-form-control pf-m-monospace"
autocomplete="off" autocomplete="off"
spellcheck="false" spellcheck="false"
@ -119,8 +123,10 @@ export class BrandForm extends ModelForm<Brand, string> {
> >
<input <input
type="text" type="text"
value="${this.instance?.brandingFavicon ?? value="${first(
DefaultBrand.brandingFavicon}" this.instance?.brandingFavicon,
DefaultBrand.brandingFavicon,
)}"
class="pf-c-form-control pf-m-monospace" class="pf-c-form-control pf-m-monospace"
autocomplete="off" autocomplete="off"
spellcheck="false" spellcheck="false"
@ -137,8 +143,10 @@ export class BrandForm extends ModelForm<Brand, string> {
> >
<input <input
type="text" type="text"
value="${this.instance?.brandingDefaultFlowBackground ?? value="${first(
"/static/dist/assets/images/flow_background.jpg"}" this.instance?.brandingDefaultFlowBackground,
"/static/dist/assets/images/flow_background.jpg",
)}"
class="pf-c-form-control pf-m-monospace" class="pf-c-form-control pf-m-monospace"
autocomplete="off" autocomplete="off"
spellcheck="false" spellcheck="false"
@ -157,8 +165,10 @@ export class BrandForm extends ModelForm<Brand, string> {
> >
<ak-codemirror <ak-codemirror
mode=${CodeMirrorMode.CSS} mode=${CodeMirrorMode.CSS}
value="${this.instance?.brandingCustomCss ?? value="${first(
DefaultBrand.brandingCustomCss}" this.instance?.brandingCustomCss,
DefaultBrand.brandingCustomCss,
)}"
> >
</ak-codemirror> </ak-codemirror>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
@ -307,7 +317,7 @@ export class BrandForm extends ModelForm<Brand, string> {
<ak-form-element-horizontal label=${msg("Attributes")} name="attributes"> <ak-form-element-horizontal label=${msg("Attributes")} name="attributes">
<ak-codemirror <ak-codemirror
mode=${CodeMirrorMode.YAML} mode=${CodeMirrorMode.YAML}
value="${YAML.stringify(this.instance?.attributes ?? {})}" value="${YAML.stringify(first(this.instance?.attributes, {}))}"
> >
</ak-codemirror> </ak-codemirror>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">

View File

@ -1,4 +1,5 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
import "@goauthentik/elements/forms/Radio"; import "@goauthentik/elements/forms/Radio";
@ -184,7 +185,7 @@ export class TransportForm extends ModelForm<NotificationTransport, string> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.sendOnce ?? false} ?checked=${first(this.instance?.sendOnce, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">

View File

@ -1,6 +1,7 @@
import { DesignationToLabel, LayoutToLabel } from "@goauthentik/admin/flows/utils"; import { DesignationToLabel, LayoutToLabel } from "@goauthentik/admin/flows/utils";
import { AuthenticationEnum } from "@goauthentik/api/dist/models/AuthenticationEnum"; import { AuthenticationEnum } from "@goauthentik/api/dist/models/AuthenticationEnum";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import { import {
CapabilitiesEnum, CapabilitiesEnum,
WithCapabilitiesConfig, WithCapabilitiesConfig,
@ -226,7 +227,7 @@ export class FlowForm extends WithCapabilitiesConfig(ModelForm<Flow, string>) {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.compatibilityMode ?? false} ?checked=${first(this.instance?.compatibilityMode, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -406,7 +407,7 @@ export class FlowForm extends WithCapabilitiesConfig(ModelForm<Flow, string>) {
> >
<input <input
type="text" type="text"
value="${this.instance?.background ?? ""}" value="${first(this.instance?.background, "")}"
class="pf-c-form-control" class="pf-c-form-control"
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">

View File

@ -1,5 +1,5 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { groupBy } from "@goauthentik/common/utils"; import { first, groupBy } from "@goauthentik/common/utils";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
import "@goauthentik/elements/forms/Radio"; import "@goauthentik/elements/forms/Radio";
@ -123,7 +123,7 @@ export class StageBindingForm extends ModelForm<FlowStageBinding, string> {
<ak-form-element-horizontal label=${msg("Order")} ?required=${true} name="order"> <ak-form-element-horizontal label=${msg("Order")} ?required=${true} name="order">
<input <input
type="number" type="number"
value="${this.instance?.order ?? this.defaultOrder}" value="${first(this.instance?.order, this.defaultOrder)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -133,7 +133,7 @@ export class StageBindingForm extends ModelForm<FlowStageBinding, string> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.evaluateOnPlan ?? false} ?checked=${first(this.instance?.evaluateOnPlan, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -151,7 +151,7 @@ export class StageBindingForm extends ModelForm<FlowStageBinding, string> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.reEvaluatePolicies ?? true} ?checked=${first(this.instance?.reEvaluatePolicies, true)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">

View File

@ -1,5 +1,6 @@
import "@goauthentik/admin/groups/MemberSelectModal"; import "@goauthentik/admin/groups/MemberSelectModal";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/CodeMirror"; import "@goauthentik/elements/CodeMirror";
import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror"; import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror";
import "@goauthentik/elements/ak-dual-select/ak-dual-select-provider"; import "@goauthentik/elements/ak-dual-select/ak-dual-select-provider";
@ -76,7 +77,7 @@ export class GroupForm extends ModelForm<Group, string> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.isSuperuser ?? false} ?checked=${first(this.instance?.isSuperuser, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -149,7 +150,7 @@ export class GroupForm extends ModelForm<Group, string> {
> >
<ak-codemirror <ak-codemirror
mode=${CodeMirrorMode.YAML} mode=${CodeMirrorMode.YAML}
value="${YAML.stringify(this.instance?.attributes ?? {})}" value="${YAML.stringify(first(this.instance?.attributes, {}))}"
> >
</ak-codemirror> </ak-codemirror>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">

View File

@ -1,5 +1,6 @@
import "@goauthentik/admin/common/ak-crypto-certificate-search"; import "@goauthentik/admin/common/ak-crypto-certificate-search";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
import "@goauthentik/elements/forms/SearchSelect"; import "@goauthentik/elements/forms/SearchSelect";
@ -52,7 +53,7 @@ export class ServiceConnectionDockerForm extends ModelForm<DockerServiceConnecti
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.local ?? false} ?checked=${first(this.instance?.local, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">

View File

@ -1,4 +1,5 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/CodeMirror"; import "@goauthentik/elements/CodeMirror";
import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror"; import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
@ -56,7 +57,7 @@ export class ServiceConnectionKubernetesForm extends ModelForm<
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.local ?? false} ?checked=${first(this.instance?.local, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -74,7 +75,7 @@ export class ServiceConnectionKubernetesForm extends ModelForm<
<ak-form-element-horizontal label=${msg("Kubeconfig")} name="kubeconfig"> <ak-form-element-horizontal label=${msg("Kubeconfig")} name="kubeconfig">
<ak-codemirror <ak-codemirror
mode=${CodeMirrorMode.YAML} mode=${CodeMirrorMode.YAML}
value="${YAML.stringify(this.instance?.kubeconfig ?? {})}" value="${YAML.stringify(first(this.instance?.kubeconfig, {}))}"
> >
</ak-codemirror> </ak-codemirror>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
@ -86,7 +87,7 @@ export class ServiceConnectionKubernetesForm extends ModelForm<
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.verifySsl ?? true} ?checked=${first(this.instance?.verifySsl, true)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">

View File

@ -3,7 +3,7 @@ import {
PolicyBindingCheckTargetToLabel, PolicyBindingCheckTargetToLabel,
} from "@goauthentik/admin/policies/utils"; } from "@goauthentik/admin/policies/utils";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { groupBy } from "@goauthentik/common/utils"; import { first, groupBy } from "@goauthentik/common/utils";
import "@goauthentik/components/ak-toggle-group"; import "@goauthentik/components/ak-toggle-group";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import { ModelForm } from "@goauthentik/elements/forms/ModelForm"; import { ModelForm } from "@goauthentik/elements/forms/ModelForm";
@ -274,7 +274,7 @@ export class PolicyBindingForm extends ModelForm<PolicyBinding, string> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.enabled ?? true} ?checked=${first(this.instance?.enabled, true)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -289,7 +289,7 @@ export class PolicyBindingForm extends ModelForm<PolicyBinding, string> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.negate ?? false} ?checked=${first(this.instance?.negate, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -305,7 +305,7 @@ export class PolicyBindingForm extends ModelForm<PolicyBinding, string> {
<ak-form-element-horizontal label=${msg("Order")} ?required=${true} name="order"> <ak-form-element-horizontal label=${msg("Order")} ?required=${true} name="order">
<input <input
type="number" type="number"
value="${this.instance?.order ?? this.defaultOrder}" value="${first(this.instance?.order, this.defaultOrder)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -313,7 +313,7 @@ export class PolicyBindingForm extends ModelForm<PolicyBinding, string> {
<ak-form-element-horizontal label=${msg("Timeout")} ?required=${true} name="timeout"> <ak-form-element-horizontal label=${msg("Timeout")} ?required=${true} name="timeout">
<input <input
type="number" type="number"
value="${this.instance?.timeout ?? 30}" value="${first(this.instance?.timeout, 30)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />

View File

@ -1,4 +1,5 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/components/ak-status-label"; import "@goauthentik/components/ak-status-label";
import "@goauthentik/elements/CodeMirror"; import "@goauthentik/elements/CodeMirror";
import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror"; import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror";
@ -124,7 +125,7 @@ export class PolicyTestForm extends Form<PolicyTestRequest> {
<ak-form-element-horizontal label=${msg("Context")} name="context"> <ak-form-element-horizontal label=${msg("Context")} name="context">
<ak-codemirror <ak-codemirror
mode=${CodeMirrorMode.YAML} mode=${CodeMirrorMode.YAML}
value=${YAML.stringify(this.request?.context ?? {})} value=${YAML.stringify(first(this.request?.context, {}))}
> >
</ak-codemirror> </ak-codemirror>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">

View File

@ -1,5 +1,6 @@
import { BasePolicyForm } from "@goauthentik/admin/policies/BasePolicyForm"; import { BasePolicyForm } from "@goauthentik/admin/policies/BasePolicyForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
@ -50,7 +51,7 @@ export class DummyPolicyForm extends BasePolicyForm<DummyPolicy> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.executionLogging ?? false} ?checked=${first(this.instance?.executionLogging, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -73,7 +74,7 @@ export class DummyPolicyForm extends BasePolicyForm<DummyPolicy> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.result ?? false} ?checked=${first(this.instance?.result, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -90,7 +91,7 @@ export class DummyPolicyForm extends BasePolicyForm<DummyPolicy> {
> >
<input <input
type="number" type="number"
value="${this.instance?.waitMin ?? 1}" value="${first(this.instance?.waitMin, 1)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -107,7 +108,7 @@ export class DummyPolicyForm extends BasePolicyForm<DummyPolicy> {
> >
<input <input
type="number" type="number"
value="${this.instance?.waitMax ?? 5}" value="${first(this.instance?.waitMax, 5)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />

View File

@ -1,5 +1,6 @@
import { BasePolicyForm } from "@goauthentik/admin/policies/BasePolicyForm"; import { BasePolicyForm } from "@goauthentik/admin/policies/BasePolicyForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import "@goauthentik/elements/forms/SearchSelect"; import "@goauthentik/elements/forms/SearchSelect";
@ -62,7 +63,7 @@ export class EventMatcherPolicyForm extends BasePolicyForm<EventMatcherPolicy> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.executionLogging ?? false} ?checked=${first(this.instance?.executionLogging, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">

View File

@ -1,5 +1,6 @@
import { BasePolicyForm } from "@goauthentik/admin/policies/BasePolicyForm"; import { BasePolicyForm } from "@goauthentik/admin/policies/BasePolicyForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
@ -50,7 +51,7 @@ export class PasswordExpiryPolicyForm extends BasePolicyForm<PasswordExpiryPolic
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.executionLogging ?? false} ?checked=${first(this.instance?.executionLogging, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -85,7 +86,7 @@ export class PasswordExpiryPolicyForm extends BasePolicyForm<PasswordExpiryPolic
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.denyOnly ?? false} ?checked=${first(this.instance?.denyOnly, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">

View File

@ -1,6 +1,7 @@
import { BasePolicyForm } from "@goauthentik/admin/policies/BasePolicyForm"; import { BasePolicyForm } from "@goauthentik/admin/policies/BasePolicyForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { docLink } from "@goauthentik/common/global"; import { docLink } from "@goauthentik/common/global";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/CodeMirror"; import "@goauthentik/elements/CodeMirror";
import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror"; import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror";
import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/FormGroup";
@ -53,7 +54,7 @@ export class ExpressionPolicyForm extends BasePolicyForm<ExpressionPolicy> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.executionLogging ?? false} ?checked=${first(this.instance?.executionLogging, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">

View File

@ -1,5 +1,6 @@
import { BasePolicyForm } from "@goauthentik/admin/policies/BasePolicyForm"; import { BasePolicyForm } from "@goauthentik/admin/policies/BasePolicyForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/ak-dual-select"; import "@goauthentik/elements/ak-dual-select";
import { DataProvision, DualSelectPair } from "@goauthentik/elements/ak-dual-select/types"; import { DataProvision, DualSelectPair } from "@goauthentik/elements/ak-dual-select/types";
import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/FormGroup";
@ -111,7 +112,7 @@ export class GeoIPPolicyForm extends BasePolicyForm<GeoIPPolicy> {
<input <input
type="number" type="number"
min="1" min="1"
value="${this.instance?.historyMaxDistanceKm ?? 100}" value="${first(this.instance?.historyMaxDistanceKm, 100)}"
class="pf-c-form-control" class="pf-c-form-control"
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
@ -127,7 +128,7 @@ export class GeoIPPolicyForm extends BasePolicyForm<GeoIPPolicy> {
<input <input
type="number" type="number"
min="1" min="1"
value="${this.instance?.distanceToleranceKm ?? 50}" value="${first(this.instance?.distanceToleranceKm, 50)}"
class="pf-c-form-control" class="pf-c-form-control"
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
@ -141,7 +142,7 @@ export class GeoIPPolicyForm extends BasePolicyForm<GeoIPPolicy> {
<input <input
type="number" type="number"
min="1" min="1"
value="${this.instance?.historyLoginCount ?? 5}" value="${first(this.instance?.historyLoginCount, 5)}"
class="pf-c-form-control" class="pf-c-form-control"
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
@ -177,7 +178,7 @@ export class GeoIPPolicyForm extends BasePolicyForm<GeoIPPolicy> {
<input <input
type="number" type="number"
min="1" min="1"
value="${this.instance?.impossibleToleranceKm ?? 50}" value="${first(this.instance?.impossibleToleranceKm, 50)}"
class="pf-c-form-control" class="pf-c-form-control"
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">

View File

@ -1,5 +1,6 @@
import { BasePolicyForm } from "@goauthentik/admin/policies/BasePolicyForm"; import { BasePolicyForm } from "@goauthentik/admin/policies/BasePolicyForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
@ -55,7 +56,7 @@ export class PasswordPolicyForm extends BasePolicyForm<PasswordPolicy> {
> >
<input <input
type="number" type="number"
value="${this.instance?.lengthMin ?? 10}" value="${first(this.instance?.lengthMin, 10)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -67,7 +68,7 @@ export class PasswordPolicyForm extends BasePolicyForm<PasswordPolicy> {
> >
<input <input
type="number" type="number"
value="${this.instance?.amountUppercase ?? 2}" value="${first(this.instance?.amountUppercase, 2)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -79,7 +80,7 @@ export class PasswordPolicyForm extends BasePolicyForm<PasswordPolicy> {
> >
<input <input
type="number" type="number"
value="${this.instance?.amountLowercase ?? 2}" value="${first(this.instance?.amountLowercase, 2)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -91,7 +92,7 @@ export class PasswordPolicyForm extends BasePolicyForm<PasswordPolicy> {
> >
<input <input
type="number" type="number"
value="${this.instance?.amountDigits ?? 2}" value="${first(this.instance?.amountDigits, 2)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -103,7 +104,7 @@ export class PasswordPolicyForm extends BasePolicyForm<PasswordPolicy> {
> >
<input <input
type="number" type="number"
value="${this.instance?.amountSymbols ?? 2}" value="${first(this.instance?.amountSymbols, 2)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -153,7 +154,7 @@ export class PasswordPolicyForm extends BasePolicyForm<PasswordPolicy> {
> >
<input <input
type="number" type="number"
value="${this.instance?.hibpAllowedCount ?? 0}" value="${first(this.instance?.hibpAllowedCount, 0)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -178,7 +179,7 @@ export class PasswordPolicyForm extends BasePolicyForm<PasswordPolicy> {
> >
<input <input
type="number" type="number"
value="${this.instance?.zxcvbnScoreThreshold ?? 0}" value="${first(this.instance?.zxcvbnScoreThreshold, 0)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -235,7 +236,7 @@ export class PasswordPolicyForm extends BasePolicyForm<PasswordPolicy> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.executionLogging ?? false} ?checked=${first(this.instance?.executionLogging, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -271,7 +272,7 @@ export class PasswordPolicyForm extends BasePolicyForm<PasswordPolicy> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.checkStaticRules ?? true} ?checked=${first(this.instance?.checkStaticRules, true)}
@change=${(ev: Event) => { @change=${(ev: Event) => {
const el = ev.target as HTMLInputElement; const el = ev.target as HTMLInputElement;
this.showStatic = el.checked; this.showStatic = el.checked;
@ -290,7 +291,7 @@ export class PasswordPolicyForm extends BasePolicyForm<PasswordPolicy> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.checkHaveIBeenPwned ?? true} ?checked=${first(this.instance?.checkHaveIBeenPwned, true)}
@change=${(ev: Event) => { @change=${(ev: Event) => {
const el = ev.target as HTMLInputElement; const el = ev.target as HTMLInputElement;
this.showHIBP = el.checked; this.showHIBP = el.checked;
@ -315,7 +316,7 @@ export class PasswordPolicyForm extends BasePolicyForm<PasswordPolicy> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.checkZxcvbn ?? true} ?checked=${first(this.instance?.checkZxcvbn, true)}
@change=${(ev: Event) => { @change=${(ev: Event) => {
const el = ev.target as HTMLInputElement; const el = ev.target as HTMLInputElement;
this.showZxcvbn = el.checked; this.showZxcvbn = el.checked;

View File

@ -1,5 +1,6 @@
import { BasePolicyForm } from "@goauthentik/admin/policies/BasePolicyForm"; import { BasePolicyForm } from "@goauthentik/admin/policies/BasePolicyForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
@ -60,7 +61,7 @@ doesn't pass when either or both of the selected options are equal or above the
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.executionLogging ?? false} ?checked=${first(this.instance?.executionLogging, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -83,7 +84,7 @@ doesn't pass when either or both of the selected options are equal or above the
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.checkIp ?? true} ?checked=${first(this.instance?.checkIp, true)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -98,7 +99,7 @@ doesn't pass when either or both of the selected options are equal or above the
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.checkUsername ?? false} ?checked=${first(this.instance?.checkUsername, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">

View File

@ -1,5 +1,6 @@
import { BasePolicyForm } from "@goauthentik/admin/policies/BasePolicyForm"; import { BasePolicyForm } from "@goauthentik/admin/policies/BasePolicyForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
@ -50,7 +51,7 @@ export class UniquePasswordPolicyForm extends BasePolicyForm<UniquePasswordPolic
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.executionLogging ?? false} ?checked=${first(this.instance?.executionLogging, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -87,7 +88,7 @@ export class UniquePasswordPolicyForm extends BasePolicyForm<UniquePasswordPolic
> >
<input <input
type="number" type="number"
value="${this.instance?.numHistoricalPasswords ?? 1}" value="${first(this.instance?.numHistoricalPasswords, 1)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />

View File

@ -1,4 +1,5 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/CodeMirror"; import "@goauthentik/elements/CodeMirror";
import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror"; import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror";
import { Form } from "@goauthentik/elements/forms/Form"; import { Form } from "@goauthentik/elements/forms/Form";
@ -180,7 +181,7 @@ export class PolicyTestForm extends Form<PropertyMappingTestRequest> {
<ak-form-element-horizontal label=${msg("Context")} name="context"> <ak-form-element-horizontal label=${msg("Context")} name="context">
<ak-codemirror <ak-codemirror
mode=${CodeMirrorMode.YAML} mode=${CodeMirrorMode.YAML}
value=${YAML.stringify(this.request?.context ?? {})} value=${YAML.stringify(first(this.request?.context, {}))}
> >
</ak-codemirror> </ak-codemirror>
<p class="pf-c-form__helper-text">${this.renderExampleButtons()}</p> <p class="pf-c-form__helper-text">${this.renderExampleButtons()}</p>

View File

@ -4,6 +4,7 @@ import {
propertyMappingsSelector, propertyMappingsSelector,
} from "@goauthentik/admin/providers/google_workspace/GoogleWorkspaceProviderFormHelpers.js"; } from "@goauthentik/admin/providers/google_workspace/GoogleWorkspaceProviderFormHelpers.js";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/CodeMirror"; import "@goauthentik/elements/CodeMirror";
import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror"; import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror";
import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js"; import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js";
@ -67,7 +68,7 @@ export class GoogleWorkspaceProviderFormPage extends BaseProviderForm<GoogleWork
> >
<ak-codemirror <ak-codemirror
mode=${CodeMirrorMode.JavaScript} mode=${CodeMirrorMode.JavaScript}
.value="${this.instance?.credentials ?? {}}" .value="${first(this.instance?.credentials, {})}"
></ak-codemirror> ></ak-codemirror>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${msg("Google Cloud credentials file.")} ${msg("Google Cloud credentials file.")}
@ -80,7 +81,7 @@ export class GoogleWorkspaceProviderFormPage extends BaseProviderForm<GoogleWork
> >
<input <input
type="email" type="email"
value="${this.instance?.delegatedSubject ?? ""}" value="${first(this.instance?.delegatedSubject, "")}"
class="pf-c-form-control pf-m-monospace" class="pf-c-form-control pf-m-monospace"
required required
/> />
@ -97,7 +98,7 @@ export class GoogleWorkspaceProviderFormPage extends BaseProviderForm<GoogleWork
> >
<input <input
type="text" type="text"
value="${this.instance?.defaultGroupEmailDomain ?? ""}" value="${first(this.instance?.defaultGroupEmailDomain, "")}"
class="pf-c-form-control pf-m-monospace" class="pf-c-form-control pf-m-monospace"
required required
/> />
@ -165,7 +166,7 @@ export class GoogleWorkspaceProviderFormPage extends BaseProviderForm<GoogleWork
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.dryRun ?? false} ?checked=${first(this.instance?.dryRun, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -190,7 +191,7 @@ export class GoogleWorkspaceProviderFormPage extends BaseProviderForm<GoogleWork
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.excludeUsersServiceAccount ?? true} ?checked=${first(this.instance?.excludeUsersServiceAccount, true)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">

View File

@ -4,6 +4,7 @@ import {
propertyMappingsSelector, propertyMappingsSelector,
} from "@goauthentik/admin/providers/microsoft_entra/MicrosoftEntraProviderFormHelpers.js"; } from "@goauthentik/admin/providers/microsoft_entra/MicrosoftEntraProviderFormHelpers.js";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js"; import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js";
import "@goauthentik/elements/ak-dual-select/ak-dual-select-provider.js"; import "@goauthentik/elements/ak-dual-select/ak-dual-select-provider.js";
import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/FormGroup";
@ -65,7 +66,7 @@ export class MicrosoftEntraProviderFormPage extends BaseProviderForm<MicrosoftEn
> >
<input <input
type="text" type="text"
value="${this.instance?.clientId ?? ""}" value="${first(this.instance?.clientId, "")}"
class="pf-c-form-control pf-m-monospace" class="pf-c-form-control pf-m-monospace"
required required
/> />
@ -80,7 +81,7 @@ export class MicrosoftEntraProviderFormPage extends BaseProviderForm<MicrosoftEn
> >
<input <input
type="text" type="text"
value="${this.instance?.clientSecret ?? ""}" value="${first(this.instance?.clientSecret, "")}"
class="pf-c-form-control pf-m-monospace" class="pf-c-form-control pf-m-monospace"
required required
/> />
@ -95,7 +96,7 @@ export class MicrosoftEntraProviderFormPage extends BaseProviderForm<MicrosoftEn
> >
<input <input
type="text" type="text"
value="${this.instance?.tenantId ?? ""}" value="${first(this.instance?.tenantId, "")}"
class="pf-c-form-control pf-m-monospace" class="pf-c-form-control pf-m-monospace"
required required
/> />
@ -154,7 +155,7 @@ export class MicrosoftEntraProviderFormPage extends BaseProviderForm<MicrosoftEn
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.dryRun ?? false} ?checked=${first(this.instance?.dryRun, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -179,7 +180,7 @@ export class MicrosoftEntraProviderFormPage extends BaseProviderForm<MicrosoftEn
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.excludeUsersServiceAccount ?? true} ?checked=${first(this.instance?.excludeUsersServiceAccount, true)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">

View File

@ -4,7 +4,7 @@ import {
IRedirectURIInput, IRedirectURIInput,
akOAuthRedirectURIInput, akOAuthRedirectURIInput,
} from "@goauthentik/admin/providers/oauth2/OAuth2ProviderRedirectURI"; } from "@goauthentik/admin/providers/oauth2/OAuth2ProviderRedirectURI";
import { ascii_letters, digits, randomString } from "@goauthentik/common/utils"; import { ascii_letters, digits, first, randomString } from "@goauthentik/common/utils";
import "@goauthentik/components/ak-radio-input"; import "@goauthentik/components/ak-radio-input";
import "@goauthentik/components/ak-text-input"; import "@goauthentik/components/ak-text-input";
import "@goauthentik/components/ak-textarea-input"; import "@goauthentik/components/ak-textarea-input";
@ -161,7 +161,7 @@ export function renderForm(
<ak-text-input <ak-text-input
name="clientId" name="clientId"
label=${msg("Client ID")} label=${msg("Client ID")}
value="${provider?.clientId ?? randomString(40, ascii_letters + digits)}" value="${first(provider?.clientId, randomString(40, ascii_letters + digits))}"
required required
inputHint="code" inputHint="code"
> >
@ -169,7 +169,10 @@ export function renderForm(
<ak-text-input <ak-text-input
name="clientSecret" name="clientSecret"
label=${msg("Client Secret")} label=${msg("Client Secret")}
value="${provider?.clientSecret ?? randomString(128, ascii_letters + digits)}" value="${first(
provider?.clientSecret,
randomString(128, ascii_letters + digits),
)}"
inputHint="code" inputHint="code"
?hidden=${!showClientSecret} ?hidden=${!showClientSecret}
> >
@ -254,7 +257,7 @@ export function renderForm(
label=${msg("Access code validity")} label=${msg("Access code validity")}
inputHint="code" inputHint="code"
required required
value="${provider?.accessCodeValidity ?? "minutes=1"}" value="${first(provider?.accessCodeValidity, "minutes=1")}"
.bighelp=${html`<p class="pf-c-form__helper-text"> .bighelp=${html`<p class="pf-c-form__helper-text">
${msg("Configure how long access codes are valid for.")} ${msg("Configure how long access codes are valid for.")}
</p> </p>
@ -264,7 +267,7 @@ export function renderForm(
<ak-text-input <ak-text-input
name="accessTokenValidity" name="accessTokenValidity"
label=${msg("Access Token validity")} label=${msg("Access Token validity")}
value="${provider?.accessTokenValidity ?? "minutes=5"}" value="${first(provider?.accessTokenValidity, "minutes=5")}"
inputHint="code" inputHint="code"
required required
.bighelp=${html` <p class="pf-c-form__helper-text"> .bighelp=${html` <p class="pf-c-form__helper-text">
@ -277,7 +280,7 @@ export function renderForm(
<ak-text-input <ak-text-input
name="refreshTokenValidity" name="refreshTokenValidity"
label=${msg("Refresh Token validity")} label=${msg("Refresh Token validity")}
value="${provider?.refreshTokenValidity ?? "days=30"}" value="${first(provider?.refreshTokenValidity, "days=30")}"
inputHint="code" inputHint="code"
?required=${true} ?required=${true}
.bighelp=${html` <p class="pf-c-form__helper-text"> .bighelp=${html` <p class="pf-c-form__helper-text">
@ -314,7 +317,7 @@ export function renderForm(
<ak-switch-input <ak-switch-input
name="includeClaimsInIdToken" name="includeClaimsInIdToken"
label=${msg("Include claims in id_token")} label=${msg("Include claims in id_token")}
?checked=${provider?.includeClaimsInIdToken ?? true} ?checked=${first(provider?.includeClaimsInIdToken, true)}
help=${msg( help=${msg(
"Include User claims from scopes in the id_token, for applications that don't access the userinfo endpoint.", "Include User claims from scopes in the id_token, for applications that don't access the userinfo endpoint.",
)} )}

View File

@ -3,6 +3,7 @@ import "@goauthentik/admin/providers/proxy/ProxyProviderForm";
import "@goauthentik/admin/rbac/ObjectPermissionsPage"; import "@goauthentik/admin/rbac/ObjectPermissionsPage";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { EVENT_REFRESH } from "@goauthentik/common/constants"; import { EVENT_REFRESH } from "@goauthentik/common/constants";
import { convertToSlug } from "@goauthentik/common/utils";
import "@goauthentik/components/ak-status-label"; import "@goauthentik/components/ak-status-label";
import "@goauthentik/components/events/ObjectChangelog"; import "@goauthentik/components/events/ObjectChangelog";
import MDCaddyStandalone from "@goauthentik/docs/add-secure-apps/providers/proxy/_caddy_standalone.md"; import MDCaddyStandalone from "@goauthentik/docs/add-secure-apps/providers/proxy/_caddy_standalone.md";
@ -21,7 +22,6 @@ import type { Replacer } from "@goauthentik/elements/ak-mdx";
import "@goauthentik/elements/buttons/ModalButton"; import "@goauthentik/elements/buttons/ModalButton";
import "@goauthentik/elements/buttons/SpinnerButton"; import "@goauthentik/elements/buttons/SpinnerButton";
import { getURLParam } from "@goauthentik/elements/router/RouteMatch"; import { getURLParam } from "@goauthentik/elements/router/RouteMatch";
import { formatSlug } from "@goauthentik/elements/router/utils.js";
import { msg } from "@lit/localize"; import { msg } from "@lit/localize";
import { CSSResult, PropertyValues, TemplateResult, css, html } from "lit"; import { CSSResult, PropertyValues, TemplateResult, css, html } from "lit";
@ -183,7 +183,7 @@ export class ProxyProviderViewPage extends AKElement {
return html`<ak-tabs pageIdentifier="proxy-setup"> return html`<ak-tabs pageIdentifier="proxy-setup">
${servers.map((server) => { ${servers.map((server) => {
return html`<section return html`<section
slot="page-${formatSlug(server.label)}" slot="page-${convertToSlug(server.label)}"
data-tab-title="${server.label}" data-tab-title="${server.label}"
class="pf-c-page__main-section pf-m-no-padding-mobile ak-markdown-section" class="pf-c-page__main-section pf-m-no-padding-mobile ak-markdown-section"
> >

View File

@ -1,4 +1,5 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/components/ak-radio-input"; import "@goauthentik/components/ak-radio-input";
import "@goauthentik/elements/CodeMirror"; import "@goauthentik/elements/CodeMirror";
import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js"; import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js";
@ -98,7 +99,7 @@ export class EndpointForm extends ModelForm<Endpoint, string> {
> >
<input <input
type="number" type="number"
value="${this.instance?.maximumConnections ?? 1}" value="${first(this.instance?.maximumConnections, 1)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -122,7 +123,7 @@ export class EndpointForm extends ModelForm<Endpoint, string> {
<ak-form-element-horizontal label=${msg("Settings")} name="settings"> <ak-form-element-horizontal label=${msg("Settings")} name="settings">
<ak-codemirror <ak-codemirror
mode="yaml" mode="yaml"
value="${YAML.stringify(this.instance?.settings ?? {})}" value="${YAML.stringify(first(this.instance?.settings, {}))}"
> >
</ak-codemirror> </ak-codemirror>
<p class="pf-c-form__helper-text">${msg("Connection settings.")}</p> <p class="pf-c-form__helper-text">${msg("Connection settings.")}</p>

View File

@ -1,6 +1,7 @@
import "@goauthentik/admin/common/ak-crypto-certificate-search"; import "@goauthentik/admin/common/ak-crypto-certificate-search";
import "@goauthentik/admin/common/ak-flow-search/ak-branded-flow-search"; import "@goauthentik/admin/common/ak-flow-search/ak-branded-flow-search";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/CodeMirror"; import "@goauthentik/elements/CodeMirror";
import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js"; import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js";
import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/FormGroup";
@ -81,7 +82,7 @@ export class RACProviderFormPage extends ModelForm<RACProvider, number> {
> >
<input <input
type="text" type="text"
value="${this.instance?.connectionExpiry ?? "hours=8"}" value="${first(this.instance?.connectionExpiry, "hours=8")}"
class="pf-c-form-control pf-m-monospace" class="pf-c-form-control pf-m-monospace"
autocomplete="off" autocomplete="off"
spellcheck="false" spellcheck="false"
@ -99,7 +100,7 @@ export class RACProviderFormPage extends ModelForm<RACProvider, number> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.deleteTokenOnDisconnect ?? false} ?checked=${first(this.instance?.deleteTokenOnDisconnect, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -134,7 +135,7 @@ export class RACProviderFormPage extends ModelForm<RACProvider, number> {
<ak-form-element-horizontal label=${msg("Settings")} name="settings"> <ak-form-element-horizontal label=${msg("Settings")} name="settings">
<ak-codemirror <ak-codemirror
mode="yaml" mode="yaml"
value="${YAML.stringify(this.instance?.settings ?? {})}" value="${YAML.stringify(first(this.instance?.settings, {}))}"
> >
</ak-codemirror> </ak-codemirror>
<p class="pf-c-form__helper-text">${msg("Connection settings.")}</p> <p class="pf-c-form__helper-text">${msg("Connection settings.")}</p>

View File

@ -1,6 +1,6 @@
import "@goauthentik/admin/common/ak-flow-search/ak-branded-flow-search"; import "@goauthentik/admin/common/ak-flow-search/ak-branded-flow-search";
import "@goauthentik/admin/common/ak-flow-search/ak-flow-search"; import "@goauthentik/admin/common/ak-flow-search/ak-flow-search";
import { ascii_letters, digits, randomString } from "@goauthentik/common/utils"; import { ascii_letters, digits, first, randomString } from "@goauthentik/common/utils";
import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import "@goauthentik/elements/forms/SearchSelect"; import "@goauthentik/elements/forms/SearchSelect";
@ -78,14 +78,17 @@ export function renderForm(
name="sharedSecret" name="sharedSecret"
label=${msg("Shared secret")} label=${msg("Shared secret")}
.errorMessages=${errors?.sharedSecret ?? []} .errorMessages=${errors?.sharedSecret ?? []}
value=${provider?.sharedSecret ?? randomString(128, ascii_letters + digits)} value=${first(
provider?.sharedSecret,
randomString(128, ascii_letters + digits),
)}
required required
inputHint="code" inputHint="code"
></ak-text-input> ></ak-text-input>
<ak-text-input <ak-text-input
name="clientNetworks" name="clientNetworks"
label=${msg("Client Networks")} label=${msg("Client Networks")}
value=${provider?.clientNetworks ?? "0.0.0.0/0, ::/0"} value=${first(provider?.clientNetworks, "0.0.0.0/0, ::/0")}
.errorMessages=${errors?.clientNetworks ?? []} .errorMessages=${errors?.clientNetworks ?? []}
required required
help=${clientNetworksHelp} help=${clientNetworksHelp}

View File

@ -1,4 +1,5 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js"; import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js";
import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
@ -36,7 +37,7 @@ export function renderForm(provider?: Partial<SCIMProvider>, errors: ValidationE
<ak-text-input <ak-text-input
name="url" name="url"
label=${msg("URL")} label=${msg("URL")}
value="${provider?.url ?? ""}" value="${first(provider?.url, "")}"
.errorMessages=${errors?.url ?? []} .errorMessages=${errors?.url ?? []}
required required
help=${msg("SCIM base url, usually ends in /v2.")} help=${msg("SCIM base url, usually ends in /v2.")}
@ -95,7 +96,7 @@ export function renderForm(provider?: Partial<SCIMProvider>, errors: ValidationE
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${provider?.dryRun ?? false} ?checked=${first(provider?.dryRun, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -118,7 +119,7 @@ export function renderForm(provider?: Partial<SCIMProvider>, errors: ValidationE
<ak-switch-input <ak-switch-input
name="excludeUsersServiceAccount" name="excludeUsersServiceAccount"
label=${msg("Exclude service accounts")} label=${msg("Exclude service accounts")}
?checked=${provider?.excludeUsersServiceAccount ?? true} ?checked=${first(provider?.excludeUsersServiceAccount, true)}
> >
</ak-switch-input> </ak-switch-input>

View File

@ -5,6 +5,7 @@ import {
oauth2ProvidersSelector, oauth2ProvidersSelector,
} from "@goauthentik/admin/providers/oauth2/OAuth2ProvidersProvider"; } from "@goauthentik/admin/providers/oauth2/OAuth2ProvidersProvider";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/components/ak-text-input"; import "@goauthentik/components/ak-text-input";
import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js"; import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js";
import "@goauthentik/elements/ak-dual-select/ak-dual-select-provider.js"; import "@goauthentik/elements/ak-dual-select/ak-dual-select-provider.js";
@ -80,7 +81,7 @@ export class SSFProviderFormPage extends BaseProviderForm<SSFProvider> {
> >
<input <input
type="text" type="text"
value="${provider?.eventRetention ?? "days=30"}" value="${first(provider?.eventRetention, "days=30")}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />

View File

@ -89,12 +89,7 @@ export class RoleObjectPermissionForm extends ModelForm<RoleAssignData, number>
> >
</ak-search-select> </ak-search-select>
</ak-form-element-horizontal> </ak-form-element-horizontal>
${this.modelPermissions?.results ${this.modelPermissions?.results.map((perm) => {
.filter((perm) => {
const [_app, model] = this.model?.split(".") || "";
return perm.codename !== `add_${model}`;
})
.map((perm) => {
return html` <ak-form-element-horizontal name="permissions.${perm.codename}"> return html` <ak-form-element-horizontal name="permissions.${perm.codename}">
<label class="pf-c-switch"> <label class="pf-c-switch">
<input class="pf-c-switch__input" type="checkbox" /> <input class="pf-c-switch__input" type="checkbox" />

View File

@ -45,7 +45,7 @@ export class RoleAssignedObjectPermissionTable extends Table<RoleAssignedObjectP
ordering: "codename", ordering: "codename",
}); });
modelPermissions.results = modelPermissions.results.filter((value) => { modelPermissions.results = modelPermissions.results.filter((value) => {
return value.codename !== `add_${this.model?.split(".")[1]}`; return !value.codename.startsWith("add_");
}); });
this.modelPermissions = modelPermissions; this.modelPermissions = modelPermissions;
return perms; return perms;

View File

@ -6,6 +6,7 @@ import {
UserMatchingModeToLabel, UserMatchingModeToLabel,
} from "@goauthentik/admin/sources/oauth/utils"; } from "@goauthentik/admin/sources/oauth/utils";
import { DEFAULT_CONFIG, config } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG, config } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/components/ak-switch-input"; import "@goauthentik/components/ak-switch-input";
import "@goauthentik/components/ak-text-input"; import "@goauthentik/components/ak-text-input";
import "@goauthentik/components/ak-textarea-input"; import "@goauthentik/components/ak-textarea-input";
@ -96,12 +97,12 @@ export class KerberosSourceForm extends WithCapabilitiesConfig(BaseSourceForm<Ke
></ak-text-input> ></ak-text-input>
<ak-switch-input <ak-switch-input
name="enabled" name="enabled"
?checked=${this.instance?.enabled ?? true} ?checked=${first(this.instance?.enabled, true)}
label=${msg("Enabled")} label=${msg("Enabled")}
></ak-switch-input> ></ak-switch-input>
<ak-switch-input <ak-switch-input
name="passwordLoginUpdateInternalPassword" name="passwordLoginUpdateInternalPassword"
?checked=${this.instance?.passwordLoginUpdateInternalPassword ?? false} ?checked=${first(this.instance?.passwordLoginUpdateInternalPassword, false)}
label=${msg("Update internal password on login")} label=${msg("Update internal password on login")}
help=${msg( help=${msg(
"When the user logs in to authentik using this source password backend, update their credentials in authentik.", "When the user logs in to authentik using this source password backend, update their credentials in authentik.",
@ -109,12 +110,12 @@ export class KerberosSourceForm extends WithCapabilitiesConfig(BaseSourceForm<Ke
></ak-switch-input> ></ak-switch-input>
<ak-switch-input <ak-switch-input
name="syncUsers" name="syncUsers"
?checked=${this.instance?.syncUsers ?? true} ?checked=${first(this.instance?.syncUsers, true)}
label=${msg("Sync users")} label=${msg("Sync users")}
></ak-switch-input> ></ak-switch-input>
<ak-switch-input <ak-switch-input
name="syncUsersPassword" name="syncUsersPassword"
?checked=${this.instance?.syncUsersPassword ?? true} ?checked=${first(this.instance?.syncUsersPassword, true)}
label=${msg("User password writeback")} label=${msg("User password writeback")}
help=${msg( help=${msg(
"Enable this option to write password changes made in authentik back to Kerberos. Ignored if sync is disabled.", "Enable this option to write password changes made in authentik back to Kerberos. Ignored if sync is disabled.",
@ -394,8 +395,10 @@ export class KerberosSourceForm extends WithCapabilitiesConfig(BaseSourceForm<Ke
<ak-text-input <ak-text-input
name="userPathTemplate" name="userPathTemplate"
label=${msg("User path")} label=${msg("User path")}
value=${this.instance?.userPathTemplate ?? value=${first(
"goauthentik.io/sources/%(slug)s"} this.instance?.userPathTemplate,
"goauthentik.io/sources/%(slug)s",
)}
help=${placeholderHelperText} help=${placeholderHelperText}
></ak-text-input> ></ak-text-input>
</div> </div>
@ -440,7 +443,7 @@ export class KerberosSourceForm extends WithCapabilitiesConfig(BaseSourceForm<Ke
: html`<ak-form-element-horizontal label=${msg("Icon")} name="icon"> : html`<ak-form-element-horizontal label=${msg("Icon")} name="icon">
<input <input
type="text" type="text"
value="${this.instance?.icon ?? ""}" value="${first(this.instance?.icon, "")}"
class="pf-c-form-control" class="pf-c-form-control"
/> />
<p class="pf-c-form__helper-text">${iconHelperText}</p> <p class="pf-c-form__helper-text">${iconHelperText}</p>

View File

@ -2,6 +2,7 @@ import "@goauthentik/admin/common/ak-crypto-certificate-search";
import { placeholderHelperText } from "@goauthentik/admin/helperText"; import { placeholderHelperText } from "@goauthentik/admin/helperText";
import { BaseSourceForm } from "@goauthentik/admin/sources/BaseSourceForm"; import { BaseSourceForm } from "@goauthentik/admin/sources/BaseSourceForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js"; import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js";
import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
@ -66,7 +67,7 @@ export class LDAPSourceForm extends BaseSourceForm<LDAPSource> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.enabled ?? true} ?checked=${first(this.instance?.enabled, true)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -81,7 +82,7 @@ export class LDAPSourceForm extends BaseSourceForm<LDAPSource> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.passwordLoginUpdateInternalPassword ?? false} ?checked=${first(this.instance?.passwordLoginUpdateInternalPassword, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -103,7 +104,7 @@ export class LDAPSourceForm extends BaseSourceForm<LDAPSource> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.syncUsers ?? true} ?checked=${first(this.instance?.syncUsers, true)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -118,7 +119,7 @@ export class LDAPSourceForm extends BaseSourceForm<LDAPSource> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.syncUsersPassword ?? true} ?checked=${first(this.instance?.syncUsersPassword, true)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -138,7 +139,7 @@ export class LDAPSourceForm extends BaseSourceForm<LDAPSource> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.syncGroups ?? true} ?checked=${first(this.instance?.syncGroups, true)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -172,7 +173,7 @@ export class LDAPSourceForm extends BaseSourceForm<LDAPSource> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.startTls ?? true} ?checked=${first(this.instance?.startTls, true)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -190,7 +191,7 @@ export class LDAPSourceForm extends BaseSourceForm<LDAPSource> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.sni ?? false} ?checked=${first(this.instance?.sni, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -334,8 +335,10 @@ export class LDAPSourceForm extends BaseSourceForm<LDAPSource> {
<ak-form-element-horizontal label=${msg("User path")} name="userPathTemplate"> <ak-form-element-horizontal label=${msg("User path")} name="userPathTemplate">
<input <input
type="text" type="text"
value="${this.instance?.userPathTemplate ?? value="${first(
"goauthentik.io/sources/%(slug)s"}" this.instance?.userPathTemplate,
"goauthentik.io/sources/%(slug)s",
)}"
class="pf-c-form-control" class="pf-c-form-control"
/> />
<p class="pf-c-form__helper-text">${placeholderHelperText}</p> <p class="pf-c-form__helper-text">${placeholderHelperText}</p>
@ -418,7 +421,7 @@ export class LDAPSourceForm extends BaseSourceForm<LDAPSource> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.lookupGroupsFromUser ?? false} ?checked=${first(this.instance?.lookupGroupsFromUser, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">

View File

@ -6,6 +6,7 @@ import {
UserMatchingModeToLabel, UserMatchingModeToLabel,
} from "@goauthentik/admin/sources/oauth/utils"; } from "@goauthentik/admin/sources/oauth/utils";
import { DEFAULT_CONFIG, config } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG, config } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/components/ak-radio-input"; import "@goauthentik/components/ak-radio-input";
import "@goauthentik/elements/CodeMirror"; import "@goauthentik/elements/CodeMirror";
import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror"; import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror";
@ -135,9 +136,11 @@ export class OAuthSourceForm extends WithCapabilitiesConfig(BaseSourceForm<OAuth
> >
<input <input
type="text" type="text"
value="${this.instance?.authorizationUrl ?? value="${first(
this.providerType.authorizationUrl ?? this.instance?.authorizationUrl,
""}" this.providerType.authorizationUrl,
"",
)}"
class="pf-c-form-control pf-m-monospace" class="pf-c-form-control pf-m-monospace"
autocomplete="off" autocomplete="off"
spellcheck="false" spellcheck="false"
@ -149,9 +152,11 @@ export class OAuthSourceForm extends WithCapabilitiesConfig(BaseSourceForm<OAuth
<ak-form-element-horizontal label=${msg("Access token URL")} name="accessTokenUrl"> <ak-form-element-horizontal label=${msg("Access token URL")} name="accessTokenUrl">
<input <input
type="url" type="url"
value="${this.instance?.accessTokenUrl ?? value="${first(
this.providerType.accessTokenUrl ?? this.instance?.accessTokenUrl,
""}" this.providerType.accessTokenUrl,
"",
)}"
class="pf-c-form-control pf-m-monospace" class="pf-c-form-control pf-m-monospace"
autocomplete="off" autocomplete="off"
spellcheck="false" spellcheck="false"
@ -163,7 +168,11 @@ export class OAuthSourceForm extends WithCapabilitiesConfig(BaseSourceForm<OAuth
<ak-form-element-horizontal label=${msg("Profile URL")} name="profileUrl"> <ak-form-element-horizontal label=${msg("Profile URL")} name="profileUrl">
<input <input
type="url" type="url"
value="${this.instance?.profileUrl ?? this.providerType.profileUrl ?? ""}" value="${first(
this.instance?.profileUrl,
this.providerType.profileUrl,
"",
)}"
class="pf-c-form-control pf-m-monospace" class="pf-c-form-control pf-m-monospace"
autocomplete="off" autocomplete="off"
spellcheck="false" spellcheck="false"
@ -179,7 +188,7 @@ export class OAuthSourceForm extends WithCapabilitiesConfig(BaseSourceForm<OAuth
> >
<input <input
type="url" type="url"
value="${this.instance?.requestTokenUrl ?? ""}" value="${first(this.instance?.requestTokenUrl, "")}"
class="pf-c-form-control pf-m-monospace" class="pf-c-form-control pf-m-monospace"
autocomplete="off" autocomplete="off"
/> />
@ -198,9 +207,11 @@ export class OAuthSourceForm extends WithCapabilitiesConfig(BaseSourceForm<OAuth
> >
<input <input
type="url" type="url"
value="${this.instance?.oidcWellKnownUrl ?? value="${first(
this.providerType.oidcWellKnownUrl ?? this.instance?.oidcWellKnownUrl,
""}" this.providerType.oidcWellKnownUrl,
"",
)}"
class="pf-c-form-control pf-m-monospace" class="pf-c-form-control pf-m-monospace"
autocomplete="off" autocomplete="off"
spellcheck="false" spellcheck="false"
@ -220,9 +231,11 @@ export class OAuthSourceForm extends WithCapabilitiesConfig(BaseSourceForm<OAuth
> >
<input <input
type="url" type="url"
value="${this.instance?.oidcJwksUrl ?? value="${first(
this.providerType.oidcJwksUrl ?? this.instance?.oidcJwksUrl,
""}" this.providerType.oidcJwksUrl,
"",
)}"
class="pf-c-form-control pf-m-monospace" class="pf-c-form-control pf-m-monospace"
autocomplete="off" autocomplete="off"
spellcheck="false" spellcheck="false"
@ -236,7 +249,7 @@ export class OAuthSourceForm extends WithCapabilitiesConfig(BaseSourceForm<OAuth
<ak-form-element-horizontal label=${msg("OIDC JWKS")} name="oidcJwks"> <ak-form-element-horizontal label=${msg("OIDC JWKS")} name="oidcJwks">
<ak-codemirror <ak-codemirror
mode=${CodeMirrorMode.JavaScript} mode=${CodeMirrorMode.JavaScript}
value="${JSON.stringify(this.instance?.oidcJwks ?? {})}" value="${JSON.stringify(first(this.instance?.oidcJwks, {}))}"
> >
</ak-codemirror> </ak-codemirror>
<p class="pf-c-form__helper-text">${msg("Raw JWKS data.")}</p> <p class="pf-c-form__helper-text">${msg("Raw JWKS data.")}</p>
@ -283,7 +296,7 @@ export class OAuthSourceForm extends WithCapabilitiesConfig(BaseSourceForm<OAuth
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.enabled ?? true} ?checked=${first(this.instance?.enabled, true)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -368,7 +381,10 @@ export class OAuthSourceForm extends WithCapabilitiesConfig(BaseSourceForm<OAuth
<ak-form-element-horizontal label=${msg("User path")} name="userPathTemplate"> <ak-form-element-horizontal label=${msg("User path")} name="userPathTemplate">
<input <input
type="text" type="text"
value="${this.instance?.userPathTemplate ?? "goauthentik.io/sources/%(slug)s"}" value="${first(
this.instance?.userPathTemplate,
"goauthentik.io/sources/%(slug)s",
)}"
class="pf-c-form-control pf-m-monospace" class="pf-c-form-control pf-m-monospace"
autocomplete="off" autocomplete="off"
spellcheck="false" spellcheck="false"
@ -416,7 +432,7 @@ export class OAuthSourceForm extends WithCapabilitiesConfig(BaseSourceForm<OAuth
: html`<ak-form-element-horizontal label=${msg("Icon")} name="icon"> : html`<ak-form-element-horizontal label=${msg("Icon")} name="icon">
<input <input
type="text" type="text"
value="${this.instance?.icon ?? ""}" value="${first(this.instance?.icon, "")}"
class="pf-c-form-control pf-m-monospace" class="pf-c-form-control pf-m-monospace"
autocomplete="off" autocomplete="off"
spellcheck="false" spellcheck="false"
@ -458,7 +474,7 @@ export class OAuthSourceForm extends WithCapabilitiesConfig(BaseSourceForm<OAuth
<ak-form-element-horizontal label=${msg("Scopes")} name="additionalScopes"> <ak-form-element-horizontal label=${msg("Scopes")} name="additionalScopes">
<input <input
type="text" type="text"
value="${this.instance?.additionalScopes ?? ""}" value="${first(this.instance?.additionalScopes, "")}"
class="pf-c-form-control pf-m-monospace" class="pf-c-form-control pf-m-monospace"
autocomplete="off" autocomplete="off"
spellcheck="false" spellcheck="false"

View File

@ -7,7 +7,7 @@ import {
} from "@goauthentik/admin/sources/oauth/utils"; } from "@goauthentik/admin/sources/oauth/utils";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { PlexAPIClient, PlexResource, popupCenterScreen } from "@goauthentik/common/helpers/plex"; import { PlexAPIClient, PlexResource, popupCenterScreen } from "@goauthentik/common/helpers/plex";
import { ascii_letters, digits, randomString } from "@goauthentik/common/utils"; import { ascii_letters, digits, first, randomString } from "@goauthentik/common/utils";
import { import {
CapabilitiesEnum, CapabilitiesEnum,
WithCapabilitiesConfig, WithCapabilitiesConfig,
@ -137,7 +137,7 @@ export class PlexSourceForm extends WithCapabilitiesConfig(BaseSourceForm<PlexSo
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.allowFriends ?? true} ?checked=${first(this.instance?.allowFriends, true)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -198,7 +198,7 @@ export class PlexSourceForm extends WithCapabilitiesConfig(BaseSourceForm<PlexSo
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.enabled ?? true} ?checked=${first(this.instance?.enabled, true)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -283,7 +283,10 @@ export class PlexSourceForm extends WithCapabilitiesConfig(BaseSourceForm<PlexSo
<ak-form-element-horizontal label=${msg("User path")} name="userPathTemplate"> <ak-form-element-horizontal label=${msg("User path")} name="userPathTemplate">
<input <input
type="text" type="text"
value="${this.instance?.userPathTemplate ?? "goauthentik.io/sources/%(slug)s"}" value="${first(
this.instance?.userPathTemplate,
"goauthentik.io/sources/%(slug)s",
)}"
class="pf-c-form-control" class="pf-c-form-control"
/> />
<p class="pf-c-form__helper-text">${placeholderHelperText}</p> <p class="pf-c-form__helper-text">${placeholderHelperText}</p>
@ -329,7 +332,7 @@ export class PlexSourceForm extends WithCapabilitiesConfig(BaseSourceForm<PlexSo
: html`<ak-form-element-horizontal label=${msg("Icon")} name="icon"> : html`<ak-form-element-horizontal label=${msg("Icon")} name="icon">
<input <input
type="text" type="text"
value="${this.instance?.icon ?? ""}" value="${first(this.instance?.icon, "")}"
class="pf-c-form-control" class="pf-c-form-control"
/> />
<p class="pf-c-form__helper-text">${iconHelperText}</p> <p class="pf-c-form__helper-text">${iconHelperText}</p>
@ -344,7 +347,7 @@ export class PlexSourceForm extends WithCapabilitiesConfig(BaseSourceForm<PlexSo
> >
<input <input
type="text" type="text"
value="${this.instance?.clientId ?? ""}" value="${first(this.instance?.clientId, "")}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />

View File

@ -7,6 +7,7 @@ import {
UserMatchingModeToLabel, UserMatchingModeToLabel,
} from "@goauthentik/admin/sources/oauth/utils"; } from "@goauthentik/admin/sources/oauth/utils";
import { DEFAULT_CONFIG, config } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG, config } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import { import {
CapabilitiesEnum, CapabilitiesEnum,
WithCapabilitiesConfig, WithCapabilitiesConfig,
@ -104,7 +105,7 @@ export class SAMLSourceForm extends WithCapabilitiesConfig(BaseSourceForm<SAMLSo
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.enabled ?? true} ?checked=${first(this.instance?.enabled, true)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -227,7 +228,7 @@ export class SAMLSourceForm extends WithCapabilitiesConfig(BaseSourceForm<SAMLSo
: html`<ak-form-element-horizontal label=${msg("Icon")} name="icon"> : html`<ak-form-element-horizontal label=${msg("Icon")} name="icon">
<input <input
type="text" type="text"
value="${this.instance?.icon ?? ""}" value="${first(this.instance?.icon, "")}"
class="pf-c-form-control" class="pf-c-form-control"
/> />
<p class="pf-c-form__helper-text">${iconHelperText}</p> <p class="pf-c-form__helper-text">${iconHelperText}</p>
@ -333,7 +334,7 @@ export class SAMLSourceForm extends WithCapabilitiesConfig(BaseSourceForm<SAMLSo
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.allowIdpInitiated ?? false} ?checked=${first(this.instance?.allowIdpInitiated, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -396,8 +397,10 @@ export class SAMLSourceForm extends WithCapabilitiesConfig(BaseSourceForm<SAMLSo
<ak-form-element-horizontal label=${msg("User path")} name="userPathTemplate"> <ak-form-element-horizontal label=${msg("User path")} name="userPathTemplate">
<input <input
type="text" type="text"
value="${this.instance?.userPathTemplate ?? value="${first(
"goauthentik.io/sources/%(slug)s"}" this.instance?.userPathTemplate,
"goauthentik.io/sources/%(slug)s",
)}"
class="pf-c-form-control" class="pf-c-form-control"
/> />
<p class="pf-c-form__helper-text">${placeholderHelperText}</p> <p class="pf-c-form__helper-text">${placeholderHelperText}</p>

View File

@ -1,6 +1,7 @@
import { placeholderHelperText } from "@goauthentik/admin/helperText"; import { placeholderHelperText } from "@goauthentik/admin/helperText";
import { BaseSourceForm } from "@goauthentik/admin/sources/BaseSourceForm"; import { BaseSourceForm } from "@goauthentik/admin/sources/BaseSourceForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js"; import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js";
import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
@ -62,7 +63,7 @@ export class SCIMSourceForm extends BaseSourceForm<SCIMSource> {
<input <input
type="checkbox" type="checkbox"
class="pf-c-check__input" class="pf-c-check__input"
?checked=${this.instance?.enabled ?? true} ?checked=${first(this.instance?.enabled, true)}
/> />
<label class="pf-c-check__label"> ${msg("Enabled")} </label> <label class="pf-c-check__label"> ${msg("Enabled")} </label>
</div> </div>
@ -110,8 +111,10 @@ export class SCIMSourceForm extends BaseSourceForm<SCIMSource> {
<ak-form-element-horizontal label=${msg("User path")} name="userPathTemplate"> <ak-form-element-horizontal label=${msg("User path")} name="userPathTemplate">
<input <input
type="text" type="text"
value="${this.instance?.userPathTemplate ?? value="${first(
"goauthentik.io/sources/%(slug)s"}" this.instance?.userPathTemplate,
"goauthentik.io/sources/%(slug)s",
)}"
class="pf-c-form-control" class="pf-c-form-control"
/> />
<p class="pf-c-form__helper-text">${placeholderHelperText}</p> <p class="pf-c-form__helper-text">${placeholderHelperText}</p>

View File

@ -1,6 +1,7 @@
import { RenderFlowOption } from "@goauthentik/admin/flows/utils"; import { RenderFlowOption } from "@goauthentik/admin/flows/utils";
import { BaseStageForm } from "@goauthentik/admin/stages/BaseStageForm"; import { BaseStageForm } from "@goauthentik/admin/stages/BaseStageForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import "@goauthentik/elements/forms/SearchSelect"; import "@goauthentik/elements/forms/SearchSelect";
@ -49,7 +50,7 @@ export class AuthenticatorDuoStageForm extends BaseStageForm<AuthenticatorDuoSta
<ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name"> <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
<input <input
type="text" type="text"
value="${this.instance?.name ?? ""}" value="${first(this.instance?.name, "")}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -61,7 +62,7 @@ export class AuthenticatorDuoStageForm extends BaseStageForm<AuthenticatorDuoSta
> >
<input <input
type="text" type="text"
value="${this.instance?.friendlyName ?? ""}" value="${first(this.instance?.friendlyName, "")}"
class="pf-c-form-control" class="pf-c-form-control"
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
@ -77,7 +78,7 @@ export class AuthenticatorDuoStageForm extends BaseStageForm<AuthenticatorDuoSta
> >
<input <input
type="text" type="text"
value="${this.instance?.apiHostname ?? ""}" value="${first(this.instance?.apiHostname, "")}"
class="pf-c-form-control pf-m-monospace" class="pf-c-form-control pf-m-monospace"
autocomplete="off" autocomplete="off"
spellcheck="false" spellcheck="false"
@ -94,7 +95,7 @@ export class AuthenticatorDuoStageForm extends BaseStageForm<AuthenticatorDuoSta
> >
<input <input
type="text" type="text"
value="${this.instance?.clientId ?? ""}" value="${first(this.instance?.clientId, "")}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -131,7 +132,7 @@ export class AuthenticatorDuoStageForm extends BaseStageForm<AuthenticatorDuoSta
> >
<input <input
type="text" type="text"
value="${this.instance?.adminIntegrationKey ?? ""}" value="${first(this.instance?.adminIntegrationKey, "")}"
class="pf-c-form-control pf-m-monospace" class="pf-c-form-control pf-m-monospace"
autocomplete="off" autocomplete="off"
spellcheck="false" spellcheck="false"

View File

@ -1,6 +1,7 @@
import { RenderFlowOption } from "@goauthentik/admin/flows/utils"; import { RenderFlowOption } from "@goauthentik/admin/flows/utils";
import { BaseStageForm } from "@goauthentik/admin/stages/BaseStageForm"; import { BaseStageForm } from "@goauthentik/admin/stages/BaseStageForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import "@goauthentik/elements/forms/Radio"; import "@goauthentik/elements/forms/Radio";
@ -64,7 +65,7 @@ export class AuthenticatorEmailStageForm extends BaseStageForm<AuthenticatorEmai
<ak-form-element-horizontal label=${msg("SMTP Port")} ?required=${true} name="port"> <ak-form-element-horizontal label=${msg("SMTP Port")} ?required=${true} name="port">
<input <input
type="number" type="number"
value="${this.instance?.port ?? 25}" value="${first(this.instance?.port, 25)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -88,7 +89,7 @@ export class AuthenticatorEmailStageForm extends BaseStageForm<AuthenticatorEmai
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.useTls ?? true} ?checked=${first(this.instance?.useTls, true)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -103,7 +104,7 @@ export class AuthenticatorEmailStageForm extends BaseStageForm<AuthenticatorEmai
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.useSsl ?? false} ?checked=${first(this.instance?.useSsl, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -120,7 +121,7 @@ export class AuthenticatorEmailStageForm extends BaseStageForm<AuthenticatorEmai
> >
<input <input
type="number" type="number"
value="${this.instance?.timeout ?? 30}" value="${first(this.instance?.timeout, 30)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -149,7 +150,7 @@ export class AuthenticatorEmailStageForm extends BaseStageForm<AuthenticatorEmai
<ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name"> <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
<input <input
type="text" type="text"
value="${this.instance?.name ?? ""}" value="${first(this.instance?.name, "")}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -161,7 +162,7 @@ export class AuthenticatorEmailStageForm extends BaseStageForm<AuthenticatorEmai
> >
<input <input
type="text" type="text"
value="${this.instance?.friendlyName ?? ""}" value="${first(this.instance?.friendlyName, "")}"
class="pf-c-form-control" class="pf-c-form-control"
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
@ -175,7 +176,7 @@ export class AuthenticatorEmailStageForm extends BaseStageForm<AuthenticatorEmai
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.useGlobalSettings ?? true} ?checked=${first(this.instance?.useGlobalSettings, true)}
@change=${(ev: Event) => { @change=${(ev: Event) => {
const target = ev.target as HTMLInputElement; const target = ev.target as HTMLInputElement;
this.showConnectionSettings = !target.checked; this.showConnectionSettings = !target.checked;
@ -205,7 +206,7 @@ export class AuthenticatorEmailStageForm extends BaseStageForm<AuthenticatorEmai
> >
<input <input
type="text" type="text"
value="${this.instance?.subject ?? "authentik Sign-in code"}" value="${first(this.instance?.subject, "authentik Sign-in code")}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -220,7 +221,7 @@ export class AuthenticatorEmailStageForm extends BaseStageForm<AuthenticatorEmai
> >
<input <input
type="text" type="text"
value="${this.instance?.tokenExpiry ?? "minutes=15"}" value="${first(this.instance?.tokenExpiry, "minutes=15")}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />

View File

@ -1,5 +1,6 @@
import { BaseStageForm } from "@goauthentik/admin/stages/BaseStageForm"; import { BaseStageForm } from "@goauthentik/admin/stages/BaseStageForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/CodeMirror"; import "@goauthentik/elements/CodeMirror";
import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror"; import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror";
import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/FormGroup";
@ -51,7 +52,7 @@ export class AuthenticatorEndpointGDTCStageForm extends BaseStageForm<Authentica
<ak-form-element-horizontal label=${msg("Name")} required name="name"> <ak-form-element-horizontal label=${msg("Name")} required name="name">
<input <input
type="text" type="text"
value="${this.instance?.name ?? ""}" value="${first(this.instance?.name, "")}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -66,7 +67,7 @@ export class AuthenticatorEndpointGDTCStageForm extends BaseStageForm<Authentica
> >
<ak-codemirror <ak-codemirror
mode=${CodeMirrorMode.JavaScript} mode=${CodeMirrorMode.JavaScript}
.value="${this.instance?.credentials ?? {}}" .value="${first(this.instance?.credentials, {})}"
></ak-codemirror> ></ak-codemirror>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
${msg("Google Cloud credentials file.")} ${msg("Google Cloud credentials file.")}

View File

@ -1,6 +1,7 @@
import { RenderFlowOption } from "@goauthentik/admin/flows/utils"; import { RenderFlowOption } from "@goauthentik/admin/flows/utils";
import { BaseStageForm } from "@goauthentik/admin/stages/BaseStageForm"; import { BaseStageForm } from "@goauthentik/admin/stages/BaseStageForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import "@goauthentik/elements/forms/Radio"; import "@goauthentik/elements/forms/Radio";
@ -65,7 +66,7 @@ export class AuthenticatorSMSStageForm extends BaseStageForm<AuthenticatorSMSSta
> >
<input <input
type="text" type="text"
value="${this.instance?.accountSid ?? ""}" value="${first(this.instance?.accountSid, "")}"
class="pf-c-form-control pf-m-monospace" class="pf-c-form-control pf-m-monospace"
autocomplete="off" autocomplete="off"
spellcheck="false" spellcheck="false"
@ -82,7 +83,7 @@ export class AuthenticatorSMSStageForm extends BaseStageForm<AuthenticatorSMSSta
> >
<input <input
type="text" type="text"
value="${this.instance?.auth ?? ""}" value="${first(this.instance?.auth, "")}"
class="pf-c-form-control pf-m-monospace" class="pf-c-form-control pf-m-monospace"
autocomplete="off" autocomplete="off"
spellcheck="false" spellcheck="false"
@ -128,7 +129,7 @@ export class AuthenticatorSMSStageForm extends BaseStageForm<AuthenticatorSMSSta
> >
<input <input
type="text" type="text"
value="${this.instance?.accountSid ?? ""}" value="${first(this.instance?.accountSid, "")}"
class="pf-c-form-control pf-m-monospace" class="pf-c-form-control pf-m-monospace"
autocomplete="off" autocomplete="off"
spellcheck="false" spellcheck="false"
@ -145,7 +146,7 @@ export class AuthenticatorSMSStageForm extends BaseStageForm<AuthenticatorSMSSta
> >
<input <input
type="text" type="text"
value="${this.instance?.auth ?? ""}" value="${first(this.instance?.auth, "")}"
class="pf-c-form-control pf-m-monospace" class="pf-c-form-control pf-m-monospace"
autocomplete="off" autocomplete="off"
spellcheck="false" spellcheck="false"
@ -163,7 +164,7 @@ export class AuthenticatorSMSStageForm extends BaseStageForm<AuthenticatorSMSSta
> >
<input <input
type="text" type="text"
value="${this.instance?.authPassword ?? ""}" value="${first(this.instance?.authPassword, "")}"
class="pf-c-form-control pf-m-monospace" class="pf-c-form-control pf-m-monospace"
autocomplete="off" autocomplete="off"
spellcheck="false" spellcheck="false"
@ -214,7 +215,7 @@ export class AuthenticatorSMSStageForm extends BaseStageForm<AuthenticatorSMSSta
<ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name"> <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
<input <input
type="text" type="text"
value="${this.instance?.name ?? ""}" value="${first(this.instance?.name, "")}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -226,7 +227,7 @@ export class AuthenticatorSMSStageForm extends BaseStageForm<AuthenticatorSMSSta
> >
<input <input
type="text" type="text"
value="${this.instance?.friendlyName ?? ""}" value="${first(this.instance?.friendlyName, "")}"
class="pf-c-form-control" class="pf-c-form-control"
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
@ -271,7 +272,7 @@ export class AuthenticatorSMSStageForm extends BaseStageForm<AuthenticatorSMSSta
> >
<input <input
type="text" type="text"
value="${this.instance?.fromNumber ?? ""}" value="${first(this.instance?.fromNumber, "")}"
class="pf-c-form-control pf-m-monospace" class="pf-c-form-control pf-m-monospace"
autocomplete="off" autocomplete="off"
spellcheck="false" spellcheck="false"
@ -289,7 +290,7 @@ export class AuthenticatorSMSStageForm extends BaseStageForm<AuthenticatorSMSSta
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.verifyOnly ?? false} ?checked=${first(this.instance?.verifyOnly, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">

View File

@ -1,6 +1,7 @@
import { RenderFlowOption } from "@goauthentik/admin/flows/utils"; import { RenderFlowOption } from "@goauthentik/admin/flows/utils";
import { BaseStageForm } from "@goauthentik/admin/stages/BaseStageForm"; import { BaseStageForm } from "@goauthentik/admin/stages/BaseStageForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import "@goauthentik/elements/forms/SearchSelect"; import "@goauthentik/elements/forms/SearchSelect";
@ -47,7 +48,7 @@ export class AuthenticatorStaticStageForm extends BaseStageForm<AuthenticatorSta
<ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name"> <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
<input <input
type="text" type="text"
value="${this.instance?.name ?? ""}" value="${first(this.instance?.name, "")}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -59,7 +60,7 @@ export class AuthenticatorStaticStageForm extends BaseStageForm<AuthenticatorSta
> >
<input <input
type="text" type="text"
value="${this.instance?.friendlyName ?? ""}" value="${first(this.instance?.friendlyName, "")}"
class="pf-c-form-control" class="pf-c-form-control"
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
@ -78,7 +79,7 @@ export class AuthenticatorStaticStageForm extends BaseStageForm<AuthenticatorSta
> >
<input <input
type="text" type="text"
value="${this.instance?.tokenCount ?? 6}" value="${first(this.instance?.tokenCount, 6)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -95,7 +96,7 @@ export class AuthenticatorStaticStageForm extends BaseStageForm<AuthenticatorSta
> >
<input <input
type="text" type="text"
value="${this.instance?.tokenLength ?? 12}" value="${first(this.instance?.tokenLength, 12)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />

View File

@ -1,6 +1,7 @@
import { RenderFlowOption } from "@goauthentik/admin/flows/utils"; import { RenderFlowOption } from "@goauthentik/admin/flows/utils";
import { BaseStageForm } from "@goauthentik/admin/stages/BaseStageForm"; import { BaseStageForm } from "@goauthentik/admin/stages/BaseStageForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import "@goauthentik/elements/forms/SearchSelect"; import "@goauthentik/elements/forms/SearchSelect";
@ -49,7 +50,7 @@ export class AuthenticatorTOTPStageForm extends BaseStageForm<AuthenticatorTOTPS
<ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name"> <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
<input <input
type="text" type="text"
value="${this.instance?.name ?? ""}" value="${first(this.instance?.name, "")}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -61,7 +62,7 @@ export class AuthenticatorTOTPStageForm extends BaseStageForm<AuthenticatorTOTPS
> >
<input <input
type="text" type="text"
value="${this.instance?.friendlyName ?? ""}" value="${first(this.instance?.friendlyName, "")}"
class="pf-c-form-control" class="pf-c-form-control"
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">

View File

@ -2,6 +2,7 @@ import { RenderFlowOption } from "@goauthentik/admin/flows/utils";
import { BaseStageForm } from "@goauthentik/admin/stages/BaseStageForm"; import { BaseStageForm } from "@goauthentik/admin/stages/BaseStageForm";
import { deviceTypeRestrictionPair } from "@goauthentik/admin/stages/authenticator_webauthn/utils"; import { deviceTypeRestrictionPair } from "@goauthentik/admin/stages/authenticator_webauthn/utils";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/ak-dual-select/ak-dual-select-provider"; import "@goauthentik/elements/ak-dual-select/ak-dual-select-provider";
import { DataProvision } from "@goauthentik/elements/ak-dual-select/types"; import { DataProvision } from "@goauthentik/elements/ak-dual-select/types";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
@ -57,7 +58,7 @@ export class AuthenticatorWebAuthnStageForm extends BaseStageForm<AuthenticatorW
<ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name"> <ak-form-element-horizontal label=${msg("Name")} ?required=${true} name="name">
<input <input
type="text" type="text"
value="${this.instance?.name ?? ""}" value="${first(this.instance?.name, "")}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -69,7 +70,7 @@ export class AuthenticatorWebAuthnStageForm extends BaseStageForm<AuthenticatorW
> >
<input <input
type="text" type="text"
value="${this.instance?.friendlyName ?? ""}" value="${first(this.instance?.friendlyName, "")}"
class="pf-c-form-control" class="pf-c-form-control"
/> />
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">

View File

@ -1,5 +1,6 @@
import { BaseStageForm } from "@goauthentik/admin/stages/BaseStageForm"; import { BaseStageForm } from "@goauthentik/admin/stages/BaseStageForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/components/ak-number-input"; import "@goauthentik/components/ak-number-input";
import "@goauthentik/components/ak-switch-input"; import "@goauthentik/components/ak-switch-input";
import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/FormGroup";
@ -117,7 +118,7 @@ export class CaptchaStageForm extends BaseStageForm<CaptchaStage> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.errorOnInvalidScore ?? true} ?checked=${first(this.instance?.errorOnInvalidScore, true)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">

View File

@ -1,5 +1,6 @@
import { BaseStageForm } from "@goauthentik/admin/stages/BaseStageForm"; import { BaseStageForm } from "@goauthentik/admin/stages/BaseStageForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import { msg } from "@lit/localize"; import { msg } from "@lit/localize";
@ -49,7 +50,7 @@ export class DummyStageForm extends BaseStageForm<DummyStage> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.throwError ?? false} ?checked=${first(this.instance?.throwError, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">

View File

@ -1,5 +1,6 @@
import { BaseStageForm } from "@goauthentik/admin/stages/BaseStageForm"; import { BaseStageForm } from "@goauthentik/admin/stages/BaseStageForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/FormGroup";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
import "@goauthentik/elements/utils/TimeDeltaHelp"; import "@goauthentik/elements/utils/TimeDeltaHelp";
@ -61,7 +62,7 @@ export class EmailStageForm extends BaseStageForm<EmailStage> {
<ak-form-element-horizontal label=${msg("SMTP Port")} ?required=${true} name="port"> <ak-form-element-horizontal label=${msg("SMTP Port")} ?required=${true} name="port">
<input <input
type="number" type="number"
value="${this.instance?.port ?? 25}" value="${first(this.instance?.port, 25)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -85,7 +86,7 @@ export class EmailStageForm extends BaseStageForm<EmailStage> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.useTls ?? true} ?checked=${first(this.instance?.useTls, true)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -100,7 +101,7 @@ export class EmailStageForm extends BaseStageForm<EmailStage> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.useSsl ?? false} ?checked=${first(this.instance?.useSsl, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -117,7 +118,7 @@ export class EmailStageForm extends BaseStageForm<EmailStage> {
> >
<input <input
type="number" type="number"
value="${this.instance?.timeout ?? 30}" value="${first(this.instance?.timeout, 30)}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -160,7 +161,7 @@ export class EmailStageForm extends BaseStageForm<EmailStage> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.activateUserOnSuccess ?? true} ?checked=${first(this.instance?.activateUserOnSuccess, true)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">
@ -182,7 +183,7 @@ export class EmailStageForm extends BaseStageForm<EmailStage> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.useGlobalSettings ?? true} ?checked=${first(this.instance?.useGlobalSettings, true)}
@change=${(ev: Event) => { @change=${(ev: Event) => {
const target = ev.target as HTMLInputElement; const target = ev.target as HTMLInputElement;
this.showConnectionSettings = !target.checked; this.showConnectionSettings = !target.checked;
@ -208,7 +209,7 @@ export class EmailStageForm extends BaseStageForm<EmailStage> {
> >
<input <input
type="text" type="text"
value="${this.instance?.tokenExpiry ?? "minutes=30"}" value="${first(this.instance?.tokenExpiry, "minutes=30")}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />
@ -224,7 +225,7 @@ export class EmailStageForm extends BaseStageForm<EmailStage> {
> >
<input <input
type="text" type="text"
value="${this.instance?.subject ?? "authentik"}" value="${first(this.instance?.subject, "authentik")}"
class="pf-c-form-control" class="pf-c-form-control"
required required
/> />

View File

@ -1,7 +1,7 @@
import "@goauthentik/admin/common/ak-flow-search/ak-flow-search"; import "@goauthentik/admin/common/ak-flow-search/ak-flow-search";
import { BaseStageForm } from "@goauthentik/admin/stages/BaseStageForm"; import { BaseStageForm } from "@goauthentik/admin/stages/BaseStageForm";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { groupBy } from "@goauthentik/common/utils"; import { first, groupBy } from "@goauthentik/common/utils";
import "@goauthentik/components/ak-switch-input.js"; import "@goauthentik/components/ak-switch-input.js";
import "@goauthentik/elements/ak-checkbox-group/ak-checkbox-group.js"; import "@goauthentik/elements/ak-checkbox-group/ak-checkbox-group.js";
import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js"; import "@goauthentik/elements/ak-dual-select/ak-dual-select-dynamic-selected-provider.js";
@ -162,7 +162,7 @@ export class IdentificationStageForm extends BaseStageForm<IdentificationStage>
<ak-switch-input <ak-switch-input
name="caseInsensitiveMatching" name="caseInsensitiveMatching"
label=${msg("Case insensitive matching")} label=${msg("Case insensitive matching")}
?checked=${this.instance?.caseInsensitiveMatching ?? true} ?checked=${first(this.instance?.caseInsensitiveMatching, true)}
help=${msg( help=${msg(
"When enabled, user fields are matched regardless of their casing.", "When enabled, user fields are matched regardless of their casing.",
)} )}
@ -170,7 +170,7 @@ export class IdentificationStageForm extends BaseStageForm<IdentificationStage>
<ak-switch-input <ak-switch-input
name="pretendUserExists" name="pretendUserExists"
label=${msg("Pretend user exists")} label=${msg("Pretend user exists")}
?checked=${this.instance?.pretendUserExists ?? true} ?checked=${first(this.instance?.pretendUserExists, true)}
help=${msg( help=${msg(
"When enabled, the stage will always accept the given user identifier and continue.", "When enabled, the stage will always accept the given user identifier and continue.",
)} )}
@ -178,7 +178,7 @@ export class IdentificationStageForm extends BaseStageForm<IdentificationStage>
<ak-switch-input <ak-switch-input
name="showMatchedUser" name="showMatchedUser"
label=${msg("Show matched user")} label=${msg("Show matched user")}
?checked=${this.instance?.showMatchedUser ?? true} ?checked=${first(this.instance?.showMatchedUser, true)}
help=${msg( help=${msg(
"When a valid username/email has been entered, and this option is enabled, the user's username and avatar will be shown. Otherwise, the text that the user entered will be shown.", "When a valid username/email has been entered, and this option is enabled, the user's username and avatar will be shown. Otherwise, the text that the user entered will be shown.",
)} )}
@ -218,7 +218,7 @@ export class IdentificationStageForm extends BaseStageForm<IdentificationStage>
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.showSourceLabels ?? false} ?checked=${first(this.instance?.showSourceLabels, false)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">

View File

@ -1,6 +1,7 @@
import "@goauthentik/admin/common/ak-flow-search/ak-flow-search"; import "@goauthentik/admin/common/ak-flow-search/ak-flow-search";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { dateTimeLocal } from "@goauthentik/common/temporal"; import { dateTimeLocal } from "@goauthentik/common/temporal";
import { first } from "@goauthentik/common/utils";
import "@goauthentik/elements/CodeMirror"; import "@goauthentik/elements/CodeMirror";
import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror"; import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror";
import "@goauthentik/elements/forms/HorizontalFormElement"; import "@goauthentik/elements/forms/HorizontalFormElement";
@ -62,7 +63,7 @@ export class InvitationForm extends ModelForm<Invitation, string> {
data-type="datetime-local" data-type="datetime-local"
class="pf-c-form-control" class="pf-c-form-control"
required required
value="${dateTimeLocal(this.instance?.expires ?? new Date())}" value="${dateTimeLocal(first(this.instance?.expires, new Date()))}"
/> />
</ak-form-element-horizontal> </ak-form-element-horizontal>
<ak-form-element-horizontal label=${msg("Flow")} name="flow"> <ak-form-element-horizontal label=${msg("Flow")} name="flow">
@ -79,7 +80,7 @@ export class InvitationForm extends ModelForm<Invitation, string> {
<ak-form-element-horizontal label=${msg("Custom attributes")} name="fixedData"> <ak-form-element-horizontal label=${msg("Custom attributes")} name="fixedData">
<ak-codemirror <ak-codemirror
mode=${CodeMirrorMode.YAML} mode=${CodeMirrorMode.YAML}
value="${YAML.stringify(this.instance?.fixedData ?? {})}" value="${YAML.stringify(first(this.instance?.fixedData, {}))}"
> >
</ak-codemirror> </ak-codemirror>
<p class="pf-c-form__helper-text"> <p class="pf-c-form__helper-text">
@ -93,7 +94,7 @@ export class InvitationForm extends ModelForm<Invitation, string> {
<input <input
class="pf-c-switch__input" class="pf-c-switch__input"
type="checkbox" type="checkbox"
?checked=${this.instance?.singleUse ?? true} ?checked=${first(this.instance?.singleUse, true)}
/> />
<span class="pf-c-switch__toggle"> <span class="pf-c-switch__toggle">
<span class="pf-c-switch__toggle-icon"> <span class="pf-c-switch__toggle-icon">

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