mirror of
https://github.com/goauthentik/authentik
synced 2026-05-12 09:57:14 +02:00
Compare commits
1 Commits
a11y-comma
...
fix-logger
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b7a478cc42 |
4
.github/actions/setup/action.yml
vendored
4
.github/actions/setup/action.yml
vendored
@@ -22,7 +22,7 @@ runs:
|
||||
sudo rm -rf /usr/local/lib/android
|
||||
- name: Install uv
|
||||
if: ${{ contains(inputs.dependencies, 'python') }}
|
||||
uses: astral-sh/setup-uv@5a095e7a2014a4212f075830d4f7277575a9d098 # v5
|
||||
uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v5
|
||||
with:
|
||||
enable-cache: true
|
||||
- name: Setup python
|
||||
@@ -36,7 +36,7 @@ runs:
|
||||
run: uv sync --all-extras --dev --frozen
|
||||
- name: Setup node
|
||||
if: ${{ contains(inputs.dependencies, 'node') }}
|
||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v4
|
||||
uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v4
|
||||
with:
|
||||
node-version-file: web/package.json
|
||||
cache: "npm"
|
||||
|
||||
@@ -67,12 +67,12 @@ jobs:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v5
|
||||
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v5
|
||||
with:
|
||||
node-version-file: web/package.json
|
||||
cache: "npm"
|
||||
cache-dependency-path: web/package-lock.json
|
||||
- uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6
|
||||
- uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6
|
||||
with:
|
||||
go-version-file: "go.mod"
|
||||
- name: Generate API Clients
|
||||
@@ -95,7 +95,7 @@ jobs:
|
||||
platforms: linux/${{ inputs.image_arch }}
|
||||
cache-from: type=registry,ref=${{ steps.ev.outputs.attestImageNames }}:buildcache-${{ inputs.image_arch }}
|
||||
cache-to: ${{ steps.ev.outputs.cacheTo }}
|
||||
- uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # v3
|
||||
- uses: actions/attest-build-provenance@96278af6caaf10aea03fd8d33a09a777ca52d62f # v3
|
||||
id: attest
|
||||
if: ${{ steps.ev.outputs.shouldPush == 'true' }}
|
||||
with:
|
||||
|
||||
2
.github/workflows/_reusable-docker-build.yml
vendored
2
.github/workflows/_reusable-docker-build.yml
vendored
@@ -97,7 +97,7 @@ jobs:
|
||||
sources: |
|
||||
${{ steps.ev.outputs.attestImageNames }}@${{ needs.build-server-amd64.outputs.image-digest }}
|
||||
${{ steps.ev.outputs.attestImageNames }}@${{ needs.build-server-arm64.outputs.image-digest }}
|
||||
- uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # v3
|
||||
- uses: actions/attest-build-provenance@96278af6caaf10aea03fd8d33a09a777ca52d62f # v3
|
||||
id: attest
|
||||
with:
|
||||
subject-name: ${{ steps.ev.outputs.attestImageNames }}
|
||||
|
||||
2
.github/workflows/api-ts-publish.yml
vendored
2
.github/workflows/api-ts-publish.yml
vendored
@@ -25,7 +25,7 @@ jobs:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
|
||||
with:
|
||||
token: ${{ steps.generate_token.outputs.token }}
|
||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v5
|
||||
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v5
|
||||
with:
|
||||
node-version-file: web/package.json
|
||||
registry-url: "https://registry.npmjs.org"
|
||||
|
||||
8
.github/workflows/ci-api-docs.yml
vendored
8
.github/workflows/ci-api-docs.yml
vendored
@@ -33,7 +33,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
|
||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v5
|
||||
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v5
|
||||
with:
|
||||
node-version-file: website/package.json
|
||||
cache: "npm"
|
||||
@@ -55,7 +55,7 @@ jobs:
|
||||
env:
|
||||
NODE_ENV: production
|
||||
run: npm run build -w api
|
||||
- uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v4
|
||||
- uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v4
|
||||
with:
|
||||
name: api-docs
|
||||
path: website/api/build
|
||||
@@ -67,11 +67,11 @@ jobs:
|
||||
- build
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
|
||||
- uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v5
|
||||
- uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v5
|
||||
with:
|
||||
name: api-docs
|
||||
path: website/api/build
|
||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v5
|
||||
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v5
|
||||
with:
|
||||
node-version-file: website/package.json
|
||||
cache: "npm"
|
||||
|
||||
2
.github/workflows/ci-aws-cfn.yml
vendored
2
.github/workflows/ci-aws-cfn.yml
vendored
@@ -24,7 +24,7 @@ jobs:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
|
||||
- name: Setup authentik env
|
||||
uses: ./.github/actions/setup
|
||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v5
|
||||
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v5
|
||||
with:
|
||||
node-version-file: lifecycle/aws/package.json
|
||||
cache: "npm"
|
||||
|
||||
6
.github/workflows/ci-docs.yml
vendored
6
.github/workflows/ci-docs.yml
vendored
@@ -36,7 +36,7 @@ jobs:
|
||||
NODE_ENV: production
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
|
||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v5
|
||||
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v5
|
||||
with:
|
||||
node-version-file: website/package.json
|
||||
cache: "npm"
|
||||
@@ -53,7 +53,7 @@ jobs:
|
||||
NODE_ENV: production
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
|
||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v5
|
||||
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v5
|
||||
with:
|
||||
node-version-file: website/package.json
|
||||
cache: "npm"
|
||||
@@ -105,7 +105,7 @@ jobs:
|
||||
context: .
|
||||
cache-from: type=registry,ref=ghcr.io/goauthentik/dev-docs:buildcache
|
||||
cache-to: ${{ steps.ev.outputs.shouldPush == 'true' && 'type=registry,ref=ghcr.io/goauthentik/dev-docs:buildcache,mode=max' || '' }}
|
||||
- uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # v3
|
||||
- uses: actions/attest-build-provenance@96278af6caaf10aea03fd8d33a09a777ca52d62f # v3
|
||||
id: attest
|
||||
if: ${{ steps.ev.outputs.shouldPush == 'true' }}
|
||||
with:
|
||||
|
||||
2
.github/workflows/ci-main.yml
vendored
2
.github/workflows/ci-main.yml
vendored
@@ -279,7 +279,7 @@ jobs:
|
||||
with:
|
||||
flags: conformance
|
||||
- if: ${{ !cancelled() }}
|
||||
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
|
||||
uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6
|
||||
with:
|
||||
name: conformance-certification-${{ matrix.job.name }}
|
||||
path: tests/openid_conformance/exports/
|
||||
|
||||
10
.github/workflows/ci-outpost.yml
vendored
10
.github/workflows/ci-outpost.yml
vendored
@@ -22,7 +22,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
|
||||
- uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6
|
||||
- uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6
|
||||
with:
|
||||
go-version-file: "go.mod"
|
||||
- name: Prepare and generate API
|
||||
@@ -43,7 +43,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
|
||||
- uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6
|
||||
- uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6
|
||||
with:
|
||||
go-version-file: "go.mod"
|
||||
- name: Setup authentik env
|
||||
@@ -122,7 +122,7 @@ jobs:
|
||||
context: .
|
||||
cache-from: type=registry,ref=ghcr.io/goauthentik/dev-${{ matrix.type }}:buildcache
|
||||
cache-to: ${{ steps.ev.outputs.shouldPush == 'true' && format('type=registry,ref=ghcr.io/goauthentik/dev-{0}:buildcache,mode=max', matrix.type) || '' }}
|
||||
- uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # v3
|
||||
- uses: actions/attest-build-provenance@96278af6caaf10aea03fd8d33a09a777ca52d62f # v3
|
||||
id: attest
|
||||
if: ${{ steps.ev.outputs.shouldPush == 'true' }}
|
||||
with:
|
||||
@@ -148,10 +148,10 @@ jobs:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
- uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6
|
||||
- uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6
|
||||
with:
|
||||
go-version-file: "go.mod"
|
||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v5
|
||||
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v5
|
||||
with:
|
||||
node-version-file: web/package.json
|
||||
cache: "npm"
|
||||
|
||||
6
.github/workflows/ci-web.yml
vendored
6
.github/workflows/ci-web.yml
vendored
@@ -32,7 +32,7 @@ jobs:
|
||||
project: web
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
|
||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v5
|
||||
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v5
|
||||
with:
|
||||
node-version-file: ${{ matrix.project }}/package.json
|
||||
cache: "npm"
|
||||
@@ -49,7 +49,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
|
||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v5
|
||||
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v5
|
||||
with:
|
||||
node-version-file: web/package.json
|
||||
cache: "npm"
|
||||
@@ -77,7 +77,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
|
||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v5
|
||||
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v5
|
||||
with:
|
||||
node-version-file: web/package.json
|
||||
cache: "npm"
|
||||
|
||||
5
.github/workflows/packages-npm-publish.yml
vendored
5
.github/workflows/packages-npm-publish.yml
vendored
@@ -9,6 +9,7 @@ on:
|
||||
- packages/eslint-config/**
|
||||
- packages/prettier-config/**
|
||||
- packages/docusaurus-config/**
|
||||
- packages/logger-js/**
|
||||
- packages/esbuild-plugin-live-reload/**
|
||||
workflow_dispatch:
|
||||
|
||||
@@ -35,13 +36,13 @@ jobs:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
|
||||
with:
|
||||
fetch-depth: 2
|
||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v5
|
||||
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v5
|
||||
with:
|
||||
node-version-file: ${{ matrix.package }}/package.json
|
||||
registry-url: "https://registry.npmjs.org"
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@22103cc46bda19c2b464ffe86db46df6922fd323 # 24d32ffd492484c1d75e0c0b894501ddb9d30d62
|
||||
uses: tj-actions/changed-files@7dee1b0c1557f278e5c7dc244927139d78c0e22a # 24d32ffd492484c1d75e0c0b894501ddb9d30d62
|
||||
with:
|
||||
files: |
|
||||
${{ matrix.package }}/package.json
|
||||
|
||||
14
.github/workflows/release-publish.yml
vendored
14
.github/workflows/release-publish.yml
vendored
@@ -58,7 +58,7 @@ jobs:
|
||||
push: true
|
||||
platforms: linux/amd64,linux/arm64
|
||||
context: .
|
||||
- uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # v3
|
||||
- uses: actions/attest-build-provenance@96278af6caaf10aea03fd8d33a09a777ca52d62f # v3
|
||||
id: attest
|
||||
if: true
|
||||
with:
|
||||
@@ -84,10 +84,10 @@ jobs:
|
||||
- rac
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
|
||||
- uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6
|
||||
- uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6
|
||||
with:
|
||||
go-version-file: "go.mod"
|
||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v5
|
||||
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v5
|
||||
with:
|
||||
node-version-file: web/package.json
|
||||
cache: "npm"
|
||||
@@ -129,7 +129,7 @@ jobs:
|
||||
file: lifecycle/container/${{ matrix.type }}.Dockerfile
|
||||
platforms: linux/amd64,linux/arm64
|
||||
context: .
|
||||
- uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # v3
|
||||
- uses: actions/attest-build-provenance@96278af6caaf10aea03fd8d33a09a777ca52d62f # v3
|
||||
id: attest
|
||||
with:
|
||||
subject-name: ${{ steps.ev.outputs.attestImageNames }}
|
||||
@@ -152,10 +152,10 @@ jobs:
|
||||
goarch: [amd64, arm64]
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
|
||||
- uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v6
|
||||
- uses: actions/setup-go@7a3fe6cf4cb3a834922a1244abfce67bcef6a0c5 # v6
|
||||
with:
|
||||
go-version-file: "go.mod"
|
||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v5
|
||||
- uses: actions/setup-node@6044e13b5dc448c55e2357c09f80417699197238 # v5
|
||||
with:
|
||||
node-version-file: web/package.json
|
||||
cache: "npm"
|
||||
@@ -180,7 +180,7 @@ jobs:
|
||||
export CGO_ENABLED=0
|
||||
go build -tags=outpost_static_embed -v -o ./authentik-outpost-${{ matrix.type }}_${{ matrix.goos }}_${{ matrix.goarch }} ./cmd/${{ matrix.type }}
|
||||
- name: Upload binaries to release
|
||||
uses: svenstaro/upload-release-action@b98a3b12e86552593f3e4e577ca8a62aa2f3f22b # v2
|
||||
uses: svenstaro/upload-release-action@6b7fa9f267e90b50a19fef07b3596790bb941741 # v2
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: ./authentik-outpost-${{ matrix.type }}_${{ matrix.goos }}_${{ matrix.goarch }}
|
||||
|
||||
5
.github/workflows/release-tag.yml
vendored
5
.github/workflows/release-tag.yml
vendored
@@ -91,7 +91,6 @@ jobs:
|
||||
# ID from https://api.github.com/users/authentik-automation[bot]
|
||||
git config --global user.name '${{ steps.app-token.outputs.app-slug }}[bot]'
|
||||
git config --global user.email '${{ steps.get-user-id.outputs.user-id }}+${{ steps.app-token.outputs.app-slug }}[bot]@users.noreply.github.com'
|
||||
git pull
|
||||
git commit -a -m "release: ${{ inputs.version }}" --allow-empty
|
||||
git tag "version/${{ inputs.version }}" HEAD -m "version/${{ inputs.version }}"
|
||||
git push --follow-tags
|
||||
@@ -175,7 +174,7 @@ jobs:
|
||||
if: "${{ inputs.release_reason == 'feature' }}"
|
||||
run: |
|
||||
changelog_url="https://docs.goauthentik.io/docs/releases/${{ needs.check-inputs.outputs.major_version }}"
|
||||
reason="${{ inputs.release_reason }}"
|
||||
reason="{{ inputs.release_reason }}"
|
||||
jq \
|
||||
--arg version "${{ inputs.version }}" \
|
||||
--arg changelog "See ${changelog_url}" \
|
||||
@@ -187,7 +186,7 @@ jobs:
|
||||
if: "${{ inputs.release_reason != 'feature' }}"
|
||||
run: |
|
||||
changelog_url="https://docs.goauthentik.io/docs/releases/${{ needs.check-inputs.outputs.major_version }}#fixed-in-$(echo -n ${{ inputs.version}} | sed 's/\.//g')"
|
||||
reason="${{ inputs.release_reason }}"
|
||||
reason="{{ inputs.release_reason }}"
|
||||
jq \
|
||||
--arg version "${{ inputs.version }}" \
|
||||
--arg changelog "See ${changelog_url}" \
|
||||
|
||||
18
Makefile
18
Makefile
@@ -168,22 +168,12 @@ gen-build: ## Extract the schema from the database
|
||||
gen-compose:
|
||||
$(UV) run scripts/generate_compose.py
|
||||
|
||||
gen-changelog: ## (Release) generate the changelog based from the commits since the last version
|
||||
# These are best-effort guesses based on commit messages
|
||||
$(eval last_version := $(shell git tag --list 'version/*' --sort 'version:refname' | grep -vE 'rc\d+$$' | tail -1))
|
||||
$(eval current_commit := $(shell git rev-parse HEAD))
|
||||
git log --pretty=format:"- %s" $(shell git merge-base ${last_version} ${current_commit})...${current_commit} > merged_to_current
|
||||
git log --pretty=format:"- %s" $(shell git merge-base ${last_version} ${current_commit})...${last_version} > merged_to_last
|
||||
grep -Eo 'cherry-pick (#\d+)' merged_to_last | cut -d ' ' -f 2 | sed 's/.*/(&)$$/' > cherry_picked_to_last
|
||||
grep -vf cherry_picked_to_last merged_to_current | sort > changelog.md
|
||||
rm merged_to_current
|
||||
rm merged_to_last
|
||||
rm cherry_picked_to_last
|
||||
gen-changelog: ## (Release) generate the changelog based from the commits since the last tag
|
||||
git log --pretty=format:" - %s" $(shell git describe --tags $(shell git rev-list --tags --max-count=1))...$(shell git branch --show-current) | sort > changelog.md
|
||||
npx prettier --write changelog.md
|
||||
|
||||
gen-diff: ## (Release) generate the changelog diff between the current schema and the last version
|
||||
$(eval last_version := $(shell git tag --list 'version/*' --sort 'version:refname' | grep -vE 'rc\d+$$' | tail -1))
|
||||
git show ${last_version}:schema.yml > schema-old.yml
|
||||
gen-diff: ## (Release) generate the changelog diff between the current schema and the last tag
|
||||
git show $(shell git describe --tags $(shell git rev-list --tags --max-count=1)):schema.yml > schema-old.yml
|
||||
docker compose -f scripts/api/compose.yml run --rm --user "${UID}:${GID}" diff \
|
||||
--markdown \
|
||||
/local/diff.md \
|
||||
|
||||
@@ -100,25 +100,13 @@ class S3Backend(ManageableBackend):
|
||||
f"storage.{self.usage.value}.{self.name}.addressing_style",
|
||||
CONFIG.get(f"storage.{self.name}.addressing_style", "auto"),
|
||||
)
|
||||
signature_version = CONFIG.get(
|
||||
f"storage.{self.usage.value}.{self.name}.signature_version",
|
||||
CONFIG.get(f"storage.{self.name}.signature_version", "s3v4"),
|
||||
)
|
||||
# Keep signature_version pass-through and let boto3/botocore handle it.
|
||||
# In boto3's S3 configuration docs, `s3v4` (default) and deprecated `s3`
|
||||
# are the documented values:
|
||||
# https://github.com/boto/boto3/blob/791a3e8f36d83664a47b4281a0586b3546cef3ec/docs/source/guide/configuration.rst?plain=1#L398-L407
|
||||
# Botocore also supports additional signer names, so we intentionally do
|
||||
# not enforce a restricted allowlist here.
|
||||
|
||||
return self.session.client(
|
||||
"s3",
|
||||
endpoint_url=endpoint_url,
|
||||
use_ssl=use_ssl,
|
||||
region_name=region_name,
|
||||
config=Config(
|
||||
signature_version=signature_version, s3={"addressing_style": addressing_style}
|
||||
),
|
||||
config=Config(signature_version="s3v4", s3={"addressing_style": addressing_style}),
|
||||
)
|
||||
|
||||
@property
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
from unittest import skipUnless
|
||||
|
||||
from botocore.exceptions import UnsupportedSignatureVersionError
|
||||
from django.test import TestCase
|
||||
|
||||
from authentik.admin.files.tests.utils import FileTestS3BackendMixin, s3_test_server_available
|
||||
@@ -82,27 +81,6 @@ class TestS3Backend(FileTestS3BackendMixin, TestCase):
|
||||
self.assertIn("X-Amz-Signature=", url)
|
||||
self.assertIn("test.png", url)
|
||||
|
||||
def test_client_signature_version_default_v4(self):
|
||||
"""Test S3 client defaults to v4 signature when not configured."""
|
||||
self.assertEqual(self.media_s3_backend.client.meta.config.signature_version, "s3v4")
|
||||
|
||||
@CONFIG.patch("storage.s3.signature_version", "s3")
|
||||
def test_client_signature_version_global_override(self):
|
||||
"""Test S3 client respects globally configured signature version."""
|
||||
self.assertEqual(self.media_s3_backend.client.meta.config.signature_version, "s3")
|
||||
|
||||
@CONFIG.patch("storage.s3.signature_version", "s3v4")
|
||||
@CONFIG.patch("storage.media.s3.signature_version", "s3")
|
||||
def test_client_signature_version_media_override(self):
|
||||
"""Test usage-specific signature version takes precedence over global."""
|
||||
self.assertEqual(self.media_s3_backend.client.meta.config.signature_version, "s3")
|
||||
|
||||
@CONFIG.patch("storage.media.s3.signature_version", "not-a-real-signature")
|
||||
def test_client_signature_version_unsupported(self):
|
||||
"""Test unsupported signature version raises botocore error."""
|
||||
with self.assertRaises(UnsupportedSignatureVersionError):
|
||||
self.media_s3_backend.file_url("test.png", use_cache=False)
|
||||
|
||||
@CONFIG.patch("storage.s3.bucket_name", "test-bucket")
|
||||
def test_file_exists_true(self):
|
||||
"""Test file_exists returns True for existing file"""
|
||||
|
||||
@@ -17,6 +17,7 @@ from django.contrib.sessions.base_session import AbstractBaseSession
|
||||
from django.core.validators import validate_slug
|
||||
from django.db import models
|
||||
from django.db.models import Q, QuerySet, options
|
||||
from django.db.models.constants import LOOKUP_SEP
|
||||
from django.http import HttpRequest
|
||||
from django.utils.functional import cached_property
|
||||
from django.utils.timezone import now
|
||||
@@ -44,7 +45,6 @@ from authentik.lib.models import (
|
||||
DomainlessFormattedURLValidator,
|
||||
SerializerModel,
|
||||
)
|
||||
from authentik.lib.utils.inheritance import get_deepest_child
|
||||
from authentik.lib.utils.time import timedelta_from_string
|
||||
from authentik.policies.models import PolicyBindingModel
|
||||
from authentik.rbac.models import Role
|
||||
@@ -803,7 +803,25 @@ class Application(SerializerModel, PolicyBindingModel):
|
||||
"""Get casted provider instance. Needs Application queryset with_provider"""
|
||||
if not self.provider:
|
||||
return None
|
||||
return get_deepest_child(self.provider)
|
||||
|
||||
candidates = []
|
||||
base_class = Provider
|
||||
for subclass in base_class.objects.get_queryset()._get_subclasses_recurse(base_class):
|
||||
parent = self.provider
|
||||
for level in subclass.split(LOOKUP_SEP):
|
||||
try:
|
||||
parent = getattr(parent, level)
|
||||
except AttributeError:
|
||||
break
|
||||
if parent in candidates:
|
||||
continue
|
||||
idx = subclass.count(LOOKUP_SEP)
|
||||
if type(parent) is not base_class:
|
||||
idx += 1
|
||||
candidates.insert(idx, parent)
|
||||
if not candidates:
|
||||
return None
|
||||
return candidates[-1]
|
||||
|
||||
def backchannel_provider_for[T: Provider](self, provider_type: type[T], **kwargs) -> T | None:
|
||||
"""Get Backchannel provider for a specific type"""
|
||||
|
||||
@@ -78,7 +78,7 @@ def generate_key_id_legacy(key_data: str) -> str:
|
||||
"""Generate Key ID using MD5 (legacy format for backwards compatibility)."""
|
||||
if not key_data:
|
||||
return ""
|
||||
return md5(key_data.encode("utf-8"), usedforsecurity=False).hexdigest() # nosec
|
||||
return md5(key_data.encode("utf-8")).hexdigest() # nosec
|
||||
|
||||
|
||||
class CertificateKeyPair(SerializerModel, ManagedModel, CreatedUpdatedModel):
|
||||
|
||||
@@ -81,8 +81,6 @@ class SignInProcessor:
|
||||
self.sign_in_request = sign_in_request
|
||||
self.saml_processor = AssertionProcessor(self.provider, self.request, AuthNRequest())
|
||||
self.saml_processor.provider.audience = self.sign_in_request.wtrealm
|
||||
if self.provider.signing_kp:
|
||||
self.saml_processor.provider.sign_assertion = True
|
||||
|
||||
def create_response_token(self):
|
||||
root = Element(f"{{{NS_WS_FED_TRUST}}}RequestSecurityTokenResponse", nsmap=NS_MAP)
|
||||
@@ -150,8 +148,7 @@ class SignInProcessor:
|
||||
def response(self) -> dict[str, str]:
|
||||
root = self.create_response_token()
|
||||
assertion = root.xpath("//saml:Assertion", namespaces=NS_MAP)[0]
|
||||
if self.provider.signing_kp:
|
||||
self.saml_processor._sign(assertion)
|
||||
self.saml_processor._sign(assertion)
|
||||
str_token = etree.tostring(root).decode("utf-8") # nosec
|
||||
return delete_none_values(
|
||||
{
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
from django.urls import path
|
||||
|
||||
from authentik.enterprise.providers.ws_federation.api.providers import WSFederationProviderViewSet
|
||||
from authentik.enterprise.providers.ws_federation.views import MetadataDownload, WSFedEntryView
|
||||
from authentik.enterprise.providers.ws_federation.views import WSFedEntryView
|
||||
from authentik.providers.saml.views.metadata import MetadataDownload
|
||||
|
||||
urlpatterns = [
|
||||
path(
|
||||
|
||||
@@ -29,12 +29,6 @@ class RefreshOtherFlowsAfterAuthentication(Flag[bool], key="flows_refresh_others
|
||||
visibility = "public"
|
||||
|
||||
|
||||
class ContinuousLogin(Flag[bool], key="flows_continuous_login"):
|
||||
|
||||
default = False
|
||||
visibility = "public"
|
||||
|
||||
|
||||
class AuthentikFlowsConfig(ManagedAppConfig):
|
||||
"""authentik flows app config"""
|
||||
|
||||
|
||||
@@ -166,7 +166,6 @@ storage:
|
||||
# region: "us-east-1"
|
||||
# use_ssl: True
|
||||
# endpoint: "https://s3.us-east-1.amazonaws.com"
|
||||
# signature_version: "s3v4"
|
||||
# access_key: ""
|
||||
# secret_key: ""
|
||||
# bucket_name: "authentik-data"
|
||||
|
||||
@@ -1,119 +0,0 @@
|
||||
"""Tests for inheritance helpers."""
|
||||
|
||||
from contextlib import contextmanager
|
||||
|
||||
from django.db import connection, models
|
||||
from django.test import TransactionTestCase
|
||||
from django.test.utils import isolate_apps
|
||||
|
||||
from authentik.lib.utils.inheritance import get_deepest_child
|
||||
|
||||
|
||||
@contextmanager
|
||||
def temporary_inheritance_models():
|
||||
"""Create a temporary multi-table inheritance graph for testing."""
|
||||
with isolate_apps("authentik.lib.tests"):
|
||||
|
||||
class GrandParent(models.Model):
|
||||
class Meta:
|
||||
app_label = "tests"
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"GrandParent({self.pk})"
|
||||
|
||||
class Parent(GrandParent):
|
||||
class Meta:
|
||||
app_label = "tests"
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"Parent({self.pk})"
|
||||
|
||||
class Child(Parent):
|
||||
class Meta:
|
||||
app_label = "tests"
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"Child({self.pk})"
|
||||
|
||||
class GrandChild(Child):
|
||||
class Meta:
|
||||
app_label = "tests"
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"GrandChild({self.pk})"
|
||||
|
||||
with connection.schema_editor() as schema_editor:
|
||||
schema_editor.create_model(GrandParent)
|
||||
schema_editor.create_model(Parent)
|
||||
schema_editor.create_model(Child)
|
||||
schema_editor.create_model(GrandChild)
|
||||
|
||||
try:
|
||||
yield GrandParent, Parent, Child, GrandChild
|
||||
finally:
|
||||
with connection.schema_editor() as schema_editor:
|
||||
schema_editor.delete_model(GrandChild)
|
||||
schema_editor.delete_model(Child)
|
||||
schema_editor.delete_model(Parent)
|
||||
schema_editor.delete_model(GrandParent)
|
||||
|
||||
|
||||
class TestInheritanceUtils(TransactionTestCase):
|
||||
"""Tests for helper functions in authentik.lib.utils.inheritance."""
|
||||
|
||||
def test_get_deepest_child_grandparent_to_parent(self):
|
||||
"""GrandParent -> Parent."""
|
||||
with temporary_inheritance_models() as (GrandParent, Parent, _Child, _GrandChild):
|
||||
parent = Parent.objects.create()
|
||||
grandparent = GrandParent.objects.get(pk=parent.pk)
|
||||
|
||||
resolved = get_deepest_child(grandparent)
|
||||
|
||||
self.assertIsInstance(resolved, Parent)
|
||||
self.assertEqual(resolved.pk, parent.pk)
|
||||
|
||||
def test_get_deepest_child_grandparent_to_child(self):
|
||||
"""GrandParent -> Child."""
|
||||
with temporary_inheritance_models() as (GrandParent, _Parent, Child, _GrandChild):
|
||||
child = Child.objects.create()
|
||||
grandparent = GrandParent.objects.get(pk=child.pk)
|
||||
|
||||
resolved = get_deepest_child(grandparent)
|
||||
|
||||
self.assertIsInstance(resolved, Child)
|
||||
self.assertEqual(resolved.pk, child.pk)
|
||||
|
||||
def test_get_deepest_child_grandparent_to_grandchild(self):
|
||||
"""GrandParent -> GrandChild."""
|
||||
with temporary_inheritance_models() as (GrandParent, _Parent, _Child, GrandChild):
|
||||
grandchild = GrandChild.objects.create()
|
||||
grandparent = GrandParent.objects.get(pk=grandchild.pk)
|
||||
|
||||
resolved = get_deepest_child(grandparent)
|
||||
|
||||
self.assertIsInstance(resolved, GrandChild)
|
||||
self.assertEqual(resolved.pk, grandchild.pk)
|
||||
|
||||
def test_get_deepest_child_parent_to_child(self):
|
||||
"""Parent -> Child (start from non-root)."""
|
||||
with temporary_inheritance_models() as (_GrandParent, Parent, Child, _GrandChild):
|
||||
child = Child.objects.create()
|
||||
parent = Parent.objects.get(pk=child.pk)
|
||||
|
||||
resolved = get_deepest_child(parent)
|
||||
|
||||
self.assertIsInstance(resolved, Child)
|
||||
self.assertEqual(resolved.pk, child.pk)
|
||||
|
||||
def test_get_deepest_child_no_queries_with_preloaded_relations(self):
|
||||
"""No extra queries when the inheritance chain is fully select_related."""
|
||||
with temporary_inheritance_models() as (GrandParent, _Parent, _Child, GrandChild):
|
||||
grandchild = GrandChild.objects.create()
|
||||
grandparent = GrandParent.objects.select_related("parent__child__grandchild").get(
|
||||
pk=grandchild.pk
|
||||
)
|
||||
|
||||
with self.assertNumQueries(0):
|
||||
resolved = get_deepest_child(grandparent)
|
||||
|
||||
self.assertIsInstance(resolved, GrandChild)
|
||||
@@ -1,41 +0,0 @@
|
||||
from django.db.models import Model, OneToOneField, OneToOneRel
|
||||
|
||||
|
||||
def get_deepest_child(parent: Model) -> Model:
|
||||
"""
|
||||
In multiple table inheritance, given any ancestor object, get the deepest child object.
|
||||
See https://docs.djangoproject.com/en/dev/topics/db/models/#multi-table-inheritance
|
||||
|
||||
This function does not query the database if `select_related` has been performed on all
|
||||
subclasses of `parent`'s model.
|
||||
"""
|
||||
|
||||
# Almost verbatim copy from django-model-utils, see
|
||||
# https://github.com/jazzband/django-model-utils/blob/5.0.0/model_utils/managers.py#L132
|
||||
one_to_one_rels = [
|
||||
field for field in parent._meta.get_fields() if isinstance(field, OneToOneRel)
|
||||
]
|
||||
|
||||
submodel_fields = [
|
||||
rel
|
||||
for rel in one_to_one_rels
|
||||
if isinstance(rel.field, OneToOneField)
|
||||
and issubclass(rel.field.model, parent._meta.model)
|
||||
and parent._meta.model is not rel.field.model
|
||||
and rel.parent_link
|
||||
]
|
||||
|
||||
submodel_accessors = [submodel_field.get_accessor_name() for submodel_field in submodel_fields]
|
||||
# End Copy
|
||||
|
||||
child = None
|
||||
for submodel in submodel_accessors:
|
||||
try:
|
||||
child = getattr(parent, submodel)
|
||||
break
|
||||
except AttributeError:
|
||||
continue
|
||||
|
||||
if not child:
|
||||
return parent
|
||||
return get_deepest_child(child)
|
||||
@@ -89,7 +89,7 @@ class PytestTestRunner(DiscoverRunner): # pragma: no cover
|
||||
sentry_init()
|
||||
self.logger.debug("Test environment configured")
|
||||
|
||||
self.task_broker = use_test_broker()
|
||||
use_test_broker()
|
||||
|
||||
# Send startup signals
|
||||
pre_startup.send(sender=self, mode="test")
|
||||
@@ -185,9 +185,7 @@ class PytestTestRunner(DiscoverRunner): # pragma: no cover
|
||||
self.logger.info("Running tests", test_files=self.args)
|
||||
with patch("guardian.shortcuts._get_ct_cached", patched__get_ct_cached):
|
||||
try:
|
||||
ret = pytest.main(self.args)
|
||||
self.task_broker.close()
|
||||
return ret
|
||||
except Exception as exc: # noqa
|
||||
self.logger.error("Error running tests", exc=exc, test_files=self.args)
|
||||
return pytest.main(self.args)
|
||||
except Exception as e: # noqa
|
||||
self.logger.error("Error running tests", error=str(e), test_files=self.args)
|
||||
return 1
|
||||
|
||||
@@ -14,7 +14,6 @@ from django.utils.translation import gettext_lazy as _
|
||||
from ldap3 import ALL, NONE, RANDOM, Connection, Server, ServerPool, Tls
|
||||
from ldap3.core.exceptions import LDAPException, LDAPInsufficientAccessRightsResult, LDAPSchemaError
|
||||
from rest_framework.serializers import Serializer
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik.core.models import (
|
||||
Group,
|
||||
@@ -32,7 +31,6 @@ from authentik.tasks.schedules.common import ScheduleSpec
|
||||
LDAP_TIMEOUT = 15
|
||||
LDAP_UNIQUENESS = "ldap_uniq"
|
||||
LDAP_DISTINGUISHED_NAME = "distinguishedName"
|
||||
LOGGER = get_logger()
|
||||
|
||||
|
||||
def flatten(value: Any) -> Any:
|
||||
@@ -270,7 +268,6 @@ class LDAPSource(IncomingSyncSource):
|
||||
)
|
||||
|
||||
if self.start_tls:
|
||||
LOGGER.debug("Connection StartTLS", source=self)
|
||||
conn.start_tls(read_server_info=False)
|
||||
try:
|
||||
successful = conn.bind()
|
||||
@@ -281,9 +278,7 @@ class LDAPSource(IncomingSyncSource):
|
||||
# See https://github.com/goauthentik/authentik/issues/4590
|
||||
# See also https://github.com/goauthentik/authentik/issues/3399
|
||||
if server_kwargs.get("get_info", ALL) == NONE:
|
||||
LOGGER.warning("Failed to connect after schema downgrade", source=self, exc=exc)
|
||||
raise exc
|
||||
LOGGER.warning("Downgrading connection to no schema info", source=self, exc=exc)
|
||||
server_kwargs["get_info"] = NONE
|
||||
return self.connection(server, server_kwargs, connection_kwargs)
|
||||
finally:
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -99,7 +99,6 @@ class IdentificationChallenge(Challenge):
|
||||
password_fields = BooleanField()
|
||||
allow_show_password = BooleanField(default=False)
|
||||
application_pre = CharField(required=False)
|
||||
application_pre_launch = CharField(required=False)
|
||||
flow_designation = ChoiceField(FlowDesignation.choices)
|
||||
captcha_stage = CaptchaChallenge(required=False, allow_null=True)
|
||||
|
||||
@@ -349,12 +348,9 @@ class IdentificationStageView(ChallengeStageView):
|
||||
# If the user has been redirected to us whilst trying to access an
|
||||
# application, PLAN_CONTEXT_APPLICATION is set in the flow plan
|
||||
if PLAN_CONTEXT_APPLICATION in self.executor.plan.context:
|
||||
app: Application = self.executor.plan.context.get(
|
||||
challenge.initial_data["application_pre"] = self.executor.plan.context.get(
|
||||
PLAN_CONTEXT_APPLICATION, Application()
|
||||
)
|
||||
challenge.initial_data["application_pre"] = app.name
|
||||
if launch_url := app.get_launch_url():
|
||||
challenge.initial_data["application_pre_launch"] = launch_url
|
||||
).name
|
||||
if (
|
||||
PLAN_CONTEXT_DEVICE in self.executor.plan.context
|
||||
and PLAN_CONTEXT_DEVICE_AUTH_TOKEN in self.executor.plan.context
|
||||
|
||||
44
authentik/tasks/forks.py
Normal file
44
authentik/tasks/forks.py
Normal file
@@ -0,0 +1,44 @@
|
||||
from signal import pause
|
||||
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik.lib.config import CONFIG
|
||||
|
||||
LOGGER = get_logger()
|
||||
|
||||
|
||||
def worker_healthcheck():
|
||||
import authentik.tasks.setup # noqa
|
||||
from authentik.tasks.middleware import WorkerHealthcheckMiddleware
|
||||
|
||||
host, _, port = CONFIG.get("listen.http").rpartition(":")
|
||||
|
||||
try:
|
||||
port = int(port)
|
||||
except ValueError:
|
||||
LOGGER.error(f"Invalid port entered: {port}")
|
||||
|
||||
WorkerHealthcheckMiddleware.run(host, port)
|
||||
pause()
|
||||
|
||||
|
||||
def worker_status():
|
||||
import authentik.tasks.setup # noqa
|
||||
from authentik.tasks.middleware import WorkerStatusMiddleware
|
||||
|
||||
WorkerStatusMiddleware.run()
|
||||
|
||||
|
||||
def worker_metrics():
|
||||
import authentik.tasks.setup # noqa
|
||||
from authentik.tasks.middleware import MetricsMiddleware
|
||||
|
||||
addr, _, port = CONFIG.get("listen.metrics").rpartition(":")
|
||||
|
||||
try:
|
||||
port = int(port)
|
||||
except ValueError:
|
||||
LOGGER.error(f"Invalid port entered: {port}")
|
||||
|
||||
MetricsMiddleware.run(addr, port)
|
||||
pause()
|
||||
@@ -1,37 +1,29 @@
|
||||
import socket
|
||||
from collections.abc import Callable
|
||||
from http.server import BaseHTTPRequestHandler
|
||||
from threading import Event as TEvent
|
||||
from threading import Thread, current_thread
|
||||
from time import sleep
|
||||
from typing import Any, cast
|
||||
|
||||
import pglock
|
||||
from django.db import OperationalError, connections, transaction
|
||||
from django.db import OperationalError, connections
|
||||
from django.utils.timezone import now
|
||||
from django_dramatiq_postgres.middleware import (
|
||||
CurrentTask as BaseCurrentTask,
|
||||
)
|
||||
from django_dramatiq_postgres.middleware import (
|
||||
HTTPServer,
|
||||
HTTPServerThread,
|
||||
)
|
||||
from django_dramatiq_postgres.middleware import HTTPServer
|
||||
from django_dramatiq_postgres.middleware import (
|
||||
MetricsMiddleware as BaseMetricsMiddleware,
|
||||
)
|
||||
from django_dramatiq_postgres.middleware import (
|
||||
_MetricsHandler as BaseMetricsHandler,
|
||||
)
|
||||
from dramatiq import Worker
|
||||
from dramatiq.broker import Broker
|
||||
from dramatiq.message import Message
|
||||
from dramatiq.middleware import Middleware
|
||||
from psycopg.errors import Error
|
||||
from setproctitle import setthreadtitle
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik import authentik_full_version
|
||||
from authentik.events.models import Event, EventAction
|
||||
from authentik.lib.config import CONFIG
|
||||
from authentik.lib.sentry import should_ignore_exception
|
||||
from authentik.lib.utils.reflection import class_to_path
|
||||
from authentik.root.monitoring import monitoring_set
|
||||
@@ -221,39 +213,17 @@ class _healthcheck_handler(BaseHTTPRequestHandler):
|
||||
|
||||
|
||||
class WorkerHealthcheckMiddleware(Middleware):
|
||||
thread: HTTPServerThread | None
|
||||
@property
|
||||
def forks(self):
|
||||
from authentik.tasks.forks import worker_healthcheck
|
||||
|
||||
def __init__(self):
|
||||
host, _, port = CONFIG.get("listen.http").rpartition(":")
|
||||
|
||||
try:
|
||||
port = int(port)
|
||||
except ValueError:
|
||||
LOGGER.error(f"Invalid port entered: {port}")
|
||||
|
||||
self.host, self.port = host, port
|
||||
|
||||
def after_worker_boot(self, broker: Broker, worker: Worker):
|
||||
self.thread = HTTPServerThread(
|
||||
target=WorkerHealthcheckMiddleware.run, args=(self.host, self.port)
|
||||
)
|
||||
self.thread.start()
|
||||
|
||||
def before_worker_shutdown(self, broker: Broker, worker: Worker):
|
||||
server = self.thread.server
|
||||
if server:
|
||||
server.shutdown()
|
||||
LOGGER.debug("Stopping WorkerHealthcheckMiddleware")
|
||||
self.thread.join()
|
||||
return [worker_healthcheck]
|
||||
|
||||
@staticmethod
|
||||
def run(addr: str, port: int):
|
||||
setthreadtitle("authentik Worker Healthcheck server")
|
||||
try:
|
||||
server = HTTPServer((addr, port), _healthcheck_handler)
|
||||
thread = cast(HTTPServerThread, current_thread())
|
||||
thread.server = server
|
||||
server.serve_forever()
|
||||
httpd = HTTPServer((addr, port), _healthcheck_handler)
|
||||
httpd.serve_forever()
|
||||
except OSError as exc:
|
||||
get_logger(__name__, type(WorkerHealthcheckMiddleware)).warning(
|
||||
"Port is already in use, not starting healthcheck server",
|
||||
@@ -262,50 +232,36 @@ class WorkerHealthcheckMiddleware(Middleware):
|
||||
|
||||
|
||||
class WorkerStatusMiddleware(Middleware):
|
||||
thread: Thread | None
|
||||
thread_event: TEvent | None
|
||||
@property
|
||||
def forks(self):
|
||||
from authentik.tasks.forks import worker_status
|
||||
|
||||
def after_worker_boot(self, broker: Broker, worker: Worker):
|
||||
self.thread_event = TEvent()
|
||||
self.thread = Thread(target=WorkerStatusMiddleware.run, args=(self.thread_event,))
|
||||
self.thread.start()
|
||||
|
||||
def before_worker_shutdown(self, broker: Broker, worker: Worker):
|
||||
self.thread_event.set()
|
||||
LOGGER.debug("Stopping WorkerStatusMiddleware")
|
||||
self.thread.join()
|
||||
return [worker_status]
|
||||
|
||||
@staticmethod
|
||||
def run(event: TEvent):
|
||||
setthreadtitle("authentik Worker status")
|
||||
with transaction.atomic():
|
||||
hostname = socket.gethostname()
|
||||
WorkerStatus.objects.filter(hostname=hostname).delete()
|
||||
status, _ = WorkerStatus.objects.update_or_create(
|
||||
hostname=hostname,
|
||||
version=authentik_full_version(),
|
||||
)
|
||||
while not event.is_set():
|
||||
def run():
|
||||
status = WorkerStatus.objects.create(
|
||||
hostname=socket.gethostname(),
|
||||
version=authentik_full_version(),
|
||||
)
|
||||
while True:
|
||||
try:
|
||||
WorkerStatusMiddleware.keep(event, status)
|
||||
WorkerStatusMiddleware.keep(status)
|
||||
except DB_ERRORS: # pragma: no cover
|
||||
event.wait(10)
|
||||
sleep(10)
|
||||
try:
|
||||
connections.close_all()
|
||||
except DB_ERRORS:
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def keep(event: TEvent, status: WorkerStatus):
|
||||
def keep(status: WorkerStatus):
|
||||
lock_id = f"goauthentik.io/worker/status/{status.pk}"
|
||||
with pglock.advisory(lock_id, side_effect=pglock.Raise):
|
||||
while not event.is_set():
|
||||
status.refresh_from_db()
|
||||
old_last_seen = status.last_seen
|
||||
while True:
|
||||
status.last_seen = now()
|
||||
if old_last_seen != status.last_seen:
|
||||
status.save(update_fields=("last_seen",))
|
||||
event.wait(30)
|
||||
status.save(update_fields=("last_seen",))
|
||||
sleep(30)
|
||||
|
||||
|
||||
class _MetricsHandler(BaseMetricsHandler):
|
||||
@@ -315,26 +271,10 @@ class _MetricsHandler(BaseMetricsHandler):
|
||||
|
||||
|
||||
class MetricsMiddleware(BaseMetricsMiddleware):
|
||||
thread: HTTPServerThread | None
|
||||
handler_class = _MetricsHandler
|
||||
|
||||
@property
|
||||
def forks(self) -> list[Callable[[], None]]:
|
||||
return []
|
||||
def forks(self):
|
||||
from authentik.tasks.forks import worker_metrics
|
||||
|
||||
def after_worker_boot(self, broker: Broker, worker: Worker):
|
||||
addr, _, port = CONFIG.get("listen.metrics").rpartition(":")
|
||||
|
||||
try:
|
||||
port = int(port)
|
||||
except ValueError:
|
||||
LOGGER.error(f"Invalid port entered: {port}")
|
||||
self.thread = HTTPServerThread(target=MetricsMiddleware.run, args=(addr, port))
|
||||
self.thread.start()
|
||||
|
||||
def before_worker_shutdown(self, broker: Broker, worker: Worker):
|
||||
server = self.thread.server
|
||||
if server:
|
||||
server.shutdown()
|
||||
LOGGER.debug("Stopping MetricsMiddleware")
|
||||
self.thread.join()
|
||||
return [worker_metrics]
|
||||
|
||||
@@ -10,26 +10,24 @@ from dramatiq.results.middleware import Results
|
||||
from dramatiq.worker import Worker, _ConsumerThread, _WorkerThread
|
||||
|
||||
from authentik.tasks.broker import PostgresBroker
|
||||
from authentik.tasks.middleware import WorkerHealthcheckMiddleware
|
||||
|
||||
TESTING_QUEUE = "testing"
|
||||
from authentik.tasks.middleware import MetricsMiddleware
|
||||
|
||||
|
||||
class TestWorker(Worker):
|
||||
def __init__(self, broker: Broker):
|
||||
def __init__(self, queue_name: str, broker: Broker):
|
||||
super().__init__(broker=broker)
|
||||
self.work_queue = PriorityQueue()
|
||||
self.consumers = {
|
||||
TESTING_QUEUE: _ConsumerThread(
|
||||
queue_name: _ConsumerThread(
|
||||
broker=self.broker,
|
||||
queue_name=TESTING_QUEUE,
|
||||
queue_name=queue_name,
|
||||
prefetch=2,
|
||||
work_queue=self.work_queue,
|
||||
worker_timeout=1,
|
||||
),
|
||||
}
|
||||
self.consumers[TESTING_QUEUE].consumer = self.broker.consume(
|
||||
queue_name=TESTING_QUEUE,
|
||||
self.consumers[queue_name].consumer = self.broker.consume(
|
||||
queue_name=queue_name,
|
||||
prefetch=2,
|
||||
timeout=1,
|
||||
)
|
||||
@@ -42,29 +40,18 @@ class TestWorker(Worker):
|
||||
|
||||
self.broker.emit_before("worker_boot", self)
|
||||
self.broker.emit_after("worker_boot", self)
|
||||
self.broker.emit_after("process_boot")
|
||||
|
||||
def process_message(self, message: MessageProxy):
|
||||
self.work_queue.put((0, message))
|
||||
self.consumers[TESTING_QUEUE].consumer.in_processing.add(message.message_id)
|
||||
self.work_queue.put(message)
|
||||
self.consumers[message.queue_name].consumer.in_processing.add(message.message_id)
|
||||
self._worker.process_message(message)
|
||||
|
||||
|
||||
class TestBroker(PostgresBroker):
|
||||
worker: TestWorker | None = None
|
||||
|
||||
def start(self):
|
||||
self.worker = TestWorker(broker=self)
|
||||
|
||||
def close(self):
|
||||
self.emit_before("worker_shutdown", self)
|
||||
return super().close()
|
||||
|
||||
def enqueue(self, *args, **kwargs):
|
||||
message = super().enqueue(*args, **kwargs).copy(queue_name=TESTING_QUEUE)
|
||||
if not self.worker:
|
||||
return message
|
||||
self.worker.process_message(MessageProxy(message))
|
||||
message = super().enqueue(*args, **kwargs)
|
||||
worker = TestWorker(message.queue_name, broker=self)
|
||||
worker.process_message(MessageProxy(message))
|
||||
return message
|
||||
|
||||
|
||||
@@ -82,8 +69,8 @@ def use_test_broker():
|
||||
middleware: Middleware = import_string(middleware_class)(
|
||||
**middleware_kwargs,
|
||||
)
|
||||
if isinstance(middleware, WorkerHealthcheckMiddleware):
|
||||
middleware.port = 9102
|
||||
if isinstance(middleware, MetricsMiddleware):
|
||||
continue
|
||||
if isinstance(middleware, Retries):
|
||||
middleware.max_retries = 0
|
||||
if isinstance(middleware, Results):
|
||||
@@ -93,6 +80,4 @@ def use_test_broker():
|
||||
)
|
||||
broker.add_middleware(middleware)
|
||||
|
||||
broker.start()
|
||||
set_broker(broker)
|
||||
return broker
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
from json import loads
|
||||
|
||||
from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
|
||||
from authentik.core.tests.utils import create_test_admin_user
|
||||
from authentik.core.models import Group, User
|
||||
from authentik.lib.generators import generate_id
|
||||
|
||||
|
||||
class TestAdminAPI(TestCase):
|
||||
@@ -9,13 +12,15 @@ class TestAdminAPI(TestCase):
|
||||
|
||||
def setUp(self) -> None:
|
||||
super().setUp()
|
||||
self.user = create_test_admin_user()
|
||||
self.user = User.objects.create(username=generate_id())
|
||||
self.group = Group.objects.create(name=generate_id(), is_superuser=True)
|
||||
self.group.users.add(self.user)
|
||||
self.group.save()
|
||||
self.client.force_login(self.user)
|
||||
|
||||
def test_workers(self):
|
||||
"""Test Workers API"""
|
||||
response = self.client.get(reverse("authentik_api:tasks_workers"))
|
||||
self.assertEqual(response.status_code, 200)
|
||||
# Disabled for flakiness
|
||||
# body = loads(response.content)
|
||||
# self.assertEqual(len(body), 1)
|
||||
body = loads(response.content)
|
||||
self.assertEqual(len(body), 0)
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
from django.test import TestCase
|
||||
from dramatiq import actor, get_broker
|
||||
|
||||
from authentik.tasks.middleware import CurrentTask
|
||||
from authentik.tasks.models import Task, TaskLog
|
||||
|
||||
|
||||
class TestWorkerMiddleware(TestCase):
|
||||
|
||||
def test_task_log(self):
|
||||
@actor
|
||||
def test_task():
|
||||
self = CurrentTask.get_task()
|
||||
self.info("foo")
|
||||
|
||||
test_task.send()
|
||||
task = Task.objects.filter(actor_name=test_task.actor_name).first()
|
||||
logs = list(
|
||||
TaskLog.objects.filter(task=task).order_by("timestamp").values_list("event", flat=True)
|
||||
)
|
||||
self.assertEqual(
|
||||
logs,
|
||||
[
|
||||
"Task has been queued",
|
||||
"Task is being processed",
|
||||
"foo",
|
||||
"Task finished processing without errors",
|
||||
],
|
||||
)
|
||||
broker = get_broker()
|
||||
del broker.actors[test_task.actor_name]
|
||||
|
||||
def test_task_exceptions(self):
|
||||
@actor
|
||||
def test_task():
|
||||
raise ValueError("foo")
|
||||
|
||||
test_task.send()
|
||||
task = Task.objects.filter(actor_name=test_task.actor_name).first()
|
||||
logs = list(
|
||||
TaskLog.objects.filter(task=task).order_by("timestamp").values_list("event", flat=True)
|
||||
)
|
||||
self.assertEqual(
|
||||
logs,
|
||||
[
|
||||
"Task has been queued",
|
||||
"Task is being processed",
|
||||
"foo",
|
||||
],
|
||||
)
|
||||
broker = get_broker()
|
||||
del broker.actors[test_task.actor_name]
|
||||
2
go.mod
2
go.mod
@@ -30,7 +30,7 @@ require (
|
||||
github.com/spf13/cobra v1.10.2
|
||||
github.com/stretchr/testify v1.11.1
|
||||
github.com/wwt/guac v1.3.2
|
||||
goauthentik.io/api/v3 v3.2026020.17-0.20260304104333-840924fe52c4
|
||||
goauthentik.io/api/v3 v3.2026020.17-0.20260223141659-4c1444ee54d9
|
||||
golang.org/x/exp v0.0.0-20230210204819-062eb4c674ab
|
||||
golang.org/x/oauth2 v0.35.0
|
||||
golang.org/x/sync v0.19.0
|
||||
|
||||
2
go.sum
2
go.sum
@@ -218,8 +218,6 @@ goauthentik.io/api/v3 v3.2026020.17-0.20260217173516-3a500f6eed7d h1:Gb26L41O+Q7
|
||||
goauthentik.io/api/v3 v3.2026020.17-0.20260217173516-3a500f6eed7d/go.mod h1:uYa+yGMglhJy8ymyUQ8KQiJjOb3UZTuPQ24Ot2s9BCo=
|
||||
goauthentik.io/api/v3 v3.2026020.17-0.20260223141659-4c1444ee54d9 h1:tuvgm4e1nV0ZPZy24wOeJcuAbMnhbJA09BuI2fzBHRk=
|
||||
goauthentik.io/api/v3 v3.2026020.17-0.20260223141659-4c1444ee54d9/go.mod h1:uYa+yGMglhJy8ymyUQ8KQiJjOb3UZTuPQ24Ot2s9BCo=
|
||||
goauthentik.io/api/v3 v3.2026020.17-0.20260304104333-840924fe52c4 h1:zjmi1QNVQPABt0Yx5hws1lXR3tuTI23Ae7MwXffbP/s=
|
||||
goauthentik.io/api/v3 v3.2026020.17-0.20260304104333-840924fe52c4/go.mod h1:uYa+yGMglhJy8ymyUQ8KQiJjOb3UZTuPQ24Ot2s9BCo=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
"goauthentik.io/api/v3"
|
||||
"goauthentik.io/internal/config"
|
||||
"goauthentik.io/internal/outpost/ak"
|
||||
"goauthentik.io/internal/outpost/proxyv2/constants"
|
||||
"goauthentik.io/internal/outpost/proxyv2/hs256"
|
||||
"goauthentik.io/internal/outpost/proxyv2/metrics"
|
||||
"goauthentik.io/internal/outpost/proxyv2/templates"
|
||||
@@ -293,16 +294,22 @@ func (a *Application) Stop() {
|
||||
|
||||
func (a *Application) handleSignOut(rw http.ResponseWriter, r *http.Request) {
|
||||
redirect := a.endpoint.EndSessionEndpoint
|
||||
cc := a.getClaimsFromSession(rw, r)
|
||||
if cc == nil {
|
||||
s, err := a.sessions.Get(r, a.SessionName())
|
||||
if err != nil {
|
||||
a.redirectToStart(rw, r)
|
||||
return
|
||||
}
|
||||
c, exists := s.Values[constants.SessionClaims]
|
||||
if c == nil && !exists {
|
||||
a.redirectToStart(rw, r)
|
||||
return
|
||||
}
|
||||
cc := c.(types.Claims)
|
||||
uv := url.Values{
|
||||
"id_token_hint": []string{cc.RawToken},
|
||||
}
|
||||
redirect += "?" + uv.Encode()
|
||||
err := a.Logout(r.Context(), func(c types.Claims) bool {
|
||||
err = a.Logout(r.Context(), func(c types.Claims) bool {
|
||||
return c.Sub == cc.Sub
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
@@ -187,7 +187,10 @@ func BuildConnConfig(cfg config.PostgreSQLConfig) (*pgx.ConnConfig, error) {
|
||||
if connConfig.RuntimeParams == nil {
|
||||
connConfig.RuntimeParams = make(map[string]string)
|
||||
}
|
||||
effectiveSearchPath := cfg.DefaultSchema
|
||||
|
||||
if cfg.DefaultSchema != "" {
|
||||
connConfig.RuntimeParams["search_path"] = cfg.DefaultSchema
|
||||
}
|
||||
|
||||
// Parse and apply connection options if specified
|
||||
if cfg.ConnOptions != "" {
|
||||
@@ -195,39 +198,12 @@ func BuildConnConfig(cfg config.PostgreSQLConfig) (*pgx.ConnConfig, error) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse connection options: %w", err)
|
||||
}
|
||||
// search_path from ConnOptions is not supported here; Django controls schema selection.
|
||||
// Always remove it so it cannot end up in startup RuntimeParams via applyConnOptions.
|
||||
delete(connOpts, "search_path")
|
||||
|
||||
if err := applyConnOptions(connConfig, connOpts); err != nil {
|
||||
return nil, fmt.Errorf("failed to apply connection options: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
// search_path may already be present via pgx/libpq inherited defaults (e.g. service files).
|
||||
// Always remove it from startup RuntimeParams; apply it via AfterConnect instead.
|
||||
if inheritedSearchPath, hasInheritedSearchPath := connConfig.RuntimeParams["search_path"]; hasInheritedSearchPath {
|
||||
if effectiveSearchPath == "" {
|
||||
effectiveSearchPath = inheritedSearchPath
|
||||
}
|
||||
delete(connConfig.RuntimeParams, "search_path")
|
||||
}
|
||||
|
||||
// Set search_path after connection startup to avoid startup-parameter issues with PgBouncer.
|
||||
if effectiveSearchPath != "" {
|
||||
connConfig.AfterConnect = func(ctx context.Context, pgConn *pgconn.PgConn) error {
|
||||
result := pgConn.ExecParams(
|
||||
ctx,
|
||||
"select pg_catalog.set_config('search_path', $1, false)",
|
||||
[][]byte{[]byte(effectiveSearchPath)},
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
).Read()
|
||||
return result.Err
|
||||
}
|
||||
}
|
||||
|
||||
return connConfig, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -700,7 +700,7 @@ func TestBuildConnConfig(t *testing.T) {
|
||||
DefaultSchema: "custom_schema",
|
||||
},
|
||||
validate: func(t *testing.T, cc *pgx.ConnConfig) {
|
||||
assert.NotNil(t, cc.AfterConnect)
|
||||
assert.Equal(t, "custom_schema", cc.RuntimeParams["search_path"])
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -756,7 +756,7 @@ func TestBuildConnConfig(t *testing.T) {
|
||||
assert.Equal(t, "admin", cc.User)
|
||||
assert.Equal(t, "my super secret password!@#", cc.Password)
|
||||
assert.Equal(t, "production", cc.Database)
|
||||
assert.NotNil(t, cc.AfterConnect)
|
||||
assert.Equal(t, "app_schema", cc.RuntimeParams["search_path"])
|
||||
assert.Equal(t, "authentik", cc.RuntimeParams["application_name"])
|
||||
},
|
||||
},
|
||||
@@ -863,7 +863,7 @@ func TestBuildConnConfig_WithSSLCertificates(t *testing.T) {
|
||||
assert.Equal(t, "db.example.com", cc.TLSConfig.ServerName)
|
||||
assert.NotNil(t, cc.TLSConfig.RootCAs)
|
||||
assert.Len(t, cc.TLSConfig.Certificates, 1)
|
||||
assert.NotNil(t, cc.AfterConnect)
|
||||
assert.Equal(t, "app_schema", cc.RuntimeParams["search_path"])
|
||||
assert.Equal(t, "authentik", cc.RuntimeParams["application_name"])
|
||||
},
|
||||
},
|
||||
@@ -1357,83 +1357,6 @@ func TestBuildConnConfig_WithBase64EncodedConnOptions(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Verifies DefaultSchema is applied via AfterConnect and never via startup RuntimeParams.
|
||||
func TestBuildConnConfig_SearchPath_DefaultSchema(t *testing.T) {
|
||||
cfg := config.PostgreSQLConfig{
|
||||
Host: "localhost",
|
||||
Port: "5432",
|
||||
User: "authentik",
|
||||
Name: "authentik",
|
||||
DefaultSchema: "default_schema",
|
||||
}
|
||||
|
||||
connConfig, err := BuildConnConfig(cfg)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, connConfig.AfterConnect)
|
||||
_, hasSearchPath := connConfig.RuntimeParams["search_path"]
|
||||
assert.False(t, hasSearchPath, "search_path should not appear in RuntimeParams")
|
||||
}
|
||||
|
||||
// Verifies ConnOptions search_path is ignored and excluded from startup RuntimeParams.
|
||||
func TestBuildConnConfig_SearchPath_ConnOptions(t *testing.T) {
|
||||
cfg := config.PostgreSQLConfig{
|
||||
Host: "localhost",
|
||||
Port: "5432",
|
||||
User: "authentik",
|
||||
Name: "authentik",
|
||||
ConnOptions: base64.StdEncoding.EncodeToString([]byte(`{"search_path":"connopt_schema"}`)),
|
||||
}
|
||||
|
||||
connConfig, err := BuildConnConfig(cfg)
|
||||
require.NoError(t, err)
|
||||
assert.Nil(t, connConfig.AfterConnect)
|
||||
_, hasSearchPath := connConfig.RuntimeParams["search_path"]
|
||||
assert.False(t, hasSearchPath, "search_path should not appear in RuntimeParams")
|
||||
}
|
||||
|
||||
// Verifies ConnOptions search_path does not override DefaultSchema and other conn options still apply.
|
||||
func TestBuildConnConfig_SearchPath_ConnOptionsIgnoredWhenDefaultSchemaSet(t *testing.T) {
|
||||
cfg := config.PostgreSQLConfig{
|
||||
Host: "localhost",
|
||||
Port: "5432",
|
||||
User: "authentik",
|
||||
Name: "authentik",
|
||||
DefaultSchema: "default_schema",
|
||||
ConnOptions: base64.StdEncoding.EncodeToString([]byte(`{"search_path":"override_schema","application_name":"authentik-proxy"}`)),
|
||||
}
|
||||
|
||||
connConfig, err := BuildConnConfig(cfg)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, connConfig.AfterConnect)
|
||||
assert.Equal(t, "authentik-proxy", connConfig.RuntimeParams["application_name"])
|
||||
_, hasSearchPath := connConfig.RuntimeParams["search_path"]
|
||||
assert.False(t, hasSearchPath, "search_path should not appear in RuntimeParams")
|
||||
}
|
||||
|
||||
// Verifies inherited search_path from pgx/libpq defaults is removed from startup RuntimeParams.
|
||||
func TestBuildConnConfig_SearchPath_InheritedServiceSetting(t *testing.T) {
|
||||
serviceFile := filepath.Join(t.TempDir(), "pg_service.conf")
|
||||
err := os.WriteFile(serviceFile, []byte("[authentik-test]\nsearch_path=service_schema\n"), 0o600)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Setenv("PGSERVICE", "authentik-test")
|
||||
t.Setenv("PGSERVICEFILE", serviceFile)
|
||||
|
||||
cfg := config.PostgreSQLConfig{
|
||||
Host: "localhost",
|
||||
Port: "5432",
|
||||
User: "authentik",
|
||||
Name: "authentik",
|
||||
}
|
||||
|
||||
connConfig, err := BuildConnConfig(cfg)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, connConfig.AfterConnect)
|
||||
|
||||
_, hasSearchPath := connConfig.RuntimeParams["search_path"]
|
||||
assert.False(t, hasSearchPath, "search_path should not appear in RuntimeParams")
|
||||
}
|
||||
|
||||
// TestBuildConnConfig_TargetSessionAttrs demonstrates how target_session_attrs
|
||||
// should be properly handled using pgx's ValidateConnect callback
|
||||
func TestBuildConnConfig_TargetSessionAttrs(t *testing.T) {
|
||||
|
||||
8
lifecycle/aws/package-lock.json
generated
8
lifecycle/aws/package-lock.json
generated
@@ -9,7 +9,7 @@
|
||||
"version": "0.0.0",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"aws-cdk": "^2.1108.0",
|
||||
"aws-cdk": "^2.1107.0",
|
||||
"cross-env": "^10.1.0"
|
||||
},
|
||||
"engines": {
|
||||
@@ -25,9 +25,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/aws-cdk": {
|
||||
"version": "2.1108.0",
|
||||
"resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1108.0.tgz",
|
||||
"integrity": "sha512-FHnyhnYZoRc2W0C9mNzhNn6fO2vH4xNINsKfJaA7AFDuymgQ39JhEnrM4AHaoikIBqXYeNLWElvvkusY9l3ulw==",
|
||||
"version": "2.1107.0",
|
||||
"resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1107.0.tgz",
|
||||
"integrity": "sha512-7GKCq7p/33Jw+C+Ohwl4LnnKjvI/MzemeNZlTu/Kg8IwuZx5WEXEi32YLOlxbE1JOvleDslCWK5AIkBZ0omx/Q==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"aws-cfn": "cross-env CI=false cdk synth --version-reporting=false > template.yaml"
|
||||
},
|
||||
"devDependencies": {
|
||||
"aws-cdk": "^2.1108.0",
|
||||
"aws-cdk": "^2.1107.0",
|
||||
"cross-env": "^10.1.0"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
@@ -26,7 +26,7 @@ RUN npm run build && \
|
||||
npm run build:sfe
|
||||
|
||||
# Stage 2: Build go proxy
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.26.0-trixie@sha256:4e603da0ea8df4a8ab10cbf0b3061f7823d277e82ea210a47c32a5fafb43cc43 AS go-builder
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.26.0-trixie@sha256:d0a3e4b733ecc47e92a7e7f0fa141392e5a2349e288470aad1ffd82552da5139 AS go-builder
|
||||
|
||||
ARG TARGETOS
|
||||
ARG TARGETARCH
|
||||
@@ -78,9 +78,9 @@ RUN --mount=type=secret,id=GEOIPUPDATE_ACCOUNT_ID \
|
||||
/bin/sh -c "GEOIPUPDATE_LICENSE_KEY_FILE=/run/secrets/GEOIPUPDATE_LICENSE_KEY /usr/bin/entry.sh || echo 'Failed to get GeoIP database, disabling'; exit 0"
|
||||
|
||||
# Stage 4: Download uv
|
||||
FROM ghcr.io/astral-sh/uv:0.10.8@sha256:88234bc9e09c2b2f6d176a3daf411419eb0370d450a08129257410de9cfafd2a AS uv
|
||||
FROM ghcr.io/astral-sh/uv:0.10.6@sha256:2f2ccd27bbf953ec7a9e3153a4563705e41c852a5e1912b438fc44d88d6cb52c AS uv
|
||||
# Stage 5: Base python image
|
||||
FROM ghcr.io/goauthentik/fips-python:3.14.3-slim-trixie-fips@sha256:43260c054d91fccebf7c5f38f682d65abfc88afa7a5d1c622a938f0fbe1fdcab AS python-base
|
||||
FROM ghcr.io/goauthentik/fips-python:3.14.3-slim-trixie-fips@sha256:de8ad649ed77baa64c07deb0dba2151e18dcb0408fe6ff37bdef236aabb9a576 AS python-base
|
||||
|
||||
ENV VENV_PATH="/ak-root/.venv" \
|
||||
PATH="/lifecycle:/ak-root/.venv/bin:$PATH" \
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
# Stage 1: Build
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.26.0-trixie@sha256:4e603da0ea8df4a8ab10cbf0b3061f7823d277e82ea210a47c32a5fafb43cc43 AS builder
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.26.0-trixie@sha256:d0a3e4b733ecc47e92a7e7f0fa141392e5a2349e288470aad1ffd82552da5139 AS builder
|
||||
|
||||
ARG TARGETOS
|
||||
ARG TARGETARCH
|
||||
@@ -31,7 +31,7 @@ RUN --mount=type=cache,sharing=locked,target=/go/pkg/mod \
|
||||
go build -o /go/ldap ./cmd/ldap
|
||||
|
||||
# Stage 2: Run
|
||||
FROM ghcr.io/goauthentik/fips-debian:trixie-slim-fips@sha256:487b9f11726364cbc83617203976b5bf61bac67ed13502b2836d64a0bd466628
|
||||
FROM ghcr.io/goauthentik/fips-debian:trixie-slim-fips@sha256:7b82e2433395fed1e400120bcd1686de2faba9f59251e19b60dd7dd1ed9efe42
|
||||
|
||||
ARG VERSION
|
||||
ARG GIT_BUILD_HASH
|
||||
|
||||
@@ -17,7 +17,7 @@ COPY web .
|
||||
RUN npm run build-proxy
|
||||
|
||||
# Stage 2: Build
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.26.0-trixie@sha256:4e603da0ea8df4a8ab10cbf0b3061f7823d277e82ea210a47c32a5fafb43cc43 AS builder
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.26.0-trixie@sha256:d0a3e4b733ecc47e92a7e7f0fa141392e5a2349e288470aad1ffd82552da5139 AS builder
|
||||
|
||||
ARG TARGETOS
|
||||
ARG TARGETARCH
|
||||
@@ -47,7 +47,7 @@ RUN --mount=type=cache,sharing=locked,target=/go/pkg/mod \
|
||||
go build -o /go/proxy ./cmd/proxy
|
||||
|
||||
# Stage 3: Run
|
||||
FROM ghcr.io/goauthentik/fips-debian:trixie-slim-fips@sha256:487b9f11726364cbc83617203976b5bf61bac67ed13502b2836d64a0bd466628
|
||||
FROM ghcr.io/goauthentik/fips-debian:trixie-slim-fips@sha256:7b82e2433395fed1e400120bcd1686de2faba9f59251e19b60dd7dd1ed9efe42
|
||||
|
||||
ARG VERSION
|
||||
ARG GIT_BUILD_HASH
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
# Stage 1: Build
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.26.0-trixie@sha256:4e603da0ea8df4a8ab10cbf0b3061f7823d277e82ea210a47c32a5fafb43cc43 AS builder
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.26.0-trixie@sha256:d0a3e4b733ecc47e92a7e7f0fa141392e5a2349e288470aad1ffd82552da5139 AS builder
|
||||
|
||||
ARG TARGETOS
|
||||
ARG TARGETARCH
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
# Stage 1: Build
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.26.0-trixie@sha256:4e603da0ea8df4a8ab10cbf0b3061f7823d277e82ea210a47c32a5fafb43cc43 AS builder
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.26.0-trixie@sha256:d0a3e4b733ecc47e92a7e7f0fa141392e5a2349e288470aad1ffd82552da5139 AS builder
|
||||
|
||||
ARG TARGETOS
|
||||
ARG TARGETARCH
|
||||
@@ -31,7 +31,7 @@ RUN --mount=type=cache,sharing=locked,target=/go/pkg/mod \
|
||||
go build -o /go/radius ./cmd/radius
|
||||
|
||||
# Stage 2: Run
|
||||
FROM ghcr.io/goauthentik/fips-debian:trixie-slim-fips@sha256:487b9f11726364cbc83617203976b5bf61bac67ed13502b2836d64a0bd466628
|
||||
FROM ghcr.io/goauthentik/fips-debian:trixie-slim-fips@sha256:7b82e2433395fed1e400120bcd1686de2faba9f59251e19b60dd7dd1ed9efe42
|
||||
|
||||
ARG VERSION
|
||||
ARG GIT_BUILD_HASH
|
||||
|
||||
694
package-lock.json
generated
694
package-lock.json
generated
@@ -10,15 +10,11 @@
|
||||
"dependencies": {
|
||||
"@eslint/js": "^9.39.3",
|
||||
"@goauthentik/eslint-config": "./packages/eslint-config",
|
||||
"@goauthentik/logger-js": "./packages/logger-js",
|
||||
"@goauthentik/prettier-config": "./packages/prettier-config",
|
||||
"@goauthentik/tsconfig": "./packages/tsconfig",
|
||||
"@typescript-eslint/eslint-plugin": "^8.56.1",
|
||||
"@typescript-eslint/parser": "^8.56.1",
|
||||
"eslint": "^9.39.3",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"pino": "^10.3.1",
|
||||
"pino-pretty": "^13.1.2",
|
||||
"prettier": "^3.8.1",
|
||||
"prettier-plugin-packagejson": "^3.0.0",
|
||||
"typescript": "^5.9.3",
|
||||
@@ -508,10 +504,6 @@
|
||||
"resolved": "packages/eslint-config",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@goauthentik/logger-js": {
|
||||
"resolved": "packages/logger-js",
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@goauthentik/prettier-config": {
|
||||
"resolved": "packages/prettier-config",
|
||||
"link": true
|
||||
@@ -698,12 +690,6 @@
|
||||
"node": ">= 8"
|
||||
}
|
||||
},
|
||||
"node_modules/@pinojs/redact": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@pinojs/redact/-/redact-0.4.0.tgz",
|
||||
"integrity": "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@rtsao/scc": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz",
|
||||
@@ -1274,15 +1260,6 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/atomic-sleep": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/atomic-sleep/-/atomic-sleep-1.0.0.tgz",
|
||||
"integrity": "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/available-typed-arrays": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
|
||||
@@ -1495,12 +1472,6 @@
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/colorette": {
|
||||
"version": "2.0.20",
|
||||
"resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
|
||||
"integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
@@ -1587,15 +1558,6 @@
|
||||
"node": ">=4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dateformat": {
|
||||
"version": "4.6.3",
|
||||
"resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz",
|
||||
"integrity": "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "4.4.3",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
|
||||
@@ -1709,24 +1671,6 @@
|
||||
"integrity": "sha512-sM6HAN2LyK82IyPBpznDRqlTQAtuSaO+ShzFiWTvoMJLHyZ+Y39r8VMfHzwbU8MVBzQ4Wdn85+wlZl2TLGIlwg==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/end-of-stream": {
|
||||
"version": "1.4.5",
|
||||
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
|
||||
"integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"once": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/error-ex": {
|
||||
"version": "1.3.4",
|
||||
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz",
|
||||
"integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"is-arrayish": "^0.2.1"
|
||||
}
|
||||
},
|
||||
"node_modules/es-abstract": {
|
||||
"version": "1.24.1",
|
||||
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.1.tgz",
|
||||
@@ -2395,12 +2339,6 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/fast-copy": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-4.0.2.tgz",
|
||||
"integrity": "sha512-ybA6PDXIXOXivLJK/z9e+Otk7ve13I4ckBvGO5I2RRmBU1gMHLVDJYEuJYhGwez7YNlYji2M2DvVU+a9mSFDlw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fast-deep-equal": {
|
||||
"version": "3.1.3",
|
||||
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
|
||||
@@ -2419,12 +2357,6 @@
|
||||
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fast-safe-stringify": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz",
|
||||
"integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fastq": {
|
||||
"version": "1.20.1",
|
||||
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz",
|
||||
@@ -3110,12 +3042,6 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/help-me": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/help-me/-/help-me-5.0.0.tgz",
|
||||
"integrity": "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/hermes-estree": {
|
||||
"version": "0.25.1",
|
||||
"resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz",
|
||||
@@ -3131,12 +3057,6 @@
|
||||
"hermes-estree": "0.25.1"
|
||||
}
|
||||
},
|
||||
"node_modules/hosted-git-info": {
|
||||
"version": "2.8.9",
|
||||
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
|
||||
"integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/ignore": {
|
||||
"version": "7.0.5",
|
||||
"resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
|
||||
@@ -3225,12 +3145,6 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/is-arrayish": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
|
||||
"integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/is-async-function": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz",
|
||||
@@ -3652,15 +3566,6 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/joycon": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz",
|
||||
"integrity": "sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/js-levenshtein-esm": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-levenshtein-esm/-/js-levenshtein-esm-2.0.0.tgz",
|
||||
@@ -3703,12 +3608,6 @@
|
||||
"integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/json-parse-better-errors": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
|
||||
"integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/json-schema-traverse": {
|
||||
"version": "0.4.1",
|
||||
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||
@@ -3782,21 +3681,6 @@
|
||||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/load-json-file": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
|
||||
"integrity": "sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.1.2",
|
||||
"parse-json": "^4.0.0",
|
||||
"pify": "^3.0.0",
|
||||
"strip-bom": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/locate-path": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
|
||||
@@ -3873,14 +3757,6 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/memorystream": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
|
||||
"integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==",
|
||||
"engines": {
|
||||
"node": ">= 0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/minimatch": {
|
||||
"version": "10.2.3",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.3.tgz",
|
||||
@@ -3935,12 +3811,6 @@
|
||||
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/nice-try": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
|
||||
"integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/node-cache": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/node-cache/-/node-cache-5.1.2.tgz",
|
||||
@@ -3986,218 +3856,6 @@
|
||||
"integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/normalize-package-data": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
|
||||
"integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
|
||||
"license": "BSD-2-Clause",
|
||||
"dependencies": {
|
||||
"hosted-git-info": "^2.1.4",
|
||||
"resolve": "^1.10.0",
|
||||
"semver": "2 || 3 || 4 || 5",
|
||||
"validate-npm-package-license": "^3.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/normalize-package-data/node_modules/semver": {
|
||||
"version": "5.7.2",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
|
||||
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"semver": "bin/semver"
|
||||
}
|
||||
},
|
||||
"node_modules/npm-run-all": {
|
||||
"version": "4.1.5",
|
||||
"resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz",
|
||||
"integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"chalk": "^2.4.1",
|
||||
"cross-spawn": "^6.0.5",
|
||||
"memorystream": "^0.3.1",
|
||||
"minimatch": "^3.0.4",
|
||||
"pidtree": "^0.3.0",
|
||||
"read-pkg": "^3.0.0",
|
||||
"shell-quote": "^1.6.1",
|
||||
"string.prototype.padend": "^3.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"npm-run-all": "bin/npm-run-all/index.js",
|
||||
"run-p": "bin/run-p/index.js",
|
||||
"run-s": "bin/run-s/index.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
}
|
||||
},
|
||||
"node_modules/npm-run-all/node_modules/ansi-styles": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"color-convert": "^1.9.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/npm-run-all/node_modules/balanced-match": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
|
||||
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/npm-run-all/node_modules/brace-expansion": {
|
||||
"version": "1.1.12",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/npm-run-all/node_modules/chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"supports-color": "^5.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/npm-run-all/node_modules/color-convert": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"color-name": "1.1.3"
|
||||
}
|
||||
},
|
||||
"node_modules/npm-run-all/node_modules/color-name": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/npm-run-all/node_modules/cross-spawn": {
|
||||
"version": "6.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.6.tgz",
|
||||
"integrity": "sha512-VqCUuhcd1iB+dsv8gxPttb5iZh/D0iubSP21g36KXdEuf6I5JiioesUVjpCdHV9MZRUfVFlvwtIUyPfxo5trtw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"nice-try": "^1.0.4",
|
||||
"path-key": "^2.0.1",
|
||||
"semver": "^5.5.0",
|
||||
"shebang-command": "^1.2.0",
|
||||
"which": "^1.2.9"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4.8"
|
||||
}
|
||||
},
|
||||
"node_modules/npm-run-all/node_modules/escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/npm-run-all/node_modules/has-flag": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
"integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/npm-run-all/node_modules/minimatch": {
|
||||
"version": "3.1.5",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
|
||||
"integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/npm-run-all/node_modules/path-key": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
|
||||
"integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/npm-run-all/node_modules/semver": {
|
||||
"version": "5.7.2",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
|
||||
"integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
|
||||
"license": "ISC",
|
||||
"bin": {
|
||||
"semver": "bin/semver"
|
||||
}
|
||||
},
|
||||
"node_modules/npm-run-all/node_modules/shebang-command": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
|
||||
"integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"shebang-regex": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/npm-run-all/node_modules/shebang-regex": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
|
||||
"integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/npm-run-all/node_modules/supports-color": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"has-flag": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/npm-run-all/node_modules/which": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
|
||||
"integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"isexe": "^2.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"which": "bin/which"
|
||||
}
|
||||
},
|
||||
"node_modules/object-assign": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||
@@ -4313,15 +3971,6 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/on-exit-leak-free": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz",
|
||||
"integrity": "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=14.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
@@ -4407,19 +4056,6 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/parse-json": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
|
||||
"integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"error-ex": "^1.3.1",
|
||||
"json-parse-better-errors": "^1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/parse5": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
|
||||
@@ -4468,18 +4104,6 @@
|
||||
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/path-type": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
|
||||
"integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"pify": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/picocolors": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
|
||||
@@ -4498,100 +4122,6 @@
|
||||
"url": "https://github.com/sponsors/jonschlinkert"
|
||||
}
|
||||
},
|
||||
"node_modules/pidtree": {
|
||||
"version": "0.3.1",
|
||||
"resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.3.1.tgz",
|
||||
"integrity": "sha512-qQbW94hLHEqCg7nhby4yRC7G2+jYHY4Rguc2bjw7Uug4GIJuu1tvf2uHaZv5Q8zdt+WKJ6qK1FOI6amaWUo5FA==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"pidtree": "bin/pidtree.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/pify": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
|
||||
"integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/pino": {
|
||||
"version": "10.3.1",
|
||||
"resolved": "https://registry.npmjs.org/pino/-/pino-10.3.1.tgz",
|
||||
"integrity": "sha512-r34yH/GlQpKZbU1BvFFqOjhISRo1MNx1tWYsYvmj6KIRHSPMT2+yHOEb1SG6NMvRoHRF0a07kCOox/9yakl1vg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@pinojs/redact": "^0.4.0",
|
||||
"atomic-sleep": "^1.0.0",
|
||||
"on-exit-leak-free": "^2.1.0",
|
||||
"pino-abstract-transport": "^3.0.0",
|
||||
"pino-std-serializers": "^7.0.0",
|
||||
"process-warning": "^5.0.0",
|
||||
"quick-format-unescaped": "^4.0.3",
|
||||
"real-require": "^0.2.0",
|
||||
"safe-stable-stringify": "^2.3.1",
|
||||
"sonic-boom": "^4.0.1",
|
||||
"thread-stream": "^4.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"pino": "bin.js"
|
||||
}
|
||||
},
|
||||
"node_modules/pino-abstract-transport": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pino-abstract-transport/-/pino-abstract-transport-3.0.0.tgz",
|
||||
"integrity": "sha512-wlfUczU+n7Hy/Ha5j9a/gZNy7We5+cXp8YL+X+PG8S0KXxw7n/JXA3c46Y0zQznIJ83URJiwy7Lh56WLokNuxg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"split2": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/pino-pretty": {
|
||||
"version": "13.1.3",
|
||||
"resolved": "https://registry.npmjs.org/pino-pretty/-/pino-pretty-13.1.3.tgz",
|
||||
"integrity": "sha512-ttXRkkOz6WWC95KeY9+xxWL6AtImwbyMHrL1mSwqwW9u+vLp/WIElvHvCSDg0xO/Dzrggz1zv3rN5ovTRVowKg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"colorette": "^2.0.7",
|
||||
"dateformat": "^4.6.3",
|
||||
"fast-copy": "^4.0.0",
|
||||
"fast-safe-stringify": "^2.1.1",
|
||||
"help-me": "^5.0.0",
|
||||
"joycon": "^3.1.1",
|
||||
"minimist": "^1.2.6",
|
||||
"on-exit-leak-free": "^2.1.0",
|
||||
"pino-abstract-transport": "^3.0.0",
|
||||
"pump": "^3.0.0",
|
||||
"secure-json-parse": "^4.0.0",
|
||||
"sonic-boom": "^4.0.1",
|
||||
"strip-json-comments": "^5.0.2"
|
||||
},
|
||||
"bin": {
|
||||
"pino-pretty": "bin.js"
|
||||
}
|
||||
},
|
||||
"node_modules/pino-pretty/node_modules/strip-json-comments": {
|
||||
"version": "5.0.3",
|
||||
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-5.0.3.tgz",
|
||||
"integrity": "sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=14.16"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/pino-std-serializers": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/pino-std-serializers/-/pino-std-serializers-7.1.0.tgz",
|
||||
"integrity": "sha512-BndPH67/JxGExRgiX1dX0w1FvZck5Wa4aal9198SrRhZjH3GxKQUKIBnYJTdj2HDN3UQAS06HlfcSbQj2OHmaw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/possible-typed-array-names": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
|
||||
@@ -4670,22 +4200,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/process-warning": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/process-warning/-/process-warning-5.0.0.tgz",
|
||||
"integrity": "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/fastify"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/fastify"
|
||||
}
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/prop-types": {
|
||||
"version": "15.8.1",
|
||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||
@@ -4697,16 +4211,6 @@
|
||||
"react-is": "^16.13.1"
|
||||
}
|
||||
},
|
||||
"node_modules/pump": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz",
|
||||
"integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"end-of-stream": "^1.1.0",
|
||||
"once": "^1.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/punycode": {
|
||||
"version": "2.3.1",
|
||||
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
|
||||
@@ -4736,41 +4240,12 @@
|
||||
],
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/quick-format-unescaped": {
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.4.tgz",
|
||||
"integrity": "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/react-is": {
|
||||
"version": "16.13.1",
|
||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/read-pkg": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
|
||||
"integrity": "sha512-BLq/cCO9two+lBgiTYNqD6GdtK8s4NpaWrl6/rCO9w0TUS8oJl7cmToOZfRYllKTISY6nt1U7jQ53brmKqY6BA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"load-json-file": "^4.0.0",
|
||||
"normalize-package-data": "^2.3.2",
|
||||
"path-type": "^3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/real-require": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz",
|
||||
"integrity": "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 12.13.0"
|
||||
}
|
||||
},
|
||||
"node_modules/reflect.getprototypeof": {
|
||||
"version": "1.0.10",
|
||||
"resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
|
||||
@@ -4949,31 +4424,6 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/safe-stable-stringify": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz",
|
||||
"integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/secure-json-parse": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-4.1.0.tgz",
|
||||
"integrity": "sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/fastify"
|
||||
},
|
||||
{
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/fastify"
|
||||
}
|
||||
],
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/segment-sort": {
|
||||
"version": "1.0.9",
|
||||
"resolved": "https://registry.npmjs.org/segment-sort/-/segment-sort-1.0.9.tgz",
|
||||
@@ -5059,18 +4509,6 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/shell-quote": {
|
||||
"version": "1.8.3",
|
||||
"resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz",
|
||||
"integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/side-channel": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
|
||||
@@ -5143,15 +4581,6 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/sonic-boom": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-4.2.1.tgz",
|
||||
"integrity": "sha512-w6AxtubXa2wTXAUsZMMWERrsIRAdrK0Sc+FUytWvYAhBJLyuI4llrMIC1DtlNSdI99EI86KZum2MMq3EAZlF9Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"atomic-sleep": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/sort-object-keys": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/sort-object-keys/-/sort-object-keys-2.1.0.tgz",
|
||||
@@ -5188,47 +4617,6 @@
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/spdx-correct": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz",
|
||||
"integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"spdx-expression-parse": "^3.0.0",
|
||||
"spdx-license-ids": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/spdx-exceptions": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz",
|
||||
"integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==",
|
||||
"license": "CC-BY-3.0"
|
||||
},
|
||||
"node_modules/spdx-expression-parse": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
|
||||
"integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"spdx-exceptions": "^2.1.0",
|
||||
"spdx-license-ids": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/spdx-license-ids": {
|
||||
"version": "3.0.23",
|
||||
"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz",
|
||||
"integrity": "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==",
|
||||
"license": "CC0-1.0"
|
||||
},
|
||||
"node_modules/split2": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
|
||||
"integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">= 10.x"
|
||||
}
|
||||
},
|
||||
"node_modules/stop-iteration-iterator": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz",
|
||||
@@ -5315,24 +4703,6 @@
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/string.prototype.padend": {
|
||||
"version": "3.1.6",
|
||||
"resolved": "https://registry.npmjs.org/string.prototype.padend/-/string.prototype.padend-3.1.6.tgz",
|
||||
"integrity": "sha512-XZpspuSB7vJWhvJc9DLSlrXl1mcA2BdoY5jjnS135ydXqLoqhs96JjDtCkjJEQHvfqZIp9hBuBMgI589peyx9Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"call-bind": "^1.0.7",
|
||||
"define-properties": "^1.2.1",
|
||||
"es-abstract": "^1.23.2",
|
||||
"es-object-atoms": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/string.prototype.repeat": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz",
|
||||
@@ -5462,18 +4832,6 @@
|
||||
"integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/thread-stream": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/thread-stream/-/thread-stream-4.0.0.tgz",
|
||||
"integrity": "sha512-4iMVL6HAINXWf1ZKZjIPcz5wYaOdPhtO8ATvZ+Xqp3BTdaqtAwQkNmKORqcIo5YkQqGXq5cwfswDwMqqQNrpJA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"real-require": "^0.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
}
|
||||
},
|
||||
"node_modules/tinyglobby": {
|
||||
"version": "0.2.15",
|
||||
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
|
||||
@@ -5751,16 +5109,6 @@
|
||||
"node": ">= 4"
|
||||
}
|
||||
},
|
||||
"node_modules/validate-npm-package-license": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
|
||||
"integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"spdx-correct": "^3.0.0",
|
||||
"spdx-expression-parse": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/validator": {
|
||||
"version": "13.15.26",
|
||||
"resolved": "https://registry.npmjs.org/validator/-/validator-13.15.26.tgz",
|
||||
@@ -5963,45 +5311,9 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"packages/logger-js": {
|
||||
"name": "@goauthentik/logger-js",
|
||||
"version": "1.0.1",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.39.3",
|
||||
"@goauthentik/prettier-config": "../prettier-config",
|
||||
"@goauthentik/tsconfig": "../tsconfig",
|
||||
"@types/node": "^25.3.0",
|
||||
"@typescript-eslint/eslint-plugin": "^8.56.1",
|
||||
"@typescript-eslint/parser": "^8.56.1",
|
||||
"eslint": "^9.39.3",
|
||||
"pino": "^10.3.1",
|
||||
"pino-pretty": "^13.1.2",
|
||||
"prettier": "^3.8.1",
|
||||
"prettier-plugin-packagejson": "^3.0.0",
|
||||
"typescript": "^5.9.3",
|
||||
"typescript-eslint": "^8.56.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=24",
|
||||
"npm": ">=11.10.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"pino": "^10.3.1",
|
||||
"pino-pretty": "^13.1.2"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"pino": {
|
||||
"optional": true
|
||||
},
|
||||
"pino-pretty": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"packages/prettier-config": {
|
||||
"name": "@goauthentik/prettier-config",
|
||||
"version": "3.4.3",
|
||||
"version": "3.4.1",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"format-imports": "^4.0.8"
|
||||
@@ -6030,11 +5342,11 @@
|
||||
},
|
||||
"packages/tsconfig": {
|
||||
"name": "@goauthentik/tsconfig",
|
||||
"version": "1.0.7",
|
||||
"version": "1.0.5",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=24",
|
||||
"npm": ">=11.10.1"
|
||||
"npm": ">=11.6.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
16
package.json
16
package.json
@@ -9,21 +9,14 @@
|
||||
"lint:spellcheck": "echo 'Skipping spellcheck linting'"
|
||||
},
|
||||
"type": "module",
|
||||
"imports": {
|
||||
"#logger": "./packages/logger-js/lib/node.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@eslint/js": "^9.39.3",
|
||||
"@goauthentik/eslint-config": "./packages/eslint-config",
|
||||
"@goauthentik/logger-js": "./packages/logger-js",
|
||||
"@goauthentik/prettier-config": "./packages/prettier-config",
|
||||
"@goauthentik/tsconfig": "./packages/tsconfig",
|
||||
"@typescript-eslint/eslint-plugin": "^8.56.1",
|
||||
"@typescript-eslint/parser": "^8.56.1",
|
||||
"eslint": "^9.39.3",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"pino": "^10.3.1",
|
||||
"pino-pretty": "^13.1.2",
|
||||
"prettier": "^3.8.1",
|
||||
"prettier-plugin-packagejson": "^3.0.0",
|
||||
"typescript": "^5.9.3",
|
||||
@@ -37,16 +30,15 @@
|
||||
"devEngines": {
|
||||
"runtime": {
|
||||
"name": "node",
|
||||
"onFail": "warn",
|
||||
"version": ">=24"
|
||||
"onFail": "ignore",
|
||||
"version": "24"
|
||||
},
|
||||
"packageManager": {
|
||||
"name": "npm",
|
||||
"version": ">=11.10.1",
|
||||
"onFail": "warn"
|
||||
"version": "11.10.1",
|
||||
"onFail": "ignore"
|
||||
}
|
||||
},
|
||||
"packageManager": "npm@11.11.0+sha512.f36811c4aae1fde639527368ae44c571d050006a608d67a191f195a801a52637a312d259186254aa3a3799b05335b7390539cf28656d18f0591a1125ba35f973",
|
||||
"prettier": "@goauthentik/prettier-config",
|
||||
"overrides": {
|
||||
"format-imports": {
|
||||
|
||||
@@ -235,16 +235,15 @@ class PostgresChannelLoopLayer(BaseChannelLayer):
|
||||
try:
|
||||
while True:
|
||||
message_id, message = await q.get()
|
||||
async with await self.connection() as conn:
|
||||
async with conn.cursor() as cursor:
|
||||
if message is None:
|
||||
if message is None:
|
||||
async with await self.connection() as conn:
|
||||
async with conn.cursor() as cursor:
|
||||
await cursor.execute(
|
||||
sql.SQL("""
|
||||
DELETE
|
||||
SELECT {table}.{message}
|
||||
FROM {table}
|
||||
WHERE {table}.{id} = %s
|
||||
RETURNING {table}.{message}
|
||||
""").format(
|
||||
""").format(
|
||||
table=sql.Identifier(MESSAGE_TABLE),
|
||||
id=sql.Identifier("id"),
|
||||
message=sql.Identifier("message"),
|
||||
@@ -255,18 +254,6 @@ class PostgresChannelLoopLayer(BaseChannelLayer):
|
||||
if row is None:
|
||||
continue
|
||||
message = row[0]
|
||||
else:
|
||||
await cursor.execute(
|
||||
sql.SQL("""
|
||||
DELETE
|
||||
FROM {table}
|
||||
WHERE {table}.{id} = %s
|
||||
""").format(
|
||||
table=sql.Identifier(MESSAGE_TABLE),
|
||||
id=sql.Identifier("id"),
|
||||
),
|
||||
(message_id,),
|
||||
)
|
||||
break
|
||||
except asyncio.CancelledError, TimeoutError, GeneratorExit:
|
||||
# We assume here that the reason we are cancelled is because the consumer
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import platform
|
||||
import sys
|
||||
from argparse import Namespace
|
||||
from multiprocessing import set_start_method
|
||||
from typing import Any
|
||||
|
||||
from django.apps.registry import apps
|
||||
@@ -71,10 +69,7 @@ class Command(BaseCommand):
|
||||
args.pid_file = pid_file
|
||||
|
||||
args.verbose = verbosity - 1
|
||||
# > On macOS [...] the fork start method should be considered unsafe
|
||||
# https://docs.python.org/3/library/multiprocessing.html#contexts-and-start-methods
|
||||
if not platform.system() == "Darwin":
|
||||
set_start_method("fork")
|
||||
|
||||
connections.close_all()
|
||||
sys.exit(main(args)) # type: ignore[no-untyped-call]
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ from collections.abc import Callable
|
||||
from http.server import BaseHTTPRequestHandler
|
||||
from http.server import HTTPServer as BaseHTTPServer
|
||||
from ipaddress import IPv6Address, ip_address
|
||||
from threading import Thread, current_thread
|
||||
from typing import TYPE_CHECKING, Any, cast
|
||||
|
||||
from django.db import DatabaseError, close_old_connections, connections
|
||||
@@ -23,13 +22,6 @@ if TYPE_CHECKING:
|
||||
from django_dramatiq_postgres.broker import PostgresBroker
|
||||
|
||||
|
||||
class HTTPServerThread(Thread):
|
||||
"""Base class for a thread which runs an HTTP Server. Mainly used for typing
|
||||
the `server` instance variable."""
|
||||
|
||||
server: HTTPServer | None
|
||||
|
||||
|
||||
class HTTPServer(BaseHTTPServer):
|
||||
def server_bind(self) -> None:
|
||||
self.socket.close()
|
||||
@@ -242,6 +234,9 @@ class MetricsMiddleware(Middleware):
|
||||
return [worker_metrics]
|
||||
|
||||
def before_worker_boot(self, broker: Broker, worker: Any) -> None:
|
||||
if Conf().test:
|
||||
return
|
||||
|
||||
from prometheus_client import Counter, Gauge, Histogram
|
||||
|
||||
self.total_messages = Counter(
|
||||
@@ -358,8 +353,6 @@ class MetricsMiddleware(Middleware):
|
||||
def run(cls, addr: str, port: int) -> None:
|
||||
try:
|
||||
server = HTTPServer((addr, port), cls.handler_class)
|
||||
thread = cast(HTTPServerThread, current_thread())
|
||||
thread.server = server
|
||||
server.serve_forever()
|
||||
except OSError:
|
||||
get_logger(__name__, type(MetricsMiddleware)).warning(
|
||||
|
||||
12
packages/docusaurus-config/package-lock.json
generated
12
packages/docusaurus-config/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@goauthentik/docusaurus-config",
|
||||
"version": "2.5.1",
|
||||
"version": "2.5.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@goauthentik/docusaurus-config",
|
||||
"version": "2.5.1",
|
||||
"version": "2.5.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"deepmerge-ts": "^7.1.5",
|
||||
@@ -34,7 +34,7 @@
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=24",
|
||||
"npm": ">=11.10.1"
|
||||
"npm": ">=11.10.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"react": ">=18",
|
||||
@@ -101,7 +101,7 @@
|
||||
},
|
||||
"../prettier-config": {
|
||||
"name": "@goauthentik/prettier-config",
|
||||
"version": "3.4.3",
|
||||
"version": "3.4.1",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -131,12 +131,12 @@
|
||||
},
|
||||
"../tsconfig": {
|
||||
"name": "@goauthentik/tsconfig",
|
||||
"version": "1.0.7",
|
||||
"version": "1.0.5",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=24",
|
||||
"npm": ">=11.10.1"
|
||||
"npm": ">=11.6.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@algolia/abtesting": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@goauthentik/docusaurus-config",
|
||||
"version": "2.5.1",
|
||||
"version": "2.5.0",
|
||||
"description": "authentik's Docusaurus config",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
@@ -68,7 +68,7 @@
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=24",
|
||||
"npm": ">=11.10.1"
|
||||
"npm": ">=11.10.0"
|
||||
},
|
||||
"devEngines": {
|
||||
"runtime": {
|
||||
@@ -78,7 +78,7 @@
|
||||
},
|
||||
"packageManager": {
|
||||
"name": "npm",
|
||||
"version": ">=11.10.1",
|
||||
"version": "11.10.1",
|
||||
"onFail": "warn"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@goauthentik/esbuild-plugin-live-reload",
|
||||
"version": "1.6.1",
|
||||
"version": "1.6.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@goauthentik/esbuild-plugin-live-reload",
|
||||
"version": "1.6.1",
|
||||
"version": "1.6.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"find-free-ports": "^3.1.1"
|
||||
@@ -31,7 +31,7 @@
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=24",
|
||||
"npm": ">=11.10.1"
|
||||
"npm": ">=11.6.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"esbuild": "^0.27.3"
|
||||
@@ -79,7 +79,7 @@
|
||||
},
|
||||
"../prettier-config": {
|
||||
"name": "@goauthentik/prettier-config",
|
||||
"version": "3.4.3",
|
||||
"version": "3.4.1",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -109,12 +109,12 @@
|
||||
},
|
||||
"../tsconfig": {
|
||||
"name": "@goauthentik/tsconfig",
|
||||
"version": "1.0.7",
|
||||
"version": "1.0.5",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=24",
|
||||
"npm": ">=11.10.1"
|
||||
"npm": ">=11.6.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/aix-ppc64": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@goauthentik/esbuild-plugin-live-reload",
|
||||
"version": "1.6.1",
|
||||
"version": "1.6.0",
|
||||
"description": "ESBuild + browser refresh. Build completes, page reloads.",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
@@ -72,7 +72,7 @@
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=24",
|
||||
"npm": ">=11.10.1"
|
||||
"npm": ">=11.6.2"
|
||||
},
|
||||
"devEngines": {
|
||||
"runtime": {
|
||||
@@ -82,7 +82,7 @@
|
||||
},
|
||||
"packageManager": {
|
||||
"name": "npm",
|
||||
"version": ">=11.10.1",
|
||||
"version": "11.10.1",
|
||||
"onFail": "warn"
|
||||
}
|
||||
},
|
||||
|
||||
6
packages/eslint-config/package-lock.json
generated
6
packages/eslint-config/package-lock.json
generated
@@ -45,7 +45,7 @@
|
||||
},
|
||||
"../prettier-config": {
|
||||
"name": "@goauthentik/prettier-config",
|
||||
"version": "3.4.3",
|
||||
"version": "3.4.1",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -75,12 +75,12 @@
|
||||
},
|
||||
"../tsconfig": {
|
||||
"name": "@goauthentik/tsconfig",
|
||||
"version": "1.0.7",
|
||||
"version": "1.0.5",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=24",
|
||||
"npm": ">=11.10.1"
|
||||
"npm": ">=11.6.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/code-frame": {
|
||||
|
||||
@@ -70,13 +70,13 @@
|
||||
"devEngines": {
|
||||
"runtime": {
|
||||
"name": "node",
|
||||
"version": ">=24",
|
||||
"onFail": "warn"
|
||||
"version": "24",
|
||||
"onFail": "ignore"
|
||||
},
|
||||
"packageManager": {
|
||||
"name": "npm",
|
||||
"version": ">=11.10.1",
|
||||
"onFail": "warn"
|
||||
"version": "11.10.1",
|
||||
"onFail": "ignore"
|
||||
}
|
||||
},
|
||||
"prettier": "@goauthentik/prettier-config",
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
* @import { IConsoleLogger } from "./shared.js"
|
||||
*/
|
||||
|
||||
/// <reference types="./shared.js" />
|
||||
/// <reference types="../types/node.js" />
|
||||
|
||||
import { fixture, prefix } from "./shared.js";
|
||||
|
||||
308
packages/logger-js/package-lock.json
generated
308
packages/logger-js/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
8
packages/prettier-config/package-lock.json
generated
8
packages/prettier-config/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@goauthentik/prettier-config",
|
||||
"version": "3.4.2",
|
||||
"version": "3.4.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@goauthentik/prettier-config",
|
||||
"version": "3.4.2",
|
||||
"version": "3.4.1",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"format-imports": "^4.0.8"
|
||||
@@ -75,12 +75,12 @@
|
||||
},
|
||||
"../tsconfig": {
|
||||
"name": "@goauthentik/tsconfig",
|
||||
"version": "1.0.7",
|
||||
"version": "1.0.5",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=24",
|
||||
"npm": ">=11.10.1"
|
||||
"npm": ">=11.6.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/helper-string-parser": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@goauthentik/prettier-config",
|
||||
"version": "3.4.3",
|
||||
"version": "3.4.1",
|
||||
"description": "authentik's Prettier config",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
@@ -64,13 +64,13 @@
|
||||
"devEngines": {
|
||||
"runtime": {
|
||||
"name": "node",
|
||||
"version": ">=24",
|
||||
"onFail": "warn"
|
||||
"version": "24",
|
||||
"onFail": "ignore"
|
||||
},
|
||||
"packageManager": {
|
||||
"name": "npm",
|
||||
"version": ">=11.10.1",
|
||||
"onFail": "warn"
|
||||
"version": "11.10.1",
|
||||
"onFail": "ignore"
|
||||
}
|
||||
},
|
||||
"prettier": "./index.js",
|
||||
|
||||
6
packages/tsconfig/package-lock.json
generated
6
packages/tsconfig/package-lock.json
generated
@@ -1,16 +1,16 @@
|
||||
{
|
||||
"name": "@goauthentik/tsconfig",
|
||||
"version": "1.0.7",
|
||||
"version": "1.0.5",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@goauthentik/tsconfig",
|
||||
"version": "1.0.7",
|
||||
"version": "1.0.5",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=24",
|
||||
"npm": ">=11.10.1"
|
||||
"npm": ">=11.6.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
{
|
||||
"name": "@goauthentik/tsconfig",
|
||||
"version": "1.0.7",
|
||||
"version": "1.0.5",
|
||||
"description": "authentik's base TypeScript configuration.",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/goauthentik/authentik.git",
|
||||
"directory": "packages/tsconfig"
|
||||
},
|
||||
"scripts": {
|
||||
"build": ""
|
||||
},
|
||||
@@ -15,24 +10,17 @@
|
||||
"type": "module",
|
||||
"engines": {
|
||||
"node": ">=24",
|
||||
"npm": ">=11.10.1"
|
||||
},
|
||||
"devEngines": {
|
||||
"runtime": {
|
||||
"name": "node",
|
||||
"version": ">=24",
|
||||
"onFail": "warn"
|
||||
},
|
||||
"packageManager": {
|
||||
"name": "npm",
|
||||
"version": ">=11.10.1",
|
||||
"onFail": "warn"
|
||||
}
|
||||
"npm": ">=11.6.2"
|
||||
},
|
||||
"keywords": [
|
||||
"tsconfig",
|
||||
"typescript"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/goauthentik/authentik.git",
|
||||
"directory": "packages/tsconfig"
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ requires-python = "==3.14.*"
|
||||
dependencies = [
|
||||
"ak-guardian==3.2.0",
|
||||
"argon2-cffi==25.1.0",
|
||||
"cachetools==7.0.2",
|
||||
"cachetools==7.0.1",
|
||||
"channels==4.3.2",
|
||||
"cryptography==46.0.5",
|
||||
"dacite==1.9.2",
|
||||
@@ -32,11 +32,11 @@ dependencies = [
|
||||
"drf-orjson-renderer==1.8.0",
|
||||
"drf-spectacular==0.28.0",
|
||||
"dumb-init==1.2.5.post1",
|
||||
"duo-client==5.6.1",
|
||||
"duo-client==5.5.0",
|
||||
"fido2==2.1.1",
|
||||
"geoip2==5.2.0",
|
||||
"geopy==2.4.1",
|
||||
"google-api-python-client==2.191.0",
|
||||
"google-api-python-client==2.190.0",
|
||||
"gssapi==1.11.1",
|
||||
"gunicorn==25.1.0",
|
||||
"jsonpatch==1.33",
|
||||
@@ -57,7 +57,7 @@ dependencies = [
|
||||
"pyyaml==6.0.3",
|
||||
"requests-oauthlib==2.0.0",
|
||||
"scim2-filter-parser==0.7.0",
|
||||
"sentry-sdk==2.54.0",
|
||||
"sentry-sdk==2.53.0",
|
||||
"service-identity==24.2.0",
|
||||
"setproctitle==1.3.7",
|
||||
"structlog==25.5.0",
|
||||
@@ -76,8 +76,8 @@ dependencies = [
|
||||
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"aws-cdk-lib==2.241.0",
|
||||
"bandit==1.9.4",
|
||||
"aws-cdk-lib==2.240.0",
|
||||
"bandit==1.9.3",
|
||||
"black==26.1.0",
|
||||
"bpython==0.26",
|
||||
"codespell==2.4.1",
|
||||
@@ -97,12 +97,12 @@ dev = [
|
||||
"pdoc==16.0.0",
|
||||
"pytest-django==4.12.0",
|
||||
"pytest-flakefinder==1.1.0",
|
||||
"pytest-github-actions-annotate-failures==0.4.0",
|
||||
"pytest-github-actions-annotate-failures==0.3.0",
|
||||
"pytest-randomly==4.0.1",
|
||||
"pytest-timeout==2.4.0",
|
||||
"pytest==9.0.2",
|
||||
"requests-mock==1.12.1",
|
||||
"ruff==0.15.4",
|
||||
"ruff==0.15.2",
|
||||
"selenium==4.41.0",
|
||||
"types-channels==4.3.0.20250822",
|
||||
"types-docker==7.1.0.20260109",
|
||||
|
||||
14
schema.yml
14
schema.yml
@@ -36805,13 +36805,10 @@ components:
|
||||
type: boolean
|
||||
policies_buffered_access_view:
|
||||
type: boolean
|
||||
flows_continuous_login:
|
||||
type: boolean
|
||||
flows_refresh_others:
|
||||
type: boolean
|
||||
required:
|
||||
- enterprise_audit_include_expanded_diff
|
||||
- flows_continuous_login
|
||||
- flows_refresh_others
|
||||
- policies_buffered_access_view
|
||||
readOnly: true
|
||||
@@ -40483,8 +40480,6 @@ components:
|
||||
default: false
|
||||
application_pre:
|
||||
type: string
|
||||
application_pre_launch:
|
||||
type: string
|
||||
flow_designation:
|
||||
$ref: '#/components/schemas/FlowDesignationEnum'
|
||||
captcha_stage:
|
||||
@@ -50466,13 +50461,10 @@ components:
|
||||
type: boolean
|
||||
policies_buffered_access_view:
|
||||
type: boolean
|
||||
flows_continuous_login:
|
||||
type: boolean
|
||||
flows_refresh_others:
|
||||
type: boolean
|
||||
required:
|
||||
- enterprise_audit_include_expanded_diff
|
||||
- flows_continuous_login
|
||||
- flows_refresh_others
|
||||
- policies_buffered_access_view
|
||||
PatchedSourceStageRequest:
|
||||
@@ -55168,13 +55160,10 @@ components:
|
||||
type: boolean
|
||||
policies_buffered_access_view:
|
||||
type: boolean
|
||||
flows_continuous_login:
|
||||
type: boolean
|
||||
flows_refresh_others:
|
||||
type: boolean
|
||||
required:
|
||||
- enterprise_audit_include_expanded_diff
|
||||
- flows_continuous_login
|
||||
- flows_refresh_others
|
||||
- policies_buffered_access_view
|
||||
required:
|
||||
@@ -55249,13 +55238,10 @@ components:
|
||||
type: boolean
|
||||
policies_buffered_access_view:
|
||||
type: boolean
|
||||
flows_continuous_login:
|
||||
type: boolean
|
||||
flows_refresh_others:
|
||||
type: boolean
|
||||
required:
|
||||
- enterprise_audit_include_expanded_diff
|
||||
- flows_continuous_login
|
||||
- flows_refresh_others
|
||||
- policies_buffered_access_view
|
||||
required:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
services:
|
||||
chromium:
|
||||
image: ghcr.io/goauthentik/selenium:145.0-ak-0.40.2
|
||||
image: ghcr.io/goauthentik/selenium:145.0-ak-0.40.0
|
||||
shm_size: 2g
|
||||
network_mode: host
|
||||
restart: always
|
||||
|
||||
114
uv.lock
generated
114
uv.lock
generated
@@ -317,7 +317,7 @@ dev = [
|
||||
requires-dist = [
|
||||
{ name = "ak-guardian", editable = "packages/ak-guardian" },
|
||||
{ name = "argon2-cffi", specifier = "==25.1.0" },
|
||||
{ name = "cachetools", specifier = "==7.0.2" },
|
||||
{ name = "cachetools", specifier = "==7.0.1" },
|
||||
{ name = "channels", specifier = "==4.3.2" },
|
||||
{ name = "cryptography", specifier = "==46.0.5" },
|
||||
{ name = "dacite", specifier = "==1.9.2" },
|
||||
@@ -342,11 +342,11 @@ requires-dist = [
|
||||
{ name = "drf-orjson-renderer", specifier = "==1.8.0" },
|
||||
{ name = "drf-spectacular", specifier = "==0.28.0" },
|
||||
{ name = "dumb-init", specifier = "==1.2.5.post1" },
|
||||
{ name = "duo-client", specifier = "==5.6.1" },
|
||||
{ name = "duo-client", specifier = "==5.5.0" },
|
||||
{ name = "fido2", specifier = "==2.1.1" },
|
||||
{ name = "geoip2", specifier = "==5.2.0" },
|
||||
{ name = "geopy", specifier = "==2.4.1" },
|
||||
{ name = "google-api-python-client", specifier = "==2.191.0" },
|
||||
{ name = "google-api-python-client", specifier = "==2.190.0" },
|
||||
{ name = "gssapi", specifier = "==1.11.1" },
|
||||
{ name = "gunicorn", specifier = "==25.1.0" },
|
||||
{ name = "jsonpatch", specifier = "==1.33" },
|
||||
@@ -367,7 +367,7 @@ requires-dist = [
|
||||
{ name = "pyyaml", specifier = "==6.0.3" },
|
||||
{ name = "requests-oauthlib", specifier = "==2.0.0" },
|
||||
{ name = "scim2-filter-parser", specifier = "==0.7.0" },
|
||||
{ name = "sentry-sdk", specifier = "==2.54.0" },
|
||||
{ name = "sentry-sdk", specifier = "==2.53.0" },
|
||||
{ name = "service-identity", specifier = "==24.2.0" },
|
||||
{ name = "setproctitle", specifier = "==1.3.7" },
|
||||
{ name = "structlog", specifier = "==25.5.0" },
|
||||
@@ -386,8 +386,8 @@ requires-dist = [
|
||||
|
||||
[package.metadata.requires-dev]
|
||||
dev = [
|
||||
{ name = "aws-cdk-lib", specifier = "==2.241.0" },
|
||||
{ name = "bandit", specifier = "==1.9.4" },
|
||||
{ name = "aws-cdk-lib", specifier = "==2.240.0" },
|
||||
{ name = "bandit", specifier = "==1.9.3" },
|
||||
{ name = "black", specifier = "==26.1.0" },
|
||||
{ name = "bpython", specifier = "==0.26" },
|
||||
{ name = "codespell", specifier = "==2.4.1" },
|
||||
@@ -408,11 +408,11 @@ dev = [
|
||||
{ name = "pytest", specifier = "==9.0.2" },
|
||||
{ name = "pytest-django", specifier = "==4.12.0" },
|
||||
{ name = "pytest-flakefinder", specifier = "==1.1.0" },
|
||||
{ name = "pytest-github-actions-annotate-failures", specifier = "==0.4.0" },
|
||||
{ name = "pytest-github-actions-annotate-failures", specifier = "==0.3.0" },
|
||||
{ name = "pytest-randomly", specifier = "==4.0.1" },
|
||||
{ name = "pytest-timeout", specifier = "==2.4.0" },
|
||||
{ name = "requests-mock", specifier = "==1.12.1" },
|
||||
{ name = "ruff", specifier = "==0.15.4" },
|
||||
{ name = "ruff", specifier = "==0.15.2" },
|
||||
{ name = "selenium", specifier = "==4.41.0" },
|
||||
{ name = "types-channels", specifier = "==4.3.0.20250822" },
|
||||
{ name = "types-docker", specifier = "==7.1.0.20260109" },
|
||||
@@ -469,35 +469,35 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "aws-cdk-asset-node-proxy-agent-v6"
|
||||
version = "2.1.1"
|
||||
version = "2.1.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "jsii" },
|
||||
{ name = "publication" },
|
||||
{ name = "typeguard" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d3/4b/0ccc9d12f66becaaf489e55d152f50376817cd808cf4068c0c5385d21c9d/aws_cdk_asset_node_proxy_agent_v6-2.1.1.tar.gz", hash = "sha256:37211fea7e308144d20666b939d8763d733000d8d837ba968dacaf4983daf574", size = 1542241, upload-time = "2026-02-26T16:38:43.95Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d5/ab/09ac3ecc0067988d02398328e088d66cbe8555c991563c8ddfa1db5296ae/aws_cdk_asset_node_proxy_agent_v6-2.1.0.tar.gz", hash = "sha256:1f292c0631f86708ba4ee328b3a2b229f7e46ea1c79fbde567ee9eb119c2b0e2", size = 1540231, upload-time = "2024-09-03T09:36:51.634Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/dc/b1/775c53a017d30d6bb0c9fa19182df11672569b6c8c7c1a1b325639abff63/aws_cdk_asset_node_proxy_agent_v6-2.1.1-py3-none-any.whl", hash = "sha256:a24fab484423fcb7c729fb376817a4dbb6a09c176243fd1dcbdaa05ddf62f037", size = 1540751, upload-time = "2026-02-26T16:38:42.464Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8d/86/1817a6da223aa80aeb94a504f07f930170284694b18f6053729e9930cc6a/aws_cdk.asset_node_proxy_agent_v6-2.1.0-py3-none-any.whl", hash = "sha256:24a388b69a44d03bae6dbf864c4e25ba650d4b61c008b4568b94ffbb9a69e40e", size = 1538724, upload-time = "2024-09-03T09:36:49.8Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-cdk-cloud-assembly-schema"
|
||||
version = "52.2.0"
|
||||
version = "50.4.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "jsii" },
|
||||
{ name = "publication" },
|
||||
{ name = "typeguard" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/81/b3/baf6ba1d34bc4fc8affb7849613978df80b6e97b5d48a885dbc84adf1a97/aws_cdk_cloud_assembly_schema-52.2.0.tar.gz", hash = "sha256:737309e2c7c7e4b46bd669cb9fe8799a36424c9a174523b54833cf1cd12b5e3f", size = 210466, upload-time = "2026-02-23T17:08:48.404Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f8/4c/a9ac7498f2b76d7697e60367b9a8c690fc54bb3bf4e591e6fe06977c847b/aws_cdk_cloud_assembly_schema-50.4.0.tar.gz", hash = "sha256:c9aa7a108ca63f3880f26594166d3e8c16b504a50424011baf785231dc009f30", size = 208573, upload-time = "2026-02-05T16:37:54.61Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/0e/b3/2305e64194634b3c1f0bff38462dd59e617dc1460ac8df1616a5b193d2fe/aws_cdk_cloud_assembly_schema-52.2.0-py3-none-any.whl", hash = "sha256:87b918589f7d627f45e330726f592ec0b39056e1403558f3a1ba8a2134dacd6f", size = 210184, upload-time = "2026-02-23T17:08:46.923Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/50/37/946c9646606cf9dffa5d15a860557c9d507655c97fb2525bb8bd0c215179/aws_cdk_cloud_assembly_schema-50.4.0-py3-none-any.whl", hash = "sha256:3f98f06d99f68f5bae5c72f0f392494dd3ef4211197afd0e75cfe1d5fc487d1c", size = 208231, upload-time = "2026-02-05T16:37:52.037Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "aws-cdk-lib"
|
||||
version = "2.241.0"
|
||||
version = "2.240.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "aws-cdk-asset-awscli-v1" },
|
||||
@@ -508,9 +508,9 @@ dependencies = [
|
||||
{ name = "publication" },
|
||||
{ name = "typeguard" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/55/8a/58fa1cc687847b5f834af45c2466a34cd68fc22489732a6f899560769c4a/aws_cdk_lib-2.241.0.tar.gz", hash = "sha256:4ea84d6caf43c3a42670a76e8a023e513ce335499e7c45f22028b2186926e7ab", size = 48209539, upload-time = "2026-03-02T14:39:12.156Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/97/c3/56cb53689bdaa5e4359cc76c5b3356be21d974486324a0091a32c59c3682/aws_cdk_lib-2.240.0.tar.gz", hash = "sha256:096fcb3efd41ba30cdcee0c97a54537f6cb3ab9e53a1f0ed68981a8b86860784", size = 47956951, upload-time = "2026-02-23T21:31:34.799Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/cb/20/9a61e0558ff9483d0146e4f563e09d59c936761d1ac77ff25ec6a0e67d02/aws_cdk_lib-2.241.0-py3-none-any.whl", hash = "sha256:5c62f97c13a2a9e65b1d2b376f267595b7b2cc3947f6bcf710e52e39a381b5e3", size = 48855242, upload-time = "2026-03-02T14:38:30.307Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2e/7c/0fdc9ffd4a516a62f0313ecb0abb0f2b1e58f3e5c409254ecefea571749f/aws_cdk_lib-2.240.0-py3-none-any.whl", hash = "sha256:6ba3343885e0ad10cb38981ea4f7e6c721253519d2601af9d6784bb5787d1292", size = 48608831, upload-time = "2026-02-23T21:30:54.727Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -544,7 +544,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "bandit"
|
||||
version = "1.9.4"
|
||||
version = "1.9.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
||||
@@ -552,9 +552,9 @@ dependencies = [
|
||||
{ name = "rich" },
|
||||
{ name = "stevedore" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/aa/c3/0cb80dfe0f3076e5da7e4c5ad8e57bac6ac357ff4a6406205501cade4965/bandit-1.9.4.tar.gz", hash = "sha256:b589e5de2afe70bd4d53fa0c1da6199f4085af666fde00e8a034f152a52cd628", size = 4242677, upload-time = "2026-02-25T06:44:15.503Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/89/76/a7f3e639b78601118aaa4a394db2c66ae2597fbd8c39644c32874ed11e0c/bandit-1.9.3.tar.gz", hash = "sha256:ade4b9b7786f89ef6fc7344a52b34558caec5da74cb90373aed01de88472f774", size = 4242154, upload-time = "2026-01-19T04:05:22.802Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/05/a4/a26d5b25671d27e03afb5401a0be5899d94ff8fab6a698b1ac5be3ec29ef/bandit-1.9.4-py3-none-any.whl", hash = "sha256:f89ffa663767f5a0585ea075f01020207e966a9c0f2b9ef56a57c7963a3f6f8e", size = 134741, upload-time = "2026-02-25T06:44:13.694Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e0/0b/8bdc52111c83e2dc2f97403dc87c0830b8989d9ae45732b34b686326fb2c/bandit-1.9.3-py3-none-any.whl", hash = "sha256:4745917c88d2246def79748bde5e08b9d5e9b92f877863d43fab70cd8814ce6a", size = 134451, upload-time = "2026-01-19T04:05:20.938Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -690,11 +690,11 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "cachetools"
|
||||
version = "7.0.2"
|
||||
version = "7.0.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/6c/c7/342b33cc6877eebc6c9bb45cb9f78e170e575839699f6f3cc96050176431/cachetools-7.0.2.tar.gz", hash = "sha256:7e7f09a4ca8b791d8bb4864afc71e9c17e607a28e6839ca1a644253c97dbeae0", size = 36983, upload-time = "2026-03-02T19:45:16.926Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d4/07/56595285564e90777d758ebd383d6b0b971b87729bbe2184a849932a3736/cachetools-7.0.1.tar.gz", hash = "sha256:e31e579d2c5b6e2944177a0397150d312888ddf4e16e12f1016068f0c03b8341", size = 36126, upload-time = "2026-02-10T22:24:05.03Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/ef/04/4b6968e77c110f12da96fdbfcb39c6557c2e5e81bd7afcf8ed893d5bc588/cachetools-7.0.2-py3-none-any.whl", hash = "sha256:938dcad184827c5e94928c4fd5526e2b46692b7fb1ae94472da9131d0299343c", size = 13793, upload-time = "2026-03-02T19:45:15.495Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ed/9e/5faefbf9db1db466d633735faceda1f94aa99ce506ac450d232536266b32/cachetools-7.0.1-py3-none-any.whl", hash = "sha256:8f086515c254d5664ae2146d14fc7f65c9a4bce75152eb247e5a9c5e6d7b2ecf", size = 13484, upload-time = "2026-02-10T22:24:03.741Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1451,14 +1451,14 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "duo-client"
|
||||
version = "5.6.1"
|
||||
version = "5.5.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "setuptools" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/c8/20/48842c3cc8b2c60129e1e52f0ab5c72ac0a30a3a345ea6d6e9aa8c94c093/duo_client-5.6.1.tar.gz", hash = "sha256:5b9bfba3bd995178cebf51db605190bdc84fec8e4b6935210e7abde4ae97cef5", size = 95447, upload-time = "2026-02-26T16:38:53.369Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/8b/c8/4e8416eec72bc77ad947b736f760ceedf818df0c48153816b1bfb0fab854/duo_client-5.5.0.tar.gz", hash = "sha256:303109e047fe7525ba4fc4a294c1f3deb4125066e89c10d33f7430378867b1d6", size = 93475, upload-time = "2025-03-24T15:35:19.175Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/9d/db/798547ea1a4af7be4454d621f8c23dbbad153dc7d9c57285fbcde03abd42/duo_client-5.6.1-py3-none-any.whl", hash = "sha256:ec7fa30548b7b8e3b7983948d08d167ada4df7a1b54b4723e7a02ee4635bb513", size = 52001, upload-time = "2026-02-26T16:38:51.85Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7a/4b/dd927d3111e1f4c78c1f5944d3b64b4fb6ab655487c23100a3feff5cdaa4/duo_client-5.5.0-py3-none-any.whl", hash = "sha256:4fbf1e97a2b25ef64e9f88171ab817162cf45bafc1c63026af4883baf8892a12", size = 51313, upload-time = "2025-03-24T15:35:18.243Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1623,7 +1623,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "google-api-python-client"
|
||||
version = "2.191.0"
|
||||
version = "2.190.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "google-api-core" },
|
||||
@@ -1632,9 +1632,9 @@ dependencies = [
|
||||
{ name = "httplib2" },
|
||||
{ name = "uritemplate" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/60/58/7d0843b7419a5ac51a27965e7233ef7c26ad693b490a74ab26548d0fd231/google_api_python_client-2.191.0.tar.gz", hash = "sha256:858c22fd46f51a65cee365a78aec2054e6d47b50434bee4ba62e91ac0944aea1", size = 14195310, upload-time = "2026-03-02T16:58:59.965Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/e4/8d/4ab3e3516b93bb50ed7814738ea61d49cba3f72f4e331dc9518ae2731e92/google_api_python_client-2.190.0.tar.gz", hash = "sha256:5357f34552e3724d80d2604c8fa146766e0a9d6bb0afada886fafed9feafeef6", size = 14111143, upload-time = "2026-02-12T00:38:03.37Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/6e/a4/da3a66c90f94b9eb433f0844f1bf79b5789bfa0859e55c0cd02c1139fed8/google_api_python_client-2.191.0-py3-none-any.whl", hash = "sha256:0768dde3202121abb3e897c4ee5150e58a25f32ee843780f6bee636dccc7ef23", size = 14769138, upload-time = "2026-03-02T16:58:57.665Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/07/ad/223d5f4b0b987669ffeb3eadd7e9f85ece633aa7fd3246f1e2f6238e1e05/google_api_python_client-2.190.0-py3-none-any.whl", hash = "sha256:d9b5266758f96c39b8c21d9bbfeb4e58c14dbfba3c931f7c5a8d7fdcd292dd57", size = 14682070, upload-time = "2026-02-12T00:38:00.974Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1945,7 +1945,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "jsii"
|
||||
version = "1.127.0"
|
||||
version = "1.126.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "attrs" },
|
||||
@@ -1956,9 +1956,9 @@ dependencies = [
|
||||
{ name = "typeguard" },
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/81/e8/a163295e70ecc652bfd7960c83f9a61ee4283f2ef73d6df23ac57b430f6c/jsii-1.127.0.tar.gz", hash = "sha256:631a13d73265eaa22c0c0804e77fe59c8fcc3af3a94de9923af65380b6ad267a", size = 461782, upload-time = "2026-02-25T16:54:04.368Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/76/22/a3c8a8bfc6bd25b761553380d91d9b5a772a3796e78b7f6d4eecc003bced/jsii-1.126.0.tar.gz", hash = "sha256:5e4739843aab3af25472490a05a271cf7d53f01a6d46167ab0f1f2cff3a8df95", size = 626608, upload-time = "2026-01-26T10:43:16.152Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b6/91/3b58a04d06cb6abbb3806ca5fcf4b8933a85e013d24d983d3535d9fb6566/jsii-1.127.0-py3-none-any.whl", hash = "sha256:92a11f39e461f5168e2467efd53351cc32b118314b95cc6323c2d044eb299eaf", size = 436980, upload-time = "2026-02-25T16:54:02.824Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a2/7d/f058cfdc20e1536b09d165303b1996d24504fbe105b0aba62c865e60bdc9/jsii-1.126.0-py3-none-any.whl", hash = "sha256:0bb3d5423fd62a499f9ce83e98668b48424ac6ef39472bff90cdf4650aa41b41", size = 602728, upload-time = "2026-01-26T10:43:14.68Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3034,14 +3034,14 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "pytest-github-actions-annotate-failures"
|
||||
version = "0.4.0"
|
||||
version = "0.3.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "pytest" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/c2/e1/8f2c242e6d75a26a8e5ddcc23f652a411e4aac3eedc4b923808ac0582685/pytest_github_actions_annotate_failures-0.4.0.tar.gz", hash = "sha256:77d6baa29c8c61c2dacc494fa76eb95a185f0ee61666714ac43fb12ea672d217", size = 10857, upload-time = "2026-03-02T18:57:40.919Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/39/d4/c54ee6a871eee4a7468e3a8c0dead28e634c0bc2110c694309dcb7563a66/pytest_github_actions_annotate_failures-0.3.0.tar.gz", hash = "sha256:d4c3177c98046c3900a7f8ddebb22ea54b9f6822201b5d3ab8fcdea51e010db7", size = 11248, upload-time = "2025-01-17T22:39:32.722Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/0f/bd/11809f5c78d5d8da2d0e004845d2382768bc20798b3e0988bca61efd349f/pytest_github_actions_annotate_failures-0.4.0-py3-none-any.whl", hash = "sha256:285fed86e16b0b7a8eac6acdcde31913798fb739b15ef5b86895b4f5e32bf237", size = 6039, upload-time = "2026-03-02T18:57:39.991Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6d/73/7b0b15cb8605ee967b34aa1d949737ab664f94e6b0f1534e8339d9e64ab2/pytest_github_actions_annotate_failures-0.3.0-py3-none-any.whl", hash = "sha256:41ea558ba10c332c0bfc053daeee0c85187507b2034e990f21e4f7e5fef044cf", size = 6030, upload-time = "2025-01-17T22:39:31.701Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3276,27 +3276,27 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.15.4"
|
||||
version = "0.15.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/da/31/d6e536cdebb6568ae75a7f00e4b4819ae0ad2640c3604c305a0428680b0c/ruff-0.15.4.tar.gz", hash = "sha256:3412195319e42d634470cc97aa9803d07e9d5c9223b99bcb1518f0c725f26ae1", size = 4569550, upload-time = "2026-02-26T20:04:14.959Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/06/04/eab13a954e763b0606f460443fcbf6bb5a0faf06890ea3754ff16523dce5/ruff-0.15.2.tar.gz", hash = "sha256:14b965afee0969e68bb871eba625343b8673375f457af4abe98553e8bbb98342", size = 4558148, upload-time = "2026-02-19T22:32:20.271Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/f2/82/c11a03cfec3a4d26a0ea1e571f0f44be5993b923f905eeddfc397c13d360/ruff-0.15.4-py3-none-linux_armv6l.whl", hash = "sha256:a1810931c41606c686bae8b5b9a8072adac2f611bb433c0ba476acba17a332e0", size = 10453333, upload-time = "2026-02-26T20:04:20.093Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ce/5d/6a1f271f6e31dffb31855996493641edc3eef8077b883eaf007a2f1c2976/ruff-0.15.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:5a1632c66672b8b4d3e1d1782859e98d6e0b4e70829530666644286600a33992", size = 10853356, upload-time = "2026-02-26T20:04:05.808Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b1/d8/0fab9f8842b83b1a9c2bf81b85063f65e93fb512e60effa95b0be49bfc54/ruff-0.15.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:a4386ba2cd6c0f4ff75252845906acc7c7c8e1ac567b7bc3d373686ac8c222ba", size = 10187434, upload-time = "2026-02-26T20:03:54.656Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/85/cc/cc220fd9394eff5db8d94dec199eec56dd6c9f3651d8869d024867a91030/ruff-0.15.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2496488bdfd3732747558b6f95ae427ff066d1fcd054daf75f5a50674411e75", size = 10535456, upload-time = "2026-02-26T20:03:52.738Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fa/0f/bced38fa5cf24373ec767713c8e4cadc90247f3863605fb030e597878661/ruff-0.15.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3f1c4893841ff2d54cbda1b2860fa3260173df5ddd7b95d370186f8a5e66a4ac", size = 10287772, upload-time = "2026-02-26T20:04:08.138Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2b/90/58a1802d84fed15f8f281925b21ab3cecd813bde52a8ca033a4de8ab0e7a/ruff-0.15.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:820b8766bd65503b6c30aaa6331e8ef3a6e564f7999c844e9a547c40179e440a", size = 11049051, upload-time = "2026-02-26T20:04:03.53Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/ac/b7ad36703c35f3866584564dc15f12f91cb1a26a897dc2fd13d7cb3ae1af/ruff-0.15.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c9fb74bab47139c1751f900f857fa503987253c3ef89129b24ed375e72873e85", size = 11890494, upload-time = "2026-02-26T20:04:10.497Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/93/3d/3eb2f47a39a8b0da99faf9c54d3eb24720add1e886a5309d4d1be73a6380/ruff-0.15.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f80c98765949c518142b3a50a5db89343aa90f2c2bf7799de9986498ae6176db", size = 11326221, upload-time = "2026-02-26T20:04:12.84Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ff/90/bf134f4c1e5243e62690e09d63c55df948a74084c8ac3e48a88468314da6/ruff-0.15.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:451a2e224151729b3b6c9ffb36aed9091b2996fe4bdbd11f47e27d8f2e8888ec", size = 11168459, upload-time = "2026-02-26T20:04:00.969Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b5/e5/a64d27688789b06b5d55162aafc32059bb8c989c61a5139a36e1368285eb/ruff-0.15.4-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:a8f157f2e583c513c4f5f896163a93198297371f34c04220daf40d133fdd4f7f", size = 11104366, upload-time = "2026-02-26T20:03:48.099Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/f6/32d1dcb66a2559763fc3027bdd65836cad9eb09d90f2ed6a63d8e9252b02/ruff-0.15.4-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:917cc68503357021f541e69b35361c99387cdbbf99bd0ea4aa6f28ca99ff5338", size = 10510887, upload-time = "2026-02-26T20:03:45.771Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ff/92/22d1ced50971c5b6433aed166fcef8c9343f567a94cf2b9d9089f6aa80fe/ruff-0.15.4-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:e9737c8161da79fd7cfec19f1e35620375bd8b2a50c3e77fa3d2c16f574105cc", size = 10285939, upload-time = "2026-02-26T20:04:22.42Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e6/f4/7c20aec3143837641a02509a4668fb146a642fd1211846634edc17eb5563/ruff-0.15.4-py3-none-musllinux_1_2_i686.whl", hash = "sha256:291258c917539e18f6ba40482fe31d6f5ac023994ee11d7bdafd716f2aab8a68", size = 10765471, upload-time = "2026-02-26T20:03:58.924Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d0/09/6d2f7586f09a16120aebdff8f64d962d7c4348313c77ebb29c566cefc357/ruff-0.15.4-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:3f83c45911da6f2cd5936c436cf86b9f09f09165f033a99dcf7477e34041cbc3", size = 11263382, upload-time = "2026-02-26T20:04:24.424Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1b/fa/2ef715a1cd329ef47c1a050e10dee91a9054b7ce2fcfdd6a06d139afb7ec/ruff-0.15.4-py3-none-win32.whl", hash = "sha256:65594a2d557d4ee9f02834fcdf0a28daa8b3b9f6cb2cb93846025a36db47ef22", size = 10506664, upload-time = "2026-02-26T20:03:50.56Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d0/a8/c688ef7e29983976820d18710f955751d9f4d4eb69df658af3d006e2ba3e/ruff-0.15.4-py3-none-win_amd64.whl", hash = "sha256:04196ad44f0df220c2ece5b0e959c2f37c777375ec744397d21d15b50a75264f", size = 11651048, upload-time = "2026-02-26T20:04:17.191Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3e/0a/9e1be9035b37448ce2e68c978f0591da94389ade5a5abafa4cf99985d1b2/ruff-0.15.4-py3-none-win_arm64.whl", hash = "sha256:60d5177e8cfc70e51b9c5fad936c634872a74209f934c1e79107d11787ad5453", size = 10966776, upload-time = "2026-02-26T20:03:56.908Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2f/70/3a4dc6d09b13cb3e695f28307e5d889b2e1a66b7af9c5e257e796695b0e6/ruff-0.15.2-py3-none-linux_armv6l.whl", hash = "sha256:120691a6fdae2f16d65435648160f5b81a9625288f75544dc40637436b5d3c0d", size = 10430565, upload-time = "2026-02-19T22:32:41.824Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/71/0b/bb8457b56185ece1305c666dc895832946d24055be90692381c31d57466d/ruff-0.15.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:a89056d831256099658b6bba4037ac6dd06f49d194199215befe2bb10457ea5e", size = 10820354, upload-time = "2026-02-19T22:32:07.366Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2d/c1/e0532d7f9c9e0b14c46f61b14afd563298b8b83f337b6789ddd987e46121/ruff-0.15.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e36dee3a64be0ebd23c86ffa3aa3fd3ac9a712ff295e192243f814a830b6bd87", size = 10170767, upload-time = "2026-02-19T22:32:13.188Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/47/e8/da1aa341d3af017a21c7a62fb5ec31d4e7ad0a93ab80e3a508316efbcb23/ruff-0.15.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9fb47b6d9764677f8c0a193c0943ce9a05d6763523f132325af8a858eadc2b9", size = 10529591, upload-time = "2026-02-19T22:32:02.547Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/93/74/184fbf38e9f3510231fbc5e437e808f0b48c42d1df9434b208821efcd8d6/ruff-0.15.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f376990f9d0d6442ea9014b19621d8f2aaf2b8e39fdbfc79220b7f0c596c9b80", size = 10260771, upload-time = "2026-02-19T22:32:36.938Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/05/ac/605c20b8e059a0bc4b42360414baa4892ff278cec1c91fff4be0dceedefd/ruff-0.15.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2dcc987551952d73cbf5c88d9fdee815618d497e4df86cd4c4824cc59d5dd75f", size = 11045791, upload-time = "2026-02-19T22:32:31.642Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fd/52/db6e419908f45a894924d410ac77d64bdd98ff86901d833364251bd08e22/ruff-0.15.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:42a47fd785cbe8c01b9ff45031af875d101b040ad8f4de7bbb716487c74c9a77", size = 11879271, upload-time = "2026-02-19T22:32:29.305Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3e/d8/7992b18f2008bdc9231d0f10b16df7dda964dbf639e2b8b4c1b4e91b83af/ruff-0.15.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cbe9f49354866e575b4c6943856989f966421870e85cd2ac94dccb0a9dcb2fea", size = 11303707, upload-time = "2026-02-19T22:32:22.492Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d7/02/849b46184bcfdd4b64cde61752cc9a146c54759ed036edd11857e9b8443b/ruff-0.15.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b7a672c82b5f9887576087d97be5ce439f04bbaf548ee987b92d3a7dede41d3a", size = 11149151, upload-time = "2026-02-19T22:32:44.234Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/70/04/f5284e388bab60d1d3b99614a5a9aeb03e0f333847e2429bebd2aaa1feec/ruff-0.15.2-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:72ecc64f46f7019e2bcc3cdc05d4a7da958b629a5ab7033195e11a438403d956", size = 11091132, upload-time = "2026-02-19T22:32:24.691Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fa/ae/88d844a21110e14d92cf73d57363fab59b727ebeabe78009b9ccb23500af/ruff-0.15.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:8dcf243b15b561c655c1ef2f2b0050e5d50db37fe90115507f6ff37d865dc8b4", size = 10504717, upload-time = "2026-02-19T22:32:26.75Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/64/27/867076a6ada7f2b9c8292884ab44d08fd2ba71bd2b5364d4136f3cd537e1/ruff-0.15.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:dab6941c862c05739774677c6273166d2510d254dac0695c0e3f5efa1b5585de", size = 10263122, upload-time = "2026-02-19T22:32:10.036Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e7/ef/faf9321d550f8ebf0c6373696e70d1758e20ccdc3951ad7af00c0956be7c/ruff-0.15.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:1b9164f57fc36058e9a6806eb92af185b0697c9fe4c7c52caa431c6554521e5c", size = 10735295, upload-time = "2026-02-19T22:32:39.227Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2f/55/e8089fec62e050ba84d71b70e7834b97709ca9b7aba10c1a0b196e493f97/ruff-0.15.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:80d24fcae24d42659db7e335b9e1531697a7102c19185b8dc4a028b952865fd8", size = 11241641, upload-time = "2026-02-19T22:32:34.617Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/23/01/1c30526460f4d23222d0fabd5888868262fd0e2b71a00570ca26483cd993/ruff-0.15.2-py3-none-win32.whl", hash = "sha256:fd5ff9e5f519a7e1bd99cbe8daa324010a74f5e2ebc97c6242c08f26f3714f6f", size = 10507885, upload-time = "2026-02-19T22:32:15.635Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5c/10/3d18e3bbdf8fc50bbb4ac3cc45970aa5a9753c5cb51bf9ed9a3cd8b79fa3/ruff-0.15.2-py3-none-win_amd64.whl", hash = "sha256:d20014e3dfa400f3ff84830dfb5755ece2de45ab62ecea4af6b7262d0fb4f7c5", size = 11623725, upload-time = "2026-02-19T22:32:04.947Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6d/78/097c0798b1dab9f8affe73da9642bb4500e098cb27fd8dc9724816ac747b/ruff-0.15.2-py3-none-win_arm64.whl", hash = "sha256:cabddc5822acdc8f7b5527b36ceac55cc51eec7b1946e60181de8fe83ca8876e", size = 10941649, upload-time = "2026-02-19T22:32:18.108Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3342,15 +3342,15 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "sentry-sdk"
|
||||
version = "2.54.0"
|
||||
version = "2.53.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "certifi" },
|
||||
{ name = "urllib3" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/c8/e9/2e3a46c304e7fa21eaa70612f60354e32699c7102eb961f67448e222ad7c/sentry_sdk-2.54.0.tar.gz", hash = "sha256:2620c2575128d009b11b20f7feb81e4e4e8ae08ec1d36cbc845705060b45cc1b", size = 413813, upload-time = "2026-03-02T15:12:41.355Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d3/06/66c8b705179bc54087845f28fd1b72f83751b6e9a195628e2e9af9926505/sentry_sdk-2.53.0.tar.gz", hash = "sha256:6520ef2c4acd823f28efc55e43eb6ce2e6d9f954a95a3aa96b6fd14871e92b77", size = 412369, upload-time = "2026-02-16T11:11:14.743Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/53/39/be412cc86bc6247b8f69e9383d7950711bd86f8d0a4a4b0fe8fad685bc21/sentry_sdk-2.54.0-py2.py3-none-any.whl", hash = "sha256:fd74e0e281dcda63afff095d23ebcd6e97006102cdc8e78a29f19ecdf796a0de", size = 439198, upload-time = "2026-03-02T15:12:39.546Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/47/d4/2fdf854bc3b9c7f55219678f812600a20a138af2dd847d99004994eada8f/sentry_sdk-2.53.0-py2.py3-none-any.whl", hash = "sha256:46e1ed8d84355ae54406c924f6b290c3d61f4048625989a723fd622aab838899", size = 437908, upload-time = "2026-02-16T11:11:13.227Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
318
web/package-lock.json
generated
318
web/package-lock.json
generated
@@ -14,21 +14,21 @@
|
||||
"dependencies": {
|
||||
"@codemirror/lang-css": "^6.3.1",
|
||||
"@codemirror/lang-html": "^6.4.11",
|
||||
"@codemirror/lang-javascript": "^6.2.5",
|
||||
"@codemirror/lang-javascript": "^6.2.4",
|
||||
"@codemirror/lang-python": "^6.2.1",
|
||||
"@codemirror/lang-xml": "^6.1.0",
|
||||
"@codemirror/legacy-modes": "^6.5.2",
|
||||
"@codemirror/theme-one-dark": "^6.1.3",
|
||||
"@eslint/js": "^9.39.3",
|
||||
"@floating-ui/dom": "^1.7.6",
|
||||
"@floating-ui/dom": "^1.7.5",
|
||||
"@formatjs/intl-listformat": "^8.2.1",
|
||||
"@fortawesome/fontawesome-free": "^7.2.0",
|
||||
"@goauthentik/api": "^2026.2.0-rc1-1770744803",
|
||||
"@goauthentik/core": "^1.0.0",
|
||||
"@goauthentik/esbuild-plugin-live-reload": "^1.6.1",
|
||||
"@goauthentik/esbuild-plugin-live-reload": "^1.6.0",
|
||||
"@goauthentik/eslint-config": "^1.3.0",
|
||||
"@goauthentik/prettier-config": "^3.4.3",
|
||||
"@goauthentik/tsconfig": "^1.0.7",
|
||||
"@goauthentik/prettier-config": "^3.4.1",
|
||||
"@goauthentik/tsconfig": "^1.0.5",
|
||||
"@hcaptcha/types": "^1.1.0",
|
||||
"@lit/context": "^1.1.6",
|
||||
"@lit/localize": "^0.12.2",
|
||||
@@ -43,15 +43,15 @@
|
||||
"@patternfly/elements": "^4.3.1",
|
||||
"@patternfly/patternfly": "^4.224.2",
|
||||
"@playwright/test": "^1.58.2",
|
||||
"@sentry/browser": "^10.42.0",
|
||||
"@storybook/addon-docs": "^10.2.13",
|
||||
"@storybook/addon-links": "^10.2.13",
|
||||
"@storybook/web-components": "^10.2.13",
|
||||
"@storybook/web-components-vite": "^10.2.13",
|
||||
"@sentry/browser": "^10.39.0",
|
||||
"@storybook/addon-docs": "^10.2.10",
|
||||
"@storybook/addon-links": "^10.2.10",
|
||||
"@storybook/web-components": "^10.2.10",
|
||||
"@storybook/web-components-vite": "^10.2.10",
|
||||
"@types/codemirror": "^5.60.17",
|
||||
"@types/grecaptcha": "^3.0.9",
|
||||
"@types/guacamole-common-js": "^1.5.5",
|
||||
"@types/node": "^25.3.3",
|
||||
"@types/node": "^25.3.0",
|
||||
"@types/react": "^19.2.14",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@typescript-eslint/eslint-plugin": "^8.56.1",
|
||||
@@ -65,7 +65,7 @@
|
||||
"chartjs-adapter-date-fns": "^3.0.0",
|
||||
"codemirror": "^6.0.2",
|
||||
"core-js": "^3.48.0",
|
||||
"country-flag-icons": "^1.6.15",
|
||||
"country-flag-icons": "^1.6.13",
|
||||
"date-fns": "^4.1.0",
|
||||
"deepmerge-ts": "^7.1.5",
|
||||
"dompurify": "^3.3.1",
|
||||
@@ -74,7 +74,7 @@
|
||||
"eslint-plugin-lit": "^2.2.1",
|
||||
"eslint-plugin-wc": "^3.1.0",
|
||||
"fuse.js": "^7.1.0",
|
||||
"globals": "^17.4.0",
|
||||
"globals": "^17.3.0",
|
||||
"guacamole-common-js": "^1.5.0",
|
||||
"hastscript": "^9.0.1",
|
||||
"knip": "^5.85.0",
|
||||
@@ -534,9 +534,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/lang-javascript": {
|
||||
"version": "6.2.5",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.2.5.tgz",
|
||||
"integrity": "sha512-zD4e5mS+50htS7F+TYjBPsiIFGanfVqg4HyUz6WNFikgOPf2BgKlx+TQedI1w6n/IqRBVBbBWmGFdLB/7uxO4A==",
|
||||
"version": "6.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.2.4.tgz",
|
||||
"integrity": "sha512-0WVmhp1QOqZ4Rt6GlVGwKJN3KW7Xh4H2q8ZZNGZaP6lRdxXJzmjm4FqvmOojVj6khWJHIb9sp7U/72W7xQgqAA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.0.0",
|
||||
@@ -1346,28 +1346,28 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@floating-ui/core": {
|
||||
"version": "1.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz",
|
||||
"integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==",
|
||||
"version": "1.7.4",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.4.tgz",
|
||||
"integrity": "sha512-C3HlIdsBxszvm5McXlB8PeOEWfBhcGBTZGkGlWc2U0KFY5IwG5OQEuQ8rq52DZmcHDlPLd+YFBK+cZcytwIFWg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@floating-ui/utils": "^0.2.11"
|
||||
"@floating-ui/utils": "^0.2.10"
|
||||
}
|
||||
},
|
||||
"node_modules/@floating-ui/dom": {
|
||||
"version": "1.7.6",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz",
|
||||
"integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==",
|
||||
"version": "1.7.5",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.5.tgz",
|
||||
"integrity": "sha512-N0bD2kIPInNHUHehXhMke1rBGs1dwqvC9O9KYMyyjK7iXt7GAhnro7UlcuYcGdS/yYOlq0MAVgrow8IbWJwyqg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@floating-ui/core": "^1.7.5",
|
||||
"@floating-ui/utils": "^0.2.11"
|
||||
"@floating-ui/core": "^1.7.4",
|
||||
"@floating-ui/utils": "^0.2.10"
|
||||
}
|
||||
},
|
||||
"node_modules/@floating-ui/utils": {
|
||||
"version": "0.2.11",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz",
|
||||
"integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==",
|
||||
"version": "0.2.10",
|
||||
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz",
|
||||
"integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@formatjs/ecma402-abstract": {
|
||||
@@ -1431,16 +1431,16 @@
|
||||
"link": true
|
||||
},
|
||||
"node_modules/@goauthentik/esbuild-plugin-live-reload": {
|
||||
"version": "1.6.1",
|
||||
"resolved": "https://registry.npmjs.org/@goauthentik/esbuild-plugin-live-reload/-/esbuild-plugin-live-reload-1.6.1.tgz",
|
||||
"integrity": "sha512-JTml8rIVMEkepbQFLlvEvb0ms+C0OlOJLLiIvAYkPrXQZ88xa9rKlj9pQj+Y8cf0QRARNZ0YEBTxjtoxZ7lLqQ==",
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@goauthentik/esbuild-plugin-live-reload/-/esbuild-plugin-live-reload-1.6.0.tgz",
|
||||
"integrity": "sha512-FEMlKXFXHFBULdyAZQt07C3mNy/z1+SVPnRiuPjjgf5vqwT+nQhvEEY5cO9vMmQSOyLSn7wfweDCPcYQ1wXfPQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"find-free-ports": "^3.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=24",
|
||||
"npm": ">=11.10.1"
|
||||
"npm": ">=11.6.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"esbuild": "^0.27.3"
|
||||
@@ -1479,9 +1479,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@goauthentik/prettier-config": {
|
||||
"version": "3.4.3",
|
||||
"resolved": "https://registry.npmjs.org/@goauthentik/prettier-config/-/prettier-config-3.4.3.tgz",
|
||||
"integrity": "sha512-yDfEZQy+vpP6lDKsA84rs4ye+M19TXNvTBZiTEbTj1xANnMjZoV92UtCnTUkW8DywuPkKQNmKZIEjhc7jExnTw==",
|
||||
"version": "3.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@goauthentik/prettier-config/-/prettier-config-3.4.1.tgz",
|
||||
"integrity": "sha512-jc8dHhdP3qjApZjLyRwLXB3Cg0hE7TVnyXaKLCULjfncTNYInLZK8j+UDiqWbEABxthhy/zwCdLKOKS1NuyE5A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"format-imports": "^4.0.8"
|
||||
@@ -1496,13 +1496,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@goauthentik/tsconfig": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@goauthentik/tsconfig/-/tsconfig-1.0.7.tgz",
|
||||
"integrity": "sha512-ftuK337VmEqC0/HvpzYsZm/IK9wUFx0uM1oQ9YAzBJ0nYKZ213RcJA9Q1bZfNf3B/jSMOxSSqF+rE2YdQdMV3Q==",
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@goauthentik/tsconfig/-/tsconfig-1.0.5.tgz",
|
||||
"integrity": "sha512-zedK2VYcsxHiNBBTCMFVz10P7S1uMDn8HgieHRlS8UpCYP1thKuvergISo31gSUFjRLbupMf4E4CipaYLJYkkg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=24",
|
||||
"npm": ">=11.10.1"
|
||||
"npm": ">=11.6.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@goauthentik/web-sfe": {
|
||||
@@ -3066,75 +3066,75 @@
|
||||
"license": "Apache-2.0"
|
||||
},
|
||||
"node_modules/@sentry-internal/browser-utils": {
|
||||
"version": "10.42.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-10.42.0.tgz",
|
||||
"integrity": "sha512-HCEICKvepxN4/6NYfnMMMlppcSwIEwtS66X6d1/mwaHdi2ivw0uGl52p7Nfhda/lIJArbrkWprxl0WcjZajhQA==",
|
||||
"version": "10.40.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-10.40.0.tgz",
|
||||
"integrity": "sha512-3CDeVNBXYOIvBVdT0SOdMZx5LzYDLuhGK/z7A14sYZz4Cd2+f4mSeFDaEOoH/g2SaY2CKR5KGkAADy8IyjZ21w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry/core": "10.42.0"
|
||||
"@sentry/core": "10.40.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry-internal/feedback": {
|
||||
"version": "10.42.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-10.42.0.tgz",
|
||||
"integrity": "sha512-lpPcHsog10MVYFTWE0Pf8vQRqQWwZHJpkVl2FEb9/HDdHFyTBUhCVoWo1KyKaG7GJl9AVKMAg7bp9SSNArhFNQ==",
|
||||
"version": "10.40.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-10.40.0.tgz",
|
||||
"integrity": "sha512-V/ixkcdCNMo04KgsCEeNEu966xUUTD6czKT2LOAO5siZACqFjT/Rp9VR1n7QQrVo3sL7P3QNiTHtX0jaeWbwzg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry/core": "10.42.0"
|
||||
"@sentry/core": "10.40.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry-internal/replay": {
|
||||
"version": "10.42.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-10.42.0.tgz",
|
||||
"integrity": "sha512-Zh3EoaH39x2lqVY1YyVB2vJEyCIrT+YLUQxYl1yvP0MJgLxaR6akVjkgxbSUJahan4cX5DxpZiEHfzdlWnYPyQ==",
|
||||
"version": "10.40.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-10.40.0.tgz",
|
||||
"integrity": "sha512-vsH2Ut0KIIQIHNdS3zzEGLJ2C9btbpvJIWAVk7l7oft66JzlUNC89qNaQ5SAypjLQx4Ln2V/ZTqfEoNzXOAsoQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry-internal/browser-utils": "10.42.0",
|
||||
"@sentry/core": "10.42.0"
|
||||
"@sentry-internal/browser-utils": "10.40.0",
|
||||
"@sentry/core": "10.40.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry-internal/replay-canvas": {
|
||||
"version": "10.42.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-10.42.0.tgz",
|
||||
"integrity": "sha512-am3m1Fj8ihoPfoYo41Qq4KeCAAICn4bySso8Oepu9dMNe9Lcnsf+reMRS2qxTPg3pZDc4JEMOcLyNCcgnAfrHw==",
|
||||
"version": "10.40.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-10.40.0.tgz",
|
||||
"integrity": "sha512-wzQwilFHO2baeCt0dTMf0eW+rgK8O+mkisf9sQzPXzG3Krr/iVtFg1T5T1Th3YsCsEdn6yQ3hcBPLEXjMSvccg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry-internal/replay": "10.42.0",
|
||||
"@sentry/core": "10.42.0"
|
||||
"@sentry-internal/replay": "10.40.0",
|
||||
"@sentry/core": "10.40.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/browser": {
|
||||
"version": "10.42.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-10.42.0.tgz",
|
||||
"integrity": "sha512-iXxYjXNEBwY1MH4lDSDZZUNjzPJDK7/YLwVIJq/3iBYpIQVIhaJsoJnf3clx9+NfJ8QFKyKfcvgae61zm+hgTA==",
|
||||
"version": "10.40.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-10.40.0.tgz",
|
||||
"integrity": "sha512-nCt3FKUMFad0C6xl5wCK0Jz+qT4Vev4fv6HJRn0YoNRRDQCfsUVxAz7pNyyiPNGM/WCDp9wJpGJsRvbBRd2anw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry-internal/browser-utils": "10.42.0",
|
||||
"@sentry-internal/feedback": "10.42.0",
|
||||
"@sentry-internal/replay": "10.42.0",
|
||||
"@sentry-internal/replay-canvas": "10.42.0",
|
||||
"@sentry/core": "10.42.0"
|
||||
"@sentry-internal/browser-utils": "10.40.0",
|
||||
"@sentry-internal/feedback": "10.40.0",
|
||||
"@sentry-internal/replay": "10.40.0",
|
||||
"@sentry-internal/replay-canvas": "10.40.0",
|
||||
"@sentry/core": "10.40.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/core": {
|
||||
"version": "10.42.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.42.0.tgz",
|
||||
"integrity": "sha512-L4rMrXMqUKBanpjpMT+TuAVk6xAijz6AWM6RiEYpohAr7SGcCEc1/T0+Ep1eLV8+pwWacfU27OvELIyNeOnGzA==",
|
||||
"version": "10.40.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.40.0.tgz",
|
||||
"integrity": "sha512-/wrcHPp9Avmgl6WBimPjS4gj810a1wU5oX9fF1bzJfeIIbF3jTsAbv0oMbgDp0cSDnkwv2+NvcPnn3+c5J6pBA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
@@ -3171,15 +3171,15 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@storybook/addon-docs": {
|
||||
"version": "10.2.13",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-10.2.13.tgz",
|
||||
"integrity": "sha512-puMxpJbt/CuodLIbKDxWrW1ZgADYomfNHWEKp2d2l2eJjp17rADx0h3PABuNbX+YHbJwYcDdqluSnQwMysFEOA==",
|
||||
"version": "10.2.12",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-10.2.12.tgz",
|
||||
"integrity": "sha512-LlLQSYxISugG2mEVVV/rNMyZaF1wIvIhaq5kGKbBuAz18GOtQmvaa/o3fJjlebmvTn/AOmipNlQ4ChOXSAwmdg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@mdx-js/react": "^3.0.0",
|
||||
"@storybook/csf-plugin": "10.2.13",
|
||||
"@storybook/csf-plugin": "10.2.12",
|
||||
"@storybook/icons": "^2.0.1",
|
||||
"@storybook/react-dom-shim": "10.2.13",
|
||||
"@storybook/react-dom-shim": "10.2.12",
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||
"ts-dedent": "^2.0.0"
|
||||
@@ -3189,13 +3189,13 @@
|
||||
"url": "https://opencollective.com/storybook"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"storybook": "^10.2.13"
|
||||
"storybook": "^10.2.12"
|
||||
}
|
||||
},
|
||||
"node_modules/@storybook/addon-links": {
|
||||
"version": "10.2.13",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-10.2.13.tgz",
|
||||
"integrity": "sha512-8wnAomGiHaUpNIc+lOzmazTrebxa64z9rihIbM/Q59vkOImHQNkGp7KP/qNgJA4GPTFtu8+fLjX2qCoAQPM0jQ==",
|
||||
"version": "10.2.12",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/addon-links/-/addon-links-10.2.12.tgz",
|
||||
"integrity": "sha512-ybqnOhje/V75AbsGsLkk6uCcOXsfyUrkdqnp/y2e6YJRws2mlNMIYduNtqorFHm3Yh+NPH9GnzulVFaDFXBiYw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@storybook/global": "^5.0.0"
|
||||
@@ -3206,7 +3206,7 @@
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||
"storybook": "^10.2.13"
|
||||
"storybook": "^10.2.12"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"react": {
|
||||
@@ -3215,12 +3215,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@storybook/builder-vite": {
|
||||
"version": "10.2.13",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/builder-vite/-/builder-vite-10.2.13.tgz",
|
||||
"integrity": "sha512-UMlPPPBa5ZbcaCXSKrFIi4tTEb0W72JTByqlJ5cGtDXGkN2uX69aL5n2JLIP0F4NzRRl6rNTeu9tGPPcD4r/CA==",
|
||||
"version": "10.2.12",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/builder-vite/-/builder-vite-10.2.12.tgz",
|
||||
"integrity": "sha512-QaOwhNpoBs4Af8xYG1NOoyOvbapcN7EpwYq53ERpMz2uU+yOeApqy4XeJ5xM7doCvkJKZqidwLMXZQeN/j/mUw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@storybook/csf-plugin": "10.2.13",
|
||||
"@storybook/csf-plugin": "10.2.12",
|
||||
"ts-dedent": "^2.0.0"
|
||||
},
|
||||
"funding": {
|
||||
@@ -3228,14 +3228,14 @@
|
||||
"url": "https://opencollective.com/storybook"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"storybook": "^10.2.13",
|
||||
"storybook": "^10.2.12",
|
||||
"vite": "^5.0.0 || ^6.0.0 || ^7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@storybook/csf-plugin": {
|
||||
"version": "10.2.13",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-10.2.13.tgz",
|
||||
"integrity": "sha512-gUCR7PmyrWYj3dIJJgxOm25dcXFolPIUPmug3z90Aaon7YPXw3pUN+dNDx8KqDJqRK1WDIB4HaefgYZIm5V7iA==",
|
||||
"version": "10.2.12",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-10.2.12.tgz",
|
||||
"integrity": "sha512-+6nv7oX21K+BRmMUCfeaFeS3UFgDu5/2M4YsLYzXnx/YmAP3yg0bb09falzvCKTCncHCJUWaO8GDvavj32anaA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"unplugin": "^2.3.5"
|
||||
@@ -3247,7 +3247,7 @@
|
||||
"peerDependencies": {
|
||||
"esbuild": "*",
|
||||
"rollup": "*",
|
||||
"storybook": "^10.2.13",
|
||||
"storybook": "^10.2.12",
|
||||
"vite": "*",
|
||||
"webpack": "*"
|
||||
},
|
||||
@@ -3283,9 +3283,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@storybook/react-dom-shim": {
|
||||
"version": "10.2.13",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-10.2.13.tgz",
|
||||
"integrity": "sha512-ZSduoB10qTI0V9z22qeULmQLsvTs8d/rtJi03qbVxpPiMRor86AmyAaBrfhGGmWBxWQZpOGQQm6yIT2YLoPs7w==",
|
||||
"version": "10.2.12",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-10.2.12.tgz",
|
||||
"integrity": "sha512-T4uHPAgtEbroRazubGDIByopvNw1WKAp1kOlNqKWR8LZPDaVyEr8X7J6zaJo1y+vE8j6fUXvk6jZVMwhi/Jeig==",
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
@@ -3294,13 +3294,13 @@
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
|
||||
"storybook": "^10.2.13"
|
||||
"storybook": "^10.2.12"
|
||||
}
|
||||
},
|
||||
"node_modules/@storybook/web-components": {
|
||||
"version": "10.2.13",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/web-components/-/web-components-10.2.13.tgz",
|
||||
"integrity": "sha512-su/f9CUdWwwc5c8+p6RvAB1LgWLbcSJ2y1bUj9QJsYyWB7cG+t76XoQ/5fuob71GgLCt7Aqz0+9oLMTUicCXgw==",
|
||||
"version": "10.2.12",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/web-components/-/web-components-10.2.12.tgz",
|
||||
"integrity": "sha512-lb57k6NkVum9vkalRnmK8qf6KRDei/yTgyPdLQoGzYl7RLtkBPrElvEV6YYnnryc8HYpmQx4vXs7cnE/SrfYVw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@storybook/global": "^5.0.0",
|
||||
@@ -3313,24 +3313,24 @@
|
||||
},
|
||||
"peerDependencies": {
|
||||
"lit": "^2.0.0 || ^3.0.0",
|
||||
"storybook": "^10.2.13"
|
||||
"storybook": "^10.2.12"
|
||||
}
|
||||
},
|
||||
"node_modules/@storybook/web-components-vite": {
|
||||
"version": "10.2.13",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/web-components-vite/-/web-components-vite-10.2.13.tgz",
|
||||
"integrity": "sha512-LLXhMREvpFJmjyt1GIycHAJlI2vleXe2wJ9XkbuD6zIIArUsuB/3iNT2RDCudzFmOXqQQjsYAd4QWbIkCCYMKA==",
|
||||
"version": "10.2.12",
|
||||
"resolved": "https://registry.npmjs.org/@storybook/web-components-vite/-/web-components-vite-10.2.12.tgz",
|
||||
"integrity": "sha512-YHeX6StEJDyrhrlrnonUQqQ8Ee68bJUCD8Sr6oSSXLQUhKVs4SNw+uMYmxKL6z/kAC0Ez0nG5z/T32UTuoVYYA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@storybook/builder-vite": "10.2.13",
|
||||
"@storybook/web-components": "10.2.13"
|
||||
"@storybook/builder-vite": "10.2.12",
|
||||
"@storybook/web-components": "10.2.12"
|
||||
},
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/storybook"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"storybook": "^10.2.13"
|
||||
"storybook": "^10.2.12"
|
||||
}
|
||||
},
|
||||
"node_modules/@swagger-api/apidom-ast": {
|
||||
@@ -3939,9 +3939,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core": {
|
||||
"version": "1.15.18",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core/-/core-1.15.18.tgz",
|
||||
"integrity": "sha512-z87aF9GphWp//fnkRsqvtY+inMVPgYW3zSlXH1kJFvRT5H/wiAn+G32qW5l3oEk63KSF1x3Ov0BfHCObAmT8RA==",
|
||||
"version": "1.15.13",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core/-/core-1.15.13.tgz",
|
||||
"integrity": "sha512-0l1gl/72PErwUZuavcRpRAQN9uSst+Nk++niC5IX6lmMWpXoScYx3oq/narT64/sKv/eRiPTaAjBFGDEQiWJIw==",
|
||||
"hasInstallScript": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
@@ -3956,16 +3956,16 @@
|
||||
"url": "https://opencollective.com/swc"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@swc/core-darwin-arm64": "1.15.18",
|
||||
"@swc/core-darwin-x64": "1.15.18",
|
||||
"@swc/core-linux-arm-gnueabihf": "1.15.18",
|
||||
"@swc/core-linux-arm64-gnu": "1.15.18",
|
||||
"@swc/core-linux-arm64-musl": "1.15.18",
|
||||
"@swc/core-linux-x64-gnu": "1.15.18",
|
||||
"@swc/core-linux-x64-musl": "1.15.18",
|
||||
"@swc/core-win32-arm64-msvc": "1.15.18",
|
||||
"@swc/core-win32-ia32-msvc": "1.15.18",
|
||||
"@swc/core-win32-x64-msvc": "1.15.18"
|
||||
"@swc/core-darwin-arm64": "1.15.13",
|
||||
"@swc/core-darwin-x64": "1.15.13",
|
||||
"@swc/core-linux-arm-gnueabihf": "1.15.13",
|
||||
"@swc/core-linux-arm64-gnu": "1.15.13",
|
||||
"@swc/core-linux-arm64-musl": "1.15.13",
|
||||
"@swc/core-linux-x64-gnu": "1.15.13",
|
||||
"@swc/core-linux-x64-musl": "1.15.13",
|
||||
"@swc/core-win32-arm64-msvc": "1.15.13",
|
||||
"@swc/core-win32-ia32-msvc": "1.15.13",
|
||||
"@swc/core-win32-x64-msvc": "1.15.13"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@swc/helpers": ">=0.5.17"
|
||||
@@ -3977,9 +3977,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-darwin-arm64": {
|
||||
"version": "1.15.18",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.15.18.tgz",
|
||||
"integrity": "sha512-+mIv7uBuSaywN3C9LNuWaX1jJJ3SKfiJuE6Lr3bd+/1Iv8oMU7oLBjYMluX1UrEPzwN2qCdY6Io0yVicABoCwQ==",
|
||||
"version": "1.15.13",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.15.13.tgz",
|
||||
"integrity": "sha512-ztXusRuC5NV2w+a6pDhX13CGioMLq8CjX5P4XgVJ21ocqz9t19288Do0y8LklplDtwcEhYGTNdMbkmUT7+lDTg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -3993,9 +3993,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-darwin-x64": {
|
||||
"version": "1.15.18",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.15.18.tgz",
|
||||
"integrity": "sha512-wZle0eaQhnzxWX5V/2kEOI6Z9vl/lTFEC6V4EWcn+5pDjhemCpQv9e/TDJ0GIoiClX8EDWRvuZwh+Z3dhL1NAg==",
|
||||
"version": "1.15.13",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.15.13.tgz",
|
||||
"integrity": "sha512-cVifxQUKhaE7qcO/y9Mq6PEhoyvN9tSLzCnnFZ4EIabFHBuLtDDO6a+vLveOy98hAs5Qu1+bb5Nv0oa1Pihe3Q==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -4009,9 +4009,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-arm-gnueabihf": {
|
||||
"version": "1.15.18",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.15.18.tgz",
|
||||
"integrity": "sha512-ao61HGXVqrJFHAcPtF4/DegmwEkVCo4HApnotLU8ognfmU8x589z7+tcf3hU+qBiU1WOXV5fQX6W9Nzs6hjxDw==",
|
||||
"version": "1.15.13",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.15.13.tgz",
|
||||
"integrity": "sha512-t+xxEzZ48enl/wGGy7SRYd7kImWQ/+wvVFD7g5JZo234g6/QnIgZ+YdfIyjHB+ZJI3F7a2IQHS7RNjxF29UkWw==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@@ -4025,9 +4025,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-arm64-gnu": {
|
||||
"version": "1.15.18",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.15.18.tgz",
|
||||
"integrity": "sha512-3xnctOBLIq3kj8PxOCgPrGjBLP/kNOddr6f5gukYt/1IZxsITQaU9TDyjeX6jG+FiCIHjCuWuffsyQDL5Ew1bg==",
|
||||
"version": "1.15.13",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.15.13.tgz",
|
||||
"integrity": "sha512-VndeGvKmTXFn6AGwjy0Kg8i7HccOCE7Jt/vmZwRxGtOfNZM1RLYRQ7MfDLo6T0h1Bq6eYzps3L5Ma4zBmjOnOg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -4041,9 +4041,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-arm64-musl": {
|
||||
"version": "1.15.18",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.15.18.tgz",
|
||||
"integrity": "sha512-0a+Lix+FSSHBSBOA0XznCcHo5/1nA6oLLjcnocvzXeqtdjnPb+SvchItHI+lfeiuj1sClYPDvPMLSLyXFaiIKw==",
|
||||
"version": "1.15.13",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.15.13.tgz",
|
||||
"integrity": "sha512-SmZ9m+XqCB35NddHCctvHFLqPZDAs5j8IgD36GoutufDJmeq2VNfgk5rQoqNqKmAK3Y7iFdEmI76QoHIWiCLyw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -4057,9 +4057,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-x64-gnu": {
|
||||
"version": "1.15.18",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.15.18.tgz",
|
||||
"integrity": "sha512-wG9J8vReUlpaHz4KOD/5UE1AUgirimU4UFT9oZmupUDEofxJKYb1mTA/DrMj0s78bkBiNI+7Fo2EgPuvOJfuAA==",
|
||||
"version": "1.15.13",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.15.13.tgz",
|
||||
"integrity": "sha512-5rij+vB9a29aNkHq72EXI2ihDZPszJb4zlApJY4aCC/q6utgqFA6CkrfTfIb+O8hxtG3zP5KERETz8mfFK6A0A==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -4073,9 +4073,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-x64-musl": {
|
||||
"version": "1.15.18",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.15.18.tgz",
|
||||
"integrity": "sha512-4nwbVvCphKzicwNWRmvD5iBaZj8JYsRGa4xOxJmOyHlMDpsvvJ2OR2cODlvWyGFH6BYL1MfIAK3qph3hp0Az6g==",
|
||||
"version": "1.15.13",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.15.13.tgz",
|
||||
"integrity": "sha512-OlSlaOK9JplQ5qn07WiBLibkOw7iml2++ojEXhhR3rbWrNEKCD7sd8+6wSavsInyFdw4PhLA+Hy6YyDBIE23Yw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -4089,9 +4089,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-win32-arm64-msvc": {
|
||||
"version": "1.15.18",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.15.18.tgz",
|
||||
"integrity": "sha512-zk0RYO+LjiBCat2RTMHzAWaMky0cra9loH4oRrLKLLNuL+jarxKLFDA8xTZWEkCPLjUTwlRN7d28eDLLMgtUcQ==",
|
||||
"version": "1.15.13",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.15.13.tgz",
|
||||
"integrity": "sha512-zwQii5YVdsfG8Ti9gIKgBKZg8qMkRZxl+OlYWUT5D93Jl4NuNBRausP20tfEkQdAPSRrMCSUZBM6FhW7izAZRg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -4105,9 +4105,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-win32-ia32-msvc": {
|
||||
"version": "1.15.18",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.15.18.tgz",
|
||||
"integrity": "sha512-yVuTrZ0RccD5+PEkpcLOBAuPbYBXS6rslENvIXfvJGXSdX5QGi1ehC4BjAMl5FkKLiam4kJECUI0l7Hq7T1vwg==",
|
||||
"version": "1.15.13",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.15.13.tgz",
|
||||
"integrity": "sha512-hYXvyVVntqRlYoAIDwNzkS3tL2ijP3rxyWQMNKaxcCxxkCDto/w3meOK/OB6rbQSkNw0qTUcBfU9k+T0ptYdfQ==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
@@ -4121,9 +4121,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-win32-x64-msvc": {
|
||||
"version": "1.15.18",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.15.18.tgz",
|
||||
"integrity": "sha512-7NRmE4hmUQNCbYU3Hn9Tz57mK9Qq4c97ZS+YlamlK6qG9Fb5g/BB3gPDe0iLlJkns/sYv2VWSkm8c3NmbEGjbg==",
|
||||
"version": "1.15.13",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.15.13.tgz",
|
||||
"integrity": "sha512-XTzKs7c/vYCcjmcwawnQvlHHNS1naJEAzcBckMI5OJlnrcgW8UtcX9NHFYvNjGtXuKv0/9KvqL4fuahdvlNGKw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -4645,9 +4645,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "25.3.3",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.3.3.tgz",
|
||||
"integrity": "sha512-DpzbrH7wIcBaJibpKo9nnSQL0MTRdnWttGyE5haGwK86xgMOkFLp7vEyfQPGLOJh5wNYiJ3V9PmUMDhV9u8kkQ==",
|
||||
"version": "25.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.3.0.tgz",
|
||||
"integrity": "sha512-4K3bqJpXpqfg2XKGK9bpDTc6xO/xoUP/RBWS7AtRMug6zZFaRekiLzjVtAoZMquxoAbzBvy5nxQ7veS5eYzf8A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~7.18.0"
|
||||
@@ -6577,9 +6577,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/country-flag-icons": {
|
||||
"version": "1.6.15",
|
||||
"resolved": "https://registry.npmjs.org/country-flag-icons/-/country-flag-icons-1.6.15.tgz",
|
||||
"integrity": "sha512-92HoA8l6DluEidku8tKBftjuFRj4Rv3zDW1lXxCuNnqAxhUSkvso9gM/Afj4F5BnK+wneHIe3ydI+s+4NA29/Q==",
|
||||
"version": "1.6.14",
|
||||
"resolved": "https://registry.npmjs.org/country-flag-icons/-/country-flag-icons-1.6.14.tgz",
|
||||
"integrity": "sha512-tPis+tN/esXXSuQJZCbkUhnIeUrZmtDKSjUuSI7Sss2GHsgAGvbSAQkx4Ut0qethZbDfPGYco8EjzOPElxYIFw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/crelt": {
|
||||
@@ -9220,9 +9220,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/globals": {
|
||||
"version": "17.4.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-17.4.0.tgz",
|
||||
"integrity": "sha512-hjrNztw/VajQwOLsMNT1cbJiH2muO3OROCHnbehc8eY5JyD2gqz4AcMHPqgaOR59DjgUjYAYLeH699g/eWi2jw==",
|
||||
"version": "17.3.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-17.3.0.tgz",
|
||||
"integrity": "sha512-yMqGUQVVCkD4tqjOJf3TnrvaaHDMYp4VlUSObbkIiuCPe/ofdMBFIAcBbCSRFWOnos6qRiTVStDwqPLUclaxIw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
@@ -15312,9 +15312,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/storybook": {
|
||||
"version": "10.2.13",
|
||||
"resolved": "https://registry.npmjs.org/storybook/-/storybook-10.2.13.tgz",
|
||||
"integrity": "sha512-heMfJjOfbHvL+wlCAwFZlSxcakyJ5yQDam6e9k2RRArB1veJhRnsjO6lO1hOXjJYrqxfHA/ldIugbBVlCDqfvQ==",
|
||||
"version": "10.2.12",
|
||||
"resolved": "https://registry.npmjs.org/storybook/-/storybook-10.2.12.tgz",
|
||||
"integrity": "sha512-eT4266OqLdRE3J/pxl2dk36Rnj9vv17Y6rNMpzxohOMjRVONyKkozUd6gaZ2C4WUcwYdIw6VE+ft4LwrJXt/4Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@storybook/global": "^5.0.0",
|
||||
@@ -17351,8 +17351,8 @@
|
||||
"version": "1.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@goauthentik/tsconfig": "^1.0.7",
|
||||
"@types/node": "^25.3.3",
|
||||
"@goauthentik/tsconfig": "^1.0.5",
|
||||
"@types/node": "^25.3.0",
|
||||
"@types/semver": "^7.7.1",
|
||||
"semver": "^7.7.4",
|
||||
"typescript": "^5.9.3"
|
||||
@@ -17385,7 +17385,7 @@
|
||||
"@rollup/plugin-node-resolve": "^16.0.3",
|
||||
"@rollup/plugin-swc": "^0.4.0",
|
||||
"@swc/cli": "^0.8.0",
|
||||
"@swc/core": "^1.15.18",
|
||||
"@swc/core": "^1.15.11",
|
||||
"base64-js": "^1.5.1",
|
||||
"core-js": "^3.48.0",
|
||||
"formdata-polyfill": "^2025.11.0",
|
||||
|
||||
@@ -89,21 +89,21 @@
|
||||
"dependencies": {
|
||||
"@codemirror/lang-css": "^6.3.1",
|
||||
"@codemirror/lang-html": "^6.4.11",
|
||||
"@codemirror/lang-javascript": "^6.2.5",
|
||||
"@codemirror/lang-javascript": "^6.2.4",
|
||||
"@codemirror/lang-python": "^6.2.1",
|
||||
"@codemirror/lang-xml": "^6.1.0",
|
||||
"@codemirror/legacy-modes": "^6.5.2",
|
||||
"@codemirror/theme-one-dark": "^6.1.3",
|
||||
"@eslint/js": "^9.39.3",
|
||||
"@floating-ui/dom": "^1.7.6",
|
||||
"@floating-ui/dom": "^1.7.5",
|
||||
"@formatjs/intl-listformat": "^8.2.1",
|
||||
"@fortawesome/fontawesome-free": "^7.2.0",
|
||||
"@goauthentik/api": "^2026.2.0-rc1-1770744803",
|
||||
"@goauthentik/core": "^1.0.0",
|
||||
"@goauthentik/esbuild-plugin-live-reload": "^1.6.1",
|
||||
"@goauthentik/esbuild-plugin-live-reload": "^1.6.0",
|
||||
"@goauthentik/eslint-config": "^1.3.0",
|
||||
"@goauthentik/prettier-config": "^3.4.3",
|
||||
"@goauthentik/tsconfig": "^1.0.7",
|
||||
"@goauthentik/prettier-config": "^3.4.1",
|
||||
"@goauthentik/tsconfig": "^1.0.5",
|
||||
"@hcaptcha/types": "^1.1.0",
|
||||
"@lit/context": "^1.1.6",
|
||||
"@lit/localize": "^0.12.2",
|
||||
@@ -118,15 +118,15 @@
|
||||
"@patternfly/elements": "^4.3.1",
|
||||
"@patternfly/patternfly": "^4.224.2",
|
||||
"@playwright/test": "^1.58.2",
|
||||
"@sentry/browser": "^10.42.0",
|
||||
"@storybook/addon-docs": "^10.2.13",
|
||||
"@storybook/addon-links": "^10.2.13",
|
||||
"@storybook/web-components": "^10.2.13",
|
||||
"@storybook/web-components-vite": "^10.2.13",
|
||||
"@sentry/browser": "^10.39.0",
|
||||
"@storybook/addon-docs": "^10.2.10",
|
||||
"@storybook/addon-links": "^10.2.10",
|
||||
"@storybook/web-components": "^10.2.10",
|
||||
"@storybook/web-components-vite": "^10.2.10",
|
||||
"@types/codemirror": "^5.60.17",
|
||||
"@types/grecaptcha": "^3.0.9",
|
||||
"@types/guacamole-common-js": "^1.5.5",
|
||||
"@types/node": "^25.3.3",
|
||||
"@types/node": "^25.3.0",
|
||||
"@types/react": "^19.2.14",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@typescript-eslint/eslint-plugin": "^8.56.1",
|
||||
@@ -140,7 +140,7 @@
|
||||
"chartjs-adapter-date-fns": "^3.0.0",
|
||||
"codemirror": "^6.0.2",
|
||||
"core-js": "^3.48.0",
|
||||
"country-flag-icons": "^1.6.15",
|
||||
"country-flag-icons": "^1.6.13",
|
||||
"date-fns": "^4.1.0",
|
||||
"deepmerge-ts": "^7.1.5",
|
||||
"dompurify": "^3.3.1",
|
||||
@@ -149,7 +149,7 @@
|
||||
"eslint-plugin-lit": "^2.2.1",
|
||||
"eslint-plugin-wc": "^3.1.0",
|
||||
"fuse.js": "^7.1.0",
|
||||
"globals": "^17.4.0",
|
||||
"globals": "^17.3.0",
|
||||
"guacamole-common-js": "^1.5.0",
|
||||
"hastscript": "^9.0.1",
|
||||
"knip": "^5.85.0",
|
||||
|
||||
@@ -44,8 +44,8 @@
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@goauthentik/tsconfig": "^1.0.7",
|
||||
"@types/node": "^25.3.3",
|
||||
"@goauthentik/tsconfig": "^1.0.5",
|
||||
"@types/node": "^25.3.0",
|
||||
"@types/semver": "^7.7.1",
|
||||
"semver": "^7.7.4",
|
||||
"typescript": "^5.9.3"
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
"@rollup/plugin-node-resolve": "^16.0.3",
|
||||
"@rollup/plugin-swc": "^0.4.0",
|
||||
"@swc/cli": "^0.8.0",
|
||||
"@swc/core": "^1.15.18",
|
||||
"@swc/core": "^1.15.11",
|
||||
"base64-js": "^1.5.1",
|
||||
"core-js": "^3.48.0",
|
||||
"formdata-polyfill": "^2025.11.0",
|
||||
|
||||
@@ -3,172 +3,137 @@ import "#elements/EmptyState";
|
||||
import { DEFAULT_CONFIG } from "#common/api/config";
|
||||
import { globalAK } from "#common/global";
|
||||
|
||||
import { ModalButton } from "#elements/buttons/ModalButton";
|
||||
import { WithBrandConfig } from "#elements/mixins/branding";
|
||||
import { WithLicenseSummary } from "#elements/mixins/license";
|
||||
import { AKModal } from "#elements/modals/ak-modal";
|
||||
import { asInvoker } from "#elements/modals/utils";
|
||||
import { ThemedImage } from "#elements/utils/images";
|
||||
|
||||
import { AdminApi, CapabilitiesEnum, LicenseSummaryStatusEnum } from "@goauthentik/api";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
import { css, html, TemplateResult } from "lit";
|
||||
import { ref } from "lit-html/directives/ref.js";
|
||||
import { styleMap } from "lit-html/directives/style-map.js";
|
||||
import { customElement, state } from "lit/decorators.js";
|
||||
import { customElement } from "lit/decorators.js";
|
||||
import { createRef, ref } from "lit/directives/ref.js";
|
||||
import { until } from "lit/directives/until.js";
|
||||
|
||||
import PFAbout from "@patternfly/patternfly/components/AboutModalBox/about-modal-box.css";
|
||||
|
||||
const DEFAULT_BRAND_IMAGE = "/static/dist/assets/images/flow_background.jpg";
|
||||
|
||||
type AboutEntry = [label: string, content: string | TemplateResult];
|
||||
|
||||
async function fetchAboutDetails(): Promise<AboutEntry[]> {
|
||||
const api = new AdminApi(DEFAULT_CONFIG);
|
||||
|
||||
const [status, version] = await Promise.all([
|
||||
api.adminSystemRetrieve(),
|
||||
api.adminVersionRetrieve(),
|
||||
]);
|
||||
|
||||
let build: string | TemplateResult = msg("Release");
|
||||
|
||||
if (globalAK().config.capabilities.includes(CapabilitiesEnum.CanDebug)) {
|
||||
build = msg("Development");
|
||||
} else if (version.buildHash) {
|
||||
build = html`<a
|
||||
rel="noopener noreferrer"
|
||||
href="https://github.com/goauthentik/authentik/commit/${version.buildHash}"
|
||||
target="_blank"
|
||||
>${version.buildHash}</a
|
||||
>`;
|
||||
}
|
||||
|
||||
return [
|
||||
[msg("Version"), version.versionCurrent],
|
||||
[msg("UI Version"), import.meta.env.AK_VERSION],
|
||||
[msg("Build"), build],
|
||||
[msg("Python version"), status.runtime.pythonVersion],
|
||||
[msg("Platform"), status.runtime.platform],
|
||||
[msg("Kernel"), status.runtime.uname],
|
||||
[
|
||||
msg("OpenSSL"),
|
||||
`${status.runtime.opensslVersion} ${status.runtime.opensslFipsEnabled ? "FIPS" : ""}`,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
@customElement("ak-about-modal")
|
||||
export class AboutModal extends WithLicenseSummary(WithBrandConfig(AKModal)) {
|
||||
static hostStyles = [
|
||||
css`
|
||||
dialog.ak-c-modal:has(ak-about-modal) {
|
||||
--ak-c-modal--BackgroundColor: var(--pf-global--palette--black-900);
|
||||
--ak-c-modal--BorderColor: var(--pf-global--palette--black-600);
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
export class AboutModal extends WithLicenseSummary(WithBrandConfig(ModalButton)) {
|
||||
static styles = [
|
||||
...AKModal.styles,
|
||||
...ModalButton.styles,
|
||||
PFAbout,
|
||||
css`
|
||||
:host {
|
||||
height: 100%;
|
||||
.pf-c-about-modal-box {
|
||||
--pf-c-about-modal-box--BackgroundColor: var(--pf-global--palette--black-900);
|
||||
}
|
||||
|
||||
.pf-c-about-modal-box {
|
||||
--pf-c-about-modal-box--BackgroundColor: var(--ak-c-modal--BackgroundColor);
|
||||
width: unset;
|
||||
height: 100%;
|
||||
max-height: unset;
|
||||
max-width: unset;
|
||||
z-index: unset;
|
||||
position: unset;
|
||||
box-shadow: unset;
|
||||
.pf-c-about-modal-box__hero {
|
||||
background-image: url("/static/dist/assets/images/flow_background.jpg");
|
||||
}
|
||||
.pf-c-about-modal-box__brand {
|
||||
--pf-c-about-modal-box__brand-image--Height: 6.25rem;
|
||||
}
|
||||
.pf-c-about-modal-box__brand i {
|
||||
font-size: var(--pf-c-about-modal-box__brand-image--Height);
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
public static open = asInvoker(AboutModal);
|
||||
|
||||
@state()
|
||||
protected entries: AboutEntry[] | null = null;
|
||||
|
||||
public refresh() {
|
||||
return fetchAboutDetails().then((entries) => {
|
||||
this.entries = entries;
|
||||
});
|
||||
async getAboutEntries(): Promise<[string, string | TemplateResult][]> {
|
||||
const status = await new AdminApi(DEFAULT_CONFIG).adminSystemRetrieve();
|
||||
const version = await new AdminApi(DEFAULT_CONFIG).adminVersionRetrieve();
|
||||
let build: string | TemplateResult = msg("Release");
|
||||
if (globalAK().config.capabilities.includes(CapabilitiesEnum.CanDebug)) {
|
||||
build = msg("Development");
|
||||
} else if (version.buildHash !== "") {
|
||||
build = html`<a
|
||||
rel="noopener noreferrer"
|
||||
href="https://github.com/goauthentik/authentik/commit/${version.buildHash}"
|
||||
target="_blank"
|
||||
>${version.buildHash}</a
|
||||
>`;
|
||||
}
|
||||
return [
|
||||
[msg("Version"), version.versionCurrent],
|
||||
[msg("UI Version"), import.meta.env.AK_VERSION],
|
||||
[msg("Build"), build],
|
||||
[msg("Python version"), status.runtime.pythonVersion],
|
||||
[msg("Platform"), status.runtime.platform],
|
||||
[msg("Kernel"), status.runtime.uname],
|
||||
[
|
||||
msg("OpenSSL"),
|
||||
`${status.runtime.opensslVersion} ${status.runtime.opensslFipsEnabled ? "FIPS" : ""}`,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
this.refresh();
|
||||
}
|
||||
#contentRef = createRef<HTMLDivElement>();
|
||||
|
||||
//#region Renderers
|
||||
#backdropListener = (event: PointerEvent) => {
|
||||
// We only want to close the modal when the backdrop is clicked, not when it's children are clicked.
|
||||
|
||||
protected override renderCloseButton() {
|
||||
return null;
|
||||
}
|
||||
if (this.#contentRef.value?.contains(event.target as Node)) {
|
||||
return;
|
||||
}
|
||||
this.close();
|
||||
};
|
||||
|
||||
protected override render() {
|
||||
protected override renderModal() {
|
||||
let product = this.brandingTitle;
|
||||
|
||||
if (this.licenseSummary?.status !== LicenseSummaryStatusEnum.Unlicensed) {
|
||||
product += ` ${msg("Enterprise")}`;
|
||||
}
|
||||
|
||||
return html`<div
|
||||
${ref(this.scrollContainerRef)}
|
||||
class="pf-c-about-modal-box"
|
||||
style=${styleMap({
|
||||
"--pf-c-about-modal-box__hero--sm--BackgroundImage": `url(${DEFAULT_BRAND_IMAGE})`,
|
||||
})}
|
||||
aria-labelledby="modal-title"
|
||||
>
|
||||
<div class="pf-c-about-modal-box__close">
|
||||
<button
|
||||
class="pf-c-button pf-m-plain"
|
||||
type="button"
|
||||
@click=${this.closeListener}
|
||||
aria-label=${msg("Close dialog")}
|
||||
return html`<div class="pf-c-backdrop" @click=${this.#backdropListener}>
|
||||
<div class="pf-l-bullseye">
|
||||
<div
|
||||
${ref(this.#contentRef)}
|
||||
class="pf-c-about-modal-box"
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
aria-labelledby="modal-title"
|
||||
>
|
||||
<i class="fas fa-times" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="pf-c-about-modal-box__brand">
|
||||
${ThemedImage({
|
||||
src: this.brandingFavicon,
|
||||
alt: msg("authentik Logo"),
|
||||
className: "pf-c-about-modal-box__brand-image",
|
||||
theme: this.activeTheme,
|
||||
themedUrls: this.brandingFaviconThemedUrls,
|
||||
})}
|
||||
</div>
|
||||
<div class="pf-c-about-modal-box__header">
|
||||
<h1 class="pf-c-title pf-m-4xl" id="modal-title">${product}</h1>
|
||||
</div>
|
||||
<div class="pf-c-about-modal-box__hero"></div>
|
||||
<div class="pf-c-about-modal-box__content">
|
||||
<div class="pf-c-about-modal-box__body">
|
||||
<div class="pf-c-content">
|
||||
${this.entries
|
||||
? html`<dl>
|
||||
${this.entries.map(([label, value]) => {
|
||||
return html`<dt>${label}</dt>
|
||||
<dd>${value}</dd>`;
|
||||
})}
|
||||
</dl>`
|
||||
: html`<ak-empty-state loading></ak-empty-state>`}
|
||||
<div class="pf-c-about-modal-box__brand">
|
||||
${ThemedImage({
|
||||
src: this.brandingFavicon,
|
||||
alt: msg("authentik Logo"),
|
||||
className: "pf-c-about-modal-box__brand-image",
|
||||
theme: this.activeTheme,
|
||||
themedUrls: this.brandingFaviconThemedUrls,
|
||||
})}
|
||||
</div>
|
||||
<div class="pf-c-about-modal-box__close">
|
||||
<button class="pf-c-button pf-m-plain" type="button" @click=${this.close}>
|
||||
<i class="fas fa-times" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="pf-c-about-modal-box__header">
|
||||
<h1 class="pf-c-title pf-m-4xl" id="modal-title">${product}</h1>
|
||||
</div>
|
||||
<div class="pf-c-about-modal-box__hero"></div>
|
||||
<div class="pf-c-about-modal-box__content">
|
||||
<div class="pf-c-about-modal-box__body">
|
||||
<div class="pf-c-content">
|
||||
${until(
|
||||
this.getAboutEntries().then((entries) => {
|
||||
return html`<dl>
|
||||
${entries.map(([label, value]) => {
|
||||
return html`<dt>${label}</dt>
|
||||
<dd>${value}</dd>`;
|
||||
})}
|
||||
</dl>`;
|
||||
}),
|
||||
html`<ak-empty-state loading></ak-empty-state>`,
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<p class="pf-c-about-modal-box__strapline"></p>
|
||||
</div>
|
||||
</div>
|
||||
<p class="pf-c-about-modal-box__strapline"></p>
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import "#admin/AdminInterface/AboutModal";
|
||||
import "#elements/banner/EnterpriseStatusBanner";
|
||||
import "#elements/banner/VersionBanner";
|
||||
import "#elements/messages/MessageContainer";
|
||||
@@ -9,7 +10,6 @@ import {
|
||||
createAdminSidebarEnterpriseEntries,
|
||||
createAdminSidebarEntries,
|
||||
renderSidebarItems,
|
||||
SidebarEntry,
|
||||
} from "./AdminSidebar.js";
|
||||
|
||||
import { isAPIResultReady } from "#common/api/responses";
|
||||
@@ -29,16 +29,16 @@ import {
|
||||
readDrawerParams,
|
||||
renderNotificationDrawerPanel,
|
||||
} from "#elements/notifications/utils";
|
||||
import { navigate } from "#elements/router/RouterOutlet";
|
||||
|
||||
import type { AboutModal } from "#admin/AdminInterface/AboutModal";
|
||||
import Styles from "#admin/AdminInterface/index.entrypoint.css";
|
||||
import { ROUTES } from "#admin/Routes";
|
||||
|
||||
import { CapabilitiesEnum } from "@goauthentik/api";
|
||||
|
||||
import { LOCALE_STATUS_EVENT, LocaleStatusEventDetail, msg } from "@lit/localize";
|
||||
import { msg } from "@lit/localize";
|
||||
import { CSSResult, html, nothing, PropertyValues, TemplateResult } from "lit";
|
||||
import { customElement, eventOptions, property, state } from "lit/decorators.js";
|
||||
import { customElement, eventOptions, property, query, state } from "lit/decorators.js";
|
||||
import { classMap } from "lit/directives/class-map.js";
|
||||
|
||||
import PFButton from "@patternfly/patternfly/components/Button/button.css";
|
||||
@@ -60,14 +60,14 @@ export class AdminInterface extends WithCapabilitiesConfig(
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region Public Properties
|
||||
//#region Properties
|
||||
|
||||
@query("ak-about-modal")
|
||||
public aboutModal?: AboutModal;
|
||||
|
||||
@property({ type: Boolean, reflect: true, attribute: "sidebar" })
|
||||
public sidebarOpen = false;
|
||||
|
||||
@property({ type: Array })
|
||||
public entries: readonly SidebarEntry[] = createAdminSidebarEntries();
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region Public Methods
|
||||
@@ -76,14 +76,9 @@ export class AdminInterface extends WithCapabilitiesConfig(
|
||||
this.sidebarOpen = !this.sidebarOpen;
|
||||
};
|
||||
|
||||
public synchronizeSidebarEntries = () => {
|
||||
this.logger.debug("Synchronizing sidebar entries with current locale");
|
||||
this.entries = createAdminSidebarEntries();
|
||||
};
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region Event Listeners
|
||||
//#region Lifecycle
|
||||
|
||||
#sidebarMatcher: MediaQueryList;
|
||||
#sidebarMediaQueryListener = (event: MediaQueryListEvent) => {
|
||||
@@ -104,17 +99,6 @@ export class AdminInterface extends WithCapabilitiesConfig(
|
||||
persistDrawerParams(event.drawer);
|
||||
};
|
||||
|
||||
@listen(LOCALE_STATUS_EVENT)
|
||||
localeStatusListener = (event: CustomEvent<LocaleStatusEventDetail>) => {
|
||||
if (event.detail.status === "ready") {
|
||||
this.synchronizeSidebarEntries();
|
||||
}
|
||||
};
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region Lifecycle
|
||||
|
||||
constructor() {
|
||||
configureSentry();
|
||||
|
||||
@@ -126,41 +110,6 @@ export class AdminInterface extends WithCapabilitiesConfig(
|
||||
this.sidebarOpen = this.#sidebarMatcher.matches;
|
||||
}
|
||||
|
||||
#refreshCommandsFrameID = -1;
|
||||
|
||||
#refreshCommands = () => {
|
||||
const commands = [
|
||||
{
|
||||
label: msg("Create a new application..."),
|
||||
action: () => navigate("/core/applications", { createWizard: true }),
|
||||
prefix: msg("Jump to", { id: "command-palette.prefix.jump-to" }),
|
||||
group: msg("Applications"),
|
||||
},
|
||||
{
|
||||
label: msg("Check the logs"),
|
||||
action: () => navigate("/events/log"),
|
||||
group: msg("Events"),
|
||||
},
|
||||
{
|
||||
label: msg("Manage users"),
|
||||
action: () => navigate("/identity/users"),
|
||||
group: msg("Users"),
|
||||
},
|
||||
...this.entries.flatMap(([, label, , children]) => [
|
||||
...(children ?? []).map(([path, childLabel]) => ({
|
||||
label: childLabel,
|
||||
prefix: msg("Jump to", { id: "command-palette.prefix.jump-to" }),
|
||||
group: label,
|
||||
action: () => {
|
||||
navigate(path!);
|
||||
},
|
||||
})),
|
||||
]),
|
||||
];
|
||||
|
||||
this.commandPalette.modal.setCommands(commands);
|
||||
};
|
||||
|
||||
public connectedCallback() {
|
||||
super.connectedCallback();
|
||||
|
||||
@@ -172,19 +121,11 @@ export class AdminInterface extends WithCapabilitiesConfig(
|
||||
public disconnectedCallback(): void {
|
||||
super.disconnectedCallback();
|
||||
|
||||
cancelAnimationFrame(this.#refreshCommandsFrameID);
|
||||
|
||||
this.#sidebarMatcher.removeEventListener("change", this.#sidebarMediaQueryListener);
|
||||
|
||||
WebsocketClient.close();
|
||||
}
|
||||
|
||||
public firstUpdated(changedProperties: PropertyValues<this>): void {
|
||||
super.firstUpdated(changedProperties);
|
||||
|
||||
this.#refreshCommandsFrameID = requestAnimationFrame(this.#refreshCommands);
|
||||
}
|
||||
|
||||
public override updated(changedProperties: PropertyValues<this>): void {
|
||||
super.updated(changedProperties);
|
||||
|
||||
@@ -217,62 +158,62 @@ export class AdminInterface extends WithCapabilitiesConfig(
|
||||
};
|
||||
|
||||
return html`<div class="pf-c-page">
|
||||
<ak-page-navbar>
|
||||
<button
|
||||
slot="toggle"
|
||||
aria-controls="global-nav"
|
||||
class="pf-c-button pf-m-plain"
|
||||
@click=${this.toggleSidebar}
|
||||
aria-label=${this.sidebarOpen
|
||||
? msg("Collapse navigation")
|
||||
: msg("Expand navigation")}
|
||||
aria-expanded=${this.sidebarOpen ? "true" : "false"}
|
||||
>
|
||||
<i aria-hidden="true" class="fas fa-bars"></i>
|
||||
</button>
|
||||
<ak-page-navbar>
|
||||
<button
|
||||
slot="toggle"
|
||||
aria-controls="global-nav"
|
||||
class="pf-c-button pf-m-plain"
|
||||
@click=${this.toggleSidebar}
|
||||
aria-label=${this.sidebarOpen
|
||||
? msg("Collapse navigation")
|
||||
: msg("Expand navigation")}
|
||||
aria-expanded=${this.sidebarOpen ? "true" : "false"}
|
||||
>
|
||||
<i aria-hidden="true" class="fas fa-bars"></i>
|
||||
</button>
|
||||
|
||||
<ak-version-banner></ak-version-banner>
|
||||
<ak-enterprise-status interface="admin"></ak-enterprise-status>
|
||||
</ak-page-navbar>
|
||||
<ak-version-banner></ak-version-banner>
|
||||
<ak-enterprise-status interface="admin"></ak-enterprise-status>
|
||||
</ak-page-navbar>
|
||||
|
||||
<ak-sidebar ?hidden=${!this.sidebarOpen} class="${classMap(sidebarClasses)}"
|
||||
>${renderSidebarItems(this.entries)}
|
||||
${this.can(CapabilitiesEnum.IsEnterprise)
|
||||
? renderSidebarItems(createAdminSidebarEnterpriseEntries())
|
||||
: nothing}
|
||||
</ak-sidebar>
|
||||
<ak-sidebar ?hidden=${!this.sidebarOpen} class="${classMap(sidebarClasses)}"
|
||||
>${renderSidebarItems(createAdminSidebarEntries())}
|
||||
${this.can(CapabilitiesEnum.IsEnterprise)
|
||||
? renderSidebarItems(createAdminSidebarEnterpriseEntries())
|
||||
: nothing}
|
||||
</ak-sidebar>
|
||||
|
||||
<div class="pf-c-page__drawer">
|
||||
<div class="pf-c-drawer ${classMap(drawerClasses)}">
|
||||
<div class="pf-c-drawer__main">
|
||||
<div class="pf-c-drawer__content">
|
||||
<div class="pf-c-drawer__body">
|
||||
<ak-router-outlet
|
||||
role="presentation"
|
||||
class="pf-c-page__main"
|
||||
tabindex="-1"
|
||||
id="main-content"
|
||||
default-url="/administration/overview"
|
||||
.routes=${ROUTES}
|
||||
@ak-route-change=${this.routeChangeListener}
|
||||
>
|
||||
</ak-router-outlet>
|
||||
</div>
|
||||
<div class="pf-c-page__drawer">
|
||||
<div class="pf-c-drawer ${classMap(drawerClasses)}">
|
||||
<div class="pf-c-drawer__main">
|
||||
<div class="pf-c-drawer__content">
|
||||
<div class="pf-c-drawer__body">
|
||||
<ak-router-outlet
|
||||
role="presentation"
|
||||
class="pf-c-page__main"
|
||||
tabindex="-1"
|
||||
id="main-content"
|
||||
default-url="/administration/overview"
|
||||
.routes=${ROUTES}
|
||||
@ak-route-change=${this.routeChangeListener}
|
||||
>
|
||||
</ak-router-outlet>
|
||||
</div>
|
||||
${renderNotificationDrawerPanel(this.drawer)}
|
||||
</div>
|
||||
${renderNotificationDrawerPanel(this.drawer)}
|
||||
<ak-about-modal></ak-about-modal>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="pf-c-page__sidebar-backdrop"
|
||||
aria-label=${this.sidebarOpen ? msg("Close sidebar") : msg("Open sidebar")}
|
||||
@click=${this.toggleSidebar}
|
||||
role="button"
|
||||
tabindex="0"
|
||||
></div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="pf-c-page__sidebar-backdrop"
|
||||
aria-label=${this.sidebarOpen ? msg("Close sidebar") : msg("Open sidebar")}
|
||||
@click=${this.toggleSidebar}
|
||||
role="button"
|
||||
tabindex="0"
|
||||
></div>
|
||||
</div>
|
||||
${this.commandPalette}`;
|
||||
</div>`;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
@@ -293,12 +293,6 @@ export class AdminSettingsForm extends Form<SettingsRequest> {
|
||||
)}
|
||||
>
|
||||
</ak-switch-input>
|
||||
<ak-switch-input
|
||||
name="flags.flowsContinuousLogin"
|
||||
?checked=${settings?.flags.flowsContinuousLogin ?? false}
|
||||
label=${msg("Continuous Login")}
|
||||
>
|
||||
</ak-switch-input>
|
||||
</div>
|
||||
</ak-form-group>
|
||||
`;
|
||||
|
||||
@@ -40,9 +40,6 @@ import { ifDefined } from "lit/directives/if-defined.js";
|
||||
export class ApplicationForm extends WithCapabilitiesConfig(ModelForm<Application, string>) {
|
||||
#api = new CoreApi(DEFAULT_CONFIG);
|
||||
|
||||
protected entitySingular = msg("Application");
|
||||
protected entityPlural = msg("Applications");
|
||||
|
||||
protected override async loadInstance(pk: string): Promise<Application> {
|
||||
const app = await this.#api.coreApplicationsRetrieve({
|
||||
slug: pk,
|
||||
|
||||
@@ -5,29 +5,24 @@ import "#elements/ak-mdx/ak-mdx";
|
||||
import "#elements/buttons/SpinnerButton/ak-spinner-button";
|
||||
import "#elements/forms/DeleteBulkForm";
|
||||
import "#elements/forms/ModalForm";
|
||||
import "#elements/modals/ak-modal";
|
||||
import "@patternfly/elements/pf-tooltip/pf-tooltip.js";
|
||||
import "./ApplicationWizardHint.js";
|
||||
|
||||
import { DEFAULT_CONFIG } from "#common/api/config";
|
||||
|
||||
import { WithBrandConfig } from "#elements/mixins/branding";
|
||||
import { asInvoker, renderModal } from "#elements/modals/utils";
|
||||
import { getURLParam } from "#elements/router/RouteMatch";
|
||||
import { PaginatedResponse, TableColumn } from "#elements/table/Table";
|
||||
import { TablePage } from "#elements/table/TablePage";
|
||||
import { SlottedTemplateResult } from "#elements/types";
|
||||
import { ifPresent } from "#elements/utils/attributes";
|
||||
|
||||
import { ApplicationForm } from "#admin/applications/ApplicationForm";
|
||||
import { AkApplicationWizard } from "#admin/applications/wizard/ak-application-wizard";
|
||||
|
||||
import { Application, CoreApi, PoliciesApi } from "@goauthentik/api";
|
||||
|
||||
import MDApplication from "~docs/add-secure-apps/applications/index.md";
|
||||
|
||||
import { msg, str } from "@lit/localize";
|
||||
import { css, CSSResult, html, nothing, PropertyValues, TemplateResult } from "lit";
|
||||
import { css, CSSResult, html, nothing, TemplateResult } from "lit";
|
||||
import { customElement, property } from "lit/decorators.js";
|
||||
|
||||
import PFCard from "@patternfly/patternfly/components/Card/card.css";
|
||||
@@ -74,26 +69,6 @@ export class ApplicationListPage extends WithBrandConfig(TablePage<Application>)
|
||||
|
||||
static styles: CSSResult[] = [...TablePage.styles, PFCard, applicationListStyle];
|
||||
|
||||
public override firstUpdated(changed: PropertyValues<this>): void {
|
||||
super.firstUpdated(changed);
|
||||
|
||||
if (getURLParam("createWizard", false)) {
|
||||
this.#openCreateWizard();
|
||||
} else if (getURLParam("createForm", false)) {
|
||||
this.#openCreateModal();
|
||||
}
|
||||
}
|
||||
|
||||
#openEditModal(event: Event) {
|
||||
const pk = (event.currentTarget as HTMLElement).dataset.pk;
|
||||
|
||||
renderModal(html`<ak-application-form .instancePk=${pk}></ak-application-form>`);
|
||||
}
|
||||
|
||||
#openCreateWizard = AkApplicationWizard.open;
|
||||
|
||||
#openCreateModal = asInvoker(ApplicationForm);
|
||||
|
||||
protected columns: TableColumn[] = [
|
||||
["", undefined, msg("Application Icon")],
|
||||
[msg("Name"), "name"],
|
||||
@@ -158,16 +133,21 @@ export class ApplicationListPage extends WithBrandConfig(TablePage<Application>)
|
||||
: html`-`,
|
||||
html`${item.providerObj?.verboseName || msg("-")}`,
|
||||
html`<div>
|
||||
<button
|
||||
class="pf-c-button pf-m-plain"
|
||||
aria-label=${msg(str`Edit "${item.name}"`)}
|
||||
data-pk=${item.slug}
|
||||
@click=${this.#openEditModal}
|
||||
>
|
||||
<pf-tooltip position="top" content=${msg("Edit")}>
|
||||
<i class="fas fa-edit" aria-hidden="true"></i>
|
||||
</pf-tooltip>
|
||||
</button>
|
||||
<ak-forms-modal>
|
||||
<span slot="submit">${msg("Update")}</span>
|
||||
<span slot="header">${msg("Update Application")}</span>
|
||||
<ak-application-form slot="form" .instancePk=${item.slug}>
|
||||
</ak-application-form>
|
||||
<button
|
||||
slot="trigger"
|
||||
class="pf-c-button pf-m-plain"
|
||||
aria-label=${msg(str`Edit "${item.name}"`)}
|
||||
>
|
||||
<pf-tooltip position="top" content=${msg("Edit")}>
|
||||
<i class="fas fa-edit" aria-hidden="true"></i>
|
||||
</pf-tooltip>
|
||||
</button>
|
||||
</ak-forms-modal>
|
||||
${item.launchUrl
|
||||
? html`<a
|
||||
href=${item.launchUrl}
|
||||
@@ -185,12 +165,21 @@ export class ApplicationListPage extends WithBrandConfig(TablePage<Application>)
|
||||
}
|
||||
|
||||
renderObjectCreate(): TemplateResult {
|
||||
return html`<button class="pf-c-button pf-m-primary" @click=${this.#openCreateWizard}>
|
||||
${msg("Create with Provider")}
|
||||
</button>
|
||||
<button class="pf-c-button pf-m-primary" @click=${this.#openCreateModal}>
|
||||
${msg("Create")}
|
||||
</button>`;
|
||||
return html` <ak-application-wizard .open=${getURLParam("createWizard", false)}>
|
||||
<button
|
||||
slot="trigger"
|
||||
class="pf-c-button pf-m-primary"
|
||||
data-ouia-component-id="start-application-wizard"
|
||||
>
|
||||
${msg("Create with Provider")}
|
||||
</button>
|
||||
</ak-application-wizard>
|
||||
<ak-forms-modal .open=${getURLParam("createForm", false)}>
|
||||
<span slot="submit">${msg("Create")}</span>
|
||||
<span slot="header">${msg("Create Application")}</span>
|
||||
<ak-application-form slot="form"> </ak-application-form>
|
||||
<button slot="trigger" class="pf-c-button pf-m-primary">${msg("Create")}</button>
|
||||
</ak-forms-modal>`;
|
||||
}
|
||||
|
||||
renderToolbar(): TemplateResult {
|
||||
|
||||
@@ -50,10 +50,6 @@ export const providerTypePriority: ProviderModelNameEnum[] = [
|
||||
|
||||
@customElement("ak-application-wizard-main")
|
||||
export class AkApplicationWizardMain extends AKElement {
|
||||
protected createRenderRoot(): HTMLElement | DocumentFragment {
|
||||
return this;
|
||||
}
|
||||
|
||||
@state()
|
||||
wizard: ApplicationWizardState = freshWizardState();
|
||||
|
||||
|
||||
@@ -1,39 +1,28 @@
|
||||
import "./ak-application-wizard-main.js";
|
||||
|
||||
import { AKModal } from "#elements/modals/ak-modal";
|
||||
import { asInvoker } from "#elements/modals/utils";
|
||||
import { SlottedTemplateResult } from "#elements/types";
|
||||
import { ModalButton } from "#elements/buttons/ModalButton";
|
||||
import { bound } from "#elements/decorators/bound";
|
||||
|
||||
import { WizardCloseEvent } from "#components/ak-wizard/events";
|
||||
|
||||
import { css, CSSResult, html } from "lit";
|
||||
import { html } from "lit";
|
||||
import { customElement } from "lit/decorators.js";
|
||||
|
||||
@customElement("ak-application-wizard")
|
||||
export class AkApplicationWizard extends AKModal {
|
||||
public static override styles: CSSResult[] = [
|
||||
...super.styles,
|
||||
css`
|
||||
[part="main"] {
|
||||
display: block;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
public static open = asInvoker(AkApplicationWizard);
|
||||
|
||||
export class AkApplicationWizard extends ModalButton {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.addEventListener(WizardCloseEvent.eventName, this.closeListener);
|
||||
this.addEventListener(WizardCloseEvent.eventName, this.onCloseEvent);
|
||||
}
|
||||
|
||||
protected renderCloseButton(): SlottedTemplateResult {
|
||||
return null;
|
||||
@bound
|
||||
onCloseEvent(ev: WizardCloseEvent) {
|
||||
ev.stopPropagation();
|
||||
this.open = false;
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`<ak-application-wizard-main part="main"></ak-application-wizard-main>`;
|
||||
renderModalInner() {
|
||||
return html` <ak-application-wizard-main> </ak-application-wizard-main>`;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ import {
|
||||
import YAML from "yaml";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
import { css, CSSResult, html, nothing, TemplateResult } from "lit";
|
||||
import { CSSResult, html, nothing, TemplateResult } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators.js";
|
||||
|
||||
import PFDescriptionList from "@patternfly/patternfly/components/DescriptionList/description-list.css";
|
||||
@@ -56,15 +56,7 @@ export class PolicyTestForm extends Form<PolicyTestRequest> {
|
||||
return (this.result = result);
|
||||
}
|
||||
|
||||
static styles: CSSResult[] = [
|
||||
...super.styles,
|
||||
PFDescriptionList,
|
||||
css`
|
||||
.ak-policy-test-log-messages {
|
||||
width: 100%;
|
||||
}
|
||||
`,
|
||||
];
|
||||
static styles: CSSResult[] = [...super.styles, PFDescriptionList];
|
||||
|
||||
renderResult(): TemplateResult {
|
||||
return html`
|
||||
@@ -97,7 +89,7 @@ export class PolicyTestForm extends Form<PolicyTestRequest> {
|
||||
|
||||
<ak-form-element-horizontal label=${msg("Log messages")}>
|
||||
<div class="pf-c-form__group-label">
|
||||
<div class="pf-c-form__horizontal-group ak-policy-test-log-messages">
|
||||
<div class="c-form__horizontal-group">
|
||||
<dl class="pf-c-description-list pf-m-horizontal">
|
||||
<ak-log-viewer .logs=${this.result?.logMessages}></ak-log-viewer>
|
||||
</dl>
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
/**
|
||||
* Given an array or length, return logical index of the element at the given delta.
|
||||
* This is effectively a modulo loop, allowing for positive and negative deltas.
|
||||
*/
|
||||
export function torusIndex(lengthLike: number | ArrayLike<number>, delta: number): number {
|
||||
const length = typeof lengthLike === "number" ? lengthLike : lengthLike.length;
|
||||
|
||||
if (delta < 0) {
|
||||
return (length + delta) % length;
|
||||
}
|
||||
|
||||
return ((delta % length) + length) % length;
|
||||
}
|
||||
@@ -371,4 +371,21 @@ export function applyBackgroundImageProperty(
|
||||
target.style.setProperty(AKBackgroundImageProperty, `url("${nextURL.href}")`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the root interface element of the page.
|
||||
*
|
||||
* @deprecated Use context controllers to access the interface root instead.
|
||||
*/
|
||||
export function rootInterface<T extends HTMLElement = HTMLElement>(): T {
|
||||
const element = document.body.querySelector<T>("[data-test-id=interface-root]");
|
||||
|
||||
if (!element) {
|
||||
throw new Error(
|
||||
`Could not find root interface element. Was this element added before the parent interface element?`,
|
||||
);
|
||||
}
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
@@ -19,7 +19,6 @@ export const DefaultBrand = {
|
||||
policiesBufferedAccessView: false,
|
||||
flowsRefreshOthers: false,
|
||||
enterpriseAuditIncludeExpandedDiff: false,
|
||||
flowsContinuousLogin: false,
|
||||
},
|
||||
} as const satisfies CurrentBrand;
|
||||
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import "#elements/buttons/Dropdown";
|
||||
|
||||
import { torusIndex } from "#common/collections";
|
||||
import { StripHTMLTrustPolicy } from "#common/purify";
|
||||
import { rootInterface } from "#common/theme";
|
||||
|
||||
import { FormAssociated, FormAssociatedElement } from "#elements/forms/form-associated-element";
|
||||
import { PaginatedResponse } from "#elements/table/Table";
|
||||
import { ifPresent } from "#elements/utils/attributes";
|
||||
import { resolveInterface } from "#elements/utils/render-roots";
|
||||
|
||||
import Styles from "#components/ak-search-ql/styles.css";
|
||||
|
||||
@@ -34,6 +33,20 @@ export class QL extends DjangoQL {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an array or length, return logical index of the element at the given delta.
|
||||
* This is effectively a modulo loop, allowing for positive and negative deltas.
|
||||
*/
|
||||
function torusIndex(lengthLike: number | ArrayLike<number>, delta: number): number {
|
||||
const length = typeof lengthLike === "number" ? lengthLike : lengthLike.length;
|
||||
|
||||
if (delta < 0) {
|
||||
return (length + delta) % length;
|
||||
}
|
||||
|
||||
return ((delta % length) + length) % length;
|
||||
}
|
||||
|
||||
@customElement("ak-search-ql")
|
||||
export class QLSearch extends FormAssociatedElement<string> implements FormAssociated {
|
||||
static shadowRootOptions = { ...LitElement.shadowRootOptions, delegatesFocus: true };
|
||||
@@ -130,7 +143,8 @@ export class QLSearch extends FormAssociatedElement<string> implements FormAssoc
|
||||
public override connectedCallback() {
|
||||
super.connectedCallback();
|
||||
|
||||
this.#scrollContainer = resolveInterface().renderRoot.querySelector("#main-content");
|
||||
this.#scrollContainer =
|
||||
rootInterface<LitElement>().renderRoot.querySelector("#main-content");
|
||||
|
||||
this.#scrollContainer?.addEventListener("scroll", this.#updateDropdownPosition, {
|
||||
passive: true,
|
||||
|
||||
@@ -7,7 +7,7 @@ import { AKElement } from "#elements/Base";
|
||||
import { bound } from "#elements/decorators/bound";
|
||||
|
||||
import { Context, ContextProvider } from "@lit/context";
|
||||
import { css, html, nothing } from "lit";
|
||||
import { html, nothing } from "lit";
|
||||
import { customElement, property } from "lit/decorators.js";
|
||||
|
||||
/**
|
||||
@@ -25,14 +25,6 @@ import { customElement, property } from "lit/decorators.js";
|
||||
|
||||
@customElement("ak-wizard-steps")
|
||||
export class WizardStepsManager extends AKElement {
|
||||
public static styles = [
|
||||
css`
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
@property({ type: String, attribute: true })
|
||||
public currentStep?: string;
|
||||
|
||||
@@ -105,10 +97,6 @@ export class WizardStepsManager extends AKElement {
|
||||
|
||||
@bound
|
||||
onSlotchange(ev: Event) {
|
||||
console.debug(
|
||||
"Slot change detected in WizardStepsManager; recalculating slots and step labels.",
|
||||
ev,
|
||||
);
|
||||
ev.stopPropagation();
|
||||
this.findSlots();
|
||||
this.findSlot(this.currentStep);
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
import { globalAK } from "#common/global";
|
||||
import {
|
||||
createCSSResult,
|
||||
createStyleSheetUnsafe,
|
||||
setAdoptedStyleSheets,
|
||||
StyleRoot,
|
||||
} from "#common/stylesheets";
|
||||
import { createCSSResult, createStyleSheetUnsafe, StyleRoot } from "#common/stylesheets";
|
||||
import { applyUITheme, ResolvedUITheme, resolveUITheme, ThemeChangeEvent } from "#common/theme";
|
||||
|
||||
import AKBase from "#styles/authentik/base.css" with { type: "bundled-text" };
|
||||
@@ -39,22 +34,7 @@ export class AKElement extends LitElement implements AKElementProps {
|
||||
|
||||
public static styles?: Array<CSSResult | CSSModule>;
|
||||
|
||||
/**
|
||||
* Host styles are styles that are applied to the element's render root,
|
||||
* but are not scoped to the element itself.
|
||||
*
|
||||
* @remarks
|
||||
*
|
||||
* This is useful if the element is a wrapper around a third-party component
|
||||
* that requires styles to be applied to the host, such as Patternfly's modals.
|
||||
*/
|
||||
public static hostStyles?: Array<CSSResult | CSSModule>;
|
||||
|
||||
private static hostStyleSheets: CSSStyleSheet[] | null = null;
|
||||
|
||||
protected static override finalizeStyles(styles: CSSResultGroup = []): CSSResultOrNative[] {
|
||||
this.hostStyleSheets = this.hostStyles ? this.hostStyles.map(createStyleSheetUnsafe) : null;
|
||||
|
||||
const elementStyles = [
|
||||
$PFBase,
|
||||
// Route around TSC`s known-to-fail typechecking of `.flat(Infinity)`. Removes types.
|
||||
@@ -122,35 +102,10 @@ export class AKElement extends LitElement implements AKElementProps {
|
||||
|
||||
this.activeTheme = preferredColorScheme;
|
||||
}
|
||||
|
||||
const rootNode = this.getRootNode();
|
||||
|
||||
if (rootNode instanceof ShadowRoot) {
|
||||
const { hostStyleSheets } = this.constructor as typeof AKElement;
|
||||
|
||||
if (hostStyleSheets) {
|
||||
setAdoptedStyleSheets(rootNode, (currentStyleSheets) => {
|
||||
return [...currentStyleSheets, ...hostStyleSheets];
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override disconnectedCallback(): void {
|
||||
this.#themeAbortController?.abort();
|
||||
|
||||
const rootNode = this.getRootNode();
|
||||
|
||||
if (rootNode instanceof ShadowRoot) {
|
||||
const { hostStyleSheets } = this.constructor as typeof AKElement;
|
||||
|
||||
if (hostStyleSheets) {
|
||||
setAdoptedStyleSheets(rootNode, (currentStyleSheets) => {
|
||||
return currentStyleSheets.filter((sheet) => !hostStyleSheets.includes(sheet));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
super.disconnectedCallback();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
import "#elements/commands/ak-command-palette";
|
||||
|
||||
import { globalAK } from "#common/global";
|
||||
import { applyDocumentTheme, createUIThemeEffect } from "#common/theme";
|
||||
|
||||
import { AKElement } from "#elements/Base";
|
||||
import { AKCommandPalette } from "#elements/commands/ak-command-palette";
|
||||
import { BrandingContextController } from "#elements/controllers/BrandContextController";
|
||||
import { ConfigContextController } from "#elements/controllers/ConfigContextController";
|
||||
import { ContextControllerRegistry } from "#elements/controllers/ContextControllerRegistry";
|
||||
@@ -14,8 +11,6 @@ import { ReactiveContextController } from "#elements/controllers/ReactiveContext
|
||||
import { BrandingContext } from "#elements/mixins/branding";
|
||||
import { AuthentikConfigContext } from "#elements/mixins/config";
|
||||
|
||||
import { ConsoleLogger, Logger } from "#logger/browser";
|
||||
|
||||
import { Context, ContextType } from "@lit/context";
|
||||
import { ReactiveController } from "lit";
|
||||
|
||||
@@ -23,8 +18,6 @@ import { ReactiveController } from "lit";
|
||||
* The base interface element for the application.
|
||||
*/
|
||||
export abstract class Interface extends AKElement {
|
||||
protected logger: Logger;
|
||||
|
||||
/**
|
||||
* Private map of controllers to their registry keys.
|
||||
*
|
||||
@@ -33,17 +26,9 @@ export abstract class Interface extends AKElement {
|
||||
*/
|
||||
#registryKeys = new WeakMap<ReactiveController, ContextType<Context<unknown, unknown>>>();
|
||||
|
||||
/**
|
||||
* The command palette instance. This must be inserted by the extending class,
|
||||
* as the palette may depend on a context that is not available at the time of this class's construction.
|
||||
*/
|
||||
public readonly commandPalette: AKCommandPalette;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.logger = ConsoleLogger.prefix(this.tagName.toLowerCase());
|
||||
|
||||
const { config, brand, locale } = globalAK();
|
||||
|
||||
createUIThemeEffect(applyDocumentTheme);
|
||||
@@ -53,8 +38,7 @@ export abstract class Interface extends AKElement {
|
||||
this.addController(new BrandingContextController(this, brand), BrandingContext);
|
||||
this.addController(new ModalOrchestrationController());
|
||||
|
||||
this.id = "interface-root";
|
||||
this.commandPalette = this.ownerDocument.createElement("ak-command-palette");
|
||||
this.dataset.testId = "interface-root";
|
||||
}
|
||||
|
||||
public override addController(
|
||||
|
||||
@@ -1,21 +1,13 @@
|
||||
import { CURRENT_CLASS, EVENT_REFRESH } from "#common/constants";
|
||||
|
||||
import { AKElement } from "#elements/Base";
|
||||
import {
|
||||
CommandPaletteState,
|
||||
PaletteCommandAction,
|
||||
PaletteCommandDefinition,
|
||||
} from "#elements/commands/shared";
|
||||
import { intersectionObserver } from "#elements/decorators/intersection-observer";
|
||||
import { getURLParams, updateURLParams } from "#elements/router/RouteMatch";
|
||||
import Styles from "#elements/Tabs.css" with { type: "bundled-text" };
|
||||
import { ifPresent } from "#elements/utils/attributes";
|
||||
import { isFocusable } from "#elements/utils/focus";
|
||||
|
||||
import { capitalCase } from "change-case";
|
||||
|
||||
import { msg, str } from "@lit/localize";
|
||||
import { CSSResult, html, LitElement, PropertyValues, TemplateResult } from "lit";
|
||||
import { msg } from "@lit/localize";
|
||||
import { CSSResult, html, LitElement, TemplateResult } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators.js";
|
||||
import { createRef, ref } from "lit/directives/ref.js";
|
||||
|
||||
@@ -38,59 +30,16 @@ export class Tabs extends AKElement {
|
||||
|
||||
@state()
|
||||
protected tabs: ReadonlyMap<string, Element> = new Map();
|
||||
/**
|
||||
* Whether the tab is visible in the viewport.
|
||||
*/
|
||||
@intersectionObserver()
|
||||
public visible = false;
|
||||
|
||||
#focusTargetRef = createRef<HTMLSlotElement>();
|
||||
#observer: MutationObserver | null = null;
|
||||
|
||||
#commands = new CommandPaletteState<string>();
|
||||
|
||||
#updateTabs = (): void => {
|
||||
this.tabs = new Map(
|
||||
Array.from(this.querySelectorAll(":scope > [slot^='page-']"), (element) => {
|
||||
return [element.getAttribute("slot") || "", element];
|
||||
}),
|
||||
);
|
||||
|
||||
requestAnimationFrame(this.#updateCommands);
|
||||
};
|
||||
|
||||
#updateCommands = (): void => {
|
||||
const commands: PaletteCommandDefinition<string>[] = [];
|
||||
|
||||
if (!this.visible) {
|
||||
this.#commands.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
const group = msg(str`Landmark: ${capitalCase(this.pageIdentifier)}`);
|
||||
const prefix = msg("Switch to tab", { id: "command-palette.switch-to-tab" });
|
||||
|
||||
const action: PaletteCommandAction<string> = (slotName) => {
|
||||
this.activateTab(slotName);
|
||||
};
|
||||
|
||||
for (const [slotName, tabPanel] of this.tabs) {
|
||||
if (this.activeTabName === slotName) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const label = tabPanel.getAttribute("aria-label") || slotName;
|
||||
|
||||
commands.push({
|
||||
label,
|
||||
action,
|
||||
group,
|
||||
prefix,
|
||||
details: slotName,
|
||||
});
|
||||
}
|
||||
|
||||
this.#commands.set(commands);
|
||||
};
|
||||
|
||||
public override connectedCallback(): void {
|
||||
@@ -129,18 +78,9 @@ export class Tabs extends AKElement {
|
||||
|
||||
public override disconnectedCallback(): void {
|
||||
this.#observer?.disconnect();
|
||||
this.#commands.clear();
|
||||
super.disconnectedCallback();
|
||||
}
|
||||
|
||||
public override updated(changedProperties: PropertyValues<this>): void {
|
||||
super.updated(changedProperties);
|
||||
|
||||
if (changedProperties.has("visible")) {
|
||||
this.#updateCommands();
|
||||
}
|
||||
}
|
||||
|
||||
public findActiveTabPanel(): Element | null {
|
||||
return this.querySelector(`[slot='${this.activeTabName}']`);
|
||||
}
|
||||
|
||||
@@ -1,180 +0,0 @@
|
||||
:host {
|
||||
--ak-c-command-palette--PaddingBlock: calc(1em * var(--pf-global--LineHeight--sm));
|
||||
--ak-c-command-palette--PaddingInline: calc(
|
||||
2 * var(--pf-global--spacer--form-element) + var(--pf-global--spacer--sm)
|
||||
);
|
||||
|
||||
--ak-c-command-palette--Translucency: 25%;
|
||||
|
||||
--ak-c-command-palette__group--BorderColor: var(
|
||||
--pf-global--BackgroundColor--dark-transparent-200
|
||||
);
|
||||
|
||||
--ak-fieldset--BorderColor: var(--pf-global--palette--purple-500);
|
||||
|
||||
--ak-c-command-palette__item--BackgroundColor: transparent;
|
||||
--ak-c-command-palette__item--Color: var(--pf-global--palette--purple-700);
|
||||
|
||||
--ak-c-command-palette__item--Color: var(--pf-global--palette--blue-50);
|
||||
--ak-c-command-palette__item--selected--BackgroundColor: var(--pf-global--palette--blue-400);
|
||||
--ak-c-command-palette__item--hover--BackgroundColor: var(--pf-global--palette--purple-600);
|
||||
--ak-c-command-palette__item--hover-selected--BackgroundColor: var(
|
||||
--pf-global--palette--blue-300
|
||||
);
|
||||
|
||||
--pf-global--Color--100: var(--pf-global--palette--purple-50);
|
||||
|
||||
@media (prefers-reduced-transparency: reduce) {
|
||||
--ak-c-command-palette--Translucency: 0%;
|
||||
}
|
||||
will-change: opacity, text-decoration-color, background-color, color;
|
||||
transform: translate3d(0, 0, 0); /* Fixes rendering artifacts. */
|
||||
}
|
||||
|
||||
:host {
|
||||
display: block;
|
||||
min-height: min(10rem, 20dvh);
|
||||
padding: var(--pf-global--spacer--sm);
|
||||
padding-block-end: var(--pf-global--spacer--md);
|
||||
color: var(--pf-global--Color--100);
|
||||
}
|
||||
|
||||
[part="command-field"] {
|
||||
border-bottom: 0.5px solid var(--pf-global--palette--black-600);
|
||||
margin-block-end: var(--pf-global--spacer--xs);
|
||||
padding-block-end: var(--pf-global--spacer--xs);
|
||||
margin-inline: var(--pf-global--spacer--sm);
|
||||
}
|
||||
|
||||
#command-input {
|
||||
background: transparent;
|
||||
display: block;
|
||||
width: 100%;
|
||||
font-size: var(--pf-global--FontSize--2xl);
|
||||
padding-block: var(--pf-global--spacer--form-element);
|
||||
padding-inline-start: calc(var(--ak-c-command-palette--PaddingInline) * 2);
|
||||
padding-inline-end: var(--ak-c-command-palette--PaddingInline);
|
||||
border: none;
|
||||
|
||||
outline: none;
|
||||
|
||||
&::placeholder {
|
||||
color: var(--pf-global--palette--purple-100);
|
||||
font-weight: 100;
|
||||
font-family: var(--pf-global--FontFamily--heading--sans-serif);
|
||||
}
|
||||
}
|
||||
|
||||
[part="results-group"] {
|
||||
border-width: 0.5px;
|
||||
padding-inline: 0 !important;
|
||||
padding-block-end: 0 !important;
|
||||
|
||||
legend {
|
||||
padding-block: var(--pf-global--spacer--xs) !important;
|
||||
}
|
||||
|
||||
&:not(:first-child) {
|
||||
margin-block-start: var(--pf-global--spacer--md);
|
||||
}
|
||||
}
|
||||
|
||||
[part="results"] {
|
||||
overflow-y: auto;
|
||||
max-height: calc(100dvh - (1.75 * var(--ak-c-modal--MarginBlockStart)));
|
||||
}
|
||||
|
||||
[part="results-list"] {
|
||||
margin-block-start: calc(var(--pf-global--spacer--sm) * -1);
|
||||
}
|
||||
|
||||
[part="command-item-label"] {
|
||||
grid-row: label;
|
||||
font-family: var(--pf-global--FontFamily--heading--sans-serif);
|
||||
}
|
||||
|
||||
[part="command-item-prefix"] {
|
||||
grid-area: prefix;
|
||||
font-variant: all-small-caps;
|
||||
font-weight: bold;
|
||||
color: var(--pf-global--palette--gold-200);
|
||||
}
|
||||
|
||||
[part="command-item-suffix"] {
|
||||
grid-area: suffix;
|
||||
font-variant: all-small-caps;
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
color: var(--pf-global--palette--gold-200);
|
||||
justify-content: end;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
[part="command-item-description"] {
|
||||
grid-area: description;
|
||||
}
|
||||
|
||||
[part="group-heading"] {
|
||||
margin-block: var(--pf-global--spacer--sm);
|
||||
margin-inline: var(--pf-global--spacer--sm);
|
||||
}
|
||||
|
||||
.command-item {
|
||||
&.selected {
|
||||
--ak-c-command-palette__item--BackgroundColor: var(
|
||||
--ak-c-command-palette__item--selected--BackgroundColor
|
||||
);
|
||||
--ak-c-command-palette__item--hover--BackgroundColor: var(
|
||||
--ak-c-command-palette__item--hover-selected--BackgroundColor
|
||||
);
|
||||
--ak-c-command-palette__item--AccentColor: var(--ak-accent);
|
||||
}
|
||||
}
|
||||
|
||||
[part="command-button"] {
|
||||
display: grid;
|
||||
grid-template-areas:
|
||||
"prefix prefix prefix suffix"
|
||||
"icon label label suffix"
|
||||
"icon description description suffix";
|
||||
width: 100%;
|
||||
background: transparent;
|
||||
padding: var(--pf-global--spacer--md);
|
||||
border: none;
|
||||
column-gap: var(--pf-global--spacer--sm);
|
||||
border-inline-start: 3px solid var(--ak-c-command-palette__item--AccentColor, transparent);
|
||||
background-color: color-mix(
|
||||
var(--ak-c-command-palette__item--BackgroundColor),
|
||||
transparent var(--ak-c-command-palette--Translucency)
|
||||
);
|
||||
width: 100%;
|
||||
border-radius: 0;
|
||||
text-align: start;
|
||||
color: var(--ak-c-command-palette__item--Color);
|
||||
|
||||
&:hover {
|
||||
background-color: color-mix(
|
||||
var(--ak-c-command-palette__item--hover--BackgroundColor),
|
||||
transparent var(--ak-c-command-palette--Translucency)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
[part="input-label"] {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
inset-block-start: var(--ak-c-command-palette--PaddingBlock);
|
||||
inset-inline-start: var(--ak-c-command-palette--PaddingInline);
|
||||
z-index: 1;
|
||||
pointer-events: none;
|
||||
|
||||
z-index: 1;
|
||||
pointer-events: none;
|
||||
|
||||
.icon {
|
||||
display: block;
|
||||
height: var(--pf-global--icon--FontSize--lg);
|
||||
fill: currentColor;
|
||||
stroke: currentColor;
|
||||
}
|
||||
}
|
||||
@@ -1,540 +0,0 @@
|
||||
import "#elements/EmptyState";
|
||||
|
||||
import { torusIndex } from "#common/collections";
|
||||
import { PFSize } from "#common/enums";
|
||||
|
||||
import Styles from "#elements/commands/ak-command-palette-modal.css";
|
||||
import { AKCommandChangeEvent } from "#elements/commands/events";
|
||||
import { PaletteCommandDefinition } from "#elements/commands/shared";
|
||||
import { listen } from "#elements/decorators/listen";
|
||||
import { AKModal } from "#elements/modals/ak-modal";
|
||||
import { asInvoker } from "#elements/modals/utils";
|
||||
import { SlottedTemplateResult } from "#elements/types";
|
||||
import { FocusTarget } from "#elements/utils/focus";
|
||||
|
||||
import { AboutModal } from "#admin/AdminInterface/AboutModal";
|
||||
|
||||
import Fuse from "fuse.js";
|
||||
|
||||
import { msg, str } from "@lit/localize";
|
||||
import { html, PropertyValues } from "lit";
|
||||
import { guard } from "lit-html/directives/guard.js";
|
||||
import { createRef, ref } from "lit-html/directives/ref.js";
|
||||
import { customElement, property, state } from "lit/decorators.js";
|
||||
import { repeat } from "lit/directives/repeat.js";
|
||||
|
||||
function openDocsSearch(query: string) {
|
||||
const url = new URL("/search", import.meta.env.AK_DOCS_URL);
|
||||
url.searchParams.set("q", query);
|
||||
|
||||
window.open(url, "_ak_docs", "noopener,noreferrer");
|
||||
}
|
||||
|
||||
function createCommonCommands(): PaletteCommandDefinition<unknown>[] {
|
||||
return [
|
||||
{
|
||||
label: msg("Integrations"),
|
||||
prefix: msg("View", { id: "command-palette.prefix.view" }),
|
||||
action: () => window.open("https://integrations.goauthentik.io/", "_blank"),
|
||||
group: msg("Documentation"),
|
||||
},
|
||||
{
|
||||
label: msg("Release notes"),
|
||||
action: () => window.open(import.meta.env.AK_DOCS_RELEASE_NOTES_URL, "_blank"),
|
||||
prefix: msg("View", { id: "command-palette.prefix.view" }),
|
||||
suffix: msg(str`New in ${import.meta.env.AK_VERSION}`, {
|
||||
id: "command-palette.suffix.new-in",
|
||||
}),
|
||||
group: msg("authentik"),
|
||||
},
|
||||
{
|
||||
label: msg("About authentik"),
|
||||
action: AboutModal.open,
|
||||
prefix: msg("View", { id: "command-palette.prefix.view" }),
|
||||
group: msg("authentik"),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
@customElement("ak-command-palette-modal")
|
||||
export class AKCommandPaletteModal extends AKModal {
|
||||
static openOnConnect = false;
|
||||
|
||||
static styles = [...AKModal.styles, Styles];
|
||||
|
||||
static open = asInvoker(AKCommandPaletteModal);
|
||||
|
||||
protected autofocusTarget = new FocusTarget<HTMLInputElement>();
|
||||
protected formRef = createRef<HTMLFormElement>();
|
||||
|
||||
#scrollCommandFrameID = -1;
|
||||
#autoFocusFrameID = -1;
|
||||
|
||||
// TODO: Fix form references.
|
||||
declare form: null;
|
||||
|
||||
protected get value() {
|
||||
return this.autofocusTarget.target?.value.trim() || "";
|
||||
}
|
||||
|
||||
protected fuse = new Fuse<PaletteCommandDefinition>([], {
|
||||
keys: [
|
||||
// ---
|
||||
{ name: "label", weight: 3 },
|
||||
"description",
|
||||
"group",
|
||||
{
|
||||
name: "keywords",
|
||||
getFn: (command) => command.keywords?.join(" ") || "",
|
||||
weight: 2,
|
||||
},
|
||||
],
|
||||
findAllMatches: true,
|
||||
includeScore: true,
|
||||
shouldSort: true,
|
||||
ignoreFieldNorm: true,
|
||||
useExtendedSearch: true,
|
||||
threshold: 0.3,
|
||||
});
|
||||
|
||||
//#region Public Properties
|
||||
|
||||
@property({ type: Number, attribute: false, useDefault: true })
|
||||
public selectionIndex = 1;
|
||||
|
||||
public get selectedCommand(): PaletteCommandDefinition | null {
|
||||
if (this.selectionIndex === -1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.filteredCommands[this.selectionIndex] || null;
|
||||
}
|
||||
|
||||
@property({ type: Number, attribute: false, useDefault: true })
|
||||
public maxCount = 20;
|
||||
|
||||
@property({ type: Array, attribute: false, useDefault: true })
|
||||
public filteredCommands: readonly PaletteCommandDefinition<unknown>[] = [];
|
||||
|
||||
/**
|
||||
* A map of the currently filtered commands to their index in the flattened commands array,
|
||||
* used to normalize the selection index while rendering groups.
|
||||
*/
|
||||
#filteredCommandsIndex = new Map<PaletteCommandDefinition<unknown>, number>();
|
||||
/**
|
||||
* A flattened array of all commands in the command palette, used for filtering and selection.
|
||||
*/
|
||||
#flattenedCommands: PaletteCommandDefinition<unknown>[] = [];
|
||||
|
||||
@state()
|
||||
public commands = new Set<readonly PaletteCommandDefinition<unknown>[]>();
|
||||
|
||||
public override size = PFSize.Medium;
|
||||
|
||||
public override focus = this.autofocusTarget.focus;
|
||||
|
||||
//#region Public Methods
|
||||
|
||||
public setCommands = (
|
||||
commands?: readonly PaletteCommandDefinition<unknown>[] | null,
|
||||
previousCommands?: readonly PaletteCommandDefinition<unknown>[] | null,
|
||||
) => {
|
||||
if (previousCommands) {
|
||||
this.commands.delete(previousCommands);
|
||||
}
|
||||
|
||||
if (commands) {
|
||||
this.commands.add(commands);
|
||||
this.#flattenedCommands = Array.from(this.commands).reverse().flat();
|
||||
}
|
||||
|
||||
const { target } = this.autofocusTarget;
|
||||
|
||||
if (target) {
|
||||
target.value = "";
|
||||
}
|
||||
|
||||
if (this.open && (commands || previousCommands)) {
|
||||
this.requestUpdate("commands");
|
||||
}
|
||||
};
|
||||
|
||||
public scrollCommandIntoView = () => {
|
||||
const id = `command-${this.selectionIndex}`;
|
||||
|
||||
const element = this.renderRoot.querySelector(`#${id}`);
|
||||
|
||||
if (!element) {
|
||||
return;
|
||||
}
|
||||
|
||||
const legend = element.closest("fieldset")?.querySelector("legend");
|
||||
|
||||
legend?.scrollIntoView({
|
||||
behavior: "auto",
|
||||
block: "nearest",
|
||||
});
|
||||
|
||||
element.scrollIntoView({
|
||||
behavior: "auto",
|
||||
block: "nearest",
|
||||
});
|
||||
};
|
||||
|
||||
//#region Lifecycle
|
||||
|
||||
public override connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
this.addEventListener("focus", this.autofocusTarget.toEventListener());
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
this.setCommands([
|
||||
{
|
||||
label: msg("Documentation"),
|
||||
action: () => openDocsSearch(this.value),
|
||||
keywords: [msg("Docs"), msg("Readme"), msg("Help")],
|
||||
prefix: msg("View", { id: "command-palette.prefix.view" }),
|
||||
suffix: msg("New Tab", { id: "command-palette.suffix.view-docs" }),
|
||||
group: msg("Documentation"),
|
||||
},
|
||||
...createCommonCommands(),
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
public override updated(changedProperties: PropertyValues<this>): void {
|
||||
super.updated(changedProperties);
|
||||
|
||||
if (changedProperties.has("commands")) {
|
||||
this.fuse.setCollection(this.#flattenedCommands);
|
||||
this.selectionIndex = 0;
|
||||
this.synchronizeFilteredCommands();
|
||||
}
|
||||
|
||||
if (changedProperties.has("open") && this.open) {
|
||||
cancelAnimationFrame(this.#autoFocusFrameID);
|
||||
|
||||
this.#autoFocusFrameID = requestAnimationFrame(() => {
|
||||
this.autofocusTarget.focus();
|
||||
this.autofocusTarget.target?.select();
|
||||
});
|
||||
}
|
||||
|
||||
if (changedProperties.has("selectionIndex")) {
|
||||
cancelAnimationFrame(this.#scrollCommandFrameID);
|
||||
this.#scrollCommandFrameID = requestAnimationFrame(this.scrollCommandIntoView);
|
||||
}
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
public synchronizeFilteredCommands = () => {
|
||||
cancelAnimationFrame(this.#scrollCommandFrameID);
|
||||
|
||||
this.selectionIndex = 0;
|
||||
|
||||
const { value } = this;
|
||||
|
||||
if (value) {
|
||||
const filteredCommands = this.fuse
|
||||
.search(value, {
|
||||
limit: this.maxCount,
|
||||
})
|
||||
.map((result) => result.item);
|
||||
|
||||
filteredCommands.push({
|
||||
group: msg("Documentation"),
|
||||
label: msg(str`Search the docs for "${value}"`),
|
||||
prefix: msg("Open", { id: "command-palette.prefix.open" }),
|
||||
suffix: msg("New Tab", { id: "command-palette.suffix.view-docs" }),
|
||||
action: () => openDocsSearch(value),
|
||||
});
|
||||
|
||||
this.filteredCommands = filteredCommands;
|
||||
} else {
|
||||
this.filteredCommands = this.#flattenedCommands.slice(0, this.maxCount);
|
||||
}
|
||||
|
||||
this.#filteredCommandsIndex = new Map(
|
||||
this.filteredCommands.map((command, index) => [command, index]),
|
||||
);
|
||||
|
||||
this.#scrollCommandFrameID = requestAnimationFrame(this.scrollCommandIntoView);
|
||||
};
|
||||
|
||||
public submit() {
|
||||
const form = this.formRef.value;
|
||||
|
||||
if (!form) return;
|
||||
|
||||
const submitEvent = new SubmitEvent("submit", {
|
||||
submitter: this,
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
cancelable: true,
|
||||
});
|
||||
|
||||
form.dispatchEvent(submitEvent);
|
||||
}
|
||||
|
||||
#submitListener = (event: SubmitEvent) => {
|
||||
let commandIndex: number;
|
||||
if (event.submitter instanceof HTMLElement && event.submitter.dataset.index) {
|
||||
commandIndex = parseInt(event.submitter.dataset.index, 10);
|
||||
} else {
|
||||
commandIndex = this.selectionIndex;
|
||||
}
|
||||
|
||||
const command = this.filteredCommands[commandIndex];
|
||||
|
||||
if (!command) return;
|
||||
|
||||
this.open = false;
|
||||
command.action(command.details || null);
|
||||
};
|
||||
|
||||
#commandClickListener = (event: MouseEvent) => {
|
||||
const target = event.currentTarget as HTMLElement;
|
||||
const index = parseInt(target.dataset.index!, 10);
|
||||
|
||||
if (isNaN(index)) return;
|
||||
|
||||
this.selectionIndex = index;
|
||||
};
|
||||
|
||||
//#region Event Listeners
|
||||
|
||||
@listen(AKCommandChangeEvent, {
|
||||
target: this,
|
||||
})
|
||||
protected commandChangeListener = (event: AKCommandChangeEvent) => {
|
||||
this.setCommands(event.commands, event.previousCommands);
|
||||
};
|
||||
|
||||
#keydownListener = (event: KeyboardEvent) => {
|
||||
const visibleCommandsCount = this.filteredCommands.length;
|
||||
|
||||
if (!this.open) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.key === "Enter" && this.form) {
|
||||
this.submit();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!visibleCommandsCount) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event.key) {
|
||||
case "ArrowDown":
|
||||
event.preventDefault();
|
||||
|
||||
this.selectionIndex = torusIndex(visibleCommandsCount, this.selectionIndex + 1);
|
||||
return;
|
||||
|
||||
case "ArrowUp":
|
||||
event.preventDefault();
|
||||
this.selectionIndex = torusIndex(visibleCommandsCount, this.selectionIndex - 1);
|
||||
|
||||
return;
|
||||
|
||||
case "Enter":
|
||||
event.preventDefault();
|
||||
this.submit();
|
||||
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
#focusListener = () => {
|
||||
this.selectionIndex = this.selectionIndex === -1 ? 0 : this.selectionIndex;
|
||||
|
||||
this.synchronizeFilteredCommands();
|
||||
};
|
||||
|
||||
//#region Rendering
|
||||
|
||||
protected override renderCloseButton(): SlottedTemplateResult {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected renderCommands() {
|
||||
const { selectionIndex, value, filteredCommands } = this;
|
||||
|
||||
return guard([filteredCommands, selectionIndex, value], () => {
|
||||
const grouped = Object.groupBy(filteredCommands, (command) => command.group || "");
|
||||
|
||||
return html`<div
|
||||
part="results"
|
||||
role="listbox"
|
||||
id="command-suggestions"
|
||||
aria-label=${msg("Query suggestions")}
|
||||
>
|
||||
${repeat(
|
||||
Object.entries(grouped),
|
||||
(_, groupIdx) => `group-${groupIdx}`,
|
||||
([groupLabel, commands], groupIdx) => html`
|
||||
<fieldset part="results-group">
|
||||
<legend
|
||||
class="pf-c-content ${!groupLabel
|
||||
? "sr-only more-contrast-only"
|
||||
: ""}"
|
||||
>
|
||||
<h2>${groupLabel || msg("Ungrouped")}</h2>
|
||||
</legend>
|
||||
|
||||
<ul
|
||||
part="results-list"
|
||||
data-group-index=${groupIdx}
|
||||
role="presentation"
|
||||
>
|
||||
${repeat(
|
||||
commands!,
|
||||
(_, commandIdx) => `group-${groupIdx}-command-${commandIdx}`,
|
||||
(command) => {
|
||||
const absoluteIdx =
|
||||
this.#filteredCommandsIndex.get(command) ?? -1;
|
||||
const { label, prefix, suffix, description } = command;
|
||||
|
||||
const selected = selectionIndex === absoluteIdx;
|
||||
return html`<li
|
||||
role="presentation"
|
||||
id="command-${absoluteIdx}"
|
||||
aria-selected=${selected ? "true" : "false"}
|
||||
class="command-item ${selected ? "selected" : ""}"
|
||||
part="command-item"
|
||||
>
|
||||
<button
|
||||
part="command-button"
|
||||
type="submit"
|
||||
formmethod="dialog"
|
||||
data-index=${absoluteIdx}
|
||||
@click=${this.#commandClickListener}
|
||||
aria-labelledby="command-${absoluteIdx}-label"
|
||||
aria-describedby="command-${absoluteIdx}-description"
|
||||
>
|
||||
${prefix
|
||||
? html`<div
|
||||
part="command-item-prefix"
|
||||
id="command-${absoluteIdx}-prefix"
|
||||
>
|
||||
${prefix}
|
||||
</div>`
|
||||
: null}
|
||||
<div
|
||||
part="command-item-label"
|
||||
id="command-${absoluteIdx}-label"
|
||||
>
|
||||
${label}
|
||||
</div>
|
||||
${suffix
|
||||
? html`<div
|
||||
part="command-item-suffix"
|
||||
id="command-${absoluteIdx}-suffix"
|
||||
>
|
||||
${suffix}
|
||||
</div>`
|
||||
: null}
|
||||
<div
|
||||
part="command-item-description"
|
||||
id="command-${absoluteIdx}-description"
|
||||
>
|
||||
${description || ""}
|
||||
</div>
|
||||
</button>
|
||||
</li>`;
|
||||
},
|
||||
)}
|
||||
</ul>
|
||||
</fieldset>
|
||||
`,
|
||||
)}
|
||||
</div>`;
|
||||
});
|
||||
}
|
||||
|
||||
protected override render() {
|
||||
const { value, filteredCommands } = this;
|
||||
|
||||
return html`<form
|
||||
${ref(this.formRef)}
|
||||
method="dialog"
|
||||
class="command-palette-form"
|
||||
@submit=${this.#submitListener}
|
||||
>
|
||||
<div
|
||||
class="input"
|
||||
aria-expanded=${this.open ? "true" : "false"}
|
||||
aria-autocomplete="list"
|
||||
role="combobox"
|
||||
aria-label=${msg("Command palette")}
|
||||
aria-haspopup="listbox"
|
||||
aria-activedescendant=${this.selectionIndex === -1
|
||||
? ""
|
||||
: `command-${this.selectionIndex}`}
|
||||
>
|
||||
<div part="command-field">
|
||||
<label
|
||||
part="input-label"
|
||||
for="command-input"
|
||||
@click=${this.show}
|
||||
aria-label=${msg("Type a command...", {
|
||||
id: "command-palette-placeholder",
|
||||
desc: "Label for the command palette input",
|
||||
})}
|
||||
>
|
||||
<svg
|
||||
class="icon"
|
||||
role="img"
|
||||
aria-hidden="true"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 32 32"
|
||||
>
|
||||
<path
|
||||
d="m29 27.586-7.552-7.552a11.018 11.018 0 1 0-1.414 1.414L27.586 29ZM4 13a9 9 0 1 1 9 9 9.01 9.01 0 0 1-9-9"
|
||||
/>
|
||||
</svg>
|
||||
</label>
|
||||
|
||||
<input
|
||||
${this.autofocusTarget.toRef()}
|
||||
autofocus
|
||||
id="command-input"
|
||||
name="command"
|
||||
aria-controls="command-suggestions"
|
||||
type="search"
|
||||
placeholder=${msg("What are you looking for?", {
|
||||
id: "command-palette-placeholder-extended",
|
||||
desc: "Placeholder for the command palette input",
|
||||
})}
|
||||
class="pf-c-control command-input"
|
||||
autocomplete="off"
|
||||
autocapitalize="off"
|
||||
spellcheck="false"
|
||||
@input=${this.synchronizeFilteredCommands}
|
||||
@focus=${this.#focusListener}
|
||||
@keydown=${this.#keydownListener}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
${this.renderCommands()}
|
||||
${!value && !filteredCommands.length
|
||||
? html`<ak-empty-state icon="pf-icon-module"
|
||||
><span>${msg("No commands")}</span>
|
||||
<div slot="body">${msg("No commands are currently available.")}</div>
|
||||
</ak-empty-state>`
|
||||
: null}
|
||||
</form>`;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ak-command-palette-modal": AKCommandPaletteModal;
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
ak-command-palette {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.ak-c-modal:has(ak-command-palette-modal) {
|
||||
overflow: visible;
|
||||
--ak-c-modal--MarginBlockStart: 25dvh;
|
||||
--ak-c-modal--BackgroundColor: var(--pf-global--palette--purple-700);
|
||||
--ak-c-modal--BorderColor: var(--pf-global--BackgroundColor--dark-300);
|
||||
--ak-c-modal__backdrop--active--BackdropFilter: blur(1px);
|
||||
--ak-c-modal__backdrop--active--BackgroundColor: hsla(0, 0%, 0%, 0.25);
|
||||
|
||||
--ak-c-command-palette--Translucency: 5%;
|
||||
--ak-c-command-palette--BackdropFilter: blur(4px);
|
||||
|
||||
border-radius: var(--pf-global--BorderRadius--sm);
|
||||
backdrop-filter: var(--ak-c-command-palette--BackdropFilter);
|
||||
background-color: color-mix(
|
||||
var(--ak-c-modal--BackgroundColor),
|
||||
transparent var(--ak-c-command-palette--Translucency)
|
||||
);
|
||||
|
||||
@media (prefers-reduced-transparency: reduce) {
|
||||
--ak-c-command-palette--Translucency: 0%;
|
||||
--ak-c-command-palette--BackdropFilter: blur(0);
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
import "#elements/commands/ak-command-palette-modal";
|
||||
|
||||
import HostStyles from "./ak-command-palette.css";
|
||||
|
||||
import { AKElement } from "#elements/Base";
|
||||
import { AKCommandPaletteModal } from "#elements/commands/ak-command-palette-modal";
|
||||
import { listen } from "#elements/decorators/listen";
|
||||
|
||||
import { ConsoleLogger, Logger } from "#logger/browser";
|
||||
|
||||
import { PropertyValues } from "lit";
|
||||
import { customElement } from "lit/decorators.js";
|
||||
|
||||
@customElement("ak-command-palette")
|
||||
export class AKCommandPalette extends AKElement {
|
||||
public static hostStyles = [HostStyles];
|
||||
|
||||
protected createRenderRoot(): HTMLElement | DocumentFragment {
|
||||
return this;
|
||||
}
|
||||
|
||||
protected logger: Logger;
|
||||
|
||||
public readonly dialog: HTMLDialogElement;
|
||||
public readonly modal: AKCommandPaletteModal;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.logger = ConsoleLogger.prefix(this.tagName.toLowerCase());
|
||||
|
||||
this.dialog = this.ownerDocument.createElement("dialog");
|
||||
this.modal = this.ownerDocument.createElement("ak-command-palette-modal");
|
||||
|
||||
this.dialog.appendChild(this.modal);
|
||||
}
|
||||
|
||||
@listen("keydown", { passive: false, capture: true })
|
||||
protected keydownListener = (event: KeyboardEvent) => {
|
||||
if (event.key !== "k" || (!event.metaKey && !event.ctrlKey)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.logger.info("Toggling command palette");
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
this.modal.open = !this.modal.open;
|
||||
};
|
||||
|
||||
protected firstUpdated(_changedProperties: PropertyValues): void {
|
||||
super.firstUpdated(_changedProperties);
|
||||
// DEBUGGING
|
||||
this.modal.open = true;
|
||||
}
|
||||
|
||||
protected override render() {
|
||||
return this.dialog;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ak-command-palette": AKCommandPalette;
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
import type { PaletteCommandDefinition } from "#elements/commands/shared";
|
||||
|
||||
/**
|
||||
* Event dispatched when the available commands in the command palette change.
|
||||
* This is used by the command palette to update the list of available commands.
|
||||
*/
|
||||
export class AKCommandChangeEvent<D = unknown> extends Event {
|
||||
public static readonly eventName = "ak-command-change";
|
||||
|
||||
public readonly commands: readonly PaletteCommandDefinition<D>[];
|
||||
public readonly previousCommands: readonly PaletteCommandDefinition<D>[] | null;
|
||||
|
||||
constructor(
|
||||
commands: PaletteCommandDefinition<D>[],
|
||||
previousCommands?: PaletteCommandDefinition<D>[] | null,
|
||||
) {
|
||||
super(AKCommandChangeEvent.eventName, { bubbles: true, composed: true });
|
||||
|
||||
this.commands = commands;
|
||||
this.previousCommands = previousCommands ?? null;
|
||||
}
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface WindowEventMap {
|
||||
[AKCommandChangeEvent.eventName]: AKCommandChangeEvent;
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
import { AKCommandChangeEvent } from "#elements/commands/events";
|
||||
import { SlottedTemplateResult } from "#elements/types";
|
||||
|
||||
export type PaletteCommandAction<D = unknown> = (data: D) => unknown | Promise<unknown>;
|
||||
|
||||
export interface PaletteCommandDefinition<D = unknown> {
|
||||
label: SlottedTemplateResult;
|
||||
keywords?: string[];
|
||||
prefix?: SlottedTemplateResult;
|
||||
suffix?: SlottedTemplateResult;
|
||||
description?: SlottedTemplateResult;
|
||||
group?: string;
|
||||
details?: D;
|
||||
action: PaletteCommandAction<D>;
|
||||
}
|
||||
|
||||
export interface CommandPaletteStateInit<D = unknown> {
|
||||
commands?: PaletteCommandDefinition<D>[] | null;
|
||||
target?: EventTarget;
|
||||
}
|
||||
|
||||
export class CommandPaletteState<D = unknown> {
|
||||
#commands: PaletteCommandDefinition<D>[] | null = null;
|
||||
#target: EventTarget;
|
||||
|
||||
constructor({ commands = null, target = window }: CommandPaletteStateInit<D> = {}) {
|
||||
this.#commands = commands;
|
||||
this.#target = target ?? window;
|
||||
}
|
||||
|
||||
public set(nextCommands: PaletteCommandDefinition<D>[] | null): void {
|
||||
const previousCommands = this.#commands;
|
||||
this.#commands = nextCommands;
|
||||
|
||||
this.#target.dispatchEvent(new AKCommandChangeEvent(nextCommands ?? [], previousCommands));
|
||||
}
|
||||
|
||||
public clear(): void {
|
||||
this.set(null);
|
||||
}
|
||||
}
|
||||
@@ -1,30 +1,20 @@
|
||||
import { DEFAULT_CONFIG } from "#common/api/config";
|
||||
import { type APIResult, isAPIResultReady } from "#common/api/responses";
|
||||
import { globalAK } from "#common/global";
|
||||
import { applyThemeChoice, formatColorScheme } from "#common/theme";
|
||||
import { createUIConfig, DefaultUIConfig } from "#common/ui/config";
|
||||
import { autoDetectLanguage } from "#common/ui/locale/utils";
|
||||
import { me } from "#common/users";
|
||||
|
||||
import { CommandPaletteState, PaletteCommandDefinition } from "#elements/commands/shared";
|
||||
import { ReactiveContextController } from "#elements/controllers/ReactiveContextController";
|
||||
import { AKConfigMixin, kAKConfig } from "#elements/mixins/config";
|
||||
import { kAKLocale, type LocaleMixin } from "#elements/mixins/locale";
|
||||
import {
|
||||
canAccessAdmin,
|
||||
SessionContext,
|
||||
SessionMixin,
|
||||
UIConfigContext,
|
||||
} from "#elements/mixins/session";
|
||||
import { AKDrawerChangeEvent } from "#elements/notifications/events";
|
||||
import { SessionContext, SessionMixin, UIConfigContext } from "#elements/mixins/session";
|
||||
import type { ReactiveElementHost } from "#elements/types";
|
||||
|
||||
import { CoreApi, SessionUser } from "@goauthentik/api";
|
||||
import { SessionUser } from "@goauthentik/api";
|
||||
|
||||
import { setUser } from "@sentry/browser";
|
||||
|
||||
import { ContextProvider } from "@lit/context";
|
||||
import { msg } from "@lit/localize";
|
||||
|
||||
/**
|
||||
* A controller that provides the session information to the element.
|
||||
@@ -62,128 +52,38 @@ export class SessionContextController extends ReactiveContextController<APIResul
|
||||
return me(requestInit);
|
||||
}
|
||||
|
||||
#refreshCommandsFrameID = -1;
|
||||
|
||||
#commands = new CommandPaletteState({
|
||||
target: this.host,
|
||||
});
|
||||
|
||||
protected doRefresh(session: APIResult<SessionUser>): void {
|
||||
this.context.setValue(session);
|
||||
this.host.session = session;
|
||||
|
||||
if (!isAPIResultReady(session)) return;
|
||||
if (isAPIResultReady(session)) {
|
||||
const localeHint: string | undefined = session.user.settings.locale;
|
||||
|
||||
const localeHint: string | undefined = session.user.settings.locale;
|
||||
if (localeHint) {
|
||||
const locale = autoDetectLanguage(localeHint);
|
||||
this.logger.info(`Activating user's configured locale '${locale}'`);
|
||||
this.host[kAKLocale]?.setLocale(locale);
|
||||
}
|
||||
|
||||
if (localeHint) {
|
||||
const locale = autoDetectLanguage(localeHint);
|
||||
this.logger.info(`Activating user's configured locale '${locale}'`);
|
||||
this.host[kAKLocale]?.setLocale(locale);
|
||||
const { settings = {} } = session.user || {};
|
||||
|
||||
const nextUIConfig = createUIConfig(settings);
|
||||
this.uiConfigContext.setValue(nextUIConfig);
|
||||
this.host.uiConfig = nextUIConfig;
|
||||
const colorScheme = formatColorScheme(nextUIConfig.theme.base);
|
||||
|
||||
applyThemeChoice(colorScheme, this.host.ownerDocument);
|
||||
|
||||
const config = this.host[kAKConfig];
|
||||
|
||||
if (config?.errorReporting.sendPii) {
|
||||
this.logger.info("Sentry with PII enabled.");
|
||||
|
||||
setUser({ email: session.user.email });
|
||||
}
|
||||
}
|
||||
|
||||
const { settings = {} } = session.user || {};
|
||||
|
||||
const nextUIConfig = createUIConfig(settings);
|
||||
this.uiConfigContext.setValue(nextUIConfig);
|
||||
this.host.uiConfig = nextUIConfig;
|
||||
const colorScheme = formatColorScheme(nextUIConfig.theme.base);
|
||||
|
||||
applyThemeChoice(colorScheme, this.host.ownerDocument);
|
||||
|
||||
const config = this.host[kAKConfig];
|
||||
|
||||
if (config?.errorReporting.sendPii) {
|
||||
this.logger.info("Sentry with PII enabled.");
|
||||
|
||||
setUser({ email: session.user.email });
|
||||
}
|
||||
|
||||
this.#refreshCommandsFrameID = requestAnimationFrame(this.#refreshCommands);
|
||||
}
|
||||
|
||||
#refreshCommands = (): void => {
|
||||
const session = this.context.value;
|
||||
|
||||
if (!isAPIResultReady(session)) {
|
||||
this.#commands.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
const base = globalAK().api.base;
|
||||
const group = msg("Session");
|
||||
|
||||
const commands: PaletteCommandDefinition[] = [
|
||||
{
|
||||
label: msg("Sign out"),
|
||||
suffix: msg("Reloads page", { id: "command-palette.prefix.reloads-page" }),
|
||||
keywords: [msg("Logout"), msg("Log off"), msg("Sign off")],
|
||||
group,
|
||||
action: () => {
|
||||
window.location.assign(`${base}flows/-/default/invalidation/`);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: msg("User settings"),
|
||||
prefix: msg("Navigate to", { id: "command-palette.prefix.navigate" }),
|
||||
group,
|
||||
action: () => {
|
||||
window.location.assign(`${base}if/user/#/settings`);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
const { notificationDrawer, apiDrawer } = this.host.uiConfig?.enabledFeatures ?? {};
|
||||
const drawerGroup = msg("Interface");
|
||||
|
||||
if (apiDrawer) {
|
||||
commands.push({
|
||||
label: msg("API requests drawer", {
|
||||
id: "command-palette.label.api-requests-drawer",
|
||||
}),
|
||||
prefix: msg("Toggle", { id: "command-palette.prefix.toggle" }),
|
||||
group: drawerGroup,
|
||||
action: AKDrawerChangeEvent.dispatchAPIToggle,
|
||||
});
|
||||
}
|
||||
|
||||
if (notificationDrawer) {
|
||||
commands.push({
|
||||
label: msg("Notifications drawer", {
|
||||
id: "command-palette.label.notifications-drawer",
|
||||
}),
|
||||
prefix: msg("Toggle", { id: "command-palette.prefix.toggle" }),
|
||||
group: drawerGroup,
|
||||
action: AKDrawerChangeEvent.dispatchNotificationsToggle,
|
||||
});
|
||||
}
|
||||
|
||||
if (canAccessAdmin(session.user)) {
|
||||
commands.push({
|
||||
label: msg("Admin interface"),
|
||||
prefix: msg("Navigate to", { id: "command-palette.prefix.navigate" }),
|
||||
group,
|
||||
action: () => {
|
||||
window.location.assign(`${base}if/admin/`);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (session.original) {
|
||||
commands.push({
|
||||
label: msg("Stop impersonation"),
|
||||
suffix: msg("Reloads page", { id: "command-palette.prefix.reloads-page" }),
|
||||
group,
|
||||
action: async () => {
|
||||
await new CoreApi(DEFAULT_CONFIG).coreUsersImpersonateEndRetrieve();
|
||||
window.location.reload();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
this.#commands.set(commands);
|
||||
};
|
||||
|
||||
public override hostConnected() {
|
||||
this.logger.debug("Host connected, refreshing session");
|
||||
this.refresh();
|
||||
@@ -191,7 +91,6 @@ export class SessionContextController extends ReactiveContextController<APIResul
|
||||
|
||||
public override hostDisconnected() {
|
||||
this.context.clearCallbacks();
|
||||
cancelAnimationFrame(this.#refreshCommandsFrameID);
|
||||
|
||||
super.hostDisconnected();
|
||||
}
|
||||
|
||||
@@ -239,11 +239,11 @@ export abstract class Form<T = Record<string, unknown>> extends AKElement {
|
||||
@property({ type: String })
|
||||
public autocomplete?: Exclude<AutoFillBase, "">;
|
||||
|
||||
@property({ type: String, useDefault: true })
|
||||
public headline?: string | null = null;
|
||||
@property({ type: String })
|
||||
public headline?: string;
|
||||
|
||||
@property({ type: String, attribute: "action-label", useDefault: true })
|
||||
public actionLabel: string | null = null;
|
||||
@property({ type: String, attribute: "action-label" })
|
||||
public actionLabel?: string;
|
||||
|
||||
//#endregion
|
||||
|
||||
@@ -254,9 +254,6 @@ export abstract class Form<T = Record<string, unknown>> extends AKElement {
|
||||
@state()
|
||||
protected nonFieldErrors: readonly string[] | null = null;
|
||||
|
||||
protected entitySingular?: string;
|
||||
protected entityPlural?: string;
|
||||
|
||||
static styles: CSSResult[] = [
|
||||
PFCard,
|
||||
PFButton,
|
||||
@@ -320,20 +317,6 @@ export abstract class Form<T = Record<string, unknown>> extends AKElement {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* An overridable method for formatting the form headline.
|
||||
*/
|
||||
protected formatHeadline(headline = this.headline): string {
|
||||
return headline || "";
|
||||
}
|
||||
|
||||
/**
|
||||
* An overridable method for formatting the submit button label.
|
||||
*/
|
||||
protected formatSubmitLabel(actionLabel = this.actionLabel): string {
|
||||
return actionLabel || msg("Submit");
|
||||
}
|
||||
|
||||
//#region Public methods
|
||||
|
||||
public reset(): void {
|
||||
@@ -529,22 +512,20 @@ export abstract class Form<T = Record<string, unknown>> extends AKElement {
|
||||
}
|
||||
|
||||
/**
|
||||
* An overridable method for rendering the form header.
|
||||
* An overridable method for rendering the form heading.
|
||||
*
|
||||
* @remarks
|
||||
* If this form is slotted, such as in a modal, this method will not render anything,
|
||||
* allowing the slot parent to provide the header in a more visually appropriate manner.
|
||||
* allowing the slot parent to provide the heading in a more visually appropriate manner.
|
||||
*/
|
||||
public renderHeader(force?: boolean): SlottedTemplateResult {
|
||||
const { assignedSlot, headline } = this;
|
||||
|
||||
return guard([force, assignedSlot, headline], () => {
|
||||
if (!force && assignedSlot && !assignedSlot.name) {
|
||||
protected renderHeading(): SlottedTemplateResult {
|
||||
return guard([this.assignedSlot, this.headline], () => {
|
||||
if (this.assignedSlot) {
|
||||
return nothing;
|
||||
}
|
||||
|
||||
return html`<header>
|
||||
<h1 class="pf-c-title pf-m-2xl">${this.formatHeadline(headline)}</h1>
|
||||
<h1 class="pf-c-title pf-m-2xl">${this.headline}</h1>
|
||||
</header>`;
|
||||
});
|
||||
}
|
||||
@@ -556,33 +537,23 @@ export abstract class Form<T = Record<string, unknown>> extends AKElement {
|
||||
* If this form is slotted, such as in a modal, this method will not render anything,
|
||||
* allowing the slot parent to provide the actions in a more visually appropriate manner.
|
||||
*/
|
||||
public renderActions(force?: boolean): SlottedTemplateResult {
|
||||
const { assignedSlot, actionLabel } = this;
|
||||
|
||||
return guard([force, assignedSlot, actionLabel], () => {
|
||||
if (!force && assignedSlot && !assignedSlot.name) {
|
||||
protected renderActions(): SlottedTemplateResult {
|
||||
return guard([this.assignedSlot], () => {
|
||||
if (this.assignedSlot) {
|
||||
return nothing;
|
||||
}
|
||||
|
||||
return html`<fieldset part="form-actions" class="pf-c-card__footer">
|
||||
<legend class="sr-only">${msg("Form actions")}</legend>
|
||||
<button
|
||||
type="button"
|
||||
type="submit"
|
||||
form="form"
|
||||
class="pf-c-button pf-m-primary"
|
||||
@click=${(event: Event) => {
|
||||
this.submit(
|
||||
new SubmitEvent("submit", {
|
||||
submitter: event.currentTarget as HTMLButtonElement,
|
||||
cancelable: true,
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
}),
|
||||
);
|
||||
}}
|
||||
part="submit-button"
|
||||
formmethod="dialog"
|
||||
aria-description=${msg("Submit action")}
|
||||
>
|
||||
${this.formatSubmitLabel(actionLabel)}
|
||||
${this.actionLabel || msg("Submit")}
|
||||
</button>
|
||||
</fieldset>`;
|
||||
});
|
||||
@@ -592,12 +563,8 @@ export abstract class Form<T = Record<string, unknown>> extends AKElement {
|
||||
* An overridable method for rendering the form when it is visible.
|
||||
*/
|
||||
protected renderVisible(): SlottedTemplateResult {
|
||||
return [
|
||||
this.renderHeader(),
|
||||
this.renderNonFieldErrors(),
|
||||
this.renderFormWrapper(),
|
||||
this.renderActions(),
|
||||
];
|
||||
return html`${this.renderHeading()}${this.renderNonFieldErrors()}
|
||||
${this.renderFormWrapper()}${this.renderActions()}`;
|
||||
}
|
||||
|
||||
protected override render(): SlottedTemplateResult {
|
||||
|
||||
@@ -8,7 +8,6 @@ import { SlottedTemplateResult } from "#elements/types";
|
||||
|
||||
import { ConsoleLogger } from "#logger/browser";
|
||||
|
||||
import { msg, str } from "@lit/localize";
|
||||
import { html } from "lit";
|
||||
import { property } from "lit/decorators.js";
|
||||
|
||||
@@ -110,22 +109,6 @@ export abstract class ModelForm<
|
||||
});
|
||||
};
|
||||
|
||||
protected override formatSubmitLabel(): string {
|
||||
return this.#instancePk ? msg("Update") : msg("Create");
|
||||
}
|
||||
|
||||
protected override formatHeadline(): string {
|
||||
const verb = this.#instancePk ? msg("Edit") : msg("New");
|
||||
const noun = this.entitySingular;
|
||||
|
||||
if (!noun) return verb;
|
||||
|
||||
return msg(str`${verb} ${noun}`, {
|
||||
id: "model-form.headline",
|
||||
desc: "The headline for a form that creates or updates a model instance.",
|
||||
});
|
||||
}
|
||||
|
||||
public override reset(): void {
|
||||
super.reset();
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { randomId } from "#elements/utils/randomId";
|
||||
import { resolveInterface } from "#elements/utils/render-roots";
|
||||
|
||||
import { autoUpdate, computePosition, flip, hide } from "@floating-ui/dom";
|
||||
|
||||
@@ -69,17 +68,13 @@ export class Portal extends LitElement implements IPortal {
|
||||
this.setAttribute("data-ouia-component-type", "ak-portal");
|
||||
this.setAttribute("data-ouia-component-id", this.getAttribute("id") || randomId());
|
||||
|
||||
this.dropdownContainer = this.ownerDocument.createElement("div");
|
||||
this.dropdownContainer = document.createElement("div");
|
||||
this.dropdownContainer.dataset.managedBy = "ak-portal";
|
||||
if (this.name) {
|
||||
this.dropdownContainer.dataset.managedFor = this.name;
|
||||
}
|
||||
|
||||
const interfaceElement = resolveInterface();
|
||||
const container =
|
||||
interfaceElement.renderRoot.querySelector("dialog") || this.ownerDocument.body;
|
||||
|
||||
container.append(this.dropdownContainer);
|
||||
document.body.append(this.dropdownContainer);
|
||||
|
||||
if (!this.anchor) {
|
||||
throw new Error("Tether entrance initialized incorrectly: missing anchor");
|
||||
|
||||
@@ -229,13 +229,11 @@ export class SearchSelectView extends AKElement implements ISearchSelectView {
|
||||
this.setAttribute("data-ouia-component-safe", "true");
|
||||
}
|
||||
|
||||
public override firstUpdated(changed: PropertyValues<this>) {
|
||||
super.firstUpdated(changed);
|
||||
|
||||
public override firstUpdated() {
|
||||
// Route around Lit's scheduling algorithm complaining about re-renders
|
||||
requestAnimationFrame(() => {
|
||||
window.setTimeout(() => {
|
||||
this.inputRefIsAvailable = Boolean(this.#inputRef?.value);
|
||||
});
|
||||
}, 0);
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
|
||||
@@ -1,496 +0,0 @@
|
||||
import { PFSize } from "#common/enums";
|
||||
|
||||
import { AKElement } from "#elements/Base";
|
||||
import { AKFormSubmittedEvent } from "#elements/forms/events";
|
||||
import { Form } from "#elements/forms/Form";
|
||||
import Styles from "#elements/modals/styles.css";
|
||||
import { SlottedTemplateResult } from "#elements/types";
|
||||
|
||||
import { ConsoleLogger, Logger } from "#logger/browser";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
import { CSSResult, html, PropertyValues } from "lit";
|
||||
import { createRef } from "lit-html/directives/ref.js";
|
||||
import { customElement, property, state } from "lit/decorators.js";
|
||||
import { guard } from "lit/directives/guard.js";
|
||||
|
||||
import PFButton from "@patternfly/patternfly/components/Button/button.css";
|
||||
import PFCard from "@patternfly/patternfly/components/Card/card.css";
|
||||
import PFContent from "@patternfly/patternfly/components/Content/content.css";
|
||||
import PFForm from "@patternfly/patternfly/components/Form/form.css";
|
||||
import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css";
|
||||
import PFPage from "@patternfly/patternfly/components/Page/page.css";
|
||||
import PFTitle from "@patternfly/patternfly/components/Title/title.css";
|
||||
|
||||
@customElement("ak-modal")
|
||||
export class AKModal extends AKElement {
|
||||
static shadowRootOptions: ShadowRootInit = {
|
||||
...AKElement.shadowRootOptions,
|
||||
delegatesFocus: true,
|
||||
};
|
||||
|
||||
/**
|
||||
* Whether the modal should open the parent dialog element when it is connected to the DOM.
|
||||
*/
|
||||
static openOnConnect = true;
|
||||
|
||||
public static styles: CSSResult[] = [
|
||||
PFButton,
|
||||
PFForm,
|
||||
PFTitle,
|
||||
PFFormControl,
|
||||
PFPage,
|
||||
PFCard,
|
||||
PFContent,
|
||||
Styles,
|
||||
];
|
||||
|
||||
#hostResizeObserver: ResizeObserver;
|
||||
|
||||
//#region Protected Properties
|
||||
|
||||
protected logger: Logger;
|
||||
|
||||
/**
|
||||
* An optional Lit ref which can automatically synchronize the modal's height with the element's height.
|
||||
*/
|
||||
protected scrollContainerRef = createRef<HTMLElement>();
|
||||
|
||||
declare parentElement: HTMLDialogElement | null;
|
||||
|
||||
//#region Public Properties
|
||||
|
||||
@property({ type: String, useDefault: true })
|
||||
public headline: string | null = null;
|
||||
|
||||
/**
|
||||
* Whether the parent dialog element is currently open.
|
||||
*/
|
||||
public get open(): boolean {
|
||||
return this.parentElement?.open ?? false;
|
||||
}
|
||||
|
||||
@property({ type: Boolean, attribute: false, reflect: false })
|
||||
public set open(value: boolean) {
|
||||
if (value) {
|
||||
this.show();
|
||||
} else {
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
|
||||
@property({ type: String })
|
||||
public size: PFSize = PFSize.Large;
|
||||
|
||||
protected defaultSlot: HTMLSlotElement;
|
||||
|
||||
@state()
|
||||
protected form: Form | null = null;
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region Public methods
|
||||
|
||||
/**
|
||||
* Show the modal, rendering its contents.
|
||||
*/
|
||||
public show() {
|
||||
const dialogElement = this.parentElement;
|
||||
|
||||
if (!dialogElement) {
|
||||
this.logger.debug("No parentElement, cannot show modal", this);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
dialogElement.addEventListener("transitionend", this.fadeInListener, {
|
||||
once: true,
|
||||
passive: true,
|
||||
});
|
||||
|
||||
dialogElement.showModal();
|
||||
|
||||
dialogElement.classList.add("fade-in");
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the modal, fading it out and then removing it from the DOM,
|
||||
* optionally with a return value.
|
||||
*
|
||||
* @param returnValue The return value for the dialog, if any.
|
||||
*/
|
||||
public close(returnValue?: string) {
|
||||
const dialogElement = this.parentElement;
|
||||
|
||||
if (!dialogElement) {
|
||||
this.logger.debug("No parentElement, cannot close modal", this);
|
||||
return;
|
||||
}
|
||||
|
||||
dialogElement.addEventListener(
|
||||
"transitionend",
|
||||
(event) => this.delegateClose(event, returnValue),
|
||||
{ once: true, passive: true },
|
||||
);
|
||||
|
||||
dialogElement.classList.remove("fade-in", "fade-in-complete");
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region Event listeners
|
||||
|
||||
/**
|
||||
* A stable reference to the dialog's open event listener.
|
||||
*
|
||||
* This is useful for simplifying adding and removing event listeners.
|
||||
*/
|
||||
protected showListener = () => {
|
||||
this.show();
|
||||
};
|
||||
|
||||
#heightSyncFrameID = -1;
|
||||
/**
|
||||
* A map of observed elements to their expected sizes,
|
||||
* used to prevent unnecessary height synchronizations.
|
||||
*/
|
||||
#expectedSizes = new WeakMap<Element, number>();
|
||||
|
||||
protected lastScrollHeight = 0;
|
||||
|
||||
protected synchronizeHeight: ResizeObserverCallback = ([entry]) => {
|
||||
this.#heightSyncFrameID = requestAnimationFrame(() => {
|
||||
const dialogElement = this.parentElement;
|
||||
|
||||
if (!dialogElement || !dialogElement.open) {
|
||||
return;
|
||||
}
|
||||
|
||||
const expectedSize = this.#expectedSizes.get(entry.target);
|
||||
const blockSize = Math.ceil(entry.borderBoxSize[0].blockSize);
|
||||
const desiredSize = Math.max(entry.target.scrollHeight, blockSize);
|
||||
|
||||
if (desiredSize === expectedSize) {
|
||||
return;
|
||||
}
|
||||
|
||||
dialogElement.style.height = desiredSize + "px";
|
||||
|
||||
this.#expectedSizes.set(entry.target, desiredSize);
|
||||
});
|
||||
};
|
||||
|
||||
#heightResetAnimationFrameID = -1;
|
||||
|
||||
protected resetHeight = () => {
|
||||
cancelAnimationFrame(this.#heightResetAnimationFrameID);
|
||||
cancelAnimationFrame(this.#heightSyncFrameID);
|
||||
|
||||
this.#heightResetAnimationFrameID = requestAnimationFrame(() => {
|
||||
if (this.parentElement) {
|
||||
this.parentElement.style.height = "";
|
||||
}
|
||||
|
||||
this.#heightResetAnimationFrameID = requestAnimationFrame(() => {
|
||||
const scrollContainer = this.scrollContainerRef.value || this;
|
||||
const scrollHeight = scrollContainer.scrollHeight;
|
||||
|
||||
this.lastScrollHeight = scrollHeight;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
protected fadeInListener = async (event: TransitionEvent) => {
|
||||
this.logger.debug("fade-in complete", event);
|
||||
|
||||
this.removeEventListener("transitionend", this.fadeInListener);
|
||||
|
||||
const dialogElement = this.parentElement;
|
||||
|
||||
if (!dialogElement) {
|
||||
this.logger.debug("Skipping height synchronization, no dialog element", this);
|
||||
return;
|
||||
}
|
||||
|
||||
dialogElement.classList.add("fade-in-complete");
|
||||
|
||||
dialogElement.style.height = dialogElement.clientHeight + "px";
|
||||
|
||||
const scrollContainer = this.scrollContainerRef.value || this;
|
||||
|
||||
this.#hostResizeObserver.observe(scrollContainer);
|
||||
|
||||
window.addEventListener("resize", this.resetHeight, {
|
||||
passive: true,
|
||||
});
|
||||
};
|
||||
|
||||
#closing = false;
|
||||
|
||||
/**
|
||||
* Delegate the close action to the parent dialog element,
|
||||
* ensuring that the correct event listeners are triggered and the modal is properly closed.
|
||||
*/
|
||||
protected delegateClose(event: TransitionEvent, returnValue?: string) {
|
||||
if (this.#closing) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.logger.debug("Closing", event);
|
||||
|
||||
this.#closing = true;
|
||||
|
||||
this.parentElement?.close(returnValue);
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
this.#closing = false;
|
||||
this.#hostResizeObserver.unobserve(this);
|
||||
window.removeEventListener("resize", this.resetHeight);
|
||||
this.resetHeight();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* A stable reference to the dialog's close event listener.
|
||||
*
|
||||
* This is useful for simplifying adding and removing event listeners.
|
||||
*/
|
||||
protected closeListener = () => {
|
||||
this.close();
|
||||
};
|
||||
|
||||
/**
|
||||
* A stable reference to the dialog's backdrop click event listener.
|
||||
*
|
||||
* @remarks
|
||||
* Note that if the browser supports {@linkcode HTMLDialogElement}'s `closeBy` property,
|
||||
* the backdrop click may trigger a "cancel" event instead of a "click" event.
|
||||
*/
|
||||
protected backdropClickListener = (event: Event) => {
|
||||
if (event.target === this.parentElement) {
|
||||
this.close();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* A stable reference to the dialog's cancel event listener.
|
||||
*
|
||||
* This is useful for simplifying adding and removing event listeners.
|
||||
*/
|
||||
protected cancelListener = (event: Event) => {
|
||||
if (!this.parentElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
this.close();
|
||||
};
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region Lifecycle
|
||||
|
||||
/**
|
||||
* A bound render method that can be safely passed as a callback without losing the correct `this` context.
|
||||
*
|
||||
* @remarks
|
||||
* This allows the implementing class to use `render`, reducing the mental
|
||||
* overhead of which method should be used for rendering content.
|
||||
*/
|
||||
protected renderContent: () => unknown;
|
||||
|
||||
public constructor() {
|
||||
super();
|
||||
|
||||
this.logger = ConsoleLogger.prefix(this.tagName.toLowerCase());
|
||||
|
||||
this.renderContent = this.render.bind(this);
|
||||
this.render = this.renderInternal;
|
||||
|
||||
this.#hostResizeObserver = new ResizeObserver(this.synchronizeHeight);
|
||||
|
||||
this.defaultSlot = this.ownerDocument.createElement("slot");
|
||||
}
|
||||
|
||||
public override connectedCallback(): void {
|
||||
super.connectedCallback();
|
||||
|
||||
if (!this.parentElement) {
|
||||
this.logger.debug("Skipping connectedCallback, no parentElement", this);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(this.parentElement instanceof HTMLDialogElement)) {
|
||||
throw new TypeError(
|
||||
`authentik/modal: ${this.tagName.toLowerCase()} must be placed inside a <dialog> element.`,
|
||||
);
|
||||
}
|
||||
|
||||
const tagName = this.tagName.toLowerCase();
|
||||
|
||||
this.parentElement.dataset.akModal = tagName;
|
||||
this.parentElement.classList.add("ak-c-modal", this.size);
|
||||
// eslint-disable-next-line wc/no-self-class
|
||||
this.classList.add("ak-c-modal__content");
|
||||
|
||||
this.parentElement.addEventListener("cancel", this.cancelListener);
|
||||
this.parentElement.addEventListener("click", this.backdropClickListener, { passive: true });
|
||||
|
||||
this.addEventListener(AKFormSubmittedEvent.eventName, this.closeListener);
|
||||
|
||||
const { openOnConnect } = this.constructor as typeof AKModal;
|
||||
|
||||
if (openOnConnect) {
|
||||
this.show();
|
||||
}
|
||||
}
|
||||
|
||||
public override disconnectedCallback(): void {
|
||||
super.disconnectedCallback();
|
||||
|
||||
this.#hostResizeObserver.disconnect();
|
||||
window.removeEventListener("resize", this.resetHeight);
|
||||
}
|
||||
|
||||
public override updated(changedProperties: PropertyValues<this>): void {
|
||||
super.updated(changedProperties);
|
||||
|
||||
const assignedElements = this.defaultSlot.assignedElements({ flatten: true });
|
||||
|
||||
const form =
|
||||
assignedElements.find((element): element is Form => element instanceof Form) ?? null;
|
||||
|
||||
if (form && form !== this.form) {
|
||||
this.form = form;
|
||||
this.form.viewportCheck = false;
|
||||
}
|
||||
|
||||
const dialogElement = this.parentElement;
|
||||
|
||||
if (dialogElement && dialogElement.open) {
|
||||
requestAnimationFrame(() => {
|
||||
const scrollContainer = this.scrollContainerRef.value || this;
|
||||
const scrollHeight = scrollContainer.scrollHeight;
|
||||
|
||||
if (scrollHeight !== this.lastScrollHeight) {
|
||||
this.resetHeight();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region Render
|
||||
|
||||
/**
|
||||
* An overridable method that determines whether the modal content should be rendered.
|
||||
*
|
||||
* By default, the modal content is only rendered when the modal is open,
|
||||
* to avoid unnecessary rendering and potential issues with elements that
|
||||
* require being in the DOM to function properly (e.g., autofocus).
|
||||
*/
|
||||
protected shouldRenderModalContent(): boolean {
|
||||
return this.open;
|
||||
}
|
||||
|
||||
/**
|
||||
* The internal render method, including the close button and header, which are common to all modals.
|
||||
*/
|
||||
protected renderInternal() {
|
||||
if (!this.shouldRenderModalContent()) {
|
||||
return super.render();
|
||||
}
|
||||
|
||||
return [
|
||||
this.renderCloseButton(),
|
||||
this.renderHeader(),
|
||||
this.renderContent(),
|
||||
this.renderActions(),
|
||||
];
|
||||
}
|
||||
|
||||
protected renderCloseButton(): SlottedTemplateResult {
|
||||
return html`<button
|
||||
@click=${this.closeListener}
|
||||
class="pf-c-button pf-m-plain"
|
||||
type="button"
|
||||
aria-label=${msg("Close dialog")}
|
||||
>
|
||||
<i class="fas fa-times" aria-hidden="true"></i>
|
||||
</button>`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the modal header.
|
||||
*
|
||||
* This method may be overridden to customize the modal header.
|
||||
*
|
||||
* @protected
|
||||
* @abstract
|
||||
*/
|
||||
protected renderHeader(): SlottedTemplateResult {
|
||||
const { headline, form } = this;
|
||||
const hasHeaderSlot = this.hasSlotted("header");
|
||||
|
||||
return guard([headline, hasHeaderSlot, form], () => {
|
||||
if (!headline && !hasHeaderSlot && !form) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return html`<header class="ak-c-modal__header">
|
||||
<div class="ak-c-modal__title">
|
||||
<h1 class="ak-c-modal__title-text" id="modal-title">
|
||||
${this.headline}
|
||||
<slot name="header"></slot>
|
||||
${form ? form.renderHeader(true) : null}
|
||||
</h1>
|
||||
</div>
|
||||
</header>`;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the modal actions.
|
||||
*
|
||||
* This method may be overridden to customize the modal actions.
|
||||
*
|
||||
* @protected
|
||||
* @abstract
|
||||
*/
|
||||
protected renderActions(): SlottedTemplateResult {
|
||||
const { form } = this;
|
||||
const hasActionsSlot = this.hasSlotted("actions");
|
||||
return guard([hasActionsSlot, form], () => {
|
||||
if (!hasActionsSlot && !form) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return html`<footer class="ak-c-modal__footer">
|
||||
<slot name="actions"></slot>
|
||||
${form ? form.renderActions(true) : null}
|
||||
</footer>`;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the modal content.
|
||||
*
|
||||
* Note that this method is only called when the modal is open.
|
||||
*
|
||||
* @protected
|
||||
* @abstract
|
||||
*/
|
||||
protected render(): unknown {
|
||||
return html`<div class="ak-c-modal__body">${this.defaultSlot}</div>`;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
}
|
||||
|
||||
declare global {
|
||||
interface HTMLElementTagNameMap {
|
||||
"ak-modal": AKModal;
|
||||
}
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
:host {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* #region Buttons */
|
||||
|
||||
:host > .pf-c-button {
|
||||
position: absolute;
|
||||
top: var(--ak-c-modal--c-button--Top);
|
||||
right: var(--ak-c-modal--c-button--Right);
|
||||
}
|
||||
|
||||
:host > .pf-c-button + .ak-c-modal__header {
|
||||
margin-right: var(--ak-c-modal--c-button--sibling--MarginRight);
|
||||
}
|
||||
|
||||
/* #endregion */
|
||||
|
||||
/* #region Header */
|
||||
|
||||
.ak-c-modal__header {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-shrink: 0;
|
||||
padding-top: var(--ak-c-modal__header--PaddingTop);
|
||||
padding-bottom: var(--ak-c-modal__header--PaddingBottom);
|
||||
padding-right: var(--ak-c-modal__header--PaddingRight);
|
||||
padding-left: var(--ak-c-modal__header--PaddingLeft);
|
||||
}
|
||||
|
||||
.ak-c-modal__header.pf-m-help {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.ak-c-modal__header:last-child {
|
||||
padding-bottom: var(--ak-c-modal__header--last-child--PaddingBottom);
|
||||
}
|
||||
|
||||
.ak-c-modal__header + .ak-c-modal__body,
|
||||
.ak-c-modal__header + slot + .ak-c-modal__body {
|
||||
/* --ak-c-modal__body--PaddingTop: var(--ak-c-modal__header--body--PaddingTop); */
|
||||
--ak-c-modal__body--PaddingTop: 0;
|
||||
}
|
||||
|
||||
.ak-c-modal__header-main {
|
||||
flex-grow: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
/* #endregion */
|
||||
|
||||
/* #region Title */
|
||||
|
||||
.ak-c-modal__title,
|
||||
.ak-c-modal__title-text {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.ak-c-modal__title {
|
||||
flex: 0 0 auto;
|
||||
font-family: var(--ak-c-modal__title--FontFamily);
|
||||
font-size: var(--ak-c-modal__title--FontSize);
|
||||
line-height: var(--ak-c-modal__title--LineHeight);
|
||||
}
|
||||
|
||||
.ak-c-modal__title.pf-m-icon {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.ak-c-modal__title-icon {
|
||||
margin-right: var(--ak-c-modal__title-icon--MarginRight);
|
||||
color: var(--ak-c-modal__title-icon--Color);
|
||||
}
|
||||
|
||||
.ak-c-modal__description {
|
||||
padding-top: var(--ak-c-modal__description--PaddingTop);
|
||||
}
|
||||
|
||||
/* #endregion */
|
||||
|
||||
/* #region Body */
|
||||
|
||||
.ak-c-modal__body {
|
||||
flex: 1 1 auto;
|
||||
|
||||
max-height: var(--ak-c-modal__body--MaxHeight);
|
||||
min-height: var(--ak-c-modal__body--MinHeight);
|
||||
padding-top: var(--ak-c-modal__body--PaddingTop);
|
||||
padding-right: var(--ak-c-modal__body--PaddingRight);
|
||||
padding-left: var(--ak-c-modal__body--PaddingLeft);
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
overscroll-behavior: contain;
|
||||
word-break: break-word;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
max-height: calc(
|
||||
75dvh - 2rem - var(--ak-c-modal__header--PaddingTop) -
|
||||
var(--ak-c-modal__footer--PaddingBottom)
|
||||
);
|
||||
}
|
||||
|
||||
.ak-c-modal__body:last-child {
|
||||
padding-bottom: var(--ak-c-modal__body--last-child--PaddingBottom);
|
||||
}
|
||||
|
||||
.ak-c-modal__footer {
|
||||
display: flex;
|
||||
flex: 0 0 auto;
|
||||
align-items: center;
|
||||
padding-top: var(--ak-c-modal__footer--PaddingTop);
|
||||
padding-right: var(--ak-c-modal__footer--PaddingRight);
|
||||
padding-bottom: var(--ak-c-modal__footer--PaddingBottom);
|
||||
padding-left: var(--ak-c-modal__footer--PaddingLeft);
|
||||
|
||||
gap: var(--pf-global--spacer--xs);
|
||||
|
||||
@media screen and (min-width: 576px) {
|
||||
gap: var(--pf-global--spacer--sm);
|
||||
}
|
||||
}
|
||||
|
||||
/* #endregion */
|
||||
|
||||
/* #region Footer */
|
||||
|
||||
fieldset.ak-c-modal__footer {
|
||||
--ak-fieldset__legend--PaddingInlineBase: var(--pf-global--spacer--md);
|
||||
padding-block: calc(var(--ak-fieldset__legend--PaddingInlineBase) / 2);
|
||||
border-inline: none;
|
||||
border-block-end: none;
|
||||
|
||||
--ak-c-modal__footer--c-button--sm--MarginRight: var(
|
||||
--ak-c-modal__footer--c-button--MarginRight
|
||||
);
|
||||
|
||||
& > ak-spinner-button:not(:last-child) {
|
||||
margin-right: var(--ak-c-modal__footer--c-button--MarginRight);
|
||||
}
|
||||
}
|
||||
|
||||
/* #endregion */
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user