mirror of
https://github.com/goauthentik/authentik
synced 2026-04-25 17:15:26 +02:00
Compare commits
112 Commits
sdko/githu
...
ea4848c7c6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ea4848c7c6 | ||
|
|
2fd9a09055 | ||
|
|
b07b71f528 | ||
|
|
c058363180 | ||
|
|
b5a92b783f | ||
|
|
a4c60ece8b | ||
|
|
d1d38edb50 | ||
|
|
c6ee7b6881 | ||
|
|
0459568a96 | ||
|
|
aa746e7585 | ||
|
|
a4dcf097b3 | ||
|
|
c2ecff559c | ||
|
|
c20ecb48f8 | ||
|
|
34a50ad46e | ||
|
|
99410f3775 | ||
|
|
86de4955aa | ||
|
|
bea9b23555 | ||
|
|
9820ee1d67 | ||
|
|
1379637389 | ||
|
|
39e6c41566 | ||
|
|
92a2d26c86 | ||
|
|
0f8d8c81d7 | ||
|
|
cce646b132 | ||
|
|
6d274d1e3d | ||
|
|
8d5489e441 | ||
|
|
8ea9a48017 | ||
|
|
c6b5869b48 | ||
|
|
e4971f9aa5 | ||
|
|
028ec05a8b | ||
|
|
b4c9ac57e0 | ||
|
|
80b93e1fbc | ||
|
|
dff6b48f53 | ||
|
|
79473341d6 | ||
|
|
99f9682d61 | ||
|
|
987f367d7b | ||
|
|
805ff9f1ab | ||
|
|
42fc9d537e | ||
|
|
3f4c0fb35d | ||
|
|
42d87072cf | ||
|
|
075a1f5875 | ||
|
|
24edee3e78 | ||
|
|
9d55b9a9b0 | ||
|
|
349be68d52 | ||
|
|
7dfb8d6129 | ||
|
|
7f7965e42c | ||
|
|
2e2b471b94 | ||
|
|
4d53cd0790 | ||
|
|
7b913eaaa9 | ||
|
|
880c1ec89a | ||
|
|
d7724a52f2 | ||
|
|
508b45b6e3 | ||
|
|
2d52756761 | ||
|
|
6e84b74797 | ||
|
|
aff93d35ef | ||
|
|
d995613212 | ||
|
|
194f04bb6f | ||
|
|
ba14cac535 | ||
|
|
953c70f5fc | ||
|
|
4c775b2258 | ||
|
|
2c851f7cd0 | ||
|
|
520f81966c | ||
|
|
7f27ee3267 | ||
|
|
6d57854bff | ||
|
|
f7871d726e | ||
|
|
189056e19a | ||
|
|
24362625a9 | ||
|
|
5266166d64 | ||
|
|
44d13e3ea5 | ||
|
|
c7e8037ef7 | ||
|
|
a10769e60e | ||
|
|
1a1f752f28 | ||
|
|
081fe60ad7 | ||
|
|
8be14a6de4 | ||
|
|
57c97d5318 | ||
|
|
d44cd63a52 | ||
|
|
33e4f8beb2 | ||
|
|
1b6da073c8 | ||
|
|
c481a5c2f0 | ||
|
|
c300a5338e | ||
|
|
742bbcc51f | ||
|
|
018c81178f | ||
|
|
8bd601f91c | ||
|
|
6f1db505b5 | ||
|
|
1e6d8aa5c4 | ||
|
|
4893d3ef61 | ||
|
|
e99200c1a9 | ||
|
|
132417c3f0 | ||
|
|
9f1318f583 | ||
|
|
d7ca75024a | ||
|
|
addbf5a2f6 | ||
|
|
3dd05a4407 | ||
|
|
058af4504f | ||
|
|
5e88751516 | ||
|
|
87639eced4 | ||
|
|
546f204c15 | ||
|
|
0c6c5661a9 | ||
|
|
fc9211220a | ||
|
|
7ad5c87e84 | ||
|
|
05c2ec315a | ||
|
|
16731116ab | ||
|
|
8147b605e7 | ||
|
|
915b5a73fc | ||
|
|
08832b8520 | ||
|
|
d158fdb792 | ||
|
|
f86ca53309 | ||
|
|
19e406700e | ||
|
|
c74350145f | ||
|
|
514ff57953 | ||
|
|
680220f977 | ||
|
|
27a3dc93e3 | ||
|
|
bd6102b59b | ||
|
|
b41cb4817a |
8
.github/actions/setup/action.yml
vendored
8
.github/actions/setup/action.yml
vendored
@@ -37,7 +37,7 @@ runs:
|
||||
sudo rsync -a --delete /tmp/empty/ /usr/local/lib/android/
|
||||
- name: Install uv
|
||||
if: ${{ contains(inputs.dependencies, 'python') }}
|
||||
uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v5
|
||||
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v5
|
||||
with:
|
||||
enable-cache: true
|
||||
- name: Setup python
|
||||
@@ -64,12 +64,12 @@ runs:
|
||||
rustflags: ""
|
||||
- name: Setup rust dependencies
|
||||
if: ${{ contains(inputs.dependencies, 'rust') }}
|
||||
uses: taiki-e/install-action@5939f3337e40968c39aa70f5ecb1417a92fb25a0 # v2
|
||||
uses: taiki-e/install-action@5f57d6cb7cd20b14a8a27f522884c4bc8a187458 # v2
|
||||
with:
|
||||
tool: cargo-deny cargo-machete cargo-llvm-cov nextest
|
||||
- name: Setup node (web)
|
||||
if: ${{ contains(inputs.dependencies, 'node') }}
|
||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v4
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v4
|
||||
with:
|
||||
node-version-file: "${{ inputs.working-directory }}web/package.json"
|
||||
cache: "npm"
|
||||
@@ -77,7 +77,7 @@ runs:
|
||||
registry-url: "https://registry.npmjs.org"
|
||||
- name: Setup node (root)
|
||||
if: ${{ contains(inputs.dependencies, 'node') }}
|
||||
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v4
|
||||
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v4
|
||||
with:
|
||||
node-version-file: "${{ inputs.working-directory }}package.json"
|
||||
cache: "npm"
|
||||
|
||||
2
.github/actions/setup/compose.yml
vendored
2
.github/actions/setup/compose.yml
vendored
@@ -2,7 +2,7 @@ services:
|
||||
postgresql:
|
||||
image: docker.io/library/postgres:${PSQL_TAG:-16}
|
||||
volumes:
|
||||
- db-data:/var/lib/postgresql/data
|
||||
- db-data:/var/lib/postgresql
|
||||
command: "-c log_statement=all"
|
||||
environment:
|
||||
POSTGRES_USER: authentik
|
||||
|
||||
8
.github/dependabot.yml
vendored
8
.github/dependabot.yml
vendored
@@ -66,6 +66,14 @@ updates:
|
||||
default-days: 7
|
||||
semver-major-days: 14
|
||||
semver-patch-days: 3
|
||||
exclude:
|
||||
- aws-lc-fips-sys
|
||||
- aws-lc-rs
|
||||
- aws-lc-sys
|
||||
- rustls
|
||||
- rustls-pki-types
|
||||
- rustls-platform-verifier
|
||||
- rustls-webpki
|
||||
|
||||
- package-ecosystem: rust-toolchain
|
||||
directory: "/"
|
||||
|
||||
2
.github/workflows/_reusable-docker-build.yml
vendored
2
.github/workflows/_reusable-docker-build.yml
vendored
@@ -90,7 +90,7 @@ jobs:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- uses: int128/docker-manifest-create-action@44422a4b046d55dc036df622039ed3aec43c613c # v2
|
||||
- uses: int128/docker-manifest-create-action@3de37de96c4e900bc3eef9055d3c50abdb4f769d # v2
|
||||
id: build
|
||||
with:
|
||||
tags: ${{ matrix.tag }}
|
||||
|
||||
4
.github/workflows/ci-api-docs.yml
vendored
4
.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@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v5
|
||||
with:
|
||||
node-version-file: website/package.json
|
||||
cache: "npm"
|
||||
@@ -71,7 +71,7 @@ jobs:
|
||||
with:
|
||||
name: api-docs
|
||||
path: website/api/build
|
||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v5
|
||||
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # 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@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v5
|
||||
with:
|
||||
node-version-file: lifecycle/aws/package.json
|
||||
cache: "npm"
|
||||
|
||||
4
.github/workflows/ci-docs.yml
vendored
4
.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@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # 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@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v5
|
||||
with:
|
||||
node-version-file: website/package.json
|
||||
cache: "npm"
|
||||
|
||||
5
.github/workflows/ci-main.yml
vendored
5
.github/workflows/ci-main.yml
vendored
@@ -127,7 +127,10 @@ jobs:
|
||||
with:
|
||||
postgresql_version: ${{ matrix.psql }}
|
||||
- name: run migrations to stable
|
||||
run: uv run python -m lifecycle.migrate
|
||||
run: |
|
||||
docker ps
|
||||
docker logs setup-postgresql-1
|
||||
uv run python -m lifecycle.migrate
|
||||
- name: checkout current code
|
||||
run: |
|
||||
set -x
|
||||
|
||||
2
.github/workflows/ci-outpost.yml
vendored
2
.github/workflows/ci-outpost.yml
vendored
@@ -145,7 +145,7 @@ jobs:
|
||||
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6
|
||||
with:
|
||||
go-version-file: "go.mod"
|
||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v5
|
||||
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # 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@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v5
|
||||
with:
|
||||
node-version-file: ${{ matrix.project }}/package.json
|
||||
cache: "npm"
|
||||
@@ -47,7 +47,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
|
||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v5
|
||||
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v5
|
||||
with:
|
||||
node-version-file: web/package.json
|
||||
cache: "npm"
|
||||
@@ -73,7 +73,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
|
||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v5
|
||||
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v5
|
||||
with:
|
||||
node-version-file: web/package.json
|
||||
cache: "npm"
|
||||
|
||||
2
.github/workflows/gen-image-compress.yml
vendored
2
.github/workflows/gen-image-compress.yml
vendored
@@ -38,7 +38,7 @@ jobs:
|
||||
token: ${{ steps.generate_token.outputs.token }}
|
||||
- name: Compress images
|
||||
id: compress
|
||||
uses: calibreapp/image-actions@4f7260f5dbd809ec86d03721c1ad71b8a841d3e0 # main
|
||||
uses: calibreapp/image-actions@e2cc8db5d49c849e00844dfebf01438318e96fa2 # main
|
||||
with:
|
||||
GITHUB_TOKEN: ${{ steps.generate_token.outputs.token }}
|
||||
compressOnly: ${{ github.event_name != 'pull_request' }}
|
||||
|
||||
4
.github/workflows/packages-npm-publish.yml
vendored
4
.github/workflows/packages-npm-publish.yml
vendored
@@ -35,13 +35,13 @@ jobs:
|
||||
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v5
|
||||
with:
|
||||
fetch-depth: 2
|
||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v5
|
||||
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # 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@9426d40962ed5378910ee2e21d5f8c6fcbf2dd96 # 24d32ffd492484c1d75e0c0b894501ddb9d30d62
|
||||
with:
|
||||
files: |
|
||||
${{ matrix.package }}/package.json
|
||||
|
||||
4
.github/workflows/release-publish.yml
vendored
4
.github/workflows/release-publish.yml
vendored
@@ -87,7 +87,7 @@ jobs:
|
||||
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6
|
||||
with:
|
||||
go-version-file: "go.mod"
|
||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v5
|
||||
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v5
|
||||
with:
|
||||
node-version-file: web/package.json
|
||||
cache: "npm"
|
||||
@@ -151,7 +151,7 @@ jobs:
|
||||
- uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6
|
||||
with:
|
||||
go-version-file: "go.mod"
|
||||
- uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v5
|
||||
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v5
|
||||
with:
|
||||
node-version-file: web/package.json
|
||||
cache: "npm"
|
||||
|
||||
65
Cargo.lock
generated
65
Cargo.lock
generated
@@ -231,9 +231,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "aws-lc-rs"
|
||||
version = "1.16.2"
|
||||
version = "1.16.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a054912289d18629dc78375ba2c3726a3afe3ff71b4edba9dedfca0e3446d1fc"
|
||||
checksum = "0ec6fb3fe69024a75fa7e1bfb48aa6cf59706a101658ea01bfd33b2b248a038f"
|
||||
dependencies = [
|
||||
"aws-lc-fips-sys",
|
||||
"aws-lc-sys",
|
||||
@@ -243,9 +243,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "aws-lc-sys"
|
||||
version = "0.39.0"
|
||||
version = "0.40.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fa7e52a4c5c547c741610a2c6f123f3881e409b714cd27e6798ef020c514f0a"
|
||||
checksum = "f50037ee5e1e41e7b8f9d161680a725bd1626cb6f8c7e901f91f942850852fe7"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cmake",
|
||||
@@ -255,9 +255,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "axum"
|
||||
version = "0.8.8"
|
||||
version = "0.8.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b52af3cb4058c895d37317bb27508dccc8e5f2d39454016b297bf4a400597b8"
|
||||
checksum = "31b698c5f9a010f6573133b09e0de5408834d0c82f8d7475a89fc1867a71cd90"
|
||||
dependencies = [
|
||||
"axum-core",
|
||||
"axum-macros",
|
||||
@@ -311,9 +311,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "axum-macros"
|
||||
version = "0.5.0"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "604fde5e028fea851ce1d8570bbdc034bec850d157f7569d10f347d06808c05c"
|
||||
checksum = "7aa268c23bfbbd2c4363b9cd302a4f504fb2a9dfe7e3451d66f35dd392e20aca"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -510,9 +510,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.6.0"
|
||||
version = "4.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351"
|
||||
checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
@@ -532,9 +532,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.6.0"
|
||||
version = "4.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6a"
|
||||
checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
@@ -1981,7 +1981,7 @@ dependencies = [
|
||||
"num-integer",
|
||||
"num-iter",
|
||||
"num-traits",
|
||||
"rand 0.8.5",
|
||||
"rand 0.8.6",
|
||||
"smallvec",
|
||||
"zeroize",
|
||||
]
|
||||
@@ -2502,9 +2502,9 @@ checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha 0.3.1",
|
||||
@@ -2737,9 +2737,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustls"
|
||||
version = "0.23.37"
|
||||
version = "0.23.39"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4"
|
||||
checksum = "7c2c118cb077cca2822033836dfb1b975355dfb784b5e8da48f7b6c5db74e60e"
|
||||
dependencies = [
|
||||
"aws-lc-rs",
|
||||
"log",
|
||||
@@ -2802,9 +2802,9 @@ checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f"
|
||||
|
||||
[[package]]
|
||||
name = "rustls-webpki"
|
||||
version = "0.103.12"
|
||||
version = "0.103.13"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8279bb85272c9f10811ae6a6c547ff594d6a7f3c6c6b02ee9726d1d0dcfcdd06"
|
||||
checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e"
|
||||
dependencies = [
|
||||
"aws-lc-rs",
|
||||
"ring",
|
||||
@@ -3315,7 +3315,7 @@ dependencies = [
|
||||
"memchr",
|
||||
"once_cell",
|
||||
"percent-encoding",
|
||||
"rand 0.8.5",
|
||||
"rand 0.8.6",
|
||||
"rsa",
|
||||
"serde",
|
||||
"sha1",
|
||||
@@ -3356,7 +3356,7 @@ dependencies = [
|
||||
"md-5",
|
||||
"memchr",
|
||||
"once_cell",
|
||||
"rand 0.8.5",
|
||||
"rand 0.8.6",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2",
|
||||
@@ -3598,9 +3598,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.51.1"
|
||||
version = "1.52.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f66bf9585cda4b724d3e78ab34b73fb2bbaba9011b9bfdf69dc836382ea13b8c"
|
||||
checksum = "b67dee974fe86fd92cc45b7a95fdd2f99a36a6d7b0d431a231178d3d670bbcc6"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"libc",
|
||||
@@ -3658,9 +3658,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tokio-tungstenite"
|
||||
version = "0.28.0"
|
||||
version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d25a406cddcc431a75d3d9afc6a7c0f7428d4891dd973e4d54c56b46127bf857"
|
||||
checksum = "8f72a05e828585856dacd553fba484c242c46e391fb0e58917c942ee9202915c"
|
||||
dependencies = [
|
||||
"futures-util",
|
||||
"log",
|
||||
@@ -3869,9 +3869,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
|
||||
|
||||
[[package]]
|
||||
name = "tungstenite"
|
||||
version = "0.28.0"
|
||||
version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8628dcc84e5a09eb3d8423d6cb682965dea9133204e8fb3efee74c2a0c259442"
|
||||
checksum = "6c01152af293afb9c7c2a57e4b559c5620b421f6d133261c60dd2d0cdb38e6b8"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"data-encoding",
|
||||
@@ -3881,7 +3881,6 @@ dependencies = [
|
||||
"rand 0.9.2",
|
||||
"sha1",
|
||||
"thiserror 2.0.18",
|
||||
"utf-8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3991,12 +3990,6 @@ dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "utf-8"
|
||||
version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
|
||||
|
||||
[[package]]
|
||||
name = "utf8-zero"
|
||||
version = "0.8.1"
|
||||
@@ -4017,9 +4010,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.23.0"
|
||||
version = "1.23.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ac8b6f42ead25368cf5b098aeb3dc8a1a2c05a3eee8a9a1a68c640edbfc79d9"
|
||||
checksum = "ddd74a9687298c6858e9b88ec8935ec45d22e8fd5e6394fa1bd4e99a87789c76"
|
||||
dependencies = [
|
||||
"getrandom 0.4.2",
|
||||
"js-sys",
|
||||
|
||||
12
Cargo.toml
12
Cargo.toml
@@ -21,9 +21,9 @@ publish = false
|
||||
[workspace.dependencies]
|
||||
arc-swap = "= 1.9.1"
|
||||
axum-server = { version = "= 0.8.0", features = ["tls-rustls-no-provider"] }
|
||||
aws-lc-rs = { version = "= 1.16.2", features = ["fips"] }
|
||||
axum = { version = "= 0.8.8", features = ["http2", "macros", "ws"] }
|
||||
clap = { version = "= 4.6.0", features = ["derive", "env"] }
|
||||
aws-lc-rs = { version = "= 1.16.3", features = ["fips"] }
|
||||
axum = { version = "= 0.8.9", features = ["http2", "macros", "ws"] }
|
||||
clap = { version = "= 4.6.1", features = ["derive", "env"] }
|
||||
client-ip = { version = "0.2.1", features = ["forwarded-header"] }
|
||||
colored = "= 3.1.1"
|
||||
config-rs = { package = "config", version = "= 0.15.22", default-features = false, features = [
|
||||
@@ -58,7 +58,7 @@ reqwest-middleware = { version = "= 0.5.1", features = [
|
||||
"query",
|
||||
"rustls",
|
||||
] }
|
||||
rustls = { version = "= 0.23.37", features = ["fips"] }
|
||||
rustls = { version = "= 0.23.39", features = ["fips"] }
|
||||
sentry = { version = "= 0.47.0", default-features = false, features = [
|
||||
"backtrace",
|
||||
"contexts",
|
||||
@@ -89,7 +89,7 @@ sqlx = { version = "= 0.8.6", default-features = false, features = [
|
||||
tempfile = "= 3.27.0"
|
||||
thiserror = "= 2.0.18"
|
||||
time = { version = "= 0.3.47", features = ["macros"] }
|
||||
tokio = { version = "= 1.51.1", features = ["full", "tracing"] }
|
||||
tokio = { version = "= 1.52.1", features = ["full", "tracing"] }
|
||||
tokio-retry2 = "= 0.9.1"
|
||||
tokio-rustls = "= 0.26.4"
|
||||
tokio-util = { version = "= 0.7.18", features = ["full"] }
|
||||
@@ -104,7 +104,7 @@ tracing-subscriber = { version = "= 0.3.23", features = [
|
||||
"tracing-log",
|
||||
] }
|
||||
url = "= 2.5.8"
|
||||
uuid = { version = "= 1.23.0", features = ["serde", "v4"] }
|
||||
uuid = { version = "= 1.23.1", features = ["serde", "v4"] }
|
||||
|
||||
ak-client = { package = "authentik-client", version = "2026.5.0-rc1", path = "./packages/client-rust" }
|
||||
ak-common = { package = "authentik-common", version = "2026.5.0-rc1", path = "./packages/ak-common", default-features = false }
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from collections.abc import Generator, Iterator
|
||||
from contextlib import contextmanager
|
||||
from tempfile import SpooledTemporaryFile
|
||||
from urllib.parse import urlsplit
|
||||
from urllib.parse import urlsplit, urlunsplit
|
||||
|
||||
import boto3
|
||||
from botocore.config import Config
|
||||
@@ -164,16 +164,19 @@ class S3Backend(ManageableBackend):
|
||||
)
|
||||
|
||||
def _file_url(name: str, request: HttpRequest | None) -> str:
|
||||
client = self.client
|
||||
params = {
|
||||
"Bucket": self.bucket_name,
|
||||
"Key": f"{self.base_path}/{name}",
|
||||
}
|
||||
|
||||
url = self.client.generate_presigned_url(
|
||||
"get_object",
|
||||
Params=params,
|
||||
ExpiresIn=expires_in,
|
||||
HttpMethod="GET",
|
||||
operation_name = "GetObject"
|
||||
operation_model = client.meta.service_model.operation_model(operation_name)
|
||||
request_dict = client._convert_to_request_dict(
|
||||
params,
|
||||
operation_model,
|
||||
endpoint_url=client.meta.endpoint_url,
|
||||
context={"is_presign_request": True},
|
||||
)
|
||||
|
||||
# Support custom domain for S3-compatible storage (so not AWS)
|
||||
@@ -183,9 +186,8 @@ class S3Backend(ManageableBackend):
|
||||
CONFIG.get(f"storage.{self.name}.custom_domain", None),
|
||||
)
|
||||
if custom_domain:
|
||||
parsed = urlsplit(url)
|
||||
scheme = "https" if use_https else "http"
|
||||
path = parsed.path
|
||||
path = request_dict["url_path"]
|
||||
|
||||
# When using path-style addressing, the presigned URL contains the bucket
|
||||
# name in the path (e.g., /bucket-name/key). Since custom_domain must
|
||||
@@ -200,9 +202,22 @@ class S3Backend(ManageableBackend):
|
||||
if not path.startswith("/"):
|
||||
path = f"/{path}"
|
||||
|
||||
url = f"{scheme}://{custom_domain}{path}?{parsed.query}"
|
||||
custom_base = urlsplit(f"{scheme}://{custom_domain}")
|
||||
|
||||
return url
|
||||
# Sign the final public URL instead of signing the internal S3 endpoint and
|
||||
# rewriting it afterwards. Presigned SigV4 URLs include the host header in the
|
||||
# canonical request, so post-sign host changes break strict backends like RustFS.
|
||||
public_path = f"{custom_base.path.rstrip('/')}{path}" if custom_base.path else path
|
||||
request_dict["url_path"] = public_path
|
||||
request_dict["url"] = urlunsplit(
|
||||
(custom_base.scheme, custom_base.netloc, public_path, "", "")
|
||||
)
|
||||
|
||||
return client._request_signer.generate_presigned_url(
|
||||
request_dict,
|
||||
operation_name,
|
||||
expires_in=expires_in,
|
||||
)
|
||||
|
||||
if use_cache:
|
||||
return self._cache_get_or_set(name, request, _file_url, expires_in)
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
from unittest import skipUnless
|
||||
from urllib.parse import parse_qs, urlsplit
|
||||
|
||||
from botocore.exceptions import UnsupportedSignatureVersionError
|
||||
from django.test import TestCase
|
||||
@@ -168,6 +169,44 @@ class TestS3Backend(FileTestS3BackendMixin, TestCase):
|
||||
f"URL: {url}",
|
||||
)
|
||||
|
||||
@CONFIG.patch("storage.s3.secure_urls", False)
|
||||
@CONFIG.patch("storage.s3.addressing_style", "path")
|
||||
def test_file_url_custom_domain_resigns_for_custom_host(self):
|
||||
"""Test presigned URLs are signed for the custom domain host.
|
||||
|
||||
Host-changing custom domains must produce a signature query string for
|
||||
the public host, not reuse the internal endpoint signature.
|
||||
"""
|
||||
bucket_name = self.media_s3_bucket_name
|
||||
key_name = "application-icons/test.svg"
|
||||
custom_domain = f"files.example.test:8020/{bucket_name}"
|
||||
|
||||
endpoint_signed_url = self.media_s3_backend.client.generate_presigned_url(
|
||||
"get_object",
|
||||
Params={
|
||||
"Bucket": bucket_name,
|
||||
"Key": f"{self.media_s3_backend.base_path}/{key_name}",
|
||||
},
|
||||
ExpiresIn=900,
|
||||
HttpMethod="GET",
|
||||
)
|
||||
|
||||
with CONFIG.patch("storage.media.s3.custom_domain", custom_domain):
|
||||
custom_url = self.media_s3_backend.file_url(key_name, use_cache=False)
|
||||
|
||||
endpoint_parts = urlsplit(endpoint_signed_url)
|
||||
custom_parts = urlsplit(custom_url)
|
||||
|
||||
self.assertEqual(custom_parts.scheme, "http")
|
||||
self.assertEqual(custom_parts.netloc, "files.example.test:8020")
|
||||
self.assertEqual(parse_qs(custom_parts.query)["X-Amz-SignedHeaders"], ["host"])
|
||||
self.assertNotEqual(
|
||||
custom_parts.query,
|
||||
endpoint_parts.query,
|
||||
"Custom-domain URLs must be signed for the public host, not reuse the endpoint "
|
||||
"signature query string.",
|
||||
)
|
||||
|
||||
def test_themed_urls_without_theme_variable(self):
|
||||
"""Test themed_urls returns None when filename has no %(theme)s"""
|
||||
result = self.media_s3_backend.themed_urls("logo.png")
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"""Apply blueprint from commandline"""
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from sys import exit as sys_exit
|
||||
|
||||
from django.core.management.base import BaseCommand, no_translations
|
||||
@@ -31,5 +32,5 @@ class Command(BaseCommand):
|
||||
sys_exit(1)
|
||||
importer.apply()
|
||||
|
||||
def add_arguments(self, parser):
|
||||
def add_arguments(self, parser: ArgumentParser):
|
||||
parser.add_argument("blueprints", nargs="+", type=str)
|
||||
|
||||
@@ -4,7 +4,7 @@ from collections.abc import Iterator
|
||||
from copy import copy
|
||||
|
||||
from django.core.cache import cache
|
||||
from django.db.models import Case, QuerySet
|
||||
from django.db.models import Case, Q, QuerySet
|
||||
from django.db.models.expressions import When
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.utils.translation import gettext as _
|
||||
@@ -36,9 +36,13 @@ from authentik.rbac.filters import ObjectFilter
|
||||
LOGGER = get_logger()
|
||||
|
||||
|
||||
def user_app_cache_key(user_pk: str, page_number: int | None = None) -> str:
|
||||
def user_app_cache_key(
|
||||
user_pk: str, page_number: int | None = None, only_with_launch_url: bool = False
|
||||
) -> str:
|
||||
"""Cache key where application list for user is saved"""
|
||||
key = f"{CACHE_PREFIX}app_access/{user_pk}"
|
||||
if only_with_launch_url:
|
||||
key += "/launch"
|
||||
if page_number:
|
||||
key += f"/{page_number}"
|
||||
return key
|
||||
@@ -274,11 +278,19 @@ class ApplicationViewSet(UsedByMixin, ModelViewSet):
|
||||
if superuser_full_list and request.user.is_superuser:
|
||||
return super().list(request)
|
||||
|
||||
only_with_launch_url = str(
|
||||
request.query_params.get("only_with_launch_url", "false")
|
||||
).lower()
|
||||
only_with_launch_url = (
|
||||
str(request.query_params.get("only_with_launch_url", "false")).lower()
|
||||
) == "true"
|
||||
|
||||
queryset = self._filter_queryset_for_list(self.get_queryset())
|
||||
if only_with_launch_url:
|
||||
# Pre-filter at DB level to skip expensive per-app policy evaluation
|
||||
# for apps that can never appear in the launcher:
|
||||
# - No meta_launch_url AND no provider: no possible launch URL
|
||||
# - meta_launch_url="blank://blank": documented convention to hide from launcher
|
||||
queryset = queryset.exclude(
|
||||
Q(meta_launch_url="", provider__isnull=True) | Q(meta_launch_url="blank://blank")
|
||||
)
|
||||
paginator: Pagination = self.paginator
|
||||
paginated_apps = paginator.paginate_queryset(queryset, request)
|
||||
|
||||
@@ -295,7 +307,6 @@ class ApplicationViewSet(UsedByMixin, ModelViewSet):
|
||||
except ValueError as exc:
|
||||
raise ValidationError from exc
|
||||
allowed_applications = self._get_allowed_applications(paginated_apps, user=for_user)
|
||||
allowed_applications = self._expand_applications(allowed_applications)
|
||||
|
||||
serializer = self.get_serializer(allowed_applications, many=True)
|
||||
return self.get_paginated_response(serializer.data)
|
||||
@@ -305,19 +316,26 @@ class ApplicationViewSet(UsedByMixin, ModelViewSet):
|
||||
allowed_applications = self._get_allowed_applications(paginated_apps)
|
||||
if should_cache:
|
||||
allowed_applications = cache.get(
|
||||
user_app_cache_key(self.request.user.pk, paginator.page.number)
|
||||
user_app_cache_key(
|
||||
self.request.user.pk, paginator.page.number, only_with_launch_url
|
||||
)
|
||||
)
|
||||
if not allowed_applications:
|
||||
if allowed_applications:
|
||||
# Re-fetch cached applications since pickled instances lose prefetched
|
||||
# relationships, causing N+1 queries during serialization
|
||||
allowed_applications = self._expand_applications(allowed_applications)
|
||||
else:
|
||||
LOGGER.debug("Caching allowed application list", page=paginator.page.number)
|
||||
allowed_applications = self._get_allowed_applications(paginated_apps)
|
||||
cache.set(
|
||||
user_app_cache_key(self.request.user.pk, paginator.page.number),
|
||||
user_app_cache_key(
|
||||
self.request.user.pk, paginator.page.number, only_with_launch_url
|
||||
),
|
||||
allowed_applications,
|
||||
timeout=86400,
|
||||
)
|
||||
allowed_applications = self._expand_applications(allowed_applications)
|
||||
|
||||
if only_with_launch_url == "true":
|
||||
if only_with_launch_url:
|
||||
allowed_applications = self._filter_applications_with_launch_url(allowed_applications)
|
||||
|
||||
serializer = self.get_serializer(allowed_applications, many=True)
|
||||
|
||||
@@ -7,6 +7,12 @@ from authentik.tasks.schedules.common import ScheduleSpec
|
||||
from authentik.tenants.flags import Flag
|
||||
|
||||
|
||||
class Setup(Flag[bool], key="setup"):
|
||||
|
||||
default = False
|
||||
visibility = "system"
|
||||
|
||||
|
||||
class AppAccessWithoutBindings(Flag[bool], key="core_default_app_access"):
|
||||
|
||||
default = True
|
||||
@@ -26,6 +32,10 @@ class AuthentikCoreConfig(ManagedAppConfig):
|
||||
mountpoint = ""
|
||||
default = True
|
||||
|
||||
def import_related(self):
|
||||
super().import_related()
|
||||
self.import_module("authentik.core.setup.signals")
|
||||
|
||||
@ManagedAppConfig.reconcile_tenant
|
||||
def source_inbuilt(self):
|
||||
"""Reconcile inbuilt source"""
|
||||
|
||||
61
authentik/core/migrations/0058_setup.py
Normal file
61
authentik/core/migrations/0058_setup.py
Normal file
@@ -0,0 +1,61 @@
|
||||
# Generated by Django 5.2.13 on 2026-04-21 18:49
|
||||
from django.apps.registry import Apps
|
||||
|
||||
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
def check_is_already_setup(apps: Apps, schema_editor: BaseDatabaseSchemaEditor):
|
||||
from django.conf import settings
|
||||
from authentik.flows.models import FlowAuthenticationRequirement
|
||||
|
||||
VersionHistory = apps.get_model("authentik_admin", "VersionHistory")
|
||||
Flow = apps.get_model("authentik_flows", "Flow")
|
||||
User = apps.get_model("authentik_core", "User")
|
||||
|
||||
db_alias = schema_editor.connection.alias
|
||||
|
||||
# Upgrading from a previous version
|
||||
if not settings.TEST and VersionHistory.objects.using(db_alias).count() > 1:
|
||||
return True
|
||||
# OOBE flow sets itself to this authentication requirement once finished
|
||||
if (
|
||||
Flow.objects.using(db_alias)
|
||||
.filter(
|
||||
slug="initial-setup", authentication=FlowAuthenticationRequirement.REQUIRE_SUPERUSER
|
||||
)
|
||||
.exists()
|
||||
):
|
||||
return True
|
||||
# non-akadmin and non-guardian anonymous user exist
|
||||
if (
|
||||
User.objects.using(db_alias)
|
||||
.exclude(username="akadmin")
|
||||
.exclude(username="AnonymousUser")
|
||||
.exists()
|
||||
):
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
def update_setup_flag(apps: Apps, schema_editor: BaseDatabaseSchemaEditor):
|
||||
from authentik.core.apps import Setup
|
||||
from authentik.tenants.utils import get_current_tenant
|
||||
|
||||
is_already_setup = check_is_already_setup(apps, schema_editor)
|
||||
if is_already_setup:
|
||||
tenant = get_current_tenant()
|
||||
tenant.flags[Setup().key] = True
|
||||
tenant.save()
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("authentik_core", "0057_remove_user_groups_remove_user_user_permissions_and_more"),
|
||||
# 0024_flow_authentication adds the `authentication` field.
|
||||
("authentik_flows", "0024_flow_authentication"),
|
||||
]
|
||||
|
||||
operations = [migrations.RunPython(update_setup_flag, migrations.RunPython.noop)]
|
||||
@@ -790,9 +790,13 @@ class Application(SerializerModel, PolicyBindingModel):
|
||||
|
||||
def get_provider(self) -> Provider | None:
|
||||
"""Get casted provider instance. Needs Application queryset with_provider"""
|
||||
if hasattr(self, "_cached_provider"):
|
||||
return self._cached_provider
|
||||
if not self.provider:
|
||||
self._cached_provider = None
|
||||
return None
|
||||
return get_deepest_child(self.provider)
|
||||
self._cached_provider = get_deepest_child(self.provider)
|
||||
return self._cached_provider
|
||||
|
||||
def backchannel_provider_for[T: Provider](self, provider_type: type[T], **kwargs) -> T | None:
|
||||
"""Get Backchannel provider for a specific type"""
|
||||
|
||||
0
authentik/core/setup/__init__.py
Normal file
0
authentik/core/setup/__init__.py
Normal file
38
authentik/core/setup/signals.py
Normal file
38
authentik/core/setup/signals.py
Normal file
@@ -0,0 +1,38 @@
|
||||
from os import getenv
|
||||
|
||||
from django.dispatch import receiver
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik.blueprints.models import BlueprintInstance
|
||||
from authentik.blueprints.v1.importer import Importer
|
||||
from authentik.core.apps import Setup
|
||||
from authentik.root.signals import post_startup
|
||||
from authentik.tenants.models import Tenant
|
||||
|
||||
BOOTSTRAP_BLUEPRINT = "system/bootstrap.yaml"
|
||||
|
||||
LOGGER = get_logger()
|
||||
|
||||
|
||||
@receiver(post_startup)
|
||||
def post_startup_setup_bootstrap(sender, **_):
|
||||
if not getenv("AUTHENTIK_BOOTSTRAP_PASSWORD") and not getenv("AUTHENTIK_BOOTSTRAP_TOKEN"):
|
||||
return
|
||||
LOGGER.info("Configuring authentik through bootstrap environment variables")
|
||||
content = BlueprintInstance(path=BOOTSTRAP_BLUEPRINT).retrieve()
|
||||
# If we have bootstrap credentials set, run bootstrap tasks outside of main server
|
||||
# sync, so that we can sure the first start actually has working bootstrap
|
||||
# credentials
|
||||
for tenant in Tenant.objects.filter(ready=True):
|
||||
if Setup.get(tenant=tenant):
|
||||
LOGGER.info("Tenant is already setup, skipping", tenant=tenant.schema_name)
|
||||
continue
|
||||
with tenant:
|
||||
importer = Importer.from_string(content)
|
||||
valid, logs = importer.validate()
|
||||
if not valid:
|
||||
LOGGER.warning("Blueprint invalid", tenant=tenant.schema_name)
|
||||
for log in logs:
|
||||
log.log()
|
||||
importer.apply()
|
||||
Setup.set(True, tenant=tenant)
|
||||
80
authentik/core/setup/views.py
Normal file
80
authentik/core/setup/views.py
Normal file
@@ -0,0 +1,80 @@
|
||||
from functools import lru_cache
|
||||
from http import HTTPMethod, HTTPStatus
|
||||
|
||||
from django.contrib.staticfiles import finders
|
||||
from django.db import transaction
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from django.shortcuts import redirect
|
||||
from django.urls import reverse
|
||||
from django.views import View
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik.blueprints.models import BlueprintInstance
|
||||
from authentik.core.apps import Setup
|
||||
from authentik.flows.models import Flow, FlowAuthenticationRequirement, in_memory_stage
|
||||
from authentik.flows.planner import FlowPlanner
|
||||
from authentik.flows.stage import StageView
|
||||
|
||||
LOGGER = get_logger()
|
||||
FLOW_CONTEXT_START_BY = "goauthentik.io/core/setup/started-by"
|
||||
|
||||
|
||||
@lru_cache
|
||||
def read_static(path: str) -> str | None:
|
||||
result = finders.find(path)
|
||||
if not result:
|
||||
return None
|
||||
with open(result, encoding="utf8") as _file:
|
||||
return _file.read()
|
||||
|
||||
|
||||
class SetupView(View):
|
||||
|
||||
setup_flow_slug = "initial-setup"
|
||||
|
||||
def dispatch(self, request: HttpRequest, *args, **kwargs):
|
||||
if request.method != HTTPMethod.HEAD and Setup.get():
|
||||
return redirect(reverse("authentik_core:root-redirect"))
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
def head(self, request: HttpRequest, *args, **kwargs):
|
||||
if Setup.get():
|
||||
return HttpResponse(status=HTTPStatus.SERVICE_UNAVAILABLE)
|
||||
if not Flow.objects.filter(slug=self.setup_flow_slug).exists():
|
||||
return HttpResponse(status=HTTPStatus.SERVICE_UNAVAILABLE)
|
||||
return HttpResponse(status=HTTPStatus.OK)
|
||||
|
||||
def get(self, request: HttpRequest):
|
||||
flow = Flow.objects.filter(slug=self.setup_flow_slug).first()
|
||||
if not flow:
|
||||
LOGGER.info("Setup flow does not exist yet, waiting for worker to finish")
|
||||
return HttpResponse(
|
||||
read_static("dist/standalone/loading/startup.html"),
|
||||
status=HTTPStatus.SERVICE_UNAVAILABLE,
|
||||
)
|
||||
planner = FlowPlanner(flow)
|
||||
plan = planner.plan(request, {FLOW_CONTEXT_START_BY: "setup"})
|
||||
plan.append_stage(in_memory_stage(PostSetupStageView))
|
||||
return plan.to_redirect(request, flow)
|
||||
|
||||
|
||||
class PostSetupStageView(StageView):
|
||||
"""Run post-setup tasks"""
|
||||
|
||||
def post(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
|
||||
"""Wrapper when this stage gets hit with a post request"""
|
||||
return self.get(request, *args, **kwargs)
|
||||
|
||||
def get(self, requeset: HttpRequest, *args, **kwargs):
|
||||
with transaction.atomic():
|
||||
# Remember we're setup
|
||||
Setup.set(True)
|
||||
# Disable OOBE Blueprints
|
||||
BlueprintInstance.objects.filter(
|
||||
**{"metadata__labels__blueprints.goauthentik.io/system-oobe": "true"}
|
||||
).update(enabled=False)
|
||||
# Make flow inaccessible
|
||||
Flow.objects.filter(slug="initial-setup").update(
|
||||
authentication=FlowAuthenticationRequirement.REQUIRE_SUPERUSER
|
||||
)
|
||||
return self.executor.stage_ok()
|
||||
@@ -4,6 +4,7 @@ from django.test import TestCase
|
||||
from django.urls import reverse
|
||||
|
||||
from authentik.brands.models import Brand
|
||||
from authentik.core.apps import Setup
|
||||
from authentik.core.models import Application, UserTypes
|
||||
from authentik.core.tests.utils import create_test_brand, create_test_user
|
||||
|
||||
@@ -12,6 +13,7 @@ class TestInterfaceRedirects(TestCase):
|
||||
"""Test RootRedirectView and BrandDefaultRedirectView redirect logic by user type"""
|
||||
|
||||
def setUp(self):
|
||||
Setup.set(True)
|
||||
self.app = Application.objects.create(name="test-app", slug="test-app")
|
||||
self.brand: Brand = create_test_brand(default_application=self.app)
|
||||
|
||||
|
||||
156
authentik/core/tests/test_setup.py
Normal file
156
authentik/core/tests/test_setup.py
Normal file
@@ -0,0 +1,156 @@
|
||||
from http import HTTPStatus
|
||||
from os import environ
|
||||
|
||||
from django.urls import reverse
|
||||
|
||||
from authentik.blueprints.tests import apply_blueprint
|
||||
from authentik.core.apps import Setup
|
||||
from authentik.core.models import Token, TokenIntents, User
|
||||
from authentik.flows.models import Flow
|
||||
from authentik.flows.tests import FlowTestCase
|
||||
from authentik.lib.generators import generate_id
|
||||
from authentik.root.signals import post_startup, pre_startup
|
||||
from authentik.tenants.flags import patch_flag
|
||||
|
||||
|
||||
class TestSetup(FlowTestCase):
|
||||
def tearDown(self):
|
||||
environ.pop("AUTHENTIK_BOOTSTRAP_PASSWORD", None)
|
||||
environ.pop("AUTHENTIK_BOOTSTRAP_TOKEN", None)
|
||||
|
||||
@patch_flag(Setup, True)
|
||||
def test_setup(self):
|
||||
"""Test existing instance"""
|
||||
res = self.client.get(reverse("authentik_core:root-redirect"))
|
||||
self.assertEqual(res.status_code, HTTPStatus.FOUND)
|
||||
self.assertRedirects(
|
||||
res,
|
||||
reverse("authentik_flows:default-authentication") + "?next=/",
|
||||
fetch_redirect_response=False,
|
||||
)
|
||||
|
||||
res = self.client.head(reverse("authentik_core:setup"))
|
||||
self.assertEqual(res.status_code, HTTPStatus.SERVICE_UNAVAILABLE)
|
||||
|
||||
res = self.client.get(reverse("authentik_core:setup"))
|
||||
self.assertEqual(res.status_code, HTTPStatus.FOUND)
|
||||
self.assertRedirects(
|
||||
res,
|
||||
reverse("authentik_core:root-redirect"),
|
||||
fetch_redirect_response=False,
|
||||
)
|
||||
|
||||
@patch_flag(Setup, False)
|
||||
def test_not_setup_no_flow(self):
|
||||
"""Test case on initial startup; setup flag is not set and oobe flow does
|
||||
not exist yet"""
|
||||
Flow.objects.filter(slug="initial-setup").delete()
|
||||
res = self.client.get(reverse("authentik_core:root-redirect"))
|
||||
self.assertEqual(res.status_code, HTTPStatus.FOUND)
|
||||
self.assertRedirects(res, reverse("authentik_core:setup"), fetch_redirect_response=False)
|
||||
# Flow does not exist, hence 503
|
||||
res = self.client.get(reverse("authentik_core:setup"))
|
||||
self.assertEqual(res.status_code, HTTPStatus.SERVICE_UNAVAILABLE)
|
||||
res = self.client.head(reverse("authentik_core:setup"))
|
||||
self.assertEqual(res.status_code, HTTPStatus.SERVICE_UNAVAILABLE)
|
||||
|
||||
@patch_flag(Setup, False)
|
||||
@apply_blueprint("default/flow-oobe.yaml")
|
||||
def test_not_setup(self):
|
||||
"""Test case for when worker comes up, and has created flow"""
|
||||
res = self.client.get(reverse("authentik_core:root-redirect"))
|
||||
self.assertEqual(res.status_code, HTTPStatus.FOUND)
|
||||
self.assertRedirects(res, reverse("authentik_core:setup"), fetch_redirect_response=False)
|
||||
# Flow does not exist, hence 503
|
||||
res = self.client.head(reverse("authentik_core:setup"))
|
||||
self.assertEqual(res.status_code, HTTPStatus.OK)
|
||||
res = self.client.get(reverse("authentik_core:setup"))
|
||||
self.assertEqual(res.status_code, HTTPStatus.FOUND)
|
||||
self.assertRedirects(
|
||||
res,
|
||||
reverse("authentik_core:if-flow", kwargs={"flow_slug": "initial-setup"}),
|
||||
fetch_redirect_response=False,
|
||||
)
|
||||
|
||||
@apply_blueprint("default/flow-oobe.yaml")
|
||||
@apply_blueprint("system/bootstrap.yaml")
|
||||
def test_setup_flow_full(self):
|
||||
"""Test full setup flow"""
|
||||
Setup.set(False)
|
||||
|
||||
res = self.client.get(reverse("authentik_core:setup"))
|
||||
self.assertEqual(res.status_code, HTTPStatus.FOUND)
|
||||
self.assertRedirects(
|
||||
res,
|
||||
reverse("authentik_core:if-flow", kwargs={"flow_slug": "initial-setup"}),
|
||||
fetch_redirect_response=False,
|
||||
)
|
||||
|
||||
res = self.client.get(
|
||||
reverse("authentik_api:flow-executor", kwargs={"flow_slug": "initial-setup"}),
|
||||
)
|
||||
self.assertEqual(res.status_code, HTTPStatus.OK)
|
||||
self.assertStageResponse(res, component="ak-stage-prompt")
|
||||
|
||||
pw = generate_id()
|
||||
res = self.client.post(
|
||||
reverse("authentik_api:flow-executor", kwargs={"flow_slug": "initial-setup"}),
|
||||
{
|
||||
"email": f"{generate_id()}@t.goauthentik.io",
|
||||
"password": pw,
|
||||
"password_repeat": pw,
|
||||
"component": "ak-stage-prompt",
|
||||
},
|
||||
)
|
||||
self.assertEqual(res.status_code, HTTPStatus.FOUND)
|
||||
|
||||
res = self.client.get(
|
||||
reverse("authentik_api:flow-executor", kwargs={"flow_slug": "initial-setup"}),
|
||||
)
|
||||
self.assertEqual(res.status_code, HTTPStatus.FOUND)
|
||||
|
||||
res = self.client.get(
|
||||
reverse("authentik_api:flow-executor", kwargs={"flow_slug": "initial-setup"}),
|
||||
)
|
||||
self.assertEqual(res.status_code, HTTPStatus.FOUND)
|
||||
|
||||
res = self.client.get(
|
||||
reverse("authentik_api:flow-executor", kwargs={"flow_slug": "initial-setup"}),
|
||||
)
|
||||
self.assertEqual(res.status_code, HTTPStatus.OK)
|
||||
|
||||
self.assertTrue(Setup.get())
|
||||
user = User.objects.get(username="akadmin")
|
||||
self.assertTrue(user.check_password(pw))
|
||||
|
||||
@patch_flag(Setup, False)
|
||||
@apply_blueprint("default/flow-oobe.yaml")
|
||||
@apply_blueprint("system/bootstrap.yaml")
|
||||
def test_setup_flow_direct(self):
|
||||
"""Test setup flow, directly accessing the flow"""
|
||||
res = self.client.get(
|
||||
reverse("authentik_api:flow-executor", kwargs={"flow_slug": "initial-setup"})
|
||||
)
|
||||
self.assertStageResponse(
|
||||
res,
|
||||
component="ak-stage-access-denied",
|
||||
error_message="Access the authentik setup by navigating to http://testserver/",
|
||||
)
|
||||
|
||||
def test_setup_bootstrap_env(self):
|
||||
"""Test setup with env vars"""
|
||||
User.objects.filter(username="akadmin").delete()
|
||||
Setup.set(False)
|
||||
|
||||
environ["AUTHENTIK_BOOTSTRAP_PASSWORD"] = generate_id()
|
||||
environ["AUTHENTIK_BOOTSTRAP_TOKEN"] = generate_id()
|
||||
pre_startup.send(sender=self)
|
||||
post_startup.send(sender=self)
|
||||
|
||||
self.assertTrue(Setup.get())
|
||||
user = User.objects.get(username="akadmin")
|
||||
self.assertTrue(user.check_password(environ["AUTHENTIK_BOOTSTRAP_PASSWORD"]))
|
||||
|
||||
token = Token.objects.filter(identifier="authentik-bootstrap-token").first()
|
||||
self.assertEqual(token.intent, TokenIntents.INTENT_API)
|
||||
self.assertEqual(token.key, environ["AUTHENTIK_BOOTSTRAP_TOKEN"])
|
||||
@@ -1,7 +1,6 @@
|
||||
"""authentik URL Configuration"""
|
||||
|
||||
from django.conf import settings
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.urls import path
|
||||
|
||||
from authentik.core.api.application_entitlements import ApplicationEntitlementViewSet
|
||||
@@ -19,6 +18,7 @@ from authentik.core.api.sources import (
|
||||
from authentik.core.api.tokens import TokenViewSet
|
||||
from authentik.core.api.transactional_applications import TransactionalApplicationView
|
||||
from authentik.core.api.users import UserViewSet
|
||||
from authentik.core.setup.views import SetupView
|
||||
from authentik.core.views.apps import RedirectToAppLaunch
|
||||
from authentik.core.views.debug import AccessDeniedView
|
||||
from authentik.core.views.interface import (
|
||||
@@ -35,7 +35,7 @@ from authentik.tenants.channels import TenantsAwareMiddleware
|
||||
urlpatterns = [
|
||||
path(
|
||||
"",
|
||||
login_required(RootRedirectView.as_view()),
|
||||
RootRedirectView.as_view(),
|
||||
name="root-redirect",
|
||||
),
|
||||
path(
|
||||
@@ -62,6 +62,11 @@ urlpatterns = [
|
||||
FlowInterfaceView.as_view(),
|
||||
name="if-flow",
|
||||
),
|
||||
path(
|
||||
"setup",
|
||||
SetupView.as_view(),
|
||||
name="setup",
|
||||
),
|
||||
# Fallback for WS
|
||||
path("ws/outpost/<uuid:pk>/", InterfaceView.as_view(template_name="if/admin.html")),
|
||||
path(
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
from json import dumps
|
||||
from typing import Any
|
||||
|
||||
from django.contrib.auth.mixins import AccessMixin
|
||||
from django.http import HttpRequest
|
||||
from django.http.response import HttpResponse
|
||||
from django.shortcuts import redirect
|
||||
@@ -14,12 +15,13 @@ from authentik.admin.tasks import LOCAL_VERSION
|
||||
from authentik.api.v3.config import ConfigView
|
||||
from authentik.brands.api import CurrentBrandSerializer
|
||||
from authentik.brands.models import Brand
|
||||
from authentik.core.apps import Setup
|
||||
from authentik.core.models import UserTypes
|
||||
from authentik.lib.config import CONFIG
|
||||
from authentik.policies.denied import AccessDeniedResponse
|
||||
|
||||
|
||||
class RootRedirectView(RedirectView):
|
||||
class RootRedirectView(AccessMixin, RedirectView):
|
||||
"""Root redirect view, redirect to brand's default application if set"""
|
||||
|
||||
pattern_name = "authentik_core:if-user"
|
||||
@@ -40,6 +42,10 @@ class RootRedirectView(RedirectView):
|
||||
return None
|
||||
|
||||
def dispatch(self, request: HttpRequest, *args: Any, **kwargs: Any) -> HttpResponse:
|
||||
if not Setup.get():
|
||||
return redirect("authentik_core:setup")
|
||||
if not request.user.is_authenticated:
|
||||
return self.handle_no_permission()
|
||||
if redirect_response := RootRedirectView().redirect_to_app(request):
|
||||
return redirect_response
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
|
||||
@@ -138,13 +138,7 @@ class AgentConnectorController(BaseController[AgentConnector]):
|
||||
"AllowDeviceIdentifiersInAttestation": True,
|
||||
"AuthenticationMethod": "UserSecureEnclaveKey",
|
||||
"EnableAuthorization": True,
|
||||
"EnableCreateUserAtLogin": True,
|
||||
"FileVaultPolicy": ["RequireAuthentication"],
|
||||
"LoginPolicy": ["RequireAuthentication"],
|
||||
"NewUserAuthorizationMode": "Standard",
|
||||
"UnlockPolicy": ["RequireAuthentication"],
|
||||
"UseSharedDeviceKeys": True,
|
||||
"UserAuthorizationMode": "Standard",
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
# Generated by Django 5.2.12 on 2026-03-06 14:38
|
||||
|
||||
import django.db.models.deletion
|
||||
import uuid
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
(
|
||||
"authentik_endpoints_connectors_agent",
|
||||
"0004_agentconnector_challenge_idle_timeout_and_more",
|
||||
),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="AppleIndependentSecureEnclave",
|
||||
fields=[
|
||||
("created", models.DateTimeField(auto_now_add=True)),
|
||||
("last_updated", models.DateTimeField(auto_now=True)),
|
||||
(
|
||||
"name",
|
||||
models.CharField(
|
||||
help_text="The human-readable name of this device.", max_length=64
|
||||
),
|
||||
),
|
||||
(
|
||||
"confirmed",
|
||||
models.BooleanField(default=True, help_text="Is this device ready for use?"),
|
||||
),
|
||||
("last_used", models.DateTimeField(null=True)),
|
||||
("uuid", models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
|
||||
("apple_secure_enclave_key", models.TextField()),
|
||||
("apple_enclave_key_id", models.TextField()),
|
||||
("device_type", models.TextField()),
|
||||
(
|
||||
"user",
|
||||
models.ForeignKey(
|
||||
help_text="The user that this device belongs to.",
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"verbose_name": "Apple Independent Secure Enclave",
|
||||
"verbose_name_plural": "Apple Independent Secure Enclaves",
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -19,6 +19,7 @@ from authentik.flows.stage import StageView
|
||||
from authentik.lib.generators import generate_key
|
||||
from authentik.lib.models import InternallyManagedMixin, SerializerModel
|
||||
from authentik.lib.utils.time import timedelta_string_validator
|
||||
from authentik.stages.authenticator.models import Device as Authenticator
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from authentik.endpoints.connectors.agent.controller import AgentConnectorController
|
||||
@@ -172,3 +173,17 @@ class AppleNonce(InternallyManagedMixin, ExpiringModel):
|
||||
class Meta(ExpiringModel.Meta):
|
||||
verbose_name = _("Apple Nonce")
|
||||
verbose_name_plural = _("Apple Nonces")
|
||||
|
||||
|
||||
class AppleIndependentSecureEnclave(Authenticator):
|
||||
"""A device-independent secure enclave key, used by Tap-to-login"""
|
||||
|
||||
uuid = models.UUIDField(primary_key=True, default=uuid4)
|
||||
|
||||
apple_secure_enclave_key = models.TextField()
|
||||
apple_enclave_key_id = models.TextField()
|
||||
device_type = models.TextField()
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("Apple Independent Secure Enclave")
|
||||
verbose_name_plural = _("Apple Independent Secure Enclaves")
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
from unittest.mock import PropertyMock, patch
|
||||
|
||||
from django.urls import reverse
|
||||
from rest_framework.test import APITestCase
|
||||
|
||||
from authentik.core.tests.utils import create_test_admin_user
|
||||
from authentik.endpoints.connectors.agent.models import AgentConnector
|
||||
from authentik.endpoints.controller import BaseController
|
||||
from authentik.endpoints.models import StageMode
|
||||
from authentik.enterprise.endpoints.connectors.fleet.models import FleetConnector
|
||||
from authentik.lib.generators import generate_id
|
||||
|
||||
|
||||
@@ -25,16 +27,22 @@ class TestAPI(APITestCase):
|
||||
)
|
||||
self.assertEqual(res.status_code, 201)
|
||||
|
||||
def test_endpoint_stage_fleet(self):
|
||||
connector = FleetConnector.objects.create(name=generate_id())
|
||||
res = self.client.post(
|
||||
reverse("authentik_api:stages-endpoint-list"),
|
||||
data={
|
||||
"name": generate_id(),
|
||||
"connector": str(connector.pk),
|
||||
"mode": StageMode.REQUIRED,
|
||||
},
|
||||
)
|
||||
def test_endpoint_stage_agent_no_stage(self):
|
||||
connector = AgentConnector.objects.create(name=generate_id())
|
||||
|
||||
class controller(BaseController):
|
||||
def capabilities(self):
|
||||
return []
|
||||
|
||||
with patch.object(AgentConnector, "controller", PropertyMock(return_value=controller)):
|
||||
res = self.client.post(
|
||||
reverse("authentik_api:stages-endpoint-list"),
|
||||
data={
|
||||
"name": generate_id(),
|
||||
"connector": str(connector.pk),
|
||||
"mode": StageMode.REQUIRED,
|
||||
},
|
||||
)
|
||||
self.assertEqual(res.status_code, 400)
|
||||
self.assertJSONEqual(
|
||||
res.content, {"connector": ["Selected connector is not compatible with this stage."]}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
from rest_framework.viewsets import ModelViewSet
|
||||
|
||||
from authentik.core.api.used_by import UsedByMixin
|
||||
from authentik.core.api.utils import ModelSerializer
|
||||
from authentik.endpoints.connectors.agent.models import AppleIndependentSecureEnclave
|
||||
|
||||
|
||||
class AppleIndependentSecureEnclaveSerializer(ModelSerializer):
|
||||
class Meta:
|
||||
model = AppleIndependentSecureEnclave
|
||||
fields = [
|
||||
"uuid",
|
||||
"user",
|
||||
"apple_secure_enclave_key",
|
||||
"apple_enclave_key_id",
|
||||
"device_type",
|
||||
]
|
||||
|
||||
|
||||
class AppleIndependentSecureEnclaveViewSet(UsedByMixin, ModelViewSet):
|
||||
queryset = AppleIndependentSecureEnclave.objects.all()
|
||||
serializer_class = AppleIndependentSecureEnclaveSerializer
|
||||
search_fields = [
|
||||
"name",
|
||||
"user__name",
|
||||
]
|
||||
ordering = ["uuid"]
|
||||
filterset_fields = ["user", "apple_enclave_key_id"]
|
||||
@@ -11,6 +11,7 @@ from authentik.endpoints.connectors.agent.models import (
|
||||
AgentConnector,
|
||||
AgentDeviceConnection,
|
||||
AgentDeviceUserBinding,
|
||||
AppleIndependentSecureEnclave,
|
||||
AppleNonce,
|
||||
DeviceToken,
|
||||
EnrollmentToken,
|
||||
@@ -25,7 +26,7 @@ class TestAppleToken(TestCase):
|
||||
|
||||
def setUp(self):
|
||||
self.apple_sign_key = create_test_cert(PrivateKeyAlg.ECDSA)
|
||||
sign_key_pem = self.apple_sign_key.public_key.public_bytes(
|
||||
self.sign_key_pem = self.apple_sign_key.public_key.public_bytes(
|
||||
encoding=serialization.Encoding.PEM,
|
||||
format=serialization.PublicFormat.SubjectPublicKeyInfo,
|
||||
).decode()
|
||||
@@ -50,7 +51,7 @@ class TestAppleToken(TestCase):
|
||||
device=self.device,
|
||||
connector=self.connector,
|
||||
apple_sign_key_id=self.apple_sign_key.kid,
|
||||
apple_signing_key=sign_key_pem,
|
||||
apple_signing_key=self.sign_key_pem,
|
||||
apple_encryption_key=self.enc_pub,
|
||||
)
|
||||
self.user = create_test_user()
|
||||
@@ -59,7 +60,7 @@ class TestAppleToken(TestCase):
|
||||
user=self.user,
|
||||
order=0,
|
||||
apple_enclave_key_id=self.apple_sign_key.kid,
|
||||
apple_secure_enclave_key=sign_key_pem,
|
||||
apple_secure_enclave_key=self.sign_key_pem,
|
||||
)
|
||||
self.device_token = DeviceToken.objects.create(device=self.connection)
|
||||
|
||||
@@ -113,3 +114,62 @@ class TestAppleToken(TestCase):
|
||||
).first()
|
||||
self.assertIsNotNone(event)
|
||||
self.assertEqual(event.context["device"]["name"], self.device.name)
|
||||
|
||||
@reconcile_app("authentik_crypto")
|
||||
def test_token_independent(self):
|
||||
nonce = generate_id()
|
||||
|
||||
AgentDeviceUserBinding.objects.all().delete()
|
||||
AppleIndependentSecureEnclave.objects.create(
|
||||
user=self.user,
|
||||
apple_enclave_key_id=self.apple_sign_key.kid,
|
||||
apple_secure_enclave_key=self.sign_key_pem,
|
||||
)
|
||||
|
||||
AppleNonce.objects.create(
|
||||
device_token=self.device_token,
|
||||
nonce=nonce,
|
||||
)
|
||||
embedded = encode(
|
||||
{"iss": str(self.connector.pk), "aud": str(self.device.pk), "request_nonce": nonce},
|
||||
self.apple_sign_key.private_key,
|
||||
headers={
|
||||
"kid": self.apple_sign_key.kid,
|
||||
},
|
||||
algorithm=JWTAlgorithms.from_private_key(self.apple_sign_key.private_key),
|
||||
)
|
||||
assertion = encode(
|
||||
{
|
||||
"iss": str(self.connector.pk),
|
||||
"aud": "http://testserver/endpoints/agent/psso/token/",
|
||||
"request_nonce": nonce,
|
||||
"assertion": embedded,
|
||||
"jwe_crypto": {
|
||||
"apv": (
|
||||
"AAAABUFwcGxlAAAAQQTFgZOospN6KbkhXhx1lfa-AKYxjEfJhTJrkpdEY_srMmkPzS7VN0Bzt2AtNBEXE"
|
||||
"aphDONiP2Mq6Oxytv5JKOxHAAAAJDgyOThERkY5LTVFMUUtNEUwMS04OEUwLUI3QkQzOUM4QjA3Qw"
|
||||
)
|
||||
},
|
||||
},
|
||||
self.apple_sign_key.private_key,
|
||||
headers={
|
||||
"kid": self.apple_sign_key.kid,
|
||||
},
|
||||
algorithm=JWTAlgorithms.from_private_key(self.apple_sign_key.private_key),
|
||||
)
|
||||
res = self.client.post(
|
||||
reverse("authentik_enterprise_endpoints_connectors_agent:psso-token"),
|
||||
data={
|
||||
"assertion": assertion,
|
||||
"platform_sso_version": "1.0",
|
||||
"grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(res.status_code, 200)
|
||||
event = Event.objects.filter(
|
||||
action=EventAction.LOGIN,
|
||||
app="authentik.endpoints.connectors.agent",
|
||||
).first()
|
||||
self.assertIsNotNone(event)
|
||||
self.assertEqual(event.context["device"]["name"], self.device.name)
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
from django.urls import path
|
||||
|
||||
from authentik.enterprise.endpoints.connectors.agent.api.secure_enclave import (
|
||||
AppleIndependentSecureEnclaveViewSet,
|
||||
)
|
||||
from authentik.enterprise.endpoints.connectors.agent.views.apple_jwks import AppleJWKSView
|
||||
from authentik.enterprise.endpoints.connectors.agent.views.apple_nonce import NonceView
|
||||
from authentik.enterprise.endpoints.connectors.agent.views.apple_register import (
|
||||
@@ -23,6 +26,7 @@ urlpatterns = [
|
||||
]
|
||||
|
||||
api_urlpatterns = [
|
||||
("endpoints/agents/psso/ise", AppleIndependentSecureEnclaveViewSet),
|
||||
path(
|
||||
"endpoints/agents/psso/register/device/",
|
||||
RegisterDeviceView.as_view(),
|
||||
|
||||
@@ -19,6 +19,7 @@ from authentik.endpoints.connectors.agent.models import (
|
||||
AgentConnector,
|
||||
AgentDeviceConnection,
|
||||
AgentDeviceUserBinding,
|
||||
AppleIndependentSecureEnclave,
|
||||
AppleNonce,
|
||||
DeviceAuthenticationToken,
|
||||
)
|
||||
@@ -103,7 +104,9 @@ class TokenView(View):
|
||||
nonce.delete()
|
||||
return decoded
|
||||
|
||||
def validate_embedded_assertion(self, assertion: str) -> tuple[AgentDeviceUserBinding, dict]:
|
||||
def validate_embedded_assertion(
|
||||
self, assertion: str
|
||||
) -> tuple[AgentDeviceUserBinding | AppleIndependentSecureEnclave, dict]:
|
||||
"""Decode an embedded assertion and validate it by looking up the matching device user"""
|
||||
decode_unvalidated = get_unverified_header(assertion)
|
||||
expected_kid = decode_unvalidated["kid"]
|
||||
@@ -112,8 +115,13 @@ class TokenView(View):
|
||||
target=self.device_connection.device, apple_enclave_key_id=expected_kid
|
||||
).first()
|
||||
if not device_user:
|
||||
LOGGER.warning("Could not find device user binding for user")
|
||||
raise ValidationError("Invalid request")
|
||||
independent_user = AppleIndependentSecureEnclave.objects.filter(
|
||||
apple_enclave_key_id=expected_kid
|
||||
).first()
|
||||
if not independent_user:
|
||||
LOGGER.warning("Could not find device user binding or independent enclave for user")
|
||||
raise ValidationError("Invalid request")
|
||||
device_user = independent_user
|
||||
decoded: dict[str, Any] = decode(
|
||||
assertion,
|
||||
device_user.apple_secure_enclave_key,
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
import re
|
||||
from plistlib import loads
|
||||
from typing import Any
|
||||
|
||||
from cryptography.hazmat.primitives import serialization
|
||||
from cryptography.x509 import load_der_x509_certificate
|
||||
from django.db import transaction
|
||||
from requests import RequestException
|
||||
from rest_framework.exceptions import ValidationError
|
||||
|
||||
from authentik.core.models import User
|
||||
from authentik.crypto.models import CertificateKeyPair
|
||||
from authentik.endpoints.controller import BaseController, Capabilities, ConnectorSyncException
|
||||
from authentik.endpoints.facts import (
|
||||
DeviceFacts,
|
||||
@@ -44,7 +48,7 @@ class FleetController(BaseController[DBC]):
|
||||
return "fleetdm.com"
|
||||
|
||||
def capabilities(self) -> list[Capabilities]:
|
||||
return [Capabilities.ENROLL_AUTOMATIC_API]
|
||||
return [Capabilities.STAGE_ENDPOINTS, Capabilities.ENROLL_AUTOMATIC_API]
|
||||
|
||||
def _url(self, path: str) -> str:
|
||||
return f"{self.connector.url}{path}"
|
||||
@@ -76,8 +80,44 @@ class FleetController(BaseController[DBC]):
|
||||
except RequestException as exc:
|
||||
raise ConnectorSyncException(exc) from exc
|
||||
|
||||
@property
|
||||
def mtls_ca_managed(self) -> str:
|
||||
return f"goauthentik.io/endpoints/connectors/fleet/{self.connector.pk}"
|
||||
|
||||
def _sync_mtls_ca(self):
|
||||
"""Sync conditional access Root CA for mTLS"""
|
||||
try:
|
||||
# Fleet doesn't have an API to just get the Conditional Access Root CA Cert (yet),
|
||||
# hence we fetch the apple config profile and extract it
|
||||
res = self._session.get(self._url("/api/v1/fleet/conditional_access/idp/apple/profile"))
|
||||
res.raise_for_status()
|
||||
profile = loads(res.text).get("PayloadContent", [])
|
||||
raw_cert = None
|
||||
for payload in profile:
|
||||
if payload.get("PayloadIdentifier", "") != "com.fleetdm.conditional-access-ca":
|
||||
continue
|
||||
raw_cert = payload.get("PayloadContent")
|
||||
if not raw_cert:
|
||||
raise ConnectorSyncException("Failed to get conditional acccess CA")
|
||||
except RequestException as exc:
|
||||
raise ConnectorSyncException(exc) from exc
|
||||
cert = load_der_x509_certificate(raw_cert)
|
||||
CertificateKeyPair.objects.update_or_create(
|
||||
managed=self.mtls_ca_managed,
|
||||
defaults={
|
||||
"name": f"Fleet Endpoint connector {self.connector.name}",
|
||||
"certificate_data": cert.public_bytes(
|
||||
encoding=serialization.Encoding.PEM,
|
||||
).decode("utf-8"),
|
||||
},
|
||||
)
|
||||
|
||||
@transaction.atomic
|
||||
def sync_endpoints(self) -> None:
|
||||
try:
|
||||
self._sync_mtls_ca()
|
||||
except ConnectorSyncException as exc:
|
||||
self.logger.warning("Failed to sync conditional access CA", exc=exc)
|
||||
for host in self._paginate_hosts():
|
||||
serial = host["hardware_serial"]
|
||||
device, _ = Device.objects.get_or_create(
|
||||
@@ -198,6 +238,8 @@ class FleetController(BaseController[DBC]):
|
||||
for policy in host.get("policies", [])
|
||||
],
|
||||
"agent_version": fleet_version,
|
||||
# Host UUID is required for conditional access matching
|
||||
"uuid": host.get("uuid", "").lower(),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -51,6 +51,12 @@ class FleetConnector(Connector):
|
||||
def component(self) -> str:
|
||||
return "ak-endpoints-connector-fleet-form"
|
||||
|
||||
@property
|
||||
def stage(self):
|
||||
from authentik.enterprise.endpoints.connectors.fleet.stage import FleetStageView
|
||||
|
||||
return FleetStageView
|
||||
|
||||
class Meta:
|
||||
verbose_name = _("Fleet Connector")
|
||||
verbose_name_plural = _("Fleet Connectors")
|
||||
|
||||
51
authentik/enterprise/endpoints/connectors/fleet/stage.py
Normal file
51
authentik/enterprise/endpoints/connectors/fleet/stage.py
Normal file
@@ -0,0 +1,51 @@
|
||||
from cryptography.x509 import (
|
||||
Certificate,
|
||||
Extension,
|
||||
SubjectAlternativeName,
|
||||
UniformResourceIdentifier,
|
||||
)
|
||||
from rest_framework.exceptions import PermissionDenied
|
||||
|
||||
from authentik.crypto.models import CertificateKeyPair, fingerprint_sha256
|
||||
from authentik.endpoints.models import Device, EndpointStage, StageMode
|
||||
from authentik.enterprise.endpoints.connectors.fleet.models import FleetConnector
|
||||
from authentik.enterprise.stages.mtls.stage import PLAN_CONTEXT_CERTIFICATE, MTLSStageView
|
||||
from authentik.flows.planner import PLAN_CONTEXT_DEVICE
|
||||
|
||||
FLEET_CONDITIONAL_ACCESS_URI_PREFIX = "urn:device:apple:uuid:"
|
||||
|
||||
|
||||
class FleetStageView(MTLSStageView):
|
||||
def get_authorities(self):
|
||||
stage: EndpointStage = self.executor.current_stage
|
||||
connector = FleetConnector.objects.filter(pk=stage.connector_id).first()
|
||||
controller = connector.controller(connector)
|
||||
kp = CertificateKeyPair.objects.filter(managed=controller.mtls_ca_managed).first()
|
||||
return [kp] if kp else None
|
||||
|
||||
def lookup_device(self, cert: Certificate, mode: StageMode):
|
||||
san_ext: Extension[SubjectAlternativeName] = cert.extensions.get_extension_for_oid(
|
||||
SubjectAlternativeName.oid
|
||||
)
|
||||
raw_values = san_ext.value.get_values_for_type(UniformResourceIdentifier)
|
||||
values = [x.removeprefix(FLEET_CONDITIONAL_ACCESS_URI_PREFIX).lower() for x in raw_values]
|
||||
self.logger.debug("Looking for devices with uuid", fleet_device_uuid=values)
|
||||
device = Device.objects.filter(
|
||||
**{"deviceconnection__devicefactsnapshot__data__vendor__fleetdm.com__uuid__in": values}
|
||||
).first()
|
||||
if not device and mode == StageMode.REQUIRED:
|
||||
raise PermissionDenied("Failed to find device")
|
||||
self.executor.plan.context[PLAN_CONTEXT_DEVICE] = device
|
||||
self.executor.plan.context[PLAN_CONTEXT_CERTIFICATE] = self._cert_to_dict(cert)
|
||||
return self.executor.stage_ok()
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
stage: EndpointStage = self.executor.current_stage
|
||||
try:
|
||||
cert = self.get_cert(stage.mode)
|
||||
if not cert:
|
||||
return self.executor.stage_ok()
|
||||
self.logger.debug("Received certificate", cert=fingerprint_sha256(cert))
|
||||
return self.lookup_device(cert, stage.mode)
|
||||
except PermissionDenied as exc:
|
||||
return self.executor.stage_invalid(error_message=exc.detail)
|
||||
23
authentik/enterprise/endpoints/connectors/fleet/tests/fixtures/cond_acc_host.pem
vendored
Normal file
23
authentik/enterprise/endpoints/connectors/fleet/tests/fixtures/cond_acc_host.pem
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDwDCCAqigAwIBAgIBBDANBgkqhkiG9w0BAQsFADBpMQkwBwYDVQQGEwAxJDAi
|
||||
BgNVBAoTG0xvY2FsIGNlcnRpZmljYXRlIGF1dGhvcml0eTEQMA4GA1UECxMHU0NF
|
||||
UCBDQTEkMCIGA1UEAxMbRmxlZXQgY29uZGl0aW9uYWwgYWNjZXNzIENBMB4XDTI2
|
||||
MDMxODExMTc1NFoXDTI3MDQyMDExMjc1NFowLDEqMCgGA1UEAxMhRmxlZXQgY29u
|
||||
ZGl0aW9uYWwgYWNjZXNzIGZvciBPa3RhMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
|
||||
MIIBCgKCAQEA3xuKxQQ8JSA4qCJ6RfOB7tbQurhwXiaJSLUDG7R5ncdRcd9LH/9y
|
||||
5ZyI5kQACOwfICHmv02zR4/CrurfzXabo3CCpvcMdS7JI/FzP1GIIZ5RsR7oPFC6
|
||||
JJg3m5BHuoHsUtCD7w0D52WiE7XVfbw47h2ChKmGMhkSrBvQnp3dHFEt8ntbl1/q
|
||||
zCSuQaLeR2sQFurBDVBdinEgsvb1YHaYHi4tdFx5joG64Q/nJXyA2OM4hO9uBF+G
|
||||
c4UVTzubx5sxwONcPhC9H+eLMpF1VHeU9gAGBlruVusUEYDmlqYQuA+bW5fTr4Zd
|
||||
ZmJ5e+CzzUBYHduAML9a5S+1jbxSPZFBSwIDAQABo4GvMIGsMA4GA1UdDwEB/wQE
|
||||
AwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAjAdBgNVHQ4EFgQUPrc1+LvbR9WoJIWZ
|
||||
7YQa/3IX2w8wHwYDVR0jBBgwFoAUfl92kU2qcH4e+hypez4kEnqMbk4wRQYDVR0R
|
||||
BD4wPIY6dXJuOmRldmljZTphcHBsZTp1dWlkOjVCRjQyMkQ2LTZFQUItNTE1Ni1B
|
||||
QzVBLTlFQURDOTUyNDcxMzANBgkqhkiG9w0BAQsFAAOCAQEAGfxJ/u4271tnUUTB
|
||||
J39YU6z2Ciav+9G3BtbvxBXI57Po7zCE6Z1sVkvYq6Xd0CcItPWRjbSPEy78ZzS0
|
||||
By+gPy5fkKc8HHJ5I1wK890xbLBUS1P4EbdVBzI9ggouEa3B2asE10asnzLoKE4C
|
||||
0FYWQwrzCsso8yxsJj1S8RKtd6MMbCis/9OQSC8om2tu6cLO+OftVn5DHtNWFidw
|
||||
tAl/oHn2cZPUfZGpJGrHNZlp5w1c1dYfQeiPayoQIbsF+8eMV424G76z/8UPhMBs
|
||||
R23LByv4TlUOPAGn2TRa2WtLIXs7FgqXRIFW4CjsPsEpXSVNlkYcn/VHY7Jl13zz
|
||||
CRQ1Pg==
|
||||
-----END CERTIFICATE-----
|
||||
46
authentik/enterprise/endpoints/connectors/fleet/tests/fixtures/cond_acc_profile.mobileconfig
vendored
Normal file
46
authentik/enterprise/endpoints/connectors/fleet/tests/fixtures/cond_acc_profile.mobileconfig
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>PayloadContent</key>
|
||||
<array>
|
||||
<!-- Trusted CA certificate -->
|
||||
<dict>
|
||||
<key>PayloadCertificateFileName</key>
|
||||
<string>conditional_access_ca.der</string>
|
||||
<key>PayloadContent</key>
|
||||
<data>MIIDjzCCAnegAwIBAgIBATANBgkqhkiG9w0BAQsFADBpMQkwBwYDVQQGEwAxJDAiBgNVBAoTG0xvY2FsIGNlcnRpZmljYXRlIGF1dGhvcml0eTEQMA4GA1UECxMHU0NFUCBDQTEkMCIGA1UEAxMbRmxlZXQgY29uZGl0aW9uYWwgYWNjZXNzIENBMB4XDTI1MTIwOTEyMjI1MVoXDTM1MTIwOTEyMjI1MVowaTEJMAcGA1UEBhMAMSQwIgYDVQQKExtMb2NhbCBjZXJ0aWZpY2F0ZSBhdXRob3JpdHkxEDAOBgNVBAsTB1NDRVAgQ0ExJDAiBgNVBAMTG0ZsZWV0IGNvbmRpdGlvbmFsIGFjY2VzcyBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANrgCcpzQci2UhH+Dn0eHopnnbx3HbMabMCHXm6xteMVFLrdQJDTFrZCQzcexUgbpPJ0az6mn4szo+E3stn0y2PPWsiAiVhFwp5M9HwNg18rPgDmITv2pM3l/hlEsfggjq6TEVO2gRcq4NujEGagcYX6kp6nWxh6bbRngQ/hlK6mXItWV3x0G9eTcbFObwZhbuC2dNbccytdqbVEIpBjp6fftQnQwAaUVjoyZBFlf1C1cDV4+1jpaVsIj11U1olA33GJCHcZQ4CJEsgh8yiSsvkH5RNf94CGINB5ixsMfppjSXV/vNkWDKEfmUXW2q4ft7KK/L/SRq8QSB4VqTAp2GsCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFH5fdpFNqnB+HvocqXs+JBJ6jG5OMA0GCSqGSIb3DQEBCwUAA4IBAQAJr4bTGlrANoHStu4Y+OXjGbEQjZOe546Bcln4eWrEB16eaVzfKuZgjJYdcOmp36/v34QY/OCXEIsixrBU5aW/Sr53IK6UQSZV3O3xbBc4Aert7AbeJ4NVGZyelfVQo/5G0qM6k9p0+zpIZqNAzFbhcSPIzuE7ig2OGsFoQU+bXhzk09bsZ+u4BXibzVNfMuMG+DHNv0PRjll272nEPI3bGwHF5tdrnfJG6e9t+qK9j9UqmSlBknHQJNeU5o8IDcmWYjWtOuBzecYsg8pZzXabJqlHTBIz/h7waRe7jtrK+XopK3jghRf9JTL+i0Y8NbVjoNkIoS3xMeRhnNbR9lw1</data>
|
||||
<key>PayloadDescription</key>
|
||||
<string>Fleet conditional access CA certificate</string>
|
||||
<key>PayloadDisplayName</key>
|
||||
<string>Fleet conditional access CA</string>
|
||||
<key>PayloadIdentifier</key>
|
||||
<string>com.fleetdm.conditional-access-ca</string>
|
||||
<key>PayloadType</key>
|
||||
<string>com.apple.security.root</string>
|
||||
<key>PayloadUUID</key>
|
||||
<string>ef1b2231-ad80-5511-9893-1f9838295147</string>
|
||||
<key>PayloadVersion</key>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
</array>
|
||||
<key>PayloadDescription</key>
|
||||
<string>Configures SCEP enrollment for Okta conditional access</string>
|
||||
<key>PayloadDisplayName</key>
|
||||
<string>Fleet conditional access for Okta</string>
|
||||
<key>PayloadIdentifier</key>
|
||||
<string>com.fleetdm.conditional-access-okta</string>
|
||||
<key>PayloadOrganization</key>
|
||||
<string>Fleet Device Management</string>
|
||||
<key>PayloadRemovalDisallowed</key>
|
||||
<false/>
|
||||
<key>PayloadScope</key>
|
||||
<string>User</string>
|
||||
<key>PayloadType</key>
|
||||
<string>Configuration</string>
|
||||
<key>PayloadUUID</key>
|
||||
<string>6fa509a3-feca-56f7-a283-d6a81c733ed2</string>
|
||||
<key>PayloadVersion</key>
|
||||
<integer>1</integer>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -1,27 +1,27 @@
|
||||
{
|
||||
"created_at": "2025-06-25T22:21:35Z",
|
||||
"updated_at": "2025-12-20T11:42:09Z",
|
||||
"created_at": "2026-02-18T16:31:34Z",
|
||||
"updated_at": "2026-03-18T11:29:18Z",
|
||||
"software": null,
|
||||
"software_updated_at": "2025-10-22T02:24:25Z",
|
||||
"id": 1,
|
||||
"detail_updated_at": "2025-10-23T23:30:31Z",
|
||||
"label_updated_at": "2025-10-23T23:30:31Z",
|
||||
"policy_updated_at": "2025-10-23T23:02:11Z",
|
||||
"last_enrolled_at": "2025-06-25T22:21:37Z",
|
||||
"seen_time": "2025-10-23T23:59:08Z",
|
||||
"software_updated_at": "2026-03-18T11:29:17Z",
|
||||
"id": 19,
|
||||
"detail_updated_at": "2026-03-18T11:29:18Z",
|
||||
"label_updated_at": "2026-03-18T11:29:18Z",
|
||||
"policy_updated_at": "2026-03-18T11:29:18Z",
|
||||
"last_enrolled_at": "2026-02-18T16:31:45Z",
|
||||
"seen_time": "2026-03-18T11:31:34Z",
|
||||
"refetch_requested": false,
|
||||
"hostname": "jens-mac-vm.local",
|
||||
"uuid": "C8B98348-A0A6-5838-A321-57B59D788269",
|
||||
"uuid": "5BF422D6-6EAB-5156-AC5A-9EADC9524713",
|
||||
"platform": "darwin",
|
||||
"osquery_version": "5.19.0",
|
||||
"osquery_version": "5.21.0",
|
||||
"orbit_version": null,
|
||||
"fleet_desktop_version": null,
|
||||
"scripts_enabled": null,
|
||||
"os_version": "macOS 26.0.1",
|
||||
"build": "25A362",
|
||||
"os_version": "macOS 26.3",
|
||||
"build": "25D125",
|
||||
"platform_like": "darwin",
|
||||
"code_name": "",
|
||||
"uptime": 256356000000000,
|
||||
"uptime": 653014000000000,
|
||||
"memory": 4294967296,
|
||||
"cpu_type": "arm64e",
|
||||
"cpu_subtype": "ARM64E",
|
||||
@@ -31,38 +31,41 @@
|
||||
"hardware_vendor": "Apple Inc.",
|
||||
"hardware_model": "VirtualMac2,1",
|
||||
"hardware_version": "",
|
||||
"hardware_serial": "Z5DDF07GK6",
|
||||
"hardware_serial": "ZV35VFDD50",
|
||||
"computer_name": "jens-mac-vm",
|
||||
"timezone": null,
|
||||
"public_ip": "92.116.179.252",
|
||||
"primary_ip": "192.168.85.3",
|
||||
"primary_mac": "e6:9d:21:c2:2f:19",
|
||||
"primary_ip": "192.168.64.7",
|
||||
"primary_mac": "5e:72:1c:89:98:29",
|
||||
"distributed_interval": 10,
|
||||
"config_tls_refresh": 60,
|
||||
"logger_tls_period": 10,
|
||||
"team_id": 2,
|
||||
"team_id": 5,
|
||||
"pack_stats": null,
|
||||
"team_name": "prod",
|
||||
"gigs_disk_space_available": 23.82,
|
||||
"percent_disk_space_available": 37,
|
||||
"team_name": "dev",
|
||||
"gigs_disk_space_available": 16.52,
|
||||
"percent_disk_space_available": 26,
|
||||
"gigs_total_disk_space": 62.83,
|
||||
"gigs_all_disk_space": null,
|
||||
"issues": {
|
||||
"failing_policies_count": 1,
|
||||
"critical_vulnerabilities_count": 2,
|
||||
"total_issues_count": 3
|
||||
"critical_vulnerabilities_count": 0,
|
||||
"total_issues_count": 1
|
||||
},
|
||||
"device_mapping": null,
|
||||
"mdm": {
|
||||
"enrollment_status": "On (manual)",
|
||||
"dep_profile_error": false,
|
||||
"server_url": "https://fleet.beryjuio-home.k8s.beryju.io/mdm/apple/mdm",
|
||||
"server_url": "https://fleet.beryjuio-prod.k8s.beryju.io/mdm/apple/mdm",
|
||||
"name": "Fleet",
|
||||
"encryption_key_available": false,
|
||||
"connected_to_fleet": true
|
||||
},
|
||||
"refetch_critical_queries_until": null,
|
||||
"last_restarted_at": "2025-10-21T00:17:55Z",
|
||||
"status": "offline",
|
||||
"last_restarted_at": "2026-03-10T22:05:44.00887Z",
|
||||
"status": "online",
|
||||
"display_text": "jens-mac-vm.local",
|
||||
"display_name": "jens-mac-vm"
|
||||
"display_name": "jens-mac-vm",
|
||||
"fleet_id": 5,
|
||||
"fleet_name": "dev"
|
||||
}
|
||||
|
||||
@@ -21,12 +21,19 @@ TEST_HOST = {"hosts": [TEST_HOST_UBUNTU, TEST_HOST_MACOS, TEST_HOST_WINDOWS, TES
|
||||
class TestFleetConnector(APITestCase):
|
||||
def setUp(self):
|
||||
self.connector = FleetConnector.objects.create(
|
||||
name=generate_id(), url="http://localhost", token=generate_id()
|
||||
name=generate_id(),
|
||||
url="http://localhost",
|
||||
token=generate_id(),
|
||||
map_teams_access_group=True,
|
||||
)
|
||||
|
||||
def test_sync(self):
|
||||
controller = self.connector.controller(self.connector)
|
||||
with Mocker() as mock:
|
||||
mock.get(
|
||||
"http://localhost/api/v1/fleet/conditional_access/idp/apple/profile",
|
||||
text=load_fixture("fixtures/cond_acc_profile.mobileconfig"),
|
||||
)
|
||||
mock.get(
|
||||
"http://localhost/api/v1/fleet/hosts?order_key=hardware_serial&page=0&per_page=50&device_mapping=true&populate_software=true&populate_users=true",
|
||||
json=TEST_HOST,
|
||||
@@ -40,6 +47,9 @@ class TestFleetConnector(APITestCase):
|
||||
identifier="VMware-56 4d 4a 5a b0 22 7b d7-9b a5 0b dc 8f f2 3b 60"
|
||||
).first()
|
||||
self.assertIsNotNone(device)
|
||||
group = device.access_group
|
||||
self.assertIsNotNone(group)
|
||||
self.assertEqual(group.name, "prod")
|
||||
self.assertEqual(
|
||||
device.cached_facts.data,
|
||||
{
|
||||
@@ -50,7 +60,13 @@ class TestFleetConnector(APITestCase):
|
||||
"version": "24.04.3 LTS",
|
||||
},
|
||||
"disks": [],
|
||||
"vendor": {"fleetdm.com": {"policies": [], "agent_version": ""}},
|
||||
"vendor": {
|
||||
"fleetdm.com": {
|
||||
"policies": [],
|
||||
"agent_version": "",
|
||||
"uuid": "5a4a4d56-22b0-d77b-9ba5-0bdc8ff23b60",
|
||||
}
|
||||
},
|
||||
"network": {"hostname": "ubuntu-desktop", "interfaces": []},
|
||||
"hardware": {
|
||||
"model": "VMware20,1",
|
||||
@@ -72,6 +88,10 @@ class TestFleetConnector(APITestCase):
|
||||
self.connector.save()
|
||||
controller = self.connector.controller(self.connector)
|
||||
with Mocker() as mock:
|
||||
mock.get(
|
||||
"http://localhost/api/v1/fleet/conditional_access/idp/apple/profile",
|
||||
text=load_fixture("fixtures/cond_acc_profile.mobileconfig"),
|
||||
)
|
||||
mock.get(
|
||||
"http://localhost/api/v1/fleet/hosts?order_key=hardware_serial&page=0&per_page=50&device_mapping=true&populate_software=true&populate_users=true",
|
||||
json=TEST_HOST,
|
||||
@@ -81,11 +101,13 @@ class TestFleetConnector(APITestCase):
|
||||
json={"hosts": []},
|
||||
)
|
||||
controller.sync_endpoints()
|
||||
self.assertEqual(mock.call_count, 2)
|
||||
self.assertEqual(mock.call_count, 3)
|
||||
self.assertEqual(mock.request_history[0].method, "GET")
|
||||
self.assertEqual(mock.request_history[0].headers["foo"], "bar")
|
||||
self.assertEqual(mock.request_history[1].method, "GET")
|
||||
self.assertEqual(mock.request_history[1].headers["foo"], "bar")
|
||||
self.assertEqual(mock.request_history[2].method, "GET")
|
||||
self.assertEqual(mock.request_history[2].headers["foo"], "bar")
|
||||
|
||||
def test_map_host_linux(self):
|
||||
controller = self.connector.controller(self.connector)
|
||||
@@ -128,6 +150,6 @@ class TestFleetConnector(APITestCase):
|
||||
"arch": "arm64e",
|
||||
"family": OSFamily.macOS,
|
||||
"name": "macOS",
|
||||
"version": "26.0.1",
|
||||
"version": "26.3",
|
||||
},
|
||||
)
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
from json import loads
|
||||
from ssl import PEM_FOOTER, PEM_HEADER
|
||||
|
||||
from django.urls import reverse
|
||||
from requests_mock import Mocker
|
||||
|
||||
from authentik.core.tests.utils import (
|
||||
create_test_flow,
|
||||
)
|
||||
from authentik.endpoints.models import Device, EndpointStage, StageMode
|
||||
from authentik.enterprise.endpoints.connectors.fleet.models import FleetConnector
|
||||
from authentik.enterprise.stages.mtls.stage import PLAN_CONTEXT_CERTIFICATE
|
||||
from authentik.flows.models import FlowDesignation, FlowStageBinding
|
||||
from authentik.flows.planner import PLAN_CONTEXT_DEVICE
|
||||
from authentik.flows.tests import FlowTestCase
|
||||
from authentik.lib.generators import generate_id
|
||||
from authentik.lib.tests.utils import load_fixture
|
||||
|
||||
|
||||
class FleetConnectorStageTests(FlowTestCase):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.connector = FleetConnector.objects.create(
|
||||
name=generate_id(), url="http://localhost", token=generate_id()
|
||||
)
|
||||
|
||||
controller = self.connector.controller(self.connector)
|
||||
with Mocker() as mock:
|
||||
mock.get(
|
||||
"http://localhost/api/v1/fleet/conditional_access/idp/apple/profile",
|
||||
text=load_fixture("fixtures/cond_acc_profile.mobileconfig"),
|
||||
)
|
||||
mock.get(
|
||||
"http://localhost/api/v1/fleet/hosts?order_key=hardware_serial&page=0&per_page=50&device_mapping=true&populate_software=true&populate_users=true",
|
||||
json={"hosts": [loads(load_fixture("fixtures/host_macos.json"))]},
|
||||
)
|
||||
mock.get(
|
||||
"http://localhost/api/v1/fleet/hosts?order_key=hardware_serial&page=1&per_page=50&device_mapping=true&populate_software=true&populate_users=true",
|
||||
json={"hosts": []},
|
||||
)
|
||||
controller.sync_endpoints()
|
||||
|
||||
self.flow = create_test_flow(FlowDesignation.AUTHENTICATION)
|
||||
self.stage = EndpointStage.objects.create(
|
||||
name=generate_id(),
|
||||
mode=StageMode.REQUIRED,
|
||||
connector=self.connector,
|
||||
)
|
||||
|
||||
self.binding = FlowStageBinding.objects.create(target=self.flow, stage=self.stage, order=0)
|
||||
|
||||
self.host_cert = load_fixture("fixtures/cond_acc_host.pem")
|
||||
|
||||
def _format_traefik(self, cert: str | None = None):
|
||||
cert = cert if cert else self.host_cert
|
||||
return cert.replace(PEM_HEADER, "").replace(PEM_FOOTER, "").replace("\n", "")
|
||||
|
||||
def test_assoc(self):
|
||||
dev = Device.objects.get(identifier="ZV35VFDD50")
|
||||
with self.assertFlowFinishes() as plan:
|
||||
res = self.client.get(
|
||||
reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug}),
|
||||
headers={"X-Forwarded-TLS-Client-Cert": self._format_traefik()},
|
||||
)
|
||||
self.assertEqual(res.status_code, 200)
|
||||
plan = plan()
|
||||
self.assertEqual(plan.context[PLAN_CONTEXT_DEVICE], dev)
|
||||
self.assertEqual(
|
||||
plan.context[PLAN_CONTEXT_CERTIFICATE]["subject"],
|
||||
"CN=Fleet conditional access for Okta",
|
||||
)
|
||||
|
||||
def test_assoc_not_found(self):
|
||||
dev = Device.objects.get(identifier="ZV35VFDD50")
|
||||
dev.delete()
|
||||
with self.assertFlowFinishes() as plan:
|
||||
res = self.client.get(
|
||||
reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug}),
|
||||
headers={"X-Forwarded-TLS-Client-Cert": self._format_traefik()},
|
||||
)
|
||||
self.assertEqual(res.status_code, 200)
|
||||
self.assertStageResponse(res, self.flow, component="ak-stage-access-denied")
|
||||
plan = plan()
|
||||
self.assertNotIn(PLAN_CONTEXT_DEVICE, plan.context)
|
||||
@@ -15,6 +15,7 @@ from cryptography.x509 import (
|
||||
)
|
||||
from cryptography.x509.verification import PolicyBuilder, Store, VerificationError
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from rest_framework.exceptions import PermissionDenied
|
||||
|
||||
from authentik.brands.models import Brand
|
||||
from authentik.core.models import User
|
||||
@@ -25,7 +26,6 @@ from authentik.enterprise.stages.mtls.models import (
|
||||
MutualTLSStage,
|
||||
UserAttributes,
|
||||
)
|
||||
from authentik.flows.challenge import AccessDeniedChallenge
|
||||
from authentik.flows.models import FlowDesignation
|
||||
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER
|
||||
from authentik.flows.stage import ChallengeStageView
|
||||
@@ -217,8 +217,7 @@ class MTLSStageView(ChallengeStageView):
|
||||
return None
|
||||
return str(_cert_attr[0])
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
stage: MutualTLSStage = self.executor.current_stage
|
||||
def get_cert(self, mode: StageMode):
|
||||
certs = [
|
||||
*self._parse_cert_xfcc(),
|
||||
*self._parse_cert_nginx(),
|
||||
@@ -228,21 +227,26 @@ class MTLSStageView(ChallengeStageView):
|
||||
authorities = self.get_authorities()
|
||||
if not authorities:
|
||||
self.logger.warning("No Certificate authority found")
|
||||
if stage.mode == StageMode.OPTIONAL:
|
||||
return self.executor.stage_ok()
|
||||
if stage.mode == StageMode.REQUIRED:
|
||||
return super().dispatch(request, *args, **kwargs)
|
||||
if mode == StageMode.OPTIONAL:
|
||||
return None
|
||||
if mode == StageMode.REQUIRED:
|
||||
raise PermissionDenied("Unknown error")
|
||||
cert = self.validate_cert(authorities, certs)
|
||||
if not cert and stage.mode == StageMode.REQUIRED:
|
||||
if not cert and mode == StageMode.REQUIRED:
|
||||
self.logger.warning("Client certificate required but no certificates given")
|
||||
return super().dispatch(
|
||||
request,
|
||||
*args,
|
||||
error_message=_("Certificate required but no certificate was given."),
|
||||
**kwargs,
|
||||
)
|
||||
if not cert and stage.mode == StageMode.OPTIONAL:
|
||||
raise PermissionDenied(str(_("Certificate required but no certificate was given.")))
|
||||
if not cert and mode == StageMode.OPTIONAL:
|
||||
self.logger.info("No certificate given, continuing")
|
||||
return None
|
||||
return cert
|
||||
|
||||
def dispatch(self, request, *args, **kwargs):
|
||||
stage: MutualTLSStage = self.executor.current_stage
|
||||
try:
|
||||
cert = self.get_cert(stage.mode)
|
||||
except PermissionDenied as exc:
|
||||
return self.executor.stage_invalid(error_message=exc.detail)
|
||||
if not cert:
|
||||
return self.executor.stage_ok()
|
||||
self.logger.debug("Received certificate", cert=fingerprint_sha256(cert))
|
||||
existing_user = self.check_if_user(cert)
|
||||
@@ -251,15 +255,5 @@ class MTLSStageView(ChallengeStageView):
|
||||
elif existing_user:
|
||||
self.auth_user(existing_user, cert)
|
||||
else:
|
||||
return super().dispatch(
|
||||
request, *args, error_message=_("No user found for certificate."), **kwargs
|
||||
)
|
||||
return self.executor.stage_invalid(_("No user found for certificate."))
|
||||
return self.executor.stage_ok()
|
||||
|
||||
def get_challenge(self, *args, error_message: str | None = None, **kwargs):
|
||||
return AccessDeniedChallenge(
|
||||
data={
|
||||
"component": "ak-stage-access-denied",
|
||||
"error_message": str(error_message or "Unknown error"),
|
||||
}
|
||||
)
|
||||
|
||||
@@ -11,6 +11,10 @@ class FlowNonApplicableException(SentryIgnoredException):
|
||||
|
||||
policy_result: PolicyResult | None = None
|
||||
|
||||
def __init__(self, policy_result: PolicyResult | None = None, *args):
|
||||
super().__init__(*args)
|
||||
self.policy_result = policy_result
|
||||
|
||||
@property
|
||||
def messages(self) -> str:
|
||||
"""Get messages from policy result, fallback to generic reason"""
|
||||
|
||||
@@ -42,6 +42,7 @@ class Migration(migrations.Migration):
|
||||
("require_superuser", "Require Superuser"),
|
||||
("require_redirect", "Require Redirect"),
|
||||
("require_outpost", "Require Outpost"),
|
||||
("require_token", "Require Token"),
|
||||
],
|
||||
default="none",
|
||||
help_text="Required level of authentication and authorization to access a flow.",
|
||||
|
||||
@@ -40,6 +40,7 @@ class FlowAuthenticationRequirement(models.TextChoices):
|
||||
REQUIRE_SUPERUSER = "require_superuser"
|
||||
REQUIRE_REDIRECT = "require_redirect"
|
||||
REQUIRE_OUTPOST = "require_outpost"
|
||||
REQUIRE_TOKEN = "require_token"
|
||||
|
||||
|
||||
class NotConfiguredAction(models.TextChoices):
|
||||
|
||||
@@ -5,6 +5,7 @@ from typing import TYPE_CHECKING, Any
|
||||
|
||||
from django.core.cache import cache
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from django.utils.translation import gettext as _
|
||||
from sentry_sdk import start_span
|
||||
from sentry_sdk.tracing import Span
|
||||
from structlog.stdlib import BoundLogger, get_logger
|
||||
@@ -26,6 +27,7 @@ from authentik.lib.config import CONFIG
|
||||
from authentik.lib.utils.urls import redirect_with_qs
|
||||
from authentik.outposts.models import Outpost
|
||||
from authentik.policies.engine import PolicyEngine
|
||||
from authentik.policies.types import PolicyResult
|
||||
from authentik.root.middleware import ClientIPMiddleware
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@@ -226,6 +228,15 @@ class FlowPlanner:
|
||||
and context.get(PLAN_CONTEXT_IS_REDIRECTED) is None
|
||||
):
|
||||
raise FlowNonApplicableException()
|
||||
if (
|
||||
self.flow.authentication == FlowAuthenticationRequirement.REQUIRE_TOKEN
|
||||
and context.get(PLAN_CONTEXT_IS_RESTORED) is None
|
||||
):
|
||||
raise FlowNonApplicableException(
|
||||
PolicyResult(
|
||||
False, _("This link is invalid or has expired. Please request a new one.")
|
||||
)
|
||||
)
|
||||
outpost_user = ClientIPMiddleware.get_outpost_user(request)
|
||||
if self.flow.authentication == FlowAuthenticationRequirement.REQUIRE_OUTPOST:
|
||||
if not outpost_user:
|
||||
@@ -273,9 +284,7 @@ class FlowPlanner:
|
||||
engine.build()
|
||||
result = engine.result
|
||||
if not result.passing:
|
||||
exc = FlowNonApplicableException()
|
||||
exc.policy_result = result
|
||||
raise exc
|
||||
raise FlowNonApplicableException(result)
|
||||
# User is passing so far, check if we have a cached plan
|
||||
cached_plan_key = cache_key(self.flow, user)
|
||||
cached_plan = cache.get(cached_plan_key, None)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"""flow views tests"""
|
||||
|
||||
from datetime import timedelta
|
||||
from unittest.mock import MagicMock, PropertyMock, patch
|
||||
from urllib.parse import urlencode
|
||||
|
||||
@@ -7,6 +8,7 @@ from django.http import HttpRequest, HttpResponse
|
||||
from django.test import override_settings
|
||||
from django.test.client import RequestFactory
|
||||
from django.urls import reverse
|
||||
from django.utils.timezone import now
|
||||
from rest_framework.exceptions import ParseError
|
||||
|
||||
from authentik.core.models import Group, User
|
||||
@@ -17,6 +19,7 @@ from authentik.flows.models import (
|
||||
FlowDeniedAction,
|
||||
FlowDesignation,
|
||||
FlowStageBinding,
|
||||
FlowToken,
|
||||
InvalidResponseAction,
|
||||
)
|
||||
from authentik.flows.planner import FlowPlan, FlowPlanner
|
||||
@@ -24,6 +27,7 @@ from authentik.flows.stage import PLAN_CONTEXT_PENDING_USER_IDENTIFIER, StageVie
|
||||
from authentik.flows.tests import FlowTestCase
|
||||
from authentik.flows.views.executor import (
|
||||
NEXT_ARG_NAME,
|
||||
QS_KEY_TOKEN,
|
||||
QS_QUERY,
|
||||
SESSION_KEY_PLAN,
|
||||
FlowExecutorView,
|
||||
@@ -740,3 +744,77 @@ class TestFlowExecutor(FlowTestCase):
|
||||
"title": flow.title,
|
||||
},
|
||||
)
|
||||
|
||||
@patch(
|
||||
"authentik.flows.views.executor.to_stage_response",
|
||||
TO_STAGE_RESPONSE_MOCK,
|
||||
)
|
||||
def test_expired_flow_token(self):
|
||||
"""Test that an expired flow token shows an appropriate error message"""
|
||||
flow = create_test_flow(
|
||||
FlowDesignation.RECOVERY,
|
||||
authentication=FlowAuthenticationRequirement.REQUIRE_TOKEN,
|
||||
)
|
||||
user = create_test_user()
|
||||
plan = FlowPlan(flow_pk=flow.pk.hex, bindings=[], markers=[])
|
||||
|
||||
token = FlowToken.objects.create(
|
||||
user=user,
|
||||
identifier=generate_id(),
|
||||
flow=flow,
|
||||
_plan=FlowToken.pickle(plan),
|
||||
expires=now() - timedelta(hours=1),
|
||||
)
|
||||
|
||||
url = reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug})
|
||||
response = self.client.get(
|
||||
url + f"?{urlencode({QS_QUERY: urlencode({QS_KEY_TOKEN: token.key})})}"
|
||||
)
|
||||
self.assertStageResponse(
|
||||
response,
|
||||
flow,
|
||||
component="ak-stage-access-denied",
|
||||
error_message="This link is invalid or has expired. Please request a new one.",
|
||||
)
|
||||
|
||||
@patch(
|
||||
"authentik.flows.views.executor.to_stage_response",
|
||||
TO_STAGE_RESPONSE_MOCK,
|
||||
)
|
||||
def test_invalid_flow_token_require_token(self):
|
||||
"""Test that an invalid/nonexistent token on a REQUIRE_TOKEN flow shows error"""
|
||||
flow = create_test_flow(
|
||||
FlowDesignation.RECOVERY,
|
||||
authentication=FlowAuthenticationRequirement.REQUIRE_TOKEN,
|
||||
)
|
||||
|
||||
url = reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug})
|
||||
response = self.client.get(
|
||||
url + f"?{urlencode({QS_QUERY: urlencode({QS_KEY_TOKEN: 'invalid-token'})})}"
|
||||
)
|
||||
self.assertStageResponse(
|
||||
response,
|
||||
flow,
|
||||
component="ak-stage-access-denied",
|
||||
error_message="This link is invalid or has expired. Please request a new one.",
|
||||
)
|
||||
|
||||
@patch(
|
||||
"authentik.flows.views.executor.to_stage_response",
|
||||
TO_STAGE_RESPONSE_MOCK,
|
||||
)
|
||||
def test_no_token_require_token(self):
|
||||
"""Test that accessing a REQUIRE_TOKEN flow without any token shows error"""
|
||||
flow = create_test_flow(
|
||||
FlowDesignation.RECOVERY,
|
||||
authentication=FlowAuthenticationRequirement.REQUIRE_TOKEN,
|
||||
)
|
||||
|
||||
url = reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug})
|
||||
response = self.client.get(url)
|
||||
self.assertStageResponse(
|
||||
response,
|
||||
flow,
|
||||
component="ak-stage-access-denied",
|
||||
error_message="This link is invalid or has expired. Please request a new one.",
|
||||
)
|
||||
|
||||
@@ -26,6 +26,7 @@ from authentik.flows.models import (
|
||||
)
|
||||
from authentik.flows.planner import (
|
||||
PLAN_CONTEXT_IS_REDIRECTED,
|
||||
PLAN_CONTEXT_IS_RESTORED,
|
||||
PLAN_CONTEXT_PENDING_USER,
|
||||
FlowPlanner,
|
||||
cache_key,
|
||||
@@ -129,6 +130,22 @@ class TestFlowPlanner(TestCase):
|
||||
planner.allow_empty_flows = True
|
||||
planner.plan(request)
|
||||
|
||||
def test_authentication_require_token(self):
|
||||
"""Test flow authentication (require_token)"""
|
||||
flow = create_test_flow()
|
||||
flow.authentication = FlowAuthenticationRequirement.REQUIRE_TOKEN
|
||||
request = self.request_factory.get(
|
||||
reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}),
|
||||
)
|
||||
planner = FlowPlanner(flow)
|
||||
planner.allow_empty_flows = True
|
||||
|
||||
with self.assertRaises(FlowNonApplicableException):
|
||||
planner.plan(request)
|
||||
|
||||
context = {PLAN_CONTEXT_IS_RESTORED: True}
|
||||
planner.plan(request, context)
|
||||
|
||||
@patch(
|
||||
"authentik.policies.engine.PolicyEngine.result",
|
||||
POLICY_RETURN_FALSE,
|
||||
|
||||
@@ -62,6 +62,7 @@ from authentik.policies.engine import PolicyEngine
|
||||
LOGGER = get_logger()
|
||||
# Argument used to redirect user after login
|
||||
NEXT_ARG_NAME = "next"
|
||||
|
||||
SESSION_KEY_PLAN = "authentik/flows/plan"
|
||||
SESSION_KEY_GET = "authentik/flows/get"
|
||||
SESSION_KEY_POST = "authentik/flows/post"
|
||||
|
||||
@@ -71,7 +71,11 @@ class FlowInspectorView(APIView):
|
||||
|
||||
flow: Flow
|
||||
_logger: BoundLogger
|
||||
permission_classes = [IsAuthenticated]
|
||||
|
||||
def get_permissions(self):
|
||||
if settings.DEBUG:
|
||||
return []
|
||||
return [IsAuthenticated()]
|
||||
|
||||
def setup(self, request: HttpRequest, flow_slug: str):
|
||||
super().setup(request, flow_slug=flow_slug)
|
||||
|
||||
@@ -14,7 +14,16 @@ def chunked_queryset[T: Model](queryset: QuerySet[T], chunk_size: int = 1_000) -
|
||||
def get_chunks(qs: QuerySet) -> Generator[QuerySet[T]]:
|
||||
qs = qs.order_by("pk")
|
||||
pks = qs.values_list("pk", flat=True)
|
||||
start_pk = pks[0]
|
||||
# The outer queryset.exists() guard can race with a concurrent
|
||||
# transaction that deletes the last matching row (or with a
|
||||
# different isolation-level snapshot), so by the time this
|
||||
# generator starts iterating the queryset may be empty and
|
||||
# pks[0] would raise IndexError and crash the caller. Using
|
||||
# .first() returns None on an empty queryset, which we bail
|
||||
# out on cleanly. See goauthentik/authentik#21643.
|
||||
start_pk = pks.first()
|
||||
if start_pk is None:
|
||||
return
|
||||
while True:
|
||||
try:
|
||||
end_pk = pks.filter(pk__gte=start_pk)[chunk_size]
|
||||
|
||||
@@ -141,26 +141,6 @@ class TestAuthorize(OAuthTestCase):
|
||||
OAuthAuthorizationParams.from_request(request)
|
||||
self.assertEqual(cm.exception.cause, "redirect_uri_forbidden_scheme")
|
||||
|
||||
def test_invalid_redirect_uri_empty(self):
|
||||
"""test missing/invalid redirect URI"""
|
||||
provider = OAuth2Provider.objects.create(
|
||||
name=generate_id(),
|
||||
client_id="test",
|
||||
authorization_flow=create_test_flow(),
|
||||
redirect_uris=[],
|
||||
)
|
||||
request = self.factory.get(
|
||||
"/",
|
||||
data={
|
||||
"response_type": "code",
|
||||
"client_id": "test",
|
||||
"redirect_uri": "+",
|
||||
},
|
||||
)
|
||||
OAuthAuthorizationParams.from_request(request)
|
||||
provider.refresh_from_db()
|
||||
self.assertEqual(provider.redirect_uris, [RedirectURI(RedirectURIMatchingMode.STRICT, "+")])
|
||||
|
||||
def test_invalid_redirect_uri_regex(self):
|
||||
"""test missing/invalid redirect URI"""
|
||||
OAuth2Provider.objects.create(
|
||||
|
||||
@@ -6,10 +6,11 @@ from urllib.parse import quote
|
||||
|
||||
from django.urls import reverse
|
||||
|
||||
from authentik.blueprints.tests import apply_blueprint
|
||||
from authentik.core.models import Application
|
||||
from authentik.core.tests.utils import create_test_flow
|
||||
from authentik.lib.generators import generate_id
|
||||
from authentik.providers.oauth2.models import OAuth2Provider
|
||||
from authentik.providers.oauth2.models import DeviceToken, OAuth2Provider, ScopeMapping
|
||||
from authentik.providers.oauth2.tests.utils import OAuthTestCase
|
||||
|
||||
|
||||
@@ -110,3 +111,57 @@ class TesOAuth2DeviceBackchannel(OAuthTestCase):
|
||||
self.assertEqual(res.status_code, 200)
|
||||
body = loads(res.content.decode())
|
||||
self.assertEqual(body["expires_in"], 60)
|
||||
|
||||
@apply_blueprint("system/providers-oauth2.yaml")
|
||||
def test_backchannel_scopes(self):
|
||||
"""Test backchannel"""
|
||||
self.provider.property_mappings.set(
|
||||
ScopeMapping.objects.filter(
|
||||
managed__in=[
|
||||
"goauthentik.io/providers/oauth2/scope-openid",
|
||||
"goauthentik.io/providers/oauth2/scope-email",
|
||||
"goauthentik.io/providers/oauth2/scope-profile",
|
||||
]
|
||||
)
|
||||
)
|
||||
creds = b64encode(f"{self.provider.client_id}:".encode()).decode()
|
||||
res = self.client.post(
|
||||
reverse("authentik_providers_oauth2:device"),
|
||||
HTTP_AUTHORIZATION=f"Basic {creds}",
|
||||
data={"scope": "openid email"},
|
||||
)
|
||||
self.assertEqual(res.status_code, 200)
|
||||
body = loads(res.content.decode())
|
||||
self.assertEqual(body["expires_in"], 60)
|
||||
token = DeviceToken.objects.filter(device_code=body["device_code"]).first()
|
||||
self.assertIsNotNone(token)
|
||||
self.assertEqual(len(token.scope), 2)
|
||||
self.assertIn("openid", token.scope)
|
||||
self.assertIn("email", token.scope)
|
||||
|
||||
@apply_blueprint("system/providers-oauth2.yaml")
|
||||
def test_backchannel_scopes_extra(self):
|
||||
"""Test backchannel"""
|
||||
self.provider.property_mappings.set(
|
||||
ScopeMapping.objects.filter(
|
||||
managed__in=[
|
||||
"goauthentik.io/providers/oauth2/scope-openid",
|
||||
"goauthentik.io/providers/oauth2/scope-email",
|
||||
"goauthentik.io/providers/oauth2/scope-profile",
|
||||
]
|
||||
)
|
||||
)
|
||||
creds = b64encode(f"{self.provider.client_id}:".encode()).decode()
|
||||
res = self.client.post(
|
||||
reverse("authentik_providers_oauth2:device"),
|
||||
HTTP_AUTHORIZATION=f"Basic {creds}",
|
||||
data={"scope": "openid email foo"},
|
||||
)
|
||||
self.assertEqual(res.status_code, 200)
|
||||
body = loads(res.content.decode())
|
||||
self.assertEqual(body["expires_in"], 60)
|
||||
token = DeviceToken.objects.filter(device_code=body["device_code"]).first()
|
||||
self.assertIsNotNone(token)
|
||||
self.assertEqual(len(token.scope), 2)
|
||||
self.assertIn("openid", token.scope)
|
||||
self.assertIn("email", token.scope)
|
||||
|
||||
@@ -48,6 +48,7 @@ class TestTokenDeviceCode(OAuthTestCase):
|
||||
reverse("authentik_providers_oauth2:token"),
|
||||
data={
|
||||
"client_id": self.provider.client_id,
|
||||
"client_secret": self.provider.client_secret,
|
||||
"grant_type": GRANT_TYPE_DEVICE_CODE,
|
||||
},
|
||||
)
|
||||
@@ -66,6 +67,7 @@ class TestTokenDeviceCode(OAuthTestCase):
|
||||
reverse("authentik_providers_oauth2:token"),
|
||||
data={
|
||||
"client_id": self.provider.client_id,
|
||||
"client_secret": self.provider.client_secret,
|
||||
"grant_type": GRANT_TYPE_DEVICE_CODE,
|
||||
"device_code": device_token.device_code,
|
||||
},
|
||||
@@ -74,6 +76,26 @@ class TestTokenDeviceCode(OAuthTestCase):
|
||||
body = loads(res.content.decode())
|
||||
self.assertEqual(body["error"], "authorization_pending")
|
||||
|
||||
def test_code_no_auth(self):
|
||||
"""Test code with user"""
|
||||
device_token = DeviceToken.objects.create(
|
||||
provider=self.provider,
|
||||
user_code=generate_code_fixed_length(),
|
||||
device_code=generate_id(),
|
||||
user=self.user,
|
||||
)
|
||||
res = self.client.post(
|
||||
reverse("authentik_providers_oauth2:token"),
|
||||
data={
|
||||
"client_id": self.provider.client_id,
|
||||
"grant_type": GRANT_TYPE_DEVICE_CODE,
|
||||
"device_code": device_token.device_code,
|
||||
},
|
||||
)
|
||||
self.assertEqual(res.status_code, 400)
|
||||
body = loads(res.content.decode())
|
||||
self.assertEqual(body["error"], "invalid_client")
|
||||
|
||||
def test_code(self):
|
||||
"""Test code with user"""
|
||||
device_token = DeviceToken.objects.create(
|
||||
@@ -86,6 +108,7 @@ class TestTokenDeviceCode(OAuthTestCase):
|
||||
reverse("authentik_providers_oauth2:token"),
|
||||
data={
|
||||
"client_id": self.provider.client_id,
|
||||
"client_secret": self.provider.client_secret,
|
||||
"grant_type": GRANT_TYPE_DEVICE_CODE,
|
||||
"device_code": device_token.device_code,
|
||||
},
|
||||
@@ -105,6 +128,7 @@ class TestTokenDeviceCode(OAuthTestCase):
|
||||
reverse("authentik_providers_oauth2:token"),
|
||||
data={
|
||||
"client_id": self.provider.client_id,
|
||||
"client_secret": self.provider.client_secret,
|
||||
"grant_type": GRANT_TYPE_DEVICE_CODE,
|
||||
"device_code": device_token.device_code,
|
||||
"scope": f"{SCOPE_OPENID} {SCOPE_OPENID_EMAIL} invalid",
|
||||
|
||||
@@ -59,9 +59,7 @@ from authentik.providers.oauth2.models import (
|
||||
AuthorizationCode,
|
||||
GrantTypes,
|
||||
OAuth2Provider,
|
||||
RedirectURI,
|
||||
RedirectURIMatchingMode,
|
||||
RedirectURIType,
|
||||
ResponseMode,
|
||||
ResponseTypes,
|
||||
ScopeMapping,
|
||||
@@ -197,18 +195,6 @@ class OAuthAuthorizationParams:
|
||||
LOGGER.warning("Missing redirect uri.")
|
||||
raise RedirectUriError("", allowed_redirect_urls).with_cause("redirect_uri_missing")
|
||||
|
||||
if len(allowed_redirect_urls) < 1:
|
||||
LOGGER.info("Setting redirect for blank redirect_uris", redirect=self.redirect_uri)
|
||||
self.provider.redirect_uris = [
|
||||
RedirectURI(
|
||||
RedirectURIMatchingMode.STRICT,
|
||||
self.redirect_uri,
|
||||
RedirectURIType.AUTHORIZATION,
|
||||
)
|
||||
]
|
||||
self.provider.save()
|
||||
allowed_redirect_urls = self.provider.authorization_redirect_uris
|
||||
|
||||
match_found = False
|
||||
for allowed in allowed_redirect_urls:
|
||||
if allowed.matching_mode == RedirectURIMatchingMode.STRICT:
|
||||
|
||||
@@ -15,7 +15,7 @@ from authentik.core.models import Application
|
||||
from authentik.lib.config import CONFIG
|
||||
from authentik.lib.utils.time import timedelta_from_string
|
||||
from authentik.providers.oauth2.errors import DeviceCodeError
|
||||
from authentik.providers.oauth2.models import DeviceToken, OAuth2Provider
|
||||
from authentik.providers.oauth2.models import DeviceToken, OAuth2Provider, ScopeMapping
|
||||
from authentik.providers.oauth2.utils import TokenResponse, extract_client_auth
|
||||
from authentik.providers.oauth2.views.device_init import QS_KEY_CODE
|
||||
|
||||
@@ -28,7 +28,7 @@ class DeviceView(View):
|
||||
|
||||
client_id: str
|
||||
provider: OAuth2Provider
|
||||
scopes: list[str] = []
|
||||
scopes: set[str] = []
|
||||
|
||||
def parse_request(self):
|
||||
"""Parse incoming request"""
|
||||
@@ -44,7 +44,21 @@ class DeviceView(View):
|
||||
raise DeviceCodeError("invalid_client") from None
|
||||
self.provider = provider
|
||||
self.client_id = client_id
|
||||
self.scopes = self.request.POST.get("scope", "").split(" ")
|
||||
|
||||
scopes_to_check = set(self.request.POST.get("scope", "").split())
|
||||
default_scope_names = set(
|
||||
ScopeMapping.objects.filter(provider__in=[self.provider]).values_list(
|
||||
"scope_name", flat=True
|
||||
)
|
||||
)
|
||||
self.scopes = scopes_to_check
|
||||
if not scopes_to_check.issubset(default_scope_names):
|
||||
LOGGER.info(
|
||||
"Application requested scopes not configured, setting to overlap",
|
||||
scope_allowed=default_scope_names,
|
||||
scope_given=self.scopes,
|
||||
)
|
||||
self.scopes = self.scopes.intersection(default_scope_names)
|
||||
|
||||
def dispatch(self, request: HttpRequest, *args, **kwargs) -> HttpResponse:
|
||||
throttle = AnonRateThrottle()
|
||||
|
||||
@@ -165,7 +165,15 @@ class TokenParams:
|
||||
raise TokenError("invalid_grant")
|
||||
|
||||
def __post_init__(self, raw_code: str, raw_token: str, request: HttpRequest):
|
||||
if self.grant_type in [GRANT_TYPE_AUTHORIZATION_CODE, GRANT_TYPE_REFRESH_TOKEN]:
|
||||
# Confidential clients MUST authenticate to the token endpoint per
|
||||
# RFC 6749 §2.3.1. The device code grant (RFC 8628 §3.4) inherits
|
||||
# that requirement - the device_code alone is not a substitute for
|
||||
# client credentials.
|
||||
if self.grant_type in [
|
||||
GRANT_TYPE_AUTHORIZATION_CODE,
|
||||
GRANT_TYPE_REFRESH_TOKEN,
|
||||
GRANT_TYPE_DEVICE_CODE,
|
||||
]:
|
||||
if self.provider.client_type == ClientTypes.CONFIDENTIAL and not compare_digest(
|
||||
self.provider.client_secret, self.client_secret
|
||||
):
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
"""authentik recovery create_admin_group"""
|
||||
|
||||
from argparse import ArgumentParser
|
||||
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from authentik.core.models import User
|
||||
@@ -12,7 +14,7 @@ class Command(TenantCommand):
|
||||
|
||||
help = _("Create admin group if the default group gets deleted.")
|
||||
|
||||
def add_arguments(self, parser):
|
||||
def add_arguments(self, parser: ArgumentParser):
|
||||
parser.add_argument("user", action="store", help="User to add to the admin group.")
|
||||
|
||||
def handle_per_tenant(self, *args, **options):
|
||||
|
||||
@@ -17,7 +17,7 @@ from authentik.core.api.sources import SourceSerializer
|
||||
from authentik.core.api.used_by import UsedByMixin
|
||||
from authentik.core.api.utils import PassiveSerializer
|
||||
from authentik.lib.utils.http import get_http_session
|
||||
from authentik.sources.oauth.models import OAuthSource
|
||||
from authentik.sources.oauth.models import OAuthSource, PKCEMethod
|
||||
from authentik.sources.oauth.types.registry import SourceType, registry
|
||||
|
||||
|
||||
@@ -83,13 +83,24 @@ class OAuthSourceSerializer(SourceSerializer):
|
||||
"authorization_url": "authorization_endpoint",
|
||||
"access_token_url": "token_endpoint",
|
||||
"profile_url": "userinfo_endpoint",
|
||||
"pkce": "code_challenge_methods_supported",
|
||||
}
|
||||
for ak_key, oidc_key in field_map.items():
|
||||
# Don't overwrite user-set values
|
||||
if ak_key in attrs and attrs[ak_key]:
|
||||
continue
|
||||
attrs[ak_key] = config.get(oidc_key, "")
|
||||
# code_challenge_methods_supported is a list per RFC 8414, not a
|
||||
# single method. Pick one (prefer S256, the RFC-recommended method)
|
||||
# rather than letting the list round-trip into the pkce TextField
|
||||
# and later str() into the authorize URL as "['plain', 'S256']".
|
||||
if not attrs.get("pkce"):
|
||||
supported_methods = config.get("code_challenge_methods_supported") or []
|
||||
attrs["pkce"] = PKCEMethod.NONE
|
||||
if isinstance(supported_methods, list):
|
||||
if PKCEMethod.S256 in supported_methods:
|
||||
attrs["pkce"] = PKCEMethod.S256
|
||||
elif PKCEMethod.PLAIN in supported_methods:
|
||||
attrs["pkce"] = PKCEMethod.PLAIN
|
||||
inferred_oidc_jwks_url = config.get("jwks_uri", "")
|
||||
|
||||
# Prefer user-entered URL to inferred URL to default URL
|
||||
|
||||
@@ -79,6 +79,7 @@ class TestOAuthSource(APITestCase):
|
||||
"token_endpoint": "http://mock/oauth/token",
|
||||
"userinfo_endpoint": "http://mock/oauth/userinfo",
|
||||
"jwks_uri": "http://mock/oauth/discovery/keys",
|
||||
"code_challenge_methods_supported": ["S256"],
|
||||
}
|
||||
jwks_config = {"keys": []}
|
||||
with Mocker() as mocker:
|
||||
@@ -109,6 +110,7 @@ class TestOAuthSource(APITestCase):
|
||||
serializer.validated_data["oidc_jwks_url"], "http://mock/oauth/discovery/keys"
|
||||
)
|
||||
self.assertEqual(serializer.validated_data["oidc_jwks"], jwks_config)
|
||||
self.assertEqual(serializer.validated_data["pkce"], PKCEMethod.S256)
|
||||
|
||||
def test_api_validate_openid_connect_invalid(self):
|
||||
"""Test API validation (with OIDC endpoints)"""
|
||||
|
||||
@@ -36,6 +36,14 @@ class UserWriteStageView(StageView):
|
||||
super().__init__(executor, **kwargs)
|
||||
self.disallowed_user_attributes = [
|
||||
"groups",
|
||||
# Block attribute writes that would otherwise land on the model's
|
||||
# primary key. An IdP that returns an `id` claim (mocksaml is one
|
||||
# example) used to crash the enrollment flow with
|
||||
# ValueError: Field 'id' expected a number but got '<hex>'
|
||||
# because hasattr(user, "id") is true and setattr(user, "id", ...)
|
||||
# was taken unchecked. See #21580.
|
||||
"id",
|
||||
"pk",
|
||||
]
|
||||
|
||||
@staticmethod
|
||||
|
||||
@@ -315,6 +315,34 @@ class TestUserWriteStage(FlowTestCase):
|
||||
component="ak-stage-access-denied",
|
||||
)
|
||||
|
||||
def test_user_update_ignores_id_from_idp(self):
|
||||
"""IdP-supplied `id`/`pk` attributes must not land on the model
|
||||
primary key and crash user save (#21580)."""
|
||||
existing = User.objects.create(username="unittest", email="test@goauthentik.io")
|
||||
original_pk = existing.pk
|
||||
|
||||
plan = FlowPlan(flow_pk=self.flow.pk.hex, bindings=[self.binding], markers=[StageMarker()])
|
||||
plan.context[PLAN_CONTEXT_PENDING_USER] = existing
|
||||
plan.context[PLAN_CONTEXT_PROMPT] = {
|
||||
"username": "idp-user",
|
||||
# Hex string from a SAML IdP; would previously crash with
|
||||
# ValueError: Field 'id' expected a number but got '<hex>'.
|
||||
"id": "1dda9fb491dc01bd24d2423ba2f22ae561f56ddf2376b29a11c80281d21201f9",
|
||||
"pk": "also-not-an-int",
|
||||
}
|
||||
session = self.client.session
|
||||
session[SESSION_KEY_PLAN] = plan
|
||||
session.save()
|
||||
|
||||
response = self.client.post(
|
||||
reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug})
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertStageRedirects(response, reverse("authentik_core:root-redirect"))
|
||||
user = User.objects.get(username="idp-user")
|
||||
self.assertEqual(user.pk, original_pk)
|
||||
|
||||
def test_write_attribute(self):
|
||||
"""Test write_attribute"""
|
||||
user = create_test_admin_user()
|
||||
|
||||
@@ -19,19 +19,32 @@ from authentik.tenants.models import Tenant
|
||||
|
||||
class FlagJSONField(JSONDictField):
|
||||
|
||||
def to_representation(self, value: dict) -> dict:
|
||||
"""Exclude any system flags that aren't modifiable"""
|
||||
new_value = value.copy()
|
||||
for flag in Flag.available(exclude_system=False):
|
||||
_flag = flag()
|
||||
if _flag.visibility == "system":
|
||||
new_value.pop(_flag.key, None)
|
||||
return super().to_representation(new_value)
|
||||
|
||||
def run_validators(self, value: dict):
|
||||
super().run_validators(value)
|
||||
for flag in Flag.available():
|
||||
for flag in Flag.available(exclude_system=False):
|
||||
_flag = flag()
|
||||
if _flag.key in value:
|
||||
flag_value = value.get(_flag.key)
|
||||
flag_type = get_args(_flag.__orig_bases__[0])[0]
|
||||
if flag_value and not isinstance(flag_value, flag_type):
|
||||
raise ValidationError(
|
||||
_("Value for flag {flag_key} needs to be of type {type}.").format(
|
||||
flag_key=_flag.key, type=flag_type.__name__
|
||||
)
|
||||
if _flag.key not in value:
|
||||
continue
|
||||
if _flag.visibility == "system":
|
||||
value.pop(_flag.key, None)
|
||||
continue
|
||||
flag_value = value.get(_flag.key)
|
||||
flag_type = get_args(_flag.__orig_bases__[0])[0]
|
||||
if flag_value and not isinstance(flag_value, flag_type):
|
||||
raise ValidationError(
|
||||
_("Value for flag {flag_key} needs to be of type {type}.").format(
|
||||
flag_key=_flag.key, type=flag_type.__name__
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class FlagsJSONExtension(OpenApiSerializerFieldExtension):
|
||||
|
||||
@@ -4,6 +4,7 @@ from functools import wraps
|
||||
from typing import TYPE_CHECKING, Any, Literal
|
||||
|
||||
from django.db import DatabaseError, InternalError, ProgrammingError
|
||||
from django.db.models import F, Func, JSONField, Value
|
||||
|
||||
from authentik.lib.utils.reflection import all_subclasses
|
||||
|
||||
@@ -13,7 +14,9 @@ if TYPE_CHECKING:
|
||||
|
||||
class Flag[T]:
|
||||
default: T | None = None
|
||||
visibility: Literal["none"] | Literal["public"] | Literal["authenticated"] = "none"
|
||||
visibility: (
|
||||
Literal["none"] | Literal["public"] | Literal["authenticated"] | Literal["system"]
|
||||
) = "none"
|
||||
description: str | None = None
|
||||
|
||||
def __init_subclass__(cls, key: str, **kwargs):
|
||||
@@ -24,12 +27,15 @@ class Flag[T]:
|
||||
return self.__key
|
||||
|
||||
@classmethod
|
||||
def get(cls) -> T | None:
|
||||
def get(cls, tenant: Tenant | None = None) -> T | None:
|
||||
from authentik.tenants.utils import get_current_tenant
|
||||
|
||||
if not tenant:
|
||||
tenant = get_current_tenant(["flags"])
|
||||
|
||||
flags = {}
|
||||
try:
|
||||
flags: dict[str, Any] = get_current_tenant(["flags"]).flags
|
||||
flags: dict[str, Any] = tenant.flags
|
||||
except DatabaseError, ProgrammingError, InternalError:
|
||||
pass
|
||||
value = flags.get(cls.__key, None)
|
||||
@@ -37,20 +43,38 @@ class Flag[T]:
|
||||
return cls().get_default()
|
||||
return value
|
||||
|
||||
@classmethod
|
||||
def set(cls, value: T, tenant: Tenant | None = None) -> T | None:
|
||||
from authentik.tenants.models import Tenant
|
||||
from authentik.tenants.utils import get_current_tenant
|
||||
|
||||
if not tenant:
|
||||
tenant = get_current_tenant()
|
||||
|
||||
Tenant.objects.filter(pk=tenant.pk).update(
|
||||
flags=Func(
|
||||
F("flags"),
|
||||
Value([cls.__key]),
|
||||
Value(value, JSONField()),
|
||||
function="jsonb_set",
|
||||
)
|
||||
)
|
||||
|
||||
def get_default(self) -> T | None:
|
||||
return self.default
|
||||
|
||||
@staticmethod
|
||||
def available(
|
||||
visibility: Literal["none"] | Literal["public"] | Literal["authenticated"] | None = None,
|
||||
exclude_system=True,
|
||||
):
|
||||
flags = all_subclasses(Flag)
|
||||
if visibility:
|
||||
for flag in flags:
|
||||
if flag.visibility == visibility:
|
||||
yield flag
|
||||
else:
|
||||
yield from flags
|
||||
for flag in flags:
|
||||
if visibility and flag.visibility != visibility:
|
||||
continue
|
||||
if exclude_system and flag.visibility == "system":
|
||||
continue
|
||||
yield flag
|
||||
|
||||
|
||||
def patch_flag[T](flag: Flag[T], value: T):
|
||||
|
||||
19
authentik/tenants/management/commands/set_flag.py
Normal file
19
authentik/tenants/management/commands/set_flag.py
Normal file
@@ -0,0 +1,19 @@
|
||||
from argparse import ArgumentParser
|
||||
from typing import Any
|
||||
|
||||
from authentik.tenants.management import TenantCommand
|
||||
from authentik.tenants.utils import get_current_tenant
|
||||
|
||||
|
||||
class Command(TenantCommand):
|
||||
|
||||
def add_arguments(self, parser: ArgumentParser):
|
||||
parser.add_argument("flag_key", type=str)
|
||||
parser.add_argument("flag_value", type=str)
|
||||
|
||||
def handle(self, *, flag_key: str, flag_value: Any, **options):
|
||||
tenant = get_current_tenant()
|
||||
val = flag_value.lower() == "true"
|
||||
tenant.flags[flag_key] = val
|
||||
tenant.save()
|
||||
self.stdout.write(f"Set flag '{flag_key}' to {val}.")
|
||||
@@ -1,10 +1,12 @@
|
||||
"""Test Settings API"""
|
||||
|
||||
from django.core.management import call_command
|
||||
from django.urls import reverse
|
||||
from rest_framework.test import APITestCase
|
||||
|
||||
from authentik.core.tests.utils import create_test_admin_user
|
||||
from authentik.tenants.flags import Flag
|
||||
from authentik.tenants.utils import get_current_tenant
|
||||
|
||||
|
||||
class TestLocalSettingsAPI(APITestCase):
|
||||
@@ -13,11 +15,19 @@ class TestLocalSettingsAPI(APITestCase):
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.local_admin = create_test_admin_user()
|
||||
self.tenant = get_current_tenant()
|
||||
|
||||
def tearDown(self):
|
||||
super().tearDown()
|
||||
self.tenant.flags = {}
|
||||
self.tenant.save()
|
||||
|
||||
def test_settings_flags(self):
|
||||
"""Test settings API"""
|
||||
self.tenant.flags = {}
|
||||
self.tenant.save()
|
||||
|
||||
class TestFlag(Flag[bool], key="tenants_test_flag"):
|
||||
class _TestFlag(Flag[bool], key="tenants_test_flag_bool"):
|
||||
|
||||
default = False
|
||||
visibility = "public"
|
||||
@@ -26,15 +36,19 @@ class TestLocalSettingsAPI(APITestCase):
|
||||
response = self.client.patch(
|
||||
reverse("authentik_api:tenant_settings"),
|
||||
data={
|
||||
"flags": {"tenants_test_flag": True},
|
||||
"flags": {"tenants_test_flag_bool": True},
|
||||
},
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.tenant.refresh_from_db()
|
||||
self.assertEqual(self.tenant.flags["tenants_test_flag_bool"], True)
|
||||
|
||||
def test_settings_flags_incorrect(self):
|
||||
"""Test settings API"""
|
||||
self.tenant.flags = {}
|
||||
self.tenant.save()
|
||||
|
||||
class TestFlag(Flag[bool], key="tenants_test_flag"):
|
||||
class _TestFlag(Flag[bool], key="tenants_test_flag_incorrect"):
|
||||
|
||||
default = False
|
||||
visibility = "public"
|
||||
@@ -43,11 +57,44 @@ class TestLocalSettingsAPI(APITestCase):
|
||||
response = self.client.patch(
|
||||
reverse("authentik_api:tenant_settings"),
|
||||
data={
|
||||
"flags": {"tenants_test_flag": 123},
|
||||
"flags": {"tenants_test_flag_incorrect": 123},
|
||||
},
|
||||
)
|
||||
self.assertEqual(response.status_code, 400)
|
||||
self.assertJSONEqual(
|
||||
response.content,
|
||||
{"flags": ["Value for flag tenants_test_flag needs to be of type bool."]},
|
||||
{"flags": ["Value for flag tenants_test_flag_incorrect needs to be of type bool."]},
|
||||
)
|
||||
self.tenant.refresh_from_db()
|
||||
self.assertEqual(self.tenant.flags, {})
|
||||
|
||||
def test_settings_flags_system(self):
|
||||
"""Test settings API"""
|
||||
self.tenant.flags = {}
|
||||
self.tenant.save()
|
||||
|
||||
class _TestFlag(Flag[bool], key="tenants_test_flag_sys"):
|
||||
|
||||
default = False
|
||||
visibility = "system"
|
||||
|
||||
self.client.force_login(self.local_admin)
|
||||
response = self.client.patch(
|
||||
reverse("authentik_api:tenant_settings"),
|
||||
data={
|
||||
"flags": {"tenants_test_flag_sys": 123},
|
||||
},
|
||||
)
|
||||
print(response.content)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.tenant.refresh_from_db()
|
||||
self.assertEqual(self.tenant.flags, {})
|
||||
|
||||
def test_command(self):
|
||||
self.tenant.flags = {}
|
||||
self.tenant.save()
|
||||
|
||||
call_command("set_flag", "foo", "true")
|
||||
|
||||
self.tenant.refresh_from_db()
|
||||
self.assertTrue(self.tenant.flags["foo"])
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
metadata:
|
||||
labels:
|
||||
blueprints.goauthentik.io/system-oobe: "true"
|
||||
blueprints.goauthentik.io/system: "true"
|
||||
name: Default - Out-of-box-experience flow
|
||||
version: 1
|
||||
entries:
|
||||
@@ -75,23 +78,20 @@ entries:
|
||||
- attrs:
|
||||
expression: |
|
||||
# This policy ensures that the setup flow can only be
|
||||
# executed when the admin user doesn''t have a password set
|
||||
# executed when the admin user doesn't have a password set
|
||||
akadmin = ak_user_by(username="akadmin")
|
||||
return not akadmin.has_usable_password()
|
||||
# Ensure flow was started correctly
|
||||
started_by = context.get("goauthentik.io/core/setup/started-by")
|
||||
if started_by != "setup":
|
||||
setup_url = request.http_request.build_absolute_uri("/")
|
||||
ak_message(f"Access the authentik setup by navigating to {setup_url}")
|
||||
return False
|
||||
return akadmin is None or not akadmin.has_usable_password()
|
||||
id: policy-default-oobe-password-usable
|
||||
identifiers:
|
||||
name: default-oobe-password-usable
|
||||
model: authentik_policies_expression.expressionpolicy
|
||||
- attrs:
|
||||
expression: |
|
||||
# This policy ensures that the setup flow can only be
|
||||
# used one time
|
||||
from authentik.flows.models import Flow, FlowAuthenticationRequirement
|
||||
Flow.objects.filter(slug="initial-setup").update(
|
||||
authentication=FlowAuthenticationRequirement.REQUIRE_SUPERUSER,
|
||||
)
|
||||
return True
|
||||
id: policy-default-oobe-flow-set-authentication
|
||||
- state: absent
|
||||
identifiers:
|
||||
name: default-oobe-flow-set-authentication
|
||||
model: authentik_policies_expression.expressionpolicy
|
||||
@@ -154,8 +154,3 @@ entries:
|
||||
policy: !KeyOf policy-default-oobe-prefill-user
|
||||
target: !KeyOf binding-password-write
|
||||
model: authentik_policies.policybinding
|
||||
- identifiers:
|
||||
order: 0
|
||||
policy: !KeyOf policy-default-oobe-flow-set-authentication
|
||||
target: !KeyOf binding-login
|
||||
model: authentik_policies.policybinding
|
||||
|
||||
@@ -5644,6 +5644,7 @@
|
||||
"authentik_endpoints_connectors_agent.add_agentconnector",
|
||||
"authentik_endpoints_connectors_agent.add_agentdeviceconnection",
|
||||
"authentik_endpoints_connectors_agent.add_agentdeviceuserbinding",
|
||||
"authentik_endpoints_connectors_agent.add_appleindependentsecureenclave",
|
||||
"authentik_endpoints_connectors_agent.add_applenonce",
|
||||
"authentik_endpoints_connectors_agent.add_deviceauthenticationtoken",
|
||||
"authentik_endpoints_connectors_agent.add_devicetoken",
|
||||
@@ -5651,6 +5652,7 @@
|
||||
"authentik_endpoints_connectors_agent.change_agentconnector",
|
||||
"authentik_endpoints_connectors_agent.change_agentdeviceconnection",
|
||||
"authentik_endpoints_connectors_agent.change_agentdeviceuserbinding",
|
||||
"authentik_endpoints_connectors_agent.change_appleindependentsecureenclave",
|
||||
"authentik_endpoints_connectors_agent.change_applenonce",
|
||||
"authentik_endpoints_connectors_agent.change_deviceauthenticationtoken",
|
||||
"authentik_endpoints_connectors_agent.change_devicetoken",
|
||||
@@ -5658,6 +5660,7 @@
|
||||
"authentik_endpoints_connectors_agent.delete_agentconnector",
|
||||
"authentik_endpoints_connectors_agent.delete_agentdeviceconnection",
|
||||
"authentik_endpoints_connectors_agent.delete_agentdeviceuserbinding",
|
||||
"authentik_endpoints_connectors_agent.delete_appleindependentsecureenclave",
|
||||
"authentik_endpoints_connectors_agent.delete_applenonce",
|
||||
"authentik_endpoints_connectors_agent.delete_deviceauthenticationtoken",
|
||||
"authentik_endpoints_connectors_agent.delete_devicetoken",
|
||||
@@ -5665,6 +5668,7 @@
|
||||
"authentik_endpoints_connectors_agent.view_agentconnector",
|
||||
"authentik_endpoints_connectors_agent.view_agentdeviceconnection",
|
||||
"authentik_endpoints_connectors_agent.view_agentdeviceuserbinding",
|
||||
"authentik_endpoints_connectors_agent.view_appleindependentsecureenclave",
|
||||
"authentik_endpoints_connectors_agent.view_applenonce",
|
||||
"authentik_endpoints_connectors_agent.view_deviceauthenticationtoken",
|
||||
"authentik_endpoints_connectors_agent.view_devicetoken",
|
||||
@@ -8426,7 +8430,8 @@
|
||||
"require_unauthenticated",
|
||||
"require_superuser",
|
||||
"require_redirect",
|
||||
"require_outpost"
|
||||
"require_outpost",
|
||||
"require_token"
|
||||
],
|
||||
"title": "Authentication",
|
||||
"description": "Required level of authentication and authorization to access a flow."
|
||||
@@ -11319,6 +11324,7 @@
|
||||
"authentik_endpoints_connectors_agent.add_agentconnector",
|
||||
"authentik_endpoints_connectors_agent.add_agentdeviceconnection",
|
||||
"authentik_endpoints_connectors_agent.add_agentdeviceuserbinding",
|
||||
"authentik_endpoints_connectors_agent.add_appleindependentsecureenclave",
|
||||
"authentik_endpoints_connectors_agent.add_applenonce",
|
||||
"authentik_endpoints_connectors_agent.add_deviceauthenticationtoken",
|
||||
"authentik_endpoints_connectors_agent.add_devicetoken",
|
||||
@@ -11326,6 +11332,7 @@
|
||||
"authentik_endpoints_connectors_agent.change_agentconnector",
|
||||
"authentik_endpoints_connectors_agent.change_agentdeviceconnection",
|
||||
"authentik_endpoints_connectors_agent.change_agentdeviceuserbinding",
|
||||
"authentik_endpoints_connectors_agent.change_appleindependentsecureenclave",
|
||||
"authentik_endpoints_connectors_agent.change_applenonce",
|
||||
"authentik_endpoints_connectors_agent.change_deviceauthenticationtoken",
|
||||
"authentik_endpoints_connectors_agent.change_devicetoken",
|
||||
@@ -11333,6 +11340,7 @@
|
||||
"authentik_endpoints_connectors_agent.delete_agentconnector",
|
||||
"authentik_endpoints_connectors_agent.delete_agentdeviceconnection",
|
||||
"authentik_endpoints_connectors_agent.delete_agentdeviceuserbinding",
|
||||
"authentik_endpoints_connectors_agent.delete_appleindependentsecureenclave",
|
||||
"authentik_endpoints_connectors_agent.delete_applenonce",
|
||||
"authentik_endpoints_connectors_agent.delete_deviceauthenticationtoken",
|
||||
"authentik_endpoints_connectors_agent.delete_devicetoken",
|
||||
@@ -11340,6 +11348,7 @@
|
||||
"authentik_endpoints_connectors_agent.view_agentconnector",
|
||||
"authentik_endpoints_connectors_agent.view_agentdeviceconnection",
|
||||
"authentik_endpoints_connectors_agent.view_agentdeviceuserbinding",
|
||||
"authentik_endpoints_connectors_agent.view_appleindependentsecureenclave",
|
||||
"authentik_endpoints_connectors_agent.view_applenonce",
|
||||
"authentik_endpoints_connectors_agent.view_deviceauthenticationtoken",
|
||||
"authentik_endpoints_connectors_agent.view_devicetoken",
|
||||
|
||||
38
go.mod
38
go.mod
@@ -7,10 +7,10 @@ require (
|
||||
beryju.io/radius-eap v0.1.0
|
||||
github.com/avast/retry-go/v4 v4.7.0
|
||||
github.com/coreos/go-oidc/v3 v3.18.0
|
||||
github.com/getsentry/sentry-go v0.44.1
|
||||
github.com/getsentry/sentry-go v0.45.1
|
||||
github.com/go-http-utils/etag v0.0.0-20161124023236-513ea8f21eb1
|
||||
github.com/go-ldap/ldap/v3 v3.4.13
|
||||
github.com/go-openapi/runtime v0.29.3
|
||||
github.com/go-openapi/runtime v0.29.4
|
||||
github.com/golang-jwt/jwt/v5 v5.3.1
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/gorilla/handlers v1.5.2
|
||||
@@ -19,11 +19,11 @@ require (
|
||||
github.com/gorilla/sessions v1.4.0
|
||||
github.com/gorilla/websocket v1.5.3
|
||||
github.com/grafana/pyroscope-go v1.2.8
|
||||
github.com/jackc/pgx/v5 v5.9.1
|
||||
github.com/jackc/pgx/v5 v5.9.2
|
||||
github.com/jellydator/ttlcache/v3 v3.4.0
|
||||
github.com/mitchellh/mapstructure v1.5.0
|
||||
github.com/nmcclain/asn1-ber v0.0.0-20170104154839-2661553a0484
|
||||
github.com/pires/go-proxyproto v0.11.0
|
||||
github.com/pires/go-proxyproto v0.12.0
|
||||
github.com/prometheus/client_golang v1.23.2
|
||||
github.com/sethvargo/go-envconfig v1.3.0
|
||||
github.com/sirupsen/logrus v1.9.4
|
||||
@@ -40,7 +40,7 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/Azure/go-ntlmssp v0.1.0 // indirect
|
||||
github.com/Azure/go-ntlmssp v0.1.1 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
@@ -51,21 +51,21 @@ require (
|
||||
github.com/go-jose/go-jose/v4 v4.1.4 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-openapi/analysis v0.24.3 // indirect
|
||||
github.com/go-openapi/analysis v0.25.0 // indirect
|
||||
github.com/go-openapi/errors v0.22.7 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.22.5 // indirect
|
||||
github.com/go-openapi/jsonreference v0.21.5 // indirect
|
||||
github.com/go-openapi/loads v0.23.3 // indirect
|
||||
github.com/go-openapi/spec v0.22.4 // indirect
|
||||
github.com/go-openapi/strfmt v0.26.0 // indirect
|
||||
github.com/go-openapi/swag/conv v0.25.5 // indirect
|
||||
github.com/go-openapi/swag/fileutils v0.25.5 // indirect
|
||||
github.com/go-openapi/strfmt v0.26.1 // indirect
|
||||
github.com/go-openapi/swag/conv v0.26.0 // indirect
|
||||
github.com/go-openapi/swag/fileutils v0.26.0 // indirect
|
||||
github.com/go-openapi/swag/jsonname v0.25.5 // indirect
|
||||
github.com/go-openapi/swag/jsonutils v0.25.5 // indirect
|
||||
github.com/go-openapi/swag/jsonutils v0.26.0 // indirect
|
||||
github.com/go-openapi/swag/loading v0.25.5 // indirect
|
||||
github.com/go-openapi/swag/mangling v0.25.5 // indirect
|
||||
github.com/go-openapi/swag/stringutils v0.25.5 // indirect
|
||||
github.com/go-openapi/swag/typeutils v0.25.5 // indirect
|
||||
github.com/go-openapi/swag/stringutils v0.26.0 // indirect
|
||||
github.com/go-openapi/swag/typeutils v0.26.0 // indirect
|
||||
github.com/go-openapi/swag/yamlutils v0.25.5 // indirect
|
||||
github.com/go-openapi/validate v0.25.2 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.5.0 // indirect
|
||||
@@ -85,15 +85,15 @@ require (
|
||||
github.com/prometheus/procfs v0.16.1 // indirect
|
||||
github.com/spf13/pflag v1.0.9 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 // indirect
|
||||
go.opentelemetry.io/otel v1.41.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.41.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.41.0 // indirect
|
||||
go.opentelemetry.io/otel v1.43.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.43.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.43.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.2 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/crypto v0.48.0 // indirect
|
||||
golang.org/x/net v0.50.0 // indirect
|
||||
golang.org/x/sys v0.41.0 // indirect
|
||||
golang.org/x/text v0.34.0 // indirect
|
||||
golang.org/x/crypto v0.49.0 // indirect
|
||||
golang.org/x/net v0.52.0 // indirect
|
||||
golang.org/x/sys v0.42.0 // indirect
|
||||
golang.org/x/text v0.35.0 // indirect
|
||||
google.golang.org/protobuf v1.36.8 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
92
go.sum
92
go.sum
@@ -2,8 +2,8 @@ beryju.io/ldap v0.2.1 h1:rhTAP2CXqrKZy/UycLC/aPSSBMcgJMzooKqk3TwVFxY=
|
||||
beryju.io/ldap v0.2.1/go.mod h1:GJSw3pVOON/3+L5att3Eysmj7j0GmjLvA6/WNmPajD4=
|
||||
beryju.io/radius-eap v0.1.0 h1:5M3HwkzH3nIEBcKDA2z5+sb4nCY3WdKL/SDDKTBvoqw=
|
||||
beryju.io/radius-eap v0.1.0/go.mod h1:yYtO59iyoLNEepdyp1gZ0i1tGdjPbrR2M/v5yOz7Fkc=
|
||||
github.com/Azure/go-ntlmssp v0.1.0 h1:DjFo6YtWzNqNvQdrwEyr/e4nhU3vRiwenz5QX7sFz+A=
|
||||
github.com/Azure/go-ntlmssp v0.1.0/go.mod h1:NYqdhxd/8aAct/s4qSYZEerdPuH1liG2/X9DiVTbhpk=
|
||||
github.com/Azure/go-ntlmssp v0.1.1 h1:l+FM/EEMb0U9QZE7mKNEDw5Mu3mFiaa2GKOoTSsNDPw=
|
||||
github.com/Azure/go-ntlmssp v0.1.1/go.mod h1:NYqdhxd/8aAct/s4qSYZEerdPuH1liG2/X9DiVTbhpk=
|
||||
github.com/alexbrainman/sspi v0.0.0-20250919150558-7d374ff0d59e h1:4dAU9FXIyQktpoUAgOJK3OTFc/xug0PCXYCqU0FgDKI=
|
||||
github.com/alexbrainman/sspi v0.0.0-20250919150558-7d374ff0d59e/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4=
|
||||
github.com/avast/retry-go/v4 v4.7.0 h1:yjDs35SlGvKwRNSykujfjdMxMhMQQM0TnIjJaHB+Zio=
|
||||
@@ -20,8 +20,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
|
||||
github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/getsentry/sentry-go v0.44.1 h1:/cPtrA5qB7uMRrhgSn9TYtcEF36auGP3Y6+ThvD/yaI=
|
||||
github.com/getsentry/sentry-go v0.44.1/go.mod h1:XDotiNZbgf5U8bPDUAfvcFmOnMQQceESxyKaObSssW0=
|
||||
github.com/getsentry/sentry-go v0.45.1 h1:9rfzJtGiJG+MGIaWZXidDGHcH5GU1Z5y0WVJGf9nysw=
|
||||
github.com/getsentry/sentry-go v0.45.1/go.mod h1:XDotiNZbgf5U8bPDUAfvcFmOnMQQceESxyKaObSssW0=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 h1:BP4M0CvQ4S3TGls2FvczZtj5Re/2ZzkV9VwqPHH/3Bo=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
|
||||
@@ -41,8 +41,8 @@ github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
|
||||
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-openapi/analysis v0.24.3 h1:a1hrvMr8X0Xt69KP5uVTu5jH62DscmDifrLzNglAayk=
|
||||
github.com/go-openapi/analysis v0.24.3/go.mod h1:Nc+dWJ/FxZbhSow5Yh3ozg5CLJioB+XXT6MdLvJUsUw=
|
||||
github.com/go-openapi/analysis v0.25.0 h1:EnjAq1yO8wEO9HbPmY8vLPEIkdZuuFhCAKBPvCB7bCs=
|
||||
github.com/go-openapi/analysis v0.25.0/go.mod h1:5WFTRE43WLkPG9r9OtlMfqkkvUTYLVVCIxLlEpyF8kE=
|
||||
github.com/go-openapi/errors v0.22.7 h1:JLFBGC0Apwdzw3484MmBqspjPbwa2SHvpDm0u5aGhUA=
|
||||
github.com/go-openapi/errors v0.22.7/go.mod h1://QW6SD9OsWtH6gHllUCddOXDL0tk0ZGNYHwsw4sW3w=
|
||||
github.com/go-openapi/jsonpointer v0.22.5 h1:8on/0Yp4uTb9f4XvTrM2+1CPrV05QPZXu+rvu2o9jcA=
|
||||
@@ -51,36 +51,36 @@ github.com/go-openapi/jsonreference v0.21.5 h1:6uCGVXU/aNF13AQNggxfysJ+5ZcU4nEAe
|
||||
github.com/go-openapi/jsonreference v0.21.5/go.mod h1:u25Bw85sX4E2jzFodh1FOKMTZLcfifd1Q+iKKOUxExw=
|
||||
github.com/go-openapi/loads v0.23.3 h1:g5Xap1JfwKkUnZdn+S0L3SzBDpcTIYzZ5Qaag0YDkKQ=
|
||||
github.com/go-openapi/loads v0.23.3/go.mod h1:NOH07zLajXo8y55hom0omlHWDVVvCwBM/S+csCK8LqA=
|
||||
github.com/go-openapi/runtime v0.29.3 h1:h5twGaEqxtQg40ePiYm9vFFH1q06Czd7Ot6ufdK0w/Y=
|
||||
github.com/go-openapi/runtime v0.29.3/go.mod h1:8A1W0/L5eyNJvKciqZtvIVQvYO66NlB7INMSZ9bw/oI=
|
||||
github.com/go-openapi/runtime v0.29.4 h1:k2lDxrGoSAJRdhFG2tONKMpkizY/4X1cciSdtzk4Jjo=
|
||||
github.com/go-openapi/runtime v0.29.4/go.mod h1:K0k/2raY6oqXJnZAgWJB2i/12QKrhUKpZcH4PfV9P18=
|
||||
github.com/go-openapi/spec v0.22.4 h1:4pxGjipMKu0FzFiu/DPwN3CTBRlVM2yLf/YTWorYfDQ=
|
||||
github.com/go-openapi/spec v0.22.4/go.mod h1:WQ6Ai0VPWMZgMT4XySjlRIE6GP1bGQOtEThn3gcWLtQ=
|
||||
github.com/go-openapi/strfmt v0.26.0 h1:SDdQLyOEqu8W96rO1FRG1fuCtVyzmukky0zcD6gMGLU=
|
||||
github.com/go-openapi/strfmt v0.26.0/go.mod h1:Zslk5VZPOISLwmWTMBIS7oiVFem1o1EI6zULY8Uer7Y=
|
||||
github.com/go-openapi/swag/conv v0.25.5 h1:wAXBYEXJjoKwE5+vc9YHhpQOFj2JYBMF2DUi+tGu97g=
|
||||
github.com/go-openapi/swag/conv v0.25.5/go.mod h1:CuJ1eWvh1c4ORKx7unQnFGyvBbNlRKbnRyAvDvzWA4k=
|
||||
github.com/go-openapi/swag/fileutils v0.25.5 h1:B6JTdOcs2c0dBIs9HnkyTW+5gC+8NIhVBUwERkFhMWk=
|
||||
github.com/go-openapi/swag/fileutils v0.25.5/go.mod h1:V3cT9UdMQIaH4WiTrUc9EPtVA4txS0TOmRURmhGF4kc=
|
||||
github.com/go-openapi/strfmt v0.26.1 h1:7zGCHji7zSYDC2tCXIusoxYQz/48jAf2q+sF6wXTG+c=
|
||||
github.com/go-openapi/strfmt v0.26.1/go.mod h1:Zslk5VZPOISLwmWTMBIS7oiVFem1o1EI6zULY8Uer7Y=
|
||||
github.com/go-openapi/swag/conv v0.26.0 h1:5yGGsPYI1ZCva93U0AoKi/iZrNhaJEjr324YVsiD89I=
|
||||
github.com/go-openapi/swag/conv v0.26.0/go.mod h1:tpAmIL7X58VPnHHiSO4uE3jBeRamGsFsfdDeDtb5ECE=
|
||||
github.com/go-openapi/swag/fileutils v0.26.0 h1:WJoPRvsA7QRiiWluowkLJa9jaYR7FCuxmDvnCgaRRxU=
|
||||
github.com/go-openapi/swag/fileutils v0.26.0/go.mod h1:0WDJ7lp67eNjPMO50wAWYlKvhOb6CQ37rzR7wrgI8Tc=
|
||||
github.com/go-openapi/swag/jsonname v0.25.5 h1:8p150i44rv/Drip4vWI3kGi9+4W9TdI3US3uUYSFhSo=
|
||||
github.com/go-openapi/swag/jsonname v0.25.5/go.mod h1:jNqqikyiAK56uS7n8sLkdaNY/uq6+D2m2LANat09pKU=
|
||||
github.com/go-openapi/swag/jsonutils v0.25.5 h1:XUZF8awQr75MXeC+/iaw5usY/iM7nXPDwdG3Jbl9vYo=
|
||||
github.com/go-openapi/swag/jsonutils v0.25.5/go.mod h1:48FXUaz8YsDAA9s5AnaUvAmry1UcLcNVWUjY42XkrN4=
|
||||
github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.5 h1:SX6sE4FrGb4sEnnxbFL/25yZBb5Hcg1inLeErd86Y1U=
|
||||
github.com/go-openapi/swag/jsonutils/fixtures_test v0.25.5/go.mod h1:/2KvOTrKWjVA5Xli3DZWdMCZDzz3uV/T7bXwrKWPquo=
|
||||
github.com/go-openapi/swag/jsonutils v0.26.0 h1:FawFML2iAXsPqmERscuMPIHmFsoP1tOqWkxBaKNMsnA=
|
||||
github.com/go-openapi/swag/jsonutils v0.26.0/go.mod h1:2VmA0CJlyFqgawOaPI9psnjFDqzyivIqLYN34t9p91E=
|
||||
github.com/go-openapi/swag/jsonutils/fixtures_test v0.26.0 h1:apqeINu/ICHouqiRZbyFvuDge5jCmmLTqGQ9V95EaOM=
|
||||
github.com/go-openapi/swag/jsonutils/fixtures_test v0.26.0/go.mod h1:AyM6QT8uz5IdKxk5akv0y6u4QvcL9GWERt0Jx/F/R8Y=
|
||||
github.com/go-openapi/swag/loading v0.25.5 h1:odQ/umlIZ1ZVRteI6ckSrvP6e2w9UTF5qgNdemJHjuU=
|
||||
github.com/go-openapi/swag/loading v0.25.5/go.mod h1:I8A8RaaQ4DApxhPSWLNYWh9NvmX2YKMoB9nwvv6oW6g=
|
||||
github.com/go-openapi/swag/mangling v0.25.5 h1:hyrnvbQRS7vKePQPHHDso+k6CGn5ZBs5232UqWZmJZw=
|
||||
github.com/go-openapi/swag/mangling v0.25.5/go.mod h1:6hadXM/o312N/h98RwByLg088U61TPGiltQn71Iw0NY=
|
||||
github.com/go-openapi/swag/stringutils v0.25.5 h1:NVkoDOA8YBgtAR/zvCx5rhJKtZF3IzXcDdwOsYzrB6M=
|
||||
github.com/go-openapi/swag/stringutils v0.25.5/go.mod h1:PKK8EZdu4QJq8iezt17HM8RXnLAzY7gW0O1KKarrZII=
|
||||
github.com/go-openapi/swag/typeutils v0.25.5 h1:EFJ+PCga2HfHGdo8s8VJXEVbeXRCYwzzr9u4rJk7L7E=
|
||||
github.com/go-openapi/swag/typeutils v0.25.5/go.mod h1:itmFmScAYE1bSD8C4rS0W+0InZUBrB2xSPbWt6DLGuc=
|
||||
github.com/go-openapi/swag/stringutils v0.26.0 h1:qZQngLxs5s7SLijc3N2ZO+fUq2o8LjuWAASSrJuh+xg=
|
||||
github.com/go-openapi/swag/stringutils v0.26.0/go.mod h1:sWn5uY+QIIspwPhvgnqJsH8xqFT2ZbYcvbcFanRyhFE=
|
||||
github.com/go-openapi/swag/typeutils v0.26.0 h1:2kdEwdiNWy+JJdOvu5MA2IIg2SylWAFuuyQIKYybfq4=
|
||||
github.com/go-openapi/swag/typeutils v0.26.0/go.mod h1:oovDuIUvTrEHVMqWilQzKzV4YlSKgyZmFh7AlfABNVE=
|
||||
github.com/go-openapi/swag/yamlutils v0.25.5 h1:kASCIS+oIeoc55j28T4o8KwlV2S4ZLPT6G0iq2SSbVQ=
|
||||
github.com/go-openapi/swag/yamlutils v0.25.5/go.mod h1:Gek1/SjjfbYvM+Iq4QGwa/2lEXde9n2j4a3wI3pNuOQ=
|
||||
github.com/go-openapi/testify/enable/yaml/v2 v2.4.1 h1:NZOrZmIb6PTv5LTFxr5/mKV/FjbUzGE7E6gLz7vFoOQ=
|
||||
github.com/go-openapi/testify/enable/yaml/v2 v2.4.1/go.mod h1:r7dwsujEHawapMsxA69i+XMGZrQ5tRauhLAjV/sxg3Q=
|
||||
github.com/go-openapi/testify/v2 v2.4.1 h1:zB34HDKj4tHwyUQHrUkpV0Q0iXQ6dUCOQtIqn8hE6Iw=
|
||||
github.com/go-openapi/testify/v2 v2.4.1/go.mod h1:HCPmvFFnheKK2BuwSA0TbbdxJ3I16pjwMkYkP4Ywn54=
|
||||
github.com/go-openapi/testify/enable/yaml/v2 v2.4.2 h1:5zRca5jw7lzVREKCZVNBpysDNBjj74rBh0N2BGQbSR0=
|
||||
github.com/go-openapi/testify/enable/yaml/v2 v2.4.2/go.mod h1:XVevPw5hUXuV+5AkI1u1PeAm27EQVrhXTTCPAF85LmE=
|
||||
github.com/go-openapi/testify/v2 v2.4.2 h1:tiByHpvE9uHrrKjOszax7ZvKB7QOgizBWGBLuq0ePx4=
|
||||
github.com/go-openapi/testify/v2 v2.4.2/go.mod h1:SgsVHtfooshd0tublTtJ50FPKhujf47YRqauXXOUxfw=
|
||||
github.com/go-openapi/validate v0.25.2 h1:12NsfLAwGegqbGWr2CnvT65X/Q2USJipmJ9b7xDJZz0=
|
||||
github.com/go-openapi/validate v0.25.2/go.mod h1:Pgl1LpPPGFnZ+ys4/hTlDiRYQdI1ocKypgE+8Q8BLfY=
|
||||
github.com/go-viper/mapstructure/v2 v2.5.0 h1:vM5IJoUAy3d7zRSVtIwQgBj7BiWtMPfmPEgAXnvj1Ro=
|
||||
@@ -117,8 +117,8 @@ github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsI
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||
github.com/jackc/pgx/v5 v5.9.1 h1:uwrxJXBnx76nyISkhr33kQLlUqjv7et7b9FjCen/tdc=
|
||||
github.com/jackc/pgx/v5 v5.9.1/go.mod h1:mal1tBGAFfLHvZzaYh77YS/eC6IX9OWbRV1QIIM0Jn4=
|
||||
github.com/jackc/pgx/v5 v5.9.2 h1:3ZhOzMWnR4yJ+RW1XImIPsD1aNSz4T4fyP7zlQb56hw=
|
||||
github.com/jackc/pgx/v5 v5.9.2/go.mod h1:mal1tBGAFfLHvZzaYh77YS/eC6IX9OWbRV1QIIM0Jn4=
|
||||
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
|
||||
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||
github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8=
|
||||
@@ -159,8 +159,8 @@ github.com/oklog/ulid/v2 v2.1.1/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNs
|
||||
github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o=
|
||||
github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4=
|
||||
github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8=
|
||||
github.com/pires/go-proxyproto v0.11.0 h1:gUQpS85X/VJMdUsYyEgyn59uLJvGqPhJV5YvG68wXH4=
|
||||
github.com/pires/go-proxyproto v0.11.0/go.mod h1:ZKAAyp3cgy5Y5Mo4n9AlScrkCZwUy0g3Jf+slqQVcuU=
|
||||
github.com/pires/go-proxyproto v0.12.0 h1:TTCxD66dU898tahivkqc3hoceZp7P44FnorWyo9d5vM=
|
||||
github.com/pires/go-proxyproto v0.12.0/go.mod h1:qUvfqUMEoX7T8g0q7TQLDnhMjdTrxnG0hvpMn+7ePNI=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
@@ -199,14 +199,14 @@ github.com/wwt/guac v1.3.2/go.mod h1:eKm+NrnK7A88l4UBEcYNpZQGMpZRryYKoz4D/0/n1C0
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
|
||||
go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
|
||||
go.opentelemetry.io/otel v1.41.0 h1:YlEwVsGAlCvczDILpUXpIpPSL/VPugt7zHThEMLce1c=
|
||||
go.opentelemetry.io/otel v1.41.0/go.mod h1:Yt4UwgEKeT05QbLwbyHXEwhnjxNO6D8L5PQP51/46dE=
|
||||
go.opentelemetry.io/otel/metric v1.41.0 h1:rFnDcs4gRzBcsO9tS8LCpgR0dxg4aaxWlJxCno7JlTQ=
|
||||
go.opentelemetry.io/otel/metric v1.41.0/go.mod h1:xPvCwd9pU0VN8tPZYzDZV/BMj9CM9vs00GuBjeKhJps=
|
||||
go.opentelemetry.io/otel/sdk v1.41.0 h1:YPIEXKmiAwkGl3Gu1huk1aYWwtpRLeskpV+wPisxBp8=
|
||||
go.opentelemetry.io/otel/sdk v1.41.0/go.mod h1:ahFdU0G5y8IxglBf0QBJXgSe7agzjE4GiTJ6HT9ud90=
|
||||
go.opentelemetry.io/otel/trace v1.41.0 h1:Vbk2co6bhj8L59ZJ6/xFTskY+tGAbOnCtQGVVa9TIN0=
|
||||
go.opentelemetry.io/otel/trace v1.41.0/go.mod h1:U1NU4ULCoxeDKc09yCWdWe+3QoyweJcISEVa1RBzOis=
|
||||
go.opentelemetry.io/otel v1.43.0 h1:mYIM03dnh5zfN7HautFE4ieIig9amkNANT+xcVxAj9I=
|
||||
go.opentelemetry.io/otel v1.43.0/go.mod h1:JuG+u74mvjvcm8vj8pI5XiHy1zDeoCS2LB1spIq7Ay0=
|
||||
go.opentelemetry.io/otel/metric v1.43.0 h1:d7638QeInOnuwOONPp4JAOGfbCEpYb+K6DVWvdxGzgM=
|
||||
go.opentelemetry.io/otel/metric v1.43.0/go.mod h1:RDnPtIxvqlgO8GRW18W6Z/4P462ldprJtfxHxyKd2PY=
|
||||
go.opentelemetry.io/otel/sdk v1.43.0 h1:pi5mE86i5rTeLXqoF/hhiBtUNcrAGHLKQdhg4h4V9Dg=
|
||||
go.opentelemetry.io/otel/sdk v1.43.0/go.mod h1:P+IkVU3iWukmiit/Yf9AWvpyRDlUeBaRg6Y+C58QHzg=
|
||||
go.opentelemetry.io/otel/trace v1.43.0 h1:BkNrHpup+4k4w+ZZ86CZoHHEkohws8AY+WTX09nk+3A=
|
||||
go.opentelemetry.io/otel/trace v1.43.0/go.mod h1:/QJhyVBUUswCphDVxq+8mld+AvhXZLhe+8WVFxiFff0=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.yaml.in/yaml/v2 v2.4.2 h1:DzmwEr2rDGHl7lsFgAHxmNz/1NlQ7xLIrlN2h5d1eGI=
|
||||
@@ -216,8 +216,8 @@ go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
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=
|
||||
golang.org/x/crypto v0.48.0 h1:/VRzVqiRSggnhY7gNRxPauEQ5Drw9haKdM0jqfcCFts=
|
||||
golang.org/x/crypto v0.48.0/go.mod h1:r0kV5h3qnFPlQnBSrULhlsRfryS2pmewsg+XfMgkVos=
|
||||
golang.org/x/crypto v0.49.0 h1:+Ng2ULVvLHnJ/ZFEq4KdcDd/cfjrrjjNSXNzxg0Y4U4=
|
||||
golang.org/x/crypto v0.49.0/go.mod h1:ErX4dUh2UM+CFYiXZRTcMpEcN8b/1gxEuv3nODoYtCA=
|
||||
golang.org/x/exp v0.0.0-20230210204819-062eb4c674ab h1:628ME69lBm9C6JY2wXhAph/yjN3jezx1z7BIDLUwxjo=
|
||||
golang.org/x/exp v0.0.0-20230210204819-062eb4c674ab/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
@@ -227,8 +227,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60=
|
||||
golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM=
|
||||
golang.org/x/net v0.52.0 h1:He/TN1l0e4mmR3QqHMT2Xab3Aj3L9qjbhRm78/6jrW0=
|
||||
golang.org/x/net v0.52.0/go.mod h1:R1MAz7uMZxVMualyPXb+VaqGSa3LIaUqk0eEt3w36Sw=
|
||||
golang.org/x/oauth2 v0.36.0 h1:peZ/1z27fi9hUOFCAZaHyrpWG5lwe0RJEEEeH0ThlIs=
|
||||
golang.org/x/oauth2 v0.36.0/go.mod h1:YDBUJMTkDnJS+A4BP4eZBjCqtokkg1hODuPjwiGPO7Q=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -245,8 +245,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.41.0 h1:Ivj+2Cp/ylzLiEU89QhWblYnOE9zerudt9Ftecq2C6k=
|
||||
golang.org/x/sys v0.41.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
|
||||
golang.org/x/sys v0.42.0 h1:omrd2nAlyT5ESRdCLYdm3+fMfNFE/+Rf4bDIQImRJeo=
|
||||
golang.org/x/sys v0.42.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
@@ -258,8 +258,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.34.0 h1:oL/Qq0Kdaqxa1KbNeMKwQq0reLCCaFtqu2eNuSeNHbk=
|
||||
golang.org/x/text v0.34.0/go.mod h1:homfLqTYRFyVYemLBFl5GgL/DWEiH5wcsQ5gSh1yziA=
|
||||
golang.org/x/text v0.35.0 h1:JOVx6vVDFokkpaq1AEptVzLTpDe9KGpj5tR4/X+ybL8=
|
||||
golang.org/x/text v0.35.0/go.mod h1:khi/HExzZJ2pGnjenulevKNX1W67CUy0AsXcNubPGCA=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"runtime"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
@@ -45,6 +46,7 @@ type APIController struct {
|
||||
reloadOffset time.Duration
|
||||
|
||||
eventConn *websocket.Conn
|
||||
eventConnMu sync.Mutex
|
||||
lastWsReconnect time.Time
|
||||
wsIsReconnecting bool
|
||||
eventHandlers []EventHandler
|
||||
|
||||
@@ -77,7 +77,12 @@ func (ac *APIController) initEvent(outpostUUID string, attempt int) error {
|
||||
Instruction: EventKindHello,
|
||||
Args: ac.getEventPingArgs(),
|
||||
}
|
||||
// Serialize this write against concurrent SendEventHello callers (health
|
||||
// ticker, RAC handlers) sharing the same *websocket.Conn. Gorilla's Conn
|
||||
// does not permit concurrent writes.
|
||||
ac.eventConnMu.Lock()
|
||||
err = ws.WriteJSON(msg)
|
||||
ac.eventConnMu.Unlock()
|
||||
if err != nil {
|
||||
ac.logger.WithField("logger", "authentik.outpost.events").WithError(err).Warning("Failed to hello to authentik")
|
||||
return err
|
||||
@@ -91,7 +96,9 @@ func (ac *APIController) initEvent(outpostUUID string, attempt int) error {
|
||||
func (ac *APIController) Shutdown() {
|
||||
// Cleanly close the connection by sending a close message and then
|
||||
// waiting (with timeout) for the server to close the connection.
|
||||
ac.eventConnMu.Lock()
|
||||
err := ac.eventConn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
|
||||
ac.eventConnMu.Unlock()
|
||||
if err != nil {
|
||||
ac.logger.WithError(err).Warning("failed to write close message")
|
||||
return
|
||||
@@ -252,6 +259,10 @@ func (a *APIController) SendEventHello(args map[string]any) error {
|
||||
Instruction: EventKindHello,
|
||||
Args: allArgs,
|
||||
}
|
||||
// Gorilla *websocket.Conn does not permit concurrent writes. This method
|
||||
// is invoked from the health ticker and from RAC session handlers.
|
||||
a.eventConnMu.Lock()
|
||||
err := a.eventConn.WriteJSON(aliveMsg)
|
||||
a.eventConnMu.Unlock()
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -84,12 +84,6 @@ if [[ "$1" == "server" ]]; then
|
||||
elif [[ "$1" == "worker" ]]; then
|
||||
set_mode "worker"
|
||||
shift
|
||||
# If we have bootstrap credentials set, run bootstrap tasks outside of main server
|
||||
# sync, so that we can sure the first start actually has working bootstrap
|
||||
# credentials
|
||||
if [[ -n "${AUTHENTIK_BOOTSTRAP_PASSWORD}" || -n "${AUTHENTIK_BOOTSTRAP_TOKEN}" ]]; then
|
||||
python -m manage apply_blueprint system/bootstrap.yaml || true
|
||||
fi
|
||||
check_if_root "python -m manage worker --pid-file ${TMPDIR}/authentik-worker.pid $@"
|
||||
elif [[ "$1" == "bash" ]]; then
|
||||
/bin/bash
|
||||
|
||||
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.1118.0",
|
||||
"aws-cdk": "^2.1118.4",
|
||||
"cross-env": "^10.1.0"
|
||||
},
|
||||
"engines": {
|
||||
@@ -25,9 +25,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/aws-cdk": {
|
||||
"version": "2.1118.0",
|
||||
"resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1118.0.tgz",
|
||||
"integrity": "sha512-Tfd865GRewDTXIbTVtix/l+v8t3rZENvdHcQQZS2wXYVXfHzljULFXe9JKkgZUNDPB1zo9tSBUu8jjiHRm7nWg==",
|
||||
"version": "2.1118.4",
|
||||
"resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1118.4.tgz",
|
||||
"integrity": "sha512-wJfRQdvb+FJ2cni059mYdmjhfwhMskP+PAB59BL9jhon+jYtjy8X3pbj3uzHgAOJwNhh6jGkP8xq36Cffccbbw==",
|
||||
"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.1118.0",
|
||||
"aws-cdk": "^2.1118.4",
|
||||
"cross-env": "^10.1.0"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
# Stage 1: Build webui
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/library/node:24-trixie-slim@sha256:9707cd4542f400df5078df04f9652a272429112f15202d22b5b8bdd148df494f AS node-builder
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/library/node:24-trixie-slim@sha256:735dd688da64d22ebd9dd374b3e7e5a874635668fd2a6ec20ca1f99264294086 AS node-builder
|
||||
|
||||
ARG GIT_BUILD_HASH
|
||||
ENV GIT_BUILD_HASH=$GIT_BUILD_HASH
|
||||
@@ -29,7 +29,7 @@ RUN npm run build && \
|
||||
npm run build:sfe
|
||||
|
||||
# Stage 2: Build go proxy
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.26.2-trixie@sha256:c0074c718b473f3827043f86532c4c0ff537e3fe7a81b8219b0d1ccfcc2c9a09 AS go-builder
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.26.2-trixie@sha256:982ae929f9a74083a242c6e25d19d7d9ed78c6e97fab639a119e90707ba819e2 AS go-builder
|
||||
|
||||
ARG TARGETOS
|
||||
ARG TARGETARCH
|
||||
@@ -42,8 +42,9 @@ WORKDIR /go/src/goauthentik.io
|
||||
|
||||
RUN --mount=type=cache,id=apt-$TARGETARCH$TARGETVARIANT,sharing=locked,target=/var/cache/apt \
|
||||
dpkg --add-architecture arm64 && \
|
||||
dpkg --add-architecture amd64 && \
|
||||
apt-get update && \
|
||||
apt-get install -y --no-install-recommends crossbuild-essential-arm64 gcc-aarch64-linux-gnu
|
||||
apt-get install -y --no-install-recommends crossbuild-essential-arm64 gcc-aarch64-linux-gnu crossbuild-essential-amd64 gcc-x86-64-linux-gnu
|
||||
|
||||
RUN --mount=type=bind,target=/go/src/goauthentik.io/go.mod,src=./go.mod \
|
||||
--mount=type=bind,target=/go/src/goauthentik.io/go.sum,src=./go.sum \
|
||||
@@ -62,7 +63,8 @@ COPY ./packages/client-go /go/src/goauthentik.io/packages/client-go
|
||||
|
||||
RUN --mount=type=cache,sharing=locked,target=/go/pkg/mod \
|
||||
--mount=type=cache,id=go-build-$TARGETARCH$TARGETVARIANT,sharing=locked,target=/root/.cache/go-build \
|
||||
if [ "$TARGETARCH" = "arm64" ]; then export CC=aarch64-linux-gnu-gcc && export CC_FOR_TARGET=gcc-aarch64-linux-gnu; fi && \
|
||||
if [ "$TARGETARCH" = "arm64" ] && [ "$(uname -m)" != "aarch64" ]; then export CC=aarch64-linux-gnu-gcc && export CC_FOR_TARGET=gcc-aarch64-linux-gnu; fi && \
|
||||
if [ "$TARGETARCH" = "amd64" ] && [ "$(uname -m)" != "x86_64" ]; then export CC=x86_64-linux-gnu-gcc; fi && \
|
||||
CGO_ENABLED=1 GOFIPS140=latest GOARM="${TARGETVARIANT#v}" \
|
||||
go build -o /go/authentik ./cmd/server
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
# Stage 1: Build
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.26.2-trixie@sha256:c0074c718b473f3827043f86532c4c0ff537e3fe7a81b8219b0d1ccfcc2c9a09 AS builder
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.26.2-trixie@sha256:982ae929f9a74083a242c6e25d19d7d9ed78c6e97fab639a119e90707ba819e2 AS builder
|
||||
|
||||
ARG TARGETOS
|
||||
ARG TARGETARCH
|
||||
|
||||
@@ -21,7 +21,7 @@ COPY web .
|
||||
RUN npm run build-proxy
|
||||
|
||||
# Stage 2: Build
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.26.2-trixie@sha256:c0074c718b473f3827043f86532c4c0ff537e3fe7a81b8219b0d1ccfcc2c9a09 AS builder
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.26.2-trixie@sha256:982ae929f9a74083a242c6e25d19d7d9ed78c6e97fab639a119e90707ba819e2 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.2-trixie@sha256:c0074c718b473f3827043f86532c4c0ff537e3fe7a81b8219b0d1ccfcc2c9a09 AS builder
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.26.2-trixie@sha256:982ae929f9a74083a242c6e25d19d7d9ed78c6e97fab639a119e90707ba819e2 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.2-trixie@sha256:c0074c718b473f3827043f86532c4c0ff537e3fe7a81b8219b0d1ccfcc2c9a09 AS builder
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.26.2-trixie@sha256:982ae929f9a74083a242c6e25d19d7d9ed78c6e97fab639a119e90707ba819e2 AS builder
|
||||
|
||||
ARG TARGETOS
|
||||
ARG TARGETARCH
|
||||
|
||||
@@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2026-04-08 00:28+0000\n"
|
||||
"POT-Creation-Date: 2026-04-23 00:25+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@@ -732,6 +732,14 @@ msgstr ""
|
||||
msgid "Apple Nonces"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/endpoints/connectors/agent/models.py
|
||||
msgid "Apple Independent Secure Enclave"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/endpoints/connectors/agent/models.py
|
||||
msgid "Apple Independent Secure Enclaves"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/endpoints/facts.py
|
||||
msgid "Operating System name, such as 'Server 2022' or 'Ubuntu'"
|
||||
msgstr ""
|
||||
@@ -1571,6 +1579,10 @@ msgstr ""
|
||||
msgid "Flow Tokens"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/flows/planner.py
|
||||
msgid "This link is invalid or has expired. Please request a new one."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/flows/views/executor.py
|
||||
msgid "Invalid next URL"
|
||||
msgstr ""
|
||||
|
||||
@@ -4,3 +4,4 @@ Yubi
|
||||
Yubikey
|
||||
Yubikeys
|
||||
mycorp
|
||||
mocksaml
|
||||
|
||||
12
package-lock.json
generated
12
package-lock.json
generated
@@ -1843,9 +1843,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "1.1.13",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz",
|
||||
"integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==",
|
||||
"version": "1.1.14",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz",
|
||||
"integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
@@ -5373,9 +5373,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/postcss": {
|
||||
"version": "8.5.8",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz",
|
||||
"integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==",
|
||||
"version": "8.5.10",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.10.tgz",
|
||||
"integrity": "sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
|
||||
552
packages/client-ts/src/apis/EndpointsApi.ts
generated
552
packages/client-ts/src/apis/EndpointsApi.ts
generated
@@ -21,6 +21,8 @@ import type {
|
||||
AgentPSSODeviceRegistrationResponse,
|
||||
AgentPSSOUserRegistrationRequest,
|
||||
AgentTokenResponse,
|
||||
AppleIndependentSecureEnclave,
|
||||
AppleIndependentSecureEnclaveRequest,
|
||||
Connector,
|
||||
DeviceAccessGroup,
|
||||
DeviceAccessGroupRequest,
|
||||
@@ -41,6 +43,7 @@ import type {
|
||||
MDMConfigRequest,
|
||||
MDMConfigResponse,
|
||||
PaginatedAgentConnectorList,
|
||||
PaginatedAppleIndependentSecureEnclaveList,
|
||||
PaginatedConnectorList,
|
||||
PaginatedDeviceAccessGroupList,
|
||||
PaginatedDeviceUserBindingList,
|
||||
@@ -49,6 +52,7 @@ import type {
|
||||
PaginatedFleetConnectorList,
|
||||
PaginatedGoogleChromeConnectorList,
|
||||
PatchedAgentConnectorRequest,
|
||||
PatchedAppleIndependentSecureEnclaveRequest,
|
||||
PatchedDeviceAccessGroupRequest,
|
||||
PatchedDeviceUserBindingRequest,
|
||||
PatchedEndpointDeviceRequest,
|
||||
@@ -69,6 +73,8 @@ import {
|
||||
AgentPSSODeviceRegistrationResponseFromJSON,
|
||||
AgentPSSOUserRegistrationRequestToJSON,
|
||||
AgentTokenResponseFromJSON,
|
||||
AppleIndependentSecureEnclaveFromJSON,
|
||||
AppleIndependentSecureEnclaveRequestToJSON,
|
||||
ConnectorFromJSON,
|
||||
DeviceAccessGroupFromJSON,
|
||||
DeviceAccessGroupRequestToJSON,
|
||||
@@ -89,6 +95,7 @@ import {
|
||||
MDMConfigRequestToJSON,
|
||||
MDMConfigResponseFromJSON,
|
||||
PaginatedAgentConnectorListFromJSON,
|
||||
PaginatedAppleIndependentSecureEnclaveListFromJSON,
|
||||
PaginatedConnectorListFromJSON,
|
||||
PaginatedDeviceAccessGroupListFromJSON,
|
||||
PaginatedDeviceUserBindingListFromJSON,
|
||||
@@ -97,6 +104,7 @@ import {
|
||||
PaginatedFleetConnectorListFromJSON,
|
||||
PaginatedGoogleChromeConnectorListFromJSON,
|
||||
PatchedAgentConnectorRequestToJSON,
|
||||
PatchedAppleIndependentSecureEnclaveRequestToJSON,
|
||||
PatchedDeviceAccessGroupRequestToJSON,
|
||||
PatchedDeviceUserBindingRequestToJSON,
|
||||
PatchedEndpointDeviceRequestToJSON,
|
||||
@@ -201,6 +209,41 @@ export interface EndpointsAgentsEnrollmentTokensViewKeyRetrieveRequest {
|
||||
tokenUuid: string;
|
||||
}
|
||||
|
||||
export interface EndpointsAgentsPssoIseCreateRequest {
|
||||
appleIndependentSecureEnclaveRequest: AppleIndependentSecureEnclaveRequest;
|
||||
}
|
||||
|
||||
export interface EndpointsAgentsPssoIseDestroyRequest {
|
||||
uuid: string;
|
||||
}
|
||||
|
||||
export interface EndpointsAgentsPssoIseListRequest {
|
||||
appleEnclaveKeyId?: string;
|
||||
ordering?: string;
|
||||
page?: number;
|
||||
pageSize?: number;
|
||||
search?: string;
|
||||
user?: number;
|
||||
}
|
||||
|
||||
export interface EndpointsAgentsPssoIsePartialUpdateRequest {
|
||||
uuid: string;
|
||||
patchedAppleIndependentSecureEnclaveRequest?: PatchedAppleIndependentSecureEnclaveRequest;
|
||||
}
|
||||
|
||||
export interface EndpointsAgentsPssoIseRetrieveRequest {
|
||||
uuid: string;
|
||||
}
|
||||
|
||||
export interface EndpointsAgentsPssoIseUpdateRequest {
|
||||
uuid: string;
|
||||
appleIndependentSecureEnclaveRequest: AppleIndependentSecureEnclaveRequest;
|
||||
}
|
||||
|
||||
export interface EndpointsAgentsPssoIseUsedByListRequest {
|
||||
uuid: string;
|
||||
}
|
||||
|
||||
export interface EndpointsAgentsPssoRegisterDeviceCreateRequest {
|
||||
agentPSSODeviceRegistrationRequest: AgentPSSODeviceRegistrationRequest;
|
||||
}
|
||||
@@ -1822,6 +1865,515 @@ export class EndpointsApi extends runtime.BaseAPI {
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates request options for endpointsAgentsPssoIseCreate without sending the request
|
||||
*/
|
||||
async endpointsAgentsPssoIseCreateRequestOpts(
|
||||
requestParameters: EndpointsAgentsPssoIseCreateRequest,
|
||||
): Promise<runtime.RequestOpts> {
|
||||
if (requestParameters["appleIndependentSecureEnclaveRequest"] == null) {
|
||||
throw new runtime.RequiredError(
|
||||
"appleIndependentSecureEnclaveRequest",
|
||||
'Required parameter "appleIndependentSecureEnclaveRequest" was null or undefined when calling endpointsAgentsPssoIseCreate().',
|
||||
);
|
||||
}
|
||||
|
||||
const queryParameters: any = {};
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
headerParameters["Content-Type"] = "application/json";
|
||||
|
||||
if (this.configuration && this.configuration.accessToken) {
|
||||
const token = this.configuration.accessToken;
|
||||
const tokenString = await token("authentik", []);
|
||||
|
||||
if (tokenString) {
|
||||
headerParameters["Authorization"] = `Bearer ${tokenString}`;
|
||||
}
|
||||
}
|
||||
|
||||
let urlPath = `/endpoints/agents/psso/ise/`;
|
||||
|
||||
return {
|
||||
path: urlPath,
|
||||
method: "POST",
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
body: AppleIndependentSecureEnclaveRequestToJSON(
|
||||
requestParameters["appleIndependentSecureEnclaveRequest"],
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Mixin to add a used_by endpoint to return a list of all objects using this object
|
||||
*/
|
||||
async endpointsAgentsPssoIseCreateRaw(
|
||||
requestParameters: EndpointsAgentsPssoIseCreateRequest,
|
||||
initOverrides?: RequestInit | runtime.InitOverrideFunction,
|
||||
): Promise<runtime.ApiResponse<AppleIndependentSecureEnclave>> {
|
||||
const requestOptions =
|
||||
await this.endpointsAgentsPssoIseCreateRequestOpts(requestParameters);
|
||||
const response = await this.request(requestOptions, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) =>
|
||||
AppleIndependentSecureEnclaveFromJSON(jsonValue),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mixin to add a used_by endpoint to return a list of all objects using this object
|
||||
*/
|
||||
async endpointsAgentsPssoIseCreate(
|
||||
requestParameters: EndpointsAgentsPssoIseCreateRequest,
|
||||
initOverrides?: RequestInit | runtime.InitOverrideFunction,
|
||||
): Promise<AppleIndependentSecureEnclave> {
|
||||
const response = await this.endpointsAgentsPssoIseCreateRaw(
|
||||
requestParameters,
|
||||
initOverrides,
|
||||
);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates request options for endpointsAgentsPssoIseDestroy without sending the request
|
||||
*/
|
||||
async endpointsAgentsPssoIseDestroyRequestOpts(
|
||||
requestParameters: EndpointsAgentsPssoIseDestroyRequest,
|
||||
): Promise<runtime.RequestOpts> {
|
||||
if (requestParameters["uuid"] == null) {
|
||||
throw new runtime.RequiredError(
|
||||
"uuid",
|
||||
'Required parameter "uuid" was null or undefined when calling endpointsAgentsPssoIseDestroy().',
|
||||
);
|
||||
}
|
||||
|
||||
const queryParameters: any = {};
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
if (this.configuration && this.configuration.accessToken) {
|
||||
const token = this.configuration.accessToken;
|
||||
const tokenString = await token("authentik", []);
|
||||
|
||||
if (tokenString) {
|
||||
headerParameters["Authorization"] = `Bearer ${tokenString}`;
|
||||
}
|
||||
}
|
||||
|
||||
let urlPath = `/endpoints/agents/psso/ise/{uuid}/`;
|
||||
urlPath = urlPath.replace(
|
||||
`{${"uuid"}}`,
|
||||
encodeURIComponent(String(requestParameters["uuid"])),
|
||||
);
|
||||
|
||||
return {
|
||||
path: urlPath,
|
||||
method: "DELETE",
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Mixin to add a used_by endpoint to return a list of all objects using this object
|
||||
*/
|
||||
async endpointsAgentsPssoIseDestroyRaw(
|
||||
requestParameters: EndpointsAgentsPssoIseDestroyRequest,
|
||||
initOverrides?: RequestInit | runtime.InitOverrideFunction,
|
||||
): Promise<runtime.ApiResponse<void>> {
|
||||
const requestOptions =
|
||||
await this.endpointsAgentsPssoIseDestroyRequestOpts(requestParameters);
|
||||
const response = await this.request(requestOptions, initOverrides);
|
||||
|
||||
return new runtime.VoidApiResponse(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mixin to add a used_by endpoint to return a list of all objects using this object
|
||||
*/
|
||||
async endpointsAgentsPssoIseDestroy(
|
||||
requestParameters: EndpointsAgentsPssoIseDestroyRequest,
|
||||
initOverrides?: RequestInit | runtime.InitOverrideFunction,
|
||||
): Promise<void> {
|
||||
await this.endpointsAgentsPssoIseDestroyRaw(requestParameters, initOverrides);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates request options for endpointsAgentsPssoIseList without sending the request
|
||||
*/
|
||||
async endpointsAgentsPssoIseListRequestOpts(
|
||||
requestParameters: EndpointsAgentsPssoIseListRequest,
|
||||
): Promise<runtime.RequestOpts> {
|
||||
const queryParameters: any = {};
|
||||
|
||||
if (requestParameters["appleEnclaveKeyId"] != null) {
|
||||
queryParameters["apple_enclave_key_id"] = requestParameters["appleEnclaveKeyId"];
|
||||
}
|
||||
|
||||
if (requestParameters["ordering"] != null) {
|
||||
queryParameters["ordering"] = requestParameters["ordering"];
|
||||
}
|
||||
|
||||
if (requestParameters["page"] != null) {
|
||||
queryParameters["page"] = requestParameters["page"];
|
||||
}
|
||||
|
||||
if (requestParameters["pageSize"] != null) {
|
||||
queryParameters["page_size"] = requestParameters["pageSize"];
|
||||
}
|
||||
|
||||
if (requestParameters["search"] != null) {
|
||||
queryParameters["search"] = requestParameters["search"];
|
||||
}
|
||||
|
||||
if (requestParameters["user"] != null) {
|
||||
queryParameters["user"] = requestParameters["user"];
|
||||
}
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
if (this.configuration && this.configuration.accessToken) {
|
||||
const token = this.configuration.accessToken;
|
||||
const tokenString = await token("authentik", []);
|
||||
|
||||
if (tokenString) {
|
||||
headerParameters["Authorization"] = `Bearer ${tokenString}`;
|
||||
}
|
||||
}
|
||||
|
||||
let urlPath = `/endpoints/agents/psso/ise/`;
|
||||
|
||||
return {
|
||||
path: urlPath,
|
||||
method: "GET",
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Mixin to add a used_by endpoint to return a list of all objects using this object
|
||||
*/
|
||||
async endpointsAgentsPssoIseListRaw(
|
||||
requestParameters: EndpointsAgentsPssoIseListRequest,
|
||||
initOverrides?: RequestInit | runtime.InitOverrideFunction,
|
||||
): Promise<runtime.ApiResponse<PaginatedAppleIndependentSecureEnclaveList>> {
|
||||
const requestOptions = await this.endpointsAgentsPssoIseListRequestOpts(requestParameters);
|
||||
const response = await this.request(requestOptions, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) =>
|
||||
PaginatedAppleIndependentSecureEnclaveListFromJSON(jsonValue),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mixin to add a used_by endpoint to return a list of all objects using this object
|
||||
*/
|
||||
async endpointsAgentsPssoIseList(
|
||||
requestParameters: EndpointsAgentsPssoIseListRequest = {},
|
||||
initOverrides?: RequestInit | runtime.InitOverrideFunction,
|
||||
): Promise<PaginatedAppleIndependentSecureEnclaveList> {
|
||||
const response = await this.endpointsAgentsPssoIseListRaw(requestParameters, initOverrides);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates request options for endpointsAgentsPssoIsePartialUpdate without sending the request
|
||||
*/
|
||||
async endpointsAgentsPssoIsePartialUpdateRequestOpts(
|
||||
requestParameters: EndpointsAgentsPssoIsePartialUpdateRequest,
|
||||
): Promise<runtime.RequestOpts> {
|
||||
if (requestParameters["uuid"] == null) {
|
||||
throw new runtime.RequiredError(
|
||||
"uuid",
|
||||
'Required parameter "uuid" was null or undefined when calling endpointsAgentsPssoIsePartialUpdate().',
|
||||
);
|
||||
}
|
||||
|
||||
const queryParameters: any = {};
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
headerParameters["Content-Type"] = "application/json";
|
||||
|
||||
if (this.configuration && this.configuration.accessToken) {
|
||||
const token = this.configuration.accessToken;
|
||||
const tokenString = await token("authentik", []);
|
||||
|
||||
if (tokenString) {
|
||||
headerParameters["Authorization"] = `Bearer ${tokenString}`;
|
||||
}
|
||||
}
|
||||
|
||||
let urlPath = `/endpoints/agents/psso/ise/{uuid}/`;
|
||||
urlPath = urlPath.replace(
|
||||
`{${"uuid"}}`,
|
||||
encodeURIComponent(String(requestParameters["uuid"])),
|
||||
);
|
||||
|
||||
return {
|
||||
path: urlPath,
|
||||
method: "PATCH",
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
body: PatchedAppleIndependentSecureEnclaveRequestToJSON(
|
||||
requestParameters["patchedAppleIndependentSecureEnclaveRequest"],
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Mixin to add a used_by endpoint to return a list of all objects using this object
|
||||
*/
|
||||
async endpointsAgentsPssoIsePartialUpdateRaw(
|
||||
requestParameters: EndpointsAgentsPssoIsePartialUpdateRequest,
|
||||
initOverrides?: RequestInit | runtime.InitOverrideFunction,
|
||||
): Promise<runtime.ApiResponse<AppleIndependentSecureEnclave>> {
|
||||
const requestOptions =
|
||||
await this.endpointsAgentsPssoIsePartialUpdateRequestOpts(requestParameters);
|
||||
const response = await this.request(requestOptions, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) =>
|
||||
AppleIndependentSecureEnclaveFromJSON(jsonValue),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mixin to add a used_by endpoint to return a list of all objects using this object
|
||||
*/
|
||||
async endpointsAgentsPssoIsePartialUpdate(
|
||||
requestParameters: EndpointsAgentsPssoIsePartialUpdateRequest,
|
||||
initOverrides?: RequestInit | runtime.InitOverrideFunction,
|
||||
): Promise<AppleIndependentSecureEnclave> {
|
||||
const response = await this.endpointsAgentsPssoIsePartialUpdateRaw(
|
||||
requestParameters,
|
||||
initOverrides,
|
||||
);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates request options for endpointsAgentsPssoIseRetrieve without sending the request
|
||||
*/
|
||||
async endpointsAgentsPssoIseRetrieveRequestOpts(
|
||||
requestParameters: EndpointsAgentsPssoIseRetrieveRequest,
|
||||
): Promise<runtime.RequestOpts> {
|
||||
if (requestParameters["uuid"] == null) {
|
||||
throw new runtime.RequiredError(
|
||||
"uuid",
|
||||
'Required parameter "uuid" was null or undefined when calling endpointsAgentsPssoIseRetrieve().',
|
||||
);
|
||||
}
|
||||
|
||||
const queryParameters: any = {};
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
if (this.configuration && this.configuration.accessToken) {
|
||||
const token = this.configuration.accessToken;
|
||||
const tokenString = await token("authentik", []);
|
||||
|
||||
if (tokenString) {
|
||||
headerParameters["Authorization"] = `Bearer ${tokenString}`;
|
||||
}
|
||||
}
|
||||
|
||||
let urlPath = `/endpoints/agents/psso/ise/{uuid}/`;
|
||||
urlPath = urlPath.replace(
|
||||
`{${"uuid"}}`,
|
||||
encodeURIComponent(String(requestParameters["uuid"])),
|
||||
);
|
||||
|
||||
return {
|
||||
path: urlPath,
|
||||
method: "GET",
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Mixin to add a used_by endpoint to return a list of all objects using this object
|
||||
*/
|
||||
async endpointsAgentsPssoIseRetrieveRaw(
|
||||
requestParameters: EndpointsAgentsPssoIseRetrieveRequest,
|
||||
initOverrides?: RequestInit | runtime.InitOverrideFunction,
|
||||
): Promise<runtime.ApiResponse<AppleIndependentSecureEnclave>> {
|
||||
const requestOptions =
|
||||
await this.endpointsAgentsPssoIseRetrieveRequestOpts(requestParameters);
|
||||
const response = await this.request(requestOptions, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) =>
|
||||
AppleIndependentSecureEnclaveFromJSON(jsonValue),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mixin to add a used_by endpoint to return a list of all objects using this object
|
||||
*/
|
||||
async endpointsAgentsPssoIseRetrieve(
|
||||
requestParameters: EndpointsAgentsPssoIseRetrieveRequest,
|
||||
initOverrides?: RequestInit | runtime.InitOverrideFunction,
|
||||
): Promise<AppleIndependentSecureEnclave> {
|
||||
const response = await this.endpointsAgentsPssoIseRetrieveRaw(
|
||||
requestParameters,
|
||||
initOverrides,
|
||||
);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates request options for endpointsAgentsPssoIseUpdate without sending the request
|
||||
*/
|
||||
async endpointsAgentsPssoIseUpdateRequestOpts(
|
||||
requestParameters: EndpointsAgentsPssoIseUpdateRequest,
|
||||
): Promise<runtime.RequestOpts> {
|
||||
if (requestParameters["uuid"] == null) {
|
||||
throw new runtime.RequiredError(
|
||||
"uuid",
|
||||
'Required parameter "uuid" was null or undefined when calling endpointsAgentsPssoIseUpdate().',
|
||||
);
|
||||
}
|
||||
|
||||
if (requestParameters["appleIndependentSecureEnclaveRequest"] == null) {
|
||||
throw new runtime.RequiredError(
|
||||
"appleIndependentSecureEnclaveRequest",
|
||||
'Required parameter "appleIndependentSecureEnclaveRequest" was null or undefined when calling endpointsAgentsPssoIseUpdate().',
|
||||
);
|
||||
}
|
||||
|
||||
const queryParameters: any = {};
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
headerParameters["Content-Type"] = "application/json";
|
||||
|
||||
if (this.configuration && this.configuration.accessToken) {
|
||||
const token = this.configuration.accessToken;
|
||||
const tokenString = await token("authentik", []);
|
||||
|
||||
if (tokenString) {
|
||||
headerParameters["Authorization"] = `Bearer ${tokenString}`;
|
||||
}
|
||||
}
|
||||
|
||||
let urlPath = `/endpoints/agents/psso/ise/{uuid}/`;
|
||||
urlPath = urlPath.replace(
|
||||
`{${"uuid"}}`,
|
||||
encodeURIComponent(String(requestParameters["uuid"])),
|
||||
);
|
||||
|
||||
return {
|
||||
path: urlPath,
|
||||
method: "PUT",
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
body: AppleIndependentSecureEnclaveRequestToJSON(
|
||||
requestParameters["appleIndependentSecureEnclaveRequest"],
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Mixin to add a used_by endpoint to return a list of all objects using this object
|
||||
*/
|
||||
async endpointsAgentsPssoIseUpdateRaw(
|
||||
requestParameters: EndpointsAgentsPssoIseUpdateRequest,
|
||||
initOverrides?: RequestInit | runtime.InitOverrideFunction,
|
||||
): Promise<runtime.ApiResponse<AppleIndependentSecureEnclave>> {
|
||||
const requestOptions =
|
||||
await this.endpointsAgentsPssoIseUpdateRequestOpts(requestParameters);
|
||||
const response = await this.request(requestOptions, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) =>
|
||||
AppleIndependentSecureEnclaveFromJSON(jsonValue),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mixin to add a used_by endpoint to return a list of all objects using this object
|
||||
*/
|
||||
async endpointsAgentsPssoIseUpdate(
|
||||
requestParameters: EndpointsAgentsPssoIseUpdateRequest,
|
||||
initOverrides?: RequestInit | runtime.InitOverrideFunction,
|
||||
): Promise<AppleIndependentSecureEnclave> {
|
||||
const response = await this.endpointsAgentsPssoIseUpdateRaw(
|
||||
requestParameters,
|
||||
initOverrides,
|
||||
);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates request options for endpointsAgentsPssoIseUsedByList without sending the request
|
||||
*/
|
||||
async endpointsAgentsPssoIseUsedByListRequestOpts(
|
||||
requestParameters: EndpointsAgentsPssoIseUsedByListRequest,
|
||||
): Promise<runtime.RequestOpts> {
|
||||
if (requestParameters["uuid"] == null) {
|
||||
throw new runtime.RequiredError(
|
||||
"uuid",
|
||||
'Required parameter "uuid" was null or undefined when calling endpointsAgentsPssoIseUsedByList().',
|
||||
);
|
||||
}
|
||||
|
||||
const queryParameters: any = {};
|
||||
|
||||
const headerParameters: runtime.HTTPHeaders = {};
|
||||
|
||||
if (this.configuration && this.configuration.accessToken) {
|
||||
const token = this.configuration.accessToken;
|
||||
const tokenString = await token("authentik", []);
|
||||
|
||||
if (tokenString) {
|
||||
headerParameters["Authorization"] = `Bearer ${tokenString}`;
|
||||
}
|
||||
}
|
||||
|
||||
let urlPath = `/endpoints/agents/psso/ise/{uuid}/used_by/`;
|
||||
urlPath = urlPath.replace(
|
||||
`{${"uuid"}}`,
|
||||
encodeURIComponent(String(requestParameters["uuid"])),
|
||||
);
|
||||
|
||||
return {
|
||||
path: urlPath,
|
||||
method: "GET",
|
||||
headers: headerParameters,
|
||||
query: queryParameters,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all objects that use this object
|
||||
*/
|
||||
async endpointsAgentsPssoIseUsedByListRaw(
|
||||
requestParameters: EndpointsAgentsPssoIseUsedByListRequest,
|
||||
initOverrides?: RequestInit | runtime.InitOverrideFunction,
|
||||
): Promise<runtime.ApiResponse<Array<UsedBy>>> {
|
||||
const requestOptions =
|
||||
await this.endpointsAgentsPssoIseUsedByListRequestOpts(requestParameters);
|
||||
const response = await this.request(requestOptions, initOverrides);
|
||||
|
||||
return new runtime.JSONApiResponse(response, (jsonValue) => jsonValue.map(UsedByFromJSON));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all objects that use this object
|
||||
*/
|
||||
async endpointsAgentsPssoIseUsedByList(
|
||||
requestParameters: EndpointsAgentsPssoIseUsedByListRequest,
|
||||
initOverrides?: RequestInit | runtime.InitOverrideFunction,
|
||||
): Promise<Array<UsedBy>> {
|
||||
const response = await this.endpointsAgentsPssoIseUsedByListRaw(
|
||||
requestParameters,
|
||||
initOverrides,
|
||||
);
|
||||
return await response.value();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates request options for endpointsAgentsPssoRegisterDeviceCreate without sending the request
|
||||
*/
|
||||
|
||||
106
packages/client-ts/src/models/AppleIndependentSecureEnclave.ts
generated
Normal file
106
packages/client-ts/src/models/AppleIndependentSecureEnclave.ts
generated
Normal file
@@ -0,0 +1,106 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* authentik
|
||||
* Making authentication simple.
|
||||
*
|
||||
* The version of the OpenAPI document: 2026.5.0-rc1
|
||||
* Contact: hello@goauthentik.io
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface AppleIndependentSecureEnclave
|
||||
*/
|
||||
export interface AppleIndependentSecureEnclave {
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof AppleIndependentSecureEnclave
|
||||
*/
|
||||
uuid?: string;
|
||||
/**
|
||||
* The user that this device belongs to.
|
||||
* @type {number}
|
||||
* @memberof AppleIndependentSecureEnclave
|
||||
*/
|
||||
user: number;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof AppleIndependentSecureEnclave
|
||||
*/
|
||||
appleSecureEnclaveKey: string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof AppleIndependentSecureEnclave
|
||||
*/
|
||||
appleEnclaveKeyId: string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof AppleIndependentSecureEnclave
|
||||
*/
|
||||
deviceType: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the AppleIndependentSecureEnclave interface.
|
||||
*/
|
||||
export function instanceOfAppleIndependentSecureEnclave(
|
||||
value: object,
|
||||
): value is AppleIndependentSecureEnclave {
|
||||
if (!("user" in value) || value["user"] === undefined) return false;
|
||||
if (!("appleSecureEnclaveKey" in value) || value["appleSecureEnclaveKey"] === undefined)
|
||||
return false;
|
||||
if (!("appleEnclaveKeyId" in value) || value["appleEnclaveKeyId"] === undefined) return false;
|
||||
if (!("deviceType" in value) || value["deviceType"] === undefined) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
export function AppleIndependentSecureEnclaveFromJSON(json: any): AppleIndependentSecureEnclave {
|
||||
return AppleIndependentSecureEnclaveFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function AppleIndependentSecureEnclaveFromJSONTyped(
|
||||
json: any,
|
||||
ignoreDiscriminator: boolean,
|
||||
): AppleIndependentSecureEnclave {
|
||||
if (json == null) {
|
||||
return json;
|
||||
}
|
||||
return {
|
||||
uuid: json["uuid"] == null ? undefined : json["uuid"],
|
||||
user: json["user"],
|
||||
appleSecureEnclaveKey: json["apple_secure_enclave_key"],
|
||||
appleEnclaveKeyId: json["apple_enclave_key_id"],
|
||||
deviceType: json["device_type"],
|
||||
};
|
||||
}
|
||||
|
||||
export function AppleIndependentSecureEnclaveToJSON(json: any): AppleIndependentSecureEnclave {
|
||||
return AppleIndependentSecureEnclaveToJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function AppleIndependentSecureEnclaveToJSONTyped(
|
||||
value?: AppleIndependentSecureEnclave | null,
|
||||
ignoreDiscriminator: boolean = false,
|
||||
): any {
|
||||
if (value == null) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return {
|
||||
uuid: value["uuid"],
|
||||
user: value["user"],
|
||||
apple_secure_enclave_key: value["appleSecureEnclaveKey"],
|
||||
apple_enclave_key_id: value["appleEnclaveKeyId"],
|
||||
device_type: value["deviceType"],
|
||||
};
|
||||
}
|
||||
110
packages/client-ts/src/models/AppleIndependentSecureEnclaveRequest.ts
generated
Normal file
110
packages/client-ts/src/models/AppleIndependentSecureEnclaveRequest.ts
generated
Normal file
@@ -0,0 +1,110 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* authentik
|
||||
* Making authentication simple.
|
||||
*
|
||||
* The version of the OpenAPI document: 2026.5.0-rc1
|
||||
* Contact: hello@goauthentik.io
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface AppleIndependentSecureEnclaveRequest
|
||||
*/
|
||||
export interface AppleIndependentSecureEnclaveRequest {
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof AppleIndependentSecureEnclaveRequest
|
||||
*/
|
||||
uuid?: string;
|
||||
/**
|
||||
* The user that this device belongs to.
|
||||
* @type {number}
|
||||
* @memberof AppleIndependentSecureEnclaveRequest
|
||||
*/
|
||||
user: number;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof AppleIndependentSecureEnclaveRequest
|
||||
*/
|
||||
appleSecureEnclaveKey: string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof AppleIndependentSecureEnclaveRequest
|
||||
*/
|
||||
appleEnclaveKeyId: string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof AppleIndependentSecureEnclaveRequest
|
||||
*/
|
||||
deviceType: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the AppleIndependentSecureEnclaveRequest interface.
|
||||
*/
|
||||
export function instanceOfAppleIndependentSecureEnclaveRequest(
|
||||
value: object,
|
||||
): value is AppleIndependentSecureEnclaveRequest {
|
||||
if (!("user" in value) || value["user"] === undefined) return false;
|
||||
if (!("appleSecureEnclaveKey" in value) || value["appleSecureEnclaveKey"] === undefined)
|
||||
return false;
|
||||
if (!("appleEnclaveKeyId" in value) || value["appleEnclaveKeyId"] === undefined) return false;
|
||||
if (!("deviceType" in value) || value["deviceType"] === undefined) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
export function AppleIndependentSecureEnclaveRequestFromJSON(
|
||||
json: any,
|
||||
): AppleIndependentSecureEnclaveRequest {
|
||||
return AppleIndependentSecureEnclaveRequestFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function AppleIndependentSecureEnclaveRequestFromJSONTyped(
|
||||
json: any,
|
||||
ignoreDiscriminator: boolean,
|
||||
): AppleIndependentSecureEnclaveRequest {
|
||||
if (json == null) {
|
||||
return json;
|
||||
}
|
||||
return {
|
||||
uuid: json["uuid"] == null ? undefined : json["uuid"],
|
||||
user: json["user"],
|
||||
appleSecureEnclaveKey: json["apple_secure_enclave_key"],
|
||||
appleEnclaveKeyId: json["apple_enclave_key_id"],
|
||||
deviceType: json["device_type"],
|
||||
};
|
||||
}
|
||||
|
||||
export function AppleIndependentSecureEnclaveRequestToJSON(
|
||||
json: any,
|
||||
): AppleIndependentSecureEnclaveRequest {
|
||||
return AppleIndependentSecureEnclaveRequestToJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function AppleIndependentSecureEnclaveRequestToJSONTyped(
|
||||
value?: AppleIndependentSecureEnclaveRequest | null,
|
||||
ignoreDiscriminator: boolean = false,
|
||||
): any {
|
||||
if (value == null) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return {
|
||||
uuid: value["uuid"],
|
||||
user: value["user"],
|
||||
apple_secure_enclave_key: value["appleSecureEnclaveKey"],
|
||||
apple_enclave_key_id: value["appleEnclaveKeyId"],
|
||||
device_type: value["deviceType"],
|
||||
};
|
||||
}
|
||||
@@ -23,6 +23,7 @@ export const AuthenticationEnum = {
|
||||
RequireSuperuser: "require_superuser",
|
||||
RequireRedirect: "require_redirect",
|
||||
RequireOutpost: "require_outpost",
|
||||
RequireToken: "require_token",
|
||||
UnknownDefaultOpenApi: "11184809",
|
||||
} as const;
|
||||
export type AuthenticationEnum = (typeof AuthenticationEnum)[keyof typeof AuthenticationEnum];
|
||||
|
||||
100
packages/client-ts/src/models/PaginatedAppleIndependentSecureEnclaveList.ts
generated
Normal file
100
packages/client-ts/src/models/PaginatedAppleIndependentSecureEnclaveList.ts
generated
Normal file
@@ -0,0 +1,100 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* authentik
|
||||
* Making authentication simple.
|
||||
*
|
||||
* The version of the OpenAPI document: 2026.5.0-rc1
|
||||
* Contact: hello@goauthentik.io
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
import type { AppleIndependentSecureEnclave } from "./AppleIndependentSecureEnclave";
|
||||
import {
|
||||
AppleIndependentSecureEnclaveFromJSON,
|
||||
AppleIndependentSecureEnclaveToJSON,
|
||||
} from "./AppleIndependentSecureEnclave";
|
||||
import type { Pagination } from "./Pagination";
|
||||
import { PaginationFromJSON, PaginationToJSON } from "./Pagination";
|
||||
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface PaginatedAppleIndependentSecureEnclaveList
|
||||
*/
|
||||
export interface PaginatedAppleIndependentSecureEnclaveList {
|
||||
/**
|
||||
*
|
||||
* @type {Pagination}
|
||||
* @memberof PaginatedAppleIndependentSecureEnclaveList
|
||||
*/
|
||||
pagination: Pagination;
|
||||
/**
|
||||
*
|
||||
* @type {Array<AppleIndependentSecureEnclave>}
|
||||
* @memberof PaginatedAppleIndependentSecureEnclaveList
|
||||
*/
|
||||
results: Array<AppleIndependentSecureEnclave>;
|
||||
/**
|
||||
*
|
||||
* @type {{ [key: string]: any; }}
|
||||
* @memberof PaginatedAppleIndependentSecureEnclaveList
|
||||
*/
|
||||
autocomplete: { [key: string]: any };
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the PaginatedAppleIndependentSecureEnclaveList interface.
|
||||
*/
|
||||
export function instanceOfPaginatedAppleIndependentSecureEnclaveList(
|
||||
value: object,
|
||||
): value is PaginatedAppleIndependentSecureEnclaveList {
|
||||
if (!("pagination" in value) || value["pagination"] === undefined) return false;
|
||||
if (!("results" in value) || value["results"] === undefined) return false;
|
||||
if (!("autocomplete" in value) || value["autocomplete"] === undefined) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
export function PaginatedAppleIndependentSecureEnclaveListFromJSON(
|
||||
json: any,
|
||||
): PaginatedAppleIndependentSecureEnclaveList {
|
||||
return PaginatedAppleIndependentSecureEnclaveListFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function PaginatedAppleIndependentSecureEnclaveListFromJSONTyped(
|
||||
json: any,
|
||||
ignoreDiscriminator: boolean,
|
||||
): PaginatedAppleIndependentSecureEnclaveList {
|
||||
if (json == null) {
|
||||
return json;
|
||||
}
|
||||
return {
|
||||
pagination: PaginationFromJSON(json["pagination"]),
|
||||
results: (json["results"] as Array<any>).map(AppleIndependentSecureEnclaveFromJSON),
|
||||
autocomplete: json["autocomplete"],
|
||||
};
|
||||
}
|
||||
|
||||
export function PaginatedAppleIndependentSecureEnclaveListToJSON(
|
||||
json: any,
|
||||
): PaginatedAppleIndependentSecureEnclaveList {
|
||||
return PaginatedAppleIndependentSecureEnclaveListToJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function PaginatedAppleIndependentSecureEnclaveListToJSONTyped(
|
||||
value?: PaginatedAppleIndependentSecureEnclaveList | null,
|
||||
ignoreDiscriminator: boolean = false,
|
||||
): any {
|
||||
if (value == null) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return {
|
||||
pagination: PaginationToJSON(value["pagination"]),
|
||||
results: (value["results"] as Array<any>).map(AppleIndependentSecureEnclaveToJSON),
|
||||
autocomplete: value["autocomplete"],
|
||||
};
|
||||
}
|
||||
107
packages/client-ts/src/models/PatchedAppleIndependentSecureEnclaveRequest.ts
generated
Normal file
107
packages/client-ts/src/models/PatchedAppleIndependentSecureEnclaveRequest.ts
generated
Normal file
@@ -0,0 +1,107 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* authentik
|
||||
* Making authentication simple.
|
||||
*
|
||||
* The version of the OpenAPI document: 2026.5.0-rc1
|
||||
* Contact: hello@goauthentik.io
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
* @export
|
||||
* @interface PatchedAppleIndependentSecureEnclaveRequest
|
||||
*/
|
||||
export interface PatchedAppleIndependentSecureEnclaveRequest {
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof PatchedAppleIndependentSecureEnclaveRequest
|
||||
*/
|
||||
uuid?: string;
|
||||
/**
|
||||
* The user that this device belongs to.
|
||||
* @type {number}
|
||||
* @memberof PatchedAppleIndependentSecureEnclaveRequest
|
||||
*/
|
||||
user?: number;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof PatchedAppleIndependentSecureEnclaveRequest
|
||||
*/
|
||||
appleSecureEnclaveKey?: string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof PatchedAppleIndependentSecureEnclaveRequest
|
||||
*/
|
||||
appleEnclaveKeyId?: string;
|
||||
/**
|
||||
*
|
||||
* @type {string}
|
||||
* @memberof PatchedAppleIndependentSecureEnclaveRequest
|
||||
*/
|
||||
deviceType?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given object implements the PatchedAppleIndependentSecureEnclaveRequest interface.
|
||||
*/
|
||||
export function instanceOfPatchedAppleIndependentSecureEnclaveRequest(
|
||||
value: object,
|
||||
): value is PatchedAppleIndependentSecureEnclaveRequest {
|
||||
return true;
|
||||
}
|
||||
|
||||
export function PatchedAppleIndependentSecureEnclaveRequestFromJSON(
|
||||
json: any,
|
||||
): PatchedAppleIndependentSecureEnclaveRequest {
|
||||
return PatchedAppleIndependentSecureEnclaveRequestFromJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function PatchedAppleIndependentSecureEnclaveRequestFromJSONTyped(
|
||||
json: any,
|
||||
ignoreDiscriminator: boolean,
|
||||
): PatchedAppleIndependentSecureEnclaveRequest {
|
||||
if (json == null) {
|
||||
return json;
|
||||
}
|
||||
return {
|
||||
uuid: json["uuid"] == null ? undefined : json["uuid"],
|
||||
user: json["user"] == null ? undefined : json["user"],
|
||||
appleSecureEnclaveKey:
|
||||
json["apple_secure_enclave_key"] == null ? undefined : json["apple_secure_enclave_key"],
|
||||
appleEnclaveKeyId:
|
||||
json["apple_enclave_key_id"] == null ? undefined : json["apple_enclave_key_id"],
|
||||
deviceType: json["device_type"] == null ? undefined : json["device_type"],
|
||||
};
|
||||
}
|
||||
|
||||
export function PatchedAppleIndependentSecureEnclaveRequestToJSON(
|
||||
json: any,
|
||||
): PatchedAppleIndependentSecureEnclaveRequest {
|
||||
return PatchedAppleIndependentSecureEnclaveRequestToJSONTyped(json, false);
|
||||
}
|
||||
|
||||
export function PatchedAppleIndependentSecureEnclaveRequestToJSONTyped(
|
||||
value?: PatchedAppleIndependentSecureEnclaveRequest | null,
|
||||
ignoreDiscriminator: boolean = false,
|
||||
): any {
|
||||
if (value == null) {
|
||||
return value;
|
||||
}
|
||||
|
||||
return {
|
||||
uuid: value["uuid"],
|
||||
user: value["user"],
|
||||
apple_secure_enclave_key: value["appleSecureEnclaveKey"],
|
||||
apple_enclave_key_id: value["appleEnclaveKeyId"],
|
||||
device_type: value["deviceType"],
|
||||
};
|
||||
}
|
||||
4
packages/client-ts/src/models/index.ts
generated
4
packages/client-ts/src/models/index.ts
generated
@@ -13,6 +13,8 @@ export * from "./AlgEnum";
|
||||
export * from "./App";
|
||||
export * from "./AppEnum";
|
||||
export * from "./AppleChallengeResponseRequest";
|
||||
export * from "./AppleIndependentSecureEnclave";
|
||||
export * from "./AppleIndependentSecureEnclaveRequest";
|
||||
export * from "./AppleLoginChallenge";
|
||||
export * from "./Application";
|
||||
export * from "./ApplicationEntitlement";
|
||||
@@ -350,6 +352,7 @@ export * from "./OutpostRequest";
|
||||
export * from "./OutpostTypeEnum";
|
||||
export * from "./PKCEMethodEnum";
|
||||
export * from "./PaginatedAgentConnectorList";
|
||||
export * from "./PaginatedAppleIndependentSecureEnclaveList";
|
||||
export * from "./PaginatedApplicationEntitlementList";
|
||||
export * from "./PaginatedApplicationList";
|
||||
export * from "./PaginatedAuthenticatedSessionList";
|
||||
@@ -515,6 +518,7 @@ export * from "./PasswordPolicyRequest";
|
||||
export * from "./PasswordStage";
|
||||
export * from "./PasswordStageRequest";
|
||||
export * from "./PatchedAgentConnectorRequest";
|
||||
export * from "./PatchedAppleIndependentSecureEnclaveRequest";
|
||||
export * from "./PatchedApplicationEntitlementRequest";
|
||||
export * from "./PatchedApplicationRequest";
|
||||
export * from "./PatchedAuthenticatorDuoStageRequest";
|
||||
|
||||
@@ -7,7 +7,7 @@ requires-python = "==3.14.*"
|
||||
dependencies = [
|
||||
"ak-guardian==3.2.0",
|
||||
"argon2-cffi==25.1.0",
|
||||
"cachetools==7.0.5",
|
||||
"cachetools==7.0.6",
|
||||
"channels==4.3.2",
|
||||
"cryptography==46.0.7",
|
||||
"dacite==1.9.2",
|
||||
@@ -33,7 +33,7 @@ dependencies = [
|
||||
"drf-spectacular==0.29.0",
|
||||
"dumb-init==1.2.5.post1",
|
||||
"duo-client==5.6.1",
|
||||
"fido2==2.1.1",
|
||||
"fido2==2.2.0",
|
||||
"geoip2==5.2.0",
|
||||
"geopy==2.4.1",
|
||||
"google-api-python-client==2.194.0",
|
||||
@@ -43,26 +43,26 @@ dependencies = [
|
||||
"jwcrypto==1.5.7",
|
||||
"kubernetes==35.0.0",
|
||||
"ldap3==2.9.1",
|
||||
"lxml==6.0.4",
|
||||
"lxml==6.1.0",
|
||||
"msgraph-sdk==1.55.0",
|
||||
"opencontainers==0.0.15",
|
||||
"packaging==26.0",
|
||||
"packaging==26.1",
|
||||
"paramiko==4.0.0",
|
||||
"psycopg[c,pool]==3.3.3",
|
||||
"pydantic-scim==0.0.8",
|
||||
"pydantic==2.12.5",
|
||||
"pydantic==2.13.3",
|
||||
"pyjwt==2.11.0",
|
||||
"pyrad==2.5.4",
|
||||
"python-kadmin-rs==0.7.0",
|
||||
"pyyaml==6.0.3",
|
||||
"requests-oauthlib==2.0.0",
|
||||
"scim2-filter-parser==0.7.0",
|
||||
"sentry-sdk==2.57.0",
|
||||
"sentry-sdk==2.58.0",
|
||||
"service-identity==24.2.0",
|
||||
"setproctitle==1.3.7",
|
||||
"structlog==25.5.0",
|
||||
"swagger-spec-validator==3.0.4",
|
||||
"twilio==9.10.4",
|
||||
"twilio==9.10.5",
|
||||
"ua-parser==1.0.2",
|
||||
"unidecode==1.4.0",
|
||||
"urllib3<3",
|
||||
@@ -76,7 +76,7 @@ dependencies = [
|
||||
|
||||
[dependency-groups]
|
||||
dev = [
|
||||
"aws-cdk-lib==2.248.0",
|
||||
"aws-cdk-lib==2.250.0",
|
||||
"bandit==1.9.4",
|
||||
"black==26.3.1",
|
||||
"bpython==0.26",
|
||||
@@ -85,7 +85,7 @@ dev = [
|
||||
"coverage[toml]==7.13.5",
|
||||
"daphne==4.2.1",
|
||||
"debugpy==1.8.20",
|
||||
"django-stubs[compatible-mypy]==6.0.2",
|
||||
"django-stubs[compatible-mypy]==6.0.3",
|
||||
"djangorestframework-stubs[compatible-mypy]==3.16.9",
|
||||
"drf-jsonschema-serializer==3.0.0",
|
||||
"freezegun==1.5.5",
|
||||
@@ -101,8 +101,8 @@ dev = [
|
||||
"pytest-timeout==2.4.0",
|
||||
"pytest==9.0.3",
|
||||
"requests-mock==1.12.1",
|
||||
"ruff==0.15.10",
|
||||
"selenium==4.41.0",
|
||||
"ruff==0.15.11",
|
||||
"selenium==4.43.0",
|
||||
"types-channels==4.3.0.20260408",
|
||||
"types-docker==7.1.0.20260409",
|
||||
"types-jwcrypto==1.5.7.20260409",
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
[toolchain]
|
||||
channel = "1.94.1"
|
||||
channel = "1.95.0"
|
||||
components = ["clippy", "rust-analyzer", "llvm-tools-preview"]
|
||||
|
||||
280
schema.yml
280
schema.yml
@@ -5649,6 +5649,209 @@ paths:
|
||||
$ref: '#/components/responses/ValidationErrorResponse'
|
||||
'403':
|
||||
$ref: '#/components/responses/GenericErrorResponse'
|
||||
/endpoints/agents/psso/ise/:
|
||||
get:
|
||||
operationId: endpoints_agents_psso_ise_list
|
||||
description: Mixin to add a used_by endpoint to return a list of all objects
|
||||
using this object
|
||||
parameters:
|
||||
- in: query
|
||||
name: apple_enclave_key_id
|
||||
schema:
|
||||
type: string
|
||||
- $ref: '#/components/parameters/QueryPaginationOrdering'
|
||||
- $ref: '#/components/parameters/QueryPaginationPage'
|
||||
- $ref: '#/components/parameters/QueryPaginationPageSize'
|
||||
- $ref: '#/components/parameters/QuerySearch'
|
||||
- in: query
|
||||
name: user
|
||||
schema:
|
||||
type: integer
|
||||
tags:
|
||||
- endpoints
|
||||
security:
|
||||
- authentik: []
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/PaginatedAppleIndependentSecureEnclaveList'
|
||||
description: ''
|
||||
'400':
|
||||
$ref: '#/components/responses/ValidationErrorResponse'
|
||||
'403':
|
||||
$ref: '#/components/responses/GenericErrorResponse'
|
||||
post:
|
||||
operationId: endpoints_agents_psso_ise_create
|
||||
description: Mixin to add a used_by endpoint to return a list of all objects
|
||||
using this object
|
||||
tags:
|
||||
- endpoints
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/AppleIndependentSecureEnclaveRequest'
|
||||
required: true
|
||||
security:
|
||||
- authentik: []
|
||||
responses:
|
||||
'201':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/AppleIndependentSecureEnclave'
|
||||
description: ''
|
||||
'400':
|
||||
$ref: '#/components/responses/ValidationErrorResponse'
|
||||
'403':
|
||||
$ref: '#/components/responses/GenericErrorResponse'
|
||||
/endpoints/agents/psso/ise/{uuid}/:
|
||||
get:
|
||||
operationId: endpoints_agents_psso_ise_retrieve
|
||||
description: Mixin to add a used_by endpoint to return a list of all objects
|
||||
using this object
|
||||
parameters:
|
||||
- in: path
|
||||
name: uuid
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
description: A UUID string identifying this Apple Independent Secure Enclave.
|
||||
required: true
|
||||
tags:
|
||||
- endpoints
|
||||
security:
|
||||
- authentik: []
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/AppleIndependentSecureEnclave'
|
||||
description: ''
|
||||
'400':
|
||||
$ref: '#/components/responses/ValidationErrorResponse'
|
||||
'403':
|
||||
$ref: '#/components/responses/GenericErrorResponse'
|
||||
put:
|
||||
operationId: endpoints_agents_psso_ise_update
|
||||
description: Mixin to add a used_by endpoint to return a list of all objects
|
||||
using this object
|
||||
parameters:
|
||||
- in: path
|
||||
name: uuid
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
description: A UUID string identifying this Apple Independent Secure Enclave.
|
||||
required: true
|
||||
tags:
|
||||
- endpoints
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/AppleIndependentSecureEnclaveRequest'
|
||||
required: true
|
||||
security:
|
||||
- authentik: []
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/AppleIndependentSecureEnclave'
|
||||
description: ''
|
||||
'400':
|
||||
$ref: '#/components/responses/ValidationErrorResponse'
|
||||
'403':
|
||||
$ref: '#/components/responses/GenericErrorResponse'
|
||||
patch:
|
||||
operationId: endpoints_agents_psso_ise_partial_update
|
||||
description: Mixin to add a used_by endpoint to return a list of all objects
|
||||
using this object
|
||||
parameters:
|
||||
- in: path
|
||||
name: uuid
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
description: A UUID string identifying this Apple Independent Secure Enclave.
|
||||
required: true
|
||||
tags:
|
||||
- endpoints
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/PatchedAppleIndependentSecureEnclaveRequest'
|
||||
security:
|
||||
- authentik: []
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/AppleIndependentSecureEnclave'
|
||||
description: ''
|
||||
'400':
|
||||
$ref: '#/components/responses/ValidationErrorResponse'
|
||||
'403':
|
||||
$ref: '#/components/responses/GenericErrorResponse'
|
||||
delete:
|
||||
operationId: endpoints_agents_psso_ise_destroy
|
||||
description: Mixin to add a used_by endpoint to return a list of all objects
|
||||
using this object
|
||||
parameters:
|
||||
- in: path
|
||||
name: uuid
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
description: A UUID string identifying this Apple Independent Secure Enclave.
|
||||
required: true
|
||||
tags:
|
||||
- endpoints
|
||||
security:
|
||||
- authentik: []
|
||||
responses:
|
||||
'204':
|
||||
description: No response body
|
||||
'400':
|
||||
$ref: '#/components/responses/ValidationErrorResponse'
|
||||
'403':
|
||||
$ref: '#/components/responses/GenericErrorResponse'
|
||||
/endpoints/agents/psso/ise/{uuid}/used_by/:
|
||||
get:
|
||||
operationId: endpoints_agents_psso_ise_used_by_list
|
||||
description: Get a list of all objects that use this object
|
||||
parameters:
|
||||
- in: path
|
||||
name: uuid
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
description: A UUID string identifying this Apple Independent Secure Enclave.
|
||||
required: true
|
||||
tags:
|
||||
- endpoints
|
||||
security:
|
||||
- authentik: []
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/UsedBy'
|
||||
description: ''
|
||||
'400':
|
||||
$ref: '#/components/responses/ValidationErrorResponse'
|
||||
'403':
|
||||
$ref: '#/components/responses/GenericErrorResponse'
|
||||
/endpoints/agents/psso/register/device/:
|
||||
post:
|
||||
operationId: endpoints_agents_psso_register_device_create
|
||||
@@ -33772,6 +33975,49 @@ components:
|
||||
type: string
|
||||
minLength: 1
|
||||
default: ak-source-oauth-apple
|
||||
AppleIndependentSecureEnclave:
|
||||
type: object
|
||||
properties:
|
||||
uuid:
|
||||
type: string
|
||||
format: uuid
|
||||
user:
|
||||
type: integer
|
||||
description: The user that this device belongs to.
|
||||
apple_secure_enclave_key:
|
||||
type: string
|
||||
apple_enclave_key_id:
|
||||
type: string
|
||||
device_type:
|
||||
type: string
|
||||
required:
|
||||
- apple_enclave_key_id
|
||||
- apple_secure_enclave_key
|
||||
- device_type
|
||||
- user
|
||||
AppleIndependentSecureEnclaveRequest:
|
||||
type: object
|
||||
properties:
|
||||
uuid:
|
||||
type: string
|
||||
format: uuid
|
||||
user:
|
||||
type: integer
|
||||
description: The user that this device belongs to.
|
||||
apple_secure_enclave_key:
|
||||
type: string
|
||||
minLength: 1
|
||||
apple_enclave_key_id:
|
||||
type: string
|
||||
minLength: 1
|
||||
device_type:
|
||||
type: string
|
||||
minLength: 1
|
||||
required:
|
||||
- apple_enclave_key_id
|
||||
- apple_secure_enclave_key
|
||||
- device_type
|
||||
- user
|
||||
AppleLoginChallenge:
|
||||
type: object
|
||||
description: Special challenge for apple-native authentication flow, which happens
|
||||
@@ -34109,6 +34355,7 @@ components:
|
||||
- require_superuser
|
||||
- require_redirect
|
||||
- require_outpost
|
||||
- require_token
|
||||
type: string
|
||||
AuthenticatorAttachmentEnum:
|
||||
enum:
|
||||
@@ -44295,6 +44542,21 @@ components:
|
||||
- autocomplete
|
||||
- pagination
|
||||
- results
|
||||
PaginatedAppleIndependentSecureEnclaveList:
|
||||
type: object
|
||||
properties:
|
||||
pagination:
|
||||
$ref: '#/components/schemas/Pagination'
|
||||
results:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/AppleIndependentSecureEnclave'
|
||||
autocomplete:
|
||||
$ref: '#/components/schemas/Autocomplete'
|
||||
required:
|
||||
- autocomplete
|
||||
- pagination
|
||||
- results
|
||||
PaginatedApplicationEntitlementList:
|
||||
type: object
|
||||
properties:
|
||||
@@ -47080,6 +47342,24 @@ components:
|
||||
type: array
|
||||
items:
|
||||
type: integer
|
||||
PatchedAppleIndependentSecureEnclaveRequest:
|
||||
type: object
|
||||
properties:
|
||||
uuid:
|
||||
type: string
|
||||
format: uuid
|
||||
user:
|
||||
type: integer
|
||||
description: The user that this device belongs to.
|
||||
apple_secure_enclave_key:
|
||||
type: string
|
||||
minLength: 1
|
||||
apple_enclave_key_id:
|
||||
type: string
|
||||
minLength: 1
|
||||
device_type:
|
||||
type: string
|
||||
minLength: 1
|
||||
PatchedApplicationEntitlementRequest:
|
||||
type: object
|
||||
description: ApplicationEntitlement Serializer
|
||||
|
||||
@@ -6,6 +6,7 @@ from django.contrib.staticfiles.testing import StaticLiveServerTestCase
|
||||
from dramatiq import get_broker
|
||||
from structlog.stdlib import get_logger
|
||||
|
||||
from authentik.core.apps import Setup
|
||||
from authentik.core.models import User
|
||||
from authentik.core.tests.utils import create_test_admin_user
|
||||
from authentik.tasks.test import use_test_broker
|
||||
@@ -27,6 +28,7 @@ class E2ETestMixin(DockerTestCase):
|
||||
self.wait_timeout = 60
|
||||
self.logger = get_logger()
|
||||
self.user = create_test_admin_user()
|
||||
Setup.set(True)
|
||||
super().setUp()
|
||||
|
||||
@classmethod
|
||||
|
||||
258
uv.lock
generated
258
uv.lock
generated
@@ -316,7 +316,7 @@ dev = [
|
||||
requires-dist = [
|
||||
{ name = "ak-guardian", editable = "packages/ak-guardian" },
|
||||
{ name = "argon2-cffi", specifier = "==25.1.0" },
|
||||
{ name = "cachetools", specifier = "==7.0.5" },
|
||||
{ name = "cachetools", specifier = "==7.0.6" },
|
||||
{ name = "channels", specifier = "==4.3.2" },
|
||||
{ name = "cryptography", specifier = "==46.0.7" },
|
||||
{ name = "dacite", specifier = "==1.9.2" },
|
||||
@@ -342,7 +342,7 @@ requires-dist = [
|
||||
{ name = "drf-spectacular", specifier = "==0.29.0" },
|
||||
{ name = "dumb-init", specifier = "==1.2.5.post1" },
|
||||
{ name = "duo-client", specifier = "==5.6.1" },
|
||||
{ name = "fido2", specifier = "==2.1.1" },
|
||||
{ name = "fido2", specifier = "==2.2.0" },
|
||||
{ name = "geoip2", specifier = "==5.2.0" },
|
||||
{ name = "geopy", specifier = "==2.4.1" },
|
||||
{ name = "google-api-python-client", specifier = "==2.194.0" },
|
||||
@@ -352,13 +352,13 @@ requires-dist = [
|
||||
{ name = "jwcrypto", specifier = "==1.5.7" },
|
||||
{ name = "kubernetes", specifier = "==35.0.0" },
|
||||
{ name = "ldap3", specifier = "==2.9.1" },
|
||||
{ name = "lxml", specifier = "==6.0.4" },
|
||||
{ name = "lxml", specifier = "==6.1.0" },
|
||||
{ name = "msgraph-sdk", specifier = "==1.55.0" },
|
||||
{ name = "opencontainers", git = "https://github.com/vsoch/oci-python?rev=ceb4fcc090851717a3069d78e85ceb1e86c2740c" },
|
||||
{ name = "packaging", specifier = "==26.0" },
|
||||
{ name = "packaging", specifier = "==26.1" },
|
||||
{ name = "paramiko", specifier = "==4.0.0" },
|
||||
{ name = "psycopg", extras = ["c", "pool"], specifier = "==3.3.3" },
|
||||
{ name = "pydantic", specifier = "==2.12.5" },
|
||||
{ name = "pydantic", specifier = "==2.13.3" },
|
||||
{ name = "pydantic-scim", specifier = "==0.0.8" },
|
||||
{ name = "pyjwt", specifier = "==2.11.0" },
|
||||
{ name = "pyrad", specifier = "==2.5.4" },
|
||||
@@ -366,12 +366,12 @@ 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.57.0" },
|
||||
{ name = "sentry-sdk", specifier = "==2.58.0" },
|
||||
{ name = "service-identity", specifier = "==24.2.0" },
|
||||
{ name = "setproctitle", specifier = "==1.3.7" },
|
||||
{ name = "structlog", specifier = "==25.5.0" },
|
||||
{ name = "swagger-spec-validator", specifier = "==3.0.4" },
|
||||
{ name = "twilio", specifier = "==9.10.4" },
|
||||
{ name = "twilio", specifier = "==9.10.5" },
|
||||
{ name = "ua-parser", specifier = "==1.0.2" },
|
||||
{ name = "unidecode", specifier = "==1.4.0" },
|
||||
{ name = "urllib3", specifier = "<3" },
|
||||
@@ -385,7 +385,7 @@ requires-dist = [
|
||||
|
||||
[package.metadata.requires-dev]
|
||||
dev = [
|
||||
{ name = "aws-cdk-lib", specifier = "==2.248.0" },
|
||||
{ name = "aws-cdk-lib", specifier = "==2.250.0" },
|
||||
{ name = "bandit", specifier = "==1.9.4" },
|
||||
{ name = "black", specifier = "==26.3.1" },
|
||||
{ name = "bpython", specifier = "==0.26" },
|
||||
@@ -394,7 +394,7 @@ dev = [
|
||||
{ name = "coverage", extras = ["toml"], specifier = "==7.13.5" },
|
||||
{ name = "daphne", specifier = "==4.2.1" },
|
||||
{ name = "debugpy", specifier = "==1.8.20" },
|
||||
{ name = "django-stubs", extras = ["compatible-mypy"], specifier = "==6.0.2" },
|
||||
{ name = "django-stubs", extras = ["compatible-mypy"], specifier = "==6.0.3" },
|
||||
{ name = "djangorestframework-stubs", extras = ["compatible-mypy"], specifier = "==3.16.9" },
|
||||
{ name = "drf-jsonschema-serializer", specifier = "==3.0.0" },
|
||||
{ name = "freezegun", specifier = "==1.5.5" },
|
||||
@@ -410,8 +410,8 @@ dev = [
|
||||
{ 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.10" },
|
||||
{ name = "selenium", specifier = "==4.41.0" },
|
||||
{ name = "ruff", specifier = "==0.15.11" },
|
||||
{ name = "selenium", specifier = "==4.43.0" },
|
||||
{ name = "types-channels", specifier = "==4.3.0.20260408" },
|
||||
{ name = "types-docker", specifier = "==7.1.0.20260409" },
|
||||
{ name = "types-jwcrypto", specifier = "==1.5.7.20260409" },
|
||||
@@ -495,7 +495,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "aws-cdk-lib"
|
||||
version = "2.248.0"
|
||||
version = "2.250.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "aws-cdk-asset-awscli-v1" },
|
||||
@@ -506,9 +506,9 @@ dependencies = [
|
||||
{ name = "publication" },
|
||||
{ name = "typeguard" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/70/42/a8250f31763adb21acb90088b99f7f37c3b8d09c3fd94dc631c0e69d9463/aws_cdk_lib-2.248.0.tar.gz", hash = "sha256:a00c73bfa6865ef62d700d6f97dd4124979ccfe69dc1ef70f2526aa49c52bbc8", size = 48734274, upload-time = "2026-04-03T07:35:05.438Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d5/7b/98c66b6ea6d4f84b70d86ec391bbcd2856a82b384a97adc223f36b36dfd6/aws_cdk_lib-2.250.0.tar.gz", hash = "sha256:6e5cb8def9208a45cede1376a81d7508b3889879ccc7e9cddaa4fd807da0b144", size = 49146123, upload-time = "2026-04-14T21:43:07.309Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b3/0b/41b0979581668c709b01a7d26f9c2716031f2b0c53ad5a01341160c631b0/aws_cdk_lib-2.248.0-py3-none-any.whl", hash = "sha256:e89db288365371e6b42aaae8b45ad2064615dfbe87e95741a2f2bb7ec1f33dad", size = 49395398, upload-time = "2026-04-03T07:34:25.671Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e9/e7/b64389b59215a42d0d7538a1d9a8006edb2eefb297ccbdcd4c55ff2cffba/aws_cdk_lib-2.250.0-py3-none-any.whl", hash = "sha256:427c9a062f350c16e301326fd6ca0440428f9cc0e85421aaa69a9afa57228acc", size = 49827287, upload-time = "2026-04-14T21:42:21.21Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -688,11 +688,11 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "cachetools"
|
||||
version = "7.0.5"
|
||||
version = "7.0.6"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/af/dd/57fe3fdb6e65b25a5987fd2cdc7e22db0aef508b91634d2e57d22928d41b/cachetools-7.0.5.tar.gz", hash = "sha256:0cd042c24377200c1dcd225f8b7b12b0ca53cc2c961b43757e774ebe190fd990", size = 37367, upload-time = "2026-03-09T20:51:29.451Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/76/7b/1755ed2c6bfabd1d98b37ae73152f8dcf94aa40fee119d163c19ed484704/cachetools-7.0.6.tar.gz", hash = "sha256:e5d524d36d65703a87243a26ff08ad84f73352adbeafb1cde81e207b456aaf24", size = 37526, upload-time = "2026-04-20T19:02:23.289Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/06/f3/39cf3367b8107baa44f861dc802cbf16263c945b62d8265d36034fc07bea/cachetools-7.0.5-py3-none-any.whl", hash = "sha256:46bc8ebefbe485407621d0a4264b23c080cedd913921bad7ac3ed2f26c183114", size = 13918, upload-time = "2026-03-09T20:51:27.33Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fe/c4/cf76242a5da1410917107ff14551764aa405a5fd10cd10cf9a5ca8fa77f4/cachetools-7.0.6-py3-none-any.whl", hash = "sha256:4e94956cfdd3086f12042cdd29318f5ced3893014f7d0d059bf3ead3f85b7f8b", size = 13976, upload-time = "2026-04-20T19:02:21.187Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1253,7 +1253,7 @@ s3 = [
|
||||
|
||||
[[package]]
|
||||
name = "django-stubs"
|
||||
version = "6.0.2"
|
||||
version = "6.0.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "django" },
|
||||
@@ -1261,9 +1261,9 @@ dependencies = [
|
||||
{ name = "types-pyyaml" },
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/03/b2/f0214d86180f937c8e3358ff831b20f0634d95bd77436b18861c647e15bc/django_stubs-6.0.2.tar.gz", hash = "sha256:56d43b5e3741563af0063e5b6283f908c625b0439aa06314268673699d1bdccd", size = 274742, upload-time = "2026-04-01T08:27:35.092Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/86/0c/8d0d875af79bf774c1c3997c84aa118dba3a77be12086b9c14e130e8ec72/django_stubs-6.0.3.tar.gz", hash = "sha256:ee895f403c373608eeb50822f0733f9d9ec5ab12731d4ab58956053bb95fdd9e", size = 278214, upload-time = "2026-04-18T15:11:22.327Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/49/e7/8f2aaa22eac7fa18db3aca0e7b651ccf5ac79a2021bf67e75a16934a7076/django_stubs-6.0.2-py3-none-any.whl", hash = "sha256:c3bc84d80421758f3b2ad9e1358e001d719388a8eb106e67c873e606216108d4", size = 538234, upload-time = "2026-04-01T08:27:33.411Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/80/a3/6751b7684d20fc4f228bdd3dd8341d382ab3faaf65d3d050c0d59ab0a1b0/django_stubs-6.0.3-py3-none-any.whl", hash = "sha256:5fee22bcbbad59a78c727a820b6f4e68ff442ca76a922b7002e57c25dd7cb390", size = 541570, upload-time = "2026-04-18T15:11:20.711Z" },
|
||||
]
|
||||
|
||||
[package.optional-dependencies]
|
||||
@@ -1474,14 +1474,14 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "fido2"
|
||||
version = "2.1.1"
|
||||
version = "2.2.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "cryptography" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/e7/3c/c65377e48c144afca6b02c69f10c0fe936db556096a4e2c9798e2aa72db6/fido2-2.1.1.tar.gz", hash = "sha256:f1379f845870cc7fc64c7f07323c3ce41e8c96c37054e79e0acd5630b3fec5ac", size = 4455940, upload-time = "2026-01-19T11:08:34.683Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/09/34/4837e2f5640baf61d8abd6125ccb6cc60b4b2933088528356ad6e781496f/fido2-2.2.0.tar.gz", hash = "sha256:0d8122e690096ad82afde42ac9d6433a4eeffda64084f36341ea02546b181dd1", size = 294167, upload-time = "2026-04-15T06:42:50.264Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/e2/ab/d0fa89cc4b982800dd88daa799612f11642bf9393851715d9eaeba3cfcac/fido2-2.1.1-py3-none-any.whl", hash = "sha256:f85c16c8084abf6530b6c6ec3a0cf8575943321842e06916686943a8b784182c", size = 226945, upload-time = "2026-01-19T11:08:29.675Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/01/82/f3c5dd87b0977f5547cc132b7969e6f5075a8c2f5881cf4b6df6378505f9/fido2-2.2.0-py3-none-any.whl", hash = "sha256:3587ccf0af7b71b5dd73f17e1dbec9f0fd157292f9163f02e7778f46d0d25fe5", size = 234025, upload-time = "2026-04-15T06:42:51.813Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2088,46 +2088,46 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "lxml"
|
||||
version = "6.0.4"
|
||||
version = "6.1.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ce/08/1217ca4043f55c3c92993b283a7dbfa456a2058d8b57bbb416cc96b6efff/lxml-6.0.4.tar.gz", hash = "sha256:4137516be2a90775f99d8ef80ec0283f8d78b5d8bd4630ff20163b72e7e9abf2", size = 4237780, upload-time = "2026-04-12T16:28:24.182Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/28/30/9abc9e34c657c33834eaf6cd02124c61bdf5944d802aa48e69be8da3585d/lxml-6.1.0.tar.gz", hash = "sha256:bfd57d8008c4965709a919c3e9a98f76c2c7cb319086b3d26858250620023b13", size = 4197006, upload-time = "2026-04-18T04:32:51.613Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/10/18/36e28a809c509a67496202771f545219ac5a2f1cd61aae325991fcf5ab91/lxml-6.0.4-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:569d3b18340863f603582d2124e742a68e85755eff5e47c26a55e298521e3a01", size = 8575045, upload-time = "2026-04-12T16:25:33.57Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/11/38/a168c820e3b08d3b4fa0f4e6b53b3930086b36cc11e428106d38c36778cd/lxml-6.0.4-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:3b6245ee5241342d45e1a54a4a8bc52ef322333ada74f24aa335c4ab36f20161", size = 4622963, upload-time = "2026-04-12T16:25:36.818Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/53/e0/2c9d6abdd82358cea3c0d8d6ca272a6af0f38156abce7827efb6d5b62d17/lxml-6.0.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:79a1173ba3213a3693889a435417d4e9f3c07d96e30dc7cc3a712ed7361015fe", size = 4948832, upload-time = "2026-04-12T16:25:39.104Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/96/d7/f2202852e91d7baf3a317f4523a9c14834145301e5b0f2e80c01c4bfbd49/lxml-6.0.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:dc18bb975666b443ba23aedd2fcf57e9d0d97546b52a1de97a447c4061ba4110", size = 5085865, upload-time = "2026-04-12T16:25:41.226Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/09/57/abee549324496e92708f71391c6060a164d3c95369656a1a15e9f20d8162/lxml-6.0.4-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2079f5dc83291ac190a52f8354b78648f221ecac19fb2972a2d056b555824de7", size = 5030001, upload-time = "2026-04-12T16:25:43.695Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c2/f8/432da7178c5917a16468af6c5da68fef7cf3357d4bd0e6f50272ec9a59b5/lxml-6.0.4-cp314-cp314-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3eda02da4ca16e9ca22bbe5654470c17fa1abcd967a52e4c2e50ff278221e351", size = 5646303, upload-time = "2026-04-12T16:25:46.577Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/82/f9/e1c04ef667a6bf9c9dbd3bf04c50fa51d7ee25b258485bb748b27eb9a1c7/lxml-6.0.4-cp314-cp314-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c3787cdc3832b70e21ac2efafea2a82a8ccb5e85bec110dc68b26023e9d3caae", size = 5237940, upload-time = "2026-04-12T16:25:49.157Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d0/f0/cdea60d92df731725fc3c4f33e387b100f210acd45c92969e42d2ba993fa/lxml-6.0.4-cp314-cp314-manylinux_2_28_i686.whl", hash = "sha256:3f276d49c23103565d39440b9b3f4fc08fa22f5a96395ea4b4d4fea4458b1505", size = 5350050, upload-time = "2026-04-12T16:25:52.027Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2e/15/bf52c7a70b6081bb9e00d37cc90fcf60aa84468d9d173ad2fade38ec34c5/lxml-6.0.4-cp314-cp314-manylinux_2_31_armv7l.whl", hash = "sha256:fdfdad73736402375b11b3a137e48cd09634177516baf5fc0bd80d1ca85f3cda", size = 4696409, upload-time = "2026-04-12T16:25:55.141Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c5/69/9bade267332cc06f9a9aa773b5a11bdfb249af485df9e142993009ea1fc4/lxml-6.0.4-cp314-cp314-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:75912421456946931daba0ec3cedfa824c756585d05bde97813a17992bfbd013", size = 5249072, upload-time = "2026-04-12T16:25:57.362Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/14/ca/043bcacb096d6ed291cbbc58724e9625a453069d6edeb840b0bf18038d05/lxml-6.0.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:48cd5a88da67233fd82f2920db344503c2818255217cd6ea462c9bb8254ba7cb", size = 5083779, upload-time = "2026-04-12T16:26:00.018Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/04/89/f5fb18d76985969e84af13682e489acabee399bb54738a363925ea6e7390/lxml-6.0.4-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:87af86a8fa55b9ff1e6ee4233d762296f2ce641ba948af783fb995c5a8a3371b", size = 4736953, upload-time = "2026-04-12T16:26:02.289Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/84/ba/d1d7284bb4ba951f188c3fc0455943c1fcbd1c33d1324d6d57b7d4a45be6/lxml-6.0.4-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:a743714cd656ba7ccb29d199783906064c7b5ba3c0e2a79f0244ea0badc6a98c", size = 5669605, upload-time = "2026-04-12T16:26:04.694Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/72/05/1463e55f2de27bb60feddc894dd7c0833bd501f8861392ed416291b38db5/lxml-6.0.4-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:e31c76bd066fb4f81d9a32e5843bffdf939ab27afb1ffc1c924e749bfbdb00e3", size = 5236886, upload-time = "2026-04-12T16:26:07.659Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fe/fb/0b6ee9194ce3ac49db4cadaa8a9158f04779fc768b6c27c4e2945d71a99d/lxml-6.0.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f185fd6e7d550e9917d7103dccf51be589aba953e15994fb04646c1730019685", size = 5263382, upload-time = "2026-04-12T16:26:10.067Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9a/93/ec18a08e98dd82cac39f1d2511ee2bed5affb94d228356d8ef165a4ec3b9/lxml-6.0.4-cp314-cp314-win32.whl", hash = "sha256:774660028f8722a598400430d2746fb0075949f84a9a5cd9767d9152e3baaac5", size = 3656164, upload-time = "2026-04-12T16:26:59.568Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/15/86/52507316abfc7150bf6bb191e39a12e301ee80334610a493884ae2f9d20d/lxml-6.0.4-cp314-cp314-win_amd64.whl", hash = "sha256:fbd7d14349413f5609c0b537b1a48117d6ccef1af37986af6b03766ad05bf43e", size = 4062512, upload-time = "2026-04-12T16:27:02.212Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f1/d5/09c593a2ef2234b8cd6cf059e2dc212e0654bf05c503f0ef2daf05adb680/lxml-6.0.4-cp314-cp314-win_arm64.whl", hash = "sha256:a61a01ec3fbfd5b73a69a7bf513271051fd6c5795d82fc5daa0255934cd8db3d", size = 3740745, upload-time = "2026-04-12T16:27:04.444Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4a/3c/42a98bf6693938bf7b285ec7f70ba2ae9d785d0e5b2cdb85d2ee29e287eb/lxml-6.0.4-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:504edb62df33cea502ea6e73847c647ba228623ca3f80a228be5723a70984dd5", size = 8826437, upload-time = "2026-04-12T16:26:12.911Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c2/c2/ad13f39b2db8709788aa2dcb6e90b81da76db3b5b2e7d35e0946cf984960/lxml-6.0.4-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:f01b7b0316d4c0926d49a7f003b2d30539f392b140a3374bb788bad180bc8478", size = 4734892, upload-time = "2026-04-12T16:26:15.871Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2c/6d/c559d7b5922c5b0380fc2cb5ac134b6a3f9d79d368347a624ee5d68b0816/lxml-6.0.4-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ab999933e662501efe4b16e6cfb7c9f9deca7d072cd1788b99c8defde78c0dfb", size = 4969173, upload-time = "2026-04-12T16:26:18.335Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c7/78/ca521e36157f38e3e1a29276855cdf48d213138fc0c8365693ff5c876ca7/lxml-6.0.4-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:67c3f084389fe75932c39b6869a377f6c8e21e818f31ae8a30c71dd2e59360e2", size = 5103134, upload-time = "2026-04-12T16:26:20.612Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/28/a7/7d62d023bacaa0aaf60af8c0a77c6c05f84327396d755f3aa64b788678a9/lxml-6.0.4-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:377ea1d654f76ed6205c87d14920f829c9f4d31df83374d3cbcbdaae804d37b2", size = 5027205, upload-time = "2026-04-12T16:26:22.981Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/34/be/51b194b81684f2e85e5d992771c45d70cb22ac6f7291ac6bc7b255830afe/lxml-6.0.4-cp314-cp314t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e60cd0bcacbfd1a96d63516b622183fb2e3f202300df9eb5533391a8a939dbfa", size = 5594461, upload-time = "2026-04-12T16:26:25.316Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/39/24/8850f38fbf89dd072ff31ba22f9e40347aeada7cadf710ecb04b8d9f32d4/lxml-6.0.4-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6e9e30fd63d41dd0bbdb020af5cdfffd5d9b554d907cb210f18e8fcdc8eac013", size = 5223378, upload-time = "2026-04-12T16:26:28.68Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2a/9b/595239ba8c719b0fdc7bc9ebdb7564459c9a6b24b8b363df4a02674aeece/lxml-6.0.4-cp314-cp314t-manylinux_2_28_i686.whl", hash = "sha256:1fb4a1606bb68c533002e7ed50d7e55e58f0ef1696330670281cb79d5ab2050d", size = 5311415, upload-time = "2026-04-12T16:26:31.513Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/be/cb/aa27ac8d041acf34691577838494ad08df78e83fdfdb66948d2903e9291e/lxml-6.0.4-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:695c7708438e449d57f404db8cc1b769e77ad5b50655f32f8175686ba752f293", size = 4637953, upload-time = "2026-04-12T16:26:33.806Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f6/f2/f19114fd86825c2d1ce41cd99daad218d30cfdd2093d4de9273986fb4d68/lxml-6.0.4-cp314-cp314t-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d49c35ae1e35ee9b569892cf8f8f88db9524f28d66e9daee547a5ef9f3c5f468", size = 5231532, upload-time = "2026-04-12T16:26:36.518Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9a/0e/c3fa354039ec0b6b09f40fbe1129efc572ac6239faa4906de42d5ce87c0a/lxml-6.0.4-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5801072f8967625e6249d162065d0d6011ef8ce3d0efb8754496b5246b81a74b", size = 5083767, upload-time = "2026-04-12T16:26:39.332Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b3/4b/1a0dbb6d6ffae16e54a8a3796ded0ad2f9c3bc1ff3728bde33456f4e1d63/lxml-6.0.4-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:cbf768541526eba5ef1a49f991122e41b39781eafd0445a5a110fc09947a20b5", size = 4758079, upload-time = "2026-04-12T16:26:42.138Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a9/01/a246cf5f80f96766051de4b305d6552f80bdaefb37f04e019e42af0aba69/lxml-6.0.4-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:eecce87cc09233786fc31c230268183bf6375126cfec1c8b3673fcdc8767b560", size = 5618686, upload-time = "2026-04-12T16:26:44.507Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/eb/1f/b072a92369039ebef11b0a654be5134fcf3ed04c0f437faf9435ac9ba845/lxml-6.0.4-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:07dce892881179e11053066faca2da17b0eeb0bb7298f11bcf842a86db207dbd", size = 5227259, upload-time = "2026-04-12T16:26:47.083Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d5/a0/dc97034f9d4c0c4d30875147d81fd2c0c7f3d261b109db36ed746bf8ab1d/lxml-6.0.4-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e4f97aee337b947e6699e5574c90d087d3e2ce517016241c07e7e98a28dca885", size = 5246190, upload-time = "2026-04-12T16:26:49.468Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f2/ef/85cb69835113583c2516fee07d0ffb4d824b557424b06ba5872c20ba6078/lxml-6.0.4-cp314-cp314t-win32.whl", hash = "sha256:064477c0d4c695aa1ea4b9c1c4ee9043ab740d12135b74c458cc658350adcd86", size = 3896005, upload-time = "2026-04-12T16:26:52.163Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3d/5e/2231f34cc54b8422b793593138d86d3fa4588fb2297d4ea0472390f25627/lxml-6.0.4-cp314-cp314t-win_amd64.whl", hash = "sha256:25bad2d8438f4ef5a7ad4a8d8bcaadde20c0daced8bdb56d46236b0a7d1cbdd0", size = 4391037, upload-time = "2026-04-12T16:26:54.398Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/39/53/8ba3cd5984f8363635450c93f63e541a0721b362bb32ae0d8237d9674aee/lxml-6.0.4-cp314-cp314t-win_arm64.whl", hash = "sha256:1dcd9e6cb9b7df808ea33daebd1801f37a8f50e8c075013ed2a2343246727838", size = 3816184, upload-time = "2026-04-12T16:26:57.011Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/eb/45/cee4cf203ef0bab5c52afc118da61d6b460c928f2893d40023cfa27e0b80/lxml-6.1.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:ab863fd37458fed6456525f297d21239d987800c46e67da5ef04fc6b3dd93ac8", size = 8576713, upload-time = "2026-04-18T04:32:06.831Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8a/a7/eda05babeb7e046839204eaf254cd4d7c9130ce2bbf0d9e90ea41af5654d/lxml-6.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:6fd8b1df8254ff4fd93fd31da1fc15770bde23ac045be9bb1f87425702f61cc9", size = 4623874, upload-time = "2026-04-18T04:32:10.755Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e7/e9/db5846de9b436b91890a62f29d80cd849ea17948a49bf532d5278ee69a9e/lxml-6.1.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:47024feaae386a92a146af0d2aeed65229bf6fff738e6a11dda6b0015fb8fd03", size = 4949535, upload-time = "2026-04-18T04:34:06.657Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5a/ba/0d3593373dcae1d68f40dc3c41a5a92f2544e68115eb2f62319a4c2a6500/lxml-6.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3f00972f84450204cd5d93a5395965e348956aaceaadec693a22ec743f8ae3eb", size = 5086881, upload-time = "2026-04-18T04:34:09.556Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/43/76/759a7484539ad1af0d125a9afe9c3fb5f82a8779fd1f5f56319d9e4ea2fd/lxml-6.1.0-cp314-cp314-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97faa0860e13b05b15a51fb4986421ef7a30f0b3334061c416e0981e9450ca4c", size = 5031305, upload-time = "2026-04-18T04:34:12.336Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dc/b9/c1f0daf981a11e47636126901fd4ab82429e18c57aeb0fc3ad2940b42d8b/lxml-6.1.0-cp314-cp314-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:972a6451204798675407beaad97b868d0c733d9a74dafefc63120b81b8c2de28", size = 5647522, upload-time = "2026-04-18T04:34:14.89Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/31/e6/1f533dcd205275363d9ba3511bcec52fa2df86abf8abe6a5f2c599f0dc31/lxml-6.1.0-cp314-cp314-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fe022f20bc4569ec66b63b3fb275a3d628d9d32da6326b2982584104db6d3086", size = 5239310, upload-time = "2026-04-18T04:34:17.652Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c3/8c/4175fb709c78a6e315ed814ed33be3defd8b8721067e70419a6cf6f971da/lxml-6.1.0-cp314-cp314-manylinux_2_28_i686.whl", hash = "sha256:75c4c7c619a744f972f4451bf5adf6d0fb00992a1ffc9fd78e13b0bc817cc99f", size = 5350799, upload-time = "2026-04-18T04:34:20.529Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fd/77/6ffdebc5994975f0dde4acb59761902bd9d9bb84422b9a0bd239a7da9ca8/lxml-6.1.0-cp314-cp314-manylinux_2_31_armv7l.whl", hash = "sha256:3648f20d25102a22b6061c688beb3a805099ea4beb0a01ce62975d926944d292", size = 4697693, upload-time = "2026-04-18T04:34:23.541Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f8/f1/565f36bd5c73294602d48e04d23f81ff4c8736be6ba5e1d1ec670ac9be80/lxml-6.1.0-cp314-cp314-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:77b9f99b17cbf14026d1e618035077060fc7195dd940d025149f3e2e830fbfcb", size = 5250708, upload-time = "2026-04-18T04:34:26.001Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5a/11/a68ab9dd18c5c499404deb4005f4bc4e0e88e5b72cd755ad96efec81d18d/lxml-6.1.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:32662519149fd7a9db354175aa5e417d83485a8039b8aaa62f873ceee7ea4cad", size = 5084737, upload-time = "2026-04-18T04:34:28.32Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ab/78/e8f41e2c74f4af564e6a0348aea69fb6daaefa64bc071ef469823d22cc18/lxml-6.1.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:73d658216fc173cf2c939e90e07b941c5e12736b0bf6a99e7af95459cfe8eabb", size = 4737817, upload-time = "2026-04-18T04:34:30.784Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/06/2d/aa4e117aa2ce2f3b35d9ff246be74a2f8e853baba5d2a92c64744474603a/lxml-6.1.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:ac4db068889f8772a4a698c5980ec302771bb545e10c4b095d4c8be26749616f", size = 5670753, upload-time = "2026-04-18T04:34:33.675Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/08/f5/dd745d50c0409031dbfcc4881740542a01e54d6f0110bd420fa7782110b8/lxml-6.1.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:45e9dfbd1b661eb64ba0d4dbe762bd210c42d86dd1e5bd2bdf89d634231beb43", size = 5238071, upload-time = "2026-04-18T04:34:36.12Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3e/74/ad424f36d0340a904665867dab310a3f1f4c96ff4039698de83b77f44c1f/lxml-6.1.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:89e8d73d09ac696a5ba42ec69787913d53284f12092f651506779314f10ba585", size = 5264319, upload-time = "2026-04-18T04:34:39.035Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/53/36/a15d8b3514ec889bfd6aa3609107fcb6c9189f8dc347f1c0b81eded8d87c/lxml-6.1.0-cp314-cp314-win32.whl", hash = "sha256:ebe33f4ec1b2de38ceb225a1749a2965855bffeef435ba93cd2d5d540783bf2f", size = 3657139, upload-time = "2026-04-18T04:32:20.006Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1a/a4/263ebb0710851a3c6c937180a9a86df1206fdfe53cc43005aa2237fd7736/lxml-6.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:398443df51c538bd578529aa7e5f7afc6c292644174b47961f3bf87fe5741120", size = 4064195, upload-time = "2026-04-18T04:32:23.876Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/80/68/2000f29d323b6c286de077ad20b429fc52272e44eae6d295467043e56012/lxml-6.1.0-cp314-cp314-win_arm64.whl", hash = "sha256:8c8984e1d8c4b3949e419158fda14d921ff703a9ed8a47236c6eb7a2b6cb4946", size = 3741870, upload-time = "2026-04-18T04:32:27.922Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/30/e9/21383c7c8d43799f0da90224c0d7c921870d476ec9b3e01e1b2c0b8237c5/lxml-6.1.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:1081dd10bc6fa437db2500e13993abf7cc30716d0a2f40e65abb935f02ec559c", size = 8827548, upload-time = "2026-04-18T04:32:15.094Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a5/01/c6bc11cd587030dd4f719f65c5657960649fe3e19196c844c75bf32cd0d6/lxml-6.1.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:dabecc48db5f42ba348d1f5d5afdc54c6c4cc758e676926c7cd327045749517d", size = 4735866, upload-time = "2026-04-18T04:32:18.924Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f3/01/757132fff5f4acf25463b5298f1a46099f3a94480b806547b29ce5e385de/lxml-6.1.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e3dd5fe19c9e0ac818a9c7f132a5e43c1339ec1cbbfecb1a938bd3a47875b7c9", size = 4969476, upload-time = "2026-04-18T04:34:41.889Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fd/fb/1bc8b9d27ed64be7c8903db6c89e74dc8c2cd9ec630a7462e4654316dc5b/lxml-6.1.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:9e7b0a4ca6dcc007a4cef00a761bba2dea959de4bd2df98f926b33c92ca5dfb9", size = 5103719, upload-time = "2026-04-18T04:34:44.797Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d5/e7/5bf82fa28133536a54601aae633b14988e89ed61d4c1eb6b899b023233aa/lxml-6.1.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5d27bbe326c6b539c64b42638b18bc6003a8d88f76213a97ac9ed4f885efeab7", size = 5027890, upload-time = "2026-04-18T04:34:47.634Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2d/20/e048db5d4b4ea0366648aa595f26bb764b2670903fc585b87436d0a5032c/lxml-6.1.0-cp314-cp314t-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c4e425db0c5445ef0ad56b0eec54f89b88b2d884656e536a90b2f52aecb4ca86", size = 5596008, upload-time = "2026-04-18T04:34:51.503Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9a/c2/d10807bc8da4824b39e5bd01b5d05c077b6fd01bd91584167edf6b269d22/lxml-6.1.0-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4b89b098105b8599dc57adac95d1813409ac476d3c948a498775d3d0c6124bfb", size = 5224451, upload-time = "2026-04-18T04:34:54.263Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3c/15/2ebea45bea427e7f0057e9ce7b2d62c5aba20c6b001cca89ed0aadb3ad41/lxml-6.1.0-cp314-cp314t-manylinux_2_28_i686.whl", hash = "sha256:c4a699432846df86cc3de502ee85f445ebad748a1c6021d445f3e514d2cd4b1c", size = 5312135, upload-time = "2026-04-18T04:34:56.818Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/31/e2/87eeae151b0be2a308d49a7ec444ff3eb192b14251e62addb29d0bf3778f/lxml-6.1.0-cp314-cp314t-manylinux_2_31_armv7l.whl", hash = "sha256:30e7b2ed63b6c8e97cca8af048589a788ab5c9c905f36d9cf1c2bb549f450d2f", size = 4639126, upload-time = "2026-04-18T04:34:59.704Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a3/51/8a3f6a20902ad604dd746ec7b4000311b240d389dac5e9d95adefd349e0c/lxml-6.1.0-cp314-cp314t-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:022981127642fe19866d2907d76241bb07ed21749601f727d5d5dd1ce5d1b773", size = 5232579, upload-time = "2026-04-18T04:35:02.658Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6d/d2/650d619bdbe048d2c3f2c31edb00e35670a5e2d65b4fe3b61bce37b19121/lxml-6.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:23cad0cc86046d4222f7f418910e46b89971c5a45d3c8abfad0f64b7b05e4a9b", size = 5084206, upload-time = "2026-04-18T04:35:05.175Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dd/8a/672ca1a3cbeabd1f511ca275a916c0514b747f4b85bdaae103b8fa92f307/lxml-6.1.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:21c3302068f50d1e8728c67c87ba92aa87043abee517aa2576cca1855326b405", size = 4758906, upload-time = "2026-04-18T04:35:08.098Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/be/f1/ef4b691da85c916cb2feb1eec7414f678162798ac85e042fa164419ac05c/lxml-6.1.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:be10838781cb3be19251e276910cd508fe127e27c3242e50521521a0f3781690", size = 5620553, upload-time = "2026-04-18T04:35:11.23Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/59/17/94e81def74107809755ac2782fdad4404420f1c92ca83433d117a6d5acf0/lxml-6.1.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:2173a7bffe97667bbf0767f8a99e587740a8c56fdf3befac4b09cb29a80276fd", size = 5229458, upload-time = "2026-04-18T04:35:14.254Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/21/55/c4be91b0f830a871fc1b0d730943d56013b683d4671d5198260e2eae722b/lxml-6.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:c6854e9cf99c84beb004eecd7d3a3868ef1109bf2b1df92d7bc11e96a36c2180", size = 5247861, upload-time = "2026-04-18T04:35:17.006Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c2/ca/77123e4d77df3cb1e968ade7b1f808f5d3a5c1c96b18a33895397de292c1/lxml-6.1.0-cp314-cp314t-win32.whl", hash = "sha256:00750d63ef0031a05331b9223463b1c7c02b9004cef2346a5b2877f0f9494dd2", size = 3897377, upload-time = "2026-04-18T04:32:07.656Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/64/ce/3554833989d074267c063209bae8b09815e5656456a2d332b947806b05ff/lxml-6.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:80410c3a7e3c617af04de17caa9f9f20adaa817093293d69eae7d7d0522836f5", size = 4392701, upload-time = "2026-04-18T04:32:12.113Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2b/a0/9b916c68c0e57752c07f8f64b30138d9d4059dbeb27b90274dedbea128ff/lxml-6.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:26dd9f57ee3bd41e7d35b4c98a2ffd89ed11591649f421f0ec19f67d50ec67ac", size = 3817120, upload-time = "2026-04-18T04:32:15.803Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2591,11 +2591,11 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "packaging"
|
||||
version = "26.0"
|
||||
version = "26.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/65/ee/299d360cdc32edc7d2cf530f3accf79c4fca01e96ffc950d8a52213bd8e4/packaging-26.0.tar.gz", hash = "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4", size = 143416, upload-time = "2026-01-21T20:50:39.064Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/df/de/0d2b39fb4af88a0258f3bac87dfcbb48e73fbdea4a2ed0e2213f9a4c2f9a/packaging-26.1.tar.gz", hash = "sha256:f042152b681c4bfac5cae2742a55e103d27ab2ec0f3d88037136b6bfe7c9c5de", size = 215519, upload-time = "2026-04-14T21:12:49.362Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b7/b9/c538f279a4e237a006a2c98387d081e9eb060d203d8ed34467cc0f0b9b53/packaging-26.0-py3-none-any.whl", hash = "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529", size = 74366, upload-time = "2026-01-21T20:50:37.788Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7a/c2/920ef838e2f0028c8262f16101ec09ebd5969864e5a64c4c05fad0617c56/packaging-26.1-py3-none-any.whl", hash = "sha256:5d9c0669c6285e491e0ced2eee587eaf67b670d94a19e94e3984a481aba6802f", size = 95831, upload-time = "2026-04-14T21:12:47.56Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -2824,7 +2824,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "pydantic"
|
||||
version = "2.12.5"
|
||||
version = "2.13.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "annotated-types" },
|
||||
@@ -2832,9 +2832,9 @@ dependencies = [
|
||||
{ name = "typing-extensions" },
|
||||
{ name = "typing-inspection" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/69/44/36f1a6e523abc58ae5f928898e4aca2e0ea509b5aa6f6f392a5d882be928/pydantic-2.12.5.tar.gz", hash = "sha256:4d351024c75c0f085a9febbb665ce8c0c6ec5d30e903bdb6394b7ede26aebb49", size = 821591, upload-time = "2025-11-26T15:11:46.471Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d9/e4/40d09941a2cebcb20609b86a559817d5b9291c49dd6f8c87e5feffbe703a/pydantic-2.13.3.tar.gz", hash = "sha256:af09e9d1d09f4e7fe37145c1f577e1d61ceb9a41924bf0094a36506285d0a84d", size = 844068, upload-time = "2026-04-20T14:46:43.632Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/5a/87/b70ad306ebb6f9b585f114d0ac2137d792b48be34d732d60e597c2f8465a/pydantic-2.12.5-py3-none-any.whl", hash = "sha256:e561593fccf61e8a20fc46dfc2dfe075b8be7d0188df33f221ad1f0139180f9d", size = 463580, upload-time = "2025-11-26T15:11:44.605Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f3/0a/fd7d723f8f8153418fb40cf9c940e82004fce7e987026b08a68a36dd3fe7/pydantic-2.13.3-py3-none-any.whl", hash = "sha256:6db14ac8dfc9a1e57f87ea2c0de670c251240f43cb0c30a5130e9720dc612927", size = 471981, upload-time = "2026-04-20T14:46:41.402Z" },
|
||||
]
|
||||
|
||||
[package.optional-dependencies]
|
||||
@@ -2844,41 +2844,43 @@ email = [
|
||||
|
||||
[[package]]
|
||||
name = "pydantic-core"
|
||||
version = "2.41.5"
|
||||
version = "2.46.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "typing-extensions" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/71/70/23b021c950c2addd24ec408e9ab05d59b035b39d97cdc1130e1bce647bb6/pydantic_core-2.41.5.tar.gz", hash = "sha256:08daa51ea16ad373ffd5e7606252cc32f07bc72b28284b6bc9c6df804816476e", size = 460952, upload-time = "2025-11-04T13:43:49.098Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/2a/ef/f7abb56c49382a246fd2ce9c799691e3c3e7175ec74b14d99e798bcddb1a/pydantic_core-2.46.3.tar.gz", hash = "sha256:41c178f65b8c29807239d47e6050262eb6bf84eb695e41101e62e38df4a5bc2c", size = 471412, upload-time = "2026-04-20T14:40:56.672Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/ea/28/46b7c5c9635ae96ea0fbb779e271a38129df2550f763937659ee6c5dbc65/pydantic_core-2.41.5-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:3f37a19d7ebcdd20b96485056ba9e8b304e27d9904d233d7b1015db320e51f0a", size = 2119622, upload-time = "2025-11-04T13:40:56.68Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/74/1a/145646e5687e8d9a1e8d09acb278c8535ebe9e972e1f162ed338a622f193/pydantic_core-2.41.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1d1d9764366c73f996edd17abb6d9d7649a7eb690006ab6adbda117717099b14", size = 1891725, upload-time = "2025-11-04T13:40:58.807Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/23/04/e89c29e267b8060b40dca97bfc64a19b2a3cf99018167ea1677d96368273/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25e1c2af0fce638d5f1988b686f3b3ea8cd7de5f244ca147c777769e798a9cd1", size = 1915040, upload-time = "2025-11-04T13:41:00.853Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/84/a3/15a82ac7bd97992a82257f777b3583d3e84bdb06ba6858f745daa2ec8a85/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:506d766a8727beef16b7adaeb8ee6217c64fc813646b424d0804d67c16eddb66", size = 2063691, upload-time = "2025-11-04T13:41:03.504Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/74/9b/0046701313c6ef08c0c1cf0e028c67c770a4e1275ca73131563c5f2a310a/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4819fa52133c9aa3c387b3328f25c1facc356491e6135b459f1de698ff64d869", size = 2213897, upload-time = "2025-11-04T13:41:05.804Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8a/cd/6bac76ecd1b27e75a95ca3a9a559c643b3afcd2dd62086d4b7a32a18b169/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2b761d210c9ea91feda40d25b4efe82a1707da2ef62901466a42492c028553a2", size = 2333302, upload-time = "2025-11-04T13:41:07.809Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4c/d2/ef2074dc020dd6e109611a8be4449b98cd25e1b9b8a303c2f0fca2f2bcf7/pydantic_core-2.41.5-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:22f0fb8c1c583a3b6f24df2470833b40207e907b90c928cc8d3594b76f874375", size = 2064877, upload-time = "2025-11-04T13:41:09.827Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/18/66/e9db17a9a763d72f03de903883c057b2592c09509ccfe468187f2a2eef29/pydantic_core-2.41.5-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2782c870e99878c634505236d81e5443092fba820f0373997ff75f90f68cd553", size = 2180680, upload-time = "2025-11-04T13:41:12.379Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d3/9e/3ce66cebb929f3ced22be85d4c2399b8e85b622db77dad36b73c5387f8f8/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:0177272f88ab8312479336e1d777f6b124537d47f2123f89cb37e0accea97f90", size = 2138960, upload-time = "2025-11-04T13:41:14.627Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a6/62/205a998f4327d2079326b01abee48e502ea739d174f0a89295c481a2272e/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:63510af5e38f8955b8ee5687740d6ebf7c2a0886d15a6d65c32814613681bc07", size = 2339102, upload-time = "2025-11-04T13:41:16.868Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3c/0d/f05e79471e889d74d3d88f5bd20d0ed189ad94c2423d81ff8d0000aab4ff/pydantic_core-2.41.5-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:e56ba91f47764cc14f1daacd723e3e82d1a89d783f0f5afe9c364b8bb491ccdb", size = 2326039, upload-time = "2025-11-04T13:41:18.934Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ec/e1/e08a6208bb100da7e0c4b288eed624a703f4d129bde2da475721a80cab32/pydantic_core-2.41.5-cp314-cp314-win32.whl", hash = "sha256:aec5cf2fd867b4ff45b9959f8b20ea3993fc93e63c7363fe6851424c8a7e7c23", size = 1995126, upload-time = "2025-11-04T13:41:21.418Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/48/5d/56ba7b24e9557f99c9237e29f5c09913c81eeb2f3217e40e922353668092/pydantic_core-2.41.5-cp314-cp314-win_amd64.whl", hash = "sha256:8e7c86f27c585ef37c35e56a96363ab8de4e549a95512445b85c96d3e2f7c1bf", size = 2015489, upload-time = "2025-11-04T13:41:24.076Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4e/bb/f7a190991ec9e3e0ba22e4993d8755bbc4a32925c0b5b42775c03e8148f9/pydantic_core-2.41.5-cp314-cp314-win_arm64.whl", hash = "sha256:e672ba74fbc2dc8eea59fb6d4aed6845e6905fc2a8afe93175d94a83ba2a01a0", size = 1977288, upload-time = "2025-11-04T13:41:26.33Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/92/ed/77542d0c51538e32e15afe7899d79efce4b81eee631d99850edc2f5e9349/pydantic_core-2.41.5-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:8566def80554c3faa0e65ac30ab0932b9e3a5cd7f8323764303d468e5c37595a", size = 2120255, upload-time = "2025-11-04T13:41:28.569Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bb/3d/6913dde84d5be21e284439676168b28d8bbba5600d838b9dca99de0fad71/pydantic_core-2.41.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b80aa5095cd3109962a298ce14110ae16b8c1aece8b72f9dafe81cf597ad80b3", size = 1863760, upload-time = "2025-11-04T13:41:31.055Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5a/f0/e5e6b99d4191da102f2b0eb9687aaa7f5bea5d9964071a84effc3e40f997/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3006c3dd9ba34b0c094c544c6006cc79e87d8612999f1a5d43b769b89181f23c", size = 1878092, upload-time = "2025-11-04T13:41:33.21Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/71/48/36fb760642d568925953bcc8116455513d6e34c4beaa37544118c36aba6d/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:72f6c8b11857a856bcfa48c86f5368439f74453563f951e473514579d44aa612", size = 2053385, upload-time = "2025-11-04T13:41:35.508Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/20/25/92dc684dd8eb75a234bc1c764b4210cf2646479d54b47bf46061657292a8/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5cb1b2f9742240e4bb26b652a5aeb840aa4b417c7748b6f8387927bc6e45e40d", size = 2218832, upload-time = "2025-11-04T13:41:37.732Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e2/09/f53e0b05023d3e30357d82eb35835d0f6340ca344720a4599cd663dca599/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bd3d54f38609ff308209bd43acea66061494157703364ae40c951f83ba99a1a9", size = 2327585, upload-time = "2025-11-04T13:41:40Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/aa/4e/2ae1aa85d6af35a39b236b1b1641de73f5a6ac4d5a7509f77b814885760c/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ff4321e56e879ee8d2a879501c8e469414d948f4aba74a2d4593184eb326660", size = 2041078, upload-time = "2025-11-04T13:41:42.323Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cd/13/2e215f17f0ef326fc72afe94776edb77525142c693767fc347ed6288728d/pydantic_core-2.41.5-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0d2568a8c11bf8225044aa94409e21da0cb09dcdafe9ecd10250b2baad531a9", size = 2173914, upload-time = "2025-11-04T13:41:45.221Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/02/7a/f999a6dcbcd0e5660bc348a3991c8915ce6599f4f2c6ac22f01d7a10816c/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:a39455728aabd58ceabb03c90e12f71fd30fa69615760a075b9fec596456ccc3", size = 2129560, upload-time = "2025-11-04T13:41:47.474Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3a/b1/6c990ac65e3b4c079a4fb9f5b05f5b013afa0f4ed6780a3dd236d2cbdc64/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:239edca560d05757817c13dc17c50766136d21f7cd0fac50295499ae24f90fdf", size = 2329244, upload-time = "2025-11-04T13:41:49.992Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d9/02/3c562f3a51afd4d88fff8dffb1771b30cfdfd79befd9883ee094f5b6c0d8/pydantic_core-2.41.5-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:2a5e06546e19f24c6a96a129142a75cee553cc018ffee48a460059b1185f4470", size = 2331955, upload-time = "2025-11-04T13:41:54.079Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5c/96/5fb7d8c3c17bc8c62fdb031c47d77a1af698f1d7a406b0f79aaa1338f9ad/pydantic_core-2.41.5-cp314-cp314t-win32.whl", hash = "sha256:b4ececa40ac28afa90871c2cc2b9ffd2ff0bf749380fbdf57d165fd23da353aa", size = 1988906, upload-time = "2025-11-04T13:41:56.606Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/22/ed/182129d83032702912c2e2d8bbe33c036f342cc735737064668585dac28f/pydantic_core-2.41.5-cp314-cp314t-win_amd64.whl", hash = "sha256:80aa89cad80b32a912a65332f64a4450ed00966111b6615ca6816153d3585a8c", size = 1981607, upload-time = "2025-11-04T13:41:58.889Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9f/ed/068e41660b832bb0b1aa5b58011dea2a3fe0ba7861ff38c4d4904c1c1a99/pydantic_core-2.41.5-cp314-cp314t-win_arm64.whl", hash = "sha256:35b44f37a3199f771c3eaa53051bc8a70cd7b54f333531c59e29fd4db5d15008", size = 1974769, upload-time = "2025-11-04T13:42:01.186Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/7f/db/a7bcb4940183fda36022cd18ba8dd12f2dff40740ec7b58ce7457befa416/pydantic_core-2.46.3-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:afa3aa644f74e290cdede48a7b0bee37d1c35e71b05105f6b340d484af536d9b", size = 2097614, upload-time = "2026-04-20T14:44:38.374Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/24/35/e4066358a22e3e99519db370494c7528f5a2aa1367370e80e27e20283543/pydantic_core-2.46.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:ced3310e51aa425f7f77da8bbbb5212616655bedbe82c70944320bc1dbe5e018", size = 1951896, upload-time = "2026-04-20T14:40:53.996Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/87/92/37cf4049d1636996e4b888c05a501f40a43ff218983a551d57f9d5e14f0d/pydantic_core-2.46.3-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e29908922ce9da1a30b4da490bd1d3d82c01dcfdf864d2a74aacee674d0bfa34", size = 1979314, upload-time = "2026-04-20T14:41:49.446Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d8/36/9ff4d676dfbdfb2d591cf43f3d90ded01e15b1404fd101180ed2d62a2fd3/pydantic_core-2.46.3-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:0c9ff69140423eea8ed2d5477df3ba037f671f5e897d206d921bc9fdc39613e7", size = 2056133, upload-time = "2026-04-20T14:42:23.574Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bc/f0/405b442a4d7ba855b06eec8b2bf9c617d43b8432d099dfdc7bf999293495/pydantic_core-2.46.3-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b675ab0a0d5b1c8fdb81195dc5bcefea3f3c240871cdd7ff9a2de8aa50772eb2", size = 2228726, upload-time = "2026-04-20T14:44:22.816Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e7/f8/65cd92dd5a0bd89ba277a98ecbfaf6fc36bbd3300973c7a4b826d6ab1391/pydantic_core-2.46.3-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0087084960f209a9a4af50ecd1fb063d9ad3658c07bb81a7a53f452dacbfb2ba", size = 2301214, upload-time = "2026-04-20T14:44:48.792Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fd/86/ef96a4c6e79e7a2d0410826a68fbc0eccc0fd44aa733be199d5fcac3bb87/pydantic_core-2.46.3-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ed42e6cc8e1b0e2b9b96e2276bad70ae625d10d6d524aed0c93de974ae029f9f", size = 2099927, upload-time = "2026-04-20T14:41:40.196Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6d/53/269caf30e0096e0a8a8f929d1982a27b3879872cca2d917d17c2f9fdf4fe/pydantic_core-2.46.3-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:f1771ce258afb3e4201e67d154edbbae712a76a6081079fe247c2f53c6322c22", size = 2128789, upload-time = "2026-04-20T14:41:15.868Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/00/b0/1a6d9b6a587e118482910c244a1c5acf4d192604174132efd12bf0ac486f/pydantic_core-2.46.3-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a7610b6a5242a6c736d8ad47fd5fff87fcfe8f833b281b1c409c3d6835d9227f", size = 2173815, upload-time = "2026-04-20T14:44:25.152Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/87/56/e7e00d4041a7e62b5a40815590114db3b535bf3ca0bf4dca9f16cef25246/pydantic_core-2.46.3-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:ff5e7783bcc5476e1db448bf268f11cb257b1c276d3e89f00b5727be86dd0127", size = 2181608, upload-time = "2026-04-20T14:41:28.933Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e8/22/4bd23c3d41f7c185d60808a1de83c76cf5aeabf792f6c636a55c3b1ec7f9/pydantic_core-2.46.3-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:9d2e32edcc143bc01e95300671915d9ca052d4f745aa0a49c48d4803f8a85f2c", size = 2326968, upload-time = "2026-04-20T14:42:03.962Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/24/ac/66cd45129e3915e5ade3b292cb3bc7fd537f58f8f8dbdaba6170f7cabb74/pydantic_core-2.46.3-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:6e42d83d1c6b87fa56b521479cff237e626a292f3b31b6345c15a99121b454c1", size = 2369842, upload-time = "2026-04-20T14:41:35.52Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a2/51/dd4248abb84113615473aa20d5545b7c4cd73c8644003b5259686f93996c/pydantic_core-2.46.3-cp314-cp314-win32.whl", hash = "sha256:07bc6d2a28c3adb4f7c6ae46aa4f2d2929af127f587ed44057af50bf1ce0f505", size = 1959661, upload-time = "2026-04-20T14:41:00.042Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/20/eb/59980e5f1ae54a3b86372bd9f0fa373ea2d402e8cdcd3459334430f91e91/pydantic_core-2.46.3-cp314-cp314-win_amd64.whl", hash = "sha256:8940562319bc621da30714617e6a7eaa6b98c84e8c685bcdc02d7ed5e7c7c44e", size = 2071686, upload-time = "2026-04-20T14:43:16.471Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8c/db/1cf77e5247047dfee34bc01fa9bca134854f528c8eb053e144298893d370/pydantic_core-2.46.3-cp314-cp314-win_arm64.whl", hash = "sha256:5dcbbcf4d22210ced8f837c96db941bdb078f419543472aca5d9a0bb7cddc7df", size = 2026907, upload-time = "2026-04-20T14:43:31.732Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/57/c0/b3df9f6a543276eadba0a48487b082ca1f201745329d97dbfa287034a230/pydantic_core-2.46.3-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:d0fe3dce1e836e418f912c1ad91c73357d03e556a4d286f441bf34fed2dbeecf", size = 2095047, upload-time = "2026-04-20T14:42:37.982Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/66/57/886a938073b97556c168fd99e1a7305bb363cd30a6d2c76086bf0587b32a/pydantic_core-2.46.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:9ce92e58abc722dac1bf835a6798a60b294e48eb0e625ec9fd994b932ac5feee", size = 1934329, upload-time = "2026-04-20T14:43:49.655Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0b/7c/b42eaa5c34b13b07ecb51da21761297a9b8eb43044c864a035999998f328/pydantic_core-2.46.3-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a03e6467f0f5ab796a486146d1b887b2dc5e5f9b3288898c1b1c3ad974e53e4a", size = 1974847, upload-time = "2026-04-20T14:42:10.737Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e6/9b/92b42db6543e7de4f99ae977101a2967b63122d4b6cf7773812da2d7d5b5/pydantic_core-2.46.3-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2798b6ba041b9d70acfb9071a2ea13c8456dd1e6a5555798e41ba7b0790e329c", size = 2041742, upload-time = "2026-04-20T14:40:44.262Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0f/19/46fbe1efabb5aa2834b43b9454e70f9a83ad9c338c1291e48bdc4fecf167/pydantic_core-2.46.3-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9be3e221bdc6d69abf294dcf7aff6af19c31a5cdcc8f0aa3b14be29df4bd03b1", size = 2236235, upload-time = "2026-04-20T14:41:27.307Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/77/da/b3f95bc009ad60ec53120f5d16c6faa8cabdbe8a20d83849a1f2b8728148/pydantic_core-2.46.3-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f13936129ce841f2a5ddf6f126fea3c43cd128807b5a59588c37cf10178c2e64", size = 2282633, upload-time = "2026-04-20T14:44:33.271Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/cc/6e/401336117722e28f32fb8220df676769d28ebdf08f2f4469646d404c43a3/pydantic_core-2.46.3-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:28b5f2ef03416facccb1c6ef744c69793175fd27e44ef15669201601cf423acb", size = 2109679, upload-time = "2026-04-20T14:44:41.065Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fc/53/b289f9bc8756a32fe718c46f55afaeaf8d489ee18d1a1e7be1db73f42cc4/pydantic_core-2.46.3-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:830d1247d77ad23852314f069e9d7ddafeec5f684baf9d7e7065ed46a049c4e6", size = 2108342, upload-time = "2026-04-20T14:42:50.144Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/10/5b/8292fc7c1f9111f1b2b7c1b0dcf1179edcd014fc3ea4517499f50b829d71/pydantic_core-2.46.3-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d0793c90c1a3c74966e7975eaef3ed30ebdff3260a0f815a62a22adc17e4c01c", size = 2157208, upload-time = "2026-04-20T14:42:08.133Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2b/9e/f80044e9ec07580f057a89fc131f78dda7a58751ddf52bbe05eaf31db50f/pydantic_core-2.46.3-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:d2d0aead851b66f5245ec0c4fb2612ef457f8bbafefdf65a2bf9d6bac6140f47", size = 2167237, upload-time = "2026-04-20T14:42:25.412Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f8/84/6781a1b037f3b96be9227edbd1101f6d3946746056231bf4ac48cdff1a8d/pydantic_core-2.46.3-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:2f40e4246676beb31c5ce77c38a55ca4e465c6b38d11ea1bd935420568e0b1ab", size = 2312540, upload-time = "2026-04-20T14:40:40.313Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3e/db/19c0839feeb728e7df03255581f198dfdf1c2aeb1e174a8420b63c5252e5/pydantic_core-2.46.3-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:cf489cf8986c543939aeee17a09c04d6ffb43bfef8ca16fcbcc5cfdcbed24dba", size = 2369556, upload-time = "2026-04-20T14:41:09.427Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e0/15/3228774cb7cd45f5f721ddf1b2242747f4eb834d0c491f0c02d606f09fed/pydantic_core-2.46.3-cp314-cp314t-win32.whl", hash = "sha256:ffe0883b56cfc05798bf994164d2b2ff03efe2d22022a2bb080f3b626176dd56", size = 1949756, upload-time = "2026-04-20T14:41:25.717Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b8/2a/c79cf53fd91e5a87e30d481809f52f9a60dd221e39de66455cf04deaad37/pydantic_core-2.46.3-cp314-cp314t-win_amd64.whl", hash = "sha256:706d9d0ce9cf4593d07270d8e9f53b161f90c57d315aeec4fb4fd7a8b10240d8", size = 2051305, upload-time = "2026-04-20T14:43:18.627Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0b/db/d8182a7f1d9343a032265aae186eb063fe26ca4c40f256b21e8da4498e89/pydantic_core-2.46.3-cp314-cp314t-win_arm64.whl", hash = "sha256:77706aeb41df6a76568434701e0917da10692da28cb69d5fb6919ce5fdb07374", size = 2026310, upload-time = "2026-04-20T14:41:01.778Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3083,11 +3085,11 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "python-dotenv"
|
||||
version = "1.2.1"
|
||||
version = "1.2.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/f0/26/19cadc79a718c5edbec86fd4919a6b6d3f681039a2f6d66d14be94e75fb9/python_dotenv-1.2.1.tar.gz", hash = "sha256:42667e897e16ab0d66954af0e60a9caa94f0fd4ecf3aaf6d2d260eec1aa36ad6", size = 44221, upload-time = "2025-10-26T15:12:10.434Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/82/ed/0301aeeac3e5353ef3d94b6ec08bbcabd04a72018415dcb29e588514bba8/python_dotenv-1.2.2.tar.gz", hash = "sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3", size = 50135, upload-time = "2026-03-01T16:00:26.196Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/14/1b/a298b06749107c305e1fe0f814c6c74aea7b2f1e10989cb30f544a1b3253/python_dotenv-1.2.1-py3-none-any.whl", hash = "sha256:b81ee9561e9ca4004139c6cbba3a238c32b03e4894671e181b671e8cb8425d61", size = 21230, upload-time = "2025-10-26T15:12:09.109Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/0b/d7/1959b9648791274998a9c3526f6d0ec8fd2233e4d4acce81bbae76b44b2a/python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a", size = 22101, upload-time = "2026-03-01T16:00:25.09Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3287,27 +3289,27 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.15.10"
|
||||
version = "0.15.11"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/e7/d9/aa3f7d59a10ef6b14fe3431706f854dbf03c5976be614a9796d36326810c/ruff-0.15.10.tar.gz", hash = "sha256:d1f86e67ebfdef88e00faefa1552b5e510e1d35f3be7d423dc7e84e63788c94e", size = 4631728, upload-time = "2026-04-09T14:06:09.884Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/e4/8d/192f3d7103816158dfd5ea50d098ef2aec19194e6cbccd4b3485bdb2eb2d/ruff-0.15.11.tar.gz", hash = "sha256:f092b21708bf0e7437ce9ada249dfe688ff9a0954fc94abab05dcea7dcd29c33", size = 4637264, upload-time = "2026-04-16T18:46:26.58Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/eb/00/a1c2fdc9939b2c03691edbda290afcd297f1f389196172826b03d6b6a595/ruff-0.15.10-py3-none-linux_armv6l.whl", hash = "sha256:0744e31482f8f7d0d10a11fcbf897af272fefdfcb10f5af907b18c2813ff4d5f", size = 10563362, upload-time = "2026-04-09T14:06:21.189Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5c/15/006990029aea0bebe9d33c73c3e28c80c391ebdba408d1b08496f00d422d/ruff-0.15.10-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b1e7c16ea0ff5a53b7c2df52d947e685973049be1cdfe2b59a9c43601897b22e", size = 10951122, upload-time = "2026-04-09T14:06:02.236Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f2/c0/4ac978fe874d0618c7da647862afe697b281c2806f13ce904ad652fa87e4/ruff-0.15.10-py3-none-macosx_11_0_arm64.whl", hash = "sha256:93cc06a19e5155b4441dd72808fdf84290d84ad8a39ca3b0f994363ade4cebb1", size = 10314005, upload-time = "2026-04-09T14:06:00.026Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/da/73/c209138a5c98c0d321266372fc4e33ad43d506d7e5dd817dd89b60a8548f/ruff-0.15.10-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:83e1dd04312997c99ea6965df66a14fb4f03ba978564574ffc68b0d61fd3989e", size = 10643450, upload-time = "2026-04-09T14:05:42.137Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ec/76/0deec355d8ec10709653635b1f90856735302cb8e149acfdf6f82a5feb70/ruff-0.15.10-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8154d43684e4333360fedd11aaa40b1b08a4e37d8ffa9d95fee6fa5b37b6fab1", size = 10379597, upload-time = "2026-04-09T14:05:49.984Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dc/be/86bba8fc8798c081e28a4b3bb6d143ccad3fd5f6f024f02002b8f08a9fa3/ruff-0.15.10-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ab88715f3a6deb6bde6c227f3a123410bec7b855c3ae331b4c006189e895cef", size = 11146645, upload-time = "2026-04-09T14:06:12.246Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a8/89/140025e65911b281c57be1d385ba1d932c2366ca88ae6663685aed8d4881/ruff-0.15.10-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a768ff5969b4f44c349d48edf4ab4f91eddb27fd9d77799598e130fb628aa158", size = 12030289, upload-time = "2026-04-09T14:06:04.776Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/88/de/ddacca9545a5e01332567db01d44bd8cf725f2db3b3d61a80550b48308ea/ruff-0.15.10-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ee3ef42dab7078bda5ff6a1bcba8539e9857deb447132ad5566a038674540d0", size = 11496266, upload-time = "2026-04-09T14:05:55.485Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bc/bb/7ddb00a83760ff4a83c4e2fc231fd63937cc7317c10c82f583302e0f6586/ruff-0.15.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:51cb8cc943e891ba99989dd92d61e29b1d231e14811db9be6440ecf25d5c1609", size = 11256418, upload-time = "2026-04-09T14:05:57.69Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/dc/8d/55de0d35aacf6cd50b6ee91ee0f291672080021896543776f4170fc5c454/ruff-0.15.10-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:e59c9bdc056a320fb9ea1700a8d591718b8faf78af065484e801258d3a76bc3f", size = 11288416, upload-time = "2026-04-09T14:05:44.695Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/68/cf/9438b1a27426ec46a80e0a718093c7f958ef72f43eb3111862949ead3cc1/ruff-0.15.10-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:136c00ca2f47b0018b073f28cb5c1506642a830ea941a60354b0e8bc8076b151", size = 10621053, upload-time = "2026-04-09T14:05:52.782Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4c/50/e29be6e2c135e9cd4cb15fbade49d6a2717e009dff3766dd080fcb82e251/ruff-0.15.10-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8b80a2f3c9c8a950d6237f2ca12b206bccff626139be9fa005f14feb881a1ae8", size = 10378302, upload-time = "2026-04-09T14:06:14.361Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/18/2f/e0b36a6f99c51bb89f3a30239bc7bf97e87a37ae80aa2d6542d6e5150364/ruff-0.15.10-py3-none-musllinux_1_2_i686.whl", hash = "sha256:e3e53c588164dc025b671c9df2462429d60357ea91af7e92e9d56c565a9f1b07", size = 10850074, upload-time = "2026-04-09T14:06:16.581Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/11/08/874da392558ce087a0f9b709dc6ec0d60cbc694c1c772dab8d5f31efe8cb/ruff-0.15.10-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:b0c52744cf9f143a393e284125d2576140b68264a93c6716464e129a3e9adb48", size = 11358051, upload-time = "2026-04-09T14:06:18.948Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e4/46/602938f030adfa043e67112b73821024dc79f3ab4df5474c25fa4c1d2d14/ruff-0.15.10-py3-none-win32.whl", hash = "sha256:d4272e87e801e9a27a2e8df7b21011c909d9ddd82f4f3281d269b6ba19789ca5", size = 10588964, upload-time = "2026-04-09T14:06:07.14Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/25/b6/261225b875d7a13b33a6d02508c39c28450b2041bb01d0f7f1a83d569512/ruff-0.15.10-py3-none-win_amd64.whl", hash = "sha256:28cb32d53203242d403d819fd6983152489b12e4a3ae44993543d6fe62ab42ed", size = 11745044, upload-time = "2026-04-09T14:05:39.473Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/58/ed/dea90a65b7d9e69888890fb14c90d7f51bf0c1e82ad800aeb0160e4bacfd/ruff-0.15.10-py3-none-win_arm64.whl", hash = "sha256:601d1610a9e1f1c2165a4f561eeaa2e2ea1e97f3287c5aa258d3dab8b57c6188", size = 11035607, upload-time = "2026-04-09T14:05:47.593Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/02/1e/6aca3427f751295ab011828e15e9bf452200ac74484f1db4be0197b8170b/ruff-0.15.11-py3-none-linux_armv6l.whl", hash = "sha256:e927cfff503135c558eb581a0c9792264aae9507904eb27809cdcff2f2c847b7", size = 10607943, upload-time = "2026-04-16T18:46:05.967Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e7/26/1341c262e74f36d4e84f3d6f4df0ac68cd53331a66bfc5080daa17c84c0b/ruff-0.15.11-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:7a1b5b2938d8f890b76084d4fa843604d787a912541eae85fd7e233398bbb73e", size = 10988592, upload-time = "2026-04-16T18:46:00.742Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/03/71/850b1d6ffa9564fbb6740429bad53df1094082fe515c8c1e74b6d8d05f18/ruff-0.15.11-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d4176f3d194afbdaee6e41b9ccb1a2c287dba8700047df474abfbe773825d1cb", size = 10338501, upload-time = "2026-04-16T18:46:03.723Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f2/11/cc1284d3e298c45a817a6aadb6c3e1d70b45c9b36d8d9cce3387b495a03a/ruff-0.15.11-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3b17c886fb88203ced3afe7f14e8d5ae96e9d2f4ccc0ee66aa19f2c2675a27e4", size = 10670693, upload-time = "2026-04-16T18:46:41.941Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ce/9e/f8288b034ab72b371513c13f9a41d9ba3effac54e24bfb467b007daee2ca/ruff-0.15.11-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:49fafa220220afe7758a487b048de4c8f9f767f37dfefad46b9dd06759d003eb", size = 10416177, upload-time = "2026-04-16T18:46:21.717Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/85/71/504d79abfd3d92532ba6bbe3d1c19fada03e494332a59e37c7c2dabae427/ruff-0.15.11-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2ab8427e74a00d93b8bda1307b1e60970d40f304af38bccb218e056c220120d", size = 11221886, upload-time = "2026-04-16T18:46:15.086Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/43/5a/947e6ab7a5ad603d65b474be15a4cbc6d29832db5d762cd142e4e3a74164/ruff-0.15.11-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:195072c0c8e1fc8f940652073df082e37a5d9cb43b4ab1e4d0566ab8977a13b7", size = 12075183, upload-time = "2026-04-16T18:46:07.944Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9f/a1/0b7bb6268775fdd3a0818aee8efd8f5b4e231d24dd4d528ced2534023182/ruff-0.15.11-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a3a0996d486af3920dec930a2e7daed4847dfc12649b537a9335585ada163e9e", size = 11516575, upload-time = "2026-04-16T18:46:31.687Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/30/c3/bb5168fc4d233cc06e95f482770d0f3c87945a0cd9f614b90ea8dc2f2833/ruff-0.15.11-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bef2cb556d509259f1fe440bb9cd33c756222cf0a7afe90d15edf0866702431", size = 11306537, upload-time = "2026-04-16T18:46:36.988Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e4/92/4cfae6441f3967317946f3b788136eecf093729b94d6561f963ed810c82e/ruff-0.15.11-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:030d921a836d7d4a12cf6e8d984a88b66094ccb0e0f17ddd55067c331191bf19", size = 11296813, upload-time = "2026-04-16T18:46:24.182Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/43/26/972784c5dde8313acde8ac71ba8ac65475b85db4a2352a76c9934361f9bc/ruff-0.15.11-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:0e783b599b4577788dbbb66b9addcef87e9a8832f4ce0c19e34bf55543a2f890", size = 10633136, upload-time = "2026-04-16T18:46:39.802Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/5b/53/3985a4f185020c2f367f2e08a103032e12564829742a1b417980ce1514a0/ruff-0.15.11-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:ae90592246625ba4a34349d68ec28d4400d75182b71baa196ddb9f82db025ef5", size = 10424701, upload-time = "2026-04-16T18:46:10.381Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d3/57/bf0dfb32241b56c83bb663a826133da4bf17f682ba8c096973065f6e6a68/ruff-0.15.11-py3-none-musllinux_1_2_i686.whl", hash = "sha256:1f111d62e3c983ed20e0ca2e800f8d77433a5b1161947df99a5c2a3fb60514f0", size = 10873887, upload-time = "2026-04-16T18:46:29.157Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/02/05/e48076b2a57dc33ee8c7a957296f97c744ca891a8ffb4ffb1aaa3b3f517d/ruff-0.15.11-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:06f483d6646f59eaffba9ae30956370d3a886625f511a3108994000480621d1c", size = 11404316, upload-time = "2026-04-16T18:46:19.462Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/88/27/0195d15fe7a897cbcba0904792c4b7c9fdd958456c3a17d2ea6093716a9a/ruff-0.15.11-py3-none-win32.whl", hash = "sha256:476a2aa56b7da0b73a3ee80b6b2f0e19cce544245479adde7baa65466664d5f3", size = 10655535, upload-time = "2026-04-16T18:46:12.47Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/3a/5e/c927b325bd4c1d3620211a4b96f47864633199feed60fa936025ab27e090/ruff-0.15.11-py3-none-win_amd64.whl", hash = "sha256:8b6756d88d7e234fb0c98c91511aae3cd519d5e3ed271cae31b20f39cb2a12a3", size = 11779692, upload-time = "2026-04-16T18:46:17.268Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/63/b6/aeadee5443e49baa2facd51131159fd6301cc4ccfc1541e4df7b021c37dd/ruff-0.15.11-py3-none-win_arm64.whl", hash = "sha256:063fed18cc1bbe0ee7393957284a6fe8b588c6a406a285af3ee3f46da2391ee4", size = 11032614, upload-time = "2026-04-16T18:46:34.487Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3336,7 +3338,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "selenium"
|
||||
version = "4.41.0"
|
||||
version = "4.43.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "certifi" },
|
||||
@@ -3346,22 +3348,22 @@ dependencies = [
|
||||
{ name = "urllib3", extra = ["socks"] },
|
||||
{ name = "websocket-client" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/04/7c/133d00d6d013a17d3f39199f27f1a780ec2e95d7b9aa997dc1b8ac2e62a7/selenium-4.41.0.tar.gz", hash = "sha256:003e971f805231ad63e671783a2b91a299355d10cefb9de964c36ff3819115aa", size = 937872, upload-time = "2026-02-20T03:42:06.216Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/09/6a/fe950b498a3c570ab538ad1c2b60f18863eecf077a865eea4459f3fa78a9/selenium-4.43.0.tar.gz", hash = "sha256:bada5c08a989f812728a4b5bea884d8e91894e939a441cc3a025201ce718581e", size = 967747, upload-time = "2026-04-10T06:47:03.149Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/a8/d6/e4160989ef6b272779af6f3e5c43c3ba9be6687bdc21c68c3fb220e555b3/selenium-4.41.0-py3-none-any.whl", hash = "sha256:b8ccde8d2e7642221ca64af184a92c19eee6accf2e27f20f30472f5efae18eb1", size = 9532858, upload-time = "2026-02-20T03:42:03.218Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/82/c7/0c55fbb0275fc368676ea50514ce7d7839d799a8b3ff8425f380186c7626/selenium-4.43.0-py3-none-any.whl", hash = "sha256:4f97639055dcfa9eadf8ccf549ba7b0e49c655d4e2bde19b9a44e916b754e769", size = 9573091, upload-time = "2026-04-10T06:47:01.134Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sentry-sdk"
|
||||
version = "2.57.0"
|
||||
version = "2.58.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "certifi" },
|
||||
{ name = "urllib3" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/4f/87/46c0406d8b5ddd026f73adaf5ab75ce144219c41a4830b52df4b9ab55f7f/sentry_sdk-2.57.0.tar.gz", hash = "sha256:4be8d1e71c32fb27f79c577a337ac8912137bba4bcbc64a4ec1da4d6d8dc5199", size = 435288, upload-time = "2026-03-31T09:39:29.264Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/26/b3/fb8291170d0e844173164709fc0fa0c221ed75a5da740c8746f2a83b4eb1/sentry_sdk-2.58.0.tar.gz", hash = "sha256:c1144d947352d54e5b7daa63596d9f848adf684989c06c4f5a659f0c85a18f6f", size = 438764, upload-time = "2026-04-13T17:23:26.265Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/c9/64/982e07b93219cb52e1cca5d272cb579e2f3eb001956c9e7a9a6d106c9473/sentry_sdk-2.57.0-py2.py3-none-any.whl", hash = "sha256:812c8bf5ff3d2f0e89c82f5ce80ab3a6423e102729c4706af7413fd1eb480585", size = 456489, upload-time = "2026-03-31T09:39:27.524Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/fa/eb/d875669993b762556ae8b2efd86219943b4c0864d22204d622a9aee3052b/sentry_sdk-2.58.0-py2.py3-none-any.whl", hash = "sha256:688d1c704ddecf382ea3326f21a67453d4caa95592d722b7c780a36a9d23109e", size = 460919, upload-time = "2026-04-13T17:23:24.675Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3545,7 +3547,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "twilio"
|
||||
version = "9.10.4"
|
||||
version = "9.10.5"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "aiohttp" },
|
||||
@@ -3553,9 +3555,9 @@ dependencies = [
|
||||
{ name = "pyjwt" },
|
||||
{ name = "requests" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d7/28/9ffb8f01fc014bf634f0731bd562fed6209bc54d4249c69acfe68cf70302/twilio-9.10.4.tar.gz", hash = "sha256:2125e0027288903e7e8954ae6d5b1b593a205c28b3d72fa3fdd0b5f25825de04", size = 1637481, upload-time = "2026-03-24T13:04:11.822Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/b5/97/c439bc2c058f8a24edd732f5cc82adedd8794bcc2da0836c2eff1e2dbe91/twilio-9.10.5.tar.gz", hash = "sha256:d9f93b9280349ee7b52e7f17a0600fd7bfd0f7ff88eb00c40270164bc058743f", size = 1641690, upload-time = "2026-04-14T09:52:09.392Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/bc/3c/3296ee9f141b83623ff2c6c4d22093f7d2a8ea7455f98f705ee5f969bcd7/twilio-9.10.4-py2.py3-none-any.whl", hash = "sha256:5e8414a88c009f40b2ab2a1f00232f5f459f724c7b4bdf25a935c7d7b297a8a3", size = 2279546, upload-time = "2026-03-24T13:04:10.383Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4a/97/4fdde5e54fcbb789aa1a70c371f2f33d7eb1e58e8a6131fdbd8a98490976/twilio-9.10.5-py2.py3-none-any.whl", hash = "sha256:7972db54496fbf501b238f34d1f717f80ff22720313dc706632787aad5934997", size = 2284944, upload-time = "2026-04-14T09:52:07.333Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
457
web/package-lock.json
generated
457
web/package-lock.json
generated
@@ -21,7 +21,7 @@
|
||||
"@codemirror/theme-one-dark": "^6.1.3",
|
||||
"@eslint/js": "^9.39.3",
|
||||
"@floating-ui/dom": "^1.7.6",
|
||||
"@formatjs/intl-listformat": "^8.3.1",
|
||||
"@formatjs/intl-listformat": "^8.3.2",
|
||||
"@fortawesome/fontawesome-free": "^7.2.0",
|
||||
"@goauthentik/api": "0.0.0",
|
||||
"@goauthentik/core": "^1.0.0",
|
||||
@@ -40,10 +40,10 @@
|
||||
"@open-wc/lit-helpers": "^0.7.0",
|
||||
"@openlayers-elements/core": "^0.4.0",
|
||||
"@openlayers-elements/maps": "^0.4.0",
|
||||
"@patternfly/elements": "^4.3.1",
|
||||
"@patternfly/elements": "^4.4.0",
|
||||
"@patternfly/patternfly": "^4.224.2",
|
||||
"@playwright/test": "^1.59.1",
|
||||
"@sentry/browser": "^10.47.0",
|
||||
"@sentry/browser": "^10.49.0",
|
||||
"@storybook/addon-docs": "^10.3.5",
|
||||
"@storybook/addon-links": "^10.3.5",
|
||||
"@storybook/web-components": "^10.3.5",
|
||||
@@ -51,7 +51,7 @@
|
||||
"@types/codemirror": "^5.60.17",
|
||||
"@types/grecaptcha": "^3.0.9",
|
||||
"@types/guacamole-common-js": "^1.5.5",
|
||||
"@types/node": "^25.5.2",
|
||||
"@types/node": "^25.6.0",
|
||||
"@types/react": "^19.2.14",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@typescript-eslint/eslint-plugin": "^8.57.2",
|
||||
@@ -75,10 +75,10 @@
|
||||
"eslint-plugin-lit": "^2.2.1",
|
||||
"eslint-plugin-wc": "^3.1.0",
|
||||
"fuse.js": "^7.3.0",
|
||||
"globals": "^17.4.0",
|
||||
"globals": "^17.5.0",
|
||||
"guacamole-common-js": "^1.5.0",
|
||||
"hastscript": "^9.0.1",
|
||||
"knip": "^6.3.1",
|
||||
"knip": "^6.4.1",
|
||||
"lex": "^2025.11.0",
|
||||
"lit": "^3.3.2",
|
||||
"lit-analyzer": "^2.0.3",
|
||||
@@ -91,7 +91,7 @@
|
||||
"pino": "^10.3.1",
|
||||
"pino-pretty": "^13.1.2",
|
||||
"playwright": "^1.58.2",
|
||||
"prettier": "^3.8.2",
|
||||
"prettier": "^3.8.3",
|
||||
"prettier-plugin-packagejson": "^3.0.2",
|
||||
"pseudolocale": "^2.2.0",
|
||||
"rapidoc": "^9.3.8",
|
||||
@@ -111,7 +111,7 @@
|
||||
"ts-pattern": "^5.9.0",
|
||||
"turnstile-types": "^1.2.3",
|
||||
"type-fest": "^5.5.0",
|
||||
"typescript": "^6.0.2",
|
||||
"typescript": "^6.0.3",
|
||||
"typescript-eslint": "^8.57.2",
|
||||
"unist-util-visit": "^5.1.0",
|
||||
"vite": "^8.0.8",
|
||||
@@ -131,7 +131,7 @@
|
||||
"@rollup/rollup-darwin-arm64": "^4.57.1",
|
||||
"@rollup/rollup-linux-arm64-gnu": "^4.57.1",
|
||||
"@rollup/rollup-linux-x64-gnu": "^4.57.1",
|
||||
"chromedriver": "^147.0.2"
|
||||
"chromedriver": "^147.0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@adobe/css-tools": {
|
||||
@@ -1304,46 +1304,28 @@
|
||||
"integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@formatjs/bigdecimal": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/bigdecimal/-/bigdecimal-0.2.0.tgz",
|
||||
"integrity": "sha512-GeaxHZbUoYvHL9tC5eltHLs+1zU70aPw0s7LwqgktIzF5oMhNY4o4deEtusJMsq7WFJF3Ye2zQEzdG8beVk73w==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@formatjs/ecma402-abstract": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-3.2.0.tgz",
|
||||
"integrity": "sha512-dHnqHgBo6GXYGRsepaE1wmsC2etaivOWd5VaJstZd+HI2zR3DCUjbDVZRtoPGkkXZmyHvBwrdEUuqfvzhF/DtQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@formatjs/bigdecimal": "0.2.0",
|
||||
"@formatjs/fast-memoize": "3.1.1",
|
||||
"@formatjs/intl-localematcher": "0.8.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@formatjs/fast-memoize": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-3.1.1.tgz",
|
||||
"integrity": "sha512-CbNbf+tlJn1baRnPkNePnBqTLxGliG6DDgNa/UtV66abwIjwsliPMOt0172tzxABYzSuxZBZfcp//qI8AvBWPg==",
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-3.1.2.tgz",
|
||||
"integrity": "sha512-vPnriihkfK0lzoQGaXq+qXH23VsYyansRTkTgo2aTG0k1NjLFyZimFVdfj4C9JkSE5dm7CEngcQ5TTc1yAyBfQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@formatjs/intl-listformat": {
|
||||
"version": "8.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/intl-listformat/-/intl-listformat-8.3.1.tgz",
|
||||
"integrity": "sha512-82pPPyPOzkFMBbUmuseMwckFtpT+meZSxZSaxyD/3wRo5DZEq08hBUe1uhzNmukI8hwJFH5mIMBwSIAuse0RDQ==",
|
||||
"version": "8.3.2",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/intl-listformat/-/intl-listformat-8.3.2.tgz",
|
||||
"integrity": "sha512-PH8V1YVSm+AcrQ1D9Th5wxWo74vDs1V1rRGz9PCFm1HTBtZLVMN3P/+tDcpizQBvvdGNwUqHBOdxN5ZZtlq2bQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@formatjs/ecma402-abstract": "3.2.0",
|
||||
"@formatjs/intl-localematcher": "0.8.2"
|
||||
"@formatjs/intl-localematcher": "0.8.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@formatjs/intl-localematcher": {
|
||||
"version": "0.8.2",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.8.2.tgz",
|
||||
"integrity": "sha512-q05KMYGJLyqFNFtIb8NhWLF5X3aK/k0wYt7dnRFuy6aLQL+vUwQ1cg5cO4qawEiINybeCPXAWlprY2mSBjSXAQ==",
|
||||
"version": "0.8.3",
|
||||
"resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.8.3.tgz",
|
||||
"integrity": "sha512-pHUjWb9NuhnMs8+PxQdzBtZRFJHlGhrURGAbm6Ltwl82BFajeuiIR3jblSa7ia3r62rXe/0YtVpUG3xWr5bFCA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@formatjs/fast-memoize": "3.1.1"
|
||||
"@formatjs/fast-memoize": "3.1.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@fortawesome/fontawesome-free": {
|
||||
@@ -2843,14 +2825,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@patternfly/elements": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@patternfly/elements/-/elements-4.3.1.tgz",
|
||||
"integrity": "sha512-MRVwxcam+ACyy+0Xy5igPr+LcSVRbX422NGPE4I7WRuwAEhRBA3BayyLi8mNVKXpLLZbk8EtJ17kM30PcMziMw==",
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@patternfly/elements/-/elements-4.4.0.tgz",
|
||||
"integrity": "sha512-ShLDYMYEWdhmYDd1XUVj41IfwEmWEXXvHEscVTuga1M9KWMXRJQgf+9jio/2Od5dNh4PAshyH0f19fHFU9EAsA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lit/context": "^1.1.6",
|
||||
"@patternfly/icons": "^1.0.3",
|
||||
"@patternfly/pfe-core": "^5.0.6",
|
||||
"@patternfly/pfe-core": "^5.0.8",
|
||||
"lit": "^3.3.2",
|
||||
"tslib": "^2.8.1"
|
||||
}
|
||||
@@ -2868,9 +2850,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@patternfly/pfe-core": {
|
||||
"version": "5.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@patternfly/pfe-core/-/pfe-core-5.0.7.tgz",
|
||||
"integrity": "sha512-cOIyW2k+l/H2592BQ00Bc0kfJClBCRiDDmeEYvhumHAKzgJiQIsVQ81GpNpOgtlibV5KTn3FxrSMadGEpEl/fg==",
|
||||
"version": "5.0.8",
|
||||
"resolved": "https://registry.npmjs.org/@patternfly/pfe-core/-/pfe-core-5.0.8.tgz",
|
||||
"integrity": "sha512-gH+gC8+lwLQ5OxcQsmJOSHNHqQgoa+VboM4LlI63N+jnDPmB7E9EZ7VzJc8C4qTPbCIfQp+o1ObjmKyNw/b9TA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lit/context": "^1.1.6",
|
||||
@@ -3609,75 +3591,75 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@sentry-internal/browser-utils": {
|
||||
"version": "10.47.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-10.47.0.tgz",
|
||||
"integrity": "sha512-bVFRAeJWMBcBCvJKIFCMJ1/yQToL4vPGqfmlnDZeypcxkqUDKQ/Y3ziLHXoDL2sx0lagcgU2vH1QhCQ67Aujjw==",
|
||||
"version": "10.49.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-10.49.0.tgz",
|
||||
"integrity": "sha512-n0QRx0Ysx6mPfIydTkz7VP0FmwM+/EqMZiRqdsU3aTYsngE9GmEDV0OL1bAy6a8N/C1xf9vntkuAtj6N/8Z51w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry/core": "10.47.0"
|
||||
"@sentry/core": "10.49.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry-internal/feedback": {
|
||||
"version": "10.47.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-10.47.0.tgz",
|
||||
"integrity": "sha512-pdvMmi4dQpX5S/vAAzrhHPIw3T3HjUgDNgUiCBrlp7N9/6zGO2gNPhUnNekP+CjgI/z0rvf49RLqlDenpNrMOg==",
|
||||
"version": "10.49.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-10.49.0.tgz",
|
||||
"integrity": "sha512-JNsUBGv0faCFE7MeZUH99Y9lU9qq3LBALbLxpE1x7ngNrQnVYRlcFgdqaD/btNBKr8awjYL8gmcSkHBWskGqLQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry/core": "10.47.0"
|
||||
"@sentry/core": "10.49.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry-internal/replay": {
|
||||
"version": "10.47.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-10.47.0.tgz",
|
||||
"integrity": "sha512-ScdovxP7hJxgMt70+7hFvwT02GIaIUAxdEM/YPsayZBeCoAukPW8WiwztJfoKtsfPyKJ5A6f0H3PIxTPcA9Row==",
|
||||
"version": "10.49.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-10.49.0.tgz",
|
||||
"integrity": "sha512-IEy4lwHVMiRE3JAcn+kFKjsTgalDOCSTf20SoFd+nkt6rN/k1RDyr4xpdfF//Kj3UdeTmbuibYjK5H/FLhhnGg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry-internal/browser-utils": "10.47.0",
|
||||
"@sentry/core": "10.47.0"
|
||||
"@sentry-internal/browser-utils": "10.49.0",
|
||||
"@sentry/core": "10.49.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry-internal/replay-canvas": {
|
||||
"version": "10.47.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-10.47.0.tgz",
|
||||
"integrity": "sha512-A5OY8friSe6g8WAK4L8IeOPiEd9D3Ps40DzRH5j2f6SUja0t90mKMvHRcRf8zq0d4BkdB+JM7tjOkwxpuv8heA==",
|
||||
"version": "10.49.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-10.49.0.tgz",
|
||||
"integrity": "sha512-7D/NrgH1Qwx5trDYaaTSSJmCb1yVQQLqFG4G/S9x2ltzl9876lSGJL8UeW8ReNQgF3CDAcwbmm/9aXaVSBUNZA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry-internal/replay": "10.47.0",
|
||||
"@sentry/core": "10.47.0"
|
||||
"@sentry-internal/replay": "10.49.0",
|
||||
"@sentry/core": "10.49.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/browser": {
|
||||
"version": "10.47.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-10.47.0.tgz",
|
||||
"integrity": "sha512-rC0agZdxKA5XWfL4VwPOr/rJMogXDqZgnVzr93YWpFn9DMZT/7LzxSJVPIJwRUjx3bFEby3PcTa3YaX7pxm1AA==",
|
||||
"version": "10.49.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-10.49.0.tgz",
|
||||
"integrity": "sha512-bGCHc+wK2Dx67YoSbmtlt04alqWfQ+dasD/GVipVOq50gvw/BBIDHTEWRJEjACl+LrvszeY54V+24p8z4IgysA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@sentry-internal/browser-utils": "10.47.0",
|
||||
"@sentry-internal/feedback": "10.47.0",
|
||||
"@sentry-internal/replay": "10.47.0",
|
||||
"@sentry-internal/replay-canvas": "10.47.0",
|
||||
"@sentry/core": "10.47.0"
|
||||
"@sentry-internal/browser-utils": "10.49.0",
|
||||
"@sentry-internal/feedback": "10.49.0",
|
||||
"@sentry-internal/replay": "10.49.0",
|
||||
"@sentry-internal/replay-canvas": "10.49.0",
|
||||
"@sentry/core": "10.49.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@sentry/core": {
|
||||
"version": "10.47.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.47.0.tgz",
|
||||
"integrity": "sha512-nsYRAx3EWezDut+Zl+UwwP07thh9uY7CfSAi2whTdcJl5hu1nSp2z8bba7Vq/MGbNLnazkd3A+GITBEML924JA==",
|
||||
"version": "10.49.0",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-10.49.0.tgz",
|
||||
"integrity": "sha512-UaFeum3LUM1mB0d67jvKnqId1yWQjyqmaDV6kWngG03x+jqXb08tJdGpSoxjXZe13jFBbiBL/wKDDYIK7rCK4g==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
@@ -4572,9 +4554,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core": {
|
||||
"version": "1.15.24",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core/-/core-1.15.24.tgz",
|
||||
"integrity": "sha512-5Hj8aNasue7yusUt8LGCUe/AjM7RMAce8ZoyDyiFwx7Al+GbYKL+yE7g4sJk8vEr1dKIkTRARkNIJENc4CjkBQ==",
|
||||
"version": "1.15.30",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core/-/core-1.15.30.tgz",
|
||||
"integrity": "sha512-R8VQbQY1BZcbIF2p3gjlTCwAQzx1A194ugWfwld5y+WgVVWqVKm7eURGGOVbQVubgKWzidP2agomBbg96rZilQ==",
|
||||
"hasInstallScript": true,
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
@@ -4589,18 +4571,18 @@
|
||||
"url": "https://opencollective.com/swc"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@swc/core-darwin-arm64": "1.15.24",
|
||||
"@swc/core-darwin-x64": "1.15.24",
|
||||
"@swc/core-linux-arm-gnueabihf": "1.15.24",
|
||||
"@swc/core-linux-arm64-gnu": "1.15.24",
|
||||
"@swc/core-linux-arm64-musl": "1.15.24",
|
||||
"@swc/core-linux-ppc64-gnu": "1.15.24",
|
||||
"@swc/core-linux-s390x-gnu": "1.15.24",
|
||||
"@swc/core-linux-x64-gnu": "1.15.24",
|
||||
"@swc/core-linux-x64-musl": "1.15.24",
|
||||
"@swc/core-win32-arm64-msvc": "1.15.24",
|
||||
"@swc/core-win32-ia32-msvc": "1.15.24",
|
||||
"@swc/core-win32-x64-msvc": "1.15.24"
|
||||
"@swc/core-darwin-arm64": "1.15.30",
|
||||
"@swc/core-darwin-x64": "1.15.30",
|
||||
"@swc/core-linux-arm-gnueabihf": "1.15.30",
|
||||
"@swc/core-linux-arm64-gnu": "1.15.30",
|
||||
"@swc/core-linux-arm64-musl": "1.15.30",
|
||||
"@swc/core-linux-ppc64-gnu": "1.15.30",
|
||||
"@swc/core-linux-s390x-gnu": "1.15.30",
|
||||
"@swc/core-linux-x64-gnu": "1.15.30",
|
||||
"@swc/core-linux-x64-musl": "1.15.30",
|
||||
"@swc/core-win32-arm64-msvc": "1.15.30",
|
||||
"@swc/core-win32-ia32-msvc": "1.15.30",
|
||||
"@swc/core-win32-x64-msvc": "1.15.30"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@swc/helpers": ">=0.5.17"
|
||||
@@ -4612,9 +4594,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-darwin-arm64": {
|
||||
"version": "1.15.24",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.15.24.tgz",
|
||||
"integrity": "sha512-uM5ZGfFXjtvtJ+fe448PVBEbn/CSxS3UAyLj3O9xOqKIWy3S6hPTXSPbszxkSsGDYKi+YFhzAsR4r/eXLxEQ0g==",
|
||||
"version": "1.15.30",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.15.30.tgz",
|
||||
"integrity": "sha512-VvpP+vq08HmGYewMWvrdsxh9s2lthz/808zXm8Yu5kaqeR8Yia2b0eYXleHQ3VAjoStUDk6LzTheBW9KXYQdMA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -4628,9 +4610,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-darwin-x64": {
|
||||
"version": "1.15.24",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.15.24.tgz",
|
||||
"integrity": "sha512-fMIb/Zfn929pw25VMBhV7Ji2Dl+lCWtUPNdYJQYOke+00E5fcQ9ynxtP8+qhUo/HZc+mYQb1gJxwHM9vty+lXg==",
|
||||
"version": "1.15.30",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.15.30.tgz",
|
||||
"integrity": "sha512-WiJA0hiZI3nwQAO6mu5RqigtWGDtth4Hiq6rbZxAaQyhIcqKIg5IoMRc1Y071lrNJn29eEDMC86Rq58xgUxlDg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -4644,9 +4626,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-arm-gnueabihf": {
|
||||
"version": "1.15.24",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.15.24.tgz",
|
||||
"integrity": "sha512-vOkjsyjjxnoYx3hMEWcGxQrMgnNrRm6WAegBXrN8foHtDAR+zpdhpGF5a4lj1bNPgXAvmysjui8cM1ov/Clkaw==",
|
||||
"version": "1.15.30",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.15.30.tgz",
|
||||
"integrity": "sha512-YANuFUo48kIT6plJgCD0keae9HFXfjxsbvsgevqc0hr/07X/p7sAWTFOGYEc2SXcASaK7UvuQqzlbW8pr7R79g==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@@ -4660,9 +4642,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-arm64-gnu": {
|
||||
"version": "1.15.24",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.15.24.tgz",
|
||||
"integrity": "sha512-h/oNu+upkXJ6Cicnq7YGVj9PkdfarLCdQa8l/FlHYvfv8CEiMaeeTnpLU7gSBH/rGxosM6Qkfa/J9mThGF9CLA==",
|
||||
"version": "1.15.30",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.15.30.tgz",
|
||||
"integrity": "sha512-VndG8jaR4ugY6u+iVOT0Q+d2fZd7sLgjPgN8W/Le+3EbZKl+cRfFxV7Eoz4gfLqhmneZPdcIzf9T3LkgkmqNLg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -4676,9 +4658,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-arm64-musl": {
|
||||
"version": "1.15.24",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.15.24.tgz",
|
||||
"integrity": "sha512-ZpF/pRe1guk6sKzQI9D1jAORtjTdNlyeXn9GDz8ophof/w2WhojRblvSDJaGe7rJjcPN8AaOkhwdRUh7q8oYIg==",
|
||||
"version": "1.15.30",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.15.30.tgz",
|
||||
"integrity": "sha512-1SYGs2l0Yyyi0pR/P/NKz/x0kqxkoiw+BXeJjLUdecSk/KasncWlJrc6hOvFSgKHOBrzgM5jwuluKtlT8dnrcA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -4692,9 +4674,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-ppc64-gnu": {
|
||||
"version": "1.15.24",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-ppc64-gnu/-/core-linux-ppc64-gnu-1.15.24.tgz",
|
||||
"integrity": "sha512-QZEsZfisHTSJlmyChgDFNmKPb3W6Lhbfo/O76HhIngfEdnQNmukS38/VSe1feho+xkV5A5hETyCbx3sALBZKAQ==",
|
||||
"version": "1.15.30",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-ppc64-gnu/-/core-linux-ppc64-gnu-1.15.30.tgz",
|
||||
"integrity": "sha512-TXREtiXeRhbfDFbmhnkIsXpKfzbfT73YkV2ZF6w0sfxgjC5zI2ZAbaCOq25qxvegofj2K93DtOpm9RLaBgqR2g==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
@@ -4708,9 +4690,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-s390x-gnu": {
|
||||
"version": "1.15.24",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-s390x-gnu/-/core-linux-s390x-gnu-1.15.24.tgz",
|
||||
"integrity": "sha512-DLdJKVsJgglqQrJBuoUYNmzm3leI7kUZhLbZGHv42onfKsGf6JDS3+bzCUQfte/XOqDjh/tmmn1DR/CF/tCJFw==",
|
||||
"version": "1.15.30",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-s390x-gnu/-/core-linux-s390x-gnu-1.15.30.tgz",
|
||||
"integrity": "sha512-DCR2YYeyd6DQE4OuDhImouuNcjXEiEdnn1Y0DyGteugPEDvVuvYk8Xddi+4o2SgWH6jiW8/I+3emZvbep1NC+g==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
@@ -4724,9 +4706,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-x64-gnu": {
|
||||
"version": "1.15.24",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.15.24.tgz",
|
||||
"integrity": "sha512-IpLYfposPA/XLxYOKpRfeccl1p5dDa3+okZDHHTchBkXEaVCnq5MADPmIWwIYj1tudt7hORsEHccG5no6IUQRw==",
|
||||
"version": "1.15.30",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.15.30.tgz",
|
||||
"integrity": "sha512-5Pizw3NgfOJ5BJOBK8TIRa59xFW2avESTOBDPTAYwZYa1JNDs+KMF9lUfjJiJLM5HiMs/wPheA9eiT0q9m2AoA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -4740,9 +4722,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-x64-musl": {
|
||||
"version": "1.15.24",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.15.24.tgz",
|
||||
"integrity": "sha512-JHy3fMSc0t/EPWgo74+OK5TGr51aElnzqfUPaiRf2qJ/BfX5CUCfMiWVBuhI7qmVMBnk1jTRnL/xZnOSHDPLYg==",
|
||||
"version": "1.15.30",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.15.30.tgz",
|
||||
"integrity": "sha512-qyqydP/wyH8alcIP4a2hnGSjHLJjm9H7yDFup+CPy9oTahFgLLwnNcv5UHXqO2Qs3AIND+cls5f/Bb6hqpxdgA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -4756,9 +4738,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-win32-arm64-msvc": {
|
||||
"version": "1.15.24",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.15.24.tgz",
|
||||
"integrity": "sha512-Txj+qUH1z2bUd1P3JvwByfjKFti3cptlAxhWgmunBUUxy/IW3CXLZ6l6Gk4liANadKkU71nIU1X30Z5vpMT3BA==",
|
||||
"version": "1.15.30",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.15.30.tgz",
|
||||
"integrity": "sha512-CaQENgDHVGOg1mSF5sQVgvfFHG9kjMor2rkLMLeLOkfZYNj13ppnJ9+lfaBZLZUMMbnlGQnavCJb8PVBUOso7Q==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -4772,9 +4754,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-win32-ia32-msvc": {
|
||||
"version": "1.15.24",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.15.24.tgz",
|
||||
"integrity": "sha512-15D/nl3XwrhFpMv+MADFOiVwv3FvH9j8c6Rf8EXBT3Q5LoMh8YnDnSgPYqw1JzPnksvsBX6QPXLiPqmcR/Z4qQ==",
|
||||
"version": "1.15.30",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.15.30.tgz",
|
||||
"integrity": "sha512-30VdLeGk6fugiUs/kUdJ/pAg7z/zpvVbR11RH60jZ0Z42WIeIniYx0rLEWN7h/pKJ3CopqsQ3RsogCAkRKiA2g==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
@@ -4788,9 +4770,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-win32-x64-msvc": {
|
||||
"version": "1.15.24",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.15.24.tgz",
|
||||
"integrity": "sha512-PR0PlTlPra2JbaDphrOAzm6s0v9rA0F17YzB+XbWD95B4g2cWcZY9LAeTa4xll70VLw9Jr7xBrlohqlQmelMFQ==",
|
||||
"version": "1.15.30",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.15.30.tgz",
|
||||
"integrity": "sha512-4iObHPR+Q4oDY110EF5SF5eIaaVJNpMdG9C0q3Q92BsJ5y467uHz7sYQhP60WYlLFsLQ1el2YrIPUItUAQGOKg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -4906,13 +4888,6 @@
|
||||
"integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@tootallnate/quickjs-emscripten": {
|
||||
"version": "0.23.0",
|
||||
"resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz",
|
||||
"integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==",
|
||||
"license": "MIT",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/@tybys/wasm-util": {
|
||||
"version": "0.10.1",
|
||||
"resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz",
|
||||
@@ -5299,12 +5274,12 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "25.5.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.5.2.tgz",
|
||||
"integrity": "sha512-tO4ZIRKNC+MDWV4qKVZe3Ql/woTnmHDr5JD8UI5hn2pwBrHEwOEMZK7WlNb5RKB6EoJ02gwmQS9OrjuFnZYdpg==",
|
||||
"version": "25.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.6.0.tgz",
|
||||
"integrity": "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~7.18.0"
|
||||
"undici-types": "~7.19.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/ramda": {
|
||||
@@ -6176,9 +6151,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@xmldom/xmldom": {
|
||||
"version": "0.8.12",
|
||||
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.12.tgz",
|
||||
"integrity": "sha512-9k/gHF6n/pAi/9tqr3m3aqkuiNosYTurLLUtc7xQ9sxB/wm7WPygCv8GYa6mS0fLJEHhqMC1ATYhz++U/lRHqg==",
|
||||
"version": "0.8.13",
|
||||
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.13.tgz",
|
||||
"integrity": "sha512-KRYzxepc14G/CEpEGc3Yn+JKaAeT63smlDr+vjB8jRfgTBBI9wRj/nkQEO+ucV8p8I9bfKLWp37uHgFrbntPvw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
@@ -6206,13 +6181,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/agent-base": {
|
||||
"version": "7.1.4",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz",
|
||||
"integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==",
|
||||
"version": "9.0.0",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-9.0.0.tgz",
|
||||
"integrity": "sha512-TQf59BsZnytt8GdJKLPfUZ54g/iaUL2OWDSFCCvMOhsHduDQxO8xC4PNeyIkVcA5KwL2phPSv0douC0fgWzmnA==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
"node": ">= 20"
|
||||
}
|
||||
},
|
||||
"node_modules/ajv": {
|
||||
@@ -6640,9 +6615,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/basic-ftp": {
|
||||
"version": "5.2.2",
|
||||
"resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.2.2.tgz",
|
||||
"integrity": "sha512-1tDrzKsdCg70WGvbFss/ulVAxupNauGnOlgpyjKzeQxzyllBLS0CGLV7tjIXTK3ZQA9/FBEm9qyFFN1bciA6pw==",
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.3.0.tgz",
|
||||
"integrity": "sha512-5K9eNNn7ywHPsYnFwjKgYH8Hf8B5emh7JKcPaVjjrMJFQQwGpwowEnZNEtHs7DfR7hCZsmaK3VA4HUK0YarT+w==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
@@ -7258,18 +7233,18 @@
|
||||
}
|
||||
},
|
||||
"node_modules/chromedriver": {
|
||||
"version": "147.0.2",
|
||||
"resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-147.0.2.tgz",
|
||||
"integrity": "sha512-CgbtfPbdE3kse2gJdVVjvpRZtPV6pooaIVTJKdCj8LaDIMJvco57t2lXJcQObjfg2bhGN7RiGOk0iKpY2vLgLQ==",
|
||||
"version": "147.0.4",
|
||||
"resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-147.0.4.tgz",
|
||||
"integrity": "sha512-eRNbfkoTvAsSfFODM4QVhs3cXB/B4/nFHeI6+ycuKan5e3bJrq8njuLTBHHOLbL0dggxEpMHLiczJUQa+Gw3JA==",
|
||||
"hasInstallScript": true,
|
||||
"license": "Apache-2.0",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"@testim/chrome-version": "^1.1.4",
|
||||
"axios": "^1.13.5",
|
||||
"axios": "^1.15.0",
|
||||
"compare-versions": "^6.1.0",
|
||||
"extract-zip": "^2.0.1",
|
||||
"proxy-agent": "^6.5.0",
|
||||
"proxy-agent": "^8.0.1",
|
||||
"proxy-from-env": "^2.0.0",
|
||||
"tcp-port-used": "^1.0.2"
|
||||
},
|
||||
@@ -8014,13 +7989,13 @@
|
||||
}
|
||||
},
|
||||
"node_modules/data-uri-to-buffer": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz",
|
||||
"integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==",
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-8.0.0.tgz",
|
||||
"integrity": "sha512-6UHfyCux51b8PTGDgveqtz1tvphBku5DrMKKJbFAZAJOI2zsjDpDoYE1+QGj7FOMS4BdTFNJsJiR3zEB0xH0yQ==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
"node": ">= 20"
|
||||
}
|
||||
},
|
||||
"node_modules/data-view-buffer": {
|
||||
@@ -8273,9 +8248,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/degenerator": {
|
||||
"version": "5.0.1",
|
||||
"resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz",
|
||||
"integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==",
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/degenerator/-/degenerator-7.0.1.tgz",
|
||||
"integrity": "sha512-ABErK0IefDSyHjlPH7WUEenIAX2rPPnrDcDM+TS3z3+zu9TfyKKi07BQM+8rmxpdE2y1v5fjjdoAS/x4D2U60w==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
@@ -8284,7 +8259,10 @@
|
||||
"esprima": "^4.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
"node": ">= 20"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"quickjs-wasi": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/delaunator": {
|
||||
@@ -10032,18 +10010,18 @@
|
||||
}
|
||||
},
|
||||
"node_modules/get-uri": {
|
||||
"version": "6.0.5",
|
||||
"resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.5.tgz",
|
||||
"integrity": "sha512-b1O07XYq8eRuVzBNgJLstU6FYc1tS6wnMtF1I1D9lE8LxZSOGZ7LhxN54yPP6mGw5f2CkXY2BQUL9Fx41qvcIg==",
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/get-uri/-/get-uri-8.0.0.tgz",
|
||||
"integrity": "sha512-CqtZlMKvfJeY0Zxv8wazDwXmSKmnMnsmNy8j8+wudi8EyG/pMUB1NqHc+Tv1QaNtpYsK9nOYjb7r7Ufu32RPSw==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"basic-ftp": "^5.0.2",
|
||||
"data-uri-to-buffer": "^6.0.2",
|
||||
"basic-ftp": "^5.2.0",
|
||||
"data-uri-to-buffer": "8.0.0",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
"node": ">= 20"
|
||||
}
|
||||
},
|
||||
"node_modules/git-hooks-list": {
|
||||
@@ -10068,9 +10046,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.5.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-17.5.0.tgz",
|
||||
"integrity": "sha512-qoV+HK2yFl/366t2/Cb3+xxPUo5BuMynomoDmiaZBIdbs+0pYbjfZU+twLhGKp4uCZ/+NbtpVepH5bGCxRyy2g==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
@@ -10560,17 +10538,17 @@
|
||||
"license": "BSD-2-Clause"
|
||||
},
|
||||
"node_modules/http-proxy-agent": {
|
||||
"version": "7.0.2",
|
||||
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz",
|
||||
"integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==",
|
||||
"version": "9.0.0",
|
||||
"resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-9.0.0.tgz",
|
||||
"integrity": "sha512-FcF8VhXYLQcxWCnt/cCpT2apKsRDUGeVEeMqGu4HSTu29U8Yw0TLOjdYIlDsYk3IkUh+taX4IDWpPcCqKDhCjA==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"agent-base": "^7.1.0",
|
||||
"agent-base": "9.0.0",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
"node": ">= 20"
|
||||
}
|
||||
},
|
||||
"node_modules/http2-wrapper": {
|
||||
@@ -10599,17 +10577,17 @@
|
||||
}
|
||||
},
|
||||
"node_modules/https-proxy-agent": {
|
||||
"version": "7.0.6",
|
||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
|
||||
"integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
|
||||
"version": "9.0.0",
|
||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-9.0.0.tgz",
|
||||
"integrity": "sha512-/MVmHp58WkOypgFhCLk4fzpPcFQvTJ/e6LBI7irpIO2HfxUbpmYoHF+KzipzJpxxzJu7aJNWQ0xojJ/dzV2G5g==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"agent-base": "^7.1.2",
|
||||
"debug": "4"
|
||||
"agent-base": "9.0.0",
|
||||
"debug": "^4.3.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
"node": ">= 20"
|
||||
}
|
||||
},
|
||||
"node_modules/human-signals": {
|
||||
@@ -11583,9 +11561,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/knip": {
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/knip/-/knip-6.3.1.tgz",
|
||||
"integrity": "sha512-22kLJloVcOVOAudCxlFOC0ICAMme7dKsS7pVTEnrmyKGpswb8ieznvAiSKUeFVDJhb01ect6dkDc1Ha1g1sPpg==",
|
||||
"version": "6.4.1",
|
||||
"resolved": "https://registry.npmjs.org/knip/-/knip-6.4.1.tgz",
|
||||
"integrity": "sha512-Ry+ywmDFSZvKp/jx7LxMgsZWRTs931alV84e60lh0Stf6kSRYqSIUTkviyyDFRcSO3yY1Kpbi83OirN+4lA2Xw==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "github",
|
||||
@@ -13674,9 +13652,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/netmask": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz",
|
||||
"integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==",
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/netmask/-/netmask-2.1.1.tgz",
|
||||
"integrity": "sha512-eonl3sLUha+S1GzTPxychyhnUzKyeQkZ7jLjKrBagJgPla13F+uQ71HgpFefyHgqrjEbCPkDArxYsjY8/+gLKA==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"engines": {
|
||||
@@ -14416,37 +14394,40 @@
|
||||
}
|
||||
},
|
||||
"node_modules/pac-proxy-agent": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz",
|
||||
"integrity": "sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==",
|
||||
"version": "9.0.1",
|
||||
"resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-9.0.1.tgz",
|
||||
"integrity": "sha512-3ZOSpLboOlpW4yp8Cuv21KlTULRqyJ5Uuad3wXpSKFrxdNgcHEyoa22GRaZ2UlgCVuR6z+5BiavtYVvbajL/Yw==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"@tootallnate/quickjs-emscripten": "^0.23.0",
|
||||
"agent-base": "^7.1.2",
|
||||
"agent-base": "9.0.0",
|
||||
"debug": "^4.3.4",
|
||||
"get-uri": "^6.0.1",
|
||||
"http-proxy-agent": "^7.0.0",
|
||||
"https-proxy-agent": "^7.0.6",
|
||||
"pac-resolver": "^7.0.1",
|
||||
"socks-proxy-agent": "^8.0.5"
|
||||
"get-uri": "8.0.0",
|
||||
"http-proxy-agent": "9.0.0",
|
||||
"https-proxy-agent": "9.0.0",
|
||||
"pac-resolver": "9.0.1",
|
||||
"quickjs-wasi": "^2.2.0",
|
||||
"socks-proxy-agent": "10.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
"node": ">= 20"
|
||||
}
|
||||
},
|
||||
"node_modules/pac-resolver": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz",
|
||||
"integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==",
|
||||
"version": "9.0.1",
|
||||
"resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-9.0.1.tgz",
|
||||
"integrity": "sha512-lJbS008tmkj08VhoM8Hzuv/VE5tK9MS0OIQ/7+s0lIF+BYhiQWFYzkSpML7lXs9iBu2jfmzBTLzhe9n6BX+dYw==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"degenerator": "^5.0.0",
|
||||
"degenerator": "7.0.1",
|
||||
"netmask": "^2.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
"node": ">= 20"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"quickjs-wasi": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"node_modules/package-manager-detector": {
|
||||
@@ -14829,9 +14810,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/postcss": {
|
||||
"version": "8.5.8",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz",
|
||||
"integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==",
|
||||
"version": "8.5.10",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.10.tgz",
|
||||
"integrity": "sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
@@ -14866,9 +14847,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/prettier": {
|
||||
"version": "3.8.2",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.2.tgz",
|
||||
"integrity": "sha512-8c3mgTe0ASwWAJK+78dpviD+A8EqhndQPUBpNUIPt6+xWlIigCwfN01lWr9MAede4uqXGTEKeQWTvzb3vjia0Q==",
|
||||
"version": "3.8.3",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.3.tgz",
|
||||
"integrity": "sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw==",
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"prettier": "bin/prettier.cjs"
|
||||
@@ -15011,23 +14992,23 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/proxy-agent": {
|
||||
"version": "6.5.0",
|
||||
"resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.5.0.tgz",
|
||||
"integrity": "sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==",
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-8.0.1.tgz",
|
||||
"integrity": "sha512-kccqGBqHZXR8onQhY/ganJjoO8QIKKRiFBhPOzbTZK16attzSZ/0XSmp9H7jrRxPKHjhGyx1q32lMPrJ3uLFgA==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"agent-base": "^7.1.2",
|
||||
"agent-base": "9.0.0",
|
||||
"debug": "^4.3.4",
|
||||
"http-proxy-agent": "^7.0.1",
|
||||
"https-proxy-agent": "^7.0.6",
|
||||
"http-proxy-agent": "9.0.0",
|
||||
"https-proxy-agent": "9.0.0",
|
||||
"lru-cache": "^7.14.1",
|
||||
"pac-proxy-agent": "^7.1.0",
|
||||
"proxy-from-env": "^1.1.0",
|
||||
"socks-proxy-agent": "^8.0.5"
|
||||
"pac-proxy-agent": "9.0.1",
|
||||
"proxy-from-env": "^2.0.0",
|
||||
"socks-proxy-agent": "10.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
"node": ">= 20"
|
||||
}
|
||||
},
|
||||
"node_modules/proxy-agent/node_modules/lru-cache": {
|
||||
@@ -15040,13 +15021,6 @@
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/proxy-agent/node_modules/proxy-from-env": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
|
||||
"license": "MIT",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/proxy-from-env": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz",
|
||||
@@ -15143,6 +15117,13 @@
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/quickjs-wasi": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/quickjs-wasi/-/quickjs-wasi-2.2.0.tgz",
|
||||
"integrity": "sha512-zQxXmQMrEoD3S+jQdYsloq4qAuaxKFHZj6hHqOYGwB2iQZH+q9e/lf5zQPXCKOk0WJuAjzRFbO4KwHIp2D05Iw==",
|
||||
"license": "MIT",
|
||||
"optional": true
|
||||
},
|
||||
"node_modules/quickselect": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/quickselect/-/quickselect-2.0.0.tgz",
|
||||
@@ -16357,18 +16338,18 @@
|
||||
}
|
||||
},
|
||||
"node_modules/socks-proxy-agent": {
|
||||
"version": "8.0.5",
|
||||
"resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz",
|
||||
"integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==",
|
||||
"version": "10.0.0",
|
||||
"resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-10.0.0.tgz",
|
||||
"integrity": "sha512-pyp2YR3mNxAMu0mGLtzs4g7O3uT4/9sQOLAKcViAkaS9fJWkud7nmaf6ZREFqQEi24IPkBcjfHjXhPTUWjo3uA==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"dependencies": {
|
||||
"agent-base": "^7.1.2",
|
||||
"agent-base": "9.0.0",
|
||||
"debug": "^4.3.4",
|
||||
"socks": "^2.8.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 14"
|
||||
"node": ">= 20"
|
||||
}
|
||||
},
|
||||
"node_modules/sonic-boom": {
|
||||
@@ -17956,9 +17937,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.2.tgz",
|
||||
"integrity": "sha512-bGdAIrZ0wiGDo5l8c++HWtbaNCWTS4UTv7RaTH/ThVIgjkveJt83m74bBHMJkuCbslY8ixgLBVZJIOiQlQTjfQ==",
|
||||
"version": "6.0.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz",
|
||||
"integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==",
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
@@ -18071,9 +18052,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "7.18.2",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz",
|
||||
"integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==",
|
||||
"version": "7.19.2",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.19.2.tgz",
|
||||
"integrity": "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/unicorn-magic": {
|
||||
@@ -19199,10 +19180,10 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@goauthentik/tsconfig": "^1.0.9",
|
||||
"@types/node": "^25.5.2",
|
||||
"@types/node": "^25.6.0",
|
||||
"@types/semver": "^7.7.1",
|
||||
"semver": "^7.7.4",
|
||||
"typescript": "^6.0.2"
|
||||
"typescript": "^6.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=24",
|
||||
@@ -19244,7 +19225,7 @@
|
||||
"@rollup/plugin-node-resolve": "^16.0.3",
|
||||
"@rollup/plugin-swc": "^0.4.0",
|
||||
"@swc/cli": "^0.8.1",
|
||||
"@swc/core": "^1.15.24",
|
||||
"@swc/core": "^1.15.30",
|
||||
"base64-js": "^1.5.1",
|
||||
"core-js": "^3.49.0",
|
||||
"formdata-polyfill": "^2025.11.0",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user