Compare commits
70 Commits
permission
...
version/20
Author | SHA1 | Date | |
---|---|---|---|
74eab55c61 | |||
06137fc633 | |||
63ec664532 | |||
4e4516f9a2 | |||
748a8e560f | |||
d6c35787b0 | |||
cc214a0eb7 | |||
0c9fd5f056 | |||
92a1f7e01a | |||
1a727b9ea0 | |||
28cc75af29 | |||
0ad245f7f6 | |||
b10957e5df | |||
3adf79c493 | |||
f478593826 | |||
edf4de7271 | |||
db43869e25 | |||
8a668af5f6 | |||
eef233fd11 | |||
833b350c42 | |||
b388265d98 | |||
faefd9776d | |||
a5ee159189 | |||
35c739ee84 | |||
e9764333ea | |||
22af17be2c | |||
679bf17d6f | |||
cbfa51fb31 | |||
5f8c21cc88 | |||
69b3d1722b | |||
fa4ce1d629 | |||
e4a392834f | |||
31fe0e5923 | |||
8b619635ea | |||
1f1db523c0 | |||
bbc23e1d77 | |||
c30b7ee3e9 | |||
2ba79627bc | |||
198cbe1d9d | |||
db6da159d5 | |||
9862e32078 | |||
a7714e2892 | |||
073e1d241b | |||
5c5cc1c7da | |||
3dccce1095 | |||
78f997fbee | |||
ed83c2b0b1 | |||
af780deb27 | |||
a4be38567f | |||
39aafbb34a | |||
07eb5fe533 | |||
301a89dd92 | |||
cd6d0a47f3 | |||
8a23eaef1e | |||
8f285fbcc5 | |||
5d391424f7 | |||
2de11f8a69 | |||
b2dcf94aba | |||
adb532fc5d | |||
5d3b35d1ba | |||
433a94d9ee | |||
f28d622d10 | |||
50a68c22c5 | |||
13c99c8546 | |||
7243add30f | |||
6611a64a62 | |||
5262f61483 | |||
9dcbb4af9e | |||
0665bfac58 | |||
790e0c4d80 |
@ -1,5 +1,5 @@
|
|||||||
[bumpversion]
|
[bumpversion]
|
||||||
current_version = 2025.2.1
|
current_version = 2025.2.4
|
||||||
tag = True
|
tag = True
|
||||||
commit = True
|
commit = True
|
||||||
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(?:-(?P<rc_t>[a-zA-Z-]+)(?P<rc_n>[1-9]\\d*))?
|
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(?:-(?P<rc_t>[a-zA-Z-]+)(?P<rc_n>[1-9]\\d*))?
|
||||||
|
6
.github/ISSUE_TEMPLATE/bug_report.md
vendored
6
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -28,11 +28,7 @@ Output of docker-compose logs or kubectl logs respectively
|
|||||||
|
|
||||||
**Version and Deployment (please complete the following information):**
|
**Version and Deployment (please complete the following information):**
|
||||||
|
|
||||||
<!--
|
- authentik version: [e.g. 2021.8.5]
|
||||||
Notice: authentik supports installation via Docker, Kubernetes, and AWS CloudFormation only. Support is not available for other methods. For detailed installation and configuration instructions, please refer to the official documentation at https://docs.goauthentik.io/docs/install-config/.
|
|
||||||
-->
|
|
||||||
|
|
||||||
- authentik version: [e.g. 2025.2.0]
|
|
||||||
- Deployment: [e.g. docker-compose, helm]
|
- Deployment: [e.g. docker-compose, helm]
|
||||||
|
|
||||||
**Additional context**
|
**Additional context**
|
||||||
|
7
.github/ISSUE_TEMPLATE/question.md
vendored
7
.github/ISSUE_TEMPLATE/question.md
vendored
@ -20,12 +20,7 @@ Output of docker-compose logs or kubectl logs respectively
|
|||||||
|
|
||||||
**Version and Deployment (please complete the following information):**
|
**Version and Deployment (please complete the following information):**
|
||||||
|
|
||||||
<!--
|
- authentik version: [e.g. 2021.8.5]
|
||||||
Notice: authentik supports installation via Docker, Kubernetes, and AWS CloudFormation only. Support is not available for other methods. For detailed installation and configuration instructions, please refer to the official documentation at https://docs.goauthentik.io/docs/install-config/.
|
|
||||||
-->
|
|
||||||
|
|
||||||
|
|
||||||
- authentik version: [e.g. 2025.2.0]
|
|
||||||
- Deployment: [e.g. docker-compose, helm]
|
- Deployment: [e.g. docker-compose, helm]
|
||||||
|
|
||||||
**Additional context**
|
**Additional context**
|
||||||
|
6
.github/actions/setup/action.yml
vendored
6
.github/actions/setup/action.yml
vendored
@ -30,16 +30,12 @@ runs:
|
|||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version-file: "go.mod"
|
go-version-file: "go.mod"
|
||||||
- name: Setup docker cache
|
|
||||||
uses: ScribeMD/docker-cache@0.5.0
|
|
||||||
with:
|
|
||||||
key: docker-images-${{ runner.os }}-${{ hashFiles('.github/actions/setup/docker-compose.yml', 'Makefile') }}-${{ inputs.postgresql_version }}
|
|
||||||
- name: Setup dependencies
|
- name: Setup dependencies
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
export PSQL_TAG=${{ inputs.postgresql_version }}
|
export PSQL_TAG=${{ inputs.postgresql_version }}
|
||||||
docker compose -f .github/actions/setup/docker-compose.yml up -d
|
docker compose -f .github/actions/setup/docker-compose.yml up -d
|
||||||
poetry sync
|
poetry install --sync
|
||||||
cd web && npm ci
|
cd web && npm ci
|
||||||
- name: Generate config
|
- name: Generate config
|
||||||
shell: poetry run python {0}
|
shell: poetry run python {0}
|
||||||
|
2
.github/actions/setup/docker-compose.yml
vendored
2
.github/actions/setup/docker-compose.yml
vendored
@ -11,7 +11,7 @@ services:
|
|||||||
- 5432:5432
|
- 5432:5432
|
||||||
restart: always
|
restart: always
|
||||||
redis:
|
redis:
|
||||||
image: docker.io/library/redis:7
|
image: docker.io/library/redis
|
||||||
ports:
|
ports:
|
||||||
- 6379:6379
|
- 6379:6379
|
||||||
restart: always
|
restart: always
|
||||||
|
33
.github/codespell-words.txt
vendored
33
.github/codespell-words.txt
vendored
@ -1,32 +1,7 @@
|
|||||||
akadmin
|
|
||||||
asgi
|
|
||||||
assertIn
|
|
||||||
authentik
|
|
||||||
authn
|
|
||||||
crate
|
|
||||||
docstrings
|
|
||||||
entra
|
|
||||||
goauthentik
|
|
||||||
gunicorn
|
|
||||||
hass
|
|
||||||
jwe
|
|
||||||
jwks
|
|
||||||
keypair
|
keypair
|
||||||
keypairs
|
keypairs
|
||||||
kubernetes
|
hass
|
||||||
oidc
|
|
||||||
ontext
|
|
||||||
openid
|
|
||||||
passwordless
|
|
||||||
plex
|
|
||||||
saml
|
|
||||||
scim
|
|
||||||
singed
|
|
||||||
slo
|
|
||||||
sso
|
|
||||||
totp
|
|
||||||
traefik
|
|
||||||
# https://github.com/codespell-project/codespell/issues/1224
|
|
||||||
upToDate
|
|
||||||
warmup
|
warmup
|
||||||
webauthn
|
ontext
|
||||||
|
singed
|
||||||
|
assertIn
|
||||||
|
6
.github/dependabot.yml
vendored
6
.github/dependabot.yml
vendored
@ -82,12 +82,6 @@ updates:
|
|||||||
docusaurus:
|
docusaurus:
|
||||||
patterns:
|
patterns:
|
||||||
- "@docusaurus/*"
|
- "@docusaurus/*"
|
||||||
build:
|
|
||||||
patterns:
|
|
||||||
- "@swc/*"
|
|
||||||
- "swc-*"
|
|
||||||
- "lightningcss*"
|
|
||||||
- "@rspack/binding*"
|
|
||||||
- package-ecosystem: npm
|
- package-ecosystem: npm
|
||||||
directory: "/lifecycle/aws"
|
directory: "/lifecycle/aws"
|
||||||
schedule:
|
schedule:
|
||||||
|
@ -40,7 +40,7 @@ jobs:
|
|||||||
attestations: write
|
attestations: write
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: docker/setup-qemu-action@v3.6.0
|
- uses: docker/setup-qemu-action@v3.4.0
|
||||||
- uses: docker/setup-buildx-action@v3
|
- uses: docker/setup-buildx-action@v3
|
||||||
- name: prepare variables
|
- name: prepare variables
|
||||||
uses: ./.github/actions/docker-push-variables
|
uses: ./.github/actions/docker-push-variables
|
||||||
|
2
.github/workflows/ci-main-daily.yml
vendored
2
.github/workflows/ci-main-daily.yml
vendored
@ -15,8 +15,8 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
version:
|
version:
|
||||||
- docs
|
- docs
|
||||||
- version-2025-2
|
|
||||||
- version-2024-12
|
- version-2024-12
|
||||||
|
- version-2024-10
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- run: |
|
- run: |
|
||||||
|
2
.github/workflows/ci-outpost.yml
vendored
2
.github/workflows/ci-outpost.yml
vendored
@ -82,7 +82,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
ref: ${{ github.event.pull_request.head.sha }}
|
ref: ${{ github.event.pull_request.head.sha }}
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v3.6.0
|
uses: docker/setup-qemu-action@v3.4.0
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
- name: prepare variables
|
- name: prepare variables
|
||||||
|
4
.github/workflows/release-publish.yml
vendored
4
.github/workflows/release-publish.yml
vendored
@ -42,7 +42,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
go-version-file: "go.mod"
|
go-version-file: "go.mod"
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v3.6.0
|
uses: docker/setup-qemu-action@v3.4.0
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
- name: prepare variables
|
- name: prepare variables
|
||||||
@ -186,7 +186,7 @@ jobs:
|
|||||||
container=$(docker container create ${{ steps.ev.outputs.imageMainName }})
|
container=$(docker container create ${{ steps.ev.outputs.imageMainName }})
|
||||||
docker cp ${container}:web/ .
|
docker cp ${container}:web/ .
|
||||||
- name: Create a Sentry.io release
|
- name: Create a Sentry.io release
|
||||||
uses: getsentry/action-release@v3
|
uses: getsentry/action-release@v1
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
env:
|
env:
|
||||||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||||
|
@ -1,13 +1,9 @@
|
|||||||
---
|
---
|
||||||
name: authentik-translate-extract-compile
|
name: authentik-backend-translate-extract-compile
|
||||||
on:
|
on:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: "0 0 * * *" # every day at midnight
|
- cron: "0 0 * * *" # every day at midnight
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
- version-*
|
|
||||||
|
|
||||||
env:
|
env:
|
||||||
POSTGRES_DB: authentik
|
POSTGRES_DB: authentik
|
||||||
@ -19,21 +15,15 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- id: generate_token
|
- id: generate_token
|
||||||
if: ${{ github.event_name != 'pull_request' }}
|
|
||||||
uses: tibdex/github-app-token@v2
|
uses: tibdex/github-app-token@v2
|
||||||
with:
|
with:
|
||||||
app_id: ${{ secrets.GH_APP_ID }}
|
app_id: ${{ secrets.GH_APP_ID }}
|
||||||
private_key: ${{ secrets.GH_APP_PRIVATE_KEY }}
|
private_key: ${{ secrets.GH_APP_PRIVATE_KEY }}
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
if: ${{ github.event_name != 'pull_request' }}
|
|
||||||
with:
|
with:
|
||||||
token: ${{ steps.generate_token.outputs.token }}
|
token: ${{ steps.generate_token.outputs.token }}
|
||||||
- uses: actions/checkout@v4
|
|
||||||
if: ${{ github.event_name == 'pull_request' }}
|
|
||||||
- name: Setup authentik env
|
- name: Setup authentik env
|
||||||
uses: ./.github/actions/setup
|
uses: ./.github/actions/setup
|
||||||
- name: Generate API
|
|
||||||
run: make gen-client-ts
|
|
||||||
- name: run extract
|
- name: run extract
|
||||||
run: |
|
run: |
|
||||||
poetry run make i18n-extract
|
poetry run make i18n-extract
|
||||||
@ -42,7 +32,6 @@ jobs:
|
|||||||
poetry run ak compilemessages
|
poetry run ak compilemessages
|
||||||
make web-check-compile
|
make web-check-compile
|
||||||
- name: Create Pull Request
|
- name: Create Pull Request
|
||||||
if: ${{ github.event_name != 'pull_request' }}
|
|
||||||
uses: peter-evans/create-pull-request@v7
|
uses: peter-evans/create-pull-request@v7
|
||||||
with:
|
with:
|
||||||
token: ${{ steps.generate_token.outputs.token }}
|
token: ${{ steps.generate_token.outputs.token }}
|
||||||
|
22
.vscode/settings.json
vendored
22
.vscode/settings.json
vendored
@ -1,4 +1,26 @@
|
|||||||
{
|
{
|
||||||
|
"cSpell.words": [
|
||||||
|
"akadmin",
|
||||||
|
"asgi",
|
||||||
|
"authentik",
|
||||||
|
"authn",
|
||||||
|
"entra",
|
||||||
|
"goauthentik",
|
||||||
|
"jwe",
|
||||||
|
"jwks",
|
||||||
|
"kubernetes",
|
||||||
|
"oidc",
|
||||||
|
"openid",
|
||||||
|
"passwordless",
|
||||||
|
"plex",
|
||||||
|
"saml",
|
||||||
|
"scim",
|
||||||
|
"slo",
|
||||||
|
"sso",
|
||||||
|
"totp",
|
||||||
|
"traefik",
|
||||||
|
"webauthn"
|
||||||
|
],
|
||||||
"todo-tree.tree.showCountsInTree": true,
|
"todo-tree.tree.showCountsInTree": true,
|
||||||
"todo-tree.tree.showBadges": true,
|
"todo-tree.tree.showBadges": true,
|
||||||
"yaml.customTags": [
|
"yaml.customTags": [
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
We as members, contributors, and leaders pledge to make participation in our
|
We as members, contributors, and leaders pledge to make participation in our
|
||||||
community a harassment-free experience for everyone, regardless of age, body
|
community a harassment-free experience for everyone, regardless of age, body
|
||||||
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||||
identity and expression, level of experience, education, socioeconomic status,
|
identity and expression, level of experience, education, socio-economic status,
|
||||||
nationality, personal appearance, race, religion, or sexual identity
|
nationality, personal appearance, race, religion, or sexual identity
|
||||||
and orientation.
|
and orientation.
|
||||||
|
|
||||||
|
@ -3,8 +3,7 @@
|
|||||||
# Stage 1: Build website
|
# Stage 1: Build website
|
||||||
FROM --platform=${BUILDPLATFORM} docker.io/library/node:22 AS website-builder
|
FROM --platform=${BUILDPLATFORM} docker.io/library/node:22 AS website-builder
|
||||||
|
|
||||||
ENV NODE_ENV=production \
|
ENV NODE_ENV=production
|
||||||
GIT_UNAVAILABLE=true
|
|
||||||
|
|
||||||
WORKDIR /work/website
|
WORKDIR /work/website
|
||||||
|
|
||||||
|
67
Makefile
67
Makefile
@ -4,17 +4,34 @@
|
|||||||
PWD = $(shell pwd)
|
PWD = $(shell pwd)
|
||||||
UID = $(shell id -u)
|
UID = $(shell id -u)
|
||||||
GID = $(shell id -g)
|
GID = $(shell id -g)
|
||||||
NPM_VERSION = $(shell python -m scripts.generate_semver)
|
NPM_VERSION = $(shell python -m scripts.npm_version)
|
||||||
PY_SOURCES = authentik tests scripts lifecycle .github
|
PY_SOURCES = authentik tests scripts lifecycle .github
|
||||||
|
GO_SOURCES = cmd internal
|
||||||
|
WEB_SOURCES = web/src web/packages
|
||||||
DOCKER_IMAGE ?= "authentik:test"
|
DOCKER_IMAGE ?= "authentik:test"
|
||||||
|
|
||||||
GEN_API_TS = "gen-ts-api"
|
GEN_API_TS = "gen-ts-api"
|
||||||
GEN_API_PY = "gen-py-api"
|
GEN_API_PY = "gen-py-api"
|
||||||
GEN_API_GO = "gen-go-api"
|
GEN_API_GO = "gen-go-api"
|
||||||
|
|
||||||
pg_user := $(shell poetry run python -m authentik.lib.config postgresql.user 2>/dev/null)
|
pg_user := $(shell python -m authentik.lib.config postgresql.user 2>/dev/null)
|
||||||
pg_host := $(shell poetry run python -m authentik.lib.config postgresql.host 2>/dev/null)
|
pg_host := $(shell python -m authentik.lib.config postgresql.host 2>/dev/null)
|
||||||
pg_name := $(shell poetry run python -m authentik.lib.config postgresql.name 2>/dev/null)
|
pg_name := $(shell python -m authentik.lib.config postgresql.name 2>/dev/null)
|
||||||
|
|
||||||
|
CODESPELL_ARGS = -D - -D .github/codespell-dictionary.txt \
|
||||||
|
-I .github/codespell-words.txt \
|
||||||
|
-S 'web/src/locales/**' \
|
||||||
|
-S 'website/docs/developer-docs/api/reference/**' \
|
||||||
|
-S '**/node_modules/**' \
|
||||||
|
-S '**/dist/**' \
|
||||||
|
$(PY_SOURCES) \
|
||||||
|
$(GO_SOURCES) \
|
||||||
|
$(WEB_SOURCES) \
|
||||||
|
website/src \
|
||||||
|
website/blog \
|
||||||
|
website/docs \
|
||||||
|
website/integrations \
|
||||||
|
website/src
|
||||||
|
|
||||||
all: lint-fix lint test gen web ## Lint, build, and test everything
|
all: lint-fix lint test gen web ## Lint, build, and test everything
|
||||||
|
|
||||||
@ -32,26 +49,26 @@ go-test:
|
|||||||
go test -timeout 0 -v -race -cover ./...
|
go test -timeout 0 -v -race -cover ./...
|
||||||
|
|
||||||
test: ## Run the server tests and produce a coverage report (locally)
|
test: ## Run the server tests and produce a coverage report (locally)
|
||||||
poetry run coverage run manage.py test --keepdb authentik
|
coverage run manage.py test --keepdb authentik
|
||||||
poetry run coverage html
|
coverage html
|
||||||
poetry run coverage report
|
coverage report
|
||||||
|
|
||||||
lint-fix: lint-codespell ## Lint and automatically fix errors in the python source code. Reports spelling errors.
|
lint-fix: lint-codespell ## Lint and automatically fix errors in the python source code. Reports spelling errors.
|
||||||
poetry run black $(PY_SOURCES)
|
black $(PY_SOURCES)
|
||||||
poetry run ruff check --fix $(PY_SOURCES)
|
ruff check --fix $(PY_SOURCES)
|
||||||
|
|
||||||
lint-codespell: ## Reports spelling errors.
|
lint-codespell: ## Reports spelling errors.
|
||||||
poetry run codespell -w
|
codespell -w $(CODESPELL_ARGS)
|
||||||
|
|
||||||
lint: ## Lint the python and golang sources
|
lint: ## Lint the python and golang sources
|
||||||
poetry run bandit -c pyproject.toml -r $(PY_SOURCES)
|
bandit -r $(PY_SOURCES) -x web/node_modules -x tests/wdio/node_modules -x website/node_modules
|
||||||
golangci-lint run -v
|
golangci-lint run -v
|
||||||
|
|
||||||
core-install:
|
core-install:
|
||||||
poetry install
|
poetry install
|
||||||
|
|
||||||
migrate: ## Run the Authentik Django server's migrations
|
migrate: ## Run the Authentik Django server's migrations
|
||||||
poetry run python -m lifecycle.migrate
|
python -m lifecycle.migrate
|
||||||
|
|
||||||
i18n-extract: core-i18n-extract web-i18n-extract ## Extract strings that require translation into files to send to a translation service
|
i18n-extract: core-i18n-extract web-i18n-extract ## Extract strings that require translation into files to send to a translation service
|
||||||
|
|
||||||
@ -59,7 +76,7 @@ aws-cfn:
|
|||||||
cd lifecycle/aws && npm run aws-cfn
|
cd lifecycle/aws && npm run aws-cfn
|
||||||
|
|
||||||
core-i18n-extract:
|
core-i18n-extract:
|
||||||
poetry run ak makemessages \
|
ak makemessages \
|
||||||
--add-location file \
|
--add-location file \
|
||||||
--no-obsolete \
|
--no-obsolete \
|
||||||
--ignore web \
|
--ignore web \
|
||||||
@ -90,11 +107,11 @@ gen-build: ## Extract the schema from the database
|
|||||||
AUTHENTIK_DEBUG=true \
|
AUTHENTIK_DEBUG=true \
|
||||||
AUTHENTIK_TENANTS__ENABLED=true \
|
AUTHENTIK_TENANTS__ENABLED=true \
|
||||||
AUTHENTIK_OUTPOSTS__DISABLE_EMBEDDED_OUTPOST=true \
|
AUTHENTIK_OUTPOSTS__DISABLE_EMBEDDED_OUTPOST=true \
|
||||||
poetry run ak make_blueprint_schema > blueprints/schema.json
|
ak make_blueprint_schema > blueprints/schema.json
|
||||||
AUTHENTIK_DEBUG=true \
|
AUTHENTIK_DEBUG=true \
|
||||||
AUTHENTIK_TENANTS__ENABLED=true \
|
AUTHENTIK_TENANTS__ENABLED=true \
|
||||||
AUTHENTIK_OUTPOSTS__DISABLE_EMBEDDED_OUTPOST=true \
|
AUTHENTIK_OUTPOSTS__DISABLE_EMBEDDED_OUTPOST=true \
|
||||||
poetry run ak spectacular --file schema.yml
|
ak spectacular --file schema.yml
|
||||||
|
|
||||||
gen-changelog: ## (Release) generate the changelog based from the commits since the last tag
|
gen-changelog: ## (Release) generate the changelog based from the commits since the last tag
|
||||||
git log --pretty=format:" - %s" $(shell git describe --tags $(shell git rev-list --tags --max-count=1))...$(shell git branch --show-current) | sort > changelog.md
|
git log --pretty=format:" - %s" $(shell git describe --tags $(shell git rev-list --tags --max-count=1))...$(shell git branch --show-current) | sort > changelog.md
|
||||||
@ -145,7 +162,7 @@ gen-client-py: gen-clean-py ## Build and install the authentik API for Python
|
|||||||
docker run \
|
docker run \
|
||||||
--rm -v ${PWD}:/local \
|
--rm -v ${PWD}:/local \
|
||||||
--user ${UID}:${GID} \
|
--user ${UID}:${GID} \
|
||||||
docker.io/openapitools/openapi-generator-cli:v7.11.0 generate \
|
docker.io/openapitools/openapi-generator-cli:v7.4.0 generate \
|
||||||
-i /local/schema.yml \
|
-i /local/schema.yml \
|
||||||
-g python \
|
-g python \
|
||||||
-o /local/${GEN_API_PY} \
|
-o /local/${GEN_API_PY} \
|
||||||
@ -173,7 +190,7 @@ gen-client-go: gen-clean-go ## Build and install the authentik API for Golang
|
|||||||
rm -rf ./${GEN_API_GO}/config.yaml ./${GEN_API_GO}/templates/
|
rm -rf ./${GEN_API_GO}/config.yaml ./${GEN_API_GO}/templates/
|
||||||
|
|
||||||
gen-dev-config: ## Generate a local development config file
|
gen-dev-config: ## Generate a local development config file
|
||||||
poetry run scripts/generate_config.py
|
python -m scripts.generate_config
|
||||||
|
|
||||||
gen: gen-build gen-client-ts
|
gen: gen-build gen-client-ts
|
||||||
|
|
||||||
@ -254,21 +271,21 @@ ci--meta-debug:
|
|||||||
node --version
|
node --version
|
||||||
|
|
||||||
ci-black: ci--meta-debug
|
ci-black: ci--meta-debug
|
||||||
poetry run black --check $(PY_SOURCES)
|
black --check $(PY_SOURCES)
|
||||||
|
|
||||||
ci-ruff: ci--meta-debug
|
ci-ruff: ci--meta-debug
|
||||||
poetry run ruff check $(PY_SOURCES)
|
ruff check $(PY_SOURCES)
|
||||||
|
|
||||||
ci-codespell: ci--meta-debug
|
ci-codespell: ci--meta-debug
|
||||||
poetry run codespell -s
|
codespell $(CODESPELL_ARGS) -s
|
||||||
|
|
||||||
ci-bandit: ci--meta-debug
|
ci-bandit: ci--meta-debug
|
||||||
poetry run bandit -r $(PY_SOURCES)
|
bandit -r $(PY_SOURCES)
|
||||||
|
|
||||||
ci-pending-migrations: ci--meta-debug
|
ci-pending-migrations: ci--meta-debug
|
||||||
poetry run ak makemigrations --check
|
ak makemigrations --check
|
||||||
|
|
||||||
ci-test: ci--meta-debug
|
ci-test: ci--meta-debug
|
||||||
poetry run coverage run manage.py test --keepdb --randomly-seed ${CI_TEST_SEED} authentik
|
coverage run manage.py test --keepdb --randomly-seed ${CI_TEST_SEED} authentik
|
||||||
poetry run coverage report
|
coverage report
|
||||||
poetry run coverage xml
|
coverage xml
|
||||||
|
@ -2,7 +2,7 @@ authentik takes security very seriously. We follow the rules of [responsible di
|
|||||||
|
|
||||||
## Independent audits and pentests
|
## Independent audits and pentests
|
||||||
|
|
||||||
We are committed to engaging in regular pentesting and security audits of authentik. Defining and adhering to a cadence of external testing ensures a stronger probability that our code base, our features, and our architecture is as secure and non-exploitable as possible. For more details about specific audits and pentests, refer to "Audits and Certificates" in our [Security documentation](https://docs.goauthentik.io/docs/security).
|
We are committed to engaging in regular pentesting and security audits of authentik. Defining and adhering to a cadence of external testing ensures a stronger probability that our code base, our features, and our architecture is as secure and non-exploitable as possible. For more details about specfic audits and pentests, refer to "Audits and Certificates" in our [Security documentation](https://docs.goauthentik.io/docs/security).
|
||||||
|
|
||||||
## What authentik classifies as a CVE
|
## What authentik classifies as a CVE
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
from os import environ
|
from os import environ
|
||||||
|
|
||||||
__version__ = "2025.2.1"
|
__version__ = "2025.2.4"
|
||||||
ENV_GIT_HASH_KEY = "GIT_BUILD_HASH"
|
ENV_GIT_HASH_KEY = "GIT_BUILD_HASH"
|
||||||
|
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ class SystemInfoSerializer(PassiveSerializer):
|
|||||||
if not isinstance(value, str):
|
if not isinstance(value, str):
|
||||||
continue
|
continue
|
||||||
actual_value = value
|
actual_value = value
|
||||||
if raw_session in actual_value:
|
if raw_session is not None and raw_session in actual_value:
|
||||||
actual_value = actual_value.replace(
|
actual_value = actual_value.replace(
|
||||||
raw_session, SafeExceptionReporterFilter.cleansed_substitute
|
raw_session, SafeExceptionReporterFilter.cleansed_substitute
|
||||||
)
|
)
|
||||||
|
@ -5,7 +5,6 @@ from collections.abc import Iterable
|
|||||||
from drf_spectacular.utils import OpenApiResponse, extend_schema
|
from drf_spectacular.utils import OpenApiResponse, extend_schema
|
||||||
from rest_framework import mixins
|
from rest_framework import mixins
|
||||||
from rest_framework.decorators import action
|
from rest_framework.decorators import action
|
||||||
from rest_framework.exceptions import ValidationError
|
|
||||||
from rest_framework.fields import CharField, ReadOnlyField, SerializerMethodField
|
from rest_framework.fields import CharField, ReadOnlyField, SerializerMethodField
|
||||||
from rest_framework.parsers import MultiPartParser
|
from rest_framework.parsers import MultiPartParser
|
||||||
from rest_framework.request import Request
|
from rest_framework.request import Request
|
||||||
@ -155,17 +154,6 @@ class SourceViewSet(
|
|||||||
matching_sources.append(source_settings.validated_data)
|
matching_sources.append(source_settings.validated_data)
|
||||||
return Response(matching_sources)
|
return Response(matching_sources)
|
||||||
|
|
||||||
def destroy(self, request: Request, *args, **kwargs):
|
|
||||||
"""Prevent deletion of built-in sources"""
|
|
||||||
instance: Source = self.get_object()
|
|
||||||
|
|
||||||
if instance.managed == Source.MANAGED_INBUILT:
|
|
||||||
raise ValidationError(
|
|
||||||
{"detail": "Built-in sources cannot be deleted"}, code="protected"
|
|
||||||
)
|
|
||||||
|
|
||||||
return super().destroy(request, *args, **kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class UserSourceConnectionSerializer(SourceSerializer):
|
class UserSourceConnectionSerializer(SourceSerializer):
|
||||||
"""User source connection"""
|
"""User source connection"""
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
"""User API Views"""
|
"""User API Views"""
|
||||||
|
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
from importlib import import_module
|
||||||
from json import loads
|
from json import loads
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.contrib.auth import update_session_auth_hash
|
from django.contrib.auth import update_session_auth_hash
|
||||||
from django.contrib.auth.models import Permission
|
from django.contrib.auth.models import Permission
|
||||||
from django.contrib.sessions.backends.cache import KEY_PREFIX
|
from django.contrib.sessions.backends.base import SessionBase
|
||||||
from django.core.cache import cache
|
|
||||||
from django.db.models.functions import ExtractHour
|
from django.db.models.functions import ExtractHour
|
||||||
from django.db.transaction import atomic
|
from django.db.transaction import atomic
|
||||||
from django.db.utils import IntegrityError
|
from django.db.utils import IntegrityError
|
||||||
@ -91,6 +92,7 @@ from authentik.stages.email.tasks import send_mails
|
|||||||
from authentik.stages.email.utils import TemplateEmailMessage
|
from authentik.stages.email.utils import TemplateEmailMessage
|
||||||
|
|
||||||
LOGGER = get_logger()
|
LOGGER = get_logger()
|
||||||
|
SessionStore: SessionBase = import_module(settings.SESSION_ENGINE).SessionStore
|
||||||
|
|
||||||
|
|
||||||
class UserGroupSerializer(ModelSerializer):
|
class UserGroupSerializer(ModelSerializer):
|
||||||
@ -373,7 +375,7 @@ class UsersFilter(FilterSet):
|
|||||||
method="filter_attributes",
|
method="filter_attributes",
|
||||||
)
|
)
|
||||||
|
|
||||||
is_superuser = BooleanFilter(field_name="ak_groups", lookup_expr="is_superuser")
|
is_superuser = BooleanFilter(field_name="ak_groups", method="filter_is_superuser")
|
||||||
uuid = UUIDFilter(field_name="uuid")
|
uuid = UUIDFilter(field_name="uuid")
|
||||||
|
|
||||||
path = CharFilter(field_name="path")
|
path = CharFilter(field_name="path")
|
||||||
@ -391,6 +393,11 @@ class UsersFilter(FilterSet):
|
|||||||
queryset=Group.objects.all().order_by("name"),
|
queryset=Group.objects.all().order_by("name"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def filter_is_superuser(self, queryset, name, value):
|
||||||
|
if value:
|
||||||
|
return queryset.filter(ak_groups__is_superuser=True).distinct()
|
||||||
|
return queryset.exclude(ak_groups__is_superuser=True).distinct()
|
||||||
|
|
||||||
def filter_attributes(self, queryset, name, value):
|
def filter_attributes(self, queryset, name, value):
|
||||||
"""Filter attributes by query args"""
|
"""Filter attributes by query args"""
|
||||||
try:
|
try:
|
||||||
@ -769,7 +776,8 @@ class UserViewSet(UsedByMixin, ModelViewSet):
|
|||||||
if not instance.is_active:
|
if not instance.is_active:
|
||||||
sessions = AuthenticatedSession.objects.filter(user=instance)
|
sessions = AuthenticatedSession.objects.filter(user=instance)
|
||||||
session_ids = sessions.values_list("session_key", flat=True)
|
session_ids = sessions.values_list("session_key", flat=True)
|
||||||
cache.delete_many(f"{KEY_PREFIX}{session}" for session in session_ids)
|
for session in session_ids:
|
||||||
|
SessionStore(session).delete()
|
||||||
sessions.delete()
|
sessions.delete()
|
||||||
LOGGER.debug("Deleted user's sessions", user=instance.username)
|
LOGGER.debug("Deleted user's sessions", user=instance.username)
|
||||||
return response
|
return response
|
||||||
|
@ -32,5 +32,5 @@ class AuthentikCoreConfig(ManagedAppConfig):
|
|||||||
"name": "authentik Built-in",
|
"name": "authentik Built-in",
|
||||||
"slug": "authentik-built-in",
|
"slug": "authentik-built-in",
|
||||||
},
|
},
|
||||||
managed=Source.MANAGED_INBUILT,
|
managed="goauthentik.io/sources/inbuilt",
|
||||||
)
|
)
|
||||||
|
@ -678,8 +678,6 @@ class SourceGroupMatchingModes(models.TextChoices):
|
|||||||
class Source(ManagedModel, SerializerModel, PolicyBindingModel):
|
class Source(ManagedModel, SerializerModel, PolicyBindingModel):
|
||||||
"""Base Authentication source, i.e. an OAuth Provider, SAML Remote or LDAP Server"""
|
"""Base Authentication source, i.e. an OAuth Provider, SAML Remote or LDAP Server"""
|
||||||
|
|
||||||
MANAGED_INBUILT = "goauthentik.io/sources/inbuilt"
|
|
||||||
|
|
||||||
name = models.TextField(help_text=_("Source's display Name."))
|
name = models.TextField(help_text=_("Source's display Name."))
|
||||||
slug = models.SlugField(help_text=_("Internal source name, used in URLs."), unique=True)
|
slug = models.SlugField(help_text=_("Internal source name, used in URLs."), unique=True)
|
||||||
|
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
"""authentik core signals"""
|
"""authentik core signals"""
|
||||||
|
|
||||||
|
from importlib import import_module
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.contrib.auth.signals import user_logged_in, user_logged_out
|
from django.contrib.auth.signals import user_logged_in, user_logged_out
|
||||||
from django.contrib.sessions.backends.cache import KEY_PREFIX
|
from django.contrib.sessions.backends.base import SessionBase
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from django.core.signals import Signal
|
from django.core.signals import Signal
|
||||||
from django.db.models import Model
|
from django.db.models import Model
|
||||||
@ -25,6 +28,7 @@ password_changed = Signal()
|
|||||||
login_failed = Signal()
|
login_failed = Signal()
|
||||||
|
|
||||||
LOGGER = get_logger()
|
LOGGER = get_logger()
|
||||||
|
SessionStore: SessionBase = import_module(settings.SESSION_ENGINE).SessionStore
|
||||||
|
|
||||||
|
|
||||||
@receiver(post_save, sender=Application)
|
@receiver(post_save, sender=Application)
|
||||||
@ -60,8 +64,7 @@ def user_logged_out_session(sender, request: HttpRequest, user: User, **_):
|
|||||||
@receiver(pre_delete, sender=AuthenticatedSession)
|
@receiver(pre_delete, sender=AuthenticatedSession)
|
||||||
def authenticated_session_delete(sender: type[Model], instance: "AuthenticatedSession", **_):
|
def authenticated_session_delete(sender: type[Model], instance: "AuthenticatedSession", **_):
|
||||||
"""Delete session when authenticated session is deleted"""
|
"""Delete session when authenticated session is deleted"""
|
||||||
cache_key = f"{KEY_PREFIX}{instance.session_key}"
|
SessionStore(instance.session_key).delete()
|
||||||
cache.delete(cache_key)
|
|
||||||
|
|
||||||
|
|
||||||
@receiver(pre_save)
|
@receiver(pre_save)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
"""Test Users API"""
|
"""Test Users API"""
|
||||||
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from json import loads
|
||||||
|
|
||||||
from django.contrib.sessions.backends.cache import KEY_PREFIX
|
from django.contrib.sessions.backends.cache import KEY_PREFIX
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
@ -15,7 +16,11 @@ from authentik.core.models import (
|
|||||||
User,
|
User,
|
||||||
UserTypes,
|
UserTypes,
|
||||||
)
|
)
|
||||||
from authentik.core.tests.utils import create_test_admin_user, create_test_brand, create_test_flow
|
from authentik.core.tests.utils import (
|
||||||
|
create_test_admin_user,
|
||||||
|
create_test_brand,
|
||||||
|
create_test_flow,
|
||||||
|
)
|
||||||
from authentik.flows.models import FlowDesignation
|
from authentik.flows.models import FlowDesignation
|
||||||
from authentik.lib.generators import generate_id, generate_key
|
from authentik.lib.generators import generate_id, generate_key
|
||||||
from authentik.stages.email.models import EmailStage
|
from authentik.stages.email.models import EmailStage
|
||||||
@ -41,6 +46,32 @@ class TestUsersAPI(APITestCase):
|
|||||||
)
|
)
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
|
def test_filter_is_superuser(self):
|
||||||
|
"""Test API filtering by superuser status"""
|
||||||
|
self.client.force_login(self.admin)
|
||||||
|
# Test superuser
|
||||||
|
response = self.client.get(
|
||||||
|
reverse("authentik_api:user-list"),
|
||||||
|
data={
|
||||||
|
"is_superuser": True,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
body = loads(response.content)
|
||||||
|
self.assertEqual(len(body["results"]), 1)
|
||||||
|
self.assertEqual(body["results"][0]["username"], self.admin.username)
|
||||||
|
# Test non-superuser
|
||||||
|
response = self.client.get(
|
||||||
|
reverse("authentik_api:user-list"),
|
||||||
|
data={
|
||||||
|
"is_superuser": False,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
body = loads(response.content)
|
||||||
|
self.assertEqual(len(body["results"]), 1, body)
|
||||||
|
self.assertEqual(body["results"][0]["username"], self.user.username)
|
||||||
|
|
||||||
def test_list_with_groups(self):
|
def test_list_with_groups(self):
|
||||||
"""Test listing with groups"""
|
"""Test listing with groups"""
|
||||||
self.client.force_login(self.admin)
|
self.client.force_login(self.admin)
|
||||||
|
@ -37,7 +37,6 @@ class GoogleWorkspaceProviderSerializer(EnterpriseRequiredMixin, ProviderSeriali
|
|||||||
"user_delete_action",
|
"user_delete_action",
|
||||||
"group_delete_action",
|
"group_delete_action",
|
||||||
"default_group_email_domain",
|
"default_group_email_domain",
|
||||||
"dry_run",
|
|
||||||
]
|
]
|
||||||
extra_kwargs = {}
|
extra_kwargs = {}
|
||||||
|
|
||||||
|
@ -8,10 +8,9 @@ from httplib2 import HttpLib2Error, HttpLib2ErrorWithResponse
|
|||||||
|
|
||||||
from authentik.enterprise.providers.google_workspace.models import GoogleWorkspaceProvider
|
from authentik.enterprise.providers.google_workspace.models import GoogleWorkspaceProvider
|
||||||
from authentik.lib.sync.outgoing import HTTP_CONFLICT
|
from authentik.lib.sync.outgoing import HTTP_CONFLICT
|
||||||
from authentik.lib.sync.outgoing.base import SAFE_METHODS, BaseOutgoingSyncClient
|
from authentik.lib.sync.outgoing.base import BaseOutgoingSyncClient
|
||||||
from authentik.lib.sync.outgoing.exceptions import (
|
from authentik.lib.sync.outgoing.exceptions import (
|
||||||
BadRequestSyncException,
|
BadRequestSyncException,
|
||||||
DryRunRejected,
|
|
||||||
NotFoundSyncException,
|
NotFoundSyncException,
|
||||||
ObjectExistsSyncException,
|
ObjectExistsSyncException,
|
||||||
StopSync,
|
StopSync,
|
||||||
@ -44,8 +43,6 @@ class GoogleWorkspaceSyncClient[TModel: Model, TConnection: Model, TSchema: dict
|
|||||||
self.domains.append(domain_name)
|
self.domains.append(domain_name)
|
||||||
|
|
||||||
def _request(self, request: HttpRequest):
|
def _request(self, request: HttpRequest):
|
||||||
if self.provider.dry_run and request.method.upper() not in SAFE_METHODS:
|
|
||||||
raise DryRunRejected(request.uri, request.method, request.body)
|
|
||||||
try:
|
try:
|
||||||
response = request.execute()
|
response = request.execute()
|
||||||
except GoogleAuthError as exc:
|
except GoogleAuthError as exc:
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
# Generated by Django 5.0.12 on 2025-02-24 19:43
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
(
|
|
||||||
"authentik_providers_google_workspace",
|
|
||||||
"0003_googleworkspaceprovidergroup_attributes_and_more",
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="googleworkspaceprovider",
|
|
||||||
name="dry_run",
|
|
||||||
field=models.BooleanField(
|
|
||||||
default=False,
|
|
||||||
help_text="When enabled, provider will not modify or create objects in the remote system.",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
]
|
|
@ -36,7 +36,6 @@ class MicrosoftEntraProviderSerializer(EnterpriseRequiredMixin, ProviderSerializ
|
|||||||
"filter_group",
|
"filter_group",
|
||||||
"user_delete_action",
|
"user_delete_action",
|
||||||
"group_delete_action",
|
"group_delete_action",
|
||||||
"dry_run",
|
|
||||||
]
|
]
|
||||||
extra_kwargs = {}
|
extra_kwargs = {}
|
||||||
|
|
||||||
|
@ -3,7 +3,6 @@ from collections.abc import Coroutine
|
|||||||
from dataclasses import asdict
|
from dataclasses import asdict
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
import httpx
|
|
||||||
from azure.core.exceptions import (
|
from azure.core.exceptions import (
|
||||||
ClientAuthenticationError,
|
ClientAuthenticationError,
|
||||||
ServiceRequestError,
|
ServiceRequestError,
|
||||||
@ -13,7 +12,6 @@ from azure.identity.aio import ClientSecretCredential
|
|||||||
from django.db.models import Model
|
from django.db.models import Model
|
||||||
from django.http import HttpResponseBadRequest, HttpResponseNotFound
|
from django.http import HttpResponseBadRequest, HttpResponseNotFound
|
||||||
from kiota_abstractions.api_error import APIError
|
from kiota_abstractions.api_error import APIError
|
||||||
from kiota_abstractions.request_information import RequestInformation
|
|
||||||
from kiota_authentication_azure.azure_identity_authentication_provider import (
|
from kiota_authentication_azure.azure_identity_authentication_provider import (
|
||||||
AzureIdentityAuthenticationProvider,
|
AzureIdentityAuthenticationProvider,
|
||||||
)
|
)
|
||||||
@ -23,15 +21,13 @@ from msgraph.generated.models.o_data_errors.o_data_error import ODataError
|
|||||||
from msgraph.graph_request_adapter import GraphRequestAdapter, options
|
from msgraph.graph_request_adapter import GraphRequestAdapter, options
|
||||||
from msgraph.graph_service_client import GraphServiceClient
|
from msgraph.graph_service_client import GraphServiceClient
|
||||||
from msgraph_core import GraphClientFactory
|
from msgraph_core import GraphClientFactory
|
||||||
from opentelemetry import trace
|
|
||||||
|
|
||||||
from authentik.enterprise.providers.microsoft_entra.models import MicrosoftEntraProvider
|
from authentik.enterprise.providers.microsoft_entra.models import MicrosoftEntraProvider
|
||||||
from authentik.events.utils import sanitize_item
|
from authentik.events.utils import sanitize_item
|
||||||
from authentik.lib.sync.outgoing import HTTP_CONFLICT
|
from authentik.lib.sync.outgoing import HTTP_CONFLICT
|
||||||
from authentik.lib.sync.outgoing.base import SAFE_METHODS, BaseOutgoingSyncClient
|
from authentik.lib.sync.outgoing.base import BaseOutgoingSyncClient
|
||||||
from authentik.lib.sync.outgoing.exceptions import (
|
from authentik.lib.sync.outgoing.exceptions import (
|
||||||
BadRequestSyncException,
|
BadRequestSyncException,
|
||||||
DryRunRejected,
|
|
||||||
NotFoundSyncException,
|
NotFoundSyncException,
|
||||||
ObjectExistsSyncException,
|
ObjectExistsSyncException,
|
||||||
StopSync,
|
StopSync,
|
||||||
@ -39,24 +35,20 @@ from authentik.lib.sync.outgoing.exceptions import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class AuthentikRequestAdapter(GraphRequestAdapter):
|
def get_request_adapter(
|
||||||
def __init__(self, auth_provider, provider: MicrosoftEntraProvider, client=None):
|
credentials: ClientSecretCredential, scopes: list[str] | None = None
|
||||||
super().__init__(auth_provider, client)
|
) -> GraphRequestAdapter:
|
||||||
self._provider = provider
|
if scopes:
|
||||||
|
auth_provider = AzureIdentityAuthenticationProvider(credentials=credentials, scopes=scopes)
|
||||||
|
else:
|
||||||
|
auth_provider = AzureIdentityAuthenticationProvider(credentials=credentials)
|
||||||
|
|
||||||
async def get_http_response_message(
|
return GraphRequestAdapter(
|
||||||
self,
|
auth_provider=auth_provider,
|
||||||
request_info: RequestInformation,
|
client=GraphClientFactory.create_with_default_middleware(
|
||||||
parent_span: trace.Span,
|
options=options, client=KiotaClientFactory.get_default_client()
|
||||||
claims: str = "",
|
),
|
||||||
) -> httpx.Response:
|
|
||||||
if self._provider.dry_run and request_info.http_method.value.upper() not in SAFE_METHODS:
|
|
||||||
raise DryRunRejected(
|
|
||||||
url=request_info.url,
|
|
||||||
method=request_info.http_method.value,
|
|
||||||
body=request_info.content.decode("utf-8"),
|
|
||||||
)
|
)
|
||||||
return await super().get_http_response_message(request_info, parent_span, claims=claims)
|
|
||||||
|
|
||||||
|
|
||||||
class MicrosoftEntraSyncClient[TModel: Model, TConnection: Model, TSchema: dict](
|
class MicrosoftEntraSyncClient[TModel: Model, TConnection: Model, TSchema: dict](
|
||||||
@ -71,27 +63,9 @@ class MicrosoftEntraSyncClient[TModel: Model, TConnection: Model, TSchema: dict]
|
|||||||
self.credentials = provider.microsoft_credentials()
|
self.credentials = provider.microsoft_credentials()
|
||||||
self.__prefetch_domains()
|
self.__prefetch_domains()
|
||||||
|
|
||||||
def get_request_adapter(
|
|
||||||
self, credentials: ClientSecretCredential, scopes: list[str] | None = None
|
|
||||||
) -> AuthentikRequestAdapter:
|
|
||||||
if scopes:
|
|
||||||
auth_provider = AzureIdentityAuthenticationProvider(
|
|
||||||
credentials=credentials, scopes=scopes
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
auth_provider = AzureIdentityAuthenticationProvider(credentials=credentials)
|
|
||||||
|
|
||||||
return AuthentikRequestAdapter(
|
|
||||||
auth_provider=auth_provider,
|
|
||||||
provider=self.provider,
|
|
||||||
client=GraphClientFactory.create_with_default_middleware(
|
|
||||||
options=options, client=KiotaClientFactory.get_default_client()
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def client(self):
|
def client(self):
|
||||||
return GraphServiceClient(request_adapter=self.get_request_adapter(**self.credentials))
|
return GraphServiceClient(request_adapter=get_request_adapter(**self.credentials))
|
||||||
|
|
||||||
def _request[T](self, request: Coroutine[Any, Any, T]) -> T:
|
def _request[T](self, request: Coroutine[Any, Any, T]) -> T:
|
||||||
try:
|
try:
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
# Generated by Django 5.0.12 on 2025-02-24 19:43
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
(
|
|
||||||
"authentik_providers_microsoft_entra",
|
|
||||||
"0002_microsoftentraprovidergroup_attributes_and_more",
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="microsoftentraprovider",
|
|
||||||
name="dry_run",
|
|
||||||
field=models.BooleanField(
|
|
||||||
default=False,
|
|
||||||
help_text="When enabled, provider will not modify or create objects in the remote system.",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
]
|
|
@ -32,6 +32,7 @@ class MicrosoftEntraUserTests(APITestCase):
|
|||||||
|
|
||||||
@apply_blueprint("system/providers-microsoft-entra.yaml")
|
@apply_blueprint("system/providers-microsoft-entra.yaml")
|
||||||
def setUp(self) -> None:
|
def setUp(self) -> None:
|
||||||
|
|
||||||
# Delete all users and groups as the mocked HTTP responses only return one ID
|
# Delete all users and groups as the mocked HTTP responses only return one ID
|
||||||
# which will cause errors with multiple users
|
# which will cause errors with multiple users
|
||||||
Tenant.objects.update(avatars="none")
|
Tenant.objects.update(avatars="none")
|
||||||
@ -96,38 +97,6 @@ class MicrosoftEntraUserTests(APITestCase):
|
|||||||
self.assertFalse(Event.objects.filter(action=EventAction.SYSTEM_EXCEPTION).exists())
|
self.assertFalse(Event.objects.filter(action=EventAction.SYSTEM_EXCEPTION).exists())
|
||||||
user_create.assert_called_once()
|
user_create.assert_called_once()
|
||||||
|
|
||||||
def test_user_create_dry_run(self):
|
|
||||||
"""Test user creation (dry run)"""
|
|
||||||
self.provider.dry_run = True
|
|
||||||
self.provider.save()
|
|
||||||
uid = generate_id()
|
|
||||||
with (
|
|
||||||
patch(
|
|
||||||
"authentik.enterprise.providers.microsoft_entra.models.MicrosoftEntraProvider.microsoft_credentials",
|
|
||||||
MagicMock(return_value={"credentials": self.creds}),
|
|
||||||
),
|
|
||||||
patch(
|
|
||||||
"msgraph.generated.organization.organization_request_builder.OrganizationRequestBuilder.get",
|
|
||||||
AsyncMock(
|
|
||||||
return_value=OrganizationCollectionResponse(
|
|
||||||
value=[
|
|
||||||
Organization(verified_domains=[VerifiedDomain(name="goauthentik.io")])
|
|
||||||
]
|
|
||||||
)
|
|
||||||
),
|
|
||||||
),
|
|
||||||
):
|
|
||||||
user = User.objects.create(
|
|
||||||
username=uid,
|
|
||||||
name=f"{uid} {uid}",
|
|
||||||
email=f"{uid}@goauthentik.io",
|
|
||||||
)
|
|
||||||
microsoft_user = MicrosoftEntraProviderUser.objects.filter(
|
|
||||||
provider=self.provider, user=user
|
|
||||||
).first()
|
|
||||||
self.assertIsNone(microsoft_user)
|
|
||||||
self.assertFalse(Event.objects.filter(action=EventAction.SYSTEM_EXCEPTION).exists())
|
|
||||||
|
|
||||||
def test_user_not_created(self):
|
def test_user_not_created(self):
|
||||||
"""Test without property mappings, no group is created"""
|
"""Test without property mappings, no group is created"""
|
||||||
self.provider.property_mappings.clear()
|
self.provider.property_mappings.clear()
|
||||||
|
@ -64,8 +64,6 @@ debugger: false
|
|||||||
log_level: info
|
log_level: info
|
||||||
|
|
||||||
session_storage: cache
|
session_storage: cache
|
||||||
sessions:
|
|
||||||
unauthenticated_age: days=1
|
|
||||||
|
|
||||||
error_reporting:
|
error_reporting:
|
||||||
enabled: false
|
enabled: false
|
||||||
|
@ -33,7 +33,6 @@ class SyncObjectSerializer(PassiveSerializer):
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
sync_object_id = CharField()
|
sync_object_id = CharField()
|
||||||
override_dry_run = BooleanField(default=False)
|
|
||||||
|
|
||||||
|
|
||||||
class SyncObjectResultSerializer(PassiveSerializer):
|
class SyncObjectResultSerializer(PassiveSerializer):
|
||||||
@ -99,7 +98,6 @@ class OutgoingSyncProviderStatusMixin:
|
|||||||
page=1,
|
page=1,
|
||||||
provider_pk=provider.pk,
|
provider_pk=provider.pk,
|
||||||
pk=params.validated_data["sync_object_id"],
|
pk=params.validated_data["sync_object_id"],
|
||||||
override_dry_run=params.validated_data["override_dry_run"],
|
|
||||||
).get()
|
).get()
|
||||||
return Response(SyncObjectResultSerializer(instance={"messages": res}).data)
|
return Response(SyncObjectResultSerializer(instance={"messages": res}).data)
|
||||||
|
|
||||||
|
@ -28,14 +28,6 @@ class Direction(StrEnum):
|
|||||||
remove = "remove"
|
remove = "remove"
|
||||||
|
|
||||||
|
|
||||||
SAFE_METHODS = [
|
|
||||||
"GET",
|
|
||||||
"HEAD",
|
|
||||||
"OPTIONS",
|
|
||||||
"TRACE",
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class BaseOutgoingSyncClient[
|
class BaseOutgoingSyncClient[
|
||||||
TModel: "Model", TConnection: "Model", TSchema: dict, TProvider: "OutgoingSyncProvider"
|
TModel: "Model", TConnection: "Model", TSchema: dict, TProvider: "OutgoingSyncProvider"
|
||||||
]:
|
]:
|
||||||
|
@ -21,22 +21,6 @@ class BadRequestSyncException(BaseSyncException):
|
|||||||
"""Exception when invalid data was sent to the remote system"""
|
"""Exception when invalid data was sent to the remote system"""
|
||||||
|
|
||||||
|
|
||||||
class DryRunRejected(BaseSyncException):
|
|
||||||
"""When dry_run is enabled and a provider dropped a mutating request"""
|
|
||||||
|
|
||||||
def __init__(self, url: str, method: str, body: dict):
|
|
||||||
super().__init__()
|
|
||||||
self.url = url
|
|
||||||
self.method = method
|
|
||||||
self.body = body
|
|
||||||
|
|
||||||
def __repr__(self):
|
|
||||||
return self.__str__()
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return f"Dry-run rejected request: {self.method} {self.url}"
|
|
||||||
|
|
||||||
|
|
||||||
class StopSync(BaseSyncException):
|
class StopSync(BaseSyncException):
|
||||||
"""Exception raised when a configuration error should stop the sync process"""
|
"""Exception raised when a configuration error should stop the sync process"""
|
||||||
|
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
from typing import Any, Self
|
from typing import Any, Self
|
||||||
|
|
||||||
import pglock
|
import pglock
|
||||||
from django.db import connection, models
|
from django.db import connection
|
||||||
from django.db.models import Model, QuerySet, TextChoices
|
from django.db.models import Model, QuerySet, TextChoices
|
||||||
from django.utils.translation import gettext_lazy as _
|
|
||||||
|
|
||||||
from authentik.core.models import Group, User
|
from authentik.core.models import Group, User
|
||||||
from authentik.lib.sync.outgoing.base import BaseOutgoingSyncClient
|
from authentik.lib.sync.outgoing.base import BaseOutgoingSyncClient
|
||||||
@ -19,14 +18,6 @@ class OutgoingSyncDeleteAction(TextChoices):
|
|||||||
|
|
||||||
|
|
||||||
class OutgoingSyncProvider(Model):
|
class OutgoingSyncProvider(Model):
|
||||||
"""Base abstract models for providers implementing outgoing sync"""
|
|
||||||
|
|
||||||
dry_run = models.BooleanField(
|
|
||||||
default=False,
|
|
||||||
help_text=_(
|
|
||||||
"When enabled, provider will not modify or create objects in the remote system."
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
abstract = True
|
abstract = True
|
||||||
@ -41,7 +32,7 @@ class OutgoingSyncProvider(Model):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def sync_lock(self) -> pglock.advisory:
|
def sync_lock(self) -> pglock.advisory:
|
||||||
"""Postgres lock for syncing to prevent multiple parallel syncs happening"""
|
"""Postgres lock for syncing SCIM to prevent multiple parallel syncs happening"""
|
||||||
return pglock.advisory(
|
return pglock.advisory(
|
||||||
lock_id=f"goauthentik.io/{connection.schema_name}/providers/outgoing-sync/{str(self.pk)}",
|
lock_id=f"goauthentik.io/{connection.schema_name}/providers/outgoing-sync/{str(self.pk)}",
|
||||||
timeout=0,
|
timeout=0,
|
||||||
|
@ -20,7 +20,6 @@ from authentik.lib.sync.outgoing import PAGE_SIZE, PAGE_TIMEOUT
|
|||||||
from authentik.lib.sync.outgoing.base import Direction
|
from authentik.lib.sync.outgoing.base import Direction
|
||||||
from authentik.lib.sync.outgoing.exceptions import (
|
from authentik.lib.sync.outgoing.exceptions import (
|
||||||
BadRequestSyncException,
|
BadRequestSyncException,
|
||||||
DryRunRejected,
|
|
||||||
StopSync,
|
StopSync,
|
||||||
TransientSyncException,
|
TransientSyncException,
|
||||||
)
|
)
|
||||||
@ -106,9 +105,7 @@ class SyncTasks:
|
|||||||
return
|
return
|
||||||
task.set_status(TaskStatus.SUCCESSFUL, *messages)
|
task.set_status(TaskStatus.SUCCESSFUL, *messages)
|
||||||
|
|
||||||
def sync_objects(
|
def sync_objects(self, object_type: str, page: int, provider_pk: int, **filter):
|
||||||
self, object_type: str, page: int, provider_pk: int, override_dry_run=False, **filter
|
|
||||||
):
|
|
||||||
_object_type = path_to_class(object_type)
|
_object_type = path_to_class(object_type)
|
||||||
self.logger = get_logger().bind(
|
self.logger = get_logger().bind(
|
||||||
provider_type=class_to_path(self._provider_model),
|
provider_type=class_to_path(self._provider_model),
|
||||||
@ -119,10 +116,6 @@ class SyncTasks:
|
|||||||
provider = self._provider_model.objects.filter(pk=provider_pk).first()
|
provider = self._provider_model.objects.filter(pk=provider_pk).first()
|
||||||
if not provider:
|
if not provider:
|
||||||
return messages
|
return messages
|
||||||
# Override dry run mode if requested, however don't save the provider
|
|
||||||
# so that scheduled sync tasks still run in dry_run mode
|
|
||||||
if override_dry_run:
|
|
||||||
provider.dry_run = False
|
|
||||||
try:
|
try:
|
||||||
client = provider.client_for_model(_object_type)
|
client = provider.client_for_model(_object_type)
|
||||||
except TransientSyncException:
|
except TransientSyncException:
|
||||||
@ -139,22 +132,6 @@ class SyncTasks:
|
|||||||
except SkipObjectException:
|
except SkipObjectException:
|
||||||
self.logger.debug("skipping object due to SkipObject", obj=obj)
|
self.logger.debug("skipping object due to SkipObject", obj=obj)
|
||||||
continue
|
continue
|
||||||
except DryRunRejected as exc:
|
|
||||||
messages.append(
|
|
||||||
asdict(
|
|
||||||
LogEvent(
|
|
||||||
_("Dropping mutating request due to dry run"),
|
|
||||||
log_level="info",
|
|
||||||
logger=f"{provider._meta.verbose_name}@{object_type}",
|
|
||||||
attributes={
|
|
||||||
"obj": sanitize_item(obj),
|
|
||||||
"method": exc.method,
|
|
||||||
"url": exc.url,
|
|
||||||
"body": exc.body,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
except BadRequestSyncException as exc:
|
except BadRequestSyncException as exc:
|
||||||
self.logger.warning("failed to sync object", exc=exc, obj=obj)
|
self.logger.warning("failed to sync object", exc=exc, obj=obj)
|
||||||
messages.append(
|
messages.append(
|
||||||
@ -254,10 +231,8 @@ class SyncTasks:
|
|||||||
raise Retry() from exc
|
raise Retry() from exc
|
||||||
except SkipObjectException:
|
except SkipObjectException:
|
||||||
continue
|
continue
|
||||||
except DryRunRejected as exc:
|
|
||||||
self.logger.info("Rejected dry-run event", exc=exc)
|
|
||||||
except StopSync as exc:
|
except StopSync as exc:
|
||||||
self.logger.warning("Stopping sync", exc=exc, provider_pk=provider.pk)
|
self.logger.warning(exc, provider_pk=provider.pk)
|
||||||
|
|
||||||
def sync_signal_m2m(self, group_pk: str, action: str, pk_set: list[int]):
|
def sync_signal_m2m(self, group_pk: str, action: str, pk_set: list[int]):
|
||||||
self.logger = get_logger().bind(
|
self.logger = get_logger().bind(
|
||||||
@ -288,7 +263,5 @@ class SyncTasks:
|
|||||||
raise Retry() from exc
|
raise Retry() from exc
|
||||||
except SkipObjectException:
|
except SkipObjectException:
|
||||||
continue
|
continue
|
||||||
except DryRunRejected as exc:
|
|
||||||
self.logger.info("Rejected dry-run event", exc=exc)
|
|
||||||
except StopSync as exc:
|
except StopSync as exc:
|
||||||
self.logger.warning("Stopping sync", exc=exc, provider_pk=provider.pk)
|
self.logger.warning(exc, provider_pk=provider.pk)
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
"""Base Kubernetes Reconciler"""
|
"""Base Kubernetes Reconciler"""
|
||||||
|
|
||||||
import re
|
|
||||||
from dataclasses import asdict
|
from dataclasses import asdict
|
||||||
from json import dumps
|
from json import dumps
|
||||||
from typing import TYPE_CHECKING, Generic, TypeVar
|
from typing import TYPE_CHECKING, Generic, TypeVar
|
||||||
@ -68,8 +67,7 @@ class KubernetesObjectReconciler(Generic[T]):
|
|||||||
@property
|
@property
|
||||||
def name(self) -> str:
|
def name(self) -> str:
|
||||||
"""Get the name of the object this reconciler manages"""
|
"""Get the name of the object this reconciler manages"""
|
||||||
|
return (
|
||||||
base_name = (
|
|
||||||
self.controller.outpost.config.object_naming_template
|
self.controller.outpost.config.object_naming_template
|
||||||
% {
|
% {
|
||||||
"name": slugify(self.controller.outpost.name),
|
"name": slugify(self.controller.outpost.name),
|
||||||
@ -77,16 +75,6 @@ class KubernetesObjectReconciler(Generic[T]):
|
|||||||
}
|
}
|
||||||
).lower()
|
).lower()
|
||||||
|
|
||||||
formatted = slugify(base_name)
|
|
||||||
formatted = re.sub(r"[^a-z0-9-]", "-", formatted)
|
|
||||||
formatted = re.sub(r"-+", "-", formatted)
|
|
||||||
formatted = formatted[:63]
|
|
||||||
|
|
||||||
if not formatted:
|
|
||||||
formatted = f"outpost-{self.controller.outpost.uuid.hex}"[:63]
|
|
||||||
|
|
||||||
return formatted
|
|
||||||
|
|
||||||
def get_patched_reference_object(self) -> T:
|
def get_patched_reference_object(self) -> T:
|
||||||
"""Get patched reference object"""
|
"""Get patched reference object"""
|
||||||
reference = self.get_reference_object()
|
reference = self.get_reference_object()
|
||||||
@ -124,6 +112,7 @@ class KubernetesObjectReconciler(Generic[T]):
|
|||||||
try:
|
try:
|
||||||
current = self.retrieve()
|
current = self.retrieve()
|
||||||
except (OpenApiException, HTTPError) as exc:
|
except (OpenApiException, HTTPError) as exc:
|
||||||
|
|
||||||
if isinstance(exc, ApiException) and exc.status == HttpResponseNotFound.status_code:
|
if isinstance(exc, ApiException) and exc.status == HttpResponseNotFound.status_code:
|
||||||
self.logger.debug("Failed to get current, triggering recreate")
|
self.logger.debug("Failed to get current, triggering recreate")
|
||||||
raise NeedsRecreate from exc
|
raise NeedsRecreate from exc
|
||||||
@ -167,6 +156,7 @@ class KubernetesObjectReconciler(Generic[T]):
|
|||||||
self.delete(current)
|
self.delete(current)
|
||||||
self.logger.debug("Removing")
|
self.logger.debug("Removing")
|
||||||
except (OpenApiException, HTTPError) as exc:
|
except (OpenApiException, HTTPError) as exc:
|
||||||
|
|
||||||
if isinstance(exc, ApiException) and exc.status == HttpResponseNotFound.status_code:
|
if isinstance(exc, ApiException) and exc.status == HttpResponseNotFound.status_code:
|
||||||
self.logger.debug("Failed to get current, assuming non-existent")
|
self.logger.debug("Failed to get current, assuming non-existent")
|
||||||
return
|
return
|
||||||
|
@ -61,14 +61,9 @@ class KubernetesController(BaseController):
|
|||||||
client: KubernetesClient
|
client: KubernetesClient
|
||||||
connection: KubernetesServiceConnection
|
connection: KubernetesServiceConnection
|
||||||
|
|
||||||
def __init__(
|
def __init__(self, outpost: Outpost, connection: KubernetesServiceConnection) -> None:
|
||||||
self,
|
|
||||||
outpost: Outpost,
|
|
||||||
connection: KubernetesServiceConnection,
|
|
||||||
client: KubernetesClient | None = None,
|
|
||||||
) -> None:
|
|
||||||
super().__init__(outpost, connection)
|
super().__init__(outpost, connection)
|
||||||
self.client = client if client else KubernetesClient(connection)
|
self.client = KubernetesClient(connection)
|
||||||
self.reconcilers = {
|
self.reconcilers = {
|
||||||
SecretReconciler.reconciler_name(): SecretReconciler,
|
SecretReconciler.reconciler_name(): SecretReconciler,
|
||||||
DeploymentReconciler.reconciler_name(): DeploymentReconciler,
|
DeploymentReconciler.reconciler_name(): DeploymentReconciler,
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
"""Kubernetes controller tests"""
|
|
||||||
|
|
||||||
from django.test import TestCase
|
|
||||||
|
|
||||||
from authentik.blueprints.tests import reconcile_app
|
|
||||||
from authentik.lib.generators import generate_id
|
|
||||||
from authentik.outposts.apps import MANAGED_OUTPOST
|
|
||||||
from authentik.outposts.controllers.k8s.deployment import DeploymentReconciler
|
|
||||||
from authentik.outposts.controllers.kubernetes import KubernetesController
|
|
||||||
from authentik.outposts.models import KubernetesServiceConnection, Outpost, OutpostType
|
|
||||||
|
|
||||||
|
|
||||||
class KubernetesControllerTests(TestCase):
|
|
||||||
"""Kubernetes controller tests"""
|
|
||||||
|
|
||||||
@reconcile_app("authentik_outposts")
|
|
||||||
def setUp(self) -> None:
|
|
||||||
self.outpost = Outpost.objects.create(
|
|
||||||
name="test",
|
|
||||||
type=OutpostType.PROXY,
|
|
||||||
)
|
|
||||||
self.integration = KubernetesServiceConnection(name="test")
|
|
||||||
|
|
||||||
def test_gen_name(self):
|
|
||||||
"""Ensure the generated name is valid"""
|
|
||||||
controller = KubernetesController(
|
|
||||||
Outpost.objects.filter(managed=MANAGED_OUTPOST).first(),
|
|
||||||
self.integration,
|
|
||||||
# Pass something not-none as client so we don't
|
|
||||||
# attempt to connect to K8s as that's not needed
|
|
||||||
client=self,
|
|
||||||
)
|
|
||||||
rec = DeploymentReconciler(controller)
|
|
||||||
self.assertEqual(rec.name, "ak-outpost-authentik-embedded-outpost")
|
|
||||||
|
|
||||||
controller.outpost.name = generate_id()
|
|
||||||
self.assertLess(len(rec.name), 64)
|
|
||||||
|
|
||||||
# Test custom naming template
|
|
||||||
_cfg = controller.outpost.config
|
|
||||||
_cfg.object_naming_template = ""
|
|
||||||
controller.outpost.config = _cfg
|
|
||||||
self.assertEqual(rec.name, f"outpost-{controller.outpost.uuid.hex}")
|
|
||||||
self.assertLess(len(rec.name), 64)
|
|
@ -9,12 +9,7 @@ from hashlib import sha256
|
|||||||
from typing import Any
|
from typing import Any
|
||||||
from urllib.parse import urlparse, urlunparse
|
from urllib.parse import urlparse, urlunparse
|
||||||
|
|
||||||
from cryptography.hazmat.primitives.asymmetric.ec import (
|
from cryptography.hazmat.primitives.asymmetric.ec import EllipticCurvePrivateKey
|
||||||
SECP256R1,
|
|
||||||
SECP384R1,
|
|
||||||
SECP521R1,
|
|
||||||
EllipticCurvePrivateKey,
|
|
||||||
)
|
|
||||||
from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey
|
from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey
|
||||||
from cryptography.hazmat.primitives.asymmetric.types import PrivateKeyTypes
|
from cryptography.hazmat.primitives.asymmetric.types import PrivateKeyTypes
|
||||||
from dacite import Config
|
from dacite import Config
|
||||||
@ -119,22 +114,6 @@ class JWTAlgorithms(models.TextChoices):
|
|||||||
HS256 = "HS256", _("HS256 (Symmetric Encryption)")
|
HS256 = "HS256", _("HS256 (Symmetric Encryption)")
|
||||||
RS256 = "RS256", _("RS256 (Asymmetric Encryption)")
|
RS256 = "RS256", _("RS256 (Asymmetric Encryption)")
|
||||||
ES256 = "ES256", _("ES256 (Asymmetric Encryption)")
|
ES256 = "ES256", _("ES256 (Asymmetric Encryption)")
|
||||||
ES384 = "ES384", _("ES384 (Asymmetric Encryption)")
|
|
||||||
ES512 = "ES512", _("ES512 (Asymmetric Encryption)")
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def from_private_key(cls, private_key: PrivateKeyTypes | None) -> str:
|
|
||||||
if isinstance(private_key, RSAPrivateKey):
|
|
||||||
return cls.RS256
|
|
||||||
if isinstance(private_key, EllipticCurvePrivateKey):
|
|
||||||
curve = private_key.curve
|
|
||||||
if isinstance(curve, SECP256R1):
|
|
||||||
return cls.ES256
|
|
||||||
if isinstance(curve, SECP384R1):
|
|
||||||
return cls.ES384
|
|
||||||
if isinstance(curve, SECP521R1):
|
|
||||||
return cls.ES512
|
|
||||||
raise ValueError(f"Invalid private key type: {type(private_key)}")
|
|
||||||
|
|
||||||
|
|
||||||
class ScopeMapping(PropertyMapping):
|
class ScopeMapping(PropertyMapping):
|
||||||
@ -284,7 +263,11 @@ class OAuth2Provider(WebfingerProvider, Provider):
|
|||||||
return self.client_secret, JWTAlgorithms.HS256
|
return self.client_secret, JWTAlgorithms.HS256
|
||||||
key: CertificateKeyPair = self.signing_key
|
key: CertificateKeyPair = self.signing_key
|
||||||
private_key = key.private_key
|
private_key = key.private_key
|
||||||
return private_key, JWTAlgorithms.from_private_key(private_key)
|
if isinstance(private_key, RSAPrivateKey):
|
||||||
|
return private_key, JWTAlgorithms.RS256
|
||||||
|
if isinstance(private_key, EllipticCurvePrivateKey):
|
||||||
|
return private_key, JWTAlgorithms.ES256
|
||||||
|
raise ValueError(f"Invalid private key type: {type(private_key)}")
|
||||||
|
|
||||||
def get_issuer(self, request: HttpRequest) -> str | None:
|
def get_issuer(self, request: HttpRequest) -> str | None:
|
||||||
"""Get issuer, based on request"""
|
"""Get issuer, based on request"""
|
||||||
|
@ -254,10 +254,10 @@ class OAuthAuthorizationParams:
|
|||||||
raise AuthorizeError(self.redirect_uri, "invalid_scope", self.grant_type, self.state)
|
raise AuthorizeError(self.redirect_uri, "invalid_scope", self.grant_type, self.state)
|
||||||
if SCOPE_OFFLINE_ACCESS in self.scope:
|
if SCOPE_OFFLINE_ACCESS in self.scope:
|
||||||
# https://openid.net/specs/openid-connect-core-1_0.html#OfflineAccess
|
# https://openid.net/specs/openid-connect-core-1_0.html#OfflineAccess
|
||||||
# Don't explicitly request consent with offline_access, as the spec allows for
|
if PROMPT_CONSENT not in self.prompt:
|
||||||
# "other conditions for processing the request permitting offline access to the
|
# Instead of ignoring the `offline_access` scope when `prompt`
|
||||||
# requested resources are in place"
|
# isn't set to `consent`, we set override it ourselves
|
||||||
# which we interpret as "the admin picks an authorization flow with or without consent"
|
self.prompt.add(PROMPT_CONSENT)
|
||||||
if self.response_type not in [
|
if self.response_type not in [
|
||||||
ResponseTypes.CODE,
|
ResponseTypes.CODE,
|
||||||
ResponseTypes.CODE_TOKEN,
|
ResponseTypes.CODE_TOKEN,
|
||||||
|
@ -75,7 +75,10 @@ class JWKSView(View):
|
|||||||
key_data = {}
|
key_data = {}
|
||||||
|
|
||||||
if use == "sig":
|
if use == "sig":
|
||||||
key_data["alg"] = JWTAlgorithms.from_private_key(private_key)
|
if isinstance(private_key, RSAPrivateKey):
|
||||||
|
key_data["alg"] = JWTAlgorithms.RS256
|
||||||
|
elif isinstance(private_key, EllipticCurvePrivateKey):
|
||||||
|
key_data["alg"] = JWTAlgorithms.ES256
|
||||||
elif use == "enc":
|
elif use == "enc":
|
||||||
key_data["alg"] = "RSA-OAEP-256"
|
key_data["alg"] = "RSA-OAEP-256"
|
||||||
key_data["enc"] = "A256CBC-HS512"
|
key_data["enc"] = "A256CBC-HS512"
|
||||||
|
@ -28,10 +28,8 @@ class SCIMProviderSerializer(ProviderSerializer):
|
|||||||
"url",
|
"url",
|
||||||
"verify_certificates",
|
"verify_certificates",
|
||||||
"token",
|
"token",
|
||||||
"compatibility_mode",
|
|
||||||
"exclude_users_service_account",
|
"exclude_users_service_account",
|
||||||
"filter_group",
|
"filter_group",
|
||||||
"dry_run",
|
|
||||||
]
|
]
|
||||||
extra_kwargs = {}
|
extra_kwargs = {}
|
||||||
|
|
||||||
|
@ -12,9 +12,8 @@ from authentik.lib.sync.outgoing import (
|
|||||||
HTTP_SERVICE_UNAVAILABLE,
|
HTTP_SERVICE_UNAVAILABLE,
|
||||||
HTTP_TOO_MANY_REQUESTS,
|
HTTP_TOO_MANY_REQUESTS,
|
||||||
)
|
)
|
||||||
from authentik.lib.sync.outgoing.base import SAFE_METHODS, BaseOutgoingSyncClient
|
from authentik.lib.sync.outgoing.base import BaseOutgoingSyncClient
|
||||||
from authentik.lib.sync.outgoing.exceptions import (
|
from authentik.lib.sync.outgoing.exceptions import (
|
||||||
DryRunRejected,
|
|
||||||
NotFoundSyncException,
|
NotFoundSyncException,
|
||||||
ObjectExistsSyncException,
|
ObjectExistsSyncException,
|
||||||
TransientSyncException,
|
TransientSyncException,
|
||||||
@ -22,7 +21,7 @@ from authentik.lib.sync.outgoing.exceptions import (
|
|||||||
from authentik.lib.utils.http import get_http_session
|
from authentik.lib.utils.http import get_http_session
|
||||||
from authentik.providers.scim.clients.exceptions import SCIMRequestException
|
from authentik.providers.scim.clients.exceptions import SCIMRequestException
|
||||||
from authentik.providers.scim.clients.schema import ServiceProviderConfiguration
|
from authentik.providers.scim.clients.schema import ServiceProviderConfiguration
|
||||||
from authentik.providers.scim.models import SCIMCompatibilityMode, SCIMProvider
|
from authentik.providers.scim.models import SCIMProvider
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from django.db.models import Model
|
from django.db.models import Model
|
||||||
@ -55,8 +54,6 @@ class SCIMClient[TModel: "Model", TConnection: "Model", TSchema: "BaseModel"](
|
|||||||
|
|
||||||
def _request(self, method: str, path: str, **kwargs) -> dict:
|
def _request(self, method: str, path: str, **kwargs) -> dict:
|
||||||
"""Wrapper to send a request to the full URL"""
|
"""Wrapper to send a request to the full URL"""
|
||||||
if self.provider.dry_run and method.upper() not in SAFE_METHODS:
|
|
||||||
raise DryRunRejected(f"{self.base_url}{path}", method, body=kwargs.get("json"))
|
|
||||||
try:
|
try:
|
||||||
response = self._session.request(
|
response = self._session.request(
|
||||||
method,
|
method,
|
||||||
@ -90,14 +87,9 @@ class SCIMClient[TModel: "Model", TConnection: "Model", TSchema: "BaseModel"](
|
|||||||
"""Get Service provider config"""
|
"""Get Service provider config"""
|
||||||
default_config = ServiceProviderConfiguration.default()
|
default_config = ServiceProviderConfiguration.default()
|
||||||
try:
|
try:
|
||||||
config = ServiceProviderConfiguration.model_validate(
|
return ServiceProviderConfiguration.model_validate(
|
||||||
self._request("GET", "/ServiceProviderConfig")
|
self._request("GET", "/ServiceProviderConfig")
|
||||||
)
|
)
|
||||||
if self.provider.compatibility_mode == SCIMCompatibilityMode.AWS:
|
|
||||||
config.patch.supported = False
|
|
||||||
if self.provider.compatibility_mode == SCIMCompatibilityMode.SLACK:
|
|
||||||
config.filter.supported = True
|
|
||||||
return config
|
|
||||||
except (ValidationError, SCIMRequestException, NotFoundSyncException) as exc:
|
except (ValidationError, SCIMRequestException, NotFoundSyncException) as exc:
|
||||||
self.logger.warning("failed to get ServiceProviderConfig", exc=exc)
|
self.logger.warning("failed to get ServiceProviderConfig", exc=exc)
|
||||||
return default_config
|
return default_config
|
||||||
|
@ -243,6 +243,7 @@ class SCIMGroupClient(SCIMClient[Group, SCIMProviderGroup, SCIMGroupSchema]):
|
|||||||
if user.value not in users_should:
|
if user.value not in users_should:
|
||||||
users_to_remove.append(user.value)
|
users_to_remove.append(user.value)
|
||||||
# Check users that should be in the group and add them
|
# Check users that should be in the group and add them
|
||||||
|
if current_group.members is not None:
|
||||||
for user in users_should:
|
for user in users_should:
|
||||||
if len([x for x in current_group.members if x.value == user]) < 1:
|
if len([x for x in current_group.members if x.value == user]) < 1:
|
||||||
users_to_add.append(user)
|
users_to_add.append(user)
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
# Generated by Django 5.0.12 on 2025-02-24 19:43
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
("authentik_providers_scim", "0010_scimprovider_verify_certificates"),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="scimprovider",
|
|
||||||
name="dry_run",
|
|
||||||
field=models.BooleanField(
|
|
||||||
default=False,
|
|
||||||
help_text="When enabled, provider will not modify or create objects in the remote system.",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
]
|
|
@ -1,24 +0,0 @@
|
|||||||
# Generated by Django 5.0.12 on 2025-03-07 23:35
|
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
("authentik_providers_scim", "0011_scimprovider_dry_run"),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AddField(
|
|
||||||
model_name="scimprovider",
|
|
||||||
name="compatibility_mode",
|
|
||||||
field=models.CharField(
|
|
||||||
choices=[("default", "Default"), ("aws", "AWS"), ("slack", "Slack")],
|
|
||||||
default="default",
|
|
||||||
help_text="Alter authentik behavior for vendor-specific SCIM implementations.",
|
|
||||||
max_length=30,
|
|
||||||
verbose_name="SCIM Compatibility Mode",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
]
|
|
@ -57,14 +57,6 @@ class SCIMProviderGroup(SerializerModel):
|
|||||||
return f"SCIM Provider Group {self.group_id} to {self.provider_id}"
|
return f"SCIM Provider Group {self.group_id} to {self.provider_id}"
|
||||||
|
|
||||||
|
|
||||||
class SCIMCompatibilityMode(models.TextChoices):
|
|
||||||
"""SCIM compatibility mode"""
|
|
||||||
|
|
||||||
DEFAULT = "default", _("Default")
|
|
||||||
AWS = "aws", _("AWS")
|
|
||||||
SLACK = "slack", _("Slack")
|
|
||||||
|
|
||||||
|
|
||||||
class SCIMProvider(OutgoingSyncProvider, BackchannelProvider):
|
class SCIMProvider(OutgoingSyncProvider, BackchannelProvider):
|
||||||
"""SCIM 2.0 provider to create users and groups in external applications"""
|
"""SCIM 2.0 provider to create users and groups in external applications"""
|
||||||
|
|
||||||
@ -85,14 +77,6 @@ class SCIMProvider(OutgoingSyncProvider, BackchannelProvider):
|
|||||||
help_text=_("Property mappings used for group creation/updating."),
|
help_text=_("Property mappings used for group creation/updating."),
|
||||||
)
|
)
|
||||||
|
|
||||||
compatibility_mode = models.CharField(
|
|
||||||
max_length=30,
|
|
||||||
choices=SCIMCompatibilityMode.choices,
|
|
||||||
default=SCIMCompatibilityMode.DEFAULT,
|
|
||||||
verbose_name=_("SCIM Compatibility Mode"),
|
|
||||||
help_text=_("Alter authentik behavior for vendor-specific SCIM implementations."),
|
|
||||||
)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def icon_url(self) -> str | None:
|
def icon_url(self) -> str | None:
|
||||||
return static("authentik/sources/scim.png")
|
return static("authentik/sources/scim.png")
|
||||||
|
@ -3,15 +3,12 @@
|
|||||||
from json import loads
|
from json import loads
|
||||||
|
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.utils.text import slugify
|
|
||||||
from jsonschema import validate
|
from jsonschema import validate
|
||||||
from requests_mock import Mocker
|
from requests_mock import Mocker
|
||||||
|
|
||||||
from authentik.blueprints.tests import apply_blueprint
|
from authentik.blueprints.tests import apply_blueprint
|
||||||
from authentik.core.models import Application, Group, User
|
from authentik.core.models import Application, Group, User
|
||||||
from authentik.events.models import SystemTask
|
|
||||||
from authentik.lib.generators import generate_id
|
from authentik.lib.generators import generate_id
|
||||||
from authentik.lib.sync.outgoing.base import SAFE_METHODS
|
|
||||||
from authentik.providers.scim.models import SCIMMapping, SCIMProvider
|
from authentik.providers.scim.models import SCIMMapping, SCIMProvider
|
||||||
from authentik.providers.scim.tasks import scim_sync, sync_tasks
|
from authentik.providers.scim.tasks import scim_sync, sync_tasks
|
||||||
from authentik.tenants.models import Tenant
|
from authentik.tenants.models import Tenant
|
||||||
@ -333,59 +330,3 @@ class SCIMUserTests(TestCase):
|
|||||||
"userName": uid,
|
"userName": uid,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_user_create_dry_run(self):
|
|
||||||
"""Test user creation (dry_run)"""
|
|
||||||
# Update the provider before we start mocking as saving the provider triggers a full sync
|
|
||||||
self.provider.dry_run = True
|
|
||||||
self.provider.save()
|
|
||||||
with Mocker() as mock:
|
|
||||||
scim_id = generate_id()
|
|
||||||
mock.get(
|
|
||||||
"https://localhost/ServiceProviderConfig",
|
|
||||||
json={},
|
|
||||||
)
|
|
||||||
mock.post(
|
|
||||||
"https://localhost/Users",
|
|
||||||
json={
|
|
||||||
"id": scim_id,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
uid = generate_id()
|
|
||||||
User.objects.create(
|
|
||||||
username=uid,
|
|
||||||
name=f"{uid} {uid}",
|
|
||||||
email=f"{uid}@goauthentik.io",
|
|
||||||
)
|
|
||||||
self.assertEqual(mock.call_count, 1, mock.request_history)
|
|
||||||
self.assertEqual(mock.request_history[0].method, "GET")
|
|
||||||
|
|
||||||
def test_sync_task_dry_run(self):
|
|
||||||
"""Test sync tasks"""
|
|
||||||
# Update the provider before we start mocking as saving the provider triggers a full sync
|
|
||||||
self.provider.dry_run = True
|
|
||||||
self.provider.save()
|
|
||||||
with Mocker() as mock:
|
|
||||||
uid = generate_id()
|
|
||||||
mock.get(
|
|
||||||
"https://localhost/ServiceProviderConfig",
|
|
||||||
json={},
|
|
||||||
)
|
|
||||||
User.objects.create(
|
|
||||||
username=uid,
|
|
||||||
name=f"{uid} {uid}",
|
|
||||||
email=f"{uid}@goauthentik.io",
|
|
||||||
)
|
|
||||||
|
|
||||||
sync_tasks.trigger_single_task(self.provider, scim_sync).get()
|
|
||||||
|
|
||||||
self.assertEqual(mock.call_count, 3)
|
|
||||||
for request in mock.request_history:
|
|
||||||
self.assertIn(request.method, SAFE_METHODS)
|
|
||||||
task = SystemTask.objects.filter(uid=slugify(self.provider.name)).first()
|
|
||||||
self.assertIsNotNone(task)
|
|
||||||
drop_msg = task.messages[2]
|
|
||||||
self.assertEqual(drop_msg["event"], "Dropping mutating request due to dry run")
|
|
||||||
self.assertIsNotNone(drop_msg["attributes"]["url"])
|
|
||||||
self.assertIsNotNone(drop_msg["attributes"]["body"])
|
|
||||||
self.assertIsNotNone(drop_msg["attributes"]["method"])
|
|
||||||
|
@ -16,7 +16,6 @@ from authentik.lib.config import CONFIG, django_db_config, redis_url
|
|||||||
from authentik.lib.logging import get_logger_config, structlog_configure
|
from authentik.lib.logging import get_logger_config, structlog_configure
|
||||||
from authentik.lib.sentry import sentry_init
|
from authentik.lib.sentry import sentry_init
|
||||||
from authentik.lib.utils.reflection import get_env
|
from authentik.lib.utils.reflection import get_env
|
||||||
from authentik.lib.utils.time import timedelta_from_string
|
|
||||||
from authentik.stages.password import BACKEND_APP_PASSWORD, BACKEND_INBUILT, BACKEND_LDAP
|
from authentik.stages.password import BACKEND_APP_PASSWORD, BACKEND_INBUILT, BACKEND_LDAP
|
||||||
|
|
||||||
BASE_DIR = Path(__file__).absolute().parent.parent.parent
|
BASE_DIR = Path(__file__).absolute().parent.parent.parent
|
||||||
@ -243,9 +242,6 @@ SESSION_CACHE_ALIAS = "default"
|
|||||||
# Configured via custom SessionMiddleware
|
# Configured via custom SessionMiddleware
|
||||||
# SESSION_COOKIE_SAMESITE = "None"
|
# SESSION_COOKIE_SAMESITE = "None"
|
||||||
# SESSION_COOKIE_SECURE = True
|
# SESSION_COOKIE_SECURE = True
|
||||||
SESSION_COOKIE_AGE = timedelta_from_string(
|
|
||||||
CONFIG.get("sessions.unauthenticated_age", "days=1")
|
|
||||||
).total_seconds()
|
|
||||||
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
|
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
|
||||||
|
|
||||||
MESSAGE_STORAGE = "authentik.root.messages.storage.ChannelsStorage"
|
MESSAGE_STORAGE = "authentik.root.messages.storage.ChannelsStorage"
|
||||||
|
@ -25,10 +25,8 @@ class RedditOAuth2Client(UserprofileHeaderAuthClient):
|
|||||||
|
|
||||||
def get_access_token(self, **request_kwargs):
|
def get_access_token(self, **request_kwargs):
|
||||||
"Fetch access token from callback request."
|
"Fetch access token from callback request."
|
||||||
request_kwargs["auth"] = HTTPBasicAuth(
|
auth = HTTPBasicAuth(self.source.consumer_key, self.source.consumer_secret)
|
||||||
self.source.consumer_key, self.source.consumer_secret
|
return super().get_access_token(auth=auth)
|
||||||
)
|
|
||||||
return super().get_access_token(**request_kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class RedditOAuth2Callback(OAuthCallback):
|
class RedditOAuth2Callback(OAuthCallback):
|
||||||
|
@ -299,6 +299,12 @@ class TestAuthenticatorEmailStage(FlowTestCase):
|
|||||||
data={"component": "ak-stage-authenticator-email", "code": device.token},
|
data={"component": "ak-stage-authenticator-email", "code": device.token},
|
||||||
)
|
)
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertTrue(device.confirmed)
|
||||||
|
# Get a fresh session to check if the key was removed
|
||||||
|
session = self.client.session
|
||||||
|
session.save()
|
||||||
|
session.load()
|
||||||
|
self.assertNotIn(SESSION_KEY_EMAIL_DEVICE, session)
|
||||||
|
|
||||||
def test_model_properties_and_methods(self):
|
def test_model_properties_and_methods(self):
|
||||||
"""Test model properties"""
|
"""Test model properties"""
|
||||||
@ -325,6 +331,7 @@ class TestAuthenticatorEmailStage(FlowTestCase):
|
|||||||
self.stage.send(device)
|
self.stage.send(device)
|
||||||
|
|
||||||
def test_email_tasks(self):
|
def test_email_tasks(self):
|
||||||
|
|
||||||
email_send_mock = MagicMock()
|
email_send_mock = MagicMock()
|
||||||
with patch(
|
with patch(
|
||||||
"authentik.stages.email.tasks.send_mails",
|
"authentik.stages.email.tasks.send_mails",
|
||||||
|
@ -146,10 +146,5 @@
|
|||||||
"name": "LogMeOnce",
|
"name": "LogMeOnce",
|
||||||
"icon_dark": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcgdmVyc2lvbj0iMS4xIiB2aWV3Qm94PSIwIDAgMjA0OCAyMDQ4IiB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTSAwIDAgTCAtNSAxIEwgLTE1IDQgTCAtMzggMTEgTCAtNTcgMTggTCAtNzYgMjkgTCAtOTAgMzggTCAtMTA5IDUyIEwgLTExNiA1OSBMIC0xMjcgNjggTCAtMTQwIDgxIEwgLTE0OCA4OCBMIC0xNDkgOTEgTCAtMTUxIDkxIEwgLTE2MSAxMDEgTCAtMTY5IDEwOCBMIC0xNjkgMTEwIEwgLTE3MSAxMTAgTCAtMTgwIDExOSBMIC0xODggMTI2IEwgLTIwMSAxMzcgTCAtMjEyIDE0NiBMIC0yMjYgMTU3IEwgLTIzOSAxNjcgTCAtMjUwIDE3NSBMIC0yNzAgMTg4IEwgLTI5MSAyMDIgTCAtMzA5IDIxMiBMIC0zMzAgMjI0IEwgLTM1MyAyMzUgTCAtMzg2IDI1MCBMIC00MDcgMjU5IEwgLTQ0OSAyNzMgTCAtNDcyIDI4MSBMIC01MDIgMjg5IEwgLTU1MSAyOTggTCAtNjE1IDMwOSBMIC02NDcgMzE2IEwgLTY4MSAzMjQgTCAtNjk4IDMzMCBMIC03MTQgMzM4IEwgLTczNSAzNTEgTCAtNzQ1IDM1OCBMIC03NTYgMzY3IEwgLTc2NCAzNzUgTCAtNzY2IDM3OSBMIC03NjggMzc5IEwgLTc3MyAzODUgTCAtNzgxIDM5NSBMIC03OTEgNDEwIEwgLTgwMSA0MjggTCAtODEwIDQ0NyBMIC04MTYgNDY1IEwgLTgyMiA1MDAgTCAtODI3IDU0NSBMIC04MzAgNTkyIEwgLTgzMiA2NTMgTCAtODMyIDcxMiBMIC04MzEgNzQyIEwgLTgyOCA3OTQgTCAtODIyIDg2NiBMIC04MTYgOTI4IEwgLTgxMiA5NTcgTCAtODAwIDEwMjAgTCAtNzg5IDEwNzIgTCAtNzgzIDEwOTggTCAtNzY1IDExNjIgTCAtNzUxIDEyMDcgTCAtNzQ0IDEyMjUgTCAtNzM0IDEyNTQgTCAtNzIwIDEyOTAgTCAtNzA0IDEzMjggTCAtNjg5IDEzNjEgTCAtNjY4IDE0MDMgTCAtNjUzIDE0MzEgTCAtNjM5IDE0NTYgTCAtNjIwIDE0ODggTCAtNjA3IDE1MDkgTCAtNTk0IDE1MjkgTCAtNTg0IDE1NDQgTCAtNTcxIDE1NjMgTCAtNTU4IDE1ODEgTCAtNTQ0IDE2MDAgTCAtNTMzIDE2MTUgTCAtNTIwIDE2MzIgTCAtNTA3IDE2NDggTCAtNDc5IDE2ODIgTCAtNDcwIDE2OTMgTCAtNDYwIDE3MDQgTCAtNDQ5IDE3MTYgTCAtNDQyIDE3MjQgTCAtNDMyIDE3MzQgTCAtNDI1IDE3NDIgTCAtMzY4IDE3OTkgTCAtMzUxIDE4MTUgTCAtMzM1IDE4MzAgTCAtMzI3IDE4MzcgTCAtMzE0IDE4NDkgTCAtMjg4IDE4NzEgTCAtMjcxIDE4ODUgTCAtMjYxIDE4OTMgTCAtMjQ0IDE5MDcgTCAtMjI4IDE5MTkgTCAtMjE1IDE5MjkgTCAtMTk2IDE5NDMgTCAtMTg0IDE5NTIgTCAtMTY4IDE5NjMgTCAtMTQ4IDE5NzcgTCAtMTMzIDE5ODcgTCAtMTEyIDIwMDAgTCAtODggMjAxMyBMIC03MiAyMDIxIEwgLTUyIDIwMzAgTCAtMzIgMjAzNyBMIDEyIDIwNDggTCA2MCAyMDQ4IEwgNjEgMjA0NyBMIDczIDIwNDQgTCAxMDAgMjAzNyBMIDEyMSAyMDI5IEwgMTQ5IDIwMTUgTCAxNjcgMjAwNSBMIDE4NiAxOTk0IEwgMjEwIDE5NzkgTCAyMzEgMTk2NSBMIDI2NiAxOTQxIEwgMjg0IDE5MjggTCAyOTUgMTkyMCBMIDMwNiAxOTExIEwgMzI0IDE4OTggTCAzMzggMTg4NyBMIDM0OSAxODc3IEwgMzU4IDE4NzAgTCAzNjkgMTg2MCBMIDM4MCAxODUxIEwgMzgwIDE4NDkgTCAzODIgMTg0OSBMIDM4NSAxODQ2IEwgMzk2IDE4MzcgTCA0MDMgMTgzMCBMIDQxMSAxODIzIEwgNDE4IDE4MTYgTCA0MjYgMTgwOSBMIDQ3NSAxNzYwIEwgNDc3IDE3NTYgTCA0NzkgMTc1NiBMIDQ4NyAxNzQ3IEwgNTAzIDE3MzAgTCA1MTAgMTcyMiBMIDUxOSAxNzEyIEwgNTI2IDE3MDQgTCA1MzggMTY5MSBMIDU0NyAxNjgwIEwgNTU4IDE2NjcgTCA1NjYgMTY1NiBMIDU3OSAxNjQwIEwgNTkwIDE2MjYgTCA2MDYgMTYwNSBMIDYyMSAxNTgzIEwgNjMxIDE1NjkgTCA2NDUgMTU0OSBMIDY1NSAxNTMzIEwgNjcwIDE1MTAgTCA2ODUgMTQ4NSBMIDY5NiAxNDY3IEwgNzA2IDE0NDkgTCA3MzAgMTQwNSBMIDc0NSAxMzc0IEwgNzYyIDEzMzggTCA3NzQgMTMxMCBMIDc5MiAxMjY3IEwgODExIDEyMTYgTCA4MjcgMTE2NiBMIDg0MiAxMTE3IEwgODU4IDEwNTEgTCA4NzAgOTk2IEwgODc1IDk2NyBMIDg4MSA5MTcgTCA4ODYgODgyIEwgODkxIDg0NiBMIDg5NCA4MTIgTCA4OTYgNzc0IEwgODk2IDY1NSBMIDg5NSA2MzAgTCA4OTIgNTkzIEwgODg4IDU1OSBMIDg3NyA0NzAgTCA4NzIgNDQ1IEwgODY1IDQyNiBMIDg1NyA0MTEgTCA4NDcgMzk1IEwgODM0IDM3OCBMIDgxNCAzNTggTCA4MDAgMzQ3IEwgNzg1IDMzNyBMIDc2NiAzMjcgTCA3NTAgMzIxIEwgNzI3IDMxNSBMIDY5MyAzMDggTCA2NTAgMzAxIEwgNTk3IDI5MiBMIDU3MCAyODYgTCA1NDggMjgwIEwgNTE1IDI3MCBMIDQ4NyAyNjEgTCA0NTkgMjUwIEwgNDM4IDI0MSBMIDQxNCAyMzAgTCAzODIgMjEzIEwgMzU4IDE5OSBMIDM0NyAxOTIgTCAzMzAgMTgwIEwgMzEyIDE2NyBMIDMwMCAxNTcgTCAyODYgMTQ2IEwgMjcxIDEzMyBMIDI2MyAxMjYgTCAyNTEgMTE1IEwgMjQwIDEwNiBMIDIyOCA5NSBMIDIwMCA3MSBMIDE4OSA2MiBMIDE3NCA1MCBMIDE1OCAzOCBMIDE0MiAyNyBMIDEyNyAxOSBMIDExNSAxNCBMIDk1IDggTCA3MSAwIEwgMCAwIHogTSAzMCA2MjIgTCA1MSA2MjMgTCA3OSA2MjcgTCAxMDAgNjMzIEwgMTIxIDY0MSBMIDE0MSA2NTIgTCAxNTcgNjYzIEwgMTcyIDY3NiBMIDE4NiA2OTAgTCAxODYgNjkyIEwgMTg4IDY5MiBMIDIwNiA3MTYgTCAyMTYgNzM0IEwgMjIxIDc0NSBMIDIyNiA3NTggTCAyMzMgNzg0IEwgMjM2IDc5OCBMIDIzNyA4MDggTCAyMzcgODQwIEwgMjMzIDg2NSBMIDIyNiA4OTEgTCAyMTkgOTA5IEwgMjA5IDkyOCBMIDE5NSA5NDkgTCAxODYgOTU5IEwgMTc5IDk2NyBMIDE2NiA5ODAgTCAxNTUgOTg5IEwgMTQyIDk5OCBMIDEyNiAxMDA3IEwgMTEzIDEwMTIgTCAxMTQgMTAyNCBMIDEyMiAxMDYwIEwgMTM3IDExMjMgTCAxNTYgMTIwOCBMIDE3MCAxMjcxIEwgMTc0IDEyOTYgTCAxNzYgMTMxMCBMIDE3NiAxMzM1IEwgMTczIDEzNDkgTCAxNjYgMTM1OSBMIDE1NyAxMzY3IEwgMTQ2IDEzNzIgTCAxNDAgMTM3NCBMIDExOSAxMzc2IEwgNTEgMTM3NiBMIC0zMiAxMzc3IEwgLTY0IDEzNzcgTCAtNzggMTM3NCBMIC04NSAxMzcwIEwgLTk4IDEzNTkgTCAtMTA2IDEzNDkgTCAtMTEwIDEzNDEgTCAtMTEyIDEzMzMgTCAtMTEyIDEzMTggTCAtMTA3IDEyODggTCAtMTAwIDEyNTYgTCAtODUgMTE5NiBMIC02OSAxMTI0IEwgLTU3IDEwNzIgTCAtNTAgMTAzNiBMIC00NyAxMDExIEwgLTUzIDEwMDkgTCAtNjkgMTAwMSBMIC04MSA5OTQgTCAtOTMgOTg1IEwgLTEwMyA5NzYgTCAtMTExIDk2OSBMIC0xMjAgOTYwIEwgLTEzMSA5NDYgTCAtMTQyIDkyOSBMIC0xNTIgOTEwIEwgLTE2MCA4OTAgTCAtMTY2IDg3MCBMIC0xNjkgODUzIEwgLTE3MCA4NDQgTCAtMTcwIDgxNCBMIC0xNjcgNzk0IEwgLTE2MSA3NjcgTCAtMTU0IDc0NiBMIC0xMzcgNzEzIEwgLTEyNiA2OTggTCAtMTE5IDY5MCBMIC0xMDggNjc4IEwgLTkzIDY2NSBMIC03NyA2NTMgTCAtNTYgNjQxIEwgLTM4IDYzMyBMIC0xNiA2MjcgTCAzIDYyNCBMIDMwIDYyMiB6ICIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoOTkxKSIgc3R5bGU9ImZpbGw6I2ZmZmZmZiIgLz4KPC9zdmc+Cg==",
|
"icon_dark": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9Im5vIj8+CjxzdmcgdmVyc2lvbj0iMS4xIiB2aWV3Qm94PSIwIDAgMjA0OCAyMDQ4IiB3aWR0aD0iMTI4IiBoZWlnaHQ9IjEyOCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTSAwIDAgTCAtNSAxIEwgLTE1IDQgTCAtMzggMTEgTCAtNTcgMTggTCAtNzYgMjkgTCAtOTAgMzggTCAtMTA5IDUyIEwgLTExNiA1OSBMIC0xMjcgNjggTCAtMTQwIDgxIEwgLTE0OCA4OCBMIC0xNDkgOTEgTCAtMTUxIDkxIEwgLTE2MSAxMDEgTCAtMTY5IDEwOCBMIC0xNjkgMTEwIEwgLTE3MSAxMTAgTCAtMTgwIDExOSBMIC0xODggMTI2IEwgLTIwMSAxMzcgTCAtMjEyIDE0NiBMIC0yMjYgMTU3IEwgLTIzOSAxNjcgTCAtMjUwIDE3NSBMIC0yNzAgMTg4IEwgLTI5MSAyMDIgTCAtMzA5IDIxMiBMIC0zMzAgMjI0IEwgLTM1MyAyMzUgTCAtMzg2IDI1MCBMIC00MDcgMjU5IEwgLTQ0OSAyNzMgTCAtNDcyIDI4MSBMIC01MDIgMjg5IEwgLTU1MSAyOTggTCAtNjE1IDMwOSBMIC02NDcgMzE2IEwgLTY4MSAzMjQgTCAtNjk4IDMzMCBMIC03MTQgMzM4IEwgLTczNSAzNTEgTCAtNzQ1IDM1OCBMIC03NTYgMzY3IEwgLTc2NCAzNzUgTCAtNzY2IDM3OSBMIC03NjggMzc5IEwgLTc3MyAzODUgTCAtNzgxIDM5NSBMIC03OTEgNDEwIEwgLTgwMSA0MjggTCAtODEwIDQ0NyBMIC04MTYgNDY1IEwgLTgyMiA1MDAgTCAtODI3IDU0NSBMIC04MzAgNTkyIEwgLTgzMiA2NTMgTCAtODMyIDcxMiBMIC04MzEgNzQyIEwgLTgyOCA3OTQgTCAtODIyIDg2NiBMIC04MTYgOTI4IEwgLTgxMiA5NTcgTCAtODAwIDEwMjAgTCAtNzg5IDEwNzIgTCAtNzgzIDEwOTggTCAtNzY1IDExNjIgTCAtNzUxIDEyMDcgTCAtNzQ0IDEyMjUgTCAtNzM0IDEyNTQgTCAtNzIwIDEyOTAgTCAtNzA0IDEzMjggTCAtNjg5IDEzNjEgTCAtNjY4IDE0MDMgTCAtNjUzIDE0MzEgTCAtNjM5IDE0NTYgTCAtNjIwIDE0ODggTCAtNjA3IDE1MDkgTCAtNTk0IDE1MjkgTCAtNTg0IDE1NDQgTCAtNTcxIDE1NjMgTCAtNTU4IDE1ODEgTCAtNTQ0IDE2MDAgTCAtNTMzIDE2MTUgTCAtNTIwIDE2MzIgTCAtNTA3IDE2NDggTCAtNDc5IDE2ODIgTCAtNDcwIDE2OTMgTCAtNDYwIDE3MDQgTCAtNDQ5IDE3MTYgTCAtNDQyIDE3MjQgTCAtNDMyIDE3MzQgTCAtNDI1IDE3NDIgTCAtMzY4IDE3OTkgTCAtMzUxIDE4MTUgTCAtMzM1IDE4MzAgTCAtMzI3IDE4MzcgTCAtMzE0IDE4NDkgTCAtMjg4IDE4NzEgTCAtMjcxIDE4ODUgTCAtMjYxIDE4OTMgTCAtMjQ0IDE5MDcgTCAtMjI4IDE5MTkgTCAtMjE1IDE5MjkgTCAtMTk2IDE5NDMgTCAtMTg0IDE5NTIgTCAtMTY4IDE5NjMgTCAtMTQ4IDE5NzcgTCAtMTMzIDE5ODcgTCAtMTEyIDIwMDAgTCAtODggMjAxMyBMIC03MiAyMDIxIEwgLTUyIDIwMzAgTCAtMzIgMjAzNyBMIDEyIDIwNDggTCA2MCAyMDQ4IEwgNjEgMjA0NyBMIDczIDIwNDQgTCAxMDAgMjAzNyBMIDEyMSAyMDI5IEwgMTQ5IDIwMTUgTCAxNjcgMjAwNSBMIDE4NiAxOTk0IEwgMjEwIDE5NzkgTCAyMzEgMTk2NSBMIDI2NiAxOTQxIEwgMjg0IDE5MjggTCAyOTUgMTkyMCBMIDMwNiAxOTExIEwgMzI0IDE4OTggTCAzMzggMTg4NyBMIDM0OSAxODc3IEwgMzU4IDE4NzAgTCAzNjkgMTg2MCBMIDM4MCAxODUxIEwgMzgwIDE4NDkgTCAzODIgMTg0OSBMIDM4NSAxODQ2IEwgMzk2IDE4MzcgTCA0MDMgMTgzMCBMIDQxMSAxODIzIEwgNDE4IDE4MTYgTCA0MjYgMTgwOSBMIDQ3NSAxNzYwIEwgNDc3IDE3NTYgTCA0NzkgMTc1NiBMIDQ4NyAxNzQ3IEwgNTAzIDE3MzAgTCA1MTAgMTcyMiBMIDUxOSAxNzEyIEwgNTI2IDE3MDQgTCA1MzggMTY5MSBMIDU0NyAxNjgwIEwgNTU4IDE2NjcgTCA1NjYgMTY1NiBMIDU3OSAxNjQwIEwgNTkwIDE2MjYgTCA2MDYgMTYwNSBMIDYyMSAxNTgzIEwgNjMxIDE1NjkgTCA2NDUgMTU0OSBMIDY1NSAxNTMzIEwgNjcwIDE1MTAgTCA2ODUgMTQ4NSBMIDY5NiAxNDY3IEwgNzA2IDE0NDkgTCA3MzAgMTQwNSBMIDc0NSAxMzc0IEwgNzYyIDEzMzggTCA3NzQgMTMxMCBMIDc5MiAxMjY3IEwgODExIDEyMTYgTCA4MjcgMTE2NiBMIDg0MiAxMTE3IEwgODU4IDEwNTEgTCA4NzAgOTk2IEwgODc1IDk2NyBMIDg4MSA5MTcgTCA4ODYgODgyIEwgODkxIDg0NiBMIDg5NCA4MTIgTCA4OTYgNzc0IEwgODk2IDY1NSBMIDg5NSA2MzAgTCA4OTIgNTkzIEwgODg4IDU1OSBMIDg3NyA0NzAgTCA4NzIgNDQ1IEwgODY1IDQyNiBMIDg1NyA0MTEgTCA4NDcgMzk1IEwgODM0IDM3OCBMIDgxNCAzNTggTCA4MDAgMzQ3IEwgNzg1IDMzNyBMIDc2NiAzMjcgTCA3NTAgMzIxIEwgNzI3IDMxNSBMIDY5MyAzMDggTCA2NTAgMzAxIEwgNTk3IDI5MiBMIDU3MCAyODYgTCA1NDggMjgwIEwgNTE1IDI3MCBMIDQ4NyAyNjEgTCA0NTkgMjUwIEwgNDM4IDI0MSBMIDQxNCAyMzAgTCAzODIgMjEzIEwgMzU4IDE5OSBMIDM0NyAxOTIgTCAzMzAgMTgwIEwgMzEyIDE2NyBMIDMwMCAxNTcgTCAyODYgMTQ2IEwgMjcxIDEzMyBMIDI2MyAxMjYgTCAyNTEgMTE1IEwgMjQwIDEwNiBMIDIyOCA5NSBMIDIwMCA3MSBMIDE4OSA2MiBMIDE3NCA1MCBMIDE1OCAzOCBMIDE0MiAyNyBMIDEyNyAxOSBMIDExNSAxNCBMIDk1IDggTCA3MSAwIEwgMCAwIHogTSAzMCA2MjIgTCA1MSA2MjMgTCA3OSA2MjcgTCAxMDAgNjMzIEwgMTIxIDY0MSBMIDE0MSA2NTIgTCAxNTcgNjYzIEwgMTcyIDY3NiBMIDE4NiA2OTAgTCAxODYgNjkyIEwgMTg4IDY5MiBMIDIwNiA3MTYgTCAyMTYgNzM0IEwgMjIxIDc0NSBMIDIyNiA3NTggTCAyMzMgNzg0IEwgMjM2IDc5OCBMIDIzNyA4MDggTCAyMzcgODQwIEwgMjMzIDg2NSBMIDIyNiA4OTEgTCAyMTkgOTA5IEwgMjA5IDkyOCBMIDE5NSA5NDkgTCAxODYgOTU5IEwgMTc5IDk2NyBMIDE2NiA5ODAgTCAxNTUgOTg5IEwgMTQyIDk5OCBMIDEyNiAxMDA3IEwgMTEzIDEwMTIgTCAxMTQgMTAyNCBMIDEyMiAxMDYwIEwgMTM3IDExMjMgTCAxNTYgMTIwOCBMIDE3MCAxMjcxIEwgMTc0IDEyOTYgTCAxNzYgMTMxMCBMIDE3NiAxMzM1IEwgMTczIDEzNDkgTCAxNjYgMTM1OSBMIDE1NyAxMzY3IEwgMTQ2IDEzNzIgTCAxNDAgMTM3NCBMIDExOSAxMzc2IEwgNTEgMTM3NiBMIC0zMiAxMzc3IEwgLTY0IDEzNzcgTCAtNzggMTM3NCBMIC04NSAxMzcwIEwgLTk4IDEzNTkgTCAtMTA2IDEzNDkgTCAtMTEwIDEzNDEgTCAtMTEyIDEzMzMgTCAtMTEyIDEzMTggTCAtMTA3IDEyODggTCAtMTAwIDEyNTYgTCAtODUgMTE5NiBMIC02OSAxMTI0IEwgLTU3IDEwNzIgTCAtNTAgMTAzNiBMIC00NyAxMDExIEwgLTUzIDEwMDkgTCAtNjkgMTAwMSBMIC04MSA5OTQgTCAtOTMgOTg1IEwgLTEwMyA5NzYgTCAtMTExIDk2OSBMIC0xMjAgOTYwIEwgLTEzMSA5NDYgTCAtMTQyIDkyOSBMIC0xNTIgOTEwIEwgLTE2MCA4OTAgTCAtMTY2IDg3MCBMIC0xNjkgODUzIEwgLTE3MCA4NDQgTCAtMTcwIDgxNCBMIC0xNjcgNzk0IEwgLTE2MSA3NjcgTCAtMTU0IDc0NiBMIC0xMzcgNzEzIEwgLTEyNiA2OTggTCAtMTE5IDY5MCBMIC0xMDggNjc4IEwgLTkzIDY2NSBMIC03NyA2NTMgTCAtNTYgNjQxIEwgLTM4IDYzMyBMIC0xNiA2MjcgTCAzIDYyNCBMIDMwIDYyMiB6ICIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoOTkxKSIgc3R5bGU9ImZpbGw6I2ZmZmZmZiIgLz4KPC9zdmc+Cg==",
|
||||||
"icon_light": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB2ZXJzaW9uPSIxLjEiIHZpZXdCb3g9IjAgMCAyMDQ4IDIwNDgiIHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8cGF0aCB0cmFuc2Zvcm09InRyYW5zbGF0ZSg5OTEpIiBkPSJtMCAwaDcxbDI0IDggMjAgNiAxMiA1IDE1IDggMTYgMTEgMTYgMTIgMTUgMTIgMTEgOSAyOCAyNCAxMiAxMSAxMSA5IDEyIDExIDggNyAxNSAxMyAxNCAxMSAxMiAxMCAxOCAxMyAxNyAxMiAxMSA3IDI0IDE0IDMyIDE3IDI0IDExIDIxIDkgMjggMTEgMjggOSAzMyAxMCAyMiA2IDI3IDYgNTMgOSA0MyA3IDM0IDcgMjMgNiAxNiA2IDE5IDEwIDE1IDEwIDE0IDExIDIwIDIwIDEzIDE3IDEwIDE2IDggMTUgNyAxOSA1IDI1IDExIDg5IDQgMzQgMyAzNyAxIDI1djExOWwtMiAzOC0zIDM0LTUgMzYtNSAzNS02IDUwLTUgMjktMTIgNTUtMTYgNjYtMTUgNDktMTYgNTAtMTkgNTEtMTggNDMtMTIgMjgtMTcgMzYtMTUgMzEtMjQgNDQtMTAgMTgtMTEgMTgtMTUgMjUtMTUgMjMtMTAgMTYtMTQgMjAtMTAgMTQtMTUgMjItMTYgMjEtMTEgMTQtMTMgMTYtOCAxMS0xMSAxMy05IDExLTEyIDEzLTcgOC05IDEwLTcgOC0xNiAxNy04IDloLTJsLTIgNC00OSA0OS04IDctNyA3LTggNy03IDctMTEgOS0zIDNoLTJ2MmwtMTEgOS0xMSAxMC05IDctMTEgMTAtMTQgMTEtMTggMTMtMTEgOS0xMSA4LTE4IDEzLTM1IDI0LTIxIDE0LTI0IDE1LTE5IDExLTE4IDEwLTI4IDE0LTIxIDgtMjcgNy0xMiAzLTEgMWgtNDhsLTQ0LTExLTIwLTctMjAtOS0xNi04LTI0LTEzLTIxLTEzLTE1LTEwLTIwLTE0LTE2LTExLTEyLTktMTktMTQtMTMtMTAtMTYtMTItMTctMTQtMTAtOC0xNy0xNC0yNi0yMi0xMy0xMi04LTctMTYtMTUtMTctMTYtNTctNTctNy04LTEwLTEwLTctOC0xMS0xMi0xMC0xMS05LTExLTI4LTM0LTEzLTE2LTEzLTE3LTExLTE1LTE0LTE5LTEzLTE4LTEzLTE5LTEwLTE1LTEzLTIwLTEzLTIxLTE5LTMyLTE0LTI1LTE1LTI4LTIxLTQyLTE1LTMzLTE2LTM4LTE0LTM2LTEwLTI5LTctMTgtMTQtNDUtMTgtNjQtNi0yNi0xMS01Mi0xMi02My00LTI5LTYtNjItNi03Mi0zLTUyLTEtMzB2LTU5bDItNjEgMy00NyA1LTQ1IDYtMzUgNi0xOCA5LTE5IDEwLTE4IDEwLTE1IDgtMTAgNS02aDJsMi00IDgtOCAxMS05IDEwLTcgMjEtMTMgMTYtOCAxNy02IDM0LTggMzItNyA2NC0xMSA0OS05IDMwLTggMjMtOCA0Mi0xNCAyMS05IDMzLTE1IDIzLTExIDIxLTEyIDE4LTEwIDIxLTE0IDIwLTEzIDExLTggMTMtMTAgMTQtMTEgMTEtOSAxMy0xMSA4LTcgOS05aDJ2LTJsOC03IDEwLTEwaDJsMS0zIDgtNyAxMy0xMyAxMS05IDctNyAxOS0xNCAxNC05IDE5LTExIDE5LTcgMjMtNyAxMC0zeiIgZmlsbD0iI0YxODQyOSIvPgo8cGF0aCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMDIxLDYyMikiIGQ9Im0wIDAgMjEgMSAyOCA0IDIxIDYgMjEgOCAyMCAxMSAxNiAxMSAxNSAxMyAxNCAxNHYyaDJsMTggMjQgMTAgMTggNSAxMSA1IDEzIDcgMjYgMyAxNCAxIDEwdjMybC00IDI1LTcgMjYtNyAxOC0xMCAxOS0xNCAyMS05IDEwLTcgOC0xMyAxMy0xMSA5LTEzIDktMTYgOS0xMyA1IDEgMTIgOCAzNiAxNSA2MyAxOSA4NSAxNCA2MyA0IDI1IDIgMTR2MjVsLTMgMTQtNyAxMC05IDgtMTEgNS02IDItMjEgMmgtNjhsLTgzIDFoLTMybC0xNC0zLTctNC0xMy0xMS04LTEwLTQtOC0yLTh2LTE1bDUtMzAgNy0zMiAxNS02MCAxNi03MiAxMi01MiA3LTM2IDMtMjUtNi0yLTE2LTgtMTItNy0xMi05LTEwLTktOC03LTktOS0xMS0xNC0xMS0xNy0xMC0xOS04LTIwLTYtMjAtMy0xNy0xLTl2LTMwbDMtMjAgNi0yNyA3LTIxIDE3LTMzIDExLTE1IDctOCAxMS0xMiAxNS0xMyAxNi0xMiAyMS0xMiAxOC04IDIyLTYgMTktM3oiIGZpbGw9IiNGRUZGRkUiLz4KPC9zdmc+Cg=="
|
"icon_light": "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB2ZXJzaW9uPSIxLjEiIHZpZXdCb3g9IjAgMCAyMDQ4IDIwNDgiIHdpZHRoPSIxMjgiIGhlaWdodD0iMTI4IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8cGF0aCB0cmFuc2Zvcm09InRyYW5zbGF0ZSg5OTEpIiBkPSJtMCAwaDcxbDI0IDggMjAgNiAxMiA1IDE1IDggMTYgMTEgMTYgMTIgMTUgMTIgMTEgOSAyOCAyNCAxMiAxMSAxMSA5IDEyIDExIDggNyAxNSAxMyAxNCAxMSAxMiAxMCAxOCAxMyAxNyAxMiAxMSA3IDI0IDE0IDMyIDE3IDI0IDExIDIxIDkgMjggMTEgMjggOSAzMyAxMCAyMiA2IDI3IDYgNTMgOSA0MyA3IDM0IDcgMjMgNiAxNiA2IDE5IDEwIDE1IDEwIDE0IDExIDIwIDIwIDEzIDE3IDEwIDE2IDggMTUgNyAxOSA1IDI1IDExIDg5IDQgMzQgMyAzNyAxIDI1djExOWwtMiAzOC0zIDM0LTUgMzYtNSAzNS02IDUwLTUgMjktMTIgNTUtMTYgNjYtMTUgNDktMTYgNTAtMTkgNTEtMTggNDMtMTIgMjgtMTcgMzYtMTUgMzEtMjQgNDQtMTAgMTgtMTEgMTgtMTUgMjUtMTUgMjMtMTAgMTYtMTQgMjAtMTAgMTQtMTUgMjItMTYgMjEtMTEgMTQtMTMgMTYtOCAxMS0xMSAxMy05IDExLTEyIDEzLTcgOC05IDEwLTcgOC0xNiAxNy04IDloLTJsLTIgNC00OSA0OS04IDctNyA3LTggNy03IDctMTEgOS0zIDNoLTJ2MmwtMTEgOS0xMSAxMC05IDctMTEgMTAtMTQgMTEtMTggMTMtMTEgOS0xMSA4LTE4IDEzLTM1IDI0LTIxIDE0LTI0IDE1LTE5IDExLTE4IDEwLTI4IDE0LTIxIDgtMjcgNy0xMiAzLTEgMWgtNDhsLTQ0LTExLTIwLTctMjAtOS0xNi04LTI0LTEzLTIxLTEzLTE1LTEwLTIwLTE0LTE2LTExLTEyLTktMTktMTQtMTMtMTAtMTYtMTItMTctMTQtMTAtOC0xNy0xNC0yNi0yMi0xMy0xMi04LTctMTYtMTUtMTctMTYtNTctNTctNy04LTEwLTEwLTctOC0xMS0xMi0xMC0xMS05LTExLTI4LTM0LTEzLTE2LTEzLTE3LTExLTE1LTE0LTE5LTEzLTE4LTEzLTE5LTEwLTE1LTEzLTIwLTEzLTIxLTE5LTMyLTE0LTI1LTE1LTI4LTIxLTQyLTE1LTMzLTE2LTM4LTE0LTM2LTEwLTI5LTctMTgtMTQtNDUtMTgtNjQtNi0yNi0xMS01Mi0xMi02My00LTI5LTYtNjItNi03Mi0zLTUyLTEtMzB2LTU5bDItNjEgMy00NyA1LTQ1IDYtMzUgNi0xOCA5LTE5IDEwLTE4IDEwLTE1IDgtMTAgNS02aDJsMi00IDgtOCAxMS05IDEwLTcgMjEtMTMgMTYtOCAxNy02IDM0LTggMzItNyA2NC0xMSA0OS05IDMwLTggMjMtOCA0Mi0xNCAyMS05IDMzLTE1IDIzLTExIDIxLTEyIDE4LTEwIDIxLTE0IDIwLTEzIDExLTggMTMtMTAgMTQtMTEgMTEtOSAxMy0xMSA4LTcgOS05aDJ2LTJsOC03IDEwLTEwaDJsMS0zIDgtNyAxMy0xMyAxMS05IDctNyAxOS0xNCAxNC05IDE5LTExIDE5LTcgMjMtNyAxMC0zeiIgZmlsbD0iI0YxODQyOSIvPgo8cGF0aCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMDIxLDYyMikiIGQ9Im0wIDAgMjEgMSAyOCA0IDIxIDYgMjEgOCAyMCAxMSAxNiAxMSAxNSAxMyAxNCAxNHYyaDJsMTggMjQgMTAgMTggNSAxMSA1IDEzIDcgMjYgMyAxNCAxIDEwdjMybC00IDI1LTcgMjYtNyAxOC0xMCAxOS0xNCAyMS05IDEwLTcgOC0xMyAxMy0xMSA5LTEzIDktMTYgOS0xMyA1IDEgMTIgOCAzNiAxNSA2MyAxOSA4NSAxNCA2MyA0IDI1IDIgMTR2MjVsLTMgMTQtNyAxMC05IDgtMTEgNS02IDItMjEgMmgtNjhsLTgzIDFoLTMybC0xNC0zLTctNC0xMy0xMS04LTEwLTQtOC0yLTh2LTE1bDUtMzAgNy0zMiAxNS02MCAxNi03MiAxMi01MiA3LTM2IDMtMjUtNi0yLTE2LTgtMTItNy0xMi05LTEwLTktOC03LTktOS0xMS0xNC0xMS0xNy0xMC0xOS04LTIwLTYtMjAtMy0xNy0xLTl2LTMwbDMtMjAgNi0yNyA3LTIxIDE3LTMzIDExLTE1IDctOCAxMS0xMiAxNS0xMyAxNi0xMiAyMS0xMiAxOC04IDIyLTYgMTktM3oiIGZpbGw9IiNGRUZGRkUiLz4KPC9zdmc+Cg=="
|
||||||
},
|
|
||||||
"a10c6dd9-465e-4226-8198-c7c44b91c555": {
|
|
||||||
"name": "Kaspersky Password Manager",
|
|
||||||
"icon_dark": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTEyIiBoZWlnaHQ9IjUxMiIgdmlld0JveD0iMCAwIDUxMiA1MTIiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzc0ODRfODc0NSkiPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMV83NDg0Xzg3NDUpIj48ZyBjbGlwLXBhdGg9InVybCgjY2xpcDJfNzQ4NF84NzQ1KSI+PHBhdGggZD0iTTI4MS45NjQgNi45NjE3MUMyNjUuODkzIC0yLjI5OTc0IDI0Ni4xMDcgLTIuMjk5NzQgMjMwLjAzNiA2Ljk2MTcxTDQ2LjAzNjUgMTEzLjAwMkMyOS45MjcxIDEyMi4yODYgMjAgMTM5LjQ2NiAyMCAxNTguMDZWMzUzLjk3MkMyMCAzNzIuNTY2IDI5LjkyNzEgMzg5Ljc0NSA0Ni4wMzY1IDM5OS4wMjlMMjMwLjAzNiA1MDUuMDdDMjQ2LjEwNyA1MTQuMzMxIDI2NS44OTMgNTE0LjMzMSAyODEuOTY0IDUwNS4wN0w0NjUuOTY0IDM5OS4wMjlDNDgyLjA3MyAzODkuNzQ1IDQ5MiAzNzIuNTY2IDQ5MiAzNTMuOTcyVjE1OC4wNkM0OTIgMTM5LjQ2NiA0ODIuMDczIDEyMi4yODYgNDY1Ljk2NCAxMTMuMDAyTDI4MS45NjQgNi45NjE3MVoiIGZpbGw9InVybCgjcGFpbnQwX2xpbmVhcl83NDg0Xzg3NDUpIi8+PHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik00NTMuOTggMTMzLjc5OEwyNjkuOTggMjcuNzU3NEMyNjEuMzI3IDIyLjc3MDQgMjUwLjY3MyAyMi43NzA0IDI0Mi4wMiAyNy43NTc0TDU4LjAxOTYgMTMzLjc5OEM0OS4zNDUzIDEzOC43OTcgNDQgMTQ4LjA0NyA0NCAxNTguMDZWMzUzLjk3MkM0NCAzNjMuOTg0IDQ5LjM0NTMgMzczLjIzNCA1OC4wMTk2IDM3OC4yMzNMMjQyLjAyIDQ4NC4yNzRDMjUwLjY3MyA0ODkuMjYxIDI2MS4zMjcgNDg5LjI2MSAyNjkuOTggNDg0LjI3NEw0NTMuOTggMzc4LjIzM0M0NjIuNjU1IDM3My4yMzQgNDY4IDM2My45ODQgNDY4IDM1My45NzJWMTU4LjA2QzQ2OCAxNDguMDQ3IDQ2Mi42NTUgMTM4Ljc5NyA0NTMuOTggMTMzLjc5OFpNMjgxLjk2NCA2Ljk2MTcxQzI2NS44OTMgLTIuMjk5NzQgMjQ2LjEwNyAtMi4yOTk3NCAyMzAuMDM2IDYuOTYxNzFMNDYuMDM2NSAxMTMuMDAyQzI5LjkyNzEgMTIyLjI4NiAyMCAxMzkuNDY2IDIwIDE1OC4wNlYzNTMuOTcyQzIwIDM3Mi41NjYgMjkuOTI3MSAzODkuNzQ1IDQ2LjAzNjUgMzk5LjAyOUwyMzAuMDM2IDUwNS4wN0MyNDYuMTA3IDUxNC4zMzEgMjY1Ljg5MyA1MTQuMzMxIDI4MS45NjQgNTA1LjA3TDQ2NS45NjQgMzk5LjAyOUM0ODIuMDczIDM4OS43NDUgNDkyIDM3Mi41NjYgNDkyIDM1My45NzJWMTU4LjA2QzQ5MiAxMzkuNDY2IDQ4Mi4wNzMgMTIyLjI4NiA0NjUuOTY0IDExMy4wMDJMMjgxLjk2NCA2Ljk2MTcxWiIgZmlsbD0iYmxhY2siLz48L2c+PHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0yNTYgMTQwQzI0Mi43NDUgMTQwIDIzMiAxNTAuNzQ1IDIzMiAxNjRDMjMyIDE3Ny4yNTUgMjQyLjc0NSAxODggMjU2IDE4OEMyNjkuMjU1IDE4OCAyODAgMTc3LjI1NSAyODAgMTY0QzI4MCAxNTAuNzQ1IDI2OS4yNTUgMTQwIDI1NiAxNDBaTTI0OCAxNjRDMjQ4IDE1OS41ODIgMjUxLjU4MiAxNTYgMjU2IDE1NkMyNjAuNDE4IDE1NiAyNjQgMTU5LjU4MiAyNjQgMTY0QzI2NCAxNjguNDE4IDI2MC40MTggMTcyIDI1NiAxNzJDMjUxLjU4MiAxNzIgMjQ4IDE2OC40MTggMjQ4IDE2NFoiIGZpbGw9ImJsYWNrIi8+PHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xNzIgMTkyQzE3MiAxNDUuNjA4IDIwOS42MDggMTA4IDI1NiAxMDhDMzAyLjM5MiAxMDggMzQwIDE0NS42MDggMzQwIDE5MkMzNDAgMjI3LjA2MSAzMTguNTE5IDI1Ny4xMDUgMjg4IDI2OS42OVYzODYuNjdDMjg4IDM5Mi4zOTEgMjg0Ljk0NiAzOTcuNjc2IDI3OS45ODkgNDAwLjUzM0wyNjMuOTg5IDQwOS43NTNDMjU5LjA0NCA0MTIuNjAzIDI1Mi45NTYgNDEyLjYwMyAyNDguMDExIDQwOS43NTNMMjMyLjAxMSA0MDAuNTMzQzIyNy4wNTQgMzk3LjY3NiAyMjQgMzkyLjM5MSAyMjQgMzg2LjY3VjM3MkMyMjQgMzY5Ljg3OCAyMjQuODQzIDM2Ny44NDQgMjI2LjM0MyAzNjYuMzQzTDIzNiAzNTYuNjg2VjM1NS4zMTRMMjI2LjM0MyAzNDUuNjU3QzIyNC44NDMgMzQ0LjE1NyAyMjQgMzQyLjEyMiAyMjQgMzQwVjMzMkMyMjQgMzI5Ljg3OCAyMjQuODQzIDMyNy44NDQgMjI2LjM0MyAzMjYuMzQzTDIzNiAzMTYuNjg2VjMxNS4zMTRMMjI2LjM0MyAzMDUuNjU3QzIyNC44NDMgMzA0LjE1NyAyMjQgMzAyLjEyMiAyMjQgMzAwVjI2OS42OUMxOTMuNDgxIDI1Ny4xMDUgMTcyIDIyNy4wNjEgMTcyIDE5MlpNMjU2IDEyNEMyMTguNDQ1IDEyNCAxODggMTU0LjQ0NSAxODggMTkyQzE4OCAyMjkuNTU1IDIxOC40NDUgMjYwIDI1NiAyNjBDMjkzLjU1NSAyNjAgMzI0IDIyOS41NTUgMzI0IDE5MkMzMjQgMTU0LjQ0NSAyOTMuNTU1IDEyNCAyNTYgMTI0Wk0yNTYgMjc2QzI2MS40NzEgMjc2IDI2Ni44MiAyNzUuNDc3IDI3MiAyNzQuNDc4VjM4Ni42N0wyNTYgMzk1Ljg5TDI0MCAzODYuNjdWMzc1LjMxNEwyNDkuNjU3IDM2NS42NTdDMjUxLjE1NyAzNjQuMTU3IDI1MiAzNjIuMTIyIDI1MiAzNjBWMzUyQzI1MiAzNDkuODc4IDI1MS4xNTcgMzQ3Ljg0NCAyNDkuNjU3IDM0Ni4zNDNMMjQwIDMzNi42ODZWMzM1LjMxNEwyNDkuNjU3IDMyNS42NTdDMjUxLjE1NyAzMjQuMTU3IDI1MiAzMjIuMTIyIDI1MiAzMjBWMzEyQzI1MiAzMDkuODc4IDI1MS4xNTcgMzA3Ljg0NCAyNDkuNjU3IDMwNi4zNDNMMjQwIDI5Ni42ODZWMjc0LjQ3OEMyNDUuMTggMjc1LjQ3NyAyNTAuNTI5IDI3NiAyNTYgMjc2WiIgZmlsbD0iYmxhY2siLz48L2c+PC9nPjxkZWZzPjxsaW5lYXJHcmFkaWVudCBpZD0icGFpbnQwX2xpbmVhcl83NDg0Xzg3NDUiIHgxPSIzOTMuODY1IiB5MT0iNjMuMjc5NiIgeDI9Ijk5LjIwNDMiIHkyPSI0MjkuOTk4IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agc3RvcC1jb2xvcj0iIzRERkY4OCIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iIzNERThDQSIvPjwvbGluZWFyR3JhZGllbnQ+PGNsaXBQYXRoIGlkPSJjbGlwMF83NDg0Xzg3NDUiPjxyZWN0IHdpZHRoPSI1MTIiIGhlaWdodD0iNTEyIiBmaWxsPSJ3aGl0ZSIvPjwvY2xpcFBhdGg+PGNsaXBQYXRoIGlkPSJjbGlwMV83NDg0Xzg3NDUiPjxyZWN0IHdpZHRoPSI1MTIiIGhlaWdodD0iNTEyIiBmaWxsPSJ3aGl0ZSIvPjwvY2xpcFBhdGg+PGNsaXBQYXRoIGlkPSJjbGlwMl83NDg0Xzg3NDUiPjxyZWN0IHdpZHRoPSI1MTIiIGhlaWdodD0iNTEyIiBmaWxsPSJ3aGl0ZSIvPjwvY2xpcFBhdGg+PC9kZWZzPjwvc3ZnPg==",
|
|
||||||
"icon_light": "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTEyIiBoZWlnaHQ9IjUxMiIgdmlld0JveD0iMCAwIDUxMiA1MTIiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzc0ODRfODc0NSkiPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMV83NDg0Xzg3NDUpIj48ZyBjbGlwLXBhdGg9InVybCgjY2xpcDJfNzQ4NF84NzQ1KSI+PHBhdGggZD0iTTI4MS45NjQgNi45NjE3MUMyNjUuODkzIC0yLjI5OTc0IDI0Ni4xMDcgLTIuMjk5NzQgMjMwLjAzNiA2Ljk2MTcxTDQ2LjAzNjUgMTEzLjAwMkMyOS45MjcxIDEyMi4yODYgMjAgMTM5LjQ2NiAyMCAxNTguMDZWMzUzLjk3MkMyMCAzNzIuNTY2IDI5LjkyNzEgMzg5Ljc0NSA0Ni4wMzY1IDM5OS4wMjlMMjMwLjAzNiA1MDUuMDdDMjQ2LjEwNyA1MTQuMzMxIDI2NS44OTMgNTE0LjMzMSAyODEuOTY0IDUwNS4wN0w0NjUuOTY0IDM5OS4wMjlDNDgyLjA3MyAzODkuNzQ1IDQ5MiAzNzIuNTY2IDQ5MiAzNTMuOTcyVjE1OC4wNkM0OTIgMTM5LjQ2NiA0ODIuMDczIDEyMi4yODYgNDY1Ljk2NCAxMTMuMDAyTDI4MS45NjQgNi45NjE3MVoiIGZpbGw9InVybCgjcGFpbnQwX2xpbmVhcl83NDg0Xzg3NDUpIi8+PHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik00NTMuOTggMTMzLjc5OEwyNjkuOTggMjcuNzU3NEMyNjEuMzI3IDIyLjc3MDQgMjUwLjY3MyAyMi43NzA0IDI0Mi4wMiAyNy43NTc0TDU4LjAxOTYgMTMzLjc5OEM0OS4zNDUzIDEzOC43OTcgNDQgMTQ4LjA0NyA0NCAxNTguMDZWMzUzLjk3MkM0NCAzNjMuOTg0IDQ5LjM0NTMgMzczLjIzNCA1OC4wMTk2IDM3OC4yMzNMMjQyLjAyIDQ4NC4yNzRDMjUwLjY3MyA0ODkuMjYxIDI2MS4zMjcgNDg5LjI2MSAyNjkuOTggNDg0LjI3NEw0NTMuOTggMzc4LjIzM0M0NjIuNjU1IDM3My4yMzQgNDY4IDM2My45ODQgNDY4IDM1My45NzJWMTU4LjA2QzQ2OCAxNDguMDQ3IDQ2Mi42NTUgMTM4Ljc5NyA0NTMuOTggMTMzLjc5OFpNMjgxLjk2NCA2Ljk2MTcxQzI2NS44OTMgLTIuMjk5NzQgMjQ2LjEwNyAtMi4yOTk3NCAyMzAuMDM2IDYuOTYxNzFMNDYuMDM2NSAxMTMuMDAyQzI5LjkyNzEgMTIyLjI4NiAyMCAxMzkuNDY2IDIwIDE1OC4wNlYzNTMuOTcyQzIwIDM3Mi41NjYgMjkuOTI3MSAzODkuNzQ1IDQ2LjAzNjUgMzk5LjAyOUwyMzAuMDM2IDUwNS4wN0MyNDYuMTA3IDUxNC4zMzEgMjY1Ljg5MyA1MTQuMzMxIDI4MS45NjQgNTA1LjA3TDQ2NS45NjQgMzk5LjAyOUM0ODIuMDczIDM4OS43NDUgNDkyIDM3Mi41NjYgNDkyIDM1My45NzJWMTU4LjA2QzQ5MiAxMzkuNDY2IDQ4Mi4wNzMgMTIyLjI4NiA0NjUuOTY0IDExMy4wMDJMMjgxLjk2NCA2Ljk2MTcxWiIgZmlsbD0iYmxhY2siLz48L2c+PHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0yNTYgMTQwQzI0Mi43NDUgMTQwIDIzMiAxNTAuNzQ1IDIzMiAxNjRDMjMyIDE3Ny4yNTUgMjQyLjc0NSAxODggMjU2IDE4OEMyNjkuMjU1IDE4OCAyODAgMTc3LjI1NSAyODAgMTY0QzI4MCAxNTAuNzQ1IDI2OS4yNTUgMTQwIDI1NiAxNDBaTTI0OCAxNjRDMjQ4IDE1OS41ODIgMjUxLjU4MiAxNTYgMjU2IDE1NkMyNjAuNDE4IDE1NiAyNjQgMTU5LjU4MiAyNjQgMTY0QzI2NCAxNjguNDE4IDI2MC40MTggMTcyIDI1NiAxNzJDMjUxLjU4MiAxNzIgMjQ4IDE2OC40MTggMjQ4IDE2NFoiIGZpbGw9ImJsYWNrIi8+PHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0xNzIgMTkyQzE3MiAxNDUuNjA4IDIwOS42MDggMTA4IDI1NiAxMDhDMzAyLjM5MiAxMDggMzQwIDE0NS42MDggMzQwIDE5MkMzNDAgMjI3LjA2MSAzMTguNTE5IDI1Ny4xMDUgMjg4IDI2OS42OVYzODYuNjdDMjg4IDM5Mi4zOTEgMjg0Ljk0NiAzOTcuNjc2IDI3OS45ODkgNDAwLjUzM0wyNjMuOTg5IDQwOS43NTNDMjU5LjA0NCA0MTIuNjAzIDI1Mi45NTYgNDEyLjYwMyAyNDguMDExIDQwOS43NTNMMjMyLjAxMSA0MDAuNTMzQzIyNy4wNTQgMzk3LjY3NiAyMjQgMzkyLjM5MSAyMjQgMzg2LjY3VjM3MkMyMjQgMzY5Ljg3OCAyMjQuODQzIDM2Ny44NDQgMjI2LjM0MyAzNjYuMzQzTDIzNiAzNTYuNjg2VjM1NS4zMTRMMjI2LjM0MyAzNDUuNjU3QzIyNC44NDMgMzQ0LjE1NyAyMjQgMzQyLjEyMiAyMjQgMzQwVjMzMkMyMjQgMzI5Ljg3OCAyMjQuODQzIDMyNy44NDQgMjI2LjM0MyAzMjYuMzQzTDIzNiAzMTYuNjg2VjMxNS4zMTRMMjI2LjM0MyAzMDUuNjU3QzIyNC44NDMgMzA0LjE1NyAyMjQgMzAyLjEyMiAyMjQgMzAwVjI2OS42OUMxOTMuNDgxIDI1Ny4xMDUgMTcyIDIyNy4wNjEgMTcyIDE5MlpNMjU2IDEyNEMyMTguNDQ1IDEyNCAxODggMTU0LjQ0NSAxODggMTkyQzE4OCAyMjkuNTU1IDIxOC40NDUgMjYwIDI1NiAyNjBDMjkzLjU1NSAyNjAgMzI0IDIyOS41NTUgMzI0IDE5MkMzMjQgMTU0LjQ0NSAyOTMuNTU1IDEyNCAyNTYgMTI0Wk0yNTYgMjc2QzI2MS40NzEgMjc2IDI2Ni44MiAyNzUuNDc3IDI3MiAyNzQuNDc4VjM4Ni42N0wyNTYgMzk1Ljg5TDI0MCAzODYuNjdWMzc1LjMxNEwyNDkuNjU3IDM2NS42NTdDMjUxLjE1NyAzNjQuMTU3IDI1MiAzNjIuMTIyIDI1MiAzNjBWMzUyQzI1MiAzNDkuODc4IDI1MS4xNTcgMzQ3Ljg0NCAyNDkuNjU3IDM0Ni4zNDNMMjQwIDMzNi42ODZWMzM1LjMxNEwyNDkuNjU3IDMyNS42NTdDMjUxLjE1NyAzMjQuMTU3IDI1MiAzMjIuMTIyIDI1MiAzMjBWMzEyQzI1MiAzMDkuODc4IDI1MS4xNTcgMzA3Ljg0NCAyNDkuNjU3IDMwNi4zNDNMMjQwIDI5Ni42ODZWMjc0LjQ3OEMyNDUuMTggMjc1LjQ3NyAyNTAuNTI5IDI3NiAyNTYgMjc2WiIgZmlsbD0iYmxhY2siLz48L2c+PC9nPjxkZWZzPjxsaW5lYXJHcmFkaWVudCBpZD0icGFpbnQwX2xpbmVhcl83NDg0Xzg3NDUiIHgxPSIzOTMuODY1IiB5MT0iNjMuMjc5NiIgeDI9Ijk5LjIwNDMiIHkyPSI0MjkuOTk4IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agc3RvcC1jb2xvcj0iIzRERkY4OCIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iIzNERThDQSIvPjwvbGluZWFyR3JhZGllbnQ+PGNsaXBQYXRoIGlkPSJjbGlwMF83NDg0Xzg3NDUiPjxyZWN0IHdpZHRoPSI1MTIiIGhlaWdodD0iNTEyIiBmaWxsPSJ3aGl0ZSIvPjwvY2xpcFBhdGg+PGNsaXBQYXRoIGlkPSJjbGlwMV83NDg0Xzg3NDUiPjxyZWN0IHdpZHRoPSI1MTIiIGhlaWdodD0iNTEyIiBmaWxsPSJ3aGl0ZSIvPjwvY2xpcFBhdGg+PGNsaXBQYXRoIGlkPSJjbGlwMl83NDg0Xzg3NDUiPjxyZWN0IHdpZHRoPSI1MTIiIGhlaWdodD0iNTEyIiBmaWxsPSJ3aGl0ZSIvPjwvY2xpcFBhdGg+PC9kZWZzPjwvc3ZnPg=="
|
|
||||||
}
|
}
|
||||||
}
|
}
|
File diff suppressed because one or more lines are too long
@ -1,54 +0,0 @@
|
|||||||
# Generated by Django 5.0.12 on 2025-02-27 04:32
|
|
||||||
|
|
||||||
import authentik.lib.utils.time
|
|
||||||
from authentik.lib.utils.time import timedelta_from_string
|
|
||||||
from django.db import migrations, models
|
|
||||||
|
|
||||||
|
|
||||||
def convert_integer_to_string_format(apps, schema_editor):
|
|
||||||
db_alias = schema_editor.connection.alias
|
|
||||||
EmailStage = apps.get_model("authentik_stages_email", "EmailStage")
|
|
||||||
for stage in EmailStage.objects.using(db_alias).all():
|
|
||||||
stage.token_expiry = f"minutes={stage.token_expiry}"
|
|
||||||
stage.save(using=db_alias)
|
|
||||||
|
|
||||||
|
|
||||||
def convert_string_to_integer_format(apps, schema_editor):
|
|
||||||
db_alias = schema_editor.connection.alias
|
|
||||||
EmailStage = apps.get_model("authentik_stages_email", "EmailStage")
|
|
||||||
for stage in EmailStage.objects.using(db_alias).all():
|
|
||||||
# Check if token_expiry is a string
|
|
||||||
if isinstance(stage.token_expiry, str):
|
|
||||||
try:
|
|
||||||
# Use the timedelta_from_string utility to convert to timedelta
|
|
||||||
# then convert to minutes by dividing seconds by 60
|
|
||||||
td = timedelta_from_string(stage.token_expiry)
|
|
||||||
minutes_value = int(td.total_seconds() / 60)
|
|
||||||
stage.token_expiry = minutes_value
|
|
||||||
stage.save(using=db_alias)
|
|
||||||
except (ValueError, TypeError):
|
|
||||||
# If the string can't be parsed or converted properly, skip
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
("authentik_stages_email", "0004_emailstage_activate_user_on_success"),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name="emailstage",
|
|
||||||
name="token_expiry",
|
|
||||||
field=models.TextField(
|
|
||||||
default="minutes=30",
|
|
||||||
help_text="Time the token sent is valid (Format: hours=3,minutes=17,seconds=300).",
|
|
||||||
validators=[authentik.lib.utils.time.timedelta_string_validator],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
migrations.RunPython(
|
|
||||||
convert_integer_to_string_format,
|
|
||||||
convert_string_to_integer_format,
|
|
||||||
),
|
|
||||||
]
|
|
@ -14,7 +14,6 @@ from structlog.stdlib import get_logger
|
|||||||
|
|
||||||
from authentik.flows.models import Stage
|
from authentik.flows.models import Stage
|
||||||
from authentik.lib.config import CONFIG
|
from authentik.lib.config import CONFIG
|
||||||
from authentik.lib.utils.time import timedelta_string_validator
|
|
||||||
|
|
||||||
LOGGER = get_logger()
|
LOGGER = get_logger()
|
||||||
|
|
||||||
@ -75,10 +74,8 @@ class EmailStage(Stage):
|
|||||||
default=False, help_text=_("Activate users upon completion of stage.")
|
default=False, help_text=_("Activate users upon completion of stage.")
|
||||||
)
|
)
|
||||||
|
|
||||||
token_expiry = models.TextField(
|
token_expiry = models.IntegerField(
|
||||||
default="minutes=30",
|
default=30, help_text=_("Time in minutes the token sent is valid.")
|
||||||
validators=[timedelta_string_validator],
|
|
||||||
help_text=_("Time the token sent is valid (Format: hours=3,minutes=17,seconds=300)."),
|
|
||||||
)
|
)
|
||||||
subject = models.TextField(default="authentik")
|
subject = models.TextField(default="authentik")
|
||||||
template = models.TextField(default=EmailTemplates.PASSWORD_RESET)
|
template = models.TextField(default=EmailTemplates.PASSWORD_RESET)
|
||||||
|
@ -22,7 +22,6 @@ from authentik.flows.planner import PLAN_CONTEXT_IS_RESTORED, PLAN_CONTEXT_PENDI
|
|||||||
from authentik.flows.stage import ChallengeStageView
|
from authentik.flows.stage import ChallengeStageView
|
||||||
from authentik.flows.views.executor import QS_KEY_TOKEN, QS_QUERY
|
from authentik.flows.views.executor import QS_KEY_TOKEN, QS_QUERY
|
||||||
from authentik.lib.utils.errors import exception_to_string
|
from authentik.lib.utils.errors import exception_to_string
|
||||||
from authentik.lib.utils.time import timedelta_from_string
|
|
||||||
from authentik.stages.email.models import EmailStage
|
from authentik.stages.email.models import EmailStage
|
||||||
from authentik.stages.email.tasks import send_mails
|
from authentik.stages.email.tasks import send_mails
|
||||||
from authentik.stages.email.utils import TemplateEmailMessage
|
from authentik.stages.email.utils import TemplateEmailMessage
|
||||||
@ -74,8 +73,8 @@ class EmailStageView(ChallengeStageView):
|
|||||||
"""Get token"""
|
"""Get token"""
|
||||||
pending_user = self.get_pending_user()
|
pending_user = self.get_pending_user()
|
||||||
current_stage: EmailStage = self.executor.current_stage
|
current_stage: EmailStage = self.executor.current_stage
|
||||||
valid_delta = timedelta_from_string(current_stage.token_expiry) + timedelta(
|
valid_delta = timedelta(
|
||||||
minutes=1
|
minutes=current_stage.token_expiry + 1
|
||||||
) # + 1 because django timesince always rounds down
|
) # + 1 because django timesince always rounds down
|
||||||
identifier = slugify(f"ak-email-stage-{current_stage.name}-{str(uuid4())}")
|
identifier = slugify(f"ak-email-stage-{current_stage.name}-{str(uuid4())}")
|
||||||
# Don't check for validity here, we only care if the token exists
|
# Don't check for validity here, we only care if the token exists
|
||||||
|
@ -104,6 +104,13 @@ def send_mail(
|
|||||||
# can't be converted to json)
|
# can't be converted to json)
|
||||||
message_object.attach(logo_data())
|
message_object.attach(logo_data())
|
||||||
|
|
||||||
|
if (
|
||||||
|
message_object.to
|
||||||
|
and isinstance(message_object.to[0], str)
|
||||||
|
and "=?utf-8?" in message_object.to[0]
|
||||||
|
):
|
||||||
|
message_object.to = [message_object.to[0].split("<")[-1].replace(">", "")]
|
||||||
|
|
||||||
LOGGER.debug("Sending mail", to=message_object.to)
|
LOGGER.debug("Sending mail", to=message_object.to)
|
||||||
backend.send_messages([message_object])
|
backend.send_messages([message_object])
|
||||||
Event.new(
|
Event.new(
|
||||||
|
@ -8,7 +8,7 @@ from django.core.mail.backends.locmem import EmailBackend
|
|||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
from authentik.core.models import User
|
from authentik.core.models import User
|
||||||
from authentik.core.tests.utils import create_test_admin_user, create_test_flow
|
from authentik.core.tests.utils import create_test_admin_user, create_test_flow, create_test_user
|
||||||
from authentik.events.models import Event, EventAction
|
from authentik.events.models import Event, EventAction
|
||||||
from authentik.flows.markers import StageMarker
|
from authentik.flows.markers import StageMarker
|
||||||
from authentik.flows.models import FlowDesignation, FlowStageBinding
|
from authentik.flows.models import FlowDesignation, FlowStageBinding
|
||||||
@ -67,6 +67,67 @@ class TestEmailStageSending(FlowTestCase):
|
|||||||
self.assertEqual(event.context["to_email"], [f"{self.user.name} <{self.user.email}>"])
|
self.assertEqual(event.context["to_email"], [f"{self.user.name} <{self.user.email}>"])
|
||||||
self.assertEqual(event.context["from_email"], "system@authentik.local")
|
self.assertEqual(event.context["from_email"], "system@authentik.local")
|
||||||
|
|
||||||
|
def test_newlines_long_name(self):
|
||||||
|
"""Test with pending user"""
|
||||||
|
plan = FlowPlan(flow_pk=self.flow.pk.hex, bindings=[self.binding], markers=[StageMarker()])
|
||||||
|
long_user = create_test_user()
|
||||||
|
long_user.name = "Test User\r\n Many Words\r\n"
|
||||||
|
long_user.save()
|
||||||
|
plan.context[PLAN_CONTEXT_PENDING_USER] = long_user
|
||||||
|
session = self.client.session
|
||||||
|
session[SESSION_KEY_PLAN] = plan
|
||||||
|
session.save()
|
||||||
|
Event.objects.filter(action=EventAction.EMAIL_SENT).delete()
|
||||||
|
|
||||||
|
url = reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug})
|
||||||
|
with patch(
|
||||||
|
"authentik.stages.email.models.EmailStage.backend_class",
|
||||||
|
PropertyMock(return_value=EmailBackend),
|
||||||
|
):
|
||||||
|
response = self.client.post(url)
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertStageResponse(
|
||||||
|
response,
|
||||||
|
self.flow,
|
||||||
|
response_errors={
|
||||||
|
"non_field_errors": [{"string": "email-sent", "code": "email-sent"}]
|
||||||
|
},
|
||||||
|
)
|
||||||
|
self.assertEqual(len(mail.outbox), 1)
|
||||||
|
self.assertEqual(mail.outbox[0].subject, "authentik")
|
||||||
|
self.assertEqual(mail.outbox[0].to, [f"Test User Many Words <{long_user.email}>"])
|
||||||
|
|
||||||
|
def test_utf8_name(self):
|
||||||
|
"""Test with pending user"""
|
||||||
|
plan = FlowPlan(flow_pk=self.flow.pk.hex, bindings=[self.binding], markers=[StageMarker()])
|
||||||
|
utf8_user = create_test_user()
|
||||||
|
utf8_user.name = "Cirilo ЉМНЊ el cirilico И̂ӢЙӤ "
|
||||||
|
utf8_user.email = "cyrillic@authentik.local"
|
||||||
|
utf8_user.save()
|
||||||
|
plan.context[PLAN_CONTEXT_PENDING_USER] = utf8_user
|
||||||
|
session = self.client.session
|
||||||
|
session[SESSION_KEY_PLAN] = plan
|
||||||
|
session.save()
|
||||||
|
Event.objects.filter(action=EventAction.EMAIL_SENT).delete()
|
||||||
|
|
||||||
|
url = reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug})
|
||||||
|
with patch(
|
||||||
|
"authentik.stages.email.models.EmailStage.backend_class",
|
||||||
|
PropertyMock(return_value=EmailBackend),
|
||||||
|
):
|
||||||
|
response = self.client.post(url)
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertStageResponse(
|
||||||
|
response,
|
||||||
|
self.flow,
|
||||||
|
response_errors={
|
||||||
|
"non_field_errors": [{"string": "email-sent", "code": "email-sent"}]
|
||||||
|
},
|
||||||
|
)
|
||||||
|
self.assertEqual(len(mail.outbox), 1)
|
||||||
|
self.assertEqual(mail.outbox[0].subject, "authentik")
|
||||||
|
self.assertEqual(mail.outbox[0].to, [f"{utf8_user.email}"])
|
||||||
|
|
||||||
def test_pending_fake_user(self):
|
def test_pending_fake_user(self):
|
||||||
"""Test with pending (fake) user"""
|
"""Test with pending (fake) user"""
|
||||||
self.flow.designation = FlowDesignation.RECOVERY
|
self.flow.designation = FlowDesignation.RECOVERY
|
||||||
|
@ -32,7 +32,14 @@ class TemplateEmailMessage(EmailMultiAlternatives):
|
|||||||
sanitized_to = []
|
sanitized_to = []
|
||||||
# Ensure that all recipients are valid
|
# Ensure that all recipients are valid
|
||||||
for recipient_name, recipient_email in to:
|
for recipient_name, recipient_email in to:
|
||||||
sanitized_to.append(sanitize_address((recipient_name, recipient_email), "utf-8"))
|
# Remove any newline characters from name and email before sanitizing
|
||||||
|
clean_name = (
|
||||||
|
recipient_name.replace("\n", " ").replace("\r", " ") if recipient_name else ""
|
||||||
|
)
|
||||||
|
clean_email = (
|
||||||
|
recipient_email.replace("\n", "").replace("\r", "") if recipient_email else ""
|
||||||
|
)
|
||||||
|
sanitized_to.append(sanitize_address((clean_name, clean_email), "utf-8"))
|
||||||
super().__init__(to=sanitized_to, **kwargs)
|
super().__init__(to=sanitized_to, **kwargs)
|
||||||
if not template_name:
|
if not template_name:
|
||||||
return
|
return
|
||||||
|
@ -5,7 +5,7 @@ entries:
|
|||||||
- attrs:
|
- attrs:
|
||||||
designation: stage_configuration
|
designation: stage_configuration
|
||||||
name: default-authenticator-totp-setup
|
name: default-authenticator-totp-setup
|
||||||
title: Set up Two-Factor authentication
|
title: Setup Two-Factor authentication
|
||||||
authentication: require_authenticated
|
authentication: require_authenticated
|
||||||
identifiers:
|
identifiers:
|
||||||
slug: default-authenticator-totp-setup
|
slug: default-authenticator-totp-setup
|
||||||
|
@ -57,7 +57,7 @@ entries:
|
|||||||
use_ssl: false
|
use_ssl: false
|
||||||
timeout: 10
|
timeout: 10
|
||||||
from_address: system@authentik.local
|
from_address: system@authentik.local
|
||||||
token_expiry: minutes=30
|
token_expiry: 30
|
||||||
subject: authentik
|
subject: authentik
|
||||||
template: email/password_reset.html
|
template: email/password_reset.html
|
||||||
activate_user_on_success: true
|
activate_user_on_success: true
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
"$schema": "http://json-schema.org/draft-07/schema",
|
"$schema": "http://json-schema.org/draft-07/schema",
|
||||||
"$id": "https://goauthentik.io/blueprints/schema.json",
|
"$id": "https://goauthentik.io/blueprints/schema.json",
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"title": "authentik 2025.2.1 Blueprint schema",
|
"title": "authentik 2025.2.4 Blueprint schema",
|
||||||
"required": [
|
"required": [
|
||||||
"version",
|
"version",
|
||||||
"entries"
|
"entries"
|
||||||
@ -6661,16 +6661,6 @@
|
|||||||
"title": "Token",
|
"title": "Token",
|
||||||
"description": "Authentication token"
|
"description": "Authentication token"
|
||||||
},
|
},
|
||||||
"compatibility_mode": {
|
|
||||||
"type": "string",
|
|
||||||
"enum": [
|
|
||||||
"default",
|
|
||||||
"aws",
|
|
||||||
"slack"
|
|
||||||
],
|
|
||||||
"title": "SCIM Compatibility Mode",
|
|
||||||
"description": "Alter authentik behavior for vendor-specific SCIM implementations."
|
|
||||||
},
|
|
||||||
"exclude_users_service_account": {
|
"exclude_users_service_account": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"title": "Exclude users service account"
|
"title": "Exclude users service account"
|
||||||
@ -6679,11 +6669,6 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "uuid",
|
"format": "uuid",
|
||||||
"title": "Filter group"
|
"title": "Filter group"
|
||||||
},
|
|
||||||
"dry_run": {
|
|
||||||
"type": "boolean",
|
|
||||||
"title": "Dry run",
|
|
||||||
"description": "When enabled, provider will not modify or create objects in the remote system."
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": []
|
"required": []
|
||||||
@ -11379,10 +11364,11 @@
|
|||||||
"title": "From address"
|
"title": "From address"
|
||||||
},
|
},
|
||||||
"token_expiry": {
|
"token_expiry": {
|
||||||
"type": "string",
|
"type": "integer",
|
||||||
"minLength": 1,
|
"minimum": -2147483648,
|
||||||
|
"maximum": 2147483647,
|
||||||
"title": "Token expiry",
|
"title": "Token expiry",
|
||||||
"description": "Time the token sent is valid (Format: hours=3,minutes=17,seconds=300)."
|
"description": "Time in minutes the token sent is valid."
|
||||||
},
|
},
|
||||||
"subject": {
|
"subject": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@ -14210,11 +14196,6 @@
|
|||||||
"type": "string",
|
"type": "string",
|
||||||
"minLength": 1,
|
"minLength": 1,
|
||||||
"title": "Default group email domain"
|
"title": "Default group email domain"
|
||||||
},
|
|
||||||
"dry_run": {
|
|
||||||
"type": "boolean",
|
|
||||||
"title": "Dry run",
|
|
||||||
"description": "When enabled, provider will not modify or create objects in the remote system."
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": []
|
"required": []
|
||||||
@ -14363,11 +14344,6 @@
|
|||||||
"suspend"
|
"suspend"
|
||||||
],
|
],
|
||||||
"title": "Group delete action"
|
"title": "Group delete action"
|
||||||
},
|
|
||||||
"dry_run": {
|
|
||||||
"type": "boolean",
|
|
||||||
"title": "Dry run",
|
|
||||||
"description": "When enabled, provider will not modify or create objects in the remote system."
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"required": []
|
"required": []
|
||||||
|
@ -31,7 +31,7 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- redis:/data
|
- redis:/data
|
||||||
server:
|
server:
|
||||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.2.1}
|
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.2.4}
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
command: server
|
command: server
|
||||||
environment:
|
environment:
|
||||||
@ -54,7 +54,7 @@ services:
|
|||||||
redis:
|
redis:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
worker:
|
worker:
|
||||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.2.1}
|
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.2.4}
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
command: worker
|
command: worker
|
||||||
environment:
|
environment:
|
||||||
|
30
go.mod
30
go.mod
@ -1,12 +1,12 @@
|
|||||||
module goauthentik.io
|
module goauthentik.io
|
||||||
|
|
||||||
go 1.23.0
|
go 1.23
|
||||||
|
|
||||||
toolchain go1.24.0
|
toolchain go1.23.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
beryju.io/ldap v0.1.0
|
beryju.io/ldap v0.1.0
|
||||||
github.com/coreos/go-oidc/v3 v3.13.0
|
github.com/coreos/go-oidc/v3 v3.12.0
|
||||||
github.com/getsentry/sentry-go v0.31.1
|
github.com/getsentry/sentry-go v0.31.1
|
||||||
github.com/go-http-utils/etag v0.0.0-20161124023236-513ea8f21eb1
|
github.com/go-http-utils/etag v0.0.0-20161124023236-513ea8f21eb1
|
||||||
github.com/go-ldap/ldap/v3 v3.4.10
|
github.com/go-ldap/ldap/v3 v3.4.10
|
||||||
@ -22,17 +22,17 @@ require (
|
|||||||
github.com/mitchellh/mapstructure v1.5.0
|
github.com/mitchellh/mapstructure v1.5.0
|
||||||
github.com/nmcclain/asn1-ber v0.0.0-20170104154839-2661553a0484
|
github.com/nmcclain/asn1-ber v0.0.0-20170104154839-2661553a0484
|
||||||
github.com/pires/go-proxyproto v0.8.0
|
github.com/pires/go-proxyproto v0.8.0
|
||||||
github.com/prometheus/client_golang v1.21.1
|
github.com/prometheus/client_golang v1.20.5
|
||||||
github.com/redis/go-redis/v9 v9.7.1
|
github.com/redis/go-redis/v9 v9.7.0
|
||||||
github.com/sethvargo/go-envconfig v1.1.1
|
github.com/sethvargo/go-envconfig v1.1.1
|
||||||
github.com/sirupsen/logrus v1.9.3
|
github.com/sirupsen/logrus v1.9.3
|
||||||
github.com/spf13/cobra v1.9.1
|
github.com/spf13/cobra v1.9.1
|
||||||
github.com/stretchr/testify v1.10.0
|
github.com/stretchr/testify v1.10.0
|
||||||
github.com/wwt/guac v1.3.2
|
github.com/wwt/guac v1.3.2
|
||||||
goauthentik.io/api/v3 v3.2025021.4
|
goauthentik.io/api/v3 v3.2024123.6
|
||||||
golang.org/x/exp v0.0.0-20230210204819-062eb4c674ab
|
golang.org/x/exp v0.0.0-20230210204819-062eb4c674ab
|
||||||
golang.org/x/oauth2 v0.28.0
|
golang.org/x/oauth2 v0.26.0
|
||||||
golang.org/x/sync v0.12.0
|
golang.org/x/sync v0.11.0
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
layeh.com/radius v0.0.0-20210819152912-ad72663a72ab
|
layeh.com/radius v0.0.0-20210819152912-ad72663a72ab
|
||||||
)
|
)
|
||||||
@ -48,7 +48,7 @@ require (
|
|||||||
github.com/go-asn1-ber/asn1-ber v1.5.7 // indirect
|
github.com/go-asn1-ber/asn1-ber v1.5.7 // indirect
|
||||||
github.com/go-http-utils/fresh v0.0.0-20161124030543-7231e26a4b27 // indirect
|
github.com/go-http-utils/fresh v0.0.0-20161124030543-7231e26a4b27 // indirect
|
||||||
github.com/go-http-utils/headers v0.0.0-20181008091004-fed159eddc2a // indirect
|
github.com/go-http-utils/headers v0.0.0-20181008091004-fed159eddc2a // indirect
|
||||||
github.com/go-jose/go-jose/v4 v4.0.5 // indirect
|
github.com/go-jose/go-jose/v4 v4.0.2 // indirect
|
||||||
github.com/go-logr/logr v1.4.1 // indirect
|
github.com/go-logr/logr v1.4.1 // indirect
|
||||||
github.com/go-logr/stdr v1.2.2 // indirect
|
github.com/go-logr/stdr v1.2.2 // indirect
|
||||||
github.com/go-openapi/analysis v0.23.0 // indirect
|
github.com/go-openapi/analysis v0.23.0 // indirect
|
||||||
@ -62,23 +62,23 @@ require (
|
|||||||
github.com/go-openapi/validate v0.24.0 // indirect
|
github.com/go-openapi/validate v0.24.0 // indirect
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
github.com/josharian/intern v1.0.0 // indirect
|
github.com/josharian/intern v1.0.0 // indirect
|
||||||
github.com/klauspost/compress v1.17.11 // indirect
|
github.com/klauspost/compress v1.17.9 // indirect
|
||||||
github.com/mailru/easyjson v0.7.7 // indirect
|
github.com/mailru/easyjson v0.7.7 // indirect
|
||||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||||
github.com/oklog/ulid v1.3.1 // indirect
|
github.com/oklog/ulid v1.3.1 // indirect
|
||||||
github.com/opentracing/opentracing-go v1.2.0 // indirect
|
github.com/opentracing/opentracing-go v1.2.0 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/prometheus/client_model v0.6.1 // indirect
|
github.com/prometheus/client_model v0.6.1 // indirect
|
||||||
github.com/prometheus/common v0.62.0 // indirect
|
github.com/prometheus/common v0.55.0 // indirect
|
||||||
github.com/prometheus/procfs v0.15.1 // indirect
|
github.com/prometheus/procfs v0.15.1 // indirect
|
||||||
github.com/spf13/pflag v1.0.6 // indirect
|
github.com/spf13/pflag v1.0.6 // indirect
|
||||||
go.mongodb.org/mongo-driver v1.14.0 // indirect
|
go.mongodb.org/mongo-driver v1.14.0 // indirect
|
||||||
go.opentelemetry.io/otel v1.24.0 // indirect
|
go.opentelemetry.io/otel v1.24.0 // indirect
|
||||||
go.opentelemetry.io/otel/metric v1.24.0 // indirect
|
go.opentelemetry.io/otel/metric v1.24.0 // indirect
|
||||||
go.opentelemetry.io/otel/trace v1.24.0 // indirect
|
go.opentelemetry.io/otel/trace v1.24.0 // indirect
|
||||||
golang.org/x/crypto v0.36.0 // indirect
|
golang.org/x/crypto v0.31.0 // indirect
|
||||||
golang.org/x/sys v0.31.0 // indirect
|
golang.org/x/sys v0.28.0 // indirect
|
||||||
golang.org/x/text v0.23.0 // indirect
|
golang.org/x/text v0.21.0 // indirect
|
||||||
google.golang.org/protobuf v1.36.1 // indirect
|
google.golang.org/protobuf v1.34.2 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
52
go.sum
52
go.sum
@ -55,8 +55,8 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P
|
|||||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||||
github.com/coreos/go-oidc/v3 v3.13.0 h1:M66zd0pcc5VxvBNM4pB331Wrsanby+QomQYjN8HamW8=
|
github.com/coreos/go-oidc/v3 v3.12.0 h1:sJk+8G2qq94rDI6ehZ71Bol3oUHy63qNYmkiSjrc/Jo=
|
||||||
github.com/coreos/go-oidc/v3 v3.13.0/go.mod h1:HaZ3szPaZ0e4r6ebqvsLWlk2Tn+aejfmrfah6hnSYEU=
|
github.com/coreos/go-oidc/v3 v3.12.0/go.mod h1:gE3LgjOgFoHi9a4ce4/tJczr0Ai2/BoDhf0r5lltWI0=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
@ -84,8 +84,8 @@ github.com/go-http-utils/fresh v0.0.0-20161124030543-7231e26a4b27 h1:O6yi4xa9b2D
|
|||||||
github.com/go-http-utils/fresh v0.0.0-20161124030543-7231e26a4b27/go.mod h1:AYvN8omj7nKLmbcXS2dyABYU6JB1Lz1bHmkkq1kf4I4=
|
github.com/go-http-utils/fresh v0.0.0-20161124030543-7231e26a4b27/go.mod h1:AYvN8omj7nKLmbcXS2dyABYU6JB1Lz1bHmkkq1kf4I4=
|
||||||
github.com/go-http-utils/headers v0.0.0-20181008091004-fed159eddc2a h1:v6zMvHuY9yue4+QkG/HQ/W67wvtQmWJ4SDo9aK/GIno=
|
github.com/go-http-utils/headers v0.0.0-20181008091004-fed159eddc2a h1:v6zMvHuY9yue4+QkG/HQ/W67wvtQmWJ4SDo9aK/GIno=
|
||||||
github.com/go-http-utils/headers v0.0.0-20181008091004-fed159eddc2a/go.mod h1:I79BieaU4fxrw4LMXby6q5OS9XnoR9UIKLOzDFjUmuw=
|
github.com/go-http-utils/headers v0.0.0-20181008091004-fed159eddc2a/go.mod h1:I79BieaU4fxrw4LMXby6q5OS9XnoR9UIKLOzDFjUmuw=
|
||||||
github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE=
|
github.com/go-jose/go-jose/v4 v4.0.2 h1:R3l3kkBds16bO7ZFAEEcofK0MkrAJt3jlJznWZG0nvk=
|
||||||
github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA=
|
github.com/go-jose/go-jose/v4 v4.0.2/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY=
|
||||||
github.com/go-ldap/ldap/v3 v3.4.10 h1:ot/iwPOhfpNVgB1o+AVXljizWZ9JTp7YF5oeyONmcJU=
|
github.com/go-ldap/ldap/v3 v3.4.10 h1:ot/iwPOhfpNVgB1o+AVXljizWZ9JTp7YF5oeyONmcJU=
|
||||||
github.com/go-ldap/ldap/v3 v3.4.10/go.mod h1:JXh4Uxgi40P6E9rdsYqpUtbW46D9UTjJ9QSwGRznplY=
|
github.com/go-ldap/ldap/v3 v3.4.10/go.mod h1:JXh4Uxgi40P6E9rdsYqpUtbW46D9UTjJ9QSwGRznplY=
|
||||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||||
@ -207,8 +207,8 @@ github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFF
|
|||||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
|
||||||
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
@ -239,17 +239,17 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
|||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/prometheus/client_golang v1.21.1 h1:DOvXXTqVzvkIewV/CDPFdejpMCGeMcbGCQ8YOmu+Ibk=
|
github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
|
||||||
github.com/prometheus/client_golang v1.21.1/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg=
|
github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
||||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||||
github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io=
|
github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc=
|
||||||
github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
|
github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8=
|
||||||
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
|
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
|
||||||
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
||||||
github.com/redis/go-redis/v9 v9.7.1 h1:4LhKRCIduqXqtvCUlaq9c8bdHOkICjDMrr1+Zb3osAc=
|
github.com/redis/go-redis/v9 v9.7.0 h1:HhLSs+B6O021gwzl+locl0zEDnyNkxMtf/Z3NNBMa9E=
|
||||||
github.com/redis/go-redis/v9 v9.7.1/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw=
|
github.com/redis/go-redis/v9 v9.7.0/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw=
|
||||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
||||||
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
|
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
|
||||||
@ -299,8 +299,8 @@ go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y
|
|||||||
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
|
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
|
||||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||||
goauthentik.io/api/v3 v3.2025021.4 h1:KFap2KW+8CwhOxjBkRnRB4flvuHEMw24+fZei9dOhzw=
|
goauthentik.io/api/v3 v3.2024123.6 h1:AGOCa7Fc/9eONCPEW4sEhTiyEBvxN57Lfqz1zm6Gy98=
|
||||||
goauthentik.io/api/v3 v3.2025021.4/go.mod h1:zz+mEZg8rY/7eEjkMGWJ2DnGqk+zqxuybGCGrR2O4Kw=
|
goauthentik.io/api/v3 v3.2024123.6/go.mod h1:zz+mEZg8rY/7eEjkMGWJ2DnGqk+zqxuybGCGrR2O4Kw=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
@ -312,9 +312,8 @@ golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58
|
|||||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||||
|
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
|
||||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||||
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
|
||||||
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||||
@ -386,17 +385,16 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
|||||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||||
|
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
|
||||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||||
golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
|
|
||||||
golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||||
golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc=
|
golang.org/x/oauth2 v0.26.0 h1:afQXWNNaeC4nvZ0Ed9XvCCzXM6UHJG7iCg0W4fPqSBE=
|
||||||
golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
|
golang.org/x/oauth2 v0.26.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
@ -411,8 +409,8 @@ golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
|||||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
|
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
|
||||||
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@ -449,9 +447,8 @@ 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.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
|
||||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
|
||||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
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.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
@ -472,9 +469,8 @@ 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.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||||
|
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||||
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
|
||||||
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
@ -599,8 +595,8 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
|
|||||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||||
google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk=
|
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
|
||||||
google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
|
@ -29,4 +29,4 @@ func UserAgent() string {
|
|||||||
return fmt.Sprintf("authentik@%s", FullVersion())
|
return fmt.Sprintf("authentik@%s", FullVersion())
|
||||||
}
|
}
|
||||||
|
|
||||||
const VERSION = "2025.2.1"
|
const VERSION = "2025.2.4"
|
||||||
|
@ -35,13 +35,19 @@ func Paginator[Tobj any, Treq any, Tres PaginatorResponse[Tobj]](
|
|||||||
req PaginatorRequest[Treq, Tres],
|
req PaginatorRequest[Treq, Tres],
|
||||||
opts PaginatorOptions,
|
opts PaginatorOptions,
|
||||||
) ([]Tobj, error) {
|
) ([]Tobj, error) {
|
||||||
|
if opts.Logger == nil {
|
||||||
|
opts.Logger = log.NewEntry(log.StandardLogger())
|
||||||
|
}
|
||||||
var bfreq, cfreq interface{}
|
var bfreq, cfreq interface{}
|
||||||
fetchOffset := func(page int32) (Tres, error) {
|
fetchOffset := func(page int32) (Tres, error) {
|
||||||
bfreq = req.Page(page)
|
bfreq = req.Page(page)
|
||||||
cfreq = bfreq.(PaginatorRequest[Treq, Tres]).PageSize(int32(opts.PageSize))
|
cfreq = bfreq.(PaginatorRequest[Treq, Tres]).PageSize(int32(opts.PageSize))
|
||||||
res, _, err := cfreq.(PaginatorRequest[Treq, Tres]).Execute()
|
res, hres, err := cfreq.(PaginatorRequest[Treq, Tres]).Execute()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
opts.Logger.WithError(err).WithField("page", page).Warning("failed to fetch page")
|
opts.Logger.WithError(err).WithField("page", page).Warning("failed to fetch page")
|
||||||
|
if hres != nil && hres.StatusCode >= 400 && hres.StatusCode < 500 {
|
||||||
|
return res, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
@ -51,6 +57,9 @@ func Paginator[Tobj any, Treq any, Tres PaginatorResponse[Tobj]](
|
|||||||
for {
|
for {
|
||||||
apiObjects, err := fetchOffset(page)
|
apiObjects, err := fetchOffset(page)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if page == 1 {
|
||||||
|
return objects, err
|
||||||
|
}
|
||||||
errs = append(errs, err)
|
errs = append(errs, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,64 @@
|
|||||||
package ak
|
package ak
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"net/http"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"goauthentik.io/api/v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
type fakeAPIType struct{}
|
||||||
|
|
||||||
|
type fakeAPIResponse struct {
|
||||||
|
results []fakeAPIType
|
||||||
|
pagination api.Pagination
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fapi *fakeAPIResponse) GetResults() []fakeAPIType { return fapi.results }
|
||||||
|
func (fapi *fakeAPIResponse) GetPagination() api.Pagination { return fapi.pagination }
|
||||||
|
|
||||||
|
type fakeAPIRequest struct {
|
||||||
|
res *fakeAPIResponse
|
||||||
|
http *http.Response
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fapi *fakeAPIRequest) Page(page int32) *fakeAPIRequest { return fapi }
|
||||||
|
func (fapi *fakeAPIRequest) PageSize(size int32) *fakeAPIRequest { return fapi }
|
||||||
|
func (fapi *fakeAPIRequest) Execute() (*fakeAPIResponse, *http.Response, error) {
|
||||||
|
return fapi.res, fapi.http, fapi.err
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_Simple(t *testing.T) {
|
||||||
|
req := &fakeAPIRequest{
|
||||||
|
res: &fakeAPIResponse{
|
||||||
|
results: []fakeAPIType{
|
||||||
|
{},
|
||||||
|
},
|
||||||
|
pagination: api.Pagination{
|
||||||
|
TotalPages: 1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
res, err := Paginator(req, PaginatorOptions{})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Len(t, res, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Test_BadRequest(t *testing.T) {
|
||||||
|
req := &fakeAPIRequest{
|
||||||
|
http: &http.Response{
|
||||||
|
StatusCode: 400,
|
||||||
|
},
|
||||||
|
err: errors.New("foo"),
|
||||||
|
}
|
||||||
|
res, err := Paginator(req, PaginatorOptions{})
|
||||||
|
assert.Error(t, err)
|
||||||
|
assert.Equal(t, []fakeAPIType{}, res)
|
||||||
|
}
|
||||||
|
|
||||||
// func Test_PaginatorCompile(t *testing.T) {
|
// func Test_PaginatorCompile(t *testing.T) {
|
||||||
// req := api.ApiCoreUsersListRequest{}
|
// req := api.ApiCoreUsersListRequest{}
|
||||||
// Paginator(req, PaginatorOptions{
|
// Paginator(req, PaginatorOptions{
|
||||||
|
8
lifecycle/aws/package-lock.json
generated
8
lifecycle/aws/package-lock.json
generated
@ -9,7 +9,7 @@
|
|||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"aws-cdk": "^2.1004.0",
|
"aws-cdk": "^2.179.0",
|
||||||
"cross-env": "^7.0.3"
|
"cross-env": "^7.0.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@ -17,9 +17,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/aws-cdk": {
|
"node_modules/aws-cdk": {
|
||||||
"version": "2.1004.0",
|
"version": "2.179.0",
|
||||||
"resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1004.0.tgz",
|
"resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.179.0.tgz",
|
||||||
"integrity": "sha512-3E5ICmSc7ZCZCwLX7NY+HFmmdUYgRaL+67h/BDoDQmkhx9StC8wG4xgzHFY9k8WQS0+ib/MP28f2d9yzHtQLlQ==",
|
"integrity": "sha512-aA2+8S2g4UBQHkUEt0mYd16VLt/ucR+QfyUJi34LDKRAhOCNDjPCZ4z9z/JEDyuni0BdzsYA55pnpDN9tMULpA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"bin": {
|
"bin": {
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
"node": ">=20"
|
"node": ">=20"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"aws-cdk": "^2.1004.0",
|
"aws-cdk": "^2.179.0",
|
||||||
"cross-env": "^7.0.3"
|
"cross-env": "^7.0.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ Parameters:
|
|||||||
Description: authentik Docker image
|
Description: authentik Docker image
|
||||||
AuthentikVersion:
|
AuthentikVersion:
|
||||||
Type: String
|
Type: String
|
||||||
Default: 2025.2.1
|
Default: 2025.2.4
|
||||||
Description: authentik Docker image tag
|
Description: authentik Docker image tag
|
||||||
AuthentikServerCPU:
|
AuthentikServerCPU:
|
||||||
Type: Number
|
Type: Number
|
||||||
|
@ -63,9 +63,7 @@ def wait_for_db():
|
|||||||
# Sanity check, ensure SECRET_KEY is set before we even check for database connectivity
|
# Sanity check, ensure SECRET_KEY is set before we even check for database connectivity
|
||||||
if CONFIG.get("secret_key") is None or len(CONFIG.get("secret_key")) == 0:
|
if CONFIG.get("secret_key") is None or len(CONFIG.get("secret_key")) == 0:
|
||||||
CONFIG.log("info", "----------------------------------------------------------------------")
|
CONFIG.log("info", "----------------------------------------------------------------------")
|
||||||
CONFIG.log(
|
CONFIG.log("info", "Secret key missing, check https://goauthentik.io/docs/installation/.")
|
||||||
"info", "Secret key missing, check https://docs.goauthentik.io/docs/install-config/"
|
|
||||||
)
|
|
||||||
CONFIG.log("info", "----------------------------------------------------------------------")
|
CONFIG.log("info", "----------------------------------------------------------------------")
|
||||||
sysexit(1)
|
sysexit(1)
|
||||||
check_postgres()
|
check_postgres()
|
||||||
|
@ -8,7 +8,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-03-13 00:10+0000\n"
|
"POT-Creation-Date: 2025-02-14 14:49+0000\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
@ -109,10 +109,6 @@ msgstr ""
|
|||||||
msgid "Extra description not available"
|
msgid "Extra description not available"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/core/api/groups.py
|
|
||||||
msgid "Cannot set group as parent of itself."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/core/api/providers.py
|
#: authentik/core/api/providers.py
|
||||||
msgid ""
|
msgid ""
|
||||||
"When not set all providers are returned. When set to true, only backchannel "
|
"When not set all providers are returned. When set to true, only backchannel "
|
||||||
@ -156,14 +152,6 @@ msgstr ""
|
|||||||
msgid "Remove user from group"
|
msgid "Remove user from group"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/core/models.py
|
|
||||||
msgid "Enable superuser status"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/core/models.py
|
|
||||||
msgid "Disable superuser status"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/core/models.py
|
#: authentik/core/models.py
|
||||||
msgid "User's display name."
|
msgid "User's display name."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -512,6 +500,57 @@ msgstr ""
|
|||||||
msgid "Microsoft Entra Provider Mappings"
|
msgid "Microsoft Entra Provider Mappings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/models.py
|
||||||
|
#: authentik/stages/user_login/models.py
|
||||||
|
msgid ""
|
||||||
|
"Determines how long a session lasts. Default of 0 means that the sessions "
|
||||||
|
"lasts until the browser is closed. (Format: hours=-1;minutes=-2;seconds=-3)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/models.py
|
||||||
|
msgid "When set to true, connection tokens will be deleted upon disconnect."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/models.py
|
||||||
|
msgid "RAC Provider"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/models.py
|
||||||
|
msgid "RAC Providers"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/models.py
|
||||||
|
msgid "RAC Endpoint"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/models.py
|
||||||
|
msgid "RAC Endpoints"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/models.py
|
||||||
|
msgid "RAC Provider Property Mapping"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/models.py
|
||||||
|
msgid "RAC Provider Property Mappings"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/models.py
|
||||||
|
msgid "RAC Connection token"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/models.py
|
||||||
|
msgid "RAC Connection tokens"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/views.py
|
||||||
|
msgid "Maximum connection limit reached."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/views.py
|
||||||
|
msgid "(You are already connected in another tab/window)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/enterprise/providers/ssf/models.py
|
#: authentik/enterprise/providers/ssf/models.py
|
||||||
#: authentik/providers/oauth2/models.py
|
#: authentik/providers/oauth2/models.py
|
||||||
msgid "Signing Key"
|
msgid "Signing Key"
|
||||||
@ -612,7 +651,7 @@ msgstr ""
|
|||||||
msgid "Slack Webhook (Slack/Discord)"
|
msgid "Slack Webhook (Slack/Discord)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/events/models.py authentik/stages/authenticator_validate/models.py
|
#: authentik/events/models.py
|
||||||
msgid "Email"
|
msgid "Email"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@ -865,12 +904,6 @@ msgstr ""
|
|||||||
msgid "Invalid next URL"
|
msgid "Invalid next URL"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/lib/sync/outgoing/models.py
|
|
||||||
msgid ""
|
|
||||||
"When enabled, provider will not modify or create objects in the remote "
|
|
||||||
"system."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/lib/sync/outgoing/tasks.py
|
#: authentik/lib/sync/outgoing/tasks.py
|
||||||
msgid "Starting full provider sync"
|
msgid "Starting full provider sync"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -885,10 +918,6 @@ msgstr ""
|
|||||||
msgid "Syncing page {page} of groups"
|
msgid "Syncing page {page} of groups"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/lib/sync/outgoing/tasks.py
|
|
||||||
msgid "Dropping mutating request due to dry run"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/lib/sync/outgoing/tasks.py
|
#: authentik/lib/sync/outgoing/tasks.py
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Stopping sync due to error: {error}"
|
msgid "Stopping sync due to error: {error}"
|
||||||
@ -1076,14 +1105,6 @@ msgstr ""
|
|||||||
msgid "Client IP is not in an allowed country."
|
msgid "Client IP is not in an allowed country."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/policies/geoip/models.py
|
|
||||||
msgid "Distance from previous authentication is larger than threshold."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/policies/geoip/models.py
|
|
||||||
msgid "Distance is further than possible."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/policies/geoip/models.py
|
#: authentik/policies/geoip/models.py
|
||||||
msgid "GeoIP Policy"
|
msgid "GeoIP Policy"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -1375,14 +1396,6 @@ msgstr ""
|
|||||||
msgid "ES256 (Asymmetric Encryption)"
|
msgid "ES256 (Asymmetric Encryption)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/providers/oauth2/models.py
|
|
||||||
msgid "ES384 (Asymmetric Encryption)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/providers/oauth2/models.py
|
|
||||||
msgid "ES512 (Asymmetric Encryption)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/providers/oauth2/models.py
|
#: authentik/providers/oauth2/models.py
|
||||||
msgid "Scope used by the client"
|
msgid "Scope used by the client"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -1630,56 +1643,6 @@ msgstr ""
|
|||||||
msgid "Proxy Providers"
|
msgid "Proxy Providers"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/providers/rac/models.py authentik/stages/user_login/models.py
|
|
||||||
msgid ""
|
|
||||||
"Determines how long a session lasts. Default of 0 means that the sessions "
|
|
||||||
"lasts until the browser is closed. (Format: hours=-1;minutes=-2;seconds=-3)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/providers/rac/models.py
|
|
||||||
msgid "When set to true, connection tokens will be deleted upon disconnect."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/providers/rac/models.py
|
|
||||||
msgid "RAC Provider"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/providers/rac/models.py
|
|
||||||
msgid "RAC Providers"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/providers/rac/models.py
|
|
||||||
msgid "RAC Endpoint"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/providers/rac/models.py
|
|
||||||
msgid "RAC Endpoints"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/providers/rac/models.py
|
|
||||||
msgid "RAC Provider Property Mapping"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/providers/rac/models.py
|
|
||||||
msgid "RAC Provider Property Mappings"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/providers/rac/models.py
|
|
||||||
msgid "RAC Connection token"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/providers/rac/models.py
|
|
||||||
msgid "RAC Connection tokens"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/providers/rac/views.py
|
|
||||||
msgid "Maximum connection limit reached."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/providers/rac/views.py
|
|
||||||
msgid "(You are already connected in another tab/window)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/providers/radius/models.py
|
#: authentik/providers/radius/models.py
|
||||||
msgid "Shared secret between clients and server to hash packets."
|
msgid "Shared secret between clients and server to hash packets."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -1883,18 +1846,6 @@ msgstr ""
|
|||||||
msgid "SAML Providers from Metadata"
|
msgid "SAML Providers from Metadata"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/providers/scim/models.py
|
|
||||||
msgid "Default"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/providers/scim/models.py
|
|
||||||
msgid "AWS"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/providers/scim/models.py
|
|
||||||
msgid "Slack"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/providers/scim/models.py
|
#: authentik/providers/scim/models.py
|
||||||
msgid "Base URL to SCIM requests, usually ends in /v2"
|
msgid "Base URL to SCIM requests, usually ends in /v2"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -1903,14 +1854,6 @@ msgstr ""
|
|||||||
msgid "Authentication token"
|
msgid "Authentication token"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/providers/scim/models.py
|
|
||||||
msgid "SCIM Compatibility Mode"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/providers/scim/models.py
|
|
||||||
msgid "Alter authentik behavior for vendor-specific SCIM implementations."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/providers/scim/models.py
|
#: authentik/providers/scim/models.py
|
||||||
msgid "SCIM Provider"
|
msgid "SCIM Provider"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -2543,99 +2486,6 @@ msgstr ""
|
|||||||
msgid "Duo Devices"
|
msgid "Duo Devices"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/models.py
|
|
||||||
msgid "Email OTP"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/models.py
|
|
||||||
#: authentik/stages/email/models.py
|
|
||||||
msgid ""
|
|
||||||
"When enabled, global Email connection settings will be used and connection "
|
|
||||||
"settings below will be ignored."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/models.py
|
|
||||||
#: authentik/stages/email/models.py
|
|
||||||
msgid "Time the token sent is valid (Format: hours=3,minutes=17,seconds=300)."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/models.py
|
|
||||||
msgid "Email Authenticator Setup Stage"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/models.py
|
|
||||||
msgid "Email Authenticator Setup Stages"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/models.py
|
|
||||||
#: authentik/stages/authenticator_email/stage.py
|
|
||||||
#: authentik/stages/email/stage.py
|
|
||||||
msgid "Exception occurred while rendering E-mail template"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/models.py
|
|
||||||
msgid "Email Device"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/models.py
|
|
||||||
msgid "Email Devices"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/stage.py
|
|
||||||
#: authentik/stages/authenticator_sms/stage.py
|
|
||||||
#: authentik/stages/authenticator_totp/stage.py
|
|
||||||
msgid "Code does not match"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/stage.py
|
|
||||||
msgid "Invalid email"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/templates/email/email_otp.html
|
|
||||||
#: authentik/stages/email/templates/email/password_reset.html
|
|
||||||
#, python-format
|
|
||||||
msgid ""
|
|
||||||
"\n"
|
|
||||||
" Hi %(username)s,\n"
|
|
||||||
" "
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/templates/email/email_otp.html
|
|
||||||
msgid ""
|
|
||||||
"\n"
|
|
||||||
" Email MFA code.\n"
|
|
||||||
" "
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/templates/email/email_otp.html
|
|
||||||
#, python-format
|
|
||||||
msgid ""
|
|
||||||
"\n"
|
|
||||||
" If you did not request this code, please ignore this email. The code "
|
|
||||||
"above is valid for %(expires)s.\n"
|
|
||||||
" "
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/templates/email/email_otp.txt
|
|
||||||
#: authentik/stages/email/templates/email/password_reset.txt
|
|
||||||
#, python-format
|
|
||||||
msgid "Hi %(username)s,"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/templates/email/email_otp.txt
|
|
||||||
msgid ""
|
|
||||||
"\n"
|
|
||||||
"Email MFA code\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/templates/email/email_otp.txt
|
|
||||||
#, python-format
|
|
||||||
msgid ""
|
|
||||||
"\n"
|
|
||||||
"If you did not request this code, please ignore this email. The code above "
|
|
||||||
"is valid for %(expires)s.\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_sms/models.py
|
#: authentik/stages/authenticator_sms/models.py
|
||||||
msgid ""
|
msgid ""
|
||||||
"When enabled, the Phone number is only used during enrollment to verify the "
|
"When enabled, the Phone number is only used during enrollment to verify the "
|
||||||
@ -2668,6 +2518,11 @@ msgstr ""
|
|||||||
msgid "SMS Devices"
|
msgid "SMS Devices"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/stages/authenticator_sms/stage.py
|
||||||
|
#: authentik/stages/authenticator_totp/stage.py
|
||||||
|
msgid "Code does not match"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/stages/authenticator_sms/stage.py
|
#: authentik/stages/authenticator_sms/stage.py
|
||||||
msgid "Invalid phone number"
|
msgid "Invalid phone number"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -2890,10 +2745,20 @@ msgstr ""
|
|||||||
msgid "Account Confirmation"
|
msgid "Account Confirmation"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/stages/email/models.py
|
||||||
|
msgid ""
|
||||||
|
"When enabled, global Email connection settings will be used and connection "
|
||||||
|
"settings below will be ignored."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/stages/email/models.py
|
#: authentik/stages/email/models.py
|
||||||
msgid "Activate users upon completion of stage."
|
msgid "Activate users upon completion of stage."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/stages/email/models.py
|
||||||
|
msgid "Time in minutes the token sent is valid."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/stages/email/models.py
|
#: authentik/stages/email/models.py
|
||||||
msgid "Email Stage"
|
msgid "Email Stage"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -2902,6 +2767,10 @@ msgstr ""
|
|||||||
msgid "Email Stages"
|
msgid "Email Stages"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/stages/email/stage.py
|
||||||
|
msgid "Exception occurred while rendering E-mail template"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/stages/email/stage.py
|
#: authentik/stages/email/stage.py
|
||||||
msgid "Successfully verified Email."
|
msgid "Successfully verified Email."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -2976,6 +2845,14 @@ msgid ""
|
|||||||
"This email was sent from the notification transport %(name)s.\n"
|
"This email was sent from the notification transport %(name)s.\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/stages/email/templates/email/password_reset.html
|
||||||
|
#, python-format
|
||||||
|
msgid ""
|
||||||
|
"\n"
|
||||||
|
" Hi %(username)s,\n"
|
||||||
|
" "
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/stages/email/templates/email/password_reset.html
|
#: authentik/stages/email/templates/email/password_reset.html
|
||||||
msgid ""
|
msgid ""
|
||||||
"\n"
|
"\n"
|
||||||
@ -2993,6 +2870,11 @@ msgid ""
|
|||||||
" "
|
" "
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/stages/email/templates/email/password_reset.txt
|
||||||
|
#, python-format
|
||||||
|
msgid "Hi %(username)s,"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/stages/email/templates/email/password_reset.txt
|
#: authentik/stages/email/templates/email/password_reset.txt
|
||||||
msgid ""
|
msgid ""
|
||||||
"\n"
|
"\n"
|
||||||
|
Binary file not shown.
@ -9,9 +9,9 @@
|
|||||||
# Kyllian Delaye-Maillot, 2023
|
# Kyllian Delaye-Maillot, 2023
|
||||||
# Manuel Viens, 2023
|
# Manuel Viens, 2023
|
||||||
# Mordecai, 2023
|
# Mordecai, 2023
|
||||||
|
# Charles Leclerc, 2024
|
||||||
# nerdinator <florian.dupret@gmail.com>, 2024
|
# nerdinator <florian.dupret@gmail.com>, 2024
|
||||||
# Tina, 2024
|
# Tina, 2024
|
||||||
# Charles Leclerc, 2025
|
|
||||||
# Marc Schmitt, 2025
|
# Marc Schmitt, 2025
|
||||||
#
|
#
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
@ -19,7 +19,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-03-13 00:10+0000\n"
|
"POT-Creation-Date: 2025-02-14 14:49+0000\n"
|
||||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||||
"Last-Translator: Marc Schmitt, 2025\n"
|
"Last-Translator: Marc Schmitt, 2025\n"
|
||||||
"Language-Team: French (https://app.transifex.com/authentik/teams/119923/fr/)\n"
|
"Language-Team: French (https://app.transifex.com/authentik/teams/119923/fr/)\n"
|
||||||
@ -129,10 +129,6 @@ msgstr "L'utilisateur n'a pas accès à l'application."
|
|||||||
msgid "Extra description not available"
|
msgid "Extra description not available"
|
||||||
msgstr "Description supplémentaire indisponible"
|
msgstr "Description supplémentaire indisponible"
|
||||||
|
|
||||||
#: authentik/core/api/groups.py
|
|
||||||
msgid "Cannot set group as parent of itself."
|
|
||||||
msgstr "Impossible de définir le groupe en tant que parent de lui-même."
|
|
||||||
|
|
||||||
#: authentik/core/api/providers.py
|
#: authentik/core/api/providers.py
|
||||||
msgid ""
|
msgid ""
|
||||||
"When not set all providers are returned. When set to true, only backchannel "
|
"When not set all providers are returned. When set to true, only backchannel "
|
||||||
@ -181,14 +177,6 @@ msgstr "Ajouter un utilisateur au groupe"
|
|||||||
msgid "Remove user from group"
|
msgid "Remove user from group"
|
||||||
msgstr "Retirer l'utilisateur du groupe"
|
msgstr "Retirer l'utilisateur du groupe"
|
||||||
|
|
||||||
#: authentik/core/models.py
|
|
||||||
msgid "Enable superuser status"
|
|
||||||
msgstr "Activer le statut super-utilisateur"
|
|
||||||
|
|
||||||
#: authentik/core/models.py
|
|
||||||
msgid "Disable superuser status"
|
|
||||||
msgstr "Désactiver le statut super-utilisateur"
|
|
||||||
|
|
||||||
#: authentik/core/models.py
|
#: authentik/core/models.py
|
||||||
msgid "User's display name."
|
msgid "User's display name."
|
||||||
msgstr "Nom d'affichage de l'utilisateur"
|
msgstr "Nom d'affichage de l'utilisateur"
|
||||||
@ -565,6 +553,61 @@ msgstr "Mappage de propriété Microsoft Entra"
|
|||||||
msgid "Microsoft Entra Provider Mappings"
|
msgid "Microsoft Entra Provider Mappings"
|
||||||
msgstr "Mappages de propriété Microsoft Entra"
|
msgstr "Mappages de propriété Microsoft Entra"
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/models.py
|
||||||
|
#: authentik/stages/user_login/models.py
|
||||||
|
msgid ""
|
||||||
|
"Determines how long a session lasts. Default of 0 means that the sessions "
|
||||||
|
"lasts until the browser is closed. (Format: hours=-1;minutes=-2;seconds=-3)"
|
||||||
|
msgstr ""
|
||||||
|
"Détermine la durée de la session. La valeur par défaut de 0 signifie que la "
|
||||||
|
"session dure jusqu'à la fermeture du navigateur. (Format : "
|
||||||
|
"hours=-1;minutes=-2;seconds=-3)"
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/models.py
|
||||||
|
msgid "When set to true, connection tokens will be deleted upon disconnect."
|
||||||
|
msgstr ""
|
||||||
|
"Si activé, les jetons de connexion seront supprimés lors de la déconnexion."
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/models.py
|
||||||
|
msgid "RAC Provider"
|
||||||
|
msgstr "Fournisseur RAC"
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/models.py
|
||||||
|
msgid "RAC Providers"
|
||||||
|
msgstr "Fournisseurs RAC"
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/models.py
|
||||||
|
msgid "RAC Endpoint"
|
||||||
|
msgstr "Point de terminaison RAC"
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/models.py
|
||||||
|
msgid "RAC Endpoints"
|
||||||
|
msgstr "Points de terminaison RAC"
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/models.py
|
||||||
|
msgid "RAC Provider Property Mapping"
|
||||||
|
msgstr "Mappage de propriété fournisseur RAC"
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/models.py
|
||||||
|
msgid "RAC Provider Property Mappings"
|
||||||
|
msgstr "Mappages de propriété fournisseur RAC"
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/models.py
|
||||||
|
msgid "RAC Connection token"
|
||||||
|
msgstr "Jeton de connexion RAC"
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/models.py
|
||||||
|
msgid "RAC Connection tokens"
|
||||||
|
msgstr "Jeton de connexions RAC"
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/views.py
|
||||||
|
msgid "Maximum connection limit reached."
|
||||||
|
msgstr "Limite maximum de connection atteinte."
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/views.py
|
||||||
|
msgid "(You are already connected in another tab/window)"
|
||||||
|
msgstr "(Vous êtes déjà connecté dans un autre onglet/une autre fenêtre)"
|
||||||
|
|
||||||
#: authentik/enterprise/providers/ssf/models.py
|
#: authentik/enterprise/providers/ssf/models.py
|
||||||
#: authentik/providers/oauth2/models.py
|
#: authentik/providers/oauth2/models.py
|
||||||
msgid "Signing Key"
|
msgid "Signing Key"
|
||||||
@ -672,7 +715,6 @@ msgid "Slack Webhook (Slack/Discord)"
|
|||||||
msgstr "Webhook Slack (ou Discord)"
|
msgstr "Webhook Slack (ou Discord)"
|
||||||
|
|
||||||
#: authentik/events/models.py
|
#: authentik/events/models.py
|
||||||
#: authentik/stages/authenticator_validate/models.py
|
|
||||||
msgid "Email"
|
msgid "Email"
|
||||||
msgstr "Courriel"
|
msgstr "Courriel"
|
||||||
|
|
||||||
@ -948,14 +990,6 @@ msgstr "Jetons du flux"
|
|||||||
msgid "Invalid next URL"
|
msgid "Invalid next URL"
|
||||||
msgstr "URL suivante invalide"
|
msgstr "URL suivante invalide"
|
||||||
|
|
||||||
#: authentik/lib/sync/outgoing/models.py
|
|
||||||
msgid ""
|
|
||||||
"When enabled, provider will not modify or create objects in the remote "
|
|
||||||
"system."
|
|
||||||
msgstr ""
|
|
||||||
"Si activé, le fournisseur ne changera ou ne créera pas d'objets auprès du "
|
|
||||||
"système distant."
|
|
||||||
|
|
||||||
#: authentik/lib/sync/outgoing/tasks.py
|
#: authentik/lib/sync/outgoing/tasks.py
|
||||||
msgid "Starting full provider sync"
|
msgid "Starting full provider sync"
|
||||||
msgstr "Démarrage d'une synchronisation complète du fournisseur"
|
msgstr "Démarrage d'une synchronisation complète du fournisseur"
|
||||||
@ -970,10 +1004,6 @@ msgstr "Synchronisation de la page {page} d'utilisateurs"
|
|||||||
msgid "Syncing page {page} of groups"
|
msgid "Syncing page {page} of groups"
|
||||||
msgstr "Synchronisation de la page {page} de groupes"
|
msgstr "Synchronisation de la page {page} de groupes"
|
||||||
|
|
||||||
#: authentik/lib/sync/outgoing/tasks.py
|
|
||||||
msgid "Dropping mutating request due to dry run"
|
|
||||||
msgstr "Abandon de la requête de mutation en raison d'une simulation"
|
|
||||||
|
|
||||||
#: authentik/lib/sync/outgoing/tasks.py
|
#: authentik/lib/sync/outgoing/tasks.py
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Stopping sync due to error: {error}"
|
msgid "Stopping sync due to error: {error}"
|
||||||
@ -1189,16 +1219,6 @@ msgstr ""
|
|||||||
msgid "Client IP is not in an allowed country."
|
msgid "Client IP is not in an allowed country."
|
||||||
msgstr "L'IP du client ne fait pas partie d'un pays autorisé."
|
msgstr "L'IP du client ne fait pas partie d'un pays autorisé."
|
||||||
|
|
||||||
#: authentik/policies/geoip/models.py
|
|
||||||
msgid "Distance from previous authentication is larger than threshold."
|
|
||||||
msgstr ""
|
|
||||||
"La distance par rapport à l'authentification précédente est supérieure au "
|
|
||||||
"seuil."
|
|
||||||
|
|
||||||
#: authentik/policies/geoip/models.py
|
|
||||||
msgid "Distance is further than possible."
|
|
||||||
msgstr "La distance est plus grande que possible."
|
|
||||||
|
|
||||||
#: authentik/policies/geoip/models.py
|
#: authentik/policies/geoip/models.py
|
||||||
msgid "GeoIP Policy"
|
msgid "GeoIP Policy"
|
||||||
msgstr "Politique GeoIP"
|
msgstr "Politique GeoIP"
|
||||||
@ -1522,14 +1542,6 @@ msgstr "RS256 (chiffrement asymétrique)"
|
|||||||
msgid "ES256 (Asymmetric Encryption)"
|
msgid "ES256 (Asymmetric Encryption)"
|
||||||
msgstr "ES256 (Chiffrement Asymétrique)"
|
msgstr "ES256 (Chiffrement Asymétrique)"
|
||||||
|
|
||||||
#: authentik/providers/oauth2/models.py
|
|
||||||
msgid "ES384 (Asymmetric Encryption)"
|
|
||||||
msgstr "ES384 (chiffrement asymétrique)"
|
|
||||||
|
|
||||||
#: authentik/providers/oauth2/models.py
|
|
||||||
msgid "ES512 (Asymmetric Encryption)"
|
|
||||||
msgstr "ES512 (chiffrement asymétrique)"
|
|
||||||
|
|
||||||
#: authentik/providers/oauth2/models.py
|
#: authentik/providers/oauth2/models.py
|
||||||
msgid "Scope used by the client"
|
msgid "Scope used by the client"
|
||||||
msgstr "Portées utilisées par le client"
|
msgstr "Portées utilisées par le client"
|
||||||
@ -1813,60 +1825,6 @@ msgstr "Fournisseur Proxy"
|
|||||||
msgid "Proxy Providers"
|
msgid "Proxy Providers"
|
||||||
msgstr "Fournisseur de Proxy"
|
msgstr "Fournisseur de Proxy"
|
||||||
|
|
||||||
#: authentik/providers/rac/models.py authentik/stages/user_login/models.py
|
|
||||||
msgid ""
|
|
||||||
"Determines how long a session lasts. Default of 0 means that the sessions "
|
|
||||||
"lasts until the browser is closed. (Format: hours=-1;minutes=-2;seconds=-3)"
|
|
||||||
msgstr ""
|
|
||||||
"Détermine la durée de la session. La valeur par défaut de 0 signifie que la "
|
|
||||||
"session dure jusqu'à la fermeture du navigateur. (Format : "
|
|
||||||
"hours=-1;minutes=-2;seconds=-3)"
|
|
||||||
|
|
||||||
#: authentik/providers/rac/models.py
|
|
||||||
msgid "When set to true, connection tokens will be deleted upon disconnect."
|
|
||||||
msgstr ""
|
|
||||||
"Si activé, les jetons de connexion seront supprimés lors de la déconnexion."
|
|
||||||
|
|
||||||
#: authentik/providers/rac/models.py
|
|
||||||
msgid "RAC Provider"
|
|
||||||
msgstr "Fournisseur RAC"
|
|
||||||
|
|
||||||
#: authentik/providers/rac/models.py
|
|
||||||
msgid "RAC Providers"
|
|
||||||
msgstr "Fournisseurs RAC"
|
|
||||||
|
|
||||||
#: authentik/providers/rac/models.py
|
|
||||||
msgid "RAC Endpoint"
|
|
||||||
msgstr "Point de terminaison RAC"
|
|
||||||
|
|
||||||
#: authentik/providers/rac/models.py
|
|
||||||
msgid "RAC Endpoints"
|
|
||||||
msgstr "Points de terminaison RAC"
|
|
||||||
|
|
||||||
#: authentik/providers/rac/models.py
|
|
||||||
msgid "RAC Provider Property Mapping"
|
|
||||||
msgstr "Mappage de propriété fournisseur RAC"
|
|
||||||
|
|
||||||
#: authentik/providers/rac/models.py
|
|
||||||
msgid "RAC Provider Property Mappings"
|
|
||||||
msgstr "Mappages de propriété fournisseur RAC"
|
|
||||||
|
|
||||||
#: authentik/providers/rac/models.py
|
|
||||||
msgid "RAC Connection token"
|
|
||||||
msgstr "Jeton de connexion RAC"
|
|
||||||
|
|
||||||
#: authentik/providers/rac/models.py
|
|
||||||
msgid "RAC Connection tokens"
|
|
||||||
msgstr "Jeton de connexions RAC"
|
|
||||||
|
|
||||||
#: authentik/providers/rac/views.py
|
|
||||||
msgid "Maximum connection limit reached."
|
|
||||||
msgstr "Limite maximum de connection atteinte."
|
|
||||||
|
|
||||||
#: authentik/providers/rac/views.py
|
|
||||||
msgid "(You are already connected in another tab/window)"
|
|
||||||
msgstr "(Vous êtes déjà connecté dans un autre onglet/une autre fenêtre)"
|
|
||||||
|
|
||||||
#: authentik/providers/radius/models.py
|
#: authentik/providers/radius/models.py
|
||||||
msgid "Shared secret between clients and server to hash packets."
|
msgid "Shared secret between clients and server to hash packets."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -2097,18 +2055,6 @@ msgstr "Fournisseur SAML depuis métadonnées"
|
|||||||
msgid "SAML Providers from Metadata"
|
msgid "SAML Providers from Metadata"
|
||||||
msgstr "Fournisseurs SAML depuis métadonnées"
|
msgstr "Fournisseurs SAML depuis métadonnées"
|
||||||
|
|
||||||
#: authentik/providers/scim/models.py
|
|
||||||
msgid "Default"
|
|
||||||
msgstr "Par défaut"
|
|
||||||
|
|
||||||
#: authentik/providers/scim/models.py
|
|
||||||
msgid "AWS"
|
|
||||||
msgstr "AWS"
|
|
||||||
|
|
||||||
#: authentik/providers/scim/models.py
|
|
||||||
msgid "Slack"
|
|
||||||
msgstr "Slack"
|
|
||||||
|
|
||||||
#: authentik/providers/scim/models.py
|
#: authentik/providers/scim/models.py
|
||||||
msgid "Base URL to SCIM requests, usually ends in /v2"
|
msgid "Base URL to SCIM requests, usually ends in /v2"
|
||||||
msgstr "URL de base pour les requêtes SCIM, se terminant généralement par /v2"
|
msgstr "URL de base pour les requêtes SCIM, se terminant généralement par /v2"
|
||||||
@ -2117,16 +2063,6 @@ msgstr "URL de base pour les requêtes SCIM, se terminant généralement par /v2
|
|||||||
msgid "Authentication token"
|
msgid "Authentication token"
|
||||||
msgstr "Jeton d'authentification"
|
msgstr "Jeton d'authentification"
|
||||||
|
|
||||||
#: authentik/providers/scim/models.py
|
|
||||||
msgid "SCIM Compatibility Mode"
|
|
||||||
msgstr "Mode de compatibilité SCIM"
|
|
||||||
|
|
||||||
#: authentik/providers/scim/models.py
|
|
||||||
msgid "Alter authentik behavior for vendor-specific SCIM implementations."
|
|
||||||
msgstr ""
|
|
||||||
"Change le comportement d'authentik en fonction des spécificités "
|
|
||||||
"d'implémentations des fournisseurs SCIM."
|
|
||||||
|
|
||||||
#: authentik/providers/scim/models.py
|
#: authentik/providers/scim/models.py
|
||||||
msgid "SCIM Provider"
|
msgid "SCIM Provider"
|
||||||
msgstr "Fournisseur SCIM"
|
msgstr "Fournisseur SCIM"
|
||||||
@ -2805,113 +2741,6 @@ msgstr "Appareil Duo"
|
|||||||
msgid "Duo Devices"
|
msgid "Duo Devices"
|
||||||
msgstr "Appareils Duo"
|
msgstr "Appareils Duo"
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/models.py
|
|
||||||
msgid "Email OTP"
|
|
||||||
msgstr "OTP Courriel"
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/models.py
|
|
||||||
#: authentik/stages/email/models.py
|
|
||||||
msgid ""
|
|
||||||
"When enabled, global Email connection settings will be used and connection "
|
|
||||||
"settings below will be ignored."
|
|
||||||
msgstr ""
|
|
||||||
"Si activé, les paramètres globaux de connexion courriel seront utilisés et "
|
|
||||||
"les paramètres de connexion ci-dessous seront ignorés."
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/models.py
|
|
||||||
#: authentik/stages/email/models.py
|
|
||||||
msgid "Time the token sent is valid (Format: hours=3,minutes=17,seconds=300)."
|
|
||||||
msgstr ""
|
|
||||||
"Durée de validité du jeton envoyé (Format : hours=3,minutes=17,seconds=300)."
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/models.py
|
|
||||||
msgid "Email Authenticator Setup Stage"
|
|
||||||
msgstr "Étape de configuration de l'authentificateur courriel"
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/models.py
|
|
||||||
msgid "Email Authenticator Setup Stages"
|
|
||||||
msgstr "Étapes de configuration de l'authentificateur courriel"
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/models.py
|
|
||||||
#: authentik/stages/authenticator_email/stage.py
|
|
||||||
#: authentik/stages/email/stage.py
|
|
||||||
msgid "Exception occurred while rendering E-mail template"
|
|
||||||
msgstr "Une erreur s'est produite lors de la modélisation du couriel"
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/models.py
|
|
||||||
msgid "Email Device"
|
|
||||||
msgstr "Équipement courriel"
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/models.py
|
|
||||||
msgid "Email Devices"
|
|
||||||
msgstr "Équipements courriel"
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/stage.py
|
|
||||||
#: authentik/stages/authenticator_sms/stage.py
|
|
||||||
#: authentik/stages/authenticator_totp/stage.py
|
|
||||||
msgid "Code does not match"
|
|
||||||
msgstr "Le Code ne correspond pas"
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/stage.py
|
|
||||||
msgid "Invalid email"
|
|
||||||
msgstr "Courriel invalide"
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/templates/email/email_otp.html
|
|
||||||
#: authentik/stages/email/templates/email/password_reset.html
|
|
||||||
#, python-format
|
|
||||||
msgid ""
|
|
||||||
"\n"
|
|
||||||
" Hi %(username)s,\n"
|
|
||||||
" "
|
|
||||||
msgstr ""
|
|
||||||
"\n"
|
|
||||||
" Salut %(username)s,\n"
|
|
||||||
" "
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/templates/email/email_otp.html
|
|
||||||
msgid ""
|
|
||||||
"\n"
|
|
||||||
" Email MFA code.\n"
|
|
||||||
" "
|
|
||||||
msgstr ""
|
|
||||||
"\n"
|
|
||||||
" Code MFA envoyé par courriel.\n"
|
|
||||||
" "
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/templates/email/email_otp.html
|
|
||||||
#, python-format
|
|
||||||
msgid ""
|
|
||||||
"\n"
|
|
||||||
" If you did not request this code, please ignore this email. The code above is valid for %(expires)s.\n"
|
|
||||||
" "
|
|
||||||
msgstr ""
|
|
||||||
"\n"
|
|
||||||
" Si vous n'avez pas demandé ce code, veuillez ignorer ce courriel. Le code ci-dessus est valid pendant %(expires)s.\n"
|
|
||||||
" "
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/templates/email/email_otp.txt
|
|
||||||
#: authentik/stages/email/templates/email/password_reset.txt
|
|
||||||
#, python-format
|
|
||||||
msgid "Hi %(username)s,"
|
|
||||||
msgstr "Bonjour %(username)s,"
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/templates/email/email_otp.txt
|
|
||||||
msgid ""
|
|
||||||
"\n"
|
|
||||||
"Email MFA code\n"
|
|
||||||
msgstr ""
|
|
||||||
"\n"
|
|
||||||
"Code MFA envoyé par e-mail\n"
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/templates/email/email_otp.txt
|
|
||||||
#, python-format
|
|
||||||
msgid ""
|
|
||||||
"\n"
|
|
||||||
"If you did not request this code, please ignore this email. The code above is valid for %(expires)s.\n"
|
|
||||||
msgstr ""
|
|
||||||
"\n"
|
|
||||||
"Si vous n'avez pas demandé ce code, veuillez ignorer ce courriel. Le code ci-dessus est valid pendant %(expires)s.\n"
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_sms/models.py
|
#: authentik/stages/authenticator_sms/models.py
|
||||||
msgid ""
|
msgid ""
|
||||||
"When enabled, the Phone number is only used during enrollment to verify the "
|
"When enabled, the Phone number is only used during enrollment to verify the "
|
||||||
@ -2949,6 +2778,11 @@ msgstr "Appareil SMS"
|
|||||||
msgid "SMS Devices"
|
msgid "SMS Devices"
|
||||||
msgstr "Appareils SMS"
|
msgstr "Appareils SMS"
|
||||||
|
|
||||||
|
#: authentik/stages/authenticator_sms/stage.py
|
||||||
|
#: authentik/stages/authenticator_totp/stage.py
|
||||||
|
msgid "Code does not match"
|
||||||
|
msgstr "Le Code ne correspond pas"
|
||||||
|
|
||||||
#: authentik/stages/authenticator_sms/stage.py
|
#: authentik/stages/authenticator_sms/stage.py
|
||||||
msgid "Invalid phone number"
|
msgid "Invalid phone number"
|
||||||
msgstr "Numéro de téléphone invalide"
|
msgstr "Numéro de téléphone invalide"
|
||||||
@ -3187,10 +3021,22 @@ msgstr "Réinitialiser le Mot de Passe"
|
|||||||
msgid "Account Confirmation"
|
msgid "Account Confirmation"
|
||||||
msgstr "Confirmation du Compte"
|
msgstr "Confirmation du Compte"
|
||||||
|
|
||||||
|
#: authentik/stages/email/models.py
|
||||||
|
msgid ""
|
||||||
|
"When enabled, global Email connection settings will be used and connection "
|
||||||
|
"settings below will be ignored."
|
||||||
|
msgstr ""
|
||||||
|
"Si activé, les paramètres globaux de connexion courriel seront utilisés et "
|
||||||
|
"les paramètres de connexion ci-dessous seront ignorés."
|
||||||
|
|
||||||
#: authentik/stages/email/models.py
|
#: authentik/stages/email/models.py
|
||||||
msgid "Activate users upon completion of stage."
|
msgid "Activate users upon completion of stage."
|
||||||
msgstr "Activer les utilisateurs à la complétion de l'étape."
|
msgstr "Activer les utilisateurs à la complétion de l'étape."
|
||||||
|
|
||||||
|
#: authentik/stages/email/models.py
|
||||||
|
msgid "Time in minutes the token sent is valid."
|
||||||
|
msgstr "Temps en minutes durant lequel le jeton envoyé est valide."
|
||||||
|
|
||||||
#: authentik/stages/email/models.py
|
#: authentik/stages/email/models.py
|
||||||
msgid "Email Stage"
|
msgid "Email Stage"
|
||||||
msgstr "Étape Email"
|
msgstr "Étape Email"
|
||||||
@ -3199,6 +3045,10 @@ msgstr "Étape Email"
|
|||||||
msgid "Email Stages"
|
msgid "Email Stages"
|
||||||
msgstr "Étape Email"
|
msgstr "Étape Email"
|
||||||
|
|
||||||
|
#: authentik/stages/email/stage.py
|
||||||
|
msgid "Exception occurred while rendering E-mail template"
|
||||||
|
msgstr "Une erreur s'est produite lors de la modélisation du couriel"
|
||||||
|
|
||||||
#: authentik/stages/email/stage.py
|
#: authentik/stages/email/stage.py
|
||||||
msgid "Successfully verified Email."
|
msgid "Successfully verified Email."
|
||||||
msgstr "Email vérifié avec succès."
|
msgstr "Email vérifié avec succès."
|
||||||
@ -3283,6 +3133,17 @@ msgstr ""
|
|||||||
"\n"
|
"\n"
|
||||||
"Cet email a été envoyé depuis le transport de notification %(name)s.\n"
|
"Cet email a été envoyé depuis le transport de notification %(name)s.\n"
|
||||||
|
|
||||||
|
#: authentik/stages/email/templates/email/password_reset.html
|
||||||
|
#, python-format
|
||||||
|
msgid ""
|
||||||
|
"\n"
|
||||||
|
" Hi %(username)s,\n"
|
||||||
|
" "
|
||||||
|
msgstr ""
|
||||||
|
"\n"
|
||||||
|
" Salut %(username)s,\n"
|
||||||
|
" "
|
||||||
|
|
||||||
#: authentik/stages/email/templates/email/password_reset.html
|
#: authentik/stages/email/templates/email/password_reset.html
|
||||||
msgid ""
|
msgid ""
|
||||||
"\n"
|
"\n"
|
||||||
@ -3304,6 +3165,11 @@ msgstr ""
|
|||||||
" Si vous n'avez pas requis de changement de mot de passe, veuillez ignorer cet e-mail. Le lien ci-dessus est valide pendant %(expires)s.\n"
|
" Si vous n'avez pas requis de changement de mot de passe, veuillez ignorer cet e-mail. Le lien ci-dessus est valide pendant %(expires)s.\n"
|
||||||
" "
|
" "
|
||||||
|
|
||||||
|
#: authentik/stages/email/templates/email/password_reset.txt
|
||||||
|
#, python-format
|
||||||
|
msgid "Hi %(username)s,"
|
||||||
|
msgstr "Bonjour %(username)s,"
|
||||||
|
|
||||||
#: authentik/stages/email/templates/email/password_reset.txt
|
#: authentik/stages/email/templates/email/password_reset.txt
|
||||||
msgid ""
|
msgid ""
|
||||||
"\n"
|
"\n"
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -7,7 +7,7 @@
|
|||||||
# Chen Zhikai, 2022
|
# Chen Zhikai, 2022
|
||||||
# 刘松, 2022
|
# 刘松, 2022
|
||||||
# Tianhao Chai <cth451@gmail.com>, 2024
|
# Tianhao Chai <cth451@gmail.com>, 2024
|
||||||
# Jens L. <jens@goauthentik.io>, 2025
|
# Jens L. <jens@goauthentik.io>, 2024
|
||||||
# deluxghost, 2025
|
# deluxghost, 2025
|
||||||
#
|
#
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
@ -15,7 +15,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-03-13 00:10+0000\n"
|
"POT-Creation-Date: 2025-02-14 14:49+0000\n"
|
||||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||||
"Last-Translator: deluxghost, 2025\n"
|
"Last-Translator: deluxghost, 2025\n"
|
||||||
"Language-Team: Chinese Simplified (https://app.transifex.com/authentik/teams/119923/zh-Hans/)\n"
|
"Language-Team: Chinese Simplified (https://app.transifex.com/authentik/teams/119923/zh-Hans/)\n"
|
||||||
@ -118,10 +118,6 @@ msgstr "用户没有访问此应用程序的权限。"
|
|||||||
msgid "Extra description not available"
|
msgid "Extra description not available"
|
||||||
msgstr "额外描述不可用"
|
msgstr "额外描述不可用"
|
||||||
|
|
||||||
#: authentik/core/api/groups.py
|
|
||||||
msgid "Cannot set group as parent of itself."
|
|
||||||
msgstr "无法设置组自身为父级。"
|
|
||||||
|
|
||||||
#: authentik/core/api/providers.py
|
#: authentik/core/api/providers.py
|
||||||
msgid ""
|
msgid ""
|
||||||
"When not set all providers are returned. When set to true, only backchannel "
|
"When not set all providers are returned. When set to true, only backchannel "
|
||||||
@ -166,14 +162,6 @@ msgstr "添加用户到组"
|
|||||||
msgid "Remove user from group"
|
msgid "Remove user from group"
|
||||||
msgstr "从组中删除用户"
|
msgstr "从组中删除用户"
|
||||||
|
|
||||||
#: authentik/core/models.py
|
|
||||||
msgid "Enable superuser status"
|
|
||||||
msgstr "启用超级用户状态"
|
|
||||||
|
|
||||||
#: authentik/core/models.py
|
|
||||||
msgid "Disable superuser status"
|
|
||||||
msgstr "禁用超级用户状态"
|
|
||||||
|
|
||||||
#: authentik/core/models.py
|
#: authentik/core/models.py
|
||||||
msgid "User's display name."
|
msgid "User's display name."
|
||||||
msgstr "用户的显示名称。"
|
msgstr "用户的显示名称。"
|
||||||
@ -522,6 +510,57 @@ msgstr "Microsoft Entra 提供程序映射"
|
|||||||
msgid "Microsoft Entra Provider Mappings"
|
msgid "Microsoft Entra Provider Mappings"
|
||||||
msgstr "Microsoft Entra 提供程序映射"
|
msgstr "Microsoft Entra 提供程序映射"
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/models.py
|
||||||
|
#: authentik/stages/user_login/models.py
|
||||||
|
msgid ""
|
||||||
|
"Determines how long a session lasts. Default of 0 means that the sessions "
|
||||||
|
"lasts until the browser is closed. (Format: hours=-1;minutes=-2;seconds=-3)"
|
||||||
|
msgstr "确定会话持续多长时间。默认值为 0 表示会话持续到浏览器关闭为止。(格式:hours=-1;minutes=-2;seconds=-3)"
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/models.py
|
||||||
|
msgid "When set to true, connection tokens will be deleted upon disconnect."
|
||||||
|
msgstr "启用时,连接令牌将会在断开连接时被删除。"
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/models.py
|
||||||
|
msgid "RAC Provider"
|
||||||
|
msgstr "RAC 提供程序"
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/models.py
|
||||||
|
msgid "RAC Providers"
|
||||||
|
msgstr "RAC 提供程序"
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/models.py
|
||||||
|
msgid "RAC Endpoint"
|
||||||
|
msgstr "RAC 端点"
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/models.py
|
||||||
|
msgid "RAC Endpoints"
|
||||||
|
msgstr "RAC 端点"
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/models.py
|
||||||
|
msgid "RAC Provider Property Mapping"
|
||||||
|
msgstr "RAC 提供程序属性映射"
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/models.py
|
||||||
|
msgid "RAC Provider Property Mappings"
|
||||||
|
msgstr "RAC 提供程序属性映射"
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/models.py
|
||||||
|
msgid "RAC Connection token"
|
||||||
|
msgstr "RAC 连接令牌"
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/models.py
|
||||||
|
msgid "RAC Connection tokens"
|
||||||
|
msgstr "RAC 连接令牌"
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/views.py
|
||||||
|
msgid "Maximum connection limit reached."
|
||||||
|
msgstr "已达到最大连接数。"
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/views.py
|
||||||
|
msgid "(You are already connected in another tab/window)"
|
||||||
|
msgstr "(您已经在另一个标签页/窗口连接了)"
|
||||||
|
|
||||||
#: authentik/enterprise/providers/ssf/models.py
|
#: authentik/enterprise/providers/ssf/models.py
|
||||||
#: authentik/providers/oauth2/models.py
|
#: authentik/providers/oauth2/models.py
|
||||||
msgid "Signing Key"
|
msgid "Signing Key"
|
||||||
@ -623,7 +662,6 @@ msgid "Slack Webhook (Slack/Discord)"
|
|||||||
msgstr "Slack Webhook(Slack/Discord)"
|
msgstr "Slack Webhook(Slack/Discord)"
|
||||||
|
|
||||||
#: authentik/events/models.py
|
#: authentik/events/models.py
|
||||||
#: authentik/stages/authenticator_validate/models.py
|
|
||||||
msgid "Email"
|
msgid "Email"
|
||||||
msgstr "电子邮箱"
|
msgstr "电子邮箱"
|
||||||
|
|
||||||
@ -878,12 +916,6 @@ msgstr "流程令牌"
|
|||||||
msgid "Invalid next URL"
|
msgid "Invalid next URL"
|
||||||
msgstr "无效的 next URL"
|
msgstr "无效的 next URL"
|
||||||
|
|
||||||
#: authentik/lib/sync/outgoing/models.py
|
|
||||||
msgid ""
|
|
||||||
"When enabled, provider will not modify or create objects in the remote "
|
|
||||||
"system."
|
|
||||||
msgstr "启用时,提供程序将不会在远程系统上修改或创建对象。"
|
|
||||||
|
|
||||||
#: authentik/lib/sync/outgoing/tasks.py
|
#: authentik/lib/sync/outgoing/tasks.py
|
||||||
msgid "Starting full provider sync"
|
msgid "Starting full provider sync"
|
||||||
msgstr "开始全量提供程序同步"
|
msgstr "开始全量提供程序同步"
|
||||||
@ -898,10 +930,6 @@ msgstr "正在同步用户页面 {page}"
|
|||||||
msgid "Syncing page {page} of groups"
|
msgid "Syncing page {page} of groups"
|
||||||
msgstr "正在同步群组页面 {page}"
|
msgstr "正在同步群组页面 {page}"
|
||||||
|
|
||||||
#: authentik/lib/sync/outgoing/tasks.py
|
|
||||||
msgid "Dropping mutating request due to dry run"
|
|
||||||
msgstr "由于启用了试运行,已放弃变更请求"
|
|
||||||
|
|
||||||
#: authentik/lib/sync/outgoing/tasks.py
|
#: authentik/lib/sync/outgoing/tasks.py
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Stopping sync due to error: {error}"
|
msgid "Stopping sync due to error: {error}"
|
||||||
@ -1091,14 +1119,6 @@ msgstr "GeoIP:无法在城市数据库中找到客户端 IP。"
|
|||||||
msgid "Client IP is not in an allowed country."
|
msgid "Client IP is not in an allowed country."
|
||||||
msgstr "客户端 IP 不在受允许的地区。"
|
msgstr "客户端 IP 不在受允许的地区。"
|
||||||
|
|
||||||
#: authentik/policies/geoip/models.py
|
|
||||||
msgid "Distance from previous authentication is larger than threshold."
|
|
||||||
msgstr "与上一次身份验证的距离超过阈值。"
|
|
||||||
|
|
||||||
#: authentik/policies/geoip/models.py
|
|
||||||
msgid "Distance is further than possible."
|
|
||||||
msgstr "距离大幅超过可能值。"
|
|
||||||
|
|
||||||
#: authentik/policies/geoip/models.py
|
#: authentik/policies/geoip/models.py
|
||||||
msgid "GeoIP Policy"
|
msgid "GeoIP Policy"
|
||||||
msgstr "GeoIP 策略"
|
msgstr "GeoIP 策略"
|
||||||
@ -1399,14 +1419,6 @@ msgstr "RS256(非对称加密)"
|
|||||||
msgid "ES256 (Asymmetric Encryption)"
|
msgid "ES256 (Asymmetric Encryption)"
|
||||||
msgstr "ES256(非对称加密)"
|
msgstr "ES256(非对称加密)"
|
||||||
|
|
||||||
#: authentik/providers/oauth2/models.py
|
|
||||||
msgid "ES384 (Asymmetric Encryption)"
|
|
||||||
msgstr "ES384(非对称加密)"
|
|
||||||
|
|
||||||
#: authentik/providers/oauth2/models.py
|
|
||||||
msgid "ES512 (Asymmetric Encryption)"
|
|
||||||
msgstr "ES512(非对称加密)"
|
|
||||||
|
|
||||||
#: authentik/providers/oauth2/models.py
|
#: authentik/providers/oauth2/models.py
|
||||||
msgid "Scope used by the client"
|
msgid "Scope used by the client"
|
||||||
msgstr "客户端使用的作用域"
|
msgstr "客户端使用的作用域"
|
||||||
@ -1656,56 +1668,6 @@ msgstr "代理提供程序"
|
|||||||
msgid "Proxy Providers"
|
msgid "Proxy Providers"
|
||||||
msgstr "代理提供程序"
|
msgstr "代理提供程序"
|
||||||
|
|
||||||
#: authentik/providers/rac/models.py authentik/stages/user_login/models.py
|
|
||||||
msgid ""
|
|
||||||
"Determines how long a session lasts. Default of 0 means that the sessions "
|
|
||||||
"lasts until the browser is closed. (Format: hours=-1;minutes=-2;seconds=-3)"
|
|
||||||
msgstr "确定会话持续多长时间。默认值为 0 表示会话持续到浏览器关闭为止。(格式:hours=-1;minutes=-2;seconds=-3)"
|
|
||||||
|
|
||||||
#: authentik/providers/rac/models.py
|
|
||||||
msgid "When set to true, connection tokens will be deleted upon disconnect."
|
|
||||||
msgstr "启用时,连接令牌将会在断开连接时被删除。"
|
|
||||||
|
|
||||||
#: authentik/providers/rac/models.py
|
|
||||||
msgid "RAC Provider"
|
|
||||||
msgstr "RAC 提供程序"
|
|
||||||
|
|
||||||
#: authentik/providers/rac/models.py
|
|
||||||
msgid "RAC Providers"
|
|
||||||
msgstr "RAC 提供程序"
|
|
||||||
|
|
||||||
#: authentik/providers/rac/models.py
|
|
||||||
msgid "RAC Endpoint"
|
|
||||||
msgstr "RAC 端点"
|
|
||||||
|
|
||||||
#: authentik/providers/rac/models.py
|
|
||||||
msgid "RAC Endpoints"
|
|
||||||
msgstr "RAC 端点"
|
|
||||||
|
|
||||||
#: authentik/providers/rac/models.py
|
|
||||||
msgid "RAC Provider Property Mapping"
|
|
||||||
msgstr "RAC 提供程序属性映射"
|
|
||||||
|
|
||||||
#: authentik/providers/rac/models.py
|
|
||||||
msgid "RAC Provider Property Mappings"
|
|
||||||
msgstr "RAC 提供程序属性映射"
|
|
||||||
|
|
||||||
#: authentik/providers/rac/models.py
|
|
||||||
msgid "RAC Connection token"
|
|
||||||
msgstr "RAC 连接令牌"
|
|
||||||
|
|
||||||
#: authentik/providers/rac/models.py
|
|
||||||
msgid "RAC Connection tokens"
|
|
||||||
msgstr "RAC 连接令牌"
|
|
||||||
|
|
||||||
#: authentik/providers/rac/views.py
|
|
||||||
msgid "Maximum connection limit reached."
|
|
||||||
msgstr "已达到最大连接数。"
|
|
||||||
|
|
||||||
#: authentik/providers/rac/views.py
|
|
||||||
msgid "(You are already connected in another tab/window)"
|
|
||||||
msgstr "(您已经在另一个标签页/窗口连接了)"
|
|
||||||
|
|
||||||
#: authentik/providers/radius/models.py
|
#: authentik/providers/radius/models.py
|
||||||
msgid "Shared secret between clients and server to hash packets."
|
msgid "Shared secret between clients and server to hash packets."
|
||||||
msgstr "用于哈希处理数据包的客户端服务端共享密钥。"
|
msgstr "用于哈希处理数据包的客户端服务端共享密钥。"
|
||||||
@ -1909,18 +1871,6 @@ msgstr "来自元数据的 SAML 提供程序"
|
|||||||
msgid "SAML Providers from Metadata"
|
msgid "SAML Providers from Metadata"
|
||||||
msgstr "来自元数据的 SAML 提供程序"
|
msgstr "来自元数据的 SAML 提供程序"
|
||||||
|
|
||||||
#: authentik/providers/scim/models.py
|
|
||||||
msgid "Default"
|
|
||||||
msgstr "默认"
|
|
||||||
|
|
||||||
#: authentik/providers/scim/models.py
|
|
||||||
msgid "AWS"
|
|
||||||
msgstr "AWS"
|
|
||||||
|
|
||||||
#: authentik/providers/scim/models.py
|
|
||||||
msgid "Slack"
|
|
||||||
msgstr "Slack"
|
|
||||||
|
|
||||||
#: authentik/providers/scim/models.py
|
#: authentik/providers/scim/models.py
|
||||||
msgid "Base URL to SCIM requests, usually ends in /v2"
|
msgid "Base URL to SCIM requests, usually ends in /v2"
|
||||||
msgstr "SCIM 请求的基础 URL,通常以 /v2 结尾"
|
msgstr "SCIM 请求的基础 URL,通常以 /v2 结尾"
|
||||||
@ -1929,14 +1879,6 @@ msgstr "SCIM 请求的基础 URL,通常以 /v2 结尾"
|
|||||||
msgid "Authentication token"
|
msgid "Authentication token"
|
||||||
msgstr "身份验证令牌"
|
msgstr "身份验证令牌"
|
||||||
|
|
||||||
#: authentik/providers/scim/models.py
|
|
||||||
msgid "SCIM Compatibility Mode"
|
|
||||||
msgstr "SCIM 兼容模式"
|
|
||||||
|
|
||||||
#: authentik/providers/scim/models.py
|
|
||||||
msgid "Alter authentik behavior for vendor-specific SCIM implementations."
|
|
||||||
msgstr "更改 authentik 的行为,以兼容特定厂商的 SCIM 实现。"
|
|
||||||
|
|
||||||
#: authentik/providers/scim/models.py
|
#: authentik/providers/scim/models.py
|
||||||
msgid "SCIM Provider"
|
msgid "SCIM Provider"
|
||||||
msgstr "SCIM 提供程序"
|
msgstr "SCIM 提供程序"
|
||||||
@ -2579,110 +2521,6 @@ msgstr "Duo 设备"
|
|||||||
msgid "Duo Devices"
|
msgid "Duo Devices"
|
||||||
msgstr "Duo 设备"
|
msgstr "Duo 设备"
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/models.py
|
|
||||||
msgid "Email OTP"
|
|
||||||
msgstr "电子邮件 OTP"
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/models.py
|
|
||||||
#: authentik/stages/email/models.py
|
|
||||||
msgid ""
|
|
||||||
"When enabled, global Email connection settings will be used and connection "
|
|
||||||
"settings below will be ignored."
|
|
||||||
msgstr "启用后,将使用全局电子邮件连接设置,下面的连接设置将被忽略。"
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/models.py
|
|
||||||
#: authentik/stages/email/models.py
|
|
||||||
msgid "Time the token sent is valid (Format: hours=3,minutes=17,seconds=300)."
|
|
||||||
msgstr "发出令牌有效的时间(格式:hours=3,minutes=17,seconds=300)。"
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/models.py
|
|
||||||
msgid "Email Authenticator Setup Stage"
|
|
||||||
msgstr "电子邮件身份验证器设置阶段"
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/models.py
|
|
||||||
msgid "Email Authenticator Setup Stages"
|
|
||||||
msgstr "电子邮件身份验证器设置阶段"
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/models.py
|
|
||||||
#: authentik/stages/authenticator_email/stage.py
|
|
||||||
#: authentik/stages/email/stage.py
|
|
||||||
msgid "Exception occurred while rendering E-mail template"
|
|
||||||
msgstr "渲染电子邮件模板时发生异常"
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/models.py
|
|
||||||
msgid "Email Device"
|
|
||||||
msgstr "电子邮件设备"
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/models.py
|
|
||||||
msgid "Email Devices"
|
|
||||||
msgstr "电子邮件设备"
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/stage.py
|
|
||||||
#: authentik/stages/authenticator_sms/stage.py
|
|
||||||
#: authentik/stages/authenticator_totp/stage.py
|
|
||||||
msgid "Code does not match"
|
|
||||||
msgstr "代码不匹配"
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/stage.py
|
|
||||||
msgid "Invalid email"
|
|
||||||
msgstr "无效电子邮件"
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/templates/email/email_otp.html
|
|
||||||
#: authentik/stages/email/templates/email/password_reset.html
|
|
||||||
#, python-format
|
|
||||||
msgid ""
|
|
||||||
"\n"
|
|
||||||
" Hi %(username)s,\n"
|
|
||||||
" "
|
|
||||||
msgstr ""
|
|
||||||
"\n"
|
|
||||||
" %(username)s 您好,\n"
|
|
||||||
" "
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/templates/email/email_otp.html
|
|
||||||
msgid ""
|
|
||||||
"\n"
|
|
||||||
" Email MFA code.\n"
|
|
||||||
" "
|
|
||||||
msgstr ""
|
|
||||||
"\n"
|
|
||||||
" 电子邮件 MFA 代码。\n"
|
|
||||||
" "
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/templates/email/email_otp.html
|
|
||||||
#, python-format
|
|
||||||
msgid ""
|
|
||||||
"\n"
|
|
||||||
" If you did not request this code, please ignore this email. The code above is valid for %(expires)s.\n"
|
|
||||||
" "
|
|
||||||
msgstr ""
|
|
||||||
"\n"
|
|
||||||
" 如果您没有请求此代码,请忽略此电子邮件。上面的代码在 %(expires)s 内有效。\n"
|
|
||||||
" "
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/templates/email/email_otp.txt
|
|
||||||
#: authentik/stages/email/templates/email/password_reset.txt
|
|
||||||
#, python-format
|
|
||||||
msgid "Hi %(username)s,"
|
|
||||||
msgstr "您好 %(username)s,"
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/templates/email/email_otp.txt
|
|
||||||
msgid ""
|
|
||||||
"\n"
|
|
||||||
"Email MFA code\n"
|
|
||||||
msgstr ""
|
|
||||||
"\n"
|
|
||||||
"电子邮件 MFA 代码\n"
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/templates/email/email_otp.txt
|
|
||||||
#, python-format
|
|
||||||
msgid ""
|
|
||||||
"\n"
|
|
||||||
"If you did not request this code, please ignore this email. The code above is valid for %(expires)s.\n"
|
|
||||||
msgstr ""
|
|
||||||
"\n"
|
|
||||||
"如果您没有请求此代码,请忽略此电子邮件。上面的代码在 %(expires)s 内有效。\n"
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_sms/models.py
|
#: authentik/stages/authenticator_sms/models.py
|
||||||
msgid ""
|
msgid ""
|
||||||
"When enabled, the Phone number is only used during enrollment to verify the "
|
"When enabled, the Phone number is only used during enrollment to verify the "
|
||||||
@ -2715,6 +2553,11 @@ msgstr "短信设备"
|
|||||||
msgid "SMS Devices"
|
msgid "SMS Devices"
|
||||||
msgstr "短信设备"
|
msgstr "短信设备"
|
||||||
|
|
||||||
|
#: authentik/stages/authenticator_sms/stage.py
|
||||||
|
#: authentik/stages/authenticator_totp/stage.py
|
||||||
|
msgid "Code does not match"
|
||||||
|
msgstr "代码不匹配"
|
||||||
|
|
||||||
#: authentik/stages/authenticator_sms/stage.py
|
#: authentik/stages/authenticator_sms/stage.py
|
||||||
msgid "Invalid phone number"
|
msgid "Invalid phone number"
|
||||||
msgstr "无效电话号码"
|
msgstr "无效电话号码"
|
||||||
@ -2937,10 +2780,20 @@ msgstr "密码重置"
|
|||||||
msgid "Account Confirmation"
|
msgid "Account Confirmation"
|
||||||
msgstr "账户确认"
|
msgstr "账户确认"
|
||||||
|
|
||||||
|
#: authentik/stages/email/models.py
|
||||||
|
msgid ""
|
||||||
|
"When enabled, global Email connection settings will be used and connection "
|
||||||
|
"settings below will be ignored."
|
||||||
|
msgstr "启用后,将使用全局电子邮件连接设置,下面的连接设置将被忽略。"
|
||||||
|
|
||||||
#: authentik/stages/email/models.py
|
#: authentik/stages/email/models.py
|
||||||
msgid "Activate users upon completion of stage."
|
msgid "Activate users upon completion of stage."
|
||||||
msgstr "完成阶段后激活用户。"
|
msgstr "完成阶段后激活用户。"
|
||||||
|
|
||||||
|
#: authentik/stages/email/models.py
|
||||||
|
msgid "Time in minutes the token sent is valid."
|
||||||
|
msgstr "发出令牌的有效时间(单位为分钟)。"
|
||||||
|
|
||||||
#: authentik/stages/email/models.py
|
#: authentik/stages/email/models.py
|
||||||
msgid "Email Stage"
|
msgid "Email Stage"
|
||||||
msgstr "电子邮件阶段"
|
msgstr "电子邮件阶段"
|
||||||
@ -2949,6 +2802,10 @@ msgstr "电子邮件阶段"
|
|||||||
msgid "Email Stages"
|
msgid "Email Stages"
|
||||||
msgstr "电子邮件阶段"
|
msgstr "电子邮件阶段"
|
||||||
|
|
||||||
|
#: authentik/stages/email/stage.py
|
||||||
|
msgid "Exception occurred while rendering E-mail template"
|
||||||
|
msgstr "渲染电子邮件模板时发生异常"
|
||||||
|
|
||||||
#: authentik/stages/email/stage.py
|
#: authentik/stages/email/stage.py
|
||||||
msgid "Successfully verified Email."
|
msgid "Successfully verified Email."
|
||||||
msgstr "已成功验证电子邮件。"
|
msgstr "已成功验证电子邮件。"
|
||||||
@ -3029,6 +2886,17 @@ msgstr ""
|
|||||||
"\n"
|
"\n"
|
||||||
"此邮件由通知递送 %(name)s 发送。\n"
|
"此邮件由通知递送 %(name)s 发送。\n"
|
||||||
|
|
||||||
|
#: authentik/stages/email/templates/email/password_reset.html
|
||||||
|
#, python-format
|
||||||
|
msgid ""
|
||||||
|
"\n"
|
||||||
|
" Hi %(username)s,\n"
|
||||||
|
" "
|
||||||
|
msgstr ""
|
||||||
|
"\n"
|
||||||
|
" %(username)s 您好,\n"
|
||||||
|
" "
|
||||||
|
|
||||||
#: authentik/stages/email/templates/email/password_reset.html
|
#: authentik/stages/email/templates/email/password_reset.html
|
||||||
msgid ""
|
msgid ""
|
||||||
"\n"
|
"\n"
|
||||||
@ -3050,6 +2918,11 @@ msgstr ""
|
|||||||
" 如果您没有请求更改密码,请忽略此电子邮件。上面的链接在 %(expires)s 内有效。\n"
|
" 如果您没有请求更改密码,请忽略此电子邮件。上面的链接在 %(expires)s 内有效。\n"
|
||||||
" "
|
" "
|
||||||
|
|
||||||
|
#: authentik/stages/email/templates/email/password_reset.txt
|
||||||
|
#, python-format
|
||||||
|
msgid "Hi %(username)s,"
|
||||||
|
msgstr "您好 %(username)s,"
|
||||||
|
|
||||||
#: authentik/stages/email/templates/email/password_reset.txt
|
#: authentik/stages/email/templates/email/password_reset.txt
|
||||||
msgid ""
|
msgid ""
|
||||||
"\n"
|
"\n"
|
||||||
|
Binary file not shown.
@ -6,7 +6,7 @@
|
|||||||
# Translators:
|
# Translators:
|
||||||
# Chen Zhikai, 2022
|
# Chen Zhikai, 2022
|
||||||
# 刘松, 2022
|
# 刘松, 2022
|
||||||
# Jens L. <jens@goauthentik.io>, 2025
|
# Jens L. <jens@goauthentik.io>, 2024
|
||||||
# deluxghost, 2025
|
# deluxghost, 2025
|
||||||
#
|
#
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
@ -14,7 +14,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-03-13 00:10+0000\n"
|
"POT-Creation-Date: 2025-02-14 14:49+0000\n"
|
||||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||||
"Last-Translator: deluxghost, 2025\n"
|
"Last-Translator: deluxghost, 2025\n"
|
||||||
"Language-Team: Chinese (China) (https://app.transifex.com/authentik/teams/119923/zh_CN/)\n"
|
"Language-Team: Chinese (China) (https://app.transifex.com/authentik/teams/119923/zh_CN/)\n"
|
||||||
@ -117,10 +117,6 @@ msgstr "用户没有访问此应用程序的权限。"
|
|||||||
msgid "Extra description not available"
|
msgid "Extra description not available"
|
||||||
msgstr "额外描述不可用"
|
msgstr "额外描述不可用"
|
||||||
|
|
||||||
#: authentik/core/api/groups.py
|
|
||||||
msgid "Cannot set group as parent of itself."
|
|
||||||
msgstr "无法设置组自身为父级。"
|
|
||||||
|
|
||||||
#: authentik/core/api/providers.py
|
#: authentik/core/api/providers.py
|
||||||
msgid ""
|
msgid ""
|
||||||
"When not set all providers are returned. When set to true, only backchannel "
|
"When not set all providers are returned. When set to true, only backchannel "
|
||||||
@ -165,14 +161,6 @@ msgstr "添加用户到组"
|
|||||||
msgid "Remove user from group"
|
msgid "Remove user from group"
|
||||||
msgstr "从组中删除用户"
|
msgstr "从组中删除用户"
|
||||||
|
|
||||||
#: authentik/core/models.py
|
|
||||||
msgid "Enable superuser status"
|
|
||||||
msgstr "启用超级用户状态"
|
|
||||||
|
|
||||||
#: authentik/core/models.py
|
|
||||||
msgid "Disable superuser status"
|
|
||||||
msgstr "禁用超级用户状态"
|
|
||||||
|
|
||||||
#: authentik/core/models.py
|
#: authentik/core/models.py
|
||||||
msgid "User's display name."
|
msgid "User's display name."
|
||||||
msgstr "用户的显示名称。"
|
msgstr "用户的显示名称。"
|
||||||
@ -521,6 +509,57 @@ msgstr "Microsoft Entra 提供程序映射"
|
|||||||
msgid "Microsoft Entra Provider Mappings"
|
msgid "Microsoft Entra Provider Mappings"
|
||||||
msgstr "Microsoft Entra 提供程序映射"
|
msgstr "Microsoft Entra 提供程序映射"
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/models.py
|
||||||
|
#: authentik/stages/user_login/models.py
|
||||||
|
msgid ""
|
||||||
|
"Determines how long a session lasts. Default of 0 means that the sessions "
|
||||||
|
"lasts until the browser is closed. (Format: hours=-1;minutes=-2;seconds=-3)"
|
||||||
|
msgstr "确定会话持续多长时间。默认值为 0 表示会话持续到浏览器关闭为止。(格式:hours=-1;minutes=-2;seconds=-3)"
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/models.py
|
||||||
|
msgid "When set to true, connection tokens will be deleted upon disconnect."
|
||||||
|
msgstr "启用时,连接令牌将会在断开连接时被删除。"
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/models.py
|
||||||
|
msgid "RAC Provider"
|
||||||
|
msgstr "RAC 提供程序"
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/models.py
|
||||||
|
msgid "RAC Providers"
|
||||||
|
msgstr "RAC 提供程序"
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/models.py
|
||||||
|
msgid "RAC Endpoint"
|
||||||
|
msgstr "RAC 端点"
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/models.py
|
||||||
|
msgid "RAC Endpoints"
|
||||||
|
msgstr "RAC 端点"
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/models.py
|
||||||
|
msgid "RAC Provider Property Mapping"
|
||||||
|
msgstr "RAC 提供程序属性映射"
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/models.py
|
||||||
|
msgid "RAC Provider Property Mappings"
|
||||||
|
msgstr "RAC 提供程序属性映射"
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/models.py
|
||||||
|
msgid "RAC Connection token"
|
||||||
|
msgstr "RAC 连接令牌"
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/models.py
|
||||||
|
msgid "RAC Connection tokens"
|
||||||
|
msgstr "RAC 连接令牌"
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/views.py
|
||||||
|
msgid "Maximum connection limit reached."
|
||||||
|
msgstr "已达到最大连接数。"
|
||||||
|
|
||||||
|
#: authentik/enterprise/providers/rac/views.py
|
||||||
|
msgid "(You are already connected in another tab/window)"
|
||||||
|
msgstr "(您已经在另一个标签页/窗口连接了)"
|
||||||
|
|
||||||
#: authentik/enterprise/providers/ssf/models.py
|
#: authentik/enterprise/providers/ssf/models.py
|
||||||
#: authentik/providers/oauth2/models.py
|
#: authentik/providers/oauth2/models.py
|
||||||
msgid "Signing Key"
|
msgid "Signing Key"
|
||||||
@ -622,7 +661,6 @@ msgid "Slack Webhook (Slack/Discord)"
|
|||||||
msgstr "Slack Webhook(Slack/Discord)"
|
msgstr "Slack Webhook(Slack/Discord)"
|
||||||
|
|
||||||
#: authentik/events/models.py
|
#: authentik/events/models.py
|
||||||
#: authentik/stages/authenticator_validate/models.py
|
|
||||||
msgid "Email"
|
msgid "Email"
|
||||||
msgstr "电子邮箱"
|
msgstr "电子邮箱"
|
||||||
|
|
||||||
@ -877,12 +915,6 @@ msgstr "流程令牌"
|
|||||||
msgid "Invalid next URL"
|
msgid "Invalid next URL"
|
||||||
msgstr "无效的 next URL"
|
msgstr "无效的 next URL"
|
||||||
|
|
||||||
#: authentik/lib/sync/outgoing/models.py
|
|
||||||
msgid ""
|
|
||||||
"When enabled, provider will not modify or create objects in the remote "
|
|
||||||
"system."
|
|
||||||
msgstr "启用时,提供程序将不会在远程系统上修改或创建对象。"
|
|
||||||
|
|
||||||
#: authentik/lib/sync/outgoing/tasks.py
|
#: authentik/lib/sync/outgoing/tasks.py
|
||||||
msgid "Starting full provider sync"
|
msgid "Starting full provider sync"
|
||||||
msgstr "开始全量提供程序同步"
|
msgstr "开始全量提供程序同步"
|
||||||
@ -897,10 +929,6 @@ msgstr "正在同步用户页面 {page}"
|
|||||||
msgid "Syncing page {page} of groups"
|
msgid "Syncing page {page} of groups"
|
||||||
msgstr "正在同步群组页面 {page}"
|
msgstr "正在同步群组页面 {page}"
|
||||||
|
|
||||||
#: authentik/lib/sync/outgoing/tasks.py
|
|
||||||
msgid "Dropping mutating request due to dry run"
|
|
||||||
msgstr "由于启用了试运行,已放弃变更请求"
|
|
||||||
|
|
||||||
#: authentik/lib/sync/outgoing/tasks.py
|
#: authentik/lib/sync/outgoing/tasks.py
|
||||||
#, python-brace-format
|
#, python-brace-format
|
||||||
msgid "Stopping sync due to error: {error}"
|
msgid "Stopping sync due to error: {error}"
|
||||||
@ -1090,14 +1118,6 @@ msgstr "GeoIP:无法在城市数据库中找到客户端 IP。"
|
|||||||
msgid "Client IP is not in an allowed country."
|
msgid "Client IP is not in an allowed country."
|
||||||
msgstr "客户端 IP 不在受允许的地区。"
|
msgstr "客户端 IP 不在受允许的地区。"
|
||||||
|
|
||||||
#: authentik/policies/geoip/models.py
|
|
||||||
msgid "Distance from previous authentication is larger than threshold."
|
|
||||||
msgstr "与上一次身份验证的距离超过阈值。"
|
|
||||||
|
|
||||||
#: authentik/policies/geoip/models.py
|
|
||||||
msgid "Distance is further than possible."
|
|
||||||
msgstr "距离大幅超过可能值。"
|
|
||||||
|
|
||||||
#: authentik/policies/geoip/models.py
|
#: authentik/policies/geoip/models.py
|
||||||
msgid "GeoIP Policy"
|
msgid "GeoIP Policy"
|
||||||
msgstr "GeoIP 策略"
|
msgstr "GeoIP 策略"
|
||||||
@ -1398,14 +1418,6 @@ msgstr "RS256(非对称加密)"
|
|||||||
msgid "ES256 (Asymmetric Encryption)"
|
msgid "ES256 (Asymmetric Encryption)"
|
||||||
msgstr "ES256(非对称加密)"
|
msgstr "ES256(非对称加密)"
|
||||||
|
|
||||||
#: authentik/providers/oauth2/models.py
|
|
||||||
msgid "ES384 (Asymmetric Encryption)"
|
|
||||||
msgstr "ES384(非对称加密)"
|
|
||||||
|
|
||||||
#: authentik/providers/oauth2/models.py
|
|
||||||
msgid "ES512 (Asymmetric Encryption)"
|
|
||||||
msgstr "ES512(非对称加密)"
|
|
||||||
|
|
||||||
#: authentik/providers/oauth2/models.py
|
#: authentik/providers/oauth2/models.py
|
||||||
msgid "Scope used by the client"
|
msgid "Scope used by the client"
|
||||||
msgstr "客户端使用的作用域"
|
msgstr "客户端使用的作用域"
|
||||||
@ -1655,56 +1667,6 @@ msgstr "代理提供程序"
|
|||||||
msgid "Proxy Providers"
|
msgid "Proxy Providers"
|
||||||
msgstr "代理提供程序"
|
msgstr "代理提供程序"
|
||||||
|
|
||||||
#: authentik/providers/rac/models.py authentik/stages/user_login/models.py
|
|
||||||
msgid ""
|
|
||||||
"Determines how long a session lasts. Default of 0 means that the sessions "
|
|
||||||
"lasts until the browser is closed. (Format: hours=-1;minutes=-2;seconds=-3)"
|
|
||||||
msgstr "确定会话持续多长时间。默认值为 0 表示会话持续到浏览器关闭为止。(格式:hours=-1;minutes=-2;seconds=-3)"
|
|
||||||
|
|
||||||
#: authentik/providers/rac/models.py
|
|
||||||
msgid "When set to true, connection tokens will be deleted upon disconnect."
|
|
||||||
msgstr "启用时,连接令牌将会在断开连接时被删除。"
|
|
||||||
|
|
||||||
#: authentik/providers/rac/models.py
|
|
||||||
msgid "RAC Provider"
|
|
||||||
msgstr "RAC 提供程序"
|
|
||||||
|
|
||||||
#: authentik/providers/rac/models.py
|
|
||||||
msgid "RAC Providers"
|
|
||||||
msgstr "RAC 提供程序"
|
|
||||||
|
|
||||||
#: authentik/providers/rac/models.py
|
|
||||||
msgid "RAC Endpoint"
|
|
||||||
msgstr "RAC 端点"
|
|
||||||
|
|
||||||
#: authentik/providers/rac/models.py
|
|
||||||
msgid "RAC Endpoints"
|
|
||||||
msgstr "RAC 端点"
|
|
||||||
|
|
||||||
#: authentik/providers/rac/models.py
|
|
||||||
msgid "RAC Provider Property Mapping"
|
|
||||||
msgstr "RAC 提供程序属性映射"
|
|
||||||
|
|
||||||
#: authentik/providers/rac/models.py
|
|
||||||
msgid "RAC Provider Property Mappings"
|
|
||||||
msgstr "RAC 提供程序属性映射"
|
|
||||||
|
|
||||||
#: authentik/providers/rac/models.py
|
|
||||||
msgid "RAC Connection token"
|
|
||||||
msgstr "RAC 连接令牌"
|
|
||||||
|
|
||||||
#: authentik/providers/rac/models.py
|
|
||||||
msgid "RAC Connection tokens"
|
|
||||||
msgstr "RAC 连接令牌"
|
|
||||||
|
|
||||||
#: authentik/providers/rac/views.py
|
|
||||||
msgid "Maximum connection limit reached."
|
|
||||||
msgstr "已达到最大连接数。"
|
|
||||||
|
|
||||||
#: authentik/providers/rac/views.py
|
|
||||||
msgid "(You are already connected in another tab/window)"
|
|
||||||
msgstr "(您已经在另一个标签页/窗口连接了)"
|
|
||||||
|
|
||||||
#: authentik/providers/radius/models.py
|
#: authentik/providers/radius/models.py
|
||||||
msgid "Shared secret between clients and server to hash packets."
|
msgid "Shared secret between clients and server to hash packets."
|
||||||
msgstr "在客户端和服务端之间共享密钥以哈希数据包。"
|
msgstr "在客户端和服务端之间共享密钥以哈希数据包。"
|
||||||
@ -1908,18 +1870,6 @@ msgstr "来自元数据的 SAML 提供程序"
|
|||||||
msgid "SAML Providers from Metadata"
|
msgid "SAML Providers from Metadata"
|
||||||
msgstr "来自元数据的 SAML 提供程序"
|
msgstr "来自元数据的 SAML 提供程序"
|
||||||
|
|
||||||
#: authentik/providers/scim/models.py
|
|
||||||
msgid "Default"
|
|
||||||
msgstr "默认"
|
|
||||||
|
|
||||||
#: authentik/providers/scim/models.py
|
|
||||||
msgid "AWS"
|
|
||||||
msgstr "AWS"
|
|
||||||
|
|
||||||
#: authentik/providers/scim/models.py
|
|
||||||
msgid "Slack"
|
|
||||||
msgstr "Slack"
|
|
||||||
|
|
||||||
#: authentik/providers/scim/models.py
|
#: authentik/providers/scim/models.py
|
||||||
msgid "Base URL to SCIM requests, usually ends in /v2"
|
msgid "Base URL to SCIM requests, usually ends in /v2"
|
||||||
msgstr "SCIM 请求的基础 URL,通常以 /v2 结尾"
|
msgstr "SCIM 请求的基础 URL,通常以 /v2 结尾"
|
||||||
@ -1928,14 +1878,6 @@ msgstr "SCIM 请求的基础 URL,通常以 /v2 结尾"
|
|||||||
msgid "Authentication token"
|
msgid "Authentication token"
|
||||||
msgstr "身份验证令牌"
|
msgstr "身份验证令牌"
|
||||||
|
|
||||||
#: authentik/providers/scim/models.py
|
|
||||||
msgid "SCIM Compatibility Mode"
|
|
||||||
msgstr "SCIM 兼容模式"
|
|
||||||
|
|
||||||
#: authentik/providers/scim/models.py
|
|
||||||
msgid "Alter authentik behavior for vendor-specific SCIM implementations."
|
|
||||||
msgstr "更改 authentik 的行为,以兼容特定厂商的 SCIM 实现。"
|
|
||||||
|
|
||||||
#: authentik/providers/scim/models.py
|
#: authentik/providers/scim/models.py
|
||||||
msgid "SCIM Provider"
|
msgid "SCIM Provider"
|
||||||
msgstr "SCIM 提供程序"
|
msgstr "SCIM 提供程序"
|
||||||
@ -2578,110 +2520,6 @@ msgstr "Duo 设备"
|
|||||||
msgid "Duo Devices"
|
msgid "Duo Devices"
|
||||||
msgstr "Duo 设备"
|
msgstr "Duo 设备"
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/models.py
|
|
||||||
msgid "Email OTP"
|
|
||||||
msgstr "电子邮件 OTP"
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/models.py
|
|
||||||
#: authentik/stages/email/models.py
|
|
||||||
msgid ""
|
|
||||||
"When enabled, global Email connection settings will be used and connection "
|
|
||||||
"settings below will be ignored."
|
|
||||||
msgstr "启用后,将使用全局电子邮件连接设置,下面的连接设置将被忽略。"
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/models.py
|
|
||||||
#: authentik/stages/email/models.py
|
|
||||||
msgid "Time the token sent is valid (Format: hours=3,minutes=17,seconds=300)."
|
|
||||||
msgstr "发出令牌有效的时间(格式:hours=3,minutes=17,seconds=300)。"
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/models.py
|
|
||||||
msgid "Email Authenticator Setup Stage"
|
|
||||||
msgstr "电子邮件身份验证器设置阶段"
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/models.py
|
|
||||||
msgid "Email Authenticator Setup Stages"
|
|
||||||
msgstr "电子邮件身份验证器设置阶段"
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/models.py
|
|
||||||
#: authentik/stages/authenticator_email/stage.py
|
|
||||||
#: authentik/stages/email/stage.py
|
|
||||||
msgid "Exception occurred while rendering E-mail template"
|
|
||||||
msgstr "渲染电子邮件模板时发生异常"
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/models.py
|
|
||||||
msgid "Email Device"
|
|
||||||
msgstr "电子邮件设备"
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/models.py
|
|
||||||
msgid "Email Devices"
|
|
||||||
msgstr "电子邮件设备"
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/stage.py
|
|
||||||
#: authentik/stages/authenticator_sms/stage.py
|
|
||||||
#: authentik/stages/authenticator_totp/stage.py
|
|
||||||
msgid "Code does not match"
|
|
||||||
msgstr "代码不匹配"
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/stage.py
|
|
||||||
msgid "Invalid email"
|
|
||||||
msgstr "无效电子邮件"
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/templates/email/email_otp.html
|
|
||||||
#: authentik/stages/email/templates/email/password_reset.html
|
|
||||||
#, python-format
|
|
||||||
msgid ""
|
|
||||||
"\n"
|
|
||||||
" Hi %(username)s,\n"
|
|
||||||
" "
|
|
||||||
msgstr ""
|
|
||||||
"\n"
|
|
||||||
" %(username)s 您好,\n"
|
|
||||||
" "
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/templates/email/email_otp.html
|
|
||||||
msgid ""
|
|
||||||
"\n"
|
|
||||||
" Email MFA code.\n"
|
|
||||||
" "
|
|
||||||
msgstr ""
|
|
||||||
"\n"
|
|
||||||
" 电子邮件 MFA 代码。\n"
|
|
||||||
" "
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/templates/email/email_otp.html
|
|
||||||
#, python-format
|
|
||||||
msgid ""
|
|
||||||
"\n"
|
|
||||||
" If you did not request this code, please ignore this email. The code above is valid for %(expires)s.\n"
|
|
||||||
" "
|
|
||||||
msgstr ""
|
|
||||||
"\n"
|
|
||||||
" 如果您没有请求此代码,请忽略此电子邮件。上面的代码在 %(expires)s 内有效。\n"
|
|
||||||
" "
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/templates/email/email_otp.txt
|
|
||||||
#: authentik/stages/email/templates/email/password_reset.txt
|
|
||||||
#, python-format
|
|
||||||
msgid "Hi %(username)s,"
|
|
||||||
msgstr "您好 %(username)s,"
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/templates/email/email_otp.txt
|
|
||||||
msgid ""
|
|
||||||
"\n"
|
|
||||||
"Email MFA code\n"
|
|
||||||
msgstr ""
|
|
||||||
"\n"
|
|
||||||
"电子邮件 MFA 代码\n"
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_email/templates/email/email_otp.txt
|
|
||||||
#, python-format
|
|
||||||
msgid ""
|
|
||||||
"\n"
|
|
||||||
"If you did not request this code, please ignore this email. The code above is valid for %(expires)s.\n"
|
|
||||||
msgstr ""
|
|
||||||
"\n"
|
|
||||||
"如果您没有请求此代码,请忽略此电子邮件。上面的代码在 %(expires)s 内有效。\n"
|
|
||||||
|
|
||||||
#: authentik/stages/authenticator_sms/models.py
|
#: authentik/stages/authenticator_sms/models.py
|
||||||
msgid ""
|
msgid ""
|
||||||
"When enabled, the Phone number is only used during enrollment to verify the "
|
"When enabled, the Phone number is only used during enrollment to verify the "
|
||||||
@ -2714,6 +2552,11 @@ msgstr "短信设备"
|
|||||||
msgid "SMS Devices"
|
msgid "SMS Devices"
|
||||||
msgstr "短信设备"
|
msgstr "短信设备"
|
||||||
|
|
||||||
|
#: authentik/stages/authenticator_sms/stage.py
|
||||||
|
#: authentik/stages/authenticator_totp/stage.py
|
||||||
|
msgid "Code does not match"
|
||||||
|
msgstr "代码不匹配"
|
||||||
|
|
||||||
#: authentik/stages/authenticator_sms/stage.py
|
#: authentik/stages/authenticator_sms/stage.py
|
||||||
msgid "Invalid phone number"
|
msgid "Invalid phone number"
|
||||||
msgstr "无效电话号码"
|
msgstr "无效电话号码"
|
||||||
@ -2936,10 +2779,20 @@ msgstr "密码重置"
|
|||||||
msgid "Account Confirmation"
|
msgid "Account Confirmation"
|
||||||
msgstr "账户确认"
|
msgstr "账户确认"
|
||||||
|
|
||||||
|
#: authentik/stages/email/models.py
|
||||||
|
msgid ""
|
||||||
|
"When enabled, global Email connection settings will be used and connection "
|
||||||
|
"settings below will be ignored."
|
||||||
|
msgstr "启用后,将使用全局电子邮件连接设置,下面的连接设置将被忽略。"
|
||||||
|
|
||||||
#: authentik/stages/email/models.py
|
#: authentik/stages/email/models.py
|
||||||
msgid "Activate users upon completion of stage."
|
msgid "Activate users upon completion of stage."
|
||||||
msgstr "完成阶段后激活用户。"
|
msgstr "完成阶段后激活用户。"
|
||||||
|
|
||||||
|
#: authentik/stages/email/models.py
|
||||||
|
msgid "Time in minutes the token sent is valid."
|
||||||
|
msgstr "发出令牌的有效时间(单位为分钟)。"
|
||||||
|
|
||||||
#: authentik/stages/email/models.py
|
#: authentik/stages/email/models.py
|
||||||
msgid "Email Stage"
|
msgid "Email Stage"
|
||||||
msgstr "电子邮件阶段"
|
msgstr "电子邮件阶段"
|
||||||
@ -2948,6 +2801,10 @@ msgstr "电子邮件阶段"
|
|||||||
msgid "Email Stages"
|
msgid "Email Stages"
|
||||||
msgstr "电子邮件阶段"
|
msgstr "电子邮件阶段"
|
||||||
|
|
||||||
|
#: authentik/stages/email/stage.py
|
||||||
|
msgid "Exception occurred while rendering E-mail template"
|
||||||
|
msgstr "渲染电子邮件模板时发生异常"
|
||||||
|
|
||||||
#: authentik/stages/email/stage.py
|
#: authentik/stages/email/stage.py
|
||||||
msgid "Successfully verified Email."
|
msgid "Successfully verified Email."
|
||||||
msgstr "已成功验证电子邮件。"
|
msgstr "已成功验证电子邮件。"
|
||||||
@ -3028,6 +2885,17 @@ msgstr ""
|
|||||||
"\n"
|
"\n"
|
||||||
"此邮件由通知递送 %(name)s 发送。\n"
|
"此邮件由通知递送 %(name)s 发送。\n"
|
||||||
|
|
||||||
|
#: authentik/stages/email/templates/email/password_reset.html
|
||||||
|
#, python-format
|
||||||
|
msgid ""
|
||||||
|
"\n"
|
||||||
|
" Hi %(username)s,\n"
|
||||||
|
" "
|
||||||
|
msgstr ""
|
||||||
|
"\n"
|
||||||
|
" %(username)s 您好,\n"
|
||||||
|
" "
|
||||||
|
|
||||||
#: authentik/stages/email/templates/email/password_reset.html
|
#: authentik/stages/email/templates/email/password_reset.html
|
||||||
msgid ""
|
msgid ""
|
||||||
"\n"
|
"\n"
|
||||||
@ -3049,6 +2917,11 @@ msgstr ""
|
|||||||
" 如果您没有请求更改密码,请忽略此电子邮件。上面的链接在 %(expires)s 内有效。\n"
|
" 如果您没有请求更改密码,请忽略此电子邮件。上面的链接在 %(expires)s 内有效。\n"
|
||||||
" "
|
" "
|
||||||
|
|
||||||
|
#: authentik/stages/email/templates/email/password_reset.txt
|
||||||
|
#, python-format
|
||||||
|
msgid "Hi %(username)s,"
|
||||||
|
msgstr "您好 %(username)s,"
|
||||||
|
|
||||||
#: authentik/stages/email/templates/email/password_reset.txt
|
#: authentik/stages/email/templates/email/password_reset.txt
|
||||||
msgid ""
|
msgid ""
|
||||||
"\n"
|
"\n"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "@goauthentik/authentik",
|
"name": "@goauthentik/authentik",
|
||||||
"version": "2025.2.1",
|
"version": "2025.2.4",
|
||||||
"private": true
|
"private": true
|
||||||
}
|
}
|
||||||
|
528
poetry.lock
generated
528
poetry.lock
generated
@ -358,18 +358,18 @@ visualize = ["Twisted (>=16.1.1)", "graphviz (>0.5.1)"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aws-cdk-asset-awscli-v1"
|
name = "aws-cdk-asset-awscli-v1"
|
||||||
version = "2.2.227"
|
version = "2.2.212"
|
||||||
description = "A library that contains the AWS CLI for use in Lambda Layers"
|
description = "A library that contains the AWS CLI for use in Lambda Layers"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "~=3.8"
|
python-versions = "~=3.8"
|
||||||
groups = ["dev"]
|
groups = ["dev"]
|
||||||
files = [
|
files = [
|
||||||
{file = "aws_cdk.asset_awscli_v1-2.2.227-py3-none-any.whl", hash = "sha256:5160cd515d94d0da252806cd853a3e861e1b76aa553e1c90aec2bd712fa3df1b"},
|
{file = "aws_cdk.asset_awscli_v1-2.2.212-py3-none-any.whl", hash = "sha256:12161e2d528698957bc2c0f53d2f5e81de54f8ad0e4b94316634bdc1db50f539"},
|
||||||
{file = "aws_cdk_asset_awscli_v1-2.2.227.tar.gz", hash = "sha256:0fa4cf382e712121b8bbe11532854018abdba19964ded9c0aa9aace4383816b6"},
|
{file = "aws_cdk_asset_awscli_v1-2.2.212.tar.gz", hash = "sha256:3a4374562f37c9cd3f59cb45173a18ef0f781c0f1df187773662a1dd14cc18fd"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
jsii = ">=1.108.0,<2.0.0"
|
jsii = ">=1.105.0,<2.0.0"
|
||||||
publication = ">=0.0.3"
|
publication = ">=0.0.3"
|
||||||
typeguard = ">=2.13.3,<4.3.0"
|
typeguard = ">=2.13.3,<4.3.0"
|
||||||
|
|
||||||
@ -392,39 +392,39 @@ typeguard = ">=2.13.3,<5.0.0"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aws-cdk-cloud-assembly-schema"
|
name = "aws-cdk-cloud-assembly-schema"
|
||||||
version = "40.7.0"
|
version = "39.2.6"
|
||||||
description = "Schema for the protocol between CDK framework and CDK CLI"
|
description = "Cloud Assembly Schema"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "~=3.8"
|
python-versions = "~=3.8"
|
||||||
groups = ["dev"]
|
groups = ["dev"]
|
||||||
files = [
|
files = [
|
||||||
{file = "aws_cdk.cloud_assembly_schema-40.7.0-py3-none-any.whl", hash = "sha256:a86de4f46a72f9445f0a0ae646c348702041047c72d10b76e3b4c8dc5e460ee1"},
|
{file = "aws_cdk.cloud_assembly_schema-39.2.6-py3-none-any.whl", hash = "sha256:23b6db157c6914515d8a5679a1c90f88122920d6f2f1fdcf762b27b78174ee4e"},
|
||||||
{file = "aws_cdk_cloud_assembly_schema-40.7.0.tar.gz", hash = "sha256:8269a74cce261e56750290a2492f04d0e6825913d321a8ab17ba3b5f872fc193"},
|
{file = "aws_cdk_cloud_assembly_schema-39.2.6.tar.gz", hash = "sha256:5e0d3d4939f141b3632c253089bb84a86782b5707ec1bbe11bbf4e27bcaeb8b2"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
jsii = ">=1.108.0,<2.0.0"
|
jsii = ">=1.106.0,<2.0.0"
|
||||||
publication = ">=0.0.3"
|
publication = ">=0.0.3"
|
||||||
typeguard = ">=2.13.3,<4.3.0"
|
typeguard = ">=2.13.3,<4.3.0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aws-cdk-lib"
|
name = "aws-cdk-lib"
|
||||||
version = "2.184.0"
|
version = "2.179.0"
|
||||||
description = "Version 2 of the AWS Cloud Development Kit library"
|
description = "Version 2 of the AWS Cloud Development Kit library"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "~=3.9"
|
python-versions = "~=3.8"
|
||||||
groups = ["dev"]
|
groups = ["dev"]
|
||||||
files = [
|
files = [
|
||||||
{file = "aws_cdk_lib-2.184.0-py3-none-any.whl", hash = "sha256:b714691e5a53d7d6dc3ca9a637c603921ccb31d31ec5cc206c96ae132be410ca"},
|
{file = "aws_cdk_lib-2.179.0-py3-none-any.whl", hash = "sha256:1d7b88ee69067b8d58dac9eeb6697bbaf5d5c032a3070898389c41e7c4f3e3d7"},
|
||||||
{file = "aws_cdk_lib-2.184.0.tar.gz", hash = "sha256:40b26e3eb7de23260c74a7cbbf8345104bb28301586859d2c5ea5cce108db9c0"},
|
{file = "aws_cdk_lib-2.179.0.tar.gz", hash = "sha256:b653a55754f4020a4b36e4ae183d213e76e27b18b842cbf9e430e9eccb700550"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
"aws-cdk.asset-awscli-v1" = ">=2.2.227,<3.0.0"
|
"aws-cdk.asset-awscli-v1" = ">=2.2.208,<3.0.0"
|
||||||
"aws-cdk.asset-node-proxy-agent-v6" = ">=2.1.0,<3.0.0"
|
"aws-cdk.asset-node-proxy-agent-v6" = ">=2.1.0,<3.0.0"
|
||||||
"aws-cdk.cloud-assembly-schema" = ">=40.7.0,<41.0.0"
|
"aws-cdk.cloud-assembly-schema" = ">=39.2.0,<40.0.0"
|
||||||
constructs = ">=10.0.0,<11.0.0"
|
constructs = ">=10.0.0,<11.0.0"
|
||||||
jsii = ">=1.109.0,<2.0.0"
|
jsii = ">=1.106.0,<2.0.0"
|
||||||
publication = ">=0.0.3"
|
publication = ">=0.0.3"
|
||||||
typeguard = ">=2.13.3,<4.3.0"
|
typeguard = ">=2.13.3,<4.3.0"
|
||||||
|
|
||||||
@ -1220,47 +1220,43 @@ toml = ["tomli ; python_full_version <= \"3.11.0a6\""]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cryptography"
|
name = "cryptography"
|
||||||
version = "44.0.2"
|
version = "44.0.1"
|
||||||
description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
|
description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "!=3.9.0,!=3.9.1,>=3.7"
|
python-versions = "!=3.9.0,!=3.9.1,>=3.7"
|
||||||
groups = ["main", "dev"]
|
groups = ["main", "dev"]
|
||||||
files = [
|
files = [
|
||||||
{file = "cryptography-44.0.2-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:efcfe97d1b3c79e486554efddeb8f6f53a4cdd4cf6086642784fa31fc384e1d7"},
|
{file = "cryptography-44.0.1-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:bf688f615c29bfe9dfc44312ca470989279f0e94bb9f631f85e3459af8efc009"},
|
||||||
{file = "cryptography-44.0.2-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29ecec49f3ba3f3849362854b7253a9f59799e3763b0c9d0826259a88efa02f1"},
|
{file = "cryptography-44.0.1-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dd7c7e2d71d908dc0f8d2027e1604102140d84b155e658c20e8ad1304317691f"},
|
||||||
{file = "cryptography-44.0.2-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc821e161ae88bfe8088d11bb39caf2916562e0a2dc7b6d56714a48b784ef0bb"},
|
{file = "cryptography-44.0.1-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:887143b9ff6bad2b7570da75a7fe8bbf5f65276365ac259a5d2d5147a73775f2"},
|
||||||
{file = "cryptography-44.0.2-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:3c00b6b757b32ce0f62c574b78b939afab9eecaf597c4d624caca4f9e71e7843"},
|
{file = "cryptography-44.0.1-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:322eb03ecc62784536bc173f1483e76747aafeb69c8728df48537eb431cd1911"},
|
||||||
{file = "cryptography-44.0.2-cp37-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7bdcd82189759aba3816d1f729ce42ffded1ac304c151d0a8e89b9996ab863d5"},
|
{file = "cryptography-44.0.1-cp37-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:21377472ca4ada2906bc313168c9dc7b1d7ca417b63c1c3011d0c74b7de9ae69"},
|
||||||
{file = "cryptography-44.0.2-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:4973da6ca3db4405c54cd0b26d328be54c7747e89e284fcff166132eb7bccc9c"},
|
{file = "cryptography-44.0.1-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:df978682c1504fc93b3209de21aeabf2375cb1571d4e61907b3e7a2540e83026"},
|
||||||
{file = "cryptography-44.0.2-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:4e389622b6927d8133f314949a9812972711a111d577a5d1f4bee5e58736b80a"},
|
{file = "cryptography-44.0.1-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:eb3889330f2a4a148abead555399ec9a32b13b7c8ba969b72d8e500eb7ef84cd"},
|
||||||
{file = "cryptography-44.0.2-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:f514ef4cd14bb6fb484b4a60203e912cfcb64f2ab139e88c2274511514bf7308"},
|
{file = "cryptography-44.0.1-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:8e6a85a93d0642bd774460a86513c5d9d80b5c002ca9693e63f6e540f1815ed0"},
|
||||||
{file = "cryptography-44.0.2-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:1bc312dfb7a6e5d66082c87c34c8a62176e684b6fe3d90fcfe1568de675e6688"},
|
{file = "cryptography-44.0.1-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:6f76fdd6fd048576a04c5210d53aa04ca34d2ed63336d4abd306d0cbe298fddf"},
|
||||||
{file = "cryptography-44.0.2-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3b721b8b4d948b218c88cb8c45a01793483821e709afe5f622861fc6182b20a7"},
|
{file = "cryptography-44.0.1-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6c8acf6f3d1f47acb2248ec3ea261171a671f3d9428e34ad0357148d492c7864"},
|
||||||
{file = "cryptography-44.0.2-cp37-abi3-win32.whl", hash = "sha256:51e4de3af4ec3899d6d178a8c005226491c27c4ba84101bfb59c901e10ca9f79"},
|
{file = "cryptography-44.0.1-cp37-abi3-win32.whl", hash = "sha256:24979e9f2040c953a94bf3c6782e67795a4c260734e5264dceea65c8f4bae64a"},
|
||||||
{file = "cryptography-44.0.2-cp37-abi3-win_amd64.whl", hash = "sha256:c505d61b6176aaf982c5717ce04e87da5abc9a36a5b39ac03905c4aafe8de7aa"},
|
{file = "cryptography-44.0.1-cp37-abi3-win_amd64.whl", hash = "sha256:fd0ee90072861e276b0ff08bd627abec29e32a53b2be44e41dbcdf87cbee2b00"},
|
||||||
{file = "cryptography-44.0.2-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:8e0ddd63e6bf1161800592c71ac794d3fb8001f2caebe0966e77c5234fa9efc3"},
|
{file = "cryptography-44.0.1-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:a2d8a7045e1ab9b9f803f0d9531ead85f90c5f2859e653b61497228b18452008"},
|
||||||
{file = "cryptography-44.0.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81276f0ea79a208d961c433a947029e1a15948966658cf6710bbabb60fcc2639"},
|
{file = "cryptography-44.0.1-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b8272f257cf1cbd3f2e120f14c68bff2b6bdfcc157fafdee84a1b795efd72862"},
|
||||||
{file = "cryptography-44.0.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a1e657c0f4ea2a23304ee3f964db058c9e9e635cc7019c4aa21c330755ef6fd"},
|
{file = "cryptography-44.0.1-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e8d181e90a777b63f3f0caa836844a1182f1f265687fac2115fcf245f5fbec3"},
|
||||||
{file = "cryptography-44.0.2-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:6210c05941994290f3f7f175a4a57dbbb2afd9273657614c506d5976db061181"},
|
{file = "cryptography-44.0.1-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:436df4f203482f41aad60ed1813811ac4ab102765ecae7a2bbb1dbb66dcff5a7"},
|
||||||
{file = "cryptography-44.0.2-cp39-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:d1c3572526997b36f245a96a2b1713bf79ce99b271bbcf084beb6b9b075f29ea"},
|
{file = "cryptography-44.0.1-cp39-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4f422e8c6a28cf8b7f883eb790695d6d45b0c385a2583073f3cec434cc705e1a"},
|
||||||
{file = "cryptography-44.0.2-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:b042d2a275c8cee83a4b7ae30c45a15e6a4baa65a179a0ec2d78ebb90e4f6699"},
|
{file = "cryptography-44.0.1-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:72198e2b5925155497a5a3e8c216c7fb3e64c16ccee11f0e7da272fa93b35c4c"},
|
||||||
{file = "cryptography-44.0.2-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:d03806036b4f89e3b13b6218fefea8d5312e450935b1a2d55f0524e2ed7c59d9"},
|
{file = "cryptography-44.0.1-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:2a46a89ad3e6176223b632056f321bc7de36b9f9b93b2cc1cccf935a3849dc62"},
|
||||||
{file = "cryptography-44.0.2-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:c7362add18b416b69d58c910caa217f980c5ef39b23a38a0880dfd87bdf8cd23"},
|
{file = "cryptography-44.0.1-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:53f23339864b617a3dfc2b0ac8d5c432625c80014c25caac9082314e9de56f41"},
|
||||||
{file = "cryptography-44.0.2-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:8cadc6e3b5a1f144a039ea08a0bdb03a2a92e19c46be3285123d32029f40a922"},
|
{file = "cryptography-44.0.1-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:888fcc3fce0c888785a4876ca55f9f43787f4c5c1cc1e2e0da71ad481ff82c5b"},
|
||||||
{file = "cryptography-44.0.2-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6f101b1f780f7fc613d040ca4bdf835c6ef3b00e9bd7125a4255ec574c7916e4"},
|
{file = "cryptography-44.0.1-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:00918d859aa4e57db8299607086f793fa7813ae2ff5a4637e318a25ef82730f7"},
|
||||||
{file = "cryptography-44.0.2-cp39-abi3-win32.whl", hash = "sha256:3dc62975e31617badc19a906481deacdeb80b4bb454394b4098e3f2525a488c5"},
|
{file = "cryptography-44.0.1-cp39-abi3-win32.whl", hash = "sha256:9b336599e2cb77b1008cb2ac264b290803ec5e8e89d618a5e978ff5eb6f715d9"},
|
||||||
{file = "cryptography-44.0.2-cp39-abi3-win_amd64.whl", hash = "sha256:5f6f90b72d8ccadb9c6e311c775c8305381db88374c65fa1a68250aa8a9cb3a6"},
|
{file = "cryptography-44.0.1-cp39-abi3-win_amd64.whl", hash = "sha256:e403f7f766ded778ecdb790da786b418a9f2394f36e8cc8b796cc056ab05f44f"},
|
||||||
{file = "cryptography-44.0.2-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:af4ff3e388f2fa7bff9f7f2b31b87d5651c45731d3e8cfa0944be43dff5cfbdb"},
|
{file = "cryptography-44.0.1-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:1f9a92144fa0c877117e9748c74501bea842f93d21ee00b0cf922846d9d0b183"},
|
||||||
{file = "cryptography-44.0.2-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:0529b1d5a0105dd3731fa65680b45ce49da4d8115ea76e9da77a875396727b41"},
|
{file = "cryptography-44.0.1-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:610a83540765a8d8ce0f351ce42e26e53e1f774a6efb71eb1b41eb01d01c3d12"},
|
||||||
{file = "cryptography-44.0.2-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:7ca25849404be2f8e4b3c59483d9d3c51298a22c1c61a0e84415104dacaf5562"},
|
{file = "cryptography-44.0.1-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:5fed5cd6102bb4eb843e3315d2bf25fede494509bddadb81e03a859c1bc17b83"},
|
||||||
{file = "cryptography-44.0.2-pp310-pypy310_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:268e4e9b177c76d569e8a145a6939eca9a5fec658c932348598818acf31ae9a5"},
|
{file = "cryptography-44.0.1-pp310-pypy310_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:f4daefc971c2d1f82f03097dc6f216744a6cd2ac0f04c68fb935ea2ba2a0d420"},
|
||||||
{file = "cryptography-44.0.2-pp310-pypy310_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:9eb9d22b0a5d8fd9925a7764a054dca914000607dff201a24c791ff5c799e1fa"},
|
{file = "cryptography-44.0.1-pp310-pypy310_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:94f99f2b943b354a5b6307d7e8d19f5c423a794462bde2bf310c770ba052b1c4"},
|
||||||
{file = "cryptography-44.0.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:2bf7bf75f7df9715f810d1b038870309342bff3069c5bd8c6b96128cb158668d"},
|
{file = "cryptography-44.0.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d9c5b9f698a83c8bd71e0f4d3f9f839ef244798e5ffe96febfa9714717db7af7"},
|
||||||
{file = "cryptography-44.0.2-pp311-pypy311_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:909c97ab43a9c0c0b0ada7a1281430e4e5ec0458e6d9244c0e821bbf152f061d"},
|
{file = "cryptography-44.0.1.tar.gz", hash = "sha256:f51f5705ab27898afda1aaa430f34ad90dc117421057782022edf0600bec5f14"},
|
||||||
{file = "cryptography-44.0.2-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:96e7a5e9d6e71f9f4fca8eebfd603f8e86c5225bb18eb621b2c1e50b290a9471"},
|
|
||||||
{file = "cryptography-44.0.2-pp311-pypy311_pp73-manylinux_2_34_aarch64.whl", hash = "sha256:d1b3031093a366ac767b3feb8bcddb596671b3aaff82d4050f984da0c248b615"},
|
|
||||||
{file = "cryptography-44.0.2-pp311-pypy311_pp73-manylinux_2_34_x86_64.whl", hash = "sha256:04abd71114848aa25edb28e225ab5f268096f44cf0127f3d36975bdf1bdf3390"},
|
|
||||||
{file = "cryptography-44.0.2.tar.gz", hash = "sha256:c63454aa261a0cf0c5b4718349629793e9e634993538db841165b3df74f37ec0"},
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
@ -1273,7 +1269,7 @@ nox = ["nox (>=2024.4.15)", "nox[uv] (>=2024.3.2) ; python_version >= \"3.8\""]
|
|||||||
pep8test = ["check-sdist ; python_version >= \"3.8\"", "click (>=8.0.1)", "mypy (>=1.4)", "ruff (>=0.3.6)"]
|
pep8test = ["check-sdist ; python_version >= \"3.8\"", "click (>=8.0.1)", "mypy (>=1.4)", "ruff (>=0.3.6)"]
|
||||||
sdist = ["build (>=1.0.0)"]
|
sdist = ["build (>=1.0.0)"]
|
||||||
ssh = ["bcrypt (>=3.1.5)"]
|
ssh = ["bcrypt (>=3.1.5)"]
|
||||||
test = ["certifi (>=2024)", "cryptography-vectors (==44.0.2)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"]
|
test = ["certifi (>=2024)", "cryptography-vectors (==44.0.1)", "pretend (>=0.7)", "pytest (>=7.4.0)", "pytest-benchmark (>=4.0)", "pytest-cov (>=2.10.1)", "pytest-xdist (>=3.5.0)"]
|
||||||
test-randomorder = ["pytest-randomly"]
|
test-randomorder = ["pytest-randomly"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1313,38 +1309,38 @@ tests = ["django", "hypothesis", "pytest", "pytest-asyncio"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "debugpy"
|
name = "debugpy"
|
||||||
version = "1.8.13"
|
version = "1.8.12"
|
||||||
description = "An implementation of the Debug Adapter Protocol for Python"
|
description = "An implementation of the Debug Adapter Protocol for Python"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
groups = ["dev"]
|
groups = ["dev"]
|
||||||
files = [
|
files = [
|
||||||
{file = "debugpy-1.8.13-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:06859f68e817966723ffe046b896b1bd75c665996a77313370336ee9e1de3e90"},
|
{file = "debugpy-1.8.12-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:a2ba7ffe58efeae5b8fad1165357edfe01464f9aef25e814e891ec690e7dd82a"},
|
||||||
{file = "debugpy-1.8.13-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb56c2db69fb8df3168bc857d7b7d2494fed295dfdbde9a45f27b4b152f37520"},
|
{file = "debugpy-1.8.12-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cbbd4149c4fc5e7d508ece083e78c17442ee13b0e69bfa6bd63003e486770f45"},
|
||||||
{file = "debugpy-1.8.13-cp310-cp310-win32.whl", hash = "sha256:46abe0b821cad751fc1fb9f860fb2e68d75e2c5d360986d0136cd1db8cad4428"},
|
{file = "debugpy-1.8.12-cp310-cp310-win32.whl", hash = "sha256:b202f591204023b3ce62ff9a47baa555dc00bb092219abf5caf0e3718ac20e7c"},
|
||||||
{file = "debugpy-1.8.13-cp310-cp310-win_amd64.whl", hash = "sha256:dc7b77f5d32674686a5f06955e4b18c0e41fb5a605f5b33cf225790f114cfeec"},
|
{file = "debugpy-1.8.12-cp310-cp310-win_amd64.whl", hash = "sha256:9649eced17a98ce816756ce50433b2dd85dfa7bc92ceb60579d68c053f98dff9"},
|
||||||
{file = "debugpy-1.8.13-cp311-cp311-macosx_14_0_universal2.whl", hash = "sha256:eee02b2ed52a563126c97bf04194af48f2fe1f68bb522a312b05935798e922ff"},
|
{file = "debugpy-1.8.12-cp311-cp311-macosx_14_0_universal2.whl", hash = "sha256:36f4829839ef0afdfdd208bb54f4c3d0eea86106d719811681a8627ae2e53dd5"},
|
||||||
{file = "debugpy-1.8.13-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4caca674206e97c85c034c1efab4483f33971d4e02e73081265ecb612af65377"},
|
{file = "debugpy-1.8.12-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a28ed481d530e3138553be60991d2d61103ce6da254e51547b79549675f539b7"},
|
||||||
{file = "debugpy-1.8.13-cp311-cp311-win32.whl", hash = "sha256:7d9a05efc6973b5aaf076d779cf3a6bbb1199e059a17738a2aa9d27a53bcc888"},
|
{file = "debugpy-1.8.12-cp311-cp311-win32.whl", hash = "sha256:4ad9a94d8f5c9b954e0e3b137cc64ef3f579d0df3c3698fe9c3734ee397e4abb"},
|
||||||
{file = "debugpy-1.8.13-cp311-cp311-win_amd64.whl", hash = "sha256:62f9b4a861c256f37e163ada8cf5a81f4c8d5148fc17ee31fb46813bd658cdcc"},
|
{file = "debugpy-1.8.12-cp311-cp311-win_amd64.whl", hash = "sha256:4703575b78dd697b294f8c65588dc86874ed787b7348c65da70cfc885efdf1e1"},
|
||||||
{file = "debugpy-1.8.13-cp312-cp312-macosx_14_0_universal2.whl", hash = "sha256:2b8de94c5c78aa0d0ed79023eb27c7c56a64c68217d881bee2ffbcb13951d0c1"},
|
{file = "debugpy-1.8.12-cp312-cp312-macosx_14_0_universal2.whl", hash = "sha256:7e94b643b19e8feb5215fa508aee531387494bf668b2eca27fa769ea11d9f498"},
|
||||||
{file = "debugpy-1.8.13-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:887d54276cefbe7290a754424b077e41efa405a3e07122d8897de54709dbe522"},
|
{file = "debugpy-1.8.12-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:086b32e233e89a2740c1615c2f775c34ae951508b28b308681dbbb87bba97d06"},
|
||||||
{file = "debugpy-1.8.13-cp312-cp312-win32.whl", hash = "sha256:3872ce5453b17837ef47fb9f3edc25085ff998ce63543f45ba7af41e7f7d370f"},
|
{file = "debugpy-1.8.12-cp312-cp312-win32.whl", hash = "sha256:2ae5df899732a6051b49ea2632a9ea67f929604fd2b036613a9f12bc3163b92d"},
|
||||||
{file = "debugpy-1.8.13-cp312-cp312-win_amd64.whl", hash = "sha256:63ca7670563c320503fea26ac688988d9d6b9c6a12abc8a8cf2e7dd8e5f6b6ea"},
|
{file = "debugpy-1.8.12-cp312-cp312-win_amd64.whl", hash = "sha256:39dfbb6fa09f12fae32639e3286112fc35ae976114f1f3d37375f3130a820969"},
|
||||||
{file = "debugpy-1.8.13-cp313-cp313-macosx_14_0_universal2.whl", hash = "sha256:31abc9618be4edad0b3e3a85277bc9ab51a2d9f708ead0d99ffb5bb750e18503"},
|
{file = "debugpy-1.8.12-cp313-cp313-macosx_14_0_universal2.whl", hash = "sha256:696d8ae4dff4cbd06bf6b10d671e088b66669f110c7c4e18a44c43cf75ce966f"},
|
||||||
{file = "debugpy-1.8.13-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0bd87557f97bced5513a74088af0b84982b6ccb2e254b9312e29e8a5c4270eb"},
|
{file = "debugpy-1.8.12-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:898fba72b81a654e74412a67c7e0a81e89723cfe2a3ea6fcd3feaa3395138ca9"},
|
||||||
{file = "debugpy-1.8.13-cp313-cp313-win32.whl", hash = "sha256:5268ae7fdca75f526d04465931cb0bd24577477ff50e8bb03dab90983f4ebd02"},
|
{file = "debugpy-1.8.12-cp313-cp313-win32.whl", hash = "sha256:22a11c493c70413a01ed03f01c3c3a2fc4478fc6ee186e340487b2edcd6f4180"},
|
||||||
{file = "debugpy-1.8.13-cp313-cp313-win_amd64.whl", hash = "sha256:79ce4ed40966c4c1631d0131606b055a5a2f8e430e3f7bf8fd3744b09943e8e8"},
|
{file = "debugpy-1.8.12-cp313-cp313-win_amd64.whl", hash = "sha256:fdb3c6d342825ea10b90e43d7f20f01535a72b3a1997850c0c3cefa5c27a4a2c"},
|
||||||
{file = "debugpy-1.8.13-cp38-cp38-macosx_14_0_x86_64.whl", hash = "sha256:acf39a6e98630959763f9669feddee540745dfc45ad28dbc9bd1f9cd60639391"},
|
{file = "debugpy-1.8.12-cp38-cp38-macosx_14_0_x86_64.whl", hash = "sha256:b0232cd42506d0c94f9328aaf0d1d0785f90f87ae72d9759df7e5051be039738"},
|
||||||
{file = "debugpy-1.8.13-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:924464d87e7d905eb0d79fb70846558910e906d9ee309b60c4fe597a2e802590"},
|
{file = "debugpy-1.8.12-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9af40506a59450f1315168d47a970db1a65aaab5df3833ac389d2899a5d63b3f"},
|
||||||
{file = "debugpy-1.8.13-cp38-cp38-win32.whl", hash = "sha256:3dae443739c6b604802da9f3e09b0f45ddf1cf23c99161f3a1a8039f61a8bb89"},
|
{file = "debugpy-1.8.12-cp38-cp38-win32.whl", hash = "sha256:5cc45235fefac57f52680902b7d197fb2f3650112379a6fa9aa1b1c1d3ed3f02"},
|
||||||
{file = "debugpy-1.8.13-cp38-cp38-win_amd64.whl", hash = "sha256:ed93c3155fc1f888ab2b43626182174e457fc31b7781cd1845629303790b8ad1"},
|
{file = "debugpy-1.8.12-cp38-cp38-win_amd64.whl", hash = "sha256:557cc55b51ab2f3371e238804ffc8510b6ef087673303890f57a24195d096e61"},
|
||||||
{file = "debugpy-1.8.13-cp39-cp39-macosx_14_0_x86_64.whl", hash = "sha256:6fab771639332bd8ceb769aacf454a30d14d7a964f2012bf9c4e04c60f16e85b"},
|
{file = "debugpy-1.8.12-cp39-cp39-macosx_14_0_x86_64.whl", hash = "sha256:b5c6c967d02fee30e157ab5227706f965d5c37679c687b1e7bbc5d9e7128bd41"},
|
||||||
{file = "debugpy-1.8.13-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32b6857f8263a969ce2ca098f228e5cc0604d277447ec05911a8c46cf3e7e307"},
|
{file = "debugpy-1.8.12-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88a77f422f31f170c4b7e9ca58eae2a6c8e04da54121900651dfa8e66c29901a"},
|
||||||
{file = "debugpy-1.8.13-cp39-cp39-win32.whl", hash = "sha256:f14d2c4efa1809da125ca62df41050d9c7cd9cb9e380a2685d1e453c4d450ccb"},
|
{file = "debugpy-1.8.12-cp39-cp39-win32.whl", hash = "sha256:a4042edef80364239f5b7b5764e55fd3ffd40c32cf6753da9bda4ff0ac466018"},
|
||||||
{file = "debugpy-1.8.13-cp39-cp39-win_amd64.whl", hash = "sha256:ea869fe405880327497e6945c09365922c79d2a1eed4c3ae04d77ac7ae34b2b5"},
|
{file = "debugpy-1.8.12-cp39-cp39-win_amd64.whl", hash = "sha256:f30b03b0f27608a0b26c75f0bb8a880c752c0e0b01090551b9d87c7d783e2069"},
|
||||||
{file = "debugpy-1.8.13-py2.py3-none-any.whl", hash = "sha256:d4ba115cdd0e3a70942bd562adba9ec8c651fe69ddde2298a1be296fc331906f"},
|
{file = "debugpy-1.8.12-py2.py3-none-any.whl", hash = "sha256:274b6a2040349b5c9864e475284bce5bb062e63dce368a394b8cc865ae3b00c6"},
|
||||||
{file = "debugpy-1.8.13.tar.gz", hash = "sha256:837e7bef95bdefba426ae38b9a94821ebdc5bea55627879cd48165c90b9e50ce"},
|
{file = "debugpy-1.8.12.tar.gz", hash = "sha256:646530b04f45c830ceae8e491ca1c9320a2d2f0efea3141487c82130aba70dce"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1406,14 +1402,14 @@ dev = ["PyTest", "PyTest-Cov", "bump2version (<1)", "sphinx (<2)", "tox"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "django"
|
name = "django"
|
||||||
version = "5.0.13"
|
version = "5.0.12"
|
||||||
description = "A high-level Python web framework that encourages rapid development and clean, pragmatic design."
|
description = "A high-level Python web framework that encourages rapid development and clean, pragmatic design."
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.10"
|
python-versions = ">=3.10"
|
||||||
groups = ["main", "dev"]
|
groups = ["main", "dev"]
|
||||||
files = [
|
files = [
|
||||||
{file = "Django-5.0.13-py3-none-any.whl", hash = "sha256:b983238dfa2eb2e6b27ebb815e14f0741cf186606eb7bcd857e740174017c50e"},
|
{file = "Django-5.0.12-py3-none-any.whl", hash = "sha256:3566604af111f586a1c9d49cb14ba6c607a0ccbbf87f57d98872cd8aae7d48ad"},
|
||||||
{file = "Django-5.0.13.tar.gz", hash = "sha256:f9d4b7b87a9dae248d5f20cec940cf7290e07d508d6d8432e3c2cabf09b3b0ff"},
|
{file = "Django-5.0.12.tar.gz", hash = "sha256:05097ea026cceb2db4db0655ecf77cc96b0753ac6a367280e458e603f6556f53"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
@ -1611,7 +1607,7 @@ Django = ">=2.1,<5.1"
|
|||||||
type = "git"
|
type = "git"
|
||||||
url = "https://github.com/rissson/django-tenants.git"
|
url = "https://github.com/rissson/django-tenants.git"
|
||||||
reference = "authentik-fixes"
|
reference = "authentik-fixes"
|
||||||
resolved_reference = "156e53a6f5902d74b73dd9d0192fffaa2587a740"
|
resolved_reference = "a7f37c53f62f355a00142473ff1e3451bb794eca"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "djangorestframework"
|
name = "djangorestframework"
|
||||||
@ -1772,28 +1768,30 @@ files = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "duo-client"
|
name = "duo-client"
|
||||||
version = "5.4.0"
|
version = "5.3.0"
|
||||||
description = "Reference client for Duo Security APIs"
|
description = "Reference client for Duo Security APIs"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
files = [
|
files = [
|
||||||
{file = "duo_client-5.4.0-py3-none-any.whl", hash = "sha256:092d2f79ca2dd7107f944807a109c98c08b99c2dd7fc422b979a248787852068"},
|
{file = "duo_client-5.3.0-py3-none-any.whl", hash = "sha256:85614bb684cef96285268aef0c1e858df939f6e8a190fb2c707d700bb0215766"},
|
||||||
{file = "duo_client-5.4.0.tar.gz", hash = "sha256:8e0fec41006951ce7d0ac5281ddfef59f154e194c71d5a00d717e1769e9077bb"},
|
{file = "duo_client-5.3.0.tar.gz", hash = "sha256:afa5ef98a42f06965a2702ca41dba9c85c483abd945e0a440f0ec4871b7593bf"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
setuptools = "*"
|
setuptools = "*"
|
||||||
|
six = "*"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "durationpy"
|
name = "durationpy"
|
||||||
version = "0.7"
|
version = "0.9"
|
||||||
description = "Module for converting between datetime.timedelta and Go's Duration strings."
|
description = "Module for converting between datetime.timedelta and Go's Duration strings."
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
files = [
|
files = [
|
||||||
{file = "durationpy-0.7.tar.gz", hash = "sha256:8447c43df4f1a0b434e70c15a38d77f5c9bd17284bfc1ff1d430f233d5083732"},
|
{file = "durationpy-0.9-py3-none-any.whl", hash = "sha256:e65359a7af5cedad07fb77a2dd3f390f8eb0b74cb845589fa6c057086834dd38"},
|
||||||
|
{file = "durationpy-0.9.tar.gz", hash = "sha256:fd3feb0a69a0057d582ef643c355c40d2fa1c942191f914d12203b1a01ac722a"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -2033,14 +2031,14 @@ grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "google-api-python-client"
|
name = "google-api-python-client"
|
||||||
version = "2.164.0"
|
version = "2.161.0"
|
||||||
description = "Google API Client Library for Python"
|
description = "Google API Client Library for Python"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
files = [
|
files = [
|
||||||
{file = "google_api_python_client-2.164.0-py2.py3-none-any.whl", hash = "sha256:b2037c3d280793c8d5180b04317b16be4acd5f77af5dfa7213ace32d140a9ffe"},
|
{file = "google_api_python_client-2.161.0-py2.py3-none-any.whl", hash = "sha256:9476a5a4f200bae368140453df40f9cda36be53fa7d0e9a9aac4cdb859a26448"},
|
||||||
{file = "google_api_python_client-2.164.0.tar.gz", hash = "sha256:116f5a05dfb95ed7f7ea0d0f561fc5464146709c583226cc814690f9bb221492"},
|
{file = "google_api_python_client-2.161.0.tar.gz", hash = "sha256:324c0cce73e9ea0a0d2afd5937e01b7c2d6a4d7e2579cdb6c384f9699d6c9f37"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
@ -2383,14 +2381,14 @@ files = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "importlib-metadata"
|
name = "importlib-metadata"
|
||||||
version = "8.6.1"
|
version = "8.5.0"
|
||||||
description = "Read metadata from Python packages"
|
description = "Read metadata from Python packages"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.9"
|
python-versions = ">=3.8"
|
||||||
groups = ["main", "dev"]
|
groups = ["main", "dev"]
|
||||||
files = [
|
files = [
|
||||||
{file = "importlib_metadata-8.6.1-py3-none-any.whl", hash = "sha256:02a89390c1e15fdfdc0d7c6b25cb3e62650d0494005c97d6f148bf5b9787525e"},
|
{file = "importlib_metadata-8.5.0-py3-none-any.whl", hash = "sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b"},
|
||||||
{file = "importlib_metadata-8.6.1.tar.gz", hash = "sha256:310b41d755445d74569f993ccfc22838295d9fe005425094fad953d7f15c8580"},
|
{file = "importlib_metadata-8.5.0.tar.gz", hash = "sha256:71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
@ -2402,7 +2400,7 @@ cover = ["pytest-cov"]
|
|||||||
doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
|
doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
|
||||||
enabler = ["pytest-enabler (>=2.2)"]
|
enabler = ["pytest-enabler (>=2.2)"]
|
||||||
perf = ["ipython"]
|
perf = ["ipython"]
|
||||||
test = ["flufl.flake8", "importlib_resources (>=1.3) ; python_version < \"3.9\"", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"]
|
test = ["flufl.flake8", "importlib-resources (>=1.3) ; python_version < \"3.9\"", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"]
|
||||||
type = ["pytest-mypy"]
|
type = ["pytest-mypy"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -2465,14 +2463,14 @@ files = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jinja2"
|
name = "jinja2"
|
||||||
version = "3.1.6"
|
version = "3.1.5"
|
||||||
description = "A very fast and expressive template engine."
|
description = "A very fast and expressive template engine."
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
groups = ["dev"]
|
groups = ["dev"]
|
||||||
files = [
|
files = [
|
||||||
{file = "jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"},
|
{file = "jinja2-3.1.5-py3-none-any.whl", hash = "sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb"},
|
||||||
{file = "jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"},
|
{file = "jinja2-3.1.5.tar.gz", hash = "sha256:8fefff8dc3034e27bb80d67c671eb8a9bc424c0ef4c0826edbff304cceff43bb"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
@ -2495,18 +2493,18 @@ files = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jsii"
|
name = "jsii"
|
||||||
version = "1.109.0"
|
version = "1.106.0"
|
||||||
description = "Python client for jsii runtime"
|
description = "Python client for jsii runtime"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "~=3.9"
|
python-versions = "~=3.8"
|
||||||
groups = ["dev"]
|
groups = ["dev"]
|
||||||
files = [
|
files = [
|
||||||
{file = "jsii-1.109.0-py3-none-any.whl", hash = "sha256:100bb48c7f74b8e22b3182c5466db1c32565ddb681ed5e2bf556076a734d3f07"},
|
{file = "jsii-1.106.0-py3-none-any.whl", hash = "sha256:5a44d7c3a5a326fa3d9befdb3770b380057e0a61e3804e7c4907f70d76afaaa2"},
|
||||||
{file = "jsii-1.109.0.tar.gz", hash = "sha256:85e0deca8089e2918776541e986d5abab90a66d4330eedfc14e8a060dd507bad"},
|
{file = "jsii-1.106.0.tar.gz", hash = "sha256:c79c47899f53a7c3c4b20f80d3cd306628fe9ed1852eee970324c71eba1d974e"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
attrs = ">=21.2,<26.0"
|
attrs = ">=21.2,<25.0"
|
||||||
cattrs = ">=1.8,<24.2"
|
cattrs = ">=1.8,<24.2"
|
||||||
importlib-resources = ">=5.2.0"
|
importlib-resources = ">=5.2.0"
|
||||||
publication = ">=0.0.3"
|
publication = ">=0.0.3"
|
||||||
@ -2644,14 +2642,14 @@ zookeeper = ["kazoo (>=2.8.0)"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kubernetes"
|
name = "kubernetes"
|
||||||
version = "32.0.1"
|
version = "32.0.0"
|
||||||
description = "Kubernetes python client"
|
description = "Kubernetes python client"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.6"
|
python-versions = ">=3.6"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
files = [
|
files = [
|
||||||
{file = "kubernetes-32.0.1-py2.py3-none-any.whl", hash = "sha256:35282ab8493b938b08ab5526c7ce66588232df00ef5e1dbe88a419107dc10998"},
|
{file = "kubernetes-32.0.0-py2.py3-none-any.whl", hash = "sha256:60fd8c29e8e43d9c553ca4811895a687426717deba9c0a66fb2dcc3f5ef96692"},
|
||||||
{file = "kubernetes-32.0.1.tar.gz", hash = "sha256:42f43d49abd437ada79a79a16bd48a604d3471a117a8347e87db693f2ba0ba28"},
|
{file = "kubernetes-32.0.0.tar.gz", hash = "sha256:319fa840345a482001ac5d6062222daeb66ec4d1bcb3087402aed685adf0aecb"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
@ -3265,14 +3263,14 @@ dev = ["bumpver", "isort", "mypy", "pylint", "pytest", "yapf"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "msgraph-sdk"
|
name = "msgraph-sdk"
|
||||||
version = "1.24.0"
|
version = "1.21.0"
|
||||||
description = "The Microsoft Graph Python SDK"
|
description = "The Microsoft Graph Python SDK"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.9"
|
python-versions = ">=3.9"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
files = [
|
files = [
|
||||||
{file = "msgraph_sdk-1.24.0-py3-none-any.whl", hash = "sha256:7cd2dd95c3e2b4d565fe11b019d26102723d252022b53dc854697378dc983538"},
|
{file = "msgraph_sdk-1.21.0-py3-none-any.whl", hash = "sha256:d8564b3d76a0c76960af94b916fc6ab3af2d11d2263ab08fafb136c334f66c0e"},
|
||||||
{file = "msgraph_sdk-1.24.0.tar.gz", hash = "sha256:d401160cfdab239867faf3b7e6984632dd11524d893a0c816db2d5a64adda650"},
|
{file = "msgraph_sdk-1.21.0.tar.gz", hash = "sha256:f45db4c1bffb22e0b54876defd06d582291f7ca2e737f0ab519e43a18cf90df4"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
@ -3442,58 +3440,58 @@ develop = false
|
|||||||
|
|
||||||
[package.source]
|
[package.source]
|
||||||
type = "git"
|
type = "git"
|
||||||
url = "https://github.com/vsoch/oci-python"
|
url = "https://github.com/BeryJu/oci-python"
|
||||||
reference = "20d69d9cc50a0fef31605b46f06da0c94f1ec3cf"
|
reference = "c791b19056769cd67957322806809ab70f5bead8"
|
||||||
resolved_reference = "20d69d9cc50a0fef31605b46f06da0c94f1ec3cf"
|
resolved_reference = "c791b19056769cd67957322806809ab70f5bead8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "opentelemetry-api"
|
name = "opentelemetry-api"
|
||||||
version = "1.31.0"
|
version = "1.28.0"
|
||||||
description = "OpenTelemetry Python API"
|
description = "OpenTelemetry Python API"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
files = [
|
files = [
|
||||||
{file = "opentelemetry_api-1.31.0-py3-none-any.whl", hash = "sha256:145b72c6c16977c005c568ec32f4946054ab793d8474a17fd884b0397582c5f2"},
|
{file = "opentelemetry_api-1.28.0-py3-none-any.whl", hash = "sha256:8457cd2c59ea1bd0988560f021656cecd254ad7ef6be4ba09dbefeca2409ce52"},
|
||||||
{file = "opentelemetry_api-1.31.0.tar.gz", hash = "sha256:d8da59e83e8e3993b4726e4c1023cd46f57c4d5a73142e239247e7d814309de1"},
|
{file = "opentelemetry_api-1.28.0.tar.gz", hash = "sha256:578610bcb8aa5cdcb11169d136cc752958548fb6ccffb0969c1036b0ee9e5353"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
deprecated = ">=1.2.6"
|
deprecated = ">=1.2.6"
|
||||||
importlib-metadata = ">=6.0,<8.7.0"
|
importlib-metadata = ">=6.0,<=8.5.0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "opentelemetry-sdk"
|
name = "opentelemetry-sdk"
|
||||||
version = "1.31.0"
|
version = "1.28.0"
|
||||||
description = "OpenTelemetry Python SDK"
|
description = "OpenTelemetry Python SDK"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
files = [
|
files = [
|
||||||
{file = "opentelemetry_sdk-1.31.0-py3-none-any.whl", hash = "sha256:97c9a03865e69723725fb64fe04343a488c3e61e684eb804bd7d6da2215dfc60"},
|
{file = "opentelemetry_sdk-1.28.0-py3-none-any.whl", hash = "sha256:4b37da81d7fad67f6683c4420288c97f4ed0d988845d5886435f428ec4b8429a"},
|
||||||
{file = "opentelemetry_sdk-1.31.0.tar.gz", hash = "sha256:452d7d5b3c1db2e5e4cb64abede0ddd20690cb244a559c73a59652fdf6726070"},
|
{file = "opentelemetry_sdk-1.28.0.tar.gz", hash = "sha256:41d5420b2e3fb7716ff4981b510d551eff1fc60eb5a95cf7335b31166812a893"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
opentelemetry-api = "1.31.0"
|
opentelemetry-api = "1.28.0"
|
||||||
opentelemetry-semantic-conventions = "0.52b0"
|
opentelemetry-semantic-conventions = "0.49b0"
|
||||||
typing-extensions = ">=3.7.4"
|
typing-extensions = ">=3.7.4"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "opentelemetry-semantic-conventions"
|
name = "opentelemetry-semantic-conventions"
|
||||||
version = "0.52b0"
|
version = "0.49b0"
|
||||||
description = "OpenTelemetry Semantic Conventions"
|
description = "OpenTelemetry Semantic Conventions"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
files = [
|
files = [
|
||||||
{file = "opentelemetry_semantic_conventions-0.52b0-py3-none-any.whl", hash = "sha256:4d843652ae1f9f3c0d4d8df0bfef740627c90495ac043fc33f0a04bad3b606e2"},
|
{file = "opentelemetry_semantic_conventions-0.49b0-py3-none-any.whl", hash = "sha256:0458117f6ead0b12e3221813e3e511d85698c31901cac84682052adb9c17c7cd"},
|
||||||
{file = "opentelemetry_semantic_conventions-0.52b0.tar.gz", hash = "sha256:f8bc8873a69d0a2f45746c31980baad2bb10ccee16b1816497ccf99417770386"},
|
{file = "opentelemetry_semantic_conventions-0.49b0.tar.gz", hash = "sha256:dbc7b28339e5390b6b28e022835f9bac4e134a80ebf640848306d3c5192557e8"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
deprecated = ">=1.2.6"
|
deprecated = ">=1.2.6"
|
||||||
opentelemetry-api = "1.31.0"
|
opentelemetry-api = "1.28.0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "orjson"
|
name = "orjson"
|
||||||
@ -3880,39 +3878,39 @@ files = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "psycopg"
|
name = "psycopg"
|
||||||
version = "3.2.6"
|
version = "3.2.4"
|
||||||
description = "PostgreSQL database adapter for Python"
|
description = "PostgreSQL database adapter for Python"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
files = [
|
files = [
|
||||||
{file = "psycopg-3.2.6-py3-none-any.whl", hash = "sha256:f3ff5488525890abb0566c429146add66b329e20d6d4835662b920cbbf90ac58"},
|
{file = "psycopg-3.2.4-py3-none-any.whl", hash = "sha256:43665368ccd48180744cab26b74332f46b63b7e06e8ce0775547a3533883d381"},
|
||||||
{file = "psycopg-3.2.6.tar.gz", hash = "sha256:16fa094efa2698f260f2af74f3710f781e4a6f226efe9d1fd0c37f384639ed8a"},
|
{file = "psycopg-3.2.4.tar.gz", hash = "sha256:f26f1346d6bf1ef5f5ef1714dd405c67fb365cfd1c6cea07de1792747b167b92"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
psycopg-c = {version = "3.2.6", optional = true, markers = "implementation_name != \"pypy\" and extra == \"c\""}
|
psycopg-c = {version = "3.2.4", optional = true, markers = "implementation_name != \"pypy\" and extra == \"c\""}
|
||||||
typing-extensions = {version = ">=4.6", markers = "python_version < \"3.13\""}
|
typing-extensions = {version = ">=4.6", markers = "python_version < \"3.13\""}
|
||||||
tzdata = {version = "*", markers = "sys_platform == \"win32\""}
|
tzdata = {version = "*", markers = "sys_platform == \"win32\""}
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
binary = ["psycopg-binary (==3.2.6) ; implementation_name != \"pypy\""]
|
binary = ["psycopg-binary (==3.2.4) ; implementation_name != \"pypy\""]
|
||||||
c = ["psycopg-c (==3.2.6) ; implementation_name != \"pypy\""]
|
c = ["psycopg-c (==3.2.4) ; implementation_name != \"pypy\""]
|
||||||
dev = ["ast-comments (>=1.1.2)", "black (>=24.1.0)", "codespell (>=2.2)", "dnspython (>=2.1)", "flake8 (>=4.0)", "isort-psycopg", "isort[colors] (>=6.0)", "mypy (>=1.14)", "pre-commit (>=4.0.1)", "types-setuptools (>=57.4)", "wheel (>=0.37)"]
|
dev = ["ast-comments (>=1.1.2)", "black (>=24.1.0)", "codespell (>=2.2)", "dnspython (>=2.1)", "flake8 (>=4.0)", "mypy (>=1.14)", "pre-commit (>=4.0.1)", "types-setuptools (>=57.4)", "wheel (>=0.37)"]
|
||||||
docs = ["Sphinx (>=5.0)", "furo (==2022.6.21)", "sphinx-autobuild (>=2021.3.14)", "sphinx-autodoc-typehints (>=1.12)"]
|
docs = ["Sphinx (>=5.0)", "furo (==2022.6.21)", "sphinx-autobuild (>=2021.3.14)", "sphinx-autodoc-typehints (>=1.12)"]
|
||||||
pool = ["psycopg-pool"]
|
pool = ["psycopg-pool"]
|
||||||
test = ["anyio (>=4.0)", "mypy (>=1.14)", "pproxy (>=2.7)", "pytest (>=6.2.5)", "pytest-cov (>=3.0)", "pytest-randomly (>=3.5)"]
|
test = ["anyio (>=4.0)", "mypy (>=1.14)", "pproxy (>=2.7)", "pytest (>=6.2.5)", "pytest-cov (>=3.0)", "pytest-randomly (>=3.5)"]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "psycopg-c"
|
name = "psycopg-c"
|
||||||
version = "3.2.6"
|
version = "3.2.4"
|
||||||
description = "PostgreSQL database adapter for Python -- C optimisation distribution"
|
description = "PostgreSQL database adapter for Python -- C optimisation distribution"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
markers = "implementation_name != \"pypy\""
|
markers = "implementation_name != \"pypy\""
|
||||||
files = [
|
files = [
|
||||||
{file = "psycopg_c-3.2.6.tar.gz", hash = "sha256:b5fd4ce70f82766a122ca5076a36c4d5818eaa9df9bf76870bc83a064ffaed3a"},
|
{file = "psycopg_c-3.2.4.tar.gz", hash = "sha256:22097a04263efb2efd2cc8b00a51fa90e23f9cd4a2e09903fe4d9c6923dac17a"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -4185,19 +4183,18 @@ tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pyopenssl"
|
name = "pyopenssl"
|
||||||
version = "25.0.0"
|
version = "24.3.0"
|
||||||
description = "Python wrapper module around the OpenSSL library"
|
description = "Python wrapper module around the OpenSSL library"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
groups = ["main", "dev"]
|
groups = ["main", "dev"]
|
||||||
files = [
|
files = [
|
||||||
{file = "pyOpenSSL-25.0.0-py3-none-any.whl", hash = "sha256:424c247065e46e76a37411b9ab1782541c23bb658bf003772c3405fbaa128e90"},
|
{file = "pyOpenSSL-24.3.0-py3-none-any.whl", hash = "sha256:e474f5a473cd7f92221cc04976e48f4d11502804657a08a989fb3be5514c904a"},
|
||||||
{file = "pyopenssl-25.0.0.tar.gz", hash = "sha256:cd2cef799efa3936bb08e8ccb9433a575722b9dd986023f1cabc4ae64e9dac16"},
|
{file = "pyopenssl-24.3.0.tar.gz", hash = "sha256:49f7a019577d834746bc55c5fce6ecbcec0f2b4ec5ce1cf43a9a173b8138bb36"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
cryptography = ">=41.0.5,<45"
|
cryptography = ">=41.0.5,<45"
|
||||||
typing-extensions = {version = ">=4.9", markers = "python_version < \"3.13\" and python_version >= \"3.8\""}
|
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
docs = ["sphinx (!=5.2.0,!=5.2.0.post0,!=7.2.5)", "sphinx_rtd_theme"]
|
docs = ["sphinx (!=5.2.0,!=5.2.0.post0,!=7.2.5)", "sphinx_rtd_theme"]
|
||||||
@ -4249,14 +4246,14 @@ files = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pytest"
|
name = "pytest"
|
||||||
version = "8.3.5"
|
version = "8.3.4"
|
||||||
description = "pytest: simple powerful testing with Python"
|
description = "pytest: simple powerful testing with Python"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
groups = ["dev"]
|
groups = ["dev"]
|
||||||
files = [
|
files = [
|
||||||
{file = "pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820"},
|
{file = "pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6"},
|
||||||
{file = "pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845"},
|
{file = "pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
@ -4749,30 +4746,30 @@ pyasn1 = ">=0.1.3"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ruff"
|
name = "ruff"
|
||||||
version = "0.9.10"
|
version = "0.9.6"
|
||||||
description = "An extremely fast Python linter and code formatter, written in Rust."
|
description = "An extremely fast Python linter and code formatter, written in Rust."
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7"
|
python-versions = ">=3.7"
|
||||||
groups = ["dev"]
|
groups = ["dev"]
|
||||||
files = [
|
files = [
|
||||||
{file = "ruff-0.9.10-py3-none-linux_armv6l.whl", hash = "sha256:eb4d25532cfd9fe461acc83498361ec2e2252795b4f40b17e80692814329e42d"},
|
{file = "ruff-0.9.6-py3-none-linux_armv6l.whl", hash = "sha256:2f218f356dd2d995839f1941322ff021c72a492c470f0b26a34f844c29cdf5ba"},
|
||||||
{file = "ruff-0.9.10-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:188a6638dab1aa9bb6228a7302387b2c9954e455fb25d6b4470cb0641d16759d"},
|
{file = "ruff-0.9.6-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b908ff4df65dad7b251c9968a2e4560836d8f5487c2f0cc238321ed951ea0504"},
|
||||||
{file = "ruff-0.9.10-py3-none-macosx_11_0_arm64.whl", hash = "sha256:5284dcac6b9dbc2fcb71fdfc26a217b2ca4ede6ccd57476f52a587451ebe450d"},
|
{file = "ruff-0.9.6-py3-none-macosx_11_0_arm64.whl", hash = "sha256:b109c0ad2ececf42e75fa99dc4043ff72a357436bb171900714a9ea581ddef83"},
|
||||||
{file = "ruff-0.9.10-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:47678f39fa2a3da62724851107f438c8229a3470f533894b5568a39b40029c0c"},
|
{file = "ruff-0.9.6-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1de4367cca3dac99bcbd15c161404e849bb0bfd543664db39232648dc00112dc"},
|
||||||
{file = "ruff-0.9.10-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:99713a6e2766b7a17147b309e8c915b32b07a25c9efd12ada79f217c9c778b3e"},
|
{file = "ruff-0.9.6-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac3ee4d7c2c92ddfdaedf0bf31b2b176fa7aa8950efc454628d477394d35638b"},
|
||||||
{file = "ruff-0.9.10-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:524ee184d92f7c7304aa568e2db20f50c32d1d0caa235d8ddf10497566ea1a12"},
|
{file = "ruff-0.9.6-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5dc1edd1775270e6aa2386119aea692039781429f0be1e0949ea5884e011aa8e"},
|
||||||
{file = "ruff-0.9.10-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:df92aeac30af821f9acf819fc01b4afc3dfb829d2782884f8739fb52a8119a16"},
|
{file = "ruff-0.9.6-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:4a091729086dffa4bd070aa5dab7e39cc6b9d62eb2bef8f3d91172d30d599666"},
|
||||||
{file = "ruff-0.9.10-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de42e4edc296f520bb84954eb992a07a0ec5a02fecb834498415908469854a52"},
|
{file = "ruff-0.9.6-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d1bbc6808bf7b15796cef0815e1dfb796fbd383e7dbd4334709642649625e7c5"},
|
||||||
{file = "ruff-0.9.10-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d257f95b65806104b6b1ffca0ea53f4ef98454036df65b1eda3693534813ecd1"},
|
{file = "ruff-0.9.6-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:589d1d9f25b5754ff230dce914a174a7c951a85a4e9270613a2b74231fdac2f5"},
|
||||||
{file = "ruff-0.9.10-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b60dec7201c0b10d6d11be00e8f2dbb6f40ef1828ee75ed739923799513db24c"},
|
{file = "ruff-0.9.6-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc61dd5131742e21103fbbdcad683a8813be0e3c204472d520d9a5021ca8b217"},
|
||||||
{file = "ruff-0.9.10-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:d838b60007da7a39c046fcdd317293d10b845001f38bcb55ba766c3875b01e43"},
|
{file = "ruff-0.9.6-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:5e2d9126161d0357e5c8f30b0bd6168d2c3872372f14481136d13de9937f79b6"},
|
||||||
{file = "ruff-0.9.10-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:ccaf903108b899beb8e09a63ffae5869057ab649c1e9231c05ae354ebc62066c"},
|
{file = "ruff-0.9.6-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:68660eab1a8e65babb5229a1f97b46e3120923757a68b5413d8561f8a85d4897"},
|
||||||
{file = "ruff-0.9.10-py3-none-musllinux_1_2_i686.whl", hash = "sha256:f9567d135265d46e59d62dc60c0bfad10e9a6822e231f5b24032dba5a55be6b5"},
|
{file = "ruff-0.9.6-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c4cae6c4cc7b9b4017c71114115db0445b00a16de3bcde0946273e8392856f08"},
|
||||||
{file = "ruff-0.9.10-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:5f202f0d93738c28a89f8ed9eaba01b7be339e5d8d642c994347eaa81c6d75b8"},
|
{file = "ruff-0.9.6-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:19f505b643228b417c1111a2a536424ddde0db4ef9023b9e04a46ed8a1cb4656"},
|
||||||
{file = "ruff-0.9.10-py3-none-win32.whl", hash = "sha256:bfb834e87c916521ce46b1788fbb8484966e5113c02df216680102e9eb960029"},
|
{file = "ruff-0.9.6-py3-none-win32.whl", hash = "sha256:194d8402bceef1b31164909540a597e0d913c0e4952015a5b40e28c146121b5d"},
|
||||||
{file = "ruff-0.9.10-py3-none-win_amd64.whl", hash = "sha256:f2160eeef3031bf4b17df74e307d4c5fb689a6f3a26a2de3f7ef4044e3c484f1"},
|
{file = "ruff-0.9.6-py3-none-win_amd64.whl", hash = "sha256:03482d5c09d90d4ee3f40d97578423698ad895c87314c4de39ed2af945633caa"},
|
||||||
{file = "ruff-0.9.10-py3-none-win_arm64.whl", hash = "sha256:5fd804c0327a5e5ea26615550e706942f348b197d5475ff34c19733aee4b2e69"},
|
{file = "ruff-0.9.6-py3-none-win_arm64.whl", hash = "sha256:0e2bb706a2be7ddfea4a4af918562fdc1bcb16df255e5fa595bbd800ce322a5a"},
|
||||||
{file = "ruff-0.9.10.tar.gz", hash = "sha256:9bacb735d7bada9cfb0f2c227d3658fc443d90a727b47f206fb33f52f3c0eac7"},
|
{file = "ruff-0.9.6.tar.gz", hash = "sha256:81761592f72b620ec8fa1068a6fd00e98a5ebee342a3642efd84454f3031dca9"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -4813,14 +4810,14 @@ django-query = ["django (>=3.2)"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "selenium"
|
name = "selenium"
|
||||||
version = "4.29.0"
|
version = "4.28.1"
|
||||||
description = "Official Python bindings for Selenium WebDriver"
|
description = "Official Python bindings for Selenium WebDriver"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.9"
|
python-versions = ">=3.9"
|
||||||
groups = ["dev"]
|
groups = ["dev"]
|
||||||
files = [
|
files = [
|
||||||
{file = "selenium-4.29.0-py3-none-any.whl", hash = "sha256:ce5d26f1ddc1111641113653af33694c13947dd36c2df09cdd33f554351d372e"},
|
{file = "selenium-4.28.1-py3-none-any.whl", hash = "sha256:4238847e45e24e4472cfcf3554427512c7aab9443396435b1623ef406fff1cc1"},
|
||||||
{file = "selenium-4.29.0.tar.gz", hash = "sha256:3a62f7ec33e669364a6c0562a701deb69745b569c50d55f1a912bf8eb33358ba"},
|
{file = "selenium-4.28.1.tar.gz", hash = "sha256:0072d08670d7ec32db901bd0107695a330cecac9f196e3afb3fa8163026e022a"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
@ -4915,97 +4912,97 @@ tests = ["coverage[toml] (>=5.0.2)", "pytest"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "setproctitle"
|
name = "setproctitle"
|
||||||
version = "1.3.5"
|
version = "1.3.4"
|
||||||
description = "A Python module to customize the process title"
|
description = "A Python module to customize the process title"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
files = [
|
files = [
|
||||||
{file = "setproctitle-1.3.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:02870e0cb0de7f68a7a8a5b23c2bc0ce63821cab3d9b126f9be80bb6cd674c80"},
|
{file = "setproctitle-1.3.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0f6661a69c68349172ba7b4d5dd65fec2b0917abc99002425ad78c3e58cf7595"},
|
||||||
{file = "setproctitle-1.3.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:55b278135be742b8901067479626d909f6613bd2d2c4fd0de6bb46f80e07a919"},
|
{file = "setproctitle-1.3.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:754bac5e470adac7f7ec2239c485cd0b75f8197ca8a5b86ffb20eb3a3676cc42"},
|
||||||
{file = "setproctitle-1.3.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:53fc971f7bf7a674f571a23cdec70f2f0ac88152c59c06aa0808d0be6d834046"},
|
{file = "setproctitle-1.3.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7bc7088c15150745baf66db62a4ced4507d44419eb66207b609f91b64a682af"},
|
||||||
{file = "setproctitle-1.3.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fb0500e1bc6f00b8ba696c3743ddff14c8679e3c2ca9d292c008ac51488d17cf"},
|
{file = "setproctitle-1.3.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a46ef3ecf61e4840fbc1145fdd38acf158d0da7543eda7b773ed2b30f75c2830"},
|
||||||
{file = "setproctitle-1.3.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:995b3ac1b5fe510f4e1d1c19ebf19f4bceb448f2d6e8d99ea23f33cb6f1a277e"},
|
{file = "setproctitle-1.3.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffcb09d5c0ffa043254ec9a734a73f3791fec8bf6333592f906bb2e91ed2af1a"},
|
||||||
{file = "setproctitle-1.3.5-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a5a05e2c3fdfbda32b9c9da72d0506398d1efb5bd2c5981b9e12d3622eb3d4f9"},
|
{file = "setproctitle-1.3.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06c16b7a91cdc5d700271899e4383384a61aae83a3d53d0e2e5a266376083342"},
|
||||||
{file = "setproctitle-1.3.5-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:310c7f4ca4c8476a9840b2cd4b22ee602a49a3c902fdcd2dd8284685abd10a9a"},
|
{file = "setproctitle-1.3.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:9f9732e59863eaeedd3feef94b2b216cb86d40dda4fad2d0f0aaec3b31592716"},
|
||||||
{file = "setproctitle-1.3.5-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:867af4a5c3d85484fbcc50ea88bcd375acf709cff88a3259575361849c0da351"},
|
{file = "setproctitle-1.3.4-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e152f4ab9ea1632b5fecdd87cee354f2b2eb6e2dfc3aceb0eb36a01c1e12f94c"},
|
||||||
{file = "setproctitle-1.3.5-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8ec0a7fe9f1ba90900144489bc93ce7dd4dec3f3df1e7f188c9e58364fe4a4c5"},
|
{file = "setproctitle-1.3.4-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:020ea47a79b2bbd7bd7b94b85ca956ba7cb026e82f41b20d2e1dac4008cead25"},
|
||||||
{file = "setproctitle-1.3.5-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:aaee7acba2733a14a886488b7495bfec4a8d6407124c04a0946dbde1684230a3"},
|
{file = "setproctitle-1.3.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8c52b12b10e4057fc302bd09cb3e3f28bb382c30c044eb3396e805179a8260e4"},
|
||||||
{file = "setproctitle-1.3.5-cp310-cp310-win32.whl", hash = "sha256:bd2cccd972e4282af4ce2c13cd9ebdf07be157eabafd8ce648fffdc8ae6fbe28"},
|
{file = "setproctitle-1.3.4-cp310-cp310-win32.whl", hash = "sha256:a65a147f545f3fac86f11acb2d0b316d3e78139a9372317b7eb50561b2817ba0"},
|
||||||
{file = "setproctitle-1.3.5-cp310-cp310-win_amd64.whl", hash = "sha256:81f2328ac34c9584e1e5f87eea916c0bc48476a06606a07debae07acdd7ab5ea"},
|
{file = "setproctitle-1.3.4-cp310-cp310-win_amd64.whl", hash = "sha256:66821fada6426998762a3650a37fba77e814a249a95b1183011070744aff47f6"},
|
||||||
{file = "setproctitle-1.3.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1c8dcc250872385f2780a5ea58050b58cbc8b6a7e8444952a5a65c359886c593"},
|
{file = "setproctitle-1.3.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f0f749f07002c2d6fecf37cedc43207a88e6c651926a470a5f229070cf791879"},
|
||||||
{file = "setproctitle-1.3.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ca82fae9eb4800231dd20229f06e8919787135a5581da245b8b05e864f34cc8b"},
|
{file = "setproctitle-1.3.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:90ea8d302a5d30b948451d146e94674a3c5b020cc0ced9a1c28f8ddb0f203a5d"},
|
||||||
{file = "setproctitle-1.3.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0424e1d33232322541cb36fb279ea5242203cd6f20de7b4fb2a11973d8e8c2ce"},
|
{file = "setproctitle-1.3.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f859c88193ed466bee4eb9d45fbc29d2253e6aa3ccd9119c9a1d8d95f409a60d"},
|
||||||
{file = "setproctitle-1.3.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fec8340ab543144d04a9d805d80a0aad73fdeb54bea6ff94e70d39a676ea4ec0"},
|
{file = "setproctitle-1.3.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b3afa5a0ed08a477ded239c05db14c19af585975194a00adf594d48533b23701"},
|
||||||
{file = "setproctitle-1.3.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eab441c89f181271ab749077dcc94045a423e51f2fb0b120a1463ef9820a08d0"},
|
{file = "setproctitle-1.3.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10a78fce9018cc3e9a772b6537bbe3fe92380acf656c9f86db2f45e685af376e"},
|
||||||
{file = "setproctitle-1.3.5-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2c371550a2288901a0dcd84192691ebd3197a43c95f3e0b396ed6d1cedf5c6c"},
|
{file = "setproctitle-1.3.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5d758e2eed2643afac5f2881542fbb5aa97640b54be20d0a5ed0691d02f0867d"},
|
||||||
{file = "setproctitle-1.3.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:78288ff5f9c415c56595b2257ad218936dd9fa726b36341b373b31ca958590fe"},
|
{file = "setproctitle-1.3.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ef133a1a2ee378d549048a12d56f4ef0e2b9113b0b25b6b77821e9af94d50634"},
|
||||||
{file = "setproctitle-1.3.5-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:f1f13a25fc46731acab518602bb1149bfd8b5fabedf8290a7c0926d61414769d"},
|
{file = "setproctitle-1.3.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1d2a154b79d5fb42d1eff06e05e22f0e8091261d877dd47b37d31352b74ecc37"},
|
||||||
{file = "setproctitle-1.3.5-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:1534d6cd3854d035e40bf4c091984cbdd4d555d7579676d406c53c8f187c006f"},
|
{file = "setproctitle-1.3.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:202eae632815571297833876a0f407d0d9c7ad9d843b38adbe687fe68c5192ee"},
|
||||||
{file = "setproctitle-1.3.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:62a01c76708daac78b9688ffb95268c57cb57fa90b543043cda01358912fe2db"},
|
{file = "setproctitle-1.3.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:2b0080819859e80a7776ac47cf6accb4b7ad313baf55fabac89c000480dcd103"},
|
||||||
{file = "setproctitle-1.3.5-cp311-cp311-win32.whl", hash = "sha256:ea07f29735d839eaed985990a0ec42c8aecefe8050da89fec35533d146a7826d"},
|
{file = "setproctitle-1.3.4-cp311-cp311-win32.whl", hash = "sha256:9c9d7d1267dee8c6627963d9376efa068858cfc8f573c083b1b6a2d297a8710f"},
|
||||||
{file = "setproctitle-1.3.5-cp311-cp311-win_amd64.whl", hash = "sha256:ab3ae11e10d13d514d4a5a15b4f619341142ba3e18da48c40e8614c5a1b5e3c3"},
|
{file = "setproctitle-1.3.4-cp311-cp311-win_amd64.whl", hash = "sha256:475986ddf6df65d619acd52188336a20f616589403f5a5ceb3fc70cdc137037a"},
|
||||||
{file = "setproctitle-1.3.5-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:523424b9be4dea97d95b8a584b183f35c7bab2d0a3d995b01febf5b8a8de90e4"},
|
{file = "setproctitle-1.3.4-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:d06990dcfcd41bb3543c18dd25c8476fbfe1f236757f42fef560f6aa03ac8dfc"},
|
||||||
{file = "setproctitle-1.3.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b6ec1d86c1b4d7b5f2bdceadf213310cf24696b82480a2a702194b8a0bfbcb47"},
|
{file = "setproctitle-1.3.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:317218c9d8b17a010ab2d2f0851e8ef584077a38b1ba2b7c55c9e44e79a61e73"},
|
||||||
{file = "setproctitle-1.3.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea6c505264275a43e9b2acd2acfc11ac33caf52bc3167c9fced4418a810f6b1c"},
|
{file = "setproctitle-1.3.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb5fefb53b9d9f334a5d9ec518a36b92a10b936011ac8a6b6dffd60135f16459"},
|
||||||
{file = "setproctitle-1.3.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0b91e68e6685998e6353f296100ecabc313a6cb3e413d66a03d74b988b61f5ff"},
|
{file = "setproctitle-1.3.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0855006261635e8669646c7c304b494b6df0a194d2626683520103153ad63cc9"},
|
||||||
{file = "setproctitle-1.3.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bc1fda208ae3a2285ad27aeab44c41daf2328abe58fa3270157a739866779199"},
|
{file = "setproctitle-1.3.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1a88e466fcaee659679c1d64dcb2eddbcb4bfadffeb68ba834d9c173a25b6184"},
|
||||||
{file = "setproctitle-1.3.5-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:828727d220e46f048b82289018300a64547b46aaed96bf8810c05fe105426b41"},
|
{file = "setproctitle-1.3.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f963b6ed8ba33eda374a98d979e8a0eaf21f891b6e334701693a2c9510613c4c"},
|
||||||
{file = "setproctitle-1.3.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:83b016221cf80028b2947be20630faa14e3e72a403e35f0ba29550b4e856767b"},
|
{file = "setproctitle-1.3.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:122c2e05697fa91f5d23f00bbe98a9da1bd457b32529192e934095fadb0853f1"},
|
||||||
{file = "setproctitle-1.3.5-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:6d8a411e752e794d052434139ca4234ffeceeb8d8d8ddc390a9051d7942b2726"},
|
{file = "setproctitle-1.3.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:1bba0a866f5895d5b769d8c36b161271c7fd407e5065862ab80ff91c29fbe554"},
|
||||||
{file = "setproctitle-1.3.5-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:50cfbf86b9c63a2c2903f1231f0a58edeb775e651ae1af84eec8430b0571f29b"},
|
{file = "setproctitle-1.3.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:97f1f861998e326e640708488c442519ad69046374b2c3fe9bcc9869b387f23c"},
|
||||||
{file = "setproctitle-1.3.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f3b5e2eacd572444770026c9dd3ddc7543ce427cdf452d40a408d1e95beefb30"},
|
{file = "setproctitle-1.3.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:726aee40357d4bdb70115442cb85ccc8e8bc554fc0bbbaa3a57cbe81df42287d"},
|
||||||
{file = "setproctitle-1.3.5-cp312-cp312-win32.whl", hash = "sha256:cf4e3ded98027de2596c6cc5bbd3302adfb3ca315c848f56516bb0b7e88de1e9"},
|
{file = "setproctitle-1.3.4-cp312-cp312-win32.whl", hash = "sha256:04d6ba8b816dbb0bfd62000b0c3e583160893e6e8c4233e1dca1a9ae4d95d924"},
|
||||||
{file = "setproctitle-1.3.5-cp312-cp312-win_amd64.whl", hash = "sha256:f7a8c01ffd013dda2bed6e7d5cb59fbb609e72f805abf3ee98360f38f7758d9b"},
|
{file = "setproctitle-1.3.4-cp312-cp312-win_amd64.whl", hash = "sha256:9c76e43cb351ba8887371240b599925cdf3ecececc5dfb7125c71678e7722c55"},
|
||||||
{file = "setproctitle-1.3.5-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:162fd76781f57f42ddf27c475e5fef6a8df4fdd69b28dd554e53e2eb2bfe0f95"},
|
{file = "setproctitle-1.3.4-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:d6e3b177e634aa6bbbfbf66d097b6d1cdb80fc60e912c7d8bace2e45699c07dd"},
|
||||||
{file = "setproctitle-1.3.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4969d996bdfbe23bbd023cd0bae6c73a27371615c4ec5296a60cecce268659ef"},
|
{file = "setproctitle-1.3.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6b17655a5f245b416e127e02087ea6347a48821cc4626bc0fd57101bfcd88afc"},
|
||||||
{file = "setproctitle-1.3.5-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd70c95a94473216e7c7a7a1f7d8ecbaca5b16d4ba93ddbfd32050fc485a8451"},
|
{file = "setproctitle-1.3.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fa5057a86df920faab8ee83960b724bace01a3231eb8e3f2c93d78283504d598"},
|
||||||
{file = "setproctitle-1.3.5-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7a887582bfdb6dcbc482db0ef9e630ad23ca95875806ef2b444bf6fbd7b7d7ca"},
|
{file = "setproctitle-1.3.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:149fdfb8a26a555780c4ce53c92e6d3c990ef7b30f90a675eca02e83c6d5f76d"},
|
||||||
{file = "setproctitle-1.3.5-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:755671c39a9e70834eeec6dc6b61e344399c49881d2e7ea3534a1c69669dd9cc"},
|
{file = "setproctitle-1.3.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ded03546938a987f463c68ab98d683af87a83db7ac8093bbc179e77680be5ba2"},
|
||||||
{file = "setproctitle-1.3.5-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ab52b4c2ce056a1b60d439991a81ca90f019488d4b4f64b2779e6badd3677e6"},
|
{file = "setproctitle-1.3.4-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8ab9f5b7f2bbc1754bc6292d9a7312071058e5a891b0391e6d13b226133f36aa"},
|
||||||
{file = "setproctitle-1.3.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:36178b944019ec7fc52bb967ffeee296a11d373734a7be276755bedb3db5c141"},
|
{file = "setproctitle-1.3.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:0b19813c852566fa031902124336fa1f080c51e262fc90266a8c3d65ca47b74c"},
|
||||||
{file = "setproctitle-1.3.5-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:269d41cd4f085b69821d1ee6599124f02dbbc79962b256e260b6c9021d037994"},
|
{file = "setproctitle-1.3.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:db78b645dc63c0ccffca367a498f3b13492fb106a2243a1e998303ba79c996e2"},
|
||||||
{file = "setproctitle-1.3.5-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:d880630fd81d1b3bde121c352ca7ea2f2ff507ef40c3c011d0928ed491f912c9"},
|
{file = "setproctitle-1.3.4-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b669aaac70bd9f03c070270b953f78d9ee56c4af6f0ff9f9cd3e6d1878c10b40"},
|
||||||
{file = "setproctitle-1.3.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:8a7fed67ab49f60bd51f3b4cffff3f8d754d1bb0a40e42869911301ec6519b65"},
|
{file = "setproctitle-1.3.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6dc3d656702791565994e64035a208be56b065675a5bc87b644c657d6d9e2232"},
|
||||||
{file = "setproctitle-1.3.5-cp313-cp313-win32.whl", hash = "sha256:e9c0d0cfcf715631b10d5950d04a9978f63bc46535724ef7c2eaf1dca9988642"},
|
{file = "setproctitle-1.3.4-cp313-cp313-win32.whl", hash = "sha256:091f682809a4d12291cf0205517619d2e7014986b7b00ebecfde3d76f8ae5a8f"},
|
||||||
{file = "setproctitle-1.3.5-cp313-cp313-win_amd64.whl", hash = "sha256:e1d28eb98c91fbebd3e443a45c7da5d84974959851ef304c330eabd654a386f1"},
|
{file = "setproctitle-1.3.4-cp313-cp313-win_amd64.whl", hash = "sha256:adcd6ba863a315702184d92d3d3bbff290514f24a14695d310f02ae5e28bd1f7"},
|
||||||
{file = "setproctitle-1.3.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:8995a1217b52d11d92bafd069961a47c5e13d8751ca976a32b3ecbbd471eaf9b"},
|
{file = "setproctitle-1.3.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:acf41cf91bbc5a36d1fa4455a818bb02bf2a4ccfed2f892ba166ba2fcbb0ec8a"},
|
||||||
{file = "setproctitle-1.3.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ae2ce64ea87837c4e3e65a7a232ff80cf09aa7d916e74cb34a245c47fcd87981"},
|
{file = "setproctitle-1.3.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ceb3ce3262b0e8e088e4117175591b7a82b3bdc5e52e33b1e74778b5fb53fd38"},
|
||||||
{file = "setproctitle-1.3.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20b84de1780bbb0adc67560a113a0ea57e6ecfce2325680de8efe6c2a2f781ac"},
|
{file = "setproctitle-1.3.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2b2ef636a6a25fe7f3d5a064bea0116b74a4c8c7df9646b17dc7386c439a26cf"},
|
||||||
{file = "setproctitle-1.3.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1b1d2628ac9868f960d7e87b3a9b2bb337104c3644b699e52e01efd7e106e4fe"},
|
{file = "setproctitle-1.3.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:28b8614de08679ae95bc4e8d6daaef6b61afdf027fa0d23bf13d619000286b3c"},
|
||||||
{file = "setproctitle-1.3.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fa912c4d08c66afda30dd5af8f2e9c59065dfc36a51edbd5419c3a7c962875aa"},
|
{file = "setproctitle-1.3.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:24f3c8be826a7d44181eac2269b15b748b76d98cd9a539d4c69f09321dcb5c12"},
|
||||||
{file = "setproctitle-1.3.5-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc4f783e100f8b451cd92fcabd3b831edfb1f7cb02be4a79b972f138e0001885"},
|
{file = "setproctitle-1.3.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc9d79b1bf833af63b7c720a6604eb16453ac1ad4e718eb8b59d1f97d986b98c"},
|
||||||
{file = "setproctitle-1.3.5-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:8ca56e39d10b6758046694a84950e5c5570a034c409ef3337595f64fc2cfa94d"},
|
{file = "setproctitle-1.3.4-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:fb693000b65842c85356b667d057ae0d0bac6519feca7e1c437cc2cfeb0afc59"},
|
||||||
{file = "setproctitle-1.3.5-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:8915d69260ba6a6aaf9a48f6b53dbf9f8e4dc0cb4ae25bc5edb16a1666b6e47c"},
|
{file = "setproctitle-1.3.4-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:a166251b8fbc6f2755e2ce9d3c11e9edb0c0c7d2ed723658ff0161fbce26ac1c"},
|
||||||
{file = "setproctitle-1.3.5-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:7edd4fbb9fd17ed0e5a7f8bde9fa61c3987a34372084c45bab4eab6a2e554762"},
|
{file = "setproctitle-1.3.4-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:0361428e6378911a378841509c56ba472d991cbed1a7e3078ec0cacc103da44a"},
|
||||||
{file = "setproctitle-1.3.5-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:d0b19fd76d46b8096a463724739c3b09cf5ce38317f559f56f424f6ce7158de3"},
|
{file = "setproctitle-1.3.4-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:62d66e0423e3bd520b4c897063506b309843a8d07343fbfad04197e91a4edd28"},
|
||||||
{file = "setproctitle-1.3.5-cp38-cp38-win32.whl", hash = "sha256:53ce572cdbd43a0bed2aa24299cd823ebf233a7fa720cc7f8634728c213679c0"},
|
{file = "setproctitle-1.3.4-cp38-cp38-win32.whl", hash = "sha256:5edd01909348f3b0b2da329836d6b5419cd4869fec2e118e8ff3275b38af6267"},
|
||||||
{file = "setproctitle-1.3.5-cp38-cp38-win_amd64.whl", hash = "sha256:a58f00f35d6038ce1e8a9e5f87cb5ecce13ce118c5977a603566ad1fccc8d2cb"},
|
{file = "setproctitle-1.3.4-cp38-cp38-win_amd64.whl", hash = "sha256:59e0dda9ad245921af0328035a961767026e1fa94bb65957ab0db0a0491325d6"},
|
||||||
{file = "setproctitle-1.3.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c4b299b5bbadf00034978b8d741c85af25173146747eb9dab22596ec805a52d6"},
|
{file = "setproctitle-1.3.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:bdaaa81a6e95a0a19fba0285f10577377f3503ae4e9988b403feba79da3e2f80"},
|
||||||
{file = "setproctitle-1.3.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d57e7626329d4fb138da5ce15270b08a91326969956fb19c7a8fec2639066704"},
|
{file = "setproctitle-1.3.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ee5b19a2d794463bcc19153dfceede7beec784b4cf7967dec0bc0fc212ab3a3"},
|
||||||
{file = "setproctitle-1.3.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4272295721cf1fd2acf960b674d6dc09bec87f2a1e48995817b4ec4a3d483faf"},
|
{file = "setproctitle-1.3.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3058a1bb0c767b3a6ccbb38b27ef870af819923eb732e21e44a3f300370fe159"},
|
||||||
{file = "setproctitle-1.3.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f8305b6e6c203222c61318f338f1de08269ec66c247bf251593c215ff1fbeaf9"},
|
{file = "setproctitle-1.3.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5a97d37ee4fe0d1c6e87d2a97229c27a88787a8f4ebfbdeee95f91b818e52efe"},
|
||||||
{file = "setproctitle-1.3.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:becc9f3f605936506d2bd63d9cf817b7ee66b10d204184c4a633064dbed579d6"},
|
{file = "setproctitle-1.3.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e61dd7d05da11fc69bb86d51f1e0ee08f74dccf3ecf884c94de41135ffdc75d"},
|
||||||
{file = "setproctitle-1.3.5-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4629de80c47155a26e8d87a0a92d9428aa8d79ccfe2c20fd18888580619704e1"},
|
{file = "setproctitle-1.3.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1eb115d53dc2a1299ae72f1119c96a556db36073bacb6da40c47ece5db0d9587"},
|
||||||
{file = "setproctitle-1.3.5-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:f1af1d310b5b6cda692da52bd862a9833086c0a3f8380fa92505dd23857dcf60"},
|
{file = "setproctitle-1.3.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:342570716e2647a51ea859b8a9126da9dc1a96a0153c9c0a3514effd60ab57ad"},
|
||||||
{file = "setproctitle-1.3.5-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3bb6ea3d6e690677619508050bc681d86223723bdf67e4e8a8dffc3d04ca3044"},
|
{file = "setproctitle-1.3.4-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:0ad212ae2b03951367a69584af034579b34e1e4199a75d377ef9f8e08ee299b1"},
|
||||||
{file = "setproctitle-1.3.5-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:322067ef1ffe70d297b00bee8a3862fed96021aa4318e3bce2d7c3bfa7a8d1e7"},
|
{file = "setproctitle-1.3.4-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:4afcb38e22122465013f4621b7e9ff8d42a7a48ae0ffeb94133a806cb91b4aad"},
|
||||||
{file = "setproctitle-1.3.5-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:1b58d49c32a46c48dcc2812635a89e6bee31139b03818da49a0bbaeaf01edef9"},
|
{file = "setproctitle-1.3.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:30bb223e6c3f95ad9e9bb2a113292759e947d1cfd60dbd4adb55851c370006b2"},
|
||||||
{file = "setproctitle-1.3.5-cp39-cp39-win32.whl", hash = "sha256:707c23d4a88f5e66f1005d93558bf84eb45fc0fb0c4f33480a0c7d0895e8e848"},
|
{file = "setproctitle-1.3.4-cp39-cp39-win32.whl", hash = "sha256:5f0521ed3bb9f02e9486573ea95e2062cd6bf036fa44e640bd54a06f22d85f35"},
|
||||||
{file = "setproctitle-1.3.5-cp39-cp39-win_amd64.whl", hash = "sha256:c64199a73d442a06d372b5286942229a43e86fa41bf36f317dcc60c036aff0bb"},
|
{file = "setproctitle-1.3.4-cp39-cp39-win_amd64.whl", hash = "sha256:0baadeb27f9e97e65922b4151f818b19c311d30b9efdb62af0e53b3db4006ce2"},
|
||||||
{file = "setproctitle-1.3.5-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:dc66b84beb0d5eb03abf0c3140c6d2cbe3d67ae9f0824a09dfa8c6ff164319a6"},
|
{file = "setproctitle-1.3.4-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:939d364a187b2adfbf6ae488664277e717d56c7951a4ddeb4f23b281bc50bfe5"},
|
||||||
{file = "setproctitle-1.3.5-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:31dc9b330e7cac7685bdef790747c07914081c11ee1066eb0c597303dfb52010"},
|
{file = "setproctitle-1.3.4-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cb8a6a19be0cbf6da6fcbf3698b76c8af03fe83e4bd77c96c3922be3b88bf7da"},
|
||||||
{file = "setproctitle-1.3.5-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4028639b511f5e641d116b3b54ad70c637ebd1b4baac0948283daf11b104119f"},
|
{file = "setproctitle-1.3.4-pp310-pypy310_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:779006f9e1aade9522a40e8d9635115ab15dd82b7af8e655967162e9c01e2573"},
|
||||||
{file = "setproctitle-1.3.5-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:6bddef4e27d0ed74e44b58bf050bc3108591bf17d20d461fc59cd141282f849c"},
|
{file = "setproctitle-1.3.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5519f2a7b8c535b0f1f77b30441476571373add72008230c81211ee17b423b57"},
|
||||||
{file = "setproctitle-1.3.5-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:9996be1d1df399c3cdc6d72ce0064e46bc74fc6e29fe16a328511a303dd4d418"},
|
{file = "setproctitle-1.3.4-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:743836d484151334ebba1490d6907ca9e718fe815dcd5756f2a01bc3067d099c"},
|
||||||
{file = "setproctitle-1.3.5-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5cefc2dbdc48121022c3c05644cd3706f08e0b3c0ce07814d3c04daba0617936"},
|
{file = "setproctitle-1.3.4-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:abda20aff8d1751e48d7967fa8945fef38536b82366c49be39b83678d4be3893"},
|
||||||
{file = "setproctitle-1.3.5-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cef63879c79a570aabf7c158f453bf8d1285f0fda4b6b9b7a52d64b49c084d40"},
|
{file = "setproctitle-1.3.4-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1a2041b5788ce52f218b5be94af458e04470f997ab46fdebd57cf0b8374cc20e"},
|
||||||
{file = "setproctitle-1.3.5-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:a863296a31fb578726c570314cb78ff3a3fddb65963dc01ea33731760f20a92c"},
|
{file = "setproctitle-1.3.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:2c3b1ce68746557aa6e6f4547e76883925cdc7f8d7c7a9f518acd203f1265ca5"},
|
||||||
{file = "setproctitle-1.3.5-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:b63bda3cb4b6526720dc7c6940b891c593f41771d119aeb8763875801ce2296d"},
|
{file = "setproctitle-1.3.4-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:0b6a4cbabf024cb263a45bdef425760f14470247ff223f0ec51699ca9046c0fe"},
|
||||||
{file = "setproctitle-1.3.5-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:95913af603da5b4c7635bf1fb67ecc5df7c18360b6cfb6740fd743bb150a6e17"},
|
{file = "setproctitle-1.3.4-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3e55d7ecc68bdc80de5a553691a3ed260395d5362c19a266cf83cbb4e046551f"},
|
||||||
{file = "setproctitle-1.3.5-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36b130cf8fe76dc05ad1d48cc9ff3699eb1f0d8edbf6f46a3ce46a7041e49d7b"},
|
{file = "setproctitle-1.3.4-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:02ca3802902d91a89957f79da3ec44b25b5804c88026362cb85eea7c1fbdefd1"},
|
||||||
{file = "setproctitle-1.3.5-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:fe3bfd5e51c24349d022e062a96c316a1b8862ea9a0cf5ea2a8b2ae008b77cec"},
|
{file = "setproctitle-1.3.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:47669fc8ed8b27baa2d698104732234b5389f6a59c37c046f6bcbf9150f7a94e"},
|
||||||
{file = "setproctitle-1.3.5.tar.gz", hash = "sha256:1e6eaeaf8a734d428a95d8c104643b39af7d247d604f40a7bebcf3960a853c5e"},
|
{file = "setproctitle-1.3.4.tar.gz", hash = "sha256:3b40d32a3e1f04e94231ed6dfee0da9e43b4f9c6b5450d53e6dd7754c34e0c50"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
@ -5121,14 +5118,14 @@ pbr = ">=2.0.0,<2.1.0 || >2.1.0"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "structlog"
|
name = "structlog"
|
||||||
version = "25.2.0"
|
version = "25.1.0"
|
||||||
description = "Structured Logging for Python"
|
description = "Structured Logging for Python"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.8"
|
python-versions = ">=3.8"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
files = [
|
files = [
|
||||||
{file = "structlog-25.2.0-py3-none-any.whl", hash = "sha256:0fecea2e345d5d491b72f3db2e5fcd6393abfc8cd06a4851f21fcd4d1a99f437"},
|
{file = "structlog-25.1.0-py3-none-any.whl", hash = "sha256:843fe4f254540329f380812cbe612e1af5ec5b8172205ae634679cd35a6d6321"},
|
||||||
{file = "structlog-25.2.0.tar.gz", hash = "sha256:d9f9776944207d1035b8b26072b9b140c63702fd7aa57c2f85d28ab701bd8e92"},
|
{file = "structlog-25.1.0.tar.gz", hash = "sha256:2ef2a572e0e27f09664965d31a576afe64e46ac6084ef5cec3c2b8cd6e4e3ad3"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
@ -5229,14 +5226,14 @@ wsproto = ">=0.14"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "twilio"
|
name = "twilio"
|
||||||
version = "9.5.0"
|
version = "9.4.5"
|
||||||
description = "Twilio API client and TwiML generator"
|
description = "Twilio API client and TwiML generator"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.7.0"
|
python-versions = ">=3.7.0"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
files = [
|
files = [
|
||||||
{file = "twilio-9.5.0-py2.py3-none-any.whl", hash = "sha256:e6d0ccf9162a83acfa6d21a02e90a22fdbc53f4269be3402ba579f13b2a259fc"},
|
{file = "twilio-9.4.5-py2.py3-none-any.whl", hash = "sha256:284295946a5dcdaae65de9116c35db9065e1f3bd237d81da05b89fe1825013c6"},
|
||||||
{file = "twilio-9.5.0.tar.gz", hash = "sha256:633d213c21b394297a27a92f20498adb1c4cd2f6fc3f4e2bfcc7d787b29fc034"},
|
{file = "twilio-9.4.5.tar.gz", hash = "sha256:8db69103a850cd05aaaa6bfb6952ef7a5d784aaff83f01d9a0c594b5ce784cd1"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
@ -5650,21 +5647,21 @@ files = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webauthn"
|
name = "webauthn"
|
||||||
version = "2.5.2"
|
version = "2.5.1"
|
||||||
description = "Pythonic WebAuthn"
|
description = "Pythonic WebAuthn"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
files = [
|
files = [
|
||||||
{file = "webauthn-2.5.2-py3-none-any.whl", hash = "sha256:44246e496e617eb5e2f51165046b9f0197fcdf470f69cd6734061a27ba365f8e"},
|
{file = "webauthn-2.5.1-py3-none-any.whl", hash = "sha256:86d1faa11ec26ebe49b9388d8c3d09bff4dca6c23d3c7e2dd066e99896d694f0"},
|
||||||
{file = "webauthn-2.5.2.tar.gz", hash = "sha256:09c13dfc1c68c810f32fa4d89b1d37acb9f9ae9091c9d7019e313be4525a95ef"},
|
{file = "webauthn-2.5.1.tar.gz", hash = "sha256:f1b7447bae1056e110a9e71ff287f639d05d4d14589911d75fea255c3a03aff0"},
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.dependencies]
|
[package.dependencies]
|
||||||
asn1crypto = ">=1.5.1"
|
asn1crypto = ">=1.5.1"
|
||||||
cbor2 = ">=5.6.5"
|
cbor2 = ">=5.6.5"
|
||||||
cryptography = ">=44.0.2"
|
cryptography = ">=43.0.3"
|
||||||
pyOpenSSL = ">=25.0.0"
|
pyOpenSSL = ">=24.2.1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "websocket-client"
|
name = "websocket-client"
|
||||||
@ -6104,17 +6101,16 @@ testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"]
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zxcvbn"
|
name = "zxcvbn"
|
||||||
version = "4.5.0"
|
version = "4.4.28"
|
||||||
description = ""
|
description = ""
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = "*"
|
python-versions = "*"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
files = [
|
files = [
|
||||||
{file = "zxcvbn-4.5.0-py2.py3-none-any.whl", hash = "sha256:2b6eed621612ce6d65e6e4c7455b966acee87d0280e257956b1f06ccc66bd5ff"},
|
{file = "zxcvbn-4.4.28.tar.gz", hash = "sha256:151bd816817e645e9064c354b13544f85137ea3320ca3be1fb6873ea75ef7dc1"},
|
||||||
{file = "zxcvbn-4.5.0.tar.gz", hash = "sha256:70392c0fff39459d7f55d0211151401e79e76fcc6e2c22b61add62900359c7c1"},
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.1"
|
lock-version = "2.1"
|
||||||
python-versions = "~3.12"
|
python-versions = "~3.12"
|
||||||
content-hash = "8a6bfd4833e415a9f4f613ab4f33e60c8332b9f5743583222cdb7190f6286216"
|
content-hash = "f6b99547f6fdf01390c12a8fb04331935ea4f67a1a1500b1d23b08c3b426787d"
|
||||||
|
@ -1,35 +1,9 @@
|
|||||||
[tool.poetry]
|
[tool.poetry]
|
||||||
name = "authentik"
|
name = "authentik"
|
||||||
version = "2025.2.1"
|
version = "2025.2.4"
|
||||||
description = ""
|
description = ""
|
||||||
authors = ["authentik Team <hello@goauthentik.io>"]
|
authors = ["authentik Team <hello@goauthentik.io>"]
|
||||||
|
|
||||||
[tool.bandit]
|
|
||||||
exclude_dirs = ["**/node_modules/**"]
|
|
||||||
|
|
||||||
[tool.codespell]
|
|
||||||
skip = [
|
|
||||||
"**/node_modules",
|
|
||||||
"**/package-lock.json",
|
|
||||||
"schema.yml",
|
|
||||||
"unittest.xml",
|
|
||||||
"./blueprints/schema.json",
|
|
||||||
"go.sum",
|
|
||||||
"locale",
|
|
||||||
"**/dist",
|
|
||||||
"**/storybook-static",
|
|
||||||
"**/web/src/locales",
|
|
||||||
"**/web/xliff",
|
|
||||||
"./web/storybook-static",
|
|
||||||
"./website/build",
|
|
||||||
"./gen-ts-api",
|
|
||||||
"./gen-py-api",
|
|
||||||
"./gen-go-api",
|
|
||||||
"*.api.mdx",
|
|
||||||
"./htmlcov",
|
|
||||||
]
|
|
||||||
dictionary = ".github/codespell-dictionary.txt,-"
|
|
||||||
ignore-words = ".github/codespell-words.txt"
|
|
||||||
[tool.black]
|
[tool.black]
|
||||||
line-length = 100
|
line-length = 100
|
||||||
target-version = ['py312']
|
target-version = ['py312']
|
||||||
@ -149,9 +123,7 @@ kubernetes = "*"
|
|||||||
ldap3 = "*"
|
ldap3 = "*"
|
||||||
lxml = "*"
|
lxml = "*"
|
||||||
msgraph-sdk = "*"
|
msgraph-sdk = "*"
|
||||||
opencontainers = { git = "https://github.com/vsoch/oci-python", rev = "20d69d9cc50a0fef31605b46f06da0c94f1ec3cf", extras = [
|
opencontainers = { git = "https://github.com/BeryJu/oci-python", rev = "c791b19056769cd67957322806809ab70f5bead8", extras = ["reggie"] }
|
||||||
"reggie",
|
|
||||||
] }
|
|
||||||
packaging = "*"
|
packaging = "*"
|
||||||
paramiko = "*"
|
paramiko = "*"
|
||||||
psycopg = { extras = ["c"], version = "*" }
|
psycopg = { extras = ["c"], version = "*" }
|
||||||
|
84
schema.yml
84
schema.yml
@ -1,7 +1,7 @@
|
|||||||
openapi: 3.0.3
|
openapi: 3.0.3
|
||||||
info:
|
info:
|
||||||
title: authentik
|
title: authentik
|
||||||
version: 2025.2.1
|
version: 2025.2.4
|
||||||
description: Making authentication simple.
|
description: Making authentication simple.
|
||||||
contact:
|
contact:
|
||||||
email: hello@goauthentik.io
|
email: hello@goauthentik.io
|
||||||
@ -35146,7 +35146,7 @@ paths:
|
|||||||
- in: query
|
- in: query
|
||||||
name: token_expiry
|
name: token_expiry
|
||||||
schema:
|
schema:
|
||||||
type: string
|
type: integer
|
||||||
- in: query
|
- in: query
|
||||||
name: use_global_settings
|
name: use_global_settings
|
||||||
schema:
|
schema:
|
||||||
@ -41582,12 +41582,6 @@ components:
|
|||||||
- confidential
|
- confidential
|
||||||
- public
|
- public
|
||||||
type: string
|
type: string
|
||||||
CompatibilityModeEnum:
|
|
||||||
enum:
|
|
||||||
- default
|
|
||||||
- aws
|
|
||||||
- slack
|
|
||||||
type: string
|
|
||||||
Config:
|
Config:
|
||||||
type: object
|
type: object
|
||||||
description: Serialize authentik Config into DRF Object
|
description: Serialize authentik Config into DRF Object
|
||||||
@ -42780,8 +42774,10 @@ components:
|
|||||||
format: email
|
format: email
|
||||||
maxLength: 254
|
maxLength: 254
|
||||||
token_expiry:
|
token_expiry:
|
||||||
type: string
|
type: integer
|
||||||
description: 'Time the token sent is valid (Format: hours=3,minutes=17,seconds=300).'
|
maximum: 2147483647
|
||||||
|
minimum: -2147483648
|
||||||
|
description: Time in minutes the token sent is valid.
|
||||||
subject:
|
subject:
|
||||||
type: string
|
type: string
|
||||||
template:
|
template:
|
||||||
@ -42837,9 +42833,10 @@ components:
|
|||||||
minLength: 1
|
minLength: 1
|
||||||
maxLength: 254
|
maxLength: 254
|
||||||
token_expiry:
|
token_expiry:
|
||||||
type: string
|
type: integer
|
||||||
minLength: 1
|
maximum: 2147483647
|
||||||
description: 'Time the token sent is valid (Format: hours=3,minutes=17,seconds=300).'
|
minimum: -2147483648
|
||||||
|
description: Time in minutes the token sent is valid.
|
||||||
subject:
|
subject:
|
||||||
type: string
|
type: string
|
||||||
minLength: 1
|
minLength: 1
|
||||||
@ -44157,10 +44154,6 @@ components:
|
|||||||
$ref: '#/components/schemas/OutgoingSyncDeleteAction'
|
$ref: '#/components/schemas/OutgoingSyncDeleteAction'
|
||||||
default_group_email_domain:
|
default_group_email_domain:
|
||||||
type: string
|
type: string
|
||||||
dry_run:
|
|
||||||
type: boolean
|
|
||||||
description: When enabled, provider will not modify or create objects in
|
|
||||||
the remote system.
|
|
||||||
required:
|
required:
|
||||||
- assigned_backchannel_application_name
|
- assigned_backchannel_application_name
|
||||||
- assigned_backchannel_application_slug
|
- assigned_backchannel_application_slug
|
||||||
@ -44324,10 +44317,6 @@ components:
|
|||||||
default_group_email_domain:
|
default_group_email_domain:
|
||||||
type: string
|
type: string
|
||||||
minLength: 1
|
minLength: 1
|
||||||
dry_run:
|
|
||||||
type: boolean
|
|
||||||
description: When enabled, provider will not modify or create objects in
|
|
||||||
the remote system.
|
|
||||||
required:
|
required:
|
||||||
- credentials
|
- credentials
|
||||||
- default_group_email_domain
|
- default_group_email_domain
|
||||||
@ -46408,10 +46397,6 @@ components:
|
|||||||
$ref: '#/components/schemas/OutgoingSyncDeleteAction'
|
$ref: '#/components/schemas/OutgoingSyncDeleteAction'
|
||||||
group_delete_action:
|
group_delete_action:
|
||||||
$ref: '#/components/schemas/OutgoingSyncDeleteAction'
|
$ref: '#/components/schemas/OutgoingSyncDeleteAction'
|
||||||
dry_run:
|
|
||||||
type: boolean
|
|
||||||
description: When enabled, provider will not modify or create objects in
|
|
||||||
the remote system.
|
|
||||||
required:
|
required:
|
||||||
- assigned_backchannel_application_name
|
- assigned_backchannel_application_name
|
||||||
- assigned_backchannel_application_slug
|
- assigned_backchannel_application_slug
|
||||||
@ -46572,10 +46557,6 @@ components:
|
|||||||
$ref: '#/components/schemas/OutgoingSyncDeleteAction'
|
$ref: '#/components/schemas/OutgoingSyncDeleteAction'
|
||||||
group_delete_action:
|
group_delete_action:
|
||||||
$ref: '#/components/schemas/OutgoingSyncDeleteAction'
|
$ref: '#/components/schemas/OutgoingSyncDeleteAction'
|
||||||
dry_run:
|
|
||||||
type: boolean
|
|
||||||
description: When enabled, provider will not modify or create objects in
|
|
||||||
the remote system.
|
|
||||||
required:
|
required:
|
||||||
- client_id
|
- client_id
|
||||||
- client_secret
|
- client_secret
|
||||||
@ -50392,9 +50373,10 @@ components:
|
|||||||
minLength: 1
|
minLength: 1
|
||||||
maxLength: 254
|
maxLength: 254
|
||||||
token_expiry:
|
token_expiry:
|
||||||
type: string
|
type: integer
|
||||||
minLength: 1
|
maximum: 2147483647
|
||||||
description: 'Time the token sent is valid (Format: hours=3,minutes=17,seconds=300).'
|
minimum: -2147483648
|
||||||
|
description: Time in minutes the token sent is valid.
|
||||||
subject:
|
subject:
|
||||||
type: string
|
type: string
|
||||||
minLength: 1
|
minLength: 1
|
||||||
@ -50697,10 +50679,6 @@ components:
|
|||||||
default_group_email_domain:
|
default_group_email_domain:
|
||||||
type: string
|
type: string
|
||||||
minLength: 1
|
minLength: 1
|
||||||
dry_run:
|
|
||||||
type: boolean
|
|
||||||
description: When enabled, provider will not modify or create objects in
|
|
||||||
the remote system.
|
|
||||||
PatchedGroupKerberosSourceConnectionRequest:
|
PatchedGroupKerberosSourceConnectionRequest:
|
||||||
type: object
|
type: object
|
||||||
description: OAuth Group-Source connection Serializer
|
description: OAuth Group-Source connection Serializer
|
||||||
@ -51282,10 +51260,6 @@ components:
|
|||||||
$ref: '#/components/schemas/OutgoingSyncDeleteAction'
|
$ref: '#/components/schemas/OutgoingSyncDeleteAction'
|
||||||
group_delete_action:
|
group_delete_action:
|
||||||
$ref: '#/components/schemas/OutgoingSyncDeleteAction'
|
$ref: '#/components/schemas/OutgoingSyncDeleteAction'
|
||||||
dry_run:
|
|
||||||
type: boolean
|
|
||||||
description: When enabled, provider will not modify or create objects in
|
|
||||||
the remote system.
|
|
||||||
PatchedNotificationRequest:
|
PatchedNotificationRequest:
|
||||||
type: object
|
type: object
|
||||||
description: Notification Serializer
|
description: Notification Serializer
|
||||||
@ -52447,21 +52421,12 @@ components:
|
|||||||
type: string
|
type: string
|
||||||
minLength: 1
|
minLength: 1
|
||||||
description: Authentication token
|
description: Authentication token
|
||||||
compatibility_mode:
|
|
||||||
allOf:
|
|
||||||
- $ref: '#/components/schemas/CompatibilityModeEnum'
|
|
||||||
title: SCIM Compatibility Mode
|
|
||||||
description: Alter authentik behavior for vendor-specific SCIM implementations.
|
|
||||||
exclude_users_service_account:
|
exclude_users_service_account:
|
||||||
type: boolean
|
type: boolean
|
||||||
filter_group:
|
filter_group:
|
||||||
type: string
|
type: string
|
||||||
format: uuid
|
format: uuid
|
||||||
nullable: true
|
nullable: true
|
||||||
dry_run:
|
|
||||||
type: boolean
|
|
||||||
description: When enabled, provider will not modify or create objects in
|
|
||||||
the remote system.
|
|
||||||
PatchedSCIMSourceGroupRequest:
|
PatchedSCIMSourceGroupRequest:
|
||||||
type: object
|
type: object
|
||||||
description: SCIMSourceGroup Serializer
|
description: SCIMSourceGroup Serializer
|
||||||
@ -55852,21 +55817,12 @@ components:
|
|||||||
token:
|
token:
|
||||||
type: string
|
type: string
|
||||||
description: Authentication token
|
description: Authentication token
|
||||||
compatibility_mode:
|
|
||||||
allOf:
|
|
||||||
- $ref: '#/components/schemas/CompatibilityModeEnum'
|
|
||||||
title: SCIM Compatibility Mode
|
|
||||||
description: Alter authentik behavior for vendor-specific SCIM implementations.
|
|
||||||
exclude_users_service_account:
|
exclude_users_service_account:
|
||||||
type: boolean
|
type: boolean
|
||||||
filter_group:
|
filter_group:
|
||||||
type: string
|
type: string
|
||||||
format: uuid
|
format: uuid
|
||||||
nullable: true
|
nullable: true
|
||||||
dry_run:
|
|
||||||
type: boolean
|
|
||||||
description: When enabled, provider will not modify or create objects in
|
|
||||||
the remote system.
|
|
||||||
required:
|
required:
|
||||||
- assigned_backchannel_application_name
|
- assigned_backchannel_application_name
|
||||||
- assigned_backchannel_application_slug
|
- assigned_backchannel_application_slug
|
||||||
@ -55947,21 +55903,12 @@ components:
|
|||||||
type: string
|
type: string
|
||||||
minLength: 1
|
minLength: 1
|
||||||
description: Authentication token
|
description: Authentication token
|
||||||
compatibility_mode:
|
|
||||||
allOf:
|
|
||||||
- $ref: '#/components/schemas/CompatibilityModeEnum'
|
|
||||||
title: SCIM Compatibility Mode
|
|
||||||
description: Alter authentik behavior for vendor-specific SCIM implementations.
|
|
||||||
exclude_users_service_account:
|
exclude_users_service_account:
|
||||||
type: boolean
|
type: boolean
|
||||||
filter_group:
|
filter_group:
|
||||||
type: string
|
type: string
|
||||||
format: uuid
|
format: uuid
|
||||||
nullable: true
|
nullable: true
|
||||||
dry_run:
|
|
||||||
type: boolean
|
|
||||||
description: When enabled, provider will not modify or create objects in
|
|
||||||
the remote system.
|
|
||||||
required:
|
required:
|
||||||
- name
|
- name
|
||||||
- token
|
- token
|
||||||
@ -57158,9 +57105,6 @@ components:
|
|||||||
sync_object_id:
|
sync_object_id:
|
||||||
type: string
|
type: string
|
||||||
minLength: 1
|
minLength: 1
|
||||||
override_dry_run:
|
|
||||||
type: boolean
|
|
||||||
default: false
|
|
||||||
required:
|
required:
|
||||||
- sync_object_id
|
- sync_object_id
|
||||||
- sync_object_model
|
- sync_object_model
|
||||||
|
@ -4,7 +4,7 @@ This package provides a generated API Client for [authentik](https://goauthentik
|
|||||||
|
|
||||||
### Building
|
### Building
|
||||||
|
|
||||||
See https://docs.goauthentik.io/docs/developer-docs/api/making-schema-changes#building-the-web-client
|
See https://docs.goauthentik.io/docs/developer-docs/making-schema-changes
|
||||||
|
|
||||||
### Consuming
|
### Consuming
|
||||||
|
|
||||||
|
1
scripts/generate_config.py
Executable file → Normal file
1
scripts/generate_config.py
Executable file → Normal file
@ -1,4 +1,3 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
"""Generate config for development"""
|
"""Generate config for development"""
|
||||||
|
|
||||||
from yaml import safe_dump
|
from yaml import safe_dump
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
#!/usr/bin/env python3
|
|
||||||
"""
|
|
||||||
Generates a Semantic Versioning identifier, suffixed with a timestamp.
|
|
||||||
"""
|
|
||||||
|
|
||||||
from time import time
|
|
||||||
|
|
||||||
from authentik import __version__ as package_version
|
|
||||||
|
|
||||||
"""
|
|
||||||
See: https://semver.org/#spec-item-9 (Pre-release spec)
|
|
||||||
"""
|
|
||||||
pre_release_timestamp = int(time())
|
|
||||||
|
|
||||||
print(f"{package_version}-{pre_release_timestamp}")
|
|
7
scripts/npm_version.py
Normal file
7
scripts/npm_version.py
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
"""Helper script to generate an NPM Version"""
|
||||||
|
|
||||||
|
from time import time
|
||||||
|
|
||||||
|
from authentik import __version__
|
||||||
|
|
||||||
|
print(f"{__version__}-{int(time())}")
|
@ -1,141 +0,0 @@
|
|||||||
import * as http from "http";
|
|
||||||
import path from "path";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Serializes a custom event to a text stream.
|
|
||||||
* a
|
|
||||||
* @param {Event} event
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
export function serializeCustomEventToStream(event) {
|
|
||||||
// @ts-ignore
|
|
||||||
const data = event.detail ?? {};
|
|
||||||
|
|
||||||
const eventContent = [`event: ${event.type}`, `data: ${JSON.stringify(data)}`];
|
|
||||||
|
|
||||||
return eventContent.join("\n") + "\n\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Options for the build observer plugin.
|
|
||||||
*
|
|
||||||
* @typedef {Object} BuildObserverOptions
|
|
||||||
*
|
|
||||||
* @property {URL} serverURL
|
|
||||||
* @property {string} logPrefix
|
|
||||||
* @property {string} relativeRoot
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a plugin that listens for build events and sends them to a server-sent event stream.
|
|
||||||
*
|
|
||||||
* @param {BuildObserverOptions} options
|
|
||||||
* @returns {import('esbuild').Plugin}
|
|
||||||
*/
|
|
||||||
export function buildObserverPlugin({ serverURL, logPrefix, relativeRoot }) {
|
|
||||||
const timerLabel = `[${logPrefix}] Build`;
|
|
||||||
const endpoint = serverURL.pathname;
|
|
||||||
const dispatcher = new EventTarget();
|
|
||||||
|
|
||||||
const eventServer = http.createServer((req, res) => {
|
|
||||||
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
||||||
res.setHeader("Access-Control-Allow-Methods", "GET");
|
|
||||||
res.setHeader("Access-Control-Allow-Headers", "Content-Type");
|
|
||||||
|
|
||||||
if (req.url !== endpoint) {
|
|
||||||
console.log(`🚫 Invalid request to ${req.url}`);
|
|
||||||
res.writeHead(404);
|
|
||||||
res.end();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("🔌 Client connected");
|
|
||||||
|
|
||||||
res.writeHead(200, {
|
|
||||||
"Content-Type": "text/event-stream",
|
|
||||||
"Cache-Control": "no-cache",
|
|
||||||
"Connection": "keep-alive",
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Event} event
|
|
||||||
*/
|
|
||||||
const listener = (event) => {
|
|
||||||
const body = serializeCustomEventToStream(event);
|
|
||||||
|
|
||||||
res.write(body);
|
|
||||||
};
|
|
||||||
|
|
||||||
dispatcher.addEventListener("esbuild:start", listener);
|
|
||||||
dispatcher.addEventListener("esbuild:error", listener);
|
|
||||||
dispatcher.addEventListener("esbuild:end", listener);
|
|
||||||
|
|
||||||
req.on("close", () => {
|
|
||||||
console.log("🔌 Client disconnected");
|
|
||||||
|
|
||||||
clearInterval(keepAliveInterval);
|
|
||||||
|
|
||||||
dispatcher.removeEventListener("esbuild:start", listener);
|
|
||||||
dispatcher.removeEventListener("esbuild:error", listener);
|
|
||||||
dispatcher.removeEventListener("esbuild:end", listener);
|
|
||||||
});
|
|
||||||
|
|
||||||
const keepAliveInterval = setInterval(() => {
|
|
||||||
console.timeStamp("🏓 Keep-alive");
|
|
||||||
|
|
||||||
res.write("event: keep-alive\n\n");
|
|
||||||
res.write(serializeCustomEventToStream(new CustomEvent("esbuild:keep-alive")));
|
|
||||||
}, 15_000);
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
name: "build-watcher",
|
|
||||||
setup: (build) => {
|
|
||||||
eventServer.listen(parseInt(serverURL.port, 10), serverURL.hostname);
|
|
||||||
|
|
||||||
build.onDispose(() => {
|
|
||||||
eventServer.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
build.onStart(() => {
|
|
||||||
console.time(timerLabel);
|
|
||||||
|
|
||||||
dispatcher.dispatchEvent(
|
|
||||||
new CustomEvent("esbuild:start", {
|
|
||||||
detail: new Date().toISOString(),
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
build.onEnd((buildResult) => {
|
|
||||||
console.timeEnd(timerLabel);
|
|
||||||
|
|
||||||
if (!buildResult.errors.length) {
|
|
||||||
dispatcher.dispatchEvent(
|
|
||||||
new CustomEvent("esbuild:end", {
|
|
||||||
detail: new Date().toISOString(),
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.warn(`Build ended with ${buildResult.errors.length} errors`);
|
|
||||||
|
|
||||||
dispatcher.dispatchEvent(
|
|
||||||
new CustomEvent("esbuild:error", {
|
|
||||||
detail: buildResult.errors.map((error) => ({
|
|
||||||
...error,
|
|
||||||
location: error.location
|
|
||||||
? {
|
|
||||||
...error.location,
|
|
||||||
file: path.resolve(relativeRoot, error.location.file),
|
|
||||||
}
|
|
||||||
: null,
|
|
||||||
})),
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
303
web/build.mjs
303
web/build.mjs
@ -1,54 +1,45 @@
|
|||||||
import { execFileSync } from "child_process";
|
import { execFileSync } from "child_process";
|
||||||
|
import * as chokidar from "chokidar";
|
||||||
import esbuild from "esbuild";
|
import esbuild from "esbuild";
|
||||||
import findFreePorts from "find-free-ports";
|
import fs from "fs";
|
||||||
import { copyFileSync, mkdirSync, readFileSync, statSync } from "fs";
|
|
||||||
import { globSync } from "glob";
|
import { globSync } from "glob";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import { cwd } from "process";
|
import { cwd } from "process";
|
||||||
import process from "process";
|
import process from "process";
|
||||||
import { fileURLToPath } from "url";
|
import { fileURLToPath } from "url";
|
||||||
|
|
||||||
import { buildObserverPlugin } from "./build-observer-plugin.mjs";
|
|
||||||
|
|
||||||
const __dirname = fileURLToPath(new URL(".", import.meta.url));
|
const __dirname = fileURLToPath(new URL(".", import.meta.url));
|
||||||
let authentikProjectRoot = __dirname + "../";
|
|
||||||
|
|
||||||
|
let authentikProjectRoot = __dirname + "../";
|
||||||
try {
|
try {
|
||||||
// Use the package.json file in the root folder, as it has the current version information.
|
// Use the package.json file in the root folder, as it has the current version information.
|
||||||
authentikProjectRoot = execFileSync("git", ["rev-parse", "--show-toplevel"], {
|
authentikProjectRoot = execFileSync("git", ["rev-parse", "--show-toplevel"], {
|
||||||
encoding: "utf8",
|
encoding: "utf8",
|
||||||
}).replace("\n", "");
|
}).replace("\n", "");
|
||||||
} catch (_error) {
|
} catch (_exc) {
|
||||||
// We probably don't have a .git folder, which could happen in container builds.
|
// We probably don't have a .git folder, which could happen in container builds
|
||||||
}
|
}
|
||||||
|
const rootPackage = JSON.parse(fs.readFileSync(path.join(authentikProjectRoot, "./package.json")));
|
||||||
|
|
||||||
const packageJSONPath = path.join(authentikProjectRoot, "./package.json");
|
const isProdBuild = process.env.NODE_ENV === "production";
|
||||||
const rootPackage = JSON.parse(readFileSync(packageJSONPath, "utf8"));
|
|
||||||
|
|
||||||
const NODE_ENV = process.env.NODE_ENV || "development";
|
const apiBasePath = process.env.AK_API_BASE_PATH || "";
|
||||||
const AK_API_BASE_PATH = process.env.AK_API_BASE_PATH || "";
|
|
||||||
|
|
||||||
const environmentVars = new Map([
|
const envGitHashKey = "GIT_BUILD_HASH";
|
||||||
["NODE_ENV", NODE_ENV],
|
|
||||||
["CWD", cwd()],
|
|
||||||
["AK_API_BASE_PATH", AK_API_BASE_PATH],
|
|
||||||
]);
|
|
||||||
|
|
||||||
const definitions = Object.fromEntries(
|
const definitions = {
|
||||||
Array.from(environmentVars).map(([key, value]) => {
|
"process.env.NODE_ENV": JSON.stringify(isProdBuild ? "production" : "development"),
|
||||||
return [`process.env.${key}`, JSON.stringify(value)];
|
"process.env.CWD": JSON.stringify(cwd()),
|
||||||
}),
|
"process.env.AK_API_BASE_PATH": JSON.stringify(apiBasePath),
|
||||||
);
|
};
|
||||||
|
|
||||||
/**
|
// All is magic is just to make sure the assets are copied into the right places. This is a very
|
||||||
* All is magic is just to make sure the assets are copied into the right places. This is a very
|
// stripped down version of what the rollup-copy-plugin does, without any of the features we don't
|
||||||
* stripped down version of what the rollup-copy-plugin does, without any of the features we don't
|
// use, and using globSync instead of globby since we already had globSync lying around thanks to
|
||||||
* use, and using globSync instead of globby since we already had globSync lying around thanks to
|
// Typescript. If there's a third argument in an array entry, it's used to replace the internal path
|
||||||
* Typescript. If there's a third argument in an array entry, it's used to replace the internal path
|
// before concatenating it all together as the destination target.
|
||||||
* before concatenating it all together as the destination target.
|
|
||||||
* @type {Array<[string, string, string?]>}
|
const otherFiles = [
|
||||||
*/
|
|
||||||
const assetsFileMappings = [
|
|
||||||
["node_modules/@patternfly/patternfly/patternfly.min.css", "."],
|
["node_modules/@patternfly/patternfly/patternfly.min.css", "."],
|
||||||
["node_modules/@patternfly/patternfly/assets/**", ".", "node_modules/@patternfly/patternfly/"],
|
["node_modules/@patternfly/patternfly/assets/**", ".", "node_modules/@patternfly/patternfly/"],
|
||||||
["src/custom.css", "."],
|
["src/custom.css", "."],
|
||||||
@ -57,47 +48,28 @@ const assetsFileMappings = [
|
|||||||
["./icons/*", "./assets/icons"],
|
["./icons/*", "./assets/icons"],
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
const isFile = (filePath) => fs.statSync(filePath).isFile();
|
||||||
* @param {string} filePath
|
|
||||||
*/
|
|
||||||
const isFile = (filePath) => statSync(filePath).isFile();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} src Source file
|
|
||||||
* @param {string} dest Destination folder
|
|
||||||
* @param {string} [strip] Path to strip from the source file
|
|
||||||
*/
|
|
||||||
function nameCopyTarget(src, dest, strip) {
|
function nameCopyTarget(src, dest, strip) {
|
||||||
const target = path.join(dest, strip ? src.replace(strip, "") : path.parse(src).base);
|
const target = path.join(dest, strip ? src.replace(strip, "") : path.parse(src).base);
|
||||||
return [src, target];
|
return [src, target];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const [source, rawdest, strip] of assetsFileMappings) {
|
for (const [source, rawdest, strip] of otherFiles) {
|
||||||
const matchedPaths = globSync(source);
|
const matchedPaths = globSync(source);
|
||||||
const dest = path.join("dist", rawdest);
|
const dest = path.join("dist", rawdest);
|
||||||
|
|
||||||
const copyTargets = matchedPaths.map((path) => nameCopyTarget(path, dest, strip));
|
const copyTargets = matchedPaths.map((path) => nameCopyTarget(path, dest, strip));
|
||||||
|
|
||||||
for (const [src, dest] of copyTargets) {
|
for (const [src, dest] of copyTargets) {
|
||||||
if (isFile(src)) {
|
if (isFile(src)) {
|
||||||
mkdirSync(path.dirname(dest), { recursive: true });
|
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
||||||
copyFileSync(src, dest);
|
fs.copyFileSync(src, dest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// This starts the definitions used for esbuild: Our targets, our arguments, the function for
|
||||||
* @typedef {[source: string, destination: string]} EntryPoint
|
// running a build, and three options for building: watching, building, and building the proxy.
|
||||||
*/
|
// Ordered by largest to smallest interface to build even faster
|
||||||
|
const interfaces = [
|
||||||
/**
|
|
||||||
* This starts the definitions used for esbuild: Our targets, our arguments, the function for
|
|
||||||
* running a build, and three options for building: watching, building, and building the proxy.
|
|
||||||
* Ordered by largest to smallest interface to build even faster
|
|
||||||
*
|
|
||||||
* @type {EntryPoint[]}
|
|
||||||
*/
|
|
||||||
const entryPoints = [
|
|
||||||
["admin/AdminInterface/AdminInterface.ts", "admin"],
|
["admin/AdminInterface/AdminInterface.ts", "admin"],
|
||||||
["user/UserInterface.ts", "user"],
|
["user/UserInterface.ts", "user"],
|
||||||
["flow/FlowInterface.ts", "flow"],
|
["flow/FlowInterface.ts", "flow"],
|
||||||
@ -107,26 +79,18 @@ const entryPoints = [
|
|||||||
["polyfill/poly.ts", "."],
|
["polyfill/poly.ts", "."],
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
const baseArgs = {
|
||||||
* @satisfies {import("esbuild").BuildOptions}
|
|
||||||
*/
|
|
||||||
const BASE_ESBUILD_OPTIONS = {
|
|
||||||
bundle: true,
|
bundle: true,
|
||||||
write: true,
|
write: true,
|
||||||
sourcemap: true,
|
sourcemap: true,
|
||||||
minify: NODE_ENV === "production",
|
minify: isProdBuild,
|
||||||
splitting: true,
|
splitting: true,
|
||||||
treeShaking: true,
|
treeShaking: true,
|
||||||
external: ["*.woff", "*.woff2"],
|
external: ["*.woff", "*.woff2"],
|
||||||
tsconfig: "./tsconfig.json",
|
tsconfig: "./tsconfig.json",
|
||||||
loader: {
|
loader: { ".css": "text", ".md": "text" },
|
||||||
".css": "text",
|
|
||||||
".md": "text",
|
|
||||||
".mdx": "text",
|
|
||||||
},
|
|
||||||
define: definitions,
|
define: definitions,
|
||||||
format: "esm",
|
format: "esm",
|
||||||
plugins: [],
|
|
||||||
logOverride: {
|
logOverride: {
|
||||||
/**
|
/**
|
||||||
* HACK: Silences issue originating in ESBuild.
|
* HACK: Silences issue originating in ESBuild.
|
||||||
@ -138,144 +102,91 @@ const BASE_ESBUILD_OPTIONS = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
function getVersion() {
|
||||||
* Creates a version ID for the build.
|
let version = rootPackage.version;
|
||||||
* @returns {string}
|
if (process.env[envGitHashKey]) {
|
||||||
*/
|
version = `${version}+${process.env[envGitHashKey]}`;
|
||||||
function composeVersionID() {
|
|
||||||
const { version } = rootPackage;
|
|
||||||
const buildHash = process.env.GIT_BUILD_HASH;
|
|
||||||
|
|
||||||
if (buildHash) {
|
|
||||||
return `${version}+${buildHash}`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
async function buildOneSource(source, dest) {
|
||||||
* Build a single entry point.
|
const DIST = path.join(__dirname, "./dist", dest);
|
||||||
*
|
console.log(`[${new Date(Date.now()).toISOString()}] Starting build for target ${source}`);
|
||||||
* @param {EntryPoint} buildTarget
|
|
||||||
* @param {Partial<esbuild.BuildOptions>} [overrides]
|
|
||||||
* @throws {Error} on build failure
|
|
||||||
*/
|
|
||||||
function createEntryPointOptions([source, dest], overrides = {}) {
|
|
||||||
const outdir = path.join(__dirname, "./dist", dest);
|
|
||||||
|
|
||||||
return {
|
try {
|
||||||
...BASE_ESBUILD_OPTIONS,
|
const start = Date.now();
|
||||||
|
await esbuild.build({
|
||||||
|
...baseArgs,
|
||||||
entryPoints: [`./src/${source}`],
|
entryPoints: [`./src/${source}`],
|
||||||
entryNames: `[dir]/[name]-${composeVersionID()}`,
|
entryNames: `[dir]/[name]-${getVersion()}`,
|
||||||
outdir,
|
outdir: DIST,
|
||||||
...overrides,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build all entry points in parallel.
|
|
||||||
*
|
|
||||||
* @param {EntryPoint[]} entryPoints
|
|
||||||
*/
|
|
||||||
async function buildParallel(entryPoints) {
|
|
||||||
await Promise.allSettled(
|
|
||||||
entryPoints.map((entryPoint) => {
|
|
||||||
return esbuild.build(createEntryPointOptions(entryPoint));
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function doHelp() {
|
|
||||||
console.log(`Build the authentik UI
|
|
||||||
|
|
||||||
options:
|
|
||||||
-w, --watch: Build all ${entryPoints.length} interfaces
|
|
||||||
-p, --proxy: Build only the polyfills and the loading application
|
|
||||||
-h, --help: This help message
|
|
||||||
`);
|
|
||||||
|
|
||||||
process.exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function doWatch() {
|
|
||||||
console.log("Watching all entry points...");
|
|
||||||
|
|
||||||
const wathcherPorts = await findFreePorts(entryPoints.length);
|
|
||||||
|
|
||||||
const buildContexts = await Promise.all(
|
|
||||||
entryPoints.map((entryPoint, i) => {
|
|
||||||
const port = wathcherPorts[i];
|
|
||||||
const serverURL = new URL(`http://localhost:${port}/events`);
|
|
||||||
|
|
||||||
return esbuild.context(
|
|
||||||
createEntryPointOptions(entryPoint, {
|
|
||||||
plugins: [
|
|
||||||
...BASE_ESBUILD_OPTIONS.plugins,
|
|
||||||
buildObserverPlugin({
|
|
||||||
serverURL,
|
|
||||||
logPrefix: entryPoint[1],
|
|
||||||
relativeRoot: __dirname,
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
define: {
|
|
||||||
...definitions,
|
|
||||||
"process.env.WATCHER_URL": JSON.stringify(serverURL.toString()),
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
|
|
||||||
await Promise.all(buildContexts.map((context) => context.rebuild()));
|
|
||||||
|
|
||||||
await Promise.allSettled(buildContexts.map((context) => context.watch()));
|
|
||||||
|
|
||||||
return /** @type {Promise<void>} */ (
|
|
||||||
new Promise((resolve) => {
|
|
||||||
process.on("SIGINT", () => {
|
|
||||||
resolve();
|
|
||||||
});
|
});
|
||||||
})
|
const end = Date.now();
|
||||||
|
console.log(
|
||||||
|
`[${new Date(end).toISOString()}] Finished build for target ${source} in ${
|
||||||
|
Date.now() - start
|
||||||
|
}ms`,
|
||||||
);
|
);
|
||||||
}
|
return 0;
|
||||||
|
} catch (exc) {
|
||||||
async function doBuild() {
|
console.error(`[${new Date(Date.now()).toISOString()}] Failed to build ${source}: ${exc}`);
|
||||||
console.log("Building all entry points");
|
return 1;
|
||||||
|
|
||||||
return buildParallel(entryPoints);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function doProxy() {
|
|
||||||
return buildParallel(
|
|
||||||
entryPoints.filter(([_, dest]) => ["standalone/loading", "."].includes(dest)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function delegateCommand() {
|
|
||||||
const command = process.argv[2];
|
|
||||||
|
|
||||||
switch (command) {
|
|
||||||
case "-h":
|
|
||||||
case "--help":
|
|
||||||
return doHelp();
|
|
||||||
case "-w":
|
|
||||||
case "--watch":
|
|
||||||
return doWatch();
|
|
||||||
// There's no watch-for-proxy, sorry.
|
|
||||||
case "-p":
|
|
||||||
case "--proxy":
|
|
||||||
return doProxy();
|
|
||||||
default:
|
|
||||||
return doBuild();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await delegateCommand()
|
async function buildAuthentik(interfaces) {
|
||||||
.then(() => {
|
const code = await Promise.allSettled(
|
||||||
console.log("Build complete");
|
interfaces.map(([source, dest]) => buildOneSource(source, dest)),
|
||||||
|
);
|
||||||
|
const finalCode = code.reduce((a, res) => a + res.value, 0);
|
||||||
|
if (finalCode > 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
let timeoutId = null;
|
||||||
|
function debouncedBuild() {
|
||||||
|
if (timeoutId !== null) {
|
||||||
|
clearTimeout(timeoutId);
|
||||||
|
}
|
||||||
|
timeoutId = setTimeout(() => {
|
||||||
|
console.clear();
|
||||||
|
buildAuthentik(interfaces);
|
||||||
|
}, 250);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (process.argv.length > 2 && (process.argv[2] === "-h" || process.argv[2] === "--help")) {
|
||||||
|
console.log(`Build the authentikUI
|
||||||
|
|
||||||
|
options:
|
||||||
|
-w, --watch: Build all ${interfaces.length} interfaces
|
||||||
|
-p, --proxy: Build only the polyfills and the loading application
|
||||||
|
-h, --help: This help message
|
||||||
|
`);
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
})
|
}
|
||||||
.catch((error) => {
|
|
||||||
console.error(error);
|
if (process.argv.length > 2 && (process.argv[2] === "-w" || process.argv[2] === "--watch")) {
|
||||||
process.exit(1);
|
console.log("Watching ./src for changes");
|
||||||
|
chokidar.watch("./src").on("all", (event, path) => {
|
||||||
|
if (!["add", "change", "unlink"].includes(event)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!/(\.css|\.ts|\.js)$/.test(path)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
debouncedBuild();
|
||||||
});
|
});
|
||||||
|
} else if (process.argv.length > 2 && (process.argv[2] === "-p" || process.argv[2] === "--proxy")) {
|
||||||
|
// There's no watch-for-proxy, sorry.
|
||||||
|
process.exit(
|
||||||
|
await buildAuthentik(
|
||||||
|
interfaces.filter(([_, dest]) => ["standalone/loading", "."].includes(dest)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// And the fallback: just build it.
|
||||||
|
process.exit(await buildAuthentik(interfaces));
|
||||||
|
}
|
||||||
|
55
web/package-lock.json
generated
55
web/package-lock.json
generated
@ -23,7 +23,7 @@
|
|||||||
"@floating-ui/dom": "^1.6.11",
|
"@floating-ui/dom": "^1.6.11",
|
||||||
"@formatjs/intl-listformat": "^7.5.7",
|
"@formatjs/intl-listformat": "^7.5.7",
|
||||||
"@fortawesome/fontawesome-free": "^6.6.0",
|
"@fortawesome/fontawesome-free": "^6.6.0",
|
||||||
"@goauthentik/api": "^2025.2.1-1741798605",
|
"@goauthentik/api": "^2024.12.3-1739965710",
|
||||||
"@lit-labs/ssr": "^3.2.2",
|
"@lit-labs/ssr": "^3.2.2",
|
||||||
"@lit/context": "^1.1.2",
|
"@lit/context": "^1.1.2",
|
||||||
"@lit/localize": "^0.12.2",
|
"@lit/localize": "^0.12.2",
|
||||||
@ -37,12 +37,11 @@
|
|||||||
"@webcomponents/webcomponentsjs": "^2.8.0",
|
"@webcomponents/webcomponentsjs": "^2.8.0",
|
||||||
"base64-js": "^1.5.1",
|
"base64-js": "^1.5.1",
|
||||||
"chart.js": "^4.4.4",
|
"chart.js": "^4.4.4",
|
||||||
"chartjs-adapter-date-fns": "^3.0.0",
|
"chartjs-adapter-moment": "^1.0.1",
|
||||||
"codemirror": "^6.0.1",
|
"codemirror": "^6.0.1",
|
||||||
"construct-style-sheets-polyfill": "^3.1.0",
|
"construct-style-sheets-polyfill": "^3.1.0",
|
||||||
"core-js": "^3.38.1",
|
"core-js": "^3.38.1",
|
||||||
"country-flag-icons": "^1.5.13",
|
"country-flag-icons": "^1.5.13",
|
||||||
"date-fns": "^4.1.0",
|
|
||||||
"dompurify": "^3.2.4",
|
"dompurify": "^3.2.4",
|
||||||
"fuse.js": "^7.0.0",
|
"fuse.js": "^7.0.0",
|
||||||
"guacamole-common-js": "^1.5.0",
|
"guacamole-common-js": "^1.5.0",
|
||||||
@ -90,7 +89,6 @@
|
|||||||
"eslint": "^9.11.1",
|
"eslint": "^9.11.1",
|
||||||
"eslint-plugin-lit": "^1.15.0",
|
"eslint-plugin-lit": "^1.15.0",
|
||||||
"eslint-plugin-wc": "^2.1.1",
|
"eslint-plugin-wc": "^2.1.1",
|
||||||
"find-free-ports": "^3.1.1",
|
|
||||||
"github-slugger": "^2.0.0",
|
"github-slugger": "^2.0.0",
|
||||||
"glob": "^11.0.0",
|
"glob": "^11.0.0",
|
||||||
"globals": "^15.10.0",
|
"globals": "^15.10.0",
|
||||||
@ -826,10 +824,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@babel/runtime-corejs3": {
|
"node_modules/@babel/runtime-corejs3": {
|
||||||
"version": "7.26.10",
|
"version": "7.25.7",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.26.10.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.25.7.tgz",
|
||||||
"integrity": "sha512-uITFQYO68pMEYR46AHgQoyBg7KPPJDAbGn4jUTIRgCFJIp88MIBUianVOplhZDEec07bp9zIyr4Kp0FCyQzmWg==",
|
"integrity": "sha512-gMmIEhg35sXk9Te5qbGp3W9YKrvLt3HV658/d3odWrHSqT0JeG5OzsJWFHRLiOohRyjRsJc/x03DhJm3i8VJxg==",
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"core-js-pure": "^3.30.2",
|
"core-js-pure": "^3.30.2",
|
||||||
"regenerator-runtime": "^0.14.0"
|
"regenerator-runtime": "^0.14.0"
|
||||||
@ -1817,9 +1814,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@goauthentik/api": {
|
"node_modules/@goauthentik/api": {
|
||||||
"version": "2025.2.1-1741798605",
|
"version": "2024.12.3-1739965710",
|
||||||
"resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2025.2.1-1741798605.tgz",
|
"resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2024.12.3-1739965710.tgz",
|
||||||
"integrity": "sha512-Go0Iij1q/imohOSqxj43pvju8D+OFH7iNBBg6FO1ytd9pcHi1QY7/jq1vy1HKWZw7oZ2fY6hZnSe+keRnBA0Fg=="
|
"integrity": "sha512-16zoQWeJhAFSwttvqLRoXoQA43tMW1ZXDEihW6r8rtWtlxqPh7n36RtcWYraYiLcjmJskI90zdgz6k1kmY5AXw=="
|
||||||
},
|
},
|
||||||
"node_modules/@goauthentik/web": {
|
"node_modules/@goauthentik/web": {
|
||||||
"resolved": "",
|
"resolved": "",
|
||||||
@ -9534,13 +9531,13 @@
|
|||||||
"pnpm": ">=8"
|
"pnpm": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/chartjs-adapter-date-fns": {
|
"node_modules/chartjs-adapter-moment": {
|
||||||
"version": "3.0.0",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/chartjs-adapter-date-fns/-/chartjs-adapter-date-fns-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/chartjs-adapter-moment/-/chartjs-adapter-moment-1.0.1.tgz",
|
||||||
"integrity": "sha512-Rs3iEB3Q5pJ973J93OBTpnP7qoGwvq3nUnoMdtxO+9aoJof7UFcRbWcIDteXuYd1fgAvct/32T9qaLyLuZVwCg==",
|
"integrity": "sha512-Uz+nTX/GxocuqXpGylxK19YG4R3OSVf8326D+HwSTsNw1LgzyIGRo+Qujwro1wy6X+soNSnfj5t2vZ+r6EaDmA==",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"chart.js": ">=2.8.0",
|
"chart.js": ">=3.0.0",
|
||||||
"date-fns": ">=2.0.0"
|
"moment": "^2.10.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/cheerio": {
|
"node_modules/cheerio": {
|
||||||
@ -10772,15 +10769,6 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/date-fns": {
|
|
||||||
"version": "4.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz",
|
|
||||||
"integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==",
|
|
||||||
"funding": {
|
|
||||||
"type": "github",
|
|
||||||
"url": "https://github.com/sponsors/kossnocorp"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/dayjs": {
|
"node_modules/dayjs": {
|
||||||
"version": "1.11.13",
|
"version": "1.11.13",
|
||||||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz",
|
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz",
|
||||||
@ -12904,13 +12892,6 @@
|
|||||||
"url": "https://github.com/avajs/find-cache-dir?sponsor=1"
|
"url": "https://github.com/avajs/find-cache-dir?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/find-free-ports": {
|
|
||||||
"version": "3.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/find-free-ports/-/find-free-ports-3.1.1.tgz",
|
|
||||||
"integrity": "sha512-hQebewth9i5qkf0a0u06iFaxQssk5ZnPBBggsa1vk8zCYaZoz9IZXpoRLTbEOrYdqfrjvcxU00gYoCPgmXugKA==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/find-up": {
|
"node_modules/find-up": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
|
||||||
@ -16591,7 +16572,6 @@
|
|||||||
"version": "2.30.1",
|
"version": "2.30.1",
|
||||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
|
"resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
|
||||||
"integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==",
|
"integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==",
|
||||||
"dev": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
@ -18235,10 +18215,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/prismjs": {
|
"node_modules/prismjs": {
|
||||||
"version": "1.30.0",
|
"version": "1.29.0",
|
||||||
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz",
|
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz",
|
||||||
"integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==",
|
"integrity": "sha512-Kx/1w86q/epKcmte75LNrEoT+lX8pBpavuAbvJWRXar7Hz8jrtF+e3vY751p0R8H9HdArwaCTNDDzHg/ScJK1Q==",
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
"@floating-ui/dom": "^1.6.11",
|
"@floating-ui/dom": "^1.6.11",
|
||||||
"@formatjs/intl-listformat": "^7.5.7",
|
"@formatjs/intl-listformat": "^7.5.7",
|
||||||
"@fortawesome/fontawesome-free": "^6.6.0",
|
"@fortawesome/fontawesome-free": "^6.6.0",
|
||||||
"@goauthentik/api": "^2025.2.1-1741798605",
|
"@goauthentik/api": "^2024.12.3-1739965710",
|
||||||
"@lit-labs/ssr": "^3.2.2",
|
"@lit-labs/ssr": "^3.2.2",
|
||||||
"@lit/context": "^1.1.2",
|
"@lit/context": "^1.1.2",
|
||||||
"@lit/localize": "^0.12.2",
|
"@lit/localize": "^0.12.2",
|
||||||
@ -25,12 +25,11 @@
|
|||||||
"@webcomponents/webcomponentsjs": "^2.8.0",
|
"@webcomponents/webcomponentsjs": "^2.8.0",
|
||||||
"base64-js": "^1.5.1",
|
"base64-js": "^1.5.1",
|
||||||
"chart.js": "^4.4.4",
|
"chart.js": "^4.4.4",
|
||||||
"chartjs-adapter-date-fns": "^3.0.0",
|
"chartjs-adapter-moment": "^1.0.1",
|
||||||
"codemirror": "^6.0.1",
|
"codemirror": "^6.0.1",
|
||||||
"construct-style-sheets-polyfill": "^3.1.0",
|
"construct-style-sheets-polyfill": "^3.1.0",
|
||||||
"core-js": "^3.38.1",
|
"core-js": "^3.38.1",
|
||||||
"country-flag-icons": "^1.5.13",
|
"country-flag-icons": "^1.5.13",
|
||||||
"date-fns": "^4.1.0",
|
|
||||||
"dompurify": "^3.2.4",
|
"dompurify": "^3.2.4",
|
||||||
"fuse.js": "^7.0.0",
|
"fuse.js": "^7.0.0",
|
||||||
"guacamole-common-js": "^1.5.0",
|
"guacamole-common-js": "^1.5.0",
|
||||||
@ -78,7 +77,6 @@
|
|||||||
"eslint": "^9.11.1",
|
"eslint": "^9.11.1",
|
||||||
"eslint-plugin-lit": "^1.15.0",
|
"eslint-plugin-lit": "^1.15.0",
|
||||||
"eslint-plugin-wc": "^2.1.1",
|
"eslint-plugin-wc": "^2.1.1",
|
||||||
"find-free-ports": "^3.1.1",
|
|
||||||
"github-slugger": "^2.0.0",
|
"github-slugger": "^2.0.0",
|
||||||
"glob": "^11.0.0",
|
"glob": "^11.0.0",
|
||||||
"globals": "^15.10.0",
|
"globals": "^15.10.0",
|
||||||
|
@ -90,14 +90,12 @@ export class AdminInterface extends AuthenticatedInterface {
|
|||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
this.ws = new WebsocketClient();
|
this.ws = new WebsocketClient();
|
||||||
|
|
||||||
window.addEventListener(EVENT_NOTIFICATION_DRAWER_TOGGLE, () => {
|
window.addEventListener(EVENT_NOTIFICATION_DRAWER_TOGGLE, () => {
|
||||||
this.notificationDrawerOpen = !this.notificationDrawerOpen;
|
this.notificationDrawerOpen = !this.notificationDrawerOpen;
|
||||||
updateURLParams({
|
updateURLParams({
|
||||||
notificationDrawerOpen: this.notificationDrawerOpen,
|
notificationDrawerOpen: this.notificationDrawerOpen,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
window.addEventListener(EVENT_API_DRAWER_TOGGLE, () => {
|
window.addEventListener(EVENT_API_DRAWER_TOGGLE, () => {
|
||||||
this.apiDrawerOpen = !this.apiDrawerOpen;
|
this.apiDrawerOpen = !this.apiDrawerOpen;
|
||||||
updateURLParams({
|
updateURLParams({
|
||||||
@ -109,7 +107,6 @@ export class AdminInterface extends AuthenticatedInterface {
|
|||||||
async firstUpdated(): Promise<void> {
|
async firstUpdated(): Promise<void> {
|
||||||
configureSentry(true);
|
configureSentry(true);
|
||||||
this.user = await me();
|
this.user = await me();
|
||||||
|
|
||||||
const canAccessAdmin =
|
const canAccessAdmin =
|
||||||
this.user.user.isSuperuser ||
|
this.user.user.isSuperuser ||
|
||||||
// TODO: somehow add `access_admin_interface` to the API schema
|
// TODO: somehow add `access_admin_interface` to the API schema
|
||||||
@ -119,16 +116,6 @@ export class AdminInterface extends AuthenticatedInterface {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async connectedCallback(): Promise<void> {
|
|
||||||
super.connectedCallback();
|
|
||||||
|
|
||||||
if (process.env.NODE_ENV === "development" && process.env.WATCHER_URL) {
|
|
||||||
const { ESBuildObserver } = await import("@goauthentik/common/client");
|
|
||||||
|
|
||||||
new ESBuildObserver(process.env.WATCHER_URL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render(): TemplateResult {
|
render(): TemplateResult {
|
||||||
const sidebarClasses = {
|
const sidebarClasses = {
|
||||||
"pf-m-light": this.activeTheme === UiThemeEnum.Light,
|
"pf-m-light": this.activeTheme === UiThemeEnum.Light,
|
||||||
|
@ -28,7 +28,6 @@ import { when } from "lit/directives/when.js";
|
|||||||
import PFContent from "@patternfly/patternfly/components/Content/content.css";
|
import PFContent from "@patternfly/patternfly/components/Content/content.css";
|
||||||
import PFDivider from "@patternfly/patternfly/components/Divider/divider.css";
|
import PFDivider from "@patternfly/patternfly/components/Divider/divider.css";
|
||||||
import PFPage from "@patternfly/patternfly/components/Page/page.css";
|
import PFPage from "@patternfly/patternfly/components/Page/page.css";
|
||||||
import PFFlex from "@patternfly/patternfly/layouts/Flex/flex.css";
|
|
||||||
import PFGrid from "@patternfly/patternfly/layouts/Grid/grid.css";
|
import PFGrid from "@patternfly/patternfly/layouts/Grid/grid.css";
|
||||||
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
||||||
|
|
||||||
@ -55,7 +54,6 @@ export class AdminOverviewPage extends AdminOverviewBase {
|
|||||||
return [
|
return [
|
||||||
PFBase,
|
PFBase,
|
||||||
PFGrid,
|
PFGrid,
|
||||||
PFFlex,
|
|
||||||
PFPage,
|
PFPage,
|
||||||
PFContent,
|
PFContent,
|
||||||
PFDivider,
|
PFDivider,
|
||||||
@ -69,6 +67,13 @@ export class AdminOverviewPage extends AdminOverviewBase {
|
|||||||
.card-container {
|
.card-container {
|
||||||
max-height: 10em;
|
max-height: 10em;
|
||||||
}
|
}
|
||||||
|
.ak-external-link {
|
||||||
|
display: inline-block;
|
||||||
|
margin-left: 0.175rem;
|
||||||
|
vertical-align: super;
|
||||||
|
line-height: normal;
|
||||||
|
font-size: var(--pf-global--icon--FontSize--sm);
|
||||||
|
}
|
||||||
`,
|
`,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@ -94,19 +99,17 @@ export class AdminOverviewPage extends AdminOverviewBase {
|
|||||||
return html`<ak-page-header description=${msg("General system status")} ?hasIcon=${false}>
|
return html`<ak-page-header description=${msg("General system status")} ?hasIcon=${false}>
|
||||||
<span slot="header"> ${msg(str`Welcome, ${name || ""}.`)} </span>
|
<span slot="header"> ${msg(str`Welcome, ${name || ""}.`)} </span>
|
||||||
</ak-page-header>
|
</ak-page-header>
|
||||||
|
|
||||||
<section class="pf-c-page__main-section">
|
<section class="pf-c-page__main-section">
|
||||||
<div class="pf-l-grid pf-m-gutter">
|
<div class="pf-l-grid pf-m-gutter">
|
||||||
${this.renderCards()}
|
<!-- row 1 -->
|
||||||
<div class="pf-l-grid__item pf-m-9-col pf-m-3-row">
|
<div
|
||||||
<ak-recent-events pageSize="6"></ak-recent-events>
|
class="pf-l-grid__item pf-m-12-col pf-m-6-col-on-xl pf-m-6-col-on-2xl pf-l-grid pf-m-gutter"
|
||||||
</div>
|
>
|
||||||
<div class="pf-l-grid__item pf-m-6-col pf-m-3-col-on-md pf-m-3-col-on-xl">
|
<div class="pf-l-grid__item pf-m-12-col pf-m-6-col-on-xl pf-m-4-col-on-2xl">
|
||||||
<ak-quick-actions-card .actions=${this.quickActions}>
|
<ak-quick-actions-card .actions=${this.quickActions}>
|
||||||
</ak-quick-actions-card>
|
</ak-quick-actions-card>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="pf-l-grid__item pf-m-12-col pf-m-6-col-on-xl pf-m-4-col-on-2xl">
|
||||||
<div class="pf-l-grid__item pf-m-6-col pf-m-3-col-on-md pf-m-3-col-on-xl">
|
|
||||||
<ak-aggregate-card
|
<ak-aggregate-card
|
||||||
icon="pf-icon pf-icon-zone"
|
icon="pf-icon pf-icon-zone"
|
||||||
header=${msg("Outpost status")}
|
header=${msg("Outpost status")}
|
||||||
@ -115,13 +118,24 @@ export class AdminOverviewPage extends AdminOverviewBase {
|
|||||||
<ak-admin-status-chart-outpost></ak-admin-status-chart-outpost>
|
<ak-admin-status-chart-outpost></ak-admin-status-chart-outpost>
|
||||||
</ak-aggregate-card>
|
</ak-aggregate-card>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
<div class="pf-l-grid__item pf-m-6-col pf-m-3-col-on-md pf-m-3-col-on-xl">
|
class="pf-l-grid__item pf-m-12-col pf-m-12-col-on-xl pf-m-4-col-on-2xl"
|
||||||
|
>
|
||||||
<ak-aggregate-card icon="fa fa-sync-alt" header=${msg("Sync status")}>
|
<ak-aggregate-card icon="fa fa-sync-alt" header=${msg("Sync status")}>
|
||||||
<ak-admin-status-chart-sync></ak-admin-status-chart-sync>
|
<ak-admin-status-chart-sync></ak-admin-status-chart-sync>
|
||||||
</ak-aggregate-card>
|
</ak-aggregate-card>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="pf-l-grid__item pf-m-12-col">
|
||||||
|
<hr class="pf-c-divider" />
|
||||||
|
</div>
|
||||||
|
${this.renderCards()}
|
||||||
|
</div>
|
||||||
|
<div class="pf-l-grid__item pf-m-12-col pf-m-6-col-on-xl">
|
||||||
|
<ak-recent-events pageSize="6"></ak-recent-events>
|
||||||
|
</div>
|
||||||
|
<div class="pf-l-grid__item pf-m-12-col">
|
||||||
|
<hr class="pf-c-divider" />
|
||||||
|
</div>
|
||||||
<!-- row 3 -->
|
<!-- row 3 -->
|
||||||
<div
|
<div
|
||||||
class="pf-l-grid__item pf-m-12-col pf-m-6-col-on-xl pf-m-8-col-on-2xl big-graph-container"
|
class="pf-l-grid__item pf-m-12-col pf-m-6-col-on-xl pf-m-8-col-on-2xl big-graph-container"
|
||||||
|
@ -1,15 +1,10 @@
|
|||||||
import { EVENT_REFRESH } from "@goauthentik/common/constants";
|
import { EVENT_REFRESH } from "@goauthentik/common/constants";
|
||||||
import { PFSize } from "@goauthentik/common/enums.js";
|
import { PFSize } from "@goauthentik/common/enums.js";
|
||||||
import {
|
|
||||||
APIError,
|
|
||||||
parseAPIResponseError,
|
|
||||||
pluckErrorDetail,
|
|
||||||
} from "@goauthentik/common/errors/network";
|
|
||||||
import { AggregateCard } from "@goauthentik/elements/cards/AggregateCard";
|
import { AggregateCard } from "@goauthentik/elements/cards/AggregateCard";
|
||||||
|
|
||||||
import { msg } from "@lit/localize";
|
import { msg } from "@lit/localize";
|
||||||
import { PropertyValues, TemplateResult, html, nothing } from "lit";
|
import { TemplateResult, html } from "lit";
|
||||||
import { state } from "lit/decorators.js";
|
import { until } from "lit/directives/until.js";
|
||||||
|
|
||||||
import { ResponseError } from "@goauthentik/api";
|
import { ResponseError } from "@goauthentik/api";
|
||||||
|
|
||||||
@ -18,143 +13,46 @@ export interface AdminStatus {
|
|||||||
message?: TemplateResult;
|
message?: TemplateResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstract base class for admin status cards with robust state management
|
|
||||||
*
|
|
||||||
* @template T - Type of the primary data value used in the card
|
|
||||||
*/
|
|
||||||
export abstract class AdminStatusCard<T> extends AggregateCard {
|
export abstract class AdminStatusCard<T> extends AggregateCard {
|
||||||
// Current data value state
|
|
||||||
@state()
|
|
||||||
value?: T;
|
|
||||||
|
|
||||||
// Current status state derived from value
|
|
||||||
@state()
|
|
||||||
protected status?: AdminStatus;
|
|
||||||
|
|
||||||
// Current error state if any request fails
|
|
||||||
@state()
|
|
||||||
protected error?: APIError;
|
|
||||||
|
|
||||||
// Abstract methods to be implemented by subclasses
|
|
||||||
abstract getPrimaryValue(): Promise<T>;
|
abstract getPrimaryValue(): Promise<T>;
|
||||||
|
|
||||||
abstract getStatus(value: T): Promise<AdminStatus>;
|
abstract getStatus(value: T): Promise<AdminStatus>;
|
||||||
|
|
||||||
|
value?: T;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
// Proper binding for event handler
|
this.addEventListener(EVENT_REFRESH, () => {
|
||||||
this.fetchData = this.fetchData.bind(this);
|
this.requestUpdate();
|
||||||
// Register refresh event listener
|
|
||||||
this.addEventListener(EVENT_REFRESH, this.fetchData);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lifecycle method: Called when component is added to DOM
|
|
||||||
connectedCallback(): void {
|
|
||||||
super.connectedCallback();
|
|
||||||
// Initial data fetch
|
|
||||||
this.fetchData();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch primary data and handle errors
|
|
||||||
*/
|
|
||||||
private fetchData() {
|
|
||||||
this.getPrimaryValue()
|
|
||||||
.then((value: T) => {
|
|
||||||
this.value = value; // Triggers shouldUpdate
|
|
||||||
this.error = undefined;
|
|
||||||
})
|
|
||||||
.catch(async (error) => {
|
|
||||||
this.status = undefined;
|
|
||||||
this.error = await parseAPIResponseError(error);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
renderValue(): TemplateResult {
|
||||||
* Lit lifecycle method: Determine if component should update
|
|
||||||
*
|
|
||||||
* @param changed - Map of changed properties
|
|
||||||
* @returns boolean indicating if update should proceed
|
|
||||||
*/
|
|
||||||
shouldUpdate(changed: PropertyValues<this>) {
|
|
||||||
if (changed.has("value") && this.value !== undefined) {
|
|
||||||
// When value changes, fetch new status
|
|
||||||
this.getStatus(this.value)
|
|
||||||
.then((status) => {
|
|
||||||
this.status = status;
|
|
||||||
this.error = undefined;
|
|
||||||
})
|
|
||||||
.catch(async (error: ResponseError) => {
|
|
||||||
this.status = undefined;
|
|
||||||
this.error = await parseAPIResponseError(error);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Prevent immediate re-render if only value changed
|
|
||||||
if (changed.size === 1) return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render the primary value display
|
|
||||||
*
|
|
||||||
* @returns TemplateResult displaying the value
|
|
||||||
*/
|
|
||||||
protected renderValue(): TemplateResult {
|
|
||||||
return html`${this.value}`;
|
return html`${this.value}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Render status state
|
|
||||||
*
|
|
||||||
* @param status - AdminStatus object containing icon and message
|
|
||||||
* @returns TemplateResult for status display
|
|
||||||
*/
|
|
||||||
private renderStatus(status: AdminStatus): TemplateResult {
|
|
||||||
return html`
|
|
||||||
<p><i class="${status.icon}"></i> ${this.renderValue()}</p>
|
|
||||||
${status.message ? html`<p class="subtext">${status.message}</p>` : nothing}
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render error state
|
|
||||||
*
|
|
||||||
* @param error - Error message to display
|
|
||||||
* @returns TemplateResult for error display
|
|
||||||
*/
|
|
||||||
private renderError(error: string): TemplateResult {
|
|
||||||
return html`
|
|
||||||
<p><i class="fa fa-times"></i> ${msg("Failed to fetch")}</p>
|
|
||||||
<p class="subtext">${error}</p>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Render loading state
|
|
||||||
*
|
|
||||||
* @returns TemplateResult for loading spinner
|
|
||||||
*/
|
|
||||||
private renderLoading(): TemplateResult {
|
|
||||||
return html`<ak-spinner size="${PFSize.Large}"></ak-spinner>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Main render method that selects appropriate state display
|
|
||||||
*
|
|
||||||
* @returns TemplateResult for current component state
|
|
||||||
*/
|
|
||||||
renderInner(): TemplateResult {
|
renderInner(): TemplateResult {
|
||||||
return html`
|
return html`<p class="center-value">
|
||||||
<p class="center-value">
|
${until(
|
||||||
${
|
this.getPrimaryValue()
|
||||||
this.status
|
.then((v) => {
|
||||||
? this.renderStatus(this.status) // Status available
|
this.value = v;
|
||||||
: this.error
|
return this.getStatus(v);
|
||||||
? this.renderError(pluckErrorDetail(this.error)) // Error state
|
})
|
||||||
: this.renderLoading() // Loading state
|
.then((status) => {
|
||||||
}
|
return html`<p><i class="${status.icon}"></i> ${this.renderValue()}</p>
|
||||||
|
${status.message
|
||||||
|
? html`<p class="subtext">${status.message}</p>`
|
||||||
|
: html``}`;
|
||||||
|
})
|
||||||
|
.catch((exc: ResponseError) => {
|
||||||
|
return html` <p>
|
||||||
|
<i class="fa fa-times"></i> ${exc.response.statusText}
|
||||||
</p>
|
</p>
|
||||||
`;
|
<p class="subtext">${msg("Failed to fetch")}</p>`;
|
||||||
|
}),
|
||||||
|
html`<ak-spinner size="${PFSize.Large}"></ak-spinner>`,
|
||||||
|
)}
|
||||||
|
</p>`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { EventUser, formatGeoEvent } from "@goauthentik/admin/events/utils";
|
import { EventGeo, EventUser } from "@goauthentik/admin/events/utils";
|
||||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||||
import { EventWithContext } from "@goauthentik/common/events";
|
import { EventWithContext } from "@goauthentik/common/events";
|
||||||
import { actionToLabel } from "@goauthentik/common/labels";
|
import { actionToLabel } from "@goauthentik/common/labels";
|
||||||
@ -10,7 +10,6 @@ import "@goauthentik/elements/buttons/ModalButton";
|
|||||||
import "@goauthentik/elements/buttons/SpinnerButton";
|
import "@goauthentik/elements/buttons/SpinnerButton";
|
||||||
import { PaginatedResponse } from "@goauthentik/elements/table/Table";
|
import { PaginatedResponse } from "@goauthentik/elements/table/Table";
|
||||||
import { Table, TableColumn } from "@goauthentik/elements/table/Table";
|
import { Table, TableColumn } from "@goauthentik/elements/table/Table";
|
||||||
import { SlottedTemplateResult } from "@goauthentik/elements/types";
|
|
||||||
|
|
||||||
import { msg } from "@lit/localize";
|
import { msg } from "@lit/localize";
|
||||||
import { CSSResult, TemplateResult, css, html } from "lit";
|
import { CSSResult, TemplateResult, css, html } from "lit";
|
||||||
@ -39,22 +38,6 @@ export class RecentEventsCard extends Table<Event> {
|
|||||||
return super.styles.concat(
|
return super.styles.concat(
|
||||||
PFCard,
|
PFCard,
|
||||||
css`
|
css`
|
||||||
.pf-c-table__sort.pf-m-selected {
|
|
||||||
background-color: var(--pf-global--BackgroundColor--dark-400);
|
|
||||||
border-block-end: var(--pf-global--BorderWidth--xl) solid var(--ak-accent);
|
|
||||||
|
|
||||||
.pf-c-table__button {
|
|
||||||
--pf-c-table__sort__button__text--Color: var(--ak-accent);
|
|
||||||
color: var(--pf-c-nav__link--m-current--Color);
|
|
||||||
|
|
||||||
.pf-c-table__text {
|
|
||||||
--pf-c-table__sort__button__text--Color: var(
|
|
||||||
--pf-c-nav__link--m-current--Color
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.pf-c-card__title {
|
.pf-c-card__title {
|
||||||
--pf-c-card__title--FontFamily: var(
|
--pf-c-card__title--FontFamily: var(
|
||||||
--pf-global--FontFamily--heading--sans-serif
|
--pf-global--FontFamily--heading--sans-serif
|
||||||
@ -62,47 +45,7 @@ export class RecentEventsCard extends Table<Event> {
|
|||||||
--pf-c-card__title--FontSize: var(--pf-global--FontSize--md);
|
--pf-c-card__title--FontSize: var(--pf-global--FontSize--md);
|
||||||
--pf-c-card__title--FontWeight: var(--pf-global--FontWeight--bold);
|
--pf-c-card__title--FontWeight: var(--pf-global--FontWeight--bold);
|
||||||
}
|
}
|
||||||
|
* {
|
||||||
td[role="cell"] .ip-address {
|
|
||||||
max-width: 18ch;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
overflow: hidden;
|
|
||||||
display: -webkit-box;
|
|
||||||
-webkit-line-clamp: 2;
|
|
||||||
-webkit-box-orient: vertical;
|
|
||||||
}
|
|
||||||
|
|
||||||
th[role="columnheader"]:nth-child(3) {
|
|
||||||
--pf-c-table--cell--MinWidth: fit-content;
|
|
||||||
--pf-c-table--cell--MaxWidth: none;
|
|
||||||
--pf-c-table--cell--Width: 1%;
|
|
||||||
--pf-c-table--cell--Overflow: visible;
|
|
||||||
--pf-c-table--cell--TextOverflow: clip;
|
|
||||||
--pf-c-table--cell--WhiteSpace: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.group-header {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1fr auto;
|
|
||||||
gap: var(--pf-global--spacer--sm);
|
|
||||||
font-weight: var(--pf-global--FontWeight--bold);
|
|
||||||
font-size: var(--pf-global--FontSize--md);
|
|
||||||
font-variant: all-petite-caps;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pf-c-table thead:not(:first-child) {
|
|
||||||
background: hsl(0deg 0% 0% / 10%);
|
|
||||||
|
|
||||||
> tr {
|
|
||||||
border-block-end: 2px solid
|
|
||||||
var(
|
|
||||||
--pf-c-page__header-tools--c-button--m-selected--before--BackgroundColor
|
|
||||||
);
|
|
||||||
font-family: var(--pf-global--FontFamily--heading--sans-serif);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tbody * {
|
|
||||||
word-break: break-all;
|
word-break: break-all;
|
||||||
}
|
}
|
||||||
`,
|
`,
|
||||||
@ -125,57 +68,20 @@ export class RecentEventsCard extends Table<Event> {
|
|||||||
</div>`;
|
</div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
override groupBy(items: Event[]): [SlottedTemplateResult, Event[]][] {
|
row(item: EventWithContext): TemplateResult[] {
|
||||||
const groupedByDay = new Map<string, Event[]>();
|
|
||||||
|
|
||||||
for (const item of items) {
|
|
||||||
const day = new Date(item.created);
|
|
||||||
day.setHours(0, 0, 0, 0);
|
|
||||||
const serializedDay = day.toISOString();
|
|
||||||
|
|
||||||
let dayEvents = groupedByDay.get(serializedDay);
|
|
||||||
if (!dayEvents) {
|
|
||||||
dayEvents = [];
|
|
||||||
groupedByDay.set(serializedDay, dayEvents);
|
|
||||||
}
|
|
||||||
|
|
||||||
dayEvents.push(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Array.from(groupedByDay, ([serializedDay, events]) => {
|
|
||||||
const day = new Date(serializedDay);
|
|
||||||
return [
|
|
||||||
html` <div class="pf-c-content group-header">
|
|
||||||
<div>${getRelativeTime(day)}</div>
|
|
||||||
<small>${day.toLocaleDateString()}</small>
|
|
||||||
</div>`,
|
|
||||||
events,
|
|
||||||
];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
row(item: EventWithContext): SlottedTemplateResult[] {
|
|
||||||
return [
|
return [
|
||||||
html`<div><a href="${`#/events/log/${item.pk}`}">${actionToLabel(item.action)}</a></div>
|
html`<div><a href="${`#/events/log/${item.pk}`}">${actionToLabel(item.action)}</a></div>
|
||||||
<small class="pf-m-monospace">${item.app}</small>`,
|
<small>${item.app}</small>`,
|
||||||
EventUser(item),
|
EventUser(item),
|
||||||
|
html`<div>${getRelativeTime(item.created)}</div>
|
||||||
html`<time datetime="${item.created.toISOString()}" class="pf-c-content">
|
<small>${item.created.toLocaleString()}</small>`,
|
||||||
<div><small>${item.created.toLocaleTimeString()}</small></div>
|
html` <div>${item.clientIp || msg("-")}</div>
|
||||||
</time>`,
|
<small>${EventGeo(item)}</small>`,
|
||||||
|
|
||||||
html`<div class="ip-address pf-m-monospace">${item.clientIp || msg("-")}</div>
|
|
||||||
<small class="geographic-location">${formatGeoEvent(item)}</small>`,
|
|
||||||
|
|
||||||
html`<span>${item.brand?.name || msg("-")}</span>`,
|
html`<span>${item.brand?.name || msg("-")}</span>`,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
renderEmpty(inner?: SlottedTemplateResult): TemplateResult {
|
renderEmpty(): TemplateResult {
|
||||||
if (this.error) {
|
|
||||||
return super.renderEmpty(inner);
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.renderEmpty(
|
return super.renderEmpty(
|
||||||
html`<ak-empty-state header=${msg("No Events found.")}>
|
html`<ak-empty-state header=${msg("No Events found.")}>
|
||||||
<div slot="body">${msg("No matching events could be found.")}</div>
|
<div slot="body">${msg("No matching events could be found.")}</div>
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user