Compare commits
	
		
			1 Commits
		
	
	
		
			openapi-ge
			...
			policies-n
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 3ba6b51ed7 | 
| @ -1,5 +1,5 @@ | |||||||
| [bumpversion] | [bumpversion] | ||||||
| current_version = 2025.4.0 | current_version = 2025.2.4 | ||||||
| tag = True | tag = True | ||||||
| commit = True | commit = True | ||||||
| parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(?:-(?P<rc_t>[a-zA-Z-]+)(?P<rc_n>[1-9]\\d*))? | parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(?:-(?P<rc_t>[a-zA-Z-]+)(?P<rc_n>[1-9]\\d*))? | ||||||
|  | |||||||
							
								
								
									
										12
									
								
								.github/workflows/ci-main.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								.github/workflows/ci-main.yml
									
									
									
									
										vendored
									
									
								
							| @ -70,18 +70,22 @@ 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: uv run python -m lifecycle.migrate |         run: poetry run python -m lifecycle.migrate | ||||||
|       - name: checkout current code |       - name: checkout current code | ||||||
|         run: | |         run: | | ||||||
|           set -x |           set -x | ||||||
|  | |||||||
							
								
								
									
										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: | ||||||
|  | |||||||
| @ -94,7 +94,7 @@ RUN --mount=type=secret,id=GEOIPUPDATE_ACCOUNT_ID \ | |||||||
|     /bin/sh -c "/usr/bin/entry.sh || echo 'Failed to get GeoIP database, disabling'; exit 0" |     /bin/sh -c "/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.7.2 AS uv | FROM ghcr.io/astral-sh/uv:0.6.14 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.12.10-slim-bookworm-fips AS python-base | ||||||
|  |  | ||||||
|  | |||||||
| @ -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.4.0" | __version__ = "2025.2.4" | ||||||
| ENV_GIT_HASH_KEY = "GIT_BUILD_HASH" | ENV_GIT_HASH_KEY = "GIT_BUILD_HASH" | ||||||
|  |  | ||||||
|  |  | ||||||
|  | |||||||
| @ -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).all().update(branding_custom_css=css) |     Brand.objects.using(db_alias).update(branding_custom_css=css) | ||||||
|  |  | ||||||
|  |  | ||||||
| class Migration(migrations.Migration): | class Migration(migrations.Migration): | ||||||
|  | |||||||
| @ -13,10 +13,7 @@ from authentik.core.models import ( | |||||||
|     TokenIntents, |     TokenIntents, | ||||||
|     User, |     User, | ||||||
| ) | ) | ||||||
| from authentik.core.tasks import ( | from authentik.core.tasks import clean_expired_models, clean_temporary_users | ||||||
|     clean_expired_models, |  | ||||||
|     clean_temporary_users, |  | ||||||
| ) |  | ||||||
| from authentik.core.tests.utils import create_test_admin_user | from authentik.core.tests.utils import create_test_admin_user | ||||||
| from authentik.lib.generators import generate_id | from authentik.lib.generators import generate_id | ||||||
|  |  | ||||||
|  | |||||||
| @ -1,27 +0,0 @@ | |||||||
| from rest_framework.viewsets import ModelViewSet |  | ||||||
|  |  | ||||||
| from authentik.core.api.used_by import UsedByMixin |  | ||||||
| from authentik.enterprise.api import EnterpriseRequiredMixin |  | ||||||
| from authentik.enterprise.policies.unique_password.models import UniquePasswordPolicy |  | ||||||
| from authentik.policies.api.policies import PolicySerializer |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class UniquePasswordPolicySerializer(EnterpriseRequiredMixin, PolicySerializer): |  | ||||||
|     """Password Uniqueness Policy Serializer""" |  | ||||||
|  |  | ||||||
|     class Meta: |  | ||||||
|         model = UniquePasswordPolicy |  | ||||||
|         fields = PolicySerializer.Meta.fields + [ |  | ||||||
|             "password_field", |  | ||||||
|             "num_historical_passwords", |  | ||||||
|         ] |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class UniquePasswordPolicyViewSet(UsedByMixin, ModelViewSet): |  | ||||||
|     """Password Uniqueness Policy Viewset""" |  | ||||||
|  |  | ||||||
|     queryset = UniquePasswordPolicy.objects.all() |  | ||||||
|     serializer_class = UniquePasswordPolicySerializer |  | ||||||
|     filterset_fields = "__all__" |  | ||||||
|     ordering = ["name"] |  | ||||||
|     search_fields = ["name"] |  | ||||||
| @ -1,10 +0,0 @@ | |||||||
| """authentik Unique Password policy app config""" |  | ||||||
|  |  | ||||||
| from authentik.enterprise.apps import EnterpriseConfig |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class AuthentikEnterprisePoliciesUniquePasswordConfig(EnterpriseConfig): |  | ||||||
|     name = "authentik.enterprise.policies.unique_password" |  | ||||||
|     label = "authentik_policies_unique_password" |  | ||||||
|     verbose_name = "authentik Enterprise.Policies.Unique Password" |  | ||||||
|     default = True |  | ||||||
| @ -1,81 +0,0 @@ | |||||||
| # Generated by Django 5.0.13 on 2025-03-26 23:02 |  | ||||||
|  |  | ||||||
| import django.db.models.deletion |  | ||||||
| from django.conf import settings |  | ||||||
| from django.db import migrations, models |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class Migration(migrations.Migration): |  | ||||||
|  |  | ||||||
|     initial = True |  | ||||||
|  |  | ||||||
|     dependencies = [ |  | ||||||
|         ("authentik_policies", "0011_policybinding_failure_result_and_more"), |  | ||||||
|         migrations.swappable_dependency(settings.AUTH_USER_MODEL), |  | ||||||
|     ] |  | ||||||
|  |  | ||||||
|     operations = [ |  | ||||||
|         migrations.CreateModel( |  | ||||||
|             name="UniquePasswordPolicy", |  | ||||||
|             fields=[ |  | ||||||
|                 ( |  | ||||||
|                     "policy_ptr", |  | ||||||
|                     models.OneToOneField( |  | ||||||
|                         auto_created=True, |  | ||||||
|                         on_delete=django.db.models.deletion.CASCADE, |  | ||||||
|                         parent_link=True, |  | ||||||
|                         primary_key=True, |  | ||||||
|                         serialize=False, |  | ||||||
|                         to="authentik_policies.policy", |  | ||||||
|                     ), |  | ||||||
|                 ), |  | ||||||
|                 ( |  | ||||||
|                     "password_field", |  | ||||||
|                     models.TextField( |  | ||||||
|                         default="password", |  | ||||||
|                         help_text="Field key to check, field keys defined in Prompt stages are available.", |  | ||||||
|                     ), |  | ||||||
|                 ), |  | ||||||
|                 ( |  | ||||||
|                     "num_historical_passwords", |  | ||||||
|                     models.PositiveIntegerField( |  | ||||||
|                         default=1, help_text="Number of passwords to check against." |  | ||||||
|                     ), |  | ||||||
|                 ), |  | ||||||
|             ], |  | ||||||
|             options={ |  | ||||||
|                 "verbose_name": "Password Uniqueness Policy", |  | ||||||
|                 "verbose_name_plural": "Password Uniqueness Policies", |  | ||||||
|                 "indexes": [ |  | ||||||
|                     models.Index(fields=["policy_ptr_id"], name="authentik_p_policy__f559aa_idx") |  | ||||||
|                 ], |  | ||||||
|             }, |  | ||||||
|             bases=("authentik_policies.policy",), |  | ||||||
|         ), |  | ||||||
|         migrations.CreateModel( |  | ||||||
|             name="UserPasswordHistory", |  | ||||||
|             fields=[ |  | ||||||
|                 ( |  | ||||||
|                     "id", |  | ||||||
|                     models.AutoField( |  | ||||||
|                         auto_created=True, primary_key=True, serialize=False, verbose_name="ID" |  | ||||||
|                     ), |  | ||||||
|                 ), |  | ||||||
|                 ("old_password", models.CharField(max_length=128)), |  | ||||||
|                 ("created_at", models.DateTimeField(auto_now_add=True)), |  | ||||||
|                 ("hibp_prefix_sha1", models.CharField(max_length=5)), |  | ||||||
|                 ("hibp_pw_hash", models.TextField()), |  | ||||||
|                 ( |  | ||||||
|                     "user", |  | ||||||
|                     models.ForeignKey( |  | ||||||
|                         on_delete=django.db.models.deletion.CASCADE, |  | ||||||
|                         related_name="old_passwords", |  | ||||||
|                         to=settings.AUTH_USER_MODEL, |  | ||||||
|                     ), |  | ||||||
|                 ), |  | ||||||
|             ], |  | ||||||
|             options={ |  | ||||||
|                 "verbose_name": "User Password History", |  | ||||||
|             }, |  | ||||||
|         ), |  | ||||||
|     ] |  | ||||||
| @ -1,151 +0,0 @@ | |||||||
| from hashlib import sha1 |  | ||||||
|  |  | ||||||
| from django.contrib.auth.hashers import identify_hasher, make_password |  | ||||||
| from django.db import models |  | ||||||
| from django.utils.translation import gettext as _ |  | ||||||
| from rest_framework.serializers import BaseSerializer |  | ||||||
| from structlog.stdlib import get_logger |  | ||||||
|  |  | ||||||
| from authentik.core.models import User |  | ||||||
| from authentik.policies.models import Policy |  | ||||||
| from authentik.policies.types import PolicyRequest, PolicyResult |  | ||||||
| from authentik.stages.prompt.stage import PLAN_CONTEXT_PROMPT |  | ||||||
|  |  | ||||||
| LOGGER = get_logger() |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class UniquePasswordPolicy(Policy): |  | ||||||
|     """This policy prevents users from reusing old passwords.""" |  | ||||||
|  |  | ||||||
|     password_field = models.TextField( |  | ||||||
|         default="password", |  | ||||||
|         help_text=_("Field key to check, field keys defined in Prompt stages are available."), |  | ||||||
|     ) |  | ||||||
|  |  | ||||||
|     # Limit on the number of previous passwords the policy evaluates |  | ||||||
|     # Also controls number of old passwords the system stores. |  | ||||||
|     num_historical_passwords = models.PositiveIntegerField( |  | ||||||
|         default=1, |  | ||||||
|         help_text=_("Number of passwords to check against."), |  | ||||||
|     ) |  | ||||||
|  |  | ||||||
|     @property |  | ||||||
|     def serializer(self) -> type[BaseSerializer]: |  | ||||||
|         from authentik.enterprise.policies.unique_password.api import UniquePasswordPolicySerializer |  | ||||||
|  |  | ||||||
|         return UniquePasswordPolicySerializer |  | ||||||
|  |  | ||||||
|     @property |  | ||||||
|     def component(self) -> str: |  | ||||||
|         return "ak-policy-password-uniqueness-form" |  | ||||||
|  |  | ||||||
|     def passes(self, request: PolicyRequest) -> PolicyResult: |  | ||||||
|         from authentik.enterprise.policies.unique_password.models import UserPasswordHistory |  | ||||||
|  |  | ||||||
|         password = request.context.get(PLAN_CONTEXT_PROMPT, {}).get( |  | ||||||
|             self.password_field, request.context.get(self.password_field) |  | ||||||
|         ) |  | ||||||
|         if not password: |  | ||||||
|             LOGGER.warning( |  | ||||||
|                 "Password field not found in request when checking UniquePasswordPolicy", |  | ||||||
|                 field=self.password_field, |  | ||||||
|                 fields=request.context.keys(), |  | ||||||
|             ) |  | ||||||
|             return PolicyResult(False, _("Password not set in context")) |  | ||||||
|         password = str(password) |  | ||||||
|  |  | ||||||
|         if not self.num_historical_passwords: |  | ||||||
|             # Policy not configured to check against any passwords |  | ||||||
|             return PolicyResult(True) |  | ||||||
|  |  | ||||||
|         num_to_check = self.num_historical_passwords |  | ||||||
|         password_history = UserPasswordHistory.objects.filter(user=request.user).order_by( |  | ||||||
|             "-created_at" |  | ||||||
|         )[:num_to_check] |  | ||||||
|  |  | ||||||
|         if not password_history: |  | ||||||
|             return PolicyResult(True) |  | ||||||
|  |  | ||||||
|         for record in password_history: |  | ||||||
|             if not record.old_password: |  | ||||||
|                 continue |  | ||||||
|  |  | ||||||
|             if self._passwords_match(new_password=password, old_password=record.old_password): |  | ||||||
|                 # Return on first match. Authentik does not consider timing attacks |  | ||||||
|                 # on old passwords to be an attack surface. |  | ||||||
|                 return PolicyResult( |  | ||||||
|                     False, |  | ||||||
|                     _("This password has been used previously. Please choose a different one."), |  | ||||||
|                 ) |  | ||||||
|  |  | ||||||
|         return PolicyResult(True) |  | ||||||
|  |  | ||||||
|     def _passwords_match(self, *, new_password: str, old_password: str) -> bool: |  | ||||||
|         try: |  | ||||||
|             hasher = identify_hasher(old_password) |  | ||||||
|         except ValueError: |  | ||||||
|             LOGGER.warning( |  | ||||||
|                 "Skipping password; could not load hash algorithm", |  | ||||||
|             ) |  | ||||||
|             return False |  | ||||||
|  |  | ||||||
|         return hasher.verify(new_password, old_password) |  | ||||||
|  |  | ||||||
|     @classmethod |  | ||||||
|     def is_in_use(cls): |  | ||||||
|         """Check if any UniquePasswordPolicy is in use, either through policy bindings |  | ||||||
|         or direct attachment to a PromptStage. |  | ||||||
|  |  | ||||||
|         Returns: |  | ||||||
|             bool: True if any policy is in use, False otherwise |  | ||||||
|         """ |  | ||||||
|         from authentik.policies.models import PolicyBinding |  | ||||||
|  |  | ||||||
|         # Check if any policy is in use through bindings |  | ||||||
|         if PolicyBinding.in_use.for_policy(cls).exists(): |  | ||||||
|             return True |  | ||||||
|  |  | ||||||
|         # Check if any policy is attached to a PromptStage |  | ||||||
|         if cls.objects.filter(promptstage__isnull=False).exists(): |  | ||||||
|             return True |  | ||||||
|  |  | ||||||
|         return False |  | ||||||
|  |  | ||||||
|     class Meta(Policy.PolicyMeta): |  | ||||||
|         verbose_name = _("Password Uniqueness Policy") |  | ||||||
|         verbose_name_plural = _("Password Uniqueness Policies") |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class UserPasswordHistory(models.Model): |  | ||||||
|     user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="old_passwords") |  | ||||||
|     # Mimic's column type of AbstractBaseUser.password |  | ||||||
|     old_password = models.CharField(max_length=128) |  | ||||||
|     created_at = models.DateTimeField(auto_now_add=True) |  | ||||||
|  |  | ||||||
|     hibp_prefix_sha1 = models.CharField(max_length=5) |  | ||||||
|     hibp_pw_hash = models.TextField() |  | ||||||
|  |  | ||||||
|     class Meta: |  | ||||||
|         verbose_name = _("User Password History") |  | ||||||
|  |  | ||||||
|     def __str__(self) -> str: |  | ||||||
|         timestamp = f"{self.created_at:%Y/%m/%d %X}" if self.created_at else "N/A" |  | ||||||
|         return f"Previous Password (user: {self.user_id}, recorded: {timestamp})" |  | ||||||
|  |  | ||||||
|     @classmethod |  | ||||||
|     def create_for_user(cls, user: User, password: str): |  | ||||||
|         # To check users' passwords against Have I been Pwned, we need the first 5 chars |  | ||||||
|         # of the password hashed with SHA1 without a salt... |  | ||||||
|         pw_hash_sha1 = sha1(password.encode("utf-8")).hexdigest()  # nosec |  | ||||||
|         # ...however that'll give us a list of hashes from HIBP, and to compare that we still |  | ||||||
|         # need a full unsalted SHA1 of the password. We don't want to save that directly in |  | ||||||
|         # the database, so we hash that SHA1 again with a modern hashing alg, |  | ||||||
|         # and then when we check users' passwords against HIBP we can use `check_password` |  | ||||||
|         # which will take care of this. |  | ||||||
|         hibp_hash_hash = make_password(pw_hash_sha1) |  | ||||||
|         return cls.objects.create( |  | ||||||
|             user=user, |  | ||||||
|             old_password=password, |  | ||||||
|             hibp_prefix_sha1=pw_hash_sha1[:5], |  | ||||||
|             hibp_pw_hash=hibp_hash_hash, |  | ||||||
|         ) |  | ||||||
| @ -1,20 +0,0 @@ | |||||||
| """Unique Password Policy settings""" |  | ||||||
|  |  | ||||||
| from celery.schedules import crontab |  | ||||||
|  |  | ||||||
| from authentik.lib.utils.time import fqdn_rand |  | ||||||
|  |  | ||||||
| CELERY_BEAT_SCHEDULE = { |  | ||||||
|     "policies_unique_password_trim_history": { |  | ||||||
|         "task": "authentik.enterprise.policies.unique_password.tasks.trim_password_histories", |  | ||||||
|         "schedule": crontab(minute=fqdn_rand("policies_unique_password_trim"), hour="*/12"), |  | ||||||
|         "options": {"queue": "authentik_scheduled"}, |  | ||||||
|     }, |  | ||||||
|     "policies_unique_password_check_purge": { |  | ||||||
|         "task": ( |  | ||||||
|             "authentik.enterprise.policies.unique_password.tasks.check_and_purge_password_history" |  | ||||||
|         ), |  | ||||||
|         "schedule": crontab(minute=fqdn_rand("policies_unique_password_purge"), hour="*/24"), |  | ||||||
|         "options": {"queue": "authentik_scheduled"}, |  | ||||||
|     }, |  | ||||||
| } |  | ||||||
| @ -1,23 +0,0 @@ | |||||||
| """authentik policy signals""" |  | ||||||
|  |  | ||||||
| from django.dispatch import receiver |  | ||||||
|  |  | ||||||
| from authentik.core.models import User |  | ||||||
| from authentik.core.signals import password_changed |  | ||||||
| from authentik.enterprise.policies.unique_password.models import ( |  | ||||||
|     UniquePasswordPolicy, |  | ||||||
|     UserPasswordHistory, |  | ||||||
| ) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @receiver(password_changed) |  | ||||||
| def copy_password_to_password_history(sender, user: User, *args, **kwargs): |  | ||||||
|     """Preserve the user's old password if UniquePasswordPolicy is enabled anywhere""" |  | ||||||
|     # Check if any UniquePasswordPolicy is in use |  | ||||||
|     unique_pwd_policy_in_use = UniquePasswordPolicy.is_in_use() |  | ||||||
|  |  | ||||||
|     if unique_pwd_policy_in_use: |  | ||||||
|         """NOTE: Because we run this in a signal after saving the user, |  | ||||||
|         we are not atomically guaranteed to save password history. |  | ||||||
|         """ |  | ||||||
|         UserPasswordHistory.create_for_user(user, user.password) |  | ||||||
| @ -1,66 +0,0 @@ | |||||||
| from django.db.models.aggregates import Count |  | ||||||
| from structlog import get_logger |  | ||||||
|  |  | ||||||
| from authentik.enterprise.policies.unique_password.models import ( |  | ||||||
|     UniquePasswordPolicy, |  | ||||||
|     UserPasswordHistory, |  | ||||||
| ) |  | ||||||
| from authentik.events.system_tasks import SystemTask, TaskStatus, prefill_task |  | ||||||
| from authentik.root.celery import CELERY_APP |  | ||||||
|  |  | ||||||
| LOGGER = get_logger() |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @CELERY_APP.task(bind=True, base=SystemTask) |  | ||||||
| @prefill_task |  | ||||||
| def check_and_purge_password_history(self: SystemTask): |  | ||||||
|     """Check if any UniquePasswordPolicy exists, and if not, purge the password history table. |  | ||||||
|     This is run on a schedule instead of being triggered by policy binding deletion. |  | ||||||
|     """ |  | ||||||
|     if not UniquePasswordPolicy.objects.exists(): |  | ||||||
|         UserPasswordHistory.objects.all().delete() |  | ||||||
|         LOGGER.debug("Purged UserPasswordHistory table as no policies are in use") |  | ||||||
|         self.set_status(TaskStatus.SUCCESSFUL, "Successfully purged UserPasswordHistory") |  | ||||||
|         return |  | ||||||
|  |  | ||||||
|     self.set_status( |  | ||||||
|         TaskStatus.SUCCESSFUL, "Not purging password histories, a unique password policy exists" |  | ||||||
|     ) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @CELERY_APP.task(bind=True, base=SystemTask) |  | ||||||
| def trim_password_histories(self: SystemTask): |  | ||||||
|     """Removes rows from UserPasswordHistory older than |  | ||||||
|     the `n` most recent entries. |  | ||||||
|  |  | ||||||
|     The `n` is defined by the largest configured value for all bound |  | ||||||
|     UniquePasswordPolicy policies. |  | ||||||
|     """ |  | ||||||
|  |  | ||||||
|     # No policy, we'll let the cleanup above do its thing |  | ||||||
|     if not UniquePasswordPolicy.objects.exists(): |  | ||||||
|         return |  | ||||||
|  |  | ||||||
|     num_rows_to_preserve = 0 |  | ||||||
|     for policy in UniquePasswordPolicy.objects.all(): |  | ||||||
|         num_rows_to_preserve = max(num_rows_to_preserve, policy.num_historical_passwords) |  | ||||||
|  |  | ||||||
|     all_pks_to_keep = [] |  | ||||||
|  |  | ||||||
|     # Get all users who have password history entries |  | ||||||
|     users_with_history = ( |  | ||||||
|         UserPasswordHistory.objects.values("user") |  | ||||||
|         .annotate(count=Count("user")) |  | ||||||
|         .filter(count__gt=0) |  | ||||||
|         .values_list("user", flat=True) |  | ||||||
|     ) |  | ||||||
|     for user_pk in users_with_history: |  | ||||||
|         entries = UserPasswordHistory.objects.filter(user__pk=user_pk) |  | ||||||
|         pks_to_keep = entries.order_by("-created_at")[:num_rows_to_preserve].values_list( |  | ||||||
|             "pk", flat=True |  | ||||||
|         ) |  | ||||||
|         all_pks_to_keep.extend(pks_to_keep) |  | ||||||
|  |  | ||||||
|     num_deleted, _ = UserPasswordHistory.objects.exclude(pk__in=all_pks_to_keep).delete() |  | ||||||
|     LOGGER.debug("Deleted stale password history records", count=num_deleted) |  | ||||||
|     self.set_status(TaskStatus.SUCCESSFUL, f"Delete {num_deleted} stale password history records") |  | ||||||
| @ -1,108 +0,0 @@ | |||||||
| """Unique Password Policy flow tests""" |  | ||||||
|  |  | ||||||
| from django.contrib.auth.hashers import make_password |  | ||||||
| from django.urls.base import reverse |  | ||||||
|  |  | ||||||
| from authentik.core.tests.utils import create_test_flow, create_test_user |  | ||||||
| from authentik.enterprise.policies.unique_password.models import ( |  | ||||||
|     UniquePasswordPolicy, |  | ||||||
|     UserPasswordHistory, |  | ||||||
| ) |  | ||||||
| from authentik.flows.models import FlowDesignation, FlowStageBinding |  | ||||||
| from authentik.flows.tests import FlowTestCase |  | ||||||
| from authentik.lib.generators import generate_id |  | ||||||
| from authentik.stages.prompt.models import FieldTypes, Prompt, PromptStage |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class TestUniquePasswordPolicyFlow(FlowTestCase): |  | ||||||
|     """Test Unique Password Policy in a flow""" |  | ||||||
|  |  | ||||||
|     REUSED_PASSWORD = "hunter1"  # nosec B105 |  | ||||||
|  |  | ||||||
|     def setUp(self) -> None: |  | ||||||
|         self.user = create_test_user() |  | ||||||
|         self.flow = create_test_flow(FlowDesignation.AUTHENTICATION) |  | ||||||
|  |  | ||||||
|         password_prompt = Prompt.objects.create( |  | ||||||
|             name=generate_id(), |  | ||||||
|             field_key="password", |  | ||||||
|             label="PASSWORD_LABEL", |  | ||||||
|             type=FieldTypes.PASSWORD, |  | ||||||
|             required=True, |  | ||||||
|             placeholder="PASSWORD_PLACEHOLDER", |  | ||||||
|         ) |  | ||||||
|  |  | ||||||
|         self.policy = UniquePasswordPolicy.objects.create( |  | ||||||
|             name="password_must_unique", |  | ||||||
|             password_field=password_prompt.field_key, |  | ||||||
|             num_historical_passwords=1, |  | ||||||
|         ) |  | ||||||
|         stage = PromptStage.objects.create(name="prompt-stage") |  | ||||||
|         stage.validation_policies.set([self.policy]) |  | ||||||
|         stage.fields.set( |  | ||||||
|             [ |  | ||||||
|                 password_prompt, |  | ||||||
|             ] |  | ||||||
|         ) |  | ||||||
|         FlowStageBinding.objects.create(target=self.flow, stage=stage, order=2) |  | ||||||
|  |  | ||||||
|         # Seed the user's password history |  | ||||||
|         UserPasswordHistory.create_for_user(self.user, make_password(self.REUSED_PASSWORD)) |  | ||||||
|  |  | ||||||
|     def test_prompt_data(self): |  | ||||||
|         """Test policy attached to a prompt stage""" |  | ||||||
|         # Test the policy directly |  | ||||||
|         from authentik.policies.types import PolicyRequest |  | ||||||
|         from authentik.stages.prompt.stage import PLAN_CONTEXT_PROMPT |  | ||||||
|  |  | ||||||
|         # Create a policy request with the reused password |  | ||||||
|         request = PolicyRequest(user=self.user) |  | ||||||
|         request.context[PLAN_CONTEXT_PROMPT] = {"password": self.REUSED_PASSWORD} |  | ||||||
|  |  | ||||||
|         # Test the policy directly |  | ||||||
|         result = self.policy.passes(request) |  | ||||||
|  |  | ||||||
|         # Verify that the policy fails (returns False) with the expected error message |  | ||||||
|         self.assertFalse(result.passing, "Policy should fail for reused password") |  | ||||||
|         self.assertEqual( |  | ||||||
|             result.messages[0], |  | ||||||
|             "This password has been used previously. Please choose a different one.", |  | ||||||
|             "Incorrect error message", |  | ||||||
|         ) |  | ||||||
|  |  | ||||||
|         # API-based testing approach: |  | ||||||
|  |  | ||||||
|         self.client.force_login(self.user) |  | ||||||
|  |  | ||||||
|         # Send a POST request to the flow executor with the reused password |  | ||||||
|         response = self.client.post( |  | ||||||
|             reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug}), |  | ||||||
|             {"password": self.REUSED_PASSWORD}, |  | ||||||
|         ) |  | ||||||
|         self.assertStageResponse( |  | ||||||
|             response, |  | ||||||
|             self.flow, |  | ||||||
|             component="ak-stage-prompt", |  | ||||||
|             fields=[ |  | ||||||
|                 { |  | ||||||
|                     "choices": None, |  | ||||||
|                     "field_key": "password", |  | ||||||
|                     "label": "PASSWORD_LABEL", |  | ||||||
|                     "order": 0, |  | ||||||
|                     "placeholder": "PASSWORD_PLACEHOLDER", |  | ||||||
|                     "initial_value": "", |  | ||||||
|                     "required": True, |  | ||||||
|                     "type": "password", |  | ||||||
|                     "sub_text": "", |  | ||||||
|                 } |  | ||||||
|             ], |  | ||||||
|             response_errors={ |  | ||||||
|                 "non_field_errors": [ |  | ||||||
|                     { |  | ||||||
|                         "code": "invalid", |  | ||||||
|                         "string": "This password has been used previously. " |  | ||||||
|                         "Please choose a different one.", |  | ||||||
|                     } |  | ||||||
|                 ] |  | ||||||
|             }, |  | ||||||
|         ) |  | ||||||
| @ -1,77 +0,0 @@ | |||||||
| """Unique Password Policy tests""" |  | ||||||
|  |  | ||||||
| from django.contrib.auth.hashers import make_password |  | ||||||
| from django.test import TestCase |  | ||||||
| from guardian.shortcuts import get_anonymous_user |  | ||||||
|  |  | ||||||
| from authentik.core.models import User |  | ||||||
| from authentik.enterprise.policies.unique_password.models import ( |  | ||||||
|     UniquePasswordPolicy, |  | ||||||
|     UserPasswordHistory, |  | ||||||
| ) |  | ||||||
| from authentik.policies.types import PolicyRequest, PolicyResult |  | ||||||
| from authentik.stages.prompt.stage import PLAN_CONTEXT_PROMPT |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class TestUniquePasswordPolicy(TestCase): |  | ||||||
|     """Test Password Uniqueness Policy""" |  | ||||||
|  |  | ||||||
|     def setUp(self) -> None: |  | ||||||
|         self.policy = UniquePasswordPolicy.objects.create( |  | ||||||
|             name="test_unique_password", num_historical_passwords=1 |  | ||||||
|         ) |  | ||||||
|         self.user = User.objects.create(username="test-user") |  | ||||||
|  |  | ||||||
|     def test_invalid(self): |  | ||||||
|         """Test without password present in request""" |  | ||||||
|         request = PolicyRequest(get_anonymous_user()) |  | ||||||
|         result: PolicyResult = self.policy.passes(request) |  | ||||||
|         self.assertFalse(result.passing) |  | ||||||
|         self.assertEqual(result.messages[0], "Password not set in context") |  | ||||||
|  |  | ||||||
|     def test_passes_no_previous_passwords(self): |  | ||||||
|         request = PolicyRequest(get_anonymous_user()) |  | ||||||
|         request.context = {PLAN_CONTEXT_PROMPT: {"password": "hunter2"}} |  | ||||||
|         result: PolicyResult = self.policy.passes(request) |  | ||||||
|         self.assertTrue(result.passing) |  | ||||||
|  |  | ||||||
|     def test_passes_passwords_are_different(self): |  | ||||||
|         # Seed database with an old password |  | ||||||
|         UserPasswordHistory.create_for_user(self.user, make_password("hunter1")) |  | ||||||
|  |  | ||||||
|         request = PolicyRequest(self.user) |  | ||||||
|         request.context = {PLAN_CONTEXT_PROMPT: {"password": "hunter2"}} |  | ||||||
|         result: PolicyResult = self.policy.passes(request) |  | ||||||
|         self.assertTrue(result.passing) |  | ||||||
|  |  | ||||||
|     def test_passes_multiple_old_passwords(self): |  | ||||||
|         # Seed with multiple old passwords |  | ||||||
|         UserPasswordHistory.objects.bulk_create( |  | ||||||
|             [ |  | ||||||
|                 UserPasswordHistory(user=self.user, old_password=make_password("hunter1")), |  | ||||||
|                 UserPasswordHistory(user=self.user, old_password=make_password("hunter2")), |  | ||||||
|             ] |  | ||||||
|         ) |  | ||||||
|         request = PolicyRequest(self.user) |  | ||||||
|         request.context = {PLAN_CONTEXT_PROMPT: {"password": "hunter3"}} |  | ||||||
|         result: PolicyResult = self.policy.passes(request) |  | ||||||
|         self.assertTrue(result.passing) |  | ||||||
|  |  | ||||||
|     def test_fails_password_matches_old_password(self): |  | ||||||
|         # Seed database with an old password |  | ||||||
|  |  | ||||||
|         UserPasswordHistory.create_for_user(self.user, make_password("hunter1")) |  | ||||||
|  |  | ||||||
|         request = PolicyRequest(self.user) |  | ||||||
|         request.context = {PLAN_CONTEXT_PROMPT: {"password": "hunter1"}} |  | ||||||
|         result: PolicyResult = self.policy.passes(request) |  | ||||||
|         self.assertFalse(result.passing) |  | ||||||
|  |  | ||||||
|     def test_fails_if_identical_password_with_different_hash_algos(self): |  | ||||||
|         UserPasswordHistory.create_for_user( |  | ||||||
|             self.user, make_password("hunter2", "somesalt", "scrypt") |  | ||||||
|         ) |  | ||||||
|         request = PolicyRequest(self.user) |  | ||||||
|         request.context = {PLAN_CONTEXT_PROMPT: {"password": "hunter2"}} |  | ||||||
|         result: PolicyResult = self.policy.passes(request) |  | ||||||
|         self.assertFalse(result.passing) |  | ||||||
| @ -1,90 +0,0 @@ | |||||||
| from django.urls import reverse |  | ||||||
|  |  | ||||||
| from authentik.core.models import Group, Source, User |  | ||||||
| from authentik.core.tests.utils import create_test_flow, create_test_user |  | ||||||
| from authentik.enterprise.policies.unique_password.models import ( |  | ||||||
|     UniquePasswordPolicy, |  | ||||||
|     UserPasswordHistory, |  | ||||||
| ) |  | ||||||
| from authentik.flows.markers import StageMarker |  | ||||||
| from authentik.flows.models import FlowStageBinding |  | ||||||
| from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER, FlowPlan |  | ||||||
| from authentik.flows.tests import FlowTestCase |  | ||||||
| from authentik.flows.views.executor import SESSION_KEY_PLAN |  | ||||||
| from authentik.lib.generators import generate_key |  | ||||||
| from authentik.policies.models import PolicyBinding, PolicyBindingModel |  | ||||||
| from authentik.stages.prompt.stage import PLAN_CONTEXT_PROMPT |  | ||||||
| from authentik.stages.user_write.models import UserWriteStage |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class TestUserWriteStage(FlowTestCase): |  | ||||||
|     """Write tests""" |  | ||||||
|  |  | ||||||
|     def setUp(self): |  | ||||||
|         super().setUp() |  | ||||||
|         self.flow = create_test_flow() |  | ||||||
|         self.group = Group.objects.create(name="test-group") |  | ||||||
|         self.other_group = Group.objects.create(name="other-group") |  | ||||||
|         self.stage: UserWriteStage = UserWriteStage.objects.create( |  | ||||||
|             name="write", create_users_as_inactive=True, create_users_group=self.group |  | ||||||
|         ) |  | ||||||
|         self.binding = FlowStageBinding.objects.create(target=self.flow, stage=self.stage, order=2) |  | ||||||
|         self.source = Source.objects.create(name="fake_source") |  | ||||||
|  |  | ||||||
|     def test_save_password_history_if_policy_binding_enforced(self): |  | ||||||
|         """Test user's new password is recorded when ANY enabled UniquePasswordPolicy exists""" |  | ||||||
|         unique_password_policy = UniquePasswordPolicy.objects.create(num_historical_passwords=5) |  | ||||||
|         pbm = PolicyBindingModel.objects.create() |  | ||||||
|         PolicyBinding.objects.create( |  | ||||||
|             target=pbm, policy=unique_password_policy, order=0, enabled=True |  | ||||||
|         ) |  | ||||||
|  |  | ||||||
|         test_user = create_test_user() |  | ||||||
|         # Store original password for verification |  | ||||||
|         original_password = test_user.password |  | ||||||
|  |  | ||||||
|         # We're changing our own password |  | ||||||
|         self.client.force_login(test_user) |  | ||||||
|  |  | ||||||
|         new_password = generate_key() |  | ||||||
|         plan = FlowPlan(flow_pk=self.flow.pk.hex, bindings=[self.binding], markers=[StageMarker()]) |  | ||||||
|         plan.context[PLAN_CONTEXT_PENDING_USER] = test_user |  | ||||||
|         plan.context[PLAN_CONTEXT_PROMPT] = { |  | ||||||
|             "username": test_user.username, |  | ||||||
|             "password": new_password, |  | ||||||
|         } |  | ||||||
|         session = self.client.session |  | ||||||
|         session[SESSION_KEY_PLAN] = plan |  | ||||||
|         session.save() |  | ||||||
|         # Password history should be recorded |  | ||||||
|         user_password_history_qs = UserPasswordHistory.objects.filter(user=test_user) |  | ||||||
|         self.assertTrue(user_password_history_qs.exists(), "Password history should be recorded") |  | ||||||
|         self.assertEqual(len(user_password_history_qs), 1, "expected 1 recorded password") |  | ||||||
|  |  | ||||||
|         # Create a password history entry manually to simulate the signal behavior |  | ||||||
|         # This is what would happen if the signal worked correctly |  | ||||||
|         UserPasswordHistory.objects.create(user=test_user, old_password=original_password) |  | ||||||
|         user_password_history_qs = UserPasswordHistory.objects.filter(user=test_user) |  | ||||||
|         self.assertTrue(user_password_history_qs.exists(), "Password history should be recorded") |  | ||||||
|         self.assertEqual(len(user_password_history_qs), 2, "expected 2 recorded password") |  | ||||||
|  |  | ||||||
|         # Execute the flow by sending a POST request to the flow executor endpoint |  | ||||||
|         response = self.client.post( |  | ||||||
|             reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug}) |  | ||||||
|         ) |  | ||||||
|  |  | ||||||
|         # Verify that the request was successful |  | ||||||
|         self.assertEqual(response.status_code, 200) |  | ||||||
|         user_qs = User.objects.filter(username=plan.context[PLAN_CONTEXT_PROMPT]["username"]) |  | ||||||
|         self.assertTrue(user_qs.exists()) |  | ||||||
|  |  | ||||||
|         # Verify the password history entry exists |  | ||||||
|         user_password_history_qs = UserPasswordHistory.objects.filter(user=test_user) |  | ||||||
|         self.assertTrue(user_password_history_qs.exists(), "Password history should be recorded") |  | ||||||
|  |  | ||||||
|         self.assertEqual(len(user_password_history_qs), 3, "expected 3 recorded password") |  | ||||||
|         # Verify that one of the entries contains the original password |  | ||||||
|         self.assertTrue( |  | ||||||
|             any(entry.old_password == original_password for entry in user_password_history_qs), |  | ||||||
|             "original password should be in password history table", |  | ||||||
|         ) |  | ||||||
| @ -1,178 +0,0 @@ | |||||||
| from datetime import datetime, timedelta |  | ||||||
|  |  | ||||||
| from django.test import TestCase |  | ||||||
|  |  | ||||||
| from authentik.core.tests.utils import create_test_user |  | ||||||
| from authentik.enterprise.policies.unique_password.models import ( |  | ||||||
|     UniquePasswordPolicy, |  | ||||||
|     UserPasswordHistory, |  | ||||||
| ) |  | ||||||
| from authentik.enterprise.policies.unique_password.tasks import ( |  | ||||||
|     check_and_purge_password_history, |  | ||||||
|     trim_password_histories, |  | ||||||
| ) |  | ||||||
| from authentik.policies.models import PolicyBinding, PolicyBindingModel |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class TestUniquePasswordPolicyModel(TestCase): |  | ||||||
|     """Test the UniquePasswordPolicy model methods""" |  | ||||||
|  |  | ||||||
|     def test_is_in_use_with_binding(self): |  | ||||||
|         """Test is_in_use returns True when a policy binding exists""" |  | ||||||
|         # Create a UniquePasswordPolicy and a PolicyBinding for it |  | ||||||
|         policy = UniquePasswordPolicy.objects.create(num_historical_passwords=5) |  | ||||||
|         pbm = PolicyBindingModel.objects.create() |  | ||||||
|         PolicyBinding.objects.create(target=pbm, policy=policy, order=0, enabled=True) |  | ||||||
|  |  | ||||||
|         # Verify is_in_use returns True |  | ||||||
|         self.assertTrue(UniquePasswordPolicy.is_in_use()) |  | ||||||
|  |  | ||||||
|     def test_is_in_use_with_promptstage(self): |  | ||||||
|         """Test is_in_use returns True when attached to a PromptStage""" |  | ||||||
|         from authentik.stages.prompt.models import PromptStage |  | ||||||
|  |  | ||||||
|         # Create a UniquePasswordPolicy and attach it to a PromptStage |  | ||||||
|         policy = UniquePasswordPolicy.objects.create(num_historical_passwords=5) |  | ||||||
|         prompt_stage = PromptStage.objects.create( |  | ||||||
|             name="Test Prompt Stage", |  | ||||||
|         ) |  | ||||||
|         # Use the set() method for many-to-many relationships |  | ||||||
|         prompt_stage.validation_policies.set([policy]) |  | ||||||
|  |  | ||||||
|         # Verify is_in_use returns True |  | ||||||
|         self.assertTrue(UniquePasswordPolicy.is_in_use()) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class TestTrimAllPasswordHistories(TestCase): |  | ||||||
|     """Test the task that trims password history for all users""" |  | ||||||
|  |  | ||||||
|     def setUp(self): |  | ||||||
|         self.user1 = create_test_user("test-user1") |  | ||||||
|         self.user2 = create_test_user("test-user2") |  | ||||||
|         self.pbm = PolicyBindingModel.objects.create() |  | ||||||
|         # Create a policy with a limit of 1 password |  | ||||||
|         self.policy = UniquePasswordPolicy.objects.create(num_historical_passwords=1) |  | ||||||
|         PolicyBinding.objects.create( |  | ||||||
|             target=self.pbm, |  | ||||||
|             policy=self.policy, |  | ||||||
|             enabled=True, |  | ||||||
|             order=0, |  | ||||||
|         ) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class TestCheckAndPurgePasswordHistory(TestCase): |  | ||||||
|     """Test the scheduled task that checks if any policy is in use and purges if not""" |  | ||||||
|  |  | ||||||
|     def setUp(self): |  | ||||||
|         self.user = create_test_user("test-user") |  | ||||||
|         self.pbm = PolicyBindingModel.objects.create() |  | ||||||
|  |  | ||||||
|     def test_purge_when_no_policy_in_use(self): |  | ||||||
|         """Test that the task purges the table when no policy is in use""" |  | ||||||
|         # Create some password history entries |  | ||||||
|         UserPasswordHistory.create_for_user(self.user, "hunter2") |  | ||||||
|  |  | ||||||
|         # Verify we have entries |  | ||||||
|         self.assertTrue(UserPasswordHistory.objects.exists()) |  | ||||||
|  |  | ||||||
|         # Run the task - should purge since no policy is in use |  | ||||||
|         check_and_purge_password_history() |  | ||||||
|  |  | ||||||
|         # Verify the table is empty |  | ||||||
|         self.assertFalse(UserPasswordHistory.objects.exists()) |  | ||||||
|  |  | ||||||
|     def test_no_purge_when_policy_in_use(self): |  | ||||||
|         """Test that the task doesn't purge when a policy is in use""" |  | ||||||
|         # Create a policy and binding |  | ||||||
|         policy = UniquePasswordPolicy.objects.create(num_historical_passwords=5) |  | ||||||
|         PolicyBinding.objects.create( |  | ||||||
|             target=self.pbm, |  | ||||||
|             policy=policy, |  | ||||||
|             enabled=True, |  | ||||||
|             order=0, |  | ||||||
|         ) |  | ||||||
|  |  | ||||||
|         # Create some password history entries |  | ||||||
|         UserPasswordHistory.create_for_user(self.user, "hunter2") |  | ||||||
|  |  | ||||||
|         # Verify we have entries |  | ||||||
|         self.assertTrue(UserPasswordHistory.objects.exists()) |  | ||||||
|  |  | ||||||
|         # Run the task - should NOT purge since a policy is in use |  | ||||||
|         check_and_purge_password_history() |  | ||||||
|  |  | ||||||
|         # Verify the entries still exist |  | ||||||
|         self.assertTrue(UserPasswordHistory.objects.exists()) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class TestTrimPasswordHistory(TestCase): |  | ||||||
|     """Test password history cleanup task""" |  | ||||||
|  |  | ||||||
|     def setUp(self): |  | ||||||
|         self.user = create_test_user("test-user") |  | ||||||
|         self.pbm = PolicyBindingModel.objects.create() |  | ||||||
|  |  | ||||||
|     def test_trim_password_history_ok(self): |  | ||||||
|         """Test passwords over the define limit are deleted""" |  | ||||||
|         _now = datetime.now() |  | ||||||
|         UserPasswordHistory.objects.bulk_create( |  | ||||||
|             [ |  | ||||||
|                 UserPasswordHistory( |  | ||||||
|                     user=self.user, |  | ||||||
|                     old_password="hunter1",  # nosec B106 |  | ||||||
|                     created_at=_now - timedelta(days=3), |  | ||||||
|                 ), |  | ||||||
|                 UserPasswordHistory( |  | ||||||
|                     user=self.user, |  | ||||||
|                     old_password="hunter2",  # nosec B106 |  | ||||||
|                     created_at=_now - timedelta(days=2), |  | ||||||
|                 ), |  | ||||||
|                 UserPasswordHistory( |  | ||||||
|                     user=self.user, |  | ||||||
|                     old_password="hunter3",  # nosec B106 |  | ||||||
|                     created_at=_now, |  | ||||||
|                 ), |  | ||||||
|             ] |  | ||||||
|         ) |  | ||||||
|  |  | ||||||
|         policy = UniquePasswordPolicy.objects.create(num_historical_passwords=1) |  | ||||||
|         PolicyBinding.objects.create( |  | ||||||
|             target=self.pbm, |  | ||||||
|             policy=policy, |  | ||||||
|             enabled=True, |  | ||||||
|             order=0, |  | ||||||
|         ) |  | ||||||
|         trim_password_histories.delay() |  | ||||||
|         user_pwd_history_qs = UserPasswordHistory.objects.filter(user=self.user) |  | ||||||
|         self.assertEqual(len(user_pwd_history_qs), 1) |  | ||||||
|  |  | ||||||
|     def test_trim_password_history_policy_diabled_no_op(self): |  | ||||||
|         """Test no passwords removed if policy binding is disabled""" |  | ||||||
|  |  | ||||||
|         # Insert a record to ensure it's not deleted after executing task |  | ||||||
|         UserPasswordHistory.create_for_user(self.user, "hunter2") |  | ||||||
|  |  | ||||||
|         policy = UniquePasswordPolicy.objects.create(num_historical_passwords=1) |  | ||||||
|         PolicyBinding.objects.create( |  | ||||||
|             target=self.pbm, |  | ||||||
|             policy=policy, |  | ||||||
|             enabled=False, |  | ||||||
|             order=0, |  | ||||||
|         ) |  | ||||||
|         trim_password_histories.delay() |  | ||||||
|         self.assertTrue(UserPasswordHistory.objects.filter(user=self.user).exists()) |  | ||||||
|  |  | ||||||
|     def test_trim_password_history_fewer_records_than_maximum_is_no_op(self): |  | ||||||
|         """Test no passwords deleted if fewer passwords exist than limit""" |  | ||||||
|  |  | ||||||
|         UserPasswordHistory.create_for_user(self.user, "hunter2") |  | ||||||
|  |  | ||||||
|         policy = UniquePasswordPolicy.objects.create(num_historical_passwords=2) |  | ||||||
|         PolicyBinding.objects.create( |  | ||||||
|             target=self.pbm, |  | ||||||
|             policy=policy, |  | ||||||
|             enabled=True, |  | ||||||
|             order=0, |  | ||||||
|         ) |  | ||||||
|         trim_password_histories.delay() |  | ||||||
|         self.assertTrue(UserPasswordHistory.objects.filter(user=self.user).exists()) |  | ||||||
| @ -1,7 +0,0 @@ | |||||||
| """API URLs""" |  | ||||||
|  |  | ||||||
| from authentik.enterprise.policies.unique_password.api import UniquePasswordPolicyViewSet |  | ||||||
|  |  | ||||||
| api_urlpatterns = [ |  | ||||||
|     ("policies/unique_password", UniquePasswordPolicyViewSet), |  | ||||||
| ] |  | ||||||
| @ -14,7 +14,6 @@ CELERY_BEAT_SCHEDULE = { | |||||||
|  |  | ||||||
| TENANT_APPS = [ | TENANT_APPS = [ | ||||||
|     "authentik.enterprise.audit", |     "authentik.enterprise.audit", | ||||||
|     "authentik.enterprise.policies.unique_password", |  | ||||||
|     "authentik.enterprise.providers.google_workspace", |     "authentik.enterprise.providers.google_workspace", | ||||||
|     "authentik.enterprise.providers.microsoft_entra", |     "authentik.enterprise.providers.microsoft_entra", | ||||||
|     "authentik.enterprise.providers.ssf", |     "authentik.enterprise.providers.ssf", | ||||||
|  | |||||||
| @ -69,6 +69,7 @@ SESSION_KEY_APPLICATION_PRE = "authentik/flows/application_pre" | |||||||
| SESSION_KEY_GET = "authentik/flows/get" | SESSION_KEY_GET = "authentik/flows/get" | ||||||
| SESSION_KEY_POST = "authentik/flows/post" | SESSION_KEY_POST = "authentik/flows/post" | ||||||
| SESSION_KEY_HISTORY = "authentik/flows/history" | SESSION_KEY_HISTORY = "authentik/flows/history" | ||||||
|  | SESSION_KEY_AUTH_STARTED = "authentik/flows/auth_started" | ||||||
| QS_KEY_TOKEN = "flow_token"  # nosec | QS_KEY_TOKEN = "flow_token"  # nosec | ||||||
| QS_QUERY = "query" | QS_QUERY = "query" | ||||||
|  |  | ||||||
| @ -453,6 +454,7 @@ class FlowExecutorView(APIView): | |||||||
|             SESSION_KEY_APPLICATION_PRE, |             SESSION_KEY_APPLICATION_PRE, | ||||||
|             SESSION_KEY_PLAN, |             SESSION_KEY_PLAN, | ||||||
|             SESSION_KEY_GET, |             SESSION_KEY_GET, | ||||||
|  |             SESSION_KEY_AUTH_STARTED, | ||||||
|             # We might need the initial POST payloads for later requests |             # We might need the initial POST payloads for later requests | ||||||
|             # SESSION_KEY_POST, |             # SESSION_KEY_POST, | ||||||
|             # We don't delete the history on purpose, as a user might |             # We don't delete the history on purpose, as a user might | ||||||
|  | |||||||
| @ -6,14 +6,22 @@ from django.shortcuts import get_object_or_404 | |||||||
| from ua_parser.user_agent_parser import Parse | from ua_parser.user_agent_parser import Parse | ||||||
|  |  | ||||||
| from authentik.core.views.interface import InterfaceView | from authentik.core.views.interface import InterfaceView | ||||||
| from authentik.flows.models import Flow | from authentik.flows.models import Flow, FlowDesignation | ||||||
|  | from authentik.flows.views.executor import SESSION_KEY_AUTH_STARTED | ||||||
|  |  | ||||||
|  |  | ||||||
| class FlowInterfaceView(InterfaceView): | 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 | ||||||
|  |         if ( | ||||||
|  |             not self.request.user.is_authenticated | ||||||
|  |             and flow.designation == FlowDesignation.AUTHENTICATION | ||||||
|  |         ): | ||||||
|  |             self.request.session[SESSION_KEY_AUTH_STARTED] = True | ||||||
|  |             self.request.session.save() | ||||||
|         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) | ||||||
|  |  | ||||||
|  | |||||||
| @ -74,8 +74,6 @@ class OutpostConfig: | |||||||
|     kubernetes_ingress_annotations: dict[str, str] = field(default_factory=dict) |     kubernetes_ingress_annotations: dict[str, str] = field(default_factory=dict) | ||||||
|     kubernetes_ingress_secret_name: str = field(default="authentik-outpost-tls") |     kubernetes_ingress_secret_name: str = field(default="authentik-outpost-tls") | ||||||
|     kubernetes_ingress_class_name: str | None = field(default=None) |     kubernetes_ingress_class_name: str | None = field(default=None) | ||||||
|     kubernetes_httproute_annotations: dict[str, str] = field(default_factory=dict) |  | ||||||
|     kubernetes_httproute_parent_refs: list[dict[str, str]] = field(default_factory=list) |  | ||||||
|     kubernetes_service_type: str = field(default="ClusterIP") |     kubernetes_service_type: str = field(default="ClusterIP") | ||||||
|     kubernetes_disabled_components: list[str] = field(default_factory=list) |     kubernetes_disabled_components: list[str] = field(default_factory=list) | ||||||
|     kubernetes_image_pull_secrets: list[str] = field(default_factory=list) |     kubernetes_image_pull_secrets: list[str] = field(default_factory=list) | ||||||
|  | |||||||
| @ -1,8 +1,4 @@ | |||||||
| """Authentik policies app config | """authentik policies app config""" | ||||||
|  |  | ||||||
| Every system policy should be its own Django app under the `policies` app. |  | ||||||
| For example: The 'dummy' policy is available at `authentik.policies.dummy`. |  | ||||||
| """ |  | ||||||
|  |  | ||||||
| from prometheus_client import Gauge, Histogram | from prometheus_client import Gauge, Histogram | ||||||
|  |  | ||||||
| @ -39,3 +35,4 @@ class AuthentikPoliciesConfig(ManagedAppConfig): | |||||||
|     label = "authentik_policies" |     label = "authentik_policies" | ||||||
|     verbose_name = "authentik Policies" |     verbose_name = "authentik Policies" | ||||||
|     default = True |     default = True | ||||||
|  |     mountpoint = "policy/" | ||||||
|  | |||||||
| @ -108,6 +108,9 @@ class PolicyEngine: | |||||||
|         self.__cached_policies.append(cached_policy) |         self.__cached_policies.append(cached_policy) | ||||||
|         return True |         return True | ||||||
|  |  | ||||||
|  |     def _should_fork(self, binding: PolicyBinding) -> bool: | ||||||
|  |         return binding.policy is not None | ||||||
|  |  | ||||||
|     def build(self) -> "PolicyEngine": |     def build(self) -> "PolicyEngine": | ||||||
|         """Build wrapper which monitors performance""" |         """Build wrapper which monitors performance""" | ||||||
|         with ( |         with ( | ||||||
| @ -134,7 +137,7 @@ class PolicyEngine: | |||||||
|                 task = PolicyProcess(binding, self.request, task_end) |                 task = PolicyProcess(binding, self.request, task_end) | ||||||
|                 task.daemon = False |                 task.daemon = False | ||||||
|                 self.logger.debug("P_ENG: Starting Process", binding=binding, request=self.request) |                 self.logger.debug("P_ENG: Starting Process", binding=binding, request=self.request) | ||||||
|                 if not CURRENT_PROCESS._config.get("daemon"): |                 if not CURRENT_PROCESS._config.get("daemon") or not self._should_fork(binding): | ||||||
|                     task.run() |                     task.run() | ||||||
|                 else: |                 else: | ||||||
|                     task.start() |                     task.start() | ||||||
|  | |||||||
| @ -52,13 +52,6 @@ class PolicyBindingModel(models.Model): | |||||||
|         return ["policy", "user", "group"] |         return ["policy", "user", "group"] | ||||||
|  |  | ||||||
|  |  | ||||||
| class BoundPolicyQuerySet(models.QuerySet): |  | ||||||
|     """QuerySet for filtering enabled bindings for a Policy type""" |  | ||||||
|  |  | ||||||
|     def for_policy(self, policy: "Policy"): |  | ||||||
|         return self.filter(policy__in=policy._default_manager.all()).filter(enabled=True) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class PolicyBinding(SerializerModel): | class PolicyBinding(SerializerModel): | ||||||
|     """Relationship between a Policy and a PolicyBindingModel.""" |     """Relationship between a Policy and a PolicyBindingModel.""" | ||||||
|  |  | ||||||
| @ -155,9 +148,6 @@ class PolicyBinding(SerializerModel): | |||||||
|             return f"Binding - #{self.order} to {suffix}" |             return f"Binding - #{self.order} to {suffix}" | ||||||
|         return "" |         return "" | ||||||
|  |  | ||||||
|     objects = models.Manager() |  | ||||||
|     in_use = BoundPolicyQuerySet.as_manager() |  | ||||||
|  |  | ||||||
|     class Meta: |     class Meta: | ||||||
|         verbose_name = _("Policy Binding") |         verbose_name = _("Policy Binding") | ||||||
|         verbose_name_plural = _("Policy Bindings") |         verbose_name_plural = _("Policy Bindings") | ||||||
|  | |||||||
| @ -2,6 +2,4 @@ | |||||||
|  |  | ||||||
| from authentik.policies.password.api import PasswordPolicyViewSet | from authentik.policies.password.api import PasswordPolicyViewSet | ||||||
|  |  | ||||||
| api_urlpatterns = [ | api_urlpatterns = [("policies/password", PasswordPolicyViewSet)] | ||||||
|     ("policies/password", PasswordPolicyViewSet), |  | ||||||
| ] |  | ||||||
|  | |||||||
							
								
								
									
										89
									
								
								authentik/policies/templates/policies/buffer.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								authentik/policies/templates/policies/buffer.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,89 @@ | |||||||
|  | {% extends 'login/base_full.html' %} | ||||||
|  |  | ||||||
|  | {% load static %} | ||||||
|  | {% load i18n %} | ||||||
|  |  | ||||||
|  | {% block head %} | ||||||
|  | {{ block.super }} | ||||||
|  | <script> | ||||||
|  |   let redirecting = false; | ||||||
|  |   const checkAuth = async () => { | ||||||
|  |     if (redirecting) return true; | ||||||
|  |     const url = "{{ check_auth_url }}"; | ||||||
|  |     console.debug("authentik/policies/buffer: Checking authentication..."); | ||||||
|  |     try { | ||||||
|  |       const result = await fetch(url, { | ||||||
|  |         method: "HEAD", | ||||||
|  |       }); | ||||||
|  |       if (result.status >= 400) { | ||||||
|  |         return false | ||||||
|  |       } | ||||||
|  |       console.debug("authentik/policies/buffer: Continuing"); | ||||||
|  |       redirecting = true; | ||||||
|  |       if ("{{ auth_req_method }}" === "post") { | ||||||
|  |         document.querySelector("form").submit(); | ||||||
|  |       } else { | ||||||
|  |         window.location.assign("{{ continue_url|escapejs }}"); | ||||||
|  |       } | ||||||
|  |     } catch { | ||||||
|  |       return false; | ||||||
|  |     } | ||||||
|  |   }; | ||||||
|  |   let timeout = 100; | ||||||
|  |   let offset = 20; | ||||||
|  |   let attempt = 0; | ||||||
|  |   const main = async () => { | ||||||
|  |     attempt += 1; | ||||||
|  |     await checkAuth(); | ||||||
|  |     console.debug(`authentik/policies/buffer: Waiting ${timeout}ms...`); | ||||||
|  |     setTimeout(main, timeout); | ||||||
|  |     timeout += (offset * attempt); | ||||||
|  |     if (timeout >= 2000) { | ||||||
|  |       timeout = 2000; | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   document.addEventListener("visibilitychange", async () => { | ||||||
|  |     if (document.hidden) return; | ||||||
|  |     console.debug("authentik/policies/buffer: Checking authentication on tab activate..."); | ||||||
|  |     await checkAuth(); | ||||||
|  |   }); | ||||||
|  |   main(); | ||||||
|  | </script> | ||||||
|  | {% endblock %} | ||||||
|  |  | ||||||
|  | {% block title %} | ||||||
|  | {% trans 'Waiting for authentication...' %} - {{ brand.branding_title }} | ||||||
|  | {% endblock %} | ||||||
|  |  | ||||||
|  | {% block card_title %} | ||||||
|  | {% trans 'Waiting for authentication...' %} | ||||||
|  | {% endblock %} | ||||||
|  |  | ||||||
|  | {% block card %} | ||||||
|  | <form class="pf-c-form" method="{{ auth_req_method }}" action="{{ continue_url }}"> | ||||||
|  |   {% if auth_req_method == "post" %} | ||||||
|  |     {% for key, value in auth_req_body.items %} | ||||||
|  |       <input type="hidden" name="{{ key }}" value="{{ value }}" /> | ||||||
|  |     {% endfor %} | ||||||
|  |   {% endif %} | ||||||
|  |   <div class="pf-c-empty-state"> | ||||||
|  |     <div class="pf-c-empty-state__content"> | ||||||
|  |       <div class="pf-c-empty-state__icon"> | ||||||
|  |         <span class="pf-c-spinner pf-m-xl" role="progressbar"> | ||||||
|  |           <span class="pf-c-spinner__clipper"></span> | ||||||
|  |           <span class="pf-c-spinner__lead-ball"></span> | ||||||
|  |           <span class="pf-c-spinner__tail-ball"></span> | ||||||
|  |         </span> | ||||||
|  |       </div> | ||||||
|  |       <h1 class="pf-c-title pf-m-lg"> | ||||||
|  |         {% trans "You're already authenticating in another tab. This page will refresh once authentication is completed." %} | ||||||
|  |       </h1> | ||||||
|  |     </div> | ||||||
|  |   </div> | ||||||
|  |   <div class="pf-c-form__group pf-m-action"> | ||||||
|  |     <a href="{{ auth_req_url }}" class="pf-c-button pf-m-primary pf-m-block"> | ||||||
|  |       {% trans "Authenticate in this tab" %} | ||||||
|  |     </a> | ||||||
|  |   </div> | ||||||
|  | </form> | ||||||
|  | {% endblock %} | ||||||
							
								
								
									
										121
									
								
								authentik/policies/tests/test_views.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								authentik/policies/tests/test_views.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,121 @@ | |||||||
|  | from django.contrib.auth.models import AnonymousUser | ||||||
|  | from django.contrib.sessions.middleware import SessionMiddleware | ||||||
|  | from django.http import HttpResponse | ||||||
|  | from django.test import RequestFactory, TestCase | ||||||
|  | from django.urls import reverse | ||||||
|  |  | ||||||
|  | from authentik.core.models import Application, Provider | ||||||
|  | from authentik.core.tests.utils import create_test_flow, create_test_user | ||||||
|  | from authentik.flows.models import FlowDesignation | ||||||
|  | from authentik.flows.planner import FlowPlan | ||||||
|  | from authentik.flows.views.executor import SESSION_KEY_PLAN | ||||||
|  | from authentik.lib.generators import generate_id | ||||||
|  | from authentik.lib.tests.utils import dummy_get_response | ||||||
|  | from authentik.policies.views import ( | ||||||
|  |     QS_BUFFER_ID, | ||||||
|  |     SESSION_KEY_BUFFER, | ||||||
|  |     BufferedPolicyAccessView, | ||||||
|  |     BufferView, | ||||||
|  |     PolicyAccessView, | ||||||
|  | ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class TestPolicyViews(TestCase): | ||||||
|  |     """Test PolicyAccessView""" | ||||||
|  |  | ||||||
|  |     def setUp(self): | ||||||
|  |         super().setUp() | ||||||
|  |         self.factory = RequestFactory() | ||||||
|  |         self.user = create_test_user() | ||||||
|  |  | ||||||
|  |     def test_pav(self): | ||||||
|  |         """Test simple policy access view""" | ||||||
|  |         provider = Provider.objects.create( | ||||||
|  |             name=generate_id(), | ||||||
|  |         ) | ||||||
|  |         app = Application.objects.create(name=generate_id(), slug=generate_id(), provider=provider) | ||||||
|  |  | ||||||
|  |         class TestView(PolicyAccessView): | ||||||
|  |             def resolve_provider_application(self): | ||||||
|  |                 self.provider = provider | ||||||
|  |                 self.application = app | ||||||
|  |  | ||||||
|  |             def get(self, *args, **kwargs): | ||||||
|  |                 return HttpResponse("foo") | ||||||
|  |  | ||||||
|  |         req = self.factory.get("/") | ||||||
|  |         req.user = self.user | ||||||
|  |         res = TestView.as_view()(req) | ||||||
|  |         self.assertEqual(res.status_code, 200) | ||||||
|  |         self.assertEqual(res.content, b"foo") | ||||||
|  |  | ||||||
|  |     def test_pav_buffer(self): | ||||||
|  |         """Test simple policy access view""" | ||||||
|  |         provider = Provider.objects.create( | ||||||
|  |             name=generate_id(), | ||||||
|  |         ) | ||||||
|  |         app = Application.objects.create(name=generate_id(), slug=generate_id(), provider=provider) | ||||||
|  |         flow = create_test_flow(FlowDesignation.AUTHENTICATION) | ||||||
|  |  | ||||||
|  |         class TestView(BufferedPolicyAccessView): | ||||||
|  |             def resolve_provider_application(self): | ||||||
|  |                 self.provider = provider | ||||||
|  |                 self.application = app | ||||||
|  |  | ||||||
|  |             def get(self, *args, **kwargs): | ||||||
|  |                 return HttpResponse("foo") | ||||||
|  |  | ||||||
|  |         req = self.factory.get("/") | ||||||
|  |         req.user = AnonymousUser() | ||||||
|  |         middleware = SessionMiddleware(dummy_get_response) | ||||||
|  |         middleware.process_request(req) | ||||||
|  |         req.session[SESSION_KEY_PLAN] = FlowPlan(flow.pk) | ||||||
|  |         req.session.save() | ||||||
|  |         res = TestView.as_view()(req) | ||||||
|  |         self.assertEqual(res.status_code, 302) | ||||||
|  |         self.assertTrue(res.url.startswith(reverse("authentik_policies:buffer"))) | ||||||
|  |  | ||||||
|  |     def test_pav_buffer_skip(self): | ||||||
|  |         """Test simple policy access view (skip buffer)""" | ||||||
|  |         provider = Provider.objects.create( | ||||||
|  |             name=generate_id(), | ||||||
|  |         ) | ||||||
|  |         app = Application.objects.create(name=generate_id(), slug=generate_id(), provider=provider) | ||||||
|  |         flow = create_test_flow(FlowDesignation.AUTHENTICATION) | ||||||
|  |  | ||||||
|  |         class TestView(BufferedPolicyAccessView): | ||||||
|  |             def resolve_provider_application(self): | ||||||
|  |                 self.provider = provider | ||||||
|  |                 self.application = app | ||||||
|  |  | ||||||
|  |             def get(self, *args, **kwargs): | ||||||
|  |                 return HttpResponse("foo") | ||||||
|  |  | ||||||
|  |         req = self.factory.get("/?skip_buffer=true") | ||||||
|  |         req.user = AnonymousUser() | ||||||
|  |         middleware = SessionMiddleware(dummy_get_response) | ||||||
|  |         middleware.process_request(req) | ||||||
|  |         req.session[SESSION_KEY_PLAN] = FlowPlan(flow.pk) | ||||||
|  |         req.session.save() | ||||||
|  |         res = TestView.as_view()(req) | ||||||
|  |         self.assertEqual(res.status_code, 302) | ||||||
|  |         self.assertTrue(res.url.startswith(reverse("authentik_flows:default-authentication"))) | ||||||
|  |  | ||||||
|  |     def test_buffer(self): | ||||||
|  |         """Test buffer view""" | ||||||
|  |         uid = generate_id() | ||||||
|  |         req = self.factory.get(f"/?{QS_BUFFER_ID}={uid}") | ||||||
|  |         req.user = AnonymousUser() | ||||||
|  |         middleware = SessionMiddleware(dummy_get_response) | ||||||
|  |         middleware.process_request(req) | ||||||
|  |         ts = generate_id() | ||||||
|  |         req.session[SESSION_KEY_BUFFER % uid] = { | ||||||
|  |             "method": "get", | ||||||
|  |             "body": {}, | ||||||
|  |             "url": f"/{ts}", | ||||||
|  |         } | ||||||
|  |         req.session.save() | ||||||
|  |  | ||||||
|  |         res = BufferView.as_view()(req) | ||||||
|  |         self.assertEqual(res.status_code, 200) | ||||||
|  |         self.assertIn(ts, res.render().content.decode()) | ||||||
| @ -1,7 +1,14 @@ | |||||||
| """API URLs""" | """API URLs""" | ||||||
|  |  | ||||||
|  | from django.urls import path | ||||||
|  |  | ||||||
| from authentik.policies.api.bindings import PolicyBindingViewSet | from authentik.policies.api.bindings import PolicyBindingViewSet | ||||||
| from authentik.policies.api.policies import PolicyViewSet | from authentik.policies.api.policies import PolicyViewSet | ||||||
|  | from authentik.policies.views import BufferView | ||||||
|  |  | ||||||
|  | urlpatterns = [ | ||||||
|  |     path("buffer", BufferView.as_view(), name="buffer"), | ||||||
|  | ] | ||||||
|  |  | ||||||
| api_urlpatterns = [ | api_urlpatterns = [ | ||||||
|     ("policies/all", PolicyViewSet), |     ("policies/all", PolicyViewSet), | ||||||
|  | |||||||
| @ -1,23 +1,37 @@ | |||||||
| """authentik access helper classes""" | """authentik access helper classes""" | ||||||
|  |  | ||||||
| from typing import Any | from typing import Any | ||||||
|  | from uuid import uuid4 | ||||||
|  |  | ||||||
| from django.contrib import messages | from django.contrib import messages | ||||||
| from django.contrib.auth.mixins import AccessMixin | from django.contrib.auth.mixins import AccessMixin | ||||||
| from django.contrib.auth.views import redirect_to_login | from django.contrib.auth.views import redirect_to_login | ||||||
| from django.http import HttpRequest, HttpResponse | from django.http import HttpRequest, HttpResponse, QueryDict | ||||||
|  | from django.shortcuts import redirect | ||||||
|  | from django.urls import reverse | ||||||
|  | from django.utils.http import urlencode | ||||||
| from django.utils.translation import gettext as _ | from django.utils.translation import gettext as _ | ||||||
| from django.views.generic.base import View | from django.views.generic.base import TemplateView, View | ||||||
| from structlog.stdlib import get_logger | from structlog.stdlib import get_logger | ||||||
|  |  | ||||||
| from authentik.core.models import Application, Provider, User | from authentik.core.models import Application, Provider, User | ||||||
| from authentik.flows.views.executor import SESSION_KEY_APPLICATION_PRE, SESSION_KEY_POST | from authentik.flows.models import Flow, FlowDesignation | ||||||
|  | from authentik.flows.planner import FlowPlan | ||||||
|  | from authentik.flows.views.executor import ( | ||||||
|  |     SESSION_KEY_APPLICATION_PRE, | ||||||
|  |     SESSION_KEY_AUTH_STARTED, | ||||||
|  |     SESSION_KEY_PLAN, | ||||||
|  |     SESSION_KEY_POST, | ||||||
|  | ) | ||||||
| from authentik.lib.sentry import SentryIgnoredException | from authentik.lib.sentry import SentryIgnoredException | ||||||
| from authentik.policies.denied import AccessDeniedResponse | from authentik.policies.denied import AccessDeniedResponse | ||||||
| from authentik.policies.engine import PolicyEngine | from authentik.policies.engine import PolicyEngine | ||||||
| from authentik.policies.types import PolicyRequest, PolicyResult | from authentik.policies.types import PolicyRequest, PolicyResult | ||||||
|  |  | ||||||
| LOGGER = get_logger() | LOGGER = get_logger() | ||||||
|  | QS_BUFFER_ID = "af_bf_id" | ||||||
|  | QS_SKIP_BUFFER = "skip_buffer" | ||||||
|  | SESSION_KEY_BUFFER = "authentik/policies/pav_buffer/%s" | ||||||
|  |  | ||||||
|  |  | ||||||
| class RequestValidationError(SentryIgnoredException): | class RequestValidationError(SentryIgnoredException): | ||||||
| @ -125,3 +139,65 @@ class PolicyAccessView(AccessMixin, View): | |||||||
|             for message in result.messages: |             for message in result.messages: | ||||||
|                 messages.error(self.request, _(message)) |                 messages.error(self.request, _(message)) | ||||||
|         return result |         return result | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def url_with_qs(url: str, **kwargs): | ||||||
|  |     """Update/set querystring of `url` with the parameters in `kwargs`. Original query string | ||||||
|  |     parameters are retained""" | ||||||
|  |     if "?" not in url: | ||||||
|  |         return url + f"?{urlencode(kwargs)}" | ||||||
|  |     url, _, qs = url.partition("?") | ||||||
|  |     qs = QueryDict(qs, mutable=True) | ||||||
|  |     qs.update(kwargs) | ||||||
|  |     return url + f"?{urlencode(qs.items())}" | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class BufferView(TemplateView): | ||||||
|  |     """Buffer view""" | ||||||
|  |  | ||||||
|  |     template_name = "policies/buffer.html" | ||||||
|  |  | ||||||
|  |     def get_context_data(self, **kwargs): | ||||||
|  |         buf_id = self.request.GET.get(QS_BUFFER_ID) | ||||||
|  |         buffer: dict = self.request.session.get(SESSION_KEY_BUFFER % buf_id) | ||||||
|  |         kwargs["auth_req_method"] = buffer["method"] | ||||||
|  |         kwargs["auth_req_body"] = buffer["body"] | ||||||
|  |         kwargs["auth_req_url"] = url_with_qs(buffer["url"], **{QS_SKIP_BUFFER: True}) | ||||||
|  |         kwargs["check_auth_url"] = reverse("authentik_api:user-me") | ||||||
|  |         kwargs["continue_url"] = url_with_qs(buffer["url"], **{QS_BUFFER_ID: buf_id}) | ||||||
|  |         return super().get_context_data(**kwargs) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class BufferedPolicyAccessView(PolicyAccessView): | ||||||
|  |     """PolicyAccessView which buffers access requests in case the user is not logged in""" | ||||||
|  |  | ||||||
|  |     def handle_no_permission(self): | ||||||
|  |         plan: FlowPlan | None = self.request.session.get(SESSION_KEY_PLAN) | ||||||
|  |         authenticating = self.request.session.get(SESSION_KEY_AUTH_STARTED) | ||||||
|  |         if plan: | ||||||
|  |             flow = Flow.objects.filter(pk=plan.flow_pk).first() | ||||||
|  |             if not flow or flow.designation != FlowDesignation.AUTHENTICATION: | ||||||
|  |                 LOGGER.debug("Not buffering request, no flow or flow not for authentication") | ||||||
|  |                 return super().handle_no_permission() | ||||||
|  |         if not plan and authenticating is None: | ||||||
|  |             LOGGER.debug("Not buffering request, no flow plan active") | ||||||
|  |             return super().handle_no_permission() | ||||||
|  |         if self.request.GET.get(QS_SKIP_BUFFER): | ||||||
|  |             LOGGER.debug("Not buffering request, explicit skip") | ||||||
|  |             return super().handle_no_permission() | ||||||
|  |         buffer_id = str(uuid4()) | ||||||
|  |         LOGGER.debug("Buffering access request", bf_id=buffer_id) | ||||||
|  |         self.request.session[SESSION_KEY_BUFFER % buffer_id] = { | ||||||
|  |             "body": self.request.POST, | ||||||
|  |             "url": self.request.build_absolute_uri(self.request.get_full_path()), | ||||||
|  |             "method": self.request.method.lower(), | ||||||
|  |         } | ||||||
|  |         return redirect( | ||||||
|  |             url_with_qs(reverse("authentik_policies:buffer"), **{QS_BUFFER_ID: buffer_id}) | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |     def dispatch(self, request, *args, **kwargs): | ||||||
|  |         response = super().dispatch(request, *args, **kwargs) | ||||||
|  |         if QS_BUFFER_ID in self.request.GET: | ||||||
|  |             self.request.session.pop(SESSION_KEY_BUFFER % self.request.GET[QS_BUFFER_ID], None) | ||||||
|  |         return response | ||||||
|  | |||||||
| @ -30,7 +30,7 @@ from authentik.flows.stage import StageView | |||||||
| from authentik.lib.utils.time import timedelta_from_string | from authentik.lib.utils.time import timedelta_from_string | ||||||
| from authentik.lib.views import bad_request_message | from authentik.lib.views import bad_request_message | ||||||
| from authentik.policies.types import PolicyRequest | from authentik.policies.types import PolicyRequest | ||||||
| from authentik.policies.views import PolicyAccessView, RequestValidationError | from authentik.policies.views import BufferedPolicyAccessView, RequestValidationError | ||||||
| from authentik.providers.oauth2.constants import ( | from authentik.providers.oauth2.constants import ( | ||||||
|     PKCE_METHOD_PLAIN, |     PKCE_METHOD_PLAIN, | ||||||
|     PKCE_METHOD_S256, |     PKCE_METHOD_S256, | ||||||
| @ -326,7 +326,7 @@ class OAuthAuthorizationParams: | |||||||
|         return code |         return code | ||||||
|  |  | ||||||
|  |  | ||||||
| class AuthorizationFlowInitView(PolicyAccessView): | class AuthorizationFlowInitView(BufferedPolicyAccessView): | ||||||
|     """OAuth2 Flow initializer, checks access to application and starts flow""" |     """OAuth2 Flow initializer, checks access to application and starts flow""" | ||||||
|  |  | ||||||
|     params: OAuthAuthorizationParams |     params: OAuthAuthorizationParams | ||||||
|  | |||||||
| @ -1,234 +0,0 @@ | |||||||
| from dataclasses import asdict, dataclass, field |  | ||||||
| from typing import TYPE_CHECKING |  | ||||||
| from urllib.parse import urlparse |  | ||||||
|  |  | ||||||
| from dacite.core import from_dict |  | ||||||
| from kubernetes.client import ApiextensionsV1Api, CustomObjectsApi, V1ObjectMeta |  | ||||||
|  |  | ||||||
| from authentik.outposts.controllers.base import FIELD_MANAGER |  | ||||||
| from authentik.outposts.controllers.k8s.base import KubernetesObjectReconciler |  | ||||||
| from authentik.outposts.controllers.k8s.triggers import NeedsUpdate |  | ||||||
| from authentik.outposts.controllers.kubernetes import KubernetesController |  | ||||||
| from authentik.providers.proxy.models import ProxyMode, ProxyProvider |  | ||||||
|  |  | ||||||
| if TYPE_CHECKING: |  | ||||||
|     from authentik.outposts.controllers.kubernetes import KubernetesController |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @dataclass(slots=True) |  | ||||||
| class RouteBackendRef: |  | ||||||
|     name: str |  | ||||||
|     port: int |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @dataclass(slots=True) |  | ||||||
| class RouteSpecParentRefs: |  | ||||||
|     name: str |  | ||||||
|     sectionName: str | None = None |  | ||||||
|     port: int | None = None |  | ||||||
|     namespace: str | None = None |  | ||||||
|     kind: str = "Gateway" |  | ||||||
|     group: str = "gateway.networking.k8s.io" |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @dataclass(slots=True) |  | ||||||
| class HTTPRouteSpecRuleMatchPath: |  | ||||||
|     type: str |  | ||||||
|     value: str |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @dataclass(slots=True) |  | ||||||
| class HTTPRouteSpecRuleMatchHeader: |  | ||||||
|     name: str |  | ||||||
|     value: str |  | ||||||
|     type: str = "Exact" |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @dataclass(slots=True) |  | ||||||
| class HTTPRouteSpecRuleMatch: |  | ||||||
|     path: HTTPRouteSpecRuleMatchPath |  | ||||||
|     headers: list[HTTPRouteSpecRuleMatchHeader] |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @dataclass(slots=True) |  | ||||||
| class HTTPRouteSpecRule: |  | ||||||
|     backendRefs: list[RouteBackendRef] |  | ||||||
|     matches: list[HTTPRouteSpecRuleMatch] |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @dataclass(slots=True) |  | ||||||
| class HTTPRouteSpec: |  | ||||||
|     parentRefs: list[RouteSpecParentRefs] |  | ||||||
|     hostnames: list[str] |  | ||||||
|     rules: list[HTTPRouteSpecRule] |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @dataclass(slots=True) |  | ||||||
| class HTTPRouteMetadata: |  | ||||||
|     name: str |  | ||||||
|     namespace: str |  | ||||||
|     annotations: dict = field(default_factory=dict) |  | ||||||
|     labels: dict = field(default_factory=dict) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| @dataclass(slots=True) |  | ||||||
| class HTTPRoute: |  | ||||||
|     apiVersion: str |  | ||||||
|     kind: str |  | ||||||
|     metadata: HTTPRouteMetadata |  | ||||||
|     spec: HTTPRouteSpec |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class HTTPRouteReconciler(KubernetesObjectReconciler): |  | ||||||
|     """Kubernetes Gateway API HTTPRoute Reconciler""" |  | ||||||
|  |  | ||||||
|     def __init__(self, controller: "KubernetesController") -> None: |  | ||||||
|         super().__init__(controller) |  | ||||||
|         self.api_ex = ApiextensionsV1Api(controller.client) |  | ||||||
|         self.api = CustomObjectsApi(controller.client) |  | ||||||
|         self.crd_group = "gateway.networking.k8s.io" |  | ||||||
|         self.crd_version = "v1" |  | ||||||
|         self.crd_plural = "httproutes" |  | ||||||
|  |  | ||||||
|     @staticmethod |  | ||||||
|     def reconciler_name() -> str: |  | ||||||
|         return "httproute" |  | ||||||
|  |  | ||||||
|     @property |  | ||||||
|     def noop(self) -> bool: |  | ||||||
|         if not self.crd_exists(): |  | ||||||
|             self.logger.debug("CRD doesn't exist") |  | ||||||
|             return True |  | ||||||
|         if not self.controller.outpost.config.kubernetes_httproute_parent_refs: |  | ||||||
|             self.logger.debug("HTTPRoute parentRefs not set.") |  | ||||||
|             return True |  | ||||||
|         return False |  | ||||||
|  |  | ||||||
|     def crd_exists(self) -> bool: |  | ||||||
|         """Check if the Gateway API resources exists""" |  | ||||||
|         return bool( |  | ||||||
|             len( |  | ||||||
|                 self.api_ex.list_custom_resource_definition( |  | ||||||
|                     field_selector=f"metadata.name={self.crd_plural}.{self.crd_group}" |  | ||||||
|                 ).items |  | ||||||
|             ) |  | ||||||
|         ) |  | ||||||
|  |  | ||||||
|     def reconcile(self, current: HTTPRoute, reference: HTTPRoute): |  | ||||||
|         super().reconcile(current, reference) |  | ||||||
|         if current.metadata.annotations != reference.metadata.annotations: |  | ||||||
|             raise NeedsUpdate() |  | ||||||
|         if current.spec.parentRefs != reference.spec.parentRefs: |  | ||||||
|             raise NeedsUpdate() |  | ||||||
|         if current.spec.hostnames != reference.spec.hostnames: |  | ||||||
|             raise NeedsUpdate() |  | ||||||
|         if current.spec.rules != reference.spec.rules: |  | ||||||
|             raise NeedsUpdate() |  | ||||||
|  |  | ||||||
|     def get_object_meta(self, **kwargs) -> V1ObjectMeta: |  | ||||||
|         return super().get_object_meta( |  | ||||||
|             **kwargs, |  | ||||||
|         ) |  | ||||||
|  |  | ||||||
|     def get_reference_object(self) -> HTTPRoute: |  | ||||||
|         hostnames = [] |  | ||||||
|         rules = [] |  | ||||||
|  |  | ||||||
|         for proxy_provider in ProxyProvider.objects.filter(outpost__in=[self.controller.outpost]): |  | ||||||
|             proxy_provider: ProxyProvider |  | ||||||
|             external_host_name = urlparse(proxy_provider.external_host) |  | ||||||
|             if proxy_provider.mode in [ProxyMode.FORWARD_SINGLE, ProxyMode.FORWARD_DOMAIN]: |  | ||||||
|                 rule = HTTPRouteSpecRule( |  | ||||||
|                     backendRefs=[RouteBackendRef(name=self.name, port=9000)], |  | ||||||
|                     matches=[ |  | ||||||
|                         HTTPRouteSpecRuleMatch( |  | ||||||
|                             headers=[ |  | ||||||
|                                 HTTPRouteSpecRuleMatchHeader( |  | ||||||
|                                     name="Host", |  | ||||||
|                                     value=external_host_name.hostname, |  | ||||||
|                                 ) |  | ||||||
|                             ], |  | ||||||
|                             path=HTTPRouteSpecRuleMatchPath( |  | ||||||
|                                 type="PathPrefix", value="/outpost.goauthentik.io" |  | ||||||
|                             ), |  | ||||||
|                         ) |  | ||||||
|                     ], |  | ||||||
|                 ) |  | ||||||
|             else: |  | ||||||
|                 rule = HTTPRouteSpecRule( |  | ||||||
|                     backendRefs=[RouteBackendRef(name=self.name, port=9000)], |  | ||||||
|                     matches=[ |  | ||||||
|                         HTTPRouteSpecRuleMatch( |  | ||||||
|                             headers=[ |  | ||||||
|                                 HTTPRouteSpecRuleMatchHeader( |  | ||||||
|                                     name="Host", |  | ||||||
|                                     value=external_host_name.hostname, |  | ||||||
|                                 ) |  | ||||||
|                             ], |  | ||||||
|                             path=HTTPRouteSpecRuleMatchPath(type="PathPrefix", value="/"), |  | ||||||
|                         ) |  | ||||||
|                     ], |  | ||||||
|                 ) |  | ||||||
|             hostnames.append(external_host_name.hostname) |  | ||||||
|             rules.append(rule) |  | ||||||
|  |  | ||||||
|         return HTTPRoute( |  | ||||||
|             apiVersion=f"{self.crd_group}/{self.crd_version}", |  | ||||||
|             kind="HTTPRoute", |  | ||||||
|             metadata=HTTPRouteMetadata( |  | ||||||
|                 name=self.name, |  | ||||||
|                 namespace=self.namespace, |  | ||||||
|                 annotations=self.controller.outpost.config.kubernetes_httproute_annotations, |  | ||||||
|                 labels=self.get_object_meta().labels, |  | ||||||
|             ), |  | ||||||
|             spec=HTTPRouteSpec( |  | ||||||
|                 parentRefs=[ |  | ||||||
|                     from_dict(RouteSpecParentRefs, spec) |  | ||||||
|                     for spec in self.controller.outpost.config.kubernetes_httproute_parent_refs |  | ||||||
|                 ], |  | ||||||
|                 hostnames=hostnames, |  | ||||||
|                 rules=rules, |  | ||||||
|             ), |  | ||||||
|         ) |  | ||||||
|  |  | ||||||
|     def create(self, reference: HTTPRoute): |  | ||||||
|         return self.api.create_namespaced_custom_object( |  | ||||||
|             group=self.crd_group, |  | ||||||
|             version=self.crd_version, |  | ||||||
|             plural=self.crd_plural, |  | ||||||
|             namespace=self.namespace, |  | ||||||
|             body=asdict(reference), |  | ||||||
|             field_manager=FIELD_MANAGER, |  | ||||||
|         ) |  | ||||||
|  |  | ||||||
|     def delete(self, reference: HTTPRoute): |  | ||||||
|         return self.api.delete_namespaced_custom_object( |  | ||||||
|             group=self.crd_group, |  | ||||||
|             version=self.crd_version, |  | ||||||
|             plural=self.crd_plural, |  | ||||||
|             namespace=self.namespace, |  | ||||||
|             name=self.name, |  | ||||||
|         ) |  | ||||||
|  |  | ||||||
|     def retrieve(self) -> HTTPRoute: |  | ||||||
|         return from_dict( |  | ||||||
|             HTTPRoute, |  | ||||||
|             self.api.get_namespaced_custom_object( |  | ||||||
|                 group=self.crd_group, |  | ||||||
|                 version=self.crd_version, |  | ||||||
|                 plural=self.crd_plural, |  | ||||||
|                 namespace=self.namespace, |  | ||||||
|                 name=self.name, |  | ||||||
|             ), |  | ||||||
|         ) |  | ||||||
|  |  | ||||||
|     def update(self, current: HTTPRoute, reference: HTTPRoute): |  | ||||||
|         return self.api.patch_namespaced_custom_object( |  | ||||||
|             group=self.crd_group, |  | ||||||
|             version=self.crd_version, |  | ||||||
|             plural=self.crd_plural, |  | ||||||
|             namespace=self.namespace, |  | ||||||
|             name=self.name, |  | ||||||
|             body=asdict(reference), |  | ||||||
|             field_manager=FIELD_MANAGER, |  | ||||||
|         ) |  | ||||||
| @ -3,7 +3,6 @@ | |||||||
| from authentik.outposts.controllers.base import DeploymentPort | from authentik.outposts.controllers.base import DeploymentPort | ||||||
| from authentik.outposts.controllers.kubernetes import KubernetesController | from authentik.outposts.controllers.kubernetes import KubernetesController | ||||||
| from authentik.outposts.models import KubernetesServiceConnection, Outpost | from authentik.outposts.models import KubernetesServiceConnection, Outpost | ||||||
| from authentik.providers.proxy.controllers.k8s.httproute import HTTPRouteReconciler |  | ||||||
| from authentik.providers.proxy.controllers.k8s.ingress import IngressReconciler | from authentik.providers.proxy.controllers.k8s.ingress import IngressReconciler | ||||||
| from authentik.providers.proxy.controllers.k8s.traefik import TraefikMiddlewareReconciler | from authentik.providers.proxy.controllers.k8s.traefik import TraefikMiddlewareReconciler | ||||||
|  |  | ||||||
| @ -19,10 +18,8 @@ class ProxyKubernetesController(KubernetesController): | |||||||
|             DeploymentPort(9443, "https", "tcp"), |             DeploymentPort(9443, "https", "tcp"), | ||||||
|         ] |         ] | ||||||
|         self.reconcilers[IngressReconciler.reconciler_name()] = IngressReconciler |         self.reconcilers[IngressReconciler.reconciler_name()] = IngressReconciler | ||||||
|         self.reconcilers[HTTPRouteReconciler.reconciler_name()] = HTTPRouteReconciler |  | ||||||
|         self.reconcilers[TraefikMiddlewareReconciler.reconciler_name()] = ( |         self.reconcilers[TraefikMiddlewareReconciler.reconciler_name()] = ( | ||||||
|             TraefikMiddlewareReconciler |             TraefikMiddlewareReconciler | ||||||
|         ) |         ) | ||||||
|         self.reconcile_order.append(IngressReconciler.reconciler_name()) |         self.reconcile_order.append(IngressReconciler.reconciler_name()) | ||||||
|         self.reconcile_order.append(HTTPRouteReconciler.reconciler_name()) |  | ||||||
|         self.reconcile_order.append(TraefikMiddlewareReconciler.reconciler_name()) |         self.reconcile_order.append(TraefikMiddlewareReconciler.reconciler_name()) | ||||||
|  | |||||||
| @ -18,11 +18,11 @@ from authentik.flows.planner import PLAN_CONTEXT_APPLICATION, FlowPlanner | |||||||
| from authentik.flows.stage import RedirectStage | from authentik.flows.stage import RedirectStage | ||||||
| from authentik.lib.utils.time import timedelta_from_string | from authentik.lib.utils.time import timedelta_from_string | ||||||
| from authentik.policies.engine import PolicyEngine | from authentik.policies.engine import PolicyEngine | ||||||
| from authentik.policies.views import PolicyAccessView | from authentik.policies.views import BufferedPolicyAccessView | ||||||
| from authentik.providers.rac.models import ConnectionToken, Endpoint, RACProvider | from authentik.providers.rac.models import ConnectionToken, Endpoint, RACProvider | ||||||
|  |  | ||||||
|  |  | ||||||
| class RACStartView(PolicyAccessView): | class RACStartView(BufferedPolicyAccessView): | ||||||
|     """Start a RAC connection by checking access and creating a connection token""" |     """Start a RAC connection by checking access and creating a connection token""" | ||||||
|  |  | ||||||
|     endpoint: Endpoint |     endpoint: Endpoint | ||||||
|  | |||||||
| @ -15,7 +15,7 @@ from authentik.flows.models import in_memory_stage | |||||||
| from authentik.flows.planner import PLAN_CONTEXT_APPLICATION, PLAN_CONTEXT_SSO, FlowPlanner | from authentik.flows.planner import PLAN_CONTEXT_APPLICATION, PLAN_CONTEXT_SSO, FlowPlanner | ||||||
| from authentik.flows.views.executor import SESSION_KEY_POST | from authentik.flows.views.executor import SESSION_KEY_POST | ||||||
| from authentik.lib.views import bad_request_message | from authentik.lib.views import bad_request_message | ||||||
| from authentik.policies.views import PolicyAccessView | from authentik.policies.views import BufferedPolicyAccessView | ||||||
| from authentik.providers.saml.exceptions import CannotHandleAssertion | from authentik.providers.saml.exceptions import CannotHandleAssertion | ||||||
| from authentik.providers.saml.models import SAMLBindings, SAMLProvider | from authentik.providers.saml.models import SAMLBindings, SAMLProvider | ||||||
| from authentik.providers.saml.processors.authn_request_parser import AuthNRequestParser | from authentik.providers.saml.processors.authn_request_parser import AuthNRequestParser | ||||||
| @ -35,7 +35,7 @@ from authentik.stages.consent.stage import ( | |||||||
| LOGGER = get_logger() | LOGGER = get_logger() | ||||||
|  |  | ||||||
|  |  | ||||||
| class SAMLSSOView(PolicyAccessView): | class SAMLSSOView(BufferedPolicyAccessView): | ||||||
|     """SAML SSO Base View, which plans a flow and injects our final stage. |     """SAML SSO Base View, which plans a flow and injects our final stage. | ||||||
|     Calls get/post handler.""" |     Calls get/post handler.""" | ||||||
|  |  | ||||||
| @ -83,7 +83,7 @@ class SAMLSSOView(PolicyAccessView): | |||||||
|  |  | ||||||
|     def post(self, request: HttpRequest, application_slug: str) -> HttpResponse: |     def post(self, request: HttpRequest, application_slug: str) -> HttpResponse: | ||||||
|         """GET and POST use the same handler, but we can't |         """GET and POST use the same handler, but we can't | ||||||
|         override .dispatch easily because PolicyAccessView's dispatch""" |         override .dispatch easily because BufferedPolicyAccessView's dispatch""" | ||||||
|         return self.get(request, application_slug) |         return self.get(request, application_slug) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | |||||||
| @ -99,7 +99,6 @@ 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", | ||||||
|  | |||||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| @ -171,8 +171,7 @@ def username_field_validator_factory() -> Callable[[PromptChallengeResponse, str | |||||||
|  |  | ||||||
|  |  | ||||||
| def password_single_validator_factory() -> Callable[[PromptChallengeResponse, str], Any]: | def password_single_validator_factory() -> Callable[[PromptChallengeResponse, str], Any]: | ||||||
|     """Return a `clean_` method for `field`. Clean method checks if the password meets configured |     """Return a `clean_` method for `field`. Clean method checks if username is taken already.""" | ||||||
|     PasswordPolicy.""" |  | ||||||
|  |  | ||||||
|     def password_single_clean(self: PromptChallengeResponse, value: str) -> Any: |     def password_single_clean(self: PromptChallengeResponse, value: str) -> Any: | ||||||
|         """Send password validation signals for e.g. LDAP Source""" |         """Send password validation signals for e.g. LDAP Source""" | ||||||
|  | |||||||
| @ -4,13 +4,7 @@ from unittest.mock import patch | |||||||
|  |  | ||||||
| from django.urls import reverse | from django.urls import reverse | ||||||
|  |  | ||||||
| from authentik.core.models import ( | from authentik.core.models import USER_ATTRIBUTE_SOURCES, Group, Source, User, UserSourceConnection | ||||||
|     USER_ATTRIBUTE_SOURCES, |  | ||||||
|     Group, |  | ||||||
|     Source, |  | ||||||
|     User, |  | ||||||
|     UserSourceConnection, |  | ||||||
| ) |  | ||||||
| from authentik.core.sources.stage import PLAN_CONTEXT_SOURCES_CONNECTION | from authentik.core.sources.stage import PLAN_CONTEXT_SOURCES_CONNECTION | ||||||
| from authentik.core.tests.utils import create_test_admin_user, create_test_flow | from authentik.core.tests.utils import create_test_admin_user, create_test_flow | ||||||
| from authentik.events.models import Event, EventAction | from authentik.events.models import Event, EventAction | ||||||
|  | |||||||
| @ -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.4.0 Blueprint schema", |     "title": "authentik 2025.2.4 Blueprint schema", | ||||||
|     "required": [ |     "required": [ | ||||||
|         "version", |         "version", | ||||||
|         "entries" |         "entries" | ||||||
| @ -3641,46 +3641,6 @@ | |||||||
|                             } |                             } | ||||||
|                         } |                         } | ||||||
|                     }, |                     }, | ||||||
|                     { |  | ||||||
|                         "type": "object", |  | ||||||
|                         "required": [ |  | ||||||
|                             "model", |  | ||||||
|                             "identifiers" |  | ||||||
|                         ], |  | ||||||
|                         "properties": { |  | ||||||
|                             "model": { |  | ||||||
|                                 "const": "authentik_policies_unique_password.uniquepasswordpolicy" |  | ||||||
|                             }, |  | ||||||
|                             "id": { |  | ||||||
|                                 "type": "string" |  | ||||||
|                             }, |  | ||||||
|                             "state": { |  | ||||||
|                                 "type": "string", |  | ||||||
|                                 "enum": [ |  | ||||||
|                                     "absent", |  | ||||||
|                                     "present", |  | ||||||
|                                     "created", |  | ||||||
|                                     "must_created" |  | ||||||
|                                 ], |  | ||||||
|                                 "default": "present" |  | ||||||
|                             }, |  | ||||||
|                             "conditions": { |  | ||||||
|                                 "type": "array", |  | ||||||
|                                 "items": { |  | ||||||
|                                     "type": "boolean" |  | ||||||
|                                 } |  | ||||||
|                             }, |  | ||||||
|                             "permissions": { |  | ||||||
|                                 "$ref": "#/$defs/model_authentik_policies_unique_password.uniquepasswordpolicy_permissions" |  | ||||||
|                             }, |  | ||||||
|                             "attrs": { |  | ||||||
|                                 "$ref": "#/$defs/model_authentik_policies_unique_password.uniquepasswordpolicy" |  | ||||||
|                             }, |  | ||||||
|                             "identifiers": { |  | ||||||
|                                 "$ref": "#/$defs/model_authentik_policies_unique_password.uniquepasswordpolicy" |  | ||||||
|                             } |  | ||||||
|                         } |  | ||||||
|                     }, |  | ||||||
|                     { |                     { | ||||||
|                         "type": "object", |                         "type": "object", | ||||||
|                         "required": [ |                         "required": [ | ||||||
| @ -4862,7 +4822,6 @@ | |||||||
|                         "authentik.core", |                         "authentik.core", | ||||||
|                         "authentik.enterprise", |                         "authentik.enterprise", | ||||||
|                         "authentik.enterprise.audit", |                         "authentik.enterprise.audit", | ||||||
|                         "authentik.enterprise.policies.unique_password", |  | ||||||
|                         "authentik.enterprise.providers.google_workspace", |                         "authentik.enterprise.providers.google_workspace", | ||||||
|                         "authentik.enterprise.providers.microsoft_entra", |                         "authentik.enterprise.providers.microsoft_entra", | ||||||
|                         "authentik.enterprise.providers.ssf", |                         "authentik.enterprise.providers.ssf", | ||||||
| @ -4970,7 +4929,6 @@ | |||||||
|                         "authentik_core.applicationentitlement", |                         "authentik_core.applicationentitlement", | ||||||
|                         "authentik_core.token", |                         "authentik_core.token", | ||||||
|                         "authentik_enterprise.license", |                         "authentik_enterprise.license", | ||||||
|                         "authentik_policies_unique_password.uniquepasswordpolicy", |  | ||||||
|                         "authentik_providers_google_workspace.googleworkspaceprovider", |                         "authentik_providers_google_workspace.googleworkspaceprovider", | ||||||
|                         "authentik_providers_google_workspace.googleworkspaceprovidermapping", |                         "authentik_providers_google_workspace.googleworkspaceprovidermapping", | ||||||
|                         "authentik_providers_microsoft_entra.microsoftentraprovider", |                         "authentik_providers_microsoft_entra.microsoftentraprovider", | ||||||
| @ -7126,14 +7084,6 @@ | |||||||
|                             "authentik_policies_reputation.delete_reputationpolicy", |                             "authentik_policies_reputation.delete_reputationpolicy", | ||||||
|                             "authentik_policies_reputation.view_reputation", |                             "authentik_policies_reputation.view_reputation", | ||||||
|                             "authentik_policies_reputation.view_reputationpolicy", |                             "authentik_policies_reputation.view_reputationpolicy", | ||||||
|                             "authentik_policies_unique_password.add_uniquepasswordpolicy", |  | ||||||
|                             "authentik_policies_unique_password.add_userpasswordhistory", |  | ||||||
|                             "authentik_policies_unique_password.change_uniquepasswordpolicy", |  | ||||||
|                             "authentik_policies_unique_password.change_userpasswordhistory", |  | ||||||
|                             "authentik_policies_unique_password.delete_uniquepasswordpolicy", |  | ||||||
|                             "authentik_policies_unique_password.delete_userpasswordhistory", |  | ||||||
|                             "authentik_policies_unique_password.view_uniquepasswordpolicy", |  | ||||||
|                             "authentik_policies_unique_password.view_userpasswordhistory", |  | ||||||
|                             "authentik_providers_google_workspace.add_googleworkspaceprovider", |                             "authentik_providers_google_workspace.add_googleworkspaceprovider", | ||||||
|                             "authentik_providers_google_workspace.add_googleworkspaceprovidergroup", |                             "authentik_providers_google_workspace.add_googleworkspaceprovidergroup", | ||||||
|                             "authentik_providers_google_workspace.add_googleworkspaceprovidermapping", |                             "authentik_providers_google_workspace.add_googleworkspaceprovidermapping", | ||||||
| @ -13834,14 +13784,6 @@ | |||||||
|                             "authentik_policies_reputation.delete_reputationpolicy", |                             "authentik_policies_reputation.delete_reputationpolicy", | ||||||
|                             "authentik_policies_reputation.view_reputation", |                             "authentik_policies_reputation.view_reputation", | ||||||
|                             "authentik_policies_reputation.view_reputationpolicy", |                             "authentik_policies_reputation.view_reputationpolicy", | ||||||
|                             "authentik_policies_unique_password.add_uniquepasswordpolicy", |  | ||||||
|                             "authentik_policies_unique_password.add_userpasswordhistory", |  | ||||||
|                             "authentik_policies_unique_password.change_uniquepasswordpolicy", |  | ||||||
|                             "authentik_policies_unique_password.change_userpasswordhistory", |  | ||||||
|                             "authentik_policies_unique_password.delete_uniquepasswordpolicy", |  | ||||||
|                             "authentik_policies_unique_password.delete_userpasswordhistory", |  | ||||||
|                             "authentik_policies_unique_password.view_uniquepasswordpolicy", |  | ||||||
|                             "authentik_policies_unique_password.view_userpasswordhistory", |  | ||||||
|                             "authentik_providers_google_workspace.add_googleworkspaceprovider", |                             "authentik_providers_google_workspace.add_googleworkspaceprovider", | ||||||
|                             "authentik_providers_google_workspace.add_googleworkspaceprovidergroup", |                             "authentik_providers_google_workspace.add_googleworkspaceprovidergroup", | ||||||
|                             "authentik_providers_google_workspace.add_googleworkspaceprovidermapping", |                             "authentik_providers_google_workspace.add_googleworkspaceprovidermapping", | ||||||
| @ -14526,61 +14468,6 @@ | |||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         }, |         }, | ||||||
|         "model_authentik_policies_unique_password.uniquepasswordpolicy": { |  | ||||||
|             "type": "object", |  | ||||||
|             "properties": { |  | ||||||
|                 "name": { |  | ||||||
|                     "type": "string", |  | ||||||
|                     "minLength": 1, |  | ||||||
|                     "title": "Name" |  | ||||||
|                 }, |  | ||||||
|                 "execution_logging": { |  | ||||||
|                     "type": "boolean", |  | ||||||
|                     "title": "Execution logging", |  | ||||||
|                     "description": "When this option is enabled, all executions of this policy will be logged. By default, only execution errors are logged." |  | ||||||
|                 }, |  | ||||||
|                 "password_field": { |  | ||||||
|                     "type": "string", |  | ||||||
|                     "minLength": 1, |  | ||||||
|                     "title": "Password field", |  | ||||||
|                     "description": "Field key to check, field keys defined in Prompt stages are available." |  | ||||||
|                 }, |  | ||||||
|                 "num_historical_passwords": { |  | ||||||
|                     "type": "integer", |  | ||||||
|                     "minimum": 0, |  | ||||||
|                     "maximum": 2147483647, |  | ||||||
|                     "title": "Num historical passwords", |  | ||||||
|                     "description": "Number of passwords to check against." |  | ||||||
|                 } |  | ||||||
|             }, |  | ||||||
|             "required": [] |  | ||||||
|         }, |  | ||||||
|         "model_authentik_policies_unique_password.uniquepasswordpolicy_permissions": { |  | ||||||
|             "type": "array", |  | ||||||
|             "items": { |  | ||||||
|                 "type": "object", |  | ||||||
|                 "required": [ |  | ||||||
|                     "permission" |  | ||||||
|                 ], |  | ||||||
|                 "properties": { |  | ||||||
|                     "permission": { |  | ||||||
|                         "type": "string", |  | ||||||
|                         "enum": [ |  | ||||||
|                             "add_uniquepasswordpolicy", |  | ||||||
|                             "change_uniquepasswordpolicy", |  | ||||||
|                             "delete_uniquepasswordpolicy", |  | ||||||
|                             "view_uniquepasswordpolicy" |  | ||||||
|                         ] |  | ||||||
|                     }, |  | ||||||
|                     "user": { |  | ||||||
|                         "type": "integer" |  | ||||||
|                     }, |  | ||||||
|                     "role": { |  | ||||||
|                         "type": "string" |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         }, |  | ||||||
|         "model_authentik_providers_google_workspace.googleworkspaceprovider": { |         "model_authentik_providers_google_workspace.googleworkspaceprovider": { | ||||||
|             "type": "object", |             "type": "object", | ||||||
|             "properties": { |             "properties": { | ||||||
|  | |||||||
| @ -31,7 +31,7 @@ services: | |||||||
|     volumes: |     volumes: | ||||||
|       - redis:/data |       - redis:/data | ||||||
|   server: |   server: | ||||||
|     image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.4.0} |     image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.2.4} | ||||||
|     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.4.0} |     image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.2.4} | ||||||
|     restart: unless-stopped |     restart: unless-stopped | ||||||
|     command: worker |     command: worker | ||||||
|     environment: |     environment: | ||||||
|  | |||||||
							
								
								
									
										8
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								go.mod
									
									
									
									
									
								
							| @ -7,7 +7,7 @@ require ( | |||||||
| 	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.32.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.10 | ||||||
| 	github.com/go-openapi/runtime v0.28.0 | 	github.com/go-openapi/runtime v0.28.0 | ||||||
| 	github.com/golang-jwt/jwt/v5 v5.2.2 | 	github.com/golang-jwt/jwt/v5 v5.2.2 | ||||||
| 	github.com/google/uuid v1.6.0 | 	github.com/google/uuid v1.6.0 | ||||||
| @ -21,13 +21,13 @@ require ( | |||||||
| 	github.com/nmcclain/asn1-ber v0.0.0-20170104154839-2661553a0484 | 	github.com/nmcclain/asn1-ber v0.0.0-20170104154839-2661553a0484 | ||||||
| 	github.com/pires/go-proxyproto v0.8.0 | 	github.com/pires/go-proxyproto v0.8.0 | ||||||
| 	github.com/prometheus/client_golang v1.22.0 | 	github.com/prometheus/client_golang v1.22.0 | ||||||
| 	github.com/redis/go-redis/v9 v9.8.0 | 	github.com/redis/go-redis/v9 v9.7.3 | ||||||
| 	github.com/sethvargo/go-envconfig v1.2.0 | 	github.com/sethvargo/go-envconfig v1.2.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.2025040.1 | 	goauthentik.io/api/v3 v3.2025024.7 | ||||||
| 	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.29.0 | ||||||
| 	golang.org/x/sync v0.13.0 | 	golang.org/x/sync v0.13.0 | ||||||
| @ -43,7 +43,7 @@ require ( | |||||||
| 	github.com/davecgh/go-spew v1.1.1 // indirect | 	github.com/davecgh/go-spew v1.1.1 // indirect | ||||||
| 	github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect | 	github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect | ||||||
| 	github.com/felixge/httpsnoop v1.0.3 // indirect | 	github.com/felixge/httpsnoop v1.0.3 // indirect | ||||||
| 	github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // indirect | 	github.com/go-asn1-ber/asn1-ber v1.5.7 // indirect | ||||||
| 	github.com/go-http-utils/fresh v0.0.0-20161124030543-7231e26a4b27 // indirect | 	github.com/go-http-utils/fresh v0.0.0-20161124030543-7231e26a4b27 // indirect | ||||||
| 	github.com/go-http-utils/headers v0.0.0-20181008091004-fed159eddc2a // indirect | 	github.com/go-http-utils/headers v0.0.0-20181008091004-fed159eddc2a // indirect | ||||||
| 	github.com/go-jose/go-jose/v4 v4.0.5 // indirect | 	github.com/go-jose/go-jose/v4 v4.0.5 // indirect | ||||||
|  | |||||||
							
								
								
									
										86
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										86
									
								
								go.sum
									
									
									
									
									
								
							| @ -71,8 +71,8 @@ github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBd | |||||||
| 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.32.0 h1:YKs+//QmwE3DcYtfKRH8/KyOOF/I6Qnx7qYGNHCGmCY= | ||||||
| github.com/getsentry/sentry-go v0.32.0/go.mod h1:CYNcMMz73YigoHljQRG+qPF+eMq8gG72XcGN/p71BAY= | github.com/getsentry/sentry-go v0.32.0/go.mod h1:CYNcMMz73YigoHljQRG+qPF+eMq8gG72XcGN/p71BAY= | ||||||
| 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.7 h1:DTX+lbVTWaTw1hQ+PbZPlnDZPEIs0SS/GCZAl535dDk= | ||||||
| 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.7/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= | ||||||
| github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= | github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= | ||||||
| github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= | github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= | ||||||
| @ -86,8 +86,8 @@ github.com/go-http-utils/headers v0.0.0-20181008091004-fed159eddc2a h1:v6zMvHuY9 | |||||||
| github.com/go-http-utils/headers v0.0.0-20181008091004-fed159eddc2a/go.mod h1:I79BieaU4fxrw4LMXby6q5OS9XnoR9UIKLOzDFjUmuw= | github.com/go-http-utils/headers v0.0.0-20181008091004-fed159eddc2a/go.mod h1:I79BieaU4fxrw4LMXby6q5OS9XnoR9UIKLOzDFjUmuw= | ||||||
| github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE= | github.com/go-jose/go-jose/v4 v4.0.5 h1:M6T8+mKZl/+fNNuFHvGIzDz7BTLQPIounk/b9dw3AaE= | ||||||
| github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA= | github.com/go-jose/go-jose/v4 v4.0.5/go.mod h1:s3P1lRrkT8igV8D9OjyL4WRyHvjB6a4JSllnOrmmBOA= | ||||||
| github.com/go-ldap/ldap/v3 v3.4.11 h1:4k0Yxweg+a3OyBLjdYn5OKglv18JNvfDykSoI8bW0gU= | github.com/go-ldap/ldap/v3 v3.4.10 h1:ot/iwPOhfpNVgB1o+AVXljizWZ9JTp7YF5oeyONmcJU= | ||||||
| github.com/go-ldap/ldap/v3 v3.4.11/go.mod h1:bY7t0FLK8OAVpp/vV6sSlpz3EQDGcQwc8pF0ujLgKvM= | github.com/go-ldap/ldap/v3 v3.4.10/go.mod h1:JXh4Uxgi40P6E9rdsYqpUtbW46D9UTjJ9QSwGRznplY= | ||||||
| github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= | github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= | ||||||
| github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= | github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= | ||||||
| github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= | github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= | ||||||
| @ -148,6 +148,7 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ | |||||||
| github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | ||||||
| github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | ||||||
| github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | ||||||
|  | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= | ||||||
| github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= | github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= | ||||||
| github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= | github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= | ||||||
| github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= | github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= | ||||||
| @ -171,13 +172,16 @@ github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyE | |||||||
| github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w= | github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w= | ||||||
| github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= | github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= | ||||||
| github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= | github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= | ||||||
|  | github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= | ||||||
| github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA= | github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA= | ||||||
| github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= | github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo= | ||||||
|  | github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= | ||||||
| github.com/gorilla/sessions v1.4.0 h1:kpIYOp/oi6MG/p5PgxApU8srsSw9tuFbt46Lt7auzqQ= | github.com/gorilla/sessions v1.4.0 h1:kpIYOp/oi6MG/p5PgxApU8srsSw9tuFbt46Lt7auzqQ= | ||||||
| github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik= | github.com/gorilla/sessions v1.4.0/go.mod h1:FLWm50oby91+hl7p/wRxDth9bWSuk0qVL2emc7lT5ik= | ||||||
| github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= | github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= | ||||||
| github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= | github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= | ||||||
| github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= | github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= | ||||||
|  | github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= | ||||||
| github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= | github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= | ||||||
| github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= | github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= | ||||||
| github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= | github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= | ||||||
| @ -245,8 +249,8 @@ 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.8.0 h1:q3nRvjrlge/6UD7eTu/DSg2uYiU2mCL0G/uzBWqhicI= | github.com/redis/go-redis/v9 v9.7.3 h1:YpPyAayJV+XErNsatSElgRZZVCwXX9QzkKYNvO7x0wM= | ||||||
| github.com/redis/go-redis/v9 v9.8.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw= | github.com/redis/go-redis/v9 v9.7.3/go.mod h1:bGUrSggJ9X9GUmZpZNEOQKaANxSGgOEBRltRTZHSvrA= | ||||||
| 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= | ||||||
| @ -262,10 +266,15 @@ github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= | |||||||
| github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= | github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= | ||||||
| github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||||||
| github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||||||
|  | github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= | ||||||
|  | github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= | ||||||
| github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= | ||||||
| github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= | ||||||
| github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= | ||||||
| github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||||||
|  | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||||||
|  | github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= | ||||||
|  | github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= | ||||||
| github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= | github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= | ||||||
| github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= | github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= | ||||||
| github.com/wwt/guac v1.3.2 h1:sH6OFGa/1tBs7ieWBVlZe7t6F5JAOWBry/tqQL/Vup4= | github.com/wwt/guac v1.3.2 h1:sH6OFGa/1tBs7ieWBVlZe7t6F5JAOWBry/tqQL/Vup4= | ||||||
| @ -273,6 +282,7 @@ github.com/wwt/guac v1.3.2/go.mod h1:eKm+NrnK7A88l4UBEcYNpZQGMpZRryYKoz4D/0/n1C0 | |||||||
| github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | ||||||
| github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | ||||||
| github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | ||||||
|  | github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= | ||||||
| go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80= | go.mongodb.org/mongo-driver v1.14.0 h1:P98w8egYRjYe3XDjxhYJagTokP/H6HzlsnojRgZRd80= | ||||||
| go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= | go.mongodb.org/mongo-driver v1.14.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= | ||||||
| go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= | go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= | ||||||
| @ -290,14 +300,20 @@ 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.2025040.1 h1:rQEcMNpz84/LPX8LVFteOJuserrd4PnU4k1Iu/wWqhs= | goauthentik.io/api/v3 v3.2025024.7 h1:OOBuyLzv+l5rtvrOYzoDs6Hy9cIfkE5sewRqR5ThSRc= | ||||||
| goauthentik.io/api/v3 v3.2025040.1/go.mod h1:zz+mEZg8rY/7eEjkMGWJ2DnGqk+zqxuybGCGrR2O4Kw= | goauthentik.io/api/v3 v3.2025024.7/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= | ||||||
| golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | ||||||
| golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | ||||||
| golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | golang.org/x/crypto v0.0.0-20200709230013-948cd5f35899/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | ||||||
|  | golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= | ||||||
|  | golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= | ||||||
|  | golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= | ||||||
|  | golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= | ||||||
|  | golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= | ||||||
|  | golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= | ||||||
| golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= | golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= | ||||||
| golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= | golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= | ||||||
| golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= | ||||||
| @ -332,6 +348,11 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB | |||||||
| golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= | golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= | ||||||
| golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | ||||||
| golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | ||||||
|  | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= | ||||||
|  | golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= | ||||||
|  | golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= | ||||||
|  | golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= | ||||||
|  | golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= | ||||||
| golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||||||
| golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||||||
| golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | ||||||
| @ -358,8 +379,17 @@ 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.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= | ||||||
| golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= | golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= | ||||||
|  | golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= | ||||||
|  | golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= | ||||||
|  | golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= | ||||||
|  | golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= | ||||||
|  | golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= | ||||||
|  | golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= | ||||||
|  | golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= | ||||||
|  | golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c= | ||||||
|  | golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= | ||||||
| golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= | ||||||
| golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= | golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= | ||||||
| golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= | ||||||
| @ -376,6 +406,12 @@ 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.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||||
|  | golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||||
|  | golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= | ||||||
|  | golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= | ||||||
|  | golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= | ||||||
|  | golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= | ||||||
| golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= | golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= | ||||||
| golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= | golang.org/x/sync v0.13.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= | ||||||
| @ -404,14 +440,40 @@ golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7w | |||||||
| golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
| golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
|  | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||||
|  | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||||
|  | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||||
| golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||||
|  | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||||
|  | golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||||
|  | golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||||
|  | golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||||
|  | golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= | ||||||
|  | golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= | ||||||
|  | golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= | ||||||
| golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= | golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= | ||||||
| golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= | golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= | ||||||
|  | golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= | ||||||
|  | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= | ||||||
|  | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= | ||||||
|  | golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= | ||||||
|  | golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= | ||||||
|  | golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= | ||||||
|  | golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= | ||||||
|  | golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= | ||||||
|  | golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM= | ||||||
| golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||||
| golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | 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.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= | ||||||
|  | golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= | ||||||
|  | golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= | ||||||
|  | golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= | ||||||
|  | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= | ||||||
|  | golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= | ||||||
|  | golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= | ||||||
| golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= | golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= | ||||||
| golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= | golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= | ||||||
| golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= | ||||||
| @ -457,6 +519,10 @@ golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roY | |||||||
| golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= | golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= | ||||||
| golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= | golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= | ||||||
| golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= | golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= | ||||||
|  | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= | ||||||
|  | golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= | ||||||
|  | golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= | ||||||
|  | golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= | ||||||
| golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||||
| golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||||
| golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||||
|  | |||||||
| @ -29,4 +29,4 @@ func UserAgent() string { | |||||||
| 	return fmt.Sprintf("authentik@%s", FullVersion()) | 	return fmt.Sprintf("authentik@%s", FullVersion()) | ||||||
| } | } | ||||||
|  |  | ||||||
| const VERSION = "2025.4.0" | const VERSION = "2025.2.4" | ||||||
|  | |||||||
| @ -62,8 +62,7 @@ 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 | ||||||
|     source "${VENV_PATH}/bin/activate" |     VIRTUAL_ENV=/ak-root/.venv uv sync --frozen | ||||||
|     uv sync --active --frozen |  | ||||||
|     touch /unittest.xml |     touch /unittest.xml | ||||||
|     chown authentik:authentik /unittest.xml |     chown authentik:authentik /unittest.xml | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										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.1013.0", |                 "aws-cdk": "^2.1010.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.1013.0", |             "version": "2.1010.0", | ||||||
|             "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1013.0.tgz", |             "resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1010.0.tgz", | ||||||
|             "integrity": "sha512-cbq4cOoEIZueMWenGgfI4RujS+AQ9GaMCTlW/3CnvEIhMD8j/tgZx7PTtgMuvwYrRoEeb/wTxgLPgUd5FhsoHA==", |             "integrity": "sha512-kYNzBXVUZoRrTuYxRRA2Loz/Uvay0MqHobg8KPZaWylIbw/meUDgtoATRNt+stOdJ9PHODTjWmlDKI+2/KoF+w==", | ||||||
|             "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.1013.0", |         "aws-cdk": "^2.1010.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.4.0 |     Default: 2025.2.4 | ||||||
|     Description: authentik Docker image tag |     Description: authentik Docker image tag | ||||||
|   AuthentikServerCPU: |   AuthentikServerCPU: | ||||||
|     Type: Number |     Type: Number | ||||||
|  | |||||||
| @ -3,7 +3,7 @@ from lifecycle.migrate import BaseMigration | |||||||
|  |  | ||||||
| SQL_STATEMENT = """ | SQL_STATEMENT = """ | ||||||
| BEGIN TRANSACTION; | BEGIN TRANSACTION; | ||||||
| ALTER TABLE IF EXISTS authentik_tenants_tenant RENAME TO authentik_brands_brand; | ALTER TABLE authentik_tenants_tenant RENAME TO authentik_brands_brand; | ||||||
| UPDATE django_migrations SET app = replace(app, 'authentik_tenants', 'authentik_brands'); | UPDATE django_migrations SET app = replace(app, 'authentik_tenants', 'authentik_brands'); | ||||||
| UPDATE django_content_type SET app_label = replace(app_label, 'authentik_tenants', 'authentik_brands'); | UPDATE django_content_type SET app_label = replace(app_label, 'authentik_tenants', 'authentik_brands'); | ||||||
| COMMIT; | COMMIT; | ||||||
|  | |||||||
										
											Binary file not shown.
										
									
								
							| @ -8,6 +8,7 @@ | |||||||
| # 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 | ||||||
| @ -29,18 +30,17 @@ | |||||||
| # Alexander Möbius, 2025 | # Alexander Möbius, 2025 | ||||||
| # Jonas, 2025 | # Jonas, 2025 | ||||||
| # Niklas Kroese, 2025 | # Niklas Kroese, 2025 | ||||||
| # datenschmutz, 2025 |  | ||||||
| # 97cce0ae0cad2a2cc552d3165d04643e_de3d740, 2025 | # 97cce0ae0cad2a2cc552d3165d04643e_de3d740, 2025 | ||||||
| # Dominic Wagner <mail@dominic-wagner.de>, 2025 | # datenschmutz, 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-23 09:00+0000\n" | "POT-Creation-Date: 2025-04-11 00:10+0000\n" | ||||||
| "PO-Revision-Date: 2022-09-26 16:47+0000\n" | "PO-Revision-Date: 2022-09-26 16:47+0000\n" | ||||||
| "Last-Translator: Dominic Wagner <mail@dominic-wagner.de>, 2025\n" | "Last-Translator: datenschmutz, 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,7 +214,6 @@ 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" | ||||||
|  |  | ||||||
| @ -403,18 +402,6 @@ 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" | ||||||
| @ -524,38 +511,6 @@ 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." | ||||||
| @ -1348,6 +1303,12 @@ 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" | ||||||
| @ -1359,6 +1320,10 @@ 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." | ||||||
| @ -1400,6 +1365,20 @@ 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" | ||||||
| @ -2229,10 +2208,6 @@ 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" | ||||||
| @ -2503,22 +2478,6 @@ 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 "" | ||||||
| @ -2528,14 +2487,6 @@ 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" | ||||||
| @ -2577,12 +2528,6 @@ 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" | ||||||
| @ -3489,12 +3434,6 @@ 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." | ||||||
| @ -3887,14 +3826,6 @@ 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 "" | ||||||
|  | |||||||
| @ -8,7 +8,7 @@ msgid "" | |||||||
| msgstr "" | msgstr "" | ||||||
| "Project-Id-Version: PACKAGE VERSION\n" | "Project-Id-Version: PACKAGE VERSION\n" | ||||||
| "Report-Msgid-Bugs-To: \n" | "Report-Msgid-Bugs-To: \n" | ||||||
| "POT-Creation-Date: 2025-04-23 09:00+0000\n" | "POT-Creation-Date: 2025-04-17 00:09+0000\n" | ||||||
| "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" | ||||||
| "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" | "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" | ||||||
| "Language-Team: LANGUAGE <LL@li.org>\n" | "Language-Team: LANGUAGE <LL@li.org>\n" | ||||||
| @ -451,36 +451,6 @@ 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 "" | ||||||
| @ -1205,6 +1175,10 @@ 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 "" | ||||||
| @ -1214,6 +1188,10 @@ 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 "" | msgstr "" | ||||||
|  |  | ||||||
|  | #: 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 "" | ||||||
| @ -1255,6 +1233,20 @@ 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 "" | ||||||
| @ -3152,12 +3144,6 @@ 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 "" | ||||||
|  | |||||||
										
											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-23 09:00+0000\n" | "POT-Creation-Date: 2025-04-11 00:10+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,7 +190,6 @@ 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" | ||||||
|  |  | ||||||
| @ -379,18 +378,6 @@ 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" | ||||||
| @ -498,38 +485,6 @@ 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." | ||||||
| @ -1313,6 +1268,12 @@ 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 "" | ||||||
| @ -1326,6 +1287,10 @@ 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." | ||||||
| @ -1367,6 +1332,20 @@ 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" | ||||||
| @ -2196,10 +2175,6 @@ 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" | ||||||
| @ -2468,22 +2443,6 @@ 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." | ||||||
| @ -2492,14 +2451,6 @@ 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" | ||||||
| @ -2540,12 +2491,6 @@ 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" | ||||||
| @ -3462,12 +3407,6 @@ 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 "" | ||||||
| @ -3855,14 +3794,6 @@ 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-23 09:00+0000\n" | "POT-Creation-Date: 2025-04-11 00:10+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,7 +186,6 @@ 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ä" | ||||||
|  |  | ||||||
| @ -372,18 +371,6 @@ 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" | ||||||
| @ -491,38 +478,6 @@ 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." | ||||||
| @ -1296,6 +1251,12 @@ 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 "" | ||||||
| @ -1308,6 +1269,10 @@ 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." | ||||||
| @ -1349,6 +1314,20 @@ 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" | ||||||
| @ -2176,10 +2155,6 @@ 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" | ||||||
| @ -2445,22 +2420,6 @@ 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ä." | ||||||
| @ -2469,14 +2428,6 @@ 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" | ||||||
| @ -2517,12 +2468,6 @@ 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" | ||||||
| @ -3432,12 +3377,6 @@ 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 "" | ||||||
| @ -3815,14 +3754,6 @@ 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.
										
									
								
							| @ -9,8 +9,8 @@ | |||||||
| # Kyllian Delaye-Maillot, 2023 | # Kyllian Delaye-Maillot, 2023 | ||||||
| # Manuel Viens, 2023 | # Manuel Viens, 2023 | ||||||
| # Mordecai, 2023 | # Mordecai, 2023 | ||||||
| # Tina, 2024 |  | ||||||
| # Charles Leclerc, 2025 | # Charles Leclerc, 2025 | ||||||
|  | # Tina, 2025 | ||||||
| # nerdinator <florian.dupret@gmail.com>, 2025 | # nerdinator <florian.dupret@gmail.com>, 2025 | ||||||
| # Marc Schmitt, 2025 | # Marc Schmitt, 2025 | ||||||
| #  | #  | ||||||
| @ -19,7 +19,7 @@ msgid "" | |||||||
| msgstr "" | msgstr "" | ||||||
| "Project-Id-Version: PACKAGE VERSION\n" | "Project-Id-Version: PACKAGE VERSION\n" | ||||||
| "Report-Msgid-Bugs-To: \n" | "Report-Msgid-Bugs-To: \n" | ||||||
| "POT-Creation-Date: 2025-04-23 09:00+0000\n" | "POT-Creation-Date: 2025-04-15 00:11+0000\n" | ||||||
| "PO-Revision-Date: 2022-09-26 16:47+0000\n" | "PO-Revision-Date: 2022-09-26 16:47+0000\n" | ||||||
| "Last-Translator: Marc Schmitt, 2025\n" | "Last-Translator: Marc Schmitt, 2025\n" | ||||||
| "Language-Team: French (https://app.transifex.com/authentik/teams/119923/fr/)\n" | "Language-Team: French (https://app.transifex.com/authentik/teams/119923/fr/)\n" | ||||||
| @ -502,38 +502,6 @@ msgstr "Utilisation de la licence" | |||||||
| msgid "License Usage Records" | msgid "License Usage Records" | ||||||
| msgstr "Registre d'utilisation de la licence" | msgstr "Registre d'utilisation de la licence" | ||||||
|  |  | ||||||
| #: 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 "" |  | ||||||
| "Clé de champ à vérifier ; les clés de champ définies dans les étapes de " |  | ||||||
| "d'invite sont disponibles." |  | ||||||
|  |  | ||||||
| #: authentik/enterprise/policies/unique_password/models.py |  | ||||||
| msgid "Number of passwords to check against." |  | ||||||
| msgstr "Nombre de mots de passe à vérifier." |  | ||||||
|  |  | ||||||
| #: authentik/enterprise/policies/unique_password/models.py |  | ||||||
| #: authentik/policies/password/models.py |  | ||||||
| msgid "Password not set in context" |  | ||||||
| msgstr "Mot de passe non défini dans le contexte" |  | ||||||
|  |  | ||||||
| #: authentik/enterprise/policies/unique_password/models.py |  | ||||||
| msgid "This password has been used previously. Please choose a different one." |  | ||||||
| msgstr "Ce mot de passe a déjà été utilisé. Veuillez en choisir un autre." |  | ||||||
|  |  | ||||||
| #: authentik/enterprise/policies/unique_password/models.py |  | ||||||
| msgid "Password Uniqueness Policy" |  | ||||||
| msgstr "Politique d'unicité des mots de passe" |  | ||||||
|  |  | ||||||
| #: authentik/enterprise/policies/unique_password/models.py |  | ||||||
| msgid "Password Uniqueness Policies" |  | ||||||
| msgstr "Politiques d'unicité des mots de passe" |  | ||||||
|  |  | ||||||
| #: authentik/enterprise/policies/unique_password/models.py |  | ||||||
| msgid "User Password History" |  | ||||||
| msgstr "Historique des mots de passe utilisateur" |  | ||||||
|  |  | ||||||
| #: authentik/enterprise/policy.py | #: authentik/enterprise/policy.py | ||||||
| msgid "Enterprise required to access this feature." | msgid "Enterprise required to access this feature." | ||||||
| msgstr "Entreprise est requis pour accéder à cette fonctionnalité." | msgstr "Entreprise est requis pour accéder à cette fonctionnalité." | ||||||
| @ -1328,6 +1296,12 @@ msgstr "Voir les métriques de cache de la politique" | |||||||
| msgid "Clear Policy's cache metrics" | msgid "Clear Policy's cache metrics" | ||||||
| msgstr "Nettoyer les métriques de cache de la politique" | msgstr "Nettoyer les métriques de cache de la politique" | ||||||
|  |  | ||||||
|  | #: authentik/policies/password/models.py | ||||||
|  | msgid "Field key to check, field keys defined in Prompt stages are available." | ||||||
|  | msgstr "" | ||||||
|  | "Clé de champ à vérifier ; les clés de champ définies dans les étapes de " | ||||||
|  | "d'invite sont 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 "" | ||||||
| @ -1341,6 +1315,10 @@ msgstr "" | |||||||
| "Si le score zxcvbn est égal ou inférieur à cette valeur, la politique " | "Si le score zxcvbn est égal ou inférieur à cette valeur, la politique " | ||||||
| "échouera." | "échouera." | ||||||
|  |  | ||||||
|  | #: authentik/policies/password/models.py | ||||||
|  | msgid "Password not set in context" | ||||||
|  | msgstr "Mot de passe non défini dans le contexte" | ||||||
|  |  | ||||||
| #: authentik/policies/password/models.py | #: authentik/policies/password/models.py | ||||||
| msgid "Invalid password." | msgid "Invalid password." | ||||||
| msgstr "Mot de passe invalide." | msgstr "Mot de passe invalide." | ||||||
| @ -1382,6 +1360,22 @@ msgstr "Score de Réputation" | |||||||
| msgid "Reputation Scores" | msgid "Reputation Scores" | ||||||
| msgstr "Scores de Réputation" | msgstr "Scores de Réputation" | ||||||
|  |  | ||||||
|  | #: authentik/policies/templates/policies/buffer.html | ||||||
|  | msgid "Waiting for authentication..." | ||||||
|  | msgstr "En attente de l'authentification..." | ||||||
|  |  | ||||||
|  | #: authentik/policies/templates/policies/buffer.html | ||||||
|  | msgid "" | ||||||
|  | "You're already authenticating in another tab. This page will refresh once " | ||||||
|  | "authentication is completed." | ||||||
|  | msgstr "" | ||||||
|  | "Vous êtes déjà en cours d'authentification dans un autre onglet. Cette page " | ||||||
|  | "se rafraîchira lorsque l'authentification sera terminée." | ||||||
|  |  | ||||||
|  | #: authentik/policies/templates/policies/buffer.html | ||||||
|  | msgid "Authenticate in this tab" | ||||||
|  | msgstr "S'authentifier dans cet onglet" | ||||||
|  |  | ||||||
| #: authentik/policies/templates/policies/denied.html | #: authentik/policies/templates/policies/denied.html | ||||||
| msgid "Permission denied" | msgid "Permission denied" | ||||||
| msgstr "Permission refusée" | msgstr "Permission refusée" | ||||||
| @ -2514,14 +2508,6 @@ msgstr "Le mot de passe ne correspond pas à la complexité d'Active Directory." | |||||||
| msgid "No token received." | msgid "No token received." | ||||||
| msgstr "Pas de jeton reçu." | msgstr "Pas de jeton reçu." | ||||||
|  |  | ||||||
| #: authentik/sources/oauth/models.py |  | ||||||
| msgid "HTTP Basic Authentication" |  | ||||||
| msgstr "Authentification HTTP Basic" |  | ||||||
|  |  | ||||||
| #: authentik/sources/oauth/models.py |  | ||||||
| msgid "Include the client ID and secret as request parameters" |  | ||||||
| msgstr "Inclure le client ID et secret comme paramètres de la requête" |  | ||||||
|  |  | ||||||
| #: authentik/sources/oauth/models.py | #: authentik/sources/oauth/models.py | ||||||
| msgid "Request Token URL" | msgid "Request Token URL" | ||||||
| msgstr "URL du jeton de requête" | msgstr "URL du jeton de requête" | ||||||
| @ -2563,14 +2549,6 @@ msgstr "" | |||||||
| msgid "Additional Scopes" | msgid "Additional Scopes" | ||||||
| msgstr "Portées additionnelles" | msgstr "Portées additionnelles" | ||||||
|  |  | ||||||
| #: authentik/sources/oauth/models.py |  | ||||||
| msgid "" |  | ||||||
| "How to perform authentication during an authorization_code token request " |  | ||||||
| "flow" |  | ||||||
| msgstr "" |  | ||||||
| "Comment effectuer l'authentification lors d'une demande de jeton pour le " |  | ||||||
| "flux authorization_code" |  | ||||||
|  |  | ||||||
| #: authentik/sources/oauth/models.py | #: authentik/sources/oauth/models.py | ||||||
| msgid "OAuth Source" | msgid "OAuth Source" | ||||||
| msgstr "Source OAuth" | msgstr "Source OAuth" | ||||||
| @ -3491,15 +3469,6 @@ msgstr "" | |||||||
| "Lorsqu'activé, l'étape réussira et continuera même lorsque les informations " | "Lorsqu'activé, l'étape réussira et continuera même lorsque les informations " | ||||||
| "utilisateurs entrées sont invalides." | "utilisateurs entrées sont invalides." | ||||||
|  |  | ||||||
| #: 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 "" |  | ||||||
| "Afficher à l'utilisateur l'option \"Se souvenir de moi sur cet appareil\", " |  | ||||||
| "afin de permettre aux utilisateurs réguliers de passer directement à la " |  | ||||||
| "saisie de leur mot de passe." |  | ||||||
|  |  | ||||||
| #: 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 "Flux d'inscription facultatif, qui sera accessible en bas de page." | msgstr "Flux d'inscription facultatif, qui sera accessible en bas de page." | ||||||
|  | |||||||
										
											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-23 09:00+0000\n" | "POT-Creation-Date: 2025-04-11 00:10+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,7 +194,6 @@ 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" | ||||||
|  |  | ||||||
| @ -381,18 +380,6 @@ 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" | ||||||
| @ -500,39 +487,6 @@ 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" | ||||||
| @ -1320,6 +1274,12 @@ 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 "" | ||||||
| @ -1332,6 +1292,10 @@ 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." | ||||||
| @ -1373,6 +1337,22 @@ 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" | ||||||
| @ -2202,10 +2182,6 @@ 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" | ||||||
| @ -2459,9 +2435,6 @@ 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" | ||||||
| @ -2479,22 +2452,6 @@ 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." | ||||||
| @ -2503,14 +2460,6 @@ 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" | ||||||
| @ -2551,14 +2500,6 @@ 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" | ||||||
| @ -3485,15 +3426,6 @@ 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." | ||||||
| @ -3880,14 +3812,6 @@ 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-04-23 09:00+0000\n" | "POT-Creation-Date: 2025-03-31 00:10+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,7 +176,6 @@ 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 "사용자" | ||||||
|  |  | ||||||
| @ -345,18 +344,6 @@ 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 "인증된 세션" | ||||||
| @ -460,36 +447,6 @@ 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 "" | ||||||
| @ -1225,6 +1182,10 @@ 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 "비밀번호 해시가 허용되는 해시 횟수" | ||||||
| @ -1234,6 +1195,10 @@ 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 "" | ||||||
| @ -1275,6 +1240,20 @@ 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 "권한 거부됨" | ||||||
| @ -2034,10 +2013,6 @@ 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 "시스템 권한" | ||||||
| @ -2256,13 +2231,6 @@ 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 소스" | ||||||
| @ -2279,22 +2247,6 @@ 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 복잡도와 일치하지 않습니다." | ||||||
| @ -2303,14 +2255,6 @@ 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" | ||||||
| @ -2349,12 +2293,6 @@ 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 소스" | ||||||
| @ -3211,12 +3149,6 @@ 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 "페이지 하단에 링크된,  선택적 등록 플로우를 참조하세요." | ||||||
| @ -3568,14 +3500,6 @@ 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-23 09:00+0000\n" | "POT-Creation-Date: 2025-04-11 00:10+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: Darek “NeroPcStation” NeroPcStation <dareknowacki2001@gmail.com>, 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,7 +189,6 @@ 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" | ||||||
|  |  | ||||||
| @ -372,18 +371,6 @@ 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" | ||||||
| @ -492,38 +479,6 @@ 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." | ||||||
| @ -1302,6 +1257,12 @@ 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" | ||||||
| @ -1313,6 +1274,10 @@ 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 "" | ||||||
| @ -1354,6 +1319,20 @@ 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ń" | ||||||
| @ -2162,10 +2141,6 @@ 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" | ||||||
| @ -2415,22 +2390,6 @@ 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." | ||||||
| @ -2439,14 +2398,6 @@ 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" | ||||||
| @ -2489,12 +2440,6 @@ 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" | ||||||
| @ -3399,12 +3344,6 @@ 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 "" | ||||||
| @ -3788,14 +3727,6 @@ 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." | ||||||
|  | |||||||
| @ -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-23 09:00+0000\n" | "POT-Creation-Date: 2025-04-11 00:10+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,7 +192,6 @@ 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" | ||||||
|  |  | ||||||
| @ -377,18 +376,6 @@ 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" | ||||||
| @ -496,38 +483,6 @@ 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" | ||||||
| @ -1297,6 +1252,12 @@ 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" | ||||||
| @ -1307,6 +1268,10 @@ 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 "" | ||||||
| @ -1348,6 +1313,20 @@ 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" | ||||||
| @ -2162,10 +2141,6 @@ 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" | ||||||
| @ -2412,22 +2387,6 @@ 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." | ||||||
| @ -2436,14 +2395,6 @@ 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" | ||||||
| @ -2484,12 +2435,6 @@ 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" | ||||||
| @ -3373,12 +3318,6 @@ 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." | ||||||
| @ -3739,14 +3678,6 @@ 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-23 09:00+0000\n" | "POT-Creation-Date: 2025-04-11 00:10+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,7 +191,6 @@ 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 "Пользователь" | ||||||
|  |  | ||||||
| @ -380,18 +379,6 @@ 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 "Аутентифицированная Сессия" | ||||||
| @ -500,37 +487,6 @@ 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." | ||||||
| @ -1311,6 +1267,11 @@ 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" | ||||||
| @ -1322,6 +1283,10 @@ 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 "Неправильный пароль" | ||||||
| @ -1363,6 +1328,20 @@ 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 "Доступ запрещен" | ||||||
| @ -2185,10 +2164,6 @@ 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 "Системное разрешение" | ||||||
| @ -2446,22 +2421,6 @@ 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." | ||||||
| @ -2470,14 +2429,6 @@ 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-адрес запроса токена" | ||||||
| @ -2520,12 +2471,6 @@ 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" | ||||||
| @ -3431,12 +3376,6 @@ 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 "" | ||||||
| @ -3828,14 +3767,6 @@ 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-04-23 09:00+0000\n" | "POT-Creation-Date: 2025-03-31 00:10+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,7 +187,6 @@ 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ı" | ||||||
|  |  | ||||||
| @ -373,18 +372,6 @@ 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" | ||||||
| @ -492,38 +479,6 @@ 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." | ||||||
| @ -1298,6 +1253,12 @@ 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 "" | ||||||
| @ -1310,6 +1271,10 @@ 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 "" | ||||||
| @ -1351,6 +1316,20 @@ 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" | ||||||
| @ -2176,10 +2155,6 @@ 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" | ||||||
| @ -2423,13 +2398,6 @@ 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ğı" | ||||||
| @ -2446,22 +2414,6 @@ 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." | ||||||
| @ -2470,14 +2422,6 @@ 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" | ||||||
| @ -2518,12 +2462,6 @@ 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ğı" | ||||||
| @ -3422,12 +3360,6 @@ 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ışı." | ||||||
| @ -3802,14 +3734,6 @@ 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.
										
									
								
							| @ -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-23 09:00+0000\n" | "POT-Creation-Date: 2025-04-15 00:11+0000\n" | ||||||
| "PO-Revision-Date: 2022-09-26 16:47+0000\n" | "PO-Revision-Date: 2022-09-26 16:47+0000\n" | ||||||
| "Last-Translator: deluxghost, 2025\n" | "Last-Translator: deluxghost, 2025\n" | ||||||
| "Language-Team: Chinese Simplified (https://app.transifex.com/authentik/teams/119923/zh-Hans/)\n" | "Language-Team: Chinese Simplified (https://app.transifex.com/authentik/teams/119923/zh-Hans/)\n" | ||||||
| @ -461,36 +461,6 @@ 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 "访问此功能需要企业版。" | ||||||
| @ -1220,6 +1190,10 @@ 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 中多少次" | ||||||
| @ -1229,6 +1203,10 @@ 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 "无效密码。" | ||||||
| @ -1270,6 +1248,20 @@ 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 "权限被拒绝" | ||||||
| @ -2294,14 +2286,6 @@ msgstr "密码与 Active Directory 复杂度不匹配。" | |||||||
| msgid "No token received." | msgid "No token received." | ||||||
| msgstr "未收到令牌。" | msgstr "未收到令牌。" | ||||||
|  |  | ||||||
| #: authentik/sources/oauth/models.py |  | ||||||
| msgid "HTTP Basic Authentication" |  | ||||||
| msgstr "HTTP 基本身份验证" |  | ||||||
|  |  | ||||||
| #: authentik/sources/oauth/models.py |  | ||||||
| msgid "Include the client ID and secret as request parameters" |  | ||||||
| msgstr "包括客户端 ID 和密钥作为请求参数" |  | ||||||
|  |  | ||||||
| #: authentik/sources/oauth/models.py | #: authentik/sources/oauth/models.py | ||||||
| msgid "Request Token URL" | msgid "Request Token URL" | ||||||
| msgstr "请求令牌 URL" | msgstr "请求令牌 URL" | ||||||
| @ -2340,12 +2324,6 @@ 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 "在 authorization_code 令牌请求流程期间,如何执行身份验证" |  | ||||||
|  |  | ||||||
| #: authentik/sources/oauth/models.py | #: authentik/sources/oauth/models.py | ||||||
| msgid "OAuth Source" | msgid "OAuth Source" | ||||||
| msgstr "OAuth 源" | msgstr "OAuth 源" | ||||||
| @ -3216,12 +3194,6 @@ 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 "可选注册流程,链接在页面底部。" | ||||||
|  | |||||||
										
											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-23 09:00+0000\n" | "POT-Creation-Date: 2025-04-15 00:11+0000\n" | ||||||
| "PO-Revision-Date: 2022-09-26 16:47+0000\n" | "PO-Revision-Date: 2022-09-26 16:47+0000\n" | ||||||
| "Last-Translator: deluxghost, 2025\n" | "Last-Translator: deluxghost, 2025\n" | ||||||
| "Language-Team: Chinese (China) (https://app.transifex.com/authentik/teams/119923/zh_CN/)\n" | "Language-Team: Chinese (China) (https://app.transifex.com/authentik/teams/119923/zh_CN/)\n" | ||||||
| @ -460,36 +460,6 @@ 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 "访问此功能需要企业版。" | ||||||
| @ -1219,6 +1189,10 @@ 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 中多少次" | ||||||
| @ -1228,6 +1202,10 @@ 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 "无效密码。" | ||||||
| @ -1269,6 +1247,20 @@ 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 "权限被拒绝" | ||||||
| @ -2293,14 +2285,6 @@ msgstr "密码与 Active Directory 复杂度不匹配。" | |||||||
| msgid "No token received." | msgid "No token received." | ||||||
| msgstr "未收到令牌。" | msgstr "未收到令牌。" | ||||||
|  |  | ||||||
| #: authentik/sources/oauth/models.py |  | ||||||
| msgid "HTTP Basic Authentication" |  | ||||||
| msgstr "HTTP 基本身份验证" |  | ||||||
|  |  | ||||||
| #: authentik/sources/oauth/models.py |  | ||||||
| msgid "Include the client ID and secret as request parameters" |  | ||||||
| msgstr "包括客户端 ID 和密钥作为请求参数" |  | ||||||
|  |  | ||||||
| #: authentik/sources/oauth/models.py | #: authentik/sources/oauth/models.py | ||||||
| msgid "Request Token URL" | msgid "Request Token URL" | ||||||
| msgstr "请求令牌 URL" | msgstr "请求令牌 URL" | ||||||
| @ -2339,12 +2323,6 @@ 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 "在 authorization_code 令牌请求流程期间,如何执行身份验证" |  | ||||||
|  |  | ||||||
| #: authentik/sources/oauth/models.py | #: authentik/sources/oauth/models.py | ||||||
| msgid "OAuth Source" | msgid "OAuth Source" | ||||||
| msgstr "OAuth 源" | msgstr "OAuth 源" | ||||||
| @ -3215,12 +3193,6 @@ 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 "可选注册流程,链接在页面底部。" | ||||||
|  | |||||||
										
											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-23 09:00+0000\n" | "POT-Creation-Date: 2025-04-11 00:10+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,7 +178,6 @@ 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 "使用者" | ||||||
|  |  | ||||||
| @ -345,18 +344,6 @@ 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 "已認證會談" | ||||||
| @ -460,36 +447,6 @@ 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 "企業版才能存取此功能。" | ||||||
| @ -1219,6 +1176,10 @@ 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 上允許出現的次數" | ||||||
| @ -1228,6 +1189,10 @@ 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 "" | ||||||
| @ -1269,6 +1234,20 @@ 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 "權限不足。" | ||||||
| @ -2020,10 +1999,6 @@ 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 "系統權限" | ||||||
| @ -2265,22 +2240,6 @@ 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 的複雜性要求。" | ||||||
| @ -2289,14 +2248,6 @@ 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 "請求權杖的網址" | ||||||
| @ -2335,12 +2286,6 @@ 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 來源" | ||||||
| @ -3192,12 +3137,6 @@ 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 "可選的註冊流程,連結在頁面的底部。" | ||||||
| @ -3542,14 +3481,6 @@ 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 "" | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| { | { | ||||||
|     "name": "@goauthentik/authentik", |     "name": "@goauthentik/authentik", | ||||||
|     "version": "2025.4.0", |     "version": "2025.2.4", | ||||||
|     "private": true |     "private": true | ||||||
| } | } | ||||||
|  | |||||||
| @ -18,7 +18,9 @@ | |||||||
| } | } | ||||||
|  |  | ||||||
| .badge--support-community { | .badge--support-community { | ||||||
|     --ifm-badge-background-color: var(--ifm-color-secondary-contrast-foreground); |     --ifm-badge-background-color: var( | ||||||
|  |         --ifm-color-secondary-contrast-foreground | ||||||
|  |     ); | ||||||
|     --ifm-badge-border-color: var(--ifm-color-secondary-dark); |     --ifm-badge-border-color: var(--ifm-color-secondary-dark); | ||||||
|     --ifm-badge-color: var(--ifm-color-secondary-contrast-background); |     --ifm-badge-color: var(--ifm-color-secondary-contrast-background); | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,12 +1,12 @@ | |||||||
| :root { | :root { | ||||||
|     --ifm-font-family-base: |     --ifm-font-family-base: | ||||||
|         RedHatVF, system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, |         RedHatVF, system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, | ||||||
|         sans-serif, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, |         Noto Sans, sans-serif, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, | ||||||
|         "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; |         sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"; | ||||||
|  |  | ||||||
|     --ifm-font-family-monospace: |     --ifm-font-family-monospace: | ||||||
|         RedHatMonoVF, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", |         RedHatMonoVF, SFMono-Regular, Menlo, Monaco, Consolas, | ||||||
|         monospace; |         "Liberation Mono", "Courier New", monospace; | ||||||
|  |  | ||||||
|     --ifm-heading-font-family: RedHatDisplayVF, var(--ifm-font-family-base); |     --ifm-heading-font-family: RedHatDisplayVF, var(--ifm-font-family-base); | ||||||
|  |  | ||||||
|  | |||||||
| @ -7,7 +7,11 @@ | |||||||
| } | } | ||||||
|  |  | ||||||
| .homepage_hero__subtitle p { | .homepage_hero__subtitle p { | ||||||
|     font-size: clamp(1.125rem, 0.9946rem + 0.6522vi, 1.5rem); /* Adjust font as page scales */ |     font-size: clamp( | ||||||
|  |         1.125rem, | ||||||
|  |         0.9946rem + 0.6522vi, | ||||||
|  |         1.5rem | ||||||
|  |     ); /* Adjust font as page scales */ | ||||||
|     max-width: 28ch; /* Apply a maximum to keep everything in the box */ |     max-width: 28ch; /* Apply a maximum to keep everything in the box */ | ||||||
|     text-wrap: balance; /* Prevent widows, orphans, and runts. Doesn't work in Safari */ |     text-wrap: balance; /* Prevent widows, orphans, and runts. Doesn't work in Safari */ | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| :root { | :root { | ||||||
|     --ifm-menu-link-padding-vertical: 0.5em; |     --ifm-menu-link-padding-vertical: 1em; | ||||||
| } | } | ||||||
|  |  | ||||||
| .menu__list-item { | .menu__list-item { | ||||||
|  | |||||||
| @ -75,14 +75,17 @@ | |||||||
|         --ifm-navbar-item-padding-horizontal: 1rem; |         --ifm-navbar-item-padding-horizontal: 1rem; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     .navbar { |     .docs-wrapper .navbar { | ||||||
|         margin: 0; |         margin: 0; | ||||||
|         padding-inline-start: 0; |         padding-inline-start: 0; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     .navbar__brand { |     .navbar__brand { | ||||||
|         justify-content: center; |         justify-content: center; | ||||||
|         width: var(--doc-sidebar-width, 300px); |     } | ||||||
|  |  | ||||||
|  |     .docs-wrapper .navbar__brand { | ||||||
|  |         width: var(--doc-sidebar-width); | ||||||
|         margin: 0; |         margin: 0; | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @ -119,8 +122,12 @@ | |||||||
|  |  | ||||||
|         @media (min-width: 999px) { |         @media (min-width: 999px) { | ||||||
|             border-inline-start: 1px solid var(--ifm-hover-overlay); |             border-inline-start: 1px solid var(--ifm-hover-overlay); | ||||||
|             margin-inline-start: calc(var(--ifm-navbar-item-padding-horizontal) / 2); |             margin-inline-start: calc( | ||||||
|             padding-inline-start: calc(var(--ifm-navbar-item-padding-horizontal) / 2); |                 var(--ifm-navbar-item-padding-horizontal) / 2 | ||||||
|  |             ); | ||||||
|  |             padding-inline-start: calc( | ||||||
|  |                 var(--ifm-navbar-item-padding-horizontal) / 2 | ||||||
|  |             ); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @ -144,14 +151,19 @@ | |||||||
|         hsl(236.84deg 34.55% 10.78%) |         hsl(236.84deg 34.55% 10.78%) | ||||||
|     ); |     ); | ||||||
|     --docsearch-key-shadow: |     --docsearch-key-shadow: | ||||||
|         inset 0 -2px 0 0 hsl(233.33deg 36% 24.51%), inset 0 0 1px 1px hsl(232.11deg 34.86% 57.25%), |         inset 0 -2px 0 0 hsl(233.33deg 36% 24.51%), | ||||||
|  |         inset 0 0 1px 1px hsl(232.11deg 34.86% 57.25%), | ||||||
|         0 2px 2px 0 rgba(3, 4, 9, 0.3); |         0 2px 2px 0 rgba(3, 4, 9, 0.3); | ||||||
|     --docsearch-key-pressed-shadow: |     --docsearch-key-pressed-shadow: | ||||||
|         inset 0 -2px 0 0 #282d55, inset 0 0 1px 1px hsl(231.82deg 21.36% 40.39%), |         inset 0 -2px 0 0 #282d55, | ||||||
|  |         inset 0 0 1px 1px hsl(231.82deg 21.36% 40.39%), | ||||||
|         0 1px 1px 0 hsl(230deg 50% 2.35% / 30.2%); |         0 1px 1px 0 hsl(230deg 50% 2.35% / 30.2%); | ||||||
|  |  | ||||||
|     padding: var(--ifm-navbar-item-padding-vertical) var(--ifm-navbar-item-padding-horizontal) !important; |     padding: var(--ifm-navbar-item-padding-vertical) | ||||||
|     padding-inline-end: calc(var(--ifm-navbar-item-padding-horizontal) * 1.25) !important; |         var(--ifm-navbar-item-padding-horizontal) !important; | ||||||
|  |     padding-inline-end: calc( | ||||||
|  |         var(--ifm-navbar-item-padding-horizontal) * 1.25 | ||||||
|  |     ) !important; | ||||||
|  |  | ||||||
|     .DocSearch-Button-Placeholder { |     .DocSearch-Button-Placeholder { | ||||||
|         font-family: var(--ifm-heading-font-family); |         font-family: var(--ifm-heading-font-family); | ||||||
|  | |||||||
| @ -13,3 +13,7 @@ | |||||||
|  |  | ||||||
|     --ifm-color-content: hsl(216 35% 3%); |     --ifm-color-content: hsl(216 35% 3%); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | body { | ||||||
|  |     overscroll-behavior-x: none; | ||||||
|  | } | ||||||
|  | |||||||
| @ -4,8 +4,8 @@ | |||||||
|  * @import { Config as DocusaurusConfig } from "@docusaurus/types" |  * @import { Config as DocusaurusConfig } from "@docusaurus/types" | ||||||
|  * @import { UserThemeConfig } from "./theme.js" |  * @import { UserThemeConfig } from "./theme.js" | ||||||
|  */ |  */ | ||||||
| import { deepmerge } from "deepmerge-ts"; |  | ||||||
|  |  | ||||||
|  | import { deepmerge } from "deepmerge-ts"; | ||||||
| import { createThemeConfig } from "./theme.js"; | import { createThemeConfig } from "./theme.js"; | ||||||
|  |  | ||||||
| //#region Types | //#region Types | ||||||
|  | |||||||
| @ -4,6 +4,7 @@ | |||||||
|  * @import { UserThemeConfig as UserThemeConfigCommon } from "@docusaurus/theme-common"; |  * @import { UserThemeConfig as UserThemeConfigCommon } from "@docusaurus/theme-common"; | ||||||
|  * @import { UserThemeConfig as UserThemeConfigAlgolia } from "@docusaurus/theme-search-algolia"; |  * @import { UserThemeConfig as UserThemeConfigAlgolia } from "@docusaurus/theme-search-algolia"; | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| import { deepmerge } from "deepmerge-ts"; | import { deepmerge } from "deepmerge-ts"; | ||||||
| import { themes as prismThemes } from "prism-react-renderer"; | import { themes as prismThemes } from "prism-react-renderer"; | ||||||
|  |  | ||||||
|  | |||||||
							
								
								
									
										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.2", | ||||||
|     "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.2", | ||||||
|             "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.4", | ||||||
|     "description": "authentik's Docusaurus config", |     "description": "authentik's Docusaurus config", | ||||||
|     "license": "MIT", |     "license": "MIT", | ||||||
|     "scripts": { |     "scripts": { | ||||||
|  | |||||||
| @ -2,3 +2,4 @@ | |||||||
| 
 | 
 | ||||||
| This package contains utility scripts common to all TypeScript and JavaScript packages in the | This package contains utility scripts common to all TypeScript and JavaScript packages in the | ||||||
| `@goauthentik` monorepo. | `@goauthentik` monorepo. | ||||||
|  | 
 | ||||||
| @ -1,9 +1,8 @@ | |||||||
| /** | /** | ||||||
|  * @file Constants for JavaScript and TypeScript files. |  * @file Constants for JavaScript and TypeScript files. | ||||||
|  |  * | ||||||
|  */ |  */ | ||||||
| 
 | 
 | ||||||
| /// <reference types="../../types/global.js" />
 |  | ||||||
| 
 |  | ||||||
| /** | /** | ||||||
|  * The current Node.js environment, defaulting to "development" when not set. |  * The current Node.js environment, defaulting to "development" when not set. | ||||||
|  * |  * | ||||||
| @ -13,4 +12,6 @@ | |||||||
|  * ensure that module tree-shaking works correctly. |  * ensure that module tree-shaking works correctly. | ||||||
|  * |  * | ||||||
|  */ |  */ | ||||||
| export const NodeEnvironment = process.env.NODE_ENV || "development"; | export const NodeEnvironment = /** @type {'development' | 'production'} */ ( | ||||||
|  |     process.env.NODE_ENV || "development" | ||||||
|  | ); | ||||||
| @ -1,7 +1,4 @@ | |||||||
| /// <reference types="./types/global.js" />
 |  | ||||||
| 
 |  | ||||||
| export * from "./paths.js"; | export * from "./paths.js"; | ||||||
| export * from "./constants.js"; | export * from "./constants.js"; | ||||||
| export * from "./build.js"; |  | ||||||
| export * from "./version.js"; | export * from "./version.js"; | ||||||
| export * from "./scripting.js"; | export * from "./scripting.js"; | ||||||
							
								
								
									
										19
									
								
								packages/monorepo/package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								packages/monorepo/package.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,19 @@ | |||||||
|  | { | ||||||
|  |     "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" | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										30
									
								
								packages/monorepo/paths.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								packages/monorepo/paths.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,30 @@ | |||||||
|  | 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); | ||||||
|  | } | ||||||
| @ -1,6 +1,6 @@ | |||||||
| import { execSync } from "node:child_process"; | import { execSync } from "node:child_process"; | ||||||
| 
 | 
 | ||||||
| import PackageJSON from "../../../package.json" with { type: "json" }; | import PackageJSON from "../../package.json" with { type: "json" }; | ||||||
| import { MonoRepoRoot } from "./paths.js"; | import { MonoRepoRoot } from "./paths.js"; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
| @ -1,6 +1,6 @@ | |||||||
| [project] | [project] | ||||||
| name = "authentik" | name = "authentik" | ||||||
| version = "2025.4.0" | version = "2025.2.4" | ||||||
| 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.12.*" | ||||||
|  | |||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user
	