Compare commits

..

1 Commits

Author SHA1 Message Date
ee6b8b596e web/NPM Workspaces: Prep SFE package. 2025-05-20 02:53:50 +02:00
124 changed files with 57002 additions and 48710 deletions

View File

@ -28,9 +28,9 @@ runs:
- name: Setup node - name: Setup node
uses: actions/setup-node@v4 uses: actions/setup-node@v4
with: with:
node-version-file: package.json node-version-file: web/package.json
cache: "npm" cache: "npm"
cache-dependency-path: package-lock.json cache-dependency-path: web/package-lock.json
- name: Setup go - name: Setup go
uses: actions/setup-go@v5 uses: actions/setup-go@v5
with: with:
@ -44,7 +44,7 @@ runs:
run: | run: |
export PSQL_TAG=${{ inputs.postgresql_version }} export PSQL_TAG=${{ inputs.postgresql_version }}
docker compose -f .github/actions/setup/docker-compose.yml up -d docker compose -f .github/actions/setup/docker-compose.yml up -d
npm ci cd web && npm ci
- name: Generate config - name: Generate config
shell: uv run python {0} shell: uv run python {0}
run: | run: |

View File

@ -23,13 +23,7 @@ updates:
- package-ecosystem: npm - package-ecosystem: npm
directories: directories:
- "/web" - "/web"
- "/web/packages/sfe" - "/web/sfe"
- "/web/packages/core"
- "/web/packages/esbuild-plugin-live-reload"
- "/packages/prettier-config"
- "/packages/tsconfig"
- "/packages/docusaurus-config"
- "/packages/eslint-config"
schedule: schedule:
interval: daily interval: daily
time: "04:00" time: "04:00"
@ -74,9 +68,6 @@ updates:
wdio: wdio:
patterns: patterns:
- "@wdio/*" - "@wdio/*"
goauthentik:
patterns:
- "@goauthentik/*"
- package-ecosystem: npm - package-ecosystem: npm
directory: "/website" directory: "/website"
schedule: schedule:
@ -97,9 +88,6 @@ updates:
- "swc-*" - "swc-*"
- "lightningcss*" - "lightningcss*"
- "@rspack/binding*" - "@rspack/binding*"
goauthentik:
patterns:
- "@goauthentik/*"
- package-ecosystem: npm - package-ecosystem: npm
directory: "/lifecycle/aws" directory: "/lifecycle/aws"
schedule: schedule:

View File

@ -20,11 +20,8 @@ jobs:
token: ${{ steps.generate_token.outputs.token }} token: ${{ steps.generate_token.outputs.token }}
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:
node-version-file: package.json node-version-file: web/package.json
registry-url: "https://registry.npmjs.org" registry-url: "https://registry.npmjs.org"
- name: Prepare Dependencies
run: |
npm ci
- name: Generate API Client - name: Generate API Client
run: make gen-client-ts run: make gen-client-ts
- name: Publish package - name: Publish package
@ -35,13 +32,15 @@ jobs:
env: env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }} NODE_AUTH_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}
- name: Upgrade /web - name: Upgrade /web
working-directory: web
run: | run: |
export VERSION=`node -e 'console.log(require("./gen-ts-api/package.json").version)'` export VERSION=`node -e 'console.log(require("../gen-ts-api/package.json").version)'`
npm i @goauthentik/api@$VERSION -w @goauthentik/web npm i @goauthentik/api@$VERSION
- name: Upgrade /web/packages/sfe - name: Upgrade /web/packages/sfe
working-directory: web/packages/sfe
run: | run: |
export VERSION=`node -e 'console.log(require("./gen-ts-api/package.json").version)'` export VERSION=`node -e 'console.log(require("../gen-ts-api/package.json").version)'`
npm i @goauthentik/api@$VERSION -w @goauthentik/web-sfe npm i @goauthentik/api@$VERSION
- uses: peter-evans/create-pull-request@v7 - uses: peter-evans/create-pull-request@v7
id: cpr id: cpr
with: with:

View File

@ -193,22 +193,23 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Setup authentik env - name: Setup authentik env
uses: ./.github/actions/setup uses: ./.github/actions/setup
- name: Setup E2E environment (Chrome, etc) - name: Setup e2e env (chrome, etc)
run: | run: |
docker compose -f tests/e2e/docker-compose.yml up -d --quiet-pull docker compose -f tests/e2e/docker-compose.yml up -d --quiet-pull
- id: cache-web - id: cache-web
uses: actions/cache@v4 uses: actions/cache@v4
with: with:
path: web/dist path: web/dist
key: ${{ runner.os }}-web-${{ hashFiles('package-lock.json', 'web/src/**', 'web/packages/sfe/src/**') }}-b key: ${{ runner.os }}-web-${{ hashFiles('web/package-lock.json', 'web/src/**', 'web/packages/sfe/src/**') }}-b
- name: Prepare Web UI - name: prepare web ui
if: steps.cache-web.outputs.cache-hit != 'true' if: steps.cache-web.outputs.cache-hit != 'true'
working-directory: web
run: | run: |
npm ci npm ci
make gen-client-ts make -C .. gen-client-ts
npm run build -w @goauthentik/web npm run build
npm run build -w @goauthentik/web-sfe npm run build:sfe
- name: Run E2E - name: run e2e
run: | run: |
uv run coverage run manage.py test ${{ matrix.job.glob }} uv run coverage run manage.py test ${{ matrix.job.glob }}
uv run coverage xml uv run coverage xml

View File

@ -26,7 +26,7 @@ jobs:
mkdir -p web/dist mkdir -p web/dist
mkdir -p website/help mkdir -p website/help
touch web/dist/test website/help/test touch web/dist/test website/help/test
- name: Generate Golang API Client - name: Generate API
run: make gen-client-go run: make gen-client-go
- name: golangci-lint - name: golangci-lint
uses: golangci/golangci-lint-action@v8 uses: golangci/golangci-lint-action@v8
@ -43,7 +43,7 @@ jobs:
go-version-file: "go.mod" go-version-file: "go.mod"
- name: Setup authentik env - name: Setup authentik env
uses: ./.github/actions/setup uses: ./.github/actions/setup
- name: Generate Golang API Client - name: Generate API
run: make gen-client-go run: make gen-client-go
- name: Go unittests - name: Go unittests
run: | run: |
@ -99,7 +99,7 @@ jobs:
registry: ghcr.io registry: ghcr.io
username: ${{ github.repository_owner }} username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }} password: ${{ secrets.GITHUB_TOKEN }}
- name: Generate Golang API Client - name: Generate API
run: make gen-client-go run: make gen-client-go
- name: Build Docker Image - name: Build Docker Image
id: push id: push
@ -145,17 +145,16 @@ jobs:
go-version-file: "go.mod" go-version-file: "go.mod"
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:
node-version-file: package.json node-version-file: web/package.json
cache: "npm" cache: "npm"
cache-dependency-path: package-lock.json cache-dependency-path: web/package-lock.json
- name: Generate Golang API Client - name: Generate API
run: make gen-client-go run: make gen-client-go
- name: Prepare Dependencies - name: Build web
working-directory: web/
run: | run: |
npm ci npm ci
- name: Run ESBuild npm run build-proxy
run: |
npm run build-proxy -w @goauthentik/web
- name: Build outpost - name: Build outpost
run: | run: |
set -x set -x

View File

@ -19,45 +19,47 @@ jobs:
matrix: matrix:
command: command:
- lint - lint
- lint:lockfile
- tsc
- prettier-check - prettier-check
project: project:
- web - web
include: include:
- command: tsc
project: web
- command: lit-analyse - command: lit-analyse
project: web project: web
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:
node-version-file: package.json node-version-file: ${{ matrix.project }}/package.json
cache: "npm" cache: "npm"
cache-dependency-path: package-lock.json cache-dependency-path: ${{ matrix.project }}/package-lock.json
- name: Prepare Dependencies - working-directory: ${{ matrix.project }}/
run: | run: |
npm ci npm ci
- name: Generate TypeScript API - name: Generate API
run: make gen-client-ts run: make gen-client-ts
- name: Lint Project - name: Lint
run: | working-directory: ${{ matrix.project }}/
npm run build-locales -w @goauthentik/web run: npm run ${{ matrix.command }}
npm run lint:types
- name: Lint Web
run: npm run ${{ matrix.command }} -w @goauthentik/web
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:
node-version-file: package.json node-version-file: web/package.json
cache: "npm" cache: "npm"
cache-dependency-path: package-lock.json cache-dependency-path: web/package-lock.json
- name: Prepare Dependencies - working-directory: web/
run: npm ci run: npm ci
- name: Generate TypeScript API - name: Generate API
run: make gen-client-ts run: make gen-client-ts
- name: build - name: build
run: npm run build -w @goauthentik/web working-directory: web/
run: npm run build
ci-web-mark: ci-web-mark:
if: always() if: always()
needs: needs:
@ -76,12 +78,13 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:
node-version-file: package.json node-version-file: web/package.json
cache: "npm" cache: "npm"
cache-dependency-path: package-lock.json cache-dependency-path: web/package-lock.json
- name: Prepare Dependencies - working-directory: web/
run: npm ci run: npm ci
- name: Generate TypeScript API - name: Generate API
run: make gen-client-ts run: make gen-client-ts
- name: test - name: test
run: npm run test -w @goauthentik/web || exit 0 working-directory: web/
run: npm run test || exit 0

View File

@ -14,44 +14,53 @@ on:
jobs: jobs:
lint: lint:
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
command:
- lint:lockfile
- prettier-check
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-node@v4 - working-directory: website/
with:
node-version-file: package.json
cache: "npm"
cache-dependency-path: package-lock.json
- name: Prepare Dependencies
run: npm ci run: npm ci
- name: Lint - name: Lint
run: npm run prettier-check -w @goauthentik/docs working-directory: website/
run: npm run ${{ matrix.command }}
test: test:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:
node-version-file: package.json node-version-file: website/package.json
cache: "npm" cache: "npm"
cache-dependency-path: package-lock.json cache-dependency-path: website/package-lock.json
- name: Prepare Dependencies - working-directory: website/
run: npm ci run: npm ci
- name: test - name: test
run: npm test -w @goauthentik/docs working-directory: website/
run: npm test
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
name: ${{ matrix.job }}
strategy:
fail-fast: false
matrix:
job:
- build
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:
node-version-file: package.json node-version-file: website/package.json
cache: "npm" cache: "npm"
cache-dependency-path: package-lock.json cache-dependency-path: website/package-lock.json
- name: Prepare Dependencies - working-directory: website/
run: npm ci run: npm ci
- name: Run Docusaurus - name: build
run: npm run build -w @goauthentik/docs working-directory: website/
run: npm run ${{ matrix.job }}
ci-website-mark: ci-website-mark:
if: always() if: always()
needs: needs:

View File

@ -7,7 +7,6 @@ on:
- packages/eslint-config/** - packages/eslint-config/**
- packages/prettier-config/** - packages/prettier-config/**
- packages/tsconfig/** - packages/tsconfig/**
- packages/web/esbuild-plugin-live-reload/**
workflow_dispatch: workflow_dispatch:
jobs: jobs:
publish: publish:
@ -17,28 +16,27 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
package: package:
- packages/docusaurus-config - docusaurus-config
- packages/eslint-config - eslint-config
- packages/prettier-config - prettier-config
- packages/tsconfig - tsconfig
- packages/web/esbuild-plugin-live-reload
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
fetch-depth: 2 fetch-depth: 2
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:
node-version-file: ${{ matrix.package }}/package.json node-version-file: packages/${{ matrix.package }}/package.json
registry-url: "https://registry.npmjs.org" registry-url: "https://registry.npmjs.org"
- name: Get changed files - name: Get changed files
id: changed-files id: changed-files
uses: tj-actions/changed-files@ed68ef82c095e0d48ec87eccea555d944a631a4c uses: tj-actions/changed-files@ed68ef82c095e0d48ec87eccea555d944a631a4c
with: with:
files: | files: |
${{ matrix.package }}/package.json packages/${{ matrix.package }}/package.json
- name: Publish package - name: Publish package
if: steps.changed-files.outputs.any_changed == 'true' if: steps.changed-files.outputs.any_changed == 'true'
working-directory: ${{ matrix.package }} working-directory: packages/${{ matrix.package}}
run: | run: |
npm ci npm ci
npm run build npm run build

View File

@ -106,14 +106,14 @@ jobs:
go-version-file: "go.mod" go-version-file: "go.mod"
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:
node-version-file: package.json node-version-file: web/package.json
cache: "npm" cache: "npm"
cache-dependency-path: package-lock.json cache-dependency-path: web/package-lock.json
- name: Prepare Dependencies - name: Build web
run: npm ci working-directory: web/
- name: Run ESBuild (Proxy)
run: | run: |
npm run build-proxy -w @goauthentik/web npm ci
npm run build-proxy
- name: Build outpost - name: Build outpost
run: | run: |
set -x set -x

View File

@ -32,25 +32,15 @@ jobs:
if: ${{ github.event_name == 'pull_request' }} if: ${{ github.event_name == 'pull_request' }}
- name: Setup authentik env - name: Setup authentik env
uses: ./.github/actions/setup uses: ./.github/actions/setup
- uses: actions/setup-node@v4 - name: Generate API
with:
node-version-file: package.json
cache: "npm"
cache-dependency-path: package-lock.json
- name: Prepare Dependencies
run: npm ci
- name: Generate TypeScript API
run: make gen-client-ts run: make gen-client-ts
- name: Run extract - name: run extract
run: | run: |
uv run make i18n-extract uv run make i18n-extract
- name: Run UV compile - name: run compile
run: | run: |
uv run ak compilemessages uv run ak compilemessages
- name: Lint Project make web-check-compile
run: |
npm run build-locales -w @goauthentik/web
npm run lint:types
- name: Create Pull Request - name: Create Pull Request
if: ${{ github.event_name != 'pull_request' }} if: ${{ github.event_name != 'pull_request' }}
uses: peter-evans/create-pull-request@v7 uses: peter-evans/create-pull-request@v7

View File

@ -15,7 +15,6 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: ${{ github.event.pull_request.user.login == 'transifex-integration[bot]'}} if: ${{ github.event.pull_request.user.login == 'transifex-integration[bot]'}}
steps: steps:
- uses: actions/checkout@v4
- id: generate_token - id: generate_token
uses: tibdex/github-app-token@v2 uses: tibdex/github-app-token@v2
with: with:
@ -32,7 +31,7 @@ jobs:
env: env:
GH_TOKEN: ${{ steps.generate_token.outputs.token }} GH_TOKEN: ${{ steps.generate_token.outputs.token }}
run: | run: |
gh pr edit ${{ github.event.pull_request.number }} -t "translate: ${{ steps.title.outputs.title }}" --add-label dependencies gh pr edit -t "translate: ${{ steps.title.outputs.title }}" --add-label dependencies
- uses: peter-evans/enable-pull-request-automerge@v3 - uses: peter-evans/enable-pull-request-automerge@v3
with: with:
token: ${{ steps.generate_token.outputs.token }} token: ${{ steps.generate_token.outputs.token }}

View File

@ -36,19 +36,12 @@ coverage
*.mdx *.mdx
*.md *.md
## Import order matters
poly.ts
src/locale-codes.ts
src/locales/
# Storybook # Storybook
storybook-static/ storybook-static/
.storybook/css-import-maps* .storybook/css-import-maps*
# JSON Schemas
schemas/**/*.json
blueprints/**/*.json
authentik/**/*.json
lifecycle/**/*.json
# Locales
web/src/locale-codes.ts
web/src/locales/
# Wireit's cache
.wireit

View File

@ -17,6 +17,6 @@
"ms-python.vscode-pylance", "ms-python.vscode-pylance",
"redhat.vscode-yaml", "redhat.vscode-yaml",
"Tobermory.es6-string-html", "Tobermory.es6-string-html",
"unifiedjs.vscode-mdx" "unifiedjs.vscode-mdx",
] ]
} }

40
.vscode/tasks.json vendored
View File

@ -4,7 +4,12 @@
{ {
"label": "authentik/core: make", "label": "authentik/core: make",
"command": "uv", "command": "uv",
"args": ["run", "make", "lint-fix", "lint"], "args": [
"run",
"make",
"lint-fix",
"lint"
],
"presentation": { "presentation": {
"panel": "new" "panel": "new"
}, },
@ -13,7 +18,11 @@
{ {
"label": "authentik/core: run", "label": "authentik/core: run",
"command": "uv", "command": "uv",
"args": ["run", "ak", "server"], "args": [
"run",
"ak",
"server"
],
"group": "build", "group": "build",
"presentation": { "presentation": {
"panel": "dedicated", "panel": "dedicated",
@ -23,13 +32,17 @@
{ {
"label": "authentik/web: make", "label": "authentik/web: make",
"command": "make", "command": "make",
"args": ["web"], "args": [
"web"
],
"group": "build" "group": "build"
}, },
{ {
"label": "authentik/web: watch", "label": "authentik/web: watch",
"command": "make", "command": "make",
"args": ["web-watch"], "args": [
"web-watch"
],
"group": "build", "group": "build",
"presentation": { "presentation": {
"panel": "dedicated", "panel": "dedicated",
@ -39,19 +52,26 @@
{ {
"label": "authentik: install", "label": "authentik: install",
"command": "make", "command": "make",
"args": ["install", "-j4"], "args": [
"install",
"-j4"
],
"group": "build" "group": "build"
}, },
{ {
"label": "authentik/website: make", "label": "authentik/website: make",
"command": "make", "command": "make",
"args": ["website"], "args": [
"website"
],
"group": "build" "group": "build"
}, },
{ {
"label": "authentik/website: watch", "label": "authentik/website: watch",
"command": "make", "command": "make",
"args": ["website-watch"], "args": [
"website-watch"
],
"group": "build", "group": "build",
"presentation": { "presentation": {
"panel": "dedicated", "panel": "dedicated",
@ -61,7 +81,11 @@
{ {
"label": "authentik/api: generate", "label": "authentik/api: generate",
"command": "uv", "command": "uv",
"args": ["run", "make", "gen"], "args": [
"run",
"make",
"gen"
],
"group": "build" "group": "build"
} }
] ]

View File

@ -1,41 +1,49 @@
# syntax=docker/dockerfile:1 # syntax=docker/dockerfile:1
# Stage 1: Build Node packages # Stage 1: Build website
FROM --platform=${BUILDPLATFORM} docker.io/library/node:24-slim AS node-packages FROM --platform=${BUILDPLATFORM} docker.io/library/node:22 AS website-builder
ARG GIT_BUILD_HASH
ENV GIT_BUILD_HASH=$GIT_BUILD_HASH
WORKDIR /work
COPY ./SECURITY.md /work
COPY ./schema.yml /work
COPY ./docker-compose.yml /work
COPY ./blueprints /work/blueprints/
COPY ./package.json /work
COPY ./package-lock.json /work
COPY ./tsconfig.json /work
COPY ./packages/ /work/packages/
COPY ./web /work/web/
COPY ./website /work/website/
COPY ./gen-ts-api /work/gen-ts-api/
RUN --mount=type=cache,id=npm-node,sharing=shared,target=/root/.npm \
npm ci
RUN cd ./gen-ts-api && npm link
RUN npm link @goauthentik/api -w @goauthentik/web
ENV NODE_ENV=production ENV NODE_ENV=production
RUN npm run build -w @goauthentik/web WORKDIR /work/website
RUN npm run build -w @goauthentik/web-sfe
RUN npm run build:api -w @goauthentik/docs RUN --mount=type=bind,target=/work/website/package.json,src=./website/package.json \
RUN npm run build:docusaurus -w @goauthentik/docs --mount=type=bind,target=/work/website/package-lock.json,src=./website/package-lock.json \
--mount=type=cache,id=npm-website,sharing=shared,target=/root/.npm \
npm ci --include=dev
# Stage 2: Build go proxy COPY ./website /work/website/
COPY ./blueprints /work/blueprints/
COPY ./schema.yml /work/
COPY ./SECURITY.md /work/
RUN npm run build-bundled
# Stage 2: Build webui
FROM --platform=${BUILDPLATFORM} docker.io/library/node:22 AS web-builder
ARG GIT_BUILD_HASH
ENV GIT_BUILD_HASH=$GIT_BUILD_HASH
ENV NODE_ENV=production
WORKDIR /work/web
RUN --mount=type=bind,target=/work/web/package.json,src=./web/package.json \
--mount=type=bind,target=/work/web/package-lock.json,src=./web/package-lock.json \
--mount=type=bind,target=/work/web/packages/sfe/package.json,src=./web/packages/sfe/package.json \
--mount=type=bind,target=/work/web/scripts,src=./web/scripts \
--mount=type=cache,id=npm-web,sharing=shared,target=/root/.npm \
npm ci --include=dev
COPY ./package.json /work
COPY ./web /work/web/
COPY ./website /work/website/
COPY ./gen-ts-api /work/web/node_modules/@goauthentik/api
RUN npm run build && \
npm run build:sfe
# Stage 3: Build go proxy
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.24-bookworm AS go-builder FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.24-bookworm AS go-builder
ARG TARGETOS ARG TARGETOS
@ -60,8 +68,8 @@ RUN --mount=type=bind,target=/go/src/goauthentik.io/go.mod,src=./go.mod \
COPY ./cmd /go/src/goauthentik.io/cmd COPY ./cmd /go/src/goauthentik.io/cmd
COPY ./authentik/lib /go/src/goauthentik.io/authentik/lib COPY ./authentik/lib /go/src/goauthentik.io/authentik/lib
COPY ./web/static.go /go/src/goauthentik.io/web/static.go COPY ./web/static.go /go/src/goauthentik.io/web/static.go
COPY --from=node-packages /work/web/robots.txt /go/src/goauthentik.io/web/robots.txt COPY --from=web-builder /work/web/robots.txt /go/src/goauthentik.io/web/robots.txt
COPY --from=node-packages /work/web/security.txt /go/src/goauthentik.io/web/security.txt COPY --from=web-builder /work/web/security.txt /go/src/goauthentik.io/web/security.txt
COPY ./internal /go/src/goauthentik.io/internal COPY ./internal /go/src/goauthentik.io/internal
COPY ./go.mod /go/src/goauthentik.io/go.mod COPY ./go.mod /go/src/goauthentik.io/go.mod
COPY ./go.sum /go/src/goauthentik.io/go.sum COPY ./go.sum /go/src/goauthentik.io/go.sum
@ -72,7 +80,7 @@ RUN --mount=type=cache,sharing=locked,target=/go/pkg/mod \
CGO_ENABLED=1 GOFIPS140=latest GOARM="${TARGETVARIANT#v}" \ CGO_ENABLED=1 GOFIPS140=latest GOARM="${TARGETVARIANT#v}" \
go build -o /go/authentik ./cmd/server go build -o /go/authentik ./cmd/server
# Stage 3: MaxMind GeoIP # Stage 4: MaxMind GeoIP
FROM --platform=${BUILDPLATFORM} ghcr.io/maxmind/geoipupdate:v7.1.0 AS geoip FROM --platform=${BUILDPLATFORM} ghcr.io/maxmind/geoipupdate:v7.1.0 AS geoip
ENV GEOIPUPDATE_EDITION_IDS="GeoLite2-City GeoLite2-ASN" ENV GEOIPUPDATE_EDITION_IDS="GeoLite2-City GeoLite2-ASN"
@ -85,9 +93,9 @@ RUN --mount=type=secret,id=GEOIPUPDATE_ACCOUNT_ID \
mkdir -p /usr/share/GeoIP && \ mkdir -p /usr/share/GeoIP && \
/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" /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 # Stage 5: Download uv
FROM ghcr.io/astral-sh/uv:0.7.6 AS uv FROM ghcr.io/astral-sh/uv:0.7.5 AS uv
# Stage 5: Base python image # Stage 6: Base python image
FROM ghcr.io/goauthentik/fips-python:3.13.3-slim-bookworm-fips AS python-base FROM ghcr.io/goauthentik/fips-python:3.13.3-slim-bookworm-fips AS python-base
ENV VENV_PATH="/ak-root/.venv" \ ENV VENV_PATH="/ak-root/.venv" \
@ -101,7 +109,7 @@ WORKDIR /ak-root/
COPY --from=uv /uv /uvx /bin/ COPY --from=uv /uv /uvx /bin/
# Stage 6: Python dependencies # Stage 7: Python dependencies
FROM python-base AS python-deps FROM python-base AS python-deps
ARG TARGETARCH ARG TARGETARCH
@ -136,7 +144,7 @@ RUN --mount=type=bind,target=pyproject.toml,src=pyproject.toml \
--mount=type=cache,target=/root/.cache/uv \ --mount=type=cache,target=/root/.cache/uv \
uv sync --frozen --no-install-project --no-dev uv sync --frozen --no-install-project --no-dev
# Stage 7: Run # Stage 8: Run
FROM python-base AS final-image FROM python-base AS final-image
ARG VERSION ARG VERSION
@ -179,9 +187,9 @@ COPY ./lifecycle/ /lifecycle
COPY ./authentik/sources/kerberos/krb5.conf /etc/krb5.conf COPY ./authentik/sources/kerberos/krb5.conf /etc/krb5.conf
COPY --from=go-builder /go/authentik /bin/authentik COPY --from=go-builder /go/authentik /bin/authentik
COPY --from=python-deps /ak-root/.venv /ak-root/.venv COPY --from=python-deps /ak-root/.venv /ak-root/.venv
COPY --from=node-packages /work/web/dist/ /web/dist/ COPY --from=web-builder /work/web/dist/ /web/dist/
COPY --from=node-packages /work/web/authentik/ /web/authentik/ COPY --from=web-builder /work/web/authentik/ /web/authentik/
COPY --from=node-packages /work/website/build/ /website/help/ COPY --from=website-builder /work/website/build/ /website/help/
COPY --from=geoip /usr/share/GeoIP /geoip COPY --from=geoip /usr/share/GeoIP /geoip
USER 1000 USER 1000

View File

@ -73,7 +73,7 @@ core-i18n-extract:
--ignore website \ --ignore website \
-l en -l en
install: npm-install core-install ## Install all requires dependencies for `web`, `website` and `core` install: web-install website-install core-install ## Install all requires dependencies for `web`, `website` and `core`
dev-drop-db: dev-drop-db:
dropdb -U ${pg_user} -h ${pg_host} ${pg_name} dropdb -U ${pg_user} -h ${pg_host} ${pg_name}
@ -146,8 +146,9 @@ gen-client-ts: gen-clean-ts ## Build and install the authentik API for Typescri
--additional-properties=npmVersion=${NPM_VERSION} \ --additional-properties=npmVersion=${NPM_VERSION} \
--git-repo-id authentik \ --git-repo-id authentik \
--git-user-id goauthentik --git-user-id goauthentik
cd ./${GEN_API_TS} && npm link mkdir -p web/node_modules/@goauthentik/api
npm link @goauthentik/api -w @goauthentik/web cd ${PWD}/${GEN_API_TS} && npm i
\cp -rf ${PWD}/${GEN_API_TS}/* web/node_modules/@goauthentik/api
gen-client-py: gen-clean-py ## Build and install the authentik API for Python gen-client-py: gen-clean-py ## Build and install the authentik API for Python
docker run \ docker run \
@ -182,34 +183,38 @@ gen: gen-build gen-client-ts
## Web ## Web
######################### #########################
web-build: npm-install ## Build the Authentik UI web-build: web-install ## Build the Authentik UI
npm run build -w @goauthentik/web cd web && npm run build
web: web-lint-fix web-lint web-check-compile ## Automatically fix formatting issues in the Authentik UI source code, lint the code, and compile it web: web-lint-fix web-lint web-check-compile ## Automatically fix formatting issues in the Authentik UI source code, lint the code, and compile it
npm-install: ## Install the necessary libraries to build the Authentik UI web-install: ## Install the necessary libraries to build the Authentik UI
npm ci cd web && npm ci
web-test: ## Run tests for the Authentik UI web-test: ## Run tests for the Authentik UI
npm run test -w @goauthentik/web cd web && npm run test
web-watch: ## Build and watch the Authentik UI for changes, updating automatically web-watch: ## Build and watch the Authentik UI for changes, updating automatically
npm run watch -w @goauthentik/web rm -rf web/dist/
mkdir web/dist/
touch web/dist/.gitkeep
cd web && npm run watch
web-storybook-watch: ## Build and run the storybook documentation server web-storybook-watch: ## Build and run the storybook documentation server
npm run storybook -w @goauthentik/web cd web && npm run storybook
web-lint-fix: web-lint-fix:
npm run prettier -w @goauthentik/web cd web && npm run prettier
web-lint: web-lint:
npm run lint -w @goauthentik/web cd web && npm run lint
cd web && npm run lit-analyse
web-check-compile: web-check-compile:
npm run lint:types cd web && npm run tsc
web-i18n-extract: web-i18n-extract:
npm run extract-locales -w @goauthentik/web cd web && npm run extract-locales
######################### #########################
## Website ## Website
@ -217,14 +222,17 @@ web-i18n-extract:
website: website-lint-fix website-build ## Automatically fix formatting issues in the Authentik website/docs source code, lint the code, and compile it website: website-lint-fix website-build ## Automatically fix formatting issues in the Authentik website/docs source code, lint the code, and compile it
website-install:
cd website && npm ci
website-lint-fix: lint-codespell website-lint-fix: lint-codespell
npm run prettier --prefix website cd website && npm run prettier
website-build: website-build:
npm run build --prefix website cd website && npm run build
website-watch: ## Build and watch the documentation website, updating automatically website-watch: ## Build and watch the documentation website, updating automatically
npm run watch --prefix website cd website && npm run watch
######################### #########################
## Docker ## Docker

View File

@ -3,14 +3,7 @@ from urllib.parse import unquote_plus
from cryptography.exceptions import InvalidSignature from cryptography.exceptions import InvalidSignature
from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives import hashes
from cryptography.x509 import ( from cryptography.x509 import Certificate, NameOID, ObjectIdentifier, load_pem_x509_certificate
Certificate,
NameOID,
ObjectIdentifier,
UnsupportedGeneralNameType,
load_pem_x509_certificate,
)
from cryptography.x509.verification import PolicyBuilder, Store, VerificationError
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from authentik.brands.models import Brand from authentik.brands.models import Brand
@ -109,22 +102,16 @@ class MTLSStageView(ChallengeStageView):
return None return None
def validate_cert(self, authorities: list[CertificateKeyPair], certs: list[Certificate]): def validate_cert(self, authorities: list[CertificateKeyPair], certs: list[Certificate]):
authorities_cert = [x.certificate for x in authorities]
for _cert in certs: for _cert in certs:
try: for ca in authorities:
PolicyBuilder().store(Store(authorities_cert)).build_client_verifier().verify( try:
_cert, [] _cert.verify_directly_issued_by(ca.certificate)
) return _cert
return _cert except (InvalidSignature, TypeError, ValueError) as exc:
except ( self.logger.warning(
InvalidSignature, "Discarding cert not issued by authority", cert=_cert, authority=ca, exc=exc
TypeError, )
ValueError, continue
VerificationError,
UnsupportedGeneralNameType,
) as exc:
self.logger.warning("Discarding invalid certificate", cert=_cert, exc=exc)
continue
return None return None
def check_if_user(self, cert: Certificate): def check_if_user(self, cert: Certificate):
@ -154,9 +141,7 @@ class MTLSStageView(ChallengeStageView):
"subject": cert.subject.rfc4514_string(), "subject": cert.subject.rfc4514_string(),
"issuer": cert.issuer.rfc4514_string(), "issuer": cert.issuer.rfc4514_string(),
"fingerprint_sha256": hexlify(cert.fingerprint(hashes.SHA256()), ":").decode("utf-8"), "fingerprint_sha256": hexlify(cert.fingerprint(hashes.SHA256()), ":").decode("utf-8"),
"fingerprint_sha1": hexlify(cert.fingerprint(hashes.SHA1()), ":").decode( # nosec "fingerprint_sha1": hexlify(cert.fingerprint(hashes.SHA256()), ":").decode("utf-8"),
"utf-8"
),
} }
def auth_user(self, user: User, cert: Certificate): def auth_user(self, user: User, cert: Certificate):

View File

@ -1,31 +1,30 @@
-----BEGIN CERTIFICATE----- -----BEGIN CERTIFICATE-----
MIIFWTCCA0GgAwIBAgIUDEnKCSmIXG/akySGes7bhOGrN/8wDQYJKoZIhvcNAQEL MIIFOzCCAyOgAwIBAgIUbnIMy+Ewi5RvK7OBDxWMCk7wi08wDQYJKoZIhvcNAQEL
BQAwRjEaMBgGA1UEAwwRYXV0aGVudGlrIFRlc3QgQ0ExEjAQBgNVBAoMCWF1dGhl BQAwRjEaMBgGA1UEAwwRYXV0aGVudGlrIFRlc3QgQ0ExEjAQBgNVBAoMCWF1dGhl
bnRpazEUMBIGA1UECwwLU2VsZi1zaWduZWQwHhcNMjUwNTE5MTIzODQ2WhcNMjYw bnRpazEUMBIGA1UECwwLU2VsZi1zaWduZWQwHhcNMjUwNDI3MTgzMTE3WhcNMjYw
NTE1MTIzODQ2WjARMQ8wDQYDVQQDDAZjbGllbnQwggIiMA0GCSqGSIb3DQEBAQUA NDIzMTgzMTE3WjARMQ8wDQYDVQQDDAZjbGllbnQwggIiMA0GCSqGSIb3DQEBAQUA
A4ICDwAwggIKAoICAQCkPkS1V6l0gj0ulxMznkxkgrw4p9Tjd8teSsGZt02A2Eo6 A4ICDwAwggIKAoICAQCdV+GEa7+7ito1i/z637OZW+0azv1kuF2aDwSzv+FJd+4L
7D8FbJ7pp3d5fYW/TWuEKVBLWTID6rijW5EGcdgTM5Jxf/QR+aZTEK6umQxUd4yO 6hCroRbVYTUFS3I3YwanOOZfau64xH0+pFM5Js8aREG68eqKBayx8vT27hyAOFhd
mOtp+xVS3KlcsSej2dFpeE5h5VkZizHpvh5xkoAP8W5VtQLOVF0hIeumHnJmaeLj giEVmSQJfla4ogvPie1rJ0HVOL7CiR72HDPQvz+9k1iDX3xQ/4sdAb3XurN13e+M
+mhK9PBFpO7k9SFrYYhd/uLrYbIdANihbIO2Q74rNEJHewhFNM7oNSjjEWzRd/7S Gtavhjiyqxmoo/H4WRd8BhD/BZQFWtaxWODDY8aKk5R7omw6Xf7aRv1BlHdE4Ucy
qNdQij9JGrVG7u8YJJscEQHqyHMYFVCEMjxmsge5BO6Vx5OWmUE3wXPzb5TbyTS4 Wozvpsj2Kz0l61rRUhiMlE0D9dpijgaRYFB+M7R2casH3CdhGQbBHTRiqBkZa6iq
+yg88g9rYTUXrzz+poCyKpaur45qBsdw35lJ8nq69VJj2xJLGQDwoTgGSXRuPciC SDkTiTwNJQQJov8yPTsR+9P8OOuV6QN+DGm/FXJJFaPnsHw/HDy7EAbA1PcdbSyK
3OilQI+Ma+j8qQGJxJ8WJxISlf1cuhp+V4ZUd1lawlM5hAXyXmHRlH4pun4y+g7O XvJ8nVjdNhCEGbLGVSwAQLO+78hChVIN5YH+QSrP84YBSxKZYArnf4z2e9drqAN3
O34+fE3pK25JjVCicMT/rC2A/sb95j/fHTzzJpbB70U0I50maTcIsOkyw6aiF//E KmC26TkaUzkXnndnxOXBEIOSmyCdD4Dutg1XPE/bs8rA6rVGIR3pKXbCr29Z8hZn
0ShTDz14x22SCMolUc6hxTDZvBB6yrcJHd7d9CCnFH2Sgo13QrtNJ/atXgm13HGh Cn9jbxwDwTX865ljR1Oc3dnIeCWa9AS/uHaSMdGlbGbDrt4Bj/nyyfu8xc034K/0
wBzRwK38XUGl/J4pJaxAupTVCPriStUM3m0EYHNelRRUE91pbyeGT0rvOuv00uLw uPh3hF3FLWNAomRVZCvtuh/v7IEIQEgUbvQMWBhZJ8hu3HdtV8V9TIAryVKzEzGy
Rj7K7hJZR8avTKWmKrVBVpq+gSojGW1DwBS0NiDNkZs0d/IjB1wkzczEgdZjXwID Q72UHuQyK0njRDTmA/T+jn7P8GWOuf9eNdzd0gH0gcEuhCZFxPPRvUAeDuC7DQID
AQABo3QwcjAfBgNVHSMEGDAWgBTa+Ns6QzqlNvnTGszkouQQtZnVJDAdBgNVHSUE AQABo1YwVDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwFAYDVR0RAQH/
FjAUBggrBgEFBQcDAgYIKwYBBQUHAwEwEQYDVR0RBAowCIIGY2xpZW50MB0GA1Ud BAowCIIGY2xpZW50MB0GA1UdDgQWBBQ5KZwTD8+4CqLnbM/cBSXg8XeLXTANBgkq
DgQWBBT1xg5sXkypRBwvCxBuyfoanaiZ5jANBgkqhkiG9w0BAQsFAAOCAgEAvUAz hkiG9w0BAQsFAAOCAgEABDkb3iyEOl1xKq1wxyRzf2L8qfPXAQw71FxMbgHArM+a
YwIjxY/0KHZDU8owdILVqKChzfLcy9OHNPyEI3TSOI8X6gNtBO+HE6r8aWGcC9vw e44wJGO3mZgPH0trOaJ+tuN6erB5YbZfsoX+xFacwskj9pKyb4QJLr/ENmJZRgyL
zzeIsNQ3UEjvRWi2r+vUVbiPTbFdZboNDSZv6ZmGHxwd85VsjXRGoXV6koCT/9zi wp5P6PB6IUJhvryvy/GxrG938YGmFtYQ+ikeJw5PWhB6218C1aZ9hsi94wZ1Zzrc
9/lCM1DwqwYSwBphMJdRVFRUMluSYk1oHflGeA18xgGuts4eFivJwhabGm1AdVVQ Ry0q0D4QvIEZ0X2HL1Harc7gerE3VqhgQ7EWyImM+lCRtNDduwDQnZauwhr2r6cW
/CYvqCuTxd/DCzWZBdyxYpDru64i/kyeJCt1pThKEFDWmpumFdBI4CxJ0OhxVSGp XG4VTe1RCNsDA0xinXQE2Xf9voCd0Zf6wOOXJseQtrXpf+tG4N13cy5heF5ihed1
dOXzK+Y6ULepxCvi6/OpSog52jQ6PnNd1ghiYtq7yO1T4GQz65M1vtHHVvQ3gfBE hDxSeki0KjTM+18kVVfVm4fzxf1Zg0gm54UlzWceIWh9EtnWMUV08H0D1M9YNmW8
AuKYQp6io7ypitRx+LpjsBQenyP4FFGfrq7pm90nLluOBOArfSdF0N+CP2wo/YFV hWTupk7M+jAw8Y+suHOe6/RLi0+fb9NSJpIpq4GqJ5UF2kerXHX0SvuAavoXyB0j
9BGf89OtvRi3BXCm2NXkE/Sc4We26tY8x7xNLOmNs8YOT0O3r/EQ690W9GIwRMx0 CQrUXkRScEKOO2KAbVExSG56Ff7Ee8cRUAQ6rLC5pQRACq/R0sa6RcUsFPXul3Yv
m0r/RXWn5V3o4Jib9r8eH9NzaDstD8g9dECcGfM4fHoM/DAGFaRrNcjMsS1APP3L vbO2rTuArAUPkNVFknwkndheN4lOslRd1If02HunZETmsnal6p+nmuMWt2pQ2fDA
jp7+BfBSXtrz9V6rVJ3CBLXlLK0AuSm7bqd1MJsGA9uMLpsVZIUA+KawcmPGdPU+ vIguG54FyQ1T1IbF/QhfTEY62CQAebcgutnqqJHt9qe7Jr6ev57hMrJDEjotSzkY
NxdpBCtzyurQSUyaTLtVqSeP35gMAwaNzUDph8Uh+vHz+kRwgXS19OQvTaud5LJu OhOVrcYqgLldr1nBqNVlIK/4VrDaWH8H5dNJ72gA9aMNVH4/bSTJhuO7cJkLnHw=
nQe4JNS+u5e2VDEBWUxt8NTpu6eShDN0iIEHtxA=
-----END CERTIFICATE----- -----END CERTIFICATE-----

View File

@ -5,12 +5,7 @@ from django.urls import reverse
from guardian.shortcuts import assign_perm from guardian.shortcuts import assign_perm
from authentik.core.models import User from authentik.core.models import User
from authentik.core.tests.utils import ( from authentik.core.tests.utils import create_test_brand, create_test_flow, create_test_user
create_test_brand,
create_test_cert,
create_test_flow,
create_test_user,
)
from authentik.crypto.models import CertificateKeyPair from authentik.crypto.models import CertificateKeyPair
from authentik.enterprise.stages.mtls.models import ( from authentik.enterprise.stages.mtls.models import (
CertAttributes, CertAttributes,
@ -132,18 +127,6 @@ class MTLSStageTests(FlowTestCase):
self.assertEqual(res.status_code, 200) self.assertEqual(res.status_code, 200)
self.assertStageResponse(res, self.flow, component="ak-stage-access-denied") self.assertStageResponse(res, self.flow, component="ak-stage-access-denied")
def test_invalid_cert(self):
"""Test invalid certificate"""
cert = create_test_cert()
with self.assertFlowFinishes() as plan:
res = self.client.get(
reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug}),
headers={"X-Forwarded-TLS-Client-Cert": quote_plus(cert.certificate_data)},
)
self.assertEqual(res.status_code, 200)
self.assertStageResponse(res, self.flow, component="ak-stage-access-denied")
self.assertNotIn(PLAN_CONTEXT_PENDING_USER, plan().context)
def test_auth_no_user(self): def test_auth_no_user(self):
"""Test auth with no user""" """Test auth with no user"""
User.objects.filter(username="client").delete() User.objects.filter(username="client").delete()
@ -217,12 +200,14 @@ class MTLSStageTests(FlowTestCase):
self.assertEqual( self.assertEqual(
plan().context[PLAN_CONTEXT_CERTIFICATE], plan().context[PLAN_CONTEXT_CERTIFICATE],
{ {
"fingerprint_sha1": "52:39:ca:1e:3a:1f:78:3a:9f:26:3b:c2:84:99:48:68:99:99:81:8a", "fingerprint_sha1": (
"08:d4:a4:79:25:ca:c3:51:28:88:bb:30:c2:96:c3:44:5a:eb:18:07:84:ca:b4:75:27:74:61:19:8a:6a:af:fc"
),
"fingerprint_sha256": ( "fingerprint_sha256": (
"c1:07:8b:7c:e9:02:57:87:1e:92:e5:81:83:21:bc:92:c7:47:65:e3:97:fb:05:97:6f:36:9e:b5:31:77:98:b7" "08:d4:a4:79:25:ca:c3:51:28:88:bb:30:c2:96:c3:44:5a:eb:18:07:84:ca:b4:75:27:74:61:19:8a:6a:af:fc"
), ),
"issuer": "OU=Self-signed,O=authentik,CN=authentik Test CA", "issuer": "OU=Self-signed,O=authentik,CN=authentik Test CA",
"serial_number": "70153443448884702681996102271549704759327537151", "serial_number": "630532384467334865093173111400266136879266564943",
"subject": "CN=client", "subject": "CN=client",
}, },
) )

View File

@ -1,11 +1,9 @@
"""Websocket tests""" """Websocket tests"""
from dataclasses import asdict from dataclasses import asdict
from unittest.mock import patch
from channels.routing import URLRouter from channels.routing import URLRouter
from channels.testing import WebsocketCommunicator from channels.testing import WebsocketCommunicator
from django.contrib.contenttypes.models import ContentType
from django.test import TransactionTestCase from django.test import TransactionTestCase
from authentik import __version__ from authentik import __version__
@ -16,12 +14,6 @@ from authentik.providers.proxy.models import ProxyProvider
from authentik.root import websocket from authentik.root import websocket
def patched__get_ct_cached(app_label, codename):
"""Caches `ContentType` instances like its `QuerySet` does."""
return ContentType.objects.get(app_label=app_label, permission__codename=codename)
@patch("guardian.shortcuts._get_ct_cached", patched__get_ct_cached)
class TestOutpostWS(TransactionTestCase): class TestOutpostWS(TransactionTestCase):
"""Websocket tests""" """Websocket tests"""
@ -46,7 +38,6 @@ class TestOutpostWS(TransactionTestCase):
) )
connected, _ = await communicator.connect() connected, _ = await communicator.connect()
self.assertFalse(connected) self.assertFalse(connected)
await communicator.disconnect()
async def test_auth_valid(self): async def test_auth_valid(self):
"""Test auth with token""" """Test auth with token"""
@ -57,7 +48,6 @@ class TestOutpostWS(TransactionTestCase):
) )
connected, _ = await communicator.connect() connected, _ = await communicator.connect()
self.assertTrue(connected) self.assertTrue(connected)
await communicator.disconnect()
async def test_send(self): async def test_send(self):
"""Test sending of Hello""" """Test sending of Hello"""

View File

@ -7,8 +7,10 @@ from django.db import migrations
def migrate_search_group(apps: Apps, schema_editor: BaseDatabaseSchemaEditor): def migrate_search_group(apps: Apps, schema_editor: BaseDatabaseSchemaEditor):
from authentik.core.models import User
from django.apps import apps as real_apps from django.apps import apps as real_apps
from django.contrib.auth.management import create_permissions from django.contrib.auth.management import create_permissions
from guardian.shortcuts import UserObjectPermission
db_alias = schema_editor.connection.alias db_alias = schema_editor.connection.alias

View File

@ -50,4 +50,3 @@ AMR_PASSWORD = "pwd" # nosec
AMR_MFA = "mfa" AMR_MFA = "mfa"
AMR_OTP = "otp" AMR_OTP = "otp"
AMR_WEBAUTHN = "user" AMR_WEBAUTHN = "user"
AMR_SMART_CARD = "sc"

View File

@ -16,7 +16,6 @@ from authentik.providers.oauth2.constants import (
ACR_AUTHENTIK_DEFAULT, ACR_AUTHENTIK_DEFAULT,
AMR_MFA, AMR_MFA,
AMR_PASSWORD, AMR_PASSWORD,
AMR_SMART_CARD,
AMR_WEBAUTHN, AMR_WEBAUTHN,
) )
from authentik.stages.password.stage import PLAN_CONTEXT_METHOD, PLAN_CONTEXT_METHOD_ARGS from authentik.stages.password.stage import PLAN_CONTEXT_METHOD, PLAN_CONTEXT_METHOD_ARGS
@ -140,10 +139,9 @@ class IDToken:
amr.append(AMR_PASSWORD) amr.append(AMR_PASSWORD)
if method == "auth_webauthn_pwl": if method == "auth_webauthn_pwl":
amr.append(AMR_WEBAUTHN) amr.append(AMR_WEBAUTHN)
if "certificate" in method_args:
amr.append(AMR_SMART_CARD)
if "mfa_devices" in method_args: if "mfa_devices" in method_args:
amr.append(AMR_MFA) if len(amr) > 0:
amr.append(AMR_MFA)
if amr: if amr:
id_token.amr = amr id_token.amr = amr

View File

@ -47,8 +47,6 @@ class IngressReconciler(KubernetesObjectReconciler[V1Ingress]):
def reconcile(self, current: V1Ingress, reference: V1Ingress): def reconcile(self, current: V1Ingress, reference: V1Ingress):
super().reconcile(current, reference) super().reconcile(current, reference)
self._check_annotations(current, reference) self._check_annotations(current, reference)
if current.spec.ingress_class_name != reference.spec.ingress_class_name:
raise NeedsUpdate()
# Create a list of all expected host and tls hosts # Create a list of all expected host and tls hosts
expected_hosts = [] expected_hosts = []
expected_hosts_tls = [] expected_hosts_tls = []

View File

@ -132,7 +132,7 @@ TENANT_CREATION_FAKES_MIGRATIONS = True
TENANT_BASE_SCHEMA = "template" TENANT_BASE_SCHEMA = "template"
PUBLIC_SCHEMA_NAME = CONFIG.get("postgresql.default_schema") PUBLIC_SCHEMA_NAME = CONFIG.get("postgresql.default_schema")
GUARDIAN_MONKEY_PATCH_USER = False GUARDIAN_MONKEY_PATCH = False
SPECTACULAR_SETTINGS = { SPECTACULAR_SETTINGS = {
"TITLE": "authentik", "TITLE": "authentik",

View File

@ -1,10 +0,0 @@
import { createESLintPackageConfig } from "@goauthentik/eslint-config";
// @ts-check
/**
* ESLint configuration for authentik's monorepo.
*/
const ESLintConfig = createESLintPackageConfig();
export default ESLintConfig;

View File

@ -83,8 +83,7 @@ if [[ "$1" == "server" ]]; then
run_authentik run_authentik
elif [[ "$1" == "worker" ]]; then elif [[ "$1" == "worker" ]]; then
set_mode "worker" set_mode "worker"
shift check_if_root "python -m manage worker"
check_if_root "python -m manage worker $@"
elif [[ "$1" == "worker-status" ]]; then elif [[ "$1" == "worker-status" ]]; then
wait_for_db wait_for_db
celery -A authentik.root.celery flower \ celery -A authentik.root.celery flower \

View File

@ -9,7 +9,7 @@
"version": "0.0.0", "version": "0.0.0",
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"aws-cdk": "^2.1016.1", "aws-cdk": "^2.1016.0",
"cross-env": "^7.0.3" "cross-env": "^7.0.3"
}, },
"engines": { "engines": {
@ -17,9 +17,9 @@
} }
}, },
"node_modules/aws-cdk": { "node_modules/aws-cdk": {
"version": "2.1016.1", "version": "2.1016.0",
"resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1016.1.tgz", "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1016.0.tgz",
"integrity": "sha512-248TBiluT8jHUjkpzvWJOHv2fS+An9fiII3eji8H7jwfTu5yMBk7on4B/AVNr9A1GXJk9I32qf9Q0A3rLWRYPQ==", "integrity": "sha512-zdJ/tQp0iE/s8l8zLQPgdUJUHpS6KblkzdP5nOYC/NbD5OCdhS8QS7vLBkT8M7mNyZh3Ep3C+/m6NsxrurRe0A==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"bin": { "bin": {

View File

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

View File

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-05-20 00:10+0000\n" "POT-Creation-Date: 2025-04-23 09:00+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -93,10 +93,6 @@ msgstr ""
msgid "Web Certificate used by the authentik Core webserver." msgid "Web Certificate used by the authentik Core webserver."
msgstr "" msgstr ""
#: authentik/brands/models.py
msgid "Certificates used for client authentication."
msgstr ""
#: authentik/brands/models.py #: authentik/brands/models.py
msgid "Brand" msgid "Brand"
msgstr "" msgstr ""
@ -620,32 +616,6 @@ msgstr ""
msgid "Verifying your browser..." msgid "Verifying your browser..."
msgstr "" msgstr ""
#: authentik/enterprise/stages/mtls/models.py
msgid ""
"Configure certificate authorities to validate the certificate against. This "
"option has a higher priority than the `client_certificate` option on `Brand`."
msgstr ""
#: authentik/enterprise/stages/mtls/models.py
msgid "Mutual TLS Stage"
msgstr ""
#: authentik/enterprise/stages/mtls/models.py
msgid "Mutual TLS Stages"
msgstr ""
#: authentik/enterprise/stages/mtls/models.py
msgid "Permissions to pass Certificates for outposts."
msgstr ""
#: authentik/enterprise/stages/mtls/stage.py
msgid "Certificate required but no certificate was given."
msgstr ""
#: authentik/enterprise/stages/mtls/stage.py
msgid "No user found for certificate."
msgstr ""
#: authentik/enterprise/stages/source/models.py #: authentik/enterprise/stages/source/models.py
msgid "" msgid ""
"Amount of time a user can take to return from the source to continue the " "Amount of time a user can take to return from the source to continue the "

View File

@ -19,7 +19,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-05-20 00:10+0000\n" "POT-Creation-Date: 2025-04-23 09:00+0000\n"
"PO-Revision-Date: 2022-09-26 16:47+0000\n" "PO-Revision-Date: 2022-09-26 16:47+0000\n"
"Last-Translator: Marc Schmitt, 2025\n" "Last-Translator: Marc Schmitt, 2025\n"
"Language-Team: French (https://app.transifex.com/authentik/teams/119923/fr/)\n" "Language-Team: French (https://app.transifex.com/authentik/teams/119923/fr/)\n"
@ -113,10 +113,6 @@ msgstr ""
msgid "Web Certificate used by the authentik Core webserver." msgid "Web Certificate used by the authentik Core webserver."
msgstr "Certificate Web utilisé par le serveur web d'authentik core." msgstr "Certificate Web utilisé par le serveur web d'authentik core."
#: authentik/brands/models.py
msgid "Certificates used for client authentication."
msgstr "Certificats utilisés pour l'authentification client."
#: authentik/brands/models.py #: authentik/brands/models.py
msgid "Brand" msgid "Brand"
msgstr "Marque" msgstr "Marque"
@ -679,36 +675,6 @@ msgstr "Appareils point de terminaison"
msgid "Verifying your browser..." msgid "Verifying your browser..."
msgstr "Vérification de votre navigateur..." msgstr "Vérification de votre navigateur..."
#: authentik/enterprise/stages/mtls/models.py
msgid ""
"Configure certificate authorities to validate the certificate against. This "
"option has a higher priority than the `client_certificate` option on "
"`Brand`."
msgstr ""
"Configurez les autorités de certification pour valider le certificat. Cette "
"option a une priorité plus élevée que l'option `client_certificate` sur "
"`Marques`."
#: authentik/enterprise/stages/mtls/models.py
msgid "Mutual TLS Stage"
msgstr "Étape TLS mutuel"
#: authentik/enterprise/stages/mtls/models.py
msgid "Mutual TLS Stages"
msgstr "Étapes TLS mutuel"
#: authentik/enterprise/stages/mtls/models.py
msgid "Permissions to pass Certificates for outposts."
msgstr "Autorisations de délivrer des certificats pour les avant-postes."
#: authentik/enterprise/stages/mtls/stage.py
msgid "Certificate required but no certificate was given."
msgstr "Certificat requis mais aucun certificat n'a été fourni."
#: authentik/enterprise/stages/mtls/stage.py
msgid "No user found for certificate."
msgstr "Aucun utilisateur trouvé pour le certificat."
#: authentik/enterprise/stages/source/models.py #: authentik/enterprise/stages/source/models.py
msgid "" msgid ""
"Amount of time a user can take to return from the source to continue the " "Amount of time a user can take to return from the source to continue the "

View File

@ -15,7 +15,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-05-20 00:10+0000\n" "POT-Creation-Date: 2025-04-23 09:00+0000\n"
"PO-Revision-Date: 2022-09-26 16:47+0000\n" "PO-Revision-Date: 2022-09-26 16:47+0000\n"
"Last-Translator: deluxghost, 2025\n" "Last-Translator: deluxghost, 2025\n"
"Language-Team: Chinese Simplified (https://app.transifex.com/authentik/teams/119923/zh-Hans/)\n" "Language-Team: Chinese Simplified (https://app.transifex.com/authentik/teams/119923/zh-Hans/)\n"
@ -102,10 +102,6 @@ msgstr "设置时,外部用户在验证身份后会被重定向到此应用程
msgid "Web Certificate used by the authentik Core webserver." msgid "Web Certificate used by the authentik Core webserver."
msgstr "authentik 核心 Web 服务器使用的 Web 证书。" msgstr "authentik 核心 Web 服务器使用的 Web 证书。"
#: authentik/brands/models.py
msgid "Certificates used for client authentication."
msgstr "用于客户端身份验证的证书"
#: authentik/brands/models.py #: authentik/brands/models.py
msgid "Brand" msgid "Brand"
msgstr "品牌" msgstr "品牌"
@ -630,33 +626,6 @@ msgstr "端点设备"
msgid "Verifying your browser..." msgid "Verifying your browser..."
msgstr "正在验证您的浏览器…" msgstr "正在验证您的浏览器…"
#: authentik/enterprise/stages/mtls/models.py
msgid ""
"Configure certificate authorities to validate the certificate against. This "
"option has a higher priority than the `client_certificate` option on "
"`Brand`."
msgstr "配置用于验证证书的证书机构。此选项的优先级比“品牌”中的“客户端证书”更高。"
#: authentik/enterprise/stages/mtls/models.py
msgid "Mutual TLS Stage"
msgstr "双向 TLS 阶段"
#: authentik/enterprise/stages/mtls/models.py
msgid "Mutual TLS Stages"
msgstr "双向 TLS 阶段"
#: authentik/enterprise/stages/mtls/models.py
msgid "Permissions to pass Certificates for outposts."
msgstr "为前哨传递证书的权限。"
#: authentik/enterprise/stages/mtls/stage.py
msgid "Certificate required but no certificate was given."
msgstr "需要证书但未提供。"
#: authentik/enterprise/stages/mtls/stage.py
msgid "No user found for certificate."
msgstr "未找到证书的用户。"
#: authentik/enterprise/stages/source/models.py #: authentik/enterprise/stages/source/models.py
msgid "" msgid ""
"Amount of time a user can take to return from the source to continue the " "Amount of time a user can take to return from the source to continue the "

View File

@ -14,7 +14,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-05-20 00:10+0000\n" "POT-Creation-Date: 2025-04-23 09:00+0000\n"
"PO-Revision-Date: 2022-09-26 16:47+0000\n" "PO-Revision-Date: 2022-09-26 16:47+0000\n"
"Last-Translator: deluxghost, 2025\n" "Last-Translator: deluxghost, 2025\n"
"Language-Team: Chinese (China) (https://app.transifex.com/authentik/teams/119923/zh_CN/)\n" "Language-Team: Chinese (China) (https://app.transifex.com/authentik/teams/119923/zh_CN/)\n"
@ -101,10 +101,6 @@ msgstr "设置时,外部用户在验证身份后会被重定向到此应用程
msgid "Web Certificate used by the authentik Core webserver." msgid "Web Certificate used by the authentik Core webserver."
msgstr "authentik 核心 Web 服务器使用的 Web 证书。" msgstr "authentik 核心 Web 服务器使用的 Web 证书。"
#: authentik/brands/models.py
msgid "Certificates used for client authentication."
msgstr "用于客户端身份验证的证书"
#: authentik/brands/models.py #: authentik/brands/models.py
msgid "Brand" msgid "Brand"
msgstr "品牌" msgstr "品牌"
@ -629,33 +625,6 @@ msgstr "端点设备"
msgid "Verifying your browser..." msgid "Verifying your browser..."
msgstr "正在验证您的浏览器…" msgstr "正在验证您的浏览器…"
#: authentik/enterprise/stages/mtls/models.py
msgid ""
"Configure certificate authorities to validate the certificate against. This "
"option has a higher priority than the `client_certificate` option on "
"`Brand`."
msgstr "配置用于验证证书的证书机构。此选项的优先级比“品牌”中的“客户端证书”更高。"
#: authentik/enterprise/stages/mtls/models.py
msgid "Mutual TLS Stage"
msgstr "双向 TLS 阶段"
#: authentik/enterprise/stages/mtls/models.py
msgid "Mutual TLS Stages"
msgstr "双向 TLS 阶段"
#: authentik/enterprise/stages/mtls/models.py
msgid "Permissions to pass Certificates for outposts."
msgstr "为前哨传递证书的权限。"
#: authentik/enterprise/stages/mtls/stage.py
msgid "Certificate required but no certificate was given."
msgstr "需要证书但未提供。"
#: authentik/enterprise/stages/mtls/stage.py
msgid "No user found for certificate."
msgstr "未找到证书的用户。"
#: authentik/enterprise/stages/source/models.py #: authentik/enterprise/stages/source/models.py
msgid "" msgid ""
"Amount of time a user can take to return from the source to continue the " "Amount of time a user can take to return from the source to continue the "

44357
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -2,33 +2,14 @@
"name": "@goauthentik/authentik", "name": "@goauthentik/authentik",
"version": "2025.4.1", "version": "2025.4.1",
"private": true, "private": true,
"scripts": {
"lint": "eslint --fix .",
"lint-check": "eslint --max-warnings 0 .",
"lint:types": "NODE_OPTIONS=\"--max-old-space-size=3000\" tsc -b .",
"prettier": "prettier --cache --write -u .",
"prettier-check": "prettier --cache --check -u ."
},
"type": "module", "type": "module",
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.11.1",
"@trivago/prettier-plugin-sort-imports": "^5.2.2", "@trivago/prettier-plugin-sort-imports": "^5.2.2",
"@typescript-eslint/eslint-plugin": "^8.28.0", "prettier": "^3.3.3",
"@typescript-eslint/parser": "^8.28.0", "prettier-plugin-organize-imports": "^4.1.0",
"eslint": "^9.23.0", "prettier-plugin-packagejson": "^2.5.10",
"eslint-plugin-lit": "^2.0.0", "typescript": "^5.6.2"
"eslint-plugin-wc": "^3.0.0",
"npm-run-all": "^4.1.5",
"prettier": "^3.5.3",
"prettier-plugin-packagejson": "^2.5.13",
"typescript": "^5.8.3",
"typescript-eslint": "^8.29.0"
}, },
"workspaces": [ "workspaces": [],
"./packages/*",
"./web/packages/*",
"./web",
"./website"
],
"prettier": "./packages/prettier-config/index.js" "prettier": "./packages/prettier-config/index.js"
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"name": "@goauthentik/docusaurus-config", "name": "@goauthentik/docusaurus-config",
"version": "1.1.0", "version": "1.0.6",
"description": "authentik's Docusaurus config", "description": "authentik's Docusaurus config",
"license": "MIT", "license": "MIT",
"scripts": { "scripts": {
@ -20,24 +20,23 @@
"prism-react-renderer": "^2.4.1" "prism-react-renderer": "^2.4.1"
}, },
"devDependencies": { "devDependencies": {
"@docusaurus/core": "^3.7.0",
"@docusaurus/preset-classic": "^3.7.0",
"@docusaurus/theme-common": "^3.7.0", "@docusaurus/theme-common": "^3.7.0",
"@docusaurus/theme-search-algolia": "^3.7.0", "@docusaurus/theme-mermaid": "^3.7.0",
"@docusaurus/types": "^3.7.0",
"@goauthentik/prettier-config": "^1.0.1", "@goauthentik/prettier-config": "^1.0.1",
"@goauthentik/tsconfig": "^1.0.1", "@goauthentik/tsconfig": "^1.0.1",
"@types/react": "^19.1.5", "react": "^18.3.1",
"@types/react-dom": "^19.1.5", "react-dom": "^18.3.1",
"prettier": "^3.5.3", "typescript": "^5.8.2"
"react": "^19.1.0",
"react-dom": "^19.1.0",
"typescript": "^5.8.3"
}, },
"peerDependencies": { "peerDependencies": {
"@docusaurus/core": "^3.7.0",
"@docusaurus/preset-classic": "^3.7.0",
"@docusaurus/theme-common": "^3.7.0", "@docusaurus/theme-common": "^3.7.0",
"@docusaurus/theme-search-algolia": "^3.7.0", "@docusaurus/theme-mermaid": "^3.7.0",
"@docusaurus/types": "^3.7.0", "react": "^18.0.0",
"react": "^18.0.0 || ^19.0.0", "react-dom": "^18.0.0"
"react-dom": "^18.0.0 || ^19.0.0"
}, },
"engines": { "engines": {
"node": ">=20.11" "node": ">=20.11"
@ -50,11 +49,6 @@
"out/**/*" "out/**/*"
], ],
"prettier": "@goauthentik/prettier-config", "prettier": "@goauthentik/prettier-config",
"peerDependenciesMeta": {
"@docusaurus/theme-search-algolia": {
"optional": true
}
},
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
} }

View File

@ -23,7 +23,6 @@ export const DefaultIgnorePatterns = [
"**/out", "**/out",
"**/dist", "**/dist",
"**/.wireit", "**/.wireit",
"**/.venv",
"website/build/**", "website/build/**",
"website/.docusaurus/**", "website/.docusaurus/**",
"**/node_modules", "**/node_modules",
@ -59,44 +58,16 @@ export function createESLintPackageConfig({ ignorePatterns = DefaultIgnorePatter
...reactConfig, ...reactConfig,
//#region TODO Incomplete Rules
{ {
// The following rules are disabled because the changes needed to satisfy them are
// are large enough to warrant several follow-up PRs.
rules: { rules: {
// TODO: High priority, common and easy to fix. "no-console": "off",
"eqeqeq": "off",
// TODO: High priority, common and easy to fix.
"no-sparse-arrays": "off",
// TODO: High priority, common and easy to fix.
"no-lonely-if": "off",
// TODO: Reconsider this rule.
"dot-notation": "off",
// TODO: Reconsider this rule.
"no-implicit-coercion": "off",
// TODO: Reconsider this rule.
"prefer-template": "off",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/no-unused-vars": "off",
"@typescript-eslint/no-use-before-define": "off",
"array-callback-return": "off",
"block-scoped-var": "off",
"consistent-return": "off",
"func-names": "off",
"guard-for-in": "off",
"no-bitwise": "off",
"no-div-regex": "off",
"no-else-return": "off",
"no-empty-function": "off",
"no-param-reassign": "off",
"no-throw-literal": "off",
"no-var": "error",
"prefer-arrow-callback": "off",
"react/jsx-no-leaked-render": "off",
"vars-on-top": "off",
}, },
files: [
// ---
"**/scripts/**/*",
"**/test/**/*",
"**/tests/**/*",
],
}, },
//#endregion
); );
} }

View File

@ -116,6 +116,7 @@ export const javaScriptConfig = tseslint.config({
"no-useless-call": "error", "no-useless-call": "error",
"no-dupe-class-members": "error", "no-dupe-class-members": "error",
"no-var": "error", "no-var": "error",
"no-void": "error",
"no-with": "error", "no-with": "error",
"prefer-arrow-callback": "error", "prefer-arrow-callback": "error",
"prefer-const": "error", "prefer-const": "error",
@ -130,6 +131,7 @@ export const javaScriptConfig = tseslint.config({
"vars-on-top": "error", "vars-on-top": "error",
"yoda": ["error", "never"], "yoda": ["error", "never"],
"no-console": ["error", { allow: ["debug", "warn", "error"] }],
// SonarJS is not yet compatible with ESLint 9. Commenting these out // SonarJS is not yet compatible with ESLint 9. Commenting these out
// until it is. // until it is.
// "sonarjs/cognitive-complexity": ["off", MAX_COGNITIVE_COMPLEXITY], // "sonarjs/cognitive-complexity": ["off", MAX_COGNITIVE_COMPLEXITY],

View File

@ -1,44 +1,37 @@
{ {
"name": "@goauthentik/eslint-config", "name": "@goauthentik/eslint-config",
"version": "1.0.5", "version": "1.0.1",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@goauthentik/eslint-config", "name": "@goauthentik/eslint-config",
"version": "1.0.5", "version": "1.0.1",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"eslint": "^9.27.0", "eslint": "^9.23.0",
"eslint-plugin-import": "^2.31.0", "eslint-plugin-import": "^2.31.0",
"eslint-plugin-lit": "^2.1.1", "eslint-plugin-lit": "^1.15.0",
"eslint-plugin-react": "^7.37.5", "eslint-plugin-react": "^7.37.4",
"eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-hooks": "^5.2.0",
"eslint-plugin-wc": "^3.0.1" "eslint-plugin-wc": "^2.1.1"
}, },
"devDependencies": { "devDependencies": {
"@goauthentik/prettier-config": "^1.0.1", "@goauthentik/prettier-config": "^1.0.1",
"@goauthentik/tsconfig": "^1.0.1", "@goauthentik/tsconfig": "^1.0.1",
"@types/eslint": "^9.6.1", "@types/eslint": "^9.6.1",
"typescript": "^5.8.3", "typescript": "^5.8.2",
"typescript-eslint": "^8.32.1" "typescript-eslint": "^8.29.0"
}, },
"engines": { "engines": {
"node": ">=20.11" "node": ">=20.11"
}, },
"peerDependencies": { "optionalDependencies": {
"react": "^18.0.0 || ^19.0.0", "react": "^18.3.1"
"react-dom": "^18.0.0 || ^19.0.0",
"typescript": "^5.8.3",
"typescript-eslint": "^8.32.1"
}, },
"peerDependenciesMeta": { "peerDependencies": {
"react": { "typescript": "^5.8.2",
"optional": true "typescript-eslint": "^8.29.0"
},
"react-dom": {
"optional": true
}
} }
}, },
"node_modules/@babel/code-frame": { "node_modules/@babel/code-frame": {
@ -177,9 +170,9 @@
} }
}, },
"node_modules/@eslint-community/eslint-utils": { "node_modules/@eslint-community/eslint-utils": {
"version": "4.7.0", "version": "4.5.1",
"resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.5.1.tgz",
"integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==", "integrity": "sha512-soEIOALTfTK6EjmKMMoLugwaP0rzkad90iIWd1hMO9ARkSAyjfMfkRRhLvD5qH7vvM0Cg72pieUfR6yh6XxC4w==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"eslint-visitor-keys": "^3.4.3" "eslint-visitor-keys": "^3.4.3"
@ -239,9 +232,9 @@
} }
}, },
"node_modules/@eslint/core": { "node_modules/@eslint/core": {
"version": "0.14.0", "version": "0.12.0",
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.14.0.tgz", "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.12.0.tgz",
"integrity": "sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==", "integrity": "sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@types/json-schema": "^7.0.15" "@types/json-schema": "^7.0.15"
@ -274,15 +267,12 @@
} }
}, },
"node_modules/@eslint/js": { "node_modules/@eslint/js": {
"version": "9.27.0", "version": "9.24.0",
"resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.27.0.tgz", "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.24.0.tgz",
"integrity": "sha512-G5JD9Tu5HJEu4z2Uo4aHY2sLV64B7CDMXxFzqzjl3NKd6RVzSXNoE80jk7Y0lJkTTkjiIhBAqmlYwjuBY3tvpA==", "integrity": "sha512-uIY/y3z0uvOGX8cp1C2fiC4+ZmBhp6yZWkojtHL1YEMnRt1Y63HB9TM17proGEmeG7HeUY+UP36F0aknKYTpYA==",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"url": "https://eslint.org/donate"
} }
}, },
"node_modules/@eslint/object-schema": { "node_modules/@eslint/object-schema": {
@ -295,18 +285,30 @@
} }
}, },
"node_modules/@eslint/plugin-kit": { "node_modules/@eslint/plugin-kit": {
"version": "0.3.1", "version": "0.2.8",
"resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.1.tgz", "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.8.tgz",
"integrity": "sha512-0J+zgWxHN+xXONWIyPWKFMgVuJoZuGiIFu8yxk7RJjxkzpGmyja5wRFqZIVtjDVOQpV+Rw0iOAjYPE2eQyjr0w==", "integrity": "sha512-ZAoA40rNMPwSm+AeHpCq8STiNAwzWLJuP8Xv4CHIc9wv/PSuExjMrmjfYNj682vW0OOiZ1HKxzvjQr9XZIisQA==",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@eslint/core": "^0.14.0", "@eslint/core": "^0.13.0",
"levn": "^0.4.1" "levn": "^0.4.1"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
} }
}, },
"node_modules/@eslint/plugin-kit/node_modules/@eslint/core": {
"version": "0.13.0",
"resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.13.0.tgz",
"integrity": "sha512-yfkgDw1KR66rkT5A8ci4irzDysN7FRpq3ttJolR88OqQikAWqwA8j5VZyas+vjyBNFIJ7MfybJ9plMILI2UrCw==",
"license": "Apache-2.0",
"dependencies": {
"@types/json-schema": "^7.0.15"
},
"engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
"node_modules/@goauthentik/prettier-config": { "node_modules/@goauthentik/prettier-config": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/@goauthentik/prettier-config/-/prettier-config-1.0.1.tgz", "resolved": "https://registry.npmjs.org/@goauthentik/prettier-config/-/prettier-config-1.0.1.tgz",
@ -576,21 +578,21 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@typescript-eslint/eslint-plugin": { "node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.32.1", "version": "8.29.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.32.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.29.1.tgz",
"integrity": "sha512-6u6Plg9nP/J1GRpe/vcjjabo6Uc5YQPAMxsgQyGC/I0RuukiG1wIe3+Vtg3IrSCVJDmqK3j8adrtzXSENRtFgg==", "integrity": "sha512-ba0rr4Wfvg23vERs3eB+P3lfj2E+2g3lhWcCVukUuhtcdUx5lSIFZlGFEBHKr+3zizDa/TvZTptdNHVZWAkSBg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@eslint-community/regexpp": "^4.10.0", "@eslint-community/regexpp": "^4.10.0",
"@typescript-eslint/scope-manager": "8.32.1", "@typescript-eslint/scope-manager": "8.29.1",
"@typescript-eslint/type-utils": "8.32.1", "@typescript-eslint/type-utils": "8.29.1",
"@typescript-eslint/utils": "8.32.1", "@typescript-eslint/utils": "8.29.1",
"@typescript-eslint/visitor-keys": "8.32.1", "@typescript-eslint/visitor-keys": "8.29.1",
"graphemer": "^1.4.0", "graphemer": "^1.4.0",
"ignore": "^7.0.0", "ignore": "^5.3.1",
"natural-compare": "^1.4.0", "natural-compare": "^1.4.0",
"ts-api-utils": "^2.1.0" "ts-api-utils": "^2.0.1"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -605,27 +607,17 @@
"typescript": ">=4.8.4 <5.9.0" "typescript": ">=4.8.4 <5.9.0"
} }
}, },
"node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.4.tgz",
"integrity": "sha512-gJzzk+PQNznz8ysRrC0aOkBNVRBDtE1n53IqyqEf3PXrYwomFs5q4pGMizBMJF+ykh03insJ27hB8gSrD2Hn8A==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 4"
}
},
"node_modules/@typescript-eslint/parser": { "node_modules/@typescript-eslint/parser": {
"version": "8.32.1", "version": "8.29.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.32.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.29.1.tgz",
"integrity": "sha512-LKMrmwCPoLhM45Z00O1ulb6jwyVr2kr3XJp+G+tSEZcbauNnScewcQwtJqXDhXeYPDEjZ8C1SjXm015CirEmGg==", "integrity": "sha512-zczrHVEqEaTwh12gWBIJWj8nx+ayDcCJs06yoNMY0kwjMWDM6+kppljY+BxWI06d2Ja+h4+WdufDcwMnnMEWmg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": "8.32.1", "@typescript-eslint/scope-manager": "8.29.1",
"@typescript-eslint/types": "8.32.1", "@typescript-eslint/types": "8.29.1",
"@typescript-eslint/typescript-estree": "8.32.1", "@typescript-eslint/typescript-estree": "8.29.1",
"@typescript-eslint/visitor-keys": "8.32.1", "@typescript-eslint/visitor-keys": "8.29.1",
"debug": "^4.3.4" "debug": "^4.3.4"
}, },
"engines": { "engines": {
@ -641,14 +633,14 @@
} }
}, },
"node_modules/@typescript-eslint/scope-manager": { "node_modules/@typescript-eslint/scope-manager": {
"version": "8.32.1", "version": "8.29.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.32.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.29.1.tgz",
"integrity": "sha512-7IsIaIDeZn7kffk7qXC3o6Z4UblZJKV3UBpkvRNpr5NSyLji7tvTcvmnMNYuYLyh26mN8W723xpo3i4MlD33vA==", "integrity": "sha512-2nggXGX5F3YrsGN08pw4XpMLO1Rgtnn4AzTegC2MDesv6q3QaTU5yU7IbS1tf1IwCR0Hv/1EFygLn9ms6LIpDA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.32.1", "@typescript-eslint/types": "8.29.1",
"@typescript-eslint/visitor-keys": "8.32.1" "@typescript-eslint/visitor-keys": "8.29.1"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -659,16 +651,16 @@
} }
}, },
"node_modules/@typescript-eslint/type-utils": { "node_modules/@typescript-eslint/type-utils": {
"version": "8.32.1", "version": "8.29.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.32.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.29.1.tgz",
"integrity": "sha512-mv9YpQGA8iIsl5KyUPi+FGLm7+bA4fgXaeRcFKRDRwDMu4iwrSHeDPipwueNXhdIIZltwCJv+NkxftECbIZWfA==", "integrity": "sha512-DkDUSDwZVCYN71xA4wzySqqcZsHKic53A4BLqmrWFFpOpNSoxX233lwGu/2135ymTCR04PoKiEEEvN1gFYg4Tw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/typescript-estree": "8.32.1", "@typescript-eslint/typescript-estree": "8.29.1",
"@typescript-eslint/utils": "8.32.1", "@typescript-eslint/utils": "8.29.1",
"debug": "^4.3.4", "debug": "^4.3.4",
"ts-api-utils": "^2.1.0" "ts-api-utils": "^2.0.1"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -683,9 +675,9 @@
} }
}, },
"node_modules/@typescript-eslint/types": { "node_modules/@typescript-eslint/types": {
"version": "8.32.1", "version": "8.29.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.32.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.29.1.tgz",
"integrity": "sha512-YmybwXUJcgGqgAp6bEsgpPXEg6dcCyPyCSr0CAAueacR/CCBi25G3V8gGQ2kRzQRBNol7VQknxMs9HvVa9Rvfg==", "integrity": "sha512-VT7T1PuJF1hpYC3AGm2rCgJBjHL3nc+A/bhOp9sGMKfi5v0WufsX/sHCFBfNTx2F+zA6qBc/PD0/kLRLjdt8mQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
@ -697,20 +689,20 @@
} }
}, },
"node_modules/@typescript-eslint/typescript-estree": { "node_modules/@typescript-eslint/typescript-estree": {
"version": "8.32.1", "version": "8.29.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.32.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.29.1.tgz",
"integrity": "sha512-Y3AP9EIfYwBb4kWGb+simvPaqQoT5oJuzzj9m0i6FCY6SPvlomY2Ei4UEMm7+FXtlNJbor80ximyslzaQF6xhg==", "integrity": "sha512-l1enRoSaUkQxOQnbi0KPUtqeZkSiFlqrx9/3ns2rEDhGKfTa+88RmXqedC1zmVTOWrLc2e6DEJrTA51C9iLH5g==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.32.1", "@typescript-eslint/types": "8.29.1",
"@typescript-eslint/visitor-keys": "8.32.1", "@typescript-eslint/visitor-keys": "8.29.1",
"debug": "^4.3.4", "debug": "^4.3.4",
"fast-glob": "^3.3.2", "fast-glob": "^3.3.2",
"is-glob": "^4.0.3", "is-glob": "^4.0.3",
"minimatch": "^9.0.4", "minimatch": "^9.0.4",
"semver": "^7.6.0", "semver": "^7.6.0",
"ts-api-utils": "^2.1.0" "ts-api-utils": "^2.0.1"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -750,9 +742,9 @@
} }
}, },
"node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": {
"version": "7.7.2", "version": "7.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
"integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
"dev": true, "dev": true,
"license": "ISC", "license": "ISC",
"bin": { "bin": {
@ -763,16 +755,16 @@
} }
}, },
"node_modules/@typescript-eslint/utils": { "node_modules/@typescript-eslint/utils": {
"version": "8.32.1", "version": "8.29.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.32.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.29.1.tgz",
"integrity": "sha512-DsSFNIgLSrc89gpq1LJB7Hm1YpuhK086DRDJSNrewcGvYloWW1vZLHBTIvarKZDcAORIy/uWNx8Gad+4oMpkSA==", "integrity": "sha512-QAkFEbytSaB8wnmB+DflhUPz6CLbFWE2SnSCrRMEa+KnXIzDYbpsn++1HGvnfAsUY44doDXmvRkO5shlM/3UfA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.7.0", "@eslint-community/eslint-utils": "^4.4.0",
"@typescript-eslint/scope-manager": "8.32.1", "@typescript-eslint/scope-manager": "8.29.1",
"@typescript-eslint/types": "8.32.1", "@typescript-eslint/types": "8.29.1",
"@typescript-eslint/typescript-estree": "8.32.1" "@typescript-eslint/typescript-estree": "8.29.1"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
@ -787,13 +779,13 @@
} }
}, },
"node_modules/@typescript-eslint/visitor-keys": { "node_modules/@typescript-eslint/visitor-keys": {
"version": "8.32.1", "version": "8.29.1",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.32.1.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.29.1.tgz",
"integrity": "sha512-ar0tjQfObzhSaW3C3QNmTc5ofj0hDoNQ5XWrCy6zDyabdr0TWhCkClp+rywGNj/odAFBVzzJrK4tEq5M4Hmu4w==", "integrity": "sha512-RGLh5CRaUEf02viP5c1Vh1cMGffQscyHe7HPAzGpfmfflFg1wUz2rYxd+OZqwpeypYvZ8UxSxuIpF++fmOzEcg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/types": "8.32.1", "@typescript-eslint/types": "8.29.1",
"eslint-visitor-keys": "^4.2.0" "eslint-visitor-keys": "^4.2.0"
}, },
"engines": { "engines": {
@ -1513,19 +1505,19 @@
} }
}, },
"node_modules/eslint": { "node_modules/eslint": {
"version": "9.27.0", "version": "9.24.0",
"resolved": "https://registry.npmjs.org/eslint/-/eslint-9.27.0.tgz", "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.24.0.tgz",
"integrity": "sha512-ixRawFQuMB9DZ7fjU3iGGganFDp3+45bPOdaRurcFHSXO1e/sYwUX/FtQZpLZJR6SjMoJH8hR2pPEAfDyCoU2Q==", "integrity": "sha512-eh/jxIEJyZrvbWRe4XuVclLPDYSYYYgLy5zXGGxD6j8zjSAxFEzI2fL/8xNq6O2yKqVt+eF2YhV+hxjV6UKXwQ==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.12.1", "@eslint-community/regexpp": "^4.12.1",
"@eslint/config-array": "^0.20.0", "@eslint/config-array": "^0.20.0",
"@eslint/config-helpers": "^0.2.1", "@eslint/config-helpers": "^0.2.0",
"@eslint/core": "^0.14.0", "@eslint/core": "^0.12.0",
"@eslint/eslintrc": "^3.3.1", "@eslint/eslintrc": "^3.3.1",
"@eslint/js": "9.27.0", "@eslint/js": "9.24.0",
"@eslint/plugin-kit": "^0.3.1", "@eslint/plugin-kit": "^0.2.7",
"@humanfs/node": "^0.16.6", "@humanfs/node": "^0.16.6",
"@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/module-importer": "^1.0.1",
"@humanwhocodes/retry": "^0.4.2", "@humanwhocodes/retry": "^0.4.2",
@ -1661,19 +1653,20 @@
} }
}, },
"node_modules/eslint-plugin-lit": { "node_modules/eslint-plugin-lit": {
"version": "2.1.1", "version": "1.15.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-lit/-/eslint-plugin-lit-2.1.1.tgz", "resolved": "https://registry.npmjs.org/eslint-plugin-lit/-/eslint-plugin-lit-1.15.0.tgz",
"integrity": "sha512-qmyAOnnTCdS+vDnNxtCoF0icSKIio4GUv6ZLnaCtTX6G/YezRa6Ag6tOQ+MfV5Elvtw9CIXeliRX4mIBSwrPIA==", "integrity": "sha512-Yhr2MYNz6Ln8megKcX503aVZQln8wsywCG49g0heiJ/Qr5UjkE4pGr4Usez2anNcc7NvlvHbQWMYwWcgH3XRKA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"parse5": "^6.0.1", "parse5": "^6.0.1",
"parse5-htmlparser2-tree-adapter": "^6.0.1" "parse5-htmlparser2-tree-adapter": "^6.0.1",
"requireindex": "^1.2.0"
}, },
"engines": { "engines": {
"node": ">= 18" "node": ">= 12"
}, },
"peerDependencies": { "peerDependencies": {
"eslint": ">= 8" "eslint": ">= 5"
} }
}, },
"node_modules/eslint-plugin-react": { "node_modules/eslint-plugin-react": {
@ -1738,13 +1731,13 @@
} }
}, },
"node_modules/eslint-plugin-wc": { "node_modules/eslint-plugin-wc": {
"version": "3.0.1", "version": "2.2.1",
"resolved": "https://registry.npmjs.org/eslint-plugin-wc/-/eslint-plugin-wc-3.0.1.tgz", "resolved": "https://registry.npmjs.org/eslint-plugin-wc/-/eslint-plugin-wc-2.2.1.tgz",
"integrity": "sha512-0p1wkSlA2Ue3FA4qW+5LZ+15sy0p1nUyVl1eyBMLq4rtN1LtE9IdI49BXNWMz8N8bM/y7Ulx8SWGAni5f8XO5g==", "integrity": "sha512-KstLqGmyQz088DvFlDYHg0sHih+w2QeulreCi1D1ftr357klO2zqHdG/bbnNMmuQdVFDuNkopNIyNhmG0XCT/g==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"is-valid-element-name": "^1.0.0", "is-valid-element-name": "^1.0.0",
"js-levenshtein-esm": "^2.0.0" "js-levenshtein-esm": "^1.2.0"
}, },
"peerDependencies": { "peerDependencies": {
"eslint": ">=8.40.0" "eslint": ">=8.40.0"
@ -2703,9 +2696,9 @@
"peer": true "peer": true
}, },
"node_modules/js-levenshtein-esm": { "node_modules/js-levenshtein-esm": {
"version": "2.0.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/js-levenshtein-esm/-/js-levenshtein-esm-2.0.0.tgz", "resolved": "https://registry.npmjs.org/js-levenshtein-esm/-/js-levenshtein-esm-1.2.0.tgz",
"integrity": "sha512-1n4LEPOL4wRXY8rOQcuA7Iuaphe5xCMayvufCzlLAi+hRsnBRDbSS6XPuV58CBVJxj5D9ApFLyjQ7KzFToyHBw==", "integrity": "sha512-fzreKVq1eD7eGcQr7MtRpQH94f8gIfhdrc7yeih38xh684TNMK9v5aAu2wxfIRMk/GpAJRrzcirMAPIaSDaByQ==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/js-tokens": { "node_modules/js-tokens": {
@ -3280,30 +3273,18 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/react": { "node_modules/react": {
"version": "19.1.0", "version": "18.3.1",
"resolved": "https://registry.npmjs.org/react/-/react-19.1.0.tgz", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
"integrity": "sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg==", "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
"license": "MIT", "license": "MIT",
"optional": true, "optional": true,
"peer": true, "dependencies": {
"loose-envify": "^1.1.0"
},
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/react-dom": {
"version": "19.1.0",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.0.tgz",
"integrity": "sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g==",
"license": "MIT",
"optional": true,
"peer": true,
"dependencies": {
"scheduler": "^0.26.0"
},
"peerDependencies": {
"react": "^19.1.0"
}
},
"node_modules/react-is": { "node_modules/react-is": {
"version": "16.13.1", "version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
@ -3352,6 +3333,15 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/requireindex": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/requireindex/-/requireindex-1.2.0.tgz",
"integrity": "sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww==",
"license": "MIT",
"engines": {
"node": ">=0.10.5"
}
},
"node_modules/resolve": { "node_modules/resolve": {
"version": "1.22.10", "version": "1.22.10",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
@ -3468,14 +3458,6 @@
"url": "https://github.com/sponsors/ljharb" "url": "https://github.com/sponsors/ljharb"
} }
}, },
"node_modules/scheduler": {
"version": "0.26.0",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.26.0.tgz",
"integrity": "sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==",
"license": "MIT",
"optional": true,
"peer": true
},
"node_modules/semver": { "node_modules/semver": {
"version": "6.3.1", "version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
@ -4018,15 +4000,15 @@
} }
}, },
"node_modules/typescript-eslint": { "node_modules/typescript-eslint": {
"version": "8.32.1", "version": "8.29.1",
"resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.32.1.tgz", "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.29.1.tgz",
"integrity": "sha512-D7el+eaDHAmXvrZBy1zpzSNIRqnCOrkwTgZxTu3MUqRWk8k0q9m9Ho4+vPf7iHtgUfrK/o8IZaEApsxPlHTFCg==", "integrity": "sha512-f8cDkvndhbQMPcysk6CUSGBWV+g1utqdn71P5YKwMumVMOG/5k7cHq0KyG4O52nB0oKS4aN2Tp5+wB4APJGC+w==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@typescript-eslint/eslint-plugin": "8.32.1", "@typescript-eslint/eslint-plugin": "8.29.1",
"@typescript-eslint/parser": "8.32.1", "@typescript-eslint/parser": "8.29.1",
"@typescript-eslint/utils": "8.32.1" "@typescript-eslint/utils": "8.29.1"
}, },
"engines": { "engines": {
"node": "^18.18.0 || ^20.9.0 || >=21.1.0" "node": "^18.18.0 || ^20.9.0 || >=21.1.0"

View File

@ -1,6 +1,6 @@
{ {
"name": "@goauthentik/eslint-config", "name": "@goauthentik/eslint-config",
"version": "1.0.5", "version": "1.0.4",
"description": "authentik's ESLint config", "description": "authentik's ESLint config",
"license": "MIT", "license": "MIT",
"scripts": { "scripts": {
@ -27,25 +27,26 @@
} }
}, },
"dependencies": { "dependencies": {
"eslint": "^9.27.0", "eslint": "^9.23.0",
"eslint-plugin-import": "^2.31.0", "eslint-plugin-import": "^2.31.0",
"eslint-plugin-lit": "^2.1.1", "eslint-plugin-lit": "^1.15.0",
"eslint-plugin-react": "^7.37.5", "eslint-plugin-react": "^7.37.4",
"eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-hooks": "^5.2.0",
"eslint-plugin-wc": "^3.0.1" "eslint-plugin-wc": "^2.1.1"
}, },
"devDependencies": { "devDependencies": {
"@goauthentik/prettier-config": "^1.0.1", "@goauthentik/prettier-config": "^1.0.1",
"@goauthentik/tsconfig": "^1.0.1", "@goauthentik/tsconfig": "^1.0.1",
"@types/eslint": "^9.6.1", "@types/eslint": "^9.6.1",
"typescript": "^5.8.3", "typescript": "^5.8.2",
"typescript-eslint": "^8.32.1" "typescript-eslint": "^8.29.0"
}, },
"peerDependencies": { "peerDependencies": {
"react": "^18.0.0 || ^19.0.0", "typescript": "^5.8.2",
"react-dom": "^18.0.0 || ^19.0.0", "typescript-eslint": "^8.29.0"
"typescript": "^5.8.3", },
"typescript-eslint": "^8.32.1" "optionalDependencies": {
"react": "^18.3.1"
}, },
"engines": { "engines": {
"node": ">=20.11" "node": ">=20.11"
@ -57,14 +58,6 @@
"out/**/*" "out/**/*"
], ],
"prettier": "@goauthentik/prettier-config", "prettier": "@goauthentik/prettier-config",
"peerDependenciesMeta": {
"react": {
"optional": true
},
"react-dom": {
"optional": true
}
},
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
} }

View File

@ -1,19 +1,19 @@
{ {
"name": "@goauthentik/prettier-config", "name": "@goauthentik/prettier-config",
"version": "1.0.4", "version": "1.0.1",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@goauthentik/prettier-config", "name": "@goauthentik/prettier-config",
"version": "1.0.4", "version": "1.0.1",
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {
"@goauthentik/tsconfig": "^1.0.1", "@goauthentik/tsconfig": "^1.0.1",
"@trivago/prettier-plugin-sort-imports": "^5.2.2", "@trivago/prettier-plugin-sort-imports": "^5.2.2",
"prettier": "^3.5.3", "prettier": "^3.5.3",
"prettier-plugin-organize-imports": "^4.1.0", "prettier-plugin-organize-imports": "^4.1.0",
"prettier-plugin-packagejson": "^2.5.14", "prettier-plugin-packagejson": "^2.5.10",
"typescript": "^5.8.2" "typescript": "^5.8.2"
}, },
"engines": { "engines": {
@ -23,7 +23,7 @@
"@trivago/prettier-plugin-sort-imports": "^5.2.2", "@trivago/prettier-plugin-sort-imports": "^5.2.2",
"prettier": "^3.5.3", "prettier": "^3.5.3",
"prettier-plugin-organize-imports": "^4.1.0", "prettier-plugin-organize-imports": "^4.1.0",
"prettier-plugin-packagejson": "^2.5.14" "prettier-plugin-packagejson": "^2.5.10"
} }
}, },
"node_modules/@babel/code-frame": { "node_modules/@babel/code-frame": {
@ -206,16 +206,16 @@
} }
}, },
"node_modules/@pkgr/core": { "node_modules/@pkgr/core": {
"version": "0.2.4", "version": "0.1.2",
"resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.4.tgz", "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.2.tgz",
"integrity": "sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw==", "integrity": "sha512-fdDH1LSGfZdTH2sxdpVMw31BanV28K/Gry0cVFxaNP77neJSkd82mM8ErPNYs9e+0O7SdHBLTDzDgwUuy18RnQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": "^12.20.0 || ^14.18.0 || >=16.0.0" "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
}, },
"funding": { "funding": {
"url": "https://opencollective.com/pkgr" "url": "https://opencollective.com/unts"
} }
}, },
"node_modules/@trivago/prettier-plugin-sort-imports": { "node_modules/@trivago/prettier-plugin-sort-imports": {
@ -295,9 +295,9 @@
} }
}, },
"node_modules/fdir": { "node_modules/fdir": {
"version": "6.4.4", "version": "6.4.3",
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.3.tgz",
"integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", "integrity": "sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peerDependencies": { "peerDependencies": {
@ -309,10 +309,23 @@
} }
} }
}, },
"node_modules/get-stdin": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz",
"integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/git-hooks-list": { "node_modules/git-hooks-list": {
"version": "4.1.1", "version": "3.2.0",
"resolved": "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-4.1.1.tgz", "resolved": "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-3.2.0.tgz",
"integrity": "sha512-cmP497iLq54AZnv4YRAEMnEyQ1eIn4tGKbmswqwmFV4GBnAqE8NLtWxxdXa++AalfgL5EBH4IxTPyquEuGY/jA==", "integrity": "sha512-ZHG9a1gEhUMX1TvGrLdyWb9kDopCBbTnI8z4JgRMYxsijWipgjSEYoPWqBuIB0DnRnvqlQSEeVmzpeuPm7NdFQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"funding": { "funding": {
@ -437,14 +450,14 @@
} }
}, },
"node_modules/prettier-plugin-packagejson": { "node_modules/prettier-plugin-packagejson": {
"version": "2.5.14", "version": "2.5.10",
"resolved": "https://registry.npmjs.org/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.5.14.tgz", "resolved": "https://registry.npmjs.org/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.5.10.tgz",
"integrity": "sha512-h+3tSpr2nVpp+YOK1MDIYtYhHVXr8/0V59UUbJpIJFaqi3w4fvUokJo6eV8W+vELrUXIZzJ+DKm5G7lYzrMcKQ==", "integrity": "sha512-LUxATI5YsImIVSaaLJlJ3aE6wTD+nvots18U3GuQMJpUyClChaZlQrqx3dBnbhF20OnKWZyx8EgyZypQtBDtgQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"sort-package-json": "3.2.1", "sort-package-json": "2.15.1",
"synckit": "0.11.6" "synckit": "0.9.2"
}, },
"peerDependencies": { "peerDependencies": {
"prettier": ">= 1.16.0" "prettier": ">= 1.16.0"
@ -456,9 +469,9 @@
} }
}, },
"node_modules/semver": { "node_modules/semver": {
"version": "7.7.2", "version": "7.7.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
"integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==", "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
"dev": true, "dev": true,
"license": "ISC", "license": "ISC",
"bin": { "bin": {
@ -476,48 +489,50 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/sort-package-json": { "node_modules/sort-package-json": {
"version": "3.2.1", "version": "2.15.1",
"resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-3.2.1.tgz", "resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-2.15.1.tgz",
"integrity": "sha512-rTfRdb20vuoAn7LDlEtCqOkYfl2X+Qze6cLbNOzcDpbmKEhJI30tTN44d5shbKJnXsvz24QQhlCm81Bag7EOKg==", "integrity": "sha512-9x9+o8krTT2saA9liI4BljNjwAbvUnWf11Wq+i/iZt8nl2UGYnf3TH5uBydE7VALmP7AGwlfszuEeL8BDyb0YA==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"detect-indent": "^7.0.1", "detect-indent": "^7.0.1",
"detect-newline": "^4.0.1", "detect-newline": "^4.0.0",
"git-hooks-list": "^4.0.0", "get-stdin": "^9.0.0",
"git-hooks-list": "^3.0.0",
"is-plain-obj": "^4.1.0", "is-plain-obj": "^4.1.0",
"semver": "^7.7.1", "semver": "^7.6.0",
"sort-object-keys": "^1.1.3", "sort-object-keys": "^1.1.3",
"tinyglobby": "^0.2.12" "tinyglobby": "^0.2.9"
}, },
"bin": { "bin": {
"sort-package-json": "cli.js" "sort-package-json": "cli.js"
} }
}, },
"node_modules/synckit": { "node_modules/synckit": {
"version": "0.11.6", "version": "0.9.2",
"resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.6.tgz", "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz",
"integrity": "sha512-2pR2ubZSV64f/vqm9eLPz/KOvR9Dm+Co/5ChLgeHl0yEDRc6h5hXHoxEQH8Y5Ljycozd3p1k5TTSVdzYGkPvLw==", "integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@pkgr/core": "^0.2.4" "@pkgr/core": "^0.1.0",
"tslib": "^2.6.2"
}, },
"engines": { "engines": {
"node": "^14.18.0 || >=16.0.0" "node": "^14.18.0 || >=16.0.0"
}, },
"funding": { "funding": {
"url": "https://opencollective.com/synckit" "url": "https://opencollective.com/unts"
} }
}, },
"node_modules/tinyglobby": { "node_modules/tinyglobby": {
"version": "0.2.13", "version": "0.2.12",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.12.tgz",
"integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==", "integrity": "sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"fdir": "^6.4.4", "fdir": "^6.4.3",
"picomatch": "^4.0.2" "picomatch": "^4.0.2"
}, },
"engines": { "engines": {
@ -527,6 +542,13 @@
"url": "https://github.com/sponsors/SuperchupuDev" "url": "https://github.com/sponsors/SuperchupuDev"
} }
}, },
"node_modules/tslib": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
"dev": true,
"license": "0BSD"
},
"node_modules/typescript": { "node_modules/typescript": {
"version": "5.8.3", "version": "5.8.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz",

View File

@ -1,26 +1,32 @@
{ {
"name": "@goauthentik/prettier-config", "name": "@goauthentik/prettier-config",
"version": "1.0.5", "version": "1.0.4",
"description": "authentik's Prettier config", "description": "authentik's Prettier config",
"license": "MIT", "license": "MIT",
"scripts": { "scripts": {
"build": "tsc -p ." "build": "tsc -p ."
}, },
"type": "module", "type": "module",
"exports": "./index.js", "exports": {
"./package.json": "./package.json",
".": {
"import": "./index.js",
"types": "./out/index.d.ts"
}
},
"devDependencies": { "devDependencies": {
"@goauthentik/tsconfig": "^1.0.1", "@goauthentik/tsconfig": "^1.0.1",
"@trivago/prettier-plugin-sort-imports": "^5.2.2", "@trivago/prettier-plugin-sort-imports": "^5.2.2",
"prettier": "^3.5.3", "prettier": "^3.5.3",
"prettier-plugin-organize-imports": "^4.1.0", "prettier-plugin-organize-imports": "^4.1.0",
"prettier-plugin-packagejson": "^2.5.14", "prettier-plugin-packagejson": "^2.5.10",
"typescript": "^5.8.2" "typescript": "^5.8.2"
}, },
"peerDependencies": { "peerDependencies": {
"@trivago/prettier-plugin-sort-imports": "^5.2.2", "@trivago/prettier-plugin-sort-imports": "^5.2.2",
"prettier": "^3.5.3", "prettier": "^3.5.3",
"prettier-plugin-organize-imports": "^4.1.0", "prettier-plugin-organize-imports": "^4.1.0",
"prettier-plugin-packagejson": "^2.5.14" "prettier-plugin-packagejson": "^2.5.10"
}, },
"engines": { "engines": {
"node": ">=20.11" "node": ">=20.11"

View File

@ -2,19 +2,19 @@
"name": "@goauthentik/tsconfig", "name": "@goauthentik/tsconfig",
"version": "1.0.4", "version": "1.0.4",
"description": "authentik's base TypeScript configuration.", "description": "authentik's base TypeScript configuration.",
"license": "MIT",
"scripts": {
"build": ""
},
"main": "tsconfig.json",
"type": "module",
"engines": {
"node": ">=20.11"
},
"keywords": [ "keywords": [
"tsconfig", "tsconfig",
"typescript" "typescript"
], ],
"license": "MIT",
"scripts": {
"build": ""
},
"type": "module",
"main": "tsconfig.json",
"engines": {
"node": ">=20.11"
},
"publishConfig": { "publishConfig": {
"access": "public" "access": "public"
} }

View File

@ -1,22 +1,20 @@
# syntax=docker/dockerfile:1 # syntax=docker/dockerfile:1
# Stage 1: Build web # Stage 1: Build web
FROM --platform=${BUILDPLATFORM} docker.io/library/node:24-slim AS web-builder FROM --platform=${BUILDPLATFORM} docker.io/library/node:22 AS web-builder
WORKDIR /work
COPY ./package.json /work
COPY ./package-lock.json /work
COPY ./tsconfig.json /work
COPY ./packages/ /work/packages/
COPY ./web /work/web/
RUN --mount=type=cache,id=npm-node,sharing=shared,target=/root/.npm \
npm ci
ENV NODE_ENV=production ENV NODE_ENV=production
WORKDIR /static
RUN npm run build-proxy -w @goauthentik/web COPY package.json /
RUN --mount=type=bind,target=/static/package.json,src=./web/package.json \
--mount=type=bind,target=/static/package-lock.json,src=./web/package-lock.json \
--mount=type=bind,target=/static/scripts,src=./web/scripts \
--mount=type=cache,target=/root/.npm \
npm ci --include=dev
COPY web .
RUN npm run build-proxy
# Stage 2: Build # Stage 2: Build
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.24-bookworm AS builder FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.24-bookworm AS builder
@ -67,10 +65,10 @@ RUN apt-get update && \
rm -rf /tmp/* /var/lib/apt/lists/* rm -rf /tmp/* /var/lib/apt/lists/*
COPY --from=builder /go/proxy / COPY --from=builder /go/proxy /
COPY --from=web-builder /work/web/robots.txt /web/robots.txt COPY --from=web-builder /static/robots.txt /web/robots.txt
COPY --from=web-builder /work/web/security.txt /web/security.txt COPY --from=web-builder /static/security.txt /web/security.txt
COPY --from=web-builder /work/web/dist/ /web/dist/ COPY --from=web-builder /static/dist/ /web/dist/
COPY --from=web-builder /work/web/authentik/ /web/authentik/ COPY --from=web-builder /static/authentik/ /web/authentik/
HEALTHCHECK --interval=5s --retries=20 --start-period=3s CMD [ "/proxy", "healthcheck" ] HEALTHCHECK --interval=5s --retries=20 --start-period=3s CMD [ "/proxy", "healthcheck" ]

View File

@ -17,7 +17,7 @@ dependencies = [
"django-countries==7.6.1", "django-countries==7.6.1",
"django-cte==1.3.3", "django-cte==1.3.3",
"django-filter==25.1", "django-filter==25.1",
"django-guardian==3.0.0", "django-guardian<3.0.0",
"django-model-utils==5.0.0", "django-model-utils==5.0.0",
"django-pglock==1.7.2", "django-pglock==1.7.2",
"django-prometheus==2.3.1", "django-prometheus==2.3.1",
@ -31,7 +31,7 @@ dependencies = [
"drf-spectacular==0.28.0", "drf-spectacular==0.28.0",
"dumb-init==1.2.5.post1", "dumb-init==1.2.5.post1",
"duo-client==5.5.0", "duo-client==5.5.0",
"fido2==2.0.0", "fido2==1.2.0",
"flower==2.0.1", "flower==2.0.1",
"geoip2==5.1.0", "geoip2==5.1.0",
"geopy==2.4.1", "geopy==2.4.1",
@ -56,7 +56,7 @@ dependencies = [
"pyyaml==6.0.2", "pyyaml==6.0.2",
"requests-oauthlib==2.0.0", "requests-oauthlib==2.0.0",
"scim2-filter-parser==0.7.0", "scim2-filter-parser==0.7.0",
"sentry-sdk==2.29.1", "sentry-sdk==2.28.0",
"service-identity==24.2.0", "service-identity==24.2.0",
"setproctitle==1.3.6", "setproctitle==1.3.6",
"structlog==25.3.0", "structlog==25.3.0",
@ -114,9 +114,9 @@ no-binary-package = [
] ]
[tool.uv.sources] [tool.uv.sources]
django-tenants = { git = "https://github.com/goauthentik/django-tenants.git", branch = "authentik-fixes" } django-tenants = { git = "https://github.com/rissson/django-tenants.git", branch = "authentik-fixes" }
opencontainers = { git = "https://github.com/vsoch/oci-python", rev = "ceb4fcc090851717a3069d78e85ceb1e86c2740c" } opencontainers = { git = "https://github.com/BeryJu/oci-python", rev = "c791b19056769cd67957322806809ab70f5bead8" }
djangorestframework = { git = "https://github.com/goauthentik/django-rest-framework", rev = "896722bab969fabc74a08b827da59409cf9f1a4e" } djangorestframework = { git = "https://github.com/authentik-community/django-rest-framework", rev = "896722bab969fabc74a08b827da59409cf9f1a4e" }
[project.scripts] [project.scripts]
ak = "lifecycle.ak:main" ak = "lifecycle.ak:main"

View File

@ -1,7 +0,0 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "dist/esm",
},
}

View File

@ -1,23 +0,0 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"composite": true,
"isolatedModules": true,
"incremental": true,
"baseUrl": ".",
"rootDir": "src",
"strict": true,
"newLine": "lf",
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "bundler",
"outDir": "dist",
"skipDefaultLibCheck": true,
"skipLibCheck": true,
"sourceMap": true,
"declaration": true,
"declarationMap": true,
"lib": ["DOM", "DOM.Iterable", "ESNext"],
},
"exclude": ["node_modules", "./out/**/*", "./dist/**/*"],
}

View File

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

View File

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

View File

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

View File

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

View File

@ -23,8 +23,6 @@
"files": [], "files": [],
"references": [ "references": [
// Note that references are in the order we want them to be built. // Note that references are in the order we want them to be built.
{ // TODO: Left blank until TypeScript workspaces are complete.
"path": "./web"
}
] ]
} }

36
uv.lock generated
View File

@ -277,21 +277,21 @@ requires-dist = [
{ name = "django-countries", specifier = "==7.6.1" }, { name = "django-countries", specifier = "==7.6.1" },
{ name = "django-cte", specifier = "==1.3.3" }, { name = "django-cte", specifier = "==1.3.3" },
{ name = "django-filter", specifier = "==25.1" }, { name = "django-filter", specifier = "==25.1" },
{ name = "django-guardian", specifier = "==3.0.0" }, { name = "django-guardian", specifier = "<3.0.0" },
{ name = "django-model-utils", specifier = "==5.0.0" }, { name = "django-model-utils", specifier = "==5.0.0" },
{ name = "django-pglock", specifier = "==1.7.2" }, { name = "django-pglock", specifier = "==1.7.2" },
{ name = "django-prometheus", specifier = "==2.3.1" }, { name = "django-prometheus", specifier = "==2.3.1" },
{ name = "django-redis", specifier = "==5.4.0" }, { name = "django-redis", specifier = "==5.4.0" },
{ name = "django-storages", extras = ["s3"], specifier = "==1.14.6" }, { name = "django-storages", extras = ["s3"], specifier = "==1.14.6" },
{ name = "django-tenants", git = "https://github.com/goauthentik/django-tenants.git?branch=authentik-fixes" }, { name = "django-tenants", git = "https://github.com/rissson/django-tenants.git?branch=authentik-fixes" },
{ name = "djangorestframework", git = "https://github.com/goauthentik/django-rest-framework?rev=896722bab969fabc74a08b827da59409cf9f1a4e" }, { name = "djangorestframework", git = "https://github.com/authentik-community/django-rest-framework?rev=896722bab969fabc74a08b827da59409cf9f1a4e" },
{ name = "djangorestframework-guardian", specifier = "==0.3.0" }, { name = "djangorestframework-guardian", specifier = "==0.3.0" },
{ name = "docker", specifier = "==7.1.0" }, { name = "docker", specifier = "==7.1.0" },
{ name = "drf-orjson-renderer", specifier = "==1.7.3" }, { name = "drf-orjson-renderer", specifier = "==1.7.3" },
{ name = "drf-spectacular", specifier = "==0.28.0" }, { name = "drf-spectacular", specifier = "==0.28.0" },
{ name = "dumb-init", specifier = "==1.2.5.post1" }, { name = "dumb-init", specifier = "==1.2.5.post1" },
{ name = "duo-client", specifier = "==5.5.0" }, { name = "duo-client", specifier = "==5.5.0" },
{ name = "fido2", specifier = "==2.0.0" }, { name = "fido2", specifier = "==1.2.0" },
{ name = "flower", specifier = "==2.0.1" }, { name = "flower", specifier = "==2.0.1" },
{ name = "geoip2", specifier = "==5.1.0" }, { name = "geoip2", specifier = "==5.1.0" },
{ name = "geopy", specifier = "==2.4.1" }, { name = "geopy", specifier = "==2.4.1" },
@ -304,7 +304,7 @@ requires-dist = [
{ name = "ldap3", specifier = "==2.9.1" }, { name = "ldap3", specifier = "==2.9.1" },
{ name = "lxml", specifier = "==5.4.0" }, { name = "lxml", specifier = "==5.4.0" },
{ name = "msgraph-sdk", specifier = "==1.30.0" }, { name = "msgraph-sdk", specifier = "==1.30.0" },
{ name = "opencontainers", git = "https://github.com/vsoch/oci-python?rev=ceb4fcc090851717a3069d78e85ceb1e86c2740c" }, { name = "opencontainers", git = "https://github.com/BeryJu/oci-python?rev=c791b19056769cd67957322806809ab70f5bead8" },
{ name = "packaging", specifier = "==25.0" }, { name = "packaging", specifier = "==25.0" },
{ name = "paramiko", specifier = "==3.5.1" }, { name = "paramiko", specifier = "==3.5.1" },
{ name = "psycopg", extras = ["c", "pool"], specifier = "==3.2.9" }, { name = "psycopg", extras = ["c", "pool"], specifier = "==3.2.9" },
@ -316,7 +316,7 @@ requires-dist = [
{ name = "pyyaml", specifier = "==6.0.2" }, { name = "pyyaml", specifier = "==6.0.2" },
{ name = "requests-oauthlib", specifier = "==2.0.0" }, { name = "requests-oauthlib", specifier = "==2.0.0" },
{ name = "scim2-filter-parser", specifier = "==0.7.0" }, { name = "scim2-filter-parser", specifier = "==0.7.0" },
{ name = "sentry-sdk", specifier = "==2.29.1" }, { name = "sentry-sdk", specifier = "==2.28.0" },
{ name = "service-identity", specifier = "==24.2.0" }, { name = "service-identity", specifier = "==24.2.0" },
{ name = "setproctitle", specifier = "==1.3.6" }, { name = "setproctitle", specifier = "==1.3.6" },
{ name = "structlog", specifier = "==25.3.0" }, { name = "structlog", specifier = "==25.3.0" },
@ -1027,14 +1027,14 @@ wheels = [
[[package]] [[package]]
name = "django-guardian" name = "django-guardian"
version = "3.0.0" version = "2.4.0"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "django" }, { name = "django" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/30/82/2c76cdf77eae3cb0c3df394686daf8f84bcd604c0da7a26fa19f5fe74ed4/django_guardian-3.0.0.tar.gz", hash = "sha256:0c79d55c4af2cfc14fbd19539846a1ebfed2a38198b7697e0f5177b7f654e1cd", size = 79895, upload-time = "2025-05-07T19:33:23.328Z" } sdist = { url = "https://files.pythonhosted.org/packages/6f/4c/d1f6923a0ad7f16c403a54c09e94acb76ac6c3765e02523fb09b2b03e1a8/django-guardian-2.4.0.tar.gz", hash = "sha256:c58a68ae76922d33e6bdc0e69af1892097838de56e93e78a8361090bcd9f89a0", size = 159008, upload-time = "2021-05-23T22:11:26.23Z" }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/a5/81/a2f3d3245d1f4cf446d78863526fba0b1b140d60784095a5cc2d4e8ac709/django_guardian-3.0.0-py3-none-any.whl", hash = "sha256:f3ebe3cc7f486e267041b780c3429ad5db72c909df40c2f74adb1b059582a3cd", size = 112672, upload-time = "2025-05-07T19:33:21.719Z" }, { url = "https://files.pythonhosted.org/packages/a2/25/869df12e544b51f583254aadbba6c1a95e11d2d08edeb9e58dd715112db5/django_guardian-2.4.0-py3-none-any.whl", hash = "sha256:440ca61358427e575323648b25f8384739e54c38b3d655c81d75e0cd0d61b697", size = 106107, upload-time = "2021-05-23T22:11:22.75Z" },
] ]
[[package]] [[package]]
@ -1119,7 +1119,7 @@ s3 = [
[[package]] [[package]]
name = "django-tenants" name = "django-tenants"
version = "3.7.0" version = "3.7.0"
source = { git = "https://github.com/goauthentik/django-tenants.git?branch=authentik-fixes#156e53a6f5902d74b73dd9d0192fffaa2587a740" } source = { git = "https://github.com/rissson/django-tenants.git?branch=authentik-fixes#156e53a6f5902d74b73dd9d0192fffaa2587a740" }
dependencies = [ dependencies = [
{ name = "django" }, { name = "django" },
] ]
@ -1127,7 +1127,7 @@ dependencies = [
[[package]] [[package]]
name = "djangorestframework" name = "djangorestframework"
version = "3.16.0" version = "3.16.0"
source = { git = "https://github.com/goauthentik/django-rest-framework?rev=896722bab969fabc74a08b827da59409cf9f1a4e#896722bab969fabc74a08b827da59409cf9f1a4e" } source = { git = "https://github.com/authentik-community/django-rest-framework?rev=896722bab969fabc74a08b827da59409cf9f1a4e#896722bab969fabc74a08b827da59409cf9f1a4e" }
dependencies = [ dependencies = [
{ name = "django" }, { name = "django" },
] ]
@ -1262,14 +1262,14 @@ wheels = [
[[package]] [[package]]
name = "fido2" name = "fido2"
version = "2.0.0" version = "1.2.0"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "cryptography" }, { name = "cryptography" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/8d/b9/6ec8d8ec5715efc6ae39e8694bd48d57c189906f0628558f56688d0447b2/fido2-2.0.0.tar.gz", hash = "sha256:3061cd05e73b3a0ef6afc3b803d57c826aa2d6a9732d16abd7277361f58e7964", size = 274942, upload-time = "2025-05-20T09:45:00.974Z" } sdist = { url = "https://files.pythonhosted.org/packages/eb/cc/4529123364d41f342145f2fd775307eaed817cd22810895dea10e15a4d06/fido2-1.2.0.tar.gz", hash = "sha256:e39f95920122d64283fda5e5581d95a206e704fa42846bfa4662f86aa0d3333b", size = 266369, upload-time = "2024-11-27T09:08:21.071Z" }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/4c/7d/a1dba174d7ec4b6b8d6360eed0ac3a4a4e2aa45f234e903592d3184c6c3f/fido2-2.0.0-py3-none-any.whl", hash = "sha256:685f54a50a57e019c6156e2dd699802a603e3abf70bab334f26affdd4fb8d4f7", size = 224761, upload-time = "2025-05-20T09:44:59.029Z" }, { url = "https://files.pythonhosted.org/packages/4c/48/e9b99d66f27d3416a619324568739fd6603e093b2f79138d6f47ccf727b6/fido2-1.2.0-py3-none-any.whl", hash = "sha256:f7c8ee62e359aa980a45773f9493965bb29ede1b237a9218169dbfe60c80e130", size = 219418, upload-time = "2024-11-27T09:08:18.932Z" },
] ]
[[package]] [[package]]
@ -2153,7 +2153,7 @@ wheels = [
[[package]] [[package]]
name = "opencontainers" name = "opencontainers"
version = "0.0.14" version = "0.0.14"
source = { git = "https://github.com/vsoch/oci-python?rev=ceb4fcc090851717a3069d78e85ceb1e86c2740c#ceb4fcc090851717a3069d78e85ceb1e86c2740c" } source = { git = "https://github.com/BeryJu/oci-python?rev=c791b19056769cd67957322806809ab70f5bead8#c791b19056769cd67957322806809ab70f5bead8" }
[[package]] [[package]]
name = "opentelemetry-api" name = "opentelemetry-api"
@ -2940,15 +2940,15 @@ wheels = [
[[package]] [[package]]
name = "sentry-sdk" name = "sentry-sdk"
version = "2.29.1" version = "2.28.0"
source = { registry = "https://pypi.org/simple" } source = { registry = "https://pypi.org/simple" }
dependencies = [ dependencies = [
{ name = "certifi" }, { name = "certifi" },
{ name = "urllib3" }, { name = "urllib3" },
] ]
sdist = { url = "https://files.pythonhosted.org/packages/22/67/d552a5f8e5a6a56b2feea6529e2d8ccd54349084c84176d5a1f7295044bc/sentry_sdk-2.29.1.tar.gz", hash = "sha256:8d4a0206b95fa5fe85e5e7517ed662e3888374bdc342c00e435e10e6d831aa6d", size = 325518, upload-time = "2025-05-19T14:27:38.512Z" } sdist = { url = "https://files.pythonhosted.org/packages/5e/bb/6a41b2e0e9121bed4d2ec68d50568ab95c49f4744156a9bbb789c866c66d/sentry_sdk-2.28.0.tar.gz", hash = "sha256:14d2b73bc93afaf2a9412490329099e6217761cbab13b6ee8bc0e82927e1504e", size = 325052, upload-time = "2025-05-12T07:53:12.785Z" }
wheels = [ wheels = [
{ url = "https://files.pythonhosted.org/packages/f0/e5/da07b0bd832cefd52d16f2b9bbbe31624d57552602c06631686b93ccb1bd/sentry_sdk-2.29.1-py2.py3-none-any.whl", hash = "sha256:90862fe0616ded4572da6c9dadb363121a1ae49a49e21c418f0634e9d10b4c19", size = 341553, upload-time = "2025-05-19T14:27:36.882Z" }, { url = "https://files.pythonhosted.org/packages/9b/4e/b1575833094c088dfdef63fbca794518860fcbc8002aadf51ebe8b6a387f/sentry_sdk-2.28.0-py2.py3-none-any.whl", hash = "sha256:51496e6cb3cb625b99c8e08907c67a9112360259b0ef08470e532c3ab184a232", size = 341693, upload-time = "2025-05-12T07:53:10.882Z" },
] ]
[[package]] [[package]]

View File

@ -1,38 +0,0 @@
/// <reference types="@wdio/globals/types" />
/// <reference types="./types/webdriver.js" />
/**
*
* @param {WebdriverIO.Browser} browser
*/
export function addCommands(browser) {
/**
* @file Custom WDIO browser commands
*/
browser.addCommand(
"focus",
/**
* @this {HTMLElement}
*/
function () {
this.focus();
return this;
},
/* attachToElement */ true,
);
browser.addCommand(
"blur",
/**
* @this {HTMLElement}
*/
function () {
this.blur();
return this;
},
/* attachToElement */ true,
);
}

View File

@ -1,54 +1,91 @@
import { createESLintPackageConfig } from "@goauthentik/eslint-config"; import eslint from "@eslint/js";
import tsparser from "@typescript-eslint/parser";
import litconf from "eslint-plugin-lit";
import wcconf from "eslint-plugin-wc";
import globals from "globals";
import tseslint from "typescript-eslint"; import tseslint from "typescript-eslint";
// @ts-check export default [
// You would not believe how much this change has frustrated users: ["if an ignores key is used
/** // without any other keys in the configuration object, then the patterns act as global
* ESLint configuration for authentik's monorepo. // ignores"](https://eslint.org/docs/latest/use/configure/ignore)
*/
const ESLintConfig = createESLintPackageConfig({
ignorePatterns: [
"**/dist/**",
"**/out/**",
"**/.wireit/**",
"**/node_modules/",
"**/.storybook/*",
"coverage/",
"src/locale-codes.ts",
"storybook-static/",
"src/locales/",
],
});
export default tseslint.config(
...ESLintConfig,
{ {
ignores: [
"dist/",
"out/",
// don't lint the cache
".wireit/",
// let packages have their own configurations
"packages/",
// don't ever lint node_modules
"node_modules/",
".storybook/*",
// don't lint build output (make sure it's set to your correct build folder name)
// don't lint nyc coverage output
"coverage/",
"src/locale-codes.ts",
"storybook-static/",
"src/locales/",
],
},
eslint.configs.recommended,
wcconf.configs["flat/recommended"],
litconf.configs["flat/recommended"],
...tseslint.configs.recommended,
{
languageOptions: {
parser: tsparser,
parserOptions: {
ecmaVersion: 12,
sourceType: "module",
},
},
files: ["src/**"],
rules: { rules: {
"lit/attribute-names": "off",
// "lit/attribute-names": "error",
"lit/no-private-properties": "error",
// "lit/prefer-nothing": "warn",
"lit/no-template-bind": "error",
"no-unused-vars": "off",
"no-console": ["error", { allow: ["debug", "warn", "error"] }], "no-console": ["error", { allow: ["debug", "warn", "error"] }],
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/no-unused-vars": [
"error",
{
argsIgnorePattern: "^_",
varsIgnorePattern: "^_",
caughtErrorsIgnorePattern: "^_",
},
],
}, },
files: ["src/**/*"],
}, },
{ {
languageOptions: {
parser: tsparser,
parserOptions: {
ecmaVersion: 12,
sourceType: "module",
},
globals: {
...globals.nodeBuiltin,
...globals.node,
},
},
files: ["scripts/**/*.mjs", "*.ts", "*.mjs", "**/node.js"],
rules: { rules: {
"no-implicit-coercion": "off", "no-unused-vars": "off",
"prefer-template": "off", // We WANT our scripts to output to the console!
"no-console": "off",
"@typescript-eslint/ban-ts-comment": "off", "@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/no-unused-vars": "off", "@typescript-eslint/no-unused-vars": [
"@typescript-eslint/no-use-before-define": "off", "error",
"array-callback-return": "off", {
"block-scoped-var": "off", argsIgnorePattern: "^_",
"consistent-return": "off", varsIgnorePattern: "^_",
"func-names": "off", caughtErrorsIgnorePattern: "^_",
"guard-for-in": "off", },
"no-bitwise": "off", ],
"no-div-regex": "off",
"no-else-return": "off",
"no-empty-function": "off",
"no-param-reassign": "off",
"no-throw-literal": "off",
"prefer-arrow-callback": "off",
"react/jsx-no-leaked-render": "off",
"vars-on-top": "off",
}, },
}, },
); ];

25547
web/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -8,20 +8,21 @@
"build-locales": "wireit", "build-locales": "wireit",
"build-locales:build": "wireit", "build-locales:build": "wireit",
"build-proxy": "wireit", "build-proxy": "wireit",
"build:sfe": "npm run build -w @goauthentik/web-sfe", "build:sfe": "wireit",
"esbuild:watch": "node scripts/build-web.mjs --watch", "esbuild:watch": "node scripts/build-web.mjs --watch",
"extract-locales": "wireit", "extract-locales": "wireit",
"format": "wireit", "format": "wireit",
"lint": "eslint --fix .", "lint": "wireit",
"lint-check": "eslint --max-warnings 0 .", "lint:imports": "wireit",
"lint:imports": "knip --config scripts/knip.config.ts",
"lint:lockfile": "wireit", "lint:lockfile": "wireit",
"lint:nightmare": "wireit",
"lint:precommit": "wireit",
"lint:types": "wireit", "lint:types": "wireit",
"lit-analyse": "wireit", "lit-analyse": "wireit",
"precommit": "wireit", "precommit": "wireit",
"prettier": "prettier --cache --write -u .", "prettier": "wireit",
"prettier-check": "prettier --cache --check -u .", "prettier-check": "wireit",
"pseudolocalize": "node ./scripts/pseudolocalize.mjs", "pseudolocalize": "wireit",
"storybook": "storybook dev -p 6006", "storybook": "storybook dev -p 6006",
"storybook:build": "wireit", "storybook:build": "wireit",
"test": "wireit", "test": "wireit",
@ -96,13 +97,13 @@
"@lit/context": "^1.1.2", "@lit/context": "^1.1.2",
"@lit/localize": "^0.12.2", "@lit/localize": "^0.12.2",
"@lit/reactive-element": "^2.0.4", "@lit/reactive-element": "^2.0.4",
"@lit/task": "^1.0.2", "@lit/task": "^1.0.1",
"@mdx-js/mdx": "^3.1.0", "@mdx-js/mdx": "^3.1.0",
"@open-wc/lit-helpers": "^0.7.0", "@open-wc/lit-helpers": "^0.7.0",
"@patternfly/elements": "^4.1.0", "@patternfly/elements": "^4.0.2",
"@patternfly/patternfly": "^4.224.2", "@patternfly/patternfly": "^4.224.2",
"@sentry/browser": "^9.22.0", "@sentry/browser": "^8.32.0",
"@spotlightjs/spotlight": "^2.13.3", "@spotlightjs/spotlight": "^2.4.2",
"@webcomponents/webcomponentsjs": "^2.8.0", "@webcomponents/webcomponentsjs": "^2.8.0",
"base64-js": "^1.5.1", "base64-js": "^1.5.1",
"change-case": "^5.4.4", "change-case": "^5.4.4",
@ -122,8 +123,8 @@
"md-front-matter": "^1.0.4", "md-front-matter": "^1.0.4",
"mermaid": "^11.4.1", "mermaid": "^11.4.1",
"rapidoc": "^9.3.8", "rapidoc": "^9.3.8",
"react": "^19.1.0", "react": "^18.3.1",
"react-dom": "^19.1.0", "react-dom": "^18.3.1",
"rehype-highlight": "^7.0.2", "rehype-highlight": "^7.0.2",
"rehype-mermaid": "^3.0.0", "rehype-mermaid": "^3.0.0",
"rehype-parse": "^9.0.1", "rehype-parse": "^9.0.1",
@ -137,19 +138,19 @@
"ts-pattern": "^5.4.0", "ts-pattern": "^5.4.0",
"unist-util-visit": "^5.0.0", "unist-util-visit": "^5.0.0",
"webcomponent-qr-code": "^1.2.0", "webcomponent-qr-code": "^1.2.0",
"yaml": "^2.8.0" "yaml": "^2.5.1"
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.27.0", "@eslint/js": "^9.11.1",
"@goauthentik/core": "^1.0.0", "@goauthentik/core": "^1.0.0",
"@goauthentik/esbuild-plugin-live-reload": "^1.0.4", "@goauthentik/esbuild-plugin-live-reload": "^1.0.4",
"@goauthentik/eslint-config": "^1.0.5", "@goauthentik/prettier-config": "^1.0.4",
"@goauthentik/prettier-config": "^1.0.5",
"@goauthentik/tsconfig": "^1.0.4", "@goauthentik/tsconfig": "^1.0.4",
"@hcaptcha/types": "^1.0.4", "@hcaptcha/types": "^1.0.4",
"@lit/localize-tools": "^0.8.0", "@lit/localize-tools": "^0.8.0",
"@rollup/plugin-replace": "^6.0.1",
"@storybook/addon-essentials": "^8.6.14", "@storybook/addon-essentials": "^8.6.14",
"@storybook/addon-links": "^8.6.14", "@storybook/addon-links": "^8.6.12",
"@storybook/blocks": "^8.6.12", "@storybook/blocks": "^8.6.12",
"@storybook/experimental-addon-test": "^8.6.14", "@storybook/experimental-addon-test": "^8.6.14",
"@storybook/manager-api": "^8.6.14", "@storybook/manager-api": "^8.6.14",
@ -160,50 +161,50 @@
"@types/chart.js": "^2.9.41", "@types/chart.js": "^2.9.41",
"@types/codemirror": "^5.60.15", "@types/codemirror": "^5.60.15",
"@types/dompurify": "^3.0.5", "@types/dompurify": "^3.0.5",
"@types/eslint__js": "^8.42.3",
"@types/grecaptcha": "^3.0.9", "@types/grecaptcha": "^3.0.9",
"@types/guacamole-common-js": "^1.5.3", "@types/guacamole-common-js": "^1.5.2",
"@types/mocha": "^10.0.8", "@types/mocha": "^10.0.8",
"@types/node": "^22.15.21", "@types/node": "^22.7.4",
"@types/react": "^19.1.5", "@types/react": "^18.3.13",
"@types/react-dom": "^19.1.5", "@types/react-dom": "^18.3.0",
"@typescript-eslint/eslint-plugin": "^8.8.0", "@typescript-eslint/eslint-plugin": "^8.8.0",
"@typescript-eslint/parser": "^8.8.0", "@typescript-eslint/parser": "^8.8.0",
"@wdio/browser-runner": "^9.14.0", "@wdio/browser-runner": "9.4",
"@wdio/cli": "^9.14.0", "@wdio/cli": "9.4",
"@wdio/spec-reporter": "^9.14.0", "@wdio/spec-reporter": "^9.1.2",
"@web/test-runner": "^0.20.2", "chromedriver": "^131.0.1",
"chromedriver": "^136.0.3", "esbuild": "^0.25.0",
"esbuild": "^0.25.4",
"esbuild-plugin-copy": "^2.1.1", "esbuild-plugin-copy": "^2.1.1",
"esbuild-plugin-polyfill-node": "^0.3.0", "esbuild-plugin-polyfill-node": "^0.3.0",
"esbuild-plugins-node-modules-polyfill": "^1.7.0", "esbuild-plugins-node-modules-polyfill": "^1.7.0",
"eslint": "^9.11.1", "eslint": "^9.11.1",
"eslint-plugin-lit": "^2.1.1", "eslint-plugin-lit": "^1.15.0",
"eslint-plugin-wc": "^3.0.1", "eslint-plugin-wc": "^2.1.1",
"github-slugger": "^2.0.0", "github-slugger": "^2.0.0",
"globals": "^15.10.0", "globals": "^15.10.0",
"knip": "^5.30.6", "knip": "^5.30.6",
"lit-analyzer": "^2.0.3", "lit-analyzer": "^2.0.3",
"npm-run-all": "^4.1.5", "npm-run-all": "^4.1.5",
"prettier": "^3.5.3", "prettier": "^3.3.3",
"pseudolocale": "^2.1.0", "pseudolocale": "^2.1.0",
"rollup-plugin-postcss-lit": "^2.2.0", "rollup-plugin-postcss-lit": "^2.1.0",
"storybook": "^8.6.14", "storybook": "^8.6.14",
"storybook-addon-mock": "^5.0.0", "storybook-addon-mock": "^5.0.0",
"turnstile-types": "^1.2.3", "turnstile-types": "^1.2.3",
"typescript": "^5.8.3", "typescript": "^5.8.3",
"typescript-eslint": "^8.32.1", "typescript-eslint": "^8.8.0",
"vite-plugin-lit-css": "^2.0.0", "vite-plugin-lit-css": "^2.0.0",
"vite-tsconfig-paths": "^5.0.1", "vite-tsconfig-paths": "^5.0.1",
"wireit": "^0.14.9" "wireit": "^0.14.9"
}, },
"optionalDependencies": { "optionalDependencies": {
"@esbuild/darwin-arm64": "^0.25.4", "@esbuild/darwin-arm64": "^0.24.0",
"@esbuild/linux-arm64": "^0.25.4", "@esbuild/linux-amd64": "^0.18.11",
"@esbuild/linux-x64": "^0.25.4", "@esbuild/linux-arm64": "^0.24.0",
"@rollup/rollup-darwin-arm64": "^4.41.0", "@rollup/rollup-darwin-arm64": "4.23.0",
"@rollup/rollup-linux-arm64-gnu": "^4.41.0", "@rollup/rollup-linux-arm64-gnu": "4.23.0",
"@rollup/rollup-linux-x64-gnu": "^4.41.0" "@rollup/rollup-linux-x64-gnu": "4.23.0"
}, },
"wireit": { "wireit": {
"build": { "build": {
@ -238,7 +239,7 @@
], ],
"dependencies": [ "dependencies": [
"build-locales", "build-locales",
"build:sfe" "./packages/sfe:build"
], ],
"env": { "env": {
"NODE_RUNNER": { "NODE_RUNNER": {
@ -247,6 +248,14 @@
} }
} }
}, },
"build:sfe": {
"dependencies": [
"./packages/sfe:build"
],
"files": [
"./packages/sfe/**/*.ts"
]
},
"build-proxy": { "build-proxy": {
"command": "node scripts/build-web.mjs --proxy", "command": "node scripts/build-web.mjs --proxy",
"dependencies": [ "dependencies": [
@ -272,17 +281,31 @@
"extract-locales": { "extract-locales": {
"command": "lit-localize extract" "command": "lit-localize extract"
}, },
"format": {
"command": "prettier --write ."
},
"format:packages": {
"dependencies": [
"./packages/sfe:prettier"
]
},
"lint": {
"command": "eslint --max-warnings 0 --fix",
"env": {
"NODE_OPTIONS": "--max_old_space_size=65536"
}
},
"lint:components": { "lint:components": {
"command": "lit-analyzer src" "command": "lit-analyzer src"
}, },
"lint:imports": {
"command": "knip --config scripts/knip.config.ts"
},
"lint:types:tests": { "lint:types:tests": {
"command": "tsc --noEmit -p ./tests" "command": "tsc --noEmit -p ./tests"
}, },
"lint:types": { "lint:types": {
"command": "tsc -p .", "command": "NODE_OPTIONS=\"--max-old-space-size=3000\" tsc -b .",
"env": {
"NODE_OPTIONS": "--max_old_space_size=8192"
},
"dependencies": [ "dependencies": [
"build-locales", "build-locales",
"lint:types:tests" "lint:types:tests"
@ -293,18 +316,58 @@
"shell": true, "shell": true,
"command": "sh ./scripts/lint-lockfile.sh package-lock.json" "command": "sh ./scripts/lint-lockfile.sh package-lock.json"
}, },
"lint:lockfiles": {
"dependencies": [
"./packages/sfe:lint:lockfile"
]
},
"lint:nightmare": {
"command": "${NODE_RUNNER} ./scripts/eslint.mjs --nightmare",
"env": {
"NODE_RUNNER": {
"external": true,
"default": "node"
}
}
},
"lint:precommit": {
"command": "${NODE_RUNNER} ./scripts/eslint.mjs --precommit",
"env": {
"NODE_RUNNER": {
"external": true,
"default": "node"
}
}
},
"lint:spelling": {
"command": "node scripts/check-spelling.mjs"
},
"lit-analyse": { "lit-analyse": {
"command": "lit-analyzer src" "command": "lit-analyzer src"
}, },
"precommit": { "precommit": {
"command": "prettier --write .", "command": "prettier --write .",
"dependencies": [ "dependencies": [
"lint",
"lint:types", "lint:types",
"lint:components", "lint:components",
"lint:lockfile" "lint:spelling",
"lint:lockfile",
"lint:lockfiles",
"lint:precommit",
"format:packages"
] ]
}, },
"prettier": {
"dependencies": [
"format"
]
},
"prettier-check": {
"command": "prettier --check ."
},
"pseudolocalize": {
"command": "node scripts/pseudolocalize.mjs"
},
"storybook:build": { "storybook:build": {
"command": "storybook build", "command": "storybook build",
"env": { "env": {
@ -347,12 +410,8 @@
} }
}, },
"tsc": { "tsc": {
"command": "tsc -p .",
"env": {
"NODE_OPTIONS": "--max_old_space_size=8192"
},
"dependencies": [ "dependencies": [
"build-locales" "lint:types"
] ]
} }
}, },
@ -364,19 +423,11 @@
], ],
"prettier": "@goauthentik/prettier-config", "prettier": "@goauthentik/prettier-config",
"overrides": { "overrides": {
"@storybook/addon-docs": {
"react": "^19.1.0",
"react-dom": "^19.1.0"
},
"chromedriver": { "chromedriver": {
"axios": "^1.8.4" "axios": "^1.8.4"
}, },
"rapidoc": { "rapidoc": {
"@apitools/openapi-parser@": "0.0.37" "@apitools/openapi-parser@": "0.0.37"
},
"storybook-addon-mock": {
"react": "^19.1.0",
"react-dom": "^19.1.0"
} }
} }
} }

View File

@ -47,9 +47,9 @@
"devDependencies": { "devDependencies": {
"@goauthentik/prettier-config": "^1.0.4", "@goauthentik/prettier-config": "^1.0.4",
"@goauthentik/tsconfig": "^1.0.4", "@goauthentik/tsconfig": "^1.0.4",
"@types/node": "^22.15.21", "@types/node": "^22.14.1",
"prettier": "^3.5.3", "prettier": "^3.3.3",
"typescript": "^5.8.3" "typescript": "^5.6.2"
}, },
"engines": { "engines": {
"node": ">=20.11" "node": ">=20.11"

View File

@ -1,40 +0,0 @@
# `@goauthentik/esbuild-plugin-live-reload`
_A plugin that enables live reloading of ESBuild during development._
## Usage
### Node.js setup
```js
import { liveReloadPlugin } from "@goauthentik/esbuild-plugin-live-reload";
import esbuild from "esbuild";
const NodeEnvironment = process.env.NODE_ENV || "development";
/**
* @type {esbuild.BuildOptions}
*/
const buildOptions = {
// ... Your build options.
define: {
"process.env.NODE_ENV": JSON.stringify(NodeEnvironment),
},
plugins: [liveReloadPlugin(/** @see {@link LiveReloadPluginOptions} */)],
};
const buildContext = await esbuild.context(buildOptions);
await buildContext.rebuild();
await buildContext.watch();
```
### Browser setup
```js
// Place this at the beginning of your application's entry point.
if (process.env.NODE_ENV === "development") {
await import("@goauthentik/esbuild-plugin-live-reload/client");
}
```

View File

@ -21,7 +21,7 @@ const log = console.debug.bind(console, logPrefix);
* ESBuild may tree-shake it out of production builds. * ESBuild may tree-shake it out of production builds.
* *
* ```ts * ```ts
* if (process.env.NODE_ENV === "development") { * if (process.env.NODE_ENV=== "development") {
* await import("@goauthentik/esbuild-plugin-live-reload/client") * await import("@goauthentik/esbuild-plugin-live-reload/client")
* .catch(() => console.warn("Failed to import watcher")) * .catch(() => console.warn("Failed to import watcher"))
* } * }

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +1,9 @@
{ {
"name": "@goauthentik/esbuild-plugin-live-reload", "name": "@goauthentik/esbuild-plugin-live-reload",
"version": "1.0.5", "version": "1.0.4",
"description": "ESBuild plugin to watch for file changes and trigger client-side reloads.", "description": "ESBuild plugin to watch for file changes and trigger client-side reloads.",
"license": "MIT", "license": "MIT",
"scripts": { "private": true,
"build": "tsc -p ."
},
"main": "index.js", "main": "index.js",
"type": "module", "type": "module",
"exports": { "exports": {
@ -27,20 +25,19 @@
"find-free-ports": "^3.1.1" "find-free-ports": "^3.1.1"
}, },
"devDependencies": { "devDependencies": {
"@goauthentik/prettier-config": "^1.0.5", "@goauthentik/prettier-config": "^1.0.4",
"@goauthentik/tsconfig": "^1.0.4", "@goauthentik/tsconfig": "^1.0.4",
"@trivago/prettier-plugin-sort-imports": "^5.2.2", "@trivago/prettier-plugin-sort-imports": "^5.2.2",
"@types/node": "^22.15.21", "@types/node": "^22.14.1",
"esbuild": "^0.25.4", "esbuild": "^0.25.0",
"prettier": "^3.5.3", "prettier": "^3.3.3",
"prettier-plugin-packagejson": "^2.5.14", "typescript": "^5.6.2"
"typescript": "^5.8.3"
}, },
"peerDependencies": { "peerDependencies": {
"esbuild": "^0.25.4" "esbuild": "^0.25.0"
}, },
"engines": { "engines": {
"node": ">=22.15.1" "node": ">=20.11"
}, },
"types": "./out/index.d.ts", "types": "./out/index.d.ts",
"files": [ "files": [

View File

@ -67,6 +67,7 @@ async function findDisparatePort() {
* @category ESBuild * @category ESBuild
*/ */
export function createRequestHandler({ pathname, dispatcher, logPrefix = "Build Observer" }) { export function createRequestHandler({ pathname, dispatcher, logPrefix = "Build Observer" }) {
// eslint-disable-next-line no-console
const log = console.log.bind(console, `[${logPrefix}]`); const log = console.log.bind(console, `[${logPrefix}]`);
/** /**
@ -129,20 +130,19 @@ export function createRequestHandler({ pathname, dispatcher, logPrefix = "Build
/** /**
* Options for the build observer plugin. * Options for the build observer plugin.
* *
* @typedef {object} LiveReloadPluginOptions * @typedef {object} BuildObserverOptions
* *
* @property {HTTPServer | HTTPSServer} [server] A server to listen on. If not provided, a new server will be created. * @property {HTTPServer | HTTPSServer} [server]
* @property {ListenOptions} [listenOptions] Options for the server's listen method. * @property {ListenOptions} [listenOptions]
* @property {string | URL} [publicURL] A URL to listen on. If not provided, a random port will be used. * @property {string | URL} [publicURL]
* @property {string} [logPrefix] A prefix to use for log messages. * @property {string} [logPrefix]
* @property {string} [relativeRoot] A relative path to the root of the project. This is used to resolve build errors, line numbers, and file paths. * @property {string} [relativeRoot]
*/ */
/** /**
* Creates a plugin that listens for build events and sends them to a server-sent event stream. * Creates a plugin that listens for build events and sends them to a server-sent event stream.
* *
* @param { * @param {BuildObserverOptions} [options]
* } [options]
* @returns {import('esbuild').Plugin} * @returns {import('esbuild').Plugin}
*/ */
export function liveReloadPlugin(options = {}) { export function liveReloadPlugin(options = {}) {
@ -177,10 +177,6 @@ export function liveReloadPlugin(options = {}) {
"import.meta.env.ESBUILD_WATCHER_URL": JSON.stringify(publicURL.href), "import.meta.env.ESBUILD_WATCHER_URL": JSON.stringify(publicURL.href),
}; };
build.initialOptions.define["process.env.NODE_ENV"] ??= JSON.stringify(
process.env.NODE_ENV || "development",
);
const requestHandler = createRequestHandler({ const requestHandler = createRequestHandler({
pathname: publicURL.pathname, pathname: publicURL.pathname,
dispatcher, dispatcher,
@ -195,6 +191,7 @@ export function liveReloadPlugin(options = {}) {
}; };
server.listen(listenOptions, () => { server.listen(listenOptions, () => {
// eslint-disable-next-line no-console
console.log(`[${logPrefix}] Listening`); console.log(`[${logPrefix}] Listening`);
}); });
@ -244,5 +241,3 @@ export function liveReloadPlugin(options = {}) {
}, },
}; };
} }
export default liveReloadPlugin;

View File

@ -1,5 +1,5 @@
{ {
"name": "@goauthentik/web-sfe", "name": "@goauthentik/sfe",
"version": "0.0.0", "version": "0.0.0",
"license": "MIT", "license": "MIT",
"private": true, "private": true,
@ -9,6 +9,7 @@
"prettier-check": "prettier --cache --check -u .", "prettier-check": "prettier --cache --check -u .",
"watch": "rollup -w -c rollup.config.mjs --bundleConfigAsCjs" "watch": "rollup -w -c rollup.config.mjs --bundleConfigAsCjs"
}, },
"type": "module",
"dependencies": { "dependencies": {
"@goauthentik/api": "^2024.6.0-1719577139", "@goauthentik/api": "^2024.6.0-1719577139",
"base64-js": "^1.5.1", "base64-js": "^1.5.1",
@ -19,15 +20,20 @@
}, },
"devDependencies": { "devDependencies": {
"@goauthentik/core": "^1.0.0", "@goauthentik/core": "^1.0.0",
"@goauthentik/prettier-config": "^1.0.1",
"@goauthentik/tsconfig": "^1.0.1",
"@goauthentik/web": "file:../web",
"@rollup/plugin-commonjs": "^28.0.0", "@rollup/plugin-commonjs": "^28.0.0",
"@rollup/plugin-node-resolve": "^16.0.1", "@rollup/plugin-node-resolve": "^15.3.0",
"@rollup/plugin-swc": "^0.4.0", "@rollup/plugin-swc": "^0.4.0",
"@swc/cli": "^0.4.0", "@swc/cli": "^0.4.0",
"@swc/core": "^1.7.28", "@swc/core": "^1.7.28",
"@trivago/prettier-plugin-sort-imports": "^5.2.2", "@trivago/prettier-plugin-sort-imports": "^5.2.2",
"prettier": "^3.5.3", "prettier": "^3.5.3",
"rollup": "^4.23.0", "prettier-plugin-packagejson": "^2.5.13",
"rollup-plugin-copy": "^3.5.0" "rollup": "^4.40.2",
"rollup-plugin-copy": "^3.5.0",
"typescript": "^5.8.3"
}, },
"optionalDependencies": { "optionalDependencies": {
"@swc/core": "^1.7.28", "@swc/core": "^1.7.28",
@ -41,5 +47,9 @@
"@swc/core-win32-arm64-msvc": "^1.6.13", "@swc/core-win32-arm64-msvc": "^1.6.13",
"@swc/core-win32-ia32-msvc": "^1.6.13", "@swc/core-win32-ia32-msvc": "^1.6.13",
"@swc/core-win32-x64-msvc": "^1.6.13" "@swc/core-win32-x64-msvc": "^1.6.13"
} },
"engines": {
"node": ">=22.15.1"
},
"prettier": "@goauthentik/prettier-config"
} }

View File

@ -1,61 +1,65 @@
/** /**
* @file Rollup configuration for the SFE package. * @file Rollup configuration for the SFE package.
*
* @import { RollupOptions } from "rollup";
*/ */
import { resolvePackage } from "@goauthentik/core/paths/node";
import commonjs from "@rollup/plugin-commonjs"; import commonjs from "@rollup/plugin-commonjs";
import resolve from "@rollup/plugin-node-resolve"; import resolve from "@rollup/plugin-node-resolve";
import swc from "@rollup/plugin-swc"; import swc from "@rollup/plugin-swc";
import { resolve as resolvePath } from "node:path"; import { resolve as resolvePath } from "node:path";
import copy from "rollup-plugin-copy"; import copy from "rollup-plugin-copy";
export async function createConfig() { import { DistDirectory } from "../../paths/node.js";
// TODO: Move this to a synchronous import once the repo root has NPM Workspaces.
const { resolvePackage, MonoRepoRoot } = await import("@goauthentik/core/paths/node");
const distDirectory = resolvePath(MonoRepoRoot, "web", "dist", "sfe"); const distDirectory = resolvePath(DistDirectory, "sfe");
const bootstrapDirectory = resolvePackage("bootstrap", import.meta);
const config = { /**
input: "src/index.ts", * @type {RollupOptions}
output: { */
dir: distDirectory, const config = {
format: "cjs", input: "src/index.ts",
}, output: {
context: "window", dir: distDirectory,
plugins: [ format: "cjs",
copy({ },
targets: [ context: "window",
{ plugins: [
src: resolvePath(bootstrapDirectory, "dist", "css", "bootstrap.min.css"), copy({
dest: distDirectory, targets: [
}, {
], src: resolvePackage(
}), "bootstrap",
resolve({ browser: true }), "dist",
commonjs(), "css",
swc({ "bootstrap.min.css",
swc: { import.meta,
jsc: { ),
loose: false, dest: distDirectory,
externalHelpers: false,
// Requires v1.2.50 or upper and requires target to be es2016 or upper.
keepClassNames: false,
},
minify: false,
env: {
targets: {
edge: "17",
ie: "11",
},
mode: "entry",
},
}, },
}), ],
], }),
}; resolve({ browser: true }),
commonjs(),
swc({
swc: {
jsc: {
loose: false,
externalHelpers: false,
// Requires v1.2.50 or upper and requires target to be es2016 or upper.
keepClassNames: false,
},
minify: false,
env: {
targets: {
edge: "17",
ie: "11",
},
mode: "entry",
},
},
}),
],
};
return config; export default config;
}
console.log("Preparing SFE package...");
export default createConfig;

View File

@ -1,8 +1,7 @@
{ {
"compilerOptions": { "compilerOptions": {
"noEmit": true, "noEmit": true,
"baseUrl": ".", "declaration": false,
"outDir": "out",
"types": [], "types": [],
"esModuleInterop": true, "esModuleInterop": true,
"lib": ["DOM", "ES2015", "ES2017"] "lib": ["DOM", "ES2015", "ES2017"]

View File

@ -10,7 +10,6 @@
* summary of how many strings are missing with respect to the source locale. * summary of how many strings are missing with respect to the source locale.
* *
* @import { ConfigFile } from "@lit/localize-tools/lib/types/config" * @import { ConfigFile } from "@lit/localize-tools/lib/types/config"
* @import { Stats } from "fs";
*/ */
import { PackageRoot } from "#paths/node"; import { PackageRoot } from "#paths/node";
import { spawnSync } from "node:child_process"; import { spawnSync } from "node:child_process";
@ -38,26 +37,16 @@ function generatedFileIsUpToDateWithXliffSource(loc) {
// than the generated file. The missing XLF file is important enough it // than the generated file. The missing XLF file is important enough it
// generates a unique error message and halts the build. // generates a unique error message and halts the build.
/**
* @type {Stats}
*/
let xlfStat;
try { try {
xlfStat = statSync(xliff); var xlfStat = statSync(xliff);
} catch (_error) { } catch (_error) {
console.error(`lit-localize expected '${loc}.xlf', but XLF file is not present`); console.error(`lit-localize expected '${loc}.xlf', but XLF file is not present`);
process.exit(1); process.exit(1);
} }
/**
* @type {Stats}
*/
let genedStat;
// If the generated file doesn't exist, of course it's not up to date. // If the generated file doesn't exist, of course it's not up to date.
try { try {
genedStat = statSync(gened); var genedStat = statSync(gened);
} catch (_error) { } catch (_error) {
return false; return false;
} }

View File

@ -10,6 +10,7 @@ import { DistDirectory, DistDirectoryName, EntryPoint, PackageRoot } from "#path
import { NodeEnvironment } from "@goauthentik/core/environment/node"; import { NodeEnvironment } from "@goauthentik/core/environment/node";
import { MonoRepoRoot, resolvePackage } from "@goauthentik/core/paths/node"; import { MonoRepoRoot, resolvePackage } from "@goauthentik/core/paths/node";
import { readBuildIdentifier } from "@goauthentik/core/version/node"; import { readBuildIdentifier } from "@goauthentik/core/version/node";
import { liveReloadPlugin } from "@goauthentik/esbuild-plugin-live-reload/plugin";
import { deepmerge } from "deepmerge-ts"; import { deepmerge } from "deepmerge-ts";
import esbuild from "esbuild"; import esbuild from "esbuild";
import copy from "esbuild-plugin-copy"; import copy from "esbuild-plugin-copy";
@ -144,17 +145,13 @@ async function doWatch() {
console.groupEnd(); console.groupEnd();
const developmentPlugins = await import("@goauthentik/esbuild-plugin-live-reload/plugin") const buildOptions = createESBuildOptions({
.then(({ liveReloadPlugin }) => [ entryPoints,
plugins: [
liveReloadPlugin({ liveReloadPlugin({
relativeRoot: PackageRoot, relativeRoot: PackageRoot,
}), }),
]) ],
.catch(() => []);
const buildOptions = createESBuildOptions({
entryPoints,
plugins: developmentPlugins,
}); });
const buildContext = await esbuild.context(buildOptions); const buildContext = await esbuild.context(buildOptions);
@ -165,7 +162,7 @@ async function doWatch() {
const httpURL = new URL("http://localhost"); const httpURL = new URL("http://localhost");
httpURL.port = process.env.COMPOSE_PORT_HTTP ?? "9000"; httpURL.port = process.env.COMPOSE_PORT_HTTP ?? "9000";
const httpsURL = new URL("https://localhost"); const httpsURL = new URL("http://localhost");
httpsURL.port = process.env.COMPOSE_PORT_HTTPS ?? "9443"; httpsURL.port = process.env.COMPOSE_PORT_HTTPS ?? "9443";
console.log(`\n${logPrefix} 🚀 Server running\n\n`); console.log(`\n${logPrefix} 🚀 Server running\n\n`);
@ -239,6 +236,7 @@ await cleanDistDirectory()
.then(() => .then(() =>
delegateCommand() delegateCommand()
.then(() => { .then(() => {
console.log("Build complete");
process.exit(0); process.exit(0);
}) })
.catch((error) => { .catch((error) => {

View File

@ -0,0 +1,15 @@
import { execSync } from "child_process";
import path from "path";
const projectRoot = execSync("git rev-parse --show-toplevel", { encoding: "utf8" }).replace(
"\n",
"",
);
const cmd = [
"codespell -D -",
`-D ${path.join(projectRoot, ".github/codespell-dictionary.txt")}`,
`-I ${path.join(projectRoot, ".github/codespell-words.txt")}`,
"-S './src/locales/**' ./src -s",
].join(" ");
console.log(execSync(cmd, { encoding: "utf8" }));

61
web/scripts/eslint.mjs Normal file
View File

@ -0,0 +1,61 @@
import { execFileSync } from "child_process";
import { ESLint } from "eslint";
import fs from "fs";
import path from "path";
import process from "process";
import { fileURLToPath } from "url";
function changedFiles() {
const gitStatus = execFileSync("git", ["diff", "--name-only", "HEAD"], { encoding: "utf8" });
const gitUntracked = execFileSync("git", ["ls-files", "--others", "--exclude-standard"], {
encoding: "utf8",
});
const changed = gitStatus
.split("\n")
.filter((line) => line.trim().substring(0, 4) === "web/")
.filter((line) => /\.(m|c)?(t|j)s$/.test(line))
.map((line) => line.substring(4))
.filter((line) => fs.existsSync(line));
const untracked = gitUntracked
.split("\n")
.filter((line) => /\.(m|c)?(t|j)s$/.test(line))
.filter((line) => fs.existsSync(line));
const sourceFiles = [...changed, ...untracked].filter((line) => /^src\//.test(line));
const scriptFiles = [...changed, ...untracked].filter(
(line) => /^scripts\//.test(line) || !/^src\//.test(line),
);
return [...sourceFiles, ...scriptFiles];
}
const __dirname = fileURLToPath(new URL(".", import.meta.url));
const projectRoot = path.join(__dirname, "..");
process.chdir(projectRoot);
/**
*
* @param {string[]} flags
* @returns
*/
const hasFlag = (flags) => process.argv.length > 1 && flags.includes(process.argv[2]);
const [configFile, files] = hasFlag(["-n", "--nightmare"])
? [path.join(__dirname, "eslint.nightmare.mjs"), changedFiles()]
: hasFlag(["-p", "--precommit"])
? [path.join(__dirname, "eslint.precommit.mjs"), changedFiles()]
: [path.join(projectRoot, "eslint.config.mjs"), ["."]];
const eslint = new ESLint({
overrideConfigFile: configFile,
warnIgnored: false,
});
const results = await eslint.lintFiles(files);
const formatter = await eslint.loadFormatter("stylish");
const resultText = formatter.format(results);
const errors = results.reduce((acc, result) => acc + result.errorCount, 0);
console.log(resultText);
process.exit(errors > 1 ? 1 : 0);

View File

@ -0,0 +1,218 @@
import eslint from "@eslint/js";
import tsparser from "@typescript-eslint/parser";
import litconf from "eslint-plugin-lit";
import wcconf from "eslint-plugin-wc";
import globals from "globals";
import tseslint from "typescript-eslint";
const MAX_DEPTH = 4;
const MAX_NESTED_CALLBACKS = 4;
const MAX_PARAMS = 5;
// Waiting for SonarJS to be compatible
// const MAX_COGNITIVE_COMPLEXITY = 9;
const rules = {
"accessor-pairs": "error",
"array-callback-return": "error",
"block-scoped-var": "error",
"consistent-return": "error",
"consistent-this": ["error", "that"],
"curly": ["error", "all"],
"dot-notation": [
"error",
{
allowKeywords: true,
},
],
"eqeqeq": "error",
"func-names": "error",
"guard-for-in": "error",
"max-depth": ["error", MAX_DEPTH],
"max-nested-callbacks": ["error", MAX_NESTED_CALLBACKS],
"max-params": ["error", MAX_PARAMS],
"new-cap": "error",
"no-alert": "error",
"no-array-constructor": "error",
"no-bitwise": "error",
"no-caller": "error",
"no-case-declarations": "error",
"no-class-assign": "error",
"no-cond-assign": "error",
"no-const-assign": "error",
"no-constant-condition": "error",
"no-control-regex": "error",
"no-debugger": "error",
"no-delete-var": "error",
"no-div-regex": "error",
"no-dupe-args": "error",
"no-dupe-keys": "error",
"no-duplicate-case": "error",
"no-else-return": "error",
"no-empty": "error",
"no-empty-character-class": "error",
"no-empty-function": "error",
"no-labels": "error",
"no-eq-null": "error",
"no-eval": "error",
"no-ex-assign": "error",
"no-extend-native": "error",
"no-extra-bind": "error",
"no-extra-boolean-cast": "error",
"no-extra-label": "error",
"no-fallthrough": "error",
"no-func-assign": "error",
"no-implied-eval": "error",
"no-implicit-coercion": "error",
"no-implicit-globals": "error",
"no-inner-declarations": ["error", "functions"],
"no-invalid-regexp": "error",
"no-irregular-whitespace": "error",
"no-iterator": "error",
"no-invalid-this": "error",
"no-label-var": "error",
"no-lone-blocks": "error",
"no-lonely-if": "error",
"no-loop-func": "error",
"no-magic-numbers": ["error", { ignore: [0, 1, -1] }],
"no-multi-str": "error",
"no-negated-condition": "error",
"no-nested-ternary": "error",
"no-new": "error",
"no-new-func": "error",
"no-new-wrappers": "error",
"no-obj-calls": "error",
"no-octal": "error",
"no-octal-escape": "error",
"no-param-reassign": "error",
"no-proto": "error",
"no-redeclare": "error",
"no-regex-spaces": "error",
"no-restricted-syntax": ["error", "WithStatement"],
"no-script-url": "error",
"no-self-assign": "error",
"no-self-compare": "error",
"no-sequences": "error",
"no-shadow": "error",
"no-shadow-restricted-names": "error",
"no-sparse-arrays": "error",
"no-this-before-super": "error",
"no-throw-literal": "error",
"no-trailing-spaces": "error",
"no-undef": "error",
"no-undef-init": "error",
"no-unexpected-multiline": "error",
"no-useless-constructor": "error",
"no-unmodified-loop-condition": "error",
"no-unneeded-ternary": "error",
"no-unreachable": "error",
"no-unused-expressions": "error",
"no-unused-labels": "error",
"no-use-before-define": "error",
"no-useless-call": "error",
"no-dupe-class-members": "error",
"no-var": "error",
"no-void": "error",
"no-with": "error",
"prefer-arrow-callback": "error",
"prefer-const": "error",
"prefer-rest-params": "error",
"prefer-spread": "error",
"prefer-template": "error",
"radix": "error",
"require-yield": "error",
"strict": ["error", "global"],
"use-isnan": "error",
"valid-typeof": "error",
"vars-on-top": "error",
"yoda": ["error", "never"],
"no-unused-vars": "off",
"no-console": ["error", { allow: ["debug", "warn", "error"] }],
// SonarJS is not yet compatible with ESLint 9. Commenting these out
// until it is.
// "sonarjs/cognitive-complexity": ["off", MAX_COGNITIVE_COMPLEXITY],
// "sonarjs/no-duplicate-string": "off",
// "sonarjs/no-nested-template-literals": "off",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/no-unused-vars": [
"error",
{
argsIgnorePattern: "^_",
varsIgnorePattern: "^_",
caughtErrorsIgnorePattern: "^_",
},
],
};
export default [
// You would not believe how much this change has frustrated users: ["if an ignores key is used
// without any other keys in the configuration object, then the patterns act as global
// ignores"](https://eslint.org/docs/latest/use/configure/ignore)
{
ignores: [
"dist/",
"out/",
".wireit/",
"packages/",
// don't ever lint node_modules
"node_modules/",
".storybook/*",
// don't lint build output (make sure it's set to your correct build folder name)
// don't lint nyc coverage output
"coverage/",
"src/locale-codes.ts",
"storybook-static/",
"src/locales/",
"src/**/*.test.ts",
],
},
eslint.configs.recommended,
wcconf.configs["flat/recommended"],
litconf.configs["flat/recommended"],
...tseslint.configs.recommended,
// sonar.configs.recommended,
{
languageOptions: {
parser: tsparser,
parserOptions: {
ecmaVersion: 12,
sourceType: "module",
},
globals: {
...globals.browser,
},
},
files: ["src/**"],
rules,
},
{
languageOptions: {
parser: tsparser,
parserOptions: {
ecmaVersion: 12,
sourceType: "module",
},
globals: {
...globals.nodeBuiltin,
},
},
files: ["scripts/*.mjs", "*.ts", "*.mjs"],
rules,
},
{
languageOptions: {
parser: tsparser,
parserOptions: {
ecmaVersion: 12,
sourceType: "module",
},
globals: {
...globals.nodeBuiltin,
...globals.jest,
},
},
files: ["src/**/*.test.ts"],
rules,
},
];

View File

@ -0,0 +1,88 @@
import eslint from "@eslint/js";
import tsparser from "@typescript-eslint/parser";
import litconf from "eslint-plugin-lit";
import wcconf from "eslint-plugin-wc";
import globals from "globals";
import tseslint from "typescript-eslint";
export default [
// You would not believe how much this change has frustrated users: ["if an ignores key is used
// without any other keys in the configuration object, then the patterns act as global
// ignores"](https://eslint.org/docs/latest/use/configure/ignore)
{
ignores: [
"dist/",
".wireit/",
"packages/",
// don't ever lint node_modules
"node_modules/",
".storybook/*",
// don't lint build output (make sure it's set to your correct build folder name)
// don't lint nyc coverage output
"coverage/",
"src/locale-codes.ts",
"storybook-static/",
"scripts/esbuild",
"src/locales/",
],
},
eslint.configs.recommended,
wcconf.configs["flat/recommended"],
litconf.configs["flat/recommended"],
...tseslint.configs.recommended,
// sonar.configs.recommended,
{
languageOptions: {
parser: tsparser,
parserOptions: {
ecmaVersion: 12,
sourceType: "module",
},
},
files: ["src/**"],
rules: {
"no-unused-vars": "off",
"no-console": ["error", { allow: ["debug", "warn", "error"] }],
// SonarJS is not yet compatible with ESLint 9. Commenting these out
// until it is.
// "sonarjs/cognitive-complexity": ["off", 9],
// "sonarjs/no-duplicate-string": "off",
// "sonarjs/no-nested-template-literals": "off",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/no-unused-vars": [
"error",
{
argsIgnorePattern: "^_",
varsIgnorePattern: "^_",
caughtErrorsIgnorePattern: "^_",
},
],
},
},
{
languageOptions: {
parser: tsparser,
parserOptions: {
ecmaVersion: 12,
sourceType: "module",
},
globals: {
...globals.nodeBuiltin,
},
},
files: ["scripts/*.mjs", "*.ts", "*.mjs"],
rules: {
"no-unused-vars": "off",
"no-console": "off",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/no-unused-vars": [
"error",
{
argsIgnorePattern: "^_",
varsIgnorePattern: "^_",
caughtErrorsIgnorePattern: "^_",
},
],
},
},
];

View File

@ -32,7 +32,7 @@ import PFNav from "@patternfly/patternfly/components/Nav/nav.css";
import PFPage from "@patternfly/patternfly/components/Page/page.css"; import PFPage from "@patternfly/patternfly/components/Page/page.css";
import PFBase from "@patternfly/patternfly/patternfly-base.css"; import PFBase from "@patternfly/patternfly/patternfly-base.css";
import { CapabilitiesEnum, SessionUser, UiThemeEnum } from "@goauthentik/api"; import { LicenseSummaryStatusEnum, SessionUser, UiThemeEnum } from "@goauthentik/api";
import { import {
AdminSidebarEnterpriseEntries, AdminSidebarEnterpriseEntries,
@ -202,7 +202,7 @@ export class AdminInterface extends WithLicenseSummary(AuthenticatedInterface) {
<ak-sidebar class="${classMap(sidebarClasses)}"> <ak-sidebar class="${classMap(sidebarClasses)}">
${renderSidebarItems(AdminSidebarEntries)} ${renderSidebarItems(AdminSidebarEntries)}
${this.config?.capabilities.includes(CapabilitiesEnum.IsEnterprise) ${this.licenseSummary?.status !== LicenseSummaryStatusEnum.Unlicensed
? renderSidebarItems(AdminSidebarEnterpriseEntries) ? renderSidebarItems(AdminSidebarEnterpriseEntries)
: nothing} : nothing}
</ak-sidebar> </ak-sidebar>

View File

@ -39,11 +39,8 @@ export class LoggingMiddleware implements Middleware {
export class CSRFMiddleware implements Middleware { export class CSRFMiddleware implements Middleware {
pre?(context: RequestContext): Promise<FetchParams | void> { pre?(context: RequestContext): Promise<FetchParams | void> {
context.init.headers = { // @ts-ignore
...context.init.headers, context.init.headers[CSRFHeaderName] = getCookie("authentik_csrf");
[CSRFHeaderName]: getCookie("authentik_csrf"),
};
return Promise.resolve(context); return Promise.resolve(context);
} }
} }

View File

@ -4,18 +4,14 @@ import { FetchParams, Middleware, RequestContext } from "@goauthentik/api";
export class SentryMiddleware implements Middleware { export class SentryMiddleware implements Middleware {
pre?(context: RequestContext): Promise<FetchParams | void> { pre?(context: RequestContext): Promise<FetchParams | void> {
if (!getCurrentScope().getClient) { if (getCurrentScope().getClient === undefined) {
return Promise.resolve(context); return Promise.resolve(context);
} }
const traceData = getTraceData(); const traceData = getTraceData();
// @ts-ignore
context.init.headers = { context.init.headers["baggage"] = traceData["baggage"];
...context.init.headers, // @ts-ignore
"baggage": traceData.baggage || "", context.init.headers["sentry-trace"] = traceData["sentry-trace"];
"sentry-trace": traceData["sentry-trace"] || "",
};
return Promise.resolve(context); return Promise.resolve(context);
} }
} }

View File

@ -10,52 +10,52 @@ const DOCS_DOMAIN = "https://goauthentik.io";
* - Resolves relative links to the public directory in the public docs domain. * - Resolves relative links to the public directory in the public docs domain.
* - Intercepts local links and scrolls to the target element. * - Intercepts local links and scrolls to the target element.
*/ */
export const MDXAnchor = ({ export const MDXAnchor = memo<React.AnchorHTMLAttributes<HTMLAnchorElement>>(
href, ({ href, children, ...props }) => {
children, const { publicDirectory } = useMDXModule();
...props
}: React.AnchorHTMLAttributes<HTMLAnchorElement>) => {
const { publicDirectory } = useMDXModule();
if (href?.startsWith(".") && publicDirectory) { if (href?.startsWith(".") && publicDirectory) {
const nextPathname = resolve(publicDirectory, href); const nextPathname = resolve(publicDirectory, href);
const nextURL = new URL(nextPathname, DOCS_DOMAIN); const nextURL = new URL(nextPathname, DOCS_DOMAIN);
// Remove trailing .md and .mdx, and trailing "index". // Remove trailing .md and .mdx, and trailing "index".
nextURL.pathname = nextURL.pathname.replace(/(index)?\.mdx?$/, ""); nextURL.pathname = nextURL.pathname.replace(/(index)?\.mdx?$/, "");
href = nextURL.toString(); href = nextURL.toString();
}
const interceptHeadingLinks = (event: React.MouseEvent<HTMLAnchorElement>) => {
if (!href || !href.startsWith("#")) return;
event.preventDefault();
const rootNode = event.currentTarget.getRootNode() as ShadowRoot;
const elementID = href.slice(1);
const target = rootNode.getElementById(elementID);
if (!target) {
console.warn(`Element with ID ${elementID} not found`);
return;
} }
target.scrollIntoView({ const interceptHeadingLinks = (event: React.MouseEvent<HTMLAnchorElement>) => {
behavior: "smooth", if (!href || !href.startsWith("#")) return;
block: "center",
});
};
return ( event.preventDefault();
<a
href={href} const rootNode = event.currentTarget.getRootNode() as ShadowRoot;
onClick={interceptHeadingLinks}
rel="noopener noreferrer" const elementID = href.slice(1);
target="_blank" const target = rootNode.getElementById(elementID);
{...props}
> if (!target) {
{children} console.warn(`Element with ID ${elementID} not found`);
</a> return;
); }
};
target.scrollIntoView({
behavior: "smooth",
block: "center",
});
};
return (
<a
href={href}
onClick={interceptHeadingLinks}
rel="noopener noreferrer"
target="_blank"
{...props}
>
{children}
</a>
);
},
);
MDXAnchor.displayName = "MDXAnchor";

View File

@ -8,7 +8,7 @@ export interface MDXWrapperProps {
/** /**
* A wrapper component for MDX content that adds a title if one is provided in the frontmatter. * A wrapper component for MDX content that adds a title if one is provided in the frontmatter.
*/ */
export const MDXWrapper = ({ children, frontmatter }: MDXWrapperProps) => { export const MDXWrapper: React.FC<MDXWrapperProps> = ({ children, frontmatter }) => {
const { title } = frontmatter; const { title } = frontmatter;
const nextChildren = React.Children.toArray(children); const nextChildren = React.Children.toArray(children);

View File

@ -4,13 +4,12 @@ import { Route } from "@goauthentik/elements/router/Route";
import { RouteMatch } from "@goauthentik/elements/router/RouteMatch"; import { RouteMatch } from "@goauthentik/elements/router/RouteMatch";
import "@goauthentik/elements/router/Router404"; import "@goauthentik/elements/router/Router404";
import { import {
BrowserClient,
SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,
Span,
getClient, getClient,
startBrowserTracingNavigationSpan, startBrowserTracingNavigationSpan,
startBrowserTracingPageLoadSpan, startBrowserTracingPageLoadSpan,
} from "@sentry/browser"; } from "@sentry/browser";
import { Client, Span } from "@sentry/types";
import { CSSResult, PropertyValues, TemplateResult, css, html } from "lit"; import { CSSResult, PropertyValues, TemplateResult, css, html } from "lit";
import { customElement, property } from "lit/decorators.js"; import { customElement, property } from "lit/decorators.js";
@ -61,7 +60,7 @@ export class RouterOutlet extends AKElement {
@property({ attribute: false }) @property({ attribute: false })
routes: Route[] = []; routes: Route[] = [];
private sentryClient?: BrowserClient; private sentryClient?: Client;
private pageLoadSpan?: Span; private pageLoadSpan?: Span;
static get styles(): CSSResult[] { static get styles(): CSSResult[] {

View File

@ -121,7 +121,8 @@ export async function setSearchSelect(name: string, value: string | RegExp) {
const control = await $(`>>>ak-search-select[name="${name}"]`); const control = await $(`>>>ak-search-select[name="${name}"]`);
await control.waitForExist({ timeout: 500 }); await control.waitForExist({ timeout: 500 });
return control; return control;
} catch (_e: unknown) { // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
} catch (_e: any) {
const control = await $(`>>>ak-search-selects-ez[name="${name}"]`); const control = await $(`>>>ak-search-selects-ez[name="${name}"]`);
return control; return control;
} }

View File

@ -61,7 +61,8 @@ export default class Page {
const control = await $(`ak-search-select[name="${name}"]`); const control = await $(`ak-search-select[name="${name}"]`);
await control.waitForExist({ timeout: 500 }); await control.waitForExist({ timeout: 500 });
return control; return control;
} catch (_e: unknown) { // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
} catch (_e: any) {
const control = await $(`ak-search-selects-ez[name="${name}"]`); const control = await $(`ak-search-selects-ez[name="${name}"]`);
return control; return control;
} }

View File

@ -1,3 +1,4 @@
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-nocheck // @ts-nocheck
// ^^^^^^^^^^^ Because TSC cannot handle metaprogramming, and metaprogramming // ^^^^^^^^^^^ Because TSC cannot handle metaprogramming, and metaprogramming
// via `defineProperties` is how we installed the OUID finders for the various // via `defineProperties` is how we installed the OUID finders for the various

View File

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

View File

@ -1,123 +0,0 @@
/**
* @file WebdriverIO configuration file for **component unit tests**.
*
* @see https://webdriver.io/docs/configurationfile.html
*/
import { cwd } from "process";
import litCSS from "vite-plugin-lit-css";
import tsconfigPaths from "vite-tsconfig-paths";
import { addCommands } from "../commands.mjs";
const NODE_ENV = process.env.NODE_ENV || "development";
const headless = !!process.env.HEADLESS || !!process.env.CI;
const lemmeSee = !!process.env.WDIO_LEMME_SEE;
/**
* @type {WebdriverIO.Capabilities[]}
*/
const capabilities = [];
const DEFAULT_MAX_INSTANCES = 10;
let maxInstances = 1;
if (headless) {
maxInstances = process.env.MAX_INSTANCES
? parseInt(process.env.MAX_INSTANCES, 10)
: DEFAULT_MAX_INSTANCES;
}
if (!process.env.WDIO_SKIP_CHROME) {
/**
* @satisfies {WebdriverIO.Capabilities}
*/
const chromeBrowserConfig = {
"browserName": "chrome",
"goog:chromeOptions": {
args: ["disable-search-engine-choice-screen"],
},
};
if (headless) {
chromeBrowserConfig["goog:chromeOptions"].args.push(
"headless",
"disable-gpu",
"no-sandbox",
"window-size=1280,672",
"browser-test",
);
}
capabilities.push(chromeBrowserConfig);
}
if (process.env.WDIO_TEST_SAFARI) {
capabilities.push({
browserName: "safari",
});
}
if (process.env.WDIO_TEST_FIREFOX) {
capabilities.push({
browserName: "firefox",
});
}
/**
* @type {WebdriverIO.BrowserRunnerOptions}
*/
const browserRunnerOptions = {
viteConfig: {
define: {
"process.env.NODE_ENV": JSON.stringify(NODE_ENV),
"process.env.CWD": JSON.stringify(cwd()),
"process.env.AK_API_BASE_PATH": JSON.stringify(process.env.AK_API_BASE_PATH || ""),
},
plugins: [
// ---
// @ts-ignore WDIO's Vite is out of date.
litCSS(),
// @ts-ignore WDIO's Vite is out of date.
tsconfigPaths(),
],
},
};
/**
* @satisfies {WebdriverIO.Config}
*/
export const config = {
runner: ["browser", browserRunnerOptions],
tsConfigPath: "./tsconfig.test.json",
specs: ["./src/**/*.test.ts"],
exclude: [],
maxInstances,
capabilities,
logLevel: "warn",
bail: 0,
waitforTimeout: 12000,
connectionRetryTimeout: 12000,
connectionRetryCount: 3,
framework: "mocha",
reporters: ["spec"],
mochaOpts: {
ui: "bdd",
timeout: 60000,
},
/**
* @param {WebdriverIO.Browser} browser
*/
before(_capabilities, _specs, browser) {
addCommands(browser);
},
afterTest() {
if (lemmeSee) return browser.pause(500);
},
};

329
web/tests/wdio.conf.ts Normal file
View File

@ -0,0 +1,329 @@
import { browser } from "@wdio/globals";
const lemmeSee = process.env.WDIO_LEMME_SEE !== undefined;
const testSafari = process.env.WDIO_TEST_SAFARI !== undefined;
const testFirefox = process.env.WDIO_TEST_FIREFOX !== undefined;
const skipChrome = process.env.WDIO_SKIP_CHROME !== undefined;
const runHeadless = process.env.CI !== undefined;
const capabilities = [];
if (!skipChrome) {
capabilities.push({
"browserName": "chrome",
"wdio:chromedriverOptions": {
binary: "./node_modules/.bin/chromedriver",
},
"goog:chromeOptions": {
args: ["disable-infobars", "window-size=1280,800"].concat(
(function () {
return runHeadless
? [
"headless",
"no-sandbox",
"disable-gpu",
"disable-setuid-sandbox",
"disable-dev-shm-usage",
]
: [];
})(),
),
},
});
}
if (testSafari) {
capabilities.push({
browserName: "safari", // or "firefox", "microsoftedge", "safari"
});
}
if (testFirefox) {
capabilities.push({
browserName: "firefox", // or "firefox", "microsoftedge", "safari"
});
}
export const config: WebdriverIO.Config = {
//
// ====================
// Runner Configuration
// ====================
// WebdriverIO supports running e2e tests as well as unit and component tests.
runner: "local",
tsConfigPath: "./tsconfig.json",
//
// ==================
// Specify Test Files
// ==================
// Define which test specs should run. The pattern is relative to the directory
// of the configuration file being run.
//
// The specs are defined as an array of spec files (optionally using wildcards
// that will be expanded). The test for each spec file will be run in a separate
// worker process. In order to have a group of spec files run in the same worker
// process simply enclose them in an array within the specs array.
//
// If you are calling `wdio` from an NPM script (see https://docs.npmjs.com/cli/run-script),
// then the current working directory is where your `package.json` resides, so `wdio`
// will be called from there.
//
specs: ["./specs/**/*.ts"],
// Patterns to exclude.
exclude: [
// 'path/to/excluded/files'
],
//
// ============
// Capabilities
// ============
// Define your capabilities here. WebdriverIO can run multiple capabilities at the same
// time. Depending on the number of capabilities, WebdriverIO launches several test
// sessions. Within your capabilities you can overwrite the spec and exclude options in
// order to group specific specs to a specific capability.
//
// First, you can define how many instances should be started at the same time. Let's
// say you have 3 different capabilities (Chrome, Firefox, and Safari) and you have
// set maxInstances to 1; wdio will spawn 3 processes. Therefore, if you have 10 spec
// files and you set maxInstances to 10, all spec files will get tested at the same time
// and 30 processes will get spawned. The property handles how many capabilities
// from the same test should run tests.
//
maxInstances: 1,
//
// If you have trouble getting all important capabilities together, check out the
// Sauce Labs platform configurator - a great tool to configure your capabilities:
// https://saucelabs.com/platform/platform-configurator
//
capabilities,
//
// ===================
// Test Configurations
// ===================
// Define all options that are relevant for the WebdriverIO instance here
//
// Level of logging verbosity: trace | debug | info | warn | error | silent
logLevel: "warn",
//
// Set specific log levels per logger
// loggers:
// - webdriver, webdriverio
// - @wdio/browserstack-service, @wdio/devtools-service, @wdio/sauce-service
// - @wdio/mocha-framework, @wdio/jasmine-framework
// - @wdio/local-runner
// - @wdio/sumologic-reporter
// - @wdio/cli, @wdio/config, @wdio/utils
// Level of logging verbosity: trace | debug | info | warn | error | silent
// logLevels: {
// webdriver: 'info',
// '@wdio/appium-service': 'info'
// },
//
// If you only want to run your tests until a specific amount of tests have failed use
// bail (default is 0 - don't bail, run all tests).
bail: 0,
//
// Set a base URL in order to shorten url command calls. If your `url` parameter starts
// with `/`, the base url gets prepended, not including the path portion of your baseUrl.
// If your `url` parameter starts without a scheme or `/` (like `some/path`), the base url
// gets prepended directly.
baseUrl: "http://localhost",
//
// Default timeout for all waitFor* commands.
waitforTimeout: 10000,
//
// Default timeout in milliseconds for request
// if browser driver or grid doesn't send response
connectionRetryTimeout: 120000,
//
// Default request retries count
connectionRetryCount: 3,
//
// Test runner services
// Services take over a specific job you don't want to take care of. They enhance
// your test setup with almost no effort. Unlike plugins, they don't add new
// commands. Instead, they hook themselves up into the test process.
// services: [],
//
// Framework you want to run your specs with.
// The following are supported: Mocha, Jasmine, and Cucumber
// see also: https://webdriver.io/docs/frameworks
//
// Make sure you have the wdio adapter package for the specific framework installed
// before running any tests.
framework: "mocha",
//
// The number of times to retry the entire specfile when it fails as a whole
// specFileRetries: 1,
//
// Delay in seconds between the spec file retry attempts
// specFileRetriesDelay: 0,
//
// Whether or not retried spec files should be retried immediately or deferred to the end of the queue
// specFileRetriesDeferred: false,
//
// Test reporter for stdout.
// The only one supported by default is 'dot'
// see also: https://webdriver.io/docs/dot-reporter
reporters: ["spec"],
//
// Options to be passed to Mocha.
// See the full list at http://mochajs.org/
mochaOpts: {
ui: "bdd",
timeout: 60000,
},
//
// =====
// Hooks
// =====
// WebdriverIO provides several hooks you can use to interfere with the test process in order to enhance
// it and to build services around it. You can either apply a single function or an array of
// methods to it. If one of them returns with a promise, WebdriverIO will wait until that promise got
// resolved to continue.
/**
* Gets executed once before all workers get launched.
* @param {object} config wdio configuration object
* @param {Array.<Object>} capabilities list of capabilities details
*/
// onPrepare: function (config, capabilities) {
// },
/**
* Gets executed before a worker process is spawned and can be used to initialise specific service
* for that worker as well as modify runtime environments in an async fashion.
* @param {string} cid capability id (e.g 0-0)
* @param {object} caps object containing capabilities for session that will be spawn in the worker
* @param {object} specs specs to be run in the worker process
* @param {object} args object that will be merged with the main configuration once worker is initialized
* @param {object} execArgv list of string arguments passed to the worker process
*/
// onWorkerStart: function (cid, caps, specs, args, execArgv) {
// },
/**
* Gets executed just after a worker process has exited.
* @param {string} cid capability id (e.g 0-0)
* @param {number} exitCode 0 - success, 1 - fail
* @param {object} specs specs to be run in the worker process
* @param {number} retries number of retries used
*/
// onWorkerEnd: function (cid, exitCode, specs, retries) {
// },
/**
* Gets executed just before initialising the webdriver session and test framework. It allows you
* to manipulate configurations depending on the capability or spec.
* @param {object} config wdio configuration object
* @param {Array.<Object>} capabilities list of capabilities details
* @param {Array.<String>} specs List of spec file paths that are to be run
* @param {string} cid worker id (e.g. 0-0)
*/
// beforeSession: function (config, capabilities, specs, cid) {
// },
/**
* Gets executed before test execution begins. At this point you can access to all global
* variables like `browser`. It is the perfect place to define custom commands.
* @param {Array.<Object>} capabilities list of capabilities details
* @param {Array.<String>} specs List of spec file paths that are to be run
* @param {object} browser instance of created browser/device session
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
before: function (_capabilities, _specs) {},
/**
* Runs before a WebdriverIO command gets executed.
* @param {string} commandName hook command name
* @param {Array} args arguments that command would receive
*/
// beforeCommand: function (commandName, args) {
// },
/**
* Hook that gets executed before the suite starts
* @param {object} suite suite details
*/
// beforeSuite: function (suite) {
// },
/**
* Function to be executed before a test (in Mocha/Jasmine) starts.
*/
// beforeTest: function (test, context) {
// },
/**
* Hook that gets executed _before_ a hook within the suite starts (e.g. runs before calling
* beforeEach in Mocha)
*/
// beforeHook: function (test, context) {
// },
/**
* Hook that gets executed _after_ a hook within the suite starts (e.g. runs after calling
* afterEach in Mocha)
*/
// afterHook: function (test, context, { error, result, duration, passed, retries }) {
// },
/**
* Function to be executed after a test (in Mocha/Jasmine only)
* @param {object} test test object
* @param {object} context scope object the test was executed with
* @param {Error} result.error error object in case the test fails, otherwise `undefined`
* @param {*} result.result return object of test function
* @param {number} result.duration duration of test
* @param {boolean} result.passed true if test has passed, otherwise false
* @param {object} result.retries information about spec related retries, e.g. `{ attempts: 0, limit: 0 }`
*/
// Below is the full signature; we're not using any of them.
// afterTest: async function (test, context, { error, result, duration, passed, retries }) {
afterTest: async function () {
if (lemmeSee) {
await browser.pause(500);
}
},
/**
* Hook that gets executed after the suite has ended
* @param {object} suite suite details
*/
// afterSuite: function (suite) {
// },
/**
* Runs after a WebdriverIO command gets executed
* @param {string} commandName hook command name
* @param {Array} args arguments that command would receive
* @param {number} result 0 - command success, 1 - command error
* @param {object} error error object if any
*/
// afterCommand: function (commandName, args, result, error) {
// },
/**
* Gets executed after all tests are done. You still have access to all global variables from
* the test.
* @param {number} result 0 - test pass, 1 - test fail
* @param {Array.<Object>} capabilities list of capabilities details
* @param {Array.<String>} specs List of spec file paths that ran
*/
// after: function (result, capabilities, specs) {
// },
/**
* Gets executed right after terminating the webdriver session.
* @param {object} config wdio configuration object
* @param {Array.<Object>} capabilities list of capabilities details
* @param {Array.<String>} specs List of spec file paths that ran
*/
// afterSession: function (config, capabilities, specs) {
// },
/**
* Gets executed after all workers got shut down and the process is about to exit. An error
* thrown in the onComplete hook will result in the test run failing.
* @param {object} exitCode 0 - success, 1 - fail
* @param {object} config wdio configuration object
* @param {Array.<Object>} capabilities list of capabilities details
* @param {<Object>} results object containing test results
*/
// onComplete: function(exitCode, config, capabilities, results) {
// },
/**
* Gets executed when a refresh happens.
* @param {string} oldSessionId session ID of the old session
* @param {string} newSessionId session ID of the new session
*/
// onReload: function(oldSessionId, newSessionId) {
// }
};

View File

@ -52,12 +52,20 @@
}, },
"exclude": [ "exclude": [
// --- // ---
"**/out/**/*", "./out/**/*",
"**/dist/**/*", "./dist/**/*",
"src/**/*.test.ts", "src/**/*.test.ts",
"./tests", "./tests",
// TODO: Remove after monorepo cleanup. // TODO: Remove after monorepo cleanup.
"src/**/*.comp.ts" "src/**/*.comp.ts"
],
"references": [
{
"path": "./packages/core"
},
{
"path": "./packages/esbuild-plugin-live-reload"
}
] ]
} }

View File

@ -3,7 +3,34 @@
"compilerOptions": { "compilerOptions": {
"baseUrl": ".", "baseUrl": ".",
"types": ["node", "webdriverio/async", "@wdio/cucumber-framework", "expect-webdriverio"], "types": ["node", "webdriverio/async", "@wdio/cucumber-framework", "expect-webdriverio"],
"extends": "./tsconfig.json", "target": "esnext",
"include": ["src", "./tests"] "module": "esnext",
"forceConsistentCasingInFileNames": true,
"experimentalDecorators": true,
"lib": [
"ES5",
"ES2015",
"ES2016",
"ES2017",
"ES2018",
"ES2019",
"ES2020",
"ESNext",
"DOM",
"DOM.Iterable",
"WebWorker"
],
"paths": {
"@goauthentik/admin/*": ["./src/admin/*"],
"@goauthentik/common/*": ["./src/common/*"],
"@goauthentik/components/*": ["./src/components/*"],
"@goauthentik/docs/*": ["../website/docs/*"],
"@goauthentik/elements/*": ["./src/elements/*"],
"@goauthentik/flow/*": ["./src/flow/*"],
"@goauthentik/locales/*": ["./src/locales/*"],
"@goauthentik/polyfill/*": ["./src/polyfill/*"],
"@goauthentik/standalone/*": ["./src/standalone/*"],
"@goauthentik/user/*": ["./src/user/*"]
}
} }
} }

View File

@ -1,14 +0,0 @@
declare namespace WebdriverIO {
interface Element {
/**
* Focus on the element.
* @monkeypatch
*/
focus(): Promise<void>;
/**
* Blur the element.
* @monkeypatch
*/
blur(): Promise<void>;
}
}

View File

@ -1,100 +0,0 @@
/**
* @file WebdriverIO configuration file for **integration tests**.
*
* @see https://webdriver.io/docs/configurationfile.html
*/
import { browser } from "@wdio/globals";
import { addCommands } from "./commands.mjs";
/// <reference types="@wdio/globals/types" />
/// <reference types="./types/webdriver.js" />
const headless = !!process.env.CI;
const lemmeSee = !!process.env.WDIO_LEMME_SEE;
/**
* @type {WebdriverIO.Capabilities[]}
*/
const capabilities = [];
if (!process.env.WDIO_SKIP_CHROME) {
/**
* @satisfies {WebdriverIO.Capabilities}
*/
const chromeBrowserConfig = {
"browserName": "chrome",
// "wdio:chromedriverOptions": {
// binary: "./node_modules/.bin/chromedriver",
// },
"goog:chromeOptions": {
args: ["disable-infobars", "window-size=1280,800"],
},
};
if (headless) {
chromeBrowserConfig["goog:chromeOptions"].args.push(
"headless",
"no-sandbox",
"disable-gpu",
"disable-setuid-sandbox",
"disable-dev-shm-usage",
);
}
capabilities.push(chromeBrowserConfig);
}
if (process.env.WDIO_TEST_SAFARI) {
capabilities.push({
browserName: "safari",
});
}
if (process.env.WDIO_TEST_FIREFOX) {
capabilities.push({
browserName: "firefox",
});
}
/**
* @satisfies {WebdriverIO.Config}
*/
export const config = {
runner: "local",
tsConfigPath: "./tsconfig.json",
specs: [
// "./tests/specs/**/*.ts"
"./tests/specs/new-application-by-wizard.ts",
],
exclude: [],
maxInstances: 1,
capabilities,
logLevel: "warn",
baseUrl: "http://localhost",
waitforTimeout: 10000,
connectionRetryTimeout: 120000,
connectionRetryCount: 3,
framework: "mocha",
reporters: ["spec"],
mochaOpts: {
ui: "bdd",
timeout: 60000,
},
/**
* @param {WebdriverIO.Capabilities} capabilities
* @param {string[]} specs
* @param {WebdriverIO.Browser} browser
* @returns {void}
*/
before(capabilities, specs, browser) {
addCommands(browser);
},
afterTest() {
if (lemmeSee) return browser.pause(500);
},
};

391
web/wdio.conf.ts Normal file
View File

@ -0,0 +1,391 @@
/// <reference types="@wdio/browser-runner" />
import { createBundleDefinitions } from "#bundler/utils/node";
import { browser } from "@wdio/globals";
import type { Options } from "@wdio/types";
import path from "node:path";
import { fileURLToPath } from "node:url";
import type { InlineConfig } from "vite";
import litCSS from "vite-plugin-lit-css";
import tsconfigPaths from "vite-tsconfig-paths";
const __dirname = fileURLToPath(new URL(".", import.meta.url));
const runHeadless = process.env.CI !== undefined;
const testSafari = process.env.WDIO_TEST_SAFARI !== undefined;
const testFirefox = process.env.WDIO_TEST_FIREFOX !== undefined;
const skipChrome = process.env.WDIO_SKIP_CHROME !== undefined;
const lemmeSee = process.env.WDIO_LEMME_SEE !== undefined;
const capabilities = [];
const DEFAULT_MAX_INSTANCES = 10;
if (!skipChrome) {
capabilities.push({
// capabilities for local browser web tests
"browserName": "chrome", // or "firefox", "microsoftedge", "safari"
"goog:chromeOptions": {
args: [
"disable-search-engine-choice-screen",
...(runHeadless
? [
"headless",
"disable-gpu",
"no-sandbox",
"window-size=1280,672",
"browser-test",
]
: []),
],
},
});
}
if (testSafari) {
capabilities.push({
browserName: "safari", // or "firefox", "microsoftedge", "safari"
});
}
if (testFirefox) {
capabilities.push({
browserName: "firefox", // or "firefox", "microsoftedge", "safari"
});
}
const maxInstances =
process.env.MAX_INSTANCES !== undefined
? parseInt(process.env.MAX_INSTANCES, DEFAULT_MAX_INSTANCES)
: runHeadless
? 1
: 1;
export const config: Options.Testrunner = {
//
// ====================
// Runner Configuration
// ====================
// WebdriverIO supports running e2e tests as well as unit and component tests.
runner: [
"browser",
{
viteConfig: {
define: createBundleDefinitions(),
plugins: [litCSS(), tsconfigPaths()],
resolve: {
alias: {
"@goauthentik/admin": path.resolve(__dirname, "src/admin"),
"@goauthentik/common": path.resolve(__dirname, "src/common"),
"@goauthentik/components": path.resolve(__dirname, "src/components"),
"@goauthentik/docs": path.resolve(__dirname, "../website/docs"),
"@goauthentik/elements": path.resolve(__dirname, "src/elements"),
"@goauthentik/flow": path.resolve(__dirname, "src/flow"),
"@goauthentik/locales": path.resolve(__dirname, "src/locales"),
"@goauthentik/polyfill": path.resolve(__dirname, "src/polyfill"),
"@goauthentik/standalone": path.resolve(__dirname, "src/standalone"),
"@goauthentik/user": path.resolve(__dirname, "src/user"),
},
},
} satisfies InlineConfig,
},
],
// @ts-expect-error TS2353: The types are not up-to-date with Wdio9.
autoCompileOpts: {
autoCompile: true,
tsNodeOpts: {
project: "./tsconfig.json",
transpileOnly: true,
},
},
//
// ==================
// Specify Test Files
// ==================
// Define which test specs should run. The pattern is relative to the directory
// of the configuration file being run.
//
// The specs are defined as an array of spec files (optionally using wildcards
// that will be expanded). The test for each spec file will be run in a separate
// worker process. In order to have a group of spec files run in the same worker
// process simply enclose them in an array within the specs array.
//
// The path of the spec files will be resolved relative from the directory of
// of the config file unless it's absolute.
//
specs: ["./src/**/*.test.ts"],
// Patterns to exclude.
exclude: [
// 'path/to/excluded/files'
],
//
// ============
// Capabilities
// ============
// Define your capabilities here. WebdriverIO can run multiple capabilities at the same
// time. Depending on the number of capabilities, WebdriverIO launches several test
// sessions. Within your capabilities you can overwrite the spec and exclude options in
// order to group specific specs to a specific capability.
//
// First, you can define how many instances should be started at the same time. Let's
// say you have 3 different capabilities (Chrome, Firefox, and Safari) and you have
// set maxInstances to 1; wdio will spawn 3 processes. Therefore, if you have 10 spec
// files and you set maxInstances to 10, all spec files will get tested at the same time
// and 30 processes will get spawned. The property handles how many capabilities
// from the same test should run tests.
//
maxInstances,
//
// If you have trouble getting all important capabilities together, check out the
// Sauce Labs platform configurator - a great tool to configure your capabilities:
// https://saucelabs.com/platform/platform-configurator
//
capabilities,
//
// ===================
// Test Configurations
// ===================
// Define all options that are relevant for the WebdriverIO instance here
//
// Level of logging verbosity: trace | debug | info | warn | error | silent
logLevel: "warn",
//
// Set specific log levels per logger
// loggers:
// - webdriver, webdriverio
// - @wdio/browserstack-service, @wdio/devtools-service, @wdio/sauce-service
// - @wdio/mocha-framework, @wdio/jasmine-framework
// - @wdio/local-runner
// - @wdio/sumologic-reporter
// - @wdio/cli, @wdio/config, @wdio/utils
// Level of logging verbosity: trace | debug | info | warn | error | silent
// logLevels: {
// webdriver: 'info',
// '@wdio/appium-service': 'info'
// },
//
// If you only want to run your tests until a specific amount of tests have failed use
// bail (default is 0 - don't bail, run all tests).
bail: 0,
//
// Set a base URL in order to shorten url command calls. If your `url` parameter starts
// with `/`, the base url gets prepended, not including the path portion of your baseUrl.
// If your `url` parameter starts without a scheme or `/` (like `some/path`), the base url
// gets prepended directly.
// baseUrl: 'http://localhost:8080',
//
// Default timeout for all waitFor* commands.
waitforTimeout: 12000,
//
// Default timeout in milliseconds for request
// if browser driver or grid doesn't send response
connectionRetryTimeout: 12000,
//
// Default request retries count
connectionRetryCount: 3,
//
// Test runner services
// Services take over a specific job you don't want to take care of. They enhance
// your test setup with almost no effort. Unlike plugins, they don't add new
// commands. Instead, they hook themselves up into the test process.
// services: [],
//
// Framework you want to run your specs with.
// The following are supported: Mocha, Jasmine, and Cucumber
// see also: https://webdriver.io/docs/frameworks
//
// Make sure you have the wdio adapter package for the specific framework installed
// before running any tests.
framework: "mocha",
//
// The number of times to retry the entire specfile when it fails as a whole
// specFileRetries: 1,
//
// Delay in seconds between the spec file retry attempts
// specFileRetriesDelay: 0,
//
// Whether or not retried spec files should be retried immediately or deferred to the end of the queue
// specFileRetriesDeferred: false,
//
// Test reporter for stdout.
// The only one supported by default is 'dot'
// see also: https://webdriver.io/docs/dot-reporter
reporters: ["spec"],
// Options to be passed to Mocha.
// See the full list at http://mochajs.org/
mochaOpts: {
ui: "bdd",
timeout: 60000,
},
//
// =====
// Hooks
// =====
// WebdriverIO provides several hooks you can use to interfere with the test process in order to enhance
// it and to build services around it. You can either apply a single function or an array of
// methods to it. If one of them returns with a promise, WebdriverIO will wait until that promise got
// resolved to continue.
/**
* Gets executed once before all workers get launched.
* @param {object} config wdio configuration object
* @param {Array.<Object>} capabilities list of capabilities details
*/
// onPrepare: function (config, capabilities) {
// },
/**
* Gets executed before a worker process is spawned and can be used to initialize specific service
* for that worker as well as modify runtime environments in an async fashion.
* @param {string} cid capability id (e.g 0-0)
* @param {object} caps object containing capabilities for session that will be spawn in the worker
* @param {object} specs specs to be run in the worker process
* @param {object} args object that will be merged with the main configuration once worker is initialized
* @param {object} execArgv list of string arguments passed to the worker process
*/
// onWorkerStart: function (cid, caps, specs, args, execArgv) {
// },
/**
* Gets executed just after a worker process has exited.
* @param {string} cid capability id (e.g 0-0)
* @param {number} exitCode 0 - success, 1 - fail
* @param {object} specs specs to be run in the worker process
* @param {number} retries number of retries used
*/
// onWorkerEnd: function (cid, exitCode, specs, retries) {
// },
/**
* Gets executed just before initialising the webdriver session and test framework. It allows you
* to manipulate configurations depending on the capability or spec.
* @param {object} config wdio configuration object
* @param {Array.<Object>} capabilities list of capabilities details
* @param {Array.<String>} specs List of spec file paths that are to be run
* @param {string} cid worker id (e.g. 0-0)
*/
// beforeSession: function (config, capabilities, specs, cid) {
// },
/**
* Gets executed before test execution begins. At this point you can access to all global
* variables like `browser`. It is the perfect place to define custom commands.
* @param {Array.<Object>} capabilities list of capabilities details
* @param {Array.<String>} specs List of spec file paths that are to be run
* @param {object} browser instance of created browser/device session
*/
// before: function (capabilities, specs) {
// },
/**
* Runs before a WebdriverIO command gets executed.
* @param {string} commandName hook command name
* @param {Array} args arguments that command would receive
*/
// beforeCommand: function (commandName, args) {
// },
/**
* Hook that gets executed before the suite starts
* @param {object} suite suite details
*/
// beforeSuite: function (suite) {
// },
/**
* Function to be executed before a test (in Mocha/Jasmine) starts.
*/
// beforeTest: function (test, context) {
// },
/**
* Hook that gets executed _before_ a hook within the suite starts (e.g. runs before calling
* beforeEach in Mocha)
*/
// beforeHook: function (test, context, hookName) {
// },
/**
* Hook that gets executed _after_ a hook within the suite starts (e.g. runs after calling
* afterEach in Mocha)
*/
// afterHook: function (test, context, { error, result, duration, passed, retries }, hookName) {
// },
/**
* Function to be executed after a test (in Mocha/Jasmine only)
* @param {object} test test object
* @param {object} context scope object the test was executed with
* @param {Error} result.error error object in case the test fails, otherwise `undefined`
* @param {*} result.result return object of test function
* @param {number} result.duration duration of test
* @param {boolean} result.passed true if test has passed, otherwise false
* @param {object} result.retries information about spec related retries, e.g. `{ attempts: 0, limit: 0 }`
*/
afterTest: async function (
_test,
_context,
{ error: _error, result: _result, duration: _duration, passed: _passed, retries: _retries },
) {
if (lemmeSee) {
// @ts-expect-error TODO
await browser.pause(500);
}
},
/**
* Hook that gets executed after the suite has ended
* @param {object} suite suite details
*/
// afterSuite: function (suite) {
// },
/**
* Runs after a WebdriverIO command gets executed
* @param {string} commandName hook command name
* @param {Array} args arguments that command would receive
* @param {number} result 0 - command success, 1 - command error
* @param {object} error error object if any
*/
// afterCommand: function (commandName, args, result, error) {
// },
/**
* Gets executed after all tests are done. You still have access to all global variables from
* the test.
* @param {number} result 0 - test pass, 1 - test fail
* @param {Array.<Object>} capabilities list of capabilities details
* @param {Array.<String>} specs List of spec file paths that ran
*/
// after: function (result, capabilities, specs) {
// },
/**
* Gets executed right after terminating the webdriver session.
* @param {object} config wdio configuration object
* @param {Array.<Object>} capabilities list of capabilities details
* @param {Array.<String>} specs List of spec file paths that ran
*/
// afterSession: function (config, capabilities, specs) {
// },
/**
* Gets executed after all workers got shut down and the process is about to exit. An error
* thrown in the onComplete hook will result in the test run failing.
* @param {object} exitCode 0 - success, 1 - fail
* @param {object} config wdio configuration object
* @param {Array.<Object>} capabilities list of capabilities details
* @param {<Object>} results object containing test results
*/
// onComplete: function(exitCode, config, capabilities, results) {
// },
/**
* Gets executed when a refresh happens.
* @param {string} oldSessionId session ID of the old session
* @param {string} newSessionId session ID of the new session
*/
// onReload: function(oldSessionId, newSessionId) {
// }
/**
* Hook that gets executed before a WebdriverIO assertion happens.
* @param {object} params information about the assertion to be executed
*/
// beforeAssertion: function(params) {
// }
/**
* Hook that gets executed after a WebdriverIO assertion happened.
* @param {object} params information about the assertion that was executed, including its results
*/
// afterAssertion: function(params) {
// }
};

View File

@ -1,16 +1,6 @@
/** export default {
* @file Web Test Runner configuration.
* @see https://modern-web.dev/docs/test-runner/cli-and-configuration/
*/
/**
* @type {import('@web/test-runner').TestRunnerConfig}
*/
const config = {
files: ["dist/**/*.spec.js"], files: ["dist/**/*.spec.js"],
nodeResolve: { nodeResolve: {
exportConditions: ["browser", "production"], exportConditions: ["browser", "production"],
}, },
}; };
export default config;

View File

@ -9174,51 +9174,6 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit> </trans-unit>
<trans-unit id="s7d4ec232535a36f0"> <trans-unit id="s7d4ec232535a36f0">
<source>Choose a Provider</source> <source>Choose a Provider</source>
</trans-unit>
<trans-unit id="sa30ba280de276758">
<source>When enabled, the SAML response will be signed.</source>
</trans-unit>
<trans-unit id="s2c42bb3c6f5420d2">
<source>Client Certificates</source>
</trans-unit>
<trans-unit id="s95901716c0629274">
<source>Available Certificates</source>
</trans-unit>
<trans-unit id="sdbf6b484fa1436b0">
<source>Selected Certificates</source>
</trans-unit>
<trans-unit id="s9300147e327fd8f6">
<source>Client-certificate/mTLS authentication/enrollment.</source>
</trans-unit>
<trans-unit id="sbf990ec848470f5c">
<source>Certificate optional</source>
</trans-unit>
<trans-unit id="s72e2876e9409b9eb">
<source>If no certificate was provided, this stage will succeed and continue to the next stage.</source>
</trans-unit>
<trans-unit id="se07d973901a6e6b9">
<source>Certificate required</source>
</trans-unit>
<trans-unit id="s664c47df020ee414">
<source>If no certificate was provided, this stage will stop flow execution.</source>
</trans-unit>
<trans-unit id="sbe9da6dad795aa39">
<source>Certificate authorities</source>
</trans-unit>
<trans-unit id="se3a6aa4f0ab7568e">
<source>Configure the certificate authority client certificates are validated against. The certificate authority can also be configured on a brand, which allows for different certificate authorities for different domains.</source>
</trans-unit>
<trans-unit id="sb8fdf5a09a969870">
<source>Certificate attribute</source>
</trans-unit>
<trans-unit id="s8069037a865037c9">
<source>Configure the attribute of the certificate used to look for a user.</source>
</trans-unit>
<trans-unit id="sc185a8ad96f8eaa2">
<source>User attribute</source>
</trans-unit>
<trans-unit id="s4f9860fefb8fbe01">
<source>Configure the attribute of the user used to look for a user.</source>
</trans-unit> </trans-unit>
</body> </body>
</file> </file>

View File

@ -7697,51 +7697,6 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit> </trans-unit>
<trans-unit id="s7d4ec232535a36f0"> <trans-unit id="s7d4ec232535a36f0">
<source>Choose a Provider</source> <source>Choose a Provider</source>
</trans-unit>
<trans-unit id="sa30ba280de276758">
<source>When enabled, the SAML response will be signed.</source>
</trans-unit>
<trans-unit id="s2c42bb3c6f5420d2">
<source>Client Certificates</source>
</trans-unit>
<trans-unit id="s95901716c0629274">
<source>Available Certificates</source>
</trans-unit>
<trans-unit id="sdbf6b484fa1436b0">
<source>Selected Certificates</source>
</trans-unit>
<trans-unit id="s9300147e327fd8f6">
<source>Client-certificate/mTLS authentication/enrollment.</source>
</trans-unit>
<trans-unit id="sbf990ec848470f5c">
<source>Certificate optional</source>
</trans-unit>
<trans-unit id="s72e2876e9409b9eb">
<source>If no certificate was provided, this stage will succeed and continue to the next stage.</source>
</trans-unit>
<trans-unit id="se07d973901a6e6b9">
<source>Certificate required</source>
</trans-unit>
<trans-unit id="s664c47df020ee414">
<source>If no certificate was provided, this stage will stop flow execution.</source>
</trans-unit>
<trans-unit id="sbe9da6dad795aa39">
<source>Certificate authorities</source>
</trans-unit>
<trans-unit id="se3a6aa4f0ab7568e">
<source>Configure the certificate authority client certificates are validated against. The certificate authority can also be configured on a brand, which allows for different certificate authorities for different domains.</source>
</trans-unit>
<trans-unit id="sb8fdf5a09a969870">
<source>Certificate attribute</source>
</trans-unit>
<trans-unit id="s8069037a865037c9">
<source>Configure the attribute of the certificate used to look for a user.</source>
</trans-unit>
<trans-unit id="sc185a8ad96f8eaa2">
<source>User attribute</source>
</trans-unit>
<trans-unit id="s4f9860fefb8fbe01">
<source>Configure the attribute of the user used to look for a user.</source>
</trans-unit> </trans-unit>
</body> </body>
</file> </file>

View File

@ -9256,51 +9256,6 @@ Las vinculaciones a grupos o usuarios se comparan con el usuario del evento.</ta
</trans-unit> </trans-unit>
<trans-unit id="s7d4ec232535a36f0"> <trans-unit id="s7d4ec232535a36f0">
<source>Choose a Provider</source> <source>Choose a Provider</source>
</trans-unit>
<trans-unit id="sa30ba280de276758">
<source>When enabled, the SAML response will be signed.</source>
</trans-unit>
<trans-unit id="s2c42bb3c6f5420d2">
<source>Client Certificates</source>
</trans-unit>
<trans-unit id="s95901716c0629274">
<source>Available Certificates</source>
</trans-unit>
<trans-unit id="sdbf6b484fa1436b0">
<source>Selected Certificates</source>
</trans-unit>
<trans-unit id="s9300147e327fd8f6">
<source>Client-certificate/mTLS authentication/enrollment.</source>
</trans-unit>
<trans-unit id="sbf990ec848470f5c">
<source>Certificate optional</source>
</trans-unit>
<trans-unit id="s72e2876e9409b9eb">
<source>If no certificate was provided, this stage will succeed and continue to the next stage.</source>
</trans-unit>
<trans-unit id="se07d973901a6e6b9">
<source>Certificate required</source>
</trans-unit>
<trans-unit id="s664c47df020ee414">
<source>If no certificate was provided, this stage will stop flow execution.</source>
</trans-unit>
<trans-unit id="sbe9da6dad795aa39">
<source>Certificate authorities</source>
</trans-unit>
<trans-unit id="se3a6aa4f0ab7568e">
<source>Configure the certificate authority client certificates are validated against. The certificate authority can also be configured on a brand, which allows for different certificate authorities for different domains.</source>
</trans-unit>
<trans-unit id="sb8fdf5a09a969870">
<source>Certificate attribute</source>
</trans-unit>
<trans-unit id="s8069037a865037c9">
<source>Configure the attribute of the certificate used to look for a user.</source>
</trans-unit>
<trans-unit id="sc185a8ad96f8eaa2">
<source>User attribute</source>
</trans-unit>
<trans-unit id="s4f9860fefb8fbe01">
<source>Configure the attribute of the user used to look for a user.</source>
</trans-unit> </trans-unit>
</body> </body>
</file> </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="fr" source-language="en" original="lit-localize-inputs" datatype="plaintext"> <file target-language="fr" source-language="en" original="lit-localize-inputs" datatype="plaintext">
<body> <body>
<trans-unit id="s4caed5b7a7e5d89b"> <trans-unit id="s4caed5b7a7e5d89b">
@ -596,9 +596,9 @@
</trans-unit> </trans-unit>
<trans-unit id="saa0e2675da69651b"> <trans-unit id="saa0e2675da69651b">
<source>The URL "<x id="0" equiv-text="${this.url}"/>" was not found.</source> <source>The URL &quot;<x id="0" equiv-text="${this.url}"/>&quot; was not found.</source>
<target>L'URL " <target>L'URL &quot;
<x id="0" equiv-text="${this.url}"/>" n'a pas été trouvée.</target> <x id="0" equiv-text="${this.url}"/>&quot; n'a pas été trouvée.</target>
</trans-unit> </trans-unit>
<trans-unit id="s58cd9c2fe836d9c6"> <trans-unit id="s58cd9c2fe836d9c6">
@ -1547,7 +1547,7 @@
</trans-unit> </trans-unit>
<trans-unit id="s33ed903c210a6209"> <trans-unit id="s33ed903c210a6209">
<source>Token to authenticate with. Currently only bearer authentication is supported.</source> <source>Token to authenticate with. Currently only bearer authentication is supported.</source>
<target>Jeton d'authentification à utiliser. Actuellement, seule l'authentification "bearer authentication" est prise en charge.</target> <target>Jeton d'authentification à utiliser. Actuellement, seule l'authentification &quot;bearer authentication&quot; est prise en charge.</target>
</trans-unit> </trans-unit>
<trans-unit id="sfc8bb104e2c05af8"> <trans-unit id="sfc8bb104e2c05af8">
@ -1715,8 +1715,8 @@
</trans-unit> </trans-unit>
<trans-unit id="sa90b7809586c35ce"> <trans-unit id="sa90b7809586c35ce">
<source>Either input a full URL, a relative path, or use 'fa://fa-test' to use the Font Awesome icon "fa-test".</source> <source>Either input a full URL, a relative path, or use 'fa://fa-test' to use the Font Awesome icon &quot;fa-test&quot;.</source>
<target>Entrez une URL complète, un chemin relatif ou utilisez 'fa://fa-test' pour utiliser l'icône Font Awesome "fa-test".</target> <target>Entrez une URL complète, un chemin relatif ou utilisez 'fa://fa-test' pour utiliser l'icône Font Awesome &quot;fa-test&quot;.</target>
</trans-unit> </trans-unit>
<trans-unit id="s0410779cb47de312"> <trans-unit id="s0410779cb47de312">
@ -2779,7 +2779,7 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit> </trans-unit>
<trans-unit id="s33683c3b1dbaf264"> <trans-unit id="s33683c3b1dbaf264">
<source>To use SSL instead, use 'ldaps://' and disable this option.</source> <source>To use SSL instead, use 'ldaps://' and disable this option.</source>
<target>Pour utiliser SSL à la base, utilisez "ldaps://" et désactviez cette option.</target> <target>Pour utiliser SSL à la base, utilisez &quot;ldaps://&quot; et désactviez cette option.</target>
</trans-unit> </trans-unit>
<trans-unit id="s2221fef80f4753a2"> <trans-unit id="s2221fef80f4753a2">
@ -3154,7 +3154,7 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit> </trans-unit>
<trans-unit id="s3198c384c2f68b08"> <trans-unit id="s3198c384c2f68b08">
<source>Time offset when temporary users should be deleted. This only applies if your IDP uses the NameID Format 'transient', and the user doesn't log out manually.</source> <source>Time offset when temporary users should be deleted. This only applies if your IDP uses the NameID Format 'transient', and the user doesn't log out manually.</source>
<target>Moment où les utilisateurs temporaires doivent être supprimés. Cela ne s'applique que si votre IDP utilise le format NameID "transient" et que l'utilisateur ne se déconnecte pas manuellement.</target> <target>Moment où les utilisateurs temporaires doivent être supprimés. Cela ne s'applique que si votre IDP utilise le format NameID &quot;transient&quot; et que l'utilisateur ne se déconnecte pas manuellement.</target>
</trans-unit> </trans-unit>
<trans-unit id="sb32e9c1faa0b8673"> <trans-unit id="sb32e9c1faa0b8673">
@ -3296,7 +3296,7 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit> </trans-unit>
<trans-unit id="s9f8aac89fe318acc"> <trans-unit id="s9f8aac89fe318acc">
<source>Optionally set the 'FriendlyName' value of the Assertion attribute.</source> <source>Optionally set the 'FriendlyName' value of the Assertion attribute.</source>
<target>Indiquer la valeur "FriendlyName" de l'attribut d'assertion (optionnel)</target> <target>Indiquer la valeur &quot;FriendlyName&quot; de l'attribut d'assertion (optionnel)</target>
</trans-unit> </trans-unit>
<trans-unit id="s851c108679653d2a"> <trans-unit id="s851c108679653d2a">
@ -3777,10 +3777,10 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit> </trans-unit>
<trans-unit id="sa95a538bfbb86111"> <trans-unit id="sa95a538bfbb86111">
<source>Are you sure you want to update <x id="0" equiv-text="${this.objectLabel}"/> "<x id="1" equiv-text="${this.obj?.name}"/>"?</source> <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>
<target>Êtes-vous sûr de vouloir mettre à jour <target>Êtes-vous sûr de vouloir mettre à jour
<x id="0" equiv-text="${this.objectLabel}"/>" <x id="0" equiv-text="${this.objectLabel}"/>&quot;
<x id="1" equiv-text="${this.obj?.name}"/>"?</target> <x id="1" equiv-text="${this.obj?.name}"/>&quot;?</target>
</trans-unit> </trans-unit>
<trans-unit id="sc92d7cfb6ee1fec6"> <trans-unit id="sc92d7cfb6ee1fec6">
@ -4846,8 +4846,8 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit> </trans-unit>
<trans-unit id="sdf1d8edef27236f0"> <trans-unit id="sdf1d8edef27236f0">
<source>A "roaming" authenticator, like a YubiKey</source> <source>A &quot;roaming&quot; authenticator, like a YubiKey</source>
<target>Un authentificateur "itinérant", comme une YubiKey</target> <target>Un authentificateur &quot;itinérant&quot;, comme une YubiKey</target>
</trans-unit> </trans-unit>
<trans-unit id="sfffba7b23d8fb40c"> <trans-unit id="sfffba7b23d8fb40c">
@ -5152,7 +5152,7 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit> </trans-unit>
<trans-unit id="s5170f9ef331949c0"> <trans-unit id="s5170f9ef331949c0">
<source>Show arbitrary input fields to the user, for example during enrollment. Data is saved in the flow context under the 'prompt_data' variable.</source> <source>Show arbitrary input fields to the user, for example during enrollment. Data is saved in the flow context under the 'prompt_data' variable.</source>
<target>Afficher des champs de saisie arbitraires à l'utilisateur, par exemple pendant l'inscription. Les données sont enregistrées dans le contexte du flux sous la variable "prompt_data".</target> <target>Afficher des champs de saisie arbitraires à l'utilisateur, par exemple pendant l'inscription. Les données sont enregistrées dans le contexte du flux sous la variable &quot;prompt_data&quot;.</target>
</trans-unit> </trans-unit>
<trans-unit id="s36cb242ac90353bc"> <trans-unit id="s36cb242ac90353bc">
@ -5205,8 +5205,8 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit> </trans-unit>
<trans-unit id="s1608b2f94fa0dbd4"> <trans-unit id="s1608b2f94fa0dbd4">
<source>If set to a duration above 0, the user will have the option to choose to "stay signed in", which will extend their session by the time specified here.</source> <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 défini à une durée supérieure à 0, l'utilisateur aura la possibilité de choisir de "rester connecté", ce qui prolongera sa session jusqu'à la durée spécifiée ici.</target> <target>Si défini à une durée supérieure à 0, l'utilisateur aura la possibilité de choisir de &quot;rester connecté&quot;, ce qui prolongera sa session jusqu'à la durée spécifiée ici.</target>
</trans-unit> </trans-unit>
<trans-unit id="s542a71bb8f41e057"> <trans-unit id="s542a71bb8f41e057">
@ -7191,7 +7191,7 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti
</trans-unit> </trans-unit>
<trans-unit id="sff0ac1ace2d90709"> <trans-unit id="sff0ac1ace2d90709">
<source>Use this provider with nginx's auth_request or traefik's forwardAuth. Each application/domain needs its own provider. Additionally, on each domain, /outpost.goauthentik.io must be routed to the outpost (when using a managed outpost, this is done for you).</source> <source>Use this provider with nginx's auth_request or traefik's forwardAuth. Each application/domain needs its own provider. Additionally, on each domain, /outpost.goauthentik.io must be routed to the outpost (when using a managed outpost, this is done for you).</source>
<target>Utilisez ce fournisseur avec l'option "auth_request" de Nginx ou "forwardAuth" de Traefik. Chaque application/domaine a besoin de son propre fournisseur. De plus, sur chaque domaine, "/outpost.goauthentik.io" doit être routé vers le poste avancé (lorsque vous utilisez un poste avancé géré, cela est fait pour vous).</target> <target>Utilisez ce fournisseur avec l'option &quot;auth_request&quot; de Nginx ou &quot;forwardAuth&quot; de Traefik. Chaque application/domaine a besoin de son propre fournisseur. De plus, sur chaque domaine, &quot;/outpost.goauthentik.io&quot; doit être routé vers le poste avancé (lorsque vous utilisez un poste avancé géré, cela est fait pour vous).</target>
</trans-unit> </trans-unit>
<trans-unit id="scb58b8a60cad8762"> <trans-unit id="scb58b8a60cad8762">
<source>Default relay state</source> <source>Default relay state</source>
@ -7491,7 +7491,7 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti
<target>Utilisateur créé et ajouté au groupe <x id="0" equiv-text="${this.group.name}"/> avec succès</target> <target>Utilisateur créé et ajouté au groupe <x id="0" equiv-text="${this.group.name}"/> avec succès</target>
</trans-unit> </trans-unit>
<trans-unit id="s824e0943a7104668"> <trans-unit id="s824e0943a7104668">
<source>This user will be added to the group "<x id="0" equiv-text="${this.targetGroup.name}"/>".</source> <source>This user will be added to the group &quot;<x id="0" equiv-text="${this.targetGroup.name}"/>&quot;.</source>
<target>Cet utilisateur sera ajouté au groupe &amp;quot;<x id="0" equiv-text="${this.targetGroup.name}"/>&amp;quot;.</target> <target>Cet utilisateur sera ajouté au groupe &amp;quot;<x id="0" equiv-text="${this.targetGroup.name}"/>&amp;quot;.</target>
</trans-unit> </trans-unit>
<trans-unit id="s62e7f6ed7d9cb3ca"> <trans-unit id="s62e7f6ed7d9cb3ca">
@ -8777,7 +8777,7 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti
<target>Synchroniser le groupe</target> <target>Synchroniser le groupe</target>
</trans-unit> </trans-unit>
<trans-unit id="s2d5f69929bb7221d"> <trans-unit id="s2d5f69929bb7221d">
<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> <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>
<target><x id="0" equiv-text="${p.name}"/> (&amp;quot;<x id="1" equiv-text="${p.fieldKey}"/>&amp;quot;, de type <x id="2" equiv-text="${p.type}"/>)</target> <target><x id="0" equiv-text="${p.name}"/> (&amp;quot;<x id="1" equiv-text="${p.fieldKey}"/>&amp;quot;, de type <x id="2" equiv-text="${p.type}"/>)</target>
</trans-unit> </trans-unit>
<trans-unit id="s25bacc19d98b444e"> <trans-unit id="s25bacc19d98b444e">
@ -9025,8 +9025,8 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti
<target>URLs de redirection autorisées après un flux d'autorisation réussi. Indiquez également toute origine ici pour les flux implicites.</target> <target>URLs de redirection autorisées après un flux d'autorisation réussi. Indiquez également toute origine ici pour les flux implicites.</target>
</trans-unit> </trans-unit>
<trans-unit id="s4c49d27de60a532b"> <trans-unit id="s4c49d27de60a532b">
<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> <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>Pour permettre n'importe quelle URI de redirection, définissez cette valeur sur ".*". Soyez conscient des possibles implications de sécurité que cela peut avoir.</target> <target>Pour permettre n'importe quelle URI de redirection, définissez cette valeur sur &quot;.*&quot;. Soyez conscient des possibles implications de sécurité que cela peut avoir.</target>
</trans-unit> </trans-unit>
<trans-unit id="sa52bf79fe1ccb13e"> <trans-unit id="sa52bf79fe1ccb13e">
<source>Federated OIDC Sources</source> <source>Federated OIDC Sources</source>
@ -9691,8 +9691,8 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti
<target>Échec de la prévisualisation de l'invite</target> <target>Échec de la prévisualisation de l'invite</target>
</trans-unit> </trans-unit>
<trans-unit id="s783964a224796865"> <trans-unit id="s783964a224796865">
<source>Field which contains members of a group. Note that if using the "memberUid" field, the value is assumed to contain a relative distinguished name. e.g. 'memberUid=some-user' instead of 'memberUid=cn=some-user,ou=groups,...'. When selecting 'Lookup using a user attribute', this should be a user attribute, otherwise a group attribute.</source> <source>Field which contains members of a group. Note that if using the &quot;memberUid&quot; field, the value is assumed to contain a relative distinguished name. e.g. 'memberUid=some-user' instead of 'memberUid=cn=some-user,ou=groups,...'. When selecting 'Lookup using a user attribute', this should be a user attribute, otherwise a group attribute.</source>
<target>Champ qui contient les membres d'un groupe. Si vous utilisez le champ "memberUid", la valeur est censée contenir un nom distinctif relatif, par exemple 'memberUid=un-utilisateur' au lieu de 'memberUid=cn=un-utilisateur,ou=groups,...'. Lorsque "Recherche avec un attribut utilisateur" est sélectionné, cet attribut doit être un attribut utilisateur, sinon un attribut de groupe.</target> <target>Champ qui contient les membres d'un groupe. Si vous utilisez le champ &quot;memberUid&quot;, la valeur est censée contenir un nom distinctif relatif, par exemple 'memberUid=un-utilisateur' au lieu de 'memberUid=cn=un-utilisateur,ou=groups,...'. Lorsque &quot;Recherche avec un attribut utilisateur&quot; est sélectionné, cet attribut doit être un attribut utilisateur, sinon un attribut de groupe.</target>
</trans-unit> </trans-unit>
<trans-unit id="s1d47b4f61ca53e8e"> <trans-unit id="s1d47b4f61ca53e8e">
<source>Lookup using user attribute</source> <source>Lookup using user attribute</source>
@ -9783,8 +9783,8 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti
<target>Comment effectuer l'authentification lors d'une demande de jeton pour le flux authorization_code</target> <target>Comment effectuer l'authentification lors d'une demande de jeton pour le flux authorization_code</target>
</trans-unit> </trans-unit>
<trans-unit id="s844baf19a6c4a9b4"> <trans-unit id="s844baf19a6c4a9b4">
<source>Enable "Remember me on this device"</source> <source>Enable &quot;Remember me on this device&quot;</source>
<target>Activer "Se souvenir de moi sur cet appareil"</target> <target>Activer &quot;Se souvenir de moi sur cet appareil&quot;</target>
</trans-unit> </trans-unit>
<trans-unit id="sfa72bca733f40692"> <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> <source>When enabled, the user can save their username in a cookie, allowing them to skip directly to entering their password.</source>
@ -9809,52 +9809,7 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti
<trans-unit id="s7d4ec232535a36f0"> <trans-unit id="s7d4ec232535a36f0">
<source>Choose a Provider</source> <source>Choose a Provider</source>
<target>Choisir un fournisseur</target> <target>Choisir un fournisseur</target>
</trans-unit>
<trans-unit id="sa30ba280de276758">
<source>When enabled, the SAML response will be signed.</source>
</trans-unit>
<trans-unit id="s2c42bb3c6f5420d2">
<source>Client Certificates</source>
</trans-unit>
<trans-unit id="s95901716c0629274">
<source>Available Certificates</source>
</trans-unit>
<trans-unit id="sdbf6b484fa1436b0">
<source>Selected Certificates</source>
</trans-unit>
<trans-unit id="s9300147e327fd8f6">
<source>Client-certificate/mTLS authentication/enrollment.</source>
</trans-unit>
<trans-unit id="sbf990ec848470f5c">
<source>Certificate optional</source>
</trans-unit>
<trans-unit id="s72e2876e9409b9eb">
<source>If no certificate was provided, this stage will succeed and continue to the next stage.</source>
</trans-unit>
<trans-unit id="se07d973901a6e6b9">
<source>Certificate required</source>
</trans-unit>
<trans-unit id="s664c47df020ee414">
<source>If no certificate was provided, this stage will stop flow execution.</source>
</trans-unit>
<trans-unit id="sbe9da6dad795aa39">
<source>Certificate authorities</source>
</trans-unit>
<trans-unit id="se3a6aa4f0ab7568e">
<source>Configure the certificate authority client certificates are validated against. The certificate authority can also be configured on a brand, which allows for different certificate authorities for different domains.</source>
</trans-unit>
<trans-unit id="sb8fdf5a09a969870">
<source>Certificate attribute</source>
</trans-unit>
<trans-unit id="s8069037a865037c9">
<source>Configure the attribute of the certificate used to look for a user.</source>
</trans-unit>
<trans-unit id="sc185a8ad96f8eaa2">
<source>User attribute</source>
</trans-unit>
<trans-unit id="s4f9860fefb8fbe01">
<source>Configure the attribute of the user used to look for a user.</source>
</trans-unit> </trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>

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="it" source-language="en" original="lit-localize-inputs" datatype="plaintext"> <file target-language="it" source-language="en" original="lit-localize-inputs" datatype="plaintext">
<body> <body>
<trans-unit id="s4caed5b7a7e5d89b"> <trans-unit id="s4caed5b7a7e5d89b">
@ -596,9 +596,9 @@
</trans-unit> </trans-unit>
<trans-unit id="saa0e2675da69651b"> <trans-unit id="saa0e2675da69651b">
<source>The URL "<x id="0" equiv-text="${this.url}"/>" was not found.</source> <source>The URL &quot;<x id="0" equiv-text="${this.url}"/>&quot; was not found.</source>
<target>La URL " <target>La URL &quot;
<x id="0" equiv-text="${this.url}"/>" non è stata trovata.</target> <x id="0" equiv-text="${this.url}"/>&quot; non è stata trovata.</target>
</trans-unit> </trans-unit>
<trans-unit id="s58cd9c2fe836d9c6"> <trans-unit id="s58cd9c2fe836d9c6">
@ -1106,7 +1106,7 @@
</trans-unit> </trans-unit>
<trans-unit id="sde949d0ef44572eb"> <trans-unit id="sde949d0ef44572eb">
<source>Requires the user to have a 'upn' attribute set, and falls back to hashed user ID. Use this mode only if you have different UPN and Mail domains.</source> <source>Requires the user to have a 'upn' attribute set, and falls back to hashed user ID. Use this mode only if you have different UPN and Mail domains.</source>
<target>Richiede che l'utente abbia un attributo "upn" impostato e ricorre all'ID utente con hash. Utilizza questa modalità solo se disponi di domini UPN e di posta diversi.</target> <target>Richiede che l'utente abbia un attributo &quot;upn&quot; impostato e ricorre all'ID utente con hash. Utilizza questa modalità solo se disponi di domini UPN e di posta diversi.</target>
</trans-unit> </trans-unit>
<trans-unit id="s9f23ed1799b4d49a"> <trans-unit id="s9f23ed1799b4d49a">
@ -1266,7 +1266,7 @@
</trans-unit> </trans-unit>
<trans-unit id="s211b75e868072162"> <trans-unit id="s211b75e868072162">
<source>Set this to the domain you wish the authentication to be valid for. Must be a parent domain of the URL above. If you're running applications as app1.domain.tld, app2.domain.tld, set this to 'domain.tld'.</source> <source>Set this to the domain you wish the authentication to be valid for. Must be a parent domain of the URL above. If you're running applications as app1.domain.tld, app2.domain.tld, set this to 'domain.tld'.</source>
<target>Impostalo sul dominio per il quale desideri che l'autenticazione sia valida. Deve essere un dominio principale dell'URL riportato sopra. Se esegui applicazioni come app1.domain.tld, app2.domain.tld, impostalo su "domain.tld".</target> <target>Impostalo sul dominio per il quale desideri che l'autenticazione sia valida. Deve essere un dominio principale dell'URL riportato sopra. Se esegui applicazioni come app1.domain.tld, app2.domain.tld, impostalo su &quot;domain.tld&quot;.</target>
</trans-unit> </trans-unit>
<trans-unit id="s2345170f7e272668"> <trans-unit id="s2345170f7e272668">
@ -1715,8 +1715,8 @@
</trans-unit> </trans-unit>
<trans-unit id="sa90b7809586c35ce"> <trans-unit id="sa90b7809586c35ce">
<source>Either input a full URL, a relative path, or use 'fa://fa-test' to use the Font Awesome icon "fa-test".</source> <source>Either input a full URL, a relative path, or use 'fa://fa-test' to use the Font Awesome icon &quot;fa-test&quot;.</source>
<target>Inserisci un URL completo, un percorso relativo oppure utilizza "fa://fa-test" per utilizzare l'icona "fa-test" di Font Awesome.</target> <target>Inserisci un URL completo, un percorso relativo oppure utilizza &quot;fa://fa-test&quot; per utilizzare l'icona &quot;fa-test&quot; di Font Awesome.</target>
</trans-unit> </trans-unit>
<trans-unit id="s0410779cb47de312"> <trans-unit id="s0410779cb47de312">
@ -3155,7 +3155,7 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit> </trans-unit>
<trans-unit id="s3198c384c2f68b08"> <trans-unit id="s3198c384c2f68b08">
<source>Time offset when temporary users should be deleted. This only applies if your IDP uses the NameID Format 'transient', and the user doesn't log out manually.</source> <source>Time offset when temporary users should be deleted. This only applies if your IDP uses the NameID Format 'transient', and the user doesn't log out manually.</source>
<target>Tempo da attendere quando gli utenti temporanei devono essere eliminati. Questo vale solo se l'IDP utilizza il formato NameID "Transient" e l'utente non si disconnette manualmente.</target> <target>Tempo da attendere quando gli utenti temporanei devono essere eliminati. Questo vale solo se l'IDP utilizza il formato NameID &quot;Transient&quot; e l'utente non si disconnette manualmente.</target>
</trans-unit> </trans-unit>
<trans-unit id="sb32e9c1faa0b8673"> <trans-unit id="sb32e9c1faa0b8673">
@ -3297,7 +3297,7 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit> </trans-unit>
<trans-unit id="s9f8aac89fe318acc"> <trans-unit id="s9f8aac89fe318acc">
<source>Optionally set the 'FriendlyName' value of the Assertion attribute.</source> <source>Optionally set the 'FriendlyName' value of the Assertion attribute.</source>
<target>Opzionale: imposta il valore "friendlyname" dell'attributo di asserzione.</target> <target>Opzionale: imposta il valore &quot;friendlyname&quot; dell'attributo di asserzione.</target>
</trans-unit> </trans-unit>
<trans-unit id="s851c108679653d2a"> <trans-unit id="s851c108679653d2a">
@ -3778,10 +3778,10 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit> </trans-unit>
<trans-unit id="sa95a538bfbb86111"> <trans-unit id="sa95a538bfbb86111">
<source>Are you sure you want to update <x id="0" equiv-text="${this.objectLabel}"/> "<x id="1" equiv-text="${this.obj?.name}"/>"?</source> <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>
<target>Sei sicuro di voler aggiornare <target>Sei sicuro di voler aggiornare
<x id="0" equiv-text="${this.objectLabel}"/>" <x id="0" equiv-text="${this.objectLabel}"/>&quot;
<x id="1" equiv-text="${this.obj?.name}"/>"?</target> <x id="1" equiv-text="${this.obj?.name}"/>&quot;?</target>
</trans-unit> </trans-unit>
<trans-unit id="sc92d7cfb6ee1fec6"> <trans-unit id="sc92d7cfb6ee1fec6">
@ -4154,7 +4154,7 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit> </trans-unit>
<trans-unit id="s7520286c8419a266"> <trans-unit id="s7520286c8419a266">
<source>Optional data which is loaded into the flow's 'prompt_data' context variable. YAML or JSON.</source> <source>Optional data which is loaded into the flow's 'prompt_data' context variable. YAML or JSON.</source>
<target>Dati facoltativi che vengono caricati nella variabile di contesto "prompt_data" del flusso. YAML o JSON.</target> <target>Dati facoltativi che vengono caricati nella variabile di contesto &quot;prompt_data&quot; del flusso. YAML o JSON.</target>
</trans-unit> </trans-unit>
<trans-unit id="sb8795b799c70776a"> <trans-unit id="sb8795b799c70776a">
@ -4847,8 +4847,8 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit> </trans-unit>
<trans-unit id="sdf1d8edef27236f0"> <trans-unit id="sdf1d8edef27236f0">
<source>A "roaming" authenticator, like a YubiKey</source> <source>A &quot;roaming&quot; authenticator, like a YubiKey</source>
<target>Un autenticatore "roaming", come un YubiKey</target> <target>Un autenticatore &quot;roaming&quot;, come un YubiKey</target>
</trans-unit> </trans-unit>
<trans-unit id="sfffba7b23d8fb40c"> <trans-unit id="sfffba7b23d8fb40c">
@ -5153,7 +5153,7 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit> </trans-unit>
<trans-unit id="s5170f9ef331949c0"> <trans-unit id="s5170f9ef331949c0">
<source>Show arbitrary input fields to the user, for example during enrollment. Data is saved in the flow context under the 'prompt_data' variable.</source> <source>Show arbitrary input fields to the user, for example during enrollment. Data is saved in the flow context under the 'prompt_data' variable.</source>
<target>Mostra campi di input arbitrari all'utente, ad esempio durante l'iscrizione. I dati vengono salvati nel contesto di flusso nell'ambito della variabile "prompt_data".</target> <target>Mostra campi di input arbitrari all'utente, ad esempio durante l'iscrizione. I dati vengono salvati nel contesto di flusso nell'ambito della variabile &quot;prompt_data&quot;.</target>
</trans-unit> </trans-unit>
<trans-unit id="s36cb242ac90353bc"> <trans-unit id="s36cb242ac90353bc">
@ -5206,8 +5206,8 @@ doesn't pass when either or both of the selected options are equal or above the
</trans-unit> </trans-unit>
<trans-unit id="s1608b2f94fa0dbd4"> <trans-unit id="s1608b2f94fa0dbd4">
<source>If set to a duration above 0, the user will have the option to choose to "stay signed in", which will extend their session by the time specified here.</source> <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>Se impostato su una durata superiore a 0, l'utente avrà la possibilità di scegliere di "rimanere firmato", che estenderà la sessione entro il momento specificato qui.</target> <target>Se impostato su una durata superiore a 0, l'utente avrà la possibilità di scegliere di &quot;rimanere firmato&quot;, che estenderà la sessione entro il momento specificato qui.</target>
</trans-unit> </trans-unit>
<trans-unit id="s542a71bb8f41e057"> <trans-unit id="s542a71bb8f41e057">
@ -5228,7 +5228,7 @@ doesn't pass when either or both of the selected options are equal or above the
<trans-unit id="s927398c400970760"> <trans-unit id="s927398c400970760">
<source>Write any data from the flow's context's 'prompt_data' to the currently pending user. If no user <source>Write any data from the flow's context's 'prompt_data' to the currently pending user. If no user
is pending, a new user is created, and data is written to them.</source> is pending, a new user is created, and data is written to them.</source>
<target>Scrivi qualsiasi dati dal contesto del flusso "prompt_data" all'utente attualmente in sospeso. Se nessun utente <target>Scrivi qualsiasi dati dal contesto del flusso &quot;prompt_data&quot; all'utente attualmente in sospeso. Se nessun utente
è in sospeso, viene creato un nuovo utente e vengono scritti dati.</target> è in sospeso, viene creato un nuovo utente e vengono scritti dati.</target>
</trans-unit> </trans-unit>
<trans-unit id="sb379d861cbed0b47"> <trans-unit id="sb379d861cbed0b47">
@ -7377,7 +7377,7 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit> </trans-unit>
<trans-unit id="s070fdfb03034ca9b"> <trans-unit id="s070fdfb03034ca9b">
<source>One hint, 'New Application Wizard', is currently hidden</source> <source>One hint, 'New Application Wizard', is currently hidden</source>
<target>Un suggerimento, "New Application Wizard", è attualmente nascosto</target> <target>Un suggerimento, &quot;New Application Wizard&quot;, è attualmente nascosto</target>
</trans-unit> </trans-unit>
<trans-unit id="s1cc306d8e28c4464"> <trans-unit id="s1cc306d8e28c4464">
<source>Deny message</source> <source>Deny message</source>
@ -7492,7 +7492,7 @@ Bindings to groups/users are checked against the user of the event.</source>
<target>Utente creato con successo e aggiunto al gruppo <x id="0" equiv-text="${this.group.name}"/></target> <target>Utente creato con successo e aggiunto al gruppo <x id="0" equiv-text="${this.group.name}"/></target>
</trans-unit> </trans-unit>
<trans-unit id="s824e0943a7104668"> <trans-unit id="s824e0943a7104668">
<source>This user will be added to the group "<x id="0" equiv-text="${this.targetGroup.name}"/>".</source> <source>This user will be added to the group &quot;<x id="0" equiv-text="${this.targetGroup.name}"/>&quot;.</source>
<target>Questo utente sarà aggiunto al gruppo &amp;quot;<x id="0" equiv-text="${this.targetGroup.name}"/>&amp;quot;.</target> <target>Questo utente sarà aggiunto al gruppo &amp;quot;<x id="0" equiv-text="${this.targetGroup.name}"/>&amp;quot;.</target>
</trans-unit> </trans-unit>
<trans-unit id="s62e7f6ed7d9cb3ca"> <trans-unit id="s62e7f6ed7d9cb3ca">
@ -8643,7 +8643,7 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit> </trans-unit>
<trans-unit id="s9dda0789d278f5c5"> <trans-unit id="s9dda0789d278f5c5">
<source>Provide users with a 'show password' button.</source> <source>Provide users with a 'show password' button.</source>
<target>Fornisci agli utenti un pulsante "Mostra password".</target> <target>Fornisci agli utenti un pulsante &quot;Mostra password&quot;.</target>
</trans-unit> </trans-unit>
<trans-unit id="s2f7f35f6a5b733f5"> <trans-unit id="s2f7f35f6a5b733f5">
<source>Show password</source> <source>Show password</source>
@ -8778,7 +8778,7 @@ Bindings to groups/users are checked against the user of the event.</source>
<target>Gruppo di sincronizzazione</target> <target>Gruppo di sincronizzazione</target>
</trans-unit> </trans-unit>
<trans-unit id="s2d5f69929bb7221d"> <trans-unit id="s2d5f69929bb7221d">
<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> <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>
<target><x id="0" equiv-text="${p.name}"/> (&amp;quot;<x id="1" equiv-text="${p.fieldKey}"/>&amp;quot;, del tipo <x id="2" equiv-text="${p.type}"/>)</target> <target><x id="0" equiv-text="${p.name}"/> (&amp;quot;<x id="1" equiv-text="${p.fieldKey}"/>&amp;quot;, del tipo <x id="2" equiv-text="${p.type}"/>)</target>
</trans-unit> </trans-unit>
<trans-unit id="s25bacc19d98b444e"> <trans-unit id="s25bacc19d98b444e">
@ -9026,8 +9026,8 @@ Bindings to groups/users are checked against the user of the event.</source>
<target>URI di reindirizzamento validi dopo un flusso di autorizzazione riuscito. Specificare anche eventuali origini per i flussi impliciti.</target> <target>URI di reindirizzamento validi dopo un flusso di autorizzazione riuscito. Specificare anche eventuali origini per i flussi impliciti.</target>
</trans-unit> </trans-unit>
<trans-unit id="s4c49d27de60a532b"> <trans-unit id="s4c49d27de60a532b">
<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> <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>Per consentire qualsiasi URI di reindirizzamento, imposta la modalità su Regex e il valore su ".*". Tieni presente le possibili implicazioni per la sicurezza.</target> <target>Per consentire qualsiasi URI di reindirizzamento, imposta la modalità su Regex e il valore su &quot;.*&quot;. Tieni presente le possibili implicazioni per la sicurezza.</target>
</trans-unit> </trans-unit>
<trans-unit id="sa52bf79fe1ccb13e"> <trans-unit id="sa52bf79fe1ccb13e">
<source>Federated OIDC Sources</source> <source>Federated OIDC Sources</source>
@ -9692,8 +9692,8 @@ Bindings to groups/users are checked against the user of the event.</source>
<target>Impossibile visualizzare l'anteprima del prompt</target> <target>Impossibile visualizzare l'anteprima del prompt</target>
</trans-unit> </trans-unit>
<trans-unit id="s783964a224796865"> <trans-unit id="s783964a224796865">
<source>Field which contains members of a group. Note that if using the "memberUid" field, the value is assumed to contain a relative distinguished name. e.g. 'memberUid=some-user' instead of 'memberUid=cn=some-user,ou=groups,...'. When selecting 'Lookup using a user attribute', this should be a user attribute, otherwise a group attribute.</source> <source>Field which contains members of a group. Note that if using the &quot;memberUid&quot; field, the value is assumed to contain a relative distinguished name. e.g. 'memberUid=some-user' instead of 'memberUid=cn=some-user,ou=groups,...'. When selecting 'Lookup using a user attribute', this should be a user attribute, otherwise a group attribute.</source>
<target>Campo che contiene i membri di un gruppo. Si noti che se si utilizza il campo "memberUid", si presume che il valore contenga un nome relativo distinto. Ad esempio, "memberUid=some-user" invece di "memberUid=cn=some-user,ou=groups,...". Quando si seleziona "Cerca utilizzando un attributo utente", questo dovrebbe essere un attributo utente, altrimenti un attributo di gruppo.</target> <target>Campo che contiene i membri di un gruppo. Si noti che se si utilizza il campo &quot;memberUid&quot;, si presume che il valore contenga un nome relativo distinto. Ad esempio, &quot;memberUid=some-user&quot; invece di &quot;memberUid=cn=some-user,ou=groups,...&quot;. Quando si seleziona &quot;Cerca utilizzando un attributo utente&quot;, questo dovrebbe essere un attributo utente, altrimenti un attributo di gruppo.</target>
</trans-unit> </trans-unit>
<trans-unit id="s1d47b4f61ca53e8e"> <trans-unit id="s1d47b4f61ca53e8e">
<source>Lookup using user attribute</source> <source>Lookup using user attribute</source>
@ -9701,7 +9701,7 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit> </trans-unit>
<trans-unit id="s17359123e1f24504"> <trans-unit id="s17359123e1f24504">
<source>Field which contains DNs of groups the user is a member of. This field is used to lookup groups from users, e.g. 'memberOf'. To lookup nested groups in an Active Directory environment use 'memberOf:1.2.840.113556.1.4.1941:'.</source> <source>Field which contains DNs of groups the user is a member of. This field is used to lookup groups from users, e.g. 'memberOf'. To lookup nested groups in an Active Directory environment use 'memberOf:1.2.840.113556.1.4.1941:'.</source>
<target>Campo che contiene i ND dei gruppi di cui l'utente è membro. Questo campo viene utilizzato per cercare i gruppi degli utenti, ad esempio "memberOf". Per cercare gruppi nidificati in un ambiente Active Directory, utilizzare "memberOf:1.2.840.113556.1.4.1941:".</target> <target>Campo che contiene i ND dei gruppi di cui l'utente è membro. Questo campo viene utilizzato per cercare i gruppi degli utenti, ad esempio &quot;memberOf&quot;. Per cercare gruppi nidificati in un ambiente Active Directory, utilizzare &quot;memberOf:1.2.840.113556.1.4.1941:&quot;.</target>
</trans-unit> </trans-unit>
<trans-unit id="s891cd64acabf23bf"> <trans-unit id="s891cd64acabf23bf">
<source>Initial Permissions</source> <source>Initial Permissions</source>
@ -9784,8 +9784,8 @@ Bindings to groups/users are checked against the user of the event.</source>
<target>Come eseguire l'autenticazione durante un flusso di richiesta del token authorization_code</target> <target>Come eseguire l'autenticazione durante un flusso di richiesta del token authorization_code</target>
</trans-unit> </trans-unit>
<trans-unit id="s844baf19a6c4a9b4"> <trans-unit id="s844baf19a6c4a9b4">
<source>Enable "Remember me on this device"</source> <source>Enable &quot;Remember me on this device&quot;</source>
<target>Abilita "Ricordami su questo dispositivo"</target> <target>Abilita &quot;Ricordami su questo dispositivo&quot;</target>
</trans-unit> </trans-unit>
<trans-unit id="sfa72bca733f40692"> <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> <source>When enabled, the user can save their username in a cookie, allowing them to skip directly to entering their password.</source>
@ -9810,52 +9810,7 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s7d4ec232535a36f0"> <trans-unit id="s7d4ec232535a36f0">
<source>Choose a Provider</source> <source>Choose a Provider</source>
<target>Scegli un Provider</target> <target>Scegli un Provider</target>
</trans-unit>
<trans-unit id="sa30ba280de276758">
<source>When enabled, the SAML response will be signed.</source>
</trans-unit>
<trans-unit id="s2c42bb3c6f5420d2">
<source>Client Certificates</source>
</trans-unit>
<trans-unit id="s95901716c0629274">
<source>Available Certificates</source>
</trans-unit>
<trans-unit id="sdbf6b484fa1436b0">
<source>Selected Certificates</source>
</trans-unit>
<trans-unit id="s9300147e327fd8f6">
<source>Client-certificate/mTLS authentication/enrollment.</source>
</trans-unit>
<trans-unit id="sbf990ec848470f5c">
<source>Certificate optional</source>
</trans-unit>
<trans-unit id="s72e2876e9409b9eb">
<source>If no certificate was provided, this stage will succeed and continue to the next stage.</source>
</trans-unit>
<trans-unit id="se07d973901a6e6b9">
<source>Certificate required</source>
</trans-unit>
<trans-unit id="s664c47df020ee414">
<source>If no certificate was provided, this stage will stop flow execution.</source>
</trans-unit>
<trans-unit id="sbe9da6dad795aa39">
<source>Certificate authorities</source>
</trans-unit>
<trans-unit id="se3a6aa4f0ab7568e">
<source>Configure the certificate authority client certificates are validated against. The certificate authority can also be configured on a brand, which allows for different certificate authorities for different domains.</source>
</trans-unit>
<trans-unit id="sb8fdf5a09a969870">
<source>Certificate attribute</source>
</trans-unit>
<trans-unit id="s8069037a865037c9">
<source>Configure the attribute of the certificate used to look for a user.</source>
</trans-unit>
<trans-unit id="sc185a8ad96f8eaa2">
<source>User attribute</source>
</trans-unit>
<trans-unit id="s4f9860fefb8fbe01">
<source>Configure the attribute of the user used to look for a user.</source>
</trans-unit> </trans-unit>
</body> </body>
</file> </file>
</xliff> </xliff>

View File

@ -9164,51 +9164,6 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit> </trans-unit>
<trans-unit id="s7d4ec232535a36f0"> <trans-unit id="s7d4ec232535a36f0">
<source>Choose a Provider</source> <source>Choose a Provider</source>
</trans-unit>
<trans-unit id="sa30ba280de276758">
<source>When enabled, the SAML response will be signed.</source>
</trans-unit>
<trans-unit id="s2c42bb3c6f5420d2">
<source>Client Certificates</source>
</trans-unit>
<trans-unit id="s95901716c0629274">
<source>Available Certificates</source>
</trans-unit>
<trans-unit id="sdbf6b484fa1436b0">
<source>Selected Certificates</source>
</trans-unit>
<trans-unit id="s9300147e327fd8f6">
<source>Client-certificate/mTLS authentication/enrollment.</source>
</trans-unit>
<trans-unit id="sbf990ec848470f5c">
<source>Certificate optional</source>
</trans-unit>
<trans-unit id="s72e2876e9409b9eb">
<source>If no certificate was provided, this stage will succeed and continue to the next stage.</source>
</trans-unit>
<trans-unit id="se07d973901a6e6b9">
<source>Certificate required</source>
</trans-unit>
<trans-unit id="s664c47df020ee414">
<source>If no certificate was provided, this stage will stop flow execution.</source>
</trans-unit>
<trans-unit id="sbe9da6dad795aa39">
<source>Certificate authorities</source>
</trans-unit>
<trans-unit id="se3a6aa4f0ab7568e">
<source>Configure the certificate authority client certificates are validated against. The certificate authority can also be configured on a brand, which allows for different certificate authorities for different domains.</source>
</trans-unit>
<trans-unit id="sb8fdf5a09a969870">
<source>Certificate attribute</source>
</trans-unit>
<trans-unit id="s8069037a865037c9">
<source>Configure the attribute of the certificate used to look for a user.</source>
</trans-unit>
<trans-unit id="sc185a8ad96f8eaa2">
<source>User attribute</source>
</trans-unit>
<trans-unit id="s4f9860fefb8fbe01">
<source>Configure the attribute of the user used to look for a user.</source>
</trans-unit> </trans-unit>
</body> </body>
</file> </file>

View File

@ -9066,51 +9066,6 @@ Bindingen naar groepen/gebruikers worden gecontroleerd tegen de gebruiker van de
</trans-unit> </trans-unit>
<trans-unit id="s7d4ec232535a36f0"> <trans-unit id="s7d4ec232535a36f0">
<source>Choose a Provider</source> <source>Choose a Provider</source>
</trans-unit>
<trans-unit id="sa30ba280de276758">
<source>When enabled, the SAML response will be signed.</source>
</trans-unit>
<trans-unit id="s2c42bb3c6f5420d2">
<source>Client Certificates</source>
</trans-unit>
<trans-unit id="s95901716c0629274">
<source>Available Certificates</source>
</trans-unit>
<trans-unit id="sdbf6b484fa1436b0">
<source>Selected Certificates</source>
</trans-unit>
<trans-unit id="s9300147e327fd8f6">
<source>Client-certificate/mTLS authentication/enrollment.</source>
</trans-unit>
<trans-unit id="sbf990ec848470f5c">
<source>Certificate optional</source>
</trans-unit>
<trans-unit id="s72e2876e9409b9eb">
<source>If no certificate was provided, this stage will succeed and continue to the next stage.</source>
</trans-unit>
<trans-unit id="se07d973901a6e6b9">
<source>Certificate required</source>
</trans-unit>
<trans-unit id="s664c47df020ee414">
<source>If no certificate was provided, this stage will stop flow execution.</source>
</trans-unit>
<trans-unit id="sbe9da6dad795aa39">
<source>Certificate authorities</source>
</trans-unit>
<trans-unit id="se3a6aa4f0ab7568e">
<source>Configure the certificate authority client certificates are validated against. The certificate authority can also be configured on a brand, which allows for different certificate authorities for different domains.</source>
</trans-unit>
<trans-unit id="sb8fdf5a09a969870">
<source>Certificate attribute</source>
</trans-unit>
<trans-unit id="s8069037a865037c9">
<source>Configure the attribute of the certificate used to look for a user.</source>
</trans-unit>
<trans-unit id="sc185a8ad96f8eaa2">
<source>User attribute</source>
</trans-unit>
<trans-unit id="s4f9860fefb8fbe01">
<source>Configure the attribute of the user used to look for a user.</source>
</trans-unit> </trans-unit>
</body> </body>
</file> </file>

View File

@ -9491,51 +9491,6 @@ Powiązania z grupami/użytkownikami są sprawdzane względem użytkownika zdarz
</trans-unit> </trans-unit>
<trans-unit id="s7d4ec232535a36f0"> <trans-unit id="s7d4ec232535a36f0">
<source>Choose a Provider</source> <source>Choose a Provider</source>
</trans-unit>
<trans-unit id="sa30ba280de276758">
<source>When enabled, the SAML response will be signed.</source>
</trans-unit>
<trans-unit id="s2c42bb3c6f5420d2">
<source>Client Certificates</source>
</trans-unit>
<trans-unit id="s95901716c0629274">
<source>Available Certificates</source>
</trans-unit>
<trans-unit id="sdbf6b484fa1436b0">
<source>Selected Certificates</source>
</trans-unit>
<trans-unit id="s9300147e327fd8f6">
<source>Client-certificate/mTLS authentication/enrollment.</source>
</trans-unit>
<trans-unit id="sbf990ec848470f5c">
<source>Certificate optional</source>
</trans-unit>
<trans-unit id="s72e2876e9409b9eb">
<source>If no certificate was provided, this stage will succeed and continue to the next stage.</source>
</trans-unit>
<trans-unit id="se07d973901a6e6b9">
<source>Certificate required</source>
</trans-unit>
<trans-unit id="s664c47df020ee414">
<source>If no certificate was provided, this stage will stop flow execution.</source>
</trans-unit>
<trans-unit id="sbe9da6dad795aa39">
<source>Certificate authorities</source>
</trans-unit>
<trans-unit id="se3a6aa4f0ab7568e">
<source>Configure the certificate authority client certificates are validated against. The certificate authority can also be configured on a brand, which allows for different certificate authorities for different domains.</source>
</trans-unit>
<trans-unit id="sb8fdf5a09a969870">
<source>Certificate attribute</source>
</trans-unit>
<trans-unit id="s8069037a865037c9">
<source>Configure the attribute of the certificate used to look for a user.</source>
</trans-unit>
<trans-unit id="sc185a8ad96f8eaa2">
<source>User attribute</source>
</trans-unit>
<trans-unit id="s4f9860fefb8fbe01">
<source>Configure the attribute of the user used to look for a user.</source>
</trans-unit> </trans-unit>
</body> </body>
</file> </file>

View File

@ -9499,49 +9499,4 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s7d4ec232535a36f0"> <trans-unit id="s7d4ec232535a36f0">
<source>Choose a Provider</source> <source>Choose a Provider</source>
</trans-unit> </trans-unit>
<trans-unit id="sa30ba280de276758">
<source>When enabled, the SAML response will be signed.</source>
</trans-unit>
<trans-unit id="s2c42bb3c6f5420d2">
<source>Client Certificates</source>
</trans-unit>
<trans-unit id="s95901716c0629274">
<source>Available Certificates</source>
</trans-unit>
<trans-unit id="sdbf6b484fa1436b0">
<source>Selected Certificates</source>
</trans-unit>
<trans-unit id="s9300147e327fd8f6">
<source>Client-certificate/mTLS authentication/enrollment.</source>
</trans-unit>
<trans-unit id="sbf990ec848470f5c">
<source>Certificate optional</source>
</trans-unit>
<trans-unit id="s72e2876e9409b9eb">
<source>If no certificate was provided, this stage will succeed and continue to the next stage.</source>
</trans-unit>
<trans-unit id="se07d973901a6e6b9">
<source>Certificate required</source>
</trans-unit>
<trans-unit id="s664c47df020ee414">
<source>If no certificate was provided, this stage will stop flow execution.</source>
</trans-unit>
<trans-unit id="sbe9da6dad795aa39">
<source>Certificate authorities</source>
</trans-unit>
<trans-unit id="se3a6aa4f0ab7568e">
<source>Configure the certificate authority client certificates are validated against. The certificate authority can also be configured on a brand, which allows for different certificate authorities for different domains.</source>
</trans-unit>
<trans-unit id="sb8fdf5a09a969870">
<source>Certificate attribute</source>
</trans-unit>
<trans-unit id="s8069037a865037c9">
<source>Configure the attribute of the certificate used to look for a user.</source>
</trans-unit>
<trans-unit id="sc185a8ad96f8eaa2">
<source>User attribute</source>
</trans-unit>
<trans-unit id="s4f9860fefb8fbe01">
<source>Configure the attribute of the user used to look for a user.</source>
</trans-unit>
</body></file></xliff> </body></file></xliff>

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