Compare commits
121 Commits
policies-e
...
version/20
Author | SHA1 | Date | |
---|---|---|---|
ae47624761 | |||
14a6430e21 | |||
ed0a9d6a0a | |||
53143e0c40 | |||
178e010ed4 | |||
49b666fbde | |||
c343e3a7f4 | |||
5febf3ce5b | |||
b8c5bd678b | |||
4dd5eccbaa | |||
2410884006 | |||
3cb921b0f9 | |||
535f92981f | |||
955d69d5b7 | |||
fb01d8e96a | |||
6d39efd3e3 | |||
3020c31bcd | |||
22412729e2 | |||
a02868a27d | |||
bfbb4a8ebc | |||
6c0e827677 | |||
29884cbf81 | |||
0f02985b0c | |||
2244e026c2 | |||
429c03021c | |||
f47e8d9d72 | |||
3e7d2587c4 | |||
55a38d4a36 | |||
6021bb932d | |||
54a5d95717 | |||
a0a1275452 | |||
919aa5df59 | |||
cedf7cf683 | |||
cbc5a1c39d | |||
5f6b69c998 | |||
cf065db3d5 | |||
86c65325ce | |||
2b8e10e979 | |||
9298807275 | |||
ed56d6ac50 | |||
8c07b385ad | |||
880db7a86c | |||
99c1250ba5 | |||
5ce126ac83 | |||
dfa21d0725 | |||
e7e4af3894 | |||
931d6ec579 | |||
ff45acb25c | |||
c96557ff2d | |||
734feac4ae | |||
b17a9ed145 | |||
2bef7695db | |||
df472dd842 | |||
98d201d34c | |||
47e89602ab | |||
ceb0851452 | |||
cac2593658 | |||
1c9705bfaa | |||
9e2566cec4 | |||
5bdef1c4f6 | |||
ae41ccd862 | |||
337956672f | |||
cf160f800d | |||
e9822cd937 | |||
5244f64be4 | |||
0df4824fd4 | |||
ea22abc75d | |||
b09bab7543 | |||
5aedc8a5f2 | |||
2f3ae0f607 | |||
e3674426b7 | |||
df915d3a5e | |||
4949c31860 | |||
4580dec06b | |||
56de969640 | |||
413902508d | |||
64af0ccba6 | |||
673db53777 | |||
8df7716d90 | |||
19bb2de13f | |||
a218fd7628 | |||
78cfb50a90 | |||
2033d52dc2 | |||
be00f47ddc | |||
2cc5f4b273 | |||
4e8f3407a4 | |||
7f861cc2a1 | |||
7bf58d0ba2 | |||
fffcb00f39 | |||
77ee868573 | |||
6aaec08496 | |||
cc15584650 | |||
e55e446b89 | |||
76088e48b5 | |||
4165a0a6b2 | |||
647fefe5ce | |||
723dccdae3 | |||
c82f747e5e | |||
43406e2464 | |||
a0ff0bef85 | |||
bedf548a5f | |||
976e81c1dd | |||
ad733033d7 | |||
ba686f6a93 | |||
dc50be1e13 | |||
205686d252 | |||
6d589013e6 | |||
2d6433ca9a | |||
b5f07acb26 | |||
ea8702077c | |||
6593357115 | |||
6daed865c1 | |||
c48a21707a | |||
e857770c0a | |||
add74c8799 | |||
12d854035d | |||
57dd4ae91d | |||
37fbc98177 | |||
14f216eb40 | |||
1209dd022e | |||
c96f13ac66 |
@ -1,5 +1,5 @@
|
|||||||
[bumpversion]
|
[bumpversion]
|
||||||
current_version = 2025.2.4
|
current_version = 2025.4.1
|
||||||
tag = True
|
tag = True
|
||||||
commit = True
|
commit = True
|
||||||
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(?:-(?P<rc_t>[a-zA-Z-]+)(?P<rc_n>[1-9]\\d*))?
|
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(?:-(?P<rc_t>[a-zA-Z-]+)(?P<rc_n>[1-9]\\d*))?
|
||||||
|
12
.github/workflows/ci-main.yml
vendored
12
.github/workflows/ci-main.yml
vendored
@ -70,22 +70,18 @@ jobs:
|
|||||||
- name: checkout stable
|
- name: checkout stable
|
||||||
run: |
|
run: |
|
||||||
# Copy current, latest config to local
|
# Copy current, latest config to local
|
||||||
# Temporarly comment the .github backup while migrating to uv
|
|
||||||
cp authentik/lib/default.yml local.env.yml
|
cp authentik/lib/default.yml local.env.yml
|
||||||
# cp -R .github ..
|
cp -R .github ..
|
||||||
cp -R scripts ..
|
cp -R scripts ..
|
||||||
git checkout $(git tag --sort=version:refname | grep '^version/' | grep -vE -- '-rc[0-9]+$' | tail -n1)
|
git checkout $(git tag --sort=version:refname | grep '^version/' | grep -vE -- '-rc[0-9]+$' | tail -n1)
|
||||||
# rm -rf .github/ scripts/
|
rm -rf .github/ scripts/
|
||||||
# mv ../.github ../scripts .
|
mv ../.github ../scripts .
|
||||||
rm -rf scripts/
|
|
||||||
mv ../scripts .
|
|
||||||
- name: Setup authentik env (stable)
|
- name: Setup authentik env (stable)
|
||||||
uses: ./.github/actions/setup
|
uses: ./.github/actions/setup
|
||||||
with:
|
with:
|
||||||
postgresql_version: ${{ matrix.psql }}
|
postgresql_version: ${{ matrix.psql }}
|
||||||
continue-on-error: true
|
|
||||||
- name: run migrations to stable
|
- name: run migrations to stable
|
||||||
run: poetry run python -m lifecycle.migrate
|
run: uv run python -m lifecycle.migrate
|
||||||
- name: checkout current code
|
- name: checkout current code
|
||||||
run: |
|
run: |
|
||||||
set -x
|
set -x
|
||||||
|
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:
|
||||||
|
@ -40,7 +40,8 @@ COPY ./web /work/web/
|
|||||||
COPY ./website /work/website/
|
COPY ./website /work/website/
|
||||||
COPY ./gen-ts-api /work/web/node_modules/@goauthentik/api
|
COPY ./gen-ts-api /work/web/node_modules/@goauthentik/api
|
||||||
|
|
||||||
RUN npm run build
|
RUN npm run build && \
|
||||||
|
npm run build:sfe
|
||||||
|
|
||||||
# Stage 3: Build go proxy
|
# Stage 3: Build go proxy
|
||||||
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.24-bookworm AS go-builder
|
FROM --platform=${BUILDPLATFORM} docker.io/library/golang:1.24-bookworm AS go-builder
|
||||||
@ -94,7 +95,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.6.14 AS uv
|
FROM ghcr.io/astral-sh/uv:0.6.16 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.2.4"
|
__version__ = "2025.4.1"
|
||||||
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).update(branding_custom_css=css)
|
Brand.objects.using(db_alias).all().update(branding_custom_css=css)
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
@ -99,18 +99,17 @@ class GroupSerializer(ModelSerializer):
|
|||||||
if superuser
|
if superuser
|
||||||
else "authentik_core.disable_group_superuser"
|
else "authentik_core.disable_group_superuser"
|
||||||
)
|
)
|
||||||
has_perm = user.has_perm(perm)
|
if self.instance or superuser:
|
||||||
if self.instance and not has_perm:
|
has_perm = user.has_perm(perm) or user.has_perm(perm, self.instance)
|
||||||
has_perm = user.has_perm(perm, self.instance)
|
if not has_perm:
|
||||||
if not has_perm:
|
raise ValidationError(
|
||||||
raise ValidationError(
|
_(
|
||||||
_(
|
(
|
||||||
(
|
"User does not have permission to set "
|
||||||
"User does not have permission to set "
|
"superuser status to {superuser_status}."
|
||||||
"superuser status to {superuser_status}."
|
).format_map({"superuser_status": superuser})
|
||||||
).format_map({"superuser_status": superuser})
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
return superuser
|
return superuser
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
from django.apps import apps
|
from django.apps import apps
|
||||||
from django.contrib.auth.management import create_permissions
|
from django.contrib.auth.management import create_permissions
|
||||||
|
from django.core.management import call_command
|
||||||
from django.core.management.base import BaseCommand, no_translations
|
from django.core.management.base import BaseCommand, no_translations
|
||||||
from guardian.management import create_anonymous_user
|
from guardian.management import create_anonymous_user
|
||||||
|
|
||||||
@ -16,6 +17,10 @@ class Command(BaseCommand):
|
|||||||
"""Check permissions for all apps"""
|
"""Check permissions for all apps"""
|
||||||
for tenant in Tenant.objects.filter(ready=True):
|
for tenant in Tenant.objects.filter(ready=True):
|
||||||
with tenant:
|
with tenant:
|
||||||
|
# See https://code.djangoproject.com/ticket/28417
|
||||||
|
# Remove potential lingering old permissions
|
||||||
|
call_command("remove_stale_contenttypes", "--no-input")
|
||||||
|
|
||||||
for app in apps.get_app_configs():
|
for app in apps.get_app_configs():
|
||||||
self.stdout.write(f"Checking app {app.name} ({app.label})\n")
|
self.stdout.write(f"Checking app {app.name} ({app.label})\n")
|
||||||
create_permissions(app, verbosity=0)
|
create_permissions(app, verbosity=0)
|
||||||
|
@ -31,7 +31,10 @@ class PickleSerializer:
|
|||||||
|
|
||||||
def loads(self, data):
|
def loads(self, data):
|
||||||
"""Unpickle data to be loaded from redis"""
|
"""Unpickle data to be loaded from redis"""
|
||||||
return pickle.loads(data) # nosec
|
try:
|
||||||
|
return pickle.loads(data) # nosec
|
||||||
|
except Exception:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
|
||||||
def _migrate_session(
|
def _migrate_session(
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
# Generated by Django 5.1.9 on 2025-05-14 11:15
|
||||||
|
|
||||||
|
from django.apps.registry import Apps
|
||||||
|
from django.db import migrations
|
||||||
|
from django.db.backends.base.schema import BaseDatabaseSchemaEditor
|
||||||
|
|
||||||
|
|
||||||
|
def remove_old_authenticated_session_content_type(
|
||||||
|
apps: Apps, schema_editor: BaseDatabaseSchemaEditor
|
||||||
|
):
|
||||||
|
db_alias = schema_editor.connection.alias
|
||||||
|
ContentType = apps.get_model("contenttypes", "ContentType")
|
||||||
|
|
||||||
|
ContentType.objects.using(db_alias).filter(model="oldauthenticatedsession").delete()
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("authentik_core", "0047_delete_oldauthenticatedsession"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RunPython(
|
||||||
|
code=remove_old_authenticated_session_content_type,
|
||||||
|
),
|
||||||
|
]
|
@ -124,6 +124,16 @@ class TestGroupsAPI(APITestCase):
|
|||||||
{"is_superuser": ["User does not have permission to set superuser status to True."]},
|
{"is_superuser": ["User does not have permission to set superuser status to True."]},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_superuser_no_perm_no_superuser(self):
|
||||||
|
"""Test creating a group without permission and without superuser flag"""
|
||||||
|
assign_perm("authentik_core.add_group", self.login_user)
|
||||||
|
self.client.force_login(self.login_user)
|
||||||
|
res = self.client.post(
|
||||||
|
reverse("authentik_api:group-list"),
|
||||||
|
data={"name": generate_id(), "is_superuser": False},
|
||||||
|
)
|
||||||
|
self.assertEqual(res.status_code, 201)
|
||||||
|
|
||||||
def test_superuser_update_no_perm(self):
|
def test_superuser_update_no_perm(self):
|
||||||
"""Test updating a superuser group without permission"""
|
"""Test updating a superuser group without permission"""
|
||||||
group = Group.objects.create(name=generate_id(), is_superuser=True)
|
group = Group.objects.create(name=generate_id(), is_superuser=True)
|
||||||
|
@ -13,7 +13,10 @@ from authentik.core.models import (
|
|||||||
TokenIntents,
|
TokenIntents,
|
||||||
User,
|
User,
|
||||||
)
|
)
|
||||||
from authentik.core.tasks import clean_expired_models, clean_temporary_users
|
from authentik.core.tasks import (
|
||||||
|
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
|
||||||
|
|
||||||
|
@ -132,13 +132,14 @@ class LicenseKey:
|
|||||||
"""Get a summarized version of all (not expired) licenses"""
|
"""Get a summarized version of all (not expired) licenses"""
|
||||||
total = LicenseKey(get_license_aud(), 0, "Summarized license", 0, 0)
|
total = LicenseKey(get_license_aud(), 0, "Summarized license", 0, 0)
|
||||||
for lic in License.objects.all():
|
for lic in License.objects.all():
|
||||||
total.internal_users += lic.internal_users
|
if lic.is_valid:
|
||||||
total.external_users += lic.external_users
|
total.internal_users += lic.internal_users
|
||||||
|
total.external_users += lic.external_users
|
||||||
|
total.license_flags.extend(lic.status.license_flags)
|
||||||
exp_ts = int(mktime(lic.expiry.timetuple()))
|
exp_ts = int(mktime(lic.expiry.timetuple()))
|
||||||
if total.exp == 0:
|
if total.exp == 0:
|
||||||
total.exp = exp_ts
|
total.exp = exp_ts
|
||||||
total.exp = max(total.exp, exp_ts)
|
total.exp = max(total.exp, exp_ts)
|
||||||
total.license_flags.extend(lic.status.license_flags)
|
|
||||||
return total
|
return total
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
@ -39,6 +39,10 @@ class License(SerializerModel):
|
|||||||
internal_users = models.BigIntegerField()
|
internal_users = models.BigIntegerField()
|
||||||
external_users = models.BigIntegerField()
|
external_users = models.BigIntegerField()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_valid(self) -> bool:
|
||||||
|
return self.expiry >= now()
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def serializer(self) -> type[BaseSerializer]:
|
def serializer(self) -> type[BaseSerializer]:
|
||||||
from authentik.enterprise.api import LicenseSerializer
|
from authentik.enterprise.api import LicenseSerializer
|
||||||
|
0
authentik/enterprise/policies/__init__.py
Normal file
0
authentik/enterprise/policies/__init__.py
Normal file
27
authentik/enterprise/policies/unique_password/api.py
Normal file
27
authentik/enterprise/policies/unique_password/api.py
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
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"]
|
10
authentik/enterprise/policies/unique_password/apps.py
Normal file
10
authentik/enterprise/policies/unique_password/apps.py
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
"""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
|
@ -0,0 +1,81 @@
|
|||||||
|
# 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",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
151
authentik/enterprise/policies/unique_password/models.py
Normal file
151
authentik/enterprise/policies/unique_password/models.py
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
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,
|
||||||
|
)
|
20
authentik/enterprise/policies/unique_password/settings.py
Normal file
20
authentik/enterprise/policies/unique_password/settings.py
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
"""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"},
|
||||||
|
},
|
||||||
|
}
|
23
authentik/enterprise/policies/unique_password/signals.py
Normal file
23
authentik/enterprise/policies/unique_password/signals.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
"""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)
|
66
authentik/enterprise/policies/unique_password/tasks.py
Normal file
66
authentik/enterprise/policies/unique_password/tasks.py
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
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")
|
@ -0,0 +1,108 @@
|
|||||||
|
"""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.",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
)
|
@ -0,0 +1,77 @@
|
|||||||
|
"""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)
|
@ -0,0 +1,90 @@
|
|||||||
|
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",
|
||||||
|
)
|
@ -0,0 +1,178 @@
|
|||||||
|
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())
|
7
authentik/enterprise/policies/unique_password/urls.py
Normal file
7
authentik/enterprise/policies/unique_password/urls.py
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
"""API URLs"""
|
||||||
|
|
||||||
|
from authentik.enterprise.policies.unique_password.api import UniquePasswordPolicyViewSet
|
||||||
|
|
||||||
|
api_urlpatterns = [
|
||||||
|
("policies/unique_password", UniquePasswordPolicyViewSet),
|
||||||
|
]
|
@ -14,6 +14,7 @@ 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",
|
||||||
|
@ -8,6 +8,7 @@ from django.test import TestCase
|
|||||||
from django.utils.timezone import now
|
from django.utils.timezone import now
|
||||||
from rest_framework.exceptions import ValidationError
|
from rest_framework.exceptions import ValidationError
|
||||||
|
|
||||||
|
from authentik.core.models import User
|
||||||
from authentik.enterprise.license import LicenseKey
|
from authentik.enterprise.license import LicenseKey
|
||||||
from authentik.enterprise.models import (
|
from authentik.enterprise.models import (
|
||||||
THRESHOLD_READ_ONLY_WEEKS,
|
THRESHOLD_READ_ONLY_WEEKS,
|
||||||
@ -71,9 +72,9 @@ class TestEnterpriseLicense(TestCase):
|
|||||||
)
|
)
|
||||||
def test_valid_multiple(self):
|
def test_valid_multiple(self):
|
||||||
"""Check license verification"""
|
"""Check license verification"""
|
||||||
lic = License.objects.create(key=generate_id())
|
lic = License.objects.create(key=generate_id(), expiry=expiry_valid)
|
||||||
self.assertTrue(lic.status.status().is_valid)
|
self.assertTrue(lic.status.status().is_valid)
|
||||||
lic2 = License.objects.create(key=generate_id())
|
lic2 = License.objects.create(key=generate_id(), expiry=expiry_valid)
|
||||||
self.assertTrue(lic2.status.status().is_valid)
|
self.assertTrue(lic2.status.status().is_valid)
|
||||||
total = LicenseKey.get_total()
|
total = LicenseKey.get_total()
|
||||||
self.assertEqual(total.internal_users, 200)
|
self.assertEqual(total.internal_users, 200)
|
||||||
@ -232,7 +233,9 @@ class TestEnterpriseLicense(TestCase):
|
|||||||
)
|
)
|
||||||
def test_expiry_expired(self):
|
def test_expiry_expired(self):
|
||||||
"""Check license verification"""
|
"""Check license verification"""
|
||||||
License.objects.create(key=generate_id())
|
User.objects.all().delete()
|
||||||
|
License.objects.all().delete()
|
||||||
|
License.objects.create(key=generate_id(), expiry=expiry_expired)
|
||||||
self.assertEqual(LicenseKey.get_total().summary().status, LicenseUsageStatus.EXPIRED)
|
self.assertEqual(LicenseKey.get_total().summary().status, LicenseUsageStatus.EXPIRED)
|
||||||
|
|
||||||
@patch(
|
@patch(
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
<link rel="stylesheet" type="text/css" href="{% static 'dist/sfe/bootstrap.min.css' %}">
|
<link rel="stylesheet" type="text/css" href="{% static 'dist/sfe/bootstrap.min.css' %}">
|
||||||
<meta name="sentry-trace" content="{{ sentry_trace }}" />
|
<meta name="sentry-trace" content="{{ sentry_trace }}" />
|
||||||
|
<link rel="prefetch" href="{{ flow_background_url }}" />
|
||||||
{% include "base/header_js.html" %}
|
{% include "base/header_js.html" %}
|
||||||
<style>
|
<style>
|
||||||
html,
|
html,
|
||||||
@ -22,7 +23,7 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
body {
|
body {
|
||||||
background-image: url("{{ flow.background_url }}");
|
background-image: url("{{ flow_background_url }}");
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-size: cover;
|
background-size: cover;
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
{% block head_before %}
|
{% block head_before %}
|
||||||
{{ block.super }}
|
{{ block.super }}
|
||||||
<link rel="prefetch" href="{{ flow.background_url }}" />
|
<link rel="prefetch" href="{{ flow_background_url }}" />
|
||||||
{% if flow.compatibility_mode and not inspector %}
|
{% if flow.compatibility_mode and not inspector %}
|
||||||
<script>ShadyDOM = { force: !navigator.webdriver };</script>
|
<script>ShadyDOM = { force: !navigator.webdriver };</script>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@ -21,7 +21,7 @@ window.authentik.flow = {
|
|||||||
<script src="{% versioned_script 'dist/flow/FlowInterface-%v.js' %}" type="module"></script>
|
<script src="{% versioned_script 'dist/flow/FlowInterface-%v.js' %}" type="module"></script>
|
||||||
<style>
|
<style>
|
||||||
:root {
|
:root {
|
||||||
--ak-flow-background: url("{{ flow.background_url }}");
|
--ak-flow-background: url("{{ flow_background_url }}");
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -69,7 +69,6 @@ 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"
|
||||||
|
|
||||||
@ -454,7 +453,6 @@ 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,8 +6,7 @@ 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, FlowDesignation
|
from authentik.flows.models import Flow
|
||||||
from authentik.flows.views.executor import SESSION_KEY_AUTH_STARTED
|
|
||||||
|
|
||||||
|
|
||||||
class FlowInterfaceView(InterfaceView):
|
class FlowInterfaceView(InterfaceView):
|
||||||
@ -16,12 +15,7 @@ class FlowInterfaceView(InterfaceView):
|
|||||||
def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
|
def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
|
||||||
flow = get_object_or_404(Flow, slug=self.kwargs.get("flow_slug"))
|
flow = get_object_or_404(Flow, slug=self.kwargs.get("flow_slug"))
|
||||||
kwargs["flow"] = flow
|
kwargs["flow"] = flow
|
||||||
if (
|
kwargs["flow_background_url"] = flow.background_url(self.request)
|
||||||
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)
|
||||||
|
|
||||||
|
@ -363,6 +363,9 @@ def django_db_config(config: ConfigLoader | None = None) -> dict:
|
|||||||
pool_options = config.get_dict_from_b64_json("postgresql.pool_options", True)
|
pool_options = config.get_dict_from_b64_json("postgresql.pool_options", True)
|
||||||
if not pool_options:
|
if not pool_options:
|
||||||
pool_options = True
|
pool_options = True
|
||||||
|
# FIXME: Temporarily force pool to be deactivated.
|
||||||
|
# See https://github.com/goauthentik/authentik/issues/14320
|
||||||
|
pool_options = False
|
||||||
|
|
||||||
db = {
|
db = {
|
||||||
"default": {
|
"default": {
|
||||||
|
@ -494,86 +494,88 @@ class TestConfig(TestCase):
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_db_pool(self):
|
# FIXME: Temporarily force pool to be deactivated.
|
||||||
"""Test DB Config with pool"""
|
# See https://github.com/goauthentik/authentik/issues/14320
|
||||||
config = ConfigLoader()
|
# def test_db_pool(self):
|
||||||
config.set("postgresql.host", "foo")
|
# """Test DB Config with pool"""
|
||||||
config.set("postgresql.name", "foo")
|
# config = ConfigLoader()
|
||||||
config.set("postgresql.user", "foo")
|
# config.set("postgresql.host", "foo")
|
||||||
config.set("postgresql.password", "foo")
|
# config.set("postgresql.name", "foo")
|
||||||
config.set("postgresql.port", "foo")
|
# config.set("postgresql.user", "foo")
|
||||||
config.set("postgresql.test.name", "foo")
|
# config.set("postgresql.password", "foo")
|
||||||
config.set("postgresql.use_pool", True)
|
# config.set("postgresql.port", "foo")
|
||||||
conf = django_db_config(config)
|
# config.set("postgresql.test.name", "foo")
|
||||||
self.assertEqual(
|
# config.set("postgresql.use_pool", True)
|
||||||
conf,
|
# conf = django_db_config(config)
|
||||||
{
|
# self.assertEqual(
|
||||||
"default": {
|
# conf,
|
||||||
"ENGINE": "authentik.root.db",
|
# {
|
||||||
"HOST": "foo",
|
# "default": {
|
||||||
"NAME": "foo",
|
# "ENGINE": "authentik.root.db",
|
||||||
"OPTIONS": {
|
# "HOST": "foo",
|
||||||
"pool": True,
|
# "NAME": "foo",
|
||||||
"sslcert": None,
|
# "OPTIONS": {
|
||||||
"sslkey": None,
|
# "pool": True,
|
||||||
"sslmode": None,
|
# "sslcert": None,
|
||||||
"sslrootcert": None,
|
# "sslkey": None,
|
||||||
},
|
# "sslmode": None,
|
||||||
"PASSWORD": "foo",
|
# "sslrootcert": None,
|
||||||
"PORT": "foo",
|
# },
|
||||||
"TEST": {"NAME": "foo"},
|
# "PASSWORD": "foo",
|
||||||
"USER": "foo",
|
# "PORT": "foo",
|
||||||
"CONN_MAX_AGE": 0,
|
# "TEST": {"NAME": "foo"},
|
||||||
"CONN_HEALTH_CHECKS": False,
|
# "USER": "foo",
|
||||||
"DISABLE_SERVER_SIDE_CURSORS": False,
|
# "CONN_MAX_AGE": 0,
|
||||||
}
|
# "CONN_HEALTH_CHECKS": False,
|
||||||
},
|
# "DISABLE_SERVER_SIDE_CURSORS": False,
|
||||||
)
|
# }
|
||||||
|
# },
|
||||||
|
# )
|
||||||
|
|
||||||
def test_db_pool_options(self):
|
# def test_db_pool_options(self):
|
||||||
"""Test DB Config with pool"""
|
# """Test DB Config with pool"""
|
||||||
config = ConfigLoader()
|
# config = ConfigLoader()
|
||||||
config.set("postgresql.host", "foo")
|
# config.set("postgresql.host", "foo")
|
||||||
config.set("postgresql.name", "foo")
|
# config.set("postgresql.name", "foo")
|
||||||
config.set("postgresql.user", "foo")
|
# config.set("postgresql.user", "foo")
|
||||||
config.set("postgresql.password", "foo")
|
# config.set("postgresql.password", "foo")
|
||||||
config.set("postgresql.port", "foo")
|
# config.set("postgresql.port", "foo")
|
||||||
config.set("postgresql.test.name", "foo")
|
# config.set("postgresql.test.name", "foo")
|
||||||
config.set("postgresql.use_pool", True)
|
# config.set("postgresql.use_pool", True)
|
||||||
config.set(
|
# config.set(
|
||||||
"postgresql.pool_options",
|
# "postgresql.pool_options",
|
||||||
base64.b64encode(
|
# base64.b64encode(
|
||||||
dumps(
|
# dumps(
|
||||||
{
|
# {
|
||||||
"max_size": 15,
|
# "max_size": 15,
|
||||||
}
|
# }
|
||||||
).encode()
|
# ).encode()
|
||||||
).decode(),
|
# ).decode(),
|
||||||
)
|
# )
|
||||||
conf = django_db_config(config)
|
# conf = django_db_config(config)
|
||||||
self.assertEqual(
|
# self.assertEqual(
|
||||||
conf,
|
# conf,
|
||||||
{
|
# {
|
||||||
"default": {
|
# "default": {
|
||||||
"ENGINE": "authentik.root.db",
|
# "ENGINE": "authentik.root.db",
|
||||||
"HOST": "foo",
|
# "HOST": "foo",
|
||||||
"NAME": "foo",
|
# "NAME": "foo",
|
||||||
"OPTIONS": {
|
# "OPTIONS": {
|
||||||
"pool": {
|
# "pool": {
|
||||||
"max_size": 15,
|
# "max_size": 15,
|
||||||
},
|
# },
|
||||||
"sslcert": None,
|
# "sslcert": None,
|
||||||
"sslkey": None,
|
# "sslkey": None,
|
||||||
"sslmode": None,
|
# "sslmode": None,
|
||||||
"sslrootcert": None,
|
# "sslrootcert": None,
|
||||||
},
|
# },
|
||||||
"PASSWORD": "foo",
|
# "PASSWORD": "foo",
|
||||||
"PORT": "foo",
|
# "PORT": "foo",
|
||||||
"TEST": {"NAME": "foo"},
|
# "TEST": {"NAME": "foo"},
|
||||||
"USER": "foo",
|
# "USER": "foo",
|
||||||
"CONN_MAX_AGE": 0,
|
# "CONN_MAX_AGE": 0,
|
||||||
"CONN_HEALTH_CHECKS": False,
|
# "CONN_HEALTH_CHECKS": False,
|
||||||
"DISABLE_SERVER_SIDE_CURSORS": False,
|
# "DISABLE_SERVER_SIDE_CURSORS": False,
|
||||||
}
|
# }
|
||||||
},
|
# },
|
||||||
)
|
# )
|
||||||
|
@ -74,6 +74,8 @@ 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,4 +1,8 @@
|
|||||||
"""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
|
||||||
|
|
||||||
@ -35,4 +39,3 @@ class AuthentikPoliciesConfig(ManagedAppConfig):
|
|||||||
label = "authentik_policies"
|
label = "authentik_policies"
|
||||||
verbose_name = "authentik Policies"
|
verbose_name = "authentik Policies"
|
||||||
default = True
|
default = True
|
||||||
mountpoint = "policy/"
|
|
||||||
|
@ -52,6 +52,13 @@ 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."""
|
||||||
|
|
||||||
@ -148,6 +155,9 @@ 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,4 +2,6 @@
|
|||||||
|
|
||||||
from authentik.policies.password.api import PasswordPolicyViewSet
|
from authentik.policies.password.api import PasswordPolicyViewSet
|
||||||
|
|
||||||
api_urlpatterns = [("policies/password", PasswordPolicyViewSet)]
|
api_urlpatterns = [
|
||||||
|
("policies/password", PasswordPolicyViewSet),
|
||||||
|
]
|
||||||
|
@ -1,89 +0,0 @@
|
|||||||
{% 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 %}
|
|
@ -1,121 +0,0 @@
|
|||||||
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,14 +1,7 @@
|
|||||||
"""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,37 +1,23 @@
|
|||||||
"""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, QueryDict
|
from django.http import HttpRequest, HttpResponse
|
||||||
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 TemplateView, View
|
from django.views.generic.base import 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.models import Flow, FlowDesignation
|
from authentik.flows.views.executor import SESSION_KEY_APPLICATION_PRE, SESSION_KEY_POST
|
||||||
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):
|
||||||
@ -139,65 +125,3 @@ 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 BufferedPolicyAccessView, RequestValidationError
|
from authentik.policies.views import PolicyAccessView, 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(BufferedPolicyAccessView):
|
class AuthorizationFlowInitView(PolicyAccessView):
|
||||||
"""OAuth2 Flow initializer, checks access to application and starts flow"""
|
"""OAuth2 Flow initializer, checks access to application and starts flow"""
|
||||||
|
|
||||||
params: OAuthAuthorizationParams
|
params: OAuthAuthorizationParams
|
||||||
|
234
authentik/providers/proxy/controllers/k8s/httproute.py
Normal file
234
authentik/providers/proxy/controllers/k8s/httproute.py
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
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,6 +3,7 @@
|
|||||||
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
|
||||||
|
|
||||||
@ -18,8 +19,10 @@ 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 BufferedPolicyAccessView
|
from authentik.policies.views import PolicyAccessView
|
||||||
from authentik.providers.rac.models import ConnectionToken, Endpoint, RACProvider
|
from authentik.providers.rac.models import ConnectionToken, Endpoint, RACProvider
|
||||||
|
|
||||||
|
|
||||||
class RACStartView(BufferedPolicyAccessView):
|
class RACStartView(PolicyAccessView):
|
||||||
"""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 BufferedPolicyAccessView
|
from authentik.policies.views import PolicyAccessView
|
||||||
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(BufferedPolicyAccessView):
|
class SAMLSSOView(PolicyAccessView):
|
||||||
"""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(BufferedPolicyAccessView):
|
|||||||
|
|
||||||
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 BufferedPolicyAccessView's dispatch"""
|
override .dispatch easily because PolicyAccessView's dispatch"""
|
||||||
return self.get(request, application_slug)
|
return self.get(request, application_slug)
|
||||||
|
|
||||||
|
|
||||||
|
@ -99,6 +99,7 @@ class RBACPermissionViewSet(ReadOnlyModelViewSet):
|
|||||||
filterset_class = PermissionFilter
|
filterset_class = PermissionFilter
|
||||||
permission_classes = [IsAuthenticated]
|
permission_classes = [IsAuthenticated]
|
||||||
search_fields = [
|
search_fields = [
|
||||||
|
"name",
|
||||||
"codename",
|
"codename",
|
||||||
"content_type__model",
|
"content_type__model",
|
||||||
"content_type__app_label",
|
"content_type__app_label",
|
||||||
|
File diff suppressed because one or more lines are too long
@ -171,7 +171,8 @@ 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 username is taken already."""
|
"""Return a `clean_` method for `field`. Clean method checks if the password meets configured
|
||||||
|
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,7 +4,13 @@ from unittest.mock import patch
|
|||||||
|
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
from authentik.core.models import USER_ATTRIBUTE_SOURCES, Group, Source, User, UserSourceConnection
|
from authentik.core.models import (
|
||||||
|
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.2.4 Blueprint schema",
|
"title": "authentik 2025.4.1 Blueprint schema",
|
||||||
"required": [
|
"required": [
|
||||||
"version",
|
"version",
|
||||||
"entries"
|
"entries"
|
||||||
@ -3641,6 +3641,46 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"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": [
|
||||||
@ -4822,6 +4862,7 @@
|
|||||||
"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",
|
||||||
@ -4929,6 +4970,7 @@
|
|||||||
"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",
|
||||||
@ -7084,6 +7126,14 @@
|
|||||||
"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",
|
||||||
@ -13784,6 +13834,14 @@
|
|||||||
"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",
|
||||||
@ -14468,6 +14526,61 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"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.2.4}
|
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.4.1}
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
command: server
|
command: server
|
||||||
environment:
|
environment:
|
||||||
@ -55,7 +55,7 @@ services:
|
|||||||
redis:
|
redis:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
worker:
|
worker:
|
||||||
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.2.4}
|
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2025.4.1}
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
command: worker
|
command: worker
|
||||||
environment:
|
environment:
|
||||||
|
6
go.mod
6
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.10
|
github.com/go-ldap/ldap/v3 v3.4.11
|
||||||
github.com/go-openapi/runtime v0.28.0
|
github.com/go-openapi/runtime v0.28.0
|
||||||
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
|
||||||
@ -27,7 +27,7 @@ require (
|
|||||||
github.com/spf13/cobra v1.9.1
|
github.com/spf13/cobra v1.9.1
|
||||||
github.com/stretchr/testify v1.10.0
|
github.com/stretchr/testify v1.10.0
|
||||||
github.com/wwt/guac v1.3.2
|
github.com/wwt/guac v1.3.2
|
||||||
goauthentik.io/api/v3 v3.2025024.7
|
goauthentik.io/api/v3 v3.2025024.9
|
||||||
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.7 // indirect
|
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // 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
|
||||||
|
82
go.sum
82
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.7 h1:DTX+lbVTWaTw1hQ+PbZPlnDZPEIs0SS/GCZAl535dDk=
|
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/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||||
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
|
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
|
||||||
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.10 h1:ot/iwPOhfpNVgB1o+AVXljizWZ9JTp7YF5oeyONmcJU=
|
github.com/go-ldap/ldap/v3 v3.4.11 h1:4k0Yxweg+a3OyBLjdYn5OKglv18JNvfDykSoI8bW0gU=
|
||||||
github.com/go-ldap/ldap/v3 v3.4.10/go.mod h1:JXh4Uxgi40P6E9rdsYqpUtbW46D9UTjJ9QSwGRznplY=
|
github.com/go-ldap/ldap/v3 v3.4.11/go.mod h1:bY7t0FLK8OAVpp/vV6sSlpz3EQDGcQwc8pF0ujLgKvM=
|
||||||
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,7 +148,6 @@ 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=
|
||||||
@ -172,16 +171,13 @@ 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=
|
||||||
@ -266,15 +262,10 @@ 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=
|
||||||
@ -282,7 +273,6 @@ 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=
|
||||||
@ -300,20 +290,14 @@ go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y
|
|||||||
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
|
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
|
||||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||||
goauthentik.io/api/v3 v3.2025024.7 h1:OOBuyLzv+l5rtvrOYzoDs6Hy9cIfkE5sewRqR5ThSRc=
|
goauthentik.io/api/v3 v3.2025024.9 h1:i3tbkyotE32ZpJ729BsPWTuLQUdtZ54Li4aP1amZzsM=
|
||||||
goauthentik.io/api/v3 v3.2025024.7/go.mod h1:zz+mEZg8rY/7eEjkMGWJ2DnGqk+zqxuybGCGrR2O4Kw=
|
goauthentik.io/api/v3 v3.2025024.9/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=
|
||||||
@ -348,11 +332,6 @@ 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=
|
||||||
@ -379,17 +358,8 @@ 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.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
||||||
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=
|
||||||
@ -406,12 +376,6 @@ 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=
|
||||||
@ -440,40 +404,14 @@ 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=
|
||||||
@ -519,10 +457,6 @@ 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.2.4"
|
const VERSION = "2025.4.1"
|
||||||
|
@ -56,6 +56,7 @@ EXPOSE 3389 6636 9300
|
|||||||
|
|
||||||
USER 1000
|
USER 1000
|
||||||
|
|
||||||
ENV GOFIPS=1
|
ENV TMPDIR=/dev/shm/ \
|
||||||
|
GOFIPS=1
|
||||||
|
|
||||||
ENTRYPOINT ["/ldap"]
|
ENTRYPOINT ["/ldap"]
|
||||||
|
@ -62,7 +62,8 @@ function prepare_debug {
|
|||||||
export DEBIAN_FRONTEND=noninteractive
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
apt-get update
|
apt-get update
|
||||||
apt-get install -y --no-install-recommends krb5-kdc krb5-user krb5-admin-server libkrb5-dev gcc
|
apt-get install -y --no-install-recommends krb5-kdc krb5-user krb5-admin-server libkrb5-dev gcc
|
||||||
VIRTUAL_ENV=/ak-root/.venv uv sync --frozen
|
source "${VENV_PATH}/bin/activate"
|
||||||
|
uv sync --active --frozen
|
||||||
touch /unittest.xml
|
touch /unittest.xml
|
||||||
chown authentik:authentik /unittest.xml
|
chown authentik:authentik /unittest.xml
|
||||||
}
|
}
|
||||||
@ -96,6 +97,7 @@ elif [[ "$1" == "test-all" ]]; then
|
|||||||
elif [[ "$1" == "healthcheck" ]]; then
|
elif [[ "$1" == "healthcheck" ]]; then
|
||||||
run_authentik healthcheck $(cat $MODE_FILE)
|
run_authentik healthcheck $(cat $MODE_FILE)
|
||||||
elif [[ "$1" == "dump_config" ]]; then
|
elif [[ "$1" == "dump_config" ]]; then
|
||||||
|
shift
|
||||||
exec python -m authentik.lib.config $@
|
exec python -m authentik.lib.config $@
|
||||||
elif [[ "$1" == "debug" ]]; then
|
elif [[ "$1" == "debug" ]]; then
|
||||||
exec sleep infinity
|
exec sleep infinity
|
||||||
|
8
lifecycle/aws/package-lock.json
generated
8
lifecycle/aws/package-lock.json
generated
@ -9,7 +9,7 @@
|
|||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"aws-cdk": "^2.1010.0",
|
"aws-cdk": "^2.1012.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.1010.0",
|
"version": "2.1012.0",
|
||||||
"resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1010.0.tgz",
|
"resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1012.0.tgz",
|
||||||
"integrity": "sha512-kYNzBXVUZoRrTuYxRRA2Loz/Uvay0MqHobg8KPZaWylIbw/meUDgtoATRNt+stOdJ9PHODTjWmlDKI+2/KoF+w==",
|
"integrity": "sha512-C6jSWkqP0hkY2Cs300VJHjspmTXDTMfB813kwZvRbd/OsKBfTBJBbYU16VoLAp1LVEOnQMf8otSlaSgzVF0X9A==",
|
||||||
"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.1010.0",
|
"aws-cdk": "^2.1012.0",
|
||||||
"cross-env": "^7.0.3"
|
"cross-env": "^7.0.3"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ Parameters:
|
|||||||
Description: authentik Docker image
|
Description: authentik Docker image
|
||||||
AuthentikVersion:
|
AuthentikVersion:
|
||||||
Type: String
|
Type: String
|
||||||
Default: 2025.2.4
|
Default: 2025.4.1
|
||||||
Description: authentik Docker image tag
|
Description: authentik Docker image tag
|
||||||
AuthentikServerCPU:
|
AuthentikServerCPU:
|
||||||
Type: Number
|
Type: Number
|
||||||
|
@ -3,7 +3,7 @@ from lifecycle.migrate import BaseMigration
|
|||||||
|
|
||||||
SQL_STATEMENT = """
|
SQL_STATEMENT = """
|
||||||
BEGIN TRANSACTION;
|
BEGIN TRANSACTION;
|
||||||
ALTER TABLE authentik_tenants_tenant RENAME TO authentik_brands_brand;
|
ALTER TABLE IF EXISTS 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,7 +8,6 @@
|
|||||||
# Jens L. <jens@goauthentik.io>, 2022
|
# Jens L. <jens@goauthentik.io>, 2022
|
||||||
# Lars Lehmann <lars@lars-lehmann.net>, 2023
|
# Lars Lehmann <lars@lars-lehmann.net>, 2023
|
||||||
# Johannes —/—, 2023
|
# Johannes —/—, 2023
|
||||||
# Dominic Wagner <mail@dominic-wagner.de>, 2023
|
|
||||||
# fde4f289d99ed356ff5cfdb762dc44aa_a8a971d, 2023
|
# fde4f289d99ed356ff5cfdb762dc44aa_a8a971d, 2023
|
||||||
# Christian Foellmann <foellmann@foe-services.de>, 2023
|
# Christian Foellmann <foellmann@foe-services.de>, 2023
|
||||||
# kidhab, 2023
|
# kidhab, 2023
|
||||||
@ -30,17 +29,18 @@
|
|||||||
# Alexander Möbius, 2025
|
# Alexander Möbius, 2025
|
||||||
# Jonas, 2025
|
# Jonas, 2025
|
||||||
# Niklas Kroese, 2025
|
# Niklas Kroese, 2025
|
||||||
# 97cce0ae0cad2a2cc552d3165d04643e_de3d740, 2025
|
|
||||||
# datenschmutz, 2025
|
# datenschmutz, 2025
|
||||||
|
# 97cce0ae0cad2a2cc552d3165d04643e_de3d740, 2025
|
||||||
|
# Dominic Wagner <mail@dominic-wagner.de>, 2025
|
||||||
#
|
#
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-04-11 00:10+0000\n"
|
"POT-Creation-Date: 2025-04-23 09:00+0000\n"
|
||||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||||
"Last-Translator: datenschmutz, 2025\n"
|
"Last-Translator: Dominic Wagner <mail@dominic-wagner.de>, 2025\n"
|
||||||
"Language-Team: German (https://app.transifex.com/authentik/teams/119923/de/)\n"
|
"Language-Team: German (https://app.transifex.com/authentik/teams/119923/de/)\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
@ -214,6 +214,7 @@ msgid "User's display name."
|
|||||||
msgstr "Anzeigename"
|
msgstr "Anzeigename"
|
||||||
|
|
||||||
#: authentik/core/models.py authentik/providers/oauth2/models.py
|
#: authentik/core/models.py authentik/providers/oauth2/models.py
|
||||||
|
#: authentik/rbac/models.py
|
||||||
msgid "User"
|
msgid "User"
|
||||||
msgstr "Benutzer"
|
msgstr "Benutzer"
|
||||||
|
|
||||||
@ -402,6 +403,18 @@ msgstr "Eigenschaft"
|
|||||||
msgid "Property Mappings"
|
msgid "Property Mappings"
|
||||||
msgstr "Eigenschaften"
|
msgstr "Eigenschaften"
|
||||||
|
|
||||||
|
#: authentik/core/models.py
|
||||||
|
msgid "session data"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/core/models.py
|
||||||
|
msgid "Session"
|
||||||
|
msgstr "Sitzung"
|
||||||
|
|
||||||
|
#: authentik/core/models.py
|
||||||
|
msgid "Sessions"
|
||||||
|
msgstr "Sitzungen"
|
||||||
|
|
||||||
#: authentik/core/models.py
|
#: authentik/core/models.py
|
||||||
msgid "Authenticated Session"
|
msgid "Authenticated Session"
|
||||||
msgstr "Authentifizierte Sitzung"
|
msgstr "Authentifizierte Sitzung"
|
||||||
@ -511,6 +524,38 @@ msgstr "Lizenzverwendung"
|
|||||||
msgid "License Usage Records"
|
msgid "License Usage Records"
|
||||||
msgstr "Lizenzverwendung Aufzeichnungen"
|
msgstr "Lizenzverwendung Aufzeichnungen"
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
#: authentik/policies/password/models.py
|
||||||
|
msgid "Field key to check, field keys defined in Prompt stages are available."
|
||||||
|
msgstr ""
|
||||||
|
"Zu prüfender Feldschlüssel, die in den Aufforderungsstufen definierten "
|
||||||
|
"Feldschlüssel sind verfügbar."
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "Number of passwords to check against."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
#: authentik/policies/password/models.py
|
||||||
|
msgid "Password not set in context"
|
||||||
|
msgstr "Passwort nicht im Kontext festgelegt"
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "This password has been used previously. Please choose a different one."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "Password Uniqueness Policy"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "Password Uniqueness Policies"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "User Password History"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/enterprise/policy.py
|
#: authentik/enterprise/policy.py
|
||||||
msgid "Enterprise required to access this feature."
|
msgid "Enterprise required to access this feature."
|
||||||
msgstr "Enterprise ist erforderlich, um auf diese Funktion zuzugreifen."
|
msgstr "Enterprise ist erforderlich, um auf diese Funktion zuzugreifen."
|
||||||
@ -1303,12 +1348,6 @@ msgstr "Richtlinien Cache Metriken anzeigen"
|
|||||||
msgid "Clear Policy's cache metrics"
|
msgid "Clear Policy's cache metrics"
|
||||||
msgstr "Richtlinien Cache Metriken löschen"
|
msgstr "Richtlinien Cache Metriken löschen"
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
|
||||||
msgid "Field key to check, field keys defined in Prompt stages are available."
|
|
||||||
msgstr ""
|
|
||||||
"Zu prüfender Feldschlüssel, die in den Aufforderungsstufen definierten "
|
|
||||||
"Feldschlüssel sind verfügbar."
|
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
#: authentik/policies/password/models.py
|
||||||
msgid "How many times the password hash is allowed to be on haveibeenpwned"
|
msgid "How many times the password hash is allowed to be on haveibeenpwned"
|
||||||
msgstr "Wie häufig der Passwort-Hash auf haveibeenpwned vertreten sein darf"
|
msgstr "Wie häufig der Passwort-Hash auf haveibeenpwned vertreten sein darf"
|
||||||
@ -1320,10 +1359,6 @@ msgstr ""
|
|||||||
"Die Richtlinie wird verweigert, wenn die zxcvbn-Bewertung gleich oder "
|
"Die Richtlinie wird verweigert, wenn die zxcvbn-Bewertung gleich oder "
|
||||||
"kleiner diesem Wert ist."
|
"kleiner diesem Wert ist."
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
|
||||||
msgid "Password not set in context"
|
|
||||||
msgstr "Passwort nicht im Kontext festgelegt"
|
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
#: authentik/policies/password/models.py
|
||||||
msgid "Invalid password."
|
msgid "Invalid password."
|
||||||
msgstr "Ungültiges Passwort."
|
msgstr "Ungültiges Passwort."
|
||||||
@ -1365,20 +1400,6 @@ msgstr "Reputationswert"
|
|||||||
msgid "Reputation Scores"
|
msgid "Reputation Scores"
|
||||||
msgstr "Reputationswert"
|
msgstr "Reputationswert"
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/buffer.html
|
|
||||||
msgid "Waiting for authentication..."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/buffer.html
|
|
||||||
msgid ""
|
|
||||||
"You're already authenticating in another tab. This page will refresh once "
|
|
||||||
"authentication is completed."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/buffer.html
|
|
||||||
msgid "Authenticate in this tab"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/denied.html
|
#: authentik/policies/templates/policies/denied.html
|
||||||
msgid "Permission denied"
|
msgid "Permission denied"
|
||||||
msgstr "Erlaubnis verweigert"
|
msgstr "Erlaubnis verweigert"
|
||||||
@ -2208,6 +2229,10 @@ msgstr "Rolle"
|
|||||||
msgid "Roles"
|
msgid "Roles"
|
||||||
msgstr "Rollen"
|
msgstr "Rollen"
|
||||||
|
|
||||||
|
#: authentik/rbac/models.py
|
||||||
|
msgid "Initial Permissions"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/rbac/models.py
|
#: authentik/rbac/models.py
|
||||||
msgid "System permission"
|
msgid "System permission"
|
||||||
msgstr "Systemberechtigung"
|
msgstr "Systemberechtigung"
|
||||||
@ -2478,6 +2503,22 @@ msgstr "LDAP Quelle Eigenschafts-Zuordnung"
|
|||||||
msgid "LDAP Source Property Mappings"
|
msgid "LDAP Source Property Mappings"
|
||||||
msgstr "LDAP Quelle Eigenschafts-Zuordnungen"
|
msgstr "LDAP Quelle Eigenschafts-Zuordnungen"
|
||||||
|
|
||||||
|
#: authentik/sources/ldap/models.py
|
||||||
|
msgid "User LDAP Source Connection"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/sources/ldap/models.py
|
||||||
|
msgid "User LDAP Source Connections"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/sources/ldap/models.py
|
||||||
|
msgid "Group LDAP Source Connection"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/sources/ldap/models.py
|
||||||
|
msgid "Group LDAP Source Connections"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/sources/ldap/signals.py
|
#: authentik/sources/ldap/signals.py
|
||||||
msgid "Password does not match Active Directory Complexity."
|
msgid "Password does not match Active Directory Complexity."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -2487,6 +2528,14 @@ msgstr ""
|
|||||||
msgid "No token received."
|
msgid "No token received."
|
||||||
msgstr "Kein Token empfangen."
|
msgstr "Kein Token empfangen."
|
||||||
|
|
||||||
|
#: authentik/sources/oauth/models.py
|
||||||
|
msgid "HTTP Basic Authentication"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/sources/oauth/models.py
|
||||||
|
msgid "Include the client ID and secret as request parameters"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/sources/oauth/models.py
|
#: authentik/sources/oauth/models.py
|
||||||
msgid "Request Token URL"
|
msgid "Request Token URL"
|
||||||
msgstr "Token-URL anfordern"
|
msgstr "Token-URL anfordern"
|
||||||
@ -2528,6 +2577,12 @@ msgstr ""
|
|||||||
msgid "Additional Scopes"
|
msgid "Additional Scopes"
|
||||||
msgstr "zusätzliche Scopes"
|
msgstr "zusätzliche Scopes"
|
||||||
|
|
||||||
|
#: authentik/sources/oauth/models.py
|
||||||
|
msgid ""
|
||||||
|
"How to perform authentication during an authorization_code token request "
|
||||||
|
"flow"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/sources/oauth/models.py
|
#: authentik/sources/oauth/models.py
|
||||||
msgid "OAuth Source"
|
msgid "OAuth Source"
|
||||||
msgstr "Outh Quelle"
|
msgstr "Outh Quelle"
|
||||||
@ -3434,6 +3489,12 @@ msgstr ""
|
|||||||
"Wenn aktiviert, wird die Phase auch dann erfolgreich abgeschlossen und "
|
"Wenn aktiviert, wird die Phase auch dann erfolgreich abgeschlossen und "
|
||||||
"fortgesetzt, wenn falsche Benutzerdaten eingegeben wurden."
|
"fortgesetzt, wenn falsche Benutzerdaten eingegeben wurden."
|
||||||
|
|
||||||
|
#: authentik/stages/identification/models.py
|
||||||
|
msgid ""
|
||||||
|
"Show the user the 'Remember me on this device' toggle, allowing repeat users"
|
||||||
|
" to skip straight to entering their password."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/stages/identification/models.py
|
#: authentik/stages/identification/models.py
|
||||||
msgid "Optional enrollment flow, which is linked at the bottom of the page."
|
msgid "Optional enrollment flow, which is linked at the bottom of the page."
|
||||||
msgstr "Optionaler Registrierungs-Flow, der unten auf der Seite verlinkt ist."
|
msgstr "Optionaler Registrierungs-Flow, der unten auf der Seite verlinkt ist."
|
||||||
@ -3826,6 +3887,14 @@ msgstr ""
|
|||||||
"Die Ereignisse werden nach dieser Dauer gelöscht (Format: "
|
"Die Ereignisse werden nach dieser Dauer gelöscht (Format: "
|
||||||
"Wochen=3;Tage=2;Stunden=3,Sekunden=2)."
|
"Wochen=3;Tage=2;Stunden=3,Sekunden=2)."
|
||||||
|
|
||||||
|
#: authentik/tenants/models.py
|
||||||
|
msgid "Reputation cannot decrease lower than this value. Zero or negative."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/tenants/models.py
|
||||||
|
msgid "Reputation cannot increase higher than this value. Zero or positive."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/tenants/models.py
|
#: authentik/tenants/models.py
|
||||||
msgid "The option configures the footer links on the flow executor pages."
|
msgid "The option configures the footer links on the flow executor pages."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -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-17 00:09+0000\n"
|
"POT-Creation-Date: 2025-04-23 09:00+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,6 +451,36 @@ msgstr ""
|
|||||||
msgid "License Usage Records"
|
msgid "License Usage Records"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
#: authentik/policies/password/models.py
|
||||||
|
msgid "Field key to check, field keys defined in Prompt stages are available."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "Number of passwords to check against."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
#: authentik/policies/password/models.py
|
||||||
|
msgid "Password not set in context"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "This password has been used previously. Please choose a different one."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "Password Uniqueness Policy"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "Password Uniqueness Policies"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "User Password History"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/enterprise/policy.py
|
#: authentik/enterprise/policy.py
|
||||||
msgid "Enterprise required to access this feature."
|
msgid "Enterprise required to access this feature."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -1175,10 +1205,6 @@ msgstr ""
|
|||||||
msgid "Clear Policy's cache metrics"
|
msgid "Clear Policy's cache metrics"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
|
||||||
msgid "Field key to check, field keys defined in Prompt stages are available."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
#: authentik/policies/password/models.py
|
||||||
msgid "How many times the password hash is allowed to be on haveibeenpwned"
|
msgid "How many times the password hash is allowed to be on haveibeenpwned"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -1188,10 +1214,6 @@ msgid ""
|
|||||||
"If the zxcvbn score is equal or less than this value, the policy will fail."
|
"If the zxcvbn score is equal or less than this value, the policy will fail."
|
||||||
msgstr ""
|
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 ""
|
||||||
@ -1233,20 +1255,6 @@ msgstr ""
|
|||||||
msgid "Reputation Scores"
|
msgid "Reputation Scores"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/buffer.html
|
|
||||||
msgid "Waiting for authentication..."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/buffer.html
|
|
||||||
msgid ""
|
|
||||||
"You're already authenticating in another tab. This page will refresh once "
|
|
||||||
"authentication is completed."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/buffer.html
|
|
||||||
msgid "Authenticate in this tab"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/denied.html
|
#: authentik/policies/templates/policies/denied.html
|
||||||
msgid "Permission denied"
|
msgid "Permission denied"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -3144,6 +3152,12 @@ msgid ""
|
|||||||
"info is entered."
|
"info is entered."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/stages/identification/models.py
|
||||||
|
msgid ""
|
||||||
|
"Show the user the 'Remember me on this device' toggle, allowing repeat users "
|
||||||
|
"to skip straight to entering their password."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/stages/identification/models.py
|
#: authentik/stages/identification/models.py
|
||||||
msgid "Optional enrollment flow, which is linked at the bottom of the page."
|
msgid "Optional enrollment flow, which is linked at the bottom of the page."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
Binary file not shown.
@ -15,7 +15,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-04-11 00:10+0000\n"
|
"POT-Creation-Date: 2025-04-23 09:00+0000\n"
|
||||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||||
"Last-Translator: Jens L. <jens@goauthentik.io>, 2025\n"
|
"Last-Translator: Jens L. <jens@goauthentik.io>, 2025\n"
|
||||||
"Language-Team: Spanish (https://app.transifex.com/authentik/teams/119923/es/)\n"
|
"Language-Team: Spanish (https://app.transifex.com/authentik/teams/119923/es/)\n"
|
||||||
@ -190,6 +190,7 @@ msgid "User's display name."
|
|||||||
msgstr "Nombre para mostrar del usuario."
|
msgstr "Nombre para mostrar del usuario."
|
||||||
|
|
||||||
#: authentik/core/models.py authentik/providers/oauth2/models.py
|
#: authentik/core/models.py authentik/providers/oauth2/models.py
|
||||||
|
#: authentik/rbac/models.py
|
||||||
msgid "User"
|
msgid "User"
|
||||||
msgstr "Usuario"
|
msgstr "Usuario"
|
||||||
|
|
||||||
@ -378,6 +379,18 @@ msgstr "Asignación de Propiedades"
|
|||||||
msgid "Property Mappings"
|
msgid "Property Mappings"
|
||||||
msgstr "Asignaciones de Propiedades"
|
msgstr "Asignaciones de Propiedades"
|
||||||
|
|
||||||
|
#: authentik/core/models.py
|
||||||
|
msgid "session data"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/core/models.py
|
||||||
|
msgid "Session"
|
||||||
|
msgstr "Sesión"
|
||||||
|
|
||||||
|
#: authentik/core/models.py
|
||||||
|
msgid "Sessions"
|
||||||
|
msgstr "Sesiones"
|
||||||
|
|
||||||
#: authentik/core/models.py
|
#: authentik/core/models.py
|
||||||
msgid "Authenticated Session"
|
msgid "Authenticated Session"
|
||||||
msgstr "Sesión autenticada"
|
msgstr "Sesión autenticada"
|
||||||
@ -485,6 +498,38 @@ msgstr "Uso de Licencias"
|
|||||||
msgid "License Usage Records"
|
msgid "License Usage Records"
|
||||||
msgstr "Registro de Uso de Licencias"
|
msgstr "Registro de Uso de Licencias"
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
#: authentik/policies/password/models.py
|
||||||
|
msgid "Field key to check, field keys defined in Prompt stages are available."
|
||||||
|
msgstr ""
|
||||||
|
"Clave de campo a verificar, las claves de campo definidas en las etapas de "
|
||||||
|
"Solicitud están disponibles."
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "Number of passwords to check against."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
#: authentik/policies/password/models.py
|
||||||
|
msgid "Password not set in context"
|
||||||
|
msgstr "La contraseña no se ha establecido en contexto"
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "This password has been used previously. Please choose a different one."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "Password Uniqueness Policy"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "Password Uniqueness Policies"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "User Password History"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/enterprise/policy.py
|
#: authentik/enterprise/policy.py
|
||||||
msgid "Enterprise required to access this feature."
|
msgid "Enterprise required to access this feature."
|
||||||
msgstr "Se requiere de Enterprise para acceder esta característica."
|
msgstr "Se requiere de Enterprise para acceder esta característica."
|
||||||
@ -1268,12 +1313,6 @@ msgstr "Ver las métricas de caché de la Política"
|
|||||||
msgid "Clear Policy's cache metrics"
|
msgid "Clear Policy's cache metrics"
|
||||||
msgstr "Borrar las métricas de caché de la Política"
|
msgstr "Borrar las métricas de caché de la Política"
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
|
||||||
msgid "Field key to check, field keys defined in Prompt stages are available."
|
|
||||||
msgstr ""
|
|
||||||
"Clave de campo a verificar, las claves de campo definidas en las etapas de "
|
|
||||||
"Solicitud están disponibles."
|
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
#: authentik/policies/password/models.py
|
||||||
msgid "How many times the password hash is allowed to be on haveibeenpwned"
|
msgid "How many times the password hash is allowed to be on haveibeenpwned"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -1287,10 +1326,6 @@ msgstr ""
|
|||||||
"Si la puntuación zxcvbn es igual o menor que este valor, la política "
|
"Si la puntuación zxcvbn es igual o menor que este valor, la política "
|
||||||
"fallará."
|
"fallará."
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
|
||||||
msgid "Password not set in context"
|
|
||||||
msgstr "La contraseña no se ha establecido en contexto"
|
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
#: authentik/policies/password/models.py
|
||||||
msgid "Invalid password."
|
msgid "Invalid password."
|
||||||
msgstr "Contraseña inválida."
|
msgstr "Contraseña inválida."
|
||||||
@ -1332,20 +1367,6 @@ msgstr "Puntuación de Reputacion"
|
|||||||
msgid "Reputation Scores"
|
msgid "Reputation Scores"
|
||||||
msgstr "Puntuaciones de Reputacion"
|
msgstr "Puntuaciones de Reputacion"
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/buffer.html
|
|
||||||
msgid "Waiting for authentication..."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/buffer.html
|
|
||||||
msgid ""
|
|
||||||
"You're already authenticating in another tab. This page will refresh once "
|
|
||||||
"authentication is completed."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/buffer.html
|
|
||||||
msgid "Authenticate in this tab"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/denied.html
|
#: authentik/policies/templates/policies/denied.html
|
||||||
msgid "Permission denied"
|
msgid "Permission denied"
|
||||||
msgstr "Permiso denegado"
|
msgstr "Permiso denegado"
|
||||||
@ -2175,6 +2196,10 @@ msgstr "Rol"
|
|||||||
msgid "Roles"
|
msgid "Roles"
|
||||||
msgstr "Roles"
|
msgstr "Roles"
|
||||||
|
|
||||||
|
#: authentik/rbac/models.py
|
||||||
|
msgid "Initial Permissions"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/rbac/models.py
|
#: authentik/rbac/models.py
|
||||||
msgid "System permission"
|
msgid "System permission"
|
||||||
msgstr "Permiso de sistema"
|
msgstr "Permiso de sistema"
|
||||||
@ -2443,6 +2468,22 @@ msgstr "Asignación de Propiedades de Fuente de LDAP"
|
|||||||
msgid "LDAP Source Property Mappings"
|
msgid "LDAP Source Property Mappings"
|
||||||
msgstr "Asignaciones de Propiedades de Fuente de LDAP"
|
msgstr "Asignaciones de Propiedades de Fuente de LDAP"
|
||||||
|
|
||||||
|
#: authentik/sources/ldap/models.py
|
||||||
|
msgid "User LDAP Source Connection"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/sources/ldap/models.py
|
||||||
|
msgid "User LDAP Source Connections"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/sources/ldap/models.py
|
||||||
|
msgid "Group LDAP Source Connection"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/sources/ldap/models.py
|
||||||
|
msgid "Group LDAP Source Connections"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/sources/ldap/signals.py
|
#: authentik/sources/ldap/signals.py
|
||||||
msgid "Password does not match Active Directory Complexity."
|
msgid "Password does not match Active Directory Complexity."
|
||||||
msgstr "La contraseña no coincide con la complejidad de Active Directory."
|
msgstr "La contraseña no coincide con la complejidad de Active Directory."
|
||||||
@ -2451,6 +2492,14 @@ msgstr "La contraseña no coincide con la complejidad de Active Directory."
|
|||||||
msgid "No token received."
|
msgid "No token received."
|
||||||
msgstr "No se recibió ningún token."
|
msgstr "No se recibió ningún token."
|
||||||
|
|
||||||
|
#: authentik/sources/oauth/models.py
|
||||||
|
msgid "HTTP Basic Authentication"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/sources/oauth/models.py
|
||||||
|
msgid "Include the client ID and secret as request parameters"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/sources/oauth/models.py
|
#: authentik/sources/oauth/models.py
|
||||||
msgid "Request Token URL"
|
msgid "Request Token URL"
|
||||||
msgstr "Solicitar URL de token"
|
msgstr "Solicitar URL de token"
|
||||||
@ -2491,6 +2540,12 @@ msgstr "URL utilizada por authentik para obtener información del usuario."
|
|||||||
msgid "Additional Scopes"
|
msgid "Additional Scopes"
|
||||||
msgstr "Alcances Adicionales"
|
msgstr "Alcances Adicionales"
|
||||||
|
|
||||||
|
#: authentik/sources/oauth/models.py
|
||||||
|
msgid ""
|
||||||
|
"How to perform authentication during an authorization_code token request "
|
||||||
|
"flow"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/sources/oauth/models.py
|
#: authentik/sources/oauth/models.py
|
||||||
msgid "OAuth Source"
|
msgid "OAuth Source"
|
||||||
msgstr "Fuente de OAuth"
|
msgstr "Fuente de OAuth"
|
||||||
@ -3407,6 +3462,12 @@ msgstr ""
|
|||||||
"Cuando está habilitado, la etapa tendrá éxito y continuará incluso cuando se"
|
"Cuando está habilitado, la etapa tendrá éxito y continuará incluso cuando se"
|
||||||
" ingrese información de usuario incorrecta."
|
" ingrese información de usuario incorrecta."
|
||||||
|
|
||||||
|
#: authentik/stages/identification/models.py
|
||||||
|
msgid ""
|
||||||
|
"Show the user the 'Remember me on this device' toggle, allowing repeat users"
|
||||||
|
" to skip straight to entering their password."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/stages/identification/models.py
|
#: authentik/stages/identification/models.py
|
||||||
msgid "Optional enrollment flow, which is linked at the bottom of the page."
|
msgid "Optional enrollment flow, which is linked at the bottom of the page."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -3794,6 +3855,14 @@ msgstr ""
|
|||||||
"Los Eventos serán eliminados después de este periodo. (Formato: "
|
"Los Eventos serán eliminados después de este periodo. (Formato: "
|
||||||
"weeks=3;days=2;hours=3,seconds=2)."
|
"weeks=3;days=2;hours=3,seconds=2)."
|
||||||
|
|
||||||
|
#: authentik/tenants/models.py
|
||||||
|
msgid "Reputation cannot decrease lower than this value. Zero or negative."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/tenants/models.py
|
||||||
|
msgid "Reputation cannot increase higher than this value. Zero or positive."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/tenants/models.py
|
#: authentik/tenants/models.py
|
||||||
msgid "The option configures the footer links on the flow executor pages."
|
msgid "The option configures the footer links on the flow executor pages."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
Binary file not shown.
@ -15,7 +15,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-04-11 00:10+0000\n"
|
"POT-Creation-Date: 2025-04-23 09:00+0000\n"
|
||||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||||
"Last-Translator: Ville Ranki, 2025\n"
|
"Last-Translator: Ville Ranki, 2025\n"
|
||||||
"Language-Team: Finnish (https://app.transifex.com/authentik/teams/119923/fi/)\n"
|
"Language-Team: Finnish (https://app.transifex.com/authentik/teams/119923/fi/)\n"
|
||||||
@ -186,6 +186,7 @@ msgid "User's display name."
|
|||||||
msgstr "Käyttäjän näytettävä nimi"
|
msgstr "Käyttäjän näytettävä nimi"
|
||||||
|
|
||||||
#: authentik/core/models.py authentik/providers/oauth2/models.py
|
#: authentik/core/models.py authentik/providers/oauth2/models.py
|
||||||
|
#: authentik/rbac/models.py
|
||||||
msgid "User"
|
msgid "User"
|
||||||
msgstr "Käyttäjä"
|
msgstr "Käyttäjä"
|
||||||
|
|
||||||
@ -371,6 +372,18 @@ msgstr "Ominaisuuskytkentä"
|
|||||||
msgid "Property Mappings"
|
msgid "Property Mappings"
|
||||||
msgstr "Ominaisuuskytkennät"
|
msgstr "Ominaisuuskytkennät"
|
||||||
|
|
||||||
|
#: authentik/core/models.py
|
||||||
|
msgid "session data"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/core/models.py
|
||||||
|
msgid "Session"
|
||||||
|
msgstr "Istunto"
|
||||||
|
|
||||||
|
#: authentik/core/models.py
|
||||||
|
msgid "Sessions"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/core/models.py
|
#: authentik/core/models.py
|
||||||
msgid "Authenticated Session"
|
msgid "Authenticated Session"
|
||||||
msgstr "Autentikoitu istunto"
|
msgstr "Autentikoitu istunto"
|
||||||
@ -478,6 +491,38 @@ msgstr "Lisenssin käyttö"
|
|||||||
msgid "License Usage Records"
|
msgid "License Usage Records"
|
||||||
msgstr "Lisenssin käyttötiedot"
|
msgstr "Lisenssin käyttötiedot"
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
#: authentik/policies/password/models.py
|
||||||
|
msgid "Field key to check, field keys defined in Prompt stages are available."
|
||||||
|
msgstr ""
|
||||||
|
"Kentän avain, joka tarkistetaan. Kysymysvaiheissa määritellyt kenttien "
|
||||||
|
"avaimet ovat käytettävissä."
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "Number of passwords to check against."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
#: authentik/policies/password/models.py
|
||||||
|
msgid "Password not set in context"
|
||||||
|
msgstr "Salasanaa ei ole asetettu kontekstissa"
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "This password has been used previously. Please choose a different one."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "Password Uniqueness Policy"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "Password Uniqueness Policies"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "User Password History"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/enterprise/policy.py
|
#: authentik/enterprise/policy.py
|
||||||
msgid "Enterprise required to access this feature."
|
msgid "Enterprise required to access this feature."
|
||||||
msgstr "Tämän ominaisuuden käyttöön tarvitaan Enterprise-versiota."
|
msgstr "Tämän ominaisuuden käyttöön tarvitaan Enterprise-versiota."
|
||||||
@ -1251,12 +1296,6 @@ msgstr "Näytä käytäntövälimuistitilastot"
|
|||||||
msgid "Clear Policy's cache metrics"
|
msgid "Clear Policy's cache metrics"
|
||||||
msgstr "Tyhjennä käytäntövälimuistitilastot"
|
msgstr "Tyhjennä käytäntövälimuistitilastot"
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
|
||||||
msgid "Field key to check, field keys defined in Prompt stages are available."
|
|
||||||
msgstr ""
|
|
||||||
"Kentän avain, joka tarkistetaan. Kysymysvaiheissa määritellyt kenttien "
|
|
||||||
"avaimet ovat käytettävissä."
|
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
#: authentik/policies/password/models.py
|
||||||
msgid "How many times the password hash is allowed to be on haveibeenpwned"
|
msgid "How many times the password hash is allowed to be on haveibeenpwned"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -1269,10 +1308,6 @@ msgstr ""
|
|||||||
"Jos zxcvbn-pistemäärä on tämä arvo tai pienempi, käytännön suorittaminen "
|
"Jos zxcvbn-pistemäärä on tämä arvo tai pienempi, käytännön suorittaminen "
|
||||||
"epäonnistuu."
|
"epäonnistuu."
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
|
||||||
msgid "Password not set in context"
|
|
||||||
msgstr "Salasanaa ei ole asetettu kontekstissa"
|
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
#: authentik/policies/password/models.py
|
||||||
msgid "Invalid password."
|
msgid "Invalid password."
|
||||||
msgstr "Virheellinen salasana."
|
msgstr "Virheellinen salasana."
|
||||||
@ -1314,20 +1349,6 @@ msgstr "Mainepistemäärä"
|
|||||||
msgid "Reputation Scores"
|
msgid "Reputation Scores"
|
||||||
msgstr "Mainepistemäärät"
|
msgstr "Mainepistemäärät"
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/buffer.html
|
|
||||||
msgid "Waiting for authentication..."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/buffer.html
|
|
||||||
msgid ""
|
|
||||||
"You're already authenticating in another tab. This page will refresh once "
|
|
||||||
"authentication is completed."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/buffer.html
|
|
||||||
msgid "Authenticate in this tab"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/denied.html
|
#: authentik/policies/templates/policies/denied.html
|
||||||
msgid "Permission denied"
|
msgid "Permission denied"
|
||||||
msgstr "Käyttö evätty"
|
msgstr "Käyttö evätty"
|
||||||
@ -2155,6 +2176,10 @@ msgstr "Rooli"
|
|||||||
msgid "Roles"
|
msgid "Roles"
|
||||||
msgstr "Roolit"
|
msgstr "Roolit"
|
||||||
|
|
||||||
|
#: authentik/rbac/models.py
|
||||||
|
msgid "Initial Permissions"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/rbac/models.py
|
#: authentik/rbac/models.py
|
||||||
msgid "System permission"
|
msgid "System permission"
|
||||||
msgstr "Järjestelmän käyttöoikeus"
|
msgstr "Järjestelmän käyttöoikeus"
|
||||||
@ -2420,6 +2445,22 @@ msgstr "LDAP-lähteen ominaisuuskytkentä"
|
|||||||
msgid "LDAP Source Property Mappings"
|
msgid "LDAP Source Property Mappings"
|
||||||
msgstr "LDAP-lähteen ominaisuuskytkennät"
|
msgstr "LDAP-lähteen ominaisuuskytkennät"
|
||||||
|
|
||||||
|
#: authentik/sources/ldap/models.py
|
||||||
|
msgid "User LDAP Source Connection"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/sources/ldap/models.py
|
||||||
|
msgid "User LDAP Source Connections"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/sources/ldap/models.py
|
||||||
|
msgid "Group LDAP Source Connection"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/sources/ldap/models.py
|
||||||
|
msgid "Group LDAP Source Connections"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/sources/ldap/signals.py
|
#: authentik/sources/ldap/signals.py
|
||||||
msgid "Password does not match Active Directory Complexity."
|
msgid "Password does not match Active Directory Complexity."
|
||||||
msgstr "Salasana ei vastaa Active Directoryn monimutkaisuusmääritystä."
|
msgstr "Salasana ei vastaa Active Directoryn monimutkaisuusmääritystä."
|
||||||
@ -2428,6 +2469,14 @@ msgstr "Salasana ei vastaa Active Directoryn monimutkaisuusmääritystä."
|
|||||||
msgid "No token received."
|
msgid "No token received."
|
||||||
msgstr "Tunnistetta ei saatu."
|
msgstr "Tunnistetta ei saatu."
|
||||||
|
|
||||||
|
#: authentik/sources/oauth/models.py
|
||||||
|
msgid "HTTP Basic Authentication"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/sources/oauth/models.py
|
||||||
|
msgid "Include the client ID and secret as request parameters"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/sources/oauth/models.py
|
#: authentik/sources/oauth/models.py
|
||||||
msgid "Request Token URL"
|
msgid "Request Token URL"
|
||||||
msgstr "Pyyntötunnisteen URL"
|
msgstr "Pyyntötunnisteen URL"
|
||||||
@ -2468,6 +2517,12 @@ msgstr "URL, jota authentik käyttää käyttäjätiedon hakemiseksi."
|
|||||||
msgid "Additional Scopes"
|
msgid "Additional Scopes"
|
||||||
msgstr "Lisäkäyttöalueet"
|
msgstr "Lisäkäyttöalueet"
|
||||||
|
|
||||||
|
#: authentik/sources/oauth/models.py
|
||||||
|
msgid ""
|
||||||
|
"How to perform authentication during an authorization_code token request "
|
||||||
|
"flow"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/sources/oauth/models.py
|
#: authentik/sources/oauth/models.py
|
||||||
msgid "OAuth Source"
|
msgid "OAuth Source"
|
||||||
msgstr "OAuth-lähde"
|
msgstr "OAuth-lähde"
|
||||||
@ -3377,6 +3432,12 @@ msgstr ""
|
|||||||
"Kun tämä on käytössä, vaihe onnistuu ja suoritus jatkuu, vaikka olisi "
|
"Kun tämä on käytössä, vaihe onnistuu ja suoritus jatkuu, vaikka olisi "
|
||||||
"syötetty virheelliset käyttäjätiedot."
|
"syötetty virheelliset käyttäjätiedot."
|
||||||
|
|
||||||
|
#: authentik/stages/identification/models.py
|
||||||
|
msgid ""
|
||||||
|
"Show the user the 'Remember me on this device' toggle, allowing repeat users"
|
||||||
|
" to skip straight to entering their password."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/stages/identification/models.py
|
#: authentik/stages/identification/models.py
|
||||||
msgid "Optional enrollment flow, which is linked at the bottom of the page."
|
msgid "Optional enrollment flow, which is linked at the bottom of the page."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -3754,6 +3815,14 @@ msgstr ""
|
|||||||
"Tapahtumat poistetaan tämän ajan jälkeen. (Muoto: "
|
"Tapahtumat poistetaan tämän ajan jälkeen. (Muoto: "
|
||||||
"weeks=3;days=2;hours=3;seconds=2)."
|
"weeks=3;days=2;hours=3;seconds=2)."
|
||||||
|
|
||||||
|
#: authentik/tenants/models.py
|
||||||
|
msgid "Reputation cannot decrease lower than this value. Zero or negative."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/tenants/models.py
|
||||||
|
msgid "Reputation cannot increase higher than this value. Zero or positive."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/tenants/models.py
|
#: authentik/tenants/models.py
|
||||||
msgid "The option configures the footer links on the flow executor pages."
|
msgid "The option configures the footer links on the flow executor pages."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
Binary file not shown.
@ -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-15 00:11+0000\n"
|
"POT-Creation-Date: 2025-04-23 09:00+0000\n"
|
||||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||||
"Last-Translator: Marc Schmitt, 2025\n"
|
"Last-Translator: Marc Schmitt, 2025\n"
|
||||||
"Language-Team: French (https://app.transifex.com/authentik/teams/119923/fr/)\n"
|
"Language-Team: French (https://app.transifex.com/authentik/teams/119923/fr/)\n"
|
||||||
@ -502,6 +502,38 @@ 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é."
|
||||||
@ -1296,12 +1328,6 @@ 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 ""
|
||||||
@ -1315,10 +1341,6 @@ 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."
|
||||||
@ -1360,22 +1382,6 @@ 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"
|
||||||
@ -2508,6 +2514,14 @@ 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"
|
||||||
@ -2549,6 +2563,14 @@ 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"
|
||||||
@ -3469,6 +3491,15 @@ 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."
|
||||||
|
@ -12,17 +12,17 @@
|
|||||||
# tmassimi, 2024
|
# tmassimi, 2024
|
||||||
# Marc Schmitt, 2024
|
# Marc Schmitt, 2024
|
||||||
# albanobattistella <albanobattistella@gmail.com>, 2024
|
# albanobattistella <albanobattistella@gmail.com>, 2024
|
||||||
# Matteo Piccina <altermatte@gmail.com>, 2025
|
|
||||||
# Kowalski Dragon (kowalski7cc) <kowalski.7cc@gmail.com>, 2025
|
# Kowalski Dragon (kowalski7cc) <kowalski.7cc@gmail.com>, 2025
|
||||||
|
# Matteo Piccina <altermatte@gmail.com>, 2025
|
||||||
#
|
#
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-04-11 00:10+0000\n"
|
"POT-Creation-Date: 2025-04-23 09:00+0000\n"
|
||||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||||
"Last-Translator: Kowalski Dragon (kowalski7cc) <kowalski.7cc@gmail.com>, 2025\n"
|
"Last-Translator: Matteo Piccina <altermatte@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"
|
||||||
"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"
|
||||||
@ -194,6 +194,7 @@ msgid "User's display name."
|
|||||||
msgstr "Nome visualizzato dell'utente."
|
msgstr "Nome visualizzato dell'utente."
|
||||||
|
|
||||||
#: authentik/core/models.py authentik/providers/oauth2/models.py
|
#: authentik/core/models.py authentik/providers/oauth2/models.py
|
||||||
|
#: authentik/rbac/models.py
|
||||||
msgid "User"
|
msgid "User"
|
||||||
msgstr "Utente"
|
msgstr "Utente"
|
||||||
|
|
||||||
@ -380,6 +381,18 @@ msgstr "Mappatura della proprietà"
|
|||||||
msgid "Property Mappings"
|
msgid "Property Mappings"
|
||||||
msgstr "Mappatura delle proprietà"
|
msgstr "Mappatura delle proprietà"
|
||||||
|
|
||||||
|
#: authentik/core/models.py
|
||||||
|
msgid "session data"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/core/models.py
|
||||||
|
msgid "Session"
|
||||||
|
msgstr "Sessione"
|
||||||
|
|
||||||
|
#: authentik/core/models.py
|
||||||
|
msgid "Sessions"
|
||||||
|
msgstr "Sessioni"
|
||||||
|
|
||||||
#: authentik/core/models.py
|
#: authentik/core/models.py
|
||||||
msgid "Authenticated Session"
|
msgid "Authenticated Session"
|
||||||
msgstr "Sessione Autenticata"
|
msgstr "Sessione Autenticata"
|
||||||
@ -487,6 +500,38 @@ 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 ""
|
||||||
|
|
||||||
|
#: 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 ""
|
||||||
|
|
||||||
|
#: 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 "Versione Enterprise richiesta per accedere a questa funzione"
|
msgstr "Versione Enterprise richiesta per accedere a questa funzione"
|
||||||
@ -1274,12 +1319,6 @@ msgstr "Visualizza le metriche della cache della Policy"
|
|||||||
msgid "Clear Policy's cache metrics"
|
msgid "Clear Policy's cache metrics"
|
||||||
msgstr "Cancellare le metriche della cache della Policy"
|
msgstr "Cancellare le metriche della cache della Policy"
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
|
||||||
msgid "Field key to check, field keys defined in Prompt stages are available."
|
|
||||||
msgstr ""
|
|
||||||
"Chiave di campo da verificare, sono disponibili le chiavi di campo definite "
|
|
||||||
"nelle fasi Richiesta."
|
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
#: authentik/policies/password/models.py
|
||||||
msgid "How many times the password hash is allowed to be on haveibeenpwned"
|
msgid "How many times the password hash is allowed to be on haveibeenpwned"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -1292,10 +1331,6 @@ msgstr ""
|
|||||||
"Se il punteggio zxcvbn è inferiore o uguale a questo valore, il criterio non"
|
"Se il punteggio zxcvbn è inferiore o uguale a questo valore, il criterio non"
|
||||||
" verrà soddisfatto."
|
" verrà soddisfatto."
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
|
||||||
msgid "Password not set in context"
|
|
||||||
msgstr "Password non impostata nel contesto"
|
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
#: authentik/policies/password/models.py
|
||||||
msgid "Invalid password."
|
msgid "Invalid password."
|
||||||
msgstr "Password invalida."
|
msgstr "Password invalida."
|
||||||
@ -1337,22 +1372,6 @@ msgstr "Punteggio di reputazione"
|
|||||||
msgid "Reputation Scores"
|
msgid "Reputation Scores"
|
||||||
msgstr "Punteggi di reputazione"
|
msgstr "Punteggi di reputazione"
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/buffer.html
|
|
||||||
msgid "Waiting for authentication..."
|
|
||||||
msgstr "In attesa di autenticazione..."
|
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/buffer.html
|
|
||||||
msgid ""
|
|
||||||
"You're already authenticating in another tab. This page will refresh once "
|
|
||||||
"authentication is completed."
|
|
||||||
msgstr ""
|
|
||||||
"Ti stai già autenticando in un'altra scheda. Questa pagina si aggiornerà una"
|
|
||||||
" volta completata l'autenticazione."
|
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/buffer.html
|
|
||||||
msgid "Authenticate in this tab"
|
|
||||||
msgstr "Autenticati in questa scheda"
|
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/denied.html
|
#: authentik/policies/templates/policies/denied.html
|
||||||
msgid "Permission denied"
|
msgid "Permission denied"
|
||||||
msgstr "Permesso negato"
|
msgstr "Permesso negato"
|
||||||
@ -2182,6 +2201,10 @@ msgstr "Ruolo"
|
|||||||
msgid "Roles"
|
msgid "Roles"
|
||||||
msgstr "Ruoli"
|
msgstr "Ruoli"
|
||||||
|
|
||||||
|
#: authentik/rbac/models.py
|
||||||
|
msgid "Initial Permissions"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/rbac/models.py
|
#: authentik/rbac/models.py
|
||||||
msgid "System permission"
|
msgid "System permission"
|
||||||
msgstr "Autorizzazione di sistema"
|
msgstr "Autorizzazione di sistema"
|
||||||
@ -2452,6 +2475,22 @@ msgstr "Mappatura delle proprietà sorgente LDAP"
|
|||||||
msgid "LDAP Source Property Mappings"
|
msgid "LDAP Source Property Mappings"
|
||||||
msgstr "Mappature delle proprietà della sorgente LDAP"
|
msgstr "Mappature delle proprietà della sorgente LDAP"
|
||||||
|
|
||||||
|
#: authentik/sources/ldap/models.py
|
||||||
|
msgid "User LDAP Source Connection"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: 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 password non soddisfa la complessità Active Directory."
|
msgstr "La password non soddisfa la complessità Active Directory."
|
||||||
@ -2460,6 +2499,14 @@ msgstr "La password non soddisfa la complessità Active Directory."
|
|||||||
msgid "No token received."
|
msgid "No token received."
|
||||||
msgstr "Nessun token ricevuto."
|
msgstr "Nessun token ricevuto."
|
||||||
|
|
||||||
|
#: authentik/sources/oauth/models.py
|
||||||
|
msgid "HTTP Basic Authentication"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: 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 di Richiesta Token"
|
msgstr "URL di Richiesta Token"
|
||||||
@ -2500,6 +2547,12 @@ 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 ""
|
||||||
|
|
||||||
#: authentik/sources/oauth/models.py
|
#: authentik/sources/oauth/models.py
|
||||||
msgid "OAuth Source"
|
msgid "OAuth Source"
|
||||||
msgstr "Sorgente OAuth"
|
msgstr "Sorgente OAuth"
|
||||||
@ -3426,6 +3479,12 @@ 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 ""
|
||||||
|
|
||||||
#: authentik/stages/identification/models.py
|
#: authentik/stages/identification/models.py
|
||||||
msgid "Optional enrollment flow, which is linked at the bottom of the page."
|
msgid "Optional enrollment flow, which is linked at the bottom of the page."
|
||||||
msgstr "Flusso di iscrizione opzionale, che è collegato in fondo alla pagina."
|
msgstr "Flusso di iscrizione opzionale, che è collegato in fondo alla pagina."
|
||||||
@ -3812,6 +3871,14 @@ msgstr ""
|
|||||||
"Gli eventi saranno cancellati dopo questa durata. (Formato: "
|
"Gli eventi saranno cancellati dopo questa durata. (Formato: "
|
||||||
"weeks=3;days=2;hours=3,seconds=2)."
|
"weeks=3;days=2;hours=3,seconds=2)."
|
||||||
|
|
||||||
|
#: authentik/tenants/models.py
|
||||||
|
msgid "Reputation cannot decrease lower than this value. Zero or negative."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: 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 ""
|
||||||
|
@ -12,7 +12,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-03-31 00:10+0000\n"
|
"POT-Creation-Date: 2025-04-23 09:00+0000\n"
|
||||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||||
"Last-Translator: NavyStack, 2023\n"
|
"Last-Translator: NavyStack, 2023\n"
|
||||||
"Language-Team: Korean (https://app.transifex.com/authentik/teams/119923/ko/)\n"
|
"Language-Team: Korean (https://app.transifex.com/authentik/teams/119923/ko/)\n"
|
||||||
@ -176,6 +176,7 @@ msgid "User's display name."
|
|||||||
msgstr "사용자의 표시 이름"
|
msgstr "사용자의 표시 이름"
|
||||||
|
|
||||||
#: authentik/core/models.py authentik/providers/oauth2/models.py
|
#: authentik/core/models.py authentik/providers/oauth2/models.py
|
||||||
|
#: authentik/rbac/models.py
|
||||||
msgid "User"
|
msgid "User"
|
||||||
msgstr "사용자"
|
msgstr "사용자"
|
||||||
|
|
||||||
@ -344,6 +345,18 @@ msgstr "속성 매핑"
|
|||||||
msgid "Property Mappings"
|
msgid "Property Mappings"
|
||||||
msgstr "속성 매핑"
|
msgstr "속성 매핑"
|
||||||
|
|
||||||
|
#: authentik/core/models.py
|
||||||
|
msgid "session data"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/core/models.py
|
||||||
|
msgid "Session"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/core/models.py
|
||||||
|
msgid "Sessions"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/core/models.py
|
#: authentik/core/models.py
|
||||||
msgid "Authenticated Session"
|
msgid "Authenticated Session"
|
||||||
msgstr "인증된 세션"
|
msgstr "인증된 세션"
|
||||||
@ -447,6 +460,36 @@ msgstr "라이선스 사용"
|
|||||||
msgid "License Usage Records"
|
msgid "License Usage Records"
|
||||||
msgstr "라이선스 사용 기록"
|
msgstr "라이선스 사용 기록"
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
#: authentik/policies/password/models.py
|
||||||
|
msgid "Field key to check, field keys defined in Prompt stages are available."
|
||||||
|
msgstr "확인하려는 필드 키, 프롬프트 스테이지에서 정의된 필드 키를 사용할 수 있습니다."
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "Number of passwords to check against."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
#: authentik/policies/password/models.py
|
||||||
|
msgid "Password not set in context"
|
||||||
|
msgstr "비밀번호가 컨텍스트에 설정되지 않음"
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "This password has been used previously. Please choose a different one."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "Password Uniqueness Policy"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "Password Uniqueness Policies"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "User Password History"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/enterprise/policy.py
|
#: authentik/enterprise/policy.py
|
||||||
msgid "Enterprise required to access this feature."
|
msgid "Enterprise required to access this feature."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -1182,10 +1225,6 @@ msgstr "정책의 캐시 메트릭 보기"
|
|||||||
msgid "Clear Policy's cache metrics"
|
msgid "Clear Policy's cache metrics"
|
||||||
msgstr "정책의 캐시 메트릭 삭제"
|
msgstr "정책의 캐시 메트릭 삭제"
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
|
||||||
msgid "Field key to check, field keys defined in Prompt stages are available."
|
|
||||||
msgstr "확인하려는 필드 키, 프롬프트 스테이지에서 정의된 필드 키를 사용할 수 있습니다."
|
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
#: authentik/policies/password/models.py
|
||||||
msgid "How many times the password hash is allowed to be on haveibeenpwned"
|
msgid "How many times the password hash is allowed to be on haveibeenpwned"
|
||||||
msgstr "비밀번호 해시가 허용되는 해시 횟수"
|
msgstr "비밀번호 해시가 허용되는 해시 횟수"
|
||||||
@ -1195,10 +1234,6 @@ msgid ""
|
|||||||
"If the zxcvbn score is equal or less than this value, the policy will fail."
|
"If the zxcvbn score is equal or less than this value, the policy will fail."
|
||||||
msgstr "만약 zxcvbn 점수가 이 값과 같거나 이 값보다 작다면, 정책이 실패합니다."
|
msgstr "만약 zxcvbn 점수가 이 값과 같거나 이 값보다 작다면, 정책이 실패합니다."
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
|
||||||
msgid "Password not set in context"
|
|
||||||
msgstr "비밀번호가 컨텍스트에 설정되지 않음"
|
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
#: authentik/policies/password/models.py
|
||||||
msgid "Invalid password."
|
msgid "Invalid password."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -1240,20 +1275,6 @@ msgstr "평판 점수"
|
|||||||
msgid "Reputation Scores"
|
msgid "Reputation Scores"
|
||||||
msgstr "평판 점수"
|
msgstr "평판 점수"
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/buffer.html
|
|
||||||
msgid "Waiting for authentication..."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/buffer.html
|
|
||||||
msgid ""
|
|
||||||
"You're already authenticating in another tab. This page will refresh once "
|
|
||||||
"authentication is completed."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/buffer.html
|
|
||||||
msgid "Authenticate in this tab"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/denied.html
|
#: authentik/policies/templates/policies/denied.html
|
||||||
msgid "Permission denied"
|
msgid "Permission denied"
|
||||||
msgstr "권한 거부됨"
|
msgstr "권한 거부됨"
|
||||||
@ -2013,6 +2034,10 @@ msgstr "역할"
|
|||||||
msgid "Roles"
|
msgid "Roles"
|
||||||
msgstr "역할"
|
msgstr "역할"
|
||||||
|
|
||||||
|
#: authentik/rbac/models.py
|
||||||
|
msgid "Initial Permissions"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/rbac/models.py
|
#: authentik/rbac/models.py
|
||||||
msgid "System permission"
|
msgid "System permission"
|
||||||
msgstr "시스템 권한"
|
msgstr "시스템 권한"
|
||||||
@ -2231,6 +2256,13 @@ msgid ""
|
|||||||
"enabled on a single LDAP source."
|
"enabled on a single LDAP source."
|
||||||
msgstr "사용자가 비밀번호를 변경하면 LDAP로 다시 동기화합니다. 이 기능은 단일의 LDAP 소스에서만 활성화할 수 있습니다."
|
msgstr "사용자가 비밀번호를 변경하면 LDAP로 다시 동기화합니다. 이 기능은 단일의 LDAP 소스에서만 활성화할 수 있습니다."
|
||||||
|
|
||||||
|
#: authentik/sources/ldap/models.py
|
||||||
|
msgid ""
|
||||||
|
"Lookup group membership based on a user attribute instead of a group "
|
||||||
|
"attribute. This allows nested group resolution on systems like FreeIPA and "
|
||||||
|
"Active Directory"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/sources/ldap/models.py
|
#: authentik/sources/ldap/models.py
|
||||||
msgid "LDAP Source"
|
msgid "LDAP Source"
|
||||||
msgstr "LDAP 소스"
|
msgstr "LDAP 소스"
|
||||||
@ -2247,6 +2279,22 @@ msgstr ""
|
|||||||
msgid "LDAP Source Property Mappings"
|
msgid "LDAP Source Property Mappings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/sources/ldap/models.py
|
||||||
|
msgid "User LDAP Source Connection"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/sources/ldap/models.py
|
||||||
|
msgid "User LDAP Source Connections"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/sources/ldap/models.py
|
||||||
|
msgid "Group LDAP Source Connection"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/sources/ldap/models.py
|
||||||
|
msgid "Group LDAP Source Connections"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/sources/ldap/signals.py
|
#: authentik/sources/ldap/signals.py
|
||||||
msgid "Password does not match Active Directory Complexity."
|
msgid "Password does not match Active Directory Complexity."
|
||||||
msgstr "비밀번호가 Active Directory 복잡도와 일치하지 않습니다."
|
msgstr "비밀번호가 Active Directory 복잡도와 일치하지 않습니다."
|
||||||
@ -2255,6 +2303,14 @@ msgstr "비밀번호가 Active Directory 복잡도와 일치하지 않습니다.
|
|||||||
msgid "No token received."
|
msgid "No token received."
|
||||||
msgstr "수신된 토큰이 없습니다."
|
msgstr "수신된 토큰이 없습니다."
|
||||||
|
|
||||||
|
#: authentik/sources/oauth/models.py
|
||||||
|
msgid "HTTP Basic Authentication"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/sources/oauth/models.py
|
||||||
|
msgid "Include the client ID and secret as request parameters"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/sources/oauth/models.py
|
#: authentik/sources/oauth/models.py
|
||||||
msgid "Request Token URL"
|
msgid "Request Token URL"
|
||||||
msgstr "토큰 요청 URL"
|
msgstr "토큰 요청 URL"
|
||||||
@ -2293,6 +2349,12 @@ msgstr "사용자 정보를 가져오기 위해 authentik에서 사용하는 URL
|
|||||||
msgid "Additional Scopes"
|
msgid "Additional Scopes"
|
||||||
msgstr "추가 스코프"
|
msgstr "추가 스코프"
|
||||||
|
|
||||||
|
#: authentik/sources/oauth/models.py
|
||||||
|
msgid ""
|
||||||
|
"How to perform authentication during an authorization_code token request "
|
||||||
|
"flow"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/sources/oauth/models.py
|
#: authentik/sources/oauth/models.py
|
||||||
msgid "OAuth Source"
|
msgid "OAuth Source"
|
||||||
msgstr "OAuth 소스"
|
msgstr "OAuth 소스"
|
||||||
@ -3149,6 +3211,12 @@ msgid ""
|
|||||||
"info is entered."
|
"info is entered."
|
||||||
msgstr "활성화되면 잘못된 사용자 정보가 입력되더라도 단계가 성공하고 계속됩니다."
|
msgstr "활성화되면 잘못된 사용자 정보가 입력되더라도 단계가 성공하고 계속됩니다."
|
||||||
|
|
||||||
|
#: authentik/stages/identification/models.py
|
||||||
|
msgid ""
|
||||||
|
"Show the user the 'Remember me on this device' toggle, allowing repeat users"
|
||||||
|
" to skip straight to entering their password."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/stages/identification/models.py
|
#: authentik/stages/identification/models.py
|
||||||
msgid "Optional enrollment flow, which is linked at the bottom of the page."
|
msgid "Optional enrollment flow, which is linked at the bottom of the page."
|
||||||
msgstr "페이지 하단에 링크된, 선택적 등록 플로우를 참조하세요."
|
msgstr "페이지 하단에 링크된, 선택적 등록 플로우를 참조하세요."
|
||||||
@ -3500,6 +3568,14 @@ msgid ""
|
|||||||
"weeks=3;days=2;hours=3,seconds=2)."
|
"weeks=3;days=2;hours=3,seconds=2)."
|
||||||
msgstr "이 기간이 지나면 이벤트가 삭제됩니다. (서식: hours=-1;minutes=-2;seconds=-3)"
|
msgstr "이 기간이 지나면 이벤트가 삭제됩니다. (서식: hours=-1;minutes=-2;seconds=-3)"
|
||||||
|
|
||||||
|
#: authentik/tenants/models.py
|
||||||
|
msgid "Reputation cannot decrease lower than this value. Zero or negative."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/tenants/models.py
|
||||||
|
msgid "Reputation cannot increase higher than this value. Zero or positive."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/tenants/models.py
|
#: authentik/tenants/models.py
|
||||||
msgid "The option configures the footer links on the flow executor pages."
|
msgid "The option configures the footer links on the flow executor pages."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -7,18 +7,18 @@
|
|||||||
# Bartosz Karpiński, 2023
|
# Bartosz Karpiński, 2023
|
||||||
# Michał Jastrzębski, 2024
|
# Michał Jastrzębski, 2024
|
||||||
# Tomci 12 <drizztes@gmail.com>, 2024
|
# Tomci 12 <drizztes@gmail.com>, 2024
|
||||||
|
# Darek “NeroPcStation” NeroPcStation <dareknowacki2001@gmail.com>, 2024
|
||||||
# Marc Schmitt, 2025
|
# Marc Schmitt, 2025
|
||||||
# Jens L. <jens@goauthentik.io>, 2025
|
# Jens L. <jens@goauthentik.io>, 2025
|
||||||
# Darek “NeroPcStation” NeroPcStation <dareknowacki2001@gmail.com>, 2025
|
|
||||||
#
|
#
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-04-11 00:10+0000\n"
|
"POT-Creation-Date: 2025-04-23 09:00+0000\n"
|
||||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||||
"Last-Translator: Darek “NeroPcStation” NeroPcStation <dareknowacki2001@gmail.com>, 2025\n"
|
"Last-Translator: Jens L. <jens@goauthentik.io>, 2025\n"
|
||||||
"Language-Team: Polish (https://app.transifex.com/authentik/teams/119923/pl/)\n"
|
"Language-Team: Polish (https://app.transifex.com/authentik/teams/119923/pl/)\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
@ -189,6 +189,7 @@ msgid "User's display name."
|
|||||||
msgstr "Wyświetlana nazwa użytkownika."
|
msgstr "Wyświetlana nazwa użytkownika."
|
||||||
|
|
||||||
#: authentik/core/models.py authentik/providers/oauth2/models.py
|
#: authentik/core/models.py authentik/providers/oauth2/models.py
|
||||||
|
#: authentik/rbac/models.py
|
||||||
msgid "User"
|
msgid "User"
|
||||||
msgstr "Użytkownik"
|
msgstr "Użytkownik"
|
||||||
|
|
||||||
@ -371,6 +372,18 @@ msgstr "Mapowanie właściwości"
|
|||||||
msgid "Property Mappings"
|
msgid "Property Mappings"
|
||||||
msgstr "Mapowanie właściwości"
|
msgstr "Mapowanie właściwości"
|
||||||
|
|
||||||
|
#: authentik/core/models.py
|
||||||
|
msgid "session data"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/core/models.py
|
||||||
|
msgid "Session"
|
||||||
|
msgstr "Sesja"
|
||||||
|
|
||||||
|
#: authentik/core/models.py
|
||||||
|
msgid "Sessions"
|
||||||
|
msgstr "Sesje"
|
||||||
|
|
||||||
#: authentik/core/models.py
|
#: authentik/core/models.py
|
||||||
msgid "Authenticated Session"
|
msgid "Authenticated Session"
|
||||||
msgstr "Sesja uwierzytelniona"
|
msgstr "Sesja uwierzytelniona"
|
||||||
@ -479,6 +492,38 @@ msgstr "Wykorzystanie licencji"
|
|||||||
msgid "License Usage Records"
|
msgid "License Usage Records"
|
||||||
msgstr "Rejestr wykorzystania licencji"
|
msgstr "Rejestr wykorzystania licencji"
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
#: authentik/policies/password/models.py
|
||||||
|
msgid "Field key to check, field keys defined in Prompt stages are available."
|
||||||
|
msgstr ""
|
||||||
|
"Klucz pola do sprawdzenia, dostępne są klucze pola zdefiniowane w etapach "
|
||||||
|
"monitu."
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "Number of passwords to check against."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
#: authentik/policies/password/models.py
|
||||||
|
msgid "Password not set in context"
|
||||||
|
msgstr "Hasło nie jest ustawione w kontekście"
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "This password has been used previously. Please choose a different one."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "Password Uniqueness Policy"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "Password Uniqueness Policies"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "User Password History"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/enterprise/policy.py
|
#: authentik/enterprise/policy.py
|
||||||
msgid "Enterprise required to access this feature."
|
msgid "Enterprise required to access this feature."
|
||||||
msgstr "Wymagane jest konto Enterprise, aby uzyskać dostęp do tej funkcji."
|
msgstr "Wymagane jest konto Enterprise, aby uzyskać dostęp do tej funkcji."
|
||||||
@ -1257,12 +1302,6 @@ msgstr "Wyświetl metryki pamięci podręcznej Zasady"
|
|||||||
msgid "Clear Policy's cache metrics"
|
msgid "Clear Policy's cache metrics"
|
||||||
msgstr "Wyczyść metryki pamięci podręcznej Zasady"
|
msgstr "Wyczyść metryki pamięci podręcznej Zasady"
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
|
||||||
msgid "Field key to check, field keys defined in Prompt stages are available."
|
|
||||||
msgstr ""
|
|
||||||
"Klucz pola do sprawdzenia, dostępne są klucze pola zdefiniowane w etapach "
|
|
||||||
"monitu."
|
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
#: authentik/policies/password/models.py
|
||||||
msgid "How many times the password hash is allowed to be on haveibeenpwned"
|
msgid "How many times the password hash is allowed to be on haveibeenpwned"
|
||||||
msgstr "Ile razy skrót hasła może być na haveibeenpwned"
|
msgstr "Ile razy skrót hasła może być na haveibeenpwned"
|
||||||
@ -1274,10 +1313,6 @@ msgstr ""
|
|||||||
"Jeśli wynik zxcvbn jest równy lub mniejszy od tej wartości, zasada zakończy "
|
"Jeśli wynik zxcvbn jest równy lub mniejszy od tej wartości, zasada zakończy "
|
||||||
"się niepowodzeniem."
|
"się niepowodzeniem."
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
|
||||||
msgid "Password not set in context"
|
|
||||||
msgstr "Hasło nie jest ustawione w kontekście"
|
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
#: authentik/policies/password/models.py
|
||||||
msgid "Invalid password."
|
msgid "Invalid password."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -1319,20 +1354,6 @@ msgstr "Punkty reputacji"
|
|||||||
msgid "Reputation Scores"
|
msgid "Reputation Scores"
|
||||||
msgstr "Punkty reputacji"
|
msgstr "Punkty reputacji"
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/buffer.html
|
|
||||||
msgid "Waiting for authentication..."
|
|
||||||
msgstr "Oczekiwanie na uwierzytelnienie..."
|
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/buffer.html
|
|
||||||
msgid ""
|
|
||||||
"You're already authenticating in another tab. This page will refresh once "
|
|
||||||
"authentication is completed."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/buffer.html
|
|
||||||
msgid "Authenticate in this tab"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/denied.html
|
#: authentik/policies/templates/policies/denied.html
|
||||||
msgid "Permission denied"
|
msgid "Permission denied"
|
||||||
msgstr "Odmowa uprawnień"
|
msgstr "Odmowa uprawnień"
|
||||||
@ -2141,6 +2162,10 @@ msgstr "Rola"
|
|||||||
msgid "Roles"
|
msgid "Roles"
|
||||||
msgstr "Role"
|
msgstr "Role"
|
||||||
|
|
||||||
|
#: authentik/rbac/models.py
|
||||||
|
msgid "Initial Permissions"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/rbac/models.py
|
#: authentik/rbac/models.py
|
||||||
msgid "System permission"
|
msgid "System permission"
|
||||||
msgstr "Uprawnienie systemowe"
|
msgstr "Uprawnienie systemowe"
|
||||||
@ -2390,6 +2415,22 @@ msgstr ""
|
|||||||
msgid "LDAP Source Property Mappings"
|
msgid "LDAP Source Property Mappings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/sources/ldap/models.py
|
||||||
|
msgid "User LDAP Source Connection"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/sources/ldap/models.py
|
||||||
|
msgid "User LDAP Source Connections"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/sources/ldap/models.py
|
||||||
|
msgid "Group LDAP Source Connection"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/sources/ldap/models.py
|
||||||
|
msgid "Group LDAP Source Connections"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/sources/ldap/signals.py
|
#: authentik/sources/ldap/signals.py
|
||||||
msgid "Password does not match Active Directory Complexity."
|
msgid "Password does not match Active Directory Complexity."
|
||||||
msgstr "Hasło nie pasuje do złożoności usługi Active Directory."
|
msgstr "Hasło nie pasuje do złożoności usługi Active Directory."
|
||||||
@ -2398,6 +2439,14 @@ msgstr "Hasło nie pasuje do złożoności usługi Active Directory."
|
|||||||
msgid "No token received."
|
msgid "No token received."
|
||||||
msgstr "Nie otrzymano tokena."
|
msgstr "Nie otrzymano tokena."
|
||||||
|
|
||||||
|
#: authentik/sources/oauth/models.py
|
||||||
|
msgid "HTTP Basic Authentication"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/sources/oauth/models.py
|
||||||
|
msgid "Include the client ID and secret as request parameters"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/sources/oauth/models.py
|
#: authentik/sources/oauth/models.py
|
||||||
msgid "Request Token URL"
|
msgid "Request Token URL"
|
||||||
msgstr "URL żądania tokena"
|
msgstr "URL żądania tokena"
|
||||||
@ -2440,6 +2489,12 @@ msgstr "URL używany przez authentik do uzyskania informacji o użytkowniku."
|
|||||||
msgid "Additional Scopes"
|
msgid "Additional Scopes"
|
||||||
msgstr "Dodatkowe zakresy"
|
msgstr "Dodatkowe zakresy"
|
||||||
|
|
||||||
|
#: authentik/sources/oauth/models.py
|
||||||
|
msgid ""
|
||||||
|
"How to perform authentication during an authorization_code token request "
|
||||||
|
"flow"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/sources/oauth/models.py
|
#: authentik/sources/oauth/models.py
|
||||||
msgid "OAuth Source"
|
msgid "OAuth Source"
|
||||||
msgstr "Źródło OAuth"
|
msgstr "Źródło OAuth"
|
||||||
@ -3344,6 +3399,12 @@ msgstr ""
|
|||||||
"Po włączeniu tej opcji etap zakończy się powodzeniem i będzie kontynuowany "
|
"Po włączeniu tej opcji etap zakończy się powodzeniem i będzie kontynuowany "
|
||||||
"nawet po wprowadzeniu nieprawidłowych danych użytkownika."
|
"nawet po wprowadzeniu nieprawidłowych danych użytkownika."
|
||||||
|
|
||||||
|
#: authentik/stages/identification/models.py
|
||||||
|
msgid ""
|
||||||
|
"Show the user the 'Remember me on this device' toggle, allowing repeat users"
|
||||||
|
" to skip straight to entering their password."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/stages/identification/models.py
|
#: authentik/stages/identification/models.py
|
||||||
msgid "Optional enrollment flow, which is linked at the bottom of the page."
|
msgid "Optional enrollment flow, which is linked at the bottom of the page."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -3727,6 +3788,14 @@ msgstr ""
|
|||||||
"Zdarzenia zostaną usunięte po upływie tego czasu. (Format: "
|
"Zdarzenia zostaną usunięte po upływie tego czasu. (Format: "
|
||||||
"weeks=3;days=2;hours=3,seconds=2)."
|
"weeks=3;days=2;hours=3,seconds=2)."
|
||||||
|
|
||||||
|
#: authentik/tenants/models.py
|
||||||
|
msgid "Reputation cannot decrease lower than this value. Zero or negative."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/tenants/models.py
|
||||||
|
msgid "Reputation cannot increase higher than this value. Zero or positive."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/tenants/models.py
|
#: authentik/tenants/models.py
|
||||||
msgid "The option configures the footer links on the flow executor pages."
|
msgid "The option configures the footer links on the flow executor pages."
|
||||||
msgstr "Opcja ta konfiguruje łącza stopki na stronach wykonawców przepływu."
|
msgstr "Opcja ta konfiguruje łącza stopki na stronach wykonawców przepływu."
|
||||||
|
@ -18,7 +18,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-04-11 00:10+0000\n"
|
"POT-Creation-Date: 2025-04-23 09:00+0000\n"
|
||||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||||
"Last-Translator: Gil Poiares-Oliveira, 2025\n"
|
"Last-Translator: Gil Poiares-Oliveira, 2025\n"
|
||||||
"Language-Team: Portuguese (Brazil) (https://app.transifex.com/authentik/teams/119923/pt_BR/)\n"
|
"Language-Team: Portuguese (Brazil) (https://app.transifex.com/authentik/teams/119923/pt_BR/)\n"
|
||||||
@ -192,6 +192,7 @@ msgid "User's display name."
|
|||||||
msgstr "Nome de exibição do usuário."
|
msgstr "Nome de exibição do usuário."
|
||||||
|
|
||||||
#: authentik/core/models.py authentik/providers/oauth2/models.py
|
#: authentik/core/models.py authentik/providers/oauth2/models.py
|
||||||
|
#: authentik/rbac/models.py
|
||||||
msgid "User"
|
msgid "User"
|
||||||
msgstr "Usuário"
|
msgstr "Usuário"
|
||||||
|
|
||||||
@ -376,6 +377,18 @@ msgstr "Mapeamento de propriedades"
|
|||||||
msgid "Property Mappings"
|
msgid "Property Mappings"
|
||||||
msgstr "Mapeamentos de propriedades"
|
msgstr "Mapeamentos de propriedades"
|
||||||
|
|
||||||
|
#: authentik/core/models.py
|
||||||
|
msgid "session data"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/core/models.py
|
||||||
|
msgid "Session"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/core/models.py
|
||||||
|
msgid "Sessions"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/core/models.py
|
#: authentik/core/models.py
|
||||||
msgid "Authenticated Session"
|
msgid "Authenticated Session"
|
||||||
msgstr "Sessão Autenticada"
|
msgstr "Sessão Autenticada"
|
||||||
@ -483,6 +496,38 @@ msgstr "Uso de licença"
|
|||||||
msgid "License Usage Records"
|
msgid "License Usage Records"
|
||||||
msgstr "Registros de uso de licença"
|
msgstr "Registros de uso de licença"
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
#: authentik/policies/password/models.py
|
||||||
|
msgid "Field key to check, field keys defined in Prompt stages are available."
|
||||||
|
msgstr ""
|
||||||
|
"Chave de campo para verificar, as chaves de campo definidas nos estágios de "
|
||||||
|
"prompt estão disponíveis."
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "Number of passwords to check against."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
#: authentik/policies/password/models.py
|
||||||
|
msgid "Password not set in context"
|
||||||
|
msgstr "Senha não definida no contexto"
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "This password has been used previously. Please choose a different one."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "Password Uniqueness Policy"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "Password Uniqueness Policies"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "User Password History"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/enterprise/policy.py
|
#: authentik/enterprise/policy.py
|
||||||
msgid "Enterprise required to access this feature."
|
msgid "Enterprise required to access this feature."
|
||||||
msgstr "Entrerprise é necessário para acessar essa funcionalidade"
|
msgstr "Entrerprise é necessário para acessar essa funcionalidade"
|
||||||
@ -1252,12 +1297,6 @@ msgstr ""
|
|||||||
msgid "Clear Policy's cache metrics"
|
msgid "Clear Policy's cache metrics"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
|
||||||
msgid "Field key to check, field keys defined in Prompt stages are available."
|
|
||||||
msgstr ""
|
|
||||||
"Chave de campo para verificar, as chaves de campo definidas nos estágios de "
|
|
||||||
"prompt estão disponíveis."
|
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
#: authentik/policies/password/models.py
|
||||||
msgid "How many times the password hash is allowed to be on haveibeenpwned"
|
msgid "How many times the password hash is allowed to be on haveibeenpwned"
|
||||||
msgstr "Quantas vezes o hash da senha pode estar em haveibeenpwned"
|
msgstr "Quantas vezes o hash da senha pode estar em haveibeenpwned"
|
||||||
@ -1268,10 +1307,6 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Se a pontuação zxcvbn for igual ou menor que esse valor, a política falhará."
|
"Se a pontuação zxcvbn for igual ou menor que esse valor, a política falhará."
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
|
||||||
msgid "Password not set in context"
|
|
||||||
msgstr "Senha não definida no contexto"
|
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
#: authentik/policies/password/models.py
|
||||||
msgid "Invalid password."
|
msgid "Invalid password."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -1313,20 +1348,6 @@ msgstr "Pontuação de reputação"
|
|||||||
msgid "Reputation Scores"
|
msgid "Reputation Scores"
|
||||||
msgstr "Pontuações de reputação"
|
msgstr "Pontuações de reputação"
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/buffer.html
|
|
||||||
msgid "Waiting for authentication..."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/buffer.html
|
|
||||||
msgid ""
|
|
||||||
"You're already authenticating in another tab. This page will refresh once "
|
|
||||||
"authentication is completed."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/buffer.html
|
|
||||||
msgid "Authenticate in this tab"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/denied.html
|
#: authentik/policies/templates/policies/denied.html
|
||||||
msgid "Permission denied"
|
msgid "Permission denied"
|
||||||
msgstr "Permissão negada"
|
msgstr "Permissão negada"
|
||||||
@ -2141,6 +2162,10 @@ msgstr ""
|
|||||||
msgid "Roles"
|
msgid "Roles"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/rbac/models.py
|
||||||
|
msgid "Initial Permissions"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/rbac/models.py
|
#: authentik/rbac/models.py
|
||||||
msgid "System permission"
|
msgid "System permission"
|
||||||
msgstr "Permissão do sistema"
|
msgstr "Permissão do sistema"
|
||||||
@ -2387,6 +2412,22 @@ msgstr ""
|
|||||||
msgid "LDAP Source Property Mappings"
|
msgid "LDAP Source Property Mappings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/sources/ldap/models.py
|
||||||
|
msgid "User LDAP Source Connection"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/sources/ldap/models.py
|
||||||
|
msgid "User LDAP Source Connections"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/sources/ldap/models.py
|
||||||
|
msgid "Group LDAP Source Connection"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/sources/ldap/models.py
|
||||||
|
msgid "Group LDAP Source Connections"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/sources/ldap/signals.py
|
#: authentik/sources/ldap/signals.py
|
||||||
msgid "Password does not match Active Directory Complexity."
|
msgid "Password does not match Active Directory Complexity."
|
||||||
msgstr "A senha não corresponde à complexidade do Active Directory."
|
msgstr "A senha não corresponde à complexidade do Active Directory."
|
||||||
@ -2395,6 +2436,14 @@ msgstr "A senha não corresponde à complexidade do Active Directory."
|
|||||||
msgid "No token received."
|
msgid "No token received."
|
||||||
msgstr "Nenhum token recebido."
|
msgstr "Nenhum token recebido."
|
||||||
|
|
||||||
|
#: authentik/sources/oauth/models.py
|
||||||
|
msgid "HTTP Basic Authentication"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/sources/oauth/models.py
|
||||||
|
msgid "Include the client ID and secret as request parameters"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/sources/oauth/models.py
|
#: authentik/sources/oauth/models.py
|
||||||
msgid "Request Token URL"
|
msgid "Request Token URL"
|
||||||
msgstr "URL do token de solicitação"
|
msgstr "URL do token de solicitação"
|
||||||
@ -2435,6 +2484,12 @@ msgstr "URL usado pelo authentik para obter informações do usuário."
|
|||||||
msgid "Additional Scopes"
|
msgid "Additional Scopes"
|
||||||
msgstr "Escopos Adicionais"
|
msgstr "Escopos Adicionais"
|
||||||
|
|
||||||
|
#: authentik/sources/oauth/models.py
|
||||||
|
msgid ""
|
||||||
|
"How to perform authentication during an authorization_code token request "
|
||||||
|
"flow"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/sources/oauth/models.py
|
#: authentik/sources/oauth/models.py
|
||||||
msgid "OAuth Source"
|
msgid "OAuth Source"
|
||||||
msgstr "Fonte OAuth"
|
msgstr "Fonte OAuth"
|
||||||
@ -3318,6 +3373,12 @@ msgid ""
|
|||||||
"info is entered."
|
"info is entered."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/stages/identification/models.py
|
||||||
|
msgid ""
|
||||||
|
"Show the user the 'Remember me on this device' toggle, allowing repeat users"
|
||||||
|
" to skip straight to entering their password."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/stages/identification/models.py
|
#: authentik/stages/identification/models.py
|
||||||
msgid "Optional enrollment flow, which is linked at the bottom of the page."
|
msgid "Optional enrollment flow, which is linked at the bottom of the page."
|
||||||
msgstr "Optional enrollment flow, which is linked at the bottom of the page."
|
msgstr "Optional enrollment flow, which is linked at the bottom of the page."
|
||||||
@ -3678,6 +3739,14 @@ msgstr ""
|
|||||||
"Os eventos serão excluídos após esta duração.(Formato: "
|
"Os eventos serão excluídos após esta duração.(Formato: "
|
||||||
"semanas=3;dias=2;horas=3,segundos=2)."
|
"semanas=3;dias=2;horas=3,segundos=2)."
|
||||||
|
|
||||||
|
#: authentik/tenants/models.py
|
||||||
|
msgid "Reputation cannot decrease lower than this value. Zero or negative."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/tenants/models.py
|
||||||
|
msgid "Reputation cannot increase higher than this value. Zero or positive."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/tenants/models.py
|
#: authentik/tenants/models.py
|
||||||
msgid "The option configures the footer links on the flow executor pages."
|
msgid "The option configures the footer links on the flow executor pages."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -18,7 +18,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-04-11 00:10+0000\n"
|
"POT-Creation-Date: 2025-04-23 09:00+0000\n"
|
||||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||||
"Last-Translator: Marc Schmitt, 2025\n"
|
"Last-Translator: Marc Schmitt, 2025\n"
|
||||||
"Language-Team: Russian (https://app.transifex.com/authentik/teams/119923/ru/)\n"
|
"Language-Team: Russian (https://app.transifex.com/authentik/teams/119923/ru/)\n"
|
||||||
@ -191,6 +191,7 @@ msgid "User's display name."
|
|||||||
msgstr "Отображаемое имя пользователя."
|
msgstr "Отображаемое имя пользователя."
|
||||||
|
|
||||||
#: authentik/core/models.py authentik/providers/oauth2/models.py
|
#: authentik/core/models.py authentik/providers/oauth2/models.py
|
||||||
|
#: authentik/rbac/models.py
|
||||||
msgid "User"
|
msgid "User"
|
||||||
msgstr "Пользователь"
|
msgstr "Пользователь"
|
||||||
|
|
||||||
@ -379,6 +380,18 @@ msgstr "Сопоставление свойств"
|
|||||||
msgid "Property Mappings"
|
msgid "Property Mappings"
|
||||||
msgstr "Сопоставление свойств"
|
msgstr "Сопоставление свойств"
|
||||||
|
|
||||||
|
#: authentik/core/models.py
|
||||||
|
msgid "session data"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/core/models.py
|
||||||
|
msgid "Session"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/core/models.py
|
||||||
|
msgid "Sessions"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/core/models.py
|
#: authentik/core/models.py
|
||||||
msgid "Authenticated Session"
|
msgid "Authenticated Session"
|
||||||
msgstr "Аутентифицированная Сессия"
|
msgstr "Аутентифицированная Сессия"
|
||||||
@ -487,6 +500,37 @@ msgstr "Использование лицензии"
|
|||||||
msgid "License Usage Records"
|
msgid "License Usage Records"
|
||||||
msgstr "Записи использования лицензии"
|
msgstr "Записи использования лицензии"
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
#: authentik/policies/password/models.py
|
||||||
|
msgid "Field key to check, field keys defined in Prompt stages are available."
|
||||||
|
msgstr ""
|
||||||
|
"Ключ поля для проверки, доступны ключи поля, определенные в этапах запроса."
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "Number of passwords to check against."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
#: authentik/policies/password/models.py
|
||||||
|
msgid "Password not set in context"
|
||||||
|
msgstr "Пароль не задан в контексте"
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "This password has been used previously. Please choose a different one."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "Password Uniqueness Policy"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "Password Uniqueness Policies"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "User Password History"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/enterprise/policy.py
|
#: authentik/enterprise/policy.py
|
||||||
msgid "Enterprise required to access this feature."
|
msgid "Enterprise required to access this feature."
|
||||||
msgstr "Для доступа к этой функции требуется Enterprise."
|
msgstr "Для доступа к этой функции требуется Enterprise."
|
||||||
@ -1267,11 +1311,6 @@ msgstr "Просмотр показателей кэша политики"
|
|||||||
msgid "Clear Policy's cache metrics"
|
msgid "Clear Policy's cache metrics"
|
||||||
msgstr "Очистка показателей кэша политики"
|
msgstr "Очистка показателей кэша политики"
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
|
||||||
msgid "Field key to check, field keys defined in Prompt stages are available."
|
|
||||||
msgstr ""
|
|
||||||
"Ключ поля для проверки, доступны ключи поля, определенные в этапах запроса."
|
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
#: authentik/policies/password/models.py
|
||||||
msgid "How many times the password hash is allowed to be on haveibeenpwned"
|
msgid "How many times the password hash is allowed to be on haveibeenpwned"
|
||||||
msgstr "Как часто хэш пароля может быть представлен на haveibeenpwned"
|
msgstr "Как часто хэш пароля может быть представлен на haveibeenpwned"
|
||||||
@ -1283,10 +1322,6 @@ msgstr ""
|
|||||||
"Если показатель zxcvbn равен или меньше этого значения, политика будет "
|
"Если показатель zxcvbn равен или меньше этого значения, политика будет "
|
||||||
"провалена."
|
"провалена."
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
|
||||||
msgid "Password not set in context"
|
|
||||||
msgstr "Пароль не задан в контексте"
|
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
#: authentik/policies/password/models.py
|
||||||
msgid "Invalid password."
|
msgid "Invalid password."
|
||||||
msgstr "Неправильный пароль"
|
msgstr "Неправильный пароль"
|
||||||
@ -1328,20 +1363,6 @@ msgstr "Оценка репутации"
|
|||||||
msgid "Reputation Scores"
|
msgid "Reputation Scores"
|
||||||
msgstr "Оценка репутации"
|
msgstr "Оценка репутации"
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/buffer.html
|
|
||||||
msgid "Waiting for authentication..."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/buffer.html
|
|
||||||
msgid ""
|
|
||||||
"You're already authenticating in another tab. This page will refresh once "
|
|
||||||
"authentication is completed."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/buffer.html
|
|
||||||
msgid "Authenticate in this tab"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/denied.html
|
#: authentik/policies/templates/policies/denied.html
|
||||||
msgid "Permission denied"
|
msgid "Permission denied"
|
||||||
msgstr "Доступ запрещен"
|
msgstr "Доступ запрещен"
|
||||||
@ -2164,6 +2185,10 @@ msgstr "Роль"
|
|||||||
msgid "Roles"
|
msgid "Roles"
|
||||||
msgstr "Роли"
|
msgstr "Роли"
|
||||||
|
|
||||||
|
#: authentik/rbac/models.py
|
||||||
|
msgid "Initial Permissions"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/rbac/models.py
|
#: authentik/rbac/models.py
|
||||||
msgid "System permission"
|
msgid "System permission"
|
||||||
msgstr "Системное разрешение"
|
msgstr "Системное разрешение"
|
||||||
@ -2421,6 +2446,22 @@ msgstr "Сопоставление свойства LDAP источника"
|
|||||||
msgid "LDAP Source Property Mappings"
|
msgid "LDAP Source Property Mappings"
|
||||||
msgstr "Сопоставление свойств LDAP источника"
|
msgstr "Сопоставление свойств LDAP источника"
|
||||||
|
|
||||||
|
#: authentik/sources/ldap/models.py
|
||||||
|
msgid "User LDAP Source Connection"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/sources/ldap/models.py
|
||||||
|
msgid "User LDAP Source Connections"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/sources/ldap/models.py
|
||||||
|
msgid "Group LDAP Source Connection"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/sources/ldap/models.py
|
||||||
|
msgid "Group LDAP Source Connections"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/sources/ldap/signals.py
|
#: authentik/sources/ldap/signals.py
|
||||||
msgid "Password does not match Active Directory Complexity."
|
msgid "Password does not match Active Directory Complexity."
|
||||||
msgstr "Пароль не соответствует сложности Active Directory."
|
msgstr "Пароль не соответствует сложности Active Directory."
|
||||||
@ -2429,6 +2470,14 @@ msgstr "Пароль не соответствует сложности Active D
|
|||||||
msgid "No token received."
|
msgid "No token received."
|
||||||
msgstr "Токен не был получен."
|
msgstr "Токен не был получен."
|
||||||
|
|
||||||
|
#: authentik/sources/oauth/models.py
|
||||||
|
msgid "HTTP Basic Authentication"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/sources/oauth/models.py
|
||||||
|
msgid "Include the client ID and secret as request parameters"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/sources/oauth/models.py
|
#: authentik/sources/oauth/models.py
|
||||||
msgid "Request Token URL"
|
msgid "Request Token URL"
|
||||||
msgstr "URL-адрес запроса токена"
|
msgstr "URL-адрес запроса токена"
|
||||||
@ -2471,6 +2520,12 @@ msgstr ""
|
|||||||
msgid "Additional Scopes"
|
msgid "Additional Scopes"
|
||||||
msgstr "Дополнительные области"
|
msgstr "Дополнительные области"
|
||||||
|
|
||||||
|
#: authentik/sources/oauth/models.py
|
||||||
|
msgid ""
|
||||||
|
"How to perform authentication during an authorization_code token request "
|
||||||
|
"flow"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/sources/oauth/models.py
|
#: authentik/sources/oauth/models.py
|
||||||
msgid "OAuth Source"
|
msgid "OAuth Source"
|
||||||
msgstr "Источник OAuth"
|
msgstr "Источник OAuth"
|
||||||
@ -3376,6 +3431,12 @@ msgstr ""
|
|||||||
"При включении этап будет завершаться успешно и продолжаться даже в случае "
|
"При включении этап будет завершаться успешно и продолжаться даже в случае "
|
||||||
"ввода неправильной информации о пользователе."
|
"ввода неправильной информации о пользователе."
|
||||||
|
|
||||||
|
#: authentik/stages/identification/models.py
|
||||||
|
msgid ""
|
||||||
|
"Show the user the 'Remember me on this device' toggle, allowing repeat users"
|
||||||
|
" to skip straight to entering their password."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/stages/identification/models.py
|
#: authentik/stages/identification/models.py
|
||||||
msgid "Optional enrollment flow, which is linked at the bottom of the page."
|
msgid "Optional enrollment flow, which is linked at the bottom of the page."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -3767,6 +3828,14 @@ msgstr ""
|
|||||||
"По истечении этого времени события будут удалены. (Формат: недели=3; дни=2; "
|
"По истечении этого времени события будут удалены. (Формат: недели=3; дни=2; "
|
||||||
"часы=3, секунды=2)."
|
"часы=3, секунды=2)."
|
||||||
|
|
||||||
|
#: authentik/tenants/models.py
|
||||||
|
msgid "Reputation cannot decrease lower than this value. Zero or negative."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/tenants/models.py
|
||||||
|
msgid "Reputation cannot increase higher than this value. Zero or positive."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/tenants/models.py
|
#: authentik/tenants/models.py
|
||||||
msgid "The option configures the footer links on the flow executor pages."
|
msgid "The option configures the footer links on the flow executor pages."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
Binary file not shown.
@ -13,7 +13,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-03-31 00:10+0000\n"
|
"POT-Creation-Date: 2025-04-23 09:00+0000\n"
|
||||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||||
"Last-Translator: Jens L. <jens@goauthentik.io>, 2025\n"
|
"Last-Translator: Jens L. <jens@goauthentik.io>, 2025\n"
|
||||||
"Language-Team: Turkish (https://app.transifex.com/authentik/teams/119923/tr/)\n"
|
"Language-Team: Turkish (https://app.transifex.com/authentik/teams/119923/tr/)\n"
|
||||||
@ -187,6 +187,7 @@ msgid "User's display name."
|
|||||||
msgstr "Kullanıcının görünen adı."
|
msgstr "Kullanıcının görünen adı."
|
||||||
|
|
||||||
#: authentik/core/models.py authentik/providers/oauth2/models.py
|
#: authentik/core/models.py authentik/providers/oauth2/models.py
|
||||||
|
#: authentik/rbac/models.py
|
||||||
msgid "User"
|
msgid "User"
|
||||||
msgstr "Kullanıcı"
|
msgstr "Kullanıcı"
|
||||||
|
|
||||||
@ -372,6 +373,18 @@ msgstr "Özellik Eşleme"
|
|||||||
msgid "Property Mappings"
|
msgid "Property Mappings"
|
||||||
msgstr "Özellik Eşlemeleri"
|
msgstr "Özellik Eşlemeleri"
|
||||||
|
|
||||||
|
#: authentik/core/models.py
|
||||||
|
msgid "session data"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/core/models.py
|
||||||
|
msgid "Session"
|
||||||
|
msgstr "Oturum"
|
||||||
|
|
||||||
|
#: authentik/core/models.py
|
||||||
|
msgid "Sessions"
|
||||||
|
msgstr "Oturumlar"
|
||||||
|
|
||||||
#: authentik/core/models.py
|
#: authentik/core/models.py
|
||||||
msgid "Authenticated Session"
|
msgid "Authenticated Session"
|
||||||
msgstr "Kimliği Doğrulanmış Oturum"
|
msgstr "Kimliği Doğrulanmış Oturum"
|
||||||
@ -479,6 +492,38 @@ msgstr "Lisans Kullanımı"
|
|||||||
msgid "License Usage Records"
|
msgid "License Usage Records"
|
||||||
msgstr "Lisans Kullanım Kayıtları"
|
msgstr "Lisans Kullanım Kayıtları"
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
#: authentik/policies/password/models.py
|
||||||
|
msgid "Field key to check, field keys defined in Prompt stages are available."
|
||||||
|
msgstr ""
|
||||||
|
"Alan tuşu kontrol etmek için, İstem aşamalarında tanımlanan alan tuşları "
|
||||||
|
"mevcuttur."
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "Number of passwords to check against."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
#: authentik/policies/password/models.py
|
||||||
|
msgid "Password not set in context"
|
||||||
|
msgstr "Parola bağlam içinde ayarlanmamış"
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "This password has been used previously. Please choose a different one."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "Password Uniqueness Policy"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "Password Uniqueness Policies"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "User Password History"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/enterprise/policy.py
|
#: authentik/enterprise/policy.py
|
||||||
msgid "Enterprise required to access this feature."
|
msgid "Enterprise required to access this feature."
|
||||||
msgstr "Bu özelliğe erişmek için Kurumsal Paket gereklidir."
|
msgstr "Bu özelliğe erişmek için Kurumsal Paket gereklidir."
|
||||||
@ -1253,12 +1298,6 @@ msgstr "İlke'nin önbellek ölçümlerini görüntüleme"
|
|||||||
msgid "Clear Policy's cache metrics"
|
msgid "Clear Policy's cache metrics"
|
||||||
msgstr "İlke'nin önbellek ölçümlerini temizleyin"
|
msgstr "İlke'nin önbellek ölçümlerini temizleyin"
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
|
||||||
msgid "Field key to check, field keys defined in Prompt stages are available."
|
|
||||||
msgstr ""
|
|
||||||
"Alan tuşu kontrol etmek için, İstem aşamalarında tanımlanan alan tuşları "
|
|
||||||
"mevcuttur."
|
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
#: authentik/policies/password/models.py
|
||||||
msgid "How many times the password hash is allowed to be on haveibeenpwned"
|
msgid "How many times the password hash is allowed to be on haveibeenpwned"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -1271,10 +1310,6 @@ msgstr ""
|
|||||||
"Eğer zxcvbn puanı bu değere eşit veya daha az ise, politika başarısız "
|
"Eğer zxcvbn puanı bu değere eşit veya daha az ise, politika başarısız "
|
||||||
"olacaktır."
|
"olacaktır."
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
|
||||||
msgid "Password not set in context"
|
|
||||||
msgstr "Parola bağlam içinde ayarlanmamış"
|
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
#: authentik/policies/password/models.py
|
||||||
msgid "Invalid password."
|
msgid "Invalid password."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -1316,20 +1351,6 @@ msgstr "İtibar Puanı"
|
|||||||
msgid "Reputation Scores"
|
msgid "Reputation Scores"
|
||||||
msgstr "İtibar Puanları"
|
msgstr "İtibar Puanları"
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/buffer.html
|
|
||||||
msgid "Waiting for authentication..."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/buffer.html
|
|
||||||
msgid ""
|
|
||||||
"You're already authenticating in another tab. This page will refresh once "
|
|
||||||
"authentication is completed."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/buffer.html
|
|
||||||
msgid "Authenticate in this tab"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/denied.html
|
#: authentik/policies/templates/policies/denied.html
|
||||||
msgid "Permission denied"
|
msgid "Permission denied"
|
||||||
msgstr "İzin reddedildi"
|
msgstr "İzin reddedildi"
|
||||||
@ -2155,6 +2176,10 @@ msgstr "Rol"
|
|||||||
msgid "Roles"
|
msgid "Roles"
|
||||||
msgstr "Roller"
|
msgstr "Roller"
|
||||||
|
|
||||||
|
#: authentik/rbac/models.py
|
||||||
|
msgid "Initial Permissions"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/rbac/models.py
|
#: authentik/rbac/models.py
|
||||||
msgid "System permission"
|
msgid "System permission"
|
||||||
msgstr "Sistem yetkisi"
|
msgstr "Sistem yetkisi"
|
||||||
@ -2398,6 +2423,13 @@ msgstr ""
|
|||||||
"Bir kullanıcı parolasını değiştirdiğinde, parolayı LDAP ile geri eşitleyin. "
|
"Bir kullanıcı parolasını değiştirdiğinde, parolayı LDAP ile geri eşitleyin. "
|
||||||
"Bu yalnızca tek bir LDAP kaynağında etkinleştirilebilir."
|
"Bu yalnızca tek bir LDAP kaynağında etkinleştirilebilir."
|
||||||
|
|
||||||
|
#: authentik/sources/ldap/models.py
|
||||||
|
msgid ""
|
||||||
|
"Lookup group membership based on a user attribute instead of a group "
|
||||||
|
"attribute. This allows nested group resolution on systems like FreeIPA and "
|
||||||
|
"Active Directory"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/sources/ldap/models.py
|
#: authentik/sources/ldap/models.py
|
||||||
msgid "LDAP Source"
|
msgid "LDAP Source"
|
||||||
msgstr "LDAP Kaynağı"
|
msgstr "LDAP Kaynağı"
|
||||||
@ -2414,6 +2446,22 @@ msgstr "LDAP Kaynak Özellik Eşlemesi"
|
|||||||
msgid "LDAP Source Property Mappings"
|
msgid "LDAP Source Property Mappings"
|
||||||
msgstr "LDAP Kaynak Özellik Eşlemeleri"
|
msgstr "LDAP Kaynak Özellik Eşlemeleri"
|
||||||
|
|
||||||
|
#: authentik/sources/ldap/models.py
|
||||||
|
msgid "User LDAP Source Connection"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/sources/ldap/models.py
|
||||||
|
msgid "User LDAP Source Connections"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/sources/ldap/models.py
|
||||||
|
msgid "Group LDAP Source Connection"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/sources/ldap/models.py
|
||||||
|
msgid "Group LDAP Source Connections"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/sources/ldap/signals.py
|
#: authentik/sources/ldap/signals.py
|
||||||
msgid "Password does not match Active Directory Complexity."
|
msgid "Password does not match Active Directory Complexity."
|
||||||
msgstr "Parola Active Directory Karmaşıklığıyla eşleşmiyor."
|
msgstr "Parola Active Directory Karmaşıklığıyla eşleşmiyor."
|
||||||
@ -2422,6 +2470,14 @@ msgstr "Parola Active Directory Karmaşıklığıyla eşleşmiyor."
|
|||||||
msgid "No token received."
|
msgid "No token received."
|
||||||
msgstr "Jeton alınmadı."
|
msgstr "Jeton alınmadı."
|
||||||
|
|
||||||
|
#: authentik/sources/oauth/models.py
|
||||||
|
msgid "HTTP Basic Authentication"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/sources/oauth/models.py
|
||||||
|
msgid "Include the client ID and secret as request parameters"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/sources/oauth/models.py
|
#: authentik/sources/oauth/models.py
|
||||||
msgid "Request Token URL"
|
msgid "Request Token URL"
|
||||||
msgstr "Jeton URL'si İste"
|
msgstr "Jeton URL'si İste"
|
||||||
@ -2462,6 +2518,12 @@ msgstr "Kullanıcı bilgilerini almak için authentik tarafından kullanılan UR
|
|||||||
msgid "Additional Scopes"
|
msgid "Additional Scopes"
|
||||||
msgstr "Ek Kapsamlar"
|
msgstr "Ek Kapsamlar"
|
||||||
|
|
||||||
|
#: authentik/sources/oauth/models.py
|
||||||
|
msgid ""
|
||||||
|
"How to perform authentication during an authorization_code token request "
|
||||||
|
"flow"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/sources/oauth/models.py
|
#: authentik/sources/oauth/models.py
|
||||||
msgid "OAuth Source"
|
msgid "OAuth Source"
|
||||||
msgstr "OAuth Kaynağı"
|
msgstr "OAuth Kaynağı"
|
||||||
@ -3360,6 +3422,12 @@ msgstr ""
|
|||||||
"Etkinleştirildiğinde, yanlış kullanıcı bilgisi girilse bile aşama başarılı "
|
"Etkinleştirildiğinde, yanlış kullanıcı bilgisi girilse bile aşama başarılı "
|
||||||
"olur ve devam eder."
|
"olur ve devam eder."
|
||||||
|
|
||||||
|
#: authentik/stages/identification/models.py
|
||||||
|
msgid ""
|
||||||
|
"Show the user the 'Remember me on this device' toggle, allowing repeat users"
|
||||||
|
" to skip straight to entering their password."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/stages/identification/models.py
|
#: authentik/stages/identification/models.py
|
||||||
msgid "Optional enrollment flow, which is linked at the bottom of the page."
|
msgid "Optional enrollment flow, which is linked at the bottom of the page."
|
||||||
msgstr "Sayfanın alt kısmında bağlanan isteğe bağlı kayıt akışı."
|
msgstr "Sayfanın alt kısmında bağlanan isteğe bağlı kayıt akışı."
|
||||||
@ -3734,6 +3802,14 @@ msgstr ""
|
|||||||
"Olaylar bu süreden sonra silinecektir (Format: "
|
"Olaylar bu süreden sonra silinecektir (Format: "
|
||||||
"weeks=3;days=2;hours=3,seconds=2)."
|
"weeks=3;days=2;hours=3,seconds=2)."
|
||||||
|
|
||||||
|
#: authentik/tenants/models.py
|
||||||
|
msgid "Reputation cannot decrease lower than this value. Zero or negative."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/tenants/models.py
|
||||||
|
msgid "Reputation cannot increase higher than this value. Zero or positive."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/tenants/models.py
|
#: authentik/tenants/models.py
|
||||||
msgid "The option configures the footer links on the flow executor pages."
|
msgid "The option configures the footer links on the flow executor pages."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
Binary file not shown.
@ -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-15 00:11+0000\n"
|
"POT-Creation-Date: 2025-04-23 09:00+0000\n"
|
||||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||||
"Last-Translator: 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,6 +461,36 @@ msgstr "许可证使用情况"
|
|||||||
msgid "License Usage Records"
|
msgid "License Usage Records"
|
||||||
msgstr "许可证使用情况记录"
|
msgstr "许可证使用情况记录"
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
#: authentik/policies/password/models.py
|
||||||
|
msgid "Field key to check, field keys defined in Prompt stages are available."
|
||||||
|
msgstr "要检查的字段键,可以使用输入阶段中定义的字段键。"
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "Number of passwords to check against."
|
||||||
|
msgstr "检查指定数量的密码。"
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
#: authentik/policies/password/models.py
|
||||||
|
msgid "Password not set in context"
|
||||||
|
msgstr "未在上下文中设置密码"
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "This password has been used previously. Please choose a different one."
|
||||||
|
msgstr "此密码被使用过。请选择其他密码。"
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "Password Uniqueness Policy"
|
||||||
|
msgstr "密码唯一性策略"
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "Password Uniqueness Policies"
|
||||||
|
msgstr "密码唯一性策略"
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "User Password History"
|
||||||
|
msgstr "用户密码历史记录"
|
||||||
|
|
||||||
#: authentik/enterprise/policy.py
|
#: authentik/enterprise/policy.py
|
||||||
msgid "Enterprise required to access this feature."
|
msgid "Enterprise required to access this feature."
|
||||||
msgstr "访问此功能需要企业版。"
|
msgstr "访问此功能需要企业版。"
|
||||||
@ -1190,10 +1220,6 @@ msgstr "查看策略缓存指标"
|
|||||||
msgid "Clear Policy's cache metrics"
|
msgid "Clear Policy's cache metrics"
|
||||||
msgstr "清除策略缓存指标"
|
msgstr "清除策略缓存指标"
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
|
||||||
msgid "Field key to check, field keys defined in Prompt stages are available."
|
|
||||||
msgstr "要检查的字段键,可以使用输入阶段中定义的字段键。"
|
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
#: authentik/policies/password/models.py
|
||||||
msgid "How many times the password hash is allowed to be on haveibeenpwned"
|
msgid "How many times the password hash is allowed to be on haveibeenpwned"
|
||||||
msgstr "密码哈希允许出现在 HaveIBeenPwned 中多少次"
|
msgstr "密码哈希允许出现在 HaveIBeenPwned 中多少次"
|
||||||
@ -1203,10 +1229,6 @@ msgid ""
|
|||||||
"If the zxcvbn score is equal or less than this value, the policy will fail."
|
"If the zxcvbn score is equal or less than this value, the policy will fail."
|
||||||
msgstr "如果 zxcvbn 分数小于等于此值,则策略失败。"
|
msgstr "如果 zxcvbn 分数小于等于此值,则策略失败。"
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
|
||||||
msgid "Password not set in context"
|
|
||||||
msgstr "未在上下文中设置密码"
|
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
#: authentik/policies/password/models.py
|
||||||
msgid "Invalid password."
|
msgid "Invalid password."
|
||||||
msgstr "无效密码。"
|
msgstr "无效密码。"
|
||||||
@ -1248,20 +1270,6 @@ msgstr "信誉分数"
|
|||||||
msgid "Reputation Scores"
|
msgid "Reputation Scores"
|
||||||
msgstr "信誉分数"
|
msgstr "信誉分数"
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/buffer.html
|
|
||||||
msgid "Waiting for authentication..."
|
|
||||||
msgstr "正在等待身份验证…"
|
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/buffer.html
|
|
||||||
msgid ""
|
|
||||||
"You're already authenticating in another tab. This page will refresh once "
|
|
||||||
"authentication is completed."
|
|
||||||
msgstr "您正在另一个标签页中验证身份。身份验证完成后,此页面会刷新。"
|
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/buffer.html
|
|
||||||
msgid "Authenticate in this tab"
|
|
||||||
msgstr "在此标签页中验证身份"
|
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/denied.html
|
#: authentik/policies/templates/policies/denied.html
|
||||||
msgid "Permission denied"
|
msgid "Permission denied"
|
||||||
msgstr "权限被拒绝"
|
msgstr "权限被拒绝"
|
||||||
@ -2286,6 +2294,14 @@ 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"
|
||||||
@ -2324,6 +2340,12 @@ msgstr "authentik 用来获取用户信息的 URL。"
|
|||||||
msgid "Additional Scopes"
|
msgid "Additional Scopes"
|
||||||
msgstr "额外的作用域"
|
msgstr "额外的作用域"
|
||||||
|
|
||||||
|
#: authentik/sources/oauth/models.py
|
||||||
|
msgid ""
|
||||||
|
"How to perform authentication during an authorization_code token request "
|
||||||
|
"flow"
|
||||||
|
msgstr "在 authorization_code 令牌请求流程期间,如何执行身份验证"
|
||||||
|
|
||||||
#: authentik/sources/oauth/models.py
|
#: authentik/sources/oauth/models.py
|
||||||
msgid "OAuth Source"
|
msgid "OAuth Source"
|
||||||
msgstr "OAuth 源"
|
msgstr "OAuth 源"
|
||||||
@ -3194,6 +3216,12 @@ msgid ""
|
|||||||
"info is entered."
|
"info is entered."
|
||||||
msgstr "启用时,即使输入错误的用户信息,此阶段也会成功并继续。"
|
msgstr "启用时,即使输入错误的用户信息,此阶段也会成功并继续。"
|
||||||
|
|
||||||
|
#: authentik/stages/identification/models.py
|
||||||
|
msgid ""
|
||||||
|
"Show the user the 'Remember me on this device' toggle, allowing repeat users"
|
||||||
|
" to skip straight to entering their password."
|
||||||
|
msgstr "向用户显示“在此设备上记住我”开关,允许相同用户直接跳过输入密码。"
|
||||||
|
|
||||||
#: authentik/stages/identification/models.py
|
#: authentik/stages/identification/models.py
|
||||||
msgid "Optional enrollment flow, which is linked at the bottom of the page."
|
msgid "Optional enrollment flow, which is linked at the bottom of the page."
|
||||||
msgstr "可选注册流程,链接在页面底部。"
|
msgstr "可选注册流程,链接在页面底部。"
|
||||||
|
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-15 00:11+0000\n"
|
"POT-Creation-Date: 2025-04-23 09:00+0000\n"
|
||||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||||
"Last-Translator: 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,6 +460,36 @@ msgstr "许可证使用情况"
|
|||||||
msgid "License Usage Records"
|
msgid "License Usage Records"
|
||||||
msgstr "许可证使用情况记录"
|
msgstr "许可证使用情况记录"
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
#: authentik/policies/password/models.py
|
||||||
|
msgid "Field key to check, field keys defined in Prompt stages are available."
|
||||||
|
msgstr "要检查的字段键,可以使用输入阶段中定义的字段键。"
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "Number of passwords to check against."
|
||||||
|
msgstr "检查指定数量的密码。"
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
#: authentik/policies/password/models.py
|
||||||
|
msgid "Password not set in context"
|
||||||
|
msgstr "未在上下文中设置密码"
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "This password has been used previously. Please choose a different one."
|
||||||
|
msgstr "此密码被使用过。请选择其他密码。"
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "Password Uniqueness Policy"
|
||||||
|
msgstr "密码唯一性策略"
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "Password Uniqueness Policies"
|
||||||
|
msgstr "密码唯一性策略"
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "User Password History"
|
||||||
|
msgstr "用户密码历史记录"
|
||||||
|
|
||||||
#: authentik/enterprise/policy.py
|
#: authentik/enterprise/policy.py
|
||||||
msgid "Enterprise required to access this feature."
|
msgid "Enterprise required to access this feature."
|
||||||
msgstr "访问此功能需要企业版。"
|
msgstr "访问此功能需要企业版。"
|
||||||
@ -1189,10 +1219,6 @@ msgstr "查看策略缓存指标"
|
|||||||
msgid "Clear Policy's cache metrics"
|
msgid "Clear Policy's cache metrics"
|
||||||
msgstr "清除策略缓存指标"
|
msgstr "清除策略缓存指标"
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
|
||||||
msgid "Field key to check, field keys defined in Prompt stages are available."
|
|
||||||
msgstr "要检查的字段键,可以使用输入阶段中定义的字段键。"
|
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
#: authentik/policies/password/models.py
|
||||||
msgid "How many times the password hash is allowed to be on haveibeenpwned"
|
msgid "How many times the password hash is allowed to be on haveibeenpwned"
|
||||||
msgstr "密码哈希允许出现在 HaveIBeenPwned 中多少次"
|
msgstr "密码哈希允许出现在 HaveIBeenPwned 中多少次"
|
||||||
@ -1202,10 +1228,6 @@ msgid ""
|
|||||||
"If the zxcvbn score is equal or less than this value, the policy will fail."
|
"If the zxcvbn score is equal or less than this value, the policy will fail."
|
||||||
msgstr "如果 zxcvbn 分数小于等于此值,则策略失败。"
|
msgstr "如果 zxcvbn 分数小于等于此值,则策略失败。"
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
|
||||||
msgid "Password not set in context"
|
|
||||||
msgstr "未在上下文中设置密码"
|
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
#: authentik/policies/password/models.py
|
||||||
msgid "Invalid password."
|
msgid "Invalid password."
|
||||||
msgstr "无效密码。"
|
msgstr "无效密码。"
|
||||||
@ -1247,20 +1269,6 @@ msgstr "信誉分数"
|
|||||||
msgid "Reputation Scores"
|
msgid "Reputation Scores"
|
||||||
msgstr "信誉分数"
|
msgstr "信誉分数"
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/buffer.html
|
|
||||||
msgid "Waiting for authentication..."
|
|
||||||
msgstr "正在等待身份验证…"
|
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/buffer.html
|
|
||||||
msgid ""
|
|
||||||
"You're already authenticating in another tab. This page will refresh once "
|
|
||||||
"authentication is completed."
|
|
||||||
msgstr "您正在另一个标签页中验证身份。身份验证完成后,此页面会刷新。"
|
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/buffer.html
|
|
||||||
msgid "Authenticate in this tab"
|
|
||||||
msgstr "在此标签页中验证身份"
|
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/denied.html
|
#: authentik/policies/templates/policies/denied.html
|
||||||
msgid "Permission denied"
|
msgid "Permission denied"
|
||||||
msgstr "权限被拒绝"
|
msgstr "权限被拒绝"
|
||||||
@ -2285,6 +2293,14 @@ 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"
|
||||||
@ -2323,6 +2339,12 @@ msgstr "authentik 用来获取用户信息的 URL。"
|
|||||||
msgid "Additional Scopes"
|
msgid "Additional Scopes"
|
||||||
msgstr "额外的作用域"
|
msgstr "额外的作用域"
|
||||||
|
|
||||||
|
#: authentik/sources/oauth/models.py
|
||||||
|
msgid ""
|
||||||
|
"How to perform authentication during an authorization_code token request "
|
||||||
|
"flow"
|
||||||
|
msgstr "在 authorization_code 令牌请求流程期间,如何执行身份验证"
|
||||||
|
|
||||||
#: authentik/sources/oauth/models.py
|
#: authentik/sources/oauth/models.py
|
||||||
msgid "OAuth Source"
|
msgid "OAuth Source"
|
||||||
msgstr "OAuth 源"
|
msgstr "OAuth 源"
|
||||||
@ -3193,6 +3215,12 @@ msgid ""
|
|||||||
"info is entered."
|
"info is entered."
|
||||||
msgstr "启用时,即使输入错误的用户信息,此阶段也会成功并继续。"
|
msgstr "启用时,即使输入错误的用户信息,此阶段也会成功并继续。"
|
||||||
|
|
||||||
|
#: authentik/stages/identification/models.py
|
||||||
|
msgid ""
|
||||||
|
"Show the user the 'Remember me on this device' toggle, allowing repeat users"
|
||||||
|
" to skip straight to entering their password."
|
||||||
|
msgstr "向用户显示“在此设备上记住我”开关,允许相同用户直接跳过输入密码。"
|
||||||
|
|
||||||
#: authentik/stages/identification/models.py
|
#: authentik/stages/identification/models.py
|
||||||
msgid "Optional enrollment flow, which is linked at the bottom of the page."
|
msgid "Optional enrollment flow, which is linked at the bottom of the page."
|
||||||
msgstr "可选注册流程,链接在页面底部。"
|
msgstr "可选注册流程,链接在页面底部。"
|
||||||
|
Binary file not shown.
@ -14,7 +14,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PACKAGE VERSION\n"
|
"Project-Id-Version: PACKAGE VERSION\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2025-04-11 00:10+0000\n"
|
"POT-Creation-Date: 2025-04-23 09:00+0000\n"
|
||||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||||
"Last-Translator: 刘松, 2025\n"
|
"Last-Translator: 刘松, 2025\n"
|
||||||
"Language-Team: Chinese (Taiwan) (https://app.transifex.com/authentik/teams/119923/zh_TW/)\n"
|
"Language-Team: Chinese (Taiwan) (https://app.transifex.com/authentik/teams/119923/zh_TW/)\n"
|
||||||
@ -178,6 +178,7 @@ msgid "User's display name."
|
|||||||
msgstr "使用者的顯示名稱。"
|
msgstr "使用者的顯示名稱。"
|
||||||
|
|
||||||
#: authentik/core/models.py authentik/providers/oauth2/models.py
|
#: authentik/core/models.py authentik/providers/oauth2/models.py
|
||||||
|
#: authentik/rbac/models.py
|
||||||
msgid "User"
|
msgid "User"
|
||||||
msgstr "使用者"
|
msgstr "使用者"
|
||||||
|
|
||||||
@ -344,6 +345,18 @@ msgstr "屬性對應"
|
|||||||
msgid "Property Mappings"
|
msgid "Property Mappings"
|
||||||
msgstr "屬性對應"
|
msgstr "屬性對應"
|
||||||
|
|
||||||
|
#: authentik/core/models.py
|
||||||
|
msgid "session data"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/core/models.py
|
||||||
|
msgid "Session"
|
||||||
|
msgstr "会话"
|
||||||
|
|
||||||
|
#: authentik/core/models.py
|
||||||
|
msgid "Sessions"
|
||||||
|
msgstr "会话"
|
||||||
|
|
||||||
#: authentik/core/models.py
|
#: authentik/core/models.py
|
||||||
msgid "Authenticated Session"
|
msgid "Authenticated Session"
|
||||||
msgstr "已認證會談"
|
msgstr "已認證會談"
|
||||||
@ -447,6 +460,36 @@ msgstr "授權使用情況"
|
|||||||
msgid "License Usage Records"
|
msgid "License Usage Records"
|
||||||
msgstr "授權使用紀錄"
|
msgstr "授權使用紀錄"
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
#: authentik/policies/password/models.py
|
||||||
|
msgid "Field key to check, field keys defined in Prompt stages are available."
|
||||||
|
msgstr "要檢查的欄位鍵,在提示階段中有可用的已定義欄位鍵。"
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "Number of passwords to check against."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
#: authentik/policies/password/models.py
|
||||||
|
msgid "Password not set in context"
|
||||||
|
msgstr "未在上下文中設定密碼"
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "This password has been used previously. Please choose a different one."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "Password Uniqueness Policy"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "Password Uniqueness Policies"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/enterprise/policies/unique_password/models.py
|
||||||
|
msgid "User Password History"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/enterprise/policy.py
|
#: authentik/enterprise/policy.py
|
||||||
msgid "Enterprise required to access this feature."
|
msgid "Enterprise required to access this feature."
|
||||||
msgstr "企業版才能存取此功能。"
|
msgstr "企業版才能存取此功能。"
|
||||||
@ -1176,10 +1219,6 @@ msgstr "檢視原則的快取指標"
|
|||||||
msgid "Clear Policy's cache metrics"
|
msgid "Clear Policy's cache metrics"
|
||||||
msgstr "清除原則的快取指標"
|
msgstr "清除原則的快取指標"
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
|
||||||
msgid "Field key to check, field keys defined in Prompt stages are available."
|
|
||||||
msgstr "要檢查的欄位鍵,在提示階段中有可用的已定義欄位鍵。"
|
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
#: authentik/policies/password/models.py
|
||||||
msgid "How many times the password hash is allowed to be on haveibeenpwned"
|
msgid "How many times the password hash is allowed to be on haveibeenpwned"
|
||||||
msgstr "密碼雜湊在 haveibeenpwned 上允許出現的次數"
|
msgstr "密碼雜湊在 haveibeenpwned 上允許出現的次數"
|
||||||
@ -1189,10 +1228,6 @@ msgid ""
|
|||||||
"If the zxcvbn score is equal or less than this value, the policy will fail."
|
"If the zxcvbn score is equal or less than this value, the policy will fail."
|
||||||
msgstr "如果 zxcvbn 分數等於或小於此值,則該政策將失敗。"
|
msgstr "如果 zxcvbn 分數等於或小於此值,則該政策將失敗。"
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
|
||||||
msgid "Password not set in context"
|
|
||||||
msgstr "未在上下文中設定密碼"
|
|
||||||
|
|
||||||
#: authentik/policies/password/models.py
|
#: authentik/policies/password/models.py
|
||||||
msgid "Invalid password."
|
msgid "Invalid password."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@ -1234,20 +1269,6 @@ msgstr "信譽分數"
|
|||||||
msgid "Reputation Scores"
|
msgid "Reputation Scores"
|
||||||
msgstr "信譽分數"
|
msgstr "信譽分數"
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/buffer.html
|
|
||||||
msgid "Waiting for authentication..."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/buffer.html
|
|
||||||
msgid ""
|
|
||||||
"You're already authenticating in another tab. This page will refresh once "
|
|
||||||
"authentication is completed."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/buffer.html
|
|
||||||
msgid "Authenticate in this tab"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: authentik/policies/templates/policies/denied.html
|
#: authentik/policies/templates/policies/denied.html
|
||||||
msgid "Permission denied"
|
msgid "Permission denied"
|
||||||
msgstr "權限不足。"
|
msgstr "權限不足。"
|
||||||
@ -1999,6 +2020,10 @@ msgstr "角色"
|
|||||||
msgid "Roles"
|
msgid "Roles"
|
||||||
msgstr "角色"
|
msgstr "角色"
|
||||||
|
|
||||||
|
#: authentik/rbac/models.py
|
||||||
|
msgid "Initial Permissions"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/rbac/models.py
|
#: authentik/rbac/models.py
|
||||||
msgid "System permission"
|
msgid "System permission"
|
||||||
msgstr "系統權限"
|
msgstr "系統權限"
|
||||||
@ -2240,6 +2265,22 @@ msgstr ""
|
|||||||
msgid "LDAP Source Property Mappings"
|
msgid "LDAP Source Property Mappings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/sources/ldap/models.py
|
||||||
|
msgid "User LDAP Source Connection"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/sources/ldap/models.py
|
||||||
|
msgid "User LDAP Source Connections"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/sources/ldap/models.py
|
||||||
|
msgid "Group LDAP Source Connection"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/sources/ldap/models.py
|
||||||
|
msgid "Group LDAP Source Connections"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/sources/ldap/signals.py
|
#: authentik/sources/ldap/signals.py
|
||||||
msgid "Password does not match Active Directory Complexity."
|
msgid "Password does not match Active Directory Complexity."
|
||||||
msgstr "密碼不符合 Active Directory 的複雜性要求。"
|
msgstr "密碼不符合 Active Directory 的複雜性要求。"
|
||||||
@ -2248,6 +2289,14 @@ msgstr "密碼不符合 Active Directory 的複雜性要求。"
|
|||||||
msgid "No token received."
|
msgid "No token received."
|
||||||
msgstr "未收到權杖。"
|
msgstr "未收到權杖。"
|
||||||
|
|
||||||
|
#: authentik/sources/oauth/models.py
|
||||||
|
msgid "HTTP Basic Authentication"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/sources/oauth/models.py
|
||||||
|
msgid "Include the client ID and secret as request parameters"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/sources/oauth/models.py
|
#: authentik/sources/oauth/models.py
|
||||||
msgid "Request Token URL"
|
msgid "Request Token URL"
|
||||||
msgstr "請求權杖的網址"
|
msgstr "請求權杖的網址"
|
||||||
@ -2286,6 +2335,12 @@ msgstr "authentik 用來擷取使用者資訊的網址。"
|
|||||||
msgid "Additional Scopes"
|
msgid "Additional Scopes"
|
||||||
msgstr "附加範圍"
|
msgstr "附加範圍"
|
||||||
|
|
||||||
|
#: authentik/sources/oauth/models.py
|
||||||
|
msgid ""
|
||||||
|
"How to perform authentication during an authorization_code token request "
|
||||||
|
"flow"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/sources/oauth/models.py
|
#: authentik/sources/oauth/models.py
|
||||||
msgid "OAuth Source"
|
msgid "OAuth Source"
|
||||||
msgstr "OAuth 來源"
|
msgstr "OAuth 來源"
|
||||||
@ -3137,6 +3192,12 @@ msgid ""
|
|||||||
"info is entered."
|
"info is entered."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/stages/identification/models.py
|
||||||
|
msgid ""
|
||||||
|
"Show the user the 'Remember me on this device' toggle, allowing repeat users"
|
||||||
|
" to skip straight to entering their password."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/stages/identification/models.py
|
#: authentik/stages/identification/models.py
|
||||||
msgid "Optional enrollment flow, which is linked at the bottom of the page."
|
msgid "Optional enrollment flow, which is linked at the bottom of the page."
|
||||||
msgstr "可選的註冊流程,連結在頁面的底部。"
|
msgstr "可選的註冊流程,連結在頁面的底部。"
|
||||||
@ -3481,6 +3542,14 @@ msgid ""
|
|||||||
"weeks=3;days=2;hours=3,seconds=2)."
|
"weeks=3;days=2;hours=3,seconds=2)."
|
||||||
msgstr "事件將在此期間後刪除。(格式:weeks=3;days=2;hours=3,seconds=2)"
|
msgstr "事件將在此期間後刪除。(格式:weeks=3;days=2;hours=3,seconds=2)"
|
||||||
|
|
||||||
|
#: authentik/tenants/models.py
|
||||||
|
msgid "Reputation cannot decrease lower than this value. Zero or negative."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: authentik/tenants/models.py
|
||||||
|
msgid "Reputation cannot increase higher than this value. Zero or positive."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#: authentik/tenants/models.py
|
#: authentik/tenants/models.py
|
||||||
msgid "The option configures the footer links on the flow executor pages."
|
msgid "The option configures the footer links on the flow executor pages."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "@goauthentik/authentik",
|
"name": "@goauthentik/authentik",
|
||||||
"version": "2025.2.4",
|
"version": "2025.4.1",
|
||||||
"private": true
|
"private": true
|
||||||
}
|
}
|
||||||
|
@ -18,9 +18,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.badge--support-community {
|
.badge--support-community {
|
||||||
--ifm-badge-background-color: var(
|
--ifm-badge-background-color: var(--ifm-color-secondary-contrast-foreground);
|
||||||
--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,
|
RedHatVF, system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans,
|
||||||
Noto Sans, sans-serif, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial,
|
sans-serif, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif,
|
||||||
sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
"Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||||
|
|
||||||
--ifm-font-family-monospace:
|
--ifm-font-family-monospace:
|
||||||
RedHatMonoVF, SFMono-Regular, Menlo, Monaco, Consolas,
|
RedHatMonoVF, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New",
|
||||||
"Liberation Mono", "Courier New", monospace;
|
monospace;
|
||||||
|
|
||||||
--ifm-heading-font-family: RedHatDisplayVF, var(--ifm-font-family-base);
|
--ifm-heading-font-family: RedHatDisplayVF, var(--ifm-font-family-base);
|
||||||
|
|
||||||
|
@ -7,11 +7,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.homepage_hero__subtitle p {
|
.homepage_hero__subtitle p {
|
||||||
font-size: clamp(
|
font-size: clamp(1.125rem, 0.9946rem + 0.6522vi, 1.5rem); /* Adjust font as page scales */
|
||||||
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: 1em;
|
--ifm-menu-link-padding-vertical: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.menu__list-item {
|
.menu__list-item {
|
||||||
|
@ -75,17 +75,14 @@
|
|||||||
--ifm-navbar-item-padding-horizontal: 1rem;
|
--ifm-navbar-item-padding-horizontal: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.docs-wrapper .navbar {
|
.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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,12 +119,8 @@
|
|||||||
|
|
||||||
@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(
|
margin-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);
|
||||||
);
|
|
||||||
padding-inline-start: calc(
|
|
||||||
var(--ifm-navbar-item-padding-horizontal) / 2
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,19 +144,14 @@
|
|||||||
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 -2px 0 0 hsl(233.33deg 36% 24.51%), inset 0 0 1px 1px hsl(232.11deg 34.86% 57.25%),
|
||||||
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 -2px 0 0 #282d55, inset 0 0 1px 1px hsl(231.82deg 21.36% 40.39%),
|
||||||
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)
|
padding: var(--ifm-navbar-item-padding-vertical) var(--ifm-navbar-item-padding-horizontal) !important;
|
||||||
var(--ifm-navbar-item-padding-horizontal) !important;
|
padding-inline-end: calc(var(--ifm-navbar-item-padding-horizontal) * 1.25) !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,7 +13,3 @@
|
|||||||
|
|
||||||
--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,7 +4,6 @@
|
|||||||
* @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.2",
|
"version": "1.0.5",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "@goauthentik/docusaurus-config",
|
"name": "@goauthentik/docusaurus-config",
|
||||||
"version": "1.0.2",
|
"version": "1.0.5",
|
||||||
"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.4",
|
"version": "1.0.5",
|
||||||
"description": "authentik's Docusaurus config",
|
"description": "authentik's Docusaurus config",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -76,6 +76,7 @@ EXPOSE 9000 9300 9443
|
|||||||
|
|
||||||
USER 1000
|
USER 1000
|
||||||
|
|
||||||
ENV GOFIPS=1
|
ENV TMPDIR=/dev/shm/ \
|
||||||
|
GOFIPS=1
|
||||||
|
|
||||||
ENTRYPOINT ["/proxy"]
|
ENTRYPOINT ["/proxy"]
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user