Compare commits
5 Commits
endpoints
...
consistent
Author | SHA1 | Date | |
---|---|---|---|
6d1bffc9f9 | |||
1a132a733f | |||
7d8bcdf8e7 | |||
2f2883edb4 | |||
95ee88c946 |
2
.github/actions/setup/action.yml
vendored
2
.github/actions/setup/action.yml
vendored
@ -36,7 +36,7 @@ runs:
|
||||
with:
|
||||
go-version-file: "go.mod"
|
||||
- name: Setup docker cache
|
||||
uses: AndreKurait/docker-cache@0fe76702a40db986d9663c24954fc14c6a6031b7
|
||||
uses: ScribeMD/docker-cache@0.5.0
|
||||
with:
|
||||
key: docker-images-${{ runner.os }}-${{ hashFiles('.github/actions/setup/docker-compose.yml', 'Makefile') }}-${{ inputs.postgresql_version }}
|
||||
- name: Setup dependencies
|
||||
|
2
.github/workflows/ci-main.yml
vendored
2
.github/workflows/ci-main.yml
vendored
@ -62,7 +62,6 @@ jobs:
|
||||
psql:
|
||||
- 15-alpine
|
||||
- 16-alpine
|
||||
- 17-alpine
|
||||
run_id: [1, 2, 3, 4, 5]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@ -117,7 +116,6 @@ jobs:
|
||||
psql:
|
||||
- 15-alpine
|
||||
- 16-alpine
|
||||
- 17-alpine
|
||||
run_id: [1, 2, 3, 4, 5]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
17
.github/workflows/packages-npm-publish.yml
vendored
17
.github/workflows/packages-npm-publish.yml
vendored
@ -7,7 +7,7 @@ on:
|
||||
- packages/eslint-config/**
|
||||
- packages/prettier-config/**
|
||||
- packages/tsconfig/**
|
||||
- web/packages/esbuild-plugin-live-reload/**
|
||||
- packages/web/esbuild-plugin-live-reload/**
|
||||
workflow_dispatch:
|
||||
jobs:
|
||||
publish:
|
||||
@ -17,28 +17,27 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
package:
|
||||
- packages/docusaurus-config
|
||||
- packages/eslint-config
|
||||
- packages/prettier-config
|
||||
- packages/tsconfig
|
||||
- web/packages/esbuild-plugin-live-reload
|
||||
- docusaurus-config
|
||||
- eslint-config
|
||||
- prettier-config
|
||||
- tsconfig
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 2
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: ${{ matrix.package }}/package.json
|
||||
node-version-file: packages/${{ matrix.package }}/package.json
|
||||
registry-url: "https://registry.npmjs.org"
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@ed68ef82c095e0d48ec87eccea555d944a631a4c
|
||||
with:
|
||||
files: |
|
||||
${{ matrix.package }}/package.json
|
||||
packages/${{ matrix.package }}/package.json
|
||||
- name: Publish package
|
||||
if: steps.changed-files.outputs.any_changed == 'true'
|
||||
working-directory: ${{ matrix.package }}
|
||||
working-directory: packages/${{ matrix.package}}
|
||||
run: |
|
||||
npm ci
|
||||
npm run build
|
||||
|
@ -94,7 +94,7 @@ RUN --mount=type=secret,id=GEOIPUPDATE_ACCOUNT_ID \
|
||||
/bin/sh -c "GEOIPUPDATE_LICENSE_KEY_FILE=/run/secrets/GEOIPUPDATE_LICENSE_KEY /usr/bin/entry.sh || echo 'Failed to get GeoIP database, disabling'; exit 0"
|
||||
|
||||
# Stage 5: Download uv
|
||||
FROM ghcr.io/astral-sh/uv:0.7.8 AS uv
|
||||
FROM ghcr.io/astral-sh/uv:0.7.7 AS uv
|
||||
# Stage 6: Base python image
|
||||
FROM ghcr.io/goauthentik/fips-python:3.13.3-slim-bookworm-fips AS python-base
|
||||
|
||||
|
2
Makefile
2
Makefile
@ -1,6 +1,6 @@
|
||||
.PHONY: gen dev-reset all clean test web website
|
||||
|
||||
SHELL := /usr/bin/env bash
|
||||
SHELL := /bin/bash
|
||||
.SHELLFLAGS += ${SHELLFLAGS} -e -o pipefail
|
||||
PWD = $(shell pwd)
|
||||
UID = $(shell id -u)
|
||||
|
@ -84,7 +84,6 @@ from authentik.flows.views.executor import QS_KEY_TOKEN
|
||||
from authentik.lib.avatars import get_avatar
|
||||
from authentik.rbac.decorators import permission_required
|
||||
from authentik.rbac.models import get_permission_choices
|
||||
from authentik.stages.email.flow import pickle_flow_token_for_email
|
||||
from authentik.stages.email.models import EmailStage
|
||||
from authentik.stages.email.tasks import send_mails
|
||||
from authentik.stages.email.utils import TemplateEmailMessage
|
||||
@ -452,7 +451,7 @@ class UserViewSet(UsedByMixin, ModelViewSet):
|
||||
def list(self, request, *args, **kwargs):
|
||||
return super().list(request, *args, **kwargs)
|
||||
|
||||
def _create_recovery_link(self, for_email=False) -> tuple[str, Token]:
|
||||
def _create_recovery_link(self) -> tuple[str, Token]:
|
||||
"""Create a recovery link (when the current brand has a recovery flow set),
|
||||
that can either be shown to an admin or sent to the user directly"""
|
||||
brand: Brand = self.request._request.brand
|
||||
@ -474,16 +473,12 @@ class UserViewSet(UsedByMixin, ModelViewSet):
|
||||
raise ValidationError(
|
||||
{"non_field_errors": "Recovery flow not applicable to user"}
|
||||
) from None
|
||||
_plan = FlowToken.pickle(plan)
|
||||
if for_email:
|
||||
_plan = pickle_flow_token_for_email(plan)
|
||||
token, __ = FlowToken.objects.update_or_create(
|
||||
identifier=f"{user.uid}-password-reset",
|
||||
defaults={
|
||||
"user": user,
|
||||
"flow": flow,
|
||||
"_plan": _plan,
|
||||
"revoke_on_execution": not for_email,
|
||||
"_plan": FlowToken.pickle(plan),
|
||||
},
|
||||
)
|
||||
querystring = urlencode({QS_KEY_TOKEN: token.key})
|
||||
@ -653,7 +648,7 @@ class UserViewSet(UsedByMixin, ModelViewSet):
|
||||
if for_user.email == "":
|
||||
LOGGER.debug("User doesn't have an email address")
|
||||
raise ValidationError({"non_field_errors": "User does not have an email address set."})
|
||||
link, token = self._create_recovery_link(for_email=True)
|
||||
link, token = self._create_recovery_link()
|
||||
# Lookup the email stage to assure the current user can access it
|
||||
stages = get_objects_for_user(
|
||||
request.user, "authentik_stages_email.view_emailstage"
|
||||
|
@ -1,12 +0,0 @@
|
||||
"""authentik endpoints app config"""
|
||||
|
||||
from authentik.blueprints.apps import ManagedAppConfig
|
||||
|
||||
|
||||
class AuthentikEndpointsConfig(ManagedAppConfig):
|
||||
"""authentik endpoints app config"""
|
||||
|
||||
name = "authentik.endpoints"
|
||||
label = "authentik_endpoints"
|
||||
verbose_name = "authentik Endpoints"
|
||||
default = True
|
@ -1,47 +0,0 @@
|
||||
from enum import Enum
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class UNSUPPORTED(BaseModel):
|
||||
pass
|
||||
|
||||
|
||||
class OSFamily(Enum):
|
||||
|
||||
linux = "linux"
|
||||
unix = "unix"
|
||||
bsd = "bsd"
|
||||
windows = "windows"
|
||||
macOS = "mac_os"
|
||||
android = "android"
|
||||
iOS = "i_os"
|
||||
other = "other"
|
||||
|
||||
class CommonDeviceData(BaseModel):
|
||||
class Disk(BaseModel):
|
||||
encryption: bool
|
||||
|
||||
class OS(BaseModel):
|
||||
firewall_enabled: bool
|
||||
family: OSFamily
|
||||
name: str
|
||||
version: str
|
||||
|
||||
class Network(BaseModel):
|
||||
hostname: str
|
||||
dns_servers: list[str]
|
||||
|
||||
class Hardware(BaseModel):
|
||||
model: str
|
||||
manufacturer: str
|
||||
|
||||
class Software(BaseModel):
|
||||
name: str
|
||||
version: str
|
||||
|
||||
os: OS | UNSUPPORTED
|
||||
disks: list[Disk] | UNSUPPORTED
|
||||
network: Network | UNSUPPORTED
|
||||
hardware: Hardware | UNSUPPORTED
|
||||
software: list[Software] | UNSUPPORTED
|
@ -1,16 +0,0 @@
|
||||
from authentik.blueprints import models
|
||||
|
||||
|
||||
class EnrollmentMethods(models.TextChoices):
|
||||
AUTOMATIC_USER = "automatic_user" # Automatically enrolled through user action
|
||||
AUTOMATIC_API = "automatic_api" # Automatically enrolled through connector integration
|
||||
MANUAL_USER = "manual_user" # Manually enrolled
|
||||
|
||||
|
||||
class BaseConnector:
|
||||
|
||||
def __init__(self) -> None:
|
||||
pass
|
||||
|
||||
def supported_enrollment_methods(self) -> list[EnrollmentMethods]:
|
||||
return []
|
@ -1,7 +0,0 @@
|
||||
from authentik.endpoints.connector import BaseConnector, EnrollmentMethods
|
||||
|
||||
|
||||
class GoogleChromeConnector(BaseConnector):
|
||||
|
||||
def supported_enrollment_methods(self) -> list[EnrollmentMethods]:
|
||||
return [EnrollmentMethods.AUTOMATIC_USER]
|
@ -1,7 +0,0 @@
|
||||
from django.db import models
|
||||
|
||||
from authentik.endpoints.models import Connector
|
||||
|
||||
|
||||
class GoogleChromeConnector(Connector):
|
||||
credentials = models.JSONField()
|
@ -1,125 +0,0 @@
|
||||
# Generated by Django 5.0.9 on 2024-09-24 19:16
|
||||
|
||||
import django.db.models.deletion
|
||||
import uuid
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="Connector",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
|
||||
),
|
||||
),
|
||||
("connector_uuid", models.UUIDField(default=uuid.uuid4)),
|
||||
("name", models.TextField()),
|
||||
(
|
||||
"enrollment_method",
|
||||
models.TextField(
|
||||
choices=[
|
||||
("automatic_user", "Automatic User"),
|
||||
("automatic_api", "Automatic Api"),
|
||||
("manual_user", "Manual User"),
|
||||
]
|
||||
),
|
||||
),
|
||||
],
|
||||
options={
|
||||
"abstract": False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="Device",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
|
||||
),
|
||||
),
|
||||
("device_uuid", models.UUIDField(default=uuid.uuid4)),
|
||||
("identifier", models.TextField(unique=True)),
|
||||
],
|
||||
options={
|
||||
"abstract": False,
|
||||
},
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="DeviceConnection",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
|
||||
),
|
||||
),
|
||||
("device_connection_uuid", models.UUIDField(default=uuid.uuid4)),
|
||||
("data", models.JSONField(default=dict)),
|
||||
(
|
||||
"connection",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to="authentik_endpoints.connector",
|
||||
),
|
||||
),
|
||||
(
|
||||
"device",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE, to="authentik_endpoints.device"
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="device",
|
||||
name="connections",
|
||||
field=models.ManyToManyField(
|
||||
through="authentik_endpoints.DeviceConnection", to="authentik_endpoints.connector"
|
||||
),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name="DeviceUser",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
|
||||
),
|
||||
),
|
||||
("device_user_uuid", models.UUIDField(default=uuid.uuid4)),
|
||||
("is_primary", models.BooleanField()),
|
||||
(
|
||||
"device",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE, to="authentik_endpoints.device"
|
||||
),
|
||||
),
|
||||
(
|
||||
"user",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="device",
|
||||
name="users",
|
||||
field=models.ManyToManyField(
|
||||
through="authentik_endpoints.DeviceUser", to=settings.AUTH_USER_MODEL
|
||||
),
|
||||
),
|
||||
]
|
@ -1,40 +0,0 @@
|
||||
from uuid import uuid4
|
||||
|
||||
from django.db import models
|
||||
from django.utils.functional import cached_property
|
||||
|
||||
from authentik.core.models import User
|
||||
from authentik.endpoints.common_data import CommonDeviceData
|
||||
from authentik.lib.models import SerializerModel
|
||||
|
||||
|
||||
class Device(SerializerModel):
|
||||
device_uuid = models.UUIDField(default=uuid4)
|
||||
|
||||
identifier = models.TextField(unique=True)
|
||||
users = models.ManyToManyField(User, through="DeviceUser")
|
||||
connections = models.ManyToManyField("Connector", through="DeviceConnection")
|
||||
|
||||
@cached_property
|
||||
def data(self) -> CommonDeviceData:
|
||||
pass
|
||||
|
||||
|
||||
class DeviceUser(models.Model):
|
||||
device_user_uuid = models.UUIDField(default=uuid4)
|
||||
device = models.ForeignKey("Device", on_delete=models.CASCADE)
|
||||
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
is_primary = models.BooleanField()
|
||||
|
||||
|
||||
class DeviceConnection(models.Model):
|
||||
device_connection_uuid = models.UUIDField(default=uuid4)
|
||||
device = models.ForeignKey("Device", on_delete=models.CASCADE)
|
||||
connection = models.ForeignKey("Connector", on_delete=models.CASCADE)
|
||||
data = models.JSONField(default=dict)
|
||||
|
||||
|
||||
class Connector(SerializerModel):
|
||||
connector_uuid = models.UUIDField(default=uuid4)
|
||||
|
||||
name = models.TextField()
|
@ -1,18 +0,0 @@
|
||||
# Generated by Django 5.1.9 on 2025-05-27 12:52
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("authentik_flows", "0027_auto_20231028_1424"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="flowtoken",
|
||||
name="revoke_on_execution",
|
||||
field=models.BooleanField(default=True),
|
||||
),
|
||||
]
|
@ -303,10 +303,9 @@ class FlowToken(Token):
|
||||
|
||||
flow = models.ForeignKey(Flow, on_delete=models.CASCADE)
|
||||
_plan = models.TextField()
|
||||
revoke_on_execution = models.BooleanField(default=True)
|
||||
|
||||
@staticmethod
|
||||
def pickle(plan: "FlowPlan") -> str:
|
||||
def pickle(plan) -> str:
|
||||
"""Pickle into string"""
|
||||
data = dumps(plan)
|
||||
return b64encode(data).decode()
|
||||
|
@ -99,10 +99,9 @@ class ChallengeStageView(StageView):
|
||||
self.logger.debug("Got StageInvalidException", exc=exc)
|
||||
return self.executor.stage_invalid()
|
||||
if not challenge.is_valid():
|
||||
self.logger.error(
|
||||
self.logger.warning(
|
||||
"f(ch): Invalid challenge",
|
||||
errors=challenge.errors,
|
||||
challenge=challenge.data,
|
||||
)
|
||||
return HttpChallengeResponse(challenge)
|
||||
|
||||
|
@ -146,8 +146,7 @@ class FlowExecutorView(APIView):
|
||||
except (AttributeError, EOFError, ImportError, IndexError) as exc:
|
||||
LOGGER.warning("f(exec): Failed to restore token plan", exc=exc)
|
||||
finally:
|
||||
if token.revoke_on_execution:
|
||||
token.delete()
|
||||
token.delete()
|
||||
if not isinstance(plan, FlowPlan):
|
||||
return None
|
||||
plan.context[PLAN_CONTEXT_IS_RESTORED] = token
|
||||
|
@ -1,7 +1,6 @@
|
||||
from collections.abc import Callable
|
||||
from dataclasses import asdict
|
||||
|
||||
from celery import group
|
||||
from celery.exceptions import Retry
|
||||
from celery.result import allow_join_result
|
||||
from django.core.paginator import Paginator
|
||||
@ -83,41 +82,21 @@ class SyncTasks:
|
||||
self.logger.debug("Failed to acquire sync lock, skipping", provider=provider.name)
|
||||
return
|
||||
try:
|
||||
messages.append(_("Syncing users"))
|
||||
user_results = (
|
||||
group(
|
||||
[
|
||||
sync_objects.signature(
|
||||
args=(class_to_path(User), page, provider_pk),
|
||||
time_limit=PAGE_TIMEOUT,
|
||||
soft_time_limit=PAGE_TIMEOUT,
|
||||
)
|
||||
for page in users_paginator.page_range
|
||||
]
|
||||
)
|
||||
.apply_async()
|
||||
.get()
|
||||
)
|
||||
for result in user_results:
|
||||
for msg in result:
|
||||
for page in users_paginator.page_range:
|
||||
messages.append(_("Syncing page {page} of users".format(page=page)))
|
||||
for msg in sync_objects.apply_async(
|
||||
args=(class_to_path(User), page, provider_pk),
|
||||
time_limit=PAGE_TIMEOUT,
|
||||
soft_time_limit=PAGE_TIMEOUT,
|
||||
).get():
|
||||
messages.append(LogEvent(**msg))
|
||||
messages.append(_("Syncing groups"))
|
||||
group_results = (
|
||||
group(
|
||||
[
|
||||
sync_objects.signature(
|
||||
args=(class_to_path(Group), page, provider_pk),
|
||||
time_limit=PAGE_TIMEOUT,
|
||||
soft_time_limit=PAGE_TIMEOUT,
|
||||
)
|
||||
for page in groups_paginator.page_range
|
||||
]
|
||||
)
|
||||
.apply_async()
|
||||
.get()
|
||||
)
|
||||
for result in group_results:
|
||||
for msg in result:
|
||||
for page in groups_paginator.page_range:
|
||||
messages.append(_("Syncing page {page} of groups".format(page=page)))
|
||||
for msg in sync_objects.apply_async(
|
||||
args=(class_to_path(Group), page, provider_pk),
|
||||
time_limit=PAGE_TIMEOUT,
|
||||
soft_time_limit=PAGE_TIMEOUT,
|
||||
).get():
|
||||
messages.append(LogEvent(**msg))
|
||||
except TransientSyncException as exc:
|
||||
self.logger.warning("transient sync exception", exc=exc)
|
||||
@ -153,15 +132,6 @@ class SyncTasks:
|
||||
self.logger.debug("starting discover")
|
||||
client.discover()
|
||||
self.logger.debug("starting sync for page", page=page)
|
||||
messages.append(
|
||||
asdict(
|
||||
LogEvent(
|
||||
_("Syncing page {page} of groups".format(page=page)),
|
||||
log_level="info",
|
||||
logger=f"{provider._meta.verbose_name}@{object_type}",
|
||||
)
|
||||
)
|
||||
)
|
||||
for obj in paginator.page(page).object_list:
|
||||
obj: Model
|
||||
try:
|
||||
|
@ -384,7 +384,7 @@ class SCIMUserTests(TestCase):
|
||||
self.assertIn(request.method, SAFE_METHODS)
|
||||
task = SystemTask.objects.filter(uid=slugify(self.provider.name)).first()
|
||||
self.assertIsNotNone(task)
|
||||
drop_msg = task.messages[3]
|
||||
drop_msg = task.messages[2]
|
||||
self.assertEqual(drop_msg["event"], "Dropping mutating request due to dry run")
|
||||
self.assertIsNotNone(drop_msg["attributes"]["url"])
|
||||
self.assertIsNotNone(drop_msg["attributes"]["body"])
|
||||
|
@ -73,7 +73,6 @@ TENANT_APPS = [
|
||||
"authentik.admin",
|
||||
"authentik.api",
|
||||
"authentik.crypto",
|
||||
"authentik.endpoints",
|
||||
"authentik.flows",
|
||||
"authentik.outposts",
|
||||
"authentik.policies.dummy",
|
||||
@ -425,7 +424,7 @@ else:
|
||||
"BACKEND": "authentik.root.storages.FileStorage",
|
||||
"OPTIONS": {
|
||||
"location": Path(CONFIG.get("storage.media.file.path")),
|
||||
"base_url": CONFIG.get("web.path", "/") + "media/",
|
||||
"base_url": "/media/",
|
||||
},
|
||||
}
|
||||
# Compatibility for apps not supporting top-level STORAGES
|
||||
|
@ -31,8 +31,6 @@ class PytestTestRunner(DiscoverRunner): # pragma: no cover
|
||||
|
||||
if kwargs.get("randomly_seed", None):
|
||||
self.args.append(f"--randomly-seed={kwargs['randomly_seed']}")
|
||||
if kwargs.get("no_capture", False):
|
||||
self.args.append("--capture=no")
|
||||
|
||||
settings.TEST = True
|
||||
settings.CELERY["task_always_eager"] = True
|
||||
@ -66,11 +64,6 @@ class PytestTestRunner(DiscoverRunner): # pragma: no cover
|
||||
"Default behaviour: use random.Random().getrandbits(32), so the seed is"
|
||||
"different on each run.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--no-capture",
|
||||
action="store_true",
|
||||
help="Disable any capturing of stdout/stderr during tests.",
|
||||
)
|
||||
|
||||
def run_tests(self, test_labels, extra_tests=None, **kwargs):
|
||||
"""Run pytest and return the exitcode.
|
||||
|
@ -111,7 +111,6 @@ class LDAPSourceSerializer(SourceSerializer):
|
||||
"sync_parent_group",
|
||||
"connectivity",
|
||||
"lookup_groups_from_user",
|
||||
"delete_not_found_objects",
|
||||
]
|
||||
extra_kwargs = {"bind_password": {"write_only": True}}
|
||||
|
||||
@ -148,7 +147,6 @@ class LDAPSourceViewSet(UsedByMixin, ModelViewSet):
|
||||
"user_property_mappings",
|
||||
"group_property_mappings",
|
||||
"lookup_groups_from_user",
|
||||
"delete_not_found_objects",
|
||||
]
|
||||
search_fields = ["name", "slug"]
|
||||
ordering = ["name"]
|
||||
|
@ -1,48 +0,0 @@
|
||||
# Generated by Django 5.1.9 on 2025-05-28 08:15
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("authentik_core", "0048_delete_oldauthenticatedsession_content_type"),
|
||||
("authentik_sources_ldap", "0008_groupldapsourceconnection_userldapsourceconnection"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="groupldapsourceconnection",
|
||||
name="validated_by",
|
||||
field=models.UUIDField(
|
||||
blank=True,
|
||||
help_text="Unique ID used while checking if this object still exists in the directory.",
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="ldapsource",
|
||||
name="delete_not_found_objects",
|
||||
field=models.BooleanField(
|
||||
default=False,
|
||||
help_text="Delete authentik users and groups which were previously supplied by this source, but are now missing from it.",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="userldapsourceconnection",
|
||||
name="validated_by",
|
||||
field=models.UUIDField(
|
||||
blank=True,
|
||||
help_text="Unique ID used while checking if this object still exists in the directory.",
|
||||
null=True,
|
||||
),
|
||||
),
|
||||
migrations.AddIndex(
|
||||
model_name="groupldapsourceconnection",
|
||||
index=models.Index(fields=["validated_by"], name="authentik_s_validat_b70447_idx"),
|
||||
),
|
||||
migrations.AddIndex(
|
||||
model_name="userldapsourceconnection",
|
||||
index=models.Index(fields=["validated_by"], name="authentik_s_validat_ff2ebc_idx"),
|
||||
),
|
||||
]
|
@ -137,14 +137,6 @@ class LDAPSource(Source):
|
||||
),
|
||||
)
|
||||
|
||||
delete_not_found_objects = models.BooleanField(
|
||||
default=False,
|
||||
help_text=_(
|
||||
"Delete authentik users and groups which were previously supplied by this source, "
|
||||
"but are now missing from it."
|
||||
),
|
||||
)
|
||||
|
||||
@property
|
||||
def component(self) -> str:
|
||||
return "ak-source-ldap-form"
|
||||
@ -329,12 +321,6 @@ class LDAPSourcePropertyMapping(PropertyMapping):
|
||||
|
||||
|
||||
class UserLDAPSourceConnection(UserSourceConnection):
|
||||
validated_by = models.UUIDField(
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text=_("Unique ID used while checking if this object still exists in the directory."),
|
||||
)
|
||||
|
||||
@property
|
||||
def serializer(self) -> type[Serializer]:
|
||||
from authentik.sources.ldap.api import (
|
||||
@ -346,18 +332,9 @@ class UserLDAPSourceConnection(UserSourceConnection):
|
||||
class Meta:
|
||||
verbose_name = _("User LDAP Source Connection")
|
||||
verbose_name_plural = _("User LDAP Source Connections")
|
||||
indexes = [
|
||||
models.Index(fields=["validated_by"]),
|
||||
]
|
||||
|
||||
|
||||
class GroupLDAPSourceConnection(GroupSourceConnection):
|
||||
validated_by = models.UUIDField(
|
||||
null=True,
|
||||
blank=True,
|
||||
help_text=_("Unique ID used while checking if this object still exists in the directory."),
|
||||
)
|
||||
|
||||
@property
|
||||
def serializer(self) -> type[Serializer]:
|
||||
from authentik.sources.ldap.api import (
|
||||
@ -369,6 +346,3 @@ class GroupLDAPSourceConnection(GroupSourceConnection):
|
||||
class Meta:
|
||||
verbose_name = _("Group LDAP Source Connection")
|
||||
verbose_name_plural = _("Group LDAP Source Connections")
|
||||
indexes = [
|
||||
models.Index(fields=["validated_by"]),
|
||||
]
|
||||
|
@ -9,7 +9,7 @@ from structlog.stdlib import BoundLogger, get_logger
|
||||
from authentik.core.sources.mapper import SourceMapper
|
||||
from authentik.lib.config import CONFIG
|
||||
from authentik.lib.sync.mapper import PropertyMappingManager
|
||||
from authentik.sources.ldap.models import LDAPSource, flatten
|
||||
from authentik.sources.ldap.models import LDAPSource
|
||||
|
||||
|
||||
class BaseLDAPSynchronizer:
|
||||
@ -77,16 +77,6 @@ class BaseLDAPSynchronizer:
|
||||
"""Get objects from LDAP, implemented in subclass"""
|
||||
raise NotImplementedError()
|
||||
|
||||
def get_attributes(self, object):
|
||||
if "attributes" not in object:
|
||||
return
|
||||
return object.get("attributes", {})
|
||||
|
||||
def get_identifier(self, attributes: dict):
|
||||
if not attributes.get(self._source.object_uniqueness_field):
|
||||
return
|
||||
return flatten(attributes[self._source.object_uniqueness_field])
|
||||
|
||||
def search_paginator( # noqa: PLR0913
|
||||
self,
|
||||
search_base,
|
||||
|
@ -1,61 +0,0 @@
|
||||
from collections.abc import Generator
|
||||
from itertools import batched
|
||||
from uuid import uuid4
|
||||
|
||||
from ldap3 import SUBTREE
|
||||
|
||||
from authentik.core.models import Group
|
||||
from authentik.sources.ldap.models import GroupLDAPSourceConnection
|
||||
from authentik.sources.ldap.sync.base import BaseLDAPSynchronizer
|
||||
from authentik.sources.ldap.sync.forward_delete_users import DELETE_CHUNK_SIZE, UPDATE_CHUNK_SIZE
|
||||
|
||||
|
||||
class GroupLDAPForwardDeletion(BaseLDAPSynchronizer):
|
||||
"""Delete LDAP Groups from authentik"""
|
||||
|
||||
@staticmethod
|
||||
def name() -> str:
|
||||
return "group_deletions"
|
||||
|
||||
def get_objects(self, **kwargs) -> Generator:
|
||||
if not self._source.sync_groups or not self._source.delete_not_found_objects:
|
||||
self.message("Group syncing is disabled for this Source")
|
||||
return iter(())
|
||||
|
||||
uuid = uuid4()
|
||||
groups = self._source.connection().extend.standard.paged_search(
|
||||
search_base=self.base_dn_groups,
|
||||
search_filter=self._source.group_object_filter,
|
||||
search_scope=SUBTREE,
|
||||
attributes=[self._source.object_uniqueness_field],
|
||||
generator=True,
|
||||
**kwargs,
|
||||
)
|
||||
for batch in batched(groups, UPDATE_CHUNK_SIZE, strict=False):
|
||||
identifiers = []
|
||||
for group in batch:
|
||||
if not (attributes := self.get_attributes(group)):
|
||||
continue
|
||||
if identifier := self.get_identifier(attributes):
|
||||
identifiers.append(identifier)
|
||||
GroupLDAPSourceConnection.objects.filter(identifier__in=identifiers).update(
|
||||
validated_by=uuid
|
||||
)
|
||||
|
||||
return batched(
|
||||
GroupLDAPSourceConnection.objects.filter(source=self._source)
|
||||
.exclude(validated_by=uuid)
|
||||
.values_list("group", flat=True)
|
||||
.iterator(chunk_size=DELETE_CHUNK_SIZE),
|
||||
DELETE_CHUNK_SIZE,
|
||||
strict=False,
|
||||
)
|
||||
|
||||
def sync(self, group_pks: tuple) -> int:
|
||||
"""Delete authentik groups"""
|
||||
if not self._source.sync_groups or not self._source.delete_not_found_objects:
|
||||
self.message("Group syncing is disabled for this Source")
|
||||
return -1
|
||||
self._logger.debug("Deleting groups", group_pks=group_pks)
|
||||
_, deleted_per_type = Group.objects.filter(pk__in=group_pks).delete()
|
||||
return deleted_per_type.get(Group._meta.label, 0)
|
@ -1,63 +0,0 @@
|
||||
from collections.abc import Generator
|
||||
from itertools import batched
|
||||
from uuid import uuid4
|
||||
|
||||
from ldap3 import SUBTREE
|
||||
|
||||
from authentik.core.models import User
|
||||
from authentik.sources.ldap.models import UserLDAPSourceConnection
|
||||
from authentik.sources.ldap.sync.base import BaseLDAPSynchronizer
|
||||
|
||||
UPDATE_CHUNK_SIZE = 10_000
|
||||
DELETE_CHUNK_SIZE = 50
|
||||
|
||||
|
||||
class UserLDAPForwardDeletion(BaseLDAPSynchronizer):
|
||||
"""Delete LDAP Users from authentik"""
|
||||
|
||||
@staticmethod
|
||||
def name() -> str:
|
||||
return "user_deletions"
|
||||
|
||||
def get_objects(self, **kwargs) -> Generator:
|
||||
if not self._source.sync_users or not self._source.delete_not_found_objects:
|
||||
self.message("User syncing is disabled for this Source")
|
||||
return iter(())
|
||||
|
||||
uuid = uuid4()
|
||||
users = self._source.connection().extend.standard.paged_search(
|
||||
search_base=self.base_dn_users,
|
||||
search_filter=self._source.user_object_filter,
|
||||
search_scope=SUBTREE,
|
||||
attributes=[self._source.object_uniqueness_field],
|
||||
generator=True,
|
||||
**kwargs,
|
||||
)
|
||||
for batch in batched(users, UPDATE_CHUNK_SIZE, strict=False):
|
||||
identifiers = []
|
||||
for user in batch:
|
||||
if not (attributes := self.get_attributes(user)):
|
||||
continue
|
||||
if identifier := self.get_identifier(attributes):
|
||||
identifiers.append(identifier)
|
||||
UserLDAPSourceConnection.objects.filter(identifier__in=identifiers).update(
|
||||
validated_by=uuid
|
||||
)
|
||||
|
||||
return batched(
|
||||
UserLDAPSourceConnection.objects.filter(source=self._source)
|
||||
.exclude(validated_by=uuid)
|
||||
.values_list("user", flat=True)
|
||||
.iterator(chunk_size=DELETE_CHUNK_SIZE),
|
||||
DELETE_CHUNK_SIZE,
|
||||
strict=False,
|
||||
)
|
||||
|
||||
def sync(self, user_pks: tuple) -> int:
|
||||
"""Delete authentik users"""
|
||||
if not self._source.sync_users or not self._source.delete_not_found_objects:
|
||||
self.message("User syncing is disabled for this Source")
|
||||
return -1
|
||||
self._logger.debug("Deleting users", user_pks=user_pks)
|
||||
_, deleted_per_type = User.objects.filter(pk__in=user_pks).delete()
|
||||
return deleted_per_type.get(User._meta.label, 0)
|
@ -58,16 +58,18 @@ class GroupLDAPSynchronizer(BaseLDAPSynchronizer):
|
||||
return -1
|
||||
group_count = 0
|
||||
for group in page_data:
|
||||
if (attributes := self.get_attributes(group)) is None:
|
||||
if "attributes" not in group:
|
||||
continue
|
||||
attributes = group.get("attributes", {})
|
||||
group_dn = flatten(flatten(group.get("entryDN", group.get("dn"))))
|
||||
if not (uniq := self.get_identifier(attributes)):
|
||||
if not attributes.get(self._source.object_uniqueness_field):
|
||||
self.message(
|
||||
f"Uniqueness field not found/not set in attributes: '{group_dn}'",
|
||||
attributes=attributes.keys(),
|
||||
dn=group_dn,
|
||||
)
|
||||
continue
|
||||
uniq = flatten(attributes[self._source.object_uniqueness_field])
|
||||
try:
|
||||
defaults = {
|
||||
k: flatten(v)
|
||||
|
@ -63,9 +63,9 @@ class MembershipLDAPSynchronizer(BaseLDAPSynchronizer):
|
||||
group_member_dn = group_member.get("dn", {})
|
||||
members.append(group_member_dn)
|
||||
else:
|
||||
if (attributes := self.get_attributes(group)) is None:
|
||||
if "attributes" not in group:
|
||||
continue
|
||||
members = attributes.get(self._source.group_membership_field, [])
|
||||
members = group.get("attributes", {}).get(self._source.group_membership_field, [])
|
||||
|
||||
ak_group = self.get_group(group)
|
||||
if not ak_group:
|
||||
|
@ -60,16 +60,18 @@ class UserLDAPSynchronizer(BaseLDAPSynchronizer):
|
||||
return -1
|
||||
user_count = 0
|
||||
for user in page_data:
|
||||
if (attributes := self.get_attributes(user)) is None:
|
||||
if "attributes" not in user:
|
||||
continue
|
||||
attributes = user.get("attributes", {})
|
||||
user_dn = flatten(user.get("entryDN", user.get("dn")))
|
||||
if not (uniq := self.get_identifier(attributes)):
|
||||
if not attributes.get(self._source.object_uniqueness_field):
|
||||
self.message(
|
||||
f"Uniqueness field not found/not set in attributes: '{user_dn}'",
|
||||
attributes=attributes.keys(),
|
||||
dn=user_dn,
|
||||
)
|
||||
continue
|
||||
uniq = flatten(attributes[self._source.object_uniqueness_field])
|
||||
try:
|
||||
defaults = {
|
||||
k: flatten(v)
|
||||
|
@ -17,8 +17,6 @@ from authentik.lib.utils.reflection import class_to_path, path_to_class
|
||||
from authentik.root.celery import CELERY_APP
|
||||
from authentik.sources.ldap.models import LDAPSource
|
||||
from authentik.sources.ldap.sync.base import BaseLDAPSynchronizer
|
||||
from authentik.sources.ldap.sync.forward_delete_groups import GroupLDAPForwardDeletion
|
||||
from authentik.sources.ldap.sync.forward_delete_users import UserLDAPForwardDeletion
|
||||
from authentik.sources.ldap.sync.groups import GroupLDAPSynchronizer
|
||||
from authentik.sources.ldap.sync.membership import MembershipLDAPSynchronizer
|
||||
from authentik.sources.ldap.sync.users import UserLDAPSynchronizer
|
||||
@ -54,11 +52,11 @@ def ldap_connectivity_check(pk: str | None = None):
|
||||
|
||||
|
||||
@CELERY_APP.task(
|
||||
# We take the configured hours timeout time by 3.5 as we run user and
|
||||
# group in parallel and then membership, then deletions, so 3x is to cover the serial tasks,
|
||||
# We take the configured hours timeout time by 2.5 as we run user and
|
||||
# group in parallel and then membership, so 2x is to cover the serial tasks,
|
||||
# and 0.5x on top of that to give some more leeway
|
||||
soft_time_limit=(60 * 60 * CONFIG.get_int("ldap.task_timeout_hours")) * 3.5,
|
||||
task_time_limit=(60 * 60 * CONFIG.get_int("ldap.task_timeout_hours")) * 3.5,
|
||||
soft_time_limit=(60 * 60 * CONFIG.get_int("ldap.task_timeout_hours")) * 2.5,
|
||||
task_time_limit=(60 * 60 * CONFIG.get_int("ldap.task_timeout_hours")) * 2.5,
|
||||
)
|
||||
def ldap_sync_single(source_pk: str):
|
||||
"""Sync a single source"""
|
||||
@ -81,25 +79,6 @@ def ldap_sync_single(source_pk: str):
|
||||
group(
|
||||
ldap_sync_paginator(source, MembershipLDAPSynchronizer),
|
||||
),
|
||||
# Finally, deletions. What we'd really like to do here is something like
|
||||
# ```
|
||||
# user_identifiers = <ldap query>
|
||||
# User.objects.exclude(
|
||||
# usersourceconnection__identifier__in=user_uniqueness_identifiers,
|
||||
# ).delete()
|
||||
# ```
|
||||
# This runs into performance issues in large installations. So instead we spread the
|
||||
# work out into three steps:
|
||||
# 1. Get every object from the LDAP source.
|
||||
# 2. Mark every object as "safe" in the database. This is quick, but any error could
|
||||
# mean deleting users which should not be deleted, so we do it immediately, in
|
||||
# large chunks, and only queue the deletion step afterwards.
|
||||
# 3. Delete every unmarked item. This is slow, so we spread it over many tasks in
|
||||
# small chunks.
|
||||
group(
|
||||
ldap_sync_paginator(source, UserLDAPForwardDeletion)
|
||||
+ ldap_sync_paginator(source, GroupLDAPForwardDeletion),
|
||||
),
|
||||
)
|
||||
task()
|
||||
|
||||
|
@ -2,33 +2,6 @@
|
||||
|
||||
from ldap3 import MOCK_SYNC, OFFLINE_SLAPD_2_4, Connection, Server
|
||||
|
||||
# The mock modifies these in place, so we have to define them per string
|
||||
user_in_slapd_dn = "cn=user_in_slapd_cn,ou=users,dc=goauthentik,dc=io"
|
||||
user_in_slapd_cn = "user_in_slapd_cn"
|
||||
user_in_slapd_uid = "user_in_slapd_uid"
|
||||
user_in_slapd_object_class = "person"
|
||||
user_in_slapd = {
|
||||
"dn": user_in_slapd_dn,
|
||||
"attributes": {
|
||||
"cn": user_in_slapd_cn,
|
||||
"uid": user_in_slapd_uid,
|
||||
"objectClass": user_in_slapd_object_class,
|
||||
},
|
||||
}
|
||||
group_in_slapd_dn = "cn=user_in_slapd_cn,ou=groups,dc=goauthentik,dc=io"
|
||||
group_in_slapd_cn = "group_in_slapd_cn"
|
||||
group_in_slapd_uid = "group_in_slapd_uid"
|
||||
group_in_slapd_object_class = "groupOfNames"
|
||||
group_in_slapd = {
|
||||
"dn": group_in_slapd_dn,
|
||||
"attributes": {
|
||||
"cn": group_in_slapd_cn,
|
||||
"uid": group_in_slapd_uid,
|
||||
"objectClass": group_in_slapd_object_class,
|
||||
"member": [user_in_slapd["dn"]],
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def mock_slapd_connection(password: str) -> Connection:
|
||||
"""Create mock SLAPD connection"""
|
||||
@ -123,14 +96,5 @@ def mock_slapd_connection(password: str) -> Connection:
|
||||
"objectClass": "posixAccount",
|
||||
},
|
||||
)
|
||||
# Known user and group
|
||||
connection.strategy.add_entry(
|
||||
user_in_slapd["dn"],
|
||||
user_in_slapd["attributes"],
|
||||
)
|
||||
connection.strategy.add_entry(
|
||||
group_in_slapd["dn"],
|
||||
group_in_slapd["attributes"],
|
||||
)
|
||||
connection.bind()
|
||||
return connection
|
||||
|
@ -13,26 +13,14 @@ from authentik.events.system_tasks import TaskStatus
|
||||
from authentik.lib.generators import generate_id, generate_key
|
||||
from authentik.lib.sync.outgoing.exceptions import StopSync
|
||||
from authentik.lib.utils.reflection import class_to_path
|
||||
from authentik.sources.ldap.models import (
|
||||
GroupLDAPSourceConnection,
|
||||
LDAPSource,
|
||||
LDAPSourcePropertyMapping,
|
||||
UserLDAPSourceConnection,
|
||||
)
|
||||
from authentik.sources.ldap.sync.forward_delete_users import DELETE_CHUNK_SIZE
|
||||
from authentik.sources.ldap.models import LDAPSource, LDAPSourcePropertyMapping
|
||||
from authentik.sources.ldap.sync.groups import GroupLDAPSynchronizer
|
||||
from authentik.sources.ldap.sync.membership import MembershipLDAPSynchronizer
|
||||
from authentik.sources.ldap.sync.users import UserLDAPSynchronizer
|
||||
from authentik.sources.ldap.tasks import ldap_sync, ldap_sync_all
|
||||
from authentik.sources.ldap.tests.mock_ad import mock_ad_connection
|
||||
from authentik.sources.ldap.tests.mock_freeipa import mock_freeipa_connection
|
||||
from authentik.sources.ldap.tests.mock_slapd import (
|
||||
group_in_slapd_cn,
|
||||
group_in_slapd_uid,
|
||||
mock_slapd_connection,
|
||||
user_in_slapd_cn,
|
||||
user_in_slapd_uid,
|
||||
)
|
||||
from authentik.sources.ldap.tests.mock_slapd import mock_slapd_connection
|
||||
|
||||
LDAP_PASSWORD = generate_key()
|
||||
|
||||
@ -320,160 +308,3 @@ class LDAPSyncTests(TestCase):
|
||||
connection = MagicMock(return_value=mock_slapd_connection(LDAP_PASSWORD))
|
||||
with patch("authentik.sources.ldap.models.LDAPSource.connection", connection):
|
||||
ldap_sync_all.delay().get()
|
||||
|
||||
def test_user_deletion(self):
|
||||
"""Test user deletion"""
|
||||
user = User.objects.create_user(username="not-in-the-source")
|
||||
UserLDAPSourceConnection.objects.create(
|
||||
user=user, source=self.source, identifier="not-in-the-source"
|
||||
)
|
||||
self.source.object_uniqueness_field = "uid"
|
||||
self.source.group_object_filter = "(objectClass=groupOfNames)"
|
||||
self.source.delete_not_found_objects = True
|
||||
self.source.save()
|
||||
|
||||
connection = MagicMock(return_value=mock_slapd_connection(LDAP_PASSWORD))
|
||||
with patch("authentik.sources.ldap.models.LDAPSource.connection", connection):
|
||||
ldap_sync_all.delay().get()
|
||||
self.assertFalse(User.objects.filter(username="not-in-the-source").exists())
|
||||
|
||||
def test_user_deletion_still_in_source(self):
|
||||
"""Test that user is not deleted if it's still in the source"""
|
||||
username = user_in_slapd_cn
|
||||
identifier = user_in_slapd_uid
|
||||
user = User.objects.create_user(username=username)
|
||||
UserLDAPSourceConnection.objects.create(
|
||||
user=user, source=self.source, identifier=identifier
|
||||
)
|
||||
self.source.object_uniqueness_field = "uid"
|
||||
self.source.group_object_filter = "(objectClass=groupOfNames)"
|
||||
self.source.delete_not_found_objects = True
|
||||
self.source.save()
|
||||
|
||||
connection = MagicMock(return_value=mock_slapd_connection(LDAP_PASSWORD))
|
||||
with patch("authentik.sources.ldap.models.LDAPSource.connection", connection):
|
||||
ldap_sync_all.delay().get()
|
||||
self.assertTrue(User.objects.filter(username=username).exists())
|
||||
|
||||
def test_user_deletion_no_sync(self):
|
||||
"""Test that user is not deleted if sync_users is False"""
|
||||
user = User.objects.create_user(username="not-in-the-source")
|
||||
UserLDAPSourceConnection.objects.create(
|
||||
user=user, source=self.source, identifier="not-in-the-source"
|
||||
)
|
||||
self.source.object_uniqueness_field = "uid"
|
||||
self.source.group_object_filter = "(objectClass=groupOfNames)"
|
||||
self.source.delete_not_found_objects = True
|
||||
self.source.sync_users = False
|
||||
self.source.save()
|
||||
|
||||
connection = MagicMock(return_value=mock_slapd_connection(LDAP_PASSWORD))
|
||||
with patch("authentik.sources.ldap.models.LDAPSource.connection", connection):
|
||||
ldap_sync_all.delay().get()
|
||||
self.assertTrue(User.objects.filter(username="not-in-the-source").exists())
|
||||
|
||||
def test_user_deletion_no_delete(self):
|
||||
"""Test that user is not deleted if delete_not_found_objects is False"""
|
||||
user = User.objects.create_user(username="not-in-the-source")
|
||||
UserLDAPSourceConnection.objects.create(
|
||||
user=user, source=self.source, identifier="not-in-the-source"
|
||||
)
|
||||
self.source.object_uniqueness_field = "uid"
|
||||
self.source.group_object_filter = "(objectClass=groupOfNames)"
|
||||
self.source.save()
|
||||
|
||||
connection = MagicMock(return_value=mock_slapd_connection(LDAP_PASSWORD))
|
||||
with patch("authentik.sources.ldap.models.LDAPSource.connection", connection):
|
||||
ldap_sync_all.delay().get()
|
||||
self.assertTrue(User.objects.filter(username="not-in-the-source").exists())
|
||||
|
||||
def test_group_deletion(self):
|
||||
"""Test group deletion"""
|
||||
group = Group.objects.create(name="not-in-the-source")
|
||||
GroupLDAPSourceConnection.objects.create(
|
||||
group=group, source=self.source, identifier="not-in-the-source"
|
||||
)
|
||||
self.source.object_uniqueness_field = "uid"
|
||||
self.source.group_object_filter = "(objectClass=groupOfNames)"
|
||||
self.source.delete_not_found_objects = True
|
||||
self.source.save()
|
||||
|
||||
connection = MagicMock(return_value=mock_slapd_connection(LDAP_PASSWORD))
|
||||
with patch("authentik.sources.ldap.models.LDAPSource.connection", connection):
|
||||
ldap_sync_all.delay().get()
|
||||
self.assertFalse(Group.objects.filter(name="not-in-the-source").exists())
|
||||
|
||||
def test_group_deletion_still_in_source(self):
|
||||
"""Test that group is not deleted if it's still in the source"""
|
||||
groupname = group_in_slapd_cn
|
||||
identifier = group_in_slapd_uid
|
||||
group = Group.objects.create(name=groupname)
|
||||
GroupLDAPSourceConnection.objects.create(
|
||||
group=group, source=self.source, identifier=identifier
|
||||
)
|
||||
self.source.object_uniqueness_field = "uid"
|
||||
self.source.group_object_filter = "(objectClass=groupOfNames)"
|
||||
self.source.delete_not_found_objects = True
|
||||
self.source.save()
|
||||
|
||||
connection = MagicMock(return_value=mock_slapd_connection(LDAP_PASSWORD))
|
||||
with patch("authentik.sources.ldap.models.LDAPSource.connection", connection):
|
||||
ldap_sync_all.delay().get()
|
||||
self.assertTrue(Group.objects.filter(name=groupname).exists())
|
||||
|
||||
def test_group_deletion_no_sync(self):
|
||||
"""Test that group is not deleted if sync_groups is False"""
|
||||
group = Group.objects.create(name="not-in-the-source")
|
||||
GroupLDAPSourceConnection.objects.create(
|
||||
group=group, source=self.source, identifier="not-in-the-source"
|
||||
)
|
||||
self.source.object_uniqueness_field = "uid"
|
||||
self.source.group_object_filter = "(objectClass=groupOfNames)"
|
||||
self.source.delete_not_found_objects = True
|
||||
self.source.sync_groups = False
|
||||
self.source.save()
|
||||
|
||||
connection = MagicMock(return_value=mock_slapd_connection(LDAP_PASSWORD))
|
||||
with patch("authentik.sources.ldap.models.LDAPSource.connection", connection):
|
||||
ldap_sync_all.delay().get()
|
||||
self.assertTrue(Group.objects.filter(name="not-in-the-source").exists())
|
||||
|
||||
def test_group_deletion_no_delete(self):
|
||||
"""Test that group is not deleted if delete_not_found_objects is False"""
|
||||
group = Group.objects.create(name="not-in-the-source")
|
||||
GroupLDAPSourceConnection.objects.create(
|
||||
group=group, source=self.source, identifier="not-in-the-source"
|
||||
)
|
||||
self.source.object_uniqueness_field = "uid"
|
||||
self.source.group_object_filter = "(objectClass=groupOfNames)"
|
||||
self.source.save()
|
||||
|
||||
connection = MagicMock(return_value=mock_slapd_connection(LDAP_PASSWORD))
|
||||
with patch("authentik.sources.ldap.models.LDAPSource.connection", connection):
|
||||
ldap_sync_all.delay().get()
|
||||
self.assertTrue(Group.objects.filter(name="not-in-the-source").exists())
|
||||
|
||||
def test_batch_deletion(self):
|
||||
"""Test batch deletion"""
|
||||
BATCH_SIZE = DELETE_CHUNK_SIZE + 1
|
||||
for i in range(BATCH_SIZE):
|
||||
user = User.objects.create_user(username=f"not-in-the-source-{i}")
|
||||
group = Group.objects.create(name=f"not-in-the-source-{i}")
|
||||
group.users.add(user)
|
||||
UserLDAPSourceConnection.objects.create(
|
||||
user=user, source=self.source, identifier=f"not-in-the-source-{i}-user"
|
||||
)
|
||||
GroupLDAPSourceConnection.objects.create(
|
||||
group=group, source=self.source, identifier=f"not-in-the-source-{i}-group"
|
||||
)
|
||||
self.source.object_uniqueness_field = "uid"
|
||||
self.source.group_object_filter = "(objectClass=groupOfNames)"
|
||||
self.source.delete_not_found_objects = True
|
||||
self.source.save()
|
||||
|
||||
connection = MagicMock(return_value=mock_slapd_connection(LDAP_PASSWORD))
|
||||
with patch("authentik.sources.ldap.models.LDAPSource.connection", connection):
|
||||
ldap_sync_all.delay().get()
|
||||
|
||||
self.assertFalse(User.objects.filter(username__startswith="not-in-the-source").exists())
|
||||
self.assertFalse(Group.objects.filter(name__startswith="not-in-the-source").exists())
|
||||
|
@ -9,7 +9,6 @@ from django.http.response import HttpResponseBadRequest
|
||||
from django.shortcuts import get_object_or_404, redirect
|
||||
from django.utils.decorators import method_decorator
|
||||
from django.utils.http import urlencode
|
||||
from django.utils.translation import gettext as _
|
||||
from django.views import View
|
||||
from django.views.decorators.csrf import csrf_exempt
|
||||
from structlog.stdlib import get_logger
|
||||
@ -129,9 +128,7 @@ class InitiateView(View):
|
||||
# otherwise we default to POST_AUTO, with direct redirect
|
||||
if source.binding_type == SAMLBindingTypes.POST:
|
||||
injected_stages.append(in_memory_stage(ConsentStageView))
|
||||
plan_kwargs[PLAN_CONTEXT_CONSENT_HEADER] = _(
|
||||
"Continue to {source_name}".format(source_name=source.name)
|
||||
)
|
||||
plan_kwargs[PLAN_CONTEXT_CONSENT_HEADER] = f"Continue to {source.name}"
|
||||
injected_stages.append(in_memory_stage(AutosubmitStageView))
|
||||
return self.handle_login_flow(
|
||||
source,
|
||||
|
@ -4,8 +4,6 @@ from uuid import uuid4
|
||||
|
||||
from django.http import HttpRequest, HttpResponse
|
||||
from django.utils.timezone import now
|
||||
from django.utils.translation import gettext as _
|
||||
from rest_framework.exceptions import ValidationError
|
||||
from rest_framework.fields import CharField
|
||||
|
||||
from authentik.core.api.utils import PassiveSerializer
|
||||
@ -49,11 +47,6 @@ class ConsentChallengeResponse(ChallengeResponse):
|
||||
component = CharField(default="ak-stage-consent")
|
||||
token = CharField(required=True)
|
||||
|
||||
def validate_token(self, token: str):
|
||||
if token != self.stage.executor.request.session[SESSION_KEY_CONSENT_TOKEN]:
|
||||
raise ValidationError(_("Invalid consent token, re-showing prompt"))
|
||||
return token
|
||||
|
||||
|
||||
class ConsentStageView(ChallengeStageView):
|
||||
"""Simple consent checker."""
|
||||
@ -127,6 +120,9 @@ class ConsentStageView(ChallengeStageView):
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
def challenge_valid(self, response: ChallengeResponse) -> HttpResponse:
|
||||
if response.data["token"] != self.request.session[SESSION_KEY_CONSENT_TOKEN]:
|
||||
self.logger.info("Invalid consent token, re-showing prompt")
|
||||
return self.get(self.request)
|
||||
if self.should_always_prompt():
|
||||
return self.executor.stage_ok()
|
||||
current_stage: ConsentStage = self.executor.current_stage
|
||||
|
@ -17,7 +17,6 @@ from authentik.flows.views.executor import SESSION_KEY_PLAN
|
||||
from authentik.lib.generators import generate_id
|
||||
from authentik.stages.consent.models import ConsentMode, ConsentStage, UserConsent
|
||||
from authentik.stages.consent.stage import (
|
||||
PLAN_CONTEXT_CONSENT_HEADER,
|
||||
PLAN_CONTEXT_CONSENT_PERMISSIONS,
|
||||
SESSION_KEY_CONSENT_TOKEN,
|
||||
)
|
||||
@ -34,40 +33,6 @@ class TestConsentStage(FlowTestCase):
|
||||
slug=generate_id(),
|
||||
)
|
||||
|
||||
def test_mismatched_token(self):
|
||||
"""Test incorrect token"""
|
||||
flow = create_test_flow(FlowDesignation.AUTHENTICATION)
|
||||
stage = ConsentStage.objects.create(name=generate_id(), mode=ConsentMode.ALWAYS_REQUIRE)
|
||||
binding = FlowStageBinding.objects.create(target=flow, stage=stage, order=2)
|
||||
|
||||
plan = FlowPlan(flow_pk=flow.pk.hex, bindings=[binding], markers=[StageMarker()])
|
||||
session = self.client.session
|
||||
session[SESSION_KEY_PLAN] = plan
|
||||
session.save()
|
||||
response = self.client.get(
|
||||
reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}),
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
session = self.client.session
|
||||
response = self.client.post(
|
||||
reverse("authentik_api:flow-executor", kwargs={"flow_slug": flow.slug}),
|
||||
{
|
||||
"token": generate_id(),
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertStageResponse(
|
||||
response,
|
||||
flow,
|
||||
component="ak-stage-consent",
|
||||
response_errors={
|
||||
"token": [{"string": "Invalid consent token, re-showing prompt", "code": "invalid"}]
|
||||
},
|
||||
)
|
||||
self.assertFalse(UserConsent.objects.filter(user=self.user).exists())
|
||||
|
||||
def test_always_required(self):
|
||||
"""Test always required consent"""
|
||||
flow = create_test_flow(FlowDesignation.AUTHENTICATION)
|
||||
@ -193,7 +158,6 @@ class TestConsentStage(FlowTestCase):
|
||||
context={
|
||||
PLAN_CONTEXT_APPLICATION: self.application,
|
||||
PLAN_CONTEXT_CONSENT_PERMISSIONS: [PermissionDict(id="foo", name="foo-desc")],
|
||||
PLAN_CONTEXT_CONSENT_HEADER: "test header",
|
||||
},
|
||||
)
|
||||
session = self.client.session
|
||||
|
@ -1,38 +0,0 @@
|
||||
from base64 import b64encode
|
||||
from copy import deepcopy
|
||||
from pickle import dumps # nosec
|
||||
|
||||
from django.utils.translation import gettext as _
|
||||
|
||||
from authentik.flows.models import FlowToken, in_memory_stage
|
||||
from authentik.flows.planner import PLAN_CONTEXT_IS_RESTORED, FlowPlan
|
||||
from authentik.stages.consent.stage import PLAN_CONTEXT_CONSENT_HEADER, ConsentStageView
|
||||
|
||||
|
||||
def pickle_flow_token_for_email(plan: FlowPlan):
|
||||
"""Insert a consent stage into the flow plan and pickle it for a FlowToken,
|
||||
to be sent via Email. This is to prevent automated email scanners, which sometimes
|
||||
open links in emails in a full browser from breaking the link."""
|
||||
plan_copy = deepcopy(plan)
|
||||
plan_copy.insert_stage(in_memory_stage(EmailTokenRevocationConsentStageView), index=0)
|
||||
plan_copy.context[PLAN_CONTEXT_CONSENT_HEADER] = _("Continue to confirm this email address.")
|
||||
data = dumps(plan_copy)
|
||||
return b64encode(data).decode()
|
||||
|
||||
|
||||
class EmailTokenRevocationConsentStageView(ConsentStageView):
|
||||
|
||||
def get(self, request, *args, **kwargs):
|
||||
token: FlowToken = self.executor.plan.context[PLAN_CONTEXT_IS_RESTORED]
|
||||
try:
|
||||
token.refresh_from_db()
|
||||
except FlowToken.DoesNotExist:
|
||||
return self.executor.stage_invalid(
|
||||
_("Link was already used, please request a new link.")
|
||||
)
|
||||
return super().get(request, *args, **kwargs)
|
||||
|
||||
def challenge_valid(self, response):
|
||||
token: FlowToken = self.executor.plan.context[PLAN_CONTEXT_IS_RESTORED]
|
||||
token.delete()
|
||||
return super().challenge_valid(response)
|
@ -23,7 +23,6 @@ from authentik.flows.stage import ChallengeStageView
|
||||
from authentik.flows.views.executor import QS_KEY_TOKEN, QS_QUERY
|
||||
from authentik.lib.utils.errors import exception_to_string
|
||||
from authentik.lib.utils.time import timedelta_from_string
|
||||
from authentik.stages.email.flow import pickle_flow_token_for_email
|
||||
from authentik.stages.email.models import EmailStage
|
||||
from authentik.stages.email.tasks import send_mails
|
||||
from authentik.stages.email.utils import TemplateEmailMessage
|
||||
@ -87,8 +86,7 @@ class EmailStageView(ChallengeStageView):
|
||||
user=pending_user,
|
||||
identifier=identifier,
|
||||
flow=self.executor.flow,
|
||||
_plan=pickle_flow_token_for_email(self.executor.plan),
|
||||
revoke_on_execution=False,
|
||||
_plan=FlowToken.pickle(self.executor.plan),
|
||||
)
|
||||
token = tokens.first()
|
||||
# Check if token is expired and rotate key if so
|
||||
|
@ -174,5 +174,5 @@ class TestEmailStageSending(FlowTestCase):
|
||||
response = self.client.post(url)
|
||||
response = self.client.post(url)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertGreaterEqual(len(mail.outbox), 1)
|
||||
self.assertTrue(len(mail.outbox) >= 1)
|
||||
self.assertEqual(mail.outbox[0].subject, "authentik")
|
||||
|
@ -17,7 +17,6 @@ from authentik.flows.tests import FlowTestCase
|
||||
from authentik.flows.views.executor import QS_KEY_TOKEN, SESSION_KEY_PLAN, FlowExecutorView
|
||||
from authentik.lib.config import CONFIG
|
||||
from authentik.lib.generators import generate_id
|
||||
from authentik.stages.consent.stage import SESSION_KEY_CONSENT_TOKEN
|
||||
from authentik.stages.email.models import EmailStage
|
||||
from authentik.stages.email.stage import PLAN_CONTEXT_EMAIL_OVERRIDE, EmailStageView
|
||||
|
||||
@ -161,17 +160,6 @@ class TestEmailStage(FlowTestCase):
|
||||
kwargs={"flow_slug": self.flow.slug},
|
||||
)
|
||||
)
|
||||
self.assertStageResponse(response, self.flow, component="ak-stage-consent")
|
||||
response = self.client.post(
|
||||
reverse(
|
||||
"authentik_api:flow-executor",
|
||||
kwargs={"flow_slug": self.flow.slug},
|
||||
),
|
||||
data={
|
||||
"token": self.client.session[SESSION_KEY_CONSENT_TOKEN],
|
||||
},
|
||||
follow=True,
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertStageRedirects(response, reverse("authentik_core:root-redirect"))
|
||||
@ -194,7 +182,6 @@ class TestEmailStage(FlowTestCase):
|
||||
# Set flow token user to a different user
|
||||
token: FlowToken = FlowToken.objects.get(user=self.user)
|
||||
token.user = create_test_admin_user()
|
||||
token.revoke_on_execution = True
|
||||
token.save()
|
||||
|
||||
with patch("authentik.flows.views.executor.FlowExecutorView.cancel", MagicMock()):
|
||||
|
@ -8180,11 +8180,6 @@
|
||||
"type": "boolean",
|
||||
"title": "Lookup groups from user",
|
||||
"description": "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"
|
||||
},
|
||||
"delete_not_found_objects": {
|
||||
"type": "boolean",
|
||||
"title": "Delete not found objects",
|
||||
"description": "Delete authentik users and groups which were previously supplied by this source, but are now missing from it."
|
||||
}
|
||||
},
|
||||
"required": []
|
||||
|
@ -28,18 +28,16 @@ func NewSessionBinder(si server.LDAPServerInstance, oldBinder bind.Binder) *Sess
|
||||
si: si,
|
||||
log: log.WithField("logger", "authentik.outpost.ldap.binder.session"),
|
||||
}
|
||||
if oldBinder != nil {
|
||||
if oldSb, ok := oldBinder.(*SessionBinder); ok {
|
||||
sb.DirectBinder = oldSb.DirectBinder
|
||||
sb.sessions = oldSb.sessions
|
||||
sb.log.Debug("re-initialised session binder")
|
||||
return sb
|
||||
}
|
||||
if oldSb, ok := oldBinder.(*SessionBinder); ok {
|
||||
sb.DirectBinder = oldSb.DirectBinder
|
||||
sb.sessions = oldSb.sessions
|
||||
sb.log.Debug("re-initialised session binder")
|
||||
} else {
|
||||
sb.sessions = ttlcache.New(ttlcache.WithDisableTouchOnHit[Credentials, ldap.LDAPResultCode]())
|
||||
sb.DirectBinder = *direct.NewDirectBinder(si)
|
||||
go sb.sessions.Start()
|
||||
sb.log.Debug("initialised session binder")
|
||||
}
|
||||
sb.sessions = ttlcache.New(ttlcache.WithDisableTouchOnHit[Credentials, ldap.LDAPResultCode]())
|
||||
sb.DirectBinder = *direct.NewDirectBinder(si)
|
||||
go sb.sessions.Start()
|
||||
sb.log.Debug("initialised session binder")
|
||||
return sb
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,6 @@ import (
|
||||
memorybind "goauthentik.io/internal/outpost/ldap/bind/memory"
|
||||
"goauthentik.io/internal/outpost/ldap/constants"
|
||||
"goauthentik.io/internal/outpost/ldap/flags"
|
||||
"goauthentik.io/internal/outpost/ldap/search"
|
||||
directsearch "goauthentik.io/internal/outpost/ldap/search/direct"
|
||||
memorysearch "goauthentik.io/internal/outpost/ldap/search/memory"
|
||||
)
|
||||
@ -86,11 +85,7 @@ func (ls *LDAPServer) Refresh() error {
|
||||
providers[idx].certUUID = *kp
|
||||
}
|
||||
if *provider.SearchMode.Ptr() == api.LDAPAPIACCESSMODE_CACHED {
|
||||
var oldSearcher search.Searcher
|
||||
if existing != nil {
|
||||
oldSearcher = existing.searcher
|
||||
}
|
||||
providers[idx].searcher = memorysearch.NewMemorySearcher(providers[idx], oldSearcher)
|
||||
providers[idx].searcher = memorysearch.NewMemorySearcher(providers[idx])
|
||||
} else if *provider.SearchMode.Ptr() == api.LDAPAPIACCESSMODE_DIRECT {
|
||||
providers[idx].searcher = directsearch.NewDirectSearcher(providers[idx])
|
||||
}
|
||||
|
@ -31,26 +31,13 @@ type MemorySearcher struct {
|
||||
groups []api.Group
|
||||
}
|
||||
|
||||
func NewMemorySearcher(si server.LDAPServerInstance, existing search.Searcher) *MemorySearcher {
|
||||
func NewMemorySearcher(si server.LDAPServerInstance) *MemorySearcher {
|
||||
ms := &MemorySearcher{
|
||||
si: si,
|
||||
log: log.WithField("logger", "authentik.outpost.ldap.searcher.memory"),
|
||||
ds: direct.NewDirectSearcher(si),
|
||||
}
|
||||
if existing != nil {
|
||||
if ems, ok := existing.(*MemorySearcher); ok {
|
||||
ems.si = si
|
||||
ems.fetch()
|
||||
ems.log.Debug("re-initialised memory searcher")
|
||||
return ems
|
||||
}
|
||||
}
|
||||
ms.fetch()
|
||||
ms.log.Debug("initialised memory searcher")
|
||||
return ms
|
||||
}
|
||||
|
||||
func (ms *MemorySearcher) fetch() {
|
||||
// Error is not handled here, we get an empty/truncated list and the error is logged
|
||||
users, _ := ak.Paginator(ms.si.GetAPIClient().CoreApi.CoreUsersList(context.TODO()).IncludeGroups(true), ak.PaginatorOptions{
|
||||
PageSize: 100,
|
||||
@ -62,6 +49,7 @@ func (ms *MemorySearcher) fetch() {
|
||||
Logger: ms.log,
|
||||
})
|
||||
ms.groups = groups
|
||||
return ms
|
||||
}
|
||||
|
||||
func (ms *MemorySearcher) SearchBase(req *search.Request) (ldap.ServerSearchResult, error) {
|
||||
|
@ -67,15 +67,11 @@ func (ws *WebServer) configureStatic() {
|
||||
|
||||
// Media files, if backend is file
|
||||
if config.Get().Storage.Media.Backend == "file" {
|
||||
fsMedia := http.FileServer(http.Dir(config.Get().Storage.Media.File.Path))
|
||||
indexLessRouter.PathPrefix(config.Get().Web.Path).PathPrefix("/media/").Handler(pathStripper(
|
||||
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Security-Policy", "default-src 'none'; style-src 'unsafe-inline'; sandbox")
|
||||
fsMedia.ServeHTTP(w, r)
|
||||
}),
|
||||
"media/",
|
||||
config.Get().Web.Path,
|
||||
))
|
||||
fsMedia := http.StripPrefix("/media", http.FileServer(http.Dir(config.Get().Storage.Media.File.Path)))
|
||||
indexLessRouter.PathPrefix(config.Get().Web.Path).PathPrefix("/media/").HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Security-Policy", "default-src 'none'; style-src 'unsafe-inline'; sandbox")
|
||||
fsMedia.ServeHTTP(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
staticRouter.PathPrefix(config.Get().Web.Path).PathPrefix("/if/help/").Handler(pathStripper(
|
||||
|
Binary file not shown.
@ -32,17 +32,15 @@
|
||||
# datenschmutz, 2025
|
||||
# 97cce0ae0cad2a2cc552d3165d04643e_de3d740, 2025
|
||||
# Dominic Wagner <mail@dominic-wagner.de>, 2025
|
||||
# Till-Frederik Riechard, 2025
|
||||
# Alexander Mnich, 2025
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-05-28 11:25+0000\n"
|
||||
"POT-Creation-Date: 2025-04-23 09:00+0000\n"
|
||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||
"Last-Translator: Alexander Mnich, 2025\n"
|
||||
"Last-Translator: Dominic Wagner <mail@dominic-wagner.de>, 2025\n"
|
||||
"Language-Team: German (https://app.transifex.com/authentik/teams/119923/de/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@ -134,10 +132,6 @@ msgstr ""
|
||||
msgid "Web Certificate used by the authentik Core webserver."
|
||||
msgstr "Vom Authentik-Core-Webserver verwendetes Zertifikat."
|
||||
|
||||
#: authentik/brands/models.py
|
||||
msgid "Certificates used for client authentication."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/brands/models.py
|
||||
msgid "Brand"
|
||||
msgstr "Marke"
|
||||
@ -411,7 +405,7 @@ msgstr "Eigenschaften"
|
||||
|
||||
#: authentik/core/models.py
|
||||
msgid "session data"
|
||||
msgstr "Sitzungsdaten"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/core/models.py
|
||||
msgid "Session"
|
||||
@ -539,7 +533,7 @@ msgstr ""
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "Number of passwords to check against."
|
||||
msgstr "Anzahl Passwörter, gegen die geprüft wird."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
#: authentik/policies/password/models.py
|
||||
@ -549,20 +543,18 @@ 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 ""
|
||||
"Dieses Passwort wurde in Vergangenheit bereits verwendet. Bitte nutzen Sie "
|
||||
"ein anderes."
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "Password Uniqueness Policy"
|
||||
msgstr "Passwort-Einzigartigkeits-Richtlinie"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "Password Uniqueness Policies"
|
||||
msgstr "Passwort-Einzigartigkeits-Richtlinien"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "User Password History"
|
||||
msgstr "Nutzer-Passwort-Historie"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policy.py
|
||||
msgid "Enterprise required to access this feature."
|
||||
@ -701,33 +693,6 @@ msgstr "Endgeräte"
|
||||
msgid "Verifying your browser..."
|
||||
msgstr "Verifiziere deinen Browser..."
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid ""
|
||||
"Configure certificate authorities to validate the certificate against. This "
|
||||
"option has a higher priority than the `client_certificate` option on "
|
||||
"`Brand`."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid "Mutual TLS Stage"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid "Mutual TLS Stages"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid "Permissions to pass Certificates for outposts."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/stage.py
|
||||
msgid "Certificate required but no certificate was given."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/stage.py
|
||||
msgid "No user found for certificate."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/source/models.py
|
||||
msgid ""
|
||||
"Amount of time a user can take to return from the source to continue the "
|
||||
@ -1023,7 +988,7 @@ msgstr ""
|
||||
|
||||
#: authentik/flows/models.py
|
||||
msgid "Evaluate policies when the Stage is presented to the user."
|
||||
msgstr "Richtlinien auswerten, wenn die Phase dem Benutzer angezeigt wird."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/flows/models.py
|
||||
msgid ""
|
||||
@ -1078,12 +1043,9 @@ msgid "Starting full provider sync"
|
||||
msgstr "Starte komplette Provider Synchronisation."
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
msgid "Syncing users"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
msgid "Syncing groups"
|
||||
msgstr ""
|
||||
#, python-brace-format
|
||||
msgid "Syncing page {page} of users"
|
||||
msgstr "Synchonisiere Benutzer Seite {page}"
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
#, python-brace-format
|
||||
@ -1631,11 +1593,11 @@ msgstr "ES256 (Asymmetrische Verschlüsselung)"
|
||||
|
||||
#: authentik/providers/oauth2/models.py
|
||||
msgid "ES384 (Asymmetric Encryption)"
|
||||
msgstr "ES384 (Asymmetrische Verschlüsselung)"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/providers/oauth2/models.py
|
||||
msgid "ES512 (Asymmetric Encryption)"
|
||||
msgstr "ES5122 (Asymmetrische Verschlüsselung)"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/providers/oauth2/models.py
|
||||
msgid "Scope used by the client"
|
||||
@ -2221,11 +2183,11 @@ msgstr "Standard"
|
||||
|
||||
#: authentik/providers/scim/models.py
|
||||
msgid "AWS"
|
||||
msgstr "AWS"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/providers/scim/models.py
|
||||
msgid "Slack"
|
||||
msgstr "Slack"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/providers/scim/models.py
|
||||
msgid "Base URL to SCIM requests, usually ends in /v2"
|
||||
@ -2237,7 +2199,7 @@ msgstr "Authentifizierungstoken"
|
||||
|
||||
#: authentik/providers/scim/models.py
|
||||
msgid "SCIM Compatibility Mode"
|
||||
msgstr "SCIM Kompatibilitätsmodus"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/providers/scim/models.py
|
||||
msgid "Alter authentik behavior for vendor-specific SCIM implementations."
|
||||
@ -2269,7 +2231,7 @@ msgstr "Rollen"
|
||||
|
||||
#: authentik/rbac/models.py
|
||||
msgid "Initial Permissions"
|
||||
msgstr "Initiale Berechtigungen"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/rbac/models.py
|
||||
msgid "System permission"
|
||||
@ -2525,12 +2487,6 @@ msgid ""
|
||||
"Active Directory"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid ""
|
||||
"Delete authentik users and groups which were previously supplied by this "
|
||||
"source, but are now missing from it."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "LDAP Source"
|
||||
msgstr "LDAP Quelle"
|
||||
@ -2548,25 +2504,20 @@ msgid "LDAP Source Property Mappings"
|
||||
msgstr "LDAP Quelle Eigenschafts-Zuordnungen"
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid ""
|
||||
"Unique ID used while checking if this object still exists in the directory."
|
||||
msgid "User LDAP Source Connection"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "User LDAP Source Connection"
|
||||
msgstr "Benutzer LDAP-Quellverbindung"
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "User LDAP Source Connections"
|
||||
msgstr "Benutzer LDAP-Quellverbindungen"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "Group LDAP Source Connection"
|
||||
msgstr "LDAP Gruppen Quellverbindung"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "Group LDAP Source Connections"
|
||||
msgstr "LDAP Gruppen Quellverbindungen"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/signals.py
|
||||
msgid "Password does not match Active Directory Complexity."
|
||||
@ -2579,7 +2530,7 @@ msgstr "Kein Token empfangen."
|
||||
|
||||
#: authentik/sources/oauth/models.py
|
||||
msgid "HTTP Basic Authentication"
|
||||
msgstr "HTTP Basic Authentifizierung"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/oauth/models.py
|
||||
msgid "Include the client ID and secret as request parameters"
|
||||
@ -2945,11 +2896,6 @@ msgstr "SAML Gruppen Quellverbindung"
|
||||
msgid "Group SAML Source Connections"
|
||||
msgstr "SAML Gruppen Quellverbindungen"
|
||||
|
||||
#: authentik/sources/saml/views.py
|
||||
#, python-brace-format
|
||||
msgid "Continue to {source_name}"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/scim/models.py
|
||||
msgid "SCIM Source"
|
||||
msgstr "SCIM Quelle"
|
||||
@ -2984,7 +2930,7 @@ msgstr "Duo Geräte"
|
||||
|
||||
#: authentik/stages/authenticator_email/models.py
|
||||
msgid "Email OTP"
|
||||
msgstr "E-Mail Einmalpasswort"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/authenticator_email/models.py
|
||||
#: authentik/stages/email/models.py
|
||||
@ -3017,11 +2963,11 @@ msgstr "Beim Rendern der E-Mail-Vorlage ist ein Fehler aufgetreten"
|
||||
|
||||
#: authentik/stages/authenticator_email/models.py
|
||||
msgid "Email Device"
|
||||
msgstr "E-Mail Gerät"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/authenticator_email/models.py
|
||||
msgid "Email Devices"
|
||||
msgstr "E-Mail Geräte"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/authenticator_email/stage.py
|
||||
#: authentik/stages/authenticator_sms/stage.py
|
||||
@ -3031,7 +2977,7 @@ msgstr "Code stimmt nicht überein"
|
||||
|
||||
#: authentik/stages/authenticator_email/stage.py
|
||||
msgid "Invalid email"
|
||||
msgstr "Ungültige E-Mail"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/authenticator_email/templates/email/email_otp.html
|
||||
#: authentik/stages/email/templates/email/password_reset.html
|
||||
@ -3327,10 +3273,6 @@ msgstr "Zustimmung der Benutzer"
|
||||
msgid "User Consents"
|
||||
msgstr "Zustimmungen der Benutzer"
|
||||
|
||||
#: authentik/stages/consent/stage.py
|
||||
msgid "Invalid consent token, re-showing prompt"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/deny/models.py
|
||||
msgid "Deny Stage"
|
||||
msgstr "Verweigerungsstufe"
|
||||
@ -3347,14 +3289,6 @@ msgstr "Dummy Stufe"
|
||||
msgid "Dummy Stages"
|
||||
msgstr "Dummy Stufen"
|
||||
|
||||
#: authentik/stages/email/flow.py
|
||||
msgid "Continue to confirm this email address."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/email/flow.py
|
||||
msgid "Link was already used, please request a new link."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/email/models.py
|
||||
msgid "Password Reset"
|
||||
msgstr "Passwort zurücksetzen"
|
||||
@ -3956,11 +3890,10 @@ msgstr ""
|
||||
#: authentik/tenants/models.py
|
||||
msgid "Reputation cannot decrease lower than this value. Zero or negative."
|
||||
msgstr ""
|
||||
"Reputation kann nicht niedriger als dieser Wert sein. Null oder negativ."
|
||||
|
||||
#: authentik/tenants/models.py
|
||||
msgid "Reputation cannot increase higher than this value. Zero or positive."
|
||||
msgstr "Reputation kann nicht höher als dieser Wert sein. Null oder positiv."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/tenants/models.py
|
||||
msgid "The option configures the footer links on the flow executor pages."
|
||||
|
@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-05-28 11:25+0000\n"
|
||||
"POT-Creation-Date: 2025-05-20 00:10+0000\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@ -961,11 +961,8 @@ msgid "Starting full provider sync"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
msgid "Syncing users"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
msgid "Syncing groups"
|
||||
#, python-brace-format
|
||||
msgid "Syncing page {page} of users"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
@ -2255,12 +2252,6 @@ msgid ""
|
||||
"Active Directory"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid ""
|
||||
"Delete authentik users and groups which were previously supplied by this "
|
||||
"source, but are now missing from it."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "LDAP Source"
|
||||
msgstr ""
|
||||
@ -2277,11 +2268,6 @@ msgstr ""
|
||||
msgid "LDAP Source Property Mappings"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid ""
|
||||
"Unique ID used while checking if this object still exists in the directory."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "User LDAP Source Connection"
|
||||
msgstr ""
|
||||
@ -2653,11 +2639,6 @@ msgstr ""
|
||||
msgid "Group SAML Source Connections"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/saml/views.py
|
||||
#, python-brace-format
|
||||
msgid "Continue to {source_name}"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/scim/models.py
|
||||
msgid "SCIM Source"
|
||||
msgstr ""
|
||||
@ -3013,10 +2994,6 @@ msgstr ""
|
||||
msgid "User Consents"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/consent/stage.py
|
||||
msgid "Invalid consent token, re-showing prompt"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/deny/models.py
|
||||
msgid "Deny Stage"
|
||||
msgstr ""
|
||||
@ -3033,14 +3010,6 @@ msgstr ""
|
||||
msgid "Dummy Stages"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/email/flow.py
|
||||
msgid "Continue to confirm this email address."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/email/flow.py
|
||||
msgid "Link was already used, please request a new link."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/email/models.py
|
||||
msgid "Password Reset"
|
||||
msgstr ""
|
||||
|
Binary file not shown.
@ -15,7 +15,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-05-28 11:25+0000\n"
|
||||
"POT-Creation-Date: 2025-04-23 09:00+0000\n"
|
||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||
"Last-Translator: Jens L. <jens@goauthentik.io>, 2025\n"
|
||||
"Language-Team: Spanish (https://app.transifex.com/authentik/teams/119923/es/)\n"
|
||||
@ -109,10 +109,6 @@ msgstr ""
|
||||
msgid "Web Certificate used by the authentik Core webserver."
|
||||
msgstr "Certificado Web usado por el servidor web Core de authentik"
|
||||
|
||||
#: authentik/brands/models.py
|
||||
msgid "Certificates used for client authentication."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/brands/models.py
|
||||
msgid "Brand"
|
||||
msgstr "Marca"
|
||||
@ -675,33 +671,6 @@ msgstr "Dispositivos de Punto de Conexión"
|
||||
msgid "Verifying your browser..."
|
||||
msgstr "Verificando tu navegador..."
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid ""
|
||||
"Configure certificate authorities to validate the certificate against. This "
|
||||
"option has a higher priority than the `client_certificate` option on "
|
||||
"`Brand`."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid "Mutual TLS Stage"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid "Mutual TLS Stages"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid "Permissions to pass Certificates for outposts."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/stage.py
|
||||
msgid "Certificate required but no certificate was given."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/stage.py
|
||||
msgid "No user found for certificate."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/source/models.py
|
||||
msgid ""
|
||||
"Amount of time a user can take to return from the source to continue the "
|
||||
@ -1040,12 +1009,9 @@ msgid "Starting full provider sync"
|
||||
msgstr "Iniciando sincronización completa de proveedor"
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
msgid "Syncing users"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
msgid "Syncing groups"
|
||||
msgstr ""
|
||||
#, python-brace-format
|
||||
msgid "Syncing page {page} of users"
|
||||
msgstr "Sincronizando página {page} de usuarios"
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
#, python-brace-format
|
||||
@ -2486,12 +2452,6 @@ msgid ""
|
||||
"Active Directory"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid ""
|
||||
"Delete authentik users and groups which were previously supplied by this "
|
||||
"source, but are now missing from it."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "LDAP Source"
|
||||
msgstr "Fuente de LDAP"
|
||||
@ -2508,11 +2468,6 @@ msgstr "Asignación de Propiedades de Fuente de LDAP"
|
||||
msgid "LDAP Source Property Mappings"
|
||||
msgstr "Asignaciones de Propiedades de Fuente de LDAP"
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid ""
|
||||
"Unique ID used while checking if this object still exists in the directory."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "User LDAP Source Connection"
|
||||
msgstr ""
|
||||
@ -2904,11 +2859,6 @@ msgstr "Conexión de Fuente de SAML de Grupo"
|
||||
msgid "Group SAML Source Connections"
|
||||
msgstr "Conexiones de Fuente de SAML de Grupo"
|
||||
|
||||
#: authentik/sources/saml/views.py
|
||||
#, python-brace-format
|
||||
msgid "Continue to {source_name}"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/scim/models.py
|
||||
msgid "SCIM Source"
|
||||
msgstr "Fuente de SCIM"
|
||||
@ -3295,10 +3245,6 @@ msgstr "Consentimiento del usuario"
|
||||
msgid "User Consents"
|
||||
msgstr "Consentimientos del usuario"
|
||||
|
||||
#: authentik/stages/consent/stage.py
|
||||
msgid "Invalid consent token, re-showing prompt"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/deny/models.py
|
||||
msgid "Deny Stage"
|
||||
msgstr "Etapa de denegación"
|
||||
@ -3315,14 +3261,6 @@ msgstr "Escenario ficticio"
|
||||
msgid "Dummy Stages"
|
||||
msgstr "Etapas ficticias"
|
||||
|
||||
#: authentik/stages/email/flow.py
|
||||
msgid "Continue to confirm this email address."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/email/flow.py
|
||||
msgid "Link was already used, please request a new link."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/email/models.py
|
||||
msgid "Password Reset"
|
||||
msgstr "Restablecimiento de contraseña"
|
||||
|
Binary file not shown.
@ -15,7 +15,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-05-28 11:25+0000\n"
|
||||
"POT-Creation-Date: 2025-04-23 09:00+0000\n"
|
||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||
"Last-Translator: Ville Ranki, 2025\n"
|
||||
"Language-Team: Finnish (https://app.transifex.com/authentik/teams/119923/fi/)\n"
|
||||
@ -106,10 +106,6 @@ msgstr ""
|
||||
msgid "Web Certificate used by the authentik Core webserver."
|
||||
msgstr "Web-sertifikaatti, jota authentik Core -verkkopalvelin käyttää."
|
||||
|
||||
#: authentik/brands/models.py
|
||||
msgid "Certificates used for client authentication."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/brands/models.py
|
||||
msgid "Brand"
|
||||
msgstr "Brändi"
|
||||
@ -662,33 +658,6 @@ msgstr "Päätelaitteet"
|
||||
msgid "Verifying your browser..."
|
||||
msgstr "Selaintasi varmennetaan..."
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid ""
|
||||
"Configure certificate authorities to validate the certificate against. This "
|
||||
"option has a higher priority than the `client_certificate` option on "
|
||||
"`Brand`."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid "Mutual TLS Stage"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid "Mutual TLS Stages"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid "Permissions to pass Certificates for outposts."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/stage.py
|
||||
msgid "Certificate required but no certificate was given."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/stage.py
|
||||
msgid "No user found for certificate."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/source/models.py
|
||||
msgid ""
|
||||
"Amount of time a user can take to return from the source to continue the "
|
||||
@ -1027,12 +996,9 @@ msgid "Starting full provider sync"
|
||||
msgstr "Käynnistetään palveluntarjoajan täysi synkronisointi"
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
msgid "Syncing users"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
msgid "Syncing groups"
|
||||
msgstr ""
|
||||
#, python-brace-format
|
||||
msgid "Syncing page {page} of users"
|
||||
msgstr "Synkronoidaan käyttäjien sivua {page}"
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
#, python-brace-format
|
||||
@ -2463,12 +2429,6 @@ msgid ""
|
||||
"Active Directory"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid ""
|
||||
"Delete authentik users and groups which were previously supplied by this "
|
||||
"source, but are now missing from it."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "LDAP Source"
|
||||
msgstr "LDAP-lähde"
|
||||
@ -2485,11 +2445,6 @@ msgstr "LDAP-lähteen ominaisuuskytkentä"
|
||||
msgid "LDAP Source Property Mappings"
|
||||
msgstr "LDAP-lähteen ominaisuuskytkennät"
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid ""
|
||||
"Unique ID used while checking if this object still exists in the directory."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "User LDAP Source Connection"
|
||||
msgstr ""
|
||||
@ -2882,11 +2837,6 @@ msgstr "Ryhmän SAML-lähteen yhteys"
|
||||
msgid "Group SAML Source Connections"
|
||||
msgstr "Ryhmän SAML-lähteen yhteydet"
|
||||
|
||||
#: authentik/sources/saml/views.py
|
||||
#, python-brace-format
|
||||
msgid "Continue to {source_name}"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/scim/models.py
|
||||
msgid "SCIM Source"
|
||||
msgstr "SCIM-lähde"
|
||||
@ -3266,10 +3216,6 @@ msgstr "Käyttäjän hyväksyntä"
|
||||
msgid "User Consents"
|
||||
msgstr "Käyttäjän hyväksynnät"
|
||||
|
||||
#: authentik/stages/consent/stage.py
|
||||
msgid "Invalid consent token, re-showing prompt"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/deny/models.py
|
||||
msgid "Deny Stage"
|
||||
msgstr "Kieltovaihe"
|
||||
@ -3286,14 +3232,6 @@ msgstr "Valevaihe"
|
||||
msgid "Dummy Stages"
|
||||
msgstr "Valevaiheet"
|
||||
|
||||
#: authentik/stages/email/flow.py
|
||||
msgid "Continue to confirm this email address."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/email/flow.py
|
||||
msgid "Link was already used, please request a new link."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/email/models.py
|
||||
msgid "Password Reset"
|
||||
msgstr "Salasanan nollaus"
|
||||
|
@ -19,7 +19,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-05-28 11:25+0000\n"
|
||||
"POT-Creation-Date: 2025-05-20 00:10+0000\n"
|
||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||
"Last-Translator: Marc Schmitt, 2025\n"
|
||||
"Language-Team: French (https://app.transifex.com/authentik/teams/119923/fr/)\n"
|
||||
@ -1056,12 +1056,9 @@ msgid "Starting full provider sync"
|
||||
msgstr "Démarrage d'une synchronisation complète du fournisseur"
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
msgid "Syncing users"
|
||||
msgstr "Synchronisation des utilisateurs"
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
msgid "Syncing groups"
|
||||
msgstr "Synchronisation des groupes"
|
||||
#, python-brace-format
|
||||
msgid "Syncing page {page} of users"
|
||||
msgstr "Synchronisation de la page {page} d'utilisateurs"
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
#, python-brace-format
|
||||
@ -2511,14 +2508,6 @@ msgstr ""
|
||||
"plutôt que sur un attribut de groupe. Cela permet la résolution des groupes "
|
||||
"imbriqués sur des systèmes tels que FreeIPA et Active Directory."
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid ""
|
||||
"Delete authentik users and groups which were previously supplied by this "
|
||||
"source, but are now missing from it."
|
||||
msgstr ""
|
||||
"Supprimer les utilisateurs et les groupes authentik qui étaient auparavant "
|
||||
"fournis par cette source, mais qui en sont maintenant absents."
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "LDAP Source"
|
||||
msgstr "Source LDAP"
|
||||
@ -2535,13 +2524,6 @@ msgstr "Mappage de propriété source LDAP"
|
||||
msgid "LDAP Source Property Mappings"
|
||||
msgstr "Mappages de propriété source LDAP"
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid ""
|
||||
"Unique ID used while checking if this object still exists in the directory."
|
||||
msgstr ""
|
||||
"ID unique utilisé pour vérifier si cet objet existe toujours dans le "
|
||||
"répertoire."
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "User LDAP Source Connection"
|
||||
msgstr "Connexion de l'utilisateur à la source LDAP"
|
||||
@ -2936,11 +2918,6 @@ msgstr "Connexion du groupe à la source SAML"
|
||||
msgid "Group SAML Source Connections"
|
||||
msgstr "Connexions du groupe à la source SAML"
|
||||
|
||||
#: authentik/sources/saml/views.py
|
||||
#, python-brace-format
|
||||
msgid "Continue to {source_name}"
|
||||
msgstr "Continuer vers {source_name}"
|
||||
|
||||
#: authentik/sources/scim/models.py
|
||||
msgid "SCIM Source"
|
||||
msgstr "Source SCIM"
|
||||
@ -3331,10 +3308,6 @@ msgstr "Consentement Utilisateur"
|
||||
msgid "User Consents"
|
||||
msgstr "Consentements Utilisateur"
|
||||
|
||||
#: authentik/stages/consent/stage.py
|
||||
msgid "Invalid consent token, re-showing prompt"
|
||||
msgstr "Jeton de consentement invalide, réaffichage de l'invite"
|
||||
|
||||
#: authentik/stages/deny/models.py
|
||||
msgid "Deny Stage"
|
||||
msgstr "Étape de Refus"
|
||||
@ -3351,14 +3324,6 @@ msgstr "Étape factice"
|
||||
msgid "Dummy Stages"
|
||||
msgstr "Étapes factices"
|
||||
|
||||
#: authentik/stages/email/flow.py
|
||||
msgid "Continue to confirm this email address."
|
||||
msgstr "Continuer pour confirmer cette adresse courriel."
|
||||
|
||||
#: authentik/stages/email/flow.py
|
||||
msgid "Link was already used, please request a new link."
|
||||
msgstr "Ce lien a déjà été utilisé, veuillez en demander un nouveau."
|
||||
|
||||
#: authentik/stages/email/models.py
|
||||
msgid "Password Reset"
|
||||
msgstr "Réinitialiser le Mot de Passe"
|
||||
|
@ -20,7 +20,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-05-28 11:25+0000\n"
|
||||
"POT-Creation-Date: 2025-04-23 09:00+0000\n"
|
||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||
"Last-Translator: Kowalski Dragon (kowalski7cc) <kowalski.7cc@gmail.com>, 2025\n"
|
||||
"Language-Team: Italian (https://app.transifex.com/authentik/teams/119923/it/)\n"
|
||||
@ -114,10 +114,6 @@ msgstr ""
|
||||
msgid "Web Certificate used by the authentik Core webserver."
|
||||
msgstr "Certificato Web utilizzato dal server Web authentik Core."
|
||||
|
||||
#: authentik/brands/models.py
|
||||
msgid "Certificates used for client authentication."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/brands/models.py
|
||||
msgid "Brand"
|
||||
msgstr "Brand"
|
||||
@ -676,33 +672,6 @@ msgstr "Dispositivi di Accesso"
|
||||
msgid "Verifying your browser..."
|
||||
msgstr "Verifica del tuo browser..."
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid ""
|
||||
"Configure certificate authorities to validate the certificate against. This "
|
||||
"option has a higher priority than the `client_certificate` option on "
|
||||
"`Brand`."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid "Mutual TLS Stage"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid "Mutual TLS Stages"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid "Permissions to pass Certificates for outposts."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/stage.py
|
||||
msgid "Certificate required but no certificate was given."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/stage.py
|
||||
msgid "No user found for certificate."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/source/models.py
|
||||
msgid ""
|
||||
"Amount of time a user can take to return from the source to continue the "
|
||||
@ -1049,12 +1018,9 @@ msgid "Starting full provider sync"
|
||||
msgstr "Avvio della sincronizzazione completa del provider"
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
msgid "Syncing users"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
msgid "Syncing groups"
|
||||
msgstr ""
|
||||
#, python-brace-format
|
||||
msgid "Syncing page {page} of users"
|
||||
msgstr "Sincronizzando pagina {page} degli utenti"
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
#, python-brace-format
|
||||
@ -2497,12 +2463,6 @@ msgstr ""
|
||||
"attributo di gruppo. Questo consente la risoluzione di gruppi nidificati su "
|
||||
"sistemi come FreeIPA e Active Directory."
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid ""
|
||||
"Delete authentik users and groups which were previously supplied by this "
|
||||
"source, but are now missing from it."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "LDAP Source"
|
||||
msgstr "Sorgente LDAP"
|
||||
@ -2519,11 +2479,6 @@ msgstr "Mappatura delle proprietà sorgente LDAP"
|
||||
msgid "LDAP Source Property Mappings"
|
||||
msgstr "Mappature delle proprietà della sorgente LDAP"
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid ""
|
||||
"Unique ID used while checking if this object still exists in the directory."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "User LDAP Source Connection"
|
||||
msgstr "Connessione Sorgente LDAP Utente"
|
||||
@ -2917,11 +2872,6 @@ msgstr "Connessione sorgente SAML di gruppo"
|
||||
msgid "Group SAML Source Connections"
|
||||
msgstr "Connessioni sorgente SAML di gruppo"
|
||||
|
||||
#: authentik/sources/saml/views.py
|
||||
#, python-brace-format
|
||||
msgid "Continue to {source_name}"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/scim/models.py
|
||||
msgid "SCIM Source"
|
||||
msgstr "Sorgente SCIM"
|
||||
@ -3319,10 +3269,6 @@ msgstr "Consenso utente"
|
||||
msgid "User Consents"
|
||||
msgstr "Consensi utente"
|
||||
|
||||
#: authentik/stages/consent/stage.py
|
||||
msgid "Invalid consent token, re-showing prompt"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/deny/models.py
|
||||
msgid "Deny Stage"
|
||||
msgstr "Fase di negazione"
|
||||
@ -3339,14 +3285,6 @@ msgstr "Fase fittizia"
|
||||
msgid "Dummy Stages"
|
||||
msgstr "Fasi fittizie"
|
||||
|
||||
#: authentik/stages/email/flow.py
|
||||
msgid "Continue to confirm this email address."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/email/flow.py
|
||||
msgid "Link was already used, please request a new link."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/email/models.py
|
||||
msgid "Password Reset"
|
||||
msgstr "Ripristino password"
|
||||
|
@ -12,7 +12,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-05-28 11:25+0000\n"
|
||||
"POT-Creation-Date: 2025-04-23 09:00+0000\n"
|
||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||
"Last-Translator: NavyStack, 2023\n"
|
||||
"Language-Team: Korean (https://app.transifex.com/authentik/teams/119923/ko/)\n"
|
||||
@ -99,10 +99,6 @@ msgstr ""
|
||||
msgid "Web Certificate used by the authentik Core webserver."
|
||||
msgstr "Authentik Core 웹서버에서 사용하는 웹 인증서."
|
||||
|
||||
#: authentik/brands/models.py
|
||||
msgid "Certificates used for client authentication."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/brands/models.py
|
||||
msgid "Brand"
|
||||
msgstr ""
|
||||
@ -629,33 +625,6 @@ msgstr ""
|
||||
msgid "Verifying your browser..."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid ""
|
||||
"Configure certificate authorities to validate the certificate against. This "
|
||||
"option has a higher priority than the `client_certificate` option on "
|
||||
"`Brand`."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid "Mutual TLS Stage"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid "Mutual TLS Stages"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid "Permissions to pass Certificates for outposts."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/stage.py
|
||||
msgid "Certificate required but no certificate was given."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/stage.py
|
||||
msgid "No user found for certificate."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/source/models.py
|
||||
msgid ""
|
||||
"Amount of time a user can take to return from the source to continue the "
|
||||
@ -977,11 +946,8 @@ msgid "Starting full provider sync"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
msgid "Syncing users"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
msgid "Syncing groups"
|
||||
#, python-brace-format
|
||||
msgid "Syncing page {page} of users"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
@ -2297,12 +2263,6 @@ msgid ""
|
||||
"Active Directory"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid ""
|
||||
"Delete authentik users and groups which were previously supplied by this "
|
||||
"source, but are now missing from it."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "LDAP Source"
|
||||
msgstr "LDAP 소스"
|
||||
@ -2319,11 +2279,6 @@ msgstr ""
|
||||
msgid "LDAP Source Property Mappings"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid ""
|
||||
"Unique ID used while checking if this object still exists in the directory."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "User LDAP Source Connection"
|
||||
msgstr ""
|
||||
@ -2702,11 +2657,6 @@ msgstr ""
|
||||
msgid "Group SAML Source Connections"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/saml/views.py
|
||||
#, python-brace-format
|
||||
msgid "Continue to {source_name}"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/scim/models.py
|
||||
msgid "SCIM Source"
|
||||
msgstr ""
|
||||
@ -3067,10 +3017,6 @@ msgstr "사용자 동의"
|
||||
msgid "User Consents"
|
||||
msgstr "사용자 동의"
|
||||
|
||||
#: authentik/stages/consent/stage.py
|
||||
msgid "Invalid consent token, re-showing prompt"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/deny/models.py
|
||||
msgid "Deny Stage"
|
||||
msgstr "거부 스테이지"
|
||||
@ -3087,14 +3033,6 @@ msgstr "더미 스테이지"
|
||||
msgid "Dummy Stages"
|
||||
msgstr "더미 스테이지"
|
||||
|
||||
#: authentik/stages/email/flow.py
|
||||
msgid "Continue to confirm this email address."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/email/flow.py
|
||||
msgid "Link was already used, please request a new link."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/email/models.py
|
||||
msgid "Password Reset"
|
||||
msgstr "비밀번호 초기화"
|
||||
|
Binary file not shown.
@ -19,7 +19,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-05-28 11:25+0000\n"
|
||||
"POT-Creation-Date: 2025-04-11 00:10+0000\n"
|
||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||
"Last-Translator: Dany Sluijk, 2025\n"
|
||||
"Language-Team: Dutch (https://app.transifex.com/authentik/teams/119923/nl/)\n"
|
||||
@ -113,10 +113,6 @@ msgstr ""
|
||||
msgid "Web Certificate used by the authentik Core webserver."
|
||||
msgstr "Webcertificaat gebruikt door de authentik Core-webserver."
|
||||
|
||||
#: authentik/brands/models.py
|
||||
msgid "Certificates used for client authentication."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/brands/models.py
|
||||
msgid "Brand"
|
||||
msgstr "Merk"
|
||||
@ -195,7 +191,6 @@ msgid "User's display name."
|
||||
msgstr "Weergavenaam van de gebruiker."
|
||||
|
||||
#: authentik/core/models.py authentik/providers/oauth2/models.py
|
||||
#: authentik/rbac/models.py
|
||||
msgid "User"
|
||||
msgstr "Gebruiker"
|
||||
|
||||
@ -384,18 +379,6 @@ msgstr "Eigenschapskoppeling"
|
||||
msgid "Property Mappings"
|
||||
msgstr "Eigenschapskoppelingen"
|
||||
|
||||
#: authentik/core/models.py
|
||||
msgid "session data"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/core/models.py
|
||||
msgid "Session"
|
||||
msgstr "Sessie"
|
||||
|
||||
#: authentik/core/models.py
|
||||
msgid "Sessions"
|
||||
msgstr "Sessies"
|
||||
|
||||
#: authentik/core/models.py
|
||||
msgid "Authenticated Session"
|
||||
msgstr "Geauthenticeerde Sessie"
|
||||
@ -503,38 +486,6 @@ msgstr "Licentie Gebruik"
|
||||
msgid "License Usage Records"
|
||||
msgstr "Licentie Gebruik Records"
|
||||
|
||||
#: 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 ""
|
||||
"Veldsleutel om te controleren, veldsleutels gedefinieerd in Prompt-stadia "
|
||||
"zijn beschikbaar."
|
||||
|
||||
#: 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 "Wachtwoord niet ingesteld in context"
|
||||
|
||||
#: 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
|
||||
msgid "Enterprise required to access this feature."
|
||||
msgstr "Enterprise benodigd voor toegang tot deze functie."
|
||||
@ -671,33 +622,6 @@ msgstr ""
|
||||
msgid "Verifying your browser..."
|
||||
msgstr "Uw browser wordt geverifieerd..."
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid ""
|
||||
"Configure certificate authorities to validate the certificate against. This "
|
||||
"option has a higher priority than the `client_certificate` option on "
|
||||
"`Brand`."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid "Mutual TLS Stage"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid "Mutual TLS Stages"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid "Permissions to pass Certificates for outposts."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/stage.py
|
||||
msgid "Certificate required but no certificate was given."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/stage.py
|
||||
msgid "No user found for certificate."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/source/models.py
|
||||
msgid ""
|
||||
"Amount of time a user can take to return from the source to continue the "
|
||||
@ -1039,11 +963,8 @@ msgid "Starting full provider sync"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
msgid "Syncing users"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
msgid "Syncing groups"
|
||||
#, python-brace-format
|
||||
msgid "Syncing page {page} of users"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
@ -1344,6 +1265,12 @@ msgstr ""
|
||||
msgid "Clear Policy's cache metrics"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "Field key to check, field keys defined in Prompt stages are available."
|
||||
msgstr ""
|
||||
"Veldsleutel om te controleren, veldsleutels gedefinieerd in Prompt-stadia "
|
||||
"zijn beschikbaar."
|
||||
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "How many times the password hash is allowed to be on haveibeenpwned"
|
||||
msgstr "Hoe vaak het wachtwoordhash op haveibeenpwned mag voorkomen"
|
||||
@ -1355,6 +1282,10 @@ msgstr ""
|
||||
"Als de zxcvbn-score gelijk is aan of lager is dan deze waarde, zal het "
|
||||
"beleid falen."
|
||||
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "Password not set in context"
|
||||
msgstr "Wachtwoord niet ingesteld in context"
|
||||
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "Invalid password."
|
||||
msgstr ""
|
||||
@ -1396,6 +1327,20 @@ msgstr "Reputatie Score"
|
||||
msgid "Reputation Scores"
|
||||
msgstr "Reputatie Scores"
|
||||
|
||||
#: 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
|
||||
msgid "Permission denied"
|
||||
msgstr "Toestemming geweigerd"
|
||||
@ -2215,10 +2160,6 @@ msgstr ""
|
||||
msgid "Roles"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/rbac/models.py
|
||||
msgid "Initial Permissions"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/rbac/models.py
|
||||
msgid "System permission"
|
||||
msgstr ""
|
||||
@ -2451,12 +2392,6 @@ msgid ""
|
||||
"Active Directory"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid ""
|
||||
"Delete authentik users and groups which were previously supplied by this "
|
||||
"source, but are now missing from it."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "LDAP Source"
|
||||
msgstr "LDAP-bron"
|
||||
@ -2473,27 +2408,6 @@ msgstr ""
|
||||
msgid "LDAP Source Property Mappings"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid ""
|
||||
"Unique ID used while checking if this object still exists in the directory."
|
||||
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
|
||||
msgid "Password does not match Active Directory Complexity."
|
||||
msgstr ""
|
||||
@ -2503,14 +2417,6 @@ msgstr ""
|
||||
msgid "No token received."
|
||||
msgstr "Geen token ontvangen."
|
||||
|
||||
#: 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
|
||||
msgid "Request Token URL"
|
||||
msgstr "URL voor aanvragen van token"
|
||||
@ -2552,12 +2458,6 @@ msgstr ""
|
||||
msgid "Additional Scopes"
|
||||
msgstr "Aanvullende scopes"
|
||||
|
||||
#: authentik/sources/oauth/models.py
|
||||
msgid ""
|
||||
"How to perform authentication during an authorization_code token request "
|
||||
"flow"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/oauth/models.py
|
||||
msgid "OAuth Source"
|
||||
msgstr "OAuth-bron"
|
||||
@ -2869,11 +2769,6 @@ msgstr ""
|
||||
msgid "Group SAML Source Connections"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/saml/views.py
|
||||
#, python-brace-format
|
||||
msgid "Continue to {source_name}"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/scim/models.py
|
||||
msgid "SCIM Source"
|
||||
msgstr ""
|
||||
@ -3247,10 +3142,6 @@ msgstr "Gebruikerstoestemming"
|
||||
msgid "User Consents"
|
||||
msgstr "Gebruikersinstemmingen"
|
||||
|
||||
#: authentik/stages/consent/stage.py
|
||||
msgid "Invalid consent token, re-showing prompt"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/deny/models.py
|
||||
msgid "Deny Stage"
|
||||
msgstr "Weigerfase"
|
||||
@ -3267,14 +3158,6 @@ msgstr "Dummystadium"
|
||||
msgid "Dummy Stages"
|
||||
msgstr "Dummystadia"
|
||||
|
||||
#: authentik/stages/email/flow.py
|
||||
msgid "Continue to confirm this email address."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/email/flow.py
|
||||
msgid "Link was already used, please request a new link."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/email/models.py
|
||||
msgid "Password Reset"
|
||||
msgstr "Wachtwoordherstel"
|
||||
@ -3474,12 +3357,6 @@ msgstr ""
|
||||
"Wanneer ingeschakeld, slaagt de stap en gaat verder wanneer ongeldige "
|
||||
"gebruikersgegevens zijn ingevoerd."
|
||||
|
||||
#: 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
|
||||
msgid "Optional enrollment flow, which is linked at the bottom of the page."
|
||||
msgstr "Optionele inschrijvingsflow, die onderaan de pagina is gekoppeld."
|
||||
@ -3865,14 +3742,6 @@ msgstr ""
|
||||
"Gebeurtenissen worden verwijderd na deze duur. (Indeling: "
|
||||
"weken=3;dagen=2;uren=3;seconden=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
|
||||
msgid "The option configures the footer links on the flow executor pages."
|
||||
msgstr "De optie stelt de voettekst links in op de flow uitvoer pagina's."
|
||||
|
@ -11,7 +11,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-05-28 11:25+0000\n"
|
||||
"POT-Creation-Date: 2025-04-23 09:00+0000\n"
|
||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||
"Last-Translator: Hugo Bicho, 2025\n"
|
||||
"Language-Team: Portuguese (https://app.transifex.com/authentik/teams/119923/pt/)\n"
|
||||
@ -105,10 +105,6 @@ msgstr ""
|
||||
msgid "Web Certificate used by the authentik Core webserver."
|
||||
msgstr "Certificado Web usado pelo servidor web authentik Core."
|
||||
|
||||
#: authentik/brands/models.py
|
||||
msgid "Certificates used for client authentication."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/brands/models.py
|
||||
msgid "Brand"
|
||||
msgstr "Marca"
|
||||
@ -666,33 +662,6 @@ msgstr "Dispositivos do ponto de ligação"
|
||||
msgid "Verifying your browser..."
|
||||
msgstr "A verificar o seu browser..."
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid ""
|
||||
"Configure certificate authorities to validate the certificate against. This "
|
||||
"option has a higher priority than the `client_certificate` option on "
|
||||
"`Brand`."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid "Mutual TLS Stage"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid "Mutual TLS Stages"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid "Permissions to pass Certificates for outposts."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/stage.py
|
||||
msgid "Certificate required but no certificate was given."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/stage.py
|
||||
msgid "No user found for certificate."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/source/models.py
|
||||
msgid ""
|
||||
"Amount of time a user can take to return from the source to continue the "
|
||||
@ -1038,12 +1007,9 @@ msgid "Starting full provider sync"
|
||||
msgstr "Iniciando a sincronização completa com o provedor"
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
msgid "Syncing users"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
msgid "Syncing groups"
|
||||
msgstr ""
|
||||
#, python-brace-format
|
||||
msgid "Syncing page {page} of users"
|
||||
msgstr "A sincronizar a página {page} dos utilizadores"
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
#, python-brace-format
|
||||
@ -2490,12 +2456,6 @@ msgstr ""
|
||||
" um atributo do grupo. Isto permite a resolução de grupos hierárquicos em "
|
||||
"sistemas como o FreeIPA e Active Directory."
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid ""
|
||||
"Delete authentik users and groups which were previously supplied by this "
|
||||
"source, but are now missing from it."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "LDAP Source"
|
||||
msgstr "Fonte LDAP"
|
||||
@ -2512,11 +2472,6 @@ msgstr "Mapeamento de propriedades de fonte LDAP"
|
||||
msgid "LDAP Source Property Mappings"
|
||||
msgstr "Mapeamentos de propriedades de fonte LDAP"
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid ""
|
||||
"Unique ID used while checking if this object still exists in the directory."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "User LDAP Source Connection"
|
||||
msgstr "Ligação à fonte LDAP de Utilizador"
|
||||
@ -2910,11 +2865,6 @@ msgstr "Ligação à fonte SAML de Grupo"
|
||||
msgid "Group SAML Source Connections"
|
||||
msgstr "Ligações à fonte SAML de Grupo"
|
||||
|
||||
#: authentik/sources/saml/views.py
|
||||
#, python-brace-format
|
||||
msgid "Continue to {source_name}"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/scim/models.py
|
||||
msgid "SCIM Source"
|
||||
msgstr "Fonte SCIM"
|
||||
@ -3305,10 +3255,6 @@ msgstr "Consentimento do Utilizador"
|
||||
msgid "User Consents"
|
||||
msgstr "Consentimentos do Utilizador"
|
||||
|
||||
#: authentik/stages/consent/stage.py
|
||||
msgid "Invalid consent token, re-showing prompt"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/deny/models.py
|
||||
msgid "Deny Stage"
|
||||
msgstr "Etapa de negação"
|
||||
@ -3325,14 +3271,6 @@ msgstr "Etapa fictícia"
|
||||
msgid "Dummy Stages"
|
||||
msgstr "Etapas fictícias"
|
||||
|
||||
#: authentik/stages/email/flow.py
|
||||
msgid "Continue to confirm this email address."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/email/flow.py
|
||||
msgid "Link was already used, please request a new link."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/email/models.py
|
||||
msgid "Password Reset"
|
||||
msgstr "Redefinição de Palavra-Passe"
|
||||
|
Binary file not shown.
@ -8,19 +8,19 @@
|
||||
# Josenivaldo Benito Junior, 2023
|
||||
# Caio Lima, 2023
|
||||
# Hacklab, 2023
|
||||
# Wagner Santos, 2024
|
||||
# Rafael Mundel, 2024
|
||||
# Anderson Silva Andrade <anderson.asa89@gmail.com>, 2025
|
||||
# Gil Poiares-Oliveira, 2025
|
||||
# Wagner Santos, 2025
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-05-28 11:25+0000\n"
|
||||
"POT-Creation-Date: 2025-04-23 09:00+0000\n"
|
||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||
"Last-Translator: Wagner Santos, 2025\n"
|
||||
"Last-Translator: Gil Poiares-Oliveira, 2025\n"
|
||||
"Language-Team: Portuguese (Brazil) (https://app.transifex.com/authentik/teams/119923/pt_BR/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@ -112,10 +112,6 @@ msgstr ""
|
||||
msgid "Web Certificate used by the authentik Core webserver."
|
||||
msgstr "Certificado da Web usado pelo servidor da web authentik Core."
|
||||
|
||||
#: authentik/brands/models.py
|
||||
msgid "Certificates used for client authentication."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/brands/models.py
|
||||
msgid "Brand"
|
||||
msgstr "Brand"
|
||||
@ -275,11 +271,11 @@ msgstr "Aplicativos"
|
||||
|
||||
#: authentik/core/models.py
|
||||
msgid "Application Entitlement"
|
||||
msgstr "Autorização de aplicação"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/core/models.py
|
||||
msgid "Application Entitlements"
|
||||
msgstr "Autorizações de aplicação"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/core/models.py
|
||||
msgid "Use the source-specific identifier"
|
||||
@ -383,15 +379,15 @@ msgstr "Mapeamentos de propriedades"
|
||||
|
||||
#: authentik/core/models.py
|
||||
msgid "session data"
|
||||
msgstr "dados de sessão"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/core/models.py
|
||||
msgid "Session"
|
||||
msgstr "Sessão"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/core/models.py
|
||||
msgid "Sessions"
|
||||
msgstr "Sessões"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/core/models.py
|
||||
msgid "Authenticated Session"
|
||||
@ -509,7 +505,7 @@ msgstr ""
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "Number of passwords to check against."
|
||||
msgstr "Número de senhas para verificar."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
#: authentik/policies/password/models.py
|
||||
@ -518,19 +514,19 @@ 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 "A senha já foi utilizada antes. Por favor, escolha uma diferente."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "Password Uniqueness Policy"
|
||||
msgstr "Política de exclusividade de senha"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "Password Uniqueness Policies"
|
||||
msgstr "Políticas de exclusividade de senha"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policies/unique_password/models.py
|
||||
msgid "User Password History"
|
||||
msgstr "Histórico de senhas do usuário"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/policy.py
|
||||
msgid "Enterprise required to access this feature."
|
||||
@ -614,39 +610,39 @@ msgstr "Chave de Assinatura"
|
||||
|
||||
#: authentik/enterprise/providers/ssf/models.py
|
||||
msgid "Key used to sign the SSF Events."
|
||||
msgstr "Chave utilizada para assinar os eventos SSF."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/providers/ssf/models.py
|
||||
msgid "Shared Signals Framework Provider"
|
||||
msgstr "Provedor de Shared Signals Framework"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/providers/ssf/models.py
|
||||
msgid "Shared Signals Framework Providers"
|
||||
msgstr "Provedores de Shared Signals Framework"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/providers/ssf/models.py
|
||||
msgid "Add stream to SSF provider"
|
||||
msgstr "Adicionar stream ao fornecedor SSF"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/providers/ssf/models.py
|
||||
msgid "SSF Stream"
|
||||
msgstr "Stream SSF"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/providers/ssf/models.py
|
||||
msgid "SSF Streams"
|
||||
msgstr "Streams SSF"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/providers/ssf/models.py
|
||||
msgid "SSF Stream Event"
|
||||
msgstr "Evento de stream SSF"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/providers/ssf/models.py
|
||||
msgid "SSF Stream Events"
|
||||
msgstr "Eventos de stream SSF"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/providers/ssf/tasks.py
|
||||
msgid "Failed to send request"
|
||||
msgstr "Falha ao enviar requisição"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/authenticator_endpoint_gdtc/models.py
|
||||
msgid "Endpoint Authenticator Google Device Trust Connector Stage"
|
||||
@ -668,33 +664,6 @@ msgstr ""
|
||||
msgid "Verifying your browser..."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid ""
|
||||
"Configure certificate authorities to validate the certificate against. This "
|
||||
"option has a higher priority than the `client_certificate` option on "
|
||||
"`Brand`."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid "Mutual TLS Stage"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid "Mutual TLS Stages"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid "Permissions to pass Certificates for outposts."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/stage.py
|
||||
msgid "Certificate required but no certificate was given."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/stage.py
|
||||
msgid "No user found for certificate."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/source/models.py
|
||||
msgid ""
|
||||
"Amount of time a user can take to return from the source to continue the "
|
||||
@ -712,7 +681,7 @@ msgstr ""
|
||||
#: authentik/events/api/tasks.py
|
||||
#, python-brace-format
|
||||
msgid "Successfully started task {name}."
|
||||
msgstr "Tarefa {name} iniciada com sucesso."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/events/models.py
|
||||
msgid "Event"
|
||||
@ -744,16 +713,12 @@ msgid ""
|
||||
"Customize the body of the request. Mapping should return data that is JSON-"
|
||||
"serializable."
|
||||
msgstr ""
|
||||
"Personalize o corpo do pedido. O mapeamento deve retornar dados que sejam "
|
||||
"serializáveis em JSON."
|
||||
|
||||
#: authentik/events/models.py
|
||||
msgid ""
|
||||
"Configure additional headers to be sent. Mapping should return a dictionary "
|
||||
"of key-value pairs"
|
||||
msgstr ""
|
||||
"Configurar cabeçalhos adicionais a serem enviados. O mapeamento deve "
|
||||
"retornar um dicionário de pares chave-valor"
|
||||
|
||||
#: authentik/events/models.py
|
||||
msgid ""
|
||||
@ -1033,11 +998,8 @@ msgid "Starting full provider sync"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
msgid "Syncing users"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
msgid "Syncing groups"
|
||||
#, python-brace-format
|
||||
msgid "Syncing page {page} of users"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
@ -1352,7 +1314,7 @@ msgstr ""
|
||||
#: authentik/policies/password/models.py
|
||||
#, python-brace-format
|
||||
msgid "Password exists on {count} online lists."
|
||||
msgstr "A senha está presente em {count} listas de senhas vulneráveis."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/policies/password/models.py
|
||||
msgid "Password is too weak."
|
||||
@ -2434,12 +2396,6 @@ msgid ""
|
||||
"Active Directory"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid ""
|
||||
"Delete authentik users and groups which were previously supplied by this "
|
||||
"source, but are now missing from it."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "LDAP Source"
|
||||
msgstr "Fonte LDAP"
|
||||
@ -2456,11 +2412,6 @@ msgstr ""
|
||||
msgid "LDAP Source Property Mappings"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid ""
|
||||
"Unique ID used while checking if this object still exists in the directory."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "User LDAP Source Connection"
|
||||
msgstr ""
|
||||
@ -2851,11 +2802,6 @@ msgstr ""
|
||||
msgid "Group SAML Source Connections"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/saml/views.py
|
||||
#, python-brace-format
|
||||
msgid "Continue to {source_name}"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/scim/models.py
|
||||
msgid "SCIM Source"
|
||||
msgstr ""
|
||||
@ -3228,10 +3174,6 @@ msgstr "Consentimento do usuário"
|
||||
msgid "User Consents"
|
||||
msgstr "Consentimentos do usuário"
|
||||
|
||||
#: authentik/stages/consent/stage.py
|
||||
msgid "Invalid consent token, re-showing prompt"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/deny/models.py
|
||||
msgid "Deny Stage"
|
||||
msgstr "Negar Estágio"
|
||||
@ -3248,14 +3190,6 @@ msgstr "Palco fictício"
|
||||
msgid "Dummy Stages"
|
||||
msgstr "Fases fictícias"
|
||||
|
||||
#: authentik/stages/email/flow.py
|
||||
msgid "Continue to confirm this email address."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/email/flow.py
|
||||
msgid "Link was already used, please request a new link."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/email/models.py
|
||||
msgid "Password Reset"
|
||||
msgstr "Redefinição de senha"
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -18,7 +18,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-05-28 11:25+0000\n"
|
||||
"POT-Creation-Date: 2025-04-23 09:00+0000\n"
|
||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||
"Last-Translator: Marc Schmitt, 2025\n"
|
||||
"Language-Team: Russian (https://app.transifex.com/authentik/teams/119923/ru/)\n"
|
||||
@ -111,10 +111,6 @@ msgstr ""
|
||||
msgid "Web Certificate used by the authentik Core webserver."
|
||||
msgstr "Web Certificate используемый для authentik Core webserver."
|
||||
|
||||
#: authentik/brands/models.py
|
||||
msgid "Certificates used for client authentication."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/brands/models.py
|
||||
msgid "Brand"
|
||||
msgstr "Бренд"
|
||||
@ -673,33 +669,6 @@ msgstr "Конечные устройства"
|
||||
msgid "Verifying your browser..."
|
||||
msgstr "Проверка вашего браузера..."
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid ""
|
||||
"Configure certificate authorities to validate the certificate against. This "
|
||||
"option has a higher priority than the `client_certificate` option on "
|
||||
"`Brand`."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid "Mutual TLS Stage"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid "Mutual TLS Stages"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid "Permissions to pass Certificates for outposts."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/stage.py
|
||||
msgid "Certificate required but no certificate was given."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/stage.py
|
||||
msgid "No user found for certificate."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/source/models.py
|
||||
msgid ""
|
||||
"Amount of time a user can take to return from the source to continue the "
|
||||
@ -1040,11 +1009,8 @@ msgid "Starting full provider sync"
|
||||
msgstr "Запуск полной синхронизации провайдера"
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
msgid "Syncing users"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
msgid "Syncing groups"
|
||||
#, python-brace-format
|
||||
msgid "Syncing page {page} of users"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
@ -2464,12 +2430,6 @@ msgid ""
|
||||
"Active Directory"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid ""
|
||||
"Delete authentik users and groups which were previously supplied by this "
|
||||
"source, but are now missing from it."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "LDAP Source"
|
||||
msgstr "Источник LDAP"
|
||||
@ -2486,11 +2446,6 @@ msgstr "Сопоставление свойства LDAP источника"
|
||||
msgid "LDAP Source Property Mappings"
|
||||
msgstr "Сопоставление свойств LDAP источника"
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid ""
|
||||
"Unique ID used while checking if this object still exists in the directory."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "User LDAP Source Connection"
|
||||
msgstr ""
|
||||
@ -2887,11 +2842,6 @@ msgstr "Групповое подключение к источнику SAML"
|
||||
msgid "Group SAML Source Connections"
|
||||
msgstr "Групповые подключения к источнику SAML"
|
||||
|
||||
#: authentik/sources/saml/views.py
|
||||
#, python-brace-format
|
||||
msgid "Continue to {source_name}"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/scim/models.py
|
||||
msgid "SCIM Source"
|
||||
msgstr "Источник SCIM"
|
||||
@ -3269,10 +3219,6 @@ msgstr "Согласие пользователя"
|
||||
msgid "User Consents"
|
||||
msgstr "Согласия пользователя"
|
||||
|
||||
#: authentik/stages/consent/stage.py
|
||||
msgid "Invalid consent token, re-showing prompt"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/deny/models.py
|
||||
msgid "Deny Stage"
|
||||
msgstr "Этап отказа"
|
||||
@ -3289,14 +3235,6 @@ msgstr "Фиктивный этап"
|
||||
msgid "Dummy Stages"
|
||||
msgstr "Фиктивные этапы"
|
||||
|
||||
#: authentik/stages/email/flow.py
|
||||
msgid "Continue to confirm this email address."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/email/flow.py
|
||||
msgid "Link was already used, please request a new link."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/email/models.py
|
||||
msgid "Password Reset"
|
||||
msgstr "Сброс пароля"
|
||||
|
@ -13,7 +13,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-05-28 11:25+0000\n"
|
||||
"POT-Creation-Date: 2025-04-23 09:00+0000\n"
|
||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||
"Last-Translator: Jens L. <jens@goauthentik.io>, 2025\n"
|
||||
"Language-Team: Turkish (https://app.transifex.com/authentik/teams/119923/tr/)\n"
|
||||
@ -107,10 +107,6 @@ msgstr ""
|
||||
msgid "Web Certificate used by the authentik Core webserver."
|
||||
msgstr "Authentik Core web sunucusu tarafından kullanılan Web Sertifikası."
|
||||
|
||||
#: authentik/brands/models.py
|
||||
msgid "Certificates used for client authentication."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/brands/models.py
|
||||
msgid "Brand"
|
||||
msgstr "Marka"
|
||||
@ -663,33 +659,6 @@ msgstr "Uç Nokta Cihazları"
|
||||
msgid "Verifying your browser..."
|
||||
msgstr "Tarayıcınız doğrulanıyor..."
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid ""
|
||||
"Configure certificate authorities to validate the certificate against. This "
|
||||
"option has a higher priority than the `client_certificate` option on "
|
||||
"`Brand`."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid "Mutual TLS Stage"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid "Mutual TLS Stages"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid "Permissions to pass Certificates for outposts."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/stage.py
|
||||
msgid "Certificate required but no certificate was given."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/stage.py
|
||||
msgid "No user found for certificate."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/source/models.py
|
||||
msgid ""
|
||||
"Amount of time a user can take to return from the source to continue the "
|
||||
@ -1031,11 +1000,8 @@ msgid "Starting full provider sync"
|
||||
msgstr "Tam sağlayıcı senkronizasyonunu başlatma"
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
msgid "Syncing users"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
msgid "Syncing groups"
|
||||
#, python-brace-format
|
||||
msgid "Syncing page {page} of users"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
@ -2464,12 +2430,6 @@ msgid ""
|
||||
"Active Directory"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid ""
|
||||
"Delete authentik users and groups which were previously supplied by this "
|
||||
"source, but are now missing from it."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "LDAP Source"
|
||||
msgstr "LDAP Kaynağı"
|
||||
@ -2486,11 +2446,6 @@ msgstr "LDAP Kaynak Özellik Eşlemesi"
|
||||
msgid "LDAP Source Property Mappings"
|
||||
msgstr "LDAP Kaynak Özellik Eşlemeleri"
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid ""
|
||||
"Unique ID used while checking if this object still exists in the directory."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "User LDAP Source Connection"
|
||||
msgstr ""
|
||||
@ -2882,11 +2837,6 @@ msgstr "Grup SAML Kaynak Bağlantısı"
|
||||
msgid "Group SAML Source Connections"
|
||||
msgstr "Grup SAML Kaynak Bağlantıları"
|
||||
|
||||
#: authentik/sources/saml/views.py
|
||||
#, python-brace-format
|
||||
msgid "Continue to {source_name}"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/scim/models.py
|
||||
msgid "SCIM Source"
|
||||
msgstr "SCIM Kaynak"
|
||||
@ -3261,10 +3211,6 @@ msgstr "Kullanıcı Onayı"
|
||||
msgid "User Consents"
|
||||
msgstr "Kullanıcı Onayları"
|
||||
|
||||
#: authentik/stages/consent/stage.py
|
||||
msgid "Invalid consent token, re-showing prompt"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/deny/models.py
|
||||
msgid "Deny Stage"
|
||||
msgstr "Aşama Alanını Reddet"
|
||||
@ -3281,14 +3227,6 @@ msgstr "Kukla Aşaması"
|
||||
msgid "Dummy Stages"
|
||||
msgstr "Kukla Aşamaları"
|
||||
|
||||
#: authentik/stages/email/flow.py
|
||||
msgid "Continue to confirm this email address."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/email/flow.py
|
||||
msgid "Link was already used, please request a new link."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/email/models.py
|
||||
msgid "Password Reset"
|
||||
msgstr "Parola Sıfırlama"
|
||||
|
Binary file not shown.
@ -15,7 +15,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-05-28 11:25+0000\n"
|
||||
"POT-Creation-Date: 2025-05-20 00:10+0000\n"
|
||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||
"Last-Translator: deluxghost, 2025\n"
|
||||
"Language-Team: Chinese Simplified (https://app.transifex.com/authentik/teams/119923/zh-Hans/)\n"
|
||||
@ -975,12 +975,9 @@ msgid "Starting full provider sync"
|
||||
msgstr "开始全量提供程序同步"
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
msgid "Syncing users"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
msgid "Syncing groups"
|
||||
msgstr ""
|
||||
#, python-brace-format
|
||||
msgid "Syncing page {page} of users"
|
||||
msgstr "正在同步用户页面 {page}"
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
#, python-brace-format
|
||||
@ -2288,12 +2285,6 @@ msgid ""
|
||||
"Active Directory"
|
||||
msgstr "基于用户属性而非组属性查询组成员身份。这允许在 FreeIPA 或 Active Directory 等系统上支持嵌套组决策"
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid ""
|
||||
"Delete authentik users and groups which were previously supplied by this "
|
||||
"source, but are now missing from it."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "LDAP Source"
|
||||
msgstr "LDAP 源"
|
||||
@ -2310,11 +2301,6 @@ msgstr "LDAP 源属性映射"
|
||||
msgid "LDAP Source Property Mappings"
|
||||
msgstr "LDAP 源属性映射"
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid ""
|
||||
"Unique ID used while checking if this object still exists in the directory."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "User LDAP Source Connection"
|
||||
msgstr "用户 LDAP 源连接"
|
||||
@ -2692,11 +2678,6 @@ msgstr "组 SAML 源连接"
|
||||
msgid "Group SAML Source Connections"
|
||||
msgstr "组 SAML 源连接"
|
||||
|
||||
#: authentik/sources/saml/views.py
|
||||
#, python-brace-format
|
||||
msgid "Continue to {source_name}"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/scim/models.py
|
||||
msgid "SCIM Source"
|
||||
msgstr "SCIM 源"
|
||||
@ -3063,10 +3044,6 @@ msgstr "用户同意授权"
|
||||
msgid "User Consents"
|
||||
msgstr "用户同意授权"
|
||||
|
||||
#: authentik/stages/consent/stage.py
|
||||
msgid "Invalid consent token, re-showing prompt"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/deny/models.py
|
||||
msgid "Deny Stage"
|
||||
msgstr "拒绝阶段"
|
||||
@ -3083,14 +3060,6 @@ msgstr "虚拟阶段"
|
||||
msgid "Dummy Stages"
|
||||
msgstr "虚拟阶段"
|
||||
|
||||
#: authentik/stages/email/flow.py
|
||||
msgid "Continue to confirm this email address."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/email/flow.py
|
||||
msgid "Link was already used, please request a new link."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/email/models.py
|
||||
msgid "Password Reset"
|
||||
msgstr "密码重置"
|
||||
|
Binary file not shown.
@ -14,7 +14,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-05-28 11:25+0000\n"
|
||||
"POT-Creation-Date: 2025-05-20 00:10+0000\n"
|
||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||
"Last-Translator: deluxghost, 2025\n"
|
||||
"Language-Team: Chinese (China) (https://app.transifex.com/authentik/teams/119923/zh_CN/)\n"
|
||||
@ -974,12 +974,9 @@ msgid "Starting full provider sync"
|
||||
msgstr "开始全量提供程序同步"
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
msgid "Syncing users"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
msgid "Syncing groups"
|
||||
msgstr ""
|
||||
#, python-brace-format
|
||||
msgid "Syncing page {page} of users"
|
||||
msgstr "正在同步用户页面 {page}"
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
#, python-brace-format
|
||||
@ -2287,12 +2284,6 @@ msgid ""
|
||||
"Active Directory"
|
||||
msgstr "基于用户属性而非组属性查询组成员身份。这允许在 FreeIPA 或 Active Directory 等系统上支持嵌套组决策"
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid ""
|
||||
"Delete authentik users and groups which were previously supplied by this "
|
||||
"source, but are now missing from it."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "LDAP Source"
|
||||
msgstr "LDAP 源"
|
||||
@ -2309,11 +2300,6 @@ msgstr "LDAP 源属性映射"
|
||||
msgid "LDAP Source Property Mappings"
|
||||
msgstr "LDAP 源属性映射"
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid ""
|
||||
"Unique ID used while checking if this object still exists in the directory."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "User LDAP Source Connection"
|
||||
msgstr "用户 LDAP 源连接"
|
||||
@ -2691,11 +2677,6 @@ msgstr "组 SAML 源连接"
|
||||
msgid "Group SAML Source Connections"
|
||||
msgstr "组 SAML 源连接"
|
||||
|
||||
#: authentik/sources/saml/views.py
|
||||
#, python-brace-format
|
||||
msgid "Continue to {source_name}"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/scim/models.py
|
||||
msgid "SCIM Source"
|
||||
msgstr "SCIM 源"
|
||||
@ -3062,10 +3043,6 @@ msgstr "用户同意授权"
|
||||
msgid "User Consents"
|
||||
msgstr "用户同意授权"
|
||||
|
||||
#: authentik/stages/consent/stage.py
|
||||
msgid "Invalid consent token, re-showing prompt"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/deny/models.py
|
||||
msgid "Deny Stage"
|
||||
msgstr "拒绝阶段"
|
||||
@ -3082,14 +3059,6 @@ msgstr "虚拟阶段"
|
||||
msgid "Dummy Stages"
|
||||
msgstr "虚拟阶段"
|
||||
|
||||
#: authentik/stages/email/flow.py
|
||||
msgid "Continue to confirm this email address."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/email/flow.py
|
||||
msgid "Link was already used, please request a new link."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/email/models.py
|
||||
msgid "Password Reset"
|
||||
msgstr "密码重置"
|
||||
|
@ -14,7 +14,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-05-28 11:25+0000\n"
|
||||
"POT-Creation-Date: 2025-04-23 09:00+0000\n"
|
||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||
"Last-Translator: 刘松, 2025\n"
|
||||
"Language-Team: Chinese (Taiwan) (https://app.transifex.com/authentik/teams/119923/zh_TW/)\n"
|
||||
@ -101,10 +101,6 @@ msgstr ""
|
||||
msgid "Web Certificate used by the authentik Core webserver."
|
||||
msgstr "用於 authentik Core 網頁伺服器的網頁憑證。"
|
||||
|
||||
#: authentik/brands/models.py
|
||||
msgid "Certificates used for client authentication."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/brands/models.py
|
||||
msgid "Brand"
|
||||
msgstr "品牌"
|
||||
@ -629,33 +625,6 @@ msgstr ""
|
||||
msgid "Verifying your browser..."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid ""
|
||||
"Configure certificate authorities to validate the certificate against. This "
|
||||
"option has a higher priority than the `client_certificate` option on "
|
||||
"`Brand`."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid "Mutual TLS Stage"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid "Mutual TLS Stages"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/models.py
|
||||
msgid "Permissions to pass Certificates for outposts."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/stage.py
|
||||
msgid "Certificate required but no certificate was given."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/mtls/stage.py
|
||||
msgid "No user found for certificate."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/enterprise/stages/source/models.py
|
||||
msgid ""
|
||||
"Amount of time a user can take to return from the source to continue the "
|
||||
@ -974,11 +943,8 @@ msgid "Starting full provider sync"
|
||||
msgstr "開始同步所有提供程式"
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
msgid "Syncing users"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
msgid "Syncing groups"
|
||||
#, python-brace-format
|
||||
msgid "Syncing page {page} of users"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
@ -2283,12 +2249,6 @@ msgid ""
|
||||
"Active Directory"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid ""
|
||||
"Delete authentik users and groups which were previously supplied by this "
|
||||
"source, but are now missing from it."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "LDAP Source"
|
||||
msgstr "LDAP 來源"
|
||||
@ -2305,11 +2265,6 @@ msgstr ""
|
||||
msgid "LDAP Source Property Mappings"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid ""
|
||||
"Unique ID used while checking if this object still exists in the directory."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/ldap/models.py
|
||||
msgid "User LDAP Source Connection"
|
||||
msgstr ""
|
||||
@ -2687,11 +2642,6 @@ msgstr ""
|
||||
msgid "Group SAML Source Connections"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/saml/views.py
|
||||
#, python-brace-format
|
||||
msgid "Continue to {source_name}"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/sources/scim/models.py
|
||||
msgid "SCIM Source"
|
||||
msgstr "SCIM 來源"
|
||||
@ -3048,10 +2998,6 @@ msgstr "使用者同意"
|
||||
msgid "User Consents"
|
||||
msgstr "使用者同意"
|
||||
|
||||
#: authentik/stages/consent/stage.py
|
||||
msgid "Invalid consent token, re-showing prompt"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/deny/models.py
|
||||
msgid "Deny Stage"
|
||||
msgstr "拒絕階段"
|
||||
@ -3068,14 +3014,6 @@ msgstr "假階段"
|
||||
msgid "Dummy Stages"
|
||||
msgstr "假階段"
|
||||
|
||||
#: authentik/stages/email/flow.py
|
||||
msgid "Continue to confirm this email address."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/email/flow.py
|
||||
msgid "Link was already used, please request a new link."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/email/models.py
|
||||
msgid "Password Reset"
|
||||
msgstr "重設密碼"
|
||||
|
8
packages/docusaurus-config/package-lock.json
generated
8
packages/docusaurus-config/package-lock.json
generated
@ -3710,9 +3710,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@goauthentik/prettier-config": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@goauthentik/prettier-config/-/prettier-config-1.0.5.tgz",
|
||||
"integrity": "sha512-3W1uJvhzBPerDao53hSXhNzB7Ev8DbGYh+gVkuku1FaUZGBpiwD/6U3ah4sny8NoRiObGQ1geF4dhNLtlRbC/Q==",
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@goauthentik/prettier-config/-/prettier-config-1.0.4.tgz",
|
||||
"integrity": "sha512-CgUVAThlJHif7ZRXUPMbR/7/YLGzkJw7YbqEcleUjjKkvID0aykrypXx04td6cG76zigspTCgJKoXimKT41E7g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@ -3722,7 +3722,7 @@
|
||||
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
|
||||
"prettier": "^3.5.3",
|
||||
"prettier-plugin-organize-imports": "^4.1.0",
|
||||
"prettier-plugin-packagejson": "^2.5.14"
|
||||
"prettier-plugin-packagejson": "^2.5.10"
|
||||
}
|
||||
},
|
||||
"node_modules/@goauthentik/tsconfig": {
|
||||
|
106
packages/eslint-config/package-lock.json
generated
106
packages/eslint-config/package-lock.json
generated
@ -308,9 +308,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@goauthentik/prettier-config": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@goauthentik/prettier-config/-/prettier-config-1.0.5.tgz",
|
||||
"integrity": "sha512-3W1uJvhzBPerDao53hSXhNzB7Ev8DbGYh+gVkuku1FaUZGBpiwD/6U3ah4sny8NoRiObGQ1geF4dhNLtlRbC/Q==",
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@goauthentik/prettier-config/-/prettier-config-1.0.1.tgz",
|
||||
"integrity": "sha512-6N0cCG3Uw3Nt+gTxRJ/FYFi/NfuL849CrQkrx307PvEBaG66OjxFFee4bhS/si4XvLdxFdog7oQsPwYmqZeZ+w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@ -320,13 +320,13 @@
|
||||
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
|
||||
"prettier": "^3.5.3",
|
||||
"prettier-plugin-organize-imports": "^4.1.0",
|
||||
"prettier-plugin-packagejson": "^2.5.14"
|
||||
"prettier-plugin-packagejson": "^2.5.10"
|
||||
}
|
||||
},
|
||||
"node_modules/@goauthentik/tsconfig": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@goauthentik/tsconfig/-/tsconfig-1.0.4.tgz",
|
||||
"integrity": "sha512-BTGVpGh8SbCRHTULBf+2WTcw6OHJ8Ws9VtVfAMUUgcq8whbH/A7Q/n8WbkDaEeihzHUFkLk3JBenHKzEKAZWlw==",
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@goauthentik/tsconfig/-/tsconfig-1.0.1.tgz",
|
||||
"integrity": "sha512-kxMDkgUHhAmQ2iIhUZJjrx/CgDb1AwvRoPtU4vrjAZu7x66+qczCjRTK+GzIGCeqB97GEpvCCjU8CThmozVFqA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
@ -491,9 +491,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@pkgr/core": {
|
||||
"version": "0.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.4.tgz",
|
||||
"integrity": "sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw==",
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.2.tgz",
|
||||
"integrity": "sha512-fdDH1LSGfZdTH2sxdpVMw31BanV28K/Gry0cVFxaNP77neJSkd82mM8ErPNYs9e+0O7SdHBLTDzDgwUuy18RnQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
@ -501,7 +501,7 @@
|
||||
"node": "^12.20.0 || ^14.18.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/pkgr"
|
||||
"url": "https://opencollective.com/unts"
|
||||
}
|
||||
},
|
||||
"node_modules/@rtsao/scc": {
|
||||
@ -2045,6 +2045,20 @@
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/get-stdin": {
|
||||
"version": "9.0.0",
|
||||
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-9.0.0.tgz",
|
||||
"integrity": "sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/get-symbol-description": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz",
|
||||
@ -2063,9 +2077,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/git-hooks-list": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-4.1.1.tgz",
|
||||
"integrity": "sha512-cmP497iLq54AZnv4YRAEMnEyQ1eIn4tGKbmswqwmFV4GBnAqE8NLtWxxdXa++AalfgL5EBH4IxTPyquEuGY/jA==",
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/git-hooks-list/-/git-hooks-list-3.2.0.tgz",
|
||||
"integrity": "sha512-ZHG9a1gEhUMX1TvGrLdyWb9kDopCBbTnI8z4JgRMYxsijWipgjSEYoPWqBuIB0DnRnvqlQSEeVmzpeuPm7NdFQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
@ -3205,15 +3219,15 @@
|
||||
}
|
||||
},
|
||||
"node_modules/prettier-plugin-packagejson": {
|
||||
"version": "2.5.14",
|
||||
"resolved": "https://registry.npmjs.org/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.5.14.tgz",
|
||||
"integrity": "sha512-h+3tSpr2nVpp+YOK1MDIYtYhHVXr8/0V59UUbJpIJFaqi3w4fvUokJo6eV8W+vELrUXIZzJ+DKm5G7lYzrMcKQ==",
|
||||
"version": "2.5.10",
|
||||
"resolved": "https://registry.npmjs.org/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.5.10.tgz",
|
||||
"integrity": "sha512-LUxATI5YsImIVSaaLJlJ3aE6wTD+nvots18U3GuQMJpUyClChaZlQrqx3dBnbhF20OnKWZyx8EgyZypQtBDtgQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"sort-package-json": "3.2.1",
|
||||
"synckit": "0.11.6"
|
||||
"sort-package-json": "2.15.1",
|
||||
"synckit": "0.9.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"prettier": ">= 1.16.0"
|
||||
@ -3619,29 +3633,30 @@
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/sort-package-json": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-3.2.1.tgz",
|
||||
"integrity": "sha512-rTfRdb20vuoAn7LDlEtCqOkYfl2X+Qze6cLbNOzcDpbmKEhJI30tTN44d5shbKJnXsvz24QQhlCm81Bag7EOKg==",
|
||||
"version": "2.15.1",
|
||||
"resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-2.15.1.tgz",
|
||||
"integrity": "sha512-9x9+o8krTT2saA9liI4BljNjwAbvUnWf11Wq+i/iZt8nl2UGYnf3TH5uBydE7VALmP7AGwlfszuEeL8BDyb0YA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"detect-indent": "^7.0.1",
|
||||
"detect-newline": "^4.0.1",
|
||||
"git-hooks-list": "^4.0.0",
|
||||
"detect-newline": "^4.0.0",
|
||||
"get-stdin": "^9.0.0",
|
||||
"git-hooks-list": "^3.0.0",
|
||||
"is-plain-obj": "^4.1.0",
|
||||
"semver": "^7.7.1",
|
||||
"semver": "^7.6.0",
|
||||
"sort-object-keys": "^1.1.3",
|
||||
"tinyglobby": "^0.2.12"
|
||||
"tinyglobby": "^0.2.9"
|
||||
},
|
||||
"bin": {
|
||||
"sort-package-json": "cli.js"
|
||||
}
|
||||
},
|
||||
"node_modules/sort-package-json/node_modules/semver": {
|
||||
"version": "7.7.2",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
|
||||
"integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
|
||||
"version": "7.7.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz",
|
||||
"integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"peer": true,
|
||||
@ -3791,31 +3806,32 @@
|
||||
}
|
||||
},
|
||||
"node_modules/synckit": {
|
||||
"version": "0.11.6",
|
||||
"resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.6.tgz",
|
||||
"integrity": "sha512-2pR2ubZSV64f/vqm9eLPz/KOvR9Dm+Co/5ChLgeHl0yEDRc6h5hXHoxEQH8Y5Ljycozd3p1k5TTSVdzYGkPvLw==",
|
||||
"version": "0.9.2",
|
||||
"resolved": "https://registry.npmjs.org/synckit/-/synckit-0.9.2.tgz",
|
||||
"integrity": "sha512-vrozgXDQwYO72vHjUb/HnFbQx1exDjoKzqx23aXEg2a9VIg2TSFZ8FmeZpTjUCFMYw7mpX4BE2SFu8wI7asYsw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@pkgr/core": "^0.2.4"
|
||||
"@pkgr/core": "^0.1.0",
|
||||
"tslib": "^2.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^14.18.0 || >=16.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://opencollective.com/synckit"
|
||||
"url": "https://opencollective.com/unts"
|
||||
}
|
||||
},
|
||||
"node_modules/tinyglobby": {
|
||||
"version": "0.2.13",
|
||||
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz",
|
||||
"integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==",
|
||||
"version": "0.2.12",
|
||||
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.12.tgz",
|
||||
"integrity": "sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"fdir": "^6.4.4",
|
||||
"fdir": "^6.4.3",
|
||||
"picomatch": "^4.0.2"
|
||||
},
|
||||
"engines": {
|
||||
@ -3826,9 +3842,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/tinyglobby/node_modules/fdir": {
|
||||
"version": "6.4.4",
|
||||
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz",
|
||||
"integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==",
|
||||
"version": "6.4.3",
|
||||
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.3.tgz",
|
||||
"integrity": "sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
@ -3893,6 +3909,14 @@
|
||||
"strip-bom": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/tslib": {
|
||||
"version": "2.8.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
|
||||
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
|
||||
"dev": true,
|
||||
"license": "0BSD",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/type-check": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
|
||||
|
@ -38,20 +38,17 @@ export const AuthentikPrettierConfig = {
|
||||
],
|
||||
importOrder: [
|
||||
// ---
|
||||
|
||||
"^(@goauthentik/|#)common.+",
|
||||
"^(@goauthentik/|#)elements.+",
|
||||
"^(@goauthentik/|#)components.+",
|
||||
"^(@goauthentik/|#)user.+",
|
||||
"^(@goauthentik/|#)admin.+",
|
||||
"^(@goauthentik/|#)flow.+",
|
||||
"^(@goauthentik/|#)flow.+",
|
||||
|
||||
"^#.+",
|
||||
"^@goauthentik.+",
|
||||
|
||||
"<THIRD_PARTY_MODULES>",
|
||||
|
||||
"^~@goauthentik.+",
|
||||
"^@goauthentik.+",
|
||||
"^(@?)lit(.*)$",
|
||||
"\\.css$",
|
||||
"^@goauthentik/api$",
|
||||
|
10
packages/prettier-config/package-lock.json
generated
10
packages/prettier-config/package-lock.json
generated
@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "@goauthentik/prettier-config",
|
||||
"version": "2.0.0",
|
||||
"version": "1.0.4",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@goauthentik/prettier-config",
|
||||
"version": "2.0.0",
|
||||
"version": "1.0.4",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@goauthentik/tsconfig": "^1.0.1",
|
||||
@ -143,9 +143,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@goauthentik/tsconfig": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@goauthentik/tsconfig/-/tsconfig-1.0.4.tgz",
|
||||
"integrity": "sha512-BTGVpGh8SbCRHTULBf+2WTcw6OHJ8Ws9VtVfAMUUgcq8whbH/A7Q/n8WbkDaEeihzHUFkLk3JBenHKzEKAZWlw==",
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@goauthentik/tsconfig/-/tsconfig-1.0.1.tgz",
|
||||
"integrity": "sha512-kxMDkgUHhAmQ2iIhUZJjrx/CgDb1AwvRoPtU4vrjAZu7x66+qczCjRTK+GzIGCeqB97GEpvCCjU8CThmozVFqA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@goauthentik/prettier-config",
|
||||
"version": "2.0.0",
|
||||
"version": "1.1.0",
|
||||
"description": "authentik's Prettier config",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
|
@ -9,7 +9,7 @@ dependencies = [
|
||||
"celery==5.5.2",
|
||||
"channels==4.2.2",
|
||||
"channels-redis==4.2.1",
|
||||
"cryptography==45.0.3",
|
||||
"cryptography==44.0.3",
|
||||
"dacite==1.9.2",
|
||||
"deepmerge==2.0",
|
||||
"defusedxml==0.7.1",
|
||||
@ -23,7 +23,7 @@ dependencies = [
|
||||
"django-prometheus==2.3.1",
|
||||
"django-redis==5.4.0",
|
||||
"django-storages[s3]==1.14.6",
|
||||
"django-tenants==3.8.0",
|
||||
"django-tenants==3.7.0",
|
||||
"djangorestframework==3.16.0",
|
||||
"djangorestframework-guardian==0.3.0",
|
||||
"docker==7.1.0",
|
||||
@ -43,7 +43,7 @@ dependencies = [
|
||||
"kubernetes==32.0.1",
|
||||
"ldap3==2.9.1",
|
||||
"lxml==5.4.0",
|
||||
"msgraph-sdk==1.31.0",
|
||||
"msgraph-sdk==1.30.0",
|
||||
"opencontainers==0.0.14",
|
||||
"packaging==25.0",
|
||||
"paramiko==3.5.1",
|
||||
@ -114,6 +114,7 @@ no-binary-package = [
|
||||
]
|
||||
|
||||
[tool.uv.sources]
|
||||
django-tenants = { git = "https://github.com/goauthentik/django-tenants.git", branch = "authentik-fixes" }
|
||||
opencontainers = { git = "https://github.com/vsoch/oci-python", rev = "ceb4fcc090851717a3069d78e85ceb1e86c2740c" }
|
||||
djangorestframework = { git = "https://github.com/goauthentik/django-rest-framework", rev = "896722bab969fabc74a08b827da59409cf9f1a4e" }
|
||||
|
||||
|
16
schema.yml
16
schema.yml
@ -28473,10 +28473,6 @@ paths:
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
- in: query
|
||||
name: delete_not_found_objects
|
||||
schema:
|
||||
type: boolean
|
||||
- in: query
|
||||
name: enabled
|
||||
schema:
|
||||
@ -47926,10 +47922,6 @@ components:
|
||||
description: 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
|
||||
delete_not_found_objects:
|
||||
type: boolean
|
||||
description: Delete authentik users and groups which were previously supplied
|
||||
by this source, but are now missing from it.
|
||||
required:
|
||||
- base_dn
|
||||
- component
|
||||
@ -48131,10 +48123,6 @@ components:
|
||||
description: 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
|
||||
delete_not_found_objects:
|
||||
type: boolean
|
||||
description: Delete authentik users and groups which were previously supplied
|
||||
by this source, but are now missing from it.
|
||||
required:
|
||||
- base_dn
|
||||
- name
|
||||
@ -53468,10 +53456,6 @@ components:
|
||||
description: 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
|
||||
delete_not_found_objects:
|
||||
type: boolean
|
||||
description: Delete authentik users and groups which were previously supplied
|
||||
by this source, but are now missing from it.
|
||||
PatchedLicenseRequest:
|
||||
type: object
|
||||
description: License Serializer
|
||||
|
@ -1,7 +0,0 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist/esm",
|
||||
},
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"isolatedModules": true,
|
||||
"incremental": true,
|
||||
"baseUrl": ".",
|
||||
"rootDir": "src",
|
||||
"strict": true,
|
||||
"newLine": "lf",
|
||||
"target": "ESNext",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"outDir": "dist",
|
||||
"skipDefaultLibCheck": true,
|
||||
"skipLibCheck": true,
|
||||
"sourceMap": true,
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"lib": ["DOM", "DOM.Iterable", "ESNext"],
|
||||
},
|
||||
"exclude": ["node_modules", "./out/**/*", "./dist/**/*"],
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
#!/bin/bash
|
||||
set -e -x -o pipefail
|
||||
hash="$(git rev-parse HEAD || openssl rand -base64 36 | sha256sum)"
|
||||
|
||||
|
@ -1,13 +1,12 @@
|
||||
services:
|
||||
chrome:
|
||||
platform: linux/x86_64
|
||||
image: docker.io/selenium/standalone-chrome:136.0
|
||||
volumes:
|
||||
- /dev/shm:/dev/shm
|
||||
network_mode: host
|
||||
restart: always
|
||||
mailpit:
|
||||
image: docker.io/axllent/mailpit:v1.25.1
|
||||
image: docker.io/axllent/mailpit:v1.25.0
|
||||
ports:
|
||||
- 1025:1025
|
||||
- 8025:8025
|
||||
|
@ -10,7 +10,6 @@ from authentik.blueprints.tests import apply_blueprint
|
||||
from authentik.core.models import User
|
||||
from authentik.flows.models import Flow
|
||||
from authentik.lib.config import CONFIG
|
||||
from authentik.lib.generators import generate_id
|
||||
from authentik.stages.identification.models import IdentificationStage
|
||||
from tests.e2e.utils import SeleniumTestCase, retry
|
||||
|
||||
@ -18,10 +17,6 @@ from tests.e2e.utils import SeleniumTestCase, retry
|
||||
class TestFlowsEnroll(SeleniumTestCase):
|
||||
"""Test Enroll flow"""
|
||||
|
||||
def setUp(self):
|
||||
super().setUp()
|
||||
self.username = generate_id()
|
||||
|
||||
@retry()
|
||||
@apply_blueprint(
|
||||
"default/flow-default-authentication-flow.yaml",
|
||||
@ -44,8 +39,8 @@ class TestFlowsEnroll(SeleniumTestCase):
|
||||
self.initial_stages()
|
||||
sleep(2)
|
||||
|
||||
user = User.objects.get(username=self.username)
|
||||
self.assertEqual(user.username, self.username)
|
||||
user = User.objects.get(username="foo")
|
||||
self.assertEqual(user.username, "foo")
|
||||
self.assertEqual(user.name, "some name")
|
||||
self.assertEqual(user.email, "foo@bar.baz")
|
||||
|
||||
@ -92,16 +87,7 @@ class TestFlowsEnroll(SeleniumTestCase):
|
||||
|
||||
sleep(2)
|
||||
|
||||
flow_executor = self.get_shadow_root("ak-flow-executor")
|
||||
consent_stage = self.get_shadow_root("ak-stage-consent", flow_executor)
|
||||
consent_stage.find_element(
|
||||
By.CSS_SELECTOR,
|
||||
"[type=submit]",
|
||||
).click()
|
||||
|
||||
self.wait_for_url(self.if_user_url())
|
||||
|
||||
self.assert_user(User.objects.get(username=self.username))
|
||||
self.assert_user(User.objects.get(username="foo"))
|
||||
|
||||
def initial_stages(self):
|
||||
"""Fill out initial stages"""
|
||||
@ -119,7 +105,7 @@ class TestFlowsEnroll(SeleniumTestCase):
|
||||
wait = WebDriverWait(prompt_stage, self.wait_timeout)
|
||||
|
||||
wait.until(ec.presence_of_element_located((By.CSS_SELECTOR, "input[name=username]")))
|
||||
prompt_stage.find_element(By.CSS_SELECTOR, "input[name=username]").send_keys(self.username)
|
||||
prompt_stage.find_element(By.CSS_SELECTOR, "input[name=username]").send_keys("foo")
|
||||
prompt_stage.find_element(By.CSS_SELECTOR, "input[name=password]").send_keys(
|
||||
self.user.username
|
||||
)
|
||||
@ -138,82 +124,3 @@ class TestFlowsEnroll(SeleniumTestCase):
|
||||
prompt_stage.find_element(By.CSS_SELECTOR, "input[name=name]").send_keys("some name")
|
||||
prompt_stage.find_element(By.CSS_SELECTOR, "input[name=email]").send_keys("foo@bar.baz")
|
||||
prompt_stage.find_element(By.CSS_SELECTOR, ".pf-c-button").click()
|
||||
|
||||
@retry()
|
||||
@apply_blueprint(
|
||||
"default/flow-default-authentication-flow.yaml",
|
||||
"default/flow-default-invalidation-flow.yaml",
|
||||
)
|
||||
@apply_blueprint(
|
||||
"example/flows-enrollment-email-verification.yaml",
|
||||
)
|
||||
@CONFIG.patch("email.port", 1025)
|
||||
def test_enroll_email_pretend_email_scanner(self):
|
||||
"""Test enroll with Email verification. Open the email link twice to pretend we have an
|
||||
email scanner that clicks on links"""
|
||||
# Attach enrollment flow to identification stage
|
||||
ident_stage: IdentificationStage = IdentificationStage.objects.get(
|
||||
name="default-authentication-identification"
|
||||
)
|
||||
ident_stage.enrollment_flow = Flow.objects.get(slug="default-enrollment-flow")
|
||||
ident_stage.save()
|
||||
|
||||
self.driver.get(self.live_server_url)
|
||||
self.initial_stages()
|
||||
|
||||
# Email stage
|
||||
flow_executor = self.get_shadow_root("ak-flow-executor")
|
||||
email_stage = self.get_shadow_root("ak-stage-email", flow_executor)
|
||||
|
||||
wait = WebDriverWait(email_stage, self.wait_timeout)
|
||||
|
||||
# Wait for the success message so we know the email is sent
|
||||
wait.until(ec.presence_of_element_located((By.CSS_SELECTOR, ".pf-c-form p")))
|
||||
|
||||
# Open Mailpit
|
||||
self.driver.get("http://localhost:8025")
|
||||
|
||||
# Click on first message
|
||||
self.wait.until(ec.presence_of_element_located((By.CLASS_NAME, "message")))
|
||||
self.driver.find_element(By.CLASS_NAME, "message").click()
|
||||
self.driver.switch_to.frame(self.driver.find_element(By.ID, "preview-html"))
|
||||
confirmation_link = self.driver.find_element(By.ID, "confirm").get_attribute("href")
|
||||
|
||||
main_tab = self.driver.current_window_handle
|
||||
|
||||
self.driver.switch_to.new_window("tab")
|
||||
confirm_tab = self.driver.current_window_handle
|
||||
|
||||
# On the new tab, check that we have the confirmation screen
|
||||
self.driver.get(confirmation_link)
|
||||
self.wait.until(ec.presence_of_element_located((By.CSS_SELECTOR, "ak-flow-executor")))
|
||||
|
||||
flow_executor = self.get_shadow_root("ak-flow-executor")
|
||||
consent_stage = self.get_shadow_root("ak-stage-consent", flow_executor)
|
||||
|
||||
self.assertEqual(
|
||||
"Continue to confirm this email address.",
|
||||
consent_stage.find_element(By.CSS_SELECTOR, "#header-text").text,
|
||||
)
|
||||
|
||||
# Back on the main tab, confirm
|
||||
self.driver.switch_to.window(main_tab)
|
||||
self.driver.get(confirmation_link)
|
||||
|
||||
flow_executor = self.get_shadow_root("ak-flow-executor")
|
||||
consent_stage = self.get_shadow_root("ak-stage-consent", flow_executor)
|
||||
consent_stage.find_element(
|
||||
By.CSS_SELECTOR,
|
||||
"[type=submit]",
|
||||
).click()
|
||||
|
||||
self.wait_for_url(self.if_user_url())
|
||||
sleep(2)
|
||||
|
||||
self.assert_user(User.objects.get(username=self.username))
|
||||
|
||||
self.driver.switch_to.window(confirm_tab)
|
||||
self.driver.refresh()
|
||||
flow_executor = self.get_shadow_root("ak-flow-executor")
|
||||
wait = WebDriverWait(flow_executor, self.wait_timeout)
|
||||
wait.until(ec.presence_of_element_located((By.CSS_SELECTOR, "ak-stage-access-denied")))
|
||||
|
@ -84,14 +84,6 @@ class TestFlowsRecovery(SeleniumTestCase):
|
||||
self.driver.switch_to.window(self.driver.window_handles[0])
|
||||
|
||||
sleep(2)
|
||||
|
||||
flow_executor = self.get_shadow_root("ak-flow-executor")
|
||||
consent_stage = self.get_shadow_root("ak-stage-consent", flow_executor)
|
||||
consent_stage.find_element(
|
||||
By.CSS_SELECTOR,
|
||||
"[type=submit]",
|
||||
).click()
|
||||
|
||||
# We can now enter the new password
|
||||
flow_executor = self.get_shadow_root("ak-flow-executor")
|
||||
prompt_stage = self.get_shadow_root("ak-stage-prompt", flow_executor)
|
||||
|
@ -166,35 +166,30 @@ class SeleniumTestCase(DockerTestCase, StaticLiveServerTestCase):
|
||||
print("::group::authentik Logs", file=stderr)
|
||||
apps.get_app_config("authentik_tenants").ready()
|
||||
self.wait_timeout = 60
|
||||
self.logger = get_logger()
|
||||
self.driver = self._get_driver()
|
||||
self.driver.implicitly_wait(30)
|
||||
self.wait = WebDriverWait(self.driver, self.wait_timeout)
|
||||
self.logger = get_logger()
|
||||
self.user = create_test_admin_user()
|
||||
super().setUp()
|
||||
|
||||
def _get_driver(self) -> WebDriver:
|
||||
count = 0
|
||||
opts = webdriver.ChromeOptions()
|
||||
opts.add_argument("--disable-search-engine-choice-screen")
|
||||
# This breaks selenium when running remotely...?
|
||||
# opts.set_capability("goog:loggingPrefs", {"browser": "ALL"})
|
||||
opts.add_experimental_option(
|
||||
"prefs",
|
||||
{
|
||||
"profile.password_manager_leak_detection": False,
|
||||
},
|
||||
)
|
||||
try:
|
||||
opts = webdriver.ChromeOptions()
|
||||
opts.add_argument("--disable-search-engine-choice-screen")
|
||||
return webdriver.Chrome(options=opts)
|
||||
except WebDriverException:
|
||||
pass
|
||||
while count < RETRIES:
|
||||
try:
|
||||
driver = webdriver.Remote(
|
||||
command_executor="http://localhost:4444/wd/hub",
|
||||
options=opts,
|
||||
options=webdriver.ChromeOptions(),
|
||||
)
|
||||
driver.maximize_window()
|
||||
return driver
|
||||
except WebDriverException as exc:
|
||||
self.logger.warning("Failed to setup webdriver", exc=exc)
|
||||
except WebDriverException:
|
||||
count += 1
|
||||
raise ValueError(f"Webdriver failed after {RETRIES}.")
|
||||
|
||||
|
75
uv.lock
generated
75
uv.lock
generated
@ -269,7 +269,7 @@ requires-dist = [
|
||||
{ name = "celery", specifier = "==5.5.2" },
|
||||
{ name = "channels", specifier = "==4.2.2" },
|
||||
{ name = "channels-redis", specifier = "==4.2.1" },
|
||||
{ name = "cryptography", specifier = "==45.0.3" },
|
||||
{ name = "cryptography", specifier = "==44.0.3" },
|
||||
{ name = "dacite", specifier = "==1.9.2" },
|
||||
{ name = "deepmerge", specifier = "==2.0" },
|
||||
{ name = "defusedxml", specifier = "==0.7.1" },
|
||||
@ -283,7 +283,7 @@ requires-dist = [
|
||||
{ name = "django-prometheus", specifier = "==2.3.1" },
|
||||
{ name = "django-redis", specifier = "==5.4.0" },
|
||||
{ name = "django-storages", extras = ["s3"], specifier = "==1.14.6" },
|
||||
{ name = "django-tenants", specifier = "==3.8.0" },
|
||||
{ name = "django-tenants", git = "https://github.com/goauthentik/django-tenants.git?branch=authentik-fixes" },
|
||||
{ name = "djangorestframework", git = "https://github.com/goauthentik/django-rest-framework?rev=896722bab969fabc74a08b827da59409cf9f1a4e" },
|
||||
{ name = "djangorestframework-guardian", specifier = "==0.3.0" },
|
||||
{ name = "docker", specifier = "==7.1.0" },
|
||||
@ -303,7 +303,7 @@ requires-dist = [
|
||||
{ name = "kubernetes", specifier = "==32.0.1" },
|
||||
{ name = "ldap3", specifier = "==2.9.1" },
|
||||
{ name = "lxml", specifier = "==5.4.0" },
|
||||
{ name = "msgraph-sdk", specifier = "==1.31.0" },
|
||||
{ name = "msgraph-sdk", specifier = "==1.30.0" },
|
||||
{ name = "opencontainers", git = "https://github.com/vsoch/oci-python?rev=ceb4fcc090851717a3069d78e85ceb1e86c2740c" },
|
||||
{ name = "packaging", specifier = "==25.0" },
|
||||
{ name = "paramiko", specifier = "==3.5.1" },
|
||||
@ -869,37 +869,37 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "cryptography"
|
||||
version = "45.0.3"
|
||||
version = "44.0.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "cffi", marker = "platform_python_implementation != 'PyPy'" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/13/1f/9fa001e74a1993a9cadd2333bb889e50c66327b8594ac538ab8a04f915b7/cryptography-45.0.3.tar.gz", hash = "sha256:ec21313dd335c51d7877baf2972569f40a4291b76a0ce51391523ae358d05899", size = 744738, upload-time = "2025-05-25T14:17:24.777Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/53/d6/1411ab4d6108ab167d06254c5be517681f1e331f90edf1379895bcb87020/cryptography-44.0.3.tar.gz", hash = "sha256:fe19d8bc5536a91a24a8133328880a41831b6c5df54599a8417b62fe015d3053", size = 711096, upload-time = "2025-05-02T19:36:04.667Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/82/b2/2345dc595998caa6f68adf84e8f8b50d18e9fc4638d32b22ea8daedd4b7a/cryptography-45.0.3-cp311-abi3-macosx_10_9_universal2.whl", hash = "sha256:7573d9eebaeceeb55285205dbbb8753ac1e962af3d9640791d12b36864065e71", size = 7056239, upload-time = "2025-05-25T14:16:12.22Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/71/3d/ac361649a0bfffc105e2298b720d8b862330a767dab27c06adc2ddbef96a/cryptography-45.0.3-cp311-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d377dde61c5d67eb4311eace661c3efda46c62113ff56bf05e2d679e02aebb5b", size = 4205541, upload-time = "2025-05-25T14:16:14.333Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/70/3e/c02a043750494d5c445f769e9c9f67e550d65060e0bfce52d91c1362693d/cryptography-45.0.3-cp311-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fae1e637f527750811588e4582988932c222f8251f7b7ea93739acb624e1487f", size = 4433275, upload-time = "2025-05-25T14:16:16.421Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/40/7a/9af0bfd48784e80eef3eb6fd6fde96fe706b4fc156751ce1b2b965dada70/cryptography-45.0.3-cp311-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:ca932e11218bcc9ef812aa497cdf669484870ecbcf2d99b765d6c27a86000942", size = 4209173, upload-time = "2025-05-25T14:16:18.163Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/31/5f/d6f8753c8708912df52e67969e80ef70b8e8897306cd9eb8b98201f8c184/cryptography-45.0.3-cp311-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:af3f92b1dc25621f5fad065288a44ac790c5798e986a34d393ab27d2b27fcff9", size = 3898150, upload-time = "2025-05-25T14:16:20.34Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/8b/50/f256ab79c671fb066e47336706dc398c3b1e125f952e07d54ce82cf4011a/cryptography-45.0.3-cp311-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:2f8f8f0b73b885ddd7f3d8c2b2234a7d3ba49002b0223f58cfde1bedd9563c56", size = 4466473, upload-time = "2025-05-25T14:16:22.605Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/62/e7/312428336bb2df0848d0768ab5a062e11a32d18139447a76dfc19ada8eed/cryptography-45.0.3-cp311-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:9cc80ce69032ffa528b5e16d217fa4d8d4bb7d6ba8659c1b4d74a1b0f4235fca", size = 4211890, upload-time = "2025-05-25T14:16:24.738Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/e7/53/8a130e22c1e432b3c14896ec5eb7ac01fb53c6737e1d705df7e0efb647c6/cryptography-45.0.3-cp311-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:c824c9281cb628015bfc3c59335163d4ca0540d49de4582d6c2637312907e4b1", size = 4466300, upload-time = "2025-05-25T14:16:26.768Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ba/75/6bb6579688ef805fd16a053005fce93944cdade465fc92ef32bbc5c40681/cryptography-45.0.3-cp311-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:5833bb4355cb377ebd880457663a972cd044e7f49585aee39245c0d592904578", size = 4332483, upload-time = "2025-05-25T14:16:28.316Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/2f/11/2538f4e1ce05c6c4f81f43c1ef2bd6de7ae5e24ee284460ff6c77e42ca77/cryptography-45.0.3-cp311-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:9bb5bf55dcb69f7067d80354d0a348368da907345a2c448b0babc4215ccd3497", size = 4573714, upload-time = "2025-05-25T14:16:30.474Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f5/bb/e86e9cf07f73a98d84a4084e8fd420b0e82330a901d9cac8149f994c3417/cryptography-45.0.3-cp311-abi3-win32.whl", hash = "sha256:3ad69eeb92a9de9421e1f6685e85a10fbcfb75c833b42cc9bc2ba9fb00da4710", size = 2934752, upload-time = "2025-05-25T14:16:32.204Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c7/75/063bc9ddc3d1c73e959054f1fc091b79572e716ef74d6caaa56e945b4af9/cryptography-45.0.3-cp311-abi3-win_amd64.whl", hash = "sha256:97787952246a77d77934d41b62fb1b6f3581d83f71b44796a4158d93b8f5c490", size = 3412465, upload-time = "2025-05-25T14:16:33.888Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/71/9b/04ead6015229a9396890d7654ee35ef630860fb42dc9ff9ec27f72157952/cryptography-45.0.3-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:c92519d242703b675ccefd0f0562eb45e74d438e001f8ab52d628e885751fb06", size = 7031892, upload-time = "2025-05-25T14:16:36.214Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/46/c7/c7d05d0e133a09fc677b8a87953815c522697bdf025e5cac13ba419e7240/cryptography-45.0.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5edcb90da1843df85292ef3a313513766a78fbbb83f584a5a58fb001a5a9d57", size = 4196181, upload-time = "2025-05-25T14:16:37.934Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/08/7a/6ad3aa796b18a683657cef930a986fac0045417e2dc428fd336cfc45ba52/cryptography-45.0.3-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:38deed72285c7ed699864f964a3f4cf11ab3fb38e8d39cfcd96710cd2b5bb716", size = 4423370, upload-time = "2025-05-25T14:16:39.502Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/4f/58/ec1461bfcb393525f597ac6a10a63938d18775b7803324072974b41a926b/cryptography-45.0.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:5555365a50efe1f486eed6ac7062c33b97ccef409f5970a0b6f205a7cfab59c8", size = 4197839, upload-time = "2025-05-25T14:16:41.322Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d4/3d/5185b117c32ad4f40846f579369a80e710d6146c2baa8ce09d01612750db/cryptography-45.0.3-cp37-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:9e4253ed8f5948a3589b3caee7ad9a5bf218ffd16869c516535325fece163dcc", size = 3886324, upload-time = "2025-05-25T14:16:43.041Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/67/85/caba91a57d291a2ad46e74016d1f83ac294f08128b26e2a81e9b4f2d2555/cryptography-45.0.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:cfd84777b4b6684955ce86156cfb5e08d75e80dc2585e10d69e47f014f0a5342", size = 4450447, upload-time = "2025-05-25T14:16:44.759Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ae/d1/164e3c9d559133a38279215c712b8ba38e77735d3412f37711b9f8f6f7e0/cryptography-45.0.3-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:a2b56de3417fd5f48773ad8e91abaa700b678dc7fe1e0c757e1ae340779acf7b", size = 4200576, upload-time = "2025-05-25T14:16:46.438Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/71/7a/e002d5ce624ed46dfc32abe1deff32190f3ac47ede911789ee936f5a4255/cryptography-45.0.3-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:57a6500d459e8035e813bd8b51b671977fb149a8c95ed814989da682314d0782", size = 4450308, upload-time = "2025-05-25T14:16:48.228Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/87/ad/3fbff9c28cf09b0a71e98af57d74f3662dea4a174b12acc493de00ea3f28/cryptography-45.0.3-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:f22af3c78abfbc7cbcdf2c55d23c3e022e1a462ee2481011d518c7fb9c9f3d65", size = 4325125, upload-time = "2025-05-25T14:16:49.844Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f5/b4/51417d0cc01802304c1984d76e9592f15e4801abd44ef7ba657060520bf0/cryptography-45.0.3-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:232954730c362638544758a8160c4ee1b832dc011d2c41a306ad8f7cccc5bb0b", size = 4560038, upload-time = "2025-05-25T14:16:51.398Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/80/38/d572f6482d45789a7202fb87d052deb7a7b136bf17473ebff33536727a2c/cryptography-45.0.3-cp37-abi3-win32.whl", hash = "sha256:cb6ab89421bc90e0422aca911c69044c2912fc3debb19bb3c1bfe28ee3dff6ab", size = 2924070, upload-time = "2025-05-25T14:16:53.472Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/91/5a/61f39c0ff4443651cc64e626fa97ad3099249152039952be8f344d6b0c86/cryptography-45.0.3-cp37-abi3-win_amd64.whl", hash = "sha256:d54ae41e6bd70ea23707843021c778f151ca258081586f0cfa31d936ae43d1b2", size = 3395005, upload-time = "2025-05-25T14:16:55.134Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/08/53/c776d80e9d26441bb3868457909b4e74dd9ccabd182e10b2b0ae7a07e265/cryptography-44.0.3-cp37-abi3-macosx_10_9_universal2.whl", hash = "sha256:962bc30480a08d133e631e8dfd4783ab71cc9e33d5d7c1e192f0b7c06397bb88", size = 6670281, upload-time = "2025-05-02T19:34:50.665Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/6a/06/af2cf8d56ef87c77319e9086601bef621bedf40f6f59069e1b6d1ec498c5/cryptography-44.0.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ffc61e8f3bf5b60346d89cd3d37231019c17a081208dfbbd6e1605ba03fa137", size = 3959305, upload-time = "2025-05-02T19:34:53.042Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ae/01/80de3bec64627207d030f47bf3536889efee8913cd363e78ca9a09b13c8e/cryptography-44.0.3-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58968d331425a6f9eedcee087f77fd3c927c88f55368f43ff7e0a19891f2642c", size = 4171040, upload-time = "2025-05-02T19:34:54.675Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/bd/48/bb16b7541d207a19d9ae8b541c70037a05e473ddc72ccb1386524d4f023c/cryptography-44.0.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:e28d62e59a4dbd1d22e747f57d4f00c459af22181f0b2f787ea83f5a876d7c76", size = 3963411, upload-time = "2025-05-02T19:34:56.61Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/42/b2/7d31f2af5591d217d71d37d044ef5412945a8a8e98d5a2a8ae4fd9cd4489/cryptography-44.0.3-cp37-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:af653022a0c25ef2e3ffb2c673a50e5a0d02fecc41608f4954176f1933b12359", size = 3689263, upload-time = "2025-05-02T19:34:58.591Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/25/50/c0dfb9d87ae88ccc01aad8eb93e23cfbcea6a6a106a9b63a7b14c1f93c75/cryptography-44.0.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:157f1f3b8d941c2bd8f3ffee0af9b049c9665c39d3da9db2dc338feca5e98a43", size = 4196198, upload-time = "2025-05-02T19:35:00.988Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/66/c9/55c6b8794a74da652690c898cb43906310a3e4e4f6ee0b5f8b3b3e70c441/cryptography-44.0.3-cp37-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:c6cd67722619e4d55fdb42ead64ed8843d64638e9c07f4011163e46bc512cf01", size = 3966502, upload-time = "2025-05-02T19:35:03.091Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b6/f7/7cb5488c682ca59a02a32ec5f975074084db4c983f849d47b7b67cc8697a/cryptography-44.0.3-cp37-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:b424563394c369a804ecbee9b06dfb34997f19d00b3518e39f83a5642618397d", size = 4196173, upload-time = "2025-05-02T19:35:05.018Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/d2/0b/2f789a8403ae089b0b121f8f54f4a3e5228df756e2146efdf4a09a3d5083/cryptography-44.0.3-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c91fc8e8fd78af553f98bc7f2a1d8db977334e4eea302a4bfd75b9461c2d8904", size = 4087713, upload-time = "2025-05-02T19:35:07.187Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1d/aa/330c13655f1af398fc154089295cf259252f0ba5df93b4bc9d9c7d7f843e/cryptography-44.0.3-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:25cd194c39fa5a0aa4169125ee27d1172097857b27109a45fadc59653ec06f44", size = 4299064, upload-time = "2025-05-02T19:35:08.879Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/10/a8/8c540a421b44fd267a7d58a1fd5f072a552d72204a3f08194f98889de76d/cryptography-44.0.3-cp37-abi3-win32.whl", hash = "sha256:3be3f649d91cb182c3a6bd336de8b61a0a71965bd13d1a04a0e15b39c3d5809d", size = 2773887, upload-time = "2025-05-02T19:35:10.41Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b9/0d/c4b1657c39ead18d76bbd122da86bd95bdc4095413460d09544000a17d56/cryptography-44.0.3-cp37-abi3-win_amd64.whl", hash = "sha256:3883076d5c4cc56dbef0b898a74eb6992fdac29a7b9013870b34efe4ddb39a0d", size = 3209737, upload-time = "2025-05-02T19:35:12.12Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/34/a3/ad08e0bcc34ad436013458d7528e83ac29910943cea42ad7dd4141a27bbb/cryptography-44.0.3-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:5639c2b16764c6f76eedf722dbad9a0914960d3489c0cc38694ddf9464f1bb2f", size = 6673501, upload-time = "2025-05-02T19:35:13.775Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/b1/f0/7491d44bba8d28b464a5bc8cc709f25a51e3eac54c0a4444cf2473a57c37/cryptography-44.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3ffef566ac88f75967d7abd852ed5f182da252d23fac11b4766da3957766759", size = 3960307, upload-time = "2025-05-02T19:35:15.917Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/f7/c8/e5c5d0e1364d3346a5747cdcd7ecbb23ca87e6dea4f942a44e88be349f06/cryptography-44.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:192ed30fac1728f7587c6f4613c29c584abdc565d7417c13904708db10206645", size = 4170876, upload-time = "2025-05-02T19:35:18.138Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/73/96/025cb26fc351d8c7d3a1c44e20cf9a01e9f7cf740353c9c7a17072e4b264/cryptography-44.0.3-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:7d5fe7195c27c32a64955740b949070f21cba664604291c298518d2e255931d2", size = 3964127, upload-time = "2025-05-02T19:35:19.864Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/01/44/eb6522db7d9f84e8833ba3bf63313f8e257729cf3a8917379473fcfd6601/cryptography-44.0.3-cp39-abi3-manylinux_2_28_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:3f07943aa4d7dad689e3bb1638ddc4944cc5e0921e3c227486daae0e31a05e54", size = 3689164, upload-time = "2025-05-02T19:35:21.449Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/68/fb/d61a4defd0d6cee20b1b8a1ea8f5e25007e26aeb413ca53835f0cae2bcd1/cryptography-44.0.3-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:cb90f60e03d563ca2445099edf605c16ed1d5b15182d21831f58460c48bffb93", size = 4198081, upload-time = "2025-05-02T19:35:23.187Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/1b/50/457f6911d36432a8811c3ab8bd5a6090e8d18ce655c22820994913dd06ea/cryptography-44.0.3-cp39-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:ab0b005721cc0039e885ac3503825661bd9810b15d4f374e473f8c89b7d5460c", size = 3967716, upload-time = "2025-05-02T19:35:25.426Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/35/6e/dca39d553075980ccb631955c47b93d87d27f3596da8d48b1ae81463d915/cryptography-44.0.3-cp39-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:3bb0847e6363c037df8f6ede57d88eaf3410ca2267fb12275370a76f85786a6f", size = 4197398, upload-time = "2025-05-02T19:35:27.678Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/9b/9d/d1f2fe681eabc682067c66a74addd46c887ebacf39038ba01f8860338d3d/cryptography-44.0.3-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:b0cc66c74c797e1db750aaa842ad5b8b78e14805a9b5d1348dc603612d3e3ff5", size = 4087900, upload-time = "2025-05-02T19:35:29.312Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c4/f5/3599e48c5464580b73b236aafb20973b953cd2e7b44c7c2533de1d888446/cryptography-44.0.3-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:6866df152b581f9429020320e5eb9794c8780e90f7ccb021940d7f50ee00ae0b", size = 4301067, upload-time = "2025-05-02T19:35:31.547Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/a7/6c/d2c48c8137eb39d0c193274db5c04a75dab20d2f7c3f81a7dcc3a8897701/cryptography-44.0.3-cp39-abi3-win32.whl", hash = "sha256:c138abae3a12a94c75c10499f1cbae81294a6f983b3af066390adee73f433028", size = 2775467, upload-time = "2025-05-02T19:35:33.805Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/c9/ad/51f212198681ea7b0deaaf8846ee10af99fba4e894f67b353524eab2bbe5/cryptography-44.0.3-cp39-abi3-win_amd64.whl", hash = "sha256:5d186f32e52e66994dce4f766884bcb9c68b8da62d61d9d215bfe5fb56d21334", size = 3210375, upload-time = "2025-05-02T19:35:35.369Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1118,12 +1118,11 @@ s3 = [
|
||||
|
||||
[[package]]
|
||||
name = "django-tenants"
|
||||
version = "3.8.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
version = "3.7.0"
|
||||
source = { git = "https://github.com/goauthentik/django-tenants.git?branch=authentik-fixes#156e53a6f5902d74b73dd9d0192fffaa2587a740" }
|
||||
dependencies = [
|
||||
{ name = "django" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/a8/7b/22e3bb79d48e5a4fdcacdcdc27bbc5c2523a2b7892b440bfe229f313d823/django_tenants-3.8.0.tar.gz", hash = "sha256:07d009d5d01be2d65c3f5ddbf323d58d1228838fc1a64fded15c8e5c6f41cf8f", size = 154307, upload-time = "2025-05-23T16:07:24.307Z" }
|
||||
|
||||
[[package]]
|
||||
name = "djangorestframework"
|
||||
@ -2066,7 +2065,7 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "msgraph-sdk"
|
||||
version = "1.31.0"
|
||||
version = "1.30.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "azure-identity" },
|
||||
@ -2076,9 +2075,9 @@ dependencies = [
|
||||
{ name = "microsoft-kiota-serialization-text" },
|
||||
{ name = "msgraph-core" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/d3/1c/5afdf21f92840c7029f0fdb6c2ead7373b1fcdc3c4279fe556a2fc3702a2/msgraph_sdk-1.31.0.tar.gz", hash = "sha256:7ae5f29152251f61c1fc19cca6389dd03b0120b179ddf39d8ab8cdfed7952dba", size = 6626610, upload-time = "2025-05-20T13:15:08.062Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/e9/4a/4ff19671f6ea06f98fb2405f73a90350e4719ccc692e85e9e0c2fa066826/msgraph_sdk-1.30.0.tar.gz", hash = "sha256:59e30af6d7244c9009146d620c331e169701b651317746b16f561e2e2452e73f", size = 6608744, upload-time = "2025-05-13T13:09:12.594Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/d9/b9/099b28478575126ec26bd61ff0931fb291263ac813afb8baf4b4cc30c6fc/msgraph_sdk-1.31.0-py3-none-any.whl", hash = "sha256:bb2edfe17c377f37bbf2e155fc915171763d49e1cf93b665bafd721a85220dc5", size = 27185846, upload-time = "2025-05-20T13:15:05.307Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/70/95/451ec4db8a924274a1f7260809ea03fe9c2b446d84dc5238e92e49a1b522/msgraph_sdk-1.30.0-py3-none-any.whl", hash = "sha256:6748f5cdb5ddbcff9e4f3fb073dd0a604cb00e1cf285dd0fea6969c93ba8282f", size = 27140767, upload-time = "2025-05-13T13:09:07.718Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2577,14 +2576,14 @@ wheels = [
|
||||
|
||||
[[package]]
|
||||
name = "pyopenssl"
|
||||
version = "25.1.0"
|
||||
version = "25.0.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "cryptography" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/04/8c/cd89ad05804f8e3c17dea8f178c3f40eeab5694c30e0c9f5bcd49f576fc3/pyopenssl-25.1.0.tar.gz", hash = "sha256:8d031884482e0c67ee92bf9a4d8cceb08d92aba7136432ffb0703c5280fc205b", size = 179937, upload-time = "2025-05-17T16:28:31.31Z" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/9f/26/e25b4a374b4639e0c235527bbe31c0524f26eda701d79456a7e1877f4cc5/pyopenssl-25.0.0.tar.gz", hash = "sha256:cd2cef799efa3936bb08e8ccb9433a575722b9dd986023f1cabc4ae64e9dac16", size = 179573, upload-time = "2025-01-12T17:22:48.897Z" }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/80/28/2659c02301b9500751f8d42f9a6632e1508aa5120de5e43042b8b30f8d5d/pyopenssl-25.1.0-py3-none-any.whl", hash = "sha256:2b11f239acc47ac2e5aca04fd7fa829800aeee22a2eb30d744572a157bd8a1ab", size = 56771, upload-time = "2025-05-17T16:28:29.197Z" },
|
||||
{ url = "https://files.pythonhosted.org/packages/ca/d7/eb76863d2060dcbe7c7e6cccfd95ac02ea0b9acc37745a0d99ff6457aefb/pyOpenSSL-25.0.0-py3-none-any.whl", hash = "sha256:424c247065e46e76a37411b9ab1782541c23bb658bf003772c3405fbaa128e90", size = 56453, upload-time = "2025-01-12T17:22:43.44Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3,10 +3,11 @@
|
||||
*
|
||||
* @import { ThemeVarsPartial } from "storybook/internal/theming";
|
||||
*/
|
||||
import { createUIThemeEffect, resolveUITheme } from "@goauthentik/web/common/theme.ts";
|
||||
import { addons } from "@storybook/manager-api";
|
||||
import { create } from "@storybook/theming/create";
|
||||
|
||||
import { createUIThemeEffect, resolveUITheme } from "@goauthentik/web/common/theme.ts";
|
||||
|
||||
/**
|
||||
* @satisfies {Partial<ThemeVarsPartial>}
|
||||
*/
|
||||
|
@ -4,27 +4,30 @@
|
||||
* @import {
|
||||
* OnLoadArgs,
|
||||
* OnLoadResult,
|
||||
* OnResolveArgs,
|
||||
* OnResolveResult,
|
||||
* Plugin,
|
||||
* PluginBuild
|
||||
* } from "esbuild"
|
||||
*/
|
||||
import { MonoRepoRoot } from "@goauthentik/core/paths/node";
|
||||
import * as fs from "node:fs/promises";
|
||||
import * as path from "node:path";
|
||||
|
||||
/**
|
||||
* @typedef {Omit<OnLoadArgs, 'pluginData'> & LoadDataFields} LoadData Data passed to `onload`.
|
||||
* @typedef {Omit<OnLoadArgs, 'pluginData'> & LoadDataFields} LoadData
|
||||
* Data passed to `onload`.
|
||||
*
|
||||
* @typedef LoadDataFields Extra fields given in `data` to `onload`.
|
||||
* @property {PluginData | null | undefined} [pluginData] Plugin data.
|
||||
* @typedef LoadDataFields
|
||||
* Extra fields given in `data` to `onload`.
|
||||
* @property {PluginData | null | undefined} [pluginData]
|
||||
* Plugin data.
|
||||
*
|
||||
* @typedef PluginData Extra data passed.
|
||||
* @property {Buffer | string | null | undefined} [contents] File contents.
|
||||
*
|
||||
* @typedef PluginData
|
||||
* Extra data passed.
|
||||
* @property {Buffer | string | null | undefined} [contents]
|
||||
* File contents.
|
||||
*/
|
||||
|
||||
const pluginName = "mdx-plugin";
|
||||
const name = "mdx-plugin";
|
||||
|
||||
/**
|
||||
* @typedef MDXPluginOptions
|
||||
@ -35,35 +38,28 @@ const pluginName = "mdx-plugin";
|
||||
/**
|
||||
* Bundle MDX into JSON modules.
|
||||
*
|
||||
* @param {MDXPluginOptions} options
|
||||
* @returns {Plugin}
|
||||
* @param {MDXPluginOptions} options Options.
|
||||
* @returns {Plugin} Plugin.
|
||||
*/
|
||||
export function mdxPlugin({ root }) {
|
||||
// TODO: Replace with `resolvePackage` after NPM Workspaces support is added.
|
||||
const docsPackageRoot = path.resolve(MonoRepoRoot, "website");
|
||||
return { name, setup };
|
||||
|
||||
/**
|
||||
* @param {PluginBuild} build
|
||||
* Build.
|
||||
* @returns {undefined}
|
||||
* Nothing.
|
||||
*/
|
||||
function setup(build) {
|
||||
/**
|
||||
* @param {OnResolveArgs} args
|
||||
* @returns {Promise<OnResolveResult>}
|
||||
*/
|
||||
async function resolveListener(args) {
|
||||
if (!args.path.startsWith("~")) return args;
|
||||
|
||||
return {
|
||||
path: path.resolve(docsPackageRoot, args.path.slice(1)),
|
||||
pluginName,
|
||||
};
|
||||
}
|
||||
build.onLoad({ filter: /\.mdx?$/ }, onload);
|
||||
|
||||
/**
|
||||
* @param {LoadData} data
|
||||
* Data.
|
||||
* @returns {Promise<OnLoadResult>}
|
||||
* Result.
|
||||
*/
|
||||
async function loadListener(data) {
|
||||
async function onload(data) {
|
||||
const content = String(
|
||||
data.pluginData &&
|
||||
data.pluginData.contents !== null &&
|
||||
@ -81,16 +77,7 @@ export function mdxPlugin({ root }) {
|
||||
return {
|
||||
contents: JSON.stringify({ content, publicPath, publicDirectory }),
|
||||
loader: "file",
|
||||
pluginName,
|
||||
};
|
||||
}
|
||||
|
||||
build.onResolve({ filter: /\.mdx?$/ }, resolveListener);
|
||||
build.onLoad({ filter: /\.mdx?$/ }, loadListener);
|
||||
}
|
||||
|
||||
return {
|
||||
name: pluginName,
|
||||
setup,
|
||||
};
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { createESLintPackageConfig } from "@goauthentik/eslint-config";
|
||||
import tseslint from "typescript-eslint";
|
||||
|
||||
import { createESLintPackageConfig } from "@goauthentik/eslint-config";
|
||||
|
||||
// @ts-check
|
||||
|
||||
/**
|
||||
|
2518
web/package-lock.json
generated
2518
web/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -91,9 +91,9 @@
|
||||
"@codemirror/legacy-modes": "^6.4.1",
|
||||
"@codemirror/theme-one-dark": "^6.1.2",
|
||||
"@floating-ui/dom": "^1.6.11",
|
||||
"@formatjs/intl-listformat": "^7.7.11",
|
||||
"@formatjs/intl-listformat": "^7.5.7",
|
||||
"@fortawesome/fontawesome-free": "^6.6.0",
|
||||
"@goauthentik/api": "^2025.4.1-1748431399",
|
||||
"@goauthentik/api": "^2025.4.1-1747687715",
|
||||
"@lit/context": "^1.1.2",
|
||||
"@lit/localize": "^0.12.2",
|
||||
"@lit/reactive-element": "^2.0.4",
|
||||
@ -111,12 +111,12 @@
|
||||
"chartjs-adapter-date-fns": "^3.0.0",
|
||||
"codemirror": "^6.0.1",
|
||||
"construct-style-sheets-polyfill": "^3.1.0",
|
||||
"core-js": "^3.42.0",
|
||||
"core-js": "^3.38.1",
|
||||
"country-flag-icons": "^1.5.19",
|
||||
"date-fns": "^4.1.0",
|
||||
"deepmerge-ts": "^7.1.5",
|
||||
"dompurify": "^3.2.6",
|
||||
"fuse.js": "^7.1.0",
|
||||
"fuse.js": "^7.0.0",
|
||||
"guacamole-common-js": "^1.5.0",
|
||||
"hastscript": "^9.0.1",
|
||||
"lit": "^3.2.0",
|
||||
@ -144,15 +144,14 @@
|
||||
"@eslint/js": "^9.27.0",
|
||||
"@goauthentik/core": "^1.0.0",
|
||||
"@goauthentik/esbuild-plugin-live-reload": "^1.0.4",
|
||||
"@goauthentik/eslint-config": "^1.0.5",
|
||||
"@goauthentik/prettier-config": "^1.0.5",
|
||||
"@goauthentik/eslint-config": "^1.0.4",
|
||||
"@goauthentik/prettier-config": "^1.0.4",
|
||||
"@goauthentik/tsconfig": "^1.0.4",
|
||||
"@hcaptcha/types": "^1.0.4",
|
||||
"@lit/localize-tools": "^0.8.0",
|
||||
"@storybook/addon-essentials": "^8.6.14",
|
||||
"@storybook/addon-links": "^8.6.14",
|
||||
"@storybook/blocks": "^8.6.12",
|
||||
"@storybook/channels": "^8.6.14",
|
||||
"@storybook/experimental-addon-test": "^8.6.14",
|
||||
"@storybook/manager-api": "^8.6.14",
|
||||
"@storybook/test": "^8.6.14",
|
||||
@ -184,7 +183,7 @@
|
||||
"eslint-plugin-wc": "^3.0.1",
|
||||
"github-slugger": "^2.0.0",
|
||||
"globals": "^15.10.0",
|
||||
"knip": "^5.58.0",
|
||||
"knip": "^5.30.6",
|
||||
"lit-analyzer": "^2.0.3",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"prettier": "^3.3.3",
|
||||
@ -203,9 +202,9 @@
|
||||
"@esbuild/darwin-arm64": "^0.25.4",
|
||||
"@esbuild/linux-arm64": "^0.25.4",
|
||||
"@esbuild/linux-x64": "^0.25.4",
|
||||
"@rollup/rollup-darwin-arm64": "^4.41.1",
|
||||
"@rollup/rollup-linux-arm64-gnu": "^4.41.1",
|
||||
"@rollup/rollup-linux-x64-gnu": "^4.41.1"
|
||||
"@rollup/rollup-darwin-arm64": "^4.41.0",
|
||||
"@rollup/rollup-linux-arm64-gnu": "^4.41.0",
|
||||
"@rollup/rollup-linux-x64-gnu": "^4.41.0"
|
||||
},
|
||||
"wireit": {
|
||||
"build": {
|
||||
@ -364,7 +363,6 @@
|
||||
"workspaces": [
|
||||
"./packages/*"
|
||||
],
|
||||
"prettier": "@goauthentik/prettier-config",
|
||||
"overrides": {
|
||||
"@storybook/addon-docs": {
|
||||
"react": "^19.1.0",
|
||||
|
@ -45,7 +45,7 @@
|
||||
}
|
||||
},
|
||||
"devDependencies": {
|
||||
"@goauthentik/prettier-config": "^1.0.5",
|
||||
"@goauthentik/prettier-config": "^1.0.4",
|
||||
"@goauthentik/tsconfig": "^1.0.4",
|
||||
"@types/node": "^22.15.21",
|
||||
"prettier": "^3.3.3",
|
||||
|
@ -1,59 +0,0 @@
|
||||
_An ESBuild development plugin that watches for file changes and triggers automatic browser refreshes._
|
||||
|
||||
## Quick start
|
||||
|
||||
```sh
|
||||
npm install -D @goauthentik/esbuild-plugin-live-reload
|
||||
# Or with Yarn:
|
||||
yarn add -D @goauthentik/esbuild-plugin-live-reload
|
||||
```
|
||||
|
||||
### 1. Configure ESBuild
|
||||
|
||||
```js
|
||||
import { liveReloadPlugin } from "@goauthentik/esbuild-plugin-live-reload";
|
||||
import esbuild from "esbuild";
|
||||
|
||||
const NodeEnvironment = process.env.NODE_ENV || "development";
|
||||
|
||||
/**
|
||||
* @type {esbuild.BuildOptions}
|
||||
*/
|
||||
const buildOptions = {
|
||||
// ... Your build options.
|
||||
define: {
|
||||
"process.env.NODE_ENV": JSON.stringify(NodeEnvironment),
|
||||
},
|
||||
plugins: [
|
||||
/** @see {@link LiveReloadPluginOptions} */
|
||||
liveReloadPlugin(),
|
||||
],
|
||||
};
|
||||
|
||||
const buildContext = await esbuild.context(buildOptions);
|
||||
|
||||
await buildContext.rebuild();
|
||||
await buildContext.watch();
|
||||
```
|
||||
|
||||
### 2. Connect your browser
|
||||
|
||||
Add the following import near the beginning of your application's entry point.
|
||||
|
||||
```js
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
await import("@goauthentik/esbuild-plugin-live-reload/client");
|
||||
}
|
||||
```
|
||||
|
||||
That's it! Your browser will now automatically refresh whenever ESBuild finishes rebuilding your code.
|
||||
|
||||
## About authentik
|
||||
|
||||
[authentik](https://goauthentik.io) is an open source Identity Provider that unifies your identity needs into a single platform, replacing Okta, Active Directory, and Auth0.
|
||||
|
||||
We built this plugin to streamline our development workflow, and we're sharing it with the community. If you have any questions, feature requests, or bug reports, please [open an issue](https://github.com/goauthentik/authentik/issues/new/choose).
|
||||
|
||||
## License
|
||||
|
||||
This code is licensed under the [MIT License](https://www.tldrlegal.com/license/mit-license)
|
@ -1,3 +0,0 @@
|
||||
README.md
|
||||
node_modules
|
||||
_media
|
@ -1,3 +0,0 @@
|
||||
node_modules
|
||||
./README.md
|
||||
out
|
@ -1,18 +0,0 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2025 Authentik Security, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
||||
associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||
including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
||||
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial
|
||||
portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
||||
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
||||
OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
40
web/packages/esbuild-plugin-live-reload/README.md
Normal file
40
web/packages/esbuild-plugin-live-reload/README.md
Normal file
@ -0,0 +1,40 @@
|
||||
# `@goauthentik/esbuild-plugin-live-reload`
|
||||
|
||||
_A plugin that enables live reloading of ESBuild during development._
|
||||
|
||||
## Usage
|
||||
|
||||
### Node.js setup
|
||||
|
||||
```js
|
||||
import { liveReloadPlugin } from "@goauthentik/esbuild-plugin-live-reload";
|
||||
import esbuild from "esbuild";
|
||||
|
||||
const NodeEnvironment = process.env.NODE_ENV || "development";
|
||||
|
||||
/**
|
||||
* @type {esbuild.BuildOptions}
|
||||
*/
|
||||
const buildOptions = {
|
||||
// ... Your build options.
|
||||
define: {
|
||||
"process.env.NODE_ENV": JSON.stringify(NodeEnvironment),
|
||||
},
|
||||
plugins: [liveReloadPlugin(/** @see {@link LiveReloadPluginOptions} */)],
|
||||
};
|
||||
|
||||
const buildContext = await esbuild.context(buildOptions);
|
||||
|
||||
await buildContext.rebuild();
|
||||
await buildContext.watch();
|
||||
```
|
||||
|
||||
### Browser setup
|
||||
|
||||
```js
|
||||
// Place this at the beginning of your application's entry point.
|
||||
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
await import("@goauthentik/esbuild-plugin-live-reload/client");
|
||||
}
|
||||
```
|
@ -28,8 +28,6 @@ const log = console.debug.bind(console, logPrefix);
|
||||
* ```
|
||||
*
|
||||
* @implements {Disposable}
|
||||
* @category Plugin
|
||||
* runtime browser
|
||||
*/
|
||||
export class ESBuildObserver extends EventSource {
|
||||
/**
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user