Compare commits

..

31 Commits

Author SHA1 Message Date
Teffen Ellis
117bf97eaa web: Flesh out Playwright. 2025-08-01 17:49:12 +02:00
dependabot[bot]
7e4bdac093 web: bump @sentry/browser from 9.43.0 to 10.0.0 in /web in the sentry group across 1 directory (#15911)
web: bump @sentry/browser in /web in the sentry group across 1 directory

Bumps the sentry group with 1 update in the /web directory: [@sentry/browser](https://github.com/getsentry/sentry-javascript).


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

---
updated-dependencies:
- dependency-name: "@sentry/browser"
  dependency-version: 10.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: sentry
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-01 12:42:54 +02:00
dependabot[bot]
5f16ea4718 core: bump github.com/prometheus/client_golang from 1.22.0 to 1.23.0 (#15908)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-01 10:22:50 +00:00
dependabot[bot]
d50a266d74 website: bump the build group in /website with 3 updates (#15910)
Bumps the build group in /website with 3 updates: [@rspack/binding-darwin-arm64](https://github.com/web-infra-dev/rspack/tree/HEAD/packages/rspack), [@rspack/binding-linux-arm64-gnu](https://github.com/web-infra-dev/rspack/tree/HEAD/packages/rspack) and [@rspack/binding-linux-x64-gnu](https://github.com/web-infra-dev/rspack/tree/HEAD/packages/rspack).


Updates `@rspack/binding-darwin-arm64` from 1.4.10 to 1.4.11
- [Release notes](https://github.com/web-infra-dev/rspack/releases)
- [Commits](https://github.com/web-infra-dev/rspack/commits/v1.4.11/packages/rspack)

Updates `@rspack/binding-linux-arm64-gnu` from 1.4.10 to 1.4.11
- [Release notes](https://github.com/web-infra-dev/rspack/releases)
- [Commits](https://github.com/web-infra-dev/rspack/commits/v1.4.11/packages/rspack)

Updates `@rspack/binding-linux-x64-gnu` from 1.4.10 to 1.4.11
- [Release notes](https://github.com/web-infra-dev/rspack/releases)
- [Commits](https://github.com/web-infra-dev/rspack/commits/v1.4.11/packages/rspack)

---
updated-dependencies:
- dependency-name: "@rspack/binding-darwin-arm64"
  dependency-version: 1.4.11
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@rspack/binding-linux-arm64-gnu"
  dependency-version: 1.4.11
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
- dependency-name: "@rspack/binding-linux-x64-gnu"
  dependency-version: 1.4.11
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: build
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-01 12:14:49 +02:00
dependabot[bot]
41ebfa24da web: bump the storybook group across 1 directory with 5 updates (#15912)
Bumps the storybook group with 4 updates in the /web directory: [@storybook/addon-docs](https://github.com/storybookjs/storybook/tree/HEAD/code/addons/docs), [@storybook/addon-links](https://github.com/storybookjs/storybook/tree/HEAD/code/addons/links), [@storybook/web-components](https://github.com/storybookjs/storybook/tree/HEAD/code/renderers/web-components) and [@storybook/web-components-vite](https://github.com/storybookjs/storybook/tree/HEAD/code/frameworks/web-components-vite).


Updates `@storybook/addon-docs` from 9.0.18 to 9.1.0
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v9.1.0/code/addons/docs)

Updates `@storybook/addon-links` from 9.0.18 to 9.1.0
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v9.1.0/code/addons/links)

Updates `@storybook/web-components` from 9.0.18 to 9.1.0
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v9.1.0/code/renderers/web-components)

Updates `@storybook/web-components-vite` from 9.0.18 to 9.1.0
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v9.1.0/code/frameworks/web-components-vite)

Updates `storybook` from 9.0.18 to 9.1.0
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v9.1.0/code/core)

---
updated-dependencies:
- dependency-name: "@storybook/addon-docs"
  dependency-version: 9.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: storybook
- dependency-name: "@storybook/addon-links"
  dependency-version: 9.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: storybook
- dependency-name: "@storybook/web-components"
  dependency-version: 9.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: storybook
- dependency-name: "@storybook/web-components-vite"
  dependency-version: 9.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: storybook
- dependency-name: storybook
  dependency-version: 9.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: storybook
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-01 12:14:23 +02:00
dependabot[bot]
8b7cc18988 web: bump typescript from 5.8.3 to 5.9.2 in /packages/docusaurus-config (#15913)
Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.8.3 to 5.9.2.
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release-publish.yml)
- [Commits](https://github.com/microsoft/TypeScript/compare/v5.8.3...v5.9.2)

---
updated-dependencies:
- dependency-name: typescript
  dependency-version: 5.9.2
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-01 12:14:08 +02:00
dependabot[bot]
e780b7d519 web: bump typescript from 5.8.3 to 5.9.2 in /packages/esbuild-plugin-live-reload (#15914)
web: bump typescript in /packages/esbuild-plugin-live-reload

Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.8.3 to 5.9.2.
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release-publish.yml)
- [Commits](https://github.com/microsoft/TypeScript/compare/v5.8.3...v5.9.2)

---
updated-dependencies:
- dependency-name: typescript
  dependency-version: 5.9.2
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-01 12:13:57 +02:00
dependabot[bot]
25894592ae web: bump typescript from 5.8.3 to 5.9.2 in /packages/eslint-config (#15915)
Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.8.3 to 5.9.2.
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release-publish.yml)
- [Commits](https://github.com/microsoft/TypeScript/compare/v5.8.3...v5.9.2)

---
updated-dependencies:
- dependency-name: typescript
  dependency-version: 5.9.2
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-01 12:13:48 +02:00
dependabot[bot]
5021d08c69 web: bump typescript from 5.8.3 to 5.9.2 in /packages/prettier-config (#15916)
Bumps [typescript](https://github.com/microsoft/TypeScript) from 5.8.3 to 5.9.2.
- [Release notes](https://github.com/microsoft/TypeScript/releases)
- [Changelog](https://github.com/microsoft/TypeScript/blob/main/azure-pipelines.release-publish.yml)
- [Commits](https://github.com/microsoft/TypeScript/compare/v5.8.3...v5.9.2)

---
updated-dependencies:
- dependency-name: typescript
  dependency-version: 5.9.2
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-01 12:13:35 +02:00
authentik-automation[bot]
cb74b47674 stages/authenticator_webauthn: Update FIDO MDS3 & Passkey aaguid blobs (#15906)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2025-08-01 12:06:19 +02:00
dependabot[bot]
aafd81ca09 core: bump github.com/getsentry/sentry-go from 0.34.1 to 0.35.0 (#15909)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-01 12:05:29 +02:00
Dominic R
a4f8e15f91 website/integrations: kimai: fix order and var (#15907)
Signed-off-by: Dominic R <dominic@sdko.org>
2025-08-01 08:30:31 +01:00
Jens L.
0c20169739 web/common: fix form element alignment (#15904)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-07-31 18:18:01 +02:00
Jens L.
24ca89c439 web/flows: fix flow inspector button always showing (#15893)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-07-31 17:19:35 +02:00
dependabot[bot]
0352d31af0 web: bump @floating-ui/dom from 1.7.2 to 1.7.3 in /web (#15899)
Bumps [@floating-ui/dom](https://github.com/floating-ui/floating-ui/tree/HEAD/packages/dom) from 1.7.2 to 1.7.3.
- [Release notes](https://github.com/floating-ui/floating-ui/releases)
- [Changelog](https://github.com/floating-ui/floating-ui/blob/master/packages/dom/CHANGELOG.md)
- [Commits](https://github.com/floating-ui/floating-ui/commits/@floating-ui/dom@1.7.3/packages/dom)

---
updated-dependencies:
- dependency-name: "@floating-ui/dom"
  dependency-version: 1.7.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-31 15:54:06 +02:00
dependabot[bot]
5bdbf06351 web: bump chromedriver from 138.0.4 to 138.0.5 in /web (#15900)
Bumps [chromedriver](https://github.com/giggio/node-chromedriver) from 138.0.4 to 138.0.5.
- [Commits](https://github.com/giggio/node-chromedriver/compare/138.0.4...138.0.5)

---
updated-dependencies:
- dependency-name: chromedriver
  dependency-version: 138.0.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-31 15:53:55 +02:00
dependabot[bot]
b3f1e7b1a2 core: bump github.com/golang-jwt/jwt/v5 from 5.2.3 to 5.3.0 (#15896)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-31 14:18:18 +02:00
dependabot[bot]
2dfda8833d core: bump github.com/coreos/go-oidc/v3 from 3.14.1 to 3.15.0 (#15897)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-31 14:18:01 +02:00
dependabot[bot]
9094b30860 core: bump astral-sh/uv from 0.8.3 to 0.8.4 (#15898)
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-31 14:16:39 +02:00
authentik-automation[bot]
7e52e932fc core, web: update translations (#15895)
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2025-07-31 14:15:25 +02:00
Teffen Ellis
b5fc28a3fd website: Ignore legacy API docs. (#15891) 2025-07-31 11:24:27 +00:00
dependabot[bot]
df49dd4ec8 web: bump the rollup group across 1 directory with 4 updates (#15884)
Bumps the rollup group with 4 updates in the /web directory: [@rollup/rollup-darwin-arm64](https://github.com/rollup/rollup), [@rollup/rollup-linux-arm64-gnu](https://github.com/rollup/rollup), [@rollup/rollup-linux-x64-gnu](https://github.com/rollup/rollup) and [rollup](https://github.com/rollup/rollup).


Updates `@rollup/rollup-darwin-arm64` from 4.46.1 to 4.46.2
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.46.1...v4.46.2)

Updates `@rollup/rollup-linux-arm64-gnu` from 4.46.1 to 4.46.2
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.46.1...v4.46.2)

Updates `@rollup/rollup-linux-x64-gnu` from 4.46.1 to 4.46.2
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.46.1...v4.46.2)

Updates `rollup` from 4.46.1 to 4.46.2
- [Release notes](https://github.com/rollup/rollup/releases)
- [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rollup/rollup/compare/v4.46.1...v4.46.2)

---
updated-dependencies:
- dependency-name: "@rollup/rollup-darwin-arm64"
  dependency-version: 4.46.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rollup
- dependency-name: "@rollup/rollup-linux-arm64-gnu"
  dependency-version: 4.46.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rollup
- dependency-name: "@rollup/rollup-linux-x64-gnu"
  dependency-version: 4.46.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rollup
- dependency-name: rollup
  dependency-version: 4.46.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rollup
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-31 01:37:58 +02:00
dependabot[bot]
3f4c58a05b lifecycle/aws: bump aws-cdk from 2.1022.0 to 2.1023.0 in /lifecycle/aws (#15881)
Bumps [aws-cdk](https://github.com/aws/aws-cdk-cli/tree/HEAD/packages/aws-cdk) from 2.1022.0 to 2.1023.0.
- [Release notes](https://github.com/aws/aws-cdk-cli/releases)
- [Commits](https://github.com/aws/aws-cdk-cli/commits/aws-cdk@v2.1023.0/packages/aws-cdk)

---
updated-dependencies:
- dependency-name: aws-cdk
  dependency-version: 2.1023.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-31 01:37:50 +02:00
dependabot[bot]
46c9bfb0aa website: bump the build group in /website with 2 updates (#15882)
Bumps the build group in /website with 2 updates: [@swc/core-darwin-arm64](https://github.com/swc-project/swc) and [@swc/core-linux-arm64-gnu](https://github.com/swc-project/swc).


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

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

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

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-31 01:37:39 +02:00
dependabot[bot]
6d325d566c web: bump @sentry/browser from 9.42.1 to 9.43.0 in /web in the sentry group across 1 directory (#15883)
web: bump @sentry/browser in /web in the sentry group across 1 directory

Bumps the sentry group with 1 update in the /web directory: [@sentry/browser](https://github.com/getsentry/sentry-javascript).


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

---
updated-dependencies:
- dependency-name: "@sentry/browser"
  dependency-version: 9.43.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: sentry
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-31 01:37:21 +02:00
dependabot[bot]
5689336f61 web: bump typedoc-plugin-markdown from 4.7.1 to 4.8.0 in /packages/esbuild-plugin-live-reload (#15885)
web: bump typedoc-plugin-markdown

Bumps [typedoc-plugin-markdown](https://github.com/typedoc2md/typedoc-plugin-markdown/tree/HEAD/packages/typedoc-plugin-markdown) from 4.7.1 to 4.8.0.
- [Release notes](https://github.com/typedoc2md/typedoc-plugin-markdown/releases)
- [Changelog](https://github.com/typedoc2md/typedoc-plugin-markdown/blob/main/packages/typedoc-plugin-markdown/CHANGELOG.md)
- [Commits](https://github.com/typedoc2md/typedoc-plugin-markdown/commits/typedoc-plugin-markdown@4.8.0/packages/typedoc-plugin-markdown)

---
updated-dependencies:
- dependency-name: typedoc-plugin-markdown
  dependency-version: 4.8.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-07-31 01:37:07 +02:00
Teffen Ellis
e04ca70cb2 web/a11y: Tables & Modals (#15877)
web: Prep for a11y, tables, modals.
2025-07-30 19:27:11 -04:00
Teffen Ellis
6a5342f621 web/a11y: Form Inputs (#15878)
web: Prep form inputs for a11y.
2025-07-30 19:27:03 -04:00
Teffen Ellis
e250c8f514 web/a11y: Navigation Banner (#15880)
web: Prepare navbar for a11y.
2025-07-30 19:26:34 -04:00
Teffen Ellis
a4e7aa0adc web/a11y: License notice ARIA attributes. (#15872)
web: Add ARIA attributes.
2025-07-30 19:26:23 -04:00
authentik-automation[bot]
ac79acd2bc core, web: update translations (#15873)
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: authentik-automation[bot] <135050075+authentik-automation[bot]@users.noreply.github.com>
2025-07-30 10:34:47 +02:00
69 changed files with 1425 additions and 1839 deletions

View File

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

File diff suppressed because one or more lines are too long

17
go.mod
View File

@@ -5,12 +5,12 @@ go 1.24.0
require (
beryju.io/ldap v0.1.0
github.com/avast/retry-go/v4 v4.6.1
github.com/coreos/go-oidc/v3 v3.14.1
github.com/getsentry/sentry-go v0.34.1
github.com/coreos/go-oidc/v3 v3.15.0
github.com/getsentry/sentry-go v0.35.0
github.com/go-http-utils/etag v0.0.0-20161124023236-513ea8f21eb1
github.com/go-ldap/ldap/v3 v3.4.11
github.com/go-openapi/runtime v0.28.0
github.com/golang-jwt/jwt/v5 v5.2.3
github.com/golang-jwt/jwt/v5 v5.3.0
github.com/google/uuid v1.6.0
github.com/gorilla/handlers v1.5.2
github.com/gorilla/mux v1.8.1
@@ -22,7 +22,7 @@ require (
github.com/mitchellh/mapstructure v1.5.0
github.com/nmcclain/asn1-ber v0.0.0-20170104154839-2661553a0484
github.com/pires/go-proxyproto v0.8.1
github.com/prometheus/client_golang v1.22.0
github.com/prometheus/client_golang v1.23.0
github.com/redis/go-redis/v9 v9.11.0
github.com/sethvargo/go-envconfig v1.3.0
github.com/sirupsen/logrus v1.9.3
@@ -69,18 +69,17 @@ require (
github.com/oklog/ulid v1.3.1 // indirect
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.62.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.65.0 // indirect
github.com/prometheus/procfs v0.16.1 // indirect
github.com/spf13/pflag v1.0.6 // indirect
go.mongodb.org/mongo-driver v1.14.0 // indirect
go.opentelemetry.io/otel v1.24.0 // indirect
go.opentelemetry.io/otel/metric v1.24.0 // indirect
go.opentelemetry.io/otel/trace v1.24.0 // indirect
golang.org/x/crypto v0.38.0 // indirect
golang.org/x/net v0.40.0 // indirect
golang.org/x/sys v0.33.0 // indirect
golang.org/x/text v0.25.0 // indirect
google.golang.org/protobuf v1.36.5 // indirect
google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

32
go.sum
View File

@@ -16,8 +16,8 @@ github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/coreos/go-oidc/v3 v3.14.1 h1:9ePWwfdwC4QKRlCXsJGou56adA/owXczOzwKdOumLqk=
github.com/coreos/go-oidc/v3 v3.14.1/go.mod h1:HaZ3szPaZ0e4r6ebqvsLWlk2Tn+aejfmrfah6hnSYEU=
github.com/coreos/go-oidc/v3 v3.15.0 h1:R6Oz8Z4bqWR7VFQ+sPSvZPQv4x8M+sJkDO5ojgwlyAg=
github.com/coreos/go-oidc/v3 v3.15.0/go.mod h1:HaZ3szPaZ0e4r6ebqvsLWlk2Tn+aejfmrfah6hnSYEU=
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@@ -26,8 +26,8 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/r
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/getsentry/sentry-go v0.34.1 h1:HSjc1C/OsnZttohEPrrqKH42Iud0HuLCXpv8cU1pWcw=
github.com/getsentry/sentry-go v0.34.1/go.mod h1:C55omcY9ChRQIUcVcGcs+Zdy4ZpQGvNJ7JYHIoSWOtE=
github.com/getsentry/sentry-go v0.35.0 h1:+FJNlnjJsZMG3g0/rmmP7GiKjQoUF5EXfEtBwtPtkzY=
github.com/getsentry/sentry-go v0.35.0/go.mod h1:C55omcY9ChRQIUcVcGcs+Zdy4ZpQGvNJ7JYHIoSWOtE=
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 h1:BP4M0CvQ4S3TGls2FvczZtj5Re/2ZzkV9VwqPHH/3Bo=
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
@@ -67,8 +67,8 @@ github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+Gr
github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ=
github.com/go-openapi/validate v0.24.0 h1:LdfDKwNbpB6Vn40xhTdNZAnfLECL81w+VX3BumrGD58=
github.com/go-openapi/validate v0.24.0/go.mod h1:iyeX1sEufmv3nPbBdX3ieNviWnOZaJ1+zquzJEf2BAQ=
github.com/golang-jwt/jwt/v5 v5.2.3 h1:kkGXqQOBSDDWRhWNXTFpqGSCMyh/PLnqUvMGJPDJDs0=
github.com/golang-jwt/jwt/v5 v5.2.3/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=
github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
@@ -140,14 +140,14 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
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/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/prometheus/client_golang v1.23.0 h1:ust4zpdl9r4trLY/gSjlm07PuiBq2ynaXXlptpfy8Uc=
github.com/prometheus/client_golang v1.23.0/go.mod h1:i/o0R9ByOnHX0McrTMTyhYvKE4haaf2mW08I+jGAjEE=
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
github.com/prometheus/common v0.65.0 h1:QDwzd+G1twt//Kwj/Ww6E9FQq1iVMmODnILtW1t2VzE=
github.com/prometheus/common v0.65.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
github.com/redis/go-redis/v9 v9.11.0 h1:E3S08Gl/nJNn5vkxd2i78wZxWAPNZgUNTp8WIJUAiIs=
github.com/redis/go-redis/v9 v9.11.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
@@ -211,8 +211,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=

View File

@@ -9,7 +9,7 @@
"version": "0.0.0",
"license": "MIT",
"devDependencies": {
"aws-cdk": "^2.1022.0",
"aws-cdk": "^2.1023.0",
"cross-env": "^10.0.0"
},
"engines": {
@@ -24,9 +24,9 @@
"license": "MIT"
},
"node_modules/aws-cdk": {
"version": "2.1022.0",
"resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1022.0.tgz",
"integrity": "sha512-GHCu+tDtYMqCiElCl7Fad2/Bt2GmtXEV3dynudoAsV9PlL5ETeLmEN7jflDQxhmr7KhKpQeZJo/PM0DoWCvoHw==",
"version": "2.1023.0",
"resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1023.0.tgz",
"integrity": "sha512-DWMA+IrAsBUNF2RvH7ujpDp7wSJkqTkRL8yfK4AYpEjoGY1KMaKIfxz3M3+Nk3ogM7VhZiW3OGWEOgyDF47HOQ==",
"dev": true,
"license": "Apache-2.0",
"bin": {

View File

@@ -10,7 +10,7 @@
"node": ">=20"
},
"devDependencies": {
"aws-cdk": "^2.1022.0",
"aws-cdk": "^2.1023.0",
"cross-env": "^10.0.0"
}
}

View File

@@ -17958,9 +17958,9 @@
}
},
"node_modules/typescript": {
"version": "5.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"version": "5.9.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz",
"integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==",
"dev": true,
"license": "Apache-2.0",
"bin": {

View File

@@ -2728,9 +2728,9 @@
}
},
"node_modules/typedoc-plugin-markdown": {
"version": "4.7.1",
"resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-4.7.1.tgz",
"integrity": "sha512-HN/fHLm2S6MD4HX8txfB4eWvVBzX/mEYy5U5s1KTAdh3E5uX5/lilswqTzZlPTT6fNZInAboAdFGpbAuBKnE4A==",
"version": "4.8.0",
"resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-4.8.0.tgz",
"integrity": "sha512-BQqXnT9PETe6WEFf8bcsvvGEGQHbwTo/BFyY+RUIsSB05Y0Wn56iF+fK1PY2OKJJIhV4kp4dp7osaP9Bm5a0Zw==",
"dev": true,
"license": "MIT",
"engines": {
@@ -2741,9 +2741,9 @@
}
},
"node_modules/typescript": {
"version": "5.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"version": "5.9.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz",
"integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==",
"dev": true,
"license": "Apache-2.0",
"bin": {

View File

@@ -500,93 +500,6 @@
"integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
"license": "MIT"
},
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.38.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.38.0.tgz",
"integrity": "sha512-CPoznzpuAnIOl4nhj4tRr4gIPj5AfKgkiJmGQDaq+fQnRJTYlcBjbX3wbciGmpoPf8DREufuPRe1tNMZnGdanA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/regexpp": "^4.10.0",
"@typescript-eslint/scope-manager": "8.38.0",
"@typescript-eslint/type-utils": "8.38.0",
"@typescript-eslint/utils": "8.38.0",
"@typescript-eslint/visitor-keys": "8.38.0",
"graphemer": "^1.4.0",
"ignore": "^7.0.0",
"natural-compare": "^1.4.0",
"ts-api-utils": "^2.1.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"@typescript-eslint/parser": "^8.38.0",
"eslint": "^8.57.0 || ^9.0.0",
"typescript": ">=4.8.4 <5.9.0"
}
},
"node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
"version": "7.0.5",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
"integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 4"
}
},
"node_modules/@typescript-eslint/parser": {
"version": "8.38.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.38.0.tgz",
"integrity": "sha512-Zhy8HCvBUEfBECzIl1PKqF4p11+d0aUJS1GeUiuqK9WmOug8YCmC4h4bjyBvMyAMI9sbRczmrYL5lKg/YMbrcQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/scope-manager": "8.38.0",
"@typescript-eslint/types": "8.38.0",
"@typescript-eslint/typescript-estree": "8.38.0",
"@typescript-eslint/visitor-keys": "8.38.0",
"debug": "^4.3.4"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0",
"typescript": ">=4.8.4 <5.9.0"
}
},
"node_modules/@typescript-eslint/project-service": {
"version": "8.38.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.38.0.tgz",
"integrity": "sha512-dbK7Jvqcb8c9QfH01YB6pORpqX1mn5gDZc9n63Ak/+jD67oWXn3Gs0M6vddAN+eDXBCS5EmNWzbSxsn9SzFWWg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/tsconfig-utils": "^8.38.0",
"@typescript-eslint/types": "^8.38.0",
"debug": "^4.3.4"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"typescript": ">=4.8.4 <5.9.0"
}
},
"node_modules/@typescript-eslint/scope-manager": {
"version": "8.38.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.38.0.tgz",
@@ -605,48 +518,6 @@
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/tsconfig-utils": {
"version": "8.38.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.38.0.tgz",
"integrity": "sha512-Lum9RtSE3EroKk/bYns+sPOodqb2Fv50XOl/gMviMKNvanETUuUcC9ObRbzrJ4VSd2JalPqgSAavwrPiPvnAiQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"typescript": ">=4.8.4 <5.9.0"
}
},
"node_modules/@typescript-eslint/type-utils": {
"version": "8.38.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.38.0.tgz",
"integrity": "sha512-c7jAvGEZVf0ao2z+nnz8BUaHZD09Agbh+DY7qvBQqLiz8uJzRgVPj5YvOh8I8uEiH8oIUGIfHzMwUcGVco/SJg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.38.0",
"@typescript-eslint/typescript-estree": "8.38.0",
"@typescript-eslint/utils": "8.38.0",
"debug": "^4.3.4",
"ts-api-utils": "^2.1.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0",
"typescript": ">=4.8.4 <5.9.0"
}
},
"node_modules/@typescript-eslint/types": {
"version": "8.38.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.38.0.tgz",
@@ -661,98 +532,6 @@
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/typescript-estree": {
"version": "8.38.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.38.0.tgz",
"integrity": "sha512-fooELKcAKzxux6fA6pxOflpNS0jc+nOQEEOipXFNjSlBS6fqrJOVY/whSn70SScHrcJ2LDsxWrneFoWYSVfqhQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/project-service": "8.38.0",
"@typescript-eslint/tsconfig-utils": "8.38.0",
"@typescript-eslint/types": "8.38.0",
"@typescript-eslint/visitor-keys": "8.38.0",
"debug": "^4.3.4",
"fast-glob": "^3.3.2",
"is-glob": "^4.0.3",
"minimatch": "^9.0.4",
"semver": "^7.6.0",
"ts-api-utils": "^2.1.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"typescript": ">=4.8.4 <5.9.0"
}
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"dev": true,
"license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/@typescript-eslint/typescript-estree/node_modules/semver": {
"version": "7.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
"integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
"dev": true,
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/@typescript-eslint/utils": {
"version": "8.38.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.38.0.tgz",
"integrity": "sha512-hHcMA86Hgt+ijJlrD8fX0j1j8w4C92zue/8LOPAFioIno+W0+L7KqE8QZKCcPGc/92Vs9x36w/4MPTJhqXdyvg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.7.0",
"@typescript-eslint/scope-manager": "8.38.0",
"@typescript-eslint/types": "8.38.0",
"@typescript-eslint/typescript-estree": "8.38.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0",
"typescript": ">=4.8.4 <5.9.0"
}
},
"node_modules/@typescript-eslint/visitor-keys": {
"version": "8.38.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.38.0.tgz",
@@ -4694,9 +4473,9 @@
}
},
"node_modules/typescript": {
"version": "5.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"version": "5.9.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz",
"integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==",
"dev": true,
"license": "Apache-2.0",
"bin": {
@@ -4731,6 +4510,227 @@
"typescript": ">=4.8.4 <5.9.0"
}
},
"node_modules/typescript-eslint/node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.38.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.38.0.tgz",
"integrity": "sha512-CPoznzpuAnIOl4nhj4tRr4gIPj5AfKgkiJmGQDaq+fQnRJTYlcBjbX3wbciGmpoPf8DREufuPRe1tNMZnGdanA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/regexpp": "^4.10.0",
"@typescript-eslint/scope-manager": "8.38.0",
"@typescript-eslint/type-utils": "8.38.0",
"@typescript-eslint/utils": "8.38.0",
"@typescript-eslint/visitor-keys": "8.38.0",
"graphemer": "^1.4.0",
"ignore": "^7.0.0",
"natural-compare": "^1.4.0",
"ts-api-utils": "^2.1.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"@typescript-eslint/parser": "^8.38.0",
"eslint": "^8.57.0 || ^9.0.0",
"typescript": ">=4.8.4 <5.9.0"
}
},
"node_modules/typescript-eslint/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": {
"version": "8.38.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.38.0.tgz",
"integrity": "sha512-c7jAvGEZVf0ao2z+nnz8BUaHZD09Agbh+DY7qvBQqLiz8uJzRgVPj5YvOh8I8uEiH8oIUGIfHzMwUcGVco/SJg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/types": "8.38.0",
"@typescript-eslint/typescript-estree": "8.38.0",
"@typescript-eslint/utils": "8.38.0",
"debug": "^4.3.4",
"ts-api-utils": "^2.1.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0",
"typescript": ">=4.8.4 <5.9.0"
}
},
"node_modules/typescript-eslint/node_modules/@typescript-eslint/parser": {
"version": "8.38.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.38.0.tgz",
"integrity": "sha512-Zhy8HCvBUEfBECzIl1PKqF4p11+d0aUJS1GeUiuqK9WmOug8YCmC4h4bjyBvMyAMI9sbRczmrYL5lKg/YMbrcQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/scope-manager": "8.38.0",
"@typescript-eslint/types": "8.38.0",
"@typescript-eslint/typescript-estree": "8.38.0",
"@typescript-eslint/visitor-keys": "8.38.0",
"debug": "^4.3.4"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0",
"typescript": ">=4.8.4 <5.9.0"
}
},
"node_modules/typescript-eslint/node_modules/@typescript-eslint/typescript-estree": {
"version": "8.38.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.38.0.tgz",
"integrity": "sha512-fooELKcAKzxux6fA6pxOflpNS0jc+nOQEEOipXFNjSlBS6fqrJOVY/whSn70SScHrcJ2LDsxWrneFoWYSVfqhQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/project-service": "8.38.0",
"@typescript-eslint/tsconfig-utils": "8.38.0",
"@typescript-eslint/types": "8.38.0",
"@typescript-eslint/visitor-keys": "8.38.0",
"debug": "^4.3.4",
"fast-glob": "^3.3.2",
"is-glob": "^4.0.3",
"minimatch": "^9.0.4",
"semver": "^7.6.0",
"ts-api-utils": "^2.1.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"typescript": ">=4.8.4 <5.9.0"
}
},
"node_modules/typescript-eslint/node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/project-service": {
"version": "8.38.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.38.0.tgz",
"integrity": "sha512-dbK7Jvqcb8c9QfH01YB6pORpqX1mn5gDZc9n63Ak/+jD67oWXn3Gs0M6vddAN+eDXBCS5EmNWzbSxsn9SzFWWg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@typescript-eslint/tsconfig-utils": "^8.38.0",
"@typescript-eslint/types": "^8.38.0",
"debug": "^4.3.4"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"typescript": ">=4.8.4 <5.9.0"
}
},
"node_modules/typescript-eslint/node_modules/@typescript-eslint/typescript-estree/node_modules/@typescript-eslint/tsconfig-utils": {
"version": "8.38.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.38.0.tgz",
"integrity": "sha512-Lum9RtSE3EroKk/bYns+sPOodqb2Fv50XOl/gMviMKNvanETUuUcC9ObRbzrJ4VSd2JalPqgSAavwrPiPvnAiQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"typescript": ">=4.8.4 <5.9.0"
}
},
"node_modules/typescript-eslint/node_modules/@typescript-eslint/utils": {
"version": "8.38.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.38.0.tgz",
"integrity": "sha512-hHcMA86Hgt+ijJlrD8fX0j1j8w4C92zue/8LOPAFioIno+W0+L7KqE8QZKCcPGc/92Vs9x36w/4MPTJhqXdyvg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@eslint-community/eslint-utils": "^4.7.0",
"@typescript-eslint/scope-manager": "8.38.0",
"@typescript-eslint/types": "8.38.0",
"@typescript-eslint/typescript-estree": "8.38.0"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"eslint": "^8.57.0 || ^9.0.0",
"typescript": ">=4.8.4 <5.9.0"
}
},
"node_modules/typescript-eslint/node_modules/brace-expansion": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/typescript-eslint/node_modules/ignore": {
"version": "7.0.5",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
"integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 4"
}
},
"node_modules/typescript-eslint/node_modules/minimatch": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"dev": true,
"license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/typescript-eslint/node_modules/semver": {
"version": "7.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
"integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
"dev": true,
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/unbox-primitive": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz",

View File

@@ -1711,9 +1711,9 @@
}
},
"node_modules/typescript": {
"version": "5.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",
"integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==",
"version": "5.9.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz",
"integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==",
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",

2
web/.gitignore vendored
View File

@@ -25,8 +25,6 @@ lib-cov
# Coverage directory used by tools like istanbul
coverage
playwright-report
test-results
*.lcov
# nyc test coverage

View File

@@ -1,90 +0,0 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import type { LocatorContext } from "#e2e/selectors/types";
import { ConsoleLogger } from "#logger/node";
import { expect, Locator } from "@playwright/test";
import { kebabCase } from "change-case";
export type LocatorMatchers = ReturnType<typeof expect<Locator>>;
export interface LocatorProxy extends Pick<Locator, keyof Locator> {
$: Locator;
expect: LocatorMatchers;
}
// Type helpers to extract the shape of the proxy
export type DeepLocatorProxy<T> =
Disposable & T extends Record<string, any>
? T extends HTMLElement
? LocatorProxy
: {
[K in keyof T]: DeepLocatorProxy<T[K]>;
}
: LocatorProxy;
export function createLocatorProxy<T extends Record<string, any>>(
ctx: LocatorContext,
initialPathPrefix: string[] = [],
dataAttribute: string = "test-id",
): DeepLocatorProxy<T> {
dataAttribute = kebabCase(dataAttribute);
function createProxy(path: string[] = initialPathPrefix): any {
const proxyCache = new Map<string, LocatorProxy>();
return new Proxy({} as any, {
get(_, property: string) {
// Build the current path
const currentPath = [...path, property];
// Convert the path to kebab-case and join with hyphens
const selectorValue = currentPath.map((segment) => kebabCase(segment)).join("-");
const selector = `[data-${dataAttribute}="${selectorValue}"]`;
// Create a locator for the current selector
const locator = ctx.locator(selector);
if (proxyCache.has(selector)) {
ConsoleLogger.debug(`Using cached locator for ${selector}`);
return proxyCache.get(selector)!;
}
// Return a new proxy that also behaves like a Locator
// This allows us to either continue chaining or use Locator methods
const nextProxy = new Proxy(locator, {
get(target, prop) {
if (typeof prop === "string") {
// The user is likely trying to access a property on the page.
if (prop === "$") {
return target as any;
}
if (prop === "expect") {
return expect(target);
}
}
// If the property exists on the Locator, use it
if (prop in target) {
const value = (target as any)[prop];
// Bind methods to the locator instance
if (typeof value === "function") {
return value.bind(target);
}
return value;
}
// Otherwise, continue building the path
return createProxy(currentPath)[prop];
},
});
proxyCache.set(selector, nextProxy as LocatorProxy);
return nextProxy;
},
});
}
return createProxy() as DeepLocatorProxy<T>;
}

735
web/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -24,8 +24,8 @@
"pseudolocalize": "node ./scripts/pseudolocalize.mjs",
"storybook": "storybook dev -p 6006",
"storybook:build": "wireit",
"test": "vitest",
"test:e2e": "playwright test",
"test": "wireit",
"test:e2e": "wireit",
"test:e2e:watch": "wireit",
"test:watch": "wireit",
"tsc": "wireit",
@@ -69,9 +69,6 @@
"#flow/*": "./src/flow/*.js",
"#locales/*": "./src/locales/*.js",
"#stories/*": "./src/stories/*.js",
"#tests/*": "./tests/*.js",
"#e2e": "./e2e/index.ts",
"#e2e/*": "./e2e/*.ts",
"#*/browser": {
"types": "./out/*/browser.d.ts",
"import": "./*/browser.js"
@@ -94,7 +91,7 @@
"@codemirror/legacy-modes": "^6.5.1",
"@codemirror/theme-one-dark": "^6.1.3",
"@eslint/js": "^9.31.0",
"@floating-ui/dom": "^1.7.2",
"@floating-ui/dom": "^1.7.3",
"@formatjs/intl-listformat": "^7.7.11",
"@fortawesome/fontawesome-free": "^7.0.0",
"@goauthentik/api": "^2025.6.4-1753714826",
@@ -116,13 +113,12 @@
"@openlayers-elements/maps": "^0.4.0",
"@patternfly/elements": "^4.1.0",
"@patternfly/patternfly": "^4.224.2",
"@playwright/test": "^1.54.1",
"@sentry/browser": "^9.42.1",
"@sentry/browser": "^10.0.0",
"@spotlightjs/spotlight": "^3.0.1",
"@storybook/addon-docs": "^9.0.18",
"@storybook/addon-links": "^9.0.18",
"@storybook/web-components": "^9.0.18",
"@storybook/web-components-vite": "^9.0.18",
"@storybook/addon-docs": "^9.1.0",
"@storybook/addon-links": "^9.1.0",
"@storybook/web-components": "^9.1.0",
"@storybook/web-components-vite": "^9.1.0",
"@types/codemirror": "^5.60.16",
"@types/grecaptcha": "^3.0.9",
"@types/guacamole-common-js": "^1.5.3",
@@ -132,7 +128,6 @@
"@types/react-dom": "^19.1.6",
"@typescript-eslint/eslint-plugin": "^8.38.0",
"@typescript-eslint/parser": "^8.38.0",
"@vitest/browser": "^3.2.4",
"@wdio/browser-runner": "^9.18.4",
"@wdio/cli": "9.15",
"@wdio/spec-reporter": "^9.15.0",
@@ -142,7 +137,7 @@
"change-case": "^5.4.4",
"chart.js": "^4.5.0",
"chartjs-adapter-date-fns": "^3.0.0",
"chromedriver": "^138.0.4",
"chromedriver": "^138.0.5",
"codemirror": "^6.0.2",
"construct-style-sheets-polyfill": "^3.1.0",
"core-js": "^3.44.0",
@@ -168,9 +163,6 @@
"md-front-matter": "^1.0.4",
"mermaid": "^11.9.0",
"npm-run-all": "^4.1.5",
"pino": "^9.7.0",
"pino-pretty": "^13.0.0",
"playwright": "^1.54.1",
"prettier": "^3.6.2",
"pseudolocale": "^2.1.0",
"rapidoc": "^9.3.8",
@@ -191,7 +183,6 @@
"turnstile-types": "^1.2.3",
"typescript": "^5.8.3",
"typescript-eslint": "^8.38.0",
"unique-names-generator": "^4.7.1",
"unist-util-visit": "^5.0.0",
"vite": "^7.0.6",
"vitest": "^3.2.4",
@@ -203,9 +194,9 @@
"@esbuild/darwin-arm64": "^0.25.4",
"@esbuild/linux-arm64": "^0.25.4",
"@esbuild/linux-x64": "^0.25.4",
"@rollup/rollup-darwin-arm64": "^4.46.1",
"@rollup/rollup-linux-arm64-gnu": "^4.46.1",
"@rollup/rollup-linux-x64-gnu": "^4.46.1"
"@rollup/rollup-darwin-arm64": "^4.46.2",
"@rollup/rollup-linux-arm64-gnu": "^4.46.2",
"@rollup/rollup-linux-x64-gnu": "^4.46.2"
},
"wireit": {
"build": {
@@ -278,7 +269,7 @@
"command": "lit-analyzer src"
},
"lint:types:tests": {
"command": "tsc --noEmit -p tsconfig.test.json"
"command": "tsc --noEmit -p ./tests"
},
"lint:types": {
"command": "tsc -p .",
@@ -327,7 +318,7 @@
],
"env": {
"CI": "true",
"TS_NODE_PROJECT": "tsconfig.test.json"
"TS_NODE_PROJECT": "./tests/tsconfig.test.json"
}
},
"test:e2e:watch": {
@@ -336,7 +327,7 @@
"build"
],
"env": {
"TS_NODE_PROJECT": "tsconfig.test.json"
"TS_NODE_PROJECT": "./tests/tsconfig.test.json"
}
},
"test:watch": {

View File

@@ -23,7 +23,7 @@
"formdata-polyfill": "^4.0.10",
"jquery": "^3.7.1",
"prettier": "^3.5.3",
"rollup": "^4.46.1",
"rollup": "^4.46.2",
"rollup-plugin-copy": "^3.5.0",
"weakmap-polyfill": "^2.0.4"
},

View File

@@ -50,12 +50,13 @@ export class CoreGroupSearch extends CustomListenerElement(AKElement) {
search!: SearchSelect<Group>;
@property({ type: String })
public name?: string | null;
name: string | null | undefined;
selectedGroup?: Group;
constructor() {
super();
this.selected = this.selected.bind(this);
this.handleSearchUpdate = this.handleSearchUpdate.bind(this);
}
@@ -82,9 +83,9 @@ export class CoreGroupSearch extends CustomListenerElement(AKElement) {
this.dispatchEvent(new InputEvent("input", { bubbles: true, composed: true }));
}
selected = (group: Group) => {
selected(group: Group) {
return this.group === group.pk;
};
}
render() {
return html`

View File

@@ -40,13 +40,7 @@ export class AkCryptoCertificateSearch extends CustomListenerElement(AKElement)
search!: SearchSelect<CertificateKeyPair>;
@property({ type: String })
public name?: string | null;
@property({ type: String })
public label?: string | undefined;
@property({ type: String })
public placeholder?: string | undefined;
name: string | null | undefined;
/**
* Set to `true` to allow certificates without private key to show up. When set to `false`,
@@ -54,7 +48,7 @@ export class AkCryptoCertificateSearch extends CustomListenerElement(AKElement)
* @attr
*/
@property({ type: Boolean, attribute: "nokey" })
public noKey = false;
noKey = false;
/**
* Set this to true if, should there be only one certificate available, you want the system to
@@ -63,12 +57,16 @@ export class AkCryptoCertificateSearch extends CustomListenerElement(AKElement)
* @attr
*/
@property({ type: Boolean, attribute: "singleton" })
public singleton = false;
singleton = false;
/**
* @todo Document this.
*/
public selectedKeypair?: CertificateKeyPair;
selectedKeypair?: CertificateKeyPair;
constructor() {
super();
this.selected = this.selected.bind(this);
this.fetchObjects = this.fetchObjects.bind(this);
this.handleSearchUpdate = this.handleSearchUpdate.bind(this);
}
get value() {
return this.selectedKeypair ? renderValue(this.selectedKeypair) : null;
@@ -87,13 +85,13 @@ export class AkCryptoCertificateSearch extends CustomListenerElement(AKElement)
}
}
handleSearchUpdate = (ev: CustomEvent) => {
handleSearchUpdate(ev: CustomEvent) {
ev.stopPropagation();
this.selectedKeypair = ev.detail.value;
this.dispatchEvent(new InputEvent("input", { bubbles: true, composed: true }));
};
}
fetchObjects = async (query?: string): Promise<CertificateKeyPair[]> => {
async fetchObjects(query?: string): Promise<CertificateKeyPair[]> {
const args: CryptoCertificatekeypairsListRequest = {
ordering: "name",
hasKey: !this.noKey,
@@ -106,21 +104,19 @@ export class AkCryptoCertificateSearch extends CustomListenerElement(AKElement)
args,
);
return certificates.results;
};
}
selected = (item: CertificateKeyPair, items: CertificateKeyPair[]) => {
selected(item: CertificateKeyPair, items: CertificateKeyPair[]) {
return (
(this.singleton && !this.certificate && items.length === 1) ||
(!!this.certificate && this.certificate === item.pk)
);
};
}
render() {
return html`
<ak-search-select
name=${ifDefined(this.name ?? undefined)}
label=${ifDefined(this.label ?? undefined)}
placeholder=${ifDefined(this.placeholder)}
.fetchObjects=${this.fetchObjects}
.renderElement=${renderElement}
.value=${renderValue}

View File

@@ -3,7 +3,6 @@ import "#elements/forms/SearchSelect/index";
import { DEFAULT_CONFIG } from "#common/api/config";
import { AKElement } from "#elements/Base";
import type { HorizontalFormElement } from "#elements/forms/HorizontalFormElement";
import { SearchSelect } from "#elements/forms/SearchSelect/index";
import { CustomListenerElement } from "#elements/utils/eventEmitter";
@@ -12,7 +11,6 @@ import { RenderFlowOption } from "#admin/flows/utils";
import type { Flow, FlowsInstancesListRequest } from "@goauthentik/api";
import { FlowsApi, FlowsInstancesListDesignationEnum } from "@goauthentik/api";
import { msg } from "@lit/localize";
import { html } from "lit";
import { property, query } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js";
@@ -35,17 +33,17 @@ export function getFlowValue(flow: Flow | undefined): string | undefined {
* A wrapper around SearchSelect that understands the basic semantics of querying about Flows. This
* code eliminates the long blocks of unreadable invocation that were embedded in every provider, as well as in
* sources, brands, and applications.
*
*/
export abstract class FlowSearch<T extends Flow> extends CustomListenerElement(AKElement) {
//#region Properties
export class FlowSearch<T extends Flow> extends CustomListenerElement(AKElement) {
/**
* The type of flow we're looking for.
*
* @attr
*/
@property({ type: String })
public flowType?: FlowsInstancesListDesignationEnum;
flowType?: FlowsInstancesListDesignationEnum;
/**
* The id of the current flow, if any. For stages where the flow is already defined.
@@ -53,7 +51,7 @@ export abstract class FlowSearch<T extends Flow> extends CustomListenerElement(A
* @attr
*/
@property({ type: String })
public currentFlow?: string | undefined;
currentFlow?: string | undefined;
/**
* If true, it is not valid to leave the flow blank.
@@ -61,7 +59,10 @@ export abstract class FlowSearch<T extends Flow> extends CustomListenerElement(A
* @attr
*/
@property({ type: Boolean })
public required?: boolean = false;
required?: boolean = false;
@query("ak-search-select")
search!: SearchSelect<T>;
/**
* When specified and the object instance does not have a flow selected, auto-select the flow with the given slug.
@@ -69,81 +70,60 @@ export abstract class FlowSearch<T extends Flow> extends CustomListenerElement(A
* @attr
*/
@property()
public defaultFlowSlug?: string;
defaultFlowSlug?: string;
@property({ type: String })
public name?: string;
name: string | null | undefined;
/**
* The label of the input, for forms.
*
* @attr
*/
@property({ type: String })
public label?: string;
/**
* The textual placeholder for the search's <input> object, if currently empty. Used as the
* native <input> object's `placeholder` field.
*
* @attr
*/
@property({ type: String })
public placeholder = msg("Select a flow...");
@query("ak-search-select")
protected search!: SearchSelect<T>;
protected selectedFlow?: T;
selectedFlow?: T;
get value() {
return this.selectedFlow ? getFlowValue(this.selectedFlow) : null;
}
protected searchUpdateListener = (event: CustomEvent) => {
event.stopPropagation();
this.selectedFlow = event.detail.value;
constructor() {
super();
this.fetchObjects = this.fetchObjects.bind(this);
this.selected = this.selected.bind(this);
this.handleSearchUpdate = this.handleSearchUpdate.bind(this);
}
handleSearchUpdate(ev: CustomEvent) {
ev.stopPropagation();
this.selectedFlow = ev.detail.value;
this.dispatchEvent(new InputEvent("input", { bubbles: true, composed: true }));
};
}
protected fetchObjects = (query?: string): Promise<Flow[]> => {
async fetchObjects(query?: string): Promise<Flow[]> {
const args: FlowsInstancesListRequest = {
ordering: "slug",
designation: this.flowType,
...(query ? { search: query } : {}),
...(query !== undefined ? { search: query } : {}),
};
return new FlowsApi(DEFAULT_CONFIG).flowsInstancesList(args).then((flows) => flows.results);
};
const flows = await new FlowsApi(DEFAULT_CONFIG).flowsInstancesList(args);
return flows.results;
}
/* This is the most commonly overridden method of this class. About half of the Flow Searches
* use this method, but several have more complex needs, such as relating to the brand, or just
* returning false.
*/
protected selected(flow: Flow): boolean {
selected(flow: Flow): boolean {
let selected = this.currentFlow === flow.pk;
if (!this.currentFlow && this.defaultFlowSlug && flow.slug === this.defaultFlowSlug) {
return true;
selected = true;
}
return this.currentFlow === flow.pk;
return selected;
}
connectedCallback() {
super.connectedCallback();
const horizontalContainer = this.closest<HorizontalFormElement>(
"ak-form-element-horizontal[name]",
);
const horizontalContainer = this.closest("ak-form-element-horizontal[name]");
if (!horizontalContainer) {
throw new Error("This search can only be used in a named ak-form-element-horizontal");
}
const name = horizontalContainer.getAttribute("name");
const myName = this.getAttribute("name");
if (name !== null && name !== myName) {
this.setAttribute("name", name);
}
@@ -157,10 +137,8 @@ export abstract class FlowSearch<T extends Flow> extends CustomListenerElement(A
.renderElement=${renderElement}
.renderDescription=${renderDescription}
.value=${getFlowValue}
placeholder=${ifDefined(this.placeholder)}
label=${ifDefined(this.label)}
name=${ifDefined(this.name)}
@ak-change=${this.searchUpdateListener}
name=${ifDefined(this.name ?? undefined)}
@ak-change=${this.handleSearchUpdate}
?blankable=${!this.required}
>
</ak-search-select>

View File

@@ -19,9 +19,14 @@ export class AkBrandedFlowSearch<T extends Flow> extends FlowSearch<T> {
* @attr
*/
@property({ attribute: false, type: String })
public brandFlow?: string;
brandFlow?: string;
protected override selected(flow: Flow): boolean {
constructor() {
super();
this.selected = this.selected.bind(this);
}
selected(flow: Flow): boolean {
return super.selected(flow) || flow.pk === this.brandFlow;
}
}

View File

@@ -24,7 +24,7 @@ export class AkFlowSearchNoDefault<T extends Flow> extends FlowSearch<T> {
.renderElement=${renderElement}
.renderDescription=${renderDescription}
.value=${getFlowValue}
@ak-change=${this.searchUpdateListener}
@ak-change=${this.handleSearchUpdate}
?blankable=${!this.required}
>
</ak-search-select>

View File

@@ -18,8 +18,9 @@ export class AkSourceFlowSearch<T extends Flow> extends FlowSearch<T> {
*
* @attr
*/
@property({ type: String })
public fallback?: string;
fallback: string | undefined;
/**
* The primary key of the Source (not the Flow). Mostly the instancePk itself, used to affirm
@@ -28,11 +29,16 @@ export class AkSourceFlowSearch<T extends Flow> extends FlowSearch<T> {
* @attr
*/
@property({ type: String })
public instanceId?: string;
instanceId: string | undefined;
constructor() {
super();
this.selected = this.selected.bind(this);
}
// If there's no instance or no currentFlowId for it and the flow resembles the fallback,
// otherwise defer to the parent class.
protected override selected(flow: Flow): boolean {
selected(flow: Flow): boolean {
return (
(!this.instanceId && !this.currentFlow && flow.slug === this.fallback) ||
super.selected(flow)

View File

@@ -10,25 +10,35 @@ import { html, nothing } from "lit";
import { customElement, property } from "lit/decorators.js";
@customElement("ak-license-notice")
export class AkLicenceNotice extends WithLicenseSummary(AKElement) {
export class AKLicenceNotice extends WithLicenseSummary(AKElement) {
static styles = [$PFBase];
@property()
notice = msg("Enterprise only");
public label = msg("Enterprise only");
@property()
public description = msg("Learn more about the enterprise license.");
render() {
return this.hasEnterpriseLicense
? nothing
: html`
<ak-alert class="pf-c-radio__description" inline plain>
<a href="#/enterprise/licenses">${this.notice}</a>
</ak-alert>
`;
if (this.hasEnterpriseLicense) {
return nothing;
}
return html`
<ak-alert class="pf-c-radio__description" inline plain>
<a
aria-label="${this.label}"
aria-description="${this.description}"
href="#/enterprise/licenses"
>${this.label}</a
>
</ak-alert>
`;
}
}
declare global {
interface HTMLElementTagNameMap {
"ak-license-notice": AkLicenceNotice;
"ak-license-notice": AKLicenceNotice;
}
}

View File

@@ -140,8 +140,6 @@ export function renderForm(
.errorMessages=${errors?.certificate ?? []}
>
<ak-crypto-certificate-search
label=${msg("Certificate")}
placeholder=${msg("Select a certificate...")}
certificate=${ifDefined(provider?.certificate ?? nothing)}
name="certificate"
>

View File

@@ -124,7 +124,6 @@ export function renderForm(
) {
return html` <ak-text-input
name="name"
placeholder=${msg("Provider name")}
label=${msg("Name")}
value=${ifDefined(provider?.name)}
required
@@ -136,8 +135,6 @@ export function renderForm(
required
>
<ak-flow-search
label=${msg("Authorization flow")}
placeholder=${msg("Select an authorization flow...")}
flowType=${FlowsInstancesListDesignationEnum.Authorization}
.currentFlow=${provider?.authorizationFlow}
required
@@ -200,8 +197,6 @@ export function renderForm(
<ak-form-element-horizontal label=${msg("Signing Key")} name="signingKey">
<!-- NOTE: 'null' cast to 'undefined' on signingKey to satisfy Lit requirements -->
<ak-crypto-certificate-search
label=${msg("Signing Key")}
placeholder=${msg("Select a signing key...")}
certificate=${ifDefined(provider?.signingKey ?? undefined)}
singleton
></ak-crypto-certificate-search>
@@ -210,8 +205,6 @@ export function renderForm(
<ak-form-element-horizontal label=${msg("Encryption Key")} name="encryptionKey">
<!-- NOTE: 'null' cast to 'undefined' on encryptionKey to satisfy Lit requirements -->
<ak-crypto-certificate-search
label=${msg("Encryption Key")}
placeholder=${msg("Select an encryption key...")}
certificate=${ifDefined(provider?.encryptionKey ?? undefined)}
></ak-crypto-certificate-search>
<p class="pf-c-form__helper-text">${msg("Key used to encrypt the tokens.")}</p>
@@ -226,8 +219,6 @@ export function renderForm(
label=${msg("Authentication flow")}
>
<ak-flow-search
label=${msg("Authentication flow")}
placeholder=${msg("Select an authentication flow...")}
flowType=${FlowsInstancesListDesignationEnum.Authentication}
.currentFlow=${provider?.authenticationFlow}
></ak-flow-search>
@@ -243,8 +234,6 @@ export function renderForm(
required
>
<ak-flow-search
label=${msg("Invalidation flow")}
placeholder=${msg("Select an invalidation flow...")}
flowType=${FlowsInstancesListDesignationEnum.Invalidation}
.currentFlow=${provider?.invalidationFlow}
defaultFlowSlug="default-provider-invalidation-flow"

View File

@@ -26,7 +26,6 @@ import {
RbacPermissionsAssignedByUsersListModelEnum,
User,
} from "@goauthentik/api";
import { IDGenerator } from "@goauthentik/core/id";
import MDProviderOAuth2 from "~docs/add-secure-apps/providers/oauth2/index.mdx";
@@ -268,16 +267,12 @@ export class OAuth2ProviderViewPage extends AKElement {
<div class="pf-c-card__body">
<form class="pf-c-form">
<div class="pf-c-form__group">
<label
class="pf-c-form__label"
for="${IDGenerator.elementID("providerInfo")}"
>
<label class="pf-c-form__label">
<span class="pf-c-form__label-text"
>${msg("OpenID Configuration URL")}</span
>
</label>
<input
id="${IDGenerator.elementID("providerInfo")}"
class="pf-c-form-control"
readonly
type="text"
@@ -285,16 +280,12 @@ export class OAuth2ProviderViewPage extends AKElement {
/>
</div>
<div class="pf-c-form__group">
<label
class="pf-c-form__label"
for="${IDGenerator.elementID("issuer")}"
>
<label class="pf-c-form__label">
<span class="pf-c-form__label-text"
>${msg("OpenID Configuration Issuer")}</span
>
</label>
<input
id="${IDGenerator.elementID("issuer")}"
class="pf-c-form-control"
readonly
type="text"
@@ -303,16 +294,12 @@ export class OAuth2ProviderViewPage extends AKElement {
</div>
<hr class="pf-c-divider" />
<div class="pf-c-form__group">
<label
class="pf-c-form__label"
for="${IDGenerator.elementID("authorize")}"
>
<label class="pf-c-form__label">
<span class="pf-c-form__label-text"
>${msg("Authorize URL")}</span
>
</label>
<input
id="${IDGenerator.elementID("authorize")}"
class="pf-c-form-control"
readonly
type="text"
@@ -320,14 +307,10 @@ export class OAuth2ProviderViewPage extends AKElement {
/>
</div>
<div class="pf-c-form__group">
<label
class="pf-c-form__label"
for="${IDGenerator.elementID("token")}"
>
<label class="pf-c-form__label">
<span class="pf-c-form__label-text">${msg("Token URL")}</span>
</label>
<input
id="${IDGenerator.elementID("token")}"
class="pf-c-form-control"
readonly
type="text"
@@ -335,16 +318,12 @@ export class OAuth2ProviderViewPage extends AKElement {
/>
</div>
<div class="pf-c-form__group">
<label
class="pf-c-form__label"
for="${IDGenerator.elementID("userInfo")}"
>
<label class="pf-c-form__label">
<span class="pf-c-form__label-text"
>${msg("Userinfo URL")}</span
>
</label>
<input
id="${IDGenerator.elementID("userInfo")}"
class="pf-c-form-control"
readonly
type="text"
@@ -352,14 +331,10 @@ export class OAuth2ProviderViewPage extends AKElement {
/>
</div>
<div class="pf-c-form__group">
<label
class="pf-c-form__label"
for="${IDGenerator.elementID("logout")}"
>
<label class="pf-c-form__label">
<span class="pf-c-form__label-text">${msg("Logout URL")}</span>
</label>
<input
id="${IDGenerator.elementID("logout")}"
class="pf-c-form-control"
readonly
type="text"
@@ -367,14 +342,10 @@ export class OAuth2ProviderViewPage extends AKElement {
/>
</div>
<div class="pf-c-form__group">
<label
class="pf-c-form__label"
for="${IDGenerator.elementID("jwks")}"
>
<label class="pf-c-form__label">
<span class="pf-c-form__label-text">${msg("JWKS URL")}</span>
</label>
<input
id="${IDGenerator.elementID("jwks")}"
class="pf-c-form-control"
readonly
type="text"
@@ -420,12 +391,9 @@ export class OAuth2ProviderViewPage extends AKElement {
${renderDescriptionList(
[
[
html`<label for="${IDGenerator.elementID("preview-user")}"
>${msg("Preview for user")}</label
>`,
msg("Preview for user"),
html`
<ak-search-select
id="${IDGenerator.elementID("preview-user")}"
.fetchObjects=${async (query?: string): Promise<User[]> => {
const args: CoreUsersListRequest = {
ordering: "username",

View File

@@ -45,7 +45,6 @@ export function renderForm(
<ak-text-input
name="name"
label=${msg("Name")}
placeholder=${msg("Provider name")}
value=${ifDefined(provider?.name)}
.errorMessages=${errors?.name ?? []}
required
@@ -59,8 +58,6 @@ export function renderForm(
.errorMessages=${errors?.authorizationFlow ?? []}
>
<ak-branded-flow-search
label=${msg("Authentication flow")}
placeholder=${msg("Select an authentication flow...")}
flowType=${FlowsInstancesListDesignationEnum.Authentication}
.currentFlow=${provider?.authorizationFlow}
.brandFlow=${brand?.flowAuthentication}

View File

@@ -35,11 +35,6 @@
--ak-navbar--height: 7rem;
}
.pf-c-form__group {
--pf-c-form--m-horizontal__group-label--md--GridColumnWidth: minmax(max-content, 9.375rem);
column-gap: var(--pf-global--spacer--md);
}
@supports selector(::-webkit-scrollbar) {
::-webkit-scrollbar {
width: 5px;

View File

@@ -292,7 +292,7 @@ export function applyDocumentTheme(hint: CSSColorSchemeValue | UIThemeHint = "au
* @todo Can this be handled with a Lit Mixin?
*/
export function rootInterface<T extends HTMLElement = HTMLElement>(): T {
const element = document.body.querySelector<T>("[data-test-id=interface-root]");
const element = document.body.querySelector<T>("[data-ak-interface-root]");
if (!element) {
throw new Error(

View File

@@ -1,14 +1,10 @@
import { SlottedTemplateResult } from "#elements/types";
import { html, nothing, TemplateResult } from "lit";
import { classMap } from "lit/directives/class-map.js";
import { map } from "lit/directives/map.js";
export type DescriptionPair = [
term: SlottedTemplateResult,
desc: SlottedTemplateResult | undefined,
];
export type DescriptionRecord = { term: string; desc: SlottedTemplateResult | undefined };
export type DescriptionDesc = string | TemplateResult | undefined | typeof nothing;
export type DescriptionPair = [string, DescriptionDesc];
export type DescriptionRecord = { term: string; desc: DescriptionDesc };
interface DescriptionConfig {
horizontal?: boolean;

View File

@@ -175,6 +175,7 @@ export class NavigationButtons extends AKElement {
return html`<img
class="pf-c-page__header-tools-item pf-c-avatar pf-m-hidden pf-m-visible-on-xl"
src=${ifDefined(this.me?.user.avatar)}
aria-hidden="true"
alt="${msg("Avatar image")}"
/>`;
}
@@ -189,7 +190,7 @@ export class NavigationButtons extends AKElement {
}
render() {
return html`<div class="pf-c-page__header-tools">
return html`<div role="presentation" class="pf-c-page__header-tools">
<div class="pf-c-page__header-tools-group">
${this.renderApiDrawerTrigger()}
<!-- -->

View File

@@ -88,7 +88,7 @@ export class AKPageNavbar
color: var(--ak-dark-foreground);
}
navbar {
.main-content {
border-bottom: var(--pf-global--BorderWidth--sm);
border-bottom-style: solid;
border-bottom-color: var(--pf-global--BorderColor--100);
@@ -350,7 +350,12 @@ export class AKPageNavbar
renderIcon() {
if (this.icon) {
if (this.iconImage && !this.icon.startsWith("fa://")) {
return html`<img class="accent-icon pf-icon" src="${this.icon}" alt="page icon" />`;
return html`<img
aria-hidden="true"
class="accent-icon pf-icon"
src="${this.icon}"
alt="page icon"
/>`;
}
const icon = this.icon.replaceAll("fa://", "fa ");
@@ -362,9 +367,9 @@ export class AKPageNavbar
render(): TemplateResult {
return html` <slot></slot>
<navbar aria-label="Main" class="navbar">
<aside class="brand ${this.open ? "" : "pf-m-collapsed"}">
<a href="#/">
<div role="banner" aria-label="Main" class="main-content">
<aside role="presentation" class="brand ${this.open ? "" : "pf-m-collapsed"}">
<a aria-label="${msg("Home")}" href="#/">
<div class="logo">
<img
src=${themeImage(this.brandingLogo)}
@@ -375,31 +380,35 @@ export class AKPageNavbar
</a>
</aside>
<button
aria-controls="global-nav"
class="sidebar-trigger pf-c-button pf-m-plain"
@click=${this.#toggleSidebar}
aria-label=${msg("Toggle sidebar")}
aria-label=${this.open ? msg("Collapse navigation") : msg("Expand navigation")}
aria-expanded=${this.open ? "true" : "false"}
>
<i class="fas fa-bars"></i>
<i aria-hidden="true" class="fas fa-bars"></i>
</button>
<section
class="items primary pf-c-content ${this.description ? "block-sibling" : ""}"
>
<h1 class="page-title">
<div class="items primary pf-c-content ${this.description ? "block-sibling" : ""}">
<h1 aria-labelledby="page-navbar-heading" class="page-title">
${this.hasIcon
? html`<slot name="icon">${this.renderIcon()}</slot>`
? html`<slot aria-hidden="true" name="icon">${this.renderIcon()}</slot>`
: nothing}
${this.header}
<span id="page-navbar-heading">${this.header}</span>
</h1>
</section>
</div>
${this.description
? html`<section class="items page-description pf-c-content">
? html`<div
role="heading"
aria-level="2"
aria-label="${this.description}"
class="items page-description pf-c-content"
>
<p>${this.description}</p>
</section>`
</div>`
: nothing}
<section class="items secondary">
<div class="items secondary">
<div class="pf-c-page__header-tools-group">
<ak-nav-buttons .uiConfig=${this.uiConfig} .me=${this.session}>
<a
@@ -411,8 +420,8 @@ export class AKPageNavbar
</a>
</ak-nav-buttons>
</div>
</section>
</navbar>`;
</div>
</div>`;
}
//#endregion

View File

@@ -28,6 +28,6 @@ export abstract class Interface extends AKElement {
public connectedCallback(): void {
super.connectedCallback();
this.dataset.testId = "interface-root";
this.dataset.akInterfaceRoot = this.tagName.toLowerCase();
}
}

View File

@@ -103,7 +103,7 @@ type ContentValue = SlottedTemplateResult | undefined;
*/
export function akLoadingOverlay(
properties: ILoadingOverlay = {},
content: string | ILoadingOverlayContent = {},
content: ILoadingOverlayContent = {},
) {
// `heading` here is an Object.key of ILoadingOverlayContent, not the obsolete
// slot-name.

View File

@@ -58,10 +58,6 @@ export class HorizontalFormElement extends AKElement {
grid-template-columns:
var(--pf-c-form--m-horizontal__group-label--md--GridColumnWidth)
var(--pf-c-form--m-horizontal__group-control--md--GridColumnWidth);
&[data-flow-direction="row"] {
grid-template-columns: 1fr;
}
}
.pf-c-form__group-label {

View File

@@ -31,99 +31,73 @@ export interface ISearchSelectBase<T> {
emptyOption: string;
}
export abstract class SearchSelectBase<T>
extends AkControlElement<string>
implements ISearchSelectBase<T>
{
export class SearchSelectBase<T> extends AkControlElement<string> implements ISearchSelectBase<T> {
static styles = [PFBase];
//#region Properties
// A function which takes the query state object (accepting that it may be empty) and returns a
// new collection of objects.
fetchObjects!: (query?: string) => Promise<T[]>;
/**
* A function which takes the query state object (accepting that it may be empty)
* and returns a
* new collection of objects.
*/
public abstract fetchObjects: (query?: string) => Promise<T[]>;
// A function passed to this object that extracts a string representation of items of the
// collection under search.
renderElement!: (element: T) => string;
/**
* A function passed to this object that extracts a string representation of items of the
* collection under search.
*/
public abstract renderElement: (element: T) => string;
// A function passed to this object that extracts an HTML representation of additional
// information for items of the collection under search.
renderDescription?: (element: T) => string | TemplateResult;
/**
* A function passed to this object that extracts an HTML representation of additional
* information for items of the collection under search.
*/
public abstract renderDescription?: (element: T) => string | TemplateResult;
// A function which returns the currently selected object's primary key, used for serialization
// into forms.
value!: (element: T | undefined) => string;
/**
* A function which returns the currently selected object's primary key, used for serialization
* into forms.
*/
public abstract value: (element?: T) => string;
// A function passed to this object that determines an object in the collection under search
// should be automatically selected. Only used when the search itself is responsible for
// fetching the data; sets an initial default value.
selected?: (element: T, elements: T[]) => boolean;
/**
* A function passed to this object that determines an object in the collection under search
* should be automatically selected. Only used when the search itself is responsible for
* fetching the data; sets an initial default value.
*/
public abstract selected?: (element: T, elements: T[]) => boolean;
/**
* A function passed to this object (or using the default below) that groups objects in the
* collection under search into categories.
*/
public groupBy: (items: T[]) => [string, T[]][] = (items) => {
return groupBy(items, () => "");
// A function passed to this object (or using the default below) that groups objects in the
// collection under search into categories.
groupBy: (items: T[]) => [string, T[]][] = (items: T[]): [string, T[]][] => {
return groupBy(items, () => {
return "";
});
};
// Whether or not the dropdown component can be left blank
@property({ type: Boolean })
public blankable = false;
blankable = false;
// An initial string to filter the search contents, and the value of the input which further
// serves to restrict the search
@property()
public query?: string;
query?: string;
// The objects currently available under search
@property({ attribute: false })
public objects?: T[];
objects?: T[];
// The currently selected object
@property({ attribute: false })
public selectedObject?: T;
selectedObject?: T;
// Used to inform the form of the name of the object
@property()
public name?: string;
// Used to inform the form of the input label.
@property()
public label?: string;
name?: string;
// The textual placeholder for the search's <input> object, if currently empty. Used as the
// native <input> object's `placeholder` field.
@property()
public placeholder: string = msg("Select an object.");
placeholder: string = msg("Select an object.");
// A textual string representing "The user has affirmed they want to leave the selection blank."
// Only used if `blankable` above is true.
@property()
public emptyOption = "---------";
emptyOption = "---------";
//#endregion
//#region State
#loading = false;
isFetchingData = false;
@state()
protected error?: APIError;
//#endregion
error?: APIError;
public toForm(): string {
if (!this.objects) {
@@ -147,29 +121,26 @@ export abstract class SearchSelectBase<T>
}
public async updateData() {
if (this.#loading) {
if (this.isFetchingData) {
return Promise.resolve();
}
this.#loading = true;
this.isFetchingData = true;
this.dispatchEvent(new Event("loading"));
return this.fetchObjects(this.query)
.then((nextObjects) => {
if (this.selected) {
for (const obj of nextObjects) {
if (this.selected(obj, nextObjects)) {
this.selectedObject = obj;
this.dispatchChangeEvent(this.selectedObject);
}
nextObjects.forEach((obj) => {
if (this.selected && this.selected(obj, nextObjects || [])) {
this.selectedObject = obj;
this.dispatchChangeEvent(this.selectedObject);
}
}
});
this.objects = nextObjects;
this.#loading = false;
this.isFetchingData = false;
})
.catch(async (error: unknown) => {
this.#loading = false;
this.isFetchingData = false;
this.objects = undefined;
const parsedError = await parseAPIResponseError(error);
@@ -192,10 +163,9 @@ export abstract class SearchSelectBase<T>
this.removeEventListener(EVENT_REFRESH, this.updateData);
}
#searchListener = (event: InputEvent) => {
private onSearch(event: InputEvent) {
const value = (event.target as SearchSelectView).rawValue;
if (!value) {
if (value === undefined) {
this.selectedObject = undefined;
return;
}
@@ -204,7 +174,7 @@ export abstract class SearchSelectBase<T>
this.updateData()?.then(() => {
this.dispatchChangeEvent(this.selectedObject);
});
};
}
private onSelect(event: InputEvent) {
const value = (event.target as SearchSelectView).value;
@@ -288,22 +258,21 @@ export abstract class SearchSelectBase<T>
.options=${options}
value=${ifDefined(value)}
?blankable=${this.blankable}
label=${ifDefined(this.label)}
name=${ifDefined(this.name)}
placeholder=${this.placeholder}
emptyOption=${ifDefined(this.blankable ? this.emptyOption : undefined)}
@input=${this.#searchListener}
@input=${this.onSearch}
@change=${this.onSelect}
></ak-search-select-view> `;
}
public override updated(changed: PropertyValues<this>) {
if (!this.#loading && changed.has("objects")) {
if (!this.isFetchingData && changed.has("objects")) {
this.dispatchEvent(new Event("ready"));
}
// It is not safe for automated tests to interact with this component while it is fetching
// data.
if (!this.#loading) {
if (!this.isFetchingData) {
this.setAttribute("data-ouia-component-safe", "true");
}
}

View File

@@ -47,26 +47,18 @@ export interface ISearchSelectEz<T> extends ISearchSelectBase<T> {
export class SearchSelectEz<T> extends SearchSelectBase<T> implements ISearchSelectEz<T> {
static styles = [...SearchSelectBase.styles];
public fetchObjects!: (query?: string) => Promise<T[]>;
public renderElement!: (element: T) => string;
public renderDescription?: ((element: T) => string | TemplateResult) | undefined;
public value!: (element?: T | undefined) => string;
public selected?: ((element: T, elements: T[]) => boolean) | undefined;
@property({ type: Object, attribute: false })
public config!: ISearchSelectApi<T>;
config!: ISearchSelectApi<T>;
public override connectedCallback() {
connectedCallback() {
this.fetchObjects = this.config.fetchObjects;
this.renderElement = this.config.renderElement;
this.renderDescription = this.config.renderDescription;
this.value = this.config.value;
this.selected = this.config.selected;
if (this.config.groupBy) {
if (this.config.groupBy !== undefined) {
this.groupBy = this.config.groupBy;
}
super.connectedCallback();
}
}

View File

@@ -5,11 +5,12 @@ import { findFlatOptions, findOptionsSubset, groupOptions, optionsToFlat } from
import { ListSelect } from "#elements/ak-list-select/ak-list-select";
import { AKElement } from "#elements/Base";
import { bound } from "#elements/decorators/bound";
import type { GroupedOptions, SelectOption, SelectOptions } from "#elements/types";
import { randomId } from "#elements/utils/randomId";
import { msg } from "@lit/localize";
import { CSSResult, html, nothing, PropertyValues } from "lit";
import { html, nothing, PropertyValues } from "lit";
import { customElement, property, state } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js";
import { createRef, ref, Ref } from "lit/directives/ref.js";
@@ -69,9 +70,7 @@ export interface ISearchSelectView {
*/
@customElement("ak-search-select-view")
export class SearchSelectView extends AKElement implements ISearchSelectView {
static styles: CSSResult[] = [PFBase, PFForm, PFFormControl, PFSelect];
//#region Properties
static styles = [PFBase, PFForm, PFFormControl, PFSelect];
/**
* The options collection. The simplest variant is just [key, label, optional<description>]. See
@@ -80,16 +79,16 @@ export class SearchSelectView extends AKElement implements ISearchSelectView {
* @prop
*/
@property({ type: Array, attribute: false })
public set options(options: SelectOptions) {
this.#options = groupOptions(options);
this.#flatOptions = optionsToFlat(this.#options);
set options(options: SelectOptions) {
this._options = groupOptions(options);
this.flatOptions = optionsToFlat(this._options);
}
public get options() {
return this.#options;
get options() {
return this._options;
}
#options!: GroupedOptions;
_options!: GroupedOptions;
/**
* The current value. Must be one of the keys in the options group above.
@@ -97,7 +96,7 @@ export class SearchSelectView extends AKElement implements ISearchSelectView {
* @prop
*/
@property({ type: String, reflect: true })
public value?: string;
value?: string;
/**
* Whether or not the dropdown is open
@@ -105,7 +104,7 @@ export class SearchSelectView extends AKElement implements ISearchSelectView {
* @attr
*/
@property({ type: Boolean, reflect: true })
public open = false;
open = false;
/**
* If set to true, this object MAY return undefined in no value is passed in and none is set
@@ -114,7 +113,7 @@ export class SearchSelectView extends AKElement implements ISearchSelectView {
* @attr
*/
@property({ type: Boolean })
public blankable = false;
blankable = false;
/**
* If not managed, make the matcher case-sensitive during interaction. If managed,
@@ -123,23 +122,15 @@ export class SearchSelectView extends AKElement implements ISearchSelectView {
* @attr
*/
@property({ type: Boolean, attribute: "case-sensitive" })
public caseSensitive = false;
caseSensitive = false;
/**
* The name of the input, for forms.
* The name of the input, for forms
*
* @attr
*/
@property({ type: String })
public name?: string;
/**
* The label of the input, for forms.
*
* @attr
*/
@property({ type: String })
public label?: string;
name?: string;
/**
* The textual placeholder for the search's <input> object, if currently empty. Used as the
@@ -148,7 +139,7 @@ export class SearchSelectView extends AKElement implements ISearchSelectView {
* @attr
*/
@property({ type: String })
public placeholder: string = msg("Select an object.");
placeholder: string = msg("Select an object.");
/**
* If true, the component only sends an input message up to a parent component. If false, the
@@ -158,7 +149,7 @@ export class SearchSelectView extends AKElement implements ISearchSelectView {
*@attr
*/
@property({ type: Boolean })
public managed = false;
managed = false;
/**
* A textual string representing "The user has affirmed they want to leave the selection blank."
@@ -167,50 +158,36 @@ export class SearchSelectView extends AKElement implements ISearchSelectView {
* @attr
*/
@property()
public emptyOption = "---------";
emptyOption = "---------";
//#endregion
// Handle the behavior of the drop-down when the :host scrolls off the page.
scrollHandler?: () => void;
//#region State
// observer: IntersectionObserver;
@state()
protected displayValue = "";
displayValue = "";
// Tracks when the inputRef is populated, so we can safely reschedule the
// render of the dropdown with respect to it.
@state()
protected inputRefIsAvailable = false;
inputRefIsAvailable = false;
/**
* Permanent identity with the portal so focus events can be checked.
*/
#menuRef: Ref<ListSelect> = createRef();
menuRef: Ref<ListSelect> = createRef();
/**
* Permanent identify for the input object, so the floating portal can find where to anchor
* itself.
*/
#inputRef: Ref<HTMLInputElement> = createRef();
inputRef: Ref<HTMLInputElement> = createRef();
/**
* Maps a value from the portal to labels to be put into the <input> field>
* Maps a value from the portal to labels to be put into the <input> field>
*/
#flatOptions: [string, SelectOption][] = [];
//#endregion
//#region Lifecycle
public override updated() {
this.setAttribute("data-ouia-component-safe", "true");
}
public override firstUpdated() {
// Route around Lit's scheduling algorithm complaining about re-renders
window.setTimeout(() => {
this.inputRefIsAvailable = Boolean(this.#inputRef?.value);
}, 0);
}
flatOptions: [string, SelectOption][] = [];
connectedCallback() {
super.connectedCallback();
@@ -226,26 +203,24 @@ export class SearchSelectView extends AKElement implements ISearchSelectView {
// TODO
}
//#endregion
//#region Event Listeners
#clickListener = (_ev: Event) => {
@bound
onClick(_ev: Event) {
this.open = !this.open;
this.#inputRef.value?.focus();
};
this.inputRef.value?.focus();
}
setFromMatchList(value: string | undefined) {
if (value === undefined) {
return;
}
const probableValue = this.#flatOptions.find((option) => option[0] === this.value);
if (probableValue && this.#inputRef.value) {
this.#inputRef.value.value = probableValue[1][1];
const probableValue = this.flatOptions.find((option) => option[0] === this.value);
if (probableValue && this.inputRef.value) {
this.inputRef.value.value = probableValue[1][1];
}
}
#searchKeydownListener = (event: KeyboardEvent) => {
@bound
onKeydown(event: KeyboardEvent) {
if (event.code === "Escape") {
event.stopPropagation();
this.open = false;
@@ -256,44 +231,45 @@ export class SearchSelectView extends AKElement implements ISearchSelectView {
if (event.code === "Tab" && this.open) {
event.preventDefault();
this.setFromMatchList(this.value);
this.#menuRef.value?.currentElement?.focus();
this.menuRef.value?.currentElement?.focus();
}
};
}
#blurListener = (event: FocusEvent) => {
@bound
onListBlur(event: FocusEvent) {
// If we lost focus but the menu got it, don't do anything;
const relatedTarget = event.relatedTarget as HTMLElement | undefined;
if (
relatedTarget &&
(this.contains(relatedTarget) ||
this.renderRoot.contains(relatedTarget) ||
this.#menuRef.value?.contains(relatedTarget) ||
this.#menuRef.value?.renderRoot.contains(relatedTarget))
this.menuRef.value?.contains(relatedTarget) ||
this.menuRef.value?.renderRoot.contains(relatedTarget))
) {
return;
}
this.open = false;
if (!this.value) {
if (this.#inputRef.value) {
this.#inputRef.value.value = "";
if (this.value === undefined) {
if (this.inputRef.value) {
this.inputRef.value.value = "";
}
this.setValue(undefined);
}
};
}
setValue(newValue: string | undefined) {
this.value = newValue;
this.dispatchEvent(new Event("change", { bubbles: true, composed: true }));
this.dispatchEvent(new Event("change", { bubbles: true, composed: true })); // prettier-ignore
}
findValueForInput() {
const value = this.#inputRef.value?.value;
const value = this.inputRef.value?.value;
if (value === undefined || value.trim() === "") {
this.setValue(undefined);
return;
}
const matchesFound = findFlatOptions(this.#flatOptions, value);
const matchesFound = findFlatOptions(this.flatOptions, value);
if (matchesFound.length > 0) {
const newValue = matchesFound[0][0];
if (newValue === value) {
@@ -305,46 +281,47 @@ export class SearchSelectView extends AKElement implements ISearchSelectView {
}
}
#inputListener = (_ev: InputEvent) => {
@bound
onInput(_ev: InputEvent) {
if (!this.managed) {
this.findValueForInput();
this.requestUpdate();
}
this.open = true;
};
}
#listKeydownListener = (event: KeyboardEvent) => {
@bound
onListKeydown(event: KeyboardEvent) {
if (event.key === "Escape") {
this.open = false;
this.#inputRef.value?.focus();
this.inputRef.value?.focus();
}
if (event.key === "Tab" && event.shiftKey) {
event.preventDefault();
this.#inputRef.value?.focus();
this.inputRef.value?.focus();
}
};
}
#changeListener = (event: InputEvent) => {
@bound
onListChange(event: InputEvent) {
if (!event.target) {
return;
}
const value = (event.target as HTMLInputElement).value;
if (value) {
if (value !== undefined) {
const newDisplayValue = this.findDisplayForValue(value);
if (this.#inputRef.value) {
this.#inputRef.value.value = newDisplayValue ?? "";
if (this.inputRef.value) {
this.inputRef.value.value = newDisplayValue ?? "";
}
} else if (this.#inputRef.value) {
this.#inputRef.value.value = "";
} else if (this.inputRef.value) {
this.inputRef.value.value = "";
}
this.open = false;
this.setValue(value);
};
//#endregion
}
findDisplayForValue(value: string) {
const newDisplayValue = this.#flatOptions.find((option) => option[0] === value);
const newDisplayValue = this.flatOptions.find((option) => option[0] === value);
return newDisplayValue ? newDisplayValue[1][1] : undefined;
}
@@ -363,17 +340,15 @@ export class SearchSelectView extends AKElement implements ISearchSelectView {
}
get rawValue() {
return this.#inputRef.value?.value ?? "";
return this.inputRef.value?.value ?? "";
}
get managedOptions() {
return this.managed
? this.#options
: findOptionsSubset(this.#options, this.rawValue, this.caseSensitive);
? this._options
: findOptionsSubset(this._options, this.rawValue, this.caseSensitive);
}
//#region Render
public override render() {
const emptyOption = this.blankable ? this.emptyOption : undefined;
const open = this.open;
@@ -386,15 +361,13 @@ export class SearchSelectView extends AKElement implements ISearchSelectView {
autocomplete="off"
class="pf-c-form-control pf-c-select__toggle-typeahead"
type="text"
${ref(this.#inputRef)}
${ref(this.inputRef)}
placeholder=${this.placeholder}
aria-label=${ifDefined(this.label)}
name=${ifDefined(this.name)}
spellcheck="false"
@input=${this.#inputListener}
@click=${this.#clickListener}
@blur=${this.#blurListener}
@keydown=${this.#searchKeydownListener}
@input=${this.onInput}
@click=${this.onClick}
@blur=${this.onListBlur}
@keydown=${this.onKeydown}
value=${this.displayValue}
/>
</div>
@@ -404,25 +377,34 @@ export class SearchSelectView extends AKElement implements ISearchSelectView {
? html`
<ak-portal
name=${ifDefined(this.name)}
.anchor=${this.#inputRef.value}
.anchor=${this.inputRef.value}
?open=${open}
>
<ak-list-select
id="menu-${this.getAttribute("data-ouia-component-id")}"
${ref(this.#menuRef)}
${ref(this.menuRef)}
.options=${this.managedOptions}
value=${ifDefined(this.value)}
@change=${this.#changeListener}
@blur=${this.#blurListener}
@change=${this.onListChange}
@blur=${this.onListBlur}
emptyOption=${ifDefined(emptyOption)}
@keydown=${this.#listKeydownListener}
@keydown=${this.onListKeydown}
></ak-list-select>
</ak-portal>
`
: nothing}`;
}
//#endregion
public override updated() {
this.setAttribute("data-ouia-component-safe", "true");
}
public override firstUpdated() {
// Route around Lit's scheduling algorithm complaining about re-renders
window.setTimeout(() => {
this.inputRefIsAvailable = Boolean(this.inputRef?.value);
}, 0);
}
}
declare global {

View File

@@ -44,28 +44,44 @@ export interface ISearchSelect<T> extends ISearchSelectBase<T> {
* consequence of the user typing or when selecting from the list.
*
*/
@customElement("ak-search-select")
export class SearchSelect<T> extends SearchSelectBase<T> implements ISearchSelect<T> {
static styles = [...SearchSelectBase.styles];
// A function which takes the query state object (accepting that it may be empty) and returns a
// new collection of objects.
@property({ attribute: false })
public fetchObjects!: (query?: string) => Promise<T[]>;
fetchObjects!: (query?: string) => Promise<T[]>;
// A function passed to this object that extracts a string representation of items of the
// collection under search.
@property({ attribute: false })
public renderElement!: (element: T) => string;
renderElement!: (element: T) => string;
// A function passed to this object that extracts an HTML representation of additional
// information for items of the collection under search.
@property({ attribute: false })
public renderDescription?: (element: T) => string | TemplateResult;
renderDescription?: (element: T) => string | TemplateResult;
// A function which returns the currently selected object's primary key, used for serialization
// into forms.
@property({ attribute: false })
public value!: (element?: T) => string;
value!: (element: T | undefined) => string;
// A function passed to this object that determines an object in the collection under search
// should be automatically selected. Only used when the search itself is responsible for
// fetching the data; sets an initial default value.
@property({ attribute: false })
public selected?: (element: T, elements: T[]) => boolean;
selected?: (element: T, elements: T[]) => boolean;
// A function passed to this object (or using the default below) that groups objects in the
// collection under search into categories.
@property({ attribute: false })
public groupBy: (items: T[]) => [string, T[]][] = (items: T[]): [string, T[]][] => {
return groupBy(items, () => "");
groupBy: (items: T[]) => [string, T[]][] = (items: T[]): [string, T[]][] => {
return groupBy(items, () => {
return "";
});
};
}

View File

@@ -580,7 +580,7 @@ export class FlowExecutor
</div>
</div>
</div>
${(this.inspectorAvailable ?? !this.inspectorOpen)
${this.inspectorAvailable || !this.inspectorOpen
? html`<button
class="inspector-toggle pf-c-button pf-m-primary"
@click=${() => {

View File

@@ -184,7 +184,7 @@ export class LibraryPage extends AKElement {
render() {
return html`<main role="main" class="pf-c-page__main" tabindex="-1" id="main-content">
<div class="pf-c-content header">
<h1 role="heading" aria-level="1" data-test-id="page-heading">
<h1 role="heading" aria-level="1" id="library-page-title">
${msg("My applications")}
</h1>
${this.uiConfig.searchEnabled ? this.renderSearch() : nothing}
@@ -193,13 +193,3 @@ export class LibraryPage extends AKElement {
</main>`;
}
}
declare global {
interface PageTestIDMap {
heading: HTMLHeadingElement;
}
interface TestIDSelectorMap {
page: PageTestIDMap;
}
}

View File

@@ -1,217 +0,0 @@
import { expect, test } from "#e2e";
import { createRandomName } from "#e2e/utils/generators";
import { ConsoleLogger } from "#logger/node";
import { IDGenerator } from "@goauthentik/core/id";
import { series } from "@goauthentik/core/promises";
test.describe("Provider Wizard", () => {
const providerNames = new Map<string, string>();
//#region Lifecycle
test.beforeEach("Configure Providers", async ({ page, session }, { testId }) => {
const seed = IDGenerator.randomID(6);
const providerName = `${createRandomName({ seed })} (${seed})`;
providerNames.set(testId, providerName);
const wizard = page.getByRole("dialog", { name: "New provider" });
await test.step("Authenticate", async () => {
await session.login({
to: "/if/admin/#/core/providers",
});
});
await test.step("Navigate to provider wizard", async () => {
await expect(wizard, "Wizard is initially closed").toBeHidden();
await page.getByRole("button", { name: "New Provider" }).click();
await expect(wizard, "Wizard opens after clicking on New Provider").toBeVisible();
await expect(
page.getByRole("listbox", { name: "Select a provider type" }),
"Wizard opens with a list of provider types",
).toBeVisible();
await expect(
wizard.getByRole("navigation").getByRole("button", {
name: /next|finish/i,
}),
"Wizard can't be navigated to next step",
).toBeDisabled();
});
});
test.afterEach("Verification", async ({ page }, { testId }) => {
//#region Confirm provider
const providerName = providerNames.get(testId)!;
const $provider = await test.step("Find provider via search", async () => {
const searchInput = page.getByRole("search").getByPlaceholder("Search for providers");
await searchInput.fill(providerName);
// We have to wait for the provider to appear in the table,
// but several UI elements will be rendered asynchronously.
// We attempt several times to find the provider to avoid flakiness.
const tries = 10;
let found = false;
for (let i = 0; i < tries; i++) {
await searchInput.press("Enter");
await searchInput.blur();
const $rowEntry = page.getByRole("row", {
name: providerName,
});
ConsoleLogger.info(
`${i + 1}/${tries} Waiting for provider ${providerName} to appear in the table`,
);
found = await $rowEntry
.waitFor({
timeout: 1500,
})
.then(() => true)
.catch(() => false);
if (found) {
ConsoleLogger.info(`Provider ${providerName} found in the table`);
return $rowEntry;
}
}
throw new Error(`Provider ${providerName} not found in the table`);
});
await expect($provider, "Provider is visible").toBeVisible();
//#endregion
});
//#endregion
//#region OAuth2
test("Simple OAuth2 Provider", async ({ form, pointer }, testInfo) => {
const providerName = providerNames.get(testInfo.testId)!;
const { fill, selectSearchValue } = form;
const { click } = pointer;
await series(
[click, "OAuth2/OpenID", "option"],
[click, "Next"],
[fill, "Provider name", providerName],
[
selectSearchValue,
"Authorization flow",
/default-provider-authorization-explicit-consent/,
],
[click, "Finish"],
);
});
test("Complete OAuth2 Provider", async ({ page, form, pointer }, testInfo) => {
const providerName = providerNames.get(testInfo.testId)!;
const { fill, selectSearchValue, setFormGroup, setRadio, setInputCheck } = form;
const { click } = pointer;
const $clientSecretInput = page.getByRole("textbox", { name: "Client Secret" });
await series(
[click, "OAuth2/OpenID", "option"],
[click, "Next"],
[fill, "Provider name", providerName],
[
selectSearchValue,
"Authorization flow",
/default-provider-authorization-explicit-consent/,
],
[setFormGroup, "Protocol settings", true],
[setRadio, "Client Type", "Public"],
[
expect(
$clientSecretInput,
"Client Secret should be hidden when Client Type is Public",
).toBeHidden,
],
[setRadio, "Client Type", "Confidential"],
[
expect(
$clientSecretInput,
"Client Secret should be visible when Client Type is Confidential",
).toBeVisible,
],
[selectSearchValue, "Signing Key", /authentik Self-signed Certificate/],
[selectSearchValue, "Encryption Key", /authentik Self-signed Certificate/],
[setFormGroup, "Advanced flow settings", true],
[selectSearchValue, "Authentication flow", /default-source-authentication/],
[selectSearchValue, "Invalidation flow", /default-invalidation-flow/],
[setFormGroup, "Advanced protocol settings", true],
[fill, "Access code validity", "minutes=2"],
[fill, "Access token validity", "minutes=10"],
[fill, "Refresh token validity", "days=40"],
[setInputCheck, "Include claims in id_token", false],
[setRadio, "Subject mode", "Based on the User's username"],
[setRadio, "Issuer mode", "Same identifier is used for all providers"],
[setFormGroup, "Machine-to-Machine authentication settings", true],
[click, "Finish", "button", page.getByRole("dialog", { name: "New Provider" })],
);
});
//#endregion
//#region LDAP
test("Complete LDAP Provider", async ({ page, pointer, form }, testInfo) => {
const providerName = providerNames.get(testInfo.testId)!;
const { fill, setFormGroup, selectSearchValue, setInputCheck, setRadio } = form;
const { click } = pointer;
await series(
[click, "LDAP", "option"],
[click, "Next"],
[fill, "Provider name", providerName],
[setFormGroup, "Flow settings", true],
[setFormGroup, "Protocol settings", true],
[selectSearchValue, "Bind flow", /default-authentication-flow/],
[fill, "Base DN", "DC=ldap-2,DC=goauthentik,DC=io"],
[selectSearchValue, "Certificate", /authentik Self-signed Certificate/],
[fill, "TLS Server name", "goauthentik.io"],
[fill, "UID start number", "2001"],
[fill, "GID start number", "4001"],
[setRadio, "Search mode", "Direct querying"],
[setRadio, "Bind mode", "Direct binding"],
[setInputCheck, "MFA Support", false],
[click, "Finish", "button", page.getByRole("dialog", { name: "New Provider" })],
);
});
//#endregion
//#region RADIUS
test("Complete RADIUS Provider", async ({ page, pointer, form }, testInfo) => {
const providerName = providerNames.get(testInfo.testId)!;
const { fill, selectSearchValue } = form;
const { click } = pointer;
await series(
[click, "RADIUS", "option"],
[click, "Next"],
[fill, "Provider name", providerName],
[selectSearchValue, "Authentication flow", /default-authentication-flow/],
[click, "Finish", "button", page.getByRole("dialog", { name: "New Provider" })],
);
});
//#endregion
});

View File

@@ -1,35 +0,0 @@
import { expect, test } from "#e2e";
import {
BAD_PASSWORD,
BAD_USERNAME,
GOOD_PASSWORD,
GOOD_USERNAME,
} from "#e2e/fixtures/SessionFixture";
test.beforeEach(async ({ session }) => {
await session.toLoginPage();
});
test.describe("Session management", () => {
test("Login with valid credentials", async ({ session, $ }) => {
await session.login({ username: GOOD_USERNAME, password: GOOD_PASSWORD });
await $.page.heading.expect.toHaveText("My applications");
});
test("Reject bad username", async ({ session }) => {
await session.submitUsernameStage(BAD_USERNAME);
await session.submitPasswordStage(GOOD_PASSWORD);
await expect(session.$authFailureMessage).toBeVisible();
await expect(session.$authFailureMessage).toHaveText("Invalid password");
});
test("Reject bad password", async ({ session }) => {
await session.submitUsernameStage(GOOD_USERNAME);
await session.submitPasswordStage(BAD_PASSWORD);
await expect(session.$authFailureMessage).toBeVisible();
await expect(session.$authFailureMessage).toHaveText("Invalid password");
});
});

View File

@@ -1,87 +0,0 @@
/**
* @file Vitest browser utilities for Lit.
*
* @import { LocatorSelectors } from '@vitest/browser/context'
* @import { PrettyDOMOptions } from '@vitest/browser/utils'
* @import { RenderOptions as LitRenderOptions } from 'lit'
*/
import { debug, getElementLocatorSelectors } from "@vitest/browser/utils";
import { render as renderLit } from "lit";
/**
* @implements {Disposable}
*/
export class LitViteContext {
/**
* @type {Set<Disposable>}
*/
static #resources = new Set();
/**
* @param {unknown} template
* @param {HTMLElement} [container]
* @param {LitRenderOptions} [options]
*
* @returns {LitViteContext}
*/
static render = (template, container = document.createElement("div"), options) => {
const context = new LitViteContext(container);
context.render(template, options);
return context;
};
static [Symbol.dispose] = () => {
this.#resources.forEach((resource) => resource[Symbol.dispose]());
this.#resources.clear();
};
static cleanup = () => {
return this[Symbol.dispose]();
};
/**
* @param {unknown} template
* @param {LitRenderOptions} [options]
*/
render(template, options) {
return renderLit(template, this.container, options);
}
/**
* @type {HTMLElement} container
*/
container;
/**
* @type {LocatorSelectors}
*/
$;
/**
* @param {HTMLElement} container
*/
constructor(container) {
this.container = container;
this.$ = getElementLocatorSelectors(container);
}
toFragment() {
return document.createRange().createContextualFragment(this.container.innerHTML);
}
/**
* @param {number} [maxLength]
* @param {PrettyDOMOptions} [options]
*/
debug(maxLength, options) {
return debug(this.container, maxLength, options);
}
[Symbol.dispose] = () => {
this.container.remove();
LitViteContext.#resources.delete(this);
};
}

View File

@@ -1,12 +0,0 @@
import { LitViteContext } from "./rendering.js";
import { page } from "@vitest/browser/context";
import { beforeEach } from "vitest";
page.extend({
// @ts-ignore
renderLit: LitViteContext.render,
[Symbol.for("vitest:component-cleanup")]: LitViteContext.cleanup,
});
beforeEach(() => LitViteContext.cleanup());

View File

@@ -1,9 +0,0 @@
import { expect, test } from "vitest";
function sum(a: number, b: number) {
return a + b;
}
test("adds 1 + 2 to equal 3", () => {
expect(sum(1, 2)).toBe(3);
});

View File

@@ -1,5 +1,6 @@
{
"compilerOptions": {
"strict": true,
"baseUrl": ".",
"moduleResolution": "node",
"module": "ESNext",

View File

@@ -2,11 +2,5 @@
{
"extends": "./tsconfig.json",
"exclude": [
// ---
"src/**/*.test.ts",
"src/**/*.comp.ts",
"./**/*.stories.ts",
"./tests"
]
"exclude": ["src/**/*.test.ts", "./tests"]
}

View File

@@ -1,5 +1,24 @@
// @file TSConfig used by the web package during build.
// @file TSConfig used during tests.
{
"extends": "./tsconfig.json"
"compilerOptions": {
"baseUrl": ".",
"types": ["node", "webdriverio/async", "@wdio/cucumber-framework", "expect-webdriverio"],
"target": "esnext",
"module": "esnext",
"forceConsistentCasingInFileNames": true,
"experimentalDecorators": true,
"lib": [
"ES5",
"ES2015",
"ES2016",
"ES2017",
"ES2018",
"ES2019",
"ES2020",
"ESNext",
"DOM",
"DOM.Iterable",
"WebWorker"
]
}
}

23
web/types/node.d.ts vendored
View File

@@ -14,13 +14,12 @@ declare module "module" {
* const relativeDirname = dirname(fileURLToPath(import.meta.url));
* ```
*/
var __dirname: string;
}
}
declare module "process" {
import { Level } from "pino";
global {
namespace NodeJS {
interface ProcessEnv {
@@ -31,26 +30,6 @@ declare module "process" {
* @see {@link https://nodejs.org/en/learn/getting-started/nodejs-the-difference-between-development-and-production | The difference between development and production}
*/
readonly NODE_ENV?: "development" | "production";
/**
* Whether or not we are running on a CI server.
*/
readonly CI?: string;
/**
* The application log level.
*/
readonly AK_LOG_LEVEL?: Level;
/**
* The base URL of web server to run the tests against.
*
* Typically this is `http://localhost:9000`.
*
* @format url
*/
readonly AK_TEST_RUNNER_PAGE_URL?: string;
/**
* @todo Determine where this is used and if it is needed,
* give it a better name.

View File

@@ -6620,7 +6620,7 @@ Bindings zu Gruppen/Benutzern werden mit dem Benutzer des Ereignisses abgegliche
</trans-unit>
<trans-unit id="saf63d34c8601dd41">
<source><x id="0" equiv-text="${prompt.label}"/></source>
<source><x id="0" equiv-text="${name}"/></source>
<target>
<x id="0" equiv-text="${prompt.label}"/>
</target>
@@ -9667,10 +9667,6 @@ Bindings zu Gruppen/Benutzern werden mit dem Benutzer des Ereignisses abgegliche
<source>Number of previous passwords to check</source>
<target>Anzahl der vorherigen Passwörter, die geprüft werden sollen</target>
</trans-unit>
<trans-unit id="sdd66c5a2e706fb81">
<source>Toggle sidebar</source>
<target>Seitenleiste umschalten</target>
</trans-unit>
<trans-unit id="s7d4ec232535a36f0">
<source>Choose a Provider</source>
<target>Wähle einen Provider</target>
@@ -9976,6 +9972,42 @@ Bindings zu Gruppen/Benutzern werden mit dem Benutzer des Ereignisses abgegliche
</trans-unit>
<trans-unit id="s5e13dff03b580216">
<source>Previous executions logs</source>
</trans-unit>
<trans-unit id="s6abb1cd87fe0114e">
<source>Home</source>
</trans-unit>
<trans-unit id="se58e6ed983bf34b0">
<source>Collapse navigation</source>
</trans-unit>
<trans-unit id="sc6ef25894ed00175">
<source>Expand navigation</source>
</trans-unit>
<trans-unit id="s148b5e365440a7c1">
<source>Table pagination</source>
</trans-unit>
<trans-unit id="s5d929ff1619ac0c9">
<source>Search</source>
</trans-unit>
<trans-unit id="sd2c2366d13599d8c">
<source>Table actions</source>
</trans-unit>
<trans-unit id="s3d195621e562d805">
<source>Select row</source>
</trans-unit>
<trans-unit id="s572d21b6a41e24fa">
<source>Table of <x id="0" equiv-text="${this.label}"/></source>
</trans-unit>
<trans-unit id="sa25b60b4fac481aa">
<source>Table content</source>
</trans-unit>
<trans-unit id="s5eba8fa19126f70a">
<source>Learn more about the enterprise license.</source>
</trans-unit>
<trans-unit id="s9db1679f3b234d4e">
<source>Search for providers…</source>
</trans-unit>
<trans-unit id="s76790480b7b28ad2">
<source>Edit provider</source>
</trans-unit>
</body>
</file>

View File

@@ -5299,7 +5299,7 @@ Bindings to groups/users are checked against the user of the event.</source>
<target>Change password</target>
</trans-unit>
<trans-unit id="saf63d34c8601dd41">
<source><x id="0" equiv-text="${prompt.label}"/></source>
<source><x id="0" equiv-text="${name}"/></source>
<target>
<x id="0" equiv-text="${prompt.label}"/>
</target>
@@ -7590,9 +7590,6 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s79b3fcd40dd63921">
<source>Number of previous passwords to check</source>
</trans-unit>
<trans-unit id="sdd66c5a2e706fb81">
<source>Toggle sidebar</source>
</trans-unit>
<trans-unit id="s7d4ec232535a36f0">
<source>Choose a Provider</source>
</trans-unit>
@@ -7853,6 +7850,42 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s5e13dff03b580216">
<source>Previous executions logs</source>
</trans-unit>
<trans-unit id="s6abb1cd87fe0114e">
<source>Home</source>
</trans-unit>
<trans-unit id="se58e6ed983bf34b0">
<source>Collapse navigation</source>
</trans-unit>
<trans-unit id="sc6ef25894ed00175">
<source>Expand navigation</source>
</trans-unit>
<trans-unit id="s148b5e365440a7c1">
<source>Table pagination</source>
</trans-unit>
<trans-unit id="s5d929ff1619ac0c9">
<source>Search</source>
</trans-unit>
<trans-unit id="sd2c2366d13599d8c">
<source>Table actions</source>
</trans-unit>
<trans-unit id="s3d195621e562d805">
<source>Select row</source>
</trans-unit>
<trans-unit id="s572d21b6a41e24fa">
<source>Table of <x id="0" equiv-text="${this.label}"/></source>
</trans-unit>
<trans-unit id="sa25b60b4fac481aa">
<source>Table content</source>
</trans-unit>
<trans-unit id="s5eba8fa19126f70a">
<source>Learn more about the enterprise license.</source>
</trans-unit>
<trans-unit id="s9db1679f3b234d4e">
<source>Search for providers…</source>
</trans-unit>
<trans-unit id="s76790480b7b28ad2">
<source>Edit provider</source>
</trans-unit>
</body>
</file>

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" ?><xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
<?xml version="1.0"?><xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" version="1.2">
<file target-language="es" source-language="en" original="lit-localize-inputs" datatype="plaintext">
<body>
<trans-unit id="s4caed5b7a7e5d89b">
@@ -596,9 +596,9 @@
</trans-unit>
<trans-unit id="saa0e2675da69651b">
<source>The URL &quot;<x id="0" equiv-text="${this.url}"/>&quot; was not found.</source>
<target>El URL &quot;
<x id="0" equiv-text="${this.url}"/>&quot; no fue encontrado.</target>
<source>The URL "<x id="0" equiv-text="${this.url}"/>" was not found.</source>
<target>El URL "
<x id="0" equiv-text="${this.url}"/>" no fue encontrado.</target>
</trans-unit>
<trans-unit id="s58cd9c2fe836d9c6">
@@ -1693,7 +1693,7 @@
</trans-unit>
<trans-unit id="sa90b7809586c35ce">
<source>Either input a full URL, a relative path, or use 'fa://fa-test' to use the Font Awesome icon &quot;fa-test&quot;.</source>
<source>Either input a full URL, a relative path, or use 'fa://fa-test' to use the Font Awesome icon "fa-test".</source>
<target>Ingrese una URL completa, una ruta relativa o use 'fa: //fa-test' para usar el ícono Font Awesome «fa-test».</target>
</trans-unit>
@@ -3732,10 +3732,10 @@ no se aprueba cuando una o ambas de las opciones seleccionadas son iguales o sup
</trans-unit>
<trans-unit id="sa95a538bfbb86111">
<source>Are you sure you want to update <x id="0" equiv-text="${this.objectLabel}"/> &quot;<x id="1" equiv-text="${this.obj?.name}"/>&quot;?</source>
<source>Are you sure you want to update <x id="0" equiv-text="${this.objectLabel}"/> "<x id="1" equiv-text="${this.obj?.name}"/>"?</source>
<target>¿Estás seguro de que deseas actualizar
<x id="0" equiv-text="${this.objectLabel}"/>&quot;
<x id="1" equiv-text="${this.obj?.name}"/>&quot;?</target>
<x id="0" equiv-text="${this.objectLabel}"/>"
<x id="1" equiv-text="${this.obj?.name}"/>"?</target>
</trans-unit>
<trans-unit id="sc92d7cfb6ee1fec6">
@@ -4790,8 +4790,8 @@ no se aprueba cuando una o ambas de las opciones seleccionadas son iguales o sup
</trans-unit>
<trans-unit id="sdf1d8edef27236f0">
<source>A &quot;roaming&quot; authenticator, like a YubiKey</source>
<target>Un autenticador &quot;roaming&quot;, como una YubiKey</target>
<source>A "roaming" authenticator, like a YubiKey</source>
<target>Un autenticador "roaming", como una YubiKey</target>
</trans-unit>
<trans-unit id="sfffba7b23d8fb40c">
@@ -5149,8 +5149,8 @@ no se aprueba cuando una o ambas de las opciones seleccionadas son iguales o sup
</trans-unit>
<trans-unit id="s1608b2f94fa0dbd4">
<source>If set to a duration above 0, the user will have the option to choose to &quot;stay signed in&quot;, which will extend their session by the time specified here.</source>
<target>Si se establece en una duración mayor a 0, el usuario tendrá la opción de &quot;mantener la sesión iniciada&quot;, lo que extenderá su sesión por el tiempo especificado aquí.</target>
<source>If set to a duration above 0, the user will have the option to choose to "stay signed in", which will extend their session by the time specified here.</source>
<target>Si se establece en una duración mayor a 0, el usuario tendrá la opción de "mantener la sesión iniciada", lo que extenderá su sesión por el tiempo especificado aquí.</target>
</trans-unit>
<trans-unit id="s542a71bb8f41e057">
@@ -6625,7 +6625,7 @@ Las vinculaciones a grupos/usuarios se verifican en función del usuario del eve
</trans-unit>
<trans-unit id="saf63d34c8601dd41">
<source><x id="0" equiv-text="${prompt.label}"/></source>
<source><x id="0" equiv-text="${name}"/></source>
<target>
<x id="0" equiv-text="${prompt.label}"/>
</target>
@@ -7398,7 +7398,7 @@ Las vinculaciones a grupos/usuarios se verifican en función del usuario del eve
<target>Usuario creado correctamente y agregado al grupo <x id="0" equiv-text="${this.group.name}"/></target>
</trans-unit>
<trans-unit id="s824e0943a7104668">
<source>This user will be added to the group &quot;<x id="0" equiv-text="${this.targetGroup.name}"/>&quot;.</source>
<source>This user will be added to the group "<x id="0" equiv-text="${this.targetGroup.name}"/>".</source>
<target>Este usuario se agregará al grupo. &amp;quot;<x id="0" equiv-text="${this.targetGroup.name}"/>&amp;quot;.</target>
</trans-unit>
<trans-unit id="s62e7f6ed7d9cb3ca">
@@ -8660,7 +8660,7 @@ Las vinculaciones a grupos/usuarios se verifican en función del usuario del eve
<target>Sincronizar Grupo</target>
</trans-unit>
<trans-unit id="s2d5f69929bb7221d">
<source><x id="0" equiv-text="${p.name}"/> (&quot;<x id="1" equiv-text="${p.fieldKey}"/>&quot;, of type <x id="2" equiv-text="${p.type}"/>)</source>
<source><x id="0" equiv-text="${p.name}"/> ("<x id="1" equiv-text="${p.fieldKey}"/>", of type <x id="2" equiv-text="${p.type}"/>)</source>
<target><x id="0" equiv-text="${p.name}"/> (&amp;quot;<x id="1" equiv-text="${p.fieldKey}"/>&amp;quot;, of type <x id="2" equiv-text="${p.type}"/>)</target>
</trans-unit>
<trans-unit id="s25bacc19d98b444e">
@@ -8908,8 +8908,8 @@ Las vinculaciones a grupos/usuarios se verifican en función del usuario del eve
<target>URI de redirección válidas tras un flujo de autorización exitoso. Especifique también aquí los orígenes de los flujos implícitos.</target>
</trans-unit>
<trans-unit id="s4c49d27de60a532b">
<source>To allow any redirect URI, set the mode to Regex and the value to &quot;.*&quot;. Be aware of the possible security implications this can have.</source>
<target>Para permitir cualquier URI de redirección, configure el modo en Expresión Regular y el valor en &quot;.*&quot;. Tenga en cuenta las posibles implicaciones de seguridad que esto puede tener.</target>
<source>To allow any redirect URI, set the mode to Regex and the value to ".*". Be aware of the possible security implications this can have.</source>
<target>Para permitir cualquier URI de redirección, configure el modo en Expresión Regular y el valor en ".*". Tenga en cuenta las posibles implicaciones de seguridad que esto puede tener.</target>
</trans-unit>
<trans-unit id="sa52bf79fe1ccb13e">
<source>Federated OIDC Sources</source>
@@ -9655,8 +9655,8 @@ Si se deja vacío, AuthnContextClassRef se establecerá según los métodos de a
<target>Cómo realizar la autenticación durante un flujo de solicitud de token de código de autorización</target>
</trans-unit>
<trans-unit id="s844baf19a6c4a9b4">
<source>Enable &quot;Remember me on this device&quot;</source>
<target>Habilita &quot;Recordarme en este dispositivo&quot;</target>
<source>Enable "Remember me on this device"</source>
<target>Habilita "Recordarme en este dispositivo"</target>
</trans-unit>
<trans-unit id="sfa72bca733f40692">
<source>When enabled, the user can save their username in a cookie, allowing them to skip directly to entering their password.</source>
@@ -9674,10 +9674,6 @@ Si se deja vacío, AuthnContextClassRef se establecerá según los métodos de a
<source>Number of previous passwords to check</source>
<target>Número de contraseñas anteriores a verificar</target>
</trans-unit>
<trans-unit id="sdd66c5a2e706fb81">
<source>Toggle sidebar</source>
<target>Alternar barra lateral</target>
</trans-unit>
<trans-unit id="s7d4ec232535a36f0">
<source>Choose a Provider</source>
<target>Elige un Proveedor</target>
@@ -10024,7 +10020,43 @@ El valor de este campo se compara con el atributo de pertenencia del usuario.</t
</trans-unit>
<trans-unit id="s5e13dff03b580216">
<source>Previous executions logs</source>
</trans-unit>
<trans-unit id="s6abb1cd87fe0114e">
<source>Home</source>
</trans-unit>
<trans-unit id="se58e6ed983bf34b0">
<source>Collapse navigation</source>
</trans-unit>
<trans-unit id="sc6ef25894ed00175">
<source>Expand navigation</source>
</trans-unit>
<trans-unit id="s148b5e365440a7c1">
<source>Table pagination</source>
</trans-unit>
<trans-unit id="s5d929ff1619ac0c9">
<source>Search</source>
</trans-unit>
<trans-unit id="sd2c2366d13599d8c">
<source>Table actions</source>
</trans-unit>
<trans-unit id="s3d195621e562d805">
<source>Select row</source>
</trans-unit>
<trans-unit id="s572d21b6a41e24fa">
<source>Table of <x id="0" equiv-text="${this.label}"/></source>
</trans-unit>
<trans-unit id="sa25b60b4fac481aa">
<source>Table content</source>
</trans-unit>
<trans-unit id="s5eba8fa19126f70a">
<source>Learn more about the enterprise license.</source>
</trans-unit>
<trans-unit id="s9db1679f3b234d4e">
<source>Search for providers…</source>
</trans-unit>
<trans-unit id="s76790480b7b28ad2">
<source>Edit provider</source>
</trans-unit>
</body>
</file>
</xliff>
</xliff>

View File

@@ -6623,7 +6623,7 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti
</trans-unit>
<trans-unit id="saf63d34c8601dd41">
<source><x id="0" equiv-text="${prompt.label}"/></source>
<source><x id="0" equiv-text="${name}"/></source>
<target>
<x id="0" equiv-text="${prompt.label}"/>
</target>
@@ -9671,10 +9671,6 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti
<source>Number of previous passwords to check</source>
<target>Nombre d'anciens mots de passe à vérifier</target>
</trans-unit>
<trans-unit id="sdd66c5a2e706fb81">
<source>Toggle sidebar</source>
<target>Afficher/masquer la barre latérale</target>
</trans-unit>
<trans-unit id="s7d4ec232535a36f0">
<source>Choose a Provider</source>
<target>Choisir un fournisseur</target>
@@ -9994,6 +9990,42 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti
</trans-unit>
<trans-unit id="s5e13dff03b580216">
<source>Previous executions logs</source>
</trans-unit>
<trans-unit id="s6abb1cd87fe0114e">
<source>Home</source>
</trans-unit>
<trans-unit id="se58e6ed983bf34b0">
<source>Collapse navigation</source>
</trans-unit>
<trans-unit id="sc6ef25894ed00175">
<source>Expand navigation</source>
</trans-unit>
<trans-unit id="s148b5e365440a7c1">
<source>Table pagination</source>
</trans-unit>
<trans-unit id="s5d929ff1619ac0c9">
<source>Search</source>
</trans-unit>
<trans-unit id="sd2c2366d13599d8c">
<source>Table actions</source>
</trans-unit>
<trans-unit id="s3d195621e562d805">
<source>Select row</source>
</trans-unit>
<trans-unit id="s572d21b6a41e24fa">
<source>Table of <x id="0" equiv-text="${this.label}"/></source>
</trans-unit>
<trans-unit id="sa25b60b4fac481aa">
<source>Table content</source>
</trans-unit>
<trans-unit id="s5eba8fa19126f70a">
<source>Learn more about the enterprise license.</source>
</trans-unit>
<trans-unit id="s9db1679f3b234d4e">
<source>Search for providers…</source>
</trans-unit>
<trans-unit id="s76790480b7b28ad2">
<source>Edit provider</source>
</trans-unit>
</body>
</file>

View File

@@ -6624,7 +6624,7 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="saf63d34c8601dd41">
<source><x id="0" equiv-text="${prompt.label}"/></source>
<source><x id="0" equiv-text="${name}"/></source>
<target>
<x id="0" equiv-text="${prompt.label}"/>
</target>
@@ -9672,10 +9672,6 @@ Bindings to groups/users are checked against the user of the event.</source>
<source>Number of previous passwords to check</source>
<target>Numero di password precedenti da controllare</target>
</trans-unit>
<trans-unit id="sdd66c5a2e706fb81">
<source>Toggle sidebar</source>
<target>Attiva/disattiva la barra laterale</target>
</trans-unit>
<trans-unit id="s7d4ec232535a36f0">
<source>Choose a Provider</source>
<target>Scegli un Provider</target>
@@ -9980,6 +9976,42 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s5e13dff03b580216">
<source>Previous executions logs</source>
</trans-unit>
<trans-unit id="s6abb1cd87fe0114e">
<source>Home</source>
</trans-unit>
<trans-unit id="se58e6ed983bf34b0">
<source>Collapse navigation</source>
</trans-unit>
<trans-unit id="sc6ef25894ed00175">
<source>Expand navigation</source>
</trans-unit>
<trans-unit id="s148b5e365440a7c1">
<source>Table pagination</source>
</trans-unit>
<trans-unit id="s5d929ff1619ac0c9">
<source>Search</source>
</trans-unit>
<trans-unit id="sd2c2366d13599d8c">
<source>Table actions</source>
</trans-unit>
<trans-unit id="s3d195621e562d805">
<source>Select row</source>
</trans-unit>
<trans-unit id="s572d21b6a41e24fa">
<source>Table of <x id="0" equiv-text="${this.label}"/></source>
</trans-unit>
<trans-unit id="sa25b60b4fac481aa">
<source>Table content</source>
</trans-unit>
<trans-unit id="s5eba8fa19126f70a">
<source>Learn more about the enterprise license.</source>
</trans-unit>
<trans-unit id="s9db1679f3b234d4e">
<source>Search for providers…</source>
</trans-unit>
<trans-unit id="s76790480b7b28ad2">
<source>Edit provider</source>
</trans-unit>
</body>
</file>

View File

@@ -6553,7 +6553,7 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="saf63d34c8601dd41">
<source><x id="0" equiv-text="${prompt.label}"/></source>
<source><x id="0" equiv-text="${name}"/></source>
<target>
<x id="0" equiv-text="${prompt.label}"/>
</target>
@@ -9038,9 +9038,6 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s79b3fcd40dd63921">
<source>Number of previous passwords to check</source>
</trans-unit>
<trans-unit id="sdd66c5a2e706fb81">
<source>Toggle sidebar</source>
</trans-unit>
<trans-unit id="s7d4ec232535a36f0">
<source>Choose a Provider</source>
</trans-unit>
@@ -9301,6 +9298,42 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s5e13dff03b580216">
<source>Previous executions logs</source>
</trans-unit>
<trans-unit id="s6abb1cd87fe0114e">
<source>Home</source>
</trans-unit>
<trans-unit id="se58e6ed983bf34b0">
<source>Collapse navigation</source>
</trans-unit>
<trans-unit id="sc6ef25894ed00175">
<source>Expand navigation</source>
</trans-unit>
<trans-unit id="s148b5e365440a7c1">
<source>Table pagination</source>
</trans-unit>
<trans-unit id="s5d929ff1619ac0c9">
<source>Search</source>
</trans-unit>
<trans-unit id="sd2c2366d13599d8c">
<source>Table actions</source>
</trans-unit>
<trans-unit id="s3d195621e562d805">
<source>Select row</source>
</trans-unit>
<trans-unit id="s572d21b6a41e24fa">
<source>Table of <x id="0" equiv-text="${this.label}"/></source>
</trans-unit>
<trans-unit id="sa25b60b4fac481aa">
<source>Table content</source>
</trans-unit>
<trans-unit id="s5eba8fa19126f70a">
<source>Learn more about the enterprise license.</source>
</trans-unit>
<trans-unit id="s9db1679f3b234d4e">
<source>Search for providers…</source>
</trans-unit>
<trans-unit id="s76790480b7b28ad2">
<source>Edit provider</source>
</trans-unit>
</body>
</file>

View File

@@ -6561,7 +6561,7 @@ Bindingen naar groepen/gebruikers worden gecontroleerd tegen de gebruiker van de
</trans-unit>
<trans-unit id="saf63d34c8601dd41">
<source><x id="0" equiv-text="${prompt.label}"/></source>
<source><x id="0" equiv-text="${name}"/></source>
<target>
<x id="0" equiv-text="${prompt.label}"/>
</target>
@@ -8942,9 +8942,6 @@ Bindingen naar groepen/gebruikers worden gecontroleerd tegen de gebruiker van de
<trans-unit id="s79b3fcd40dd63921">
<source>Number of previous passwords to check</source>
</trans-unit>
<trans-unit id="sdd66c5a2e706fb81">
<source>Toggle sidebar</source>
</trans-unit>
<trans-unit id="s7d4ec232535a36f0">
<source>Choose a Provider</source>
</trans-unit>
@@ -9205,6 +9202,42 @@ Bindingen naar groepen/gebruikers worden gecontroleerd tegen de gebruiker van de
</trans-unit>
<trans-unit id="s5e13dff03b580216">
<source>Previous executions logs</source>
</trans-unit>
<trans-unit id="s6abb1cd87fe0114e">
<source>Home</source>
</trans-unit>
<trans-unit id="se58e6ed983bf34b0">
<source>Collapse navigation</source>
</trans-unit>
<trans-unit id="sc6ef25894ed00175">
<source>Expand navigation</source>
</trans-unit>
<trans-unit id="s148b5e365440a7c1">
<source>Table pagination</source>
</trans-unit>
<trans-unit id="s5d929ff1619ac0c9">
<source>Search</source>
</trans-unit>
<trans-unit id="sd2c2366d13599d8c">
<source>Table actions</source>
</trans-unit>
<trans-unit id="s3d195621e562d805">
<source>Select row</source>
</trans-unit>
<trans-unit id="s572d21b6a41e24fa">
<source>Table of <x id="0" equiv-text="${this.label}"/></source>
</trans-unit>
<trans-unit id="sa25b60b4fac481aa">
<source>Table content</source>
</trans-unit>
<trans-unit id="s5eba8fa19126f70a">
<source>Learn more about the enterprise license.</source>
</trans-unit>
<trans-unit id="s9db1679f3b234d4e">
<source>Search for providers…</source>
</trans-unit>
<trans-unit id="s76790480b7b28ad2">
<source>Edit provider</source>
</trans-unit>
</body>
</file>

View File

@@ -6625,7 +6625,7 @@ Powiązania z grupami/użytkownikami są sprawdzane względem użytkownika zdarz
</trans-unit>
<trans-unit id="saf63d34c8601dd41">
<source><x id="0" equiv-text="${prompt.label}"/></source>
<source><x id="0" equiv-text="${name}"/></source>
<target>
<x id="0" equiv-text="${prompt.label}"/>
</target>
@@ -9359,9 +9359,6 @@ Powiązania z grupami/użytkownikami są sprawdzane względem użytkownika zdarz
<trans-unit id="s79b3fcd40dd63921">
<source>Number of previous passwords to check</source>
</trans-unit>
<trans-unit id="sdd66c5a2e706fb81">
<source>Toggle sidebar</source>
</trans-unit>
<trans-unit id="s7d4ec232535a36f0">
<source>Choose a Provider</source>
</trans-unit>
@@ -9622,6 +9619,42 @@ Powiązania z grupami/użytkownikami są sprawdzane względem użytkownika zdarz
</trans-unit>
<trans-unit id="s5e13dff03b580216">
<source>Previous executions logs</source>
</trans-unit>
<trans-unit id="s6abb1cd87fe0114e">
<source>Home</source>
</trans-unit>
<trans-unit id="se58e6ed983bf34b0">
<source>Collapse navigation</source>
</trans-unit>
<trans-unit id="sc6ef25894ed00175">
<source>Expand navigation</source>
</trans-unit>
<trans-unit id="s148b5e365440a7c1">
<source>Table pagination</source>
</trans-unit>
<trans-unit id="s5d929ff1619ac0c9">
<source>Search</source>
</trans-unit>
<trans-unit id="sd2c2366d13599d8c">
<source>Table actions</source>
</trans-unit>
<trans-unit id="s3d195621e562d805">
<source>Select row</source>
</trans-unit>
<trans-unit id="s572d21b6a41e24fa">
<source>Table of <x id="0" equiv-text="${this.label}"/></source>
</trans-unit>
<trans-unit id="sa25b60b4fac481aa">
<source>Table content</source>
</trans-unit>
<trans-unit id="s5eba8fa19126f70a">
<source>Learn more about the enterprise license.</source>
</trans-unit>
<trans-unit id="s9db1679f3b234d4e">
<source>Search for providers…</source>
</trans-unit>
<trans-unit id="s76790480b7b28ad2">
<source>Edit provider</source>
</trans-unit>
</body>
</file>

View File

@@ -6584,7 +6584,7 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="saf63d34c8601dd41">
<source><x id="0" equiv-text="${prompt.label}"/></source>
<source><x id="0" equiv-text="${name}"/></source>
<target><x id="0" equiv-text="${prompt.label}"/></target>
</trans-unit>
@@ -9367,9 +9367,6 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s79b3fcd40dd63921">
<source>Number of previous passwords to check</source>
</trans-unit>
<trans-unit id="sdd66c5a2e706fb81">
<source>Toggle sidebar</source>
</trans-unit>
<trans-unit id="s7d4ec232535a36f0">
<source>Choose a Provider</source>
</trans-unit>
@@ -9631,4 +9628,40 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s5e13dff03b580216">
<source>Previous executions logs</source>
</trans-unit>
<trans-unit id="s6abb1cd87fe0114e">
<source>Home</source>
</trans-unit>
<trans-unit id="se58e6ed983bf34b0">
<source>Collapse navigation</source>
</trans-unit>
<trans-unit id="sc6ef25894ed00175">
<source>Expand navigation</source>
</trans-unit>
<trans-unit id="s148b5e365440a7c1">
<source>Table pagination</source>
</trans-unit>
<trans-unit id="s5d929ff1619ac0c9">
<source>Search</source>
</trans-unit>
<trans-unit id="sd2c2366d13599d8c">
<source>Table actions</source>
</trans-unit>
<trans-unit id="s3d195621e562d805">
<source>Select row</source>
</trans-unit>
<trans-unit id="s572d21b6a41e24fa">
<source>Table of <x id="0" equiv-text="${this.label}"/></source>
</trans-unit>
<trans-unit id="sa25b60b4fac481aa">
<source>Table content</source>
</trans-unit>
<trans-unit id="s5eba8fa19126f70a">
<source>Learn more about the enterprise license.</source>
</trans-unit>
<trans-unit id="s9db1679f3b234d4e">
<source>Search for providers…</source>
</trans-unit>
<trans-unit id="s76790480b7b28ad2">
<source>Edit provider</source>
</trans-unit>
</body></file></xliff>

View File

@@ -6624,7 +6624,7 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="saf63d34c8601dd41">
<source><x id="0" equiv-text="${prompt.label}"/></source>
<source><x id="0" equiv-text="${name}"/></source>
<target>
<x id="0" equiv-text="${prompt.label}"/>
</target>
@@ -9450,9 +9450,6 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s79b3fcd40dd63921">
<source>Number of previous passwords to check</source>
</trans-unit>
<trans-unit id="sdd66c5a2e706fb81">
<source>Toggle sidebar</source>
</trans-unit>
<trans-unit id="s7d4ec232535a36f0">
<source>Choose a Provider</source>
</trans-unit>
@@ -9713,6 +9710,42 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s5e13dff03b580216">
<source>Previous executions logs</source>
</trans-unit>
<trans-unit id="s6abb1cd87fe0114e">
<source>Home</source>
</trans-unit>
<trans-unit id="se58e6ed983bf34b0">
<source>Collapse navigation</source>
</trans-unit>
<trans-unit id="sc6ef25894ed00175">
<source>Expand navigation</source>
</trans-unit>
<trans-unit id="s148b5e365440a7c1">
<source>Table pagination</source>
</trans-unit>
<trans-unit id="s5d929ff1619ac0c9">
<source>Search</source>
</trans-unit>
<trans-unit id="sd2c2366d13599d8c">
<source>Table actions</source>
</trans-unit>
<trans-unit id="s3d195621e562d805">
<source>Select row</source>
</trans-unit>
<trans-unit id="s572d21b6a41e24fa">
<source>Table of <x id="0" equiv-text="${this.label}"/></source>
</trans-unit>
<trans-unit id="sa25b60b4fac481aa">
<source>Table content</source>
</trans-unit>
<trans-unit id="s5eba8fa19126f70a">
<source>Learn more about the enterprise license.</source>
</trans-unit>
<trans-unit id="s9db1679f3b234d4e">
<source>Search for providers…</source>
</trans-unit>
<trans-unit id="s76790480b7b28ad2">
<source>Edit provider</source>
</trans-unit>
</body>
</file>

View File

@@ -6585,7 +6585,7 @@ Gruplara/kullanıcılara yapılan bağlamalar, etkinliğin kullanıcısına kar
</trans-unit>
<trans-unit id="saf63d34c8601dd41">
<source><x id="0" equiv-text="${prompt.label}"/></source>
<source><x id="0" equiv-text="${name}"/></source>
<target>
<x id="0" equiv-text="${prompt.label}"/>
</target>
@@ -9423,9 +9423,6 @@ Gruplara/kullanıcılara yapılan bağlamalar, etkinliğin kullanıcısına kar
<trans-unit id="s79b3fcd40dd63921">
<source>Number of previous passwords to check</source>
</trans-unit>
<trans-unit id="sdd66c5a2e706fb81">
<source>Toggle sidebar</source>
</trans-unit>
<trans-unit id="s7d4ec232535a36f0">
<source>Choose a Provider</source>
</trans-unit>
@@ -9686,6 +9683,42 @@ Gruplara/kullanıcılara yapılan bağlamalar, etkinliğin kullanıcısına kar
</trans-unit>
<trans-unit id="s5e13dff03b580216">
<source>Previous executions logs</source>
</trans-unit>
<trans-unit id="s6abb1cd87fe0114e">
<source>Home</source>
</trans-unit>
<trans-unit id="se58e6ed983bf34b0">
<source>Collapse navigation</source>
</trans-unit>
<trans-unit id="sc6ef25894ed00175">
<source>Expand navigation</source>
</trans-unit>
<trans-unit id="s148b5e365440a7c1">
<source>Table pagination</source>
</trans-unit>
<trans-unit id="s5d929ff1619ac0c9">
<source>Search</source>
</trans-unit>
<trans-unit id="sd2c2366d13599d8c">
<source>Table actions</source>
</trans-unit>
<trans-unit id="s3d195621e562d805">
<source>Select row</source>
</trans-unit>
<trans-unit id="s572d21b6a41e24fa">
<source>Table of <x id="0" equiv-text="${this.label}"/></source>
</trans-unit>
<trans-unit id="sa25b60b4fac481aa">
<source>Table content</source>
</trans-unit>
<trans-unit id="s5eba8fa19126f70a">
<source>Learn more about the enterprise license.</source>
</trans-unit>
<trans-unit id="s9db1679f3b234d4e">
<source>Search for providers…</source>
</trans-unit>
<trans-unit id="s76790480b7b28ad2">
<source>Edit provider</source>
</trans-unit>
</body>
</file>

View File

@@ -4617,7 +4617,7 @@ Bindings to groups/users are checked against the user of the event.</source>
<source>Change password</source>
</trans-unit>
<trans-unit id="saf63d34c8601dd41">
<source><x id="0" equiv-text="${prompt.label}"/></source>
<source><x id="0" equiv-text="${name}"/></source>
</trans-unit>
<trans-unit id="s33f85f24c0f5f008">
<source>Save</source>
@@ -6214,9 +6214,6 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s79b3fcd40dd63921">
<source>Number of previous passwords to check</source>
</trans-unit>
<trans-unit id="sdd66c5a2e706fb81">
<source>Toggle sidebar</source>
</trans-unit>
<trans-unit id="s7d4ec232535a36f0">
<source>Choose a Provider</source>
</trans-unit>
@@ -6478,6 +6475,42 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s5e13dff03b580216">
<source>Previous executions logs</source>
</trans-unit>
<trans-unit id="s6abb1cd87fe0114e">
<source>Home</source>
</trans-unit>
<trans-unit id="se58e6ed983bf34b0">
<source>Collapse navigation</source>
</trans-unit>
<trans-unit id="sc6ef25894ed00175">
<source>Expand navigation</source>
</trans-unit>
<trans-unit id="s148b5e365440a7c1">
<source>Table pagination</source>
</trans-unit>
<trans-unit id="s5d929ff1619ac0c9">
<source>Search</source>
</trans-unit>
<trans-unit id="sd2c2366d13599d8c">
<source>Table actions</source>
</trans-unit>
<trans-unit id="s3d195621e562d805">
<source>Select row</source>
</trans-unit>
<trans-unit id="s572d21b6a41e24fa">
<source>Table of <x id="0" equiv-text="${this.label}"/></source>
</trans-unit>
<trans-unit id="sa25b60b4fac481aa">
<source>Table content</source>
</trans-unit>
<trans-unit id="s5eba8fa19126f70a">
<source>Learn more about the enterprise license.</source>
</trans-unit>
<trans-unit id="s9db1679f3b234d4e">
<source>Search for providers…</source>
</trans-unit>
<trans-unit id="s76790480b7b28ad2">
<source>Edit provider</source>
</trans-unit>
</body>
</file>
</xliff>

View File

@@ -6624,7 +6624,7 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="saf63d34c8601dd41">
<source><x id="0" equiv-text="${prompt.label}"/></source>
<source><x id="0" equiv-text="${name}"/></source>
<target>
<x id="0" equiv-text="${prompt.label}"/>
</target>
@@ -9672,10 +9672,6 @@ Bindings to groups/users are checked against the user of the event.</source>
<source>Number of previous passwords to check</source>
<target>检查历史密码数量</target>
</trans-unit>
<trans-unit id="sdd66c5a2e706fb81">
<source>Toggle sidebar</source>
<target>切换侧边栏</target>
</trans-unit>
<trans-unit id="s7d4ec232535a36f0">
<source>Choose a Provider</source>
<target>选择提供程序</target>
@@ -9981,6 +9977,42 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s5e13dff03b580216">
<source>Previous executions logs</source>
</trans-unit>
<trans-unit id="s6abb1cd87fe0114e">
<source>Home</source>
</trans-unit>
<trans-unit id="se58e6ed983bf34b0">
<source>Collapse navigation</source>
</trans-unit>
<trans-unit id="sc6ef25894ed00175">
<source>Expand navigation</source>
</trans-unit>
<trans-unit id="s148b5e365440a7c1">
<source>Table pagination</source>
</trans-unit>
<trans-unit id="s5d929ff1619ac0c9">
<source>Search</source>
</trans-unit>
<trans-unit id="sd2c2366d13599d8c">
<source>Table actions</source>
</trans-unit>
<trans-unit id="s3d195621e562d805">
<source>Select row</source>
</trans-unit>
<trans-unit id="s572d21b6a41e24fa">
<source>Table of <x id="0" equiv-text="${this.label}"/></source>
</trans-unit>
<trans-unit id="sa25b60b4fac481aa">
<source>Table content</source>
</trans-unit>
<trans-unit id="s5eba8fa19126f70a">
<source>Learn more about the enterprise license.</source>
</trans-unit>
<trans-unit id="s9db1679f3b234d4e">
<source>Search for providers…</source>
</trans-unit>
<trans-unit id="s76790480b7b28ad2">
<source>Edit provider</source>
</trans-unit>
</body>
</file>

View File

@@ -5010,7 +5010,7 @@ Bindings to groups/users are checked against the user of the event.</source>
<target>修改密码</target>
</trans-unit>
<trans-unit id="saf63d34c8601dd41">
<source><x id="0" equiv-text="${prompt.label}"/></source>
<source><x id="0" equiv-text="${name}"/></source>
<target>
<x id="0" equiv-text="${prompt.label}"/>
</target>
@@ -7296,9 +7296,6 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s79b3fcd40dd63921">
<source>Number of previous passwords to check</source>
</trans-unit>
<trans-unit id="sdd66c5a2e706fb81">
<source>Toggle sidebar</source>
</trans-unit>
<trans-unit id="s7d4ec232535a36f0">
<source>Choose a Provider</source>
</trans-unit>
@@ -7559,6 +7556,42 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s5e13dff03b580216">
<source>Previous executions logs</source>
</trans-unit>
<trans-unit id="s6abb1cd87fe0114e">
<source>Home</source>
</trans-unit>
<trans-unit id="se58e6ed983bf34b0">
<source>Collapse navigation</source>
</trans-unit>
<trans-unit id="sc6ef25894ed00175">
<source>Expand navigation</source>
</trans-unit>
<trans-unit id="s148b5e365440a7c1">
<source>Table pagination</source>
</trans-unit>
<trans-unit id="s5d929ff1619ac0c9">
<source>Search</source>
</trans-unit>
<trans-unit id="sd2c2366d13599d8c">
<source>Table actions</source>
</trans-unit>
<trans-unit id="s3d195621e562d805">
<source>Select row</source>
</trans-unit>
<trans-unit id="s572d21b6a41e24fa">
<source>Table of <x id="0" equiv-text="${this.label}"/></source>
</trans-unit>
<trans-unit id="sa25b60b4fac481aa">
<source>Table content</source>
</trans-unit>
<trans-unit id="s5eba8fa19126f70a">
<source>Learn more about the enterprise license.</source>
</trans-unit>
<trans-unit id="s9db1679f3b234d4e">
<source>Search for providers…</source>
</trans-unit>
<trans-unit id="s76790480b7b28ad2">
<source>Edit provider</source>
</trans-unit>
</body>
</file>

View File

@@ -6543,7 +6543,7 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="saf63d34c8601dd41">
<source><x id="0" equiv-text="${prompt.label}"/></source>
<source><x id="0" equiv-text="${name}"/></source>
<target>
<x id="0" equiv-text="${prompt.label}"/>
</target>
@@ -9018,9 +9018,6 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s79b3fcd40dd63921">
<source>Number of previous passwords to check</source>
</trans-unit>
<trans-unit id="sdd66c5a2e706fb81">
<source>Toggle sidebar</source>
</trans-unit>
<trans-unit id="s7d4ec232535a36f0">
<source>Choose a Provider</source>
</trans-unit>
@@ -9281,6 +9278,42 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s5e13dff03b580216">
<source>Previous executions logs</source>
</trans-unit>
<trans-unit id="s6abb1cd87fe0114e">
<source>Home</source>
</trans-unit>
<trans-unit id="se58e6ed983bf34b0">
<source>Collapse navigation</source>
</trans-unit>
<trans-unit id="sc6ef25894ed00175">
<source>Expand navigation</source>
</trans-unit>
<trans-unit id="s148b5e365440a7c1">
<source>Table pagination</source>
</trans-unit>
<trans-unit id="s5d929ff1619ac0c9">
<source>Search</source>
</trans-unit>
<trans-unit id="sd2c2366d13599d8c">
<source>Table actions</source>
</trans-unit>
<trans-unit id="s3d195621e562d805">
<source>Select row</source>
</trans-unit>
<trans-unit id="s572d21b6a41e24fa">
<source>Table of <x id="0" equiv-text="${this.label}"/></source>
</trans-unit>
<trans-unit id="sa25b60b4fac481aa">
<source>Table content</source>
</trans-unit>
<trans-unit id="s5eba8fa19126f70a">
<source>Learn more about the enterprise license.</source>
</trans-unit>
<trans-unit id="s9db1679f3b234d4e">
<source>Search for providers…</source>
</trans-unit>
<trans-unit id="s76790480b7b28ad2">
<source>Edit provider</source>
</trans-unit>
</body>
</file>

View File

@@ -45,11 +45,11 @@
"typescript": "^5.8.3"
},
"optionalDependencies": {
"@rspack/binding-darwin-arm64": "1.4.10",
"@rspack/binding-linux-arm64-gnu": "1.4.10",
"@rspack/binding-linux-x64-gnu": "1.4.10",
"@swc/core-darwin-arm64": "1.13.2",
"@swc/core-linux-arm64-gnu": "1.13.2",
"@rspack/binding-darwin-arm64": "1.4.11",
"@rspack/binding-linux-arm64-gnu": "1.4.11",
"@rspack/binding-linux-x64-gnu": "1.4.11",
"@swc/core-darwin-arm64": "1.13.3",
"@swc/core-linux-arm64-gnu": "1.13.3",
"@swc/core-linux-x64-gnu": "1.13.3",
"@swc/html-darwin-arm64": "1.13.3",
"@swc/html-linux-arm64-gnu": "1.13.3",

View File

@@ -56,6 +56,14 @@ export default createDocusaurusConfig(
path: "pages",
},
docs: {
exclude: [
/**
* Exclude previously generated API docs.
*
* @expires 2025-12-01
*/
"**/developer-docs/api/reference/**",
],
routeBasePath: "/docs",
path: ".",

View File

@@ -35,9 +35,9 @@ To support the integration of Kimai with authentik, you need to create an applic
- **Choose a Provider type**: select **SAML Provider** as the provider type.
- **Configure the Provider**: provide a name (or accept the auto-provided name), the authorization flow to use for this provider, and the following required configurations.
- Set the **ACS URL** to `https://kimai.company/auth/saml/acs`.
- Set the **Audience** to `https://kimai.companyauth/saml`.
- Set the **Issuer** to `https://authentik.company`.
- Set the **Service Provider Binding** to `Post`.
- Set the **Audience** to `https://kimai.company/auth/saml`.
- Under **Advanced protocol settings**, select an available signing certificate.
- **Configure Bindings** _(optional)_: you can create a [binding](/docs/add-secure-apps/flows-stages/bindings/) (policy, group, or user) to manage the listing and access to applications on a user's **My applications** page.

View File

@@ -19,7 +19,7 @@
"@goauthentik/eslint-config": "^1.0.5",
"@goauthentik/prettier-config": "^3.1.0",
"@goauthentik/tsconfig": "^1.0.4",
"@swc/html-linux-x64-gnu": "1.13.3",
"@rspack/binding-linux-x64-gnu": "1.4.11",
"@types/node": "^24.1.0",
"@typescript-eslint/eslint-plugin": "^8.38.0",
"@typescript-eslint/parser": "^8.38.0",
@@ -33,11 +33,11 @@
"node": ">=24"
},
"optionalDependencies": {
"@rspack/binding-darwin-arm64": "1.4.10",
"@rspack/binding-linux-arm64-gnu": "1.4.10",
"@rspack/binding-linux-x64-gnu": "1.4.10",
"@swc/core-darwin-arm64": "1.13.2",
"@swc/core-linux-arm64-gnu": "1.13.2",
"@rspack/binding-darwin-arm64": "1.4.11",
"@rspack/binding-linux-arm64-gnu": "1.4.11",
"@rspack/binding-linux-x64-gnu": "1.4.11",
"@swc/core-darwin-arm64": "1.13.3",
"@swc/core-linux-arm64-gnu": "1.13.3",
"@swc/core-linux-x64-gnu": "1.13.3",
"@swc/html-darwin-arm64": "1.13.3",
"@swc/html-linux-arm64-gnu": "1.13.3",
@@ -77,11 +77,11 @@
"typescript": "^5.8.3"
},
"optionalDependencies": {
"@rspack/binding-darwin-arm64": "1.4.10",
"@rspack/binding-linux-arm64-gnu": "1.4.10",
"@rspack/binding-linux-x64-gnu": "1.4.10",
"@swc/core-darwin-arm64": "1.13.2",
"@swc/core-linux-arm64-gnu": "1.13.2",
"@rspack/binding-darwin-arm64": "1.4.11",
"@rspack/binding-linux-arm64-gnu": "1.4.11",
"@rspack/binding-linux-x64-gnu": "1.4.11",
"@swc/core-darwin-arm64": "1.13.3",
"@swc/core-linux-arm64-gnu": "1.13.3",
"@swc/core-linux-x64-gnu": "1.13.3",
"@swc/html-darwin-arm64": "1.13.3",
"@swc/html-linux-arm64-gnu": "1.13.3",
@@ -5776,9 +5776,9 @@
}
},
"node_modules/@rspack/binding-darwin-arm64": {
"version": "1.4.10",
"resolved": "https://registry.npmjs.org/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-1.4.10.tgz",
"integrity": "sha512-PraYGuVSzvEwdoYC8T70qI/8j1QeUe2sysiWmjSdxUpxJsDfw35hK9TfxULeAJULlAUAiiXs03hdZk29DBc3ow==",
"version": "1.4.11",
"resolved": "https://registry.npmjs.org/@rspack/binding-darwin-arm64/-/binding-darwin-arm64-1.4.11.tgz",
"integrity": "sha512-PrmBVhR8MC269jo6uQ+BMy1uwIDx0HAJYLQRQur8gXiehWabUBCRg/d4U9KR7rLzdaSScRyc5JWXR52T7/4MfA==",
"cpu": [
"arm64"
],
@@ -5802,9 +5802,9 @@
]
},
"node_modules/@rspack/binding-linux-arm64-gnu": {
"version": "1.4.10",
"resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.4.10.tgz",
"integrity": "sha512-cs6yu250FzRU1hl+02VLoJRdzbAveTOqvREeHgqL5AiTc6q1dQo1IZ16/Qt4+g0DMjnvM66pELRIO2nphXL8aA==",
"version": "1.4.11",
"resolved": "https://registry.npmjs.org/@rspack/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.4.11.tgz",
"integrity": "sha512-ms6uwECUIcu+6e82C5HJhRMHnfsI+l33v7XQezntzRPN0+sG3EpikEoT7SGbgt4vDwaWLR7wS20suN4qd5r3GA==",
"cpu": [
"arm64"
],
@@ -5828,9 +5828,9 @@
]
},
"node_modules/@rspack/binding-linux-x64-gnu": {
"version": "1.4.10",
"resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.4.10.tgz",
"integrity": "sha512-FcaBqMclADWiqX+Mez15kggwaVYZkoEqDiQwYRpYDbBMsiJEtfp41GnNRstTWxYxFbcmuWoZl2cYy+LepR21ag==",
"version": "1.4.11",
"resolved": "https://registry.npmjs.org/@rspack/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.4.11.tgz",
"integrity": "sha512-bHYFLxPPYBOSaHdQbEoCYGMQ1gOrEWj7Mro/DLfSHZi1a0okcQ2Q1y0i1DczReim3ZhLGNrK7k1IpFXCRbAobQ==",
"cpu": [
"x64"
],
@@ -6327,9 +6327,9 @@
}
},
"node_modules/@swc/core-darwin-arm64": {
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.13.2.tgz",
"integrity": "sha512-44p7ivuLSGFJ15Vly4ivLJjg3ARo4879LtEBAabcHhSZygpmkP8eyjyWxrH3OxkY1eRZSIJe8yRZPFw4kPXFPw==",
"version": "1.13.3",
"resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.13.3.tgz",
"integrity": "sha512-ux0Ws4pSpBTqbDS9GlVP354MekB1DwYlbxXU3VhnDr4GBcCOimpocx62x7cFJkSpEBF8bmX8+/TTCGKh4PbyXw==",
"cpu": [
"arm64"
],
@@ -6375,9 +6375,9 @@
}
},
"node_modules/@swc/core-linux-arm64-gnu": {
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.13.2.tgz",
"integrity": "sha512-KJUSl56DBk7AWMAIEcU83zl5mg3vlQYhLELhjwRFkGFMvghQvdqQ3zFOYa4TexKA7noBZa3C8fb24rI5sw9Exg==",
"version": "1.13.3",
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.13.3.tgz",
"integrity": "sha512-STfKku3QfnuUj6k3g9ld4vwhtgCGYIFQmsGPPgT9MK/dI3Lwnpe5Gs5t1inoUIoGNP8sIOLlBB4HV4MmBjQuhw==",
"cpu": [
"arm64"
],

View File

@@ -32,11 +32,11 @@
"typescript-eslint": "^8.38.0"
},
"optionalDependencies": {
"@rspack/binding-darwin-arm64": "1.4.10",
"@rspack/binding-linux-arm64-gnu": "1.4.10",
"@rspack/binding-linux-x64-gnu": "1.4.10",
"@swc/core-darwin-arm64": "1.13.2",
"@swc/core-linux-arm64-gnu": "1.13.2",
"@rspack/binding-darwin-arm64": "1.4.11",
"@rspack/binding-linux-arm64-gnu": "1.4.11",
"@rspack/binding-linux-x64-gnu": "1.4.11",
"@swc/core-darwin-arm64": "1.13.3",
"@swc/core-linux-arm64-gnu": "1.13.3",
"@swc/core-linux-x64-gnu": "1.13.3",
"@swc/html-darwin-arm64": "1.13.3",
"@swc/html-linux-arm64-gnu": "1.13.3",