Compare commits
	
		
			208 Commits
		
	
	
		
			safari-cra
			...
			tests/e2e/
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 4b0d641a51 | |||
| 99b559893b | |||
| 8014088c3a | |||
| 3ee353126f | |||
| db76c5d9e2 | |||
| 61bff69b7d | |||
| 69651323e3 | |||
| 75a0ac9588 | |||
| 941a697397 | |||
| 4a74db17a1 | |||
| 0cf6bff93c | |||
| 814e438422 | |||
| 2db77a37dd | |||
| e40c5ac617 | |||
| 7440900dac | |||
| ca96b27825 | |||
| ad4a765a80 | |||
| 4dcd481010 | |||
| d0dc14d84d | |||
| 7bf960352b | |||
| c07d01661b | |||
| 427597ec14 | |||
| 7cc77bd387 | |||
| 381a1a2c49 | |||
| 08f8222224 | |||
| 1211c34a18 | |||
| 22efb57369 | |||
| 3eeda53be6 | |||
| 82ace18703 | |||
| 8589079252 | |||
| ae2af6e58e | |||
| 86a7f98ff6 | |||
| 3af45371d3 | |||
| b01ffd934f | |||
| f11ba94603 | |||
| 7d2aa43364 | |||
| f1351a7577 | |||
| 0611eea0e7 | |||
| d0b46fcf9c | |||
| dcbdc37d31 | |||
| d07f396379 | |||
| 0972103b83 | |||
| b448e76db4 | |||
| f2937bd6dd | |||
| 53c2e3e77c | |||
| 7dd62c1f55 | |||
| 33e3510fba | |||
| 0e5fac2642 | |||
| c53b1fe78a | |||
| 838a7457b2 | |||
| a3c07bc9ff | |||
| 121f2c609d | |||
| 365affc28e | |||
| f367822779 | |||
| 848198125d | |||
| 497ac5e3d0 | |||
| 1773d4d681 | |||
| 4edbb51939 | |||
| c7e97ab48e | |||
| 31f7faae1c | |||
| f5dae2ae92 | |||
| 2c043dba0b | |||
| bda10e5db1 | |||
| be9ae7d4f7 | |||
| b4a6189bfa | |||
| bfdb827ff9 | |||
| 488a58e1c5 | |||
| 3f83e69453 | |||
| e92fa5df0b | |||
| f8c22170df | |||
| e3d08a8434 | |||
| 97d3e9afdc | |||
| 1eb08def73 | |||
| 6e3b379e4a | |||
| 264f59775c | |||
| d048f1ecbd | |||
| eb31f31584 | |||
| fe5c842e92 | |||
| b82d3100c9 | |||
| 49bb668036 | |||
| 52c70c7700 | |||
| b99fd36f86 | |||
| 8a5381eca3 | |||
| 2c77830179 | |||
| ffcd7def60 | |||
| ed121bc2a3 | |||
| d5ab9d9167 | |||
| a983321ad6 | |||
| 9c3420ede4 | |||
| 91b40350aa | |||
| 1912991682 | |||
| 71b9117f53 | |||
| b5f947f460 | |||
| 3a2f7e9549 | |||
| 1582ce0920 | |||
| 6d3eea5266 | |||
| e987208bd1 | |||
| 0efab8eef7 | |||
| 9402dac8ae | |||
| f57a290eee | |||
| 5dab0d2b7a | |||
| 2da6036248 | |||
| cdba94cea4 | |||
| c59eca664a | |||
| d5b205f9c0 | |||
| 8ad9ad833e | |||
| 599ce15f68 | |||
| 91310eff52 | |||
| b522d6732a | |||
| 17d96f204e | |||
| 65e4667bc3 | |||
| f67f9e5ed0 | |||
| 62dd6a4393 | |||
| a46eae8276 | |||
| c4acc9fc24 | |||
| e748a03082 | |||
| e473f28e21 | |||
| f70635c295 | |||
| 70d60c7ab2 | |||
| 61a26c02b7 | |||
| a06645d558 | |||
| 7730ecbd37 | |||
| 80e1be8db7 | |||
| c528c74e48 | |||
| 6d7bf36afe | |||
| 44fb59eb18 | |||
| 8f8d924935 | |||
| 602adaa5c5 | |||
| 5c9e97e11c | |||
| 2e7c620c9c | |||
| 30a2770781 | |||
| ef49fa0e79 | |||
| ac524ef425 | |||
| 6f3c1c4537 | |||
| 87886ca1b6 | |||
| 7ff96e30f9 | |||
| b26271557a | |||
| 15c99ff129 | |||
| 2a38e08e31 | |||
| 3696706466 | |||
| d0c9635033 | |||
| 7731014e1c | |||
| d478582a5c | |||
| 6255f380aa | |||
| 1f02e67c5c | |||
| d0bfb894b4 | |||
| c5dfdc6deb | |||
| d04a66ad9a | |||
| a5edaabec0 | |||
| daa367bc62 | |||
| 78345853c2 | |||
| f0fa8a3226 | |||
| 3335fdc6ad | |||
| 29c2c0f7dc | |||
| ada4254f52 | |||
| 39035de552 | |||
| e76d388ce4 | |||
| a52f887692 | |||
| d8b12a9a07 | |||
| ec01f16e99 | |||
| 9e3aaefc20 | |||
| 4454592442 | |||
| 593c953ecc | |||
| bcefe7123c | |||
| 812cf6c4f2 | |||
| 73b6ef6a73 | |||
| b58ebcddbf | |||
| 8b6ac3c806 | |||
| c6aa792076 | |||
| ee4792734e | |||
| 445f11ca6b | |||
| 8e4810fb20 | |||
| 96a122c5d1 | |||
| 3c6b8b10e5 | |||
| 15999caa5d | |||
| 57d8375de1 | |||
| 07ec787076 | |||
| bc96bef097 | |||
| 28869858b5 | |||
| cbc5a1c39d | |||
| 5f6b69c998 | |||
| cf065db3d5 | |||
| 86c65325ce | |||
| 2b8e10e979 | |||
| 9298807275 | |||
| ed56d6ac50 | |||
| 8c07b385ad | |||
| 880db7a86c | |||
| 99c1250ba5 | |||
| 5ce126ac83 | |||
| dfa21d0725 | |||
| e7e4af3894 | |||
| 931d6ec579 | |||
| ff45acb25c | |||
| c96557ff2d | |||
| 734feac4ae | |||
| b17a9ed145 | |||
| 2bef7695db | |||
| df472dd842 | |||
| 98d201d34c | |||
| 47e89602ab | |||
| ceb0851452 | |||
| cac2593658 | |||
| 1c9705bfaa | |||
| 9e2566cec4 | |||
| 5bdef1c4f6 | |||
| ae41ccd862 | |||
| 337956672f | 
| @ -1,5 +1,5 @@ | |||||||
| [bumpversion] | [bumpversion] | ||||||
| current_version = 2025.2.4 | current_version = 2025.4.1 | ||||||
| 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*))? | ||||||
|  | |||||||
							
								
								
									
										12
									
								
								.github/dependabot.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								.github/dependabot.yml
									
									
									
									
										vendored
									
									
								
							| @ -118,3 +118,15 @@ updates: | |||||||
|       prefix: "core:" |       prefix: "core:" | ||||||
|     labels: |     labels: | ||||||
|       - dependencies |       - dependencies | ||||||
|  |   - package-ecosystem: docker-compose | ||||||
|  |     directories: | ||||||
|  |       # - /scripts # Maybe | ||||||
|  |       - /tests/e2e | ||||||
|  |     schedule: | ||||||
|  |       interval: daily | ||||||
|  |       time: "04:00" | ||||||
|  |     open-pull-requests-limit: 10 | ||||||
|  |     commit-message: | ||||||
|  |       prefix: "core:" | ||||||
|  |     labels: | ||||||
|  |       - dependencies | ||||||
|  | |||||||
							
								
								
									
										15
									
								
								.github/workflows/ci-main.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								.github/workflows/ci-main.yml
									
									
									
									
										vendored
									
									
								
							| @ -70,22 +70,18 @@ jobs: | |||||||
|       - name: checkout stable |       - name: checkout stable | ||||||
|         run: | |         run: | | ||||||
|           # Copy current, latest config to local |           # Copy current, latest config to local | ||||||
|           # Temporarly comment the .github backup while migrating to uv |  | ||||||
|           cp authentik/lib/default.yml local.env.yml |           cp authentik/lib/default.yml local.env.yml | ||||||
|           # cp -R .github .. |           cp -R .github .. | ||||||
|           cp -R scripts .. |           cp -R scripts .. | ||||||
|           git checkout $(git tag --sort=version:refname | grep '^version/' | grep -vE -- '-rc[0-9]+$' | tail -n1) |           git checkout $(git tag --sort=version:refname | grep '^version/' | grep -vE -- '-rc[0-9]+$' | tail -n1) | ||||||
|           # rm -rf .github/ scripts/ |           rm -rf .github/ scripts/ | ||||||
|           # mv ../.github ../scripts . |           mv ../.github ../scripts . | ||||||
|           rm -rf scripts/ |  | ||||||
|           mv ../scripts . |  | ||||||
|       - name: Setup authentik env (stable) |       - name: Setup authentik env (stable) | ||||||
|         uses: ./.github/actions/setup |         uses: ./.github/actions/setup | ||||||
|         with: |         with: | ||||||
|           postgresql_version: ${{ matrix.psql }} |           postgresql_version: ${{ matrix.psql }} | ||||||
|         continue-on-error: true |  | ||||||
|       - name: run migrations to stable |       - name: run migrations to stable | ||||||
|         run: poetry run python -m lifecycle.migrate |         run: uv run python -m lifecycle.migrate | ||||||
|       - name: checkout current code |       - name: checkout current code | ||||||
|         run: | |         run: | | ||||||
|           set -x |           set -x | ||||||
| @ -204,7 +200,7 @@ jobs: | |||||||
|         uses: actions/cache@v4 |         uses: actions/cache@v4 | ||||||
|         with: |         with: | ||||||
|           path: web/dist |           path: web/dist | ||||||
|           key: ${{ runner.os }}-web-${{ hashFiles('web/package-lock.json', 'web/src/**') }} |           key: ${{ runner.os }}-web-${{ hashFiles('web/package-lock.json', 'web/src/**', 'web/packages/sfe/src/**') }}-b | ||||||
|       - name: prepare web ui |       - name: prepare web ui | ||||||
|         if: steps.cache-web.outputs.cache-hit != 'true' |         if: steps.cache-web.outputs.cache-hit != 'true' | ||||||
|         working-directory: web |         working-directory: web | ||||||
| @ -212,6 +208,7 @@ jobs: | |||||||
|           npm ci |           npm ci | ||||||
|           make -C .. gen-client-ts |           make -C .. gen-client-ts | ||||||
|           npm run build |           npm run build | ||||||
|  |           npm run build:sfe | ||||||
|       - name: run e2e |       - name: run e2e | ||||||
|         run: | |         run: | | ||||||
|           uv run coverage run manage.py test ${{ matrix.job.glob }} |           uv run coverage run manage.py test ${{ matrix.job.glob }} | ||||||
|  | |||||||
							
								
								
									
										2
									
								
								.github/workflows/ci-outpost.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/ci-outpost.yml
									
									
									
									
										vendored
									
									
								
							| @ -29,7 +29,7 @@ jobs: | |||||||
|       - name: Generate API |       - name: Generate API | ||||||
|         run: make gen-client-go |         run: make gen-client-go | ||||||
|       - name: golangci-lint |       - name: golangci-lint | ||||||
|         uses: golangci/golangci-lint-action@v7 |         uses: golangci/golangci-lint-action@v8 | ||||||
|         with: |         with: | ||||||
|           version: latest |           version: latest | ||||||
|           args: --timeout 5000s --verbose |           args: --timeout 5000s --verbose | ||||||
|  | |||||||
							
								
								
									
										8
									
								
								.github/workflows/packages-npm-publish.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								.github/workflows/packages-npm-publish.yml
									
									
									
									
										vendored
									
									
								
							| @ -3,10 +3,10 @@ on: | |||||||
|   push: |   push: | ||||||
|     branches: [main] |     branches: [main] | ||||||
|     paths: |     paths: | ||||||
|       - packages/docusaurus-config |       - packages/docusaurus-config/** | ||||||
|       - packages/eslint-config |       - packages/eslint-config/** | ||||||
|       - packages/prettier-config |       - packages/prettier-config/** | ||||||
|       - packages/tsconfig |       - packages/tsconfig/** | ||||||
|   workflow_dispatch: |   workflow_dispatch: | ||||||
| jobs: | jobs: | ||||||
|   publish: |   publish: | ||||||
|  | |||||||
							
								
								
									
										6
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							| @ -16,7 +16,7 @@ | |||||||
|     ], |     ], | ||||||
|     "typescript.preferences.importModuleSpecifier": "non-relative", |     "typescript.preferences.importModuleSpecifier": "non-relative", | ||||||
|     "typescript.preferences.importModuleSpecifierEnding": "index", |     "typescript.preferences.importModuleSpecifierEnding": "index", | ||||||
|     "typescript.tsdk": "./web/node_modules/typescript/lib", |     "typescript.tsdk": "./node_modules/typescript/lib", | ||||||
|     "typescript.enablePromptUseWorkspaceTsdk": true, |     "typescript.enablePromptUseWorkspaceTsdk": true, | ||||||
|     "yaml.schemas": { |     "yaml.schemas": { | ||||||
|         "./blueprints/schema.json": "blueprints/**/*.yaml" |         "./blueprints/schema.json": "blueprints/**/*.yaml" | ||||||
| @ -30,7 +30,5 @@ | |||||||
|         } |         } | ||||||
|     ], |     ], | ||||||
|     "go.testFlags": ["-count=1"], |     "go.testFlags": ["-count=1"], | ||||||
|     "github-actions.workflows.pinned.workflows": [ |     "github-actions.workflows.pinned.workflows": [".github/workflows/ci-main.yml"] | ||||||
|         ".github/workflows/ci-main.yml" |  | ||||||
|     ] |  | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										10
									
								
								Dockerfile
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								Dockerfile
									
									
									
									
									
								
							| @ -40,7 +40,8 @@ COPY ./web /work/web/ | |||||||
| COPY ./website /work/website/ | COPY ./website /work/website/ | ||||||
| COPY ./gen-ts-api /work/web/node_modules/@goauthentik/api | COPY ./gen-ts-api /work/web/node_modules/@goauthentik/api | ||||||
|  |  | ||||||
| RUN npm run build | RUN npm run build && \ | ||||||
|  |     npm run build:sfe | ||||||
|  |  | ||||||
| # Stage 3: Build go proxy | # Stage 3: Build go proxy | ||||||
| FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.24-bookworm AS go-builder | FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.24-bookworm AS go-builder | ||||||
| @ -85,18 +86,17 @@ FROM --platform=${BUILDPLATFORM} ghcr.io/maxmind/geoipupdate:v7.1.0 AS geoip | |||||||
| ENV GEOIPUPDATE_EDITION_IDS="GeoLite2-City GeoLite2-ASN" | ENV GEOIPUPDATE_EDITION_IDS="GeoLite2-City GeoLite2-ASN" | ||||||
| ENV GEOIPUPDATE_VERBOSE="1" | ENV GEOIPUPDATE_VERBOSE="1" | ||||||
| ENV GEOIPUPDATE_ACCOUNT_ID_FILE="/run/secrets/GEOIPUPDATE_ACCOUNT_ID" | ENV GEOIPUPDATE_ACCOUNT_ID_FILE="/run/secrets/GEOIPUPDATE_ACCOUNT_ID" | ||||||
| ENV GEOIPUPDATE_LICENSE_KEY_FILE="/run/secrets/GEOIPUPDATE_LICENSE_KEY" |  | ||||||
|  |  | ||||||
| USER root | USER root | ||||||
| RUN --mount=type=secret,id=GEOIPUPDATE_ACCOUNT_ID \ | RUN --mount=type=secret,id=GEOIPUPDATE_ACCOUNT_ID \ | ||||||
|     --mount=type=secret,id=GEOIPUPDATE_LICENSE_KEY \ |     --mount=type=secret,id=GEOIPUPDATE_LICENSE_KEY \ | ||||||
|     mkdir -p /usr/share/GeoIP && \ |     mkdir -p /usr/share/GeoIP && \ | ||||||
|     /bin/sh -c "/usr/bin/entry.sh || echo 'Failed to get GeoIP database, disabling'; exit 0" |     /bin/sh -c "GEOIPUPDATE_LICENSE_KEY_FILE=/run/secrets/GEOIPUPDATE_LICENSE_KEY /usr/bin/entry.sh || echo 'Failed to get GeoIP database, disabling'; exit 0" | ||||||
|  |  | ||||||
| # Stage 5: Download uv | # Stage 5: Download uv | ||||||
| FROM ghcr.io/astral-sh/uv:0.6.16 AS uv | FROM ghcr.io/astral-sh/uv:0.7.4 AS uv | ||||||
| # Stage 6: Base python image | # Stage 6: Base python image | ||||||
| FROM ghcr.io/goauthentik/fips-python:3.12.10-slim-bookworm-fips AS python-base | FROM ghcr.io/goauthentik/fips-python:3.13.3-slim-bookworm-fips AS python-base | ||||||
|  |  | ||||||
| ENV VENV_PATH="/ak-root/.venv" \ | ENV VENV_PATH="/ak-root/.venv" \ | ||||||
|     PATH="/lifecycle:/ak-root/.venv/bin:$PATH" \ |     PATH="/lifecycle:/ak-root/.venv/bin:$PATH" \ | ||||||
|  | |||||||
| @ -42,4 +42,4 @@ See [SECURITY.md](SECURITY.md) | |||||||
|  |  | ||||||
| ## Adoption and Contributions | ## Adoption and Contributions | ||||||
|  |  | ||||||
| Your organization uses authentik? We'd love to add your logo to the readme and our website! Email us @ hello@goauthentik.io or open a GitHub Issue/PR! For more information on how to contribute to authentik, please refer to our [CONTRIBUTING.md file](./CONTRIBUTING.md). | Your organization uses authentik? We'd love to add your logo to the readme and our website! Email us @ hello@goauthentik.io or open a GitHub Issue/PR! For more information on how to contribute to authentik, please refer to our [contribution guide](https://docs.goauthentik.io/docs/developer-docs?utm_source=github). | ||||||
|  | |||||||
| @ -20,8 +20,8 @@ Even if the issue is not a CVE, we still greatly appreciate your help in hardeni | |||||||
|  |  | ||||||
| | Version   | Supported | | | Version   | Supported | | ||||||
| | --------- | --------- | | | --------- | --------- | | ||||||
| | 2024.12.x | ✅        | |  | ||||||
| | 2025.2.x  | ✅        | | | 2025.2.x  | ✅        | | ||||||
|  | | 2025.4.x  | ✅        | | ||||||
|  |  | ||||||
| ## Reporting a Vulnerability | ## Reporting a Vulnerability | ||||||
|  |  | ||||||
|  | |||||||
| @ -2,7 +2,7 @@ | |||||||
|  |  | ||||||
| from os import environ | from os import environ | ||||||
|  |  | ||||||
| __version__ = "2025.2.4" | __version__ = "2025.4.1" | ||||||
| ENV_GIT_HASH_KEY = "GIT_BUILD_HASH" | ENV_GIT_HASH_KEY = "GIT_BUILD_HASH" | ||||||
|  |  | ||||||
|  |  | ||||||
|  | |||||||
| @ -54,7 +54,7 @@ def create_component(generator: SchemaGenerator, name, schema, type_=ResolvedCom | |||||||
|     return component |     return component | ||||||
|  |  | ||||||
|  |  | ||||||
| def postprocess_schema_responses(result, generator: SchemaGenerator, **kwargs):  # noqa: W0613 | def postprocess_schema_responses(result, generator: SchemaGenerator, **kwargs): | ||||||
|     """Workaround to set a default response for endpoints. |     """Workaround to set a default response for endpoints. | ||||||
|     Workaround suggested at |     Workaround suggested at | ||||||
|     <https://github.com/tfranzel/drf-spectacular/issues/119#issuecomment-656970357> |     <https://github.com/tfranzel/drf-spectacular/issues/119#issuecomment-656970357> | ||||||
|  | |||||||
| @ -164,9 +164,7 @@ class BlueprintEntry: | |||||||
|         """Get the blueprint model, with yaml tags resolved if present""" |         """Get the blueprint model, with yaml tags resolved if present""" | ||||||
|         return str(self.tag_resolver(self.model, blueprint)) |         return str(self.tag_resolver(self.model, blueprint)) | ||||||
|  |  | ||||||
|     def get_permissions( |     def get_permissions(self, blueprint: "Blueprint") -> Generator[BlueprintEntryPermission]: | ||||||
|         self, blueprint: "Blueprint" |  | ||||||
|     ) -> Generator[BlueprintEntryPermission, None, None]: |  | ||||||
|         """Get permissions of this entry, with all yaml tags resolved""" |         """Get permissions of this entry, with all yaml tags resolved""" | ||||||
|         for perm in self.permissions: |         for perm in self.permissions: | ||||||
|             yield BlueprintEntryPermission( |             yield BlueprintEntryPermission( | ||||||
|  | |||||||
| @ -16,7 +16,7 @@ def migrate_custom_css(apps: Apps, schema_editor: BaseDatabaseSchemaEditor): | |||||||
|     if not path.exists(): |     if not path.exists(): | ||||||
|         return |         return | ||||||
|     css = path.read_text() |     css = path.read_text() | ||||||
|     Brand.objects.using(db_alias).update(branding_custom_css=css) |     Brand.objects.using(db_alias).all().update(branding_custom_css=css) | ||||||
|  |  | ||||||
|  |  | ||||||
| class Migration(migrations.Migration): | class Migration(migrations.Migration): | ||||||
|  | |||||||
| @ -5,10 +5,10 @@ from typing import Any | |||||||
| from django.db.models import F, Q | from django.db.models import F, Q | ||||||
| from django.db.models import Value as V | from django.db.models import Value as V | ||||||
| from django.http.request import HttpRequest | from django.http.request import HttpRequest | ||||||
| from sentry_sdk import get_current_span |  | ||||||
|  |  | ||||||
| from authentik import get_full_version | from authentik import get_full_version | ||||||
| from authentik.brands.models import Brand | from authentik.brands.models import Brand | ||||||
|  | from authentik.lib.sentry import get_http_meta | ||||||
| from authentik.tenants.models import Tenant | from authentik.tenants.models import Tenant | ||||||
|  |  | ||||||
| _q_default = Q(default=True) | _q_default = Q(default=True) | ||||||
| @ -32,13 +32,9 @@ def context_processor(request: HttpRequest) -> dict[str, Any]: | |||||||
|     """Context Processor that injects brand object into every template""" |     """Context Processor that injects brand object into every template""" | ||||||
|     brand = getattr(request, "brand", DEFAULT_BRAND) |     brand = getattr(request, "brand", DEFAULT_BRAND) | ||||||
|     tenant = getattr(request, "tenant", Tenant()) |     tenant = getattr(request, "tenant", Tenant()) | ||||||
|     trace = "" |  | ||||||
|     span = get_current_span() |  | ||||||
|     if span: |  | ||||||
|         trace = span.to_traceparent() |  | ||||||
|     return { |     return { | ||||||
|         "brand": brand, |         "brand": brand, | ||||||
|         "footer_links": tenant.footer_links, |         "footer_links": tenant.footer_links, | ||||||
|         "sentry_trace": trace, |         "html_meta": {**get_http_meta()}, | ||||||
|         "version": get_full_version(), |         "version": get_full_version(), | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -99,9 +99,8 @@ class GroupSerializer(ModelSerializer): | |||||||
|             if superuser |             if superuser | ||||||
|             else "authentik_core.disable_group_superuser" |             else "authentik_core.disable_group_superuser" | ||||||
|         ) |         ) | ||||||
|         has_perm = user.has_perm(perm) |         if self.instance or superuser: | ||||||
|         if self.instance and not has_perm: |             has_perm = user.has_perm(perm) or user.has_perm(perm, self.instance) | ||||||
|             has_perm = user.has_perm(perm, self.instance) |  | ||||||
|             if not has_perm: |             if not has_perm: | ||||||
|                 raise ValidationError( |                 raise ValidationError( | ||||||
|                     _( |                     _( | ||||||
|  | |||||||
| @ -2,6 +2,7 @@ | |||||||
|  |  | ||||||
| from django.apps import apps | from django.apps import apps | ||||||
| from django.contrib.auth.management import create_permissions | from django.contrib.auth.management import create_permissions | ||||||
|  | from django.core.management import call_command | ||||||
| from django.core.management.base import BaseCommand, no_translations | from django.core.management.base import BaseCommand, no_translations | ||||||
| from guardian.management import create_anonymous_user | from guardian.management import create_anonymous_user | ||||||
|  |  | ||||||
| @ -16,6 +17,10 @@ class Command(BaseCommand): | |||||||
|         """Check permissions for all apps""" |         """Check permissions for all apps""" | ||||||
|         for tenant in Tenant.objects.filter(ready=True): |         for tenant in Tenant.objects.filter(ready=True): | ||||||
|             with tenant: |             with tenant: | ||||||
|  |                 # See https://code.djangoproject.com/ticket/28417 | ||||||
|  |                 # Remove potential lingering old permissions | ||||||
|  |                 call_command("remove_stale_contenttypes", "--no-input") | ||||||
|  |  | ||||||
|                 for app in apps.get_app_configs(): |                 for app in apps.get_app_configs(): | ||||||
|                     self.stdout.write(f"Checking app {app.name} ({app.label})\n") |                     self.stdout.write(f"Checking app {app.name} ({app.label})\n") | ||||||
|                     create_permissions(app, verbosity=0) |                     create_permissions(app, verbosity=0) | ||||||
|  | |||||||
| @ -31,7 +31,10 @@ class PickleSerializer: | |||||||
|  |  | ||||||
|     def loads(self, data): |     def loads(self, data): | ||||||
|         """Unpickle data to be loaded from redis""" |         """Unpickle data to be loaded from redis""" | ||||||
|  |         try: | ||||||
|             return pickle.loads(data)  # nosec |             return pickle.loads(data)  # nosec | ||||||
|  |         except Exception: | ||||||
|  |             return {} | ||||||
|  |  | ||||||
|  |  | ||||||
| def _migrate_session( | def _migrate_session( | ||||||
|  | |||||||
| @ -0,0 +1,27 @@ | |||||||
|  | # Generated by Django 5.1.9 on 2025-05-14 11:15 | ||||||
|  |  | ||||||
|  | from django.apps.registry import Apps | ||||||
|  | from django.db import migrations | ||||||
|  | from django.db.backends.base.schema import BaseDatabaseSchemaEditor | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def remove_old_authenticated_session_content_type( | ||||||
|  |     apps: Apps, schema_editor: BaseDatabaseSchemaEditor | ||||||
|  | ): | ||||||
|  |     db_alias = schema_editor.connection.alias | ||||||
|  |     ContentType = apps.get_model("contenttypes", "ContentType") | ||||||
|  |  | ||||||
|  |     ContentType.objects.using(db_alias).filter(model="oldauthenticatedsession").delete() | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class Migration(migrations.Migration): | ||||||
|  |  | ||||||
|  |     dependencies = [ | ||||||
|  |         ("authentik_core", "0047_delete_oldauthenticatedsession"), | ||||||
|  |     ] | ||||||
|  |  | ||||||
|  |     operations = [ | ||||||
|  |         migrations.RunPython( | ||||||
|  |             code=remove_old_authenticated_session_content_type, | ||||||
|  |         ), | ||||||
|  |     ] | ||||||
| @ -21,7 +21,9 @@ | |||||||
|         <script src="{% versioned_script 'dist/standalone/loading/index-%v.js' %}" type="module"></script> |         <script src="{% versioned_script 'dist/standalone/loading/index-%v.js' %}" type="module"></script> | ||||||
|         {% block head %} |         {% block head %} | ||||||
|         {% endblock %} |         {% endblock %} | ||||||
|         <meta name="sentry-trace" content="{{ sentry_trace }}" /> |         {% for key, value in html_meta.items %} | ||||||
|  |         <meta name="{{key}}" content="{{ value }}" /> | ||||||
|  |         {% endfor %} | ||||||
|     </head> |     </head> | ||||||
|     <body> |     <body> | ||||||
|         {% block body %} |         {% block body %} | ||||||
|  | |||||||
| @ -124,6 +124,16 @@ class TestGroupsAPI(APITestCase): | |||||||
|             {"is_superuser": ["User does not have permission to set superuser status to True."]}, |             {"is_superuser": ["User does not have permission to set superuser status to True."]}, | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|  |     def test_superuser_no_perm_no_superuser(self): | ||||||
|  |         """Test creating a group without permission and without superuser flag""" | ||||||
|  |         assign_perm("authentik_core.add_group", self.login_user) | ||||||
|  |         self.client.force_login(self.login_user) | ||||||
|  |         res = self.client.post( | ||||||
|  |             reverse("authentik_api:group-list"), | ||||||
|  |             data={"name": generate_id(), "is_superuser": False}, | ||||||
|  |         ) | ||||||
|  |         self.assertEqual(res.status_code, 201) | ||||||
|  |  | ||||||
|     def test_superuser_update_no_perm(self): |     def test_superuser_update_no_perm(self): | ||||||
|         """Test updating a superuser group without permission""" |         """Test updating a superuser group without permission""" | ||||||
|         group = Group.objects.create(name=generate_id(), is_superuser=True) |         group = Group.objects.create(name=generate_id(), is_superuser=True) | ||||||
|  | |||||||
| @ -132,13 +132,14 @@ class LicenseKey: | |||||||
|         """Get a summarized version of all (not expired) licenses""" |         """Get a summarized version of all (not expired) licenses""" | ||||||
|         total = LicenseKey(get_license_aud(), 0, "Summarized license", 0, 0) |         total = LicenseKey(get_license_aud(), 0, "Summarized license", 0, 0) | ||||||
|         for lic in License.objects.all(): |         for lic in License.objects.all(): | ||||||
|  |             if lic.is_valid: | ||||||
|                 total.internal_users += lic.internal_users |                 total.internal_users += lic.internal_users | ||||||
|                 total.external_users += lic.external_users |                 total.external_users += lic.external_users | ||||||
|  |                 total.license_flags.extend(lic.status.license_flags) | ||||||
|             exp_ts = int(mktime(lic.expiry.timetuple())) |             exp_ts = int(mktime(lic.expiry.timetuple())) | ||||||
|             if total.exp == 0: |             if total.exp == 0: | ||||||
|                 total.exp = exp_ts |                 total.exp = exp_ts | ||||||
|             total.exp = max(total.exp, exp_ts) |             total.exp = max(total.exp, exp_ts) | ||||||
|             total.license_flags.extend(lic.status.license_flags) |  | ||||||
|         return total |         return total | ||||||
|  |  | ||||||
|     @staticmethod |     @staticmethod | ||||||
|  | |||||||
| @ -39,6 +39,10 @@ class License(SerializerModel): | |||||||
|     internal_users = models.BigIntegerField() |     internal_users = models.BigIntegerField() | ||||||
|     external_users = models.BigIntegerField() |     external_users = models.BigIntegerField() | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def is_valid(self) -> bool: | ||||||
|  |         return self.expiry >= now() | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def serializer(self) -> type[BaseSerializer]: |     def serializer(self) -> type[BaseSerializer]: | ||||||
|         from authentik.enterprise.api import LicenseSerializer |         from authentik.enterprise.api import LicenseSerializer | ||||||
|  | |||||||
| @ -8,6 +8,7 @@ from django.test import TestCase | |||||||
| from django.utils.timezone import now | from django.utils.timezone import now | ||||||
| from rest_framework.exceptions import ValidationError | from rest_framework.exceptions import ValidationError | ||||||
|  |  | ||||||
|  | from authentik.core.models import User | ||||||
| from authentik.enterprise.license import LicenseKey | from authentik.enterprise.license import LicenseKey | ||||||
| from authentik.enterprise.models import ( | from authentik.enterprise.models import ( | ||||||
|     THRESHOLD_READ_ONLY_WEEKS, |     THRESHOLD_READ_ONLY_WEEKS, | ||||||
| @ -71,9 +72,9 @@ class TestEnterpriseLicense(TestCase): | |||||||
|     ) |     ) | ||||||
|     def test_valid_multiple(self): |     def test_valid_multiple(self): | ||||||
|         """Check license verification""" |         """Check license verification""" | ||||||
|         lic = License.objects.create(key=generate_id()) |         lic = License.objects.create(key=generate_id(), expiry=expiry_valid) | ||||||
|         self.assertTrue(lic.status.status().is_valid) |         self.assertTrue(lic.status.status().is_valid) | ||||||
|         lic2 = License.objects.create(key=generate_id()) |         lic2 = License.objects.create(key=generate_id(), expiry=expiry_valid) | ||||||
|         self.assertTrue(lic2.status.status().is_valid) |         self.assertTrue(lic2.status.status().is_valid) | ||||||
|         total = LicenseKey.get_total() |         total = LicenseKey.get_total() | ||||||
|         self.assertEqual(total.internal_users, 200) |         self.assertEqual(total.internal_users, 200) | ||||||
| @ -232,7 +233,9 @@ class TestEnterpriseLicense(TestCase): | |||||||
|     ) |     ) | ||||||
|     def test_expiry_expired(self): |     def test_expiry_expired(self): | ||||||
|         """Check license verification""" |         """Check license verification""" | ||||||
|         License.objects.create(key=generate_id()) |         User.objects.all().delete() | ||||||
|  |         License.objects.all().delete() | ||||||
|  |         License.objects.create(key=generate_id(), expiry=expiry_expired) | ||||||
|         self.assertEqual(LicenseKey.get_total().summary().status, LicenseUsageStatus.EXPIRED) |         self.assertEqual(LicenseKey.get_total().summary().status, LicenseUsageStatus.EXPIRED) | ||||||
|  |  | ||||||
|     @patch( |     @patch( | ||||||
|  | |||||||
| @ -57,7 +57,7 @@ class LogEventSerializer(PassiveSerializer): | |||||||
|  |  | ||||||
|  |  | ||||||
| @contextmanager | @contextmanager | ||||||
| def capture_logs(log_default_output=True) -> Generator[list[LogEvent], None, None]: | def capture_logs(log_default_output=True) -> Generator[list[LogEvent]]: | ||||||
|     """Capture log entries created""" |     """Capture log entries created""" | ||||||
|     logs = [] |     logs = [] | ||||||
|     cap = LogCapture() |     cap = LogCapture() | ||||||
|  | |||||||
| @ -15,6 +15,7 @@ | |||||||
|         {% endblock %} |         {% endblock %} | ||||||
|         <link rel="stylesheet" type="text/css" href="{% static 'dist/sfe/bootstrap.min.css' %}"> |         <link rel="stylesheet" type="text/css" href="{% static 'dist/sfe/bootstrap.min.css' %}"> | ||||||
|         <meta name="sentry-trace" content="{{ sentry_trace }}" /> |         <meta name="sentry-trace" content="{{ sentry_trace }}" /> | ||||||
|  |         <link rel="prefetch" href="{{ flow_background_url }}" /> | ||||||
|         {% include "base/header_js.html" %} |         {% include "base/header_js.html" %} | ||||||
|         <style> |         <style> | ||||||
|           html, |           html, | ||||||
| @ -22,7 +23,7 @@ | |||||||
|             height: 100%; |             height: 100%; | ||||||
|           } |           } | ||||||
|           body { |           body { | ||||||
|             background-image: url("{{ flow.background_url }}"); |             background-image: url("{{ flow_background_url }}"); | ||||||
|             background-repeat: no-repeat; |             background-repeat: no-repeat; | ||||||
|             background-size: cover; |             background-size: cover; | ||||||
|           } |           } | ||||||
|  | |||||||
| @ -5,9 +5,9 @@ | |||||||
|  |  | ||||||
| {% block head_before %} | {% block head_before %} | ||||||
| {{ block.super }} | {{ block.super }} | ||||||
| <link rel="prefetch" href="{{ flow.background_url }}" /> | <link rel="prefetch" href="{{ flow_background_url }}" /> | ||||||
| {% if flow.compatibility_mode and not inspector %} | {% if flow.compatibility_mode and not inspector %} | ||||||
| <script>ShadyDOM = { force: !navigator.webdriver };</script> | <script>ShadyDOM = { force: true };</script> | ||||||
| {% endif %} | {% endif %} | ||||||
| {% include "base/header_js.html" %} | {% include "base/header_js.html" %} | ||||||
| <script> | <script> | ||||||
| @ -21,7 +21,7 @@ window.authentik.flow = { | |||||||
| <script src="{% versioned_script 'dist/flow/FlowInterface-%v.js' %}" type="module"></script> | <script src="{% versioned_script 'dist/flow/FlowInterface-%v.js' %}" type="module"></script> | ||||||
| <style> | <style> | ||||||
| :root { | :root { | ||||||
|     --ak-flow-background: url("{{ flow.background_url }}"); |     --ak-flow-background: url("{{ flow_background_url }}"); | ||||||
| } | } | ||||||
| </style> | </style> | ||||||
| {% endblock %} | {% endblock %} | ||||||
|  | |||||||
| @ -13,7 +13,9 @@ class FlowInterfaceView(InterfaceView): | |||||||
|     """Flow interface""" |     """Flow interface""" | ||||||
|  |  | ||||||
|     def get_context_data(self, **kwargs: Any) -> dict[str, Any]: |     def get_context_data(self, **kwargs: Any) -> dict[str, Any]: | ||||||
|         kwargs["flow"] = get_object_or_404(Flow, slug=self.kwargs.get("flow_slug")) |         flow = get_object_or_404(Flow, slug=self.kwargs.get("flow_slug")) | ||||||
|  |         kwargs["flow"] = flow | ||||||
|  |         kwargs["flow_background_url"] = flow.background_url(self.request) | ||||||
|         kwargs["inspector"] = "inspector" in self.request.GET |         kwargs["inspector"] = "inspector" in self.request.GET | ||||||
|         return super().get_context_data(**kwargs) |         return super().get_context_data(**kwargs) | ||||||
|  |  | ||||||
|  | |||||||
| @ -363,6 +363,9 @@ def django_db_config(config: ConfigLoader | None = None) -> dict: | |||||||
|         pool_options = config.get_dict_from_b64_json("postgresql.pool_options", True) |         pool_options = config.get_dict_from_b64_json("postgresql.pool_options", True) | ||||||
|         if not pool_options: |         if not pool_options: | ||||||
|             pool_options = True |             pool_options = True | ||||||
|  |     # FIXME: Temporarily force pool to be deactivated. | ||||||
|  |     # See https://github.com/goauthentik/authentik/issues/14320 | ||||||
|  |     pool_options = False | ||||||
|  |  | ||||||
|     db = { |     db = { | ||||||
|         "default": { |         "default": { | ||||||
|  | |||||||
| @ -17,7 +17,7 @@ from ldap3.core.exceptions import LDAPException | |||||||
| from redis.exceptions import ConnectionError as RedisConnectionError | from redis.exceptions import ConnectionError as RedisConnectionError | ||||||
| from redis.exceptions import RedisError, ResponseError | from redis.exceptions import RedisError, ResponseError | ||||||
| from rest_framework.exceptions import APIException | from rest_framework.exceptions import APIException | ||||||
| from sentry_sdk import HttpTransport | from sentry_sdk import HttpTransport, get_current_scope | ||||||
| from sentry_sdk import init as sentry_sdk_init | from sentry_sdk import init as sentry_sdk_init | ||||||
| from sentry_sdk.api import set_tag | from sentry_sdk.api import set_tag | ||||||
| from sentry_sdk.integrations.argv import ArgvIntegration | from sentry_sdk.integrations.argv import ArgvIntegration | ||||||
| @ -27,6 +27,7 @@ from sentry_sdk.integrations.redis import RedisIntegration | |||||||
| from sentry_sdk.integrations.socket import SocketIntegration | from sentry_sdk.integrations.socket import SocketIntegration | ||||||
| from sentry_sdk.integrations.stdlib import StdlibIntegration | from sentry_sdk.integrations.stdlib import StdlibIntegration | ||||||
| from sentry_sdk.integrations.threading import ThreadingIntegration | from sentry_sdk.integrations.threading import ThreadingIntegration | ||||||
|  | from sentry_sdk.tracing import BAGGAGE_HEADER_NAME, SENTRY_TRACE_HEADER_NAME | ||||||
| from structlog.stdlib import get_logger | from structlog.stdlib import get_logger | ||||||
| from websockets.exceptions import WebSocketException | from websockets.exceptions import WebSocketException | ||||||
|  |  | ||||||
| @ -95,6 +96,8 @@ def traces_sampler(sampling_context: dict) -> float: | |||||||
|         return 0 |         return 0 | ||||||
|     if _type == "websocket": |     if _type == "websocket": | ||||||
|         return 0 |         return 0 | ||||||
|  |     if CONFIG.get_bool("debug"): | ||||||
|  |         return 1 | ||||||
|     return float(CONFIG.get("error_reporting.sample_rate", 0.1)) |     return float(CONFIG.get("error_reporting.sample_rate", 0.1)) | ||||||
|  |  | ||||||
|  |  | ||||||
| @ -167,3 +170,14 @@ def before_send(event: dict, hint: dict) -> dict | None: | |||||||
|     if settings.DEBUG: |     if settings.DEBUG: | ||||||
|         return None |         return None | ||||||
|     return event |     return event | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def get_http_meta(): | ||||||
|  |     """Get sentry-related meta key-values""" | ||||||
|  |     scope = get_current_scope() | ||||||
|  |     meta = { | ||||||
|  |         SENTRY_TRACE_HEADER_NAME: scope.get_traceparent() or "", | ||||||
|  |     } | ||||||
|  |     if bag := scope.get_baggage(): | ||||||
|  |         meta[BAGGAGE_HEADER_NAME] = bag.serialize() | ||||||
|  |     return meta | ||||||
|  | |||||||
| @ -59,7 +59,7 @@ class PropertyMappingManager: | |||||||
|         request: HttpRequest | None, |         request: HttpRequest | None, | ||||||
|         return_mapping: bool = False, |         return_mapping: bool = False, | ||||||
|         **kwargs, |         **kwargs, | ||||||
|     ) -> Generator[tuple[dict, PropertyMapping], None]: |     ) -> Generator[tuple[dict, PropertyMapping]]: | ||||||
|         """Iterate over all mappings that were pre-compiled and |         """Iterate over all mappings that were pre-compiled and | ||||||
|         execute all of them with the given context""" |         execute all of them with the given context""" | ||||||
|         if not self.__has_compiled: |         if not self.__has_compiled: | ||||||
|  | |||||||
| @ -494,86 +494,88 @@ class TestConfig(TestCase): | |||||||
|             }, |             }, | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|     def test_db_pool(self): |     # FIXME: Temporarily force pool to be deactivated. | ||||||
|         """Test DB Config with pool""" |     # See https://github.com/goauthentik/authentik/issues/14320 | ||||||
|         config = ConfigLoader() |     # def test_db_pool(self): | ||||||
|         config.set("postgresql.host", "foo") |     #     """Test DB Config with pool""" | ||||||
|         config.set("postgresql.name", "foo") |     #     config = ConfigLoader() | ||||||
|         config.set("postgresql.user", "foo") |     #     config.set("postgresql.host", "foo") | ||||||
|         config.set("postgresql.password", "foo") |     #     config.set("postgresql.name", "foo") | ||||||
|         config.set("postgresql.port", "foo") |     #     config.set("postgresql.user", "foo") | ||||||
|         config.set("postgresql.test.name", "foo") |     #     config.set("postgresql.password", "foo") | ||||||
|         config.set("postgresql.use_pool", True) |     #     config.set("postgresql.port", "foo") | ||||||
|         conf = django_db_config(config) |     #     config.set("postgresql.test.name", "foo") | ||||||
|         self.assertEqual( |     #     config.set("postgresql.use_pool", True) | ||||||
|             conf, |     #     conf = django_db_config(config) | ||||||
|             { |     #     self.assertEqual( | ||||||
|                 "default": { |     #         conf, | ||||||
|                     "ENGINE": "authentik.root.db", |     #         { | ||||||
|                     "HOST": "foo", |     #             "default": { | ||||||
|                     "NAME": "foo", |     #                 "ENGINE": "authentik.root.db", | ||||||
|                     "OPTIONS": { |     #                 "HOST": "foo", | ||||||
|                         "pool": True, |     #                 "NAME": "foo", | ||||||
|                         "sslcert": None, |     #                 "OPTIONS": { | ||||||
|                         "sslkey": None, |     #                     "pool": True, | ||||||
|                         "sslmode": None, |     #                     "sslcert": None, | ||||||
|                         "sslrootcert": None, |     #                     "sslkey": None, | ||||||
|                     }, |     #                     "sslmode": None, | ||||||
|                     "PASSWORD": "foo", |     #                     "sslrootcert": None, | ||||||
|                     "PORT": "foo", |     #                 }, | ||||||
|                     "TEST": {"NAME": "foo"}, |     #                 "PASSWORD": "foo", | ||||||
|                     "USER": "foo", |     #                 "PORT": "foo", | ||||||
|                     "CONN_MAX_AGE": 0, |     #                 "TEST": {"NAME": "foo"}, | ||||||
|                     "CONN_HEALTH_CHECKS": False, |     #                 "USER": "foo", | ||||||
|                     "DISABLE_SERVER_SIDE_CURSORS": False, |     #                 "CONN_MAX_AGE": 0, | ||||||
|                 } |     #                 "CONN_HEALTH_CHECKS": False, | ||||||
|             }, |     #                 "DISABLE_SERVER_SIDE_CURSORS": False, | ||||||
|         ) |     #             } | ||||||
|  |     #         }, | ||||||
|  |     #     ) | ||||||
|  |  | ||||||
|     def test_db_pool_options(self): |     # def test_db_pool_options(self): | ||||||
|         """Test DB Config with pool""" |     #     """Test DB Config with pool""" | ||||||
|         config = ConfigLoader() |     #     config = ConfigLoader() | ||||||
|         config.set("postgresql.host", "foo") |     #     config.set("postgresql.host", "foo") | ||||||
|         config.set("postgresql.name", "foo") |     #     config.set("postgresql.name", "foo") | ||||||
|         config.set("postgresql.user", "foo") |     #     config.set("postgresql.user", "foo") | ||||||
|         config.set("postgresql.password", "foo") |     #     config.set("postgresql.password", "foo") | ||||||
|         config.set("postgresql.port", "foo") |     #     config.set("postgresql.port", "foo") | ||||||
|         config.set("postgresql.test.name", "foo") |     #     config.set("postgresql.test.name", "foo") | ||||||
|         config.set("postgresql.use_pool", True) |     #     config.set("postgresql.use_pool", True) | ||||||
|         config.set( |     #     config.set( | ||||||
|             "postgresql.pool_options", |     #         "postgresql.pool_options", | ||||||
|             base64.b64encode( |     #         base64.b64encode( | ||||||
|                 dumps( |     #             dumps( | ||||||
|                     { |     #                 { | ||||||
|                         "max_size": 15, |     #                     "max_size": 15, | ||||||
|                     } |     #                 } | ||||||
|                 ).encode() |     #             ).encode() | ||||||
|             ).decode(), |     #         ).decode(), | ||||||
|         ) |     #     ) | ||||||
|         conf = django_db_config(config) |     #     conf = django_db_config(config) | ||||||
|         self.assertEqual( |     #     self.assertEqual( | ||||||
|             conf, |     #         conf, | ||||||
|             { |     #         { | ||||||
|                 "default": { |     #             "default": { | ||||||
|                     "ENGINE": "authentik.root.db", |     #                 "ENGINE": "authentik.root.db", | ||||||
|                     "HOST": "foo", |     #                 "HOST": "foo", | ||||||
|                     "NAME": "foo", |     #                 "NAME": "foo", | ||||||
|                     "OPTIONS": { |     #                 "OPTIONS": { | ||||||
|                         "pool": { |     #                     "pool": { | ||||||
|                             "max_size": 15, |     #                         "max_size": 15, | ||||||
|                         }, |     #                     }, | ||||||
|                         "sslcert": None, |     #                     "sslcert": None, | ||||||
|                         "sslkey": None, |     #                     "sslkey": None, | ||||||
|                         "sslmode": None, |     #                     "sslmode": None, | ||||||
|                         "sslrootcert": None, |     #                     "sslrootcert": None, | ||||||
|                     }, |     #                 }, | ||||||
|                     "PASSWORD": "foo", |     #                 "PASSWORD": "foo", | ||||||
|                     "PORT": "foo", |     #                 "PORT": "foo", | ||||||
|                     "TEST": {"NAME": "foo"}, |     #                 "TEST": {"NAME": "foo"}, | ||||||
|                     "USER": "foo", |     #                 "USER": "foo", | ||||||
|                     "CONN_MAX_AGE": 0, |     #                 "CONN_MAX_AGE": 0, | ||||||
|                     "CONN_HEALTH_CHECKS": False, |     #                 "CONN_HEALTH_CHECKS": False, | ||||||
|                     "DISABLE_SERVER_SIDE_CURSORS": False, |     #                 "DISABLE_SERVER_SIDE_CURSORS": False, | ||||||
|                 } |     #             } | ||||||
|             }, |     #         }, | ||||||
|         ) |     #     ) | ||||||
|  | |||||||
| @ -199,7 +199,7 @@ class SCIMGroupClient(SCIMClient[Group, SCIMProviderGroup, SCIMGroupSchema]): | |||||||
|             chunk_size = len(ops) |             chunk_size = len(ops) | ||||||
|         if len(ops) < 1: |         if len(ops) < 1: | ||||||
|             return |             return | ||||||
|         for chunk in batched(ops, chunk_size): |         for chunk in batched(ops, chunk_size, strict=False): | ||||||
|             req = PatchRequest(Operations=list(chunk)) |             req = PatchRequest(Operations=list(chunk)) | ||||||
|             self._request( |             self._request( | ||||||
|                 "PATCH", |                 "PATCH", | ||||||
|  | |||||||
| @ -99,6 +99,7 @@ class RBACPermissionViewSet(ReadOnlyModelViewSet): | |||||||
|     filterset_class = PermissionFilter |     filterset_class = PermissionFilter | ||||||
|     permission_classes = [IsAuthenticated] |     permission_classes = [IsAuthenticated] | ||||||
|     search_fields = [ |     search_fields = [ | ||||||
|  |         "name", | ||||||
|         "codename", |         "codename", | ||||||
|         "content_type__model", |         "content_type__model", | ||||||
|         "content_type__app_label", |         "content_type__app_label", | ||||||
|  | |||||||
| @ -11,7 +11,7 @@ from django.test.runner import DiscoverRunner | |||||||
| from authentik.lib.config import CONFIG | from authentik.lib.config import CONFIG | ||||||
| from authentik.lib.sentry import sentry_init | from authentik.lib.sentry import sentry_init | ||||||
| from authentik.root.signals import post_startup, pre_startup, startup | from authentik.root.signals import post_startup, pre_startup, startup | ||||||
| from tests.e2e.utils import get_docker_tag | from tests.docker import get_docker_tag | ||||||
|  |  | ||||||
| # globally set maxDiff to none to show full assert error | # globally set maxDiff to none to show full assert error | ||||||
| TestCase.maxDiff = None | TestCase.maxDiff = None | ||||||
|  | |||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @ -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.4 Blueprint schema", |     "title": "authentik 2025.4.1 Blueprint schema", | ||||||
|     "required": [ |     "required": [ | ||||||
|         "version", |         "version", | ||||||
|         "entries" |         "entries" | ||||||
|  | |||||||
| @ -31,7 +31,7 @@ services: | |||||||
|     volumes: |     volumes: | ||||||
|       - redis:/data |       - redis:/data | ||||||
|   server: |   server: | ||||||
|     image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.2.4} |     image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.4.1} | ||||||
|     restart: unless-stopped |     restart: unless-stopped | ||||||
|     command: server |     command: server | ||||||
|     environment: |     environment: | ||||||
| @ -55,7 +55,7 @@ services: | |||||||
|       redis: |       redis: | ||||||
|         condition: service_healthy |         condition: service_healthy | ||||||
|   worker: |   worker: | ||||||
|     image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.2.4} |     image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.4.1} | ||||||
|     restart: unless-stopped |     restart: unless-stopped | ||||||
|     command: worker |     command: worker | ||||||
|     environment: |     environment: | ||||||
|  | |||||||
							
								
								
									
										16
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								go.mod
									
									
									
									
									
								
							| @ -5,7 +5,7 @@ go 1.24.0 | |||||||
| require ( | require ( | ||||||
| 	beryju.io/ldap v0.1.0 | 	beryju.io/ldap v0.1.0 | ||||||
| 	github.com/coreos/go-oidc/v3 v3.14.1 | 	github.com/coreos/go-oidc/v3 v3.14.1 | ||||||
| 	github.com/getsentry/sentry-go v0.32.0 | 	github.com/getsentry/sentry-go v0.33.0 | ||||||
| 	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.11 | 	github.com/go-ldap/ldap/v3 v3.4.11 | ||||||
| 	github.com/go-openapi/runtime v0.28.0 | 	github.com/go-openapi/runtime v0.28.0 | ||||||
| @ -19,18 +19,18 @@ require ( | |||||||
| 	github.com/jellydator/ttlcache/v3 v3.3.0 | 	github.com/jellydator/ttlcache/v3 v3.3.0 | ||||||
| 	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.1 | ||||||
| 	github.com/prometheus/client_golang v1.22.0 | 	github.com/prometheus/client_golang v1.22.0 | ||||||
| 	github.com/redis/go-redis/v9 v9.7.3 | 	github.com/redis/go-redis/v9 v9.8.0 | ||||||
| 	github.com/sethvargo/go-envconfig v1.2.0 | 	github.com/sethvargo/go-envconfig v1.3.0 | ||||||
| 	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.2025024.9 | 	goauthentik.io/api/v3 v3.2025041.1 | ||||||
| 	golang.org/x/exp v0.0.0-20230210204819-062eb4c674ab | 	golang.org/x/exp v0.0.0-20230210204819-062eb4c674ab | ||||||
| 	golang.org/x/oauth2 v0.29.0 | 	golang.org/x/oauth2 v0.30.0 | ||||||
| 	golang.org/x/sync v0.13.0 | 	golang.org/x/sync v0.14.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 | ||||||
| ) | ) | ||||||
| @ -75,7 +75,7 @@ require ( | |||||||
| 	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.36.0 // indirect | ||||||
| 	golang.org/x/sys v0.31.0 // indirect | 	golang.org/x/sys v0.31.0 // indirect | ||||||
| 	golang.org/x/text v0.23.0 // indirect | 	golang.org/x/text v0.24.0 // indirect | ||||||
| 	google.golang.org/protobuf v1.36.5 // indirect | 	google.golang.org/protobuf v1.36.5 // indirect | ||||||
| 	gopkg.in/yaml.v3 v3.0.1 // indirect | 	gopkg.in/yaml.v3 v3.0.1 // indirect | ||||||
| ) | ) | ||||||
|  | |||||||
							
								
								
									
										36
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										36
									
								
								go.sum
									
									
									
									
									
								
							| @ -69,8 +69,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m | |||||||
| github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= | ||||||
| github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= | github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= | ||||||
| github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= | github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= | ||||||
| github.com/getsentry/sentry-go v0.32.0 h1:YKs+//QmwE3DcYtfKRH8/KyOOF/I6Qnx7qYGNHCGmCY= | github.com/getsentry/sentry-go v0.33.0 h1:YWyDii0KGVov3xOaamOnF0mjOrqSjBqwv48UEzn7QFg= | ||||||
| github.com/getsentry/sentry-go v0.32.0/go.mod h1:CYNcMMz73YigoHljQRG+qPF+eMq8gG72XcGN/p71BAY= | github.com/getsentry/sentry-go v0.33.0/go.mod h1:C55omcY9ChRQIUcVcGcs+Zdy4ZpQGvNJ7JYHIoSWOtE= | ||||||
| github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 h1:BP4M0CvQ4S3TGls2FvczZtj5Re/2ZzkV9VwqPHH/3Bo= | github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 h1:BP4M0CvQ4S3TGls2FvczZtj5Re/2ZzkV9VwqPHH/3Bo= | ||||||
| github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= | github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0= | ||||||
| github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= | github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= | ||||||
| @ -230,8 +230,8 @@ github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+ | |||||||
| github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= | github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= | ||||||
| github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= | github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= | ||||||
| github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= | github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= | ||||||
| github.com/pires/go-proxyproto v0.8.0 h1:5unRmEAPbHXHuLjDg01CxJWf91cw3lKHc/0xzKpXEe0= | github.com/pires/go-proxyproto v0.8.1 h1:9KEixbdJfhrbtjpz/ZwCdWDD2Xem0NZ38qMYaASJgp0= | ||||||
| github.com/pires/go-proxyproto v0.8.0/go.mod h1:iknsfgnH8EkjrMeMyvfKByp9TiBZCKZM0jx2xmKqnVY= | github.com/pires/go-proxyproto v0.8.1/go.mod h1:ZKAAyp3cgy5Y5Mo4n9AlScrkCZwUy0g3Jf+slqQVcuU= | ||||||
| github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= | 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= | ||||||
| @ -245,14 +245,14 @@ github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ | |||||||
| github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= | github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= | ||||||
| github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= | github.com/prometheus/procfs v0.15.1 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.3 h1:YpPyAayJV+XErNsatSElgRZZVCwXX9QzkKYNvO7x0wM= | github.com/redis/go-redis/v9 v9.8.0 h1:q3nRvjrlge/6UD7eTu/DSg2uYiU2mCL0G/uzBWqhicI= | ||||||
| github.com/redis/go-redis/v9 v9.7.3/go.mod h1:bGUrSggJ9X9GUmZpZNEOQKaANxSGgOEBRltRTZHSvrA= | github.com/redis/go-redis/v9 v9.8.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= | ||||||
| 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= | ||||||
| github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= | github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= | ||||||
| github.com/sethvargo/go-envconfig v1.2.0 h1:q3XkOZWkC+G1sMLCrw9oPGTjYexygLOXDmGUit1ti8Q= | github.com/sethvargo/go-envconfig v1.3.0 h1:gJs+Fuv8+f05omTpwWIu6KmuseFAXKrIaOZSh8RMt0U= | ||||||
| github.com/sethvargo/go-envconfig v1.2.0/go.mod h1:JLd0KFWQYzyENqnEPWWZ49i4vzZo/6nRidxI8YvGiHw= | github.com/sethvargo/go-envconfig v1.3.0/go.mod h1:JLd0KFWQYzyENqnEPWWZ49i4vzZo/6nRidxI8YvGiHw= | ||||||
| github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= | github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= | ||||||
| github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= | github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= | ||||||
| github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= | github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= | ||||||
| @ -290,8 +290,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.2025024.9 h1:i3tbkyotE32ZpJ729BsPWTuLQUdtZ54Li4aP1amZzsM= | goauthentik.io/api/v3 v3.2025041.1 h1:GAN6AoTmfnCGgx1SyM07jP4/LR/T3rkTEyShSBd3Co8= | ||||||
| goauthentik.io/api/v3 v3.2025024.9/go.mod h1:zz+mEZg8rY/7eEjkMGWJ2DnGqk+zqxuybGCGrR2O4Kw= | goauthentik.io/api/v3 v3.2025041.1/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= | ||||||
| @ -358,16 +358,16 @@ golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/ | |||||||
| golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= | golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= | ||||||
| golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= | golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= | ||||||
| golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= | golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= | ||||||
| golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= | golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= | ||||||
| golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= | golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= | ||||||
| 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.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98= | golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= | ||||||
| golang.org/x/oauth2 v0.29.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8= | golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= | ||||||
| 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= | ||||||
| @ -376,8 +376,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ | |||||||
| golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||||
| golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||||
| golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||||
| golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= | golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= | ||||||
| golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= | golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= | ||||||
| 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= | ||||||
| @ -412,8 +412,8 @@ golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | |||||||
| golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||||
| golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= | ||||||
| golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||||||
| golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= | golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= | ||||||
| golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= | golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= | ||||||
| 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= | ||||||
|  | |||||||
| @ -29,4 +29,4 @@ func UserAgent() string { | |||||||
| 	return fmt.Sprintf("authentik@%s", FullVersion()) | 	return fmt.Sprintf("authentik@%s", FullVersion()) | ||||||
| } | } | ||||||
|  |  | ||||||
| const VERSION = "2025.2.4" | const VERSION = "2025.4.1" | ||||||
|  | |||||||
| @ -56,6 +56,7 @@ EXPOSE 3389 6636 9300 | |||||||
|  |  | ||||||
| USER 1000 | USER 1000 | ||||||
|  |  | ||||||
| ENV GOFIPS=1 | ENV TMPDIR=/dev/shm/ \ | ||||||
|  |     GOFIPS=1 | ||||||
|  |  | ||||||
| ENTRYPOINT ["/ldap"] | ENTRYPOINT ["/ldap"] | ||||||
|  | |||||||
| @ -62,7 +62,8 @@ function prepare_debug { | |||||||
|     export DEBIAN_FRONTEND=noninteractive |     export DEBIAN_FRONTEND=noninteractive | ||||||
|     apt-get update |     apt-get update | ||||||
|     apt-get install -y --no-install-recommends krb5-kdc krb5-user krb5-admin-server libkrb5-dev gcc |     apt-get install -y --no-install-recommends krb5-kdc krb5-user krb5-admin-server libkrb5-dev gcc | ||||||
|     VIRTUAL_ENV=/ak-root/.venv uv sync --frozen |     source "${VENV_PATH}/bin/activate" | ||||||
|  |     uv sync --active --frozen | ||||||
|     touch /unittest.xml |     touch /unittest.xml | ||||||
|     chown authentik:authentik /unittest.xml |     chown authentik:authentik /unittest.xml | ||||||
| } | } | ||||||
| @ -96,6 +97,7 @@ elif [[ "$1" == "test-all" ]]; then | |||||||
| elif [[ "$1" == "healthcheck" ]]; then | elif [[ "$1" == "healthcheck" ]]; then | ||||||
|     run_authentik healthcheck $(cat $MODE_FILE) |     run_authentik healthcheck $(cat $MODE_FILE) | ||||||
| elif [[ "$1" == "dump_config" ]]; then | elif [[ "$1" == "dump_config" ]]; then | ||||||
|  |     shift | ||||||
|     exec python -m authentik.lib.config $@ |     exec python -m authentik.lib.config $@ | ||||||
| elif [[ "$1" == "debug" ]]; then | elif [[ "$1" == "debug" ]]; then | ||||||
|     exec sleep infinity |     exec sleep infinity | ||||||
|  | |||||||
							
								
								
									
										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.1012.0", |                 "aws-cdk": "^2.1015.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.1012.0", |             "version": "2.1015.0", | ||||||
|             "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1012.0.tgz", |             "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1015.0.tgz", | ||||||
|             "integrity": "sha512-C6jSWkqP0hkY2Cs300VJHjspmTXDTMfB813kwZvRbd/OsKBfTBJBbYU16VoLAp1LVEOnQMf8otSlaSgzVF0X9A==", |             "integrity": "sha512-txd+yMVVybtLfiwT409+fahbP0SkiwhmQvQf6PVVYnWzDPSknxYlUNJHisHV4tJEcbHWn1QPsLmqqMT0bw8hBg==", | ||||||
|             "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.1012.0", |         "aws-cdk": "^2.1015.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.4 |     Default: 2025.4.1 | ||||||
|     Description: authentik Docker image tag |     Description: authentik Docker image tag | ||||||
|   AuthentikServerCPU: |   AuthentikServerCPU: | ||||||
|     Type: Number |     Type: Number | ||||||
|  | |||||||
										
											Binary file not shown.
										
									
								
							| @ -8,7 +8,6 @@ | |||||||
| # Jens L. <jens@goauthentik.io>, 2022 | # Jens L. <jens@goauthentik.io>, 2022 | ||||||
| # Lars Lehmann <lars@lars-lehmann.net>, 2023 | # Lars Lehmann <lars@lars-lehmann.net>, 2023 | ||||||
| # Johannes —/—, 2023 | # Johannes —/—, 2023 | ||||||
| # Dominic Wagner <mail@dominic-wagner.de>, 2023 |  | ||||||
| # fde4f289d99ed356ff5cfdb762dc44aa_a8a971d, 2023 | # fde4f289d99ed356ff5cfdb762dc44aa_a8a971d, 2023 | ||||||
| # Christian Foellmann <foellmann@foe-services.de>, 2023 | # Christian Foellmann <foellmann@foe-services.de>, 2023 | ||||||
| # kidhab, 2023 | # kidhab, 2023 | ||||||
| @ -30,17 +29,18 @@ | |||||||
| # Alexander Möbius, 2025 | # Alexander Möbius, 2025 | ||||||
| # Jonas, 2025 | # Jonas, 2025 | ||||||
| # Niklas Kroese, 2025 | # Niklas Kroese, 2025 | ||||||
| # 97cce0ae0cad2a2cc552d3165d04643e_de3d740, 2025 |  | ||||||
| # datenschmutz, 2025 | # datenschmutz, 2025 | ||||||
|  | # 97cce0ae0cad2a2cc552d3165d04643e_de3d740, 2025 | ||||||
|  | # Dominic Wagner <mail@dominic-wagner.de>, 2025 | ||||||
| #  | #  | ||||||
| #, fuzzy | #, fuzzy | ||||||
| msgid "" | 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-04-11 00:10+0000\n" | "POT-Creation-Date: 2025-04-23 09:00+0000\n" | ||||||
| "PO-Revision-Date: 2022-09-26 16:47+0000\n" | "PO-Revision-Date: 2022-09-26 16:47+0000\n" | ||||||
| "Last-Translator: datenschmutz, 2025\n" | "Last-Translator: Dominic Wagner <mail@dominic-wagner.de>, 2025\n" | ||||||
| "Language-Team: German (https://app.transifex.com/authentik/teams/119923/de/)\n" | "Language-Team: German (https://app.transifex.com/authentik/teams/119923/de/)\n" | ||||||
| "MIME-Version: 1.0\n" | "MIME-Version: 1.0\n" | ||||||
| "Content-Type: text/plain; charset=UTF-8\n" | "Content-Type: text/plain; charset=UTF-8\n" | ||||||
| @ -214,6 +214,7 @@ msgid "User's display name." | |||||||
| msgstr "Anzeigename" | msgstr "Anzeigename" | ||||||
|  |  | ||||||
| #: authentik/core/models.py authentik/providers/oauth2/models.py | #: authentik/core/models.py authentik/providers/oauth2/models.py | ||||||
|  | #: authentik/rbac/models.py | ||||||
| msgid "User" | msgid "User" | ||||||
| msgstr "Benutzer" | msgstr "Benutzer" | ||||||
|  |  | ||||||
| @ -402,6 +403,18 @@ msgstr "Eigenschaft" | |||||||
| msgid "Property Mappings" | msgid "Property Mappings" | ||||||
| msgstr "Eigenschaften" | msgstr "Eigenschaften" | ||||||
|  |  | ||||||
|  | #: authentik/core/models.py | ||||||
|  | msgid "session data" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/core/models.py | ||||||
|  | msgid "Session" | ||||||
|  | msgstr "Sitzung" | ||||||
|  |  | ||||||
|  | #: authentik/core/models.py | ||||||
|  | msgid "Sessions" | ||||||
|  | msgstr "Sitzungen" | ||||||
|  |  | ||||||
| #: authentik/core/models.py | #: authentik/core/models.py | ||||||
| msgid "Authenticated Session" | msgid "Authenticated Session" | ||||||
| msgstr "Authentifizierte Sitzung" | msgstr "Authentifizierte Sitzung" | ||||||
| @ -511,6 +524,38 @@ msgstr "Lizenzverwendung" | |||||||
| msgid "License Usage Records" | msgid "License Usage Records" | ||||||
| msgstr "Lizenzverwendung Aufzeichnungen" | msgstr "Lizenzverwendung Aufzeichnungen" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | #: authentik/policies/password/models.py | ||||||
|  | msgid "Field key to check, field keys defined in Prompt stages are available." | ||||||
|  | msgstr "" | ||||||
|  | "Zu prüfender Feldschlüssel, die in den Aufforderungsstufen definierten " | ||||||
|  | "Feldschlüssel sind verfügbar." | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "Number of passwords to check against." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | #: authentik/policies/password/models.py | ||||||
|  | msgid "Password not set in context" | ||||||
|  | msgstr "Passwort nicht im Kontext festgelegt" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "This password has been used previously. Please choose a different one." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "Password Uniqueness Policy" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "Password Uniqueness Policies" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "User Password History" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/enterprise/policy.py | #: authentik/enterprise/policy.py | ||||||
| msgid "Enterprise required to access this feature." | msgid "Enterprise required to access this feature." | ||||||
| msgstr "Enterprise ist erforderlich, um auf diese Funktion zuzugreifen." | msgstr "Enterprise ist erforderlich, um auf diese Funktion zuzugreifen." | ||||||
| @ -1303,12 +1348,6 @@ msgstr "Richtlinien Cache Metriken anzeigen" | |||||||
| msgid "Clear Policy's cache metrics" | msgid "Clear Policy's cache metrics" | ||||||
| msgstr "Richtlinien Cache Metriken löschen" | msgstr "Richtlinien Cache Metriken löschen" | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py |  | ||||||
| msgid "Field key to check, field keys defined in Prompt stages are available." |  | ||||||
| msgstr "" |  | ||||||
| "Zu prüfender Feldschlüssel, die in den Aufforderungsstufen definierten " |  | ||||||
| "Feldschlüssel sind verfügbar." |  | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py | #: authentik/policies/password/models.py | ||||||
| msgid "How many times the password hash is allowed to be on haveibeenpwned" | msgid "How many times the password hash is allowed to be on haveibeenpwned" | ||||||
| msgstr "Wie häufig der Passwort-Hash auf haveibeenpwned vertreten sein darf" | msgstr "Wie häufig der Passwort-Hash auf haveibeenpwned vertreten sein darf" | ||||||
| @ -1320,10 +1359,6 @@ msgstr "" | |||||||
| "Die Richtlinie wird verweigert, wenn die zxcvbn-Bewertung gleich oder " | "Die Richtlinie wird verweigert, wenn die zxcvbn-Bewertung gleich oder " | ||||||
| "kleiner diesem Wert ist." | "kleiner diesem Wert ist." | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py |  | ||||||
| msgid "Password not set in context" |  | ||||||
| msgstr "Passwort nicht im Kontext festgelegt" |  | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py | #: authentik/policies/password/models.py | ||||||
| msgid "Invalid password." | msgid "Invalid password." | ||||||
| msgstr "Ungültiges Passwort." | msgstr "Ungültiges Passwort." | ||||||
| @ -1365,20 +1400,6 @@ msgstr "Reputationswert" | |||||||
| msgid "Reputation Scores" | msgid "Reputation Scores" | ||||||
| msgstr "Reputationswert" | msgstr "Reputationswert" | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/buffer.html |  | ||||||
| msgid "Waiting for authentication..." |  | ||||||
| msgstr "" |  | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/buffer.html |  | ||||||
| msgid "" |  | ||||||
| "You're already authenticating in another tab. This page will refresh once " |  | ||||||
| "authentication is completed." |  | ||||||
| msgstr "" |  | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/buffer.html |  | ||||||
| msgid "Authenticate in this tab" |  | ||||||
| msgstr "" |  | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/denied.html | #: authentik/policies/templates/policies/denied.html | ||||||
| msgid "Permission denied" | msgid "Permission denied" | ||||||
| msgstr "Erlaubnis verweigert" | msgstr "Erlaubnis verweigert" | ||||||
| @ -2208,6 +2229,10 @@ msgstr "Rolle" | |||||||
| msgid "Roles" | msgid "Roles" | ||||||
| msgstr "Rollen" | msgstr "Rollen" | ||||||
|  |  | ||||||
|  | #: authentik/rbac/models.py | ||||||
|  | msgid "Initial Permissions" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/rbac/models.py | #: authentik/rbac/models.py | ||||||
| msgid "System permission" | msgid "System permission" | ||||||
| msgstr "Systemberechtigung" | msgstr "Systemberechtigung" | ||||||
| @ -2478,6 +2503,22 @@ msgstr "LDAP Quelle Eigenschafts-Zuordnung" | |||||||
| msgid "LDAP Source Property Mappings" | msgid "LDAP Source Property Mappings" | ||||||
| msgstr "LDAP Quelle Eigenschafts-Zuordnungen" | msgstr "LDAP Quelle Eigenschafts-Zuordnungen" | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "User LDAP Source Connection" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "User LDAP Source Connections" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "Group LDAP Source Connection" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "Group LDAP Source Connections" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/sources/ldap/signals.py | #: authentik/sources/ldap/signals.py | ||||||
| msgid "Password does not match Active Directory Complexity." | msgid "Password does not match Active Directory Complexity." | ||||||
| msgstr "" | msgstr "" | ||||||
| @ -2487,6 +2528,14 @@ msgstr "" | |||||||
| msgid "No token received." | msgid "No token received." | ||||||
| msgstr "Kein Token empfangen." | msgstr "Kein Token empfangen." | ||||||
|  |  | ||||||
|  | #: authentik/sources/oauth/models.py | ||||||
|  | msgid "HTTP Basic Authentication" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/sources/oauth/models.py | ||||||
|  | msgid "Include the client ID and secret as request parameters" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/sources/oauth/models.py | #: authentik/sources/oauth/models.py | ||||||
| msgid "Request Token URL" | msgid "Request Token URL" | ||||||
| msgstr "Token-URL anfordern" | msgstr "Token-URL anfordern" | ||||||
| @ -2528,6 +2577,12 @@ msgstr "" | |||||||
| msgid "Additional Scopes" | msgid "Additional Scopes" | ||||||
| msgstr "zusätzliche Scopes" | msgstr "zusätzliche Scopes" | ||||||
|  |  | ||||||
|  | #: authentik/sources/oauth/models.py | ||||||
|  | msgid "" | ||||||
|  | "How to perform authentication during an authorization_code token request " | ||||||
|  | "flow" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/sources/oauth/models.py | #: authentik/sources/oauth/models.py | ||||||
| msgid "OAuth Source" | msgid "OAuth Source" | ||||||
| msgstr "Outh Quelle" | msgstr "Outh Quelle" | ||||||
| @ -3434,6 +3489,12 @@ msgstr "" | |||||||
| "Wenn aktiviert, wird die Phase auch dann erfolgreich abgeschlossen und " | "Wenn aktiviert, wird die Phase auch dann erfolgreich abgeschlossen und " | ||||||
| "fortgesetzt, wenn falsche Benutzerdaten eingegeben wurden." | "fortgesetzt, wenn falsche Benutzerdaten eingegeben wurden." | ||||||
|  |  | ||||||
|  | #: authentik/stages/identification/models.py | ||||||
|  | msgid "" | ||||||
|  | "Show the user the 'Remember me on this device' toggle, allowing repeat users" | ||||||
|  | " to skip straight to entering their password." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/stages/identification/models.py | #: authentik/stages/identification/models.py | ||||||
| msgid "Optional enrollment flow, which is linked at the bottom of the page." | msgid "Optional enrollment flow, which is linked at the bottom of the page." | ||||||
| msgstr "Optionaler Registrierungs-Flow, der unten auf der Seite verlinkt ist." | msgstr "Optionaler Registrierungs-Flow, der unten auf der Seite verlinkt ist." | ||||||
| @ -3826,6 +3887,14 @@ msgstr "" | |||||||
| "Die Ereignisse werden nach dieser Dauer gelöscht (Format: " | "Die Ereignisse werden nach dieser Dauer gelöscht (Format: " | ||||||
| "Wochen=3;Tage=2;Stunden=3,Sekunden=2)." | "Wochen=3;Tage=2;Stunden=3,Sekunden=2)." | ||||||
|  |  | ||||||
|  | #: authentik/tenants/models.py | ||||||
|  | msgid "Reputation cannot decrease lower than this value. Zero or negative." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/tenants/models.py | ||||||
|  | msgid "Reputation cannot increase higher than this value. Zero or positive." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/tenants/models.py | #: authentik/tenants/models.py | ||||||
| msgid "The option configures the footer links on the flow executor pages." | msgid "The option configures the footer links on the flow executor pages." | ||||||
| msgstr "" | msgstr "" | ||||||
|  | |||||||
										
											Binary file not shown.
										
									
								
							| @ -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-04-11 00:10+0000\n" | "POT-Creation-Date: 2025-04-23 09:00+0000\n" | ||||||
| "PO-Revision-Date: 2022-09-26 16:47+0000\n" | "PO-Revision-Date: 2022-09-26 16:47+0000\n" | ||||||
| "Last-Translator: Jens L. <jens@goauthentik.io>, 2025\n" | "Last-Translator: Jens L. <jens@goauthentik.io>, 2025\n" | ||||||
| "Language-Team: Spanish (https://app.transifex.com/authentik/teams/119923/es/)\n" | "Language-Team: Spanish (https://app.transifex.com/authentik/teams/119923/es/)\n" | ||||||
| @ -190,6 +190,7 @@ msgid "User's display name." | |||||||
| msgstr "Nombre para mostrar del usuario." | msgstr "Nombre para mostrar del usuario." | ||||||
|  |  | ||||||
| #: authentik/core/models.py authentik/providers/oauth2/models.py | #: authentik/core/models.py authentik/providers/oauth2/models.py | ||||||
|  | #: authentik/rbac/models.py | ||||||
| msgid "User" | msgid "User" | ||||||
| msgstr "Usuario" | msgstr "Usuario" | ||||||
|  |  | ||||||
| @ -378,6 +379,18 @@ msgstr "Asignación de Propiedades" | |||||||
| msgid "Property Mappings" | msgid "Property Mappings" | ||||||
| msgstr "Asignaciones de Propiedades" | msgstr "Asignaciones de Propiedades" | ||||||
|  |  | ||||||
|  | #: authentik/core/models.py | ||||||
|  | msgid "session data" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/core/models.py | ||||||
|  | msgid "Session" | ||||||
|  | msgstr "Sesión" | ||||||
|  |  | ||||||
|  | #: authentik/core/models.py | ||||||
|  | msgid "Sessions" | ||||||
|  | msgstr "Sesiones" | ||||||
|  |  | ||||||
| #: authentik/core/models.py | #: authentik/core/models.py | ||||||
| msgid "Authenticated Session" | msgid "Authenticated Session" | ||||||
| msgstr "Sesión autenticada" | msgstr "Sesión autenticada" | ||||||
| @ -485,6 +498,38 @@ msgstr "Uso de Licencias" | |||||||
| msgid "License Usage Records" | msgid "License Usage Records" | ||||||
| msgstr "Registro de Uso de Licencias" | msgstr "Registro de Uso de Licencias" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | #: authentik/policies/password/models.py | ||||||
|  | msgid "Field key to check, field keys defined in Prompt stages are available." | ||||||
|  | msgstr "" | ||||||
|  | "Clave de campo a verificar, las claves de campo definidas en las etapas de " | ||||||
|  | "Solicitud están disponibles." | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "Number of passwords to check against." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | #: authentik/policies/password/models.py | ||||||
|  | msgid "Password not set in context" | ||||||
|  | msgstr "La contraseña no se ha establecido en contexto" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "This password has been used previously. Please choose a different one." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "Password Uniqueness Policy" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "Password Uniqueness Policies" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "User Password History" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/enterprise/policy.py | #: authentik/enterprise/policy.py | ||||||
| msgid "Enterprise required to access this feature." | msgid "Enterprise required to access this feature." | ||||||
| msgstr "Se requiere de Enterprise para acceder esta característica." | msgstr "Se requiere de Enterprise para acceder esta característica." | ||||||
| @ -1268,12 +1313,6 @@ msgstr "Ver las métricas de caché de la Política" | |||||||
| msgid "Clear Policy's cache metrics" | msgid "Clear Policy's cache metrics" | ||||||
| msgstr "Borrar las métricas de caché de la Política" | msgstr "Borrar las métricas de caché de la Política" | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py |  | ||||||
| msgid "Field key to check, field keys defined in Prompt stages are available." |  | ||||||
| msgstr "" |  | ||||||
| "Clave de campo a verificar, las claves de campo definidas en las etapas de " |  | ||||||
| "Solicitud están disponibles." |  | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py | #: authentik/policies/password/models.py | ||||||
| msgid "How many times the password hash is allowed to be on haveibeenpwned" | msgid "How many times the password hash is allowed to be on haveibeenpwned" | ||||||
| msgstr "" | msgstr "" | ||||||
| @ -1287,10 +1326,6 @@ msgstr "" | |||||||
| "Si la puntuación zxcvbn es igual o menor que este valor, la política " | "Si la puntuación zxcvbn es igual o menor que este valor, la política " | ||||||
| "fallará." | "fallará." | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py |  | ||||||
| msgid "Password not set in context" |  | ||||||
| msgstr "La contraseña no se ha establecido en contexto" |  | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py | #: authentik/policies/password/models.py | ||||||
| msgid "Invalid password." | msgid "Invalid password." | ||||||
| msgstr "Contraseña inválida." | msgstr "Contraseña inválida." | ||||||
| @ -1332,20 +1367,6 @@ msgstr "Puntuación de Reputacion" | |||||||
| msgid "Reputation Scores" | msgid "Reputation Scores" | ||||||
| msgstr "Puntuaciones de Reputacion" | msgstr "Puntuaciones de Reputacion" | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/buffer.html |  | ||||||
| msgid "Waiting for authentication..." |  | ||||||
| msgstr "" |  | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/buffer.html |  | ||||||
| msgid "" |  | ||||||
| "You're already authenticating in another tab. This page will refresh once " |  | ||||||
| "authentication is completed." |  | ||||||
| msgstr "" |  | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/buffer.html |  | ||||||
| msgid "Authenticate in this tab" |  | ||||||
| msgstr "" |  | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/denied.html | #: authentik/policies/templates/policies/denied.html | ||||||
| msgid "Permission denied" | msgid "Permission denied" | ||||||
| msgstr "Permiso denegado" | msgstr "Permiso denegado" | ||||||
| @ -2175,6 +2196,10 @@ msgstr "Rol" | |||||||
| msgid "Roles" | msgid "Roles" | ||||||
| msgstr "Roles" | msgstr "Roles" | ||||||
|  |  | ||||||
|  | #: authentik/rbac/models.py | ||||||
|  | msgid "Initial Permissions" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/rbac/models.py | #: authentik/rbac/models.py | ||||||
| msgid "System permission" | msgid "System permission" | ||||||
| msgstr "Permiso de sistema" | msgstr "Permiso de sistema" | ||||||
| @ -2443,6 +2468,22 @@ msgstr "Asignación de Propiedades de Fuente de LDAP" | |||||||
| msgid "LDAP Source Property Mappings" | msgid "LDAP Source Property Mappings" | ||||||
| msgstr "Asignaciones de Propiedades de Fuente de LDAP" | msgstr "Asignaciones de Propiedades de Fuente de LDAP" | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "User LDAP Source Connection" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "User LDAP Source Connections" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "Group LDAP Source Connection" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "Group LDAP Source Connections" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/sources/ldap/signals.py | #: authentik/sources/ldap/signals.py | ||||||
| msgid "Password does not match Active Directory Complexity." | msgid "Password does not match Active Directory Complexity." | ||||||
| msgstr "La contraseña no coincide con la complejidad de Active Directory." | msgstr "La contraseña no coincide con la complejidad de Active Directory." | ||||||
| @ -2451,6 +2492,14 @@ msgstr "La contraseña no coincide con la complejidad de Active Directory." | |||||||
| msgid "No token received." | msgid "No token received." | ||||||
| msgstr "No se recibió ningún token." | msgstr "No se recibió ningún token." | ||||||
|  |  | ||||||
|  | #: authentik/sources/oauth/models.py | ||||||
|  | msgid "HTTP Basic Authentication" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/sources/oauth/models.py | ||||||
|  | msgid "Include the client ID and secret as request parameters" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/sources/oauth/models.py | #: authentik/sources/oauth/models.py | ||||||
| msgid "Request Token URL" | msgid "Request Token URL" | ||||||
| msgstr "Solicitar URL de token" | msgstr "Solicitar URL de token" | ||||||
| @ -2491,6 +2540,12 @@ msgstr "URL utilizada por authentik para obtener información del usuario." | |||||||
| msgid "Additional Scopes" | msgid "Additional Scopes" | ||||||
| msgstr "Alcances Adicionales" | msgstr "Alcances Adicionales" | ||||||
|  |  | ||||||
|  | #: authentik/sources/oauth/models.py | ||||||
|  | msgid "" | ||||||
|  | "How to perform authentication during an authorization_code token request " | ||||||
|  | "flow" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/sources/oauth/models.py | #: authentik/sources/oauth/models.py | ||||||
| msgid "OAuth Source" | msgid "OAuth Source" | ||||||
| msgstr "Fuente de OAuth" | msgstr "Fuente de OAuth" | ||||||
| @ -3407,6 +3462,12 @@ msgstr "" | |||||||
| "Cuando está habilitado, la etapa tendrá éxito y continuará incluso cuando se" | "Cuando está habilitado, la etapa tendrá éxito y continuará incluso cuando se" | ||||||
| " ingrese información de usuario incorrecta." | " ingrese información de usuario incorrecta." | ||||||
|  |  | ||||||
|  | #: authentik/stages/identification/models.py | ||||||
|  | msgid "" | ||||||
|  | "Show the user the 'Remember me on this device' toggle, allowing repeat users" | ||||||
|  | " to skip straight to entering their password." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/stages/identification/models.py | #: authentik/stages/identification/models.py | ||||||
| msgid "Optional enrollment flow, which is linked at the bottom of the page." | msgid "Optional enrollment flow, which is linked at the bottom of the page." | ||||||
| msgstr "" | msgstr "" | ||||||
| @ -3794,6 +3855,14 @@ msgstr "" | |||||||
| "Los Eventos serán eliminados después de este periodo. (Formato: " | "Los Eventos serán eliminados después de este periodo. (Formato: " | ||||||
| "weeks=3;days=2;hours=3,seconds=2)." | "weeks=3;days=2;hours=3,seconds=2)." | ||||||
|  |  | ||||||
|  | #: authentik/tenants/models.py | ||||||
|  | msgid "Reputation cannot decrease lower than this value. Zero or negative." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/tenants/models.py | ||||||
|  | msgid "Reputation cannot increase higher than this value. Zero or positive." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/tenants/models.py | #: authentik/tenants/models.py | ||||||
| msgid "The option configures the footer links on the flow executor pages." | msgid "The option configures the footer links on the flow executor pages." | ||||||
| msgstr "" | msgstr "" | ||||||
|  | |||||||
										
											Binary file not shown.
										
									
								
							| @ -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-04-11 00:10+0000\n" | "POT-Creation-Date: 2025-04-23 09:00+0000\n" | ||||||
| "PO-Revision-Date: 2022-09-26 16:47+0000\n" | "PO-Revision-Date: 2022-09-26 16:47+0000\n" | ||||||
| "Last-Translator: Ville Ranki, 2025\n" | "Last-Translator: Ville Ranki, 2025\n" | ||||||
| "Language-Team: Finnish (https://app.transifex.com/authentik/teams/119923/fi/)\n" | "Language-Team: Finnish (https://app.transifex.com/authentik/teams/119923/fi/)\n" | ||||||
| @ -186,6 +186,7 @@ msgid "User's display name." | |||||||
| msgstr "Käyttäjän näytettävä nimi" | msgstr "Käyttäjän näytettävä nimi" | ||||||
|  |  | ||||||
| #: authentik/core/models.py authentik/providers/oauth2/models.py | #: authentik/core/models.py authentik/providers/oauth2/models.py | ||||||
|  | #: authentik/rbac/models.py | ||||||
| msgid "User" | msgid "User" | ||||||
| msgstr "Käyttäjä" | msgstr "Käyttäjä" | ||||||
|  |  | ||||||
| @ -371,6 +372,18 @@ msgstr "Ominaisuuskytkentä" | |||||||
| msgid "Property Mappings" | msgid "Property Mappings" | ||||||
| msgstr "Ominaisuuskytkennät" | msgstr "Ominaisuuskytkennät" | ||||||
|  |  | ||||||
|  | #: authentik/core/models.py | ||||||
|  | msgid "session data" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/core/models.py | ||||||
|  | msgid "Session" | ||||||
|  | msgstr "Istunto" | ||||||
|  |  | ||||||
|  | #: authentik/core/models.py | ||||||
|  | msgid "Sessions" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/core/models.py | #: authentik/core/models.py | ||||||
| msgid "Authenticated Session" | msgid "Authenticated Session" | ||||||
| msgstr "Autentikoitu istunto" | msgstr "Autentikoitu istunto" | ||||||
| @ -478,6 +491,38 @@ msgstr "Lisenssin käyttö" | |||||||
| msgid "License Usage Records" | msgid "License Usage Records" | ||||||
| msgstr "Lisenssin käyttötiedot" | msgstr "Lisenssin käyttötiedot" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | #: authentik/policies/password/models.py | ||||||
|  | msgid "Field key to check, field keys defined in Prompt stages are available." | ||||||
|  | msgstr "" | ||||||
|  | "Kentän avain, joka tarkistetaan. Kysymysvaiheissa määritellyt kenttien " | ||||||
|  | "avaimet ovat käytettävissä." | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "Number of passwords to check against." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | #: authentik/policies/password/models.py | ||||||
|  | msgid "Password not set in context" | ||||||
|  | msgstr "Salasanaa ei ole asetettu kontekstissa" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "This password has been used previously. Please choose a different one." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "Password Uniqueness Policy" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "Password Uniqueness Policies" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "User Password History" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/enterprise/policy.py | #: authentik/enterprise/policy.py | ||||||
| msgid "Enterprise required to access this feature." | msgid "Enterprise required to access this feature." | ||||||
| msgstr "Tämän ominaisuuden käyttöön tarvitaan Enterprise-versiota." | msgstr "Tämän ominaisuuden käyttöön tarvitaan Enterprise-versiota." | ||||||
| @ -1251,12 +1296,6 @@ msgstr "Näytä käytäntövälimuistitilastot" | |||||||
| msgid "Clear Policy's cache metrics" | msgid "Clear Policy's cache metrics" | ||||||
| msgstr "Tyhjennä käytäntövälimuistitilastot" | msgstr "Tyhjennä käytäntövälimuistitilastot" | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py |  | ||||||
| msgid "Field key to check, field keys defined in Prompt stages are available." |  | ||||||
| msgstr "" |  | ||||||
| "Kentän avain, joka tarkistetaan. Kysymysvaiheissa määritellyt kenttien " |  | ||||||
| "avaimet ovat käytettävissä." |  | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py | #: authentik/policies/password/models.py | ||||||
| msgid "How many times the password hash is allowed to be on haveibeenpwned" | msgid "How many times the password hash is allowed to be on haveibeenpwned" | ||||||
| msgstr "" | msgstr "" | ||||||
| @ -1269,10 +1308,6 @@ msgstr "" | |||||||
| "Jos zxcvbn-pistemäärä on tämä arvo tai pienempi, käytännön suorittaminen " | "Jos zxcvbn-pistemäärä on tämä arvo tai pienempi, käytännön suorittaminen " | ||||||
| "epäonnistuu." | "epäonnistuu." | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py |  | ||||||
| msgid "Password not set in context" |  | ||||||
| msgstr "Salasanaa ei ole asetettu kontekstissa" |  | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py | #: authentik/policies/password/models.py | ||||||
| msgid "Invalid password." | msgid "Invalid password." | ||||||
| msgstr "Virheellinen salasana." | msgstr "Virheellinen salasana." | ||||||
| @ -1314,20 +1349,6 @@ msgstr "Mainepistemäärä" | |||||||
| msgid "Reputation Scores" | msgid "Reputation Scores" | ||||||
| msgstr "Mainepistemäärät" | msgstr "Mainepistemäärät" | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/buffer.html |  | ||||||
| msgid "Waiting for authentication..." |  | ||||||
| msgstr "" |  | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/buffer.html |  | ||||||
| msgid "" |  | ||||||
| "You're already authenticating in another tab. This page will refresh once " |  | ||||||
| "authentication is completed." |  | ||||||
| msgstr "" |  | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/buffer.html |  | ||||||
| msgid "Authenticate in this tab" |  | ||||||
| msgstr "" |  | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/denied.html | #: authentik/policies/templates/policies/denied.html | ||||||
| msgid "Permission denied" | msgid "Permission denied" | ||||||
| msgstr "Käyttö evätty" | msgstr "Käyttö evätty" | ||||||
| @ -2155,6 +2176,10 @@ msgstr "Rooli" | |||||||
| msgid "Roles" | msgid "Roles" | ||||||
| msgstr "Roolit" | msgstr "Roolit" | ||||||
|  |  | ||||||
|  | #: authentik/rbac/models.py | ||||||
|  | msgid "Initial Permissions" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/rbac/models.py | #: authentik/rbac/models.py | ||||||
| msgid "System permission" | msgid "System permission" | ||||||
| msgstr "Järjestelmän käyttöoikeus" | msgstr "Järjestelmän käyttöoikeus" | ||||||
| @ -2420,6 +2445,22 @@ msgstr "LDAP-lähteen ominaisuuskytkentä" | |||||||
| msgid "LDAP Source Property Mappings" | msgid "LDAP Source Property Mappings" | ||||||
| msgstr "LDAP-lähteen ominaisuuskytkennät" | msgstr "LDAP-lähteen ominaisuuskytkennät" | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "User LDAP Source Connection" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "User LDAP Source Connections" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "Group LDAP Source Connection" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "Group LDAP Source Connections" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/sources/ldap/signals.py | #: authentik/sources/ldap/signals.py | ||||||
| msgid "Password does not match Active Directory Complexity." | msgid "Password does not match Active Directory Complexity." | ||||||
| msgstr "Salasana ei vastaa Active Directoryn monimutkaisuusmääritystä." | msgstr "Salasana ei vastaa Active Directoryn monimutkaisuusmääritystä." | ||||||
| @ -2428,6 +2469,14 @@ msgstr "Salasana ei vastaa Active Directoryn monimutkaisuusmääritystä." | |||||||
| msgid "No token received." | msgid "No token received." | ||||||
| msgstr "Tunnistetta ei saatu." | msgstr "Tunnistetta ei saatu." | ||||||
|  |  | ||||||
|  | #: authentik/sources/oauth/models.py | ||||||
|  | msgid "HTTP Basic Authentication" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/sources/oauth/models.py | ||||||
|  | msgid "Include the client ID and secret as request parameters" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/sources/oauth/models.py | #: authentik/sources/oauth/models.py | ||||||
| msgid "Request Token URL" | msgid "Request Token URL" | ||||||
| msgstr "Pyyntötunnisteen URL" | msgstr "Pyyntötunnisteen URL" | ||||||
| @ -2468,6 +2517,12 @@ msgstr "URL, jota authentik käyttää käyttäjätiedon hakemiseksi." | |||||||
| msgid "Additional Scopes" | msgid "Additional Scopes" | ||||||
| msgstr "Lisäkäyttöalueet" | msgstr "Lisäkäyttöalueet" | ||||||
|  |  | ||||||
|  | #: authentik/sources/oauth/models.py | ||||||
|  | msgid "" | ||||||
|  | "How to perform authentication during an authorization_code token request " | ||||||
|  | "flow" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/sources/oauth/models.py | #: authentik/sources/oauth/models.py | ||||||
| msgid "OAuth Source" | msgid "OAuth Source" | ||||||
| msgstr "OAuth-lähde" | msgstr "OAuth-lähde" | ||||||
| @ -3377,6 +3432,12 @@ msgstr "" | |||||||
| "Kun tämä on käytössä, vaihe onnistuu ja suoritus jatkuu, vaikka olisi " | "Kun tämä on käytössä, vaihe onnistuu ja suoritus jatkuu, vaikka olisi " | ||||||
| "syötetty virheelliset käyttäjätiedot." | "syötetty virheelliset käyttäjätiedot." | ||||||
|  |  | ||||||
|  | #: authentik/stages/identification/models.py | ||||||
|  | msgid "" | ||||||
|  | "Show the user the 'Remember me on this device' toggle, allowing repeat users" | ||||||
|  | " to skip straight to entering their password." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/stages/identification/models.py | #: authentik/stages/identification/models.py | ||||||
| msgid "Optional enrollment flow, which is linked at the bottom of the page." | msgid "Optional enrollment flow, which is linked at the bottom of the page." | ||||||
| msgstr "" | msgstr "" | ||||||
| @ -3754,6 +3815,14 @@ msgstr "" | |||||||
| "Tapahtumat poistetaan tämän ajan jälkeen. (Muoto: " | "Tapahtumat poistetaan tämän ajan jälkeen. (Muoto: " | ||||||
| "weeks=3;days=2;hours=3;seconds=2)." | "weeks=3;days=2;hours=3;seconds=2)." | ||||||
|  |  | ||||||
|  | #: authentik/tenants/models.py | ||||||
|  | msgid "Reputation cannot decrease lower than this value. Zero or negative." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/tenants/models.py | ||||||
|  | msgid "Reputation cannot increase higher than this value. Zero or positive." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/tenants/models.py | #: authentik/tenants/models.py | ||||||
| msgid "The option configures the footer links on the flow executor pages." | msgid "The option configures the footer links on the flow executor pages." | ||||||
| msgstr "" | msgstr "" | ||||||
|  | |||||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							| @ -20,7 +20,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-04-11 00:10+0000\n" | "POT-Creation-Date: 2025-04-23 09:00+0000\n" | ||||||
| "PO-Revision-Date: 2022-09-26 16:47+0000\n" | "PO-Revision-Date: 2022-09-26 16:47+0000\n" | ||||||
| "Last-Translator: Kowalski Dragon (kowalski7cc) <kowalski.7cc@gmail.com>, 2025\n" | "Last-Translator: Kowalski Dragon (kowalski7cc) <kowalski.7cc@gmail.com>, 2025\n" | ||||||
| "Language-Team: Italian (https://app.transifex.com/authentik/teams/119923/it/)\n" | "Language-Team: Italian (https://app.transifex.com/authentik/teams/119923/it/)\n" | ||||||
| @ -194,6 +194,7 @@ msgid "User's display name." | |||||||
| msgstr "Nome visualizzato dell'utente." | msgstr "Nome visualizzato dell'utente." | ||||||
|  |  | ||||||
| #: authentik/core/models.py authentik/providers/oauth2/models.py | #: authentik/core/models.py authentik/providers/oauth2/models.py | ||||||
|  | #: authentik/rbac/models.py | ||||||
| msgid "User" | msgid "User" | ||||||
| msgstr "Utente" | msgstr "Utente" | ||||||
|  |  | ||||||
| @ -380,6 +381,18 @@ msgstr "Mappatura della proprietà" | |||||||
| msgid "Property Mappings" | msgid "Property Mappings" | ||||||
| msgstr "Mappatura delle proprietà" | msgstr "Mappatura delle proprietà" | ||||||
|  |  | ||||||
|  | #: authentik/core/models.py | ||||||
|  | msgid "session data" | ||||||
|  | msgstr "dati sessione" | ||||||
|  |  | ||||||
|  | #: authentik/core/models.py | ||||||
|  | msgid "Session" | ||||||
|  | msgstr "Sessione" | ||||||
|  |  | ||||||
|  | #: authentik/core/models.py | ||||||
|  | msgid "Sessions" | ||||||
|  | msgstr "Sessioni" | ||||||
|  |  | ||||||
| #: authentik/core/models.py | #: authentik/core/models.py | ||||||
| msgid "Authenticated Session" | msgid "Authenticated Session" | ||||||
| msgstr "Sessione Autenticata" | msgstr "Sessione Autenticata" | ||||||
| @ -487,6 +500,39 @@ msgstr "Utilizzo della licenza" | |||||||
| msgid "License Usage Records" | msgid "License Usage Records" | ||||||
| msgstr "Registri sull'utilizzo della licenza" | msgstr "Registri sull'utilizzo della licenza" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | #: authentik/policies/password/models.py | ||||||
|  | msgid "Field key to check, field keys defined in Prompt stages are available." | ||||||
|  | msgstr "" | ||||||
|  | "Chiave di campo da verificare, sono disponibili le chiavi di campo definite " | ||||||
|  | "nelle fasi Richiesta." | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "Number of passwords to check against." | ||||||
|  | msgstr "Numero di password da verificare." | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | #: authentik/policies/password/models.py | ||||||
|  | msgid "Password not set in context" | ||||||
|  | msgstr "Password non impostata nel contesto" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "This password has been used previously. Please choose a different one." | ||||||
|  | msgstr "" | ||||||
|  | "Questa password è già stata utilizzata in precedenza. Scegline una diversa." | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "Password Uniqueness Policy" | ||||||
|  | msgstr "Politica di unicità della password" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "Password Uniqueness Policies" | ||||||
|  | msgstr "Criteri di unicità delle password" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "User Password History" | ||||||
|  | msgstr "Cronologia password utente" | ||||||
|  |  | ||||||
| #: authentik/enterprise/policy.py | #: authentik/enterprise/policy.py | ||||||
| msgid "Enterprise required to access this feature." | msgid "Enterprise required to access this feature." | ||||||
| msgstr "Versione Enterprise richiesta per accedere a questa funzione" | msgstr "Versione Enterprise richiesta per accedere a questa funzione" | ||||||
| @ -1274,12 +1320,6 @@ msgstr "Visualizza le metriche della cache della Policy" | |||||||
| msgid "Clear Policy's cache metrics" | msgid "Clear Policy's cache metrics" | ||||||
| msgstr "Cancellare le metriche della cache della Policy" | msgstr "Cancellare le metriche della cache della Policy" | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py |  | ||||||
| msgid "Field key to check, field keys defined in Prompt stages are available." |  | ||||||
| msgstr "" |  | ||||||
| "Chiave di campo da verificare, sono disponibili le chiavi di campo definite " |  | ||||||
| "nelle fasi Richiesta." |  | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py | #: authentik/policies/password/models.py | ||||||
| msgid "How many times the password hash is allowed to be on haveibeenpwned" | msgid "How many times the password hash is allowed to be on haveibeenpwned" | ||||||
| msgstr "" | msgstr "" | ||||||
| @ -1292,10 +1332,6 @@ msgstr "" | |||||||
| "Se il punteggio zxcvbn è inferiore o uguale a questo valore, il criterio non" | "Se il punteggio zxcvbn è inferiore o uguale a questo valore, il criterio non" | ||||||
| " verrà soddisfatto." | " verrà soddisfatto." | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py |  | ||||||
| msgid "Password not set in context" |  | ||||||
| msgstr "Password non impostata nel contesto" |  | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py | #: authentik/policies/password/models.py | ||||||
| msgid "Invalid password." | msgid "Invalid password." | ||||||
| msgstr "Password invalida." | msgstr "Password invalida." | ||||||
| @ -1337,22 +1373,6 @@ msgstr "Punteggio di reputazione" | |||||||
| msgid "Reputation Scores" | msgid "Reputation Scores" | ||||||
| msgstr "Punteggi di reputazione" | msgstr "Punteggi di reputazione" | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/buffer.html |  | ||||||
| msgid "Waiting for authentication..." |  | ||||||
| msgstr "In attesa di autenticazione..." |  | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/buffer.html |  | ||||||
| msgid "" |  | ||||||
| "You're already authenticating in another tab. This page will refresh once " |  | ||||||
| "authentication is completed." |  | ||||||
| msgstr "" |  | ||||||
| "Ti stai già autenticando in un'altra scheda. Questa pagina si aggiornerà una" |  | ||||||
| " volta completata l'autenticazione." |  | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/buffer.html |  | ||||||
| msgid "Authenticate in this tab" |  | ||||||
| msgstr "Autenticati in questa scheda" |  | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/denied.html | #: authentik/policies/templates/policies/denied.html | ||||||
| msgid "Permission denied" | msgid "Permission denied" | ||||||
| msgstr "Permesso negato" | msgstr "Permesso negato" | ||||||
| @ -2182,6 +2202,10 @@ msgstr "Ruolo" | |||||||
| msgid "Roles" | msgid "Roles" | ||||||
| msgstr "Ruoli" | msgstr "Ruoli" | ||||||
|  |  | ||||||
|  | #: authentik/rbac/models.py | ||||||
|  | msgid "Initial Permissions" | ||||||
|  | msgstr "Permessi Iniziali" | ||||||
|  |  | ||||||
| #: authentik/rbac/models.py | #: authentik/rbac/models.py | ||||||
| msgid "System permission" | msgid "System permission" | ||||||
| msgstr "Autorizzazione di sistema" | msgstr "Autorizzazione di sistema" | ||||||
| @ -2435,6 +2459,9 @@ msgid "" | |||||||
| "attribute. This allows nested group resolution on systems like FreeIPA and " | "attribute. This allows nested group resolution on systems like FreeIPA and " | ||||||
| "Active Directory" | "Active Directory" | ||||||
| msgstr "" | msgstr "" | ||||||
|  | "Cerca l'appartenenza al gruppo in base a un attributo utente anziché a un " | ||||||
|  | "attributo di gruppo. Questo consente la risoluzione di gruppi nidificati su " | ||||||
|  | "sistemi come FreeIPA e Active Directory." | ||||||
|  |  | ||||||
| #: authentik/sources/ldap/models.py | #: authentik/sources/ldap/models.py | ||||||
| msgid "LDAP Source" | msgid "LDAP Source" | ||||||
| @ -2452,6 +2479,22 @@ msgstr "Mappatura delle proprietà sorgente LDAP" | |||||||
| msgid "LDAP Source Property Mappings" | msgid "LDAP Source Property Mappings" | ||||||
| msgstr "Mappature delle proprietà della sorgente LDAP" | msgstr "Mappature delle proprietà della sorgente LDAP" | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "User LDAP Source Connection" | ||||||
|  | msgstr "Connessione Sorgente LDAP Utente" | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "User LDAP Source Connections" | ||||||
|  | msgstr "Connessioni Sorgente LDAP Utente" | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "Group LDAP Source Connection" | ||||||
|  | msgstr "Connessione Sorgente LDAP Gruppo" | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "Group LDAP Source Connections" | ||||||
|  | msgstr "Connessioni Sorgente LDAP Gruppo" | ||||||
|  |  | ||||||
| #: authentik/sources/ldap/signals.py | #: authentik/sources/ldap/signals.py | ||||||
| msgid "Password does not match Active Directory Complexity." | msgid "Password does not match Active Directory Complexity." | ||||||
| msgstr "La password non soddisfa la complessità Active Directory." | msgstr "La password non soddisfa la complessità Active Directory." | ||||||
| @ -2460,6 +2503,14 @@ msgstr "La password non soddisfa la complessità Active Directory." | |||||||
| msgid "No token received." | msgid "No token received." | ||||||
| msgstr "Nessun token ricevuto." | msgstr "Nessun token ricevuto." | ||||||
|  |  | ||||||
|  | #: authentik/sources/oauth/models.py | ||||||
|  | msgid "HTTP Basic Authentication" | ||||||
|  | msgstr "HTTP Basic Authentication" | ||||||
|  |  | ||||||
|  | #: authentik/sources/oauth/models.py | ||||||
|  | msgid "Include the client ID and secret as request parameters" | ||||||
|  | msgstr "Includi il client ID e il segreto come parametri di richiesta" | ||||||
|  |  | ||||||
| #: authentik/sources/oauth/models.py | #: authentik/sources/oauth/models.py | ||||||
| msgid "Request Token URL" | msgid "Request Token URL" | ||||||
| msgstr "URL di Richiesta Token" | msgstr "URL di Richiesta Token" | ||||||
| @ -2500,6 +2551,14 @@ msgstr "URL utilizzato da authentik per ottenere le informazioni dell'utente." | |||||||
| msgid "Additional Scopes" | msgid "Additional Scopes" | ||||||
| msgstr "Ambiti aggiuntivi" | msgstr "Ambiti aggiuntivi" | ||||||
|  |  | ||||||
|  | #: authentik/sources/oauth/models.py | ||||||
|  | msgid "" | ||||||
|  | "How to perform authentication during an authorization_code token request " | ||||||
|  | "flow" | ||||||
|  | msgstr "" | ||||||
|  | "Come eseguire l'autenticazione durante un flusso di richiesta del token " | ||||||
|  | "authorization_code" | ||||||
|  |  | ||||||
| #: authentik/sources/oauth/models.py | #: authentik/sources/oauth/models.py | ||||||
| msgid "OAuth Source" | msgid "OAuth Source" | ||||||
| msgstr "Sorgente OAuth" | msgstr "Sorgente OAuth" | ||||||
| @ -3426,6 +3485,15 @@ msgstr "" | |||||||
| "Quando abilitato, la fase avrà successo e continuerà anche quando vengono " | "Quando abilitato, la fase avrà successo e continuerà anche quando vengono " | ||||||
| "inserite informazioni utente errate." | "inserite informazioni utente errate." | ||||||
|  |  | ||||||
|  | #: authentik/stages/identification/models.py | ||||||
|  | msgid "" | ||||||
|  | "Show the user the 'Remember me on this device' toggle, allowing repeat users" | ||||||
|  | " to skip straight to entering their password." | ||||||
|  | msgstr "" | ||||||
|  | "Mostra all'utente il pulsante \"Ricordami su questo dispositivo\", " | ||||||
|  | "consentendo agli utenti abituali di passare direttamente all'inserimento " | ||||||
|  | "della password." | ||||||
|  |  | ||||||
| #: authentik/stages/identification/models.py | #: authentik/stages/identification/models.py | ||||||
| msgid "Optional enrollment flow, which is linked at the bottom of the page." | msgid "Optional enrollment flow, which is linked at the bottom of the page." | ||||||
| msgstr "Flusso di iscrizione opzionale, che è collegato in fondo alla pagina." | msgstr "Flusso di iscrizione opzionale, che è collegato in fondo alla pagina." | ||||||
| @ -3812,6 +3880,14 @@ msgstr "" | |||||||
| "Gli eventi saranno cancellati dopo questa durata. (Formato: " | "Gli eventi saranno cancellati dopo questa durata. (Formato: " | ||||||
| "weeks=3;days=2;hours=3,seconds=2)." | "weeks=3;days=2;hours=3,seconds=2)." | ||||||
|  |  | ||||||
|  | #: authentik/tenants/models.py | ||||||
|  | msgid "Reputation cannot decrease lower than this value. Zero or negative." | ||||||
|  | msgstr "La reputazione non può scendere sotto questo valore. Zero o negativo." | ||||||
|  |  | ||||||
|  | #: authentik/tenants/models.py | ||||||
|  | msgid "Reputation cannot increase higher than this value. Zero or positive." | ||||||
|  | msgstr "La reputazione non può superare questo valore. Zero o positivo." | ||||||
|  |  | ||||||
| #: authentik/tenants/models.py | #: authentik/tenants/models.py | ||||||
| msgid "The option configures the footer links on the flow executor pages." | msgid "The option configures the footer links on the flow executor pages." | ||||||
| msgstr "" | msgstr "" | ||||||
|  | |||||||
										
											Binary file not shown.
										
									
								
							| @ -12,7 +12,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-31 00:10+0000\n" | "POT-Creation-Date: 2025-04-23 09:00+0000\n" | ||||||
| "PO-Revision-Date: 2022-09-26 16:47+0000\n" | "PO-Revision-Date: 2022-09-26 16:47+0000\n" | ||||||
| "Last-Translator: NavyStack, 2023\n" | "Last-Translator: NavyStack, 2023\n" | ||||||
| "Language-Team: Korean (https://app.transifex.com/authentik/teams/119923/ko/)\n" | "Language-Team: Korean (https://app.transifex.com/authentik/teams/119923/ko/)\n" | ||||||
| @ -176,6 +176,7 @@ msgid "User's display name." | |||||||
| msgstr "사용자의 표시 이름" | msgstr "사용자의 표시 이름" | ||||||
|  |  | ||||||
| #: authentik/core/models.py authentik/providers/oauth2/models.py | #: authentik/core/models.py authentik/providers/oauth2/models.py | ||||||
|  | #: authentik/rbac/models.py | ||||||
| msgid "User" | msgid "User" | ||||||
| msgstr "사용자" | msgstr "사용자" | ||||||
|  |  | ||||||
| @ -344,6 +345,18 @@ msgstr "속성 매핑" | |||||||
| msgid "Property Mappings" | msgid "Property Mappings" | ||||||
| msgstr "속성 매핑" | msgstr "속성 매핑" | ||||||
|  |  | ||||||
|  | #: authentik/core/models.py | ||||||
|  | msgid "session data" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/core/models.py | ||||||
|  | msgid "Session" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/core/models.py | ||||||
|  | msgid "Sessions" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/core/models.py | #: authentik/core/models.py | ||||||
| msgid "Authenticated Session" | msgid "Authenticated Session" | ||||||
| msgstr "인증된 세션" | msgstr "인증된 세션" | ||||||
| @ -447,6 +460,36 @@ msgstr "라이선스 사용" | |||||||
| msgid "License Usage Records" | msgid "License Usage Records" | ||||||
| msgstr "라이선스 사용 기록" | msgstr "라이선스 사용 기록" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | #: authentik/policies/password/models.py | ||||||
|  | msgid "Field key to check, field keys defined in Prompt stages are available." | ||||||
|  | msgstr "확인하려는 필드 키, 프롬프트 스테이지에서 정의된 필드 키를 사용할 수 있습니다." | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "Number of passwords to check against." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | #: authentik/policies/password/models.py | ||||||
|  | msgid "Password not set in context" | ||||||
|  | msgstr "비밀번호가 컨텍스트에 설정되지 않음" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "This password has been used previously. Please choose a different one." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "Password Uniqueness Policy" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "Password Uniqueness Policies" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "User Password History" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/enterprise/policy.py | #: authentik/enterprise/policy.py | ||||||
| msgid "Enterprise required to access this feature." | msgid "Enterprise required to access this feature." | ||||||
| msgstr "" | msgstr "" | ||||||
| @ -1182,10 +1225,6 @@ msgstr "정책의 캐시 메트릭 보기" | |||||||
| msgid "Clear Policy's cache metrics" | msgid "Clear Policy's cache metrics" | ||||||
| msgstr "정책의 캐시 메트릭 삭제" | msgstr "정책의 캐시 메트릭 삭제" | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py |  | ||||||
| msgid "Field key to check, field keys defined in Prompt stages are available." |  | ||||||
| msgstr "확인하려는 필드 키, 프롬프트 스테이지에서 정의된 필드 키를 사용할 수 있습니다." |  | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py | #: authentik/policies/password/models.py | ||||||
| msgid "How many times the password hash is allowed to be on haveibeenpwned" | msgid "How many times the password hash is allowed to be on haveibeenpwned" | ||||||
| msgstr "비밀번호 해시가 허용되는 해시 횟수" | msgstr "비밀번호 해시가 허용되는 해시 횟수" | ||||||
| @ -1195,10 +1234,6 @@ msgid "" | |||||||
| "If the zxcvbn score is equal or less than this value, the policy will fail." | "If the zxcvbn score is equal or less than this value, the policy will fail." | ||||||
| msgstr "만약 zxcvbn 점수가 이 값과 같거나 이 값보다 작다면, 정책이 실패합니다." | msgstr "만약 zxcvbn 점수가 이 값과 같거나 이 값보다 작다면, 정책이 실패합니다." | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py |  | ||||||
| msgid "Password not set in context" |  | ||||||
| msgstr "비밀번호가 컨텍스트에 설정되지 않음" |  | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py | #: authentik/policies/password/models.py | ||||||
| msgid "Invalid password." | msgid "Invalid password." | ||||||
| msgstr "" | msgstr "" | ||||||
| @ -1240,20 +1275,6 @@ msgstr "평판 점수" | |||||||
| msgid "Reputation Scores" | msgid "Reputation Scores" | ||||||
| msgstr "평판 점수" | msgstr "평판 점수" | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/buffer.html |  | ||||||
| msgid "Waiting for authentication..." |  | ||||||
| msgstr "" |  | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/buffer.html |  | ||||||
| msgid "" |  | ||||||
| "You're already authenticating in another tab. This page will refresh once " |  | ||||||
| "authentication is completed." |  | ||||||
| msgstr "" |  | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/buffer.html |  | ||||||
| msgid "Authenticate in this tab" |  | ||||||
| msgstr "" |  | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/denied.html | #: authentik/policies/templates/policies/denied.html | ||||||
| msgid "Permission denied" | msgid "Permission denied" | ||||||
| msgstr "권한 거부됨" | msgstr "권한 거부됨" | ||||||
| @ -2013,6 +2034,10 @@ msgstr "역할" | |||||||
| msgid "Roles" | msgid "Roles" | ||||||
| msgstr "역할" | msgstr "역할" | ||||||
|  |  | ||||||
|  | #: authentik/rbac/models.py | ||||||
|  | msgid "Initial Permissions" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/rbac/models.py | #: authentik/rbac/models.py | ||||||
| msgid "System permission" | msgid "System permission" | ||||||
| msgstr "시스템 권한" | msgstr "시스템 권한" | ||||||
| @ -2231,6 +2256,13 @@ msgid "" | |||||||
| "enabled on a single LDAP source." | "enabled on a single LDAP source." | ||||||
| msgstr "사용자가 비밀번호를 변경하면 LDAP로 다시 동기화합니다. 이 기능은 단일의 LDAP 소스에서만 활성화할 수 있습니다." | msgstr "사용자가 비밀번호를 변경하면 LDAP로 다시 동기화합니다. 이 기능은 단일의 LDAP 소스에서만 활성화할 수 있습니다." | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "" | ||||||
|  | "Lookup group membership based on a user attribute instead of a group " | ||||||
|  | "attribute. This allows nested group resolution on systems like FreeIPA and " | ||||||
|  | "Active Directory" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/sources/ldap/models.py | #: authentik/sources/ldap/models.py | ||||||
| msgid "LDAP Source" | msgid "LDAP Source" | ||||||
| msgstr "LDAP 소스" | msgstr "LDAP 소스" | ||||||
| @ -2247,6 +2279,22 @@ msgstr "" | |||||||
| msgid "LDAP Source Property Mappings" | msgid "LDAP Source Property Mappings" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "User LDAP Source Connection" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "User LDAP Source Connections" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "Group LDAP Source Connection" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "Group LDAP Source Connections" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/sources/ldap/signals.py | #: authentik/sources/ldap/signals.py | ||||||
| msgid "Password does not match Active Directory Complexity." | msgid "Password does not match Active Directory Complexity." | ||||||
| msgstr "비밀번호가 Active Directory 복잡도와 일치하지 않습니다." | msgstr "비밀번호가 Active Directory 복잡도와 일치하지 않습니다." | ||||||
| @ -2255,6 +2303,14 @@ msgstr "비밀번호가 Active Directory 복잡도와 일치하지 않습니다. | |||||||
| msgid "No token received." | msgid "No token received." | ||||||
| msgstr "수신된 토큰이 없습니다." | msgstr "수신된 토큰이 없습니다." | ||||||
|  |  | ||||||
|  | #: authentik/sources/oauth/models.py | ||||||
|  | msgid "HTTP Basic Authentication" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/sources/oauth/models.py | ||||||
|  | msgid "Include the client ID and secret as request parameters" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/sources/oauth/models.py | #: authentik/sources/oauth/models.py | ||||||
| msgid "Request Token URL" | msgid "Request Token URL" | ||||||
| msgstr "토큰 요청 URL" | msgstr "토큰 요청 URL" | ||||||
| @ -2293,6 +2349,12 @@ msgstr "사용자 정보를 가져오기 위해 authentik에서 사용하는 URL | |||||||
| msgid "Additional Scopes" | msgid "Additional Scopes" | ||||||
| msgstr "추가 스코프" | msgstr "추가 스코프" | ||||||
|  |  | ||||||
|  | #: authentik/sources/oauth/models.py | ||||||
|  | msgid "" | ||||||
|  | "How to perform authentication during an authorization_code token request " | ||||||
|  | "flow" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/sources/oauth/models.py | #: authentik/sources/oauth/models.py | ||||||
| msgid "OAuth Source" | msgid "OAuth Source" | ||||||
| msgstr "OAuth 소스" | msgstr "OAuth 소스" | ||||||
| @ -3149,6 +3211,12 @@ msgid "" | |||||||
| "info is entered." | "info is entered." | ||||||
| msgstr "활성화되면 잘못된 사용자 정보가 입력되더라도 단계가 성공하고 계속됩니다." | msgstr "활성화되면 잘못된 사용자 정보가 입력되더라도 단계가 성공하고 계속됩니다." | ||||||
|  |  | ||||||
|  | #: authentik/stages/identification/models.py | ||||||
|  | msgid "" | ||||||
|  | "Show the user the 'Remember me on this device' toggle, allowing repeat users" | ||||||
|  | " to skip straight to entering their password." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/stages/identification/models.py | #: authentik/stages/identification/models.py | ||||||
| msgid "Optional enrollment flow, which is linked at the bottom of the page." | msgid "Optional enrollment flow, which is linked at the bottom of the page." | ||||||
| msgstr "페이지 하단에 링크된,  선택적 등록 플로우를 참조하세요." | msgstr "페이지 하단에 링크된,  선택적 등록 플로우를 참조하세요." | ||||||
| @ -3500,6 +3568,14 @@ msgid "" | |||||||
| "weeks=3;days=2;hours=3,seconds=2)." | "weeks=3;days=2;hours=3,seconds=2)." | ||||||
| msgstr "이 기간이 지나면 이벤트가 삭제됩니다. (서식: hours=-1;minutes=-2;seconds=-3)" | msgstr "이 기간이 지나면 이벤트가 삭제됩니다. (서식: hours=-1;minutes=-2;seconds=-3)" | ||||||
|  |  | ||||||
|  | #: authentik/tenants/models.py | ||||||
|  | msgid "Reputation cannot decrease lower than this value. Zero or negative." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/tenants/models.py | ||||||
|  | msgid "Reputation cannot increase higher than this value. Zero or positive." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/tenants/models.py | #: authentik/tenants/models.py | ||||||
| msgid "The option configures the footer links on the flow executor pages." | msgid "The option configures the footer links on the flow executor pages." | ||||||
| msgstr "" | msgstr "" | ||||||
|  | |||||||
										
											Binary file not shown.
										
									
								
							| @ -7,18 +7,18 @@ | |||||||
| # Bartosz Karpiński, 2023 | # Bartosz Karpiński, 2023 | ||||||
| # Michał Jastrzębski, 2024 | # Michał Jastrzębski, 2024 | ||||||
| # Tomci 12 <drizztes@gmail.com>, 2024 | # Tomci 12 <drizztes@gmail.com>, 2024 | ||||||
|  | # Darek “NeroPcStation” NeroPcStation <dareknowacki2001@gmail.com>, 2024 | ||||||
| # Marc Schmitt, 2025 | # Marc Schmitt, 2025 | ||||||
| # Jens L. <jens@goauthentik.io>, 2025 | # Jens L. <jens@goauthentik.io>, 2025 | ||||||
| # Darek “NeroPcStation” NeroPcStation <dareknowacki2001@gmail.com>, 2025 |  | ||||||
| #  | #  | ||||||
| #, fuzzy | #, fuzzy | ||||||
| msgid "" | 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-04-11 00:10+0000\n" | "POT-Creation-Date: 2025-04-23 09:00+0000\n" | ||||||
| "PO-Revision-Date: 2022-09-26 16:47+0000\n" | "PO-Revision-Date: 2022-09-26 16:47+0000\n" | ||||||
| "Last-Translator: Darek “NeroPcStation” NeroPcStation <dareknowacki2001@gmail.com>, 2025\n" | "Last-Translator: Jens L. <jens@goauthentik.io>, 2025\n" | ||||||
| "Language-Team: Polish (https://app.transifex.com/authentik/teams/119923/pl/)\n" | "Language-Team: Polish (https://app.transifex.com/authentik/teams/119923/pl/)\n" | ||||||
| "MIME-Version: 1.0\n" | "MIME-Version: 1.0\n" | ||||||
| "Content-Type: text/plain; charset=UTF-8\n" | "Content-Type: text/plain; charset=UTF-8\n" | ||||||
| @ -189,6 +189,7 @@ msgid "User's display name." | |||||||
| msgstr "Wyświetlana nazwa użytkownika." | msgstr "Wyświetlana nazwa użytkownika." | ||||||
|  |  | ||||||
| #: authentik/core/models.py authentik/providers/oauth2/models.py | #: authentik/core/models.py authentik/providers/oauth2/models.py | ||||||
|  | #: authentik/rbac/models.py | ||||||
| msgid "User" | msgid "User" | ||||||
| msgstr "Użytkownik" | msgstr "Użytkownik" | ||||||
|  |  | ||||||
| @ -371,6 +372,18 @@ msgstr "Mapowanie właściwości" | |||||||
| msgid "Property Mappings" | msgid "Property Mappings" | ||||||
| msgstr "Mapowanie właściwości" | msgstr "Mapowanie właściwości" | ||||||
|  |  | ||||||
|  | #: authentik/core/models.py | ||||||
|  | msgid "session data" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/core/models.py | ||||||
|  | msgid "Session" | ||||||
|  | msgstr "Sesja" | ||||||
|  |  | ||||||
|  | #: authentik/core/models.py | ||||||
|  | msgid "Sessions" | ||||||
|  | msgstr "Sesje" | ||||||
|  |  | ||||||
| #: authentik/core/models.py | #: authentik/core/models.py | ||||||
| msgid "Authenticated Session" | msgid "Authenticated Session" | ||||||
| msgstr "Sesja uwierzytelniona" | msgstr "Sesja uwierzytelniona" | ||||||
| @ -479,6 +492,38 @@ msgstr "Wykorzystanie licencji" | |||||||
| msgid "License Usage Records" | msgid "License Usage Records" | ||||||
| msgstr "Rejestr wykorzystania licencji" | msgstr "Rejestr wykorzystania licencji" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | #: authentik/policies/password/models.py | ||||||
|  | msgid "Field key to check, field keys defined in Prompt stages are available." | ||||||
|  | msgstr "" | ||||||
|  | "Klucz pola do sprawdzenia, dostępne są klucze pola zdefiniowane w etapach " | ||||||
|  | "monitu." | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "Number of passwords to check against." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | #: authentik/policies/password/models.py | ||||||
|  | msgid "Password not set in context" | ||||||
|  | msgstr "Hasło nie jest ustawione w kontekście" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "This password has been used previously. Please choose a different one." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "Password Uniqueness Policy" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "Password Uniqueness Policies" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "User Password History" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/enterprise/policy.py | #: authentik/enterprise/policy.py | ||||||
| msgid "Enterprise required to access this feature." | msgid "Enterprise required to access this feature." | ||||||
| msgstr "Wymagane jest konto Enterprise, aby uzyskać dostęp do tej funkcji." | msgstr "Wymagane jest konto Enterprise, aby uzyskać dostęp do tej funkcji." | ||||||
| @ -1257,12 +1302,6 @@ msgstr "Wyświetl metryki pamięci podręcznej Zasady" | |||||||
| msgid "Clear Policy's cache metrics" | msgid "Clear Policy's cache metrics" | ||||||
| msgstr "Wyczyść metryki pamięci podręcznej Zasady" | msgstr "Wyczyść metryki pamięci podręcznej Zasady" | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py |  | ||||||
| msgid "Field key to check, field keys defined in Prompt stages are available." |  | ||||||
| msgstr "" |  | ||||||
| "Klucz pola do sprawdzenia, dostępne są klucze pola zdefiniowane w etapach " |  | ||||||
| "monitu." |  | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py | #: authentik/policies/password/models.py | ||||||
| msgid "How many times the password hash is allowed to be on haveibeenpwned" | msgid "How many times the password hash is allowed to be on haveibeenpwned" | ||||||
| msgstr "Ile razy skrót hasła może być na haveibeenpwned" | msgstr "Ile razy skrót hasła może być na haveibeenpwned" | ||||||
| @ -1274,10 +1313,6 @@ msgstr "" | |||||||
| "Jeśli wynik zxcvbn jest równy lub mniejszy od tej wartości, zasada zakończy " | "Jeśli wynik zxcvbn jest równy lub mniejszy od tej wartości, zasada zakończy " | ||||||
| "się niepowodzeniem." | "się niepowodzeniem." | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py |  | ||||||
| msgid "Password not set in context" |  | ||||||
| msgstr "Hasło nie jest ustawione w kontekście" |  | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py | #: authentik/policies/password/models.py | ||||||
| msgid "Invalid password." | msgid "Invalid password." | ||||||
| msgstr "" | msgstr "" | ||||||
| @ -1319,20 +1354,6 @@ msgstr "Punkty reputacji" | |||||||
| msgid "Reputation Scores" | msgid "Reputation Scores" | ||||||
| msgstr "Punkty reputacji" | msgstr "Punkty reputacji" | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/buffer.html |  | ||||||
| msgid "Waiting for authentication..." |  | ||||||
| msgstr "Oczekiwanie na uwierzytelnienie..." |  | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/buffer.html |  | ||||||
| msgid "" |  | ||||||
| "You're already authenticating in another tab. This page will refresh once " |  | ||||||
| "authentication is completed." |  | ||||||
| msgstr "" |  | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/buffer.html |  | ||||||
| msgid "Authenticate in this tab" |  | ||||||
| msgstr "" |  | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/denied.html | #: authentik/policies/templates/policies/denied.html | ||||||
| msgid "Permission denied" | msgid "Permission denied" | ||||||
| msgstr "Odmowa uprawnień" | msgstr "Odmowa uprawnień" | ||||||
| @ -2141,6 +2162,10 @@ msgstr "Rola" | |||||||
| msgid "Roles" | msgid "Roles" | ||||||
| msgstr "Role" | msgstr "Role" | ||||||
|  |  | ||||||
|  | #: authentik/rbac/models.py | ||||||
|  | msgid "Initial Permissions" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/rbac/models.py | #: authentik/rbac/models.py | ||||||
| msgid "System permission" | msgid "System permission" | ||||||
| msgstr "Uprawnienie systemowe" | msgstr "Uprawnienie systemowe" | ||||||
| @ -2390,6 +2415,22 @@ msgstr "" | |||||||
| msgid "LDAP Source Property Mappings" | msgid "LDAP Source Property Mappings" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "User LDAP Source Connection" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "User LDAP Source Connections" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "Group LDAP Source Connection" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "Group LDAP Source Connections" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/sources/ldap/signals.py | #: authentik/sources/ldap/signals.py | ||||||
| msgid "Password does not match Active Directory Complexity." | msgid "Password does not match Active Directory Complexity." | ||||||
| msgstr "Hasło nie pasuje do złożoności usługi Active Directory." | msgstr "Hasło nie pasuje do złożoności usługi Active Directory." | ||||||
| @ -2398,6 +2439,14 @@ msgstr "Hasło nie pasuje do złożoności usługi Active Directory." | |||||||
| msgid "No token received." | msgid "No token received." | ||||||
| msgstr "Nie otrzymano tokena." | msgstr "Nie otrzymano tokena." | ||||||
|  |  | ||||||
|  | #: authentik/sources/oauth/models.py | ||||||
|  | msgid "HTTP Basic Authentication" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/sources/oauth/models.py | ||||||
|  | msgid "Include the client ID and secret as request parameters" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/sources/oauth/models.py | #: authentik/sources/oauth/models.py | ||||||
| msgid "Request Token URL" | msgid "Request Token URL" | ||||||
| msgstr "URL żądania tokena" | msgstr "URL żądania tokena" | ||||||
| @ -2440,6 +2489,12 @@ msgstr "URL używany przez authentik do uzyskania informacji o użytkowniku." | |||||||
| msgid "Additional Scopes" | msgid "Additional Scopes" | ||||||
| msgstr "Dodatkowe zakresy" | msgstr "Dodatkowe zakresy" | ||||||
|  |  | ||||||
|  | #: authentik/sources/oauth/models.py | ||||||
|  | msgid "" | ||||||
|  | "How to perform authentication during an authorization_code token request " | ||||||
|  | "flow" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/sources/oauth/models.py | #: authentik/sources/oauth/models.py | ||||||
| msgid "OAuth Source" | msgid "OAuth Source" | ||||||
| msgstr "Źródło OAuth" | msgstr "Źródło OAuth" | ||||||
| @ -3344,6 +3399,12 @@ msgstr "" | |||||||
| "Po włączeniu tej opcji etap zakończy się powodzeniem i będzie kontynuowany " | "Po włączeniu tej opcji etap zakończy się powodzeniem i będzie kontynuowany " | ||||||
| "nawet po wprowadzeniu nieprawidłowych danych użytkownika." | "nawet po wprowadzeniu nieprawidłowych danych użytkownika." | ||||||
|  |  | ||||||
|  | #: authentik/stages/identification/models.py | ||||||
|  | msgid "" | ||||||
|  | "Show the user the 'Remember me on this device' toggle, allowing repeat users" | ||||||
|  | " to skip straight to entering their password." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/stages/identification/models.py | #: authentik/stages/identification/models.py | ||||||
| msgid "Optional enrollment flow, which is linked at the bottom of the page." | msgid "Optional enrollment flow, which is linked at the bottom of the page." | ||||||
| msgstr "" | msgstr "" | ||||||
| @ -3727,6 +3788,14 @@ msgstr "" | |||||||
| "Zdarzenia zostaną usunięte po upływie tego czasu. (Format: " | "Zdarzenia zostaną usunięte po upływie tego czasu. (Format: " | ||||||
| "weeks=3;days=2;hours=3,seconds=2)." | "weeks=3;days=2;hours=3,seconds=2)." | ||||||
|  |  | ||||||
|  | #: authentik/tenants/models.py | ||||||
|  | msgid "Reputation cannot decrease lower than this value. Zero or negative." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/tenants/models.py | ||||||
|  | msgid "Reputation cannot increase higher than this value. Zero or positive." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/tenants/models.py | #: authentik/tenants/models.py | ||||||
| msgid "The option configures the footer links on the flow executor pages." | msgid "The option configures the footer links on the flow executor pages." | ||||||
| msgstr "Opcja ta konfiguruje łącza stopki na stronach wykonawców przepływu." | msgstr "Opcja ta konfiguruje łącza stopki na stronach wykonawców przepływu." | ||||||
|  | |||||||
							
								
								
									
										
											BIN
										
									
								
								locale/pt/LC_MESSAGES/django.mo
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								locale/pt/LC_MESSAGES/django.mo
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										3924
									
								
								locale/pt/LC_MESSAGES/django.po
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3924
									
								
								locale/pt/LC_MESSAGES/django.po
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -18,7 +18,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-04-11 00:10+0000\n" | "POT-Creation-Date: 2025-04-23 09:00+0000\n" | ||||||
| "PO-Revision-Date: 2022-09-26 16:47+0000\n" | "PO-Revision-Date: 2022-09-26 16:47+0000\n" | ||||||
| "Last-Translator: Gil Poiares-Oliveira, 2025\n" | "Last-Translator: Gil Poiares-Oliveira, 2025\n" | ||||||
| "Language-Team: Portuguese (Brazil) (https://app.transifex.com/authentik/teams/119923/pt_BR/)\n" | "Language-Team: Portuguese (Brazil) (https://app.transifex.com/authentik/teams/119923/pt_BR/)\n" | ||||||
| @ -192,6 +192,7 @@ msgid "User's display name." | |||||||
| msgstr "Nome de exibição do usuário." | msgstr "Nome de exibição do usuário." | ||||||
|  |  | ||||||
| #: authentik/core/models.py authentik/providers/oauth2/models.py | #: authentik/core/models.py authentik/providers/oauth2/models.py | ||||||
|  | #: authentik/rbac/models.py | ||||||
| msgid "User" | msgid "User" | ||||||
| msgstr "Usuário" | msgstr "Usuário" | ||||||
|  |  | ||||||
| @ -376,6 +377,18 @@ msgstr "Mapeamento de propriedades" | |||||||
| msgid "Property Mappings" | msgid "Property Mappings" | ||||||
| msgstr "Mapeamentos de propriedades" | msgstr "Mapeamentos de propriedades" | ||||||
|  |  | ||||||
|  | #: authentik/core/models.py | ||||||
|  | msgid "session data" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/core/models.py | ||||||
|  | msgid "Session" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/core/models.py | ||||||
|  | msgid "Sessions" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/core/models.py | #: authentik/core/models.py | ||||||
| msgid "Authenticated Session" | msgid "Authenticated Session" | ||||||
| msgstr "Sessão Autenticada" | msgstr "Sessão Autenticada" | ||||||
| @ -483,6 +496,38 @@ msgstr "Uso de licença" | |||||||
| msgid "License Usage Records" | msgid "License Usage Records" | ||||||
| msgstr "Registros de uso de licença" | msgstr "Registros de uso de licença" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | #: authentik/policies/password/models.py | ||||||
|  | msgid "Field key to check, field keys defined in Prompt stages are available." | ||||||
|  | msgstr "" | ||||||
|  | "Chave de campo para verificar, as chaves de campo definidas nos estágios de " | ||||||
|  | "prompt estão disponíveis." | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "Number of passwords to check against." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | #: authentik/policies/password/models.py | ||||||
|  | msgid "Password not set in context" | ||||||
|  | msgstr "Senha não definida no contexto" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "This password has been used previously. Please choose a different one." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "Password Uniqueness Policy" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "Password Uniqueness Policies" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "User Password History" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/enterprise/policy.py | #: authentik/enterprise/policy.py | ||||||
| msgid "Enterprise required to access this feature." | msgid "Enterprise required to access this feature." | ||||||
| msgstr "Entrerprise é necessário para acessar essa funcionalidade" | msgstr "Entrerprise é necessário para acessar essa funcionalidade" | ||||||
| @ -1252,12 +1297,6 @@ msgstr "" | |||||||
| msgid "Clear Policy's cache metrics" | msgid "Clear Policy's cache metrics" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py |  | ||||||
| msgid "Field key to check, field keys defined in Prompt stages are available." |  | ||||||
| msgstr "" |  | ||||||
| "Chave de campo para verificar, as chaves de campo definidas nos estágios de " |  | ||||||
| "prompt estão disponíveis." |  | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py | #: authentik/policies/password/models.py | ||||||
| msgid "How many times the password hash is allowed to be on haveibeenpwned" | msgid "How many times the password hash is allowed to be on haveibeenpwned" | ||||||
| msgstr "Quantas vezes o hash da senha pode estar em haveibeenpwned" | msgstr "Quantas vezes o hash da senha pode estar em haveibeenpwned" | ||||||
| @ -1268,10 +1307,6 @@ msgid "" | |||||||
| msgstr "" | msgstr "" | ||||||
| "Se a pontuação zxcvbn for igual ou menor que esse valor, a política falhará." | "Se a pontuação zxcvbn for igual ou menor que esse valor, a política falhará." | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py |  | ||||||
| msgid "Password not set in context" |  | ||||||
| msgstr "Senha não definida no contexto" |  | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py | #: authentik/policies/password/models.py | ||||||
| msgid "Invalid password." | msgid "Invalid password." | ||||||
| msgstr "" | msgstr "" | ||||||
| @ -1313,20 +1348,6 @@ msgstr "Pontuação de reputação" | |||||||
| msgid "Reputation Scores" | msgid "Reputation Scores" | ||||||
| msgstr "Pontuações de reputação" | msgstr "Pontuações de reputação" | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/buffer.html |  | ||||||
| msgid "Waiting for authentication..." |  | ||||||
| msgstr "" |  | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/buffer.html |  | ||||||
| msgid "" |  | ||||||
| "You're already authenticating in another tab. This page will refresh once " |  | ||||||
| "authentication is completed." |  | ||||||
| msgstr "" |  | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/buffer.html |  | ||||||
| msgid "Authenticate in this tab" |  | ||||||
| msgstr "" |  | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/denied.html | #: authentik/policies/templates/policies/denied.html | ||||||
| msgid "Permission denied" | msgid "Permission denied" | ||||||
| msgstr "Permissão negada" | msgstr "Permissão negada" | ||||||
| @ -2141,6 +2162,10 @@ msgstr "" | |||||||
| msgid "Roles" | msgid "Roles" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/rbac/models.py | ||||||
|  | msgid "Initial Permissions" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/rbac/models.py | #: authentik/rbac/models.py | ||||||
| msgid "System permission" | msgid "System permission" | ||||||
| msgstr "Permissão do sistema" | msgstr "Permissão do sistema" | ||||||
| @ -2387,6 +2412,22 @@ msgstr "" | |||||||
| msgid "LDAP Source Property Mappings" | msgid "LDAP Source Property Mappings" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "User LDAP Source Connection" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "User LDAP Source Connections" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "Group LDAP Source Connection" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "Group LDAP Source Connections" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/sources/ldap/signals.py | #: authentik/sources/ldap/signals.py | ||||||
| msgid "Password does not match Active Directory Complexity." | msgid "Password does not match Active Directory Complexity." | ||||||
| msgstr "A senha não corresponde à complexidade do Active Directory." | msgstr "A senha não corresponde à complexidade do Active Directory." | ||||||
| @ -2395,6 +2436,14 @@ msgstr "A senha não corresponde à complexidade do Active Directory." | |||||||
| msgid "No token received." | msgid "No token received." | ||||||
| msgstr "Nenhum token recebido." | msgstr "Nenhum token recebido." | ||||||
|  |  | ||||||
|  | #: authentik/sources/oauth/models.py | ||||||
|  | msgid "HTTP Basic Authentication" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/sources/oauth/models.py | ||||||
|  | msgid "Include the client ID and secret as request parameters" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/sources/oauth/models.py | #: authentik/sources/oauth/models.py | ||||||
| msgid "Request Token URL" | msgid "Request Token URL" | ||||||
| msgstr "URL do token de solicitação" | msgstr "URL do token de solicitação" | ||||||
| @ -2435,6 +2484,12 @@ msgstr "URL usado pelo authentik para obter informações do usuário." | |||||||
| msgid "Additional Scopes" | msgid "Additional Scopes" | ||||||
| msgstr "Escopos Adicionais" | msgstr "Escopos Adicionais" | ||||||
|  |  | ||||||
|  | #: authentik/sources/oauth/models.py | ||||||
|  | msgid "" | ||||||
|  | "How to perform authentication during an authorization_code token request " | ||||||
|  | "flow" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/sources/oauth/models.py | #: authentik/sources/oauth/models.py | ||||||
| msgid "OAuth Source" | msgid "OAuth Source" | ||||||
| msgstr "Fonte OAuth" | msgstr "Fonte OAuth" | ||||||
| @ -3318,6 +3373,12 @@ msgid "" | |||||||
| "info is entered." | "info is entered." | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/stages/identification/models.py | ||||||
|  | msgid "" | ||||||
|  | "Show the user the 'Remember me on this device' toggle, allowing repeat users" | ||||||
|  | " to skip straight to entering their password." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/stages/identification/models.py | #: authentik/stages/identification/models.py | ||||||
| msgid "Optional enrollment flow, which is linked at the bottom of the page." | msgid "Optional enrollment flow, which is linked at the bottom of the page." | ||||||
| msgstr "Optional enrollment flow, which is linked at the bottom of the page." | msgstr "Optional enrollment flow, which is linked at the bottom of the page." | ||||||
| @ -3678,6 +3739,14 @@ msgstr "" | |||||||
| "Os eventos serão excluídos após esta duração.(Formato: " | "Os eventos serão excluídos após esta duração.(Formato: " | ||||||
| "semanas=3;dias=2;horas=3,segundos=2)." | "semanas=3;dias=2;horas=3,segundos=2)." | ||||||
|  |  | ||||||
|  | #: authentik/tenants/models.py | ||||||
|  | msgid "Reputation cannot decrease lower than this value. Zero or negative." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/tenants/models.py | ||||||
|  | msgid "Reputation cannot increase higher than this value. Zero or positive." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/tenants/models.py | #: authentik/tenants/models.py | ||||||
| msgid "The option configures the footer links on the flow executor pages." | msgid "The option configures the footer links on the flow executor pages." | ||||||
| msgstr "" | msgstr "" | ||||||
|  | |||||||
| @ -18,7 +18,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-04-11 00:10+0000\n" | "POT-Creation-Date: 2025-04-23 09:00+0000\n" | ||||||
| "PO-Revision-Date: 2022-09-26 16:47+0000\n" | "PO-Revision-Date: 2022-09-26 16:47+0000\n" | ||||||
| "Last-Translator: Marc Schmitt, 2025\n" | "Last-Translator: Marc Schmitt, 2025\n" | ||||||
| "Language-Team: Russian (https://app.transifex.com/authentik/teams/119923/ru/)\n" | "Language-Team: Russian (https://app.transifex.com/authentik/teams/119923/ru/)\n" | ||||||
| @ -191,6 +191,7 @@ msgid "User's display name." | |||||||
| msgstr "Отображаемое имя пользователя." | msgstr "Отображаемое имя пользователя." | ||||||
|  |  | ||||||
| #: authentik/core/models.py authentik/providers/oauth2/models.py | #: authentik/core/models.py authentik/providers/oauth2/models.py | ||||||
|  | #: authentik/rbac/models.py | ||||||
| msgid "User" | msgid "User" | ||||||
| msgstr "Пользователь" | msgstr "Пользователь" | ||||||
|  |  | ||||||
| @ -379,6 +380,18 @@ msgstr "Сопоставление свойств" | |||||||
| msgid "Property Mappings" | msgid "Property Mappings" | ||||||
| msgstr "Сопоставление свойств" | msgstr "Сопоставление свойств" | ||||||
|  |  | ||||||
|  | #: authentik/core/models.py | ||||||
|  | msgid "session data" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/core/models.py | ||||||
|  | msgid "Session" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/core/models.py | ||||||
|  | msgid "Sessions" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/core/models.py | #: authentik/core/models.py | ||||||
| msgid "Authenticated Session" | msgid "Authenticated Session" | ||||||
| msgstr "Аутентифицированная Сессия" | msgstr "Аутентифицированная Сессия" | ||||||
| @ -487,6 +500,37 @@ msgstr "Использование лицензии" | |||||||
| msgid "License Usage Records" | msgid "License Usage Records" | ||||||
| msgstr "Записи использования лицензии" | msgstr "Записи использования лицензии" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | #: authentik/policies/password/models.py | ||||||
|  | msgid "Field key to check, field keys defined in Prompt stages are available." | ||||||
|  | msgstr "" | ||||||
|  | "Ключ поля для проверки, доступны ключи поля, определенные в этапах запроса." | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "Number of passwords to check against." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | #: authentik/policies/password/models.py | ||||||
|  | msgid "Password not set in context" | ||||||
|  | msgstr "Пароль не задан в контексте" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "This password has been used previously. Please choose a different one." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "Password Uniqueness Policy" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "Password Uniqueness Policies" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "User Password History" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/enterprise/policy.py | #: authentik/enterprise/policy.py | ||||||
| msgid "Enterprise required to access this feature." | msgid "Enterprise required to access this feature." | ||||||
| msgstr "Для доступа к этой функции требуется Enterprise." | msgstr "Для доступа к этой функции требуется Enterprise." | ||||||
| @ -1267,11 +1311,6 @@ msgstr "Просмотр показателей кэша политики" | |||||||
| msgid "Clear Policy's cache metrics" | msgid "Clear Policy's cache metrics" | ||||||
| msgstr "Очистка показателей кэша политики" | msgstr "Очистка показателей кэша политики" | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py |  | ||||||
| msgid "Field key to check, field keys defined in Prompt stages are available." |  | ||||||
| msgstr "" |  | ||||||
| "Ключ поля для проверки, доступны ключи поля, определенные в этапах запроса." |  | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py | #: authentik/policies/password/models.py | ||||||
| msgid "How many times the password hash is allowed to be on haveibeenpwned" | msgid "How many times the password hash is allowed to be on haveibeenpwned" | ||||||
| msgstr "Как часто хэш пароля может быть представлен на haveibeenpwned" | msgstr "Как часто хэш пароля может быть представлен на haveibeenpwned" | ||||||
| @ -1283,10 +1322,6 @@ msgstr "" | |||||||
| "Если показатель zxcvbn равен или меньше этого значения, политика будет " | "Если показатель zxcvbn равен или меньше этого значения, политика будет " | ||||||
| "провалена." | "провалена." | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py |  | ||||||
| msgid "Password not set in context" |  | ||||||
| msgstr "Пароль не задан в контексте" |  | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py | #: authentik/policies/password/models.py | ||||||
| msgid "Invalid password." | msgid "Invalid password." | ||||||
| msgstr "Неправильный пароль" | msgstr "Неправильный пароль" | ||||||
| @ -1328,20 +1363,6 @@ msgstr "Оценка репутации" | |||||||
| msgid "Reputation Scores" | msgid "Reputation Scores" | ||||||
| msgstr "Оценка репутации" | msgstr "Оценка репутации" | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/buffer.html |  | ||||||
| msgid "Waiting for authentication..." |  | ||||||
| msgstr "" |  | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/buffer.html |  | ||||||
| msgid "" |  | ||||||
| "You're already authenticating in another tab. This page will refresh once " |  | ||||||
| "authentication is completed." |  | ||||||
| msgstr "" |  | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/buffer.html |  | ||||||
| msgid "Authenticate in this tab" |  | ||||||
| msgstr "" |  | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/denied.html | #: authentik/policies/templates/policies/denied.html | ||||||
| msgid "Permission denied" | msgid "Permission denied" | ||||||
| msgstr "Доступ запрещен" | msgstr "Доступ запрещен" | ||||||
| @ -2164,6 +2185,10 @@ msgstr "Роль" | |||||||
| msgid "Roles" | msgid "Roles" | ||||||
| msgstr "Роли" | msgstr "Роли" | ||||||
|  |  | ||||||
|  | #: authentik/rbac/models.py | ||||||
|  | msgid "Initial Permissions" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/rbac/models.py | #: authentik/rbac/models.py | ||||||
| msgid "System permission" | msgid "System permission" | ||||||
| msgstr "Системное разрешение" | msgstr "Системное разрешение" | ||||||
| @ -2421,6 +2446,22 @@ msgstr "Сопоставление свойства LDAP источника" | |||||||
| msgid "LDAP Source Property Mappings" | msgid "LDAP Source Property Mappings" | ||||||
| msgstr "Сопоставление свойств LDAP источника" | msgstr "Сопоставление свойств LDAP источника" | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "User LDAP Source Connection" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "User LDAP Source Connections" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "Group LDAP Source Connection" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "Group LDAP Source Connections" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/sources/ldap/signals.py | #: authentik/sources/ldap/signals.py | ||||||
| msgid "Password does not match Active Directory Complexity." | msgid "Password does not match Active Directory Complexity." | ||||||
| msgstr "Пароль не соответствует сложности Active Directory." | msgstr "Пароль не соответствует сложности Active Directory." | ||||||
| @ -2429,6 +2470,14 @@ msgstr "Пароль не соответствует сложности Active D | |||||||
| msgid "No token received." | msgid "No token received." | ||||||
| msgstr "Токен не был получен." | msgstr "Токен не был получен." | ||||||
|  |  | ||||||
|  | #: authentik/sources/oauth/models.py | ||||||
|  | msgid "HTTP Basic Authentication" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/sources/oauth/models.py | ||||||
|  | msgid "Include the client ID and secret as request parameters" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/sources/oauth/models.py | #: authentik/sources/oauth/models.py | ||||||
| msgid "Request Token URL" | msgid "Request Token URL" | ||||||
| msgstr "URL-адрес запроса токена" | msgstr "URL-адрес запроса токена" | ||||||
| @ -2471,6 +2520,12 @@ msgstr "" | |||||||
| msgid "Additional Scopes" | msgid "Additional Scopes" | ||||||
| msgstr "Дополнительные области" | msgstr "Дополнительные области" | ||||||
|  |  | ||||||
|  | #: authentik/sources/oauth/models.py | ||||||
|  | msgid "" | ||||||
|  | "How to perform authentication during an authorization_code token request " | ||||||
|  | "flow" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/sources/oauth/models.py | #: authentik/sources/oauth/models.py | ||||||
| msgid "OAuth Source" | msgid "OAuth Source" | ||||||
| msgstr "Источник OAuth" | msgstr "Источник OAuth" | ||||||
| @ -3376,6 +3431,12 @@ msgstr "" | |||||||
| "При включении этап будет завершаться успешно и продолжаться даже в случае " | "При включении этап будет завершаться успешно и продолжаться даже в случае " | ||||||
| "ввода неправильной информации о пользователе." | "ввода неправильной информации о пользователе." | ||||||
|  |  | ||||||
|  | #: authentik/stages/identification/models.py | ||||||
|  | msgid "" | ||||||
|  | "Show the user the 'Remember me on this device' toggle, allowing repeat users" | ||||||
|  | " to skip straight to entering their password." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/stages/identification/models.py | #: authentik/stages/identification/models.py | ||||||
| msgid "Optional enrollment flow, which is linked at the bottom of the page." | msgid "Optional enrollment flow, which is linked at the bottom of the page." | ||||||
| msgstr "" | msgstr "" | ||||||
| @ -3767,6 +3828,14 @@ msgstr "" | |||||||
| "По истечении этого времени события будут удалены. (Формат: недели=3; дни=2; " | "По истечении этого времени события будут удалены. (Формат: недели=3; дни=2; " | ||||||
| "часы=3, секунды=2)." | "часы=3, секунды=2)." | ||||||
|  |  | ||||||
|  | #: authentik/tenants/models.py | ||||||
|  | msgid "Reputation cannot decrease lower than this value. Zero or negative." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/tenants/models.py | ||||||
|  | msgid "Reputation cannot increase higher than this value. Zero or positive." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/tenants/models.py | #: authentik/tenants/models.py | ||||||
| msgid "The option configures the footer links on the flow executor pages." | msgid "The option configures the footer links on the flow executor pages." | ||||||
| msgstr "" | msgstr "" | ||||||
|  | |||||||
										
											Binary file not shown.
										
									
								
							| @ -13,7 +13,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-31 00:10+0000\n" | "POT-Creation-Date: 2025-04-23 09:00+0000\n" | ||||||
| "PO-Revision-Date: 2022-09-26 16:47+0000\n" | "PO-Revision-Date: 2022-09-26 16:47+0000\n" | ||||||
| "Last-Translator: Jens L. <jens@goauthentik.io>, 2025\n" | "Last-Translator: Jens L. <jens@goauthentik.io>, 2025\n" | ||||||
| "Language-Team: Turkish (https://app.transifex.com/authentik/teams/119923/tr/)\n" | "Language-Team: Turkish (https://app.transifex.com/authentik/teams/119923/tr/)\n" | ||||||
| @ -187,6 +187,7 @@ msgid "User's display name." | |||||||
| msgstr "Kullanıcının görünen adı." | msgstr "Kullanıcının görünen adı." | ||||||
|  |  | ||||||
| #: authentik/core/models.py authentik/providers/oauth2/models.py | #: authentik/core/models.py authentik/providers/oauth2/models.py | ||||||
|  | #: authentik/rbac/models.py | ||||||
| msgid "User" | msgid "User" | ||||||
| msgstr "Kullanıcı" | msgstr "Kullanıcı" | ||||||
|  |  | ||||||
| @ -372,6 +373,18 @@ msgstr "Özellik Eşleme" | |||||||
| msgid "Property Mappings" | msgid "Property Mappings" | ||||||
| msgstr "Özellik Eşlemeleri" | msgstr "Özellik Eşlemeleri" | ||||||
|  |  | ||||||
|  | #: authentik/core/models.py | ||||||
|  | msgid "session data" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/core/models.py | ||||||
|  | msgid "Session" | ||||||
|  | msgstr "Oturum" | ||||||
|  |  | ||||||
|  | #: authentik/core/models.py | ||||||
|  | msgid "Sessions" | ||||||
|  | msgstr "Oturumlar" | ||||||
|  |  | ||||||
| #: authentik/core/models.py | #: authentik/core/models.py | ||||||
| msgid "Authenticated Session" | msgid "Authenticated Session" | ||||||
| msgstr "Kimliği Doğrulanmış Oturum" | msgstr "Kimliği Doğrulanmış Oturum" | ||||||
| @ -479,6 +492,38 @@ msgstr "Lisans Kullanımı" | |||||||
| msgid "License Usage Records" | msgid "License Usage Records" | ||||||
| msgstr "Lisans Kullanım Kayıtları" | msgstr "Lisans Kullanım Kayıtları" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | #: authentik/policies/password/models.py | ||||||
|  | msgid "Field key to check, field keys defined in Prompt stages are available." | ||||||
|  | msgstr "" | ||||||
|  | "Alan tuşu kontrol etmek için, İstem aşamalarında tanımlanan alan tuşları " | ||||||
|  | "mevcuttur." | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "Number of passwords to check against." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | #: authentik/policies/password/models.py | ||||||
|  | msgid "Password not set in context" | ||||||
|  | msgstr "Parola bağlam içinde ayarlanmamış" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "This password has been used previously. Please choose a different one." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "Password Uniqueness Policy" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "Password Uniqueness Policies" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "User Password History" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/enterprise/policy.py | #: authentik/enterprise/policy.py | ||||||
| msgid "Enterprise required to access this feature." | msgid "Enterprise required to access this feature." | ||||||
| msgstr "Bu özelliğe erişmek için Kurumsal Paket gereklidir." | msgstr "Bu özelliğe erişmek için Kurumsal Paket gereklidir." | ||||||
| @ -1253,12 +1298,6 @@ msgstr "İlke'nin önbellek ölçümlerini görüntüleme" | |||||||
| msgid "Clear Policy's cache metrics" | msgid "Clear Policy's cache metrics" | ||||||
| msgstr "İlke'nin önbellek ölçümlerini temizleyin" | msgstr "İlke'nin önbellek ölçümlerini temizleyin" | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py |  | ||||||
| msgid "Field key to check, field keys defined in Prompt stages are available." |  | ||||||
| msgstr "" |  | ||||||
| "Alan tuşu kontrol etmek için, İstem aşamalarında tanımlanan alan tuşları " |  | ||||||
| "mevcuttur." |  | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py | #: authentik/policies/password/models.py | ||||||
| msgid "How many times the password hash is allowed to be on haveibeenpwned" | msgid "How many times the password hash is allowed to be on haveibeenpwned" | ||||||
| msgstr "" | msgstr "" | ||||||
| @ -1271,10 +1310,6 @@ msgstr "" | |||||||
| "Eğer zxcvbn puanı bu değere eşit veya daha az ise, politika başarısız " | "Eğer zxcvbn puanı bu değere eşit veya daha az ise, politika başarısız " | ||||||
| "olacaktır." | "olacaktır." | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py |  | ||||||
| msgid "Password not set in context" |  | ||||||
| msgstr "Parola bağlam içinde ayarlanmamış" |  | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py | #: authentik/policies/password/models.py | ||||||
| msgid "Invalid password." | msgid "Invalid password." | ||||||
| msgstr "" | msgstr "" | ||||||
| @ -1316,20 +1351,6 @@ msgstr "İtibar Puanı" | |||||||
| msgid "Reputation Scores" | msgid "Reputation Scores" | ||||||
| msgstr "İtibar Puanları" | msgstr "İtibar Puanları" | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/buffer.html |  | ||||||
| msgid "Waiting for authentication..." |  | ||||||
| msgstr "" |  | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/buffer.html |  | ||||||
| msgid "" |  | ||||||
| "You're already authenticating in another tab. This page will refresh once " |  | ||||||
| "authentication is completed." |  | ||||||
| msgstr "" |  | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/buffer.html |  | ||||||
| msgid "Authenticate in this tab" |  | ||||||
| msgstr "" |  | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/denied.html | #: authentik/policies/templates/policies/denied.html | ||||||
| msgid "Permission denied" | msgid "Permission denied" | ||||||
| msgstr "İzin reddedildi" | msgstr "İzin reddedildi" | ||||||
| @ -2155,6 +2176,10 @@ msgstr "Rol" | |||||||
| msgid "Roles" | msgid "Roles" | ||||||
| msgstr "Roller" | msgstr "Roller" | ||||||
|  |  | ||||||
|  | #: authentik/rbac/models.py | ||||||
|  | msgid "Initial Permissions" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/rbac/models.py | #: authentik/rbac/models.py | ||||||
| msgid "System permission" | msgid "System permission" | ||||||
| msgstr "Sistem yetkisi" | msgstr "Sistem yetkisi" | ||||||
| @ -2398,6 +2423,13 @@ msgstr "" | |||||||
| "Bir kullanıcı parolasını değiştirdiğinde, parolayı LDAP ile geri eşitleyin. " | "Bir kullanıcı parolasını değiştirdiğinde, parolayı LDAP ile geri eşitleyin. " | ||||||
| "Bu yalnızca tek bir LDAP kaynağında etkinleştirilebilir." | "Bu yalnızca tek bir LDAP kaynağında etkinleştirilebilir." | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "" | ||||||
|  | "Lookup group membership based on a user attribute instead of a group " | ||||||
|  | "attribute. This allows nested group resolution on systems like FreeIPA and " | ||||||
|  | "Active Directory" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/sources/ldap/models.py | #: authentik/sources/ldap/models.py | ||||||
| msgid "LDAP Source" | msgid "LDAP Source" | ||||||
| msgstr "LDAP Kaynağı" | msgstr "LDAP Kaynağı" | ||||||
| @ -2414,6 +2446,22 @@ msgstr "LDAP Kaynak Özellik Eşlemesi" | |||||||
| msgid "LDAP Source Property Mappings" | msgid "LDAP Source Property Mappings" | ||||||
| msgstr "LDAP Kaynak Özellik Eşlemeleri" | msgstr "LDAP Kaynak Özellik Eşlemeleri" | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "User LDAP Source Connection" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "User LDAP Source Connections" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "Group LDAP Source Connection" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "Group LDAP Source Connections" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/sources/ldap/signals.py | #: authentik/sources/ldap/signals.py | ||||||
| msgid "Password does not match Active Directory Complexity." | msgid "Password does not match Active Directory Complexity." | ||||||
| msgstr "Parola Active Directory Karmaşıklığıyla eşleşmiyor." | msgstr "Parola Active Directory Karmaşıklığıyla eşleşmiyor." | ||||||
| @ -2422,6 +2470,14 @@ msgstr "Parola Active Directory Karmaşıklığıyla eşleşmiyor." | |||||||
| msgid "No token received." | msgid "No token received." | ||||||
| msgstr "Jeton alınmadı." | msgstr "Jeton alınmadı." | ||||||
|  |  | ||||||
|  | #: authentik/sources/oauth/models.py | ||||||
|  | msgid "HTTP Basic Authentication" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/sources/oauth/models.py | ||||||
|  | msgid "Include the client ID and secret as request parameters" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/sources/oauth/models.py | #: authentik/sources/oauth/models.py | ||||||
| msgid "Request Token URL" | msgid "Request Token URL" | ||||||
| msgstr "Jeton URL'si İste" | msgstr "Jeton URL'si İste" | ||||||
| @ -2462,6 +2518,12 @@ msgstr "Kullanıcı bilgilerini almak için authentik tarafından kullanılan UR | |||||||
| msgid "Additional Scopes" | msgid "Additional Scopes" | ||||||
| msgstr "Ek Kapsamlar" | msgstr "Ek Kapsamlar" | ||||||
|  |  | ||||||
|  | #: authentik/sources/oauth/models.py | ||||||
|  | msgid "" | ||||||
|  | "How to perform authentication during an authorization_code token request " | ||||||
|  | "flow" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/sources/oauth/models.py | #: authentik/sources/oauth/models.py | ||||||
| msgid "OAuth Source" | msgid "OAuth Source" | ||||||
| msgstr "OAuth Kaynağı" | msgstr "OAuth Kaynağı" | ||||||
| @ -3360,6 +3422,12 @@ msgstr "" | |||||||
| "Etkinleştirildiğinde, yanlış kullanıcı bilgisi girilse bile aşama başarılı " | "Etkinleştirildiğinde, yanlış kullanıcı bilgisi girilse bile aşama başarılı " | ||||||
| "olur ve devam eder." | "olur ve devam eder." | ||||||
|  |  | ||||||
|  | #: authentik/stages/identification/models.py | ||||||
|  | msgid "" | ||||||
|  | "Show the user the 'Remember me on this device' toggle, allowing repeat users" | ||||||
|  | " to skip straight to entering their password." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/stages/identification/models.py | #: authentik/stages/identification/models.py | ||||||
| msgid "Optional enrollment flow, which is linked at the bottom of the page." | msgid "Optional enrollment flow, which is linked at the bottom of the page." | ||||||
| msgstr "Sayfanın alt kısmında bağlanan isteğe bağlı kayıt akışı." | msgstr "Sayfanın alt kısmında bağlanan isteğe bağlı kayıt akışı." | ||||||
| @ -3734,6 +3802,14 @@ msgstr "" | |||||||
| "Olaylar bu süreden sonra silinecektir (Format: " | "Olaylar bu süreden sonra silinecektir (Format: " | ||||||
| "weeks=3;days=2;hours=3,seconds=2)." | "weeks=3;days=2;hours=3,seconds=2)." | ||||||
|  |  | ||||||
|  | #: authentik/tenants/models.py | ||||||
|  | msgid "Reputation cannot decrease lower than this value. Zero or negative." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/tenants/models.py | ||||||
|  | msgid "Reputation cannot increase higher than this value. Zero or positive." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/tenants/models.py | #: authentik/tenants/models.py | ||||||
| msgid "The option configures the footer links on the flow executor pages." | msgid "The option configures the footer links on the flow executor pages." | ||||||
| msgstr "" | msgstr "" | ||||||
|  | |||||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							| @ -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-04-11 00:10+0000\n" | "POT-Creation-Date: 2025-04-23 09:00+0000\n" | ||||||
| "PO-Revision-Date: 2022-09-26 16:47+0000\n" | "PO-Revision-Date: 2022-09-26 16:47+0000\n" | ||||||
| "Last-Translator: 刘松, 2025\n" | "Last-Translator: 刘松, 2025\n" | ||||||
| "Language-Team: Chinese (Taiwan) (https://app.transifex.com/authentik/teams/119923/zh_TW/)\n" | "Language-Team: Chinese (Taiwan) (https://app.transifex.com/authentik/teams/119923/zh_TW/)\n" | ||||||
| @ -178,6 +178,7 @@ msgid "User's display name." | |||||||
| msgstr "使用者的顯示名稱。" | msgstr "使用者的顯示名稱。" | ||||||
|  |  | ||||||
| #: authentik/core/models.py authentik/providers/oauth2/models.py | #: authentik/core/models.py authentik/providers/oauth2/models.py | ||||||
|  | #: authentik/rbac/models.py | ||||||
| msgid "User" | msgid "User" | ||||||
| msgstr "使用者" | msgstr "使用者" | ||||||
|  |  | ||||||
| @ -344,6 +345,18 @@ msgstr "屬性對應" | |||||||
| msgid "Property Mappings" | msgid "Property Mappings" | ||||||
| msgstr "屬性對應" | msgstr "屬性對應" | ||||||
|  |  | ||||||
|  | #: authentik/core/models.py | ||||||
|  | msgid "session data" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/core/models.py | ||||||
|  | msgid "Session" | ||||||
|  | msgstr "会话" | ||||||
|  |  | ||||||
|  | #: authentik/core/models.py | ||||||
|  | msgid "Sessions" | ||||||
|  | msgstr "会话" | ||||||
|  |  | ||||||
| #: authentik/core/models.py | #: authentik/core/models.py | ||||||
| msgid "Authenticated Session" | msgid "Authenticated Session" | ||||||
| msgstr "已認證會談" | msgstr "已認證會談" | ||||||
| @ -447,6 +460,36 @@ msgstr "授權使用情況" | |||||||
| msgid "License Usage Records" | msgid "License Usage Records" | ||||||
| msgstr "授權使用紀錄" | msgstr "授權使用紀錄" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | #: authentik/policies/password/models.py | ||||||
|  | msgid "Field key to check, field keys defined in Prompt stages are available." | ||||||
|  | msgstr "要檢查的欄位鍵,在提示階段中有可用的已定義欄位鍵。" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "Number of passwords to check against." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | #: authentik/policies/password/models.py | ||||||
|  | msgid "Password not set in context" | ||||||
|  | msgstr "未在上下文中設定密碼" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "This password has been used previously. Please choose a different one." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "Password Uniqueness Policy" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "Password Uniqueness Policies" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/enterprise/policies/unique_password/models.py | ||||||
|  | msgid "User Password History" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/enterprise/policy.py | #: authentik/enterprise/policy.py | ||||||
| msgid "Enterprise required to access this feature." | msgid "Enterprise required to access this feature." | ||||||
| msgstr "企業版才能存取此功能。" | msgstr "企業版才能存取此功能。" | ||||||
| @ -1176,10 +1219,6 @@ msgstr "檢視原則的快取指標" | |||||||
| msgid "Clear Policy's cache metrics" | msgid "Clear Policy's cache metrics" | ||||||
| msgstr "清除原則的快取指標" | msgstr "清除原則的快取指標" | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py |  | ||||||
| msgid "Field key to check, field keys defined in Prompt stages are available." |  | ||||||
| msgstr "要檢查的欄位鍵,在提示階段中有可用的已定義欄位鍵。" |  | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py | #: authentik/policies/password/models.py | ||||||
| msgid "How many times the password hash is allowed to be on haveibeenpwned" | msgid "How many times the password hash is allowed to be on haveibeenpwned" | ||||||
| msgstr "密碼雜湊在 haveibeenpwned 上允許出現的次數" | msgstr "密碼雜湊在 haveibeenpwned 上允許出現的次數" | ||||||
| @ -1189,10 +1228,6 @@ msgid "" | |||||||
| "If the zxcvbn score is equal or less than this value, the policy will fail." | "If the zxcvbn score is equal or less than this value, the policy will fail." | ||||||
| msgstr "如果 zxcvbn 分數等於或小於此值,則該政策將失敗。" | msgstr "如果 zxcvbn 分數等於或小於此值,則該政策將失敗。" | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py |  | ||||||
| msgid "Password not set in context" |  | ||||||
| msgstr "未在上下文中設定密碼" |  | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py | #: authentik/policies/password/models.py | ||||||
| msgid "Invalid password." | msgid "Invalid password." | ||||||
| msgstr "" | msgstr "" | ||||||
| @ -1234,20 +1269,6 @@ msgstr "信譽分數" | |||||||
| msgid "Reputation Scores" | msgid "Reputation Scores" | ||||||
| msgstr "信譽分數" | msgstr "信譽分數" | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/buffer.html |  | ||||||
| msgid "Waiting for authentication..." |  | ||||||
| msgstr "" |  | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/buffer.html |  | ||||||
| msgid "" |  | ||||||
| "You're already authenticating in another tab. This page will refresh once " |  | ||||||
| "authentication is completed." |  | ||||||
| msgstr "" |  | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/buffer.html |  | ||||||
| msgid "Authenticate in this tab" |  | ||||||
| msgstr "" |  | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/denied.html | #: authentik/policies/templates/policies/denied.html | ||||||
| msgid "Permission denied" | msgid "Permission denied" | ||||||
| msgstr "權限不足。" | msgstr "權限不足。" | ||||||
| @ -1999,6 +2020,10 @@ msgstr "角色" | |||||||
| msgid "Roles" | msgid "Roles" | ||||||
| msgstr "角色" | msgstr "角色" | ||||||
|  |  | ||||||
|  | #: authentik/rbac/models.py | ||||||
|  | msgid "Initial Permissions" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/rbac/models.py | #: authentik/rbac/models.py | ||||||
| msgid "System permission" | msgid "System permission" | ||||||
| msgstr "系統權限" | msgstr "系統權限" | ||||||
| @ -2240,6 +2265,22 @@ msgstr "" | |||||||
| msgid "LDAP Source Property Mappings" | msgid "LDAP Source Property Mappings" | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "User LDAP Source Connection" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "User LDAP Source Connections" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "Group LDAP Source Connection" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/sources/ldap/models.py | ||||||
|  | msgid "Group LDAP Source Connections" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/sources/ldap/signals.py | #: authentik/sources/ldap/signals.py | ||||||
| msgid "Password does not match Active Directory Complexity." | msgid "Password does not match Active Directory Complexity." | ||||||
| msgstr "密碼不符合 Active Directory 的複雜性要求。" | msgstr "密碼不符合 Active Directory 的複雜性要求。" | ||||||
| @ -2248,6 +2289,14 @@ msgstr "密碼不符合 Active Directory 的複雜性要求。" | |||||||
| msgid "No token received." | msgid "No token received." | ||||||
| msgstr "未收到權杖。" | msgstr "未收到權杖。" | ||||||
|  |  | ||||||
|  | #: authentik/sources/oauth/models.py | ||||||
|  | msgid "HTTP Basic Authentication" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/sources/oauth/models.py | ||||||
|  | msgid "Include the client ID and secret as request parameters" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/sources/oauth/models.py | #: authentik/sources/oauth/models.py | ||||||
| msgid "Request Token URL" | msgid "Request Token URL" | ||||||
| msgstr "請求權杖的網址" | msgstr "請求權杖的網址" | ||||||
| @ -2286,6 +2335,12 @@ msgstr "authentik 用來擷取使用者資訊的網址。" | |||||||
| msgid "Additional Scopes" | msgid "Additional Scopes" | ||||||
| msgstr "附加範圍" | msgstr "附加範圍" | ||||||
|  |  | ||||||
|  | #: authentik/sources/oauth/models.py | ||||||
|  | msgid "" | ||||||
|  | "How to perform authentication during an authorization_code token request " | ||||||
|  | "flow" | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/sources/oauth/models.py | #: authentik/sources/oauth/models.py | ||||||
| msgid "OAuth Source" | msgid "OAuth Source" | ||||||
| msgstr "OAuth 來源" | msgstr "OAuth 來源" | ||||||
| @ -3137,6 +3192,12 @@ msgid "" | |||||||
| "info is entered." | "info is entered." | ||||||
| msgstr "" | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/stages/identification/models.py | ||||||
|  | msgid "" | ||||||
|  | "Show the user the 'Remember me on this device' toggle, allowing repeat users" | ||||||
|  | " to skip straight to entering their password." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/stages/identification/models.py | #: authentik/stages/identification/models.py | ||||||
| msgid "Optional enrollment flow, which is linked at the bottom of the page." | msgid "Optional enrollment flow, which is linked at the bottom of the page." | ||||||
| msgstr "可選的註冊流程,連結在頁面的底部。" | msgstr "可選的註冊流程,連結在頁面的底部。" | ||||||
| @ -3481,6 +3542,14 @@ msgid "" | |||||||
| "weeks=3;days=2;hours=3,seconds=2)." | "weeks=3;days=2;hours=3,seconds=2)." | ||||||
| msgstr "事件將在此期間後刪除。(格式:weeks=3;days=2;hours=3,seconds=2)" | msgstr "事件將在此期間後刪除。(格式:weeks=3;days=2;hours=3,seconds=2)" | ||||||
|  |  | ||||||
|  | #: authentik/tenants/models.py | ||||||
|  | msgid "Reputation cannot decrease lower than this value. Zero or negative." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
|  | #: authentik/tenants/models.py | ||||||
|  | msgid "Reputation cannot increase higher than this value. Zero or positive." | ||||||
|  | msgstr "" | ||||||
|  |  | ||||||
| #: authentik/tenants/models.py | #: authentik/tenants/models.py | ||||||
| msgid "The option configures the footer links on the flow executor pages." | msgid "The option configures the footer links on the flow executor pages." | ||||||
| msgstr "" | msgstr "" | ||||||
|  | |||||||
							
								
								
									
										538
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										538
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -1,12 +1,546 @@ | |||||||
| { | { | ||||||
|     "name": "@goauthentik/authentik", |     "name": "@goauthentik/authentik", | ||||||
|     "version": "2025.2.1", |     "version": "2025.4.0", | ||||||
|     "lockfileVersion": 3, |     "lockfileVersion": 3, | ||||||
|     "requires": true, |     "requires": true, | ||||||
|     "packages": { |     "packages": { | ||||||
|         "": { |         "": { | ||||||
|             "name": "@goauthentik/authentik", |             "name": "@goauthentik/authentik", | ||||||
|             "version": "2025.2.1" |             "version": "2025.4.0", | ||||||
|  |             "devDependencies": { | ||||||
|  |                 "@trivago/prettier-plugin-sort-imports": "^5.2.2", | ||||||
|  |                 "prettier": "^3.3.3", | ||||||
|  |                 "prettier-plugin-organize-imports": "^4.1.0", | ||||||
|  |                 "prettier-plugin-packagejson": "^2.5.10", | ||||||
|  |                 "typescript": "^5.6.2" | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "node_modules/@babel/code-frame": { | ||||||
|  |             "version": "7.26.2", | ||||||
|  |             "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", | ||||||
|  |             "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "MIT", | ||||||
|  |             "dependencies": { | ||||||
|  |                 "@babel/helper-validator-identifier": "^7.25.9", | ||||||
|  |                 "js-tokens": "^4.0.0", | ||||||
|  |                 "picocolors": "^1.0.0" | ||||||
|  |             }, | ||||||
|  |             "engines": { | ||||||
|  |                 "node": ">=6.9.0" | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "node_modules/@babel/generator": { | ||||||
|  |             "version": "7.27.0", | ||||||
|  |             "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz", | ||||||
|  |             "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "MIT", | ||||||
|  |             "dependencies": { | ||||||
|  |                 "@babel/parser": "^7.27.0", | ||||||
|  |                 "@babel/types": "^7.27.0", | ||||||
|  |                 "@jridgewell/gen-mapping": "^0.3.5", | ||||||
|  |                 "@jridgewell/trace-mapping": "^0.3.25", | ||||||
|  |                 "jsesc": "^3.0.2" | ||||||
|  |             }, | ||||||
|  |             "engines": { | ||||||
|  |                 "node": ">=6.9.0" | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "node_modules/@babel/helper-string-parser": { | ||||||
|  |             "version": "7.25.9", | ||||||
|  |             "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", | ||||||
|  |             "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "MIT", | ||||||
|  |             "engines": { | ||||||
|  |                 "node": ">=6.9.0" | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "node_modules/@babel/helper-validator-identifier": { | ||||||
|  |             "version": "7.25.9", | ||||||
|  |             "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", | ||||||
|  |             "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "MIT", | ||||||
|  |             "engines": { | ||||||
|  |                 "node": ">=6.9.0" | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "node_modules/@babel/parser": { | ||||||
|  |             "version": "7.27.0", | ||||||
|  |             "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz", | ||||||
|  |             "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "MIT", | ||||||
|  |             "dependencies": { | ||||||
|  |                 "@babel/types": "^7.27.0" | ||||||
|  |             }, | ||||||
|  |             "bin": { | ||||||
|  |                 "parser": "bin/babel-parser.js" | ||||||
|  |             }, | ||||||
|  |             "engines": { | ||||||
|  |                 "node": ">=6.0.0" | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "node_modules/@babel/template": { | ||||||
|  |             "version": "7.27.0", | ||||||
|  |             "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz", | ||||||
|  |             "integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "MIT", | ||||||
|  |             "dependencies": { | ||||||
|  |                 "@babel/code-frame": "^7.26.2", | ||||||
|  |                 "@babel/parser": "^7.27.0", | ||||||
|  |                 "@babel/types": "^7.27.0" | ||||||
|  |             }, | ||||||
|  |             "engines": { | ||||||
|  |                 "node": ">=6.9.0" | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "node_modules/@babel/traverse": { | ||||||
|  |             "version": "7.27.0", | ||||||
|  |             "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz", | ||||||
|  |             "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "MIT", | ||||||
|  |             "dependencies": { | ||||||
|  |                 "@babel/code-frame": "^7.26.2", | ||||||
|  |                 "@babel/generator": "^7.27.0", | ||||||
|  |                 "@babel/parser": "^7.27.0", | ||||||
|  |                 "@babel/template": "^7.27.0", | ||||||
|  |                 "@babel/types": "^7.27.0", | ||||||
|  |                 "debug": "^4.3.1", | ||||||
|  |                 "globals": "^11.1.0" | ||||||
|  |             }, | ||||||
|  |             "engines": { | ||||||
|  |                 "node": ">=6.9.0" | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "node_modules/@babel/types": { | ||||||
|  |             "version": "7.27.0", | ||||||
|  |             "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", | ||||||
|  |             "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "MIT", | ||||||
|  |             "dependencies": { | ||||||
|  |                 "@babel/helper-string-parser": "^7.25.9", | ||||||
|  |                 "@babel/helper-validator-identifier": "^7.25.9" | ||||||
|  |             }, | ||||||
|  |             "engines": { | ||||||
|  |                 "node": ">=6.9.0" | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "node_modules/@jridgewell/gen-mapping": { | ||||||
|  |             "version": "0.3.8", | ||||||
|  |             "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", | ||||||
|  |             "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "MIT", | ||||||
|  |             "dependencies": { | ||||||
|  |                 "@jridgewell/set-array": "^1.2.1", | ||||||
|  |                 "@jridgewell/sourcemap-codec": "^1.4.10", | ||||||
|  |                 "@jridgewell/trace-mapping": "^0.3.24" | ||||||
|  |             }, | ||||||
|  |             "engines": { | ||||||
|  |                 "node": ">=6.0.0" | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "node_modules/@jridgewell/resolve-uri": { | ||||||
|  |             "version": "3.1.2", | ||||||
|  |             "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", | ||||||
|  |             "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "MIT", | ||||||
|  |             "engines": { | ||||||
|  |                 "node": ">=6.0.0" | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "node_modules/@jridgewell/set-array": { | ||||||
|  |             "version": "1.2.1", | ||||||
|  |             "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", | ||||||
|  |             "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "MIT", | ||||||
|  |             "engines": { | ||||||
|  |                 "node": ">=6.0.0" | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "node_modules/@jridgewell/sourcemap-codec": { | ||||||
|  |             "version": "1.5.0", | ||||||
|  |             "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", | ||||||
|  |             "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "MIT" | ||||||
|  |         }, | ||||||
|  |         "node_modules/@jridgewell/trace-mapping": { | ||||||
|  |             "version": "0.3.25", | ||||||
|  |             "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", | ||||||
|  |             "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "MIT", | ||||||
|  |             "dependencies": { | ||||||
|  |                 "@jridgewell/resolve-uri": "^3.1.0", | ||||||
|  |                 "@jridgewell/sourcemap-codec": "^1.4.14" | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "node_modules/@pkgr/core": { | ||||||
|  |             "version": "0.1.2", | ||||||
|  |             "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.2.tgz", | ||||||
|  |             "integrity": "sha512-fdDH1LSGfZdTH2sxdpVMw31BanV28K/Gry0cVFxaNP77neJSkd82mM8ErPNYs9e+0O7SdHBLTDzDgwUuy18RnQ==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "MIT", | ||||||
|  |             "engines": { | ||||||
|  |                 "node": "^12.20.0 || ^14.18.0 || >=16.0.0" | ||||||
|  |             }, | ||||||
|  |             "funding": { | ||||||
|  |                 "url": "https://opencollective.com/unts" | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "node_modules/@trivago/prettier-plugin-sort-imports": { | ||||||
|  |             "version": "5.2.2", | ||||||
|  |             "resolved": "https://registry.npmjs.org/@trivago/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-5.2.2.tgz", | ||||||
|  |             "integrity": "sha512-fYDQA9e6yTNmA13TLVSA+WMQRc5Bn/c0EUBditUHNfMMxN7M82c38b1kEggVE3pLpZ0FwkwJkUEKMiOi52JXFA==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "Apache-2.0", | ||||||
|  |             "dependencies": { | ||||||
|  |                 "@babel/generator": "^7.26.5", | ||||||
|  |                 "@babel/parser": "^7.26.7", | ||||||
|  |                 "@babel/traverse": "^7.26.7", | ||||||
|  |                 "@babel/types": "^7.26.7", | ||||||
|  |                 "javascript-natural-sort": "^0.7.1", | ||||||
|  |                 "lodash": "^4.17.21" | ||||||
|  |             }, | ||||||
|  |             "engines": { | ||||||
|  |                 "node": ">18.12" | ||||||
|  |             }, | ||||||
|  |             "peerDependencies": { | ||||||
|  |                 "@vue/compiler-sfc": "3.x", | ||||||
|  |                 "prettier": "2.x - 3.x", | ||||||
|  |                 "prettier-plugin-svelte": "3.x", | ||||||
|  |                 "svelte": "4.x || 5.x" | ||||||
|  |             }, | ||||||
|  |             "peerDependenciesMeta": { | ||||||
|  |                 "@vue/compiler-sfc": { | ||||||
|  |                     "optional": true | ||||||
|  |                 }, | ||||||
|  |                 "prettier-plugin-svelte": { | ||||||
|  |                     "optional": true | ||||||
|  |                 }, | ||||||
|  |                 "svelte": { | ||||||
|  |                     "optional": true | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "node_modules/debug": { | ||||||
|  |             "version": "4.4.0", | ||||||
|  |             "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", | ||||||
|  |             "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "MIT", | ||||||
|  |             "dependencies": { | ||||||
|  |                 "ms": "^2.1.3" | ||||||
|  |             }, | ||||||
|  |             "engines": { | ||||||
|  |                 "node": ">=6.0" | ||||||
|  |             }, | ||||||
|  |             "peerDependenciesMeta": { | ||||||
|  |                 "supports-color": { | ||||||
|  |                     "optional": true | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "node_modules/detect-indent": { | ||||||
|  |             "version": "7.0.1", | ||||||
|  |             "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-7.0.1.tgz", | ||||||
|  |             "integrity": "sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "MIT", | ||||||
|  |             "engines": { | ||||||
|  |                 "node": ">=12.20" | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "node_modules/detect-newline": { | ||||||
|  |             "version": "4.0.1", | ||||||
|  |             "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-4.0.1.tgz", | ||||||
|  |             "integrity": "sha512-qE3Veg1YXzGHQhlA6jzebZN2qVf6NX+A7m7qlhCGG30dJixrAQhYOsJjsnBjJkCSmuOPpCk30145fr8FV0bzog==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "MIT", | ||||||
|  |             "engines": { | ||||||
|  |                 "node": "^12.20.0 || ^14.13.1 || >=16.0.0" | ||||||
|  |             }, | ||||||
|  |             "funding": { | ||||||
|  |                 "url": "https://github.com/sponsors/sindresorhus" | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "node_modules/fdir": { | ||||||
|  |             "version": "6.4.4", | ||||||
|  |             "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", | ||||||
|  |             "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "MIT", | ||||||
|  |             "peerDependencies": { | ||||||
|  |                 "picomatch": "^3 || ^4" | ||||||
|  |             }, | ||||||
|  |             "peerDependenciesMeta": { | ||||||
|  |                 "picomatch": { | ||||||
|  |                     "optional": true | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "node_modules/get-stdin": { | ||||||
|  |             "version": "9.0.0", | ||||||
|  |             "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz", | ||||||
|  |             "integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "MIT", | ||||||
|  |             "engines": { | ||||||
|  |                 "node": ">=12" | ||||||
|  |             }, | ||||||
|  |             "funding": { | ||||||
|  |                 "url": "https://github.com/sponsors/sindresorhus" | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "node_modules/git-hooks-list": { | ||||||
|  |             "version": "3.2.0", | ||||||
|  |             "resolved": "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-3.2.0.tgz", | ||||||
|  |             "integrity": "sha512-ZHG9a1gEhUMX1TvGrLdyWb9kDopCBbTnI8z4JgRMYxsijWipgjSEYoPWqBuIB0DnRnvqlQSEeVmzpeuPm7NdFQ==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "MIT", | ||||||
|  |             "funding": { | ||||||
|  |                 "url": "https://github.com/fisker/git-hooks-list?sponsor=1" | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "node_modules/globals": { | ||||||
|  |             "version": "11.12.0", | ||||||
|  |             "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", | ||||||
|  |             "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "MIT", | ||||||
|  |             "engines": { | ||||||
|  |                 "node": ">=4" | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "node_modules/is-plain-obj": { | ||||||
|  |             "version": "4.1.0", | ||||||
|  |             "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", | ||||||
|  |             "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "MIT", | ||||||
|  |             "engines": { | ||||||
|  |                 "node": ">=12" | ||||||
|  |             }, | ||||||
|  |             "funding": { | ||||||
|  |                 "url": "https://github.com/sponsors/sindresorhus" | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "node_modules/javascript-natural-sort": { | ||||||
|  |             "version": "0.7.1", | ||||||
|  |             "resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz", | ||||||
|  |             "integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "MIT" | ||||||
|  |         }, | ||||||
|  |         "node_modules/js-tokens": { | ||||||
|  |             "version": "4.0.0", | ||||||
|  |             "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", | ||||||
|  |             "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "MIT" | ||||||
|  |         }, | ||||||
|  |         "node_modules/jsesc": { | ||||||
|  |             "version": "3.1.0", | ||||||
|  |             "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", | ||||||
|  |             "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "MIT", | ||||||
|  |             "bin": { | ||||||
|  |                 "jsesc": "bin/jsesc" | ||||||
|  |             }, | ||||||
|  |             "engines": { | ||||||
|  |                 "node": ">=6" | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "node_modules/lodash": { | ||||||
|  |             "version": "4.17.21", | ||||||
|  |             "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", | ||||||
|  |             "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "MIT" | ||||||
|  |         }, | ||||||
|  |         "node_modules/ms": { | ||||||
|  |             "version": "2.1.3", | ||||||
|  |             "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", | ||||||
|  |             "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "MIT" | ||||||
|  |         }, | ||||||
|  |         "node_modules/picocolors": { | ||||||
|  |             "version": "1.1.1", | ||||||
|  |             "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", | ||||||
|  |             "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "ISC" | ||||||
|  |         }, | ||||||
|  |         "node_modules/picomatch": { | ||||||
|  |             "version": "4.0.2", | ||||||
|  |             "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", | ||||||
|  |             "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "MIT", | ||||||
|  |             "engines": { | ||||||
|  |                 "node": ">=12" | ||||||
|  |             }, | ||||||
|  |             "funding": { | ||||||
|  |                 "url": "https://github.com/sponsors/jonschlinkert" | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "node_modules/prettier": { | ||||||
|  |             "version": "3.5.3", | ||||||
|  |             "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz", | ||||||
|  |             "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "MIT", | ||||||
|  |             "bin": { | ||||||
|  |                 "prettier": "bin/prettier.cjs" | ||||||
|  |             }, | ||||||
|  |             "engines": { | ||||||
|  |                 "node": ">=14" | ||||||
|  |             }, | ||||||
|  |             "funding": { | ||||||
|  |                 "url": "https://github.com/prettier/prettier?sponsor=1" | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "node_modules/prettier-plugin-organize-imports": { | ||||||
|  |             "version": "4.1.0", | ||||||
|  |             "resolved": "https://registry.npmjs.org/prettier-plugin-organize-imports/-/prettier-plugin-organize-imports-4.1.0.tgz", | ||||||
|  |             "integrity": "sha512-5aWRdCgv645xaa58X8lOxzZoiHAldAPChljr/MT0crXVOWTZ+Svl4hIWlz+niYSlO6ikE5UXkN1JrRvIP2ut0A==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "MIT", | ||||||
|  |             "peerDependencies": { | ||||||
|  |                 "prettier": ">=2.0", | ||||||
|  |                 "typescript": ">=2.9", | ||||||
|  |                 "vue-tsc": "^2.1.0" | ||||||
|  |             }, | ||||||
|  |             "peerDependenciesMeta": { | ||||||
|  |                 "vue-tsc": { | ||||||
|  |                     "optional": true | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "node_modules/prettier-plugin-packagejson": { | ||||||
|  |             "version": "2.5.10", | ||||||
|  |             "resolved": "https://registry.npmjs.org/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.5.10.tgz", | ||||||
|  |             "integrity": "sha512-LUxATI5YsImIVSaaLJlJ3aE6wTD+nvots18U3GuQMJpUyClChaZlQrqx3dBnbhF20OnKWZyx8EgyZypQtBDtgQ==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "MIT", | ||||||
|  |             "dependencies": { | ||||||
|  |                 "sort-package-json": "2.15.1", | ||||||
|  |                 "synckit": "0.9.2" | ||||||
|  |             }, | ||||||
|  |             "peerDependencies": { | ||||||
|  |                 "prettier": ">= 1.16.0" | ||||||
|  |             }, | ||||||
|  |             "peerDependenciesMeta": { | ||||||
|  |                 "prettier": { | ||||||
|  |                     "optional": true | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "node_modules/semver": { | ||||||
|  |             "version": "7.7.1", | ||||||
|  |             "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", | ||||||
|  |             "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "ISC", | ||||||
|  |             "bin": { | ||||||
|  |                 "semver": "bin/semver.js" | ||||||
|  |             }, | ||||||
|  |             "engines": { | ||||||
|  |                 "node": ">=10" | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "node_modules/sort-object-keys": { | ||||||
|  |             "version": "1.1.3", | ||||||
|  |             "resolved": "https://registry.npmjs.org/sort-object-keys/-/sort-object-keys-1.1.3.tgz", | ||||||
|  |             "integrity": "sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "MIT" | ||||||
|  |         }, | ||||||
|  |         "node_modules/sort-package-json": { | ||||||
|  |             "version": "2.15.1", | ||||||
|  |             "resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-2.15.1.tgz", | ||||||
|  |             "integrity": "sha512-9x9+o8krTT2saA9liI4BljNjwAbvUnWf11Wq+i/iZt8nl2UGYnf3TH5uBydE7VALmP7AGwlfszuEeL8BDyb0YA==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "MIT", | ||||||
|  |             "dependencies": { | ||||||
|  |                 "detect-indent": "^7.0.1", | ||||||
|  |                 "detect-newline": "^4.0.0", | ||||||
|  |                 "get-stdin": "^9.0.0", | ||||||
|  |                 "git-hooks-list": "^3.0.0", | ||||||
|  |                 "is-plain-obj": "^4.1.0", | ||||||
|  |                 "semver": "^7.6.0", | ||||||
|  |                 "sort-object-keys": "^1.1.3", | ||||||
|  |                 "tinyglobby": "^0.2.9" | ||||||
|  |             }, | ||||||
|  |             "bin": { | ||||||
|  |                 "sort-package-json": "cli.js" | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "node_modules/synckit": { | ||||||
|  |             "version": "0.9.2", | ||||||
|  |             "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz", | ||||||
|  |             "integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "MIT", | ||||||
|  |             "dependencies": { | ||||||
|  |                 "@pkgr/core": "^0.1.0", | ||||||
|  |                 "tslib": "^2.6.2" | ||||||
|  |             }, | ||||||
|  |             "engines": { | ||||||
|  |                 "node": "^14.18.0 || >=16.0.0" | ||||||
|  |             }, | ||||||
|  |             "funding": { | ||||||
|  |                 "url": "https://opencollective.com/unts" | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "node_modules/tinyglobby": { | ||||||
|  |             "version": "0.2.13", | ||||||
|  |             "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz", | ||||||
|  |             "integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "MIT", | ||||||
|  |             "dependencies": { | ||||||
|  |                 "fdir": "^6.4.4", | ||||||
|  |                 "picomatch": "^4.0.2" | ||||||
|  |             }, | ||||||
|  |             "engines": { | ||||||
|  |                 "node": ">=12.0.0" | ||||||
|  |             }, | ||||||
|  |             "funding": { | ||||||
|  |                 "url": "https://github.com/sponsors/SuperchupuDev" | ||||||
|  |             } | ||||||
|  |         }, | ||||||
|  |         "node_modules/tslib": { | ||||||
|  |             "version": "2.8.1", | ||||||
|  |             "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", | ||||||
|  |             "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "0BSD" | ||||||
|  |         }, | ||||||
|  |         "node_modules/typescript": { | ||||||
|  |             "version": "5.8.3", | ||||||
|  |             "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", | ||||||
|  |             "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", | ||||||
|  |             "dev": true, | ||||||
|  |             "license": "Apache-2.0", | ||||||
|  |             "bin": { | ||||||
|  |                 "tsc": "bin/tsc", | ||||||
|  |                 "tsserver": "bin/tsserver" | ||||||
|  |             }, | ||||||
|  |             "engines": { | ||||||
|  |                 "node": ">=14.17" | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										14
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								package.json
									
									
									
									
									
								
							| @ -1,5 +1,15 @@ | |||||||
| { | { | ||||||
|     "name": "@goauthentik/authentik", |     "name": "@goauthentik/authentik", | ||||||
|     "version": "2025.2.4", |     "version": "2025.4.1", | ||||||
|     "private": true |     "private": true, | ||||||
|  |     "type": "module", | ||||||
|  |     "devDependencies": { | ||||||
|  |         "@trivago/prettier-plugin-sort-imports": "^5.2.2", | ||||||
|  |         "prettier": "^3.3.3", | ||||||
|  |         "prettier-plugin-organize-imports": "^4.1.0", | ||||||
|  |         "prettier-plugin-packagejson": "^2.5.10", | ||||||
|  |         "typescript": "^5.6.2" | ||||||
|  |     }, | ||||||
|  |     "workspaces": [], | ||||||
|  |     "prettier": "./packages/prettier-config/index.js" | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										4
									
								
								packages/docusaurus-config/package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										4
									
								
								packages/docusaurus-config/package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -1,12 +1,12 @@ | |||||||
| { | { | ||||||
|     "name": "@goauthentik/docusaurus-config", |     "name": "@goauthentik/docusaurus-config", | ||||||
|     "version": "1.0.5", |     "version": "1.0.6", | ||||||
|     "lockfileVersion": 3, |     "lockfileVersion": 3, | ||||||
|     "requires": true, |     "requires": true, | ||||||
|     "packages": { |     "packages": { | ||||||
|         "": { |         "": { | ||||||
|             "name": "@goauthentik/docusaurus-config", |             "name": "@goauthentik/docusaurus-config", | ||||||
|             "version": "1.0.5", |             "version": "1.0.6", | ||||||
|             "license": "MIT", |             "license": "MIT", | ||||||
|             "dependencies": { |             "dependencies": { | ||||||
|                 "deepmerge-ts": "^7.1.5", |                 "deepmerge-ts": "^7.1.5", | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| { | { | ||||||
|     "name": "@goauthentik/docusaurus-config", |     "name": "@goauthentik/docusaurus-config", | ||||||
|     "version": "1.0.5", |     "version": "1.0.6", | ||||||
|     "description": "authentik's Docusaurus config", |     "description": "authentik's Docusaurus config", | ||||||
|     "license": "MIT", |     "license": "MIT", | ||||||
|     "scripts": { |     "scripts": { | ||||||
|  | |||||||
| @ -1,19 +0,0 @@ | |||||||
| { |  | ||||||
|     "name": "@goauthentik/monorepo", |  | ||||||
|     "version": "1.0.0", |  | ||||||
|     "description": "Utilities for the authentik monorepo.", |  | ||||||
|     "private": true, |  | ||||||
|     "license": "MIT", |  | ||||||
|     "type": "module", |  | ||||||
|     "exports": { |  | ||||||
|         "./package.json": "./package.json", |  | ||||||
|         ".": { |  | ||||||
|             "import": "./index.js", |  | ||||||
|             "types": "./out/index.d.ts" |  | ||||||
|         } |  | ||||||
|     }, |  | ||||||
|     "types": "./out/index.d.ts", |  | ||||||
|     "engines": { |  | ||||||
|         "node": ">=20.11" |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,30 +0,0 @@ | |||||||
| import { createRequire } from "node:module"; |  | ||||||
| import { dirname, join, resolve } from "node:path"; |  | ||||||
| import { fileURLToPath } from "node:url"; |  | ||||||
|  |  | ||||||
| const __dirname = dirname(fileURLToPath(import.meta.url)); |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * @typedef {'~authentik'} MonoRepoRoot |  | ||||||
|  */ |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * The root of the authentik monorepo. |  | ||||||
|  */ |  | ||||||
| export const MonoRepoRoot = /** @type {MonoRepoRoot} */ (resolve(__dirname, "..", "..")); |  | ||||||
|  |  | ||||||
| const require = createRequire(import.meta.url); |  | ||||||
|  |  | ||||||
| /** |  | ||||||
|  * Resolve a package name to its location in the monorepo to the single node_modules directory. |  | ||||||
|  * @param {string} packageName |  | ||||||
|  * @returns {string} The resolved path to the package. |  | ||||||
|  * @throws {Error} If the package cannot be resolved. |  | ||||||
|  */ |  | ||||||
| export function resolvePackage(packageName) { |  | ||||||
|     const packageJSONPath = require.resolve(join(packageName, "package.json"), { |  | ||||||
|         paths: [MonoRepoRoot], |  | ||||||
|     }); |  | ||||||
|  |  | ||||||
|     return dirname(packageJSONPath); |  | ||||||
| } |  | ||||||
| @ -76,6 +76,7 @@ EXPOSE 9000 9300 9443 | |||||||
|  |  | ||||||
| USER 1000 | USER 1000 | ||||||
|  |  | ||||||
| ENV GOFIPS=1 | ENV TMPDIR=/dev/shm/ \ | ||||||
|  |     GOFIPS=1 | ||||||
|  |  | ||||||
| ENTRYPOINT ["/proxy"] | ENTRYPOINT ["/proxy"] | ||||||
|  | |||||||
							
								
								
									
										196
									
								
								pyproject.toml
									
									
									
									
									
								
							
							
						
						
									
										196
									
								
								pyproject.toml
									
									
									
									
									
								
							| @ -1,104 +1,116 @@ | |||||||
| [project] | [project] | ||||||
| name = "authentik" | name = "authentik" | ||||||
| version = "2025.2.4" | version = "2025.4.1" | ||||||
| description = "" | description = "" | ||||||
| authors = [{ name = "authentik Team", email = "hello@goauthentik.io" }] | authors = [{ name = "authentik Team", email = "hello@goauthentik.io" }] | ||||||
| requires-python = "==3.12.*" | requires-python = "==3.13.*" | ||||||
| dependencies = [ | dependencies = [ | ||||||
|     "argon2-cffi", |     "argon2-cffi==23.1.0", | ||||||
|     "celery", |     "celery==5.5.2", | ||||||
|     "channels", |     "channels==4.2.2", | ||||||
|     "channels-redis", |     "channels-redis==4.2.1", | ||||||
|     "cryptography", |     "cryptography==44.0.3", | ||||||
|     "dacite", |     "dacite==1.9.2", | ||||||
|     "deepmerge", |     "deepmerge==2.0", | ||||||
|     "defusedxml", |     "defusedxml==0.7.1", | ||||||
|     "django", |     "django==5.1.9", | ||||||
|     "django-countries", |     "django-countries==7.6.1", | ||||||
|     "django-cte", |     "django-cte==1.3.3", | ||||||
|     "django-filter", |     "django-filter==25.1", | ||||||
|     "django-guardian", |     "django-guardian<3.0.0", | ||||||
|     "django-model-utils", |     "django-model-utils==5.0.0", | ||||||
|     "django-pglock", |     "django-pglock==1.7.2", | ||||||
|     "django-prometheus", |     "django-prometheus==2.3.1", | ||||||
|     "django-redis", |     "django-redis==5.4.0", | ||||||
|     "django-storages[s3]", |     "django-storages[s3]==1.14.6", | ||||||
|     "django-tenants", |     "django-tenants==3.7.0", | ||||||
|     "djangorestframework", |     "djangorestframework==3.16.0", | ||||||
|     "djangorestframework-guardian", |     "djangorestframework-guardian==0.3.0", | ||||||
|     "docker", |     "docker==7.1.0", | ||||||
|     "drf-orjson-renderer", |     "drf-orjson-renderer==1.7.3", | ||||||
|     "drf-spectacular", |     "drf-spectacular==0.28.0", | ||||||
|     "dumb-init", |     "dumb-init==1.2.5.post1", | ||||||
|     "duo-client", |     "duo-client==5.5.0", | ||||||
|     "fido2", |     "fido2==1.2.0", | ||||||
|     "flower", |     "flower==2.0.1", | ||||||
|     "geoip2", |     "geoip2==5.1.0", | ||||||
|     "geopy", |     "geopy==2.4.1", | ||||||
|     "google-api-python-client", |     "google-api-python-client==2.169.0", | ||||||
|     "gssapi", |     "gssapi==1.9.0", | ||||||
|     "gunicorn", |     "gunicorn==23.0.0", | ||||||
|     "jsonpatch", |     "jsonpatch==1.33", | ||||||
|     "jwcrypto", |     "jwcrypto==1.5.6", | ||||||
|     "kubernetes", |     "kubernetes==32.0.1", | ||||||
|     "ldap3", |     "ldap3==2.9.1", | ||||||
|     "lxml", |     "lxml==5.4.0", | ||||||
|     "msgraph-sdk", |     "msgraph-sdk==1.30.0", | ||||||
|     "opencontainers", |     "opencontainers==0.0.14", | ||||||
|     "packaging", |     "packaging==25.0", | ||||||
|     "paramiko", |     "paramiko==3.5.1", | ||||||
|     "psycopg[c, pool]", |     "psycopg[c,pool]==3.2.9", | ||||||
|     "pydantic", |     "pydantic==2.11.4", | ||||||
|     "pydantic-scim", |     "pydantic-scim==0.0.8", | ||||||
|     "pyjwt", |     "pyjwt==2.10.1", | ||||||
|     "pyrad", |     "pyrad==2.4", | ||||||
|     "python-kadmin-rs==0.6.0", |     "python-kadmin-rs==0.6.0", | ||||||
|     "pyyaml", |     "pyyaml==6.0.2", | ||||||
|     "requests-oauthlib", |     "requests-oauthlib==2.0.0", | ||||||
|     "scim2-filter-parser", |     "scim2-filter-parser==0.7.0", | ||||||
|     "sentry-sdk", |     "sentry-sdk==2.28.0", | ||||||
|     "service_identity", |     "service-identity==24.2.0", | ||||||
|     "setproctitle", |     "setproctitle==1.3.6", | ||||||
|     "structlog", |     "structlog==25.3.0", | ||||||
|     "swagger-spec-validator", |     "swagger-spec-validator==3.0.4", | ||||||
|     "tenant-schemas-celery", |     "tenant-schemas-celery==4.0.1", | ||||||
|     "twilio", |     "twilio==9.6.1", | ||||||
|     "ua-parser", |     "ua-parser==1.0.1", | ||||||
|     "unidecode", |     "unidecode==1.4.0", | ||||||
|     "urllib3<3", |     "urllib3<3", | ||||||
|     "uvicorn[standard]", |     "uvicorn[standard]==0.34.2", | ||||||
|     "watchdog", |     "watchdog==6.0.0", | ||||||
|     "webauthn", |     "webauthn==2.5.2", | ||||||
|     "wsproto", |     "wsproto==1.2.0", | ||||||
|     "xmlsec <= 1.3.14", |     "xmlsec==1.3.15", | ||||||
|     "zxcvbn", |     "zxcvbn==4.5.0", | ||||||
| ] | ] | ||||||
|  |  | ||||||
| [dependency-groups] | [dependency-groups] | ||||||
| dev = [ | dev = [ | ||||||
|     "aws-cdk-lib", |     "aws-cdk-lib==2.188.0", | ||||||
|     "bandit", |     "bandit==1.8.3", | ||||||
|     "black", |     "black==25.1.0", | ||||||
|     "bump2version", |     "bump2version==1.0.1", | ||||||
|     "channels[daphne]", |     "channels[daphne]==4.2.2", | ||||||
|     "codespell", |     "codespell==2.4.1", | ||||||
|     "colorama", |     "colorama==0.4.6", | ||||||
|     "constructs", |     "constructs==10.4.2", | ||||||
|     "coverage[toml]", |     "coverage[toml]==7.8.0", | ||||||
|     "debugpy", |     "debugpy==1.8.14", | ||||||
|     "drf-jsonschema-serializer", |     "drf-jsonschema-serializer==3.0.0", | ||||||
|     "freezegun", |     "freezegun==1.5.1", | ||||||
|     "importlib-metadata", |     "importlib-metadata==8.6.1", | ||||||
|     "k5test", |     "k5test==0.10.4", | ||||||
|     "pdoc", |     "pdoc==15.0.3", | ||||||
|     "pytest", |     "pytest==8.3.5", | ||||||
|     "pytest-django", |     "pytest-django==4.11.1", | ||||||
|     "pytest-github-actions-annotate-failures", |     "pytest-github-actions-annotate-failures==0.3.0", | ||||||
|     "pytest-randomly", |     "pytest-randomly==3.16.0", | ||||||
|     "pytest-timeout", |     "pytest-timeout==2.4.0", | ||||||
|     "requests-mock", |     "requests-mock==1.12.1", | ||||||
|     "ruff", |     "ruff==0.11.9", | ||||||
|     "selenium", |     "selenium==4.32.0", | ||||||
|  | ] | ||||||
|  |  | ||||||
|  | [tool.uv] | ||||||
|  | no-binary-package = [ | ||||||
|  |     # This differs from the no-binary packages in the Dockerfile. This is due to the fact | ||||||
|  |     # that these packages are built from source for different reasons than cryptography and kadmin. | ||||||
|  |     # These packages are built from source to link against the libxml2 on the system which is | ||||||
|  |     # required for functionality and to stay up-to-date on both libraries. | ||||||
|  |     # The other packages specified in the dockerfile are compiled from source to link against the | ||||||
|  |     # correct FIPS OpenSSL libraries | ||||||
|  |     "lxml", | ||||||
|  |     "xmlsec", | ||||||
| ] | ] | ||||||
|  |  | ||||||
| [tool.uv.sources] | [tool.uv.sources] | ||||||
| @ -143,12 +155,12 @@ ignore-words = ".github/codespell-words.txt" | |||||||
|  |  | ||||||
| [tool.black] | [tool.black] | ||||||
| line-length = 100 | line-length = 100 | ||||||
| target-version = ['py312'] | target-version = ['py313'] | ||||||
| exclude = 'node_modules' | exclude = 'node_modules' | ||||||
|  |  | ||||||
| [tool.ruff] | [tool.ruff] | ||||||
| line-length = 100 | line-length = 100 | ||||||
| target-version = "py312" | target-version = "py313" | ||||||
| exclude = ["**/migrations/**", "**/node_modules/**"] | exclude = ["**/migrations/**", "**/node_modules/**"] | ||||||
|  |  | ||||||
| [tool.ruff.lint] | [tool.ruff.lint] | ||||||
|  | |||||||
| @ -56,6 +56,7 @@ HEALTHCHECK --interval=5s --retries=20 --start-period=3s CMD [ "/rac", "healthch | |||||||
|  |  | ||||||
| USER 1000 | USER 1000 | ||||||
|  |  | ||||||
| ENV GOFIPS=1 | ENV TMPDIR=/dev/shm/ \ | ||||||
|  |     GOFIPS=1 | ||||||
|  |  | ||||||
| ENTRYPOINT ["/rac"] | ENTRYPOINT ["/rac"] | ||||||
|  | |||||||
| @ -56,6 +56,7 @@ EXPOSE 1812/udp 9300 | |||||||
|  |  | ||||||
| USER 1000 | USER 1000 | ||||||
|  |  | ||||||
| ENV GOFIPS=1 | ENV TMPDIR=/dev/shm/ \ | ||||||
|  |     GOFIPS=1 | ||||||
|  |  | ||||||
| ENTRYPOINT ["/radius"] | ENTRYPOINT ["/radius"] | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| openapi: 3.0.3 | openapi: 3.0.3 | ||||||
| info: | info: | ||||||
|   title: authentik |   title: authentik | ||||||
|   version: 2025.2.4 |   version: 2025.4.1 | ||||||
|   description: Making authentication simple. |   description: Making authentication simple. | ||||||
|   contact: |   contact: | ||||||
|     email: hello@goauthentik.io |     email: hello@goauthentik.io | ||||||
|  | |||||||
| @ -0,0 +1,12 @@ | |||||||
|  | import socket | ||||||
|  | from os import environ | ||||||
|  |  | ||||||
|  | IS_CI = "CI" in environ | ||||||
|  | RETRIES = int(environ.get("RETRIES", "3")) if IS_CI else 1 | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def get_local_ip() -> str: | ||||||
|  |     """Get the local machine's IP""" | ||||||
|  |     hostname = socket.gethostname() | ||||||
|  |     ip_addr = socket.gethostbyname(hostname) | ||||||
|  |     return ip_addr | ||||||
|  | |||||||
							
								
								
									
										190
									
								
								tests/browser.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										190
									
								
								tests/browser.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,190 @@ | |||||||
|  | """authentik e2e testing utilities""" | ||||||
|  |  | ||||||
|  | # This file cannot import anything django or anything that will load django | ||||||
|  |  | ||||||
|  | import json | ||||||
|  | from sys import stderr | ||||||
|  | from time import sleep | ||||||
|  | from typing import TYPE_CHECKING | ||||||
|  | from unittest.case import TestCase | ||||||
|  | from urllib.parse import urlencode | ||||||
|  |  | ||||||
|  | from django.contrib.staticfiles.testing import StaticLiveServerTestCase | ||||||
|  | from django.urls import reverse | ||||||
|  | from selenium import webdriver | ||||||
|  | from selenium.common.exceptions import WebDriverException | ||||||
|  | from selenium.webdriver.common.by import By | ||||||
|  | from selenium.webdriver.common.keys import Keys | ||||||
|  | from selenium.webdriver.remote.command import Command | ||||||
|  | from selenium.webdriver.remote.webdriver import WebDriver | ||||||
|  | from selenium.webdriver.remote.webelement import WebElement | ||||||
|  | from selenium.webdriver.support import expected_conditions as ec | ||||||
|  | from selenium.webdriver.support.wait import WebDriverWait | ||||||
|  | from structlog.stdlib import get_logger | ||||||
|  |  | ||||||
|  | from tests import IS_CI, RETRIES, get_local_ip | ||||||
|  | from tests.websocket import BaseWebsocketTestCase | ||||||
|  |  | ||||||
|  | if TYPE_CHECKING: | ||||||
|  |     from authentik.core.models import User | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class BaseSeleniumTestCase(TestCase): | ||||||
|  |     """Mixin which adds helpers for spinning up Selenium""" | ||||||
|  |  | ||||||
|  |     host = get_local_ip() | ||||||
|  |     wait_timeout: int | ||||||
|  |     user: "User" | ||||||
|  |  | ||||||
|  |     def setUp(self): | ||||||
|  |         if IS_CI: | ||||||
|  |             print("::group::authentik Logs", file=stderr) | ||||||
|  |         from django.apps import apps | ||||||
|  |  | ||||||
|  |         from authentik.core.tests.utils import create_test_admin_user | ||||||
|  |  | ||||||
|  |         apps.get_app_config("authentik_tenants").ready() | ||||||
|  |         self.wait_timeout = 60 | ||||||
|  |         self.driver = self._get_driver() | ||||||
|  |         self.driver.implicitly_wait(30) | ||||||
|  |         self.wait = WebDriverWait(self.driver, self.wait_timeout) | ||||||
|  |         self.logger = get_logger() | ||||||
|  |         self.user = create_test_admin_user() | ||||||
|  |         super().setUp() | ||||||
|  |  | ||||||
|  |     def _get_driver(self) -> WebDriver: | ||||||
|  |         count = 0 | ||||||
|  |         try: | ||||||
|  |             opts = webdriver.ChromeOptions() | ||||||
|  |             opts.add_argument("--disable-search-engine-choice-screen") | ||||||
|  |             return webdriver.Chrome(options=opts) | ||||||
|  |         except WebDriverException: | ||||||
|  |             pass | ||||||
|  |         while count < RETRIES: | ||||||
|  |             try: | ||||||
|  |                 driver = webdriver.Remote( | ||||||
|  |                     command_executor="http://localhost:4444/wd/hub", | ||||||
|  |                     options=webdriver.ChromeOptions(), | ||||||
|  |                 ) | ||||||
|  |                 driver.maximize_window() | ||||||
|  |                 return driver | ||||||
|  |             except WebDriverException: | ||||||
|  |                 count += 1 | ||||||
|  |         raise ValueError(f"Webdriver failed after {RETRIES}.") | ||||||
|  |  | ||||||
|  |     def tearDown(self): | ||||||
|  |         if IS_CI: | ||||||
|  |             print("::endgroup::", file=stderr) | ||||||
|  |         super().tearDown() | ||||||
|  |         if IS_CI: | ||||||
|  |             print("::group::Browser logs") | ||||||
|  |         # Very verbose way to get browser logs | ||||||
|  |         # https://github.com/SeleniumHQ/selenium/pull/15641 | ||||||
|  |         # for some reason this removes the `get_log` API from Remote Webdriver | ||||||
|  |         # and only keeps it on the local Chrome web driver, even when using | ||||||
|  |         # a remote chrome driver...? (nvm the fact this was released as a minor version) | ||||||
|  |         for line in self.driver.execute(Command.GET_LOG, {"type": "browser"})["value"]: | ||||||
|  |             print(line["message"]) | ||||||
|  |         if IS_CI: | ||||||
|  |             print("::endgroup::") | ||||||
|  |         self.driver.quit() | ||||||
|  |  | ||||||
|  |     def wait_for_url(self, desired_url): | ||||||
|  |         """Wait until URL is `desired_url`.""" | ||||||
|  |         self.wait.until( | ||||||
|  |             lambda driver: driver.current_url == desired_url, | ||||||
|  |             f"URL {self.driver.current_url} doesn't match expected URL {desired_url}", | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |     def url(self, view, query: dict | None = None, **kwargs) -> str: | ||||||
|  |         """reverse `view` with `**kwargs` into full URL using live_server_url""" | ||||||
|  |         url = self.live_server_url + reverse(view, kwargs=kwargs) | ||||||
|  |         if query: | ||||||
|  |             return url + "?" + urlencode(query) | ||||||
|  |         return url | ||||||
|  |  | ||||||
|  |     def if_user_url(self, path: str | None = None) -> str: | ||||||
|  |         """same as self.url() but show URL in shell""" | ||||||
|  |         url = self.url("authentik_core:if-user") | ||||||
|  |         if path: | ||||||
|  |             return f"{url}#{path}" | ||||||
|  |         return url | ||||||
|  |  | ||||||
|  |     def get_shadow_root( | ||||||
|  |         self, selector: str, container: WebElement | WebDriver | None = None | ||||||
|  |     ) -> WebElement: | ||||||
|  |         """Get shadow root element's inner shadowRoot""" | ||||||
|  |         if not container: | ||||||
|  |             container = self.driver | ||||||
|  |         shadow_root = container.find_element(By.CSS_SELECTOR, selector) | ||||||
|  |         element = self.driver.execute_script("return arguments[0].shadowRoot", shadow_root) | ||||||
|  |         return element | ||||||
|  |  | ||||||
|  |     def shady_dom(self) -> WebElement: | ||||||
|  |         class wrapper: | ||||||
|  |             def __init__(self, container: WebDriver): | ||||||
|  |                 self.container = container | ||||||
|  |  | ||||||
|  |             def find_element(self, by: str, selector: str) -> WebElement: | ||||||
|  |                 return self.container.execute_script( | ||||||
|  |                     "return document.__shady_native_querySelector(arguments[0])", selector | ||||||
|  |                 ) | ||||||
|  |  | ||||||
|  |         return wrapper(self.driver) | ||||||
|  |  | ||||||
|  |     def login(self, shadow_dom=True): | ||||||
|  |         """Do entire login flow""" | ||||||
|  |  | ||||||
|  |         if shadow_dom: | ||||||
|  |             flow_executor = self.get_shadow_root("ak-flow-executor") | ||||||
|  |             identification_stage = self.get_shadow_root("ak-stage-identification", flow_executor) | ||||||
|  |         else: | ||||||
|  |             flow_executor = self.shady_dom() | ||||||
|  |             identification_stage = self.shady_dom() | ||||||
|  |  | ||||||
|  |         wait = WebDriverWait(identification_stage, self.wait_timeout) | ||||||
|  |         wait.until(ec.presence_of_element_located((By.CSS_SELECTOR, "input[name=uidField]"))) | ||||||
|  |  | ||||||
|  |         identification_stage.find_element(By.CSS_SELECTOR, "input[name=uidField]").click() | ||||||
|  |         identification_stage.find_element(By.CSS_SELECTOR, "input[name=uidField]").send_keys( | ||||||
|  |             self.user.username | ||||||
|  |         ) | ||||||
|  |         identification_stage.find_element(By.CSS_SELECTOR, "input[name=uidField]").send_keys( | ||||||
|  |             Keys.ENTER | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |         if shadow_dom: | ||||||
|  |             flow_executor = self.get_shadow_root("ak-flow-executor") | ||||||
|  |             password_stage = self.get_shadow_root("ak-stage-password", flow_executor) | ||||||
|  |         else: | ||||||
|  |             flow_executor = self.shady_dom() | ||||||
|  |             password_stage = self.shady_dom() | ||||||
|  |  | ||||||
|  |         wait = WebDriverWait(password_stage, self.wait_timeout) | ||||||
|  |         wait.until(ec.presence_of_element_located((By.CSS_SELECTOR, "input[name=password]"))) | ||||||
|  |  | ||||||
|  |         password_stage.find_element(By.CSS_SELECTOR, "input[name=password]").send_keys( | ||||||
|  |             self.user.username | ||||||
|  |         ) | ||||||
|  |         password_stage.find_element(By.CSS_SELECTOR, "input[name=password]").send_keys(Keys.ENTER) | ||||||
|  |         sleep(1) | ||||||
|  |  | ||||||
|  |     def assert_user(self, expected_user: "User"): | ||||||
|  |         """Check users/me API and assert it matches expected_user""" | ||||||
|  |         from authentik.core.api.users import UserSerializer | ||||||
|  |  | ||||||
|  |         self.driver.get(self.url("authentik_api:user-me") + "?format=json") | ||||||
|  |         user_json = self.driver.find_element(By.CSS_SELECTOR, "pre").text | ||||||
|  |         user = UserSerializer(data=json.loads(user_json)["user"]) | ||||||
|  |         user.is_valid() | ||||||
|  |         self.assertEqual(user["username"].value, expected_user.username) | ||||||
|  |         self.assertEqual(user["name"].value, expected_user.name) | ||||||
|  |         self.assertEqual(user["email"].value, expected_user.email) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class SeleniumTestCase(BaseSeleniumTestCase, StaticLiveServerTestCase): | ||||||
|  |     """Test case which spins up a selenium instance and a HTTP-only test server""" | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class WebsocketSeleniumTestCase(BaseSeleniumTestCase, BaseWebsocketTestCase): | ||||||
|  |     """Test case which spins up a selenium instance and a Websocket/HTTP test server""" | ||||||
							
								
								
									
										48
									
								
								tests/decorators.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								tests/decorators.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,48 @@ | |||||||
|  | """authentik e2e testing utilities""" | ||||||
|  |  | ||||||
|  | from collections.abc import Callable | ||||||
|  | from functools import wraps | ||||||
|  |  | ||||||
|  | from django.test.testcases import TransactionTestCase | ||||||
|  | from selenium.common.exceptions import NoSuchElementException, TimeoutException, WebDriverException | ||||||
|  | from structlog.stdlib import get_logger | ||||||
|  |  | ||||||
|  | from tests import RETRIES | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def retry(max_retires=RETRIES, exceptions=None): | ||||||
|  |     """Retry test multiple times. Default to catching Selenium Timeout Exception""" | ||||||
|  |  | ||||||
|  |     if not exceptions: | ||||||
|  |         exceptions = [WebDriverException, TimeoutException, NoSuchElementException] | ||||||
|  |  | ||||||
|  |     logger = get_logger() | ||||||
|  |  | ||||||
|  |     def retry_actual(func: Callable): | ||||||
|  |         """Retry test multiple times""" | ||||||
|  |         count = 1 | ||||||
|  |  | ||||||
|  |         @wraps(func) | ||||||
|  |         def wrapper(self: TransactionTestCase, *args, **kwargs): | ||||||
|  |             """Run test again if we're below max_retries, including tearDown and | ||||||
|  |             setUp. Otherwise raise the error""" | ||||||
|  |             nonlocal count | ||||||
|  |             try: | ||||||
|  |                 return func(self, *args, **kwargs) | ||||||
|  |  | ||||||
|  |             except tuple(exceptions) as exc: | ||||||
|  |                 count += 1 | ||||||
|  |                 if count > max_retires: | ||||||
|  |                     logger.debug("Exceeded retry count", exc=exc, test=self) | ||||||
|  |  | ||||||
|  |                     raise exc | ||||||
|  |                 logger.debug("Retrying on error", exc=exc, test=self) | ||||||
|  |                 self.tearDown() | ||||||
|  |                 self._post_teardown() | ||||||
|  |                 self._pre_setup() | ||||||
|  |                 self.setUp() | ||||||
|  |                 return wrapper(self, *args, **kwargs) | ||||||
|  |  | ||||||
|  |         return wrapper | ||||||
|  |  | ||||||
|  |     return retry_actual | ||||||
							
								
								
									
										139
									
								
								tests/docker.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								tests/docker.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,139 @@ | |||||||
|  | """Docker testing helpers""" | ||||||
|  |  | ||||||
|  | import os | ||||||
|  | from time import sleep | ||||||
|  | from typing import TYPE_CHECKING, Any | ||||||
|  | from unittest.case import TestCase | ||||||
|  |  | ||||||
|  | from docker import DockerClient, from_env | ||||||
|  | from docker.errors import DockerException | ||||||
|  | from docker.models.containers import Container | ||||||
|  | from docker.models.networks import Network | ||||||
|  |  | ||||||
|  | from authentik.lib.generators import generate_id | ||||||
|  | from tests import IS_CI | ||||||
|  |  | ||||||
|  | if TYPE_CHECKING: | ||||||
|  |     from authentik.outposts.models import Outpost | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def get_docker_tag() -> str: | ||||||
|  |     """Get docker-tag based off of CI variables""" | ||||||
|  |     env_pr_branch = "GITHUB_HEAD_REF" | ||||||
|  |     default_branch = "GITHUB_REF" | ||||||
|  |     branch_name = os.environ.get(default_branch, "main") | ||||||
|  |     if os.environ.get(env_pr_branch, "") != "": | ||||||
|  |         branch_name = os.environ[env_pr_branch] | ||||||
|  |     branch_name = branch_name.replace("refs/heads/", "").replace("/", "-") | ||||||
|  |     return f"gh-{branch_name}" | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class DockerTestCase(TestCase): | ||||||
|  |     """Mixin for dealing with containers""" | ||||||
|  |  | ||||||
|  |     max_healthcheck_attempts = 30 | ||||||
|  |  | ||||||
|  |     __client: DockerClient | ||||||
|  |     __network: Network | ||||||
|  |  | ||||||
|  |     __label_id = generate_id() | ||||||
|  |  | ||||||
|  |     def setUp(self) -> None: | ||||||
|  |         self.__client = from_env() | ||||||
|  |         self.__network = self.docker_client.networks.create( | ||||||
|  |             name=f"authentik-test-{self.__label_id}" | ||||||
|  |         ) | ||||||
|  |         super().setUp() | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def docker_client(self) -> DockerClient: | ||||||
|  |         return self.__client | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def docker_network(self) -> Network: | ||||||
|  |         return self.__network | ||||||
|  |  | ||||||
|  |     @property | ||||||
|  |     def docker_labels(self) -> dict: | ||||||
|  |         return {"io.goauthentik.test": self.__label_id} | ||||||
|  |  | ||||||
|  |     def get_container_image(self, base: str) -> str: | ||||||
|  |         """Try to pull docker image based on git branch, fallback to main if not found.""" | ||||||
|  |         image = f"{base}:gh-main" | ||||||
|  |         if not IS_CI: | ||||||
|  |             return image | ||||||
|  |         try: | ||||||
|  |             branch_image = f"{base}:{get_docker_tag()}" | ||||||
|  |             self.docker_client.images.pull(branch_image) | ||||||
|  |             return branch_image | ||||||
|  |         except DockerException: | ||||||
|  |             self.docker_client.images.pull(image) | ||||||
|  |         return image | ||||||
|  |  | ||||||
|  |     def run_container(self, **specs: dict[str, Any]) -> Container: | ||||||
|  |         if "network_mode" not in specs: | ||||||
|  |             specs["network"] = self.__network.name | ||||||
|  |         specs["labels"] = self.docker_labels | ||||||
|  |         specs["detach"] = True | ||||||
|  |         if hasattr(self, "live_server_url"): | ||||||
|  |             specs.setdefault("environment", {}) | ||||||
|  |             specs["environment"]["AUTHENTIK_HOST"] = self.live_server_url | ||||||
|  |         container = self.docker_client.containers.run(**specs) | ||||||
|  |         container.reload() | ||||||
|  |         state = container.attrs.get("State", {}) | ||||||
|  |         if "Health" not in state: | ||||||
|  |             return container | ||||||
|  |         self.wait_for_container(container) | ||||||
|  |         return container | ||||||
|  |  | ||||||
|  |     def output_container_logs(self, container: Container | None = None): | ||||||
|  |         """Output the container logs to our STDOUT""" | ||||||
|  |         if IS_CI: | ||||||
|  |             image = container.image | ||||||
|  |             tags = image.tags[0] if len(image.tags) > 0 else str(image) | ||||||
|  |             print(f"::group::Container logs - {tags}") | ||||||
|  |         for log in container.logs().decode().split("\n"): | ||||||
|  |             print(log) | ||||||
|  |         if IS_CI: | ||||||
|  |             print("::endgroup::") | ||||||
|  |  | ||||||
|  |     def tearDown(self): | ||||||
|  |         containers: list[Container] = self.docker_client.containers.list( | ||||||
|  |             filters={"label": ",".join(f"{x}={y}" for x, y in self.docker_labels.items())} | ||||||
|  |         ) | ||||||
|  |         for container in containers: | ||||||
|  |             self.output_container_logs(container) | ||||||
|  |             try: | ||||||
|  |                 container.stop() | ||||||
|  |             except DockerException: | ||||||
|  |                 pass | ||||||
|  |             try: | ||||||
|  |                 container.remove(force=True) | ||||||
|  |             except DockerException: | ||||||
|  |                 pass | ||||||
|  |         self.__network.remove() | ||||||
|  |         super().tearDown() | ||||||
|  |  | ||||||
|  |     def wait_for_container(self, container: Container): | ||||||
|  |         """Check that container is health""" | ||||||
|  |         attempt = 0 | ||||||
|  |         while attempt < self.max_healthcheck_attempts: | ||||||
|  |             container.reload() | ||||||
|  |             status = container.attrs.get("State", {}).get("Health", {}).get("Status") | ||||||
|  |             if status == "healthy": | ||||||
|  |                 return container | ||||||
|  |             attempt += 1 | ||||||
|  |             sleep(0.5) | ||||||
|  |         self.failureException("Container failed to start") | ||||||
|  |  | ||||||
|  |     def wait_for_outpost(self, outpost: "Outpost"): | ||||||
|  |         # Wait until outpost healthcheck succeeds | ||||||
|  |         attempt = 0 | ||||||
|  |         while attempt < self.max_healthcheck_attempts: | ||||||
|  |             if len(outpost.state) > 0: | ||||||
|  |                 state = outpost.state[0] | ||||||
|  |                 if state.last_seen: | ||||||
|  |                     return | ||||||
|  |             attempt += 1 | ||||||
|  |             sleep(0.5) | ||||||
|  |         self.failureException("Outpost failed to become healthy") | ||||||
| @ -1,12 +1,12 @@ | |||||||
| services: | services: | ||||||
|   chrome: |   chrome: | ||||||
|     image: docker.io/selenium/standalone-chrome:122.0 |     image: docker.io/selenium/standalone-chrome:136.0 | ||||||
|     volumes: |     volumes: | ||||||
|       - /dev/shm:/dev/shm |       - /dev/shm:/dev/shm | ||||||
|     network_mode: host |     network_mode: host | ||||||
|     restart: always |     restart: always | ||||||
|   mailpit: |   mailpit: | ||||||
|     image: docker.io/axllent/mailpit:v1.6.5 |     image: docker.io/axllent/mailpit:v1.24.2 | ||||||
|     ports: |     ports: | ||||||
|       - 1025:1025 |       - 1025:1025 | ||||||
|       - 8025:8025 |       - 8025:8025 | ||||||
|  | |||||||
| @ -18,10 +18,12 @@ from authentik.stages.authenticator_static.models import ( | |||||||
|     StaticToken, |     StaticToken, | ||||||
| ) | ) | ||||||
| from authentik.stages.authenticator_totp.models import AuthenticatorTOTPStage, TOTPDevice | from authentik.stages.authenticator_totp.models import AuthenticatorTOTPStage, TOTPDevice | ||||||
| from tests.e2e.utils import SeleniumTestCase, retry | from tests.browser import SeleniumTestCase | ||||||
|  | from tests.decorators import retry | ||||||
|  | from tests.docker import DockerTestCase | ||||||
|  |  | ||||||
|  |  | ||||||
| class TestFlowsAuthenticator(SeleniumTestCase): | class TestFlowsAuthenticator(DockerTestCase, SeleniumTestCase): | ||||||
|     """test flow with otp stages""" |     """test flow with otp stages""" | ||||||
|  |  | ||||||
|     @retry() |     @retry() | ||||||
|  | |||||||
| @ -11,10 +11,12 @@ from authentik.core.models import User | |||||||
| from authentik.flows.models import Flow | from authentik.flows.models import Flow | ||||||
| from authentik.lib.config import CONFIG | from authentik.lib.config import CONFIG | ||||||
| from authentik.stages.identification.models import IdentificationStage | from authentik.stages.identification.models import IdentificationStage | ||||||
| from tests.e2e.utils import SeleniumTestCase, retry | from tests.browser import SeleniumTestCase | ||||||
|  | from tests.decorators import retry | ||||||
|  | from tests.docker import DockerTestCase | ||||||
|  |  | ||||||
|  |  | ||||||
| class TestFlowsEnroll(SeleniumTestCase): | class TestFlowsEnroll(DockerTestCase, SeleniumTestCase): | ||||||
|     """Test Enroll flow""" |     """Test Enroll flow""" | ||||||
|  |  | ||||||
|     @retry() |     @retry() | ||||||
|  | |||||||
| @ -1,12 +1,21 @@ | |||||||
| """test default login flow""" | """test default login flow""" | ||||||
|  |  | ||||||
| from authentik.blueprints.tests import apply_blueprint | from authentik.blueprints.tests import apply_blueprint | ||||||
| from tests.e2e.utils import SeleniumTestCase, retry | from authentik.flows.models import Flow | ||||||
|  | from tests.browser import SeleniumTestCase | ||||||
|  | from tests.decorators import retry | ||||||
|  | from tests.docker import DockerTestCase | ||||||
|  |  | ||||||
|  |  | ||||||
| class TestFlowsLogin(SeleniumTestCase): | class TestFlowsLogin(DockerTestCase, SeleniumTestCase): | ||||||
|     """test default login flow""" |     """test default login flow""" | ||||||
|  |  | ||||||
|  |     def tearDown(self): | ||||||
|  |         # Reset authentication flow's compatibility mode; we need to do this as its | ||||||
|  |         # not specified in the blueprint | ||||||
|  |         Flow.objects.filter(slug="default-authentication-flow").update(compatibility_mode=False) | ||||||
|  |         return super().tearDown() | ||||||
|  |  | ||||||
|     @retry() |     @retry() | ||||||
|     @apply_blueprint( |     @apply_blueprint( | ||||||
|         "default/flow-default-authentication-flow.yaml", |         "default/flow-default-authentication-flow.yaml", | ||||||
| @ -23,3 +32,21 @@ class TestFlowsLogin(SeleniumTestCase): | |||||||
|         self.login() |         self.login() | ||||||
|         self.wait_for_url(self.if_user_url("/library")) |         self.wait_for_url(self.if_user_url("/library")) | ||||||
|         self.assert_user(self.user) |         self.assert_user(self.user) | ||||||
|  |  | ||||||
|  |     @retry() | ||||||
|  |     @apply_blueprint( | ||||||
|  |         "default/flow-default-authentication-flow.yaml", | ||||||
|  |         "default/flow-default-invalidation-flow.yaml", | ||||||
|  |     ) | ||||||
|  |     def test_login_compatibility_mode(self): | ||||||
|  |         """test default login flow with compatibility mode enabled""" | ||||||
|  |         Flow.objects.filter(slug="default-authentication-flow").update(compatibility_mode=True) | ||||||
|  |         self.driver.get( | ||||||
|  |             self.url( | ||||||
|  |                 "authentik_core:if-flow", | ||||||
|  |                 flow_slug="default-authentication-flow", | ||||||
|  |             ) | ||||||
|  |         ) | ||||||
|  |         self.login(shadow_dom=False) | ||||||
|  |         self.wait_for_url(self.if_user_url("/library")) | ||||||
|  |         self.assert_user(self.user) | ||||||
|  | |||||||
							
								
								
									
										53
									
								
								tests/e2e/test_flows_login_sfe.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								tests/e2e/test_flows_login_sfe.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,53 @@ | |||||||
|  | """test default login (using SFE interface) flow""" | ||||||
|  |  | ||||||
|  | from time import sleep | ||||||
|  |  | ||||||
|  | from selenium.webdriver.common.by import By | ||||||
|  | from selenium.webdriver.common.keys import Keys | ||||||
|  |  | ||||||
|  | from authentik.blueprints.tests import apply_blueprint | ||||||
|  | from tests.browser import SeleniumTestCase | ||||||
|  | from tests.decorators import retry | ||||||
|  | from tests.docker import DockerTestCase | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class TestFlowsLoginSFE(DockerTestCase, SeleniumTestCase): | ||||||
|  |     """test default login flow""" | ||||||
|  |  | ||||||
|  |     def login(self): | ||||||
|  |         """Do entire login flow adjusted for SFE""" | ||||||
|  |         flow_executor = self.driver.find_element(By.ID, "flow-sfe-container") | ||||||
|  |         identification_stage = flow_executor.find_element(By.ID, "ident-form") | ||||||
|  |  | ||||||
|  |         identification_stage.find_element(By.CSS_SELECTOR, "input[name=uid_field]").click() | ||||||
|  |         identification_stage.find_element(By.CSS_SELECTOR, "input[name=uid_field]").send_keys( | ||||||
|  |             self.user.username | ||||||
|  |         ) | ||||||
|  |         identification_stage.find_element(By.CSS_SELECTOR, "input[name=uid_field]").send_keys( | ||||||
|  |             Keys.ENTER | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |         password_stage = flow_executor.find_element(By.ID, "password-form") | ||||||
|  |         password_stage.find_element(By.CSS_SELECTOR, "input[name=password]").send_keys( | ||||||
|  |             self.user.username | ||||||
|  |         ) | ||||||
|  |         password_stage.find_element(By.CSS_SELECTOR, "input[name=password]").send_keys(Keys.ENTER) | ||||||
|  |         sleep(1) | ||||||
|  |  | ||||||
|  |     @retry() | ||||||
|  |     @apply_blueprint( | ||||||
|  |         "default/flow-default-authentication-flow.yaml", | ||||||
|  |         "default/flow-default-invalidation-flow.yaml", | ||||||
|  |     ) | ||||||
|  |     def test_login(self): | ||||||
|  |         """test default login flow""" | ||||||
|  |         self.driver.get( | ||||||
|  |             self.url( | ||||||
|  |                 "authentik_core:if-flow", | ||||||
|  |                 flow_slug="default-authentication-flow", | ||||||
|  |                 query={"sfe": True}, | ||||||
|  |             ) | ||||||
|  |         ) | ||||||
|  |         self.login() | ||||||
|  |         self.wait_for_url(self.if_user_url("/library")) | ||||||
|  |         self.assert_user(self.user) | ||||||
| @ -13,10 +13,12 @@ from authentik.flows.models import Flow | |||||||
| from authentik.lib.config import CONFIG | from authentik.lib.config import CONFIG | ||||||
| from authentik.lib.generators import generate_id | from authentik.lib.generators import generate_id | ||||||
| from authentik.stages.identification.models import IdentificationStage | from authentik.stages.identification.models import IdentificationStage | ||||||
| from tests.e2e.utils import SeleniumTestCase, retry | from tests.browser import SeleniumTestCase | ||||||
|  | from tests.decorators import retry | ||||||
|  | from tests.docker import DockerTestCase | ||||||
|  |  | ||||||
|  |  | ||||||
| class TestFlowsRecovery(SeleniumTestCase): | class TestFlowsRecovery(DockerTestCase, SeleniumTestCase): | ||||||
|     """Test Recovery flow""" |     """Test Recovery flow""" | ||||||
|  |  | ||||||
|     def initial_stages(self, user: User): |     def initial_stages(self, user: User): | ||||||
|  | |||||||
| @ -8,10 +8,12 @@ from authentik.core.models import User | |||||||
| from authentik.flows.models import Flow, FlowDesignation | from authentik.flows.models import Flow, FlowDesignation | ||||||
| from authentik.lib.generators import generate_key | from authentik.lib.generators import generate_key | ||||||
| from authentik.stages.password.models import PasswordStage | from authentik.stages.password.models import PasswordStage | ||||||
| from tests.e2e.utils import SeleniumTestCase, retry | from tests.browser import SeleniumTestCase | ||||||
|  | from tests.decorators import retry | ||||||
|  | from tests.docker import DockerTestCase | ||||||
|  |  | ||||||
|  |  | ||||||
| class TestFlowsStageSetup(SeleniumTestCase): | class TestFlowsStageSetup(DockerTestCase, SeleniumTestCase): | ||||||
|     """test stage setup flows""" |     """test stage setup flows""" | ||||||
|  |  | ||||||
|     @retry() |     @retry() | ||||||
|  | |||||||
| @ -16,10 +16,12 @@ from authentik.lib.generators import generate_id | |||||||
| from authentik.outposts.apps import MANAGED_OUTPOST | from authentik.outposts.apps import MANAGED_OUTPOST | ||||||
| from authentik.outposts.models import Outpost, OutpostConfig, OutpostType | from authentik.outposts.models import Outpost, OutpostConfig, OutpostType | ||||||
| from authentik.providers.ldap.models import APIAccessMode, LDAPProvider | from authentik.providers.ldap.models import APIAccessMode, LDAPProvider | ||||||
| from tests.e2e.utils import SeleniumTestCase, retry | from tests.decorators import retry | ||||||
|  | from tests.docker import DockerTestCase | ||||||
|  | from tests.websocket import WebsocketTestCase | ||||||
|  |  | ||||||
|  |  | ||||||
| class TestProviderLDAP(SeleniumTestCase): | class TestProviderLDAP(DockerTestCase, WebsocketTestCase): | ||||||
|     """LDAP and Outpost e2e tests""" |     """LDAP and Outpost e2e tests""" | ||||||
|  |  | ||||||
|     def start_ldap(self, outpost: Outpost): |     def start_ldap(self, outpost: Outpost): | ||||||
|  | |||||||
| @ -18,10 +18,12 @@ from authentik.providers.oauth2.models import ( | |||||||
|     RedirectURI, |     RedirectURI, | ||||||
|     RedirectURIMatchingMode, |     RedirectURIMatchingMode, | ||||||
| ) | ) | ||||||
| from tests.e2e.utils import SeleniumTestCase, retry | from tests.browser import SeleniumTestCase | ||||||
|  | from tests.decorators import retry | ||||||
|  | from tests.docker import DockerTestCase | ||||||
|  |  | ||||||
|  |  | ||||||
| class TestProviderOAuth2Github(SeleniumTestCase): | class TestProviderOAuth2Github(DockerTestCase, SeleniumTestCase): | ||||||
|     """test OAuth Provider flow""" |     """test OAuth Provider flow""" | ||||||
|  |  | ||||||
|     def setUp(self): |     def setUp(self): | ||||||
|  | |||||||
| @ -26,10 +26,12 @@ from authentik.providers.oauth2.models import ( | |||||||
|     RedirectURIMatchingMode, |     RedirectURIMatchingMode, | ||||||
|     ScopeMapping, |     ScopeMapping, | ||||||
| ) | ) | ||||||
| from tests.e2e.utils import SeleniumTestCase, retry | from tests.browser import SeleniumTestCase | ||||||
|  | from tests.decorators import retry | ||||||
|  | from tests.docker import DockerTestCase | ||||||
|  |  | ||||||
|  |  | ||||||
| class TestProviderOAuth2OAuth(SeleniumTestCase): | class TestProviderOAuth2OAuth(DockerTestCase, SeleniumTestCase): | ||||||
|     """test OAuth with OAuth Provider flow""" |     """test OAuth with OAuth Provider flow""" | ||||||
|  |  | ||||||
|     def setUp(self): |     def setUp(self): | ||||||
|  | |||||||
| @ -26,10 +26,12 @@ from authentik.providers.oauth2.models import ( | |||||||
|     RedirectURIMatchingMode, |     RedirectURIMatchingMode, | ||||||
|     ScopeMapping, |     ScopeMapping, | ||||||
| ) | ) | ||||||
| from tests.e2e.utils import SeleniumTestCase, retry | from tests.browser import SeleniumTestCase | ||||||
|  | from tests.decorators import retry | ||||||
|  | from tests.docker import DockerTestCase | ||||||
|  |  | ||||||
|  |  | ||||||
| class TestProviderOAuth2OIDC(SeleniumTestCase): | class TestProviderOAuth2OIDC(DockerTestCase, SeleniumTestCase): | ||||||
|     """test OAuth with OpenID Provider flow""" |     """test OAuth with OpenID Provider flow""" | ||||||
|  |  | ||||||
|     def setUp(self): |     def setUp(self): | ||||||
|  | |||||||
| @ -26,10 +26,12 @@ from authentik.providers.oauth2.models import ( | |||||||
|     RedirectURIMatchingMode, |     RedirectURIMatchingMode, | ||||||
|     ScopeMapping, |     ScopeMapping, | ||||||
| ) | ) | ||||||
| from tests.e2e.utils import SeleniumTestCase, retry | from tests.browser import SeleniumTestCase | ||||||
|  | from tests.decorators import retry | ||||||
|  | from tests.docker import DockerTestCase | ||||||
|  |  | ||||||
|  |  | ||||||
| class TestProviderOAuth2OIDCImplicit(SeleniumTestCase): | class TestProviderOAuth2OIDCImplicit(DockerTestCase, SeleniumTestCase): | ||||||
|     """test OAuth with OpenID Provider flow""" |     """test OAuth with OpenID Provider flow""" | ||||||
|  |  | ||||||
|     def setUp(self): |     def setUp(self): | ||||||
|  | |||||||
| @ -3,11 +3,8 @@ | |||||||
| from base64 import b64encode | from base64 import b64encode | ||||||
| from dataclasses import asdict | from dataclasses import asdict | ||||||
| from json import loads | from json import loads | ||||||
| from sys import platform |  | ||||||
| from time import sleep | from time import sleep | ||||||
| from unittest.case import skip, skipUnless |  | ||||||
|  |  | ||||||
| from channels.testing import ChannelsLiveServerTestCase |  | ||||||
| from jwt import decode | from jwt import decode | ||||||
| from selenium.webdriver.common.by import By | from selenium.webdriver.common.by import By | ||||||
|  |  | ||||||
| @ -18,10 +15,13 @@ from authentik.lib.generators import generate_id | |||||||
| from authentik.outposts.models import DockerServiceConnection, Outpost, OutpostConfig, OutpostType | from authentik.outposts.models import DockerServiceConnection, Outpost, OutpostConfig, OutpostType | ||||||
| from authentik.outposts.tasks import outpost_connection_discovery | from authentik.outposts.tasks import outpost_connection_discovery | ||||||
| from authentik.providers.proxy.models import ProxyProvider | from authentik.providers.proxy.models import ProxyProvider | ||||||
| from tests.e2e.utils import SeleniumTestCase, retry | from tests.browser import SeleniumTestCase | ||||||
|  | from tests.decorators import retry | ||||||
|  | from tests.docker import DockerTestCase | ||||||
|  | from tests.websocket import WebsocketTestCase | ||||||
|  |  | ||||||
|  |  | ||||||
| class TestProviderProxy(SeleniumTestCase): | class TestProviderProxy(DockerTestCase, SeleniumTestCase): | ||||||
|     """Proxy and Outpost e2e tests""" |     """Proxy and Outpost e2e tests""" | ||||||
|  |  | ||||||
|     def setUp(self): |     def setUp(self): | ||||||
| @ -37,13 +37,41 @@ class TestProviderProxy(SeleniumTestCase): | |||||||
|         """Start proxy container based on outpost created""" |         """Start proxy container based on outpost created""" | ||||||
|         self.run_container( |         self.run_container( | ||||||
|             image=self.get_container_image("ghcr.io/goauthentik/dev-proxy"), |             image=self.get_container_image("ghcr.io/goauthentik/dev-proxy"), | ||||||
|             ports={ |             ports={"9000": "9000"}, | ||||||
|                 "9000": "9000", |             environment={"AUTHENTIK_TOKEN": outpost.token.key}, | ||||||
|             }, |  | ||||||
|             environment={ |  | ||||||
|                 "AUTHENTIK_TOKEN": outpost.token.key, |  | ||||||
|             }, |  | ||||||
|         ) |         ) | ||||||
|  |         self.wait_for_outpost(outpost) | ||||||
|  |  | ||||||
|  |     def _prepare(self): | ||||||
|  |         # set additionalHeaders to test later | ||||||
|  |         self.user.attributes["additionalHeaders"] = {"X-Foo": "bar"} | ||||||
|  |         self.user.save() | ||||||
|  |  | ||||||
|  |         proxy: ProxyProvider = ProxyProvider.objects.create( | ||||||
|  |             name=generate_id(), | ||||||
|  |             authorization_flow=Flow.objects.get( | ||||||
|  |                 slug="default-provider-authorization-implicit-consent" | ||||||
|  |             ), | ||||||
|  |             invalidation_flow=Flow.objects.get(slug="default-provider-invalidation-flow"), | ||||||
|  |             internal_host=f"http://{self.host}", | ||||||
|  |             external_host="http://localhost:9000", | ||||||
|  |             basic_auth_enabled=True, | ||||||
|  |             basic_auth_user_attribute="basic-username", | ||||||
|  |             basic_auth_password_attribute="basic-password",  # nosec | ||||||
|  |         ) | ||||||
|  |         # Ensure OAuth2 Params are set | ||||||
|  |         proxy.set_oauth_defaults() | ||||||
|  |         proxy.save() | ||||||
|  |         # we need to create an application to actually access the proxy | ||||||
|  |         Application.objects.create(name=generate_id(), slug=generate_id(), provider=proxy) | ||||||
|  |         outpost: Outpost = Outpost.objects.create( | ||||||
|  |             name=generate_id(), | ||||||
|  |             type=OutpostType.PROXY, | ||||||
|  |         ) | ||||||
|  |         outpost.providers.add(proxy) | ||||||
|  |         outpost.build_user_permissions(outpost.user) | ||||||
|  |  | ||||||
|  |         self.start_proxy(outpost) | ||||||
|  |  | ||||||
|     @retry() |     @retry() | ||||||
|     @apply_blueprint( |     @apply_blueprint( | ||||||
| @ -61,44 +89,7 @@ class TestProviderProxy(SeleniumTestCase): | |||||||
|     @reconcile_app("authentik_crypto") |     @reconcile_app("authentik_crypto") | ||||||
|     def test_proxy_simple(self): |     def test_proxy_simple(self): | ||||||
|         """Test simple outpost setup with single provider""" |         """Test simple outpost setup with single provider""" | ||||||
|         # set additionalHeaders to test later |         self._prepare() | ||||||
|         self.user.attributes["additionalHeaders"] = {"X-Foo": "bar"} |  | ||||||
|         self.user.save() |  | ||||||
|  |  | ||||||
|         proxy: ProxyProvider = ProxyProvider.objects.create( |  | ||||||
|             name=generate_id(), |  | ||||||
|             authorization_flow=Flow.objects.get( |  | ||||||
|                 slug="default-provider-authorization-implicit-consent" |  | ||||||
|             ), |  | ||||||
|             invalidation_flow=Flow.objects.get(slug="default-provider-invalidation-flow"), |  | ||||||
|             internal_host=f"http://{self.host}", |  | ||||||
|             external_host="http://localhost:9000", |  | ||||||
|         ) |  | ||||||
|         # Ensure OAuth2 Params are set |  | ||||||
|         proxy.set_oauth_defaults() |  | ||||||
|         proxy.save() |  | ||||||
|         # we need to create an application to actually access the proxy |  | ||||||
|         Application.objects.create(name=generate_id(), slug=generate_id(), provider=proxy) |  | ||||||
|         outpost: Outpost = Outpost.objects.create( |  | ||||||
|             name=generate_id(), |  | ||||||
|             type=OutpostType.PROXY, |  | ||||||
|         ) |  | ||||||
|         outpost.providers.add(proxy) |  | ||||||
|         outpost.build_user_permissions(outpost.user) |  | ||||||
|  |  | ||||||
|         self.start_proxy(outpost) |  | ||||||
|  |  | ||||||
|         # Wait until outpost healthcheck succeeds |  | ||||||
|         healthcheck_retries = 0 |  | ||||||
|         while healthcheck_retries < 50:  # noqa: PLR2004 |  | ||||||
|             if len(outpost.state) > 0: |  | ||||||
|                 state = outpost.state[0] |  | ||||||
|                 if state.last_seen: |  | ||||||
|                     break |  | ||||||
|             healthcheck_retries += 1 |  | ||||||
|             sleep(0.5) |  | ||||||
|         sleep(5) |  | ||||||
|  |  | ||||||
|         self.driver.get("http://localhost:9000/api") |         self.driver.get("http://localhost:9000/api") | ||||||
|         self.login() |         self.login() | ||||||
|         sleep(1) |         sleep(1) | ||||||
| @ -137,49 +128,13 @@ class TestProviderProxy(SeleniumTestCase): | |||||||
|     @reconcile_app("authentik_crypto") |     @reconcile_app("authentik_crypto") | ||||||
|     def test_proxy_basic_auth(self): |     def test_proxy_basic_auth(self): | ||||||
|         """Test simple outpost setup with single provider""" |         """Test simple outpost setup with single provider""" | ||||||
|  |         self._prepare() | ||||||
|  |         # Setup basic auth | ||||||
|         cred = generate_id() |         cred = generate_id() | ||||||
|         attr = "basic-password"  # nosec |  | ||||||
|         self.user.attributes["basic-username"] = cred |         self.user.attributes["basic-username"] = cred | ||||||
|         self.user.attributes[attr] = cred |         self.user.attributes["basic-password"] = cred | ||||||
|         self.user.save() |         self.user.save() | ||||||
|  |  | ||||||
|         proxy: ProxyProvider = ProxyProvider.objects.create( |  | ||||||
|             name=generate_id(), |  | ||||||
|             authorization_flow=Flow.objects.get( |  | ||||||
|                 slug="default-provider-authorization-implicit-consent" |  | ||||||
|             ), |  | ||||||
|             invalidation_flow=Flow.objects.get(slug="default-provider-invalidation-flow"), |  | ||||||
|             internal_host=f"http://{self.host}", |  | ||||||
|             external_host="http://localhost:9000", |  | ||||||
|             basic_auth_enabled=True, |  | ||||||
|             basic_auth_user_attribute="basic-username", |  | ||||||
|             basic_auth_password_attribute=attr, |  | ||||||
|         ) |  | ||||||
|         # Ensure OAuth2 Params are set |  | ||||||
|         proxy.set_oauth_defaults() |  | ||||||
|         proxy.save() |  | ||||||
|         # we need to create an application to actually access the proxy |  | ||||||
|         Application.objects.create(name=generate_id(), slug=generate_id(), provider=proxy) |  | ||||||
|         outpost: Outpost = Outpost.objects.create( |  | ||||||
|             name=generate_id(), |  | ||||||
|             type=OutpostType.PROXY, |  | ||||||
|         ) |  | ||||||
|         outpost.providers.add(proxy) |  | ||||||
|         outpost.build_user_permissions(outpost.user) |  | ||||||
|  |  | ||||||
|         self.start_proxy(outpost) |  | ||||||
|  |  | ||||||
|         # Wait until outpost healthcheck succeeds |  | ||||||
|         healthcheck_retries = 0 |  | ||||||
|         while healthcheck_retries < 50:  # noqa: PLR2004 |  | ||||||
|             if len(outpost.state) > 0: |  | ||||||
|                 state = outpost.state[0] |  | ||||||
|                 if state.last_seen: |  | ||||||
|                     break |  | ||||||
|             healthcheck_retries += 1 |  | ||||||
|             sleep(0.5) |  | ||||||
|         sleep(5) |  | ||||||
|  |  | ||||||
|         self.driver.get("http://localhost:9000/api") |         self.driver.get("http://localhost:9000/api") | ||||||
|         self.login() |         self.login() | ||||||
|         sleep(1) |         sleep(1) | ||||||
| @ -187,9 +142,9 @@ class TestProviderProxy(SeleniumTestCase): | |||||||
|         full_body_text = self.driver.find_element(By.CSS_SELECTOR, "pre").text |         full_body_text = self.driver.find_element(By.CSS_SELECTOR, "pre").text | ||||||
|         body = loads(full_body_text) |         body = loads(full_body_text) | ||||||
|  |  | ||||||
|         self.assertEqual(body["headers"]["X-Authentik-Username"], [self.user.username]) |         self.assertEqual(body.get("headers").get("X-Authentik-Username"), [self.user.username]) | ||||||
|         auth_header = b64encode(f"{cred}:{cred}".encode()).decode() |         auth_header = b64encode(f"{cred}:{cred}".encode()).decode() | ||||||
|         self.assertEqual(body["headers"]["Authorization"], [f"Basic {auth_header}"]) |         self.assertEqual(body.get("headers").get("Authorization"), [f"Basic {auth_header}"]) | ||||||
|  |  | ||||||
|         self.driver.get("http://localhost:9000/outpost.goauthentik.io/sign_out") |         self.driver.get("http://localhost:9000/outpost.goauthentik.io/sign_out") | ||||||
|         sleep(2) |         sleep(2) | ||||||
| @ -199,10 +154,7 @@ class TestProviderProxy(SeleniumTestCase): | |||||||
|         self.assertIn("You've logged out of", title) |         self.assertIn("You've logged out of", title) | ||||||
|  |  | ||||||
|  |  | ||||||
| # TODO: Fix flaky test | class TestProviderProxyConnect(DockerTestCase, WebsocketTestCase): | ||||||
| @skip("Flaky test") |  | ||||||
| @skipUnless(platform.startswith("linux"), "requires local docker") |  | ||||||
| class TestProviderProxyConnect(ChannelsLiveServerTestCase): |  | ||||||
|     """Test Proxy connectivity over websockets""" |     """Test Proxy connectivity over websockets""" | ||||||
|  |  | ||||||
|     @retry(exceptions=[AssertionError]) |     @retry(exceptions=[AssertionError]) | ||||||
| @ -241,14 +193,7 @@ class TestProviderProxyConnect(ChannelsLiveServerTestCase): | |||||||
|         outpost.build_user_permissions(outpost.user) |         outpost.build_user_permissions(outpost.user) | ||||||
|  |  | ||||||
|         # Wait until outpost healthcheck succeeds |         # Wait until outpost healthcheck succeeds | ||||||
|         healthcheck_retries = 0 |         self.wait_for_outpost(outpost) | ||||||
|         while healthcheck_retries < 50:  # noqa: PLR2004 |  | ||||||
|             if len(outpost.state) > 0: |  | ||||||
|                 state = outpost.state[0] |  | ||||||
|                 if state.last_seen and state.version: |  | ||||||
|                     break |  | ||||||
|             healthcheck_retries += 1 |  | ||||||
|             sleep(0.5) |  | ||||||
|  |  | ||||||
|         state = outpost.state |         state = outpost.state | ||||||
|         self.assertGreaterEqual(len(state), 1) |         self.assertGreaterEqual(len(state), 1) | ||||||
|  | |||||||
| @ -13,10 +13,12 @@ from authentik.flows.models import Flow | |||||||
| from authentik.lib.generators import generate_id | from authentik.lib.generators import generate_id | ||||||
| from authentik.outposts.models import Outpost, OutpostType | from authentik.outposts.models import Outpost, OutpostType | ||||||
| from authentik.providers.proxy.models import ProxyMode, ProxyProvider | from authentik.providers.proxy.models import ProxyMode, ProxyProvider | ||||||
| from tests.e2e.utils import SeleniumTestCase, retry | from tests.browser import SeleniumTestCase | ||||||
|  | from tests.decorators import retry | ||||||
|  | from tests.docker import DockerTestCase | ||||||
|  |  | ||||||
|  |  | ||||||
| class TestProviderProxyForward(SeleniumTestCase): | class TestProviderProxyForward(DockerTestCase, SeleniumTestCase): | ||||||
|     """Proxy and Outpost e2e tests""" |     """Proxy and Outpost e2e tests""" | ||||||
|  |  | ||||||
|     def setUp(self): |     def setUp(self): | ||||||
| @ -30,14 +32,11 @@ class TestProviderProxyForward(SeleniumTestCase): | |||||||
|         """Start proxy container based on outpost created""" |         """Start proxy container based on outpost created""" | ||||||
|         self.run_container( |         self.run_container( | ||||||
|             image=self.get_container_image("ghcr.io/goauthentik/dev-proxy"), |             image=self.get_container_image("ghcr.io/goauthentik/dev-proxy"), | ||||||
|             ports={ |             ports={"9000": "9000"}, | ||||||
|                 "9000": "9000", |             environment={"AUTHENTIK_TOKEN": outpost.token.key}, | ||||||
|             }, |  | ||||||
|             environment={ |  | ||||||
|                 "AUTHENTIK_TOKEN": outpost.token.key, |  | ||||||
|             }, |  | ||||||
|             name="ak-test-outpost", |             name="ak-test-outpost", | ||||||
|         ) |         ) | ||||||
|  |         self.wait_for_outpost(outpost) | ||||||
|  |  | ||||||
|     @apply_blueprint( |     @apply_blueprint( | ||||||
|         "default/flow-default-authentication-flow.yaml", |         "default/flow-default-authentication-flow.yaml", | ||||||
| @ -77,17 +76,6 @@ class TestProviderProxyForward(SeleniumTestCase): | |||||||
|  |  | ||||||
|         self.start_outpost(outpost) |         self.start_outpost(outpost) | ||||||
|  |  | ||||||
|         # Wait until outpost healthcheck succeeds |  | ||||||
|         healthcheck_retries = 0 |  | ||||||
|         while healthcheck_retries < 50:  # noqa: PLR2004 |  | ||||||
|             if len(outpost.state) > 0: |  | ||||||
|                 state = outpost.state[0] |  | ||||||
|                 if state.last_seen: |  | ||||||
|                     break |  | ||||||
|             healthcheck_retries += 1 |  | ||||||
|             sleep(0.5) |  | ||||||
|         sleep(5) |  | ||||||
|  |  | ||||||
|     @retry() |     @retry() | ||||||
|     def test_traefik(self): |     def test_traefik(self): | ||||||
|         """Test traefik""" |         """Test traefik""" | ||||||
|  | |||||||
| @ -1,7 +1,6 @@ | |||||||
| """Radius e2e tests""" | """Radius e2e tests""" | ||||||
|  |  | ||||||
| from dataclasses import asdict | from dataclasses import asdict | ||||||
| from time import sleep |  | ||||||
|  |  | ||||||
| from pyrad.client import Client | from pyrad.client import Client | ||||||
| from pyrad.dictionary import Dictionary | from pyrad.dictionary import Dictionary | ||||||
| @ -9,14 +8,17 @@ from pyrad.packet import AccessAccept, AccessReject, AccessRequest | |||||||
|  |  | ||||||
| from authentik.blueprints.tests import apply_blueprint | from authentik.blueprints.tests import apply_blueprint | ||||||
| from authentik.core.models import Application, User | from authentik.core.models import Application, User | ||||||
|  | from authentik.core.tests.utils import create_test_user | ||||||
| from authentik.flows.models import Flow | from authentik.flows.models import Flow | ||||||
| from authentik.lib.generators import generate_id, generate_key | from authentik.lib.generators import generate_id, generate_key | ||||||
| from authentik.outposts.models import Outpost, OutpostConfig, OutpostType | from authentik.outposts.models import Outpost, OutpostConfig, OutpostType | ||||||
| from authentik.providers.radius.models import RadiusProvider | from authentik.providers.radius.models import RadiusProvider | ||||||
| from tests.e2e.utils import SeleniumTestCase, retry | from tests.decorators import retry | ||||||
|  | from tests.docker import DockerTestCase | ||||||
|  | from tests.websocket import WebsocketTestCase | ||||||
|  |  | ||||||
|  |  | ||||||
| class TestProviderRadius(SeleniumTestCase): | class TestProviderRadius(DockerTestCase, WebsocketTestCase): | ||||||
|     """Radius Outpost e2e tests""" |     """Radius Outpost e2e tests""" | ||||||
|  |  | ||||||
|     def setUp(self): |     def setUp(self): | ||||||
| @ -28,13 +30,13 @@ class TestProviderRadius(SeleniumTestCase): | |||||||
|         self.run_container( |         self.run_container( | ||||||
|             image=self.get_container_image("ghcr.io/goauthentik/dev-radius"), |             image=self.get_container_image("ghcr.io/goauthentik/dev-radius"), | ||||||
|             ports={"1812/udp": "1812/udp"}, |             ports={"1812/udp": "1812/udp"}, | ||||||
|             environment={ |             environment={"AUTHENTIK_TOKEN": outpost.token.key}, | ||||||
|                 "AUTHENTIK_TOKEN": outpost.token.key, |  | ||||||
|             }, |  | ||||||
|         ) |         ) | ||||||
|  |         self.wait_for_outpost(outpost) | ||||||
|  |  | ||||||
|     def _prepare(self) -> User: |     def _prepare(self) -> User: | ||||||
|         """prepare user, provider, app and container""" |         """prepare user, provider, app and container""" | ||||||
|  |         self.user = create_test_user() | ||||||
|         radius: RadiusProvider = RadiusProvider.objects.create( |         radius: RadiusProvider = RadiusProvider.objects.create( | ||||||
|             name=generate_id(), |             name=generate_id(), | ||||||
|             authorization_flow=Flow.objects.get(slug="default-authentication-flow"), |             authorization_flow=Flow.objects.get(slug="default-authentication-flow"), | ||||||
| @ -50,17 +52,6 @@ class TestProviderRadius(SeleniumTestCase): | |||||||
|         outpost.providers.add(radius) |         outpost.providers.add(radius) | ||||||
|  |  | ||||||
|         self.start_radius(outpost) |         self.start_radius(outpost) | ||||||
|  |  | ||||||
|         # Wait until outpost healthcheck succeeds |  | ||||||
|         healthcheck_retries = 0 |  | ||||||
|         while healthcheck_retries < 50:  # noqa: PLR2004 |  | ||||||
|             if len(outpost.state) > 0: |  | ||||||
|                 state = outpost.state[0] |  | ||||||
|                 if state.last_seen: |  | ||||||
|                     break |  | ||||||
|             healthcheck_retries += 1 |  | ||||||
|             sleep(0.5) |  | ||||||
|         sleep(5) |  | ||||||
|         return outpost |         return outpost | ||||||
|  |  | ||||||
|     @retry() |     @retry() | ||||||
|  | |||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user
	