diff --git a/.dockerignore b/.dockerignore
index 1e6a89ac0..72cdb7ebe 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -7,3 +7,4 @@ build/**
build_docs/**
Dockerfile
authentik/enterprise
+blueprints/local
diff --git a/.github/workflows/gha-cache-cleanup.yml b/.github/workflows/gha-cache-cleanup.yml
new file mode 100644
index 000000000..b2fa16407
--- /dev/null
+++ b/.github/workflows/gha-cache-cleanup.yml
@@ -0,0 +1,34 @@
+---
+# See https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#force-deleting-cache-entries
+name: Cleanup cache after PR is closed
+on:
+ pull_request:
+ types:
+ - closed
+
+jobs:
+ cleanup:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Check out code
+ uses: actions/checkout@v3
+
+ - name: Cleanup
+ run: |
+ gh extension install actions/gh-actions-cache
+
+ REPO=${{ github.repository }}
+ BRANCH="refs/pull/${{ github.event.pull_request.number }}/merge"
+
+ echo "Fetching list of cache key"
+ cacheKeysForPR=$(gh actions-cache list -R $REPO -B $BRANCH -L 100 | cut -f 1 )
+
+ # Setting this to not fail the workflow while deleting cache keys.
+ set +e
+ echo "Deleting caches..."
+ for cacheKey in $cacheKeysForPR; do
+ gh actions-cache delete $cacheKey -R $REPO -B $BRANCH --confirm
+ done
+ echo "Done"
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/publish-source-docs.yml b/.github/workflows/publish-source-docs.yml
index eb091bfaa..d6615a03f 100644
--- a/.github/workflows/publish-source-docs.yml
+++ b/.github/workflows/publish-source-docs.yml
@@ -5,6 +5,11 @@ on:
branches:
- main
+env:
+ POSTGRES_DB: authentik
+ POSTGRES_USER: authentik
+ POSTGRES_PASSWORD: "EK-5jnKfjrGRm<77"
+
jobs:
publish-source-docs:
runs-on: ubuntu-latest
@@ -15,6 +20,7 @@ jobs:
uses: ./.github/actions/setup
- name: generate docs
run: |
+ poetry run make migrate
poetry run ak build_source_docs
- name: Publish
uses: netlify/actions/cli@master
diff --git a/Dockerfile b/Dockerfile
index 278607aa7..c78b4a96a 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -20,7 +20,7 @@ WORKDIR /work/web
RUN npm ci --include=dev && npm run build
# Stage 3: Poetry to requirements.txt export
-FROM docker.io/python:3.11.4-slim-bullseye AS poetry-locker
+FROM docker.io/python:3.11.5-slim-bookworm AS poetry-locker
WORKDIR /work
COPY ./pyproject.toml /work
@@ -31,7 +31,7 @@ RUN pip install --no-cache-dir poetry && \
poetry export -f requirements.txt --dev --output requirements-dev.txt
# Stage 4: Build go proxy
-FROM docker.io/golang:1.21.0-bullseye AS go-builder
+FROM docker.io/golang:1.21.0-bookworm AS go-builder
WORKDIR /work
@@ -39,12 +39,13 @@ COPY --from=web-builder /work/web/robots.txt /work/web/robots.txt
COPY --from=web-builder /work/web/security.txt /work/web/security.txt
COPY ./cmd /work/cmd
+COPY ./authentik/lib /work/authentik/lib
COPY ./web/static.go /work/web/static.go
COPY ./internal /work/internal
COPY ./go.mod /work/go.mod
COPY ./go.sum /work/go.sum
-RUN go build -o /work/authentik ./cmd/server/
+RUN go build -o /work/bin/authentik ./cmd/server/
# Stage 5: MaxMind GeoIP
FROM ghcr.io/maxmind/geoipupdate:v6.0 as geoip
@@ -61,7 +62,7 @@ RUN --mount=type=secret,id=GEOIPUPDATE_ACCOUNT_ID \
/bin/sh -c "/usr/bin/entry.sh || echo 'Failed to get GeoIP database, disabling'; exit 0"
# Stage 6: Run
-FROM docker.io/python:3.11.4-slim-bullseye AS final-image
+FROM docker.io/python:3.11.5-slim-bookworm AS final-image
ARG GIT_BUILD_HASH
ARG VERSION
@@ -104,7 +105,7 @@ COPY ./tests /tests
COPY ./manage.py /
COPY ./blueprints /blueprints
COPY ./lifecycle/ /lifecycle
-COPY --from=go-builder /work/authentik /bin/authentik
+COPY --from=go-builder /work/bin/authentik /bin/authentik
COPY --from=web-builder /work/web/dist/ /web/dist/
COPY --from=web-builder /work/web/authentik/ /web/authentik/
COPY --from=website-builder /work/website/help/ /website/help/
diff --git a/SECURITY.md b/SECURITY.md
index 3a02de671..0e3b00b9e 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -27,6 +27,8 @@ To report a vulnerability, send an email to [security@goauthentik.io](mailto:se
authentik reserves the right to reclassify CVSS as necessary. To determine severity, we will use the CVSS calculator from NVD (https://nvd.nist.gov/vuln-metrics/cvss/v3-calculator). The calculated CVSS score will then be translated into one of the following categories:
+| Score | Severity |
+| --- | --- |
| 0.0 | None |
| 0.1 – 3.9 | Low |
| 4.0 – 6.9 | Medium |
diff --git a/authentik/blueprints/tests/fixtures/conditional_fields.yaml b/authentik/blueprints/tests/fixtures/conditional_fields.yaml
index 0380ecd00..5ce07719c 100644
--- a/authentik/blueprints/tests/fixtures/conditional_fields.yaml
+++ b/authentik/blueprints/tests/fixtures/conditional_fields.yaml
@@ -45,3 +45,8 @@ entries:
attrs:
name: "%(uid)s"
password: "%(uid)s"
+ - model: authentik_core.user
+ identifiers:
+ username: "%(uid)s-no-password"
+ attrs:
+ name: "%(uid)s"
diff --git a/authentik/blueprints/tests/fixtures/tags.yaml b/authentik/blueprints/tests/fixtures/tags.yaml
index 16785ee78..832443117 100644
--- a/authentik/blueprints/tests/fixtures/tags.yaml
+++ b/authentik/blueprints/tests/fixtures/tags.yaml
@@ -36,6 +36,7 @@ entries:
model: authentik_policies_expression.expressionpolicy
- attrs:
attributes:
+ env_null: !Env [bar-baz, null]
policy_pk1:
!Format [
"%s-%s",
diff --git a/authentik/blueprints/tests/test_v1.py b/authentik/blueprints/tests/test_v1.py
index ae10bb66a..73ec9d553 100644
--- a/authentik/blueprints/tests/test_v1.py
+++ b/authentik/blueprints/tests/test_v1.py
@@ -213,8 +213,9 @@ class TestBlueprintsV1(TransactionTestCase):
},
},
"nested_context": "context-nested-value",
+ "env_null": None,
}
- )
+ ).exists()
)
self.assertTrue(
OAuthSource.objects.filter(
diff --git a/authentik/blueprints/tests/test_v1_conditional_fields.py b/authentik/blueprints/tests/test_v1_conditional_fields.py
index a8b880157..309bd38df 100644
--- a/authentik/blueprints/tests/test_v1_conditional_fields.py
+++ b/authentik/blueprints/tests/test_v1_conditional_fields.py
@@ -51,3 +51,9 @@ class TestBlueprintsV1ConditionalFields(TransactionTestCase):
user: User = User.objects.filter(username=self.uid).first()
self.assertIsNotNone(user)
self.assertTrue(user.check_password(self.uid))
+
+ def test_user_null(self):
+ """Test user"""
+ user: User = User.objects.filter(username=f"{self.uid}-no-password").first()
+ self.assertIsNotNone(user)
+ self.assertFalse(user.has_usable_password())
diff --git a/authentik/blueprints/v1/common.py b/authentik/blueprints/v1/common.py
index f00c27bc0..b4b2a7f26 100644
--- a/authentik/blueprints/v1/common.py
+++ b/authentik/blueprints/v1/common.py
@@ -224,11 +224,11 @@ class Env(YAMLTag):
if isinstance(node, ScalarNode):
self.key = node.value
if isinstance(node, SequenceNode):
- self.key = node.value[0].value
- self.default = node.value[1].value
+ self.key = loader.construct_object(node.value[0])
+ self.default = loader.construct_object(node.value[1])
def resolve(self, entry: BlueprintEntry, blueprint: Blueprint) -> Any:
- return getenv(self.key, self.default)
+ return getenv(self.key) or self.default
class Context(YAMLTag):
@@ -243,8 +243,8 @@ class Context(YAMLTag):
if isinstance(node, ScalarNode):
self.key = node.value
if isinstance(node, SequenceNode):
- self.key = node.value[0].value
- self.default = node.value[1].value
+ self.key = loader.construct_object(node.value[0])
+ self.default = loader.construct_object(node.value[1])
def resolve(self, entry: BlueprintEntry, blueprint: Blueprint) -> Any:
value = self.default
@@ -263,7 +263,7 @@ class Format(YAMLTag):
def __init__(self, loader: "BlueprintLoader", node: SequenceNode) -> None:
super().__init__()
- self.format_string = node.value[0].value
+ self.format_string = loader.construct_object(node.value[0])
self.args = []
for raw_node in node.value[1:]:
self.args.append(loader.construct_object(raw_node))
@@ -342,7 +342,7 @@ class Condition(YAMLTag):
def __init__(self, loader: "BlueprintLoader", node: SequenceNode) -> None:
super().__init__()
- self.mode = node.value[0].value
+ self.mode = loader.construct_object(node.value[0])
self.args = []
for raw_node in node.value[1:]:
self.args.append(loader.construct_object(raw_node))
@@ -417,7 +417,7 @@ class Enumerate(YAMLTag, YAMLTagContext):
def __init__(self, loader: "BlueprintLoader", node: SequenceNode) -> None:
super().__init__()
self.iterable = loader.construct_object(node.value[0])
- self.output_body = node.value[1].value
+ self.output_body = loader.construct_object(node.value[1])
self.item_body = loader.construct_object(node.value[2])
self.__current_context: tuple[Any, Any] = tuple()
diff --git a/authentik/core/api/users.py b/authentik/core/api/users.py
index 8a817d0b7..2029ff7a6 100644
--- a/authentik/core/api/users.py
+++ b/authentik/core/api/users.py
@@ -123,27 +123,35 @@ class UserSerializer(ModelSerializer):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if SERIALIZER_CONTEXT_BLUEPRINT in self.context:
- self.fields["password"] = CharField(required=False)
+ self.fields["password"] = CharField(required=False, allow_null=True)
def create(self, validated_data: dict) -> User:
"""If this serializer is used in the blueprint context, we allow for
directly setting a password. However should be done via the `set_password`
method instead of directly setting it like rest_framework."""
+ password = validated_data.pop("password", None)
instance: User = super().create(validated_data)
- if SERIALIZER_CONTEXT_BLUEPRINT in self.context and "password" in validated_data:
- instance.set_password(validated_data["password"])
- instance.save()
+ self._set_password(instance, password)
return instance
def update(self, instance: User, validated_data: dict) -> User:
"""Same as `create` above, set the password directly if we're in a blueprint
context"""
+ password = validated_data.pop("password", None)
instance = super().update(instance, validated_data)
- if SERIALIZER_CONTEXT_BLUEPRINT in self.context and "password" in validated_data:
- instance.set_password(validated_data["password"])
- instance.save()
+ self._set_password(instance, password)
return instance
+ def _set_password(self, instance: User, password: Optional[str]):
+ """Set password of user if we're in a blueprint context, and if it's an empty
+ string then use an unusable password"""
+ if SERIALIZER_CONTEXT_BLUEPRINT in self.context and password:
+ instance.set_password(password)
+ instance.save()
+ if len(instance.password) == 0:
+ instance.set_unusable_password()
+ instance.save()
+
def validate_path(self, path: str) -> str:
"""Validate path"""
if path[:1] == "/" or path[-1] == "/":
@@ -309,7 +317,7 @@ class UsersFilter(FilterSet):
path = CharFilter(field_name="path")
path_startswith = CharFilter(field_name="path", lookup_expr="startswith")
- type = MultipleChoiceFilter(field_name="type")
+ type = MultipleChoiceFilter(choices=UserTypes.choices, field_name="type")
groups_by_name = ModelMultipleChoiceFilter(
field_name="ak_groups__name",
diff --git a/authentik/core/tests/test_users_api.py b/authentik/core/tests/test_users_api.py
index 60a1d61fc..f256fb262 100644
--- a/authentik/core/tests/test_users_api.py
+++ b/authentik/core/tests/test_users_api.py
@@ -28,6 +28,19 @@ class TestUsersAPI(APITestCase):
self.admin = create_test_admin_user()
self.user = User.objects.create(username="test-user")
+ def test_filter_type(self):
+ """Test API filtering by type"""
+ self.client.force_login(self.admin)
+ user = create_test_admin_user(type=UserTypes.EXTERNAL)
+ response = self.client.get(
+ reverse("authentik_api:user-list"),
+ data={
+ "type": UserTypes.EXTERNAL,
+ "username": user.username,
+ },
+ )
+ self.assertEqual(response.status_code, 200)
+
def test_metrics(self):
"""Test user's metrics"""
self.client.force_login(self.admin)
diff --git a/authentik/core/tests/utils.py b/authentik/core/tests/utils.py
index ad6942d80..2406edc2a 100644
--- a/authentik/core/tests/utils.py
+++ b/authentik/core/tests/utils.py
@@ -21,7 +21,7 @@ def create_test_flow(
)
-def create_test_admin_user(name: Optional[str] = None) -> User:
+def create_test_admin_user(name: Optional[str] = None, **kwargs) -> User:
"""Generate a test-admin user"""
uid = generate_id(20) if not name else name
group = Group.objects.create(name=uid, is_superuser=True)
@@ -29,6 +29,7 @@ def create_test_admin_user(name: Optional[str] = None) -> User:
username=uid,
name=uid,
email=f"{uid}@goauthentik.io",
+ **kwargs,
)
user.set_password(uid)
user.save()
@@ -36,12 +37,12 @@ def create_test_admin_user(name: Optional[str] = None) -> User:
return user
-def create_test_tenant() -> Tenant:
+def create_test_tenant(**kwargs) -> Tenant:
"""Generate a test tenant, removing all other tenants to make sure this one
matches."""
uid = generate_id(20)
Tenant.objects.all().delete()
- return Tenant.objects.create(domain=uid, default=True)
+ return Tenant.objects.create(domain=uid, default=True, **kwargs)
def create_test_cert(use_ec_private_key=False) -> CertificateKeyPair:
diff --git a/authentik/enterprise/api.py b/authentik/enterprise/api.py
index cdc63563c..6a215b1fe 100644
--- a/authentik/enterprise/api.py
+++ b/authentik/enterprise/api.py
@@ -35,13 +35,13 @@ class LicenseSerializer(ModelSerializer):
"name",
"key",
"expiry",
- "users",
+ "internal_users",
"external_users",
]
extra_kwargs = {
"name": {"read_only": True},
"expiry": {"read_only": True},
- "users": {"read_only": True},
+ "internal_users": {"read_only": True},
"external_users": {"read_only": True},
}
@@ -49,7 +49,7 @@ class LicenseSerializer(ModelSerializer):
class LicenseSummary(PassiveSerializer):
"""Serializer for license status"""
- users = IntegerField(required=True)
+ internal_users = IntegerField(required=True)
external_users = IntegerField(required=True)
valid = BooleanField()
show_admin_warning = BooleanField()
@@ -62,9 +62,9 @@ class LicenseSummary(PassiveSerializer):
class LicenseForecastSerializer(PassiveSerializer):
"""Serializer for license forecast"""
- users = IntegerField(required=True)
+ internal_users = IntegerField(required=True)
external_users = IntegerField(required=True)
- forecasted_users = IntegerField(required=True)
+ forecasted_internal_users = IntegerField(required=True)
forecasted_external_users = IntegerField(required=True)
@@ -111,7 +111,7 @@ class LicenseViewSet(UsedByMixin, ModelViewSet):
latest_valid = datetime.fromtimestamp(total.exp)
response = LicenseSummary(
data={
- "users": total.users,
+ "internal_users": total.internal_users,
"external_users": total.external_users,
"valid": total.is_valid(),
"show_admin_warning": show_admin_warning,
@@ -135,8 +135,8 @@ class LicenseViewSet(UsedByMixin, ModelViewSet):
def forecast(self, request: Request) -> Response:
"""Forecast how many users will be required in a year"""
last_month = now() - timedelta(days=30)
- # Forecast for default users
- users_in_last_month = User.objects.filter(
+ # Forecast for internal users
+ internal_in_last_month = User.objects.filter(
type=UserTypes.INTERNAL, date_joined__gte=last_month
).count()
# Forecast for external users
@@ -144,9 +144,9 @@ class LicenseViewSet(UsedByMixin, ModelViewSet):
forecast_for_months = 12
response = LicenseForecastSerializer(
data={
- "users": LicenseKey.get_default_user_count(),
+ "internal_users": LicenseKey.get_default_user_count(),
"external_users": LicenseKey.get_external_user_count(),
- "forecasted_users": (users_in_last_month * forecast_for_months),
+ "forecasted_internal_users": (internal_in_last_month * forecast_for_months),
"forecasted_external_users": (external_in_last_month * forecast_for_months),
}
)
diff --git a/authentik/enterprise/migrations/0002_rename_users_license_internal_users_and_more.py b/authentik/enterprise/migrations/0002_rename_users_license_internal_users_and_more.py
new file mode 100644
index 000000000..e8ad7dc4e
--- /dev/null
+++ b/authentik/enterprise/migrations/0002_rename_users_license_internal_users_and_more.py
@@ -0,0 +1,29 @@
+# Generated by Django 4.2.4 on 2023-08-23 10:06
+
+import django.contrib.postgres.indexes
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ("authentik_enterprise", "0001_initial"),
+ ]
+
+ operations = [
+ migrations.RenameField(
+ model_name="license",
+ old_name="users",
+ new_name="internal_users",
+ ),
+ migrations.AlterField(
+ model_name="license",
+ name="key",
+ field=models.TextField(),
+ ),
+ migrations.AddIndex(
+ model_name="license",
+ index=django.contrib.postgres.indexes.HashIndex(
+ fields=["key"], name="authentik_e_key_523e13_hash"
+ ),
+ ),
+ ]
diff --git a/authentik/enterprise/models.py b/authentik/enterprise/models.py
index 103859b23..37b95ba96 100644
--- a/authentik/enterprise/models.py
+++ b/authentik/enterprise/models.py
@@ -11,6 +11,7 @@ from uuid import uuid4
from cryptography.exceptions import InvalidSignature
from cryptography.x509 import Certificate, load_der_x509_certificate, load_pem_x509_certificate
from dacite import from_dict
+from django.contrib.postgres.indexes import HashIndex
from django.db import models
from django.db.models.query import QuerySet
from django.utils.timezone import now
@@ -46,8 +47,8 @@ class LicenseKey:
exp: int
name: str
- users: int
- external_users: int
+ internal_users: int = 0
+ external_users: int = 0
flags: list[LicenseFlags] = field(default_factory=list)
@staticmethod
@@ -87,7 +88,7 @@ class LicenseKey:
active_licenses = License.objects.filter(expiry__gte=now())
total = LicenseKey(get_license_aud(), 0, "Summarized license", 0, 0)
for lic in active_licenses:
- total.users += lic.users
+ total.internal_users += lic.internal_users
total.external_users += lic.external_users
exp_ts = int(mktime(lic.expiry.timetuple()))
if total.exp == 0:
@@ -123,7 +124,7 @@ class LicenseKey:
Only checks the current count, no historical data is checked"""
default_users = self.get_default_user_count()
- if default_users > self.users:
+ if default_users > self.internal_users:
return False
active_users = self.get_external_user_count()
if active_users > self.external_users:
@@ -153,11 +154,11 @@ class License(models.Model):
"""An authentik enterprise license"""
license_uuid = models.UUIDField(primary_key=True, editable=False, default=uuid4)
- key = models.TextField(unique=True)
+ key = models.TextField()
name = models.TextField()
expiry = models.DateTimeField()
- users = models.BigIntegerField()
+ internal_users = models.BigIntegerField()
external_users = models.BigIntegerField()
@property
@@ -165,6 +166,9 @@ class License(models.Model):
"""Get parsed license status"""
return LicenseKey.validate(self.key)
+ class Meta:
+ indexes = (HashIndex(fields=("key",)),)
+
def usage_expiry():
"""Keep license usage records for 3 months"""
diff --git a/authentik/enterprise/signals.py b/authentik/enterprise/signals.py
index b891f8f2c..67e7c5745 100644
--- a/authentik/enterprise/signals.py
+++ b/authentik/enterprise/signals.py
@@ -13,6 +13,6 @@ def pre_save_license(sender: type[License], instance: License, **_):
"""Extract data from license jwt and save it into model"""
status = instance.status
instance.name = status.name
- instance.users = status.users
+ instance.internal_users = status.internal_users
instance.external_users = status.external_users
instance.expiry = datetime.fromtimestamp(status.exp, tz=get_current_timezone())
diff --git a/authentik/enterprise/tests/test_license.py b/authentik/enterprise/tests/test_license.py
index 6e21e6d11..dd91af1a6 100644
--- a/authentik/enterprise/tests/test_license.py
+++ b/authentik/enterprise/tests/test_license.py
@@ -23,7 +23,7 @@ class TestEnterpriseLicense(TestCase):
aud="",
exp=_exp,
name=generate_id(),
- users=100,
+ internal_users=100,
external_users=100,
)
),
@@ -32,7 +32,7 @@ class TestEnterpriseLicense(TestCase):
"""Check license verification"""
lic = License.objects.create(key=generate_id())
self.assertTrue(lic.status.is_valid())
- self.assertEqual(lic.users, 100)
+ self.assertEqual(lic.internal_users, 100)
def test_invalid(self):
"""Test invalid license"""
@@ -46,7 +46,7 @@ class TestEnterpriseLicense(TestCase):
aud="",
exp=_exp,
name=generate_id(),
- users=100,
+ internal_users=100,
external_users=100,
)
),
@@ -58,7 +58,7 @@ class TestEnterpriseLicense(TestCase):
lic2 = License.objects.create(key=generate_id())
self.assertTrue(lic2.status.is_valid())
total = LicenseKey.get_total()
- self.assertEqual(total.users, 200)
+ self.assertEqual(total.internal_users, 200)
self.assertEqual(total.external_users, 200)
self.assertEqual(total.exp, _exp)
self.assertTrue(total.is_valid())
diff --git a/authentik/lib/config.go b/authentik/lib/config.go
new file mode 100644
index 000000000..f595f2423
--- /dev/null
+++ b/authentik/lib/config.go
@@ -0,0 +1,10 @@
+package lib
+
+import _ "embed"
+
+//go:embed default.yml
+var defaultConfig []byte
+
+func DefaultConfig() []byte {
+ return defaultConfig
+}
diff --git a/authentik/lib/default.yml b/authentik/lib/default.yml
index 45ffb3073..b9aad30bd 100644
--- a/authentik/lib/default.yml
+++ b/authentik/lib/default.yml
@@ -11,7 +11,11 @@ postgresql:
listen:
listen_http: 0.0.0.0:9000
listen_https: 0.0.0.0:9443
+ listen_ldap: 0.0.0.0:3389
+ listen_ldaps: 0.0.0.0:6636
+ listen_radius: 0.0.0.0:1812
listen_metrics: 0.0.0.0:9300
+ listen_debug: 0.0.0.0:9900
trusted_proxy_cidrs:
- 127.0.0.0/8
- 10.0.0.0/8
@@ -32,6 +36,9 @@ redis:
cache_timeout_policies: 300
cache_timeout_reputation: 300
+paths:
+ media: ./media
+
debug: false
remote_debug: false
diff --git a/authentik/providers/oauth2/models.py b/authentik/providers/oauth2/models.py
index 1357b2101..e9a2f731a 100644
--- a/authentik/providers/oauth2/models.py
+++ b/authentik/providers/oauth2/models.py
@@ -2,6 +2,7 @@
import base64
import binascii
import json
+from dataclasses import asdict
from functools import cached_property
from hashlib import sha256
from typing import Any, Optional
@@ -358,7 +359,7 @@ class AccessToken(SerializerModel, ExpiringModel, BaseGrantModel):
@id_token.setter
def id_token(self, value: IDToken):
self.token = value.to_access_token(self.provider)
- self._id_token = json.dumps(value.to_dict())
+ self._id_token = json.dumps(asdict(value))
@property
def at_hash(self):
@@ -400,7 +401,7 @@ class RefreshToken(SerializerModel, ExpiringModel, BaseGrantModel):
@id_token.setter
def id_token(self, value: IDToken):
- self._id_token = json.dumps(value.to_dict())
+ self._id_token = json.dumps(asdict(value))
@property
def serializer(self) -> Serializer:
diff --git a/authentik/providers/oauth2/tests/test_token_cc.py b/authentik/providers/oauth2/tests/test_token_cc.py
index 8becccb95..81f595d63 100644
--- a/authentik/providers/oauth2/tests/test_token_cc.py
+++ b/authentik/providers/oauth2/tests/test_token_cc.py
@@ -151,6 +151,14 @@ class TestTokenClientCredentials(OAuthTestCase):
)
self.assertEqual(jwt["given_name"], self.user.name)
self.assertEqual(jwt["preferred_username"], self.user.username)
+ jwt = decode(
+ body["id_token"],
+ key=self.provider.signing_key.public_key,
+ algorithms=[alg],
+ audience=self.provider.client_id,
+ )
+ self.assertEqual(jwt["given_name"], self.user.name)
+ self.assertEqual(jwt["preferred_username"], self.user.username)
def test_successful_password(self):
"""test successful (password grant)"""
diff --git a/authentik/providers/scim/clients/base.py b/authentik/providers/scim/clients/base.py
index ed99f6070..b214c30e4 100644
--- a/authentik/providers/scim/clients/base.py
+++ b/authentik/providers/scim/clients/base.py
@@ -68,7 +68,7 @@ class SCIMClient(Generic[T, SchemaType]):
"""Get Service provider config"""
default_config = ServiceProviderConfiguration.default()
try:
- return ServiceProviderConfiguration.parse_obj(
+ return ServiceProviderConfiguration.model_validate(
self._request("GET", "/ServiceProviderConfig")
)
except (ValidationError, SCIMRequestException) as exc:
diff --git a/authentik/providers/scim/clients/group.py b/authentik/providers/scim/clients/group.py
index 9af35dd22..98771315d 100644
--- a/authentik/providers/scim/clients/group.py
+++ b/authentik/providers/scim/clients/group.py
@@ -74,7 +74,7 @@ class SCIMGroupClient(SCIMClient[Group, SCIMGroupSchema]):
if not raw_scim_group:
raise StopSync(ValueError("No group mappings configured"), obj)
try:
- scim_group = SCIMGroupSchema.parse_obj(delete_none_values(raw_scim_group))
+ scim_group = SCIMGroupSchema.model_validate(delete_none_values(raw_scim_group))
except ValidationError as exc:
raise StopSync(exc, obj) from exc
if not scim_group.externalId:
@@ -99,7 +99,8 @@ class SCIMGroupClient(SCIMClient[Group, SCIMGroupSchema]):
response = self._request(
"POST",
"/Groups",
- data=scim_group.json(
+ json=scim_group.model_dump(
+ mode="json",
exclude_unset=True,
),
)
@@ -113,7 +114,8 @@ class SCIMGroupClient(SCIMClient[Group, SCIMGroupSchema]):
return self._request(
"PUT",
f"/Groups/{scim_group.id}",
- data=scim_group.json(
+ json=scim_group.model_dump(
+ mode="json",
exclude_unset=True,
),
)
@@ -160,7 +162,13 @@ class SCIMGroupClient(SCIMClient[Group, SCIMGroupSchema]):
*ops: PatchOperation,
):
req = PatchRequest(Operations=ops)
- self._request("PATCH", f"/Groups/{group_id}", data=req.json())
+ self._request(
+ "PATCH",
+ f"/Groups/{group_id}",
+ json=req.model_dump(
+ mode="json",
+ ),
+ )
def _patch_add_users(self, group: Group, users_set: set[int]):
"""Add users in users_set to group"""
diff --git a/authentik/providers/scim/clients/schema.py b/authentik/providers/scim/clients/schema.py
index 3f2868d96..b9cbe3d43 100644
--- a/authentik/providers/scim/clients/schema.py
+++ b/authentik/providers/scim/clients/schema.py
@@ -52,7 +52,7 @@ class ServiceProviderConfiguration(BaseServiceProviderConfiguration):
class PatchRequest(BasePatchRequest):
"""PatchRequest which correctly sets schemas"""
- schemas: tuple[str] = ["urn:ietf:params:scim:api:messages:2.0:PatchOp"]
+ schemas: tuple[str] = ("urn:ietf:params:scim:api:messages:2.0:PatchOp",)
class SCIMError(BaseSCIMError):
diff --git a/authentik/providers/scim/clients/user.py b/authentik/providers/scim/clients/user.py
index f68f2f91d..31d912858 100644
--- a/authentik/providers/scim/clients/user.py
+++ b/authentik/providers/scim/clients/user.py
@@ -64,7 +64,7 @@ class SCIMUserClient(SCIMClient[User, SCIMUserSchema]):
if not raw_scim_user:
raise StopSync(ValueError("No user mappings configured"), obj)
try:
- scim_user = SCIMUserSchema.parse_obj(delete_none_values(raw_scim_user))
+ scim_user = SCIMUserSchema.model_validate(delete_none_values(raw_scim_user))
except ValidationError as exc:
raise StopSync(exc, obj) from exc
if not scim_user.externalId:
@@ -77,7 +77,8 @@ class SCIMUserClient(SCIMClient[User, SCIMUserSchema]):
response = self._request(
"POST",
"/Users",
- data=scim_user.json(
+ json=scim_user.model_dump(
+ mode="json",
exclude_unset=True,
),
)
@@ -90,7 +91,8 @@ class SCIMUserClient(SCIMClient[User, SCIMUserSchema]):
self._request(
"PUT",
f"/Users/{connection.id}",
- data=scim_user.json(
+ json=scim_user.model_dump(
+ mode="json",
exclude_unset=True,
),
)
diff --git a/authentik/providers/scim/tests/test_membership.py b/authentik/providers/scim/tests/test_membership.py
index 48207de72..a0506a7cd 100644
--- a/authentik/providers/scim/tests/test_membership.py
+++ b/authentik/providers/scim/tests/test_membership.py
@@ -47,6 +47,7 @@ class SCIMMembershipTests(TestCase):
def test_member_add(self):
"""Test member add"""
config = ServiceProviderConfiguration.default()
+ # pylint: disable=assigning-non-slot
config.patch.supported = True
user_scim_id = generate_id()
group_scim_id = generate_id()
@@ -60,7 +61,7 @@ class SCIMMembershipTests(TestCase):
with Mocker() as mocker:
mocker.get(
"https://localhost/ServiceProviderConfig",
- json=config.dict(),
+ json=config.model_dump(),
)
mocker.post(
"https://localhost/Users",
@@ -104,7 +105,7 @@ class SCIMMembershipTests(TestCase):
with Mocker() as mocker:
mocker.get(
"https://localhost/ServiceProviderConfig",
- json=config.dict(),
+ json=config.model_dump(),
)
mocker.patch(
f"https://localhost/Groups/{group_scim_id}",
@@ -131,6 +132,7 @@ class SCIMMembershipTests(TestCase):
def test_member_remove(self):
"""Test member remove"""
config = ServiceProviderConfiguration.default()
+ # pylint: disable=assigning-non-slot
config.patch.supported = True
user_scim_id = generate_id()
group_scim_id = generate_id()
@@ -144,7 +146,7 @@ class SCIMMembershipTests(TestCase):
with Mocker() as mocker:
mocker.get(
"https://localhost/ServiceProviderConfig",
- json=config.dict(),
+ json=config.model_dump(),
)
mocker.post(
"https://localhost/Users",
@@ -188,7 +190,7 @@ class SCIMMembershipTests(TestCase):
with Mocker() as mocker:
mocker.get(
"https://localhost/ServiceProviderConfig",
- json=config.dict(),
+ json=config.model_dump(),
)
mocker.patch(
f"https://localhost/Groups/{group_scim_id}",
@@ -215,7 +217,7 @@ class SCIMMembershipTests(TestCase):
with Mocker() as mocker:
mocker.get(
"https://localhost/ServiceProviderConfig",
- json=config.dict(),
+ json=config.model_dump(),
)
mocker.patch(
f"https://localhost/Groups/{group_scim_id}",
diff --git a/authentik/sources/oauth/api/source.py b/authentik/sources/oauth/api/source.py
index 6c9399f95..4b1785a54 100644
--- a/authentik/sources/oauth/api/source.py
+++ b/authentik/sources/oauth/api/source.py
@@ -62,7 +62,8 @@ class OAuthSourceSerializer(SourceSerializer):
well_known_config = session.get(well_known)
well_known_config.raise_for_status()
except RequestException as exc:
- raise ValidationError(exc.response.text)
+ text = exc.response.text if exc.response else str(exc)
+ raise ValidationError(text)
config = well_known_config.json()
try:
attrs["authorization_url"] = config["authorization_endpoint"]
@@ -78,7 +79,8 @@ class OAuthSourceSerializer(SourceSerializer):
jwks_config = session.get(jwks_url)
jwks_config.raise_for_status()
except RequestException as exc:
- raise ValidationError(exc.response.text)
+ text = exc.response.text if exc.response else str(exc)
+ raise ValidationError(text)
config = jwks_config.json()
attrs["oidc_jwks"] = config
diff --git a/authentik/stages/authenticator_validate/challenge.py b/authentik/stages/authenticator_validate/challenge.py
index 96e5dc764..c8d86bf10 100644
--- a/authentik/stages/authenticator_validate/challenge.py
+++ b/authentik/stages/authenticator_validate/challenge.py
@@ -1,5 +1,4 @@
"""Validation stage challenge checking"""
-from json import dumps, loads
from typing import Optional
from urllib.parse import urlencode
@@ -17,7 +16,6 @@ from webauthn.authentication.generate_authentication_options import generate_aut
from webauthn.authentication.verify_authentication_response import verify_authentication_response
from webauthn.helpers.base64url_to_bytes import base64url_to_bytes
from webauthn.helpers.exceptions import InvalidAuthenticationResponse
-from webauthn.helpers.options_to_json import options_to_json
from webauthn.helpers.structs import AuthenticationCredential
from authentik.core.api.utils import PassiveSerializer
@@ -68,7 +66,12 @@ def get_webauthn_challenge_without_user(
)
request.session[SESSION_KEY_WEBAUTHN_CHALLENGE] = authentication_options.challenge
- return loads(options_to_json(authentication_options))
+ return authentication_options.model_dump(
+ mode="json",
+ by_alias=True,
+ exclude_unset=False,
+ exclude_none=True,
+ )
def get_webauthn_challenge(
@@ -93,7 +96,12 @@ def get_webauthn_challenge(
request.session[SESSION_KEY_WEBAUTHN_CHALLENGE] = authentication_options.challenge
- return loads(options_to_json(authentication_options))
+ return authentication_options.model_dump(
+ mode="json",
+ by_alias=True,
+ exclude_unset=False,
+ exclude_none=True,
+ )
def select_challenge(request: HttpRequest, device: Device):
@@ -144,7 +152,7 @@ def validate_challenge_webauthn(data: dict, stage_view: StageView, user: User) -
try:
authentication_verification = verify_authentication_response(
- credential=AuthenticationCredential.parse_raw(dumps(data)),
+ credential=AuthenticationCredential.model_validate(data),
expected_challenge=challenge,
expected_rp_id=get_rp_id(request),
expected_origin=get_origin(request),
diff --git a/authentik/stages/authenticator_validate/tests/test_webauthn.py b/authentik/stages/authenticator_validate/tests/test_webauthn.py
index 3a6071089..8ea9c6856 100644
--- a/authentik/stages/authenticator_validate/tests/test_webauthn.py
+++ b/authentik/stages/authenticator_validate/tests/test_webauthn.py
@@ -234,14 +234,12 @@ class AuthenticatorValidateStageWebAuthnTests(FlowTestCase):
"assertionClientExtensions": "{}",
"response": {
"clientDataJSON": (
- (
- "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiZzk4STUxbVF2WlhvN"
- "Wx4TGZockQyemZvbGhaYkxSeUNncWtrWWFwMWp3U2FKMTNCZ3VvSldDRjlfTGczQW"
- "dPNFdoLUJxYTU1NkpFMjBvS3NZYmw2UkEiLCJvcmlnaW4iOiJodHRwOi8vbG9jYWx"
- "ob3N0OjkwMDAiLCJjcm9zc09yaWdpbiI6ZmFsc2UsIm90aGVyX2tleXNfY2FuX2Jl"
- "X2FkZGVkX2hlcmUiOiJkbyBub3QgY29tcGFyZSBjbGllbnREYXRhSlNPTiBhZ2Fpb"
- "nN0IGEgdGVtcGxhdGUuIFNlZSBodHRwczovL2dvby5nbC95YWJQZXgifQ=="
- ),
+ "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiZzk4STUxbVF2WlhvN"
+ "Wx4TGZockQyemZvbGhaYkxSeUNncWtrWWFwMWp3U2FKMTNCZ3VvSldDRjlfTGczQW"
+ "dPNFdoLUJxYTU1NkpFMjBvS3NZYmw2UkEiLCJvcmlnaW4iOiJodHRwOi8vbG9jYWx"
+ "ob3N0OjkwMDAiLCJjcm9zc09yaWdpbiI6ZmFsc2UsIm90aGVyX2tleXNfY2FuX2Jl"
+ "X2FkZGVkX2hlcmUiOiJkbyBub3QgY29tcGFyZSBjbGllbnREYXRhSlNPTiBhZ2Fpb"
+ "nN0IGEgdGVtcGxhdGUuIFNlZSBodHRwczovL2dvby5nbC95YWJQZXgifQ=="
),
"signature": (
"MEQCIFNlrHf9ablJAalXLWkrqvHB8oIu8kwvRpH3X3rbJVpI"
@@ -306,14 +304,12 @@ class AuthenticatorValidateStageWebAuthnTests(FlowTestCase):
"assertionClientExtensions": "{}",
"response": {
"clientDataJSON": (
- (
- "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiZzk4STUxbVF2Wlhv"
- "NWx4TGZockQyemZvbGhaYkxSeUNncWtrWWFwMWp3U2FKMTNCZ3VvSldDRjlfTGcz"
- "QWdPNFdoLUJxYTU1NkpFMjBvS3NZYmw2UkEiLCJvcmlnaW4iOiJodHRwOi8vbG9j"
- "YWxob3N0OjkwMDAiLCJjcm9zc09yaWdpbiI6ZmFsc2UsIm90aGVyX2tleXNfY2Fu"
- "X2JlX2FkZGVkX2hlcmUiOiJkbyBub3QgY29tcGFyZSBjbGllbnREYXRhSlNPTiBh"
- "Z2FpbnN0IGEgdGVtcGxhdGUuIFNlZSBodHRwczovL2dvby5nbC95YWJQZXgifQ=="
- ),
+ "eyJ0eXBlIjoid2ViYXV0aG4uZ2V0IiwiY2hhbGxlbmdlIjoiZzk4STUxbVF2Wlhv"
+ "NWx4TGZockQyemZvbGhaYkxSeUNncWtrWWFwMWp3U2FKMTNCZ3VvSldDRjlfTGcz"
+ "QWdPNFdoLUJxYTU1NkpFMjBvS3NZYmw2UkEiLCJvcmlnaW4iOiJodHRwOi8vbG9j"
+ "YWxob3N0OjkwMDAiLCJjcm9zc09yaWdpbiI6ZmFsc2UsIm90aGVyX2tleXNfY2Fu"
+ "X2JlX2FkZGVkX2hlcmUiOiJkbyBub3QgY29tcGFyZSBjbGllbnREYXRhSlNPTiBh"
+ "Z2FpbnN0IGEgdGVtcGxhdGUuIFNlZSBodHRwczovL2dvby5nbC95YWJQZXgifQ=="
),
"signature": (
"MEQCIFNlrHf9ablJAalXLWkrqvHB8oIu8kwvRpH3X3rbJVpI"
diff --git a/authentik/stages/authenticator_webauthn/stage.py b/authentik/stages/authenticator_webauthn/stage.py
index 41132f4aa..153409879 100644
--- a/authentik/stages/authenticator_webauthn/stage.py
+++ b/authentik/stages/authenticator_webauthn/stage.py
@@ -1,13 +1,10 @@
"""WebAuthn stage"""
-from json import dumps, loads
-
from django.http import HttpRequest, HttpResponse
from django.http.request import QueryDict
from rest_framework.fields import CharField, JSONField
from rest_framework.serializers import ValidationError
from webauthn.helpers.bytes_to_base64url import bytes_to_base64url
from webauthn.helpers.exceptions import InvalidRegistrationResponse
-from webauthn.helpers.options_to_json import options_to_json
from webauthn.helpers.structs import (
AuthenticatorSelectionCriteria,
PublicKeyCredentialCreationOptions,
@@ -55,7 +52,7 @@ class AuthenticatorWebAuthnChallengeResponse(ChallengeResponse):
try:
registration: VerifiedRegistration = verify_registration_response(
- credential=RegistrationCredential.parse_raw(dumps(response)),
+ credential=RegistrationCredential.model_validate(response),
expected_challenge=challenge,
expected_rp_id=get_rp_id(self.request),
expected_origin=get_origin(self.request),
@@ -108,7 +105,12 @@ class AuthenticatorWebAuthnStageView(ChallengeStageView):
return AuthenticatorWebAuthnChallenge(
data={
"type": ChallengeTypes.NATIVE.value,
- "registration": loads(options_to_json(registration_options)),
+ "registration": registration_options.model_dump(
+ mode="json",
+ by_alias=True,
+ exclude_unset=False,
+ exclude_none=True,
+ ),
}
)
diff --git a/blueprints/schema.json b/blueprints/schema.json
index e405ffea5..fc14ff613 100644
--- a/blueprints/schema.json
+++ b/blueprints/schema.json
@@ -8471,7 +8471,10 @@
"title": "Type"
},
"password": {
- "type": "string",
+ "type": [
+ "string",
+ "null"
+ ],
"minLength": 1,
"title": "Password"
}
diff --git a/go.mod b/go.mod
index 8c15ae221..24e205327 100644
--- a/go.mod
+++ b/go.mod
@@ -13,20 +13,20 @@ require (
github.com/go-openapi/runtime v0.26.0
github.com/go-openapi/strfmt v0.21.7
github.com/golang-jwt/jwt v3.2.2+incompatible
- github.com/google/uuid v1.3.0
+ github.com/google/uuid v1.3.1
github.com/gorilla/handlers v1.5.1
github.com/gorilla/mux v1.8.0
github.com/gorilla/securecookie v1.1.1
github.com/gorilla/sessions v1.2.1
github.com/gorilla/websocket v1.5.0
- github.com/jellydator/ttlcache/v3 v3.0.1
+ github.com/jellydator/ttlcache/v3 v3.1.0
github.com/nmcclain/asn1-ber v0.0.0-20170104154839-2661553a0484
github.com/pires/go-proxyproto v0.7.0
github.com/prometheus/client_golang v1.16.0
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.7.0
github.com/stretchr/testify v1.8.4
- goauthentik.io/api/v3 v3.2023061.12
+ goauthentik.io/api/v3 v3.2023061.13
golang.org/x/exp v0.0.0-20230210204819-062eb4c674ab
golang.org/x/oauth2 v0.11.0
golang.org/x/sync v0.3.0
diff --git a/go.sum b/go.sum
index d117a77ec..431d21471 100644
--- a/go.sum
+++ b/go.sum
@@ -859,8 +859,9 @@ github.com/google/s2a-go v0.1.3/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkj
github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
+github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
github.com/googleapis/enterprise-certificate-proxy v0.1.0/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8=
github.com/googleapis/enterprise-certificate-proxy v0.2.0/go.mod h1:8C0jb7/mgJe/9KK8Lm7X9ctZC2t60YyIpYEI16jx0Qg=
@@ -903,8 +904,8 @@ github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
-github.com/jellydator/ttlcache/v3 v3.0.1 h1:cHgCSMS7TdQcoprXnWUptJZzyFsqs18Lt8VVhRuZYVU=
-github.com/jellydator/ttlcache/v3 v3.0.1/go.mod h1:WwTaEmcXQ3MTjOm4bsZoDFiCu/hMvNWLO1w67RXz6h4=
+github.com/jellydator/ttlcache/v3 v3.1.0 h1:0gPFG0IHHP6xyUyXq+JaD8fwkDCqgqwohXNJBcYE71g=
+github.com/jellydator/ttlcache/v3 v3.1.0/go.mod h1:hi7MGFdMAwZna5n2tuvh63DvFLzVKySzCVW6+0gA2n4=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
@@ -1069,9 +1070,9 @@ go.opentelemetry.io/otel/trace v1.14.0/go.mod h1:8avnQLK+CG77yNLUae4ea2JDQ6iT+go
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.opentelemetry.io/proto/otlp v0.15.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
go.opentelemetry.io/proto/otlp v0.19.0/go.mod h1:H7XAot3MsfNsj7EXtrA2q5xSNQ10UqI405h3+duxN4U=
-go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0=
-goauthentik.io/api/v3 v3.2023061.12 h1:VtxeDeOpEtO8DXHVSYnhVQwtD80zIrwWSnI8b7lJlb0=
-goauthentik.io/api/v3 v3.2023061.12/go.mod h1:sP1/Ak/vGw96xNgpyoObHgXfyAElcTN5CbbC+VdPQXk=
+go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
+goauthentik.io/api/v3 v3.2023061.13 h1:0V5XrryJdMrOug/5wWazmH+D3Y/dDGPyLDhWcbJ5Gm0=
+goauthentik.io/api/v3 v3.2023061.13/go.mod h1:sP1/Ak/vGw96xNgpyoObHgXfyAElcTN5CbbC+VdPQXk=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
@@ -1133,7 +1134,6 @@ golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRu
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
-golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
@@ -1454,7 +1454,6 @@ golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.3.0/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
-golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4=
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
diff --git a/internal/config/config.go b/internal/config/config.go
index 0b50729f9..ac37d277e 100644
--- a/internal/config/config.go
+++ b/internal/config/config.go
@@ -1,67 +1,102 @@
package config
import (
+ _ "embed"
"errors"
"fmt"
"net/url"
"os"
+ "path/filepath"
"reflect"
"strings"
env "github.com/Netflix/go-env"
log "github.com/sirupsen/logrus"
+ "goauthentik.io/authentik/lib"
"gopkg.in/yaml.v2"
)
var cfg *Config
+const defaultConfigPath = "./authentik/lib/default.yml"
+
+func getConfigPaths() []string {
+ configPaths := []string{defaultConfigPath, "/etc/authentik/config.yml", ""}
+ globConfigPaths, _ := filepath.Glob("/etc/authentik/config.d/*.yml")
+ configPaths = append(configPaths, globConfigPaths...)
+
+ environment := "local"
+ if v, ok := os.LookupEnv("AUTHENTIK_ENV"); ok {
+ environment = v
+ }
+
+ computedConfigPaths := []string{}
+
+ for _, path := range configPaths {
+ path, err := filepath.Abs(path)
+ if err != nil {
+ continue
+ }
+ if stat, err := os.Stat(path); err == nil {
+ if !stat.IsDir() {
+ computedConfigPaths = append(computedConfigPaths, path)
+ } else {
+ envPaths := []string{
+ filepath.Join(path, environment+".yml"),
+ filepath.Join(path, environment+".env.yml"),
+ }
+ for _, envPath := range envPaths {
+ if stat, err = os.Stat(envPath); err == nil && !stat.IsDir() {
+ computedConfigPaths = append(computedConfigPaths, envPath)
+ }
+ }
+ }
+ }
+ }
+
+ return computedConfigPaths
+}
+
func Get() *Config {
if cfg == nil {
- c := defaultConfig()
- c.Setup("./authentik/lib/default.yml", "/etc/authentik/config.yml", "./local.env.yml")
+ c := &Config{}
+ c.Setup(getConfigPaths()...)
cfg = c
}
return cfg
}
-func defaultConfig() *Config {
- return &Config{
- Debug: false,
- Listen: ListenConfig{
- HTTP: "0.0.0.0:9000",
- HTTPS: "0.0.0.0:9443",
- LDAP: "0.0.0.0:3389",
- LDAPS: "0.0.0.0:6636",
- Radius: "0.0.0.0:1812",
- Metrics: "0.0.0.0:9300",
- Debug: "0.0.0.0:9900",
- },
- Paths: PathsConfig{
- Media: "./media",
- },
- LogLevel: "info",
- ErrorReporting: ErrorReportingConfig{
- Enabled: false,
- SampleRate: 1,
- },
- }
-}
-
func (c *Config) Setup(paths ...string) {
+ // initially try to load the default config which is compiled in
+ err := c.LoadConfig(lib.DefaultConfig())
+ // this should never fail
+ if err != nil {
+ panic(fmt.Errorf("failed to load inbuilt config: %v", err))
+ }
+ log.WithField("path", "inbuilt-default").Debug("Loaded config")
for _, path := range paths {
- err := c.LoadConfig(path)
+ err := c.LoadConfigFromFile(path)
if err != nil {
log.WithError(err).Info("failed to load config, skipping")
}
}
- err := c.fromEnv()
+ err = c.fromEnv()
if err != nil {
log.WithError(err).Info("failed to load env vars")
}
c.configureLogger()
}
-func (c *Config) LoadConfig(path string) error {
+func (c *Config) LoadConfig(raw []byte) error {
+ err := yaml.Unmarshal(raw, c)
+ if err != nil {
+ return fmt.Errorf("failed to parse YAML: %w", err)
+ }
+ c.walkScheme(c)
+ return nil
+}
+
+func (c *Config) LoadConfigFromFile(path string) error {
raw, err := os.ReadFile(path)
if err != nil {
if errors.Is(err, os.ErrNotExist) {
@@ -69,11 +104,10 @@ func (c *Config) LoadConfig(path string) error {
}
return fmt.Errorf("failed to load config file: %w", err)
}
- err = yaml.Unmarshal(raw, c)
+ err = c.LoadConfig(raw)
if err != nil {
- return fmt.Errorf("failed to parse YAML: %w", err)
+ return err
}
- c.walkScheme(c)
log.WithField("path", path).Debug("Loaded config")
return nil
}
diff --git a/internal/outpost/proxyv2/application/application.go b/internal/outpost/proxyv2/application/application.go
index 324909562..3c8af5af3 100644
--- a/internal/outpost/proxyv2/application/application.go
+++ b/internal/outpost/proxyv2/application/application.go
@@ -55,6 +55,8 @@ type Application struct {
errorTemplates *template.Template
authHeaderCache *ttlcache.Cache[string, Claims]
+
+ isEmbedded bool
}
type Server interface {
@@ -86,15 +88,15 @@ func NewApplication(p api.ProxyOutpostConfig, c *http.Client, server Server) (*A
CallbackSignature: []string{"true"},
}.Encode()
- managed := false
+ isEmbedded := false
if m := server.API().Outpost.Managed.Get(); m != nil {
- managed = *m == "goauthentik.io/outposts/embedded"
+ isEmbedded = *m == "goauthentik.io/outposts/embedded"
}
// Configure an OpenID Connect aware OAuth2 client.
endpoint := GetOIDCEndpoint(
p,
server.API().Outpost.Config["authentik_host"].(string),
- managed,
+ isEmbedded,
)
verifier := oidc.NewVerifier(endpoint.Issuer, ks, &oidc.Config{
@@ -132,6 +134,7 @@ func NewApplication(p api.ProxyOutpostConfig, c *http.Client, server Server) (*A
ak: server.API(),
authHeaderCache: ttlcache.New(ttlcache.WithDisableTouchOnHit[string, Claims]()),
srv: server,
+ isEmbedded: isEmbedded,
}
go a.authHeaderCache.Start()
a.sessions = a.getStore(p, externalHost)
diff --git a/internal/outpost/proxyv2/application/endpoint.go b/internal/outpost/proxyv2/application/endpoint.go
index 8029952b5..9a9145918 100644
--- a/internal/outpost/proxyv2/application/endpoint.go
+++ b/internal/outpost/proxyv2/application/endpoint.go
@@ -30,6 +30,7 @@ func updateURL(rawUrl string, scheme string, host string) string {
func GetOIDCEndpoint(p api.ProxyOutpostConfig, authentikHost string, embedded bool) OIDCEndpoint {
authUrl := p.OidcConfiguration.AuthorizationEndpoint
endUrl := p.OidcConfiguration.EndSessionEndpoint
+ jwksUri := p.OidcConfiguration.JwksUri
issuer := p.OidcConfiguration.Issuer
ep := OIDCEndpoint{
Endpoint: oauth2.Endpoint{
@@ -38,10 +39,14 @@ func GetOIDCEndpoint(p api.ProxyOutpostConfig, authentikHost string, embedded bo
AuthStyle: oauth2.AuthStyleInParams,
},
EndSessionEndpoint: endUrl,
- JwksUri: p.OidcConfiguration.JwksUri,
+ JwksUri: jwksUri,
TokenIntrospection: p.OidcConfiguration.IntrospectionEndpoint,
Issuer: issuer,
}
+ aku, err := url.Parse(authentikHost)
+ if err != nil {
+ return ep
+ }
// For the embedded outpost, we use the configure `authentik_host` for the browser URLs
// and localhost (which is what we've got from the API) for backchannel URLs
//
@@ -51,27 +56,24 @@ func GetOIDCEndpoint(p api.ProxyOutpostConfig, authentikHost string, embedded bo
if !embedded && hostBrowser == "" {
return ep
}
- var newHost *url.URL
+ var newHost *url.URL = aku
+ var newBrowserHost *url.URL
if embedded {
if authentikHost == "" {
log.Warning("Outpost has localhost/blank API Connection but no authentik_host is configured.")
return ep
}
- aku, err := url.Parse(authentikHost)
- if err != nil {
- return ep
- }
- newHost = aku
+ newBrowserHost = aku
} else if hostBrowser != "" {
- aku, err := url.Parse(hostBrowser)
+ browser, err := url.Parse(hostBrowser)
if err != nil {
return ep
}
- newHost = aku
+ newBrowserHost = browser
}
// Update all browser-accessed URLs to use the new host and scheme
- ep.AuthURL = updateURL(authUrl, newHost.Scheme, newHost.Host)
- ep.EndSessionEndpoint = updateURL(endUrl, newHost.Scheme, newHost.Host)
+ ep.AuthURL = updateURL(authUrl, newBrowserHost.Scheme, newBrowserHost.Host)
+ ep.EndSessionEndpoint = updateURL(endUrl, newBrowserHost.Scheme, newBrowserHost.Host)
// Update issuer to use the same host and scheme, which would normally break as we don't
// change the token URL here, but the token HTTP transport overwrites the Host header
//
@@ -79,6 +81,7 @@ func GetOIDCEndpoint(p api.ProxyOutpostConfig, authentikHost string, embedded bo
// is routed correctly
if embedded {
ep.Issuer = updateURL(ep.Issuer, newHost.Scheme, newHost.Host)
+ ep.JwksUri = updateURL(jwksUri, newHost.Scheme, newHost.Host)
}
return ep
}
diff --git a/internal/outpost/proxyv2/application/endpoint_test.go b/internal/outpost/proxyv2/application/endpoint_test.go
index cf267350a..d3d0f7426 100644
--- a/internal/outpost/proxyv2/application/endpoint_test.go
+++ b/internal/outpost/proxyv2/application/endpoint_test.go
@@ -82,7 +82,7 @@ func TestEndpointEmbedded(t *testing.T) {
assert.Equal(t, "https://authentik-host.test.goauthentik.io/application/o/authorize/", ep.AuthURL)
assert.Equal(t, "https://authentik-host.test.goauthentik.io/application/o/test-app/", ep.Issuer)
assert.Equal(t, "https://test.goauthentik.io/application/o/token/", ep.TokenURL)
- assert.Equal(t, "https://test.goauthentik.io/application/o/test-app/jwks/", ep.JwksUri)
+ assert.Equal(t, "https://authentik-host.test.goauthentik.io/application/o/test-app/jwks/", ep.JwksUri)
assert.Equal(t, "https://authentik-host.test.goauthentik.io/application/o/test-app/end-session/", ep.EndSessionEndpoint)
assert.Equal(t, "https://test.goauthentik.io/application/o/introspect/", ep.TokenIntrospection)
}
diff --git a/internal/outpost/proxyv2/application/session.go b/internal/outpost/proxyv2/application/session.go
index a6c36ae73..bf426c10e 100644
--- a/internal/outpost/proxyv2/application/session.go
+++ b/internal/outpost/proxyv2/application/session.go
@@ -29,7 +29,7 @@ func (a *Application) getStore(p api.ProxyOutpostConfig, externalHost *url.URL)
// Add one to the validity to ensure we don't have a session with indefinite length
maxAge = int(*t) + 1
}
- if config.Get().Redis.Host != "" {
+ if a.isEmbedded {
rs, err := redistore.NewRediStoreWithDB(10, "tcp", fmt.Sprintf("%s:%d", config.Get().Redis.Host, config.Get().Redis.Port), config.Get().Redis.Password, strconv.Itoa(config.Get().Redis.DB))
if err != nil {
panic(err)
diff --git a/ldap.Dockerfile b/ldap.Dockerfile
index 8fb9002b1..2bd4dc2c6 100644
--- a/ldap.Dockerfile
+++ b/ldap.Dockerfile
@@ -1,5 +1,5 @@
# Stage 1: Build
-FROM docker.io/golang:1.21.0-bullseye AS builder
+FROM docker.io/golang:1.21.0-bookworm AS builder
WORKDIR /go/src/goauthentik.io
diff --git a/locale/en/LC_MESSAGES/django.po b/locale/en/LC_MESSAGES/django.po
index ebdc06553..069fcadd6 100644
--- a/locale/en/LC_MESSAGES/django.po
+++ b/locale/en/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2023-08-17 17:37+0000\n"
+"POT-Creation-Date: 2023-08-23 10:04+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
@@ -98,125 +98,125 @@ msgstr ""
msgid "Users added to this group will be superusers."
msgstr ""
-#: authentik/core/models.py:162
+#: authentik/core/models.py:142
msgid "User's display name."
msgstr ""
-#: authentik/core/models.py:256 authentik/providers/oauth2/models.py:294
+#: authentik/core/models.py:268 authentik/providers/oauth2/models.py:294
msgid "User"
msgstr ""
-#: authentik/core/models.py:257
+#: authentik/core/models.py:269
msgid "Users"
msgstr ""
-#: authentik/core/models.py:270
+#: authentik/core/models.py:282
msgid ""
"Flow used for authentication when the associated application is accessed by "
"an un-authenticated user."
msgstr ""
-#: authentik/core/models.py:280
+#: authentik/core/models.py:292
msgid "Flow used when authorizing this provider."
msgstr ""
-#: authentik/core/models.py:292
+#: authentik/core/models.py:304
msgid ""
"Accessed from applications; optional backchannel providers for protocols "
"like LDAP and SCIM."
msgstr ""
-#: authentik/core/models.py:347
+#: authentik/core/models.py:359
msgid "Application's display Name."
msgstr ""
-#: authentik/core/models.py:348
+#: authentik/core/models.py:360
msgid "Internal application name, used in URLs."
msgstr ""
-#: authentik/core/models.py:360
+#: authentik/core/models.py:372
msgid "Open launch URL in a new browser tab or window."
msgstr ""
-#: authentik/core/models.py:424
+#: authentik/core/models.py:436
msgid "Application"
msgstr ""
-#: authentik/core/models.py:425
+#: authentik/core/models.py:437
msgid "Applications"
msgstr ""
-#: authentik/core/models.py:431
+#: authentik/core/models.py:443
msgid "Use the source-specific identifier"
msgstr ""
-#: authentik/core/models.py:433
+#: authentik/core/models.py:445
msgid ""
"Link to a user with identical email address. Can have security implications "
"when a source doesn't validate email addresses."
msgstr ""
-#: authentik/core/models.py:437
+#: authentik/core/models.py:449
msgid ""
"Use the user's email address, but deny enrollment when the email address "
"already exists."
msgstr ""
-#: authentik/core/models.py:440
+#: authentik/core/models.py:452
msgid ""
"Link to a user with identical username. Can have security implications when "
"a username is used with another source."
msgstr ""
-#: authentik/core/models.py:444
+#: authentik/core/models.py:456
msgid ""
"Use the user's username, but deny enrollment when the username already "
"exists."
msgstr ""
-#: authentik/core/models.py:451
+#: authentik/core/models.py:463
msgid "Source's display Name."
msgstr ""
-#: authentik/core/models.py:452
+#: authentik/core/models.py:464
msgid "Internal source name, used in URLs."
msgstr ""
-#: authentik/core/models.py:471
+#: authentik/core/models.py:483
msgid "Flow to use when authenticating existing users."
msgstr ""
-#: authentik/core/models.py:480
+#: authentik/core/models.py:492
msgid "Flow to use when enrolling new users."
msgstr ""
-#: authentik/core/models.py:488
+#: authentik/core/models.py:500
msgid ""
"How the source determines if an existing user should be authenticated or a "
"new user enrolled."
msgstr ""
-#: authentik/core/models.py:660
+#: authentik/core/models.py:672
msgid "Token"
msgstr ""
-#: authentik/core/models.py:661
+#: authentik/core/models.py:673
msgid "Tokens"
msgstr ""
-#: authentik/core/models.py:702
+#: authentik/core/models.py:714
msgid "Property Mapping"
msgstr ""
-#: authentik/core/models.py:703
+#: authentik/core/models.py:715
msgid "Property Mappings"
msgstr ""
-#: authentik/core/models.py:738
+#: authentik/core/models.py:750
msgid "Authenticated Session"
msgstr ""
-#: authentik/core/models.py:739
+#: authentik/core/models.py:751
msgid "Authenticated Sessions"
msgstr ""
diff --git a/locale/nl/LC_MESSAGES/django.mo b/locale/nl/LC_MESSAGES/django.mo
new file mode 100644
index 000000000..2e7e7fc26
Binary files /dev/null and b/locale/nl/LC_MESSAGES/django.mo differ
diff --git a/locale/nl/LC_MESSAGES/django.po b/locale/nl/LC_MESSAGES/django.po
new file mode 100644
index 000000000..e68eef205
--- /dev/null
+++ b/locale/nl/LC_MESSAGES/django.po
@@ -0,0 +1,2746 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR , YEAR.
+#
+# Translators:
+# Dany Sluijk, 2022
+# Alex Kruidenberg , 2022
+# Melvin Snijders , 2023
+# Michel Heusschen, 2023
+# ServusNL, 2023
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2023-08-23 10:04+0000\n"
+"PO-Revision-Date: 2022-09-26 16:47+0000\n"
+"Last-Translator: ServusNL, 2023\n"
+"Language-Team: Dutch (https://app.transifex.com/authentik/teams/119923/nl/)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Language: nl\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: authentik/admin/api/tasks.py:125
+#, python-format
+msgid "Successfully re-scheduled Task %(name)s!"
+msgstr "Taak %(name)s succesvol opnieuw ingepland!"
+
+#: authentik/api/schema.py:24
+msgid "Generic API Error"
+msgstr "Algemene API-fout"
+
+#: authentik/api/schema.py:32
+msgid "Validation Error"
+msgstr "Validatiefout"
+
+#: authentik/blueprints/api.py:44
+msgid "Blueprint file does not exist"
+msgstr "Blauwdrukbestand bestaat niet"
+
+#: authentik/blueprints/api.py:55
+#, python-format
+msgid "Failed to validate blueprint: %(logs)s"
+msgstr "Blauwdrukvalidatie is mislukt: %(logs)s"
+
+#: authentik/blueprints/api.py:60
+msgid "Either path or content must be set."
+msgstr "Ofwel het pad of de inhoud moet worden ingesteld."
+
+#: authentik/blueprints/models.py:30
+msgid "Managed by authentik"
+msgstr "Beheerd door authentik"
+
+#: authentik/blueprints/models.py:32
+msgid ""
+"Objects that are managed by authentik. These objects are created and updated"
+" automatically. This flag only indicates that an object can be overwritten "
+"by migrations. You can still modify the objects via the API, but expect "
+"changes to be overwritten in a later update."
+msgstr ""
+"Objecten die worden beheerd door authentik. Deze objecten worden automatisch"
+" aangemaakt en bijgewerkt. Deze vlag geeft alleen aan dat een object kan "
+"worden overschreven door migraties. U kunt de objecten nog steeds wijzigen "
+"via de API, maar verwacht dat wijzigingen in een latere update worden "
+"overschreven."
+
+#: authentik/blueprints/models.py:112
+msgid "Blueprint Instance"
+msgstr "Blauwdruk Instantie"
+
+#: authentik/blueprints/models.py:113
+msgid "Blueprint Instances"
+msgstr "Blauwdruk Instanties"
+
+#: authentik/blueprints/v1/exporter.py:62
+#, python-format
+msgid "authentik Export - %(date)s"
+msgstr "authentik Export - %(date)s"
+
+#: authentik/blueprints/v1/tasks.py:150 authentik/crypto/tasks.py:93
+#, python-format
+msgid "Successfully imported %(count)d files."
+msgstr "%(count)d bestanden succesvol geïmporteerd."
+
+#: authentik/core/api/providers.py:120
+msgid "SAML Provider from Metadata"
+msgstr "SAML-provider uit metagegevens"
+
+#: authentik/core/api/providers.py:121
+msgid "Create a SAML Provider by importing its Metadata."
+msgstr "Maak een SAML-provider door de metagegevens te importeren."
+
+#: authentik/core/api/users.py:150
+msgid "No leading or trailing slashes allowed."
+msgstr "Geen voor- of achtervoegsels toegestaan."
+
+#: authentik/core/api/users.py:153
+msgid "No empty segments in user path allowed."
+msgstr "Geen lege segmenten in het gebruikerspad toegestaan."
+
+#: authentik/core/models.py:86
+msgid "name"
+msgstr "naam"
+
+#: authentik/core/models.py:88
+msgid "Users added to this group will be superusers."
+msgstr ""
+"Gebruikers die aan deze groep worden toegevoegd, worden supergebruikers."
+
+#: authentik/core/models.py:142
+msgid "User's display name."
+msgstr "Weergavenaam van de gebruiker."
+
+#: authentik/core/models.py:268 authentik/providers/oauth2/models.py:294
+msgid "User"
+msgstr "Gebruiker"
+
+#: authentik/core/models.py:269
+msgid "Users"
+msgstr "Gebruikers"
+
+#: authentik/core/models.py:282
+msgid ""
+"Flow used for authentication when the associated application is accessed by "
+"an un-authenticated user."
+msgstr ""
+"Flow gebruikt voor authenticatie wanneer de bijbehorende applicatie wordt "
+"geopend door een niet-geauthenticeerde gebruiker."
+
+#: authentik/core/models.py:292
+msgid "Flow used when authorizing this provider."
+msgstr "Flow gebruikt bij het autoriseren van deze provider."
+
+#: authentik/core/models.py:304
+msgid ""
+"Accessed from applications; optional backchannel providers for protocols "
+"like LDAP and SCIM."
+msgstr ""
+"Toegankelijk vanuit applicaties; optionele backchannel-providers voor "
+"protocollen zoals LDAP en SCIM."
+
+#: authentik/core/models.py:359
+msgid "Application's display Name."
+msgstr "Weergavenaam van de applicatie."
+
+#: authentik/core/models.py:360
+msgid "Internal application name, used in URLs."
+msgstr "Interne naam van de applicatie, gebruikt in URL's."
+
+#: authentik/core/models.py:372
+msgid "Open launch URL in a new browser tab or window."
+msgstr "Open de lanceer-URL in een nieuw browser-tabblad of venster."
+
+#: authentik/core/models.py:436
+msgid "Application"
+msgstr "Applicatie"
+
+#: authentik/core/models.py:437
+msgid "Applications"
+msgstr "Applicaties"
+
+#: authentik/core/models.py:443
+msgid "Use the source-specific identifier"
+msgstr "Gebruik de bron-specifieke identificator"
+
+#: authentik/core/models.py:445
+msgid ""
+"Link to a user with identical email address. Can have security implications "
+"when a source doesn't validate email addresses."
+msgstr ""
+"Koppel aan een gebruiker met een identiek e-mailadres. Kan "
+"beveiligingsimplicaties hebben wanneer een bron e-mailadressen niet "
+"valideert."
+
+#: authentik/core/models.py:449
+msgid ""
+"Use the user's email address, but deny enrollment when the email address "
+"already exists."
+msgstr ""
+"Gebruik het e-mailadres van de gebruiker, maar weiger inschrijving als het "
+"e-mailadres al bestaat."
+
+#: authentik/core/models.py:452
+msgid ""
+"Link to a user with identical username. Can have security implications when "
+"a username is used with another source."
+msgstr ""
+"Koppel aan een gebruiker met dezelfde gebruikersnaam. Kan "
+"beveiligingsimplicaties hebben wanneer een gebruikersnaam wordt gebruikt met"
+" een andere bron."
+
+#: authentik/core/models.py:456
+msgid ""
+"Use the user's username, but deny enrollment when the username already "
+"exists."
+msgstr ""
+"Gebruik de gebruikersnaam van de gebruiker, maar weiger inschrijving als de "
+"gebruikersnaam al bestaat."
+
+#: authentik/core/models.py:463
+msgid "Source's display Name."
+msgstr "Weergavenaam van de bron."
+
+#: authentik/core/models.py:464
+msgid "Internal source name, used in URLs."
+msgstr "Interne naam van de bron, gebruikt in URL's."
+
+#: authentik/core/models.py:483
+msgid "Flow to use when authenticating existing users."
+msgstr "Flow om te gebruiken bij het authenticeren van bestaande gebruikers."
+
+#: authentik/core/models.py:492
+msgid "Flow to use when enrolling new users."
+msgstr "Flow om te gebruiken bij het inschrijven van nieuwe gebruikers."
+
+#: authentik/core/models.py:500
+msgid ""
+"How the source determines if an existing user should be authenticated or a "
+"new user enrolled."
+msgstr ""
+"Hoe de bron bepaalt of een bestaande gebruiker moet worden geauthenticeerd "
+"of een nieuwe gebruiker moet worden ingeschreven."
+
+#: authentik/core/models.py:672
+msgid "Token"
+msgstr "Token"
+
+#: authentik/core/models.py:673
+msgid "Tokens"
+msgstr "Tokens"
+
+#: authentik/core/models.py:714
+msgid "Property Mapping"
+msgstr "Eigenschapskoppeling"
+
+#: authentik/core/models.py:715
+msgid "Property Mappings"
+msgstr "Eigenschapskoppelingen"
+
+#: authentik/core/models.py:750
+msgid "Authenticated Session"
+msgstr "Geauthenticeerde Sessie"
+
+#: authentik/core/models.py:751
+msgid "Authenticated Sessions"
+msgstr "Geauthenticeerde Sessies"
+
+#: authentik/core/sources/flow_manager.py:193
+#, python-format
+msgid ""
+"Request to authenticate with %(source)s has been denied. Please authenticate"
+" with the source you've previously signed up with."
+msgstr ""
+"Het verzoek om te authenticeren met %(source)s is geweigerd. Authenticeer "
+"alstublieft met de bron waarbij u zich eerder heeft aangemeld."
+
+#: authentik/core/sources/flow_manager.py:245
+msgid "Configured flow does not exist."
+msgstr "Geconfigureerde flow bestaat niet."
+
+#: authentik/core/sources/flow_manager.py:275
+#: authentik/core/sources/flow_manager.py:327
+#, python-format
+msgid "Successfully authenticated with %(source)s!"
+msgstr "Succesvol geauthenticeerd met %(source)s!"
+
+#: authentik/core/sources/flow_manager.py:299
+#, python-format
+msgid "Successfully linked %(source)s!"
+msgstr "Succesvol gekoppeld aan %(source)s!"
+
+#: authentik/core/sources/flow_manager.py:318
+msgid "Source is not configured for enrollment."
+msgstr "Bron is niet geconfigureerd voor inschrijving."
+
+#: authentik/core/templates/if/end_session.html:7
+msgid "End session"
+msgstr "Einde sessie"
+
+#: authentik/core/templates/if/end_session.html:11
+#, python-format
+msgid ""
+"\n"
+"You've logged out of %(application)s.\n"
+msgstr ""
+"\n"
+"U bent afgemeld bij %(application)s.\n"
+
+#: authentik/core/templates/if/end_session.html:19
+#, python-format
+msgid ""
+"\n"
+" You've logged out of %(application)s. You can go back to the overview to launch another application, or log out of your authentik account.\n"
+" "
+msgstr ""
+"\n"
+" U bent afgemeld bij %(application)s. U kunt teruggaan naar het overzicht om een andere applicatie te starten, of u kunt zich afmelden bij uw authentik-account.\n"
+
+#: authentik/core/templates/if/end_session.html:25
+msgid "Go back to overview"
+msgstr "Terug naar overzicht"
+
+#: authentik/core/templates/if/end_session.html:29
+#, python-format
+msgid ""
+"\n"
+" Log out of %(branding_title)s\n"
+" "
+msgstr ""
+"\n"
+" Meld u af bij %(branding_title)s\n"
+
+#: authentik/core/templates/if/end_session.html:36
+#, python-format
+msgid ""
+"\n"
+" Log back into %(application)s\n"
+" "
+msgstr ""
+"\n"
+" Meld u opnieuw aan bij %(application)s\n"
+
+#: authentik/core/templates/if/error.html:18
+msgid "Go home"
+msgstr "Ga naar startpagina"
+
+#: authentik/core/templates/login/base_full.html:90
+msgid "Powered by authentik"
+msgstr "Aangedreven door authentik"
+
+#: authentik/core/views/apps.py:53
+#: authentik/providers/oauth2/views/authorize.py:391
+#: authentik/providers/oauth2/views/device_init.py:70
+#: authentik/providers/saml/views/sso.py:70
+#, python-format
+msgid "You're about to sign into %(application)s."
+msgstr "U staat op het punt om in te loggen bij %(application)s."
+
+#: authentik/crypto/api.py:179
+msgid "Subject-alt name"
+msgstr "Alternatieve onderwerpsnaam"
+
+#: authentik/crypto/models.py:30
+msgid "PEM-encoded Certificate data"
+msgstr "PEM-gecodeerde certificaatgegevens"
+
+#: authentik/crypto/models.py:33
+msgid ""
+"Optional Private Key. If this is set, you can use this keypair for "
+"encryption."
+msgstr ""
+"Optionele privésleutel. Als deze is ingesteld, kunt u dit sleutelpaar "
+"gebruiken voor versleuteling."
+
+#: authentik/crypto/models.py:101
+msgid "Certificate-Key Pair"
+msgstr "Certificaat-Sleutelpaar"
+
+#: authentik/crypto/models.py:102
+msgid "Certificate-Key Pairs"
+msgstr "Certificaat-Sleutelparen"
+
+#: authentik/events/models.py:290
+msgid "Event"
+msgstr "Gebeurtenis"
+
+#: authentik/events/models.py:291
+msgid "Events"
+msgstr "Gebeurtenissen"
+
+#: authentik/events/models.py:297
+msgid "authentik inbuilt notifications"
+msgstr "authentik ingebouwde meldingen"
+
+#: authentik/events/models.py:298
+msgid "Generic Webhook"
+msgstr "Generieke Webhook"
+
+#: authentik/events/models.py:299
+msgid "Slack Webhook (Slack/Discord)"
+msgstr "Slack Webhook (Slack/Discord)"
+
+#: authentik/events/models.py:300
+msgid "Email"
+msgstr "E-mail"
+
+#: authentik/events/models.py:318
+msgid ""
+"Only send notification once, for example when sending a webhook into a chat "
+"channel."
+msgstr ""
+"Stuur de melding slechts eenmaal, bijvoorbeeld bij het verzenden van een "
+"webhook naar een chatkanaal."
+
+#: authentik/events/models.py:383
+msgid "Severity"
+msgstr "Ernst"
+
+#: authentik/events/models.py:388
+msgid "Dispatched for user"
+msgstr "Verzonden voor gebruiker"
+
+#: authentik/events/models.py:397
+msgid "Event user"
+msgstr "Gebruiker van gebeurtenis"
+
+#: authentik/events/models.py:484
+msgid "Notification Transport"
+msgstr "Meldingsvervoer"
+
+#: authentik/events/models.py:485
+msgid "Notification Transports"
+msgstr "Meldingsvervoer"
+
+#: authentik/events/models.py:491
+msgid "Notice"
+msgstr "Kennisgeving"
+
+#: authentik/events/models.py:492
+msgid "Warning"
+msgstr "Waarschuwing"
+
+#: authentik/events/models.py:493
+msgid "Alert"
+msgstr "Alarm"
+
+#: authentik/events/models.py:518
+msgid "Notification"
+msgstr "Melding"
+
+#: authentik/events/models.py:519
+msgid "Notifications"
+msgstr "Meldingen"
+
+#: authentik/events/models.py:529
+msgid ""
+"Select which transports should be used to notify the user. If none are "
+"selected, the notification will only be shown in the authentik UI."
+msgstr ""
+"Kies welke vervoersmiddelen moeten worden gebruikt om de gebruiker op de "
+"hoogte te stellen. Als er geen zijn geselecteerd, wordt de melding alleen "
+"getoond in de authentik-UI."
+
+#: authentik/events/models.py:537
+msgid "Controls which severity level the created notifications will have."
+msgstr "Regelt welk ernstniveau de aangemaakte meldingen zullen hebben."
+
+#: authentik/events/models.py:542
+msgid ""
+"Define which group of users this notification should be sent and shown to. "
+"If left empty, Notification won't ben sent."
+msgstr ""
+"Definieer welke groep gebruikers deze melding moet ontvangen en zien. Als "
+"dit leeg wordt gelaten, wordt er geen melding verzonden."
+
+#: authentik/events/models.py:560
+msgid "Notification Rule"
+msgstr "Meldingsregel"
+
+#: authentik/events/models.py:561
+msgid "Notification Rules"
+msgstr "Meldingsregels"
+
+#: authentik/events/models.py:581
+msgid "Webhook Mapping"
+msgstr "Webhook-toewijzing"
+
+#: authentik/events/models.py:582
+msgid "Webhook Mappings"
+msgstr "Webhook-toewijzingen"
+
+#: authentik/events/monitored_tasks.py:205
+msgid "Task has not been run yet."
+msgstr "Taak is nog niet uitgevoerd."
+
+#: authentik/flows/api/flows.py:295
+#, python-format
+msgid "Flow not applicable to current user/request: %(messages)s"
+msgstr ""
+"Flow is niet van toepassing op de huidige gebruiker/aanvraag: %(messages)s"
+
+#: authentik/flows/api/flows_diagram.py:68
+#: authentik/flows/api/flows_diagram.py:94
+#, python-format
+msgid "Policy (%(type)s)"
+msgstr "Beleid (%(type)s)"
+
+#: authentik/flows/api/flows_diagram.py:71
+#, python-format
+msgid "Binding %(order)d"
+msgstr "Bindend %(order)d"
+
+#: authentik/flows/api/flows_diagram.py:118
+msgid "Policy passed"
+msgstr "Beleid geslaagd"
+
+#: authentik/flows/api/flows_diagram.py:122
+#, python-format
+msgid "Stage (%(type)s)"
+msgstr "Fase (%(type)s)"
+
+#: authentik/flows/api/flows_diagram.py:146
+#: authentik/flows/api/flows_diagram.py:206
+msgid "Policy denied"
+msgstr "Beleid geweigerd"
+
+#: authentik/flows/api/flows_diagram.py:156
+#: authentik/flows/api/flows_diagram.py:168
+#: authentik/flows/api/flows_diagram.py:205
+#: authentik/flows/api/flows_diagram.py:227
+msgid "End of the flow"
+msgstr "Einde van de flow"
+
+#: authentik/flows/api/flows_diagram.py:169
+msgid "Requirement not fulfilled"
+msgstr "Vereiste niet vervuld"
+
+#: authentik/flows/api/flows_diagram.py:177
+msgid "Flow authentication requirement"
+msgstr "Authenticatievereiste voor flow"
+
+#: authentik/flows/api/flows_diagram.py:183
+msgid "Requirement fulfilled"
+msgstr "Vereiste vervuld"
+
+#: authentik/flows/api/flows_diagram.py:196
+msgid "Pre-flow policies"
+msgstr "Beleid voorafgaand aan flow"
+
+#: authentik/flows/api/flows_diagram.py:214 authentik/flows/models.py:193
+msgid "Flow"
+msgstr "Flow"
+
+#: authentik/flows/exceptions.py:19
+msgid "Flow does not apply to current user."
+msgstr "Flow is niet van toepassing op de huidige gebruiker."
+
+#: authentik/flows/models.py:114
+#, python-format
+msgid "Dynamic In-memory stage: %(doc)s"
+msgstr "Dynamische In-Memory fase: %(doc)s"
+
+#: authentik/flows/models.py:129
+msgid "Visible in the URL."
+msgstr "Zichtbaar in de URL."
+
+#: authentik/flows/models.py:131
+msgid "Shown as the Title in Flow pages."
+msgstr "Weergegeven als de titel op Flow-pagina's."
+
+#: authentik/flows/models.py:138
+msgid ""
+"Decides what this Flow is used for. For example, the Authentication flow is "
+"redirect to when an un-authenticated user visits authentik."
+msgstr ""
+"Bepaalt waarvoor deze Flow wordt gebruikt. Bijvoorbeeld, de "
+"Authenticatieflow wordt gebruikt wanneer een niet-geauthenticeerde gebruiker"
+" authentik bezoekt."
+
+#: authentik/flows/models.py:147
+msgid "Background shown during execution"
+msgstr "Achtergrond weergegeven tijdens uitvoering"
+
+#: authentik/flows/models.py:154
+msgid ""
+"Enable compatibility mode, increases compatibility with password managers on"
+" mobile devices."
+msgstr ""
+"Schakel compatibiliteitsmodus in, verhoogt de compatibiliteit met "
+"wachtwoordbeheerders op mobiele apparaten."
+
+#: authentik/flows/models.py:162
+msgid "Configure what should happen when a flow denies access to a user."
+msgstr ""
+"Configureer wat er moet gebeuren wanneer een flow de toegang tot een "
+"gebruiker weigert."
+
+#: authentik/flows/models.py:168
+msgid "Required level of authentication and authorization to access a flow."
+msgstr ""
+"Vereist niveau van authenticatie en autorisatie om toegang te krijgen tot "
+"een flow."
+
+#: authentik/flows/models.py:194
+msgid "Flows"
+msgstr "Stromen"
+
+#: authentik/flows/models.py:215
+msgid "Evaluate policies during the Flow planning process."
+msgstr "Evalueer beleid tijdens het planningsproces van de Flow."
+
+#: authentik/flows/models.py:219
+msgid "Evaluate policies when the Stage is present to the user."
+msgstr "Evalueer beleid wanneer het Stadium aan de gebruiker wordt getoond."
+
+#: authentik/flows/models.py:226
+msgid ""
+"Configure how the flow executor should handle an invalid response to a "
+"challenge. RETRY returns the error message and a similar challenge to the "
+"executor. RESTART restarts the flow from the beginning, and "
+"RESTART_WITH_CONTEXT restarts the flow while keeping the current context."
+msgstr ""
+"Configureer hoe de flowuitvoerder moet omgaan met een ongeldige reactie op "
+"een uitdaging. RETRY geeft het foutbericht en een soortgelijke uitdaging "
+"terug aan de uitvoerder. RESTART start de flow opnieuw vanaf het begin, en "
+"RESTART_WITH_CONTEXT start de flow opnieuw terwijl de huidige context "
+"behouden blijft."
+
+#: authentik/flows/models.py:249
+msgid "Flow Stage Binding"
+msgstr "Flowfasebinding"
+
+#: authentik/flows/models.py:250
+msgid "Flow Stage Bindings"
+msgstr "Flowfasebindingen"
+
+#: authentik/flows/models.py:265
+msgid ""
+"Flow used by an authenticated user to configure this Stage. If empty, user "
+"will not be able to configure this stage."
+msgstr ""
+"Flow gebruikt door een geauthenticeerde gebruiker om deze fase te "
+"configureren. Als leeg, zal de gebruiker deze fase niet kunnen configureren."
+
+#: authentik/flows/models.py:305
+msgid "Flow Token"
+msgstr "Flowtoken"
+
+#: authentik/flows/models.py:306
+msgid "Flow Tokens"
+msgstr "Flowtokens"
+
+#: authentik/lib/utils/time.py:27
+#, python-format
+msgid "%(value)s is not in the correct format of 'hours=3;minutes=1'."
+msgstr "%(value)s heeft niet het juiste formaat van 'uren=3;minuten=1'."
+
+#: authentik/outposts/api/service_connections.py:127
+msgid ""
+"You can only use an empty kubeconfig when connecting to a local cluster."
+msgstr ""
+"U kunt alleen een lege kubeconfig gebruiken bij het verbinden met een lokale"
+" cluster."
+
+#: authentik/outposts/api/service_connections.py:135
+msgid "Invalid kubeconfig"
+msgstr "Ongeldige kubeconfig"
+
+#: authentik/outposts/models.py:122
+msgid ""
+"If enabled, use the local connection. Required Docker socket/Kubernetes "
+"Integration"
+msgstr ""
+"Indien ingeschakeld, gebruik de lokale verbinding. Vereist Docker-"
+"socket/Kubernetes-integratie."
+
+#: authentik/outposts/models.py:152
+msgid "Outpost Service-Connection"
+msgstr "Buitenpost Service-verbinding"
+
+#: authentik/outposts/models.py:153
+msgid "Outpost Service-Connections"
+msgstr "Buitenpost Service-verbindingen"
+
+#: authentik/outposts/models.py:161
+msgid ""
+"Can be in the format of 'unix://' when connecting to a local docker "
+"daemon, or 'https://:2376' when connecting to a remote system."
+msgstr ""
+"Kan in het formaat 'unix://' zijn bij het verbinden met een lokale "
+"dockerdaemon, of 'https://:2376' bij het verbinden met een extern "
+"systeem."
+
+#: authentik/outposts/models.py:173
+msgid ""
+"CA which the endpoint's Certificate is verified against. Can be left empty "
+"for no validation."
+msgstr ""
+"CA waartegen het certificaat van de eindpunt wordt geverifieerd. Kan leeg "
+"worden gelaten voor geen validatie."
+
+#: authentik/outposts/models.py:185
+msgid ""
+"Certificate/Key used for authentication. Can be left empty for no "
+"authentication."
+msgstr ""
+"Certificaat/Sleutel gebruikt voor authenticatie. Kan leeg worden gelaten "
+"voor geen authenticatie."
+
+#: authentik/outposts/models.py:203
+msgid "Docker Service-Connection"
+msgstr "Docker Service-verbinding"
+
+#: authentik/outposts/models.py:204
+msgid "Docker Service-Connections"
+msgstr "Docker Service-verbindingen"
+
+#: authentik/outposts/models.py:212
+msgid ""
+"Paste your kubeconfig here. authentik will automatically use the currently "
+"selected context."
+msgstr ""
+"Plak hier uw kubeconfig. Authentik zal automatisch de momenteel "
+"geselecteerde context gebruiken."
+
+#: authentik/outposts/models.py:218
+msgid "Verify SSL Certificates of the Kubernetes API endpoint"
+msgstr "SSL-certificaten van het Kubernetes API-eindpunt verifiëren"
+
+#: authentik/outposts/models.py:235
+msgid "Kubernetes Service-Connection"
+msgstr "Kubernetes Service-verbinding"
+
+#: authentik/outposts/models.py:236
+msgid "Kubernetes Service-Connections"
+msgstr "Kubernetes Service-verbindingen"
+
+#: authentik/outposts/models.py:252
+msgid ""
+"Select Service-Connection authentik should use to manage this outpost. Leave"
+" empty if authentik should not handle the deployment."
+msgstr ""
+"Selecteer de Service-verbinding die authentik moet gebruiken om deze "
+"buitenpost te beheren. Laat leeg als authentik de implementatie niet moet "
+"afhandelen."
+
+#: authentik/policies/denied.py:24
+msgid "Access denied"
+msgstr "Toegang geweigerd"
+
+#: authentik/policies/dummy/models.py:44
+msgid "Dummy Policy"
+msgstr "Dumme Beleid"
+
+#: authentik/policies/dummy/models.py:45
+msgid "Dummy Policies"
+msgstr "Dumme Beleid"
+
+#: authentik/policies/event_matcher/api.py:20
+#: authentik/policies/event_matcher/models.py:56
+msgid ""
+"Match events created by selected application. When left empty, all "
+"applications are matched."
+msgstr ""
+"Overeenkomst met gebeurtenissen gemaakt door de geselecteerde toepassing. "
+"Als leeg gelaten, worden alle toepassingen overeenkomen."
+
+#: authentik/policies/event_matcher/api.py:29
+#: authentik/policies/event_matcher/models.py:64
+msgid ""
+"Match events created by selected model. When left empty, all models are "
+"matched. When an app is selected, all the application's models are matched."
+msgstr ""
+"Overeenkomst met gebeurtenissen gemaakt door het geselecteerde model. Als "
+"leeg gelaten, worden alle modellen overeenkomen. Wanneer een toepassing is "
+"geselecteerd, worden alle modellen van de toepassing overeenkomen."
+
+#: authentik/policies/event_matcher/api.py:42
+msgid "At least one criteria must be set."
+msgstr "Minstens één criterium moet worden ingesteld."
+
+#: authentik/policies/event_matcher/models.py:48
+msgid ""
+"Match created events with this action type. When left empty, all action "
+"types will be matched."
+msgstr ""
+"Overeenkomst met gemaakte gebeurtenissen met dit actietype. Als leeg "
+"gelaten, worden alle actietypen overeenkomen."
+
+#: authentik/policies/event_matcher/models.py:73
+msgid ""
+"Matches Event's Client IP (strict matching, for network matching use an "
+"Expression Policy)"
+msgstr ""
+"Komt overeen met het client-IP van de gebeurtenis (strikte overeenkomst, "
+"voor netwerkomgeving gebruik een Expressiebeleid)."
+
+#: authentik/policies/event_matcher/models.py:143
+msgid "Event Matcher Policy"
+msgstr "Gebeurtenismatcher Beleid"
+
+#: authentik/policies/event_matcher/models.py:144
+msgid "Event Matcher Policies"
+msgstr "Gebeurtenismatcher Beleid"
+
+#: authentik/policies/expiry/models.py:45
+#, python-format
+msgid "Password expired %(days)d days ago. Please update your password."
+msgstr "Wachtwoord verlopen %(days)d dagen geleden. Werk uw wachtwoord bij."
+
+#: authentik/policies/expiry/models.py:49
+msgid "Password has expired."
+msgstr "Wachtwoord is verlopen."
+
+#: authentik/policies/expiry/models.py:53
+msgid "Password Expiry Policy"
+msgstr "Wachtwoordvervalbeleid"
+
+#: authentik/policies/expiry/models.py:54
+msgid "Password Expiry Policies"
+msgstr "Wachtwoordvervalbeleid"
+
+#: authentik/policies/expression/models.py:40
+msgid "Expression Policy"
+msgstr "Expressiebeleid"
+
+#: authentik/policies/expression/models.py:41
+msgid "Expression Policies"
+msgstr "Expressiebeleid"
+
+#: authentik/policies/models.py:22
+msgid "all, all policies must pass"
+msgstr "alle, alle beleidsregels moeten slagen"
+
+#: authentik/policies/models.py:23
+msgid "any, any policy must pass"
+msgstr "elk, elk beleid moet slagen"
+
+#: authentik/policies/models.py:46
+msgid "Policy Binding Model"
+msgstr "Beleidsbinding Model"
+
+#: authentik/policies/models.py:47
+msgid "Policy Binding Models"
+msgstr "Beleidsbinding Modellen"
+
+#: authentik/policies/models.py:86
+msgid "Negates the outcome of the policy. Messages are unaffected."
+msgstr ""
+"Maakt de uitkomst van het beleid ongedaan. Berichten worden niet beïnvloed."
+
+#: authentik/policies/models.py:89
+msgid "Timeout after which Policy execution is terminated."
+msgstr "Time-out na welke de uitvoering van het beleid wordt beëindigd."
+
+#: authentik/policies/models.py:142
+msgid "Policy Binding"
+msgstr "Beleidsbinding"
+
+#: authentik/policies/models.py:143
+msgid "Policy Bindings"
+msgstr "Beleidsbindingen"
+
+#: authentik/policies/models.py:164
+msgid ""
+"When this option is enabled, all executions of this policy will be logged. "
+"By default, only execution errors are logged."
+msgstr ""
+"Wanneer deze optie is ingeschakeld, worden alle uitvoeringen van dit beleid "
+"gelogd. Standaard worden alleen uitvoeringsfouten gelogd."
+
+#: authentik/policies/models.py:186
+msgid "Policy"
+msgstr "Beleid"
+
+#: authentik/policies/models.py:187
+msgid "Policies"
+msgstr "Beleid"
+
+#: authentik/policies/password/models.py:27
+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:44
+msgid "How many times the password hash is allowed to be on haveibeenpwned"
+msgstr "Hoe vaak het wachtwoordhash op haveibeenpwned mag voorkomen"
+
+#: authentik/policies/password/models.py:49
+msgid ""
+"If the zxcvbn score is equal or less than this value, the policy will fail."
+msgstr ""
+"Als de zxcvbn-score gelijk is aan of lager is dan deze waarde, zal het "
+"beleid falen."
+
+#: authentik/policies/password/models.py:72
+msgid "Password not set in context"
+msgstr "Wachtwoord niet ingesteld in context"
+
+#: authentik/policies/password/models.py:134
+#, python-format
+msgid "Password exists on %(count)d online lists."
+msgstr "Wachtwoord bestaat op %(count)d online lijsten."
+
+#: authentik/policies/password/models.py:154
+msgid "Password is too weak."
+msgstr "Wachtwoord is te zwak."
+
+#: authentik/policies/password/models.py:162
+msgid "Password Policy"
+msgstr "Wachtwoordbeleid"
+
+#: authentik/policies/password/models.py:163
+msgid "Password Policies"
+msgstr "Wachtwoordbeleiden"
+
+#: authentik/policies/reputation/models.py:58
+msgid "Reputation Policy"
+msgstr "Reputatiebeleid"
+
+#: authentik/policies/reputation/models.py:59
+msgid "Reputation Policies"
+msgstr "Reputatiebeleiden"
+
+#: authentik/policies/templates/policies/denied.html:7
+#: authentik/policies/templates/policies/denied.html:11
+msgid "Permission denied"
+msgstr "Toestemming geweigerd"
+
+#: authentik/policies/templates/policies/denied.html:21
+msgid "User's avatar"
+msgstr "Avatar van de gebruiker"
+
+#: authentik/policies/templates/policies/denied.html:25
+msgid "Not you?"
+msgstr "Niet jij?"
+
+#: authentik/policies/templates/policies/denied.html:33
+msgid "Request has been denied."
+msgstr "Verzoek is geweigerd."
+
+#: authentik/policies/templates/policies/denied.html:44
+msgid "Messages:"
+msgstr "Berichten:"
+
+#: authentik/policies/templates/policies/denied.html:54
+msgid "Explanation:"
+msgstr "Uitleg:"
+
+#: authentik/policies/templates/policies/denied.html:58
+#, python-format
+msgid ""
+"\n"
+" Policy binding '%(name)s' returned result '%(result)s'\n"
+" "
+msgstr ""
+"\n"
+" Beleidsbinding '%(name)s' gaf resultaat '%(result)s' terug\n"
+" "
+
+#: authentik/policies/views.py:68
+msgid "Failed to resolve application"
+msgstr "Kan toepassing niet oplossen"
+
+#: authentik/providers/ldap/models.py:25
+msgid "DN under which objects are accessible."
+msgstr "DN waarin objecten toegankelijk zijn."
+
+#: authentik/providers/ldap/models.py:34
+msgid ""
+"Users in this group can do search queries. If not set, every user can "
+"execute search queries."
+msgstr ""
+"Gebruikers in deze groep kunnen zoekopdrachten uitvoeren. Als dit niet is "
+"ingesteld, kan elke gebruiker zoekopdrachten uitvoeren."
+
+#: authentik/providers/ldap/models.py:53
+msgid ""
+"The start for uidNumbers, this number is added to the user.pk to make sure "
+"that the numbers aren't too low for POSIX users. Default is 2000 to ensure "
+"that we don't collide with local users uidNumber"
+msgstr ""
+"Het begin voor uidNumbers, dit nummer wordt toegevoegd aan user.pk om ervoor"
+" te zorgen dat de nummers niet te laag zijn voor POSIX-gebruikers. De "
+"standaardwaarde is 2000 om ervoor te zorgen dat we geen conflict hebben met "
+"lokale gebruikers uidNumber."
+
+#: authentik/providers/ldap/models.py:62
+msgid ""
+"The start for gidNumbers, this number is added to a number generated from "
+"the group.pk to make sure that the numbers aren't too low for POSIX groups. "
+"Default is 4000 to ensure that we don't collide with local groups or users "
+"primary groups gidNumber"
+msgstr ""
+"Het begin voor gidNumbers, dit nummer wordt toegevoegd aan een nummer dat is"
+" gegenereerd uit group.pk om ervoor te zorgen dat de nummers niet te laag "
+"zijn voor POSIX-groepen. De standaardwaarde is 4000 om ervoor te zorgen dat "
+"we geen conflict hebben met lokale groepen of gebruikers primaire groepen "
+"gidNumber."
+
+#: authentik/providers/ldap/models.py:76
+msgid ""
+"When enabled, code-based multi-factor authentication can be used by "
+"appending a semicolon and the TOTP code to the password. This should only be"
+" enabled if all users that will bind to this provider have a TOTP device "
+"configured, as otherwise a password may incorrectly be rejected if it "
+"contains a semicolon."
+msgstr ""
+"Indien ingeschakeld, kan codegebaseerde multi-factor authenticatie worden "
+"gebruikt door een puntkomma en de TOTP-code aan het wachtwoord toe te "
+"voegen. Dit moet alleen worden ingeschakeld als alle gebruikers die zich bij"
+" deze provider willen aanmelden een TOTP-apparaat geconfigureerd hebben, "
+"omdat anders een wachtwoord mogelijk onterecht wordt afgewezen als het een "
+"puntkomma bevat."
+
+#: authentik/providers/ldap/models.py:108
+msgid "LDAP Provider"
+msgstr "LDAP-provider"
+
+#: authentik/providers/ldap/models.py:109
+msgid "LDAP Providers"
+msgstr "LDAP-providers"
+
+#: authentik/providers/oauth2/id_token.py:27
+msgid "Based on the Hashed User ID"
+msgstr "Gebaseerd op de Gehashte Gebruikers-ID"
+
+#: authentik/providers/oauth2/id_token.py:28
+msgid "Based on user ID"
+msgstr "Gebaseerd op gebruikers-ID"
+
+#: authentik/providers/oauth2/id_token.py:29
+msgid "Based on user UUID"
+msgstr "Gebaseerd op gebruikers-UUID"
+
+#: authentik/providers/oauth2/id_token.py:30
+msgid "Based on the username"
+msgstr "Gebaseerd op de gebruikersnaam"
+
+#: authentik/providers/oauth2/id_token.py:33
+msgid "Based on the User's Email. This is recommended over the UPN method."
+msgstr ""
+"Gebaseerd op het e-mailadres van de gebruiker. Dit wordt aanbevolen boven de"
+" UPN-methode."
+
+#: authentik/providers/oauth2/id_token.py:38
+msgid ""
+"Based on the User's UPN, only works if user has a 'upn' attribute set. Use "
+"this method only if you have different UPN and Mail domains."
+msgstr ""
+"Gebaseerd op de UPN van de gebruiker, werkt alleen als de gebruiker een "
+"'upn'-attribuut heeft ingesteld. Gebruik deze methode alleen als u "
+"verschillende UPN- en Mail-domeinen heeft."
+
+#: authentik/providers/oauth2/models.py:42
+msgid "Confidential"
+msgstr "Vertrouwelijk"
+
+#: authentik/providers/oauth2/models.py:43
+msgid "Public"
+msgstr "Openbaar"
+
+#: authentik/providers/oauth2/models.py:65
+msgid "Same identifier is used for all providers"
+msgstr "Hetzelfde identificatiemiddel wordt voor alle providers gebruikt"
+
+#: authentik/providers/oauth2/models.py:67
+msgid "Each provider has a different issuer, based on the application slug."
+msgstr ""
+"Elke provider heeft een andere uitgever, gebaseerd op de toepassingsslug."
+
+#: authentik/providers/oauth2/models.py:74
+msgid "code (Authorization Code Flow)"
+msgstr "code (Autorisatiecode-flow)"
+
+#: authentik/providers/oauth2/models.py:75
+msgid "id_token (Implicit Flow)"
+msgstr "id_token (Impliciete Flow)"
+
+#: authentik/providers/oauth2/models.py:76
+msgid "id_token token (Implicit Flow)"
+msgstr "id_token token (Impliciete Flow)"
+
+#: authentik/providers/oauth2/models.py:77
+msgid "code token (Hybrid Flow)"
+msgstr "code token (Hybride Flow)"
+
+#: authentik/providers/oauth2/models.py:78
+msgid "code id_token (Hybrid Flow)"
+msgstr "code id_token (Hybride Flow)"
+
+#: authentik/providers/oauth2/models.py:79
+msgid "code id_token token (Hybrid Flow)"
+msgstr "code id_token token (Hybride Flow)"
+
+#: authentik/providers/oauth2/models.py:85
+msgid "HS256 (Symmetric Encryption)"
+msgstr "HS256 (Symmetrische Versleuteling)"
+
+#: authentik/providers/oauth2/models.py:86
+msgid "RS256 (Asymmetric Encryption)"
+msgstr "RS256 (Asymmetrische Versleuteling)"
+
+#: authentik/providers/oauth2/models.py:87
+msgid "ES256 (Asymmetric Encryption)"
+msgstr "ES256 (Asymmetrische Versleuteling)"
+
+#: authentik/providers/oauth2/models.py:93
+msgid "Scope used by the client"
+msgstr "Scope gebruikt door de cliënt"
+
+#: authentik/providers/oauth2/models.py:97
+msgid ""
+"Description shown to the user when consenting. If left empty, the user won't"
+" be informed."
+msgstr ""
+"Beschrijving getoond aan de gebruiker bij toestemming. Als leeg gelaten, "
+"wordt de gebruiker niet geïnformeerd."
+
+#: authentik/providers/oauth2/models.py:116
+msgid "Scope Mapping"
+msgstr "Scope-mapping"
+
+#: authentik/providers/oauth2/models.py:117
+msgid "Scope Mappings"
+msgstr "Scope-mappings"
+
+#: authentik/providers/oauth2/models.py:127
+msgid "Client Type"
+msgstr "Clienttype"
+
+#: authentik/providers/oauth2/models.py:129
+msgid ""
+"Confidential clients are capable of maintaining the confidentiality of their"
+" credentials. Public clients are incapable"
+msgstr ""
+"Vertrouwelijke clients zijn in staat om de vertrouwelijkheid van hun "
+"referenties te behouden. Openbare clients zijn dat niet."
+
+#: authentik/providers/oauth2/models.py:136
+msgid "Client ID"
+msgstr "Client-ID"
+
+#: authentik/providers/oauth2/models.py:142
+msgid "Client Secret"
+msgstr "Client Geheim"
+
+#: authentik/providers/oauth2/models.py:148
+msgid "Redirect URIs"
+msgstr "Omleidings-URI's"
+
+#: authentik/providers/oauth2/models.py:149
+msgid "Enter each URI on a new line."
+msgstr "Voer elke URI op een nieuwe regel in."
+
+#: authentik/providers/oauth2/models.py:154
+msgid "Include claims in id_token"
+msgstr "Inclusief claims in id_token"
+
+#: authentik/providers/oauth2/models.py:156
+msgid ""
+"Include User claims from scopes in the id_token, for applications that don't"
+" access the userinfo endpoint."
+msgstr ""
+"Inclusief Gebruikersclaims uit scopes in id_token, voor toepassingen die "
+"geen toegang hebben tot het userinfo-eindpunt."
+
+#: authentik/providers/oauth2/models.py:165
+msgid ""
+"Access codes not valid on or after current time + this value (Format: "
+"hours=1;minutes=2;seconds=3)."
+msgstr ""
+"Toegangscodes zijn niet geldig op of na de huidige tijd + deze waarde "
+"(Formaat: uren=1;minuten=2;seconden=3)."
+
+#: authentik/providers/oauth2/models.py:173
+#: authentik/providers/oauth2/models.py:181
+msgid ""
+"Tokens not valid on or after current time + this value (Format: "
+"hours=1;minutes=2;seconds=3)."
+msgstr ""
+"Tokens zijn niet geldig op of na de huidige tijd + deze waarde (Formaat: "
+"uren=1;minuten=2;seconden=3)."
+
+#: authentik/providers/oauth2/models.py:190
+msgid ""
+"Configure what data should be used as unique User Identifier. For most "
+"cases, the default should be fine."
+msgstr ""
+"Configureer welke gegevens moeten worden gebruikt als unieke "
+"gebruikersidentificatie. In de meeste gevallen is de standaardinstelling "
+"prima."
+
+#: authentik/providers/oauth2/models.py:197
+msgid "Configure how the issuer field of the ID Token should be filled."
+msgstr ""
+"Configureer hoe het uitgeversveld van het ID-token moet worden ingevuld."
+
+#: authentik/providers/oauth2/models.py:202
+msgid "Signing Key"
+msgstr "Ondertekeningsleutel"
+
+#: authentik/providers/oauth2/models.py:206
+msgid ""
+"Key used to sign the tokens. Only required when JWT Algorithm is set to "
+"RS256."
+msgstr ""
+"Sleutel gebruikt om de tokens te ondertekenen. Alleen vereist wanneer het "
+"JWT-algoritme is ingesteld op RS256."
+
+#: authentik/providers/oauth2/models.py:213
+msgid ""
+"Any JWT signed by the JWK of the selected source can be used to "
+"authenticate."
+msgstr ""
+"Elke JWT ondertekend door de JWK van de geselecteerde bron kan worden "
+"gebruikt voor authenticatie."
+
+#: authentik/providers/oauth2/models.py:286
+msgid "OAuth2/OpenID Provider"
+msgstr "OAuth2/OpenID-provider"
+
+#: authentik/providers/oauth2/models.py:287
+msgid "OAuth2/OpenID Providers"
+msgstr "OAuth2/OpenID-providers"
+
+#: authentik/providers/oauth2/models.py:296
+#: authentik/providers/oauth2/models.py:428
+msgid "Scopes"
+msgstr "Scopes"
+
+#: authentik/providers/oauth2/models.py:315
+msgid "Code"
+msgstr "Code"
+
+#: authentik/providers/oauth2/models.py:316
+msgid "Nonce"
+msgstr "Nonce"
+
+#: authentik/providers/oauth2/models.py:317
+msgid "Code Challenge"
+msgstr "Code-uitdaging"
+
+#: authentik/providers/oauth2/models.py:319
+msgid "Code Challenge Method"
+msgstr "Code-uitdaging methode"
+
+#: authentik/providers/oauth2/models.py:339
+msgid "Authorization Code"
+msgstr "Autorisatiecode"
+
+#: authentik/providers/oauth2/models.py:340
+msgid "Authorization Codes"
+msgstr "Autorisatiecodes"
+
+#: authentik/providers/oauth2/models.py:382
+msgid "OAuth2 Access Token"
+msgstr "OAuth2 Toegangstoken"
+
+#: authentik/providers/oauth2/models.py:383
+msgid "OAuth2 Access Tokens"
+msgstr "OAuth2 Toegangstokens"
+
+#: authentik/providers/oauth2/models.py:393
+msgid "ID Token"
+msgstr "ID-token"
+
+#: authentik/providers/oauth2/models.py:412
+msgid "OAuth2 Refresh Token"
+msgstr "OAuth2 Verversingstoken"
+
+#: authentik/providers/oauth2/models.py:413
+msgid "OAuth2 Refresh Tokens"
+msgstr "OAuth2 Verversingstokens"
+
+#: authentik/providers/oauth2/models.py:440
+msgid "Device Token"
+msgstr "Apparaattoken"
+
+#: authentik/providers/oauth2/models.py:441
+msgid "Device Tokens"
+msgstr "Apparaattokens"
+
+#: authentik/providers/oauth2/views/authorize.py:446
+#: authentik/providers/saml/views/flows.py:87
+#, python-format
+msgid "Redirecting to %(app)s..."
+msgstr "Doorverwijzen naar %(app)s..."
+
+#: authentik/providers/oauth2/views/device_init.py:151
+msgid "Invalid code"
+msgstr "Ongeldige code"
+
+#: authentik/providers/oauth2/views/userinfo.py:51
+#: authentik/providers/oauth2/views/userinfo.py:52
+msgid "GitHub Compatibility: Access your User Information"
+msgstr "GitHub-compatibiliteit: Toegang tot uw Gebruikersinformatie"
+
+#: authentik/providers/oauth2/views/userinfo.py:53
+msgid "GitHub Compatibility: Access you Email addresses"
+msgstr "GitHub-compatibiliteit: Toegang tot uw E-mailadressen"
+
+#: authentik/providers/oauth2/views/userinfo.py:54
+msgid "GitHub Compatibility: Access your Groups"
+msgstr "GitHub-compatibiliteit: Toegang tot uw Groepen"
+
+#: authentik/providers/oauth2/views/userinfo.py:55
+msgid "authentik API Access on behalf of your user"
+msgstr "authentik API-toegang namens uw gebruiker"
+
+#: authentik/providers/proxy/api.py:52
+msgid "User and password attributes must be set when basic auth is enabled."
+msgstr ""
+"Gebruikers- en wachtwoordeigenschappen moeten worden ingesteld wanneer "
+"basisverificatie is ingeschakeld."
+
+#: authentik/providers/proxy/api.py:62
+msgid "Internal host cannot be empty when forward auth is disabled."
+msgstr ""
+"Interne host kan niet leeg zijn wanneer doorsturen van verificatie is "
+"uitgeschakeld."
+
+#: authentik/providers/proxy/models.py:54
+msgid "Validate SSL Certificates of upstream servers"
+msgstr "Valideer SSL-certificaten van upstream-servers"
+
+#: authentik/providers/proxy/models.py:55
+msgid "Internal host SSL Validation"
+msgstr "Interne host SSL-validatie"
+
+#: authentik/providers/proxy/models.py:61
+msgid ""
+"Enable support for forwardAuth in traefik and nginx auth_request. Exclusive "
+"with internal_host."
+msgstr ""
+"Schakel ondersteuning in voor forwardAuth in traefik en nginx auth_request. "
+"Uitsluitend met interne host."
+
+#: authentik/providers/proxy/models.py:70
+msgid ""
+"Regular expressions for which authentication is not required. Each new line "
+"is interpreted as a new Regular Expression."
+msgstr ""
+"Reguliere expressies waarvoor geen verificatie vereist is. Elke nieuwe regel"
+" wordt geïnterpreteerd als een nieuwe reguliere expressie."
+
+#: authentik/providers/proxy/models.py:78
+msgid ""
+"When enabled, this provider will intercept the authorization header and "
+"authenticate requests based on its value."
+msgstr ""
+"Wanneer ingeschakeld, zal deze provider de autorisatieheader onderscheppen "
+"en verzoeken verifiëren op basis van de waarde ervan."
+
+#: authentik/providers/proxy/models.py:84
+msgid "Set HTTP-Basic Authentication"
+msgstr "Stel HTTP-Basisverificatie in"
+
+#: authentik/providers/proxy/models.py:86
+msgid ""
+"Set a custom HTTP-Basic Authentication header based on values from "
+"authentik."
+msgstr ""
+"Stel een aangepaste HTTP-Basisverificatieheader in op basis van waarden van "
+"authentik."
+
+#: authentik/providers/proxy/models.py:91
+msgid "HTTP-Basic Username Key"
+msgstr "HTTP-Basis Gebruikersnaamsleutel"
+
+#: authentik/providers/proxy/models.py:93
+msgid ""
+"User/Group Attribute used for the user part of the HTTP-Basic Header. If not"
+" set, the user's Email address is used."
+msgstr ""
+"Gebruikers-/Groepseigenschap gebruikt voor het gebruikersgedeelte van de "
+"HTTP-Basisheader. Als het niet is ingesteld, wordt het e-mailadres van de "
+"gebruiker gebruikt."
+
+#: authentik/providers/proxy/models.py:99
+msgid "HTTP-Basic Password Key"
+msgstr "HTTP-Basis Wachtwoordsleutel"
+
+#: authentik/providers/proxy/models.py:100
+msgid ""
+"User/Group Attribute used for the password part of the HTTP-Basic Header."
+msgstr ""
+"Gebruikers-/Groepseigenschap gebruikt voor het wachtwoordgedeelte van de "
+"HTTP-Basisheader."
+
+#: authentik/providers/proxy/models.py:154
+msgid "Proxy Provider"
+msgstr "Proxy-provider"
+
+#: authentik/providers/proxy/models.py:155
+msgid "Proxy Providers"
+msgstr "Proxy-providers"
+
+#: authentik/providers/radius/models.py:18
+msgid "Shared secret between clients and server to hash packets."
+msgstr "Gedeeld geheim tussen clients en server om pakketten te hashen."
+
+#: authentik/providers/radius/models.py:24
+msgid ""
+"List of CIDRs (comma-separated) that clients can connect from. A more "
+"specific CIDR will match before a looser one. Clients connecting from a non-"
+"specified CIDR will be dropped."
+msgstr ""
+"Lijst met CIDR's (door komma's gescheiden) waarvan clients kunnen verbinden."
+" Een specifiekere CIDR zal eerder overeenkomen dan een lossere. Clients die "
+"verbinden vanaf een niet-gespecificeerde CIDR zullen worden verworpen."
+
+#: authentik/providers/radius/models.py:49
+msgid "Radius Provider"
+msgstr "Radius-provider"
+
+#: authentik/providers/radius/models.py:50
+msgid "Radius Providers"
+msgstr "Radius-providers"
+
+#: authentik/providers/saml/api/providers.py:260
+msgid "Invalid XML Syntax"
+msgstr "Ongeldige XML-syntaxis"
+
+#: authentik/providers/saml/api/providers.py:270
+#, python-format
+msgid "Failed to import Metadata: %(message)s"
+msgstr "Mislukt om Metadata te importeren: %(message)s"
+
+#: authentik/providers/saml/models.py:38
+msgid "ACS URL"
+msgstr "ACS-URL"
+
+#: authentik/providers/saml/models.py:43
+msgid ""
+"Value of the audience restriction field of the assertion. When left empty, "
+"no audience restriction will be added."
+msgstr ""
+"Waarde van het veld voor publieksbeperking van de bewering. Als het leeg "
+"wordt gelaten, wordt er geen publieksbeperking toegevoegd."
+
+#: authentik/providers/saml/models.py:47
+msgid "Also known as EntityID"
+msgstr "Ook bekend als EntityID"
+
+#: authentik/providers/saml/models.py:51
+msgid "Service Provider Binding"
+msgstr "Serviceproviderbinding"
+
+#: authentik/providers/saml/models.py:53
+msgid ""
+"This determines how authentik sends the response back to the Service "
+"Provider."
+msgstr ""
+"Dit bepaalt hoe authentik de reactie terugstuurt naar de serviceprovider."
+
+#: authentik/providers/saml/models.py:63
+msgid "NameID Property Mapping"
+msgstr "Naam-ID-eigenschapsafbeelding"
+
+#: authentik/providers/saml/models.py:65
+msgid ""
+"Configure how the NameID value will be created. When left empty, the "
+"NameIDPolicy of the incoming request will be considered"
+msgstr ""
+"Configureer hoe de waarde van de Naam-ID zal worden gemaakt. Als het leeg "
+"wordt gelaten, wordt de Naam-ID-policy van het inkomende verzoek overwogen."
+
+#: authentik/providers/saml/models.py:74
+msgid ""
+"Assertion valid not before current time + this value (Format: "
+"hours=-1;minutes=-2;seconds=-3)."
+msgstr ""
+"Bewering geldig niet voor huidige tijd + deze waarde (Indeling: "
+"uren=-1;minuten=-2;seconden=-3)."
+
+#: authentik/providers/saml/models.py:82
+msgid ""
+"Assertion not valid on or after current time + this value (Format: "
+"hours=1;minutes=2;seconds=3)."
+msgstr ""
+"Bewering niet geldig op of na huidige tijd + deze waarde (Indeling: "
+"uren=1;minuten=2;seconden=3)."
+
+#: authentik/providers/saml/models.py:91
+msgid ""
+"Session not valid on or after current time + this value (Format: "
+"hours=1;minutes=2;seconds=3)."
+msgstr ""
+"Sessie niet geldig op of na huidige tijd + deze waarde (Indeling: "
+"uren=1;minuten=2;seconden=3)."
+
+#: authentik/providers/saml/models.py:99 authentik/sources/saml/models.py:150
+msgid "SHA1"
+msgstr "SHA1"
+
+#: authentik/providers/saml/models.py:100 authentik/sources/saml/models.py:151
+msgid "SHA256"
+msgstr "SHA256"
+
+#: authentik/providers/saml/models.py:101 authentik/sources/saml/models.py:152
+msgid "SHA384"
+msgstr "SHA384"
+
+#: authentik/providers/saml/models.py:102 authentik/sources/saml/models.py:153
+msgid "SHA512"
+msgstr "SHA512"
+
+#: authentik/providers/saml/models.py:109 authentik/sources/saml/models.py:160
+msgid "RSA-SHA1"
+msgstr "RSA-SHA1"
+
+#: authentik/providers/saml/models.py:110 authentik/sources/saml/models.py:161
+msgid "RSA-SHA256"
+msgstr "RSA-SHA256"
+
+#: authentik/providers/saml/models.py:111 authentik/sources/saml/models.py:162
+msgid "RSA-SHA384"
+msgstr "RSA-SHA384"
+
+#: authentik/providers/saml/models.py:112 authentik/sources/saml/models.py:163
+msgid "RSA-SHA512"
+msgstr "RSA-SHA512"
+
+#: authentik/providers/saml/models.py:113 authentik/sources/saml/models.py:164
+msgid "DSA-SHA1"
+msgstr "DSA-SHA1"
+
+#: authentik/providers/saml/models.py:124 authentik/sources/saml/models.py:130
+msgid ""
+"When selected, incoming assertion's Signatures will be validated against "
+"this certificate. To allow unsigned Requests, leave on default."
+msgstr ""
+"Wanneer geselecteerd, worden handtekeningen van inkomende beweringen "
+"gevalideerd tegen dit certificaat. Om niet-ondertekende verzoeken toe te "
+"staan, laat het op de standaardwaarde staan."
+
+#: authentik/providers/saml/models.py:128 authentik/sources/saml/models.py:134
+msgid "Verification Certificate"
+msgstr "Verificatiecertificaat"
+
+#: authentik/providers/saml/models.py:136
+msgid "Keypair used to sign outgoing Responses going to the Service Provider."
+msgstr ""
+"Sleutelpaar dat wordt gebruikt om uitgaande reacties te ondertekenen die "
+"naar de serviceprovider gaan."
+
+#: authentik/providers/saml/models.py:138 authentik/sources/saml/models.py:144
+msgid "Signing Keypair"
+msgstr "Ondertekeningssleutelpaar"
+
+#: authentik/providers/saml/models.py:167
+msgid "SAML Provider"
+msgstr "SAML-provider"
+
+#: authentik/providers/saml/models.py:168
+msgid "SAML Providers"
+msgstr "SAML-providers"
+
+#: authentik/providers/saml/models.py:192
+msgid "SAML Property Mapping"
+msgstr "SAML Eigenschapsafbeelding"
+
+#: authentik/providers/saml/models.py:193
+msgid "SAML Property Mappings"
+msgstr "SAML Eigenschapsafbeeldingen"
+
+#: authentik/providers/scim/models.py:20
+msgid "Base URL to SCIM requests, usually ends in /v2"
+msgstr "Basis-URL voor SCIM-verzoeken, eindigt meestal op /v2"
+
+#: authentik/providers/scim/models.py:21
+msgid "Authentication token"
+msgstr "Verificatietoken"
+
+#: authentik/providers/scim/models.py:27 authentik/sources/ldap/models.py:94
+msgid "Property mappings used for group creation/updating."
+msgstr ""
+"Eigenschapsafbeeldingen gebruikt voor het maken/bijwerken van groepen."
+
+#: authentik/providers/scim/models.py:60
+msgid "SCIM Provider"
+msgstr "SCIM-provider"
+
+#: authentik/providers/scim/models.py:61
+msgid "SCIM Providers"
+msgstr "SCIM-providers"
+
+#: authentik/providers/scim/models.py:81
+msgid "SCIM Mapping"
+msgstr "SCIM-afbeelding"
+
+#: authentik/providers/scim/models.py:82
+msgid "SCIM Mappings"
+msgstr "SCIM-afbeeldingen"
+
+#: authentik/providers/scim/tasks.py:52
+msgid "Starting full SCIM sync"
+msgstr "Start volledige SCIM-synchronisatie"
+
+#: authentik/providers/scim/tasks.py:59
+#, python-format
+msgid "Syncing page %(page)d of users"
+msgstr "Synchroniseren van pagina %(page)d van gebruikers"
+
+#: authentik/providers/scim/tasks.py:63
+#, python-format
+msgid "Syncing page %(page)d of groups"
+msgstr "Synchroniseren van pagina %(page)d van groepen"
+
+#: authentik/providers/scim/tasks.py:92
+#, python-format
+msgid "Failed to sync user %(user_name)s due to remote error: %(error)s"
+msgstr ""
+"Kan gebruiker %(user_name)s niet synchroniseren vanwege een externe fout: "
+"%(error)s"
+
+#: authentik/providers/scim/tasks.py:103 authentik/providers/scim/tasks.py:144
+#, python-format
+msgid "Stopping sync due to error: %(error)s"
+msgstr "Synchronisatie stoppen vanwege een fout: %(error)s"
+
+#: authentik/providers/scim/tasks.py:133
+#, python-format
+msgid "Failed to sync group %(group_name)s due to remote error: %(error)s"
+msgstr ""
+"Kan groep %(group_name)s niet synchroniseren vanwege een externe fout: "
+"%(error)s"
+
+#: authentik/recovery/management/commands/create_admin_group.py:11
+msgid "Create admin group if the default group gets deleted."
+msgstr "Maak een beheergroep aan als de standaardgroep wordt verwijderd."
+
+#: authentik/recovery/management/commands/create_recovery_key.py:17
+msgid "Create a Key which can be used to restore access to authentik."
+msgstr ""
+"Maak een sleutel aan die kan worden gebruikt om toegang tot authentik te "
+"herstellen."
+
+#: authentik/recovery/views.py:24
+msgid "Used recovery-link to authenticate."
+msgstr "Gebruikte herstelkoppeling om te verifiëren."
+
+#: authentik/sources/ldap/models.py:37
+msgid "Server URI"
+msgstr "Server-URI"
+
+#: authentik/sources/ldap/models.py:46
+msgid ""
+"Optionally verify the LDAP Server's Certificate against the CA Chain in this"
+" keypair."
+msgstr ""
+"Optioneel het certificaat van de LDAP-server verifiëren tegen de CA-keten in"
+" dit sleutelpaar."
+
+#: authentik/sources/ldap/models.py:55
+msgid ""
+"Client certificate to authenticate against the LDAP Server's Certificate."
+msgstr ""
+"Clientcertificaat om te verifiëren tegen het certificaat van de LDAP-server."
+
+#: authentik/sources/ldap/models.py:58
+msgid "Bind CN"
+msgstr "Bind CN"
+
+#: authentik/sources/ldap/models.py:60
+msgid "Enable Start TLS"
+msgstr "Start TLS inschakelen"
+
+#: authentik/sources/ldap/models.py:61
+msgid "Use Server URI for SNI verification"
+msgstr "Gebruik Server-URI voor SNI-verificatie"
+
+#: authentik/sources/ldap/models.py:63
+msgid "Base DN"
+msgstr "Basis-DN"
+
+#: authentik/sources/ldap/models.py:65
+msgid "Prepended to Base DN for User-queries."
+msgstr "Toegevoegd aan Basis-DN voor Gebruikersquery's."
+
+#: authentik/sources/ldap/models.py:66
+msgid "Addition User DN"
+msgstr "Aanvullende Gebruikers-DN"
+
+#: authentik/sources/ldap/models.py:70
+msgid "Prepended to Base DN for Group-queries."
+msgstr "Toegevoegd aan Basis-DN voor Groepquery's."
+
+#: authentik/sources/ldap/models.py:71
+msgid "Addition Group DN"
+msgstr "Aanvullende Groeps-DN"
+
+#: authentik/sources/ldap/models.py:77
+msgid "Consider Objects matching this filter to be Users."
+msgstr "Beschouw objecten die overeenkomen met deze filter als Gebruikers."
+
+#: authentik/sources/ldap/models.py:80
+msgid "Field which contains members of a group."
+msgstr "Veld dat leden van een groep bevat."
+
+#: authentik/sources/ldap/models.py:84
+msgid "Consider Objects matching this filter to be Groups."
+msgstr "Beschouw objecten die overeenkomen met deze filter als Groepen."
+
+#: authentik/sources/ldap/models.py:87
+msgid "Field which contains a unique Identifier."
+msgstr "Veld dat een unieke identificatie bevat."
+
+#: authentik/sources/ldap/models.py:101
+msgid ""
+"When a user changes their password, sync it back to LDAP. This can only be "
+"enabled on a single LDAP source."
+msgstr ""
+"Wanneer een gebruiker zijn wachtwoord wijzigt, synchroniseer het dan terug "
+"naar LDAP. Dit kan alleen worden ingeschakeld voor een enkele LDAP-bron."
+
+#: authentik/sources/ldap/models.py:190
+msgid "LDAP Source"
+msgstr "LDAP-bron"
+
+#: authentik/sources/ldap/models.py:191
+msgid "LDAP Sources"
+msgstr "LDAP-bronnen"
+
+#: authentik/sources/ldap/models.py:213
+msgid "LDAP Property Mapping"
+msgstr "Eigenschapsafbeelding LDAP"
+
+#: authentik/sources/ldap/models.py:214
+msgid "LDAP Property Mappings"
+msgstr "Eigenschapsafbeeldingen LDAP"
+
+#: authentik/sources/ldap/signals.py:50
+msgid "Password does not match Active Directory Complexity."
+msgstr ""
+"Wachtwoord voldoet niet aan de complexiteitseisen van Active Directory."
+
+#: authentik/sources/oauth/clients/oauth2.py:68
+msgid "No token received."
+msgstr "Geen token ontvangen."
+
+#: authentik/sources/oauth/models.py:24
+msgid "Request Token URL"
+msgstr "URL voor aanvragen van token"
+
+#: authentik/sources/oauth/models.py:26
+msgid ""
+"URL used to request the initial token. This URL is only required for OAuth "
+"1."
+msgstr ""
+"URL die wordt gebruikt om het initiële token aan te vragen. Deze URL is "
+"alleen vereist voor OAuth 1."
+
+#: authentik/sources/oauth/models.py:32
+msgid "Authorization URL"
+msgstr "Autorisatie-URL"
+
+#: authentik/sources/oauth/models.py:33
+msgid "URL the user is redirect to to conest the flow."
+msgstr "URL waarnaar de gebruiker wordt omgeleid om de flow te verbinden."
+
+#: authentik/sources/oauth/models.py:38
+msgid "Access Token URL"
+msgstr "URL voor toegangstoken"
+
+#: authentik/sources/oauth/models.py:39
+msgid "URL used by authentik to retrieve tokens."
+msgstr "URL die door authentik wordt gebruikt om tokens op te halen."
+
+#: authentik/sources/oauth/models.py:44
+msgid "Profile URL"
+msgstr "Profiel-URL"
+
+#: authentik/sources/oauth/models.py:45
+msgid "URL used by authentik to get user information."
+msgstr ""
+"URL die door authentik wordt gebruikt om gebruikersinformatie op te halen."
+
+#: authentik/sources/oauth/models.py:48
+msgid "Additional Scopes"
+msgstr "Aanvullende scopes"
+
+#: authentik/sources/oauth/models.py:108
+msgid "OAuth Source"
+msgstr "OAuth-bron"
+
+#: authentik/sources/oauth/models.py:109
+msgid "OAuth Sources"
+msgstr "OAuth-bronnen"
+
+#: authentik/sources/oauth/models.py:117
+msgid "GitHub OAuth Source"
+msgstr "GitHub OAuth-bron"
+
+#: authentik/sources/oauth/models.py:118
+msgid "GitHub OAuth Sources"
+msgstr "GitHub OAuth-bronnen"
+
+#: authentik/sources/oauth/models.py:126
+msgid "Twitch OAuth Source"
+msgstr "Twitch OAuth-bron"
+
+#: authentik/sources/oauth/models.py:127
+msgid "Twitch OAuth Sources"
+msgstr "Twitch OAuth-bronnen"
+
+#: authentik/sources/oauth/models.py:135
+msgid "Mailcow OAuth Source"
+msgstr "Mailcow OAuth-bron"
+
+#: authentik/sources/oauth/models.py:136
+msgid "Mailcow OAuth Sources"
+msgstr "Mailcow OAuth-bronnen"
+
+#: authentik/sources/oauth/models.py:144
+msgid "Twitter OAuth Source"
+msgstr "Twitter OAuth-bron"
+
+#: authentik/sources/oauth/models.py:145
+msgid "Twitter OAuth Sources"
+msgstr "Twitter OAuth-bronnen"
+
+#: authentik/sources/oauth/models.py:153
+msgid "Facebook OAuth Source"
+msgstr "Facebook OAuth-bron"
+
+#: authentik/sources/oauth/models.py:154
+msgid "Facebook OAuth Sources"
+msgstr "Facebook OAuth-bronnen"
+
+#: authentik/sources/oauth/models.py:162
+msgid "Discord OAuth Source"
+msgstr "Discord OAuth-bron"
+
+#: authentik/sources/oauth/models.py:163
+msgid "Discord OAuth Sources"
+msgstr "Discord OAuth-bronnen"
+
+#: authentik/sources/oauth/models.py:171
+msgid "Patreon OAuth Source"
+msgstr "Patreon OAuth-bron"
+
+#: authentik/sources/oauth/models.py:172
+msgid "Patreon OAuth Sources"
+msgstr "Patreon OAuth-bronnen"
+
+#: authentik/sources/oauth/models.py:180
+msgid "Google OAuth Source"
+msgstr "Google OAuth-bron"
+
+#: authentik/sources/oauth/models.py:181
+msgid "Google OAuth Sources"
+msgstr "Google OAuth-bronnen"
+
+#: authentik/sources/oauth/models.py:189
+msgid "Azure AD OAuth Source"
+msgstr "Azure AD OAuth-bron"
+
+#: authentik/sources/oauth/models.py:190
+msgid "Azure AD OAuth Sources"
+msgstr "Azure AD OAuth-bronnen"
+
+#: authentik/sources/oauth/models.py:198
+msgid "OpenID OAuth Source"
+msgstr "OpenID OAuth-bron"
+
+#: authentik/sources/oauth/models.py:199
+msgid "OpenID OAuth Sources"
+msgstr "OpenID OAuth-bronnen"
+
+#: authentik/sources/oauth/models.py:207
+msgid "Apple OAuth Source"
+msgstr "Apple OAuth-bron"
+
+#: authentik/sources/oauth/models.py:208
+msgid "Apple OAuth Sources"
+msgstr "Apple OAuth-bronnen"
+
+#: authentik/sources/oauth/models.py:216
+msgid "Okta OAuth Source"
+msgstr "Okta OAuth-bron"
+
+#: authentik/sources/oauth/models.py:217
+msgid "Okta OAuth Sources"
+msgstr "Okta OAuth-bronnen"
+
+#: authentik/sources/oauth/models.py:225
+msgid "Reddit OAuth Source"
+msgstr "Reddit OAuth-bron"
+
+#: authentik/sources/oauth/models.py:226
+msgid "Reddit OAuth Sources"
+msgstr "Reddit OAuth-bronnen"
+
+#: authentik/sources/oauth/models.py:248
+msgid "User OAuth Source Connection"
+msgstr "Gebruikers OAuth-bronverbinding"
+
+#: authentik/sources/oauth/models.py:249
+msgid "User OAuth Source Connections"
+msgstr "Gebruikers OAuth-bronverbindingen"
+
+#: authentik/sources/oauth/views/callback.py:100
+#, python-format
+msgid "Authentication failed: %(reason)s"
+msgstr "Authenticatie mislukt: %(reason)s"
+
+#: authentik/sources/plex/models.py:37
+msgid "Client identifier used to talk to Plex."
+msgstr "Client-identificatie gebruikt om met Plex te communiceren."
+
+#: authentik/sources/plex/models.py:44
+msgid ""
+"Which servers a user has to be a member of to be granted access. Empty list "
+"allows every server."
+msgstr ""
+"Aan welke servers een gebruiker lid moet zijn om toegang te krijgen. Een "
+"lege lijst staat alle servers toe."
+
+#: authentik/sources/plex/models.py:50
+msgid "Allow friends to authenticate, even if you don't share a server."
+msgstr "Laat vrienden zich authenticeren, zelfs als je geen server deelt."
+
+#: authentik/sources/plex/models.py:52
+msgid "Plex token used to check friends"
+msgstr "Plex-token gebruikt om vrienden te controleren"
+
+#: authentik/sources/plex/models.py:95
+msgid "Plex Source"
+msgstr "Plex-bron"
+
+#: authentik/sources/plex/models.py:96
+msgid "Plex Sources"
+msgstr "Plex-bronnen"
+
+#: authentik/sources/plex/models.py:112
+msgid "User Plex Source Connection"
+msgstr "Gebruikers Plex-bronverbinding"
+
+#: authentik/sources/plex/models.py:113
+msgid "User Plex Source Connections"
+msgstr "Gebruikers Plex-bronverbindingen"
+
+#: authentik/sources/saml/models.py:40
+msgid "Redirect Binding"
+msgstr "Doorverwijzing Binding"
+
+#: authentik/sources/saml/models.py:41
+msgid "POST Binding"
+msgstr "POST Binding"
+
+#: authentik/sources/saml/models.py:42
+msgid "POST Binding with auto-confirmation"
+msgstr "POST Binding met automatische bevestiging"
+
+#: authentik/sources/saml/models.py:70
+msgid "Flow used before authentication."
+msgstr "Flow gebruikt vóór authenticatie."
+
+#: authentik/sources/saml/models.py:77
+msgid "Issuer"
+msgstr "Uitgever"
+
+#: authentik/sources/saml/models.py:78
+msgid "Also known as Entity ID. Defaults the Metadata URL."
+msgstr "Ook bekend als Entity ID. Standaard de Metadat URL."
+
+#: authentik/sources/saml/models.py:82
+msgid "SSO URL"
+msgstr "SSO URL"
+
+#: authentik/sources/saml/models.py:83
+msgid "URL that the initial Login request is sent to."
+msgstr "URL waarnaar het initiële loginverzoek wordt verzonden."
+
+#: authentik/sources/saml/models.py:89
+msgid "SLO URL"
+msgstr "SLO URL"
+
+#: authentik/sources/saml/models.py:90
+msgid "Optional URL if your IDP supports Single-Logout."
+msgstr "Optionele URL als uw IDP Single-Logout ondersteunt."
+
+#: authentik/sources/saml/models.py:96
+msgid ""
+"Allows authentication flows initiated by the IdP. This can be a security "
+"risk, as no validation of the request ID is done."
+msgstr ""
+"Staat authenticatiestromen toe die zijn geïnitieerd door de IdP. Dit kan een"
+" beveiligingsrisico zijn, aangezien er geen validatie van het verzoek-ID "
+"wordt uitgevoerd."
+
+#: authentik/sources/saml/models.py:104
+msgid ""
+"NameID Policy sent to the IdP. Can be unset, in which case no Policy is "
+"sent."
+msgstr ""
+"NameID-beleid verzonden naar de IdP. Kan niet ingesteld zijn, in welk geval "
+"er geen beleid wordt verzonden."
+
+#: authentik/sources/saml/models.py:115
+msgid "Delete temporary users after"
+msgstr "Verwijder tijdelijke gebruikers na"
+
+#: authentik/sources/saml/models.py:118
+msgid ""
+"Time offset when temporary users should be deleted. This only applies if "
+"your IDP uses the NameID Format 'transient', and the user doesn't log out "
+"manually. (Format: hours=1;minutes=2;seconds=3)."
+msgstr ""
+"Tijdverschil wanneer tijdelijke gebruikers moeten worden verwijderd. Dit is "
+"alleen van toepassing als uw IDP de NameID-indeling 'tijdelijk' gebruikt en "
+"de gebruiker niet handmatig uitlogt. (Formaat: uren=1;minuten=2;seconden=3)."
+
+#: authentik/sources/saml/models.py:142
+msgid ""
+"Keypair used to sign outgoing Responses going to the Identity Provider."
+msgstr ""
+"Sleutelpaar dat wordt gebruikt om uitgaande antwoorden te ondertekenen die "
+"naar de Identity Provider gaan."
+
+#: authentik/sources/saml/models.py:226
+msgid "SAML Source"
+msgstr "SAML-bron"
+
+#: authentik/sources/saml/models.py:227
+msgid "SAML Sources"
+msgstr "SAML-bronnen"
+
+#: authentik/sources/saml/models.py:242
+msgid "User SAML Source Connection"
+msgstr "Gebruikers SAML-bronverbinding"
+
+#: authentik/sources/saml/models.py:243
+msgid "User SAML Source Connections"
+msgstr "Gebruikers SAML-bronverbindingen"
+
+#: authentik/stages/authenticator_duo/models.py:79
+msgid "Duo Authenticator Setup Stage"
+msgstr "Duo Authenticator Installatiestadium"
+
+#: authentik/stages/authenticator_duo/models.py:80
+msgid "Duo Authenticator Setup Stages"
+msgstr "Duo Authenticator Installatiestadia"
+
+#: authentik/stages/authenticator_duo/models.py:103
+msgid "Duo Device"
+msgstr "Duo-apparaat"
+
+#: authentik/stages/authenticator_duo/models.py:104
+msgid "Duo Devices"
+msgstr "Duo-apparaten"
+
+#: authentik/stages/authenticator_sms/models.py:57
+msgid ""
+"When enabled, the Phone number is only used during enrollment to verify the "
+"users authenticity. Only a hash of the phone number is saved to ensure it is"
+" not re-used in the future."
+msgstr ""
+"Indien ingeschakeld, wordt het telefoonnummer alleen gebruikt tijdens "
+"inschrijving om de authenticiteit van de gebruiker te verifiëren. Alleen een"
+" hash van het telefoonnummer wordt opgeslagen om ervoor te zorgen dat het in"
+" de toekomst niet opnieuw wordt gebruikt."
+
+#: authentik/stages/authenticator_sms/models.py:68
+msgid "Optionally modify the payload being sent to custom providers."
+msgstr ""
+"Optioneel de payload aanpassen die naar aangepaste providers wordt "
+"verzonden."
+
+#: authentik/stages/authenticator_sms/models.py:81
+#, python-format
+msgid "Use this code to authenticate in authentik: %(token)s"
+msgstr "Gebruik deze code om in authentik te authenticeren: %(token)s"
+
+#: authentik/stages/authenticator_sms/models.py:180
+msgid "SMS Authenticator Setup Stage"
+msgstr "SMS Authenticator Installatiestadium"
+
+#: authentik/stages/authenticator_sms/models.py:181
+msgid "SMS Authenticator Setup Stages"
+msgstr "SMS Authenticator Installatiestadia"
+
+#: authentik/stages/authenticator_sms/models.py:226
+msgid "SMS Device"
+msgstr "SMS-apparaat"
+
+#: authentik/stages/authenticator_sms/models.py:227
+msgid "SMS Devices"
+msgstr "SMS-apparaten"
+
+#: authentik/stages/authenticator_sms/stage.py:55
+#: authentik/stages/authenticator_totp/stage.py:42
+#: authentik/stages/authenticator_totp/stage.py:45
+msgid "Code does not match"
+msgstr "Code komt niet overeen"
+
+#: authentik/stages/authenticator_sms/stage.py:71
+msgid "Invalid phone number"
+msgstr "Onjuist telefoonnummer"
+
+#: authentik/stages/authenticator_static/models.py:47
+msgid "Static Authenticator Stage"
+msgstr "Statische Authenticatorfase"
+
+#: authentik/stages/authenticator_static/models.py:48
+msgid "Static Authenticator Stages"
+msgstr "Statische Authenticatorfasen"
+
+#: authentik/stages/authenticator_totp/models.py:16
+msgid "6 digits, widely compatible"
+msgstr "6 cijfers, breed compatibel"
+
+#: authentik/stages/authenticator_totp/models.py:17
+msgid "8 digits, not compatible with apps like Google Authenticator"
+msgstr "8 cijfers, niet compatibel met apps zoals Google Authenticator"
+
+#: authentik/stages/authenticator_totp/models.py:53
+msgid "TOTP Authenticator Setup Stage"
+msgstr "TOTP Authenticator Installatiestadium"
+
+#: authentik/stages/authenticator_totp/models.py:54
+msgid "TOTP Authenticator Setup Stages"
+msgstr "TOTP Authenticator Installatiestadia"
+
+#: authentik/stages/authenticator_validate/challenge.py:123
+msgid "Invalid Token"
+msgstr "Ongeldig token"
+
+#: authentik/stages/authenticator_validate/models.py:18
+msgid "Static"
+msgstr "Statisch"
+
+#: authentik/stages/authenticator_validate/models.py:19
+msgid "TOTP"
+msgstr "TOTP"
+
+#: authentik/stages/authenticator_validate/models.py:20
+msgid "WebAuthn"
+msgstr "WebAuthn"
+
+#: authentik/stages/authenticator_validate/models.py:21
+msgid "Duo"
+msgstr "Duo"
+
+#: authentik/stages/authenticator_validate/models.py:22
+msgid "SMS"
+msgstr "SMS"
+
+#: authentik/stages/authenticator_validate/models.py:49
+msgid ""
+"Stages used to configure Authenticator when user doesn't have any compatible"
+" devices. After this configuration Stage passes, the user is not prompted "
+"again."
+msgstr ""
+"Fasen die worden gebruikt om Authenticator te configureren wanneer de "
+"gebruiker geen compatibele apparaten heeft. Nadat deze configuratiefase is "
+"doorlopen, wordt de gebruiker niet opnieuw gevraagd."
+
+#: authentik/stages/authenticator_validate/models.py:56
+msgid "Device classes which can be used to authenticate"
+msgstr "Apparaatklassen die kunnen worden gebruikt om te authenticeren"
+
+#: authentik/stages/authenticator_validate/models.py:64
+msgid ""
+"If any of the user's device has been used within this threshold, this stage "
+"will be skipped"
+msgstr ""
+"Als een van de apparaten van de gebruiker binnen deze drempel is gebruikt, "
+"wordt deze fase overgeslagen."
+
+#: authentik/stages/authenticator_validate/models.py:70
+msgid "Enforce user verification for WebAuthn devices."
+msgstr "Dwing gebruikersverificatie af voor WebAuthn-apparaten."
+
+#: authentik/stages/authenticator_validate/models.py:92
+msgid "Authenticator Validation Stage"
+msgstr "Authenticator Validatiefase"
+
+#: authentik/stages/authenticator_validate/models.py:93
+msgid "Authenticator Validation Stages"
+msgstr "Authenticator Validatiefasen"
+
+#: authentik/stages/authenticator_webauthn/models.py:112
+msgid "WebAuthn Authenticator Setup Stage"
+msgstr "WebAuthn Authenticator Installatiestadium"
+
+#: authentik/stages/authenticator_webauthn/models.py:113
+msgid "WebAuthn Authenticator Setup Stages"
+msgstr "WebAuthn Authenticator Installatiestadia"
+
+#: authentik/stages/authenticator_webauthn/models.py:151
+msgid "WebAuthn Device"
+msgstr "WebAuthn-apparaat"
+
+#: authentik/stages/authenticator_webauthn/models.py:152
+msgid "WebAuthn Devices"
+msgstr "WebAuthn-apparaten"
+
+#: authentik/stages/captcha/models.py:14
+msgid "Public key, acquired your captcha Provider."
+msgstr "Openbare sleutel, verworven door uw captcha-provider."
+
+#: authentik/stages/captcha/models.py:15
+msgid "Private key, acquired your captcha Provider."
+msgstr "Privésleutel, verworven door uw captcha-provider."
+
+#: authentik/stages/captcha/models.py:37
+msgid "Captcha Stage"
+msgstr "Captcha-fase"
+
+#: authentik/stages/captcha/models.py:38
+msgid "Captcha Stages"
+msgstr "Captcha-fasen"
+
+#: authentik/stages/consent/models.py:30
+msgid ""
+"Offset after which consent expires. (Format: hours=1;minutes=2;seconds=3)."
+msgstr ""
+"Offset waarna toestemming vervalt. (Formaat: uren=1;minuten=2;seconden=3)."
+
+#: authentik/stages/consent/models.py:50
+msgid "Consent Stage"
+msgstr "Toestemmingsfase"
+
+#: authentik/stages/consent/models.py:51
+msgid "Consent Stages"
+msgstr "Toestemmingsfasen"
+
+#: authentik/stages/consent/models.py:72
+msgid "User Consent"
+msgstr "Gebruikerstoestemming"
+
+#: authentik/stages/consent/models.py:73
+msgid "User Consents"
+msgstr "Gebruikersinstemmingen"
+
+#: authentik/stages/deny/models.py:30
+msgid "Deny Stage"
+msgstr "Weigerfase"
+
+#: authentik/stages/deny/models.py:31
+msgid "Deny Stages"
+msgstr "Weigerfasen"
+
+#: authentik/stages/dummy/models.py:34
+msgid "Dummy Stage"
+msgstr "Dummystadium"
+
+#: authentik/stages/dummy/models.py:35
+msgid "Dummy Stages"
+msgstr "Dummystadia"
+
+#: authentik/stages/email/models.py:26
+msgid "Password Reset"
+msgstr "Wachtwoordherstel"
+
+#: authentik/stages/email/models.py:30
+msgid "Account Confirmation"
+msgstr "Accountbevestiging"
+
+#: authentik/stages/email/models.py:59
+msgid ""
+"When enabled, global Email connection settings will be used and connection "
+"settings below will be ignored."
+msgstr ""
+"Wanneer ingeschakeld, worden de wereldwijde e-mailverbindinginstellingen "
+"gebruikt en worden de onderstaande verbindingsinstellingen genegeerd."
+
+#: authentik/stages/email/models.py:74
+msgid "Activate users upon completion of stage."
+msgstr "Activeer gebruikers na voltooiing van het stadium."
+
+#: authentik/stages/email/models.py:78
+msgid "Time in minutes the token sent is valid."
+msgstr "Tijd in minuten dat het verzonden token geldig is."
+
+#: authentik/stages/email/models.py:132
+msgid "Email Stage"
+msgstr "E-mailstadium"
+
+#: authentik/stages/email/models.py:133
+msgid "Email Stages"
+msgstr "E-mailstadia"
+
+#: authentik/stages/email/stage.py:112
+msgid "Successfully verified Email."
+msgstr "E-mail succesvol geverifieerd."
+
+#: authentik/stages/email/stage.py:119 authentik/stages/email/stage.py:141
+msgid "No pending user."
+msgstr "Geen wachtende gebruiker."
+
+#: authentik/stages/email/stage.py:131
+msgid "Email sent."
+msgstr "E-mail verzonden."
+
+#: authentik/stages/email/templates/email/account_confirmation.html:9
+msgid "Welcome!"
+msgstr "Welkom!"
+
+#: authentik/stages/email/templates/email/account_confirmation.html:12
+msgid ""
+"We're excited to have you get started. First, you need to confirm your "
+"account. Just press the button below."
+msgstr ""
+"We zijn verheugd dat je aan de slag gaat. Allereerst moet je je account "
+"bevestigen. Druk gewoon op de knop hieronder."
+
+#: authentik/stages/email/templates/email/account_confirmation.html:21
+msgid "Confirm Account"
+msgstr "Bevestig account"
+
+#: authentik/stages/email/templates/email/account_confirmation.html:30
+#, python-format
+msgid ""
+"\n"
+" If that doesn't work, copy and paste the following link in your browser: %(url)s\n"
+" "
+msgstr ""
+"\n"
+" Als dat niet werkt, kopieer en plak de volgende link in uw browser: %(url)s\n"
+
+#: authentik/stages/email/templates/email/account_confirmation.html:35
+msgid ""
+"If you have any questions, just reply to this email—we're always happy to "
+"help out."
+msgstr ""
+"Als je vragen hebt, antwoord dan gewoon op deze e-mail - we helpen je graag."
+
+#: authentik/stages/email/templates/email/generic.html:24
+msgid "Additional Information"
+msgstr "Aanvullende informatie"
+
+#: authentik/stages/email/templates/email/password_reset.html:9
+#, python-format
+msgid ""
+"\n"
+" Hi %(username)s,\n"
+" "
+msgstr ""
+"\n"
+" Hallo %(username)s,\n"
+
+#: authentik/stages/email/templates/email/password_reset.html:19
+msgid ""
+"\n"
+" You recently requested to change your password for your authentik account. Use the button below to set a new password.\n"
+" "
+msgstr ""
+"\n"
+" Je hebt onlangs gevraagd om je wachtwoord voor je authentik-account te wijzigen. Gebruik de knop hieronder om een nieuw wachtwoord in te stellen.\n"
+
+#: authentik/stages/email/templates/email/password_reset.html:33
+msgid "Reset Password"
+msgstr "Wachtwoord herstellen"
+
+#: authentik/stages/email/templates/email/password_reset.html:45
+#, python-format
+msgid ""
+"\n"
+" If you did not request a password change, please ignore this Email. The link above is valid for %(expires)s.\n"
+" "
+msgstr ""
+"\n"
+" Als je geen verzoek hebt ingediend om je wachtwoord te wijzigen, negeer dan deze e-mail. De bovenstaande link is geldig tot %(expires)s.\n"
+
+#: authentik/stages/email/templates/email/setup.html:9
+msgid "authentik Test-Email"
+msgstr "authentik Test-E-mail"
+
+#: authentik/stages/email/templates/email/setup.html:17
+msgid ""
+"\n"
+" This is a test email to inform you, that you've successfully configured authentik emails.\n"
+" "
+msgstr ""
+"\n"
+" Dit is een test-e-mail om u te informeren dat u authentik-e-mails succesvol heeft geconfigureerd.\n"
+
+#: authentik/stages/identification/api.py:20
+msgid "When no user fields are selected, at least one source must be selected"
+msgstr ""
+"Wanneer er geen gebruikersvelden zijn geselecteerd, moet ten minste één bron"
+" worden geselecteerd"
+
+#: authentik/stages/identification/models.py:29
+msgid ""
+"Fields of the user object to match against. (Hold shift to select multiple "
+"options)"
+msgstr ""
+"Velden van het gebruikersobject om tegen te matchen. (Houd Shift ingedrukt "
+"om meerdere opties te selecteren)"
+
+#: authentik/stages/identification/models.py:47
+msgid "When enabled, user fields are matched regardless of their casing."
+msgstr ""
+"Indien ingeschakeld, worden gebruikersvelden gematcht ongeacht hun "
+"hoofdlettergebruik."
+
+#: authentik/stages/identification/models.py:52
+msgid ""
+"When a valid username/email has been entered, and this option is enabled, "
+"the user's username and avatar will be shown. Otherwise, the text that the "
+"user entered will be shown"
+msgstr ""
+"Als een geldige gebruikersnaam/e-mail is ingevoerd en deze optie is "
+"ingeschakeld, worden de gebruikersnaam en avatar van de gebruiker "
+"weergegeven. Anders wordt de tekst die de gebruiker heeft ingevoerd getoond."
+
+#: authentik/stages/identification/models.py:65
+msgid "Optional enrollment flow, which is linked at the bottom of the page."
+msgstr "Optionele inschrijvingsflow, die onderaan de pagina is gekoppeld."
+
+#: authentik/stages/identification/models.py:74
+msgid "Optional recovery flow, which is linked at the bottom of the page."
+msgstr "Optionele herstelflow, die onderaan de pagina is gekoppeld."
+
+#: authentik/stages/identification/models.py:83
+msgid "Optional passwordless flow, which is linked at the bottom of the page."
+msgstr "Optionele wachtwoordloze flow, die onderaan de pagina is gekoppeld."
+
+#: authentik/stages/identification/models.py:87
+msgid "Specify which sources should be shown."
+msgstr "Specificeer welke bronnen moeten worden getoond."
+
+#: authentik/stages/identification/models.py:108
+msgid "Identification Stage"
+msgstr "Identificatiestadium"
+
+#: authentik/stages/identification/models.py:109
+msgid "Identification Stages"
+msgstr "Identificatiestadia"
+
+#: authentik/stages/identification/stage.py:184
+msgid "Log in"
+msgstr "Inloggen"
+
+#: authentik/stages/identification/stage.py:185
+msgid "Continue"
+msgstr "Doorgaan"
+
+#: authentik/stages/invitation/models.py:21
+msgid ""
+"If this flag is set, this Stage will jump to the next Stage when no "
+"Invitation is given. By default this Stage will cancel the Flow when no "
+"invitation is given."
+msgstr ""
+"Als deze vlag is ingesteld, zal dit stadium naar het volgende stadium "
+"springen wanneer er geen uitnodiging wordt gegeven. Standaard zal dit "
+"stadium de flow annuleren als er geen uitnodiging wordt gegeven."
+
+#: authentik/stages/invitation/models.py:44
+msgid "Invitation Stage"
+msgstr "Uitnodigingsstadium"
+
+#: authentik/stages/invitation/models.py:45
+msgid "Invitation Stages"
+msgstr "Uitnodigingsstadia"
+
+#: authentik/stages/invitation/models.py:60
+msgid "When set, only the configured flow can use this invitation."
+msgstr ""
+"Wanneer ingesteld, kan alleen de geconfigureerde flow deze uitnodiging "
+"gebruiken."
+
+#: authentik/stages/invitation/models.py:64
+msgid "When enabled, the invitation will be deleted after usage."
+msgstr "Indien ingeschakeld, wordt de uitnodiging verwijderd na gebruik."
+
+#: authentik/stages/invitation/models.py:71
+msgid "Optional fixed data to enforce on user enrollment."
+msgstr "Optionele vaste gegevens om af te dwingen bij gebruikersinschrijving."
+
+#: authentik/stages/invitation/models.py:84
+msgid "Invitation"
+msgstr "Uitnodiging"
+
+#: authentik/stages/invitation/models.py:85
+msgid "Invitations"
+msgstr "Uitnodigingen"
+
+#: authentik/stages/invitation/stage.py:66
+msgid "Invalid invite/invite not found"
+msgstr "Ongeldige uitnodiging/uitnodiging niet gevonden"
+
+#: authentik/stages/password/models.py:20
+msgid "User database + standard password"
+msgstr "Gebruikersdatabase + standaard wachtwoord"
+
+#: authentik/stages/password/models.py:24
+msgid "User database + app passwords"
+msgstr "Gebruikersdatabase + app-wachtwoorden"
+
+#: authentik/stages/password/models.py:28
+msgid "User database + LDAP password"
+msgstr "Gebruikersdatabase + LDAP-wachtwoord"
+
+#: authentik/stages/password/models.py:38
+msgid "Selection of backends to test the password against."
+msgstr "Selectie van back-ends om het wachtwoord tegen te testen."
+
+#: authentik/stages/password/models.py:43
+msgid ""
+"How many attempts a user has before the flow is canceled. To lock the user "
+"out, use a reputation policy and a user_write stage."
+msgstr ""
+"Hoeveel pogingen een gebruiker heeft voordat de flow wordt geannuleerd. Om "
+"de gebruiker buiten te sluiten, gebruik een reputatiebeleid en een "
+"gebruikersschrijffase."
+
+#: authentik/stages/password/models.py:75
+msgid "Password Stage"
+msgstr "Wachtwoordstadium"
+
+#: authentik/stages/password/models.py:76
+msgid "Password Stages"
+msgstr "Wachtwoordstadia"
+
+#: authentik/stages/password/stage.py:159
+msgid "Invalid password"
+msgstr "Ongeldig wachtwoord"
+
+#: authentik/stages/prompt/models.py:43
+msgid "Text: Simple Text input"
+msgstr "Tekst: Eenvoudige tekstinvoer"
+
+#: authentik/stages/prompt/models.py:45
+msgid "Text area: Multiline Text Input."
+msgstr "Tekstgebied: Meerregelige tekstinvoer."
+
+#: authentik/stages/prompt/models.py:48
+msgid "Text (read-only): Simple Text input, but cannot be edited."
+msgstr ""
+"Tekst (alleen-lezen): Eenvoudige tekstinvoer, maar kan niet worden bewerkt."
+
+#: authentik/stages/prompt/models.py:52
+msgid "Text area (read-only): Multiline Text input, but cannot be edited."
+msgstr ""
+"Tekstgebied (alleen-lezen): Meerregelige tekstinvoer, maar kan niet worden "
+"bewerkt."
+
+#: authentik/stages/prompt/models.py:58
+msgid ""
+"Username: Same as Text input, but checks for and prevents duplicate "
+"usernames."
+msgstr ""
+"Gebruikersnaam: Hetzelfde als Tekstinvoer, maar controleert op en voorkomt "
+"dubbele gebruikersnamen."
+
+#: authentik/stages/prompt/models.py:60
+msgid "Email: Text field with Email type."
+msgstr "E-mail: Tekstveld met e-mailtype."
+
+#: authentik/stages/prompt/models.py:64
+msgid ""
+"Password: Masked input, multiple inputs of this type on the same prompt need"
+" to be identical."
+msgstr ""
+"Wachtwoord: Gemaskeerde invoer, meerdere invoer van dit type op dezelfde "
+"prompt moeten identiek zijn."
+
+#: authentik/stages/prompt/models.py:71
+msgid "Fixed choice field rendered as a group of radio buttons."
+msgstr "Vast keuzeveld weergegeven als een groep radioknoppen."
+
+#: authentik/stages/prompt/models.py:73
+msgid "Fixed choice field rendered as a dropdown."
+msgstr "Vast keuzeveld weergegeven als een vervolgkeuzemenu."
+
+#: authentik/stages/prompt/models.py:80
+msgid ""
+"File: File upload for arbitrary files. File content will be available in "
+"flow context as data-URI"
+msgstr ""
+"Bestand: Bestandsupload voor willekeurige bestanden. Bestandsinhoud is "
+"beschikbaar in de flowcontext als gegevens-URI."
+
+#: authentik/stages/prompt/models.py:85
+msgid "Separator: Static Separator Line"
+msgstr "Scheidingsteken: Statische scheiderlijn"
+
+#: authentik/stages/prompt/models.py:86
+msgid "Hidden: Hidden field, can be used to insert data into form."
+msgstr ""
+"Verborgen: Verborgen veld, kan worden gebruikt om gegevens in het formulier "
+"in te voegen."
+
+#: authentik/stages/prompt/models.py:87
+msgid "Static: Static value, displayed as-is."
+msgstr "Statisch: Statische waarde, weergegeven zoals deze is."
+
+#: authentik/stages/prompt/models.py:89
+msgid "authentik: Selection of locales authentik supports"
+msgstr ""
+"authentik: Selectie van de door authentik ondersteunde taalinstellingen"
+
+#: authentik/stages/prompt/models.py:116
+msgid "Name of the form field, also used to store the value"
+msgstr ""
+"Naam van het formulierenveld, wordt ook gebruikt om de waarde op te slaan"
+
+#: authentik/stages/prompt/models.py:124
+msgid ""
+"Optionally provide a short hint that describes the expected input value. "
+"When creating a fixed choice field, enable interpreting as expression and "
+"return a list to return multiple choices."
+msgstr ""
+"Optioneel een korte hint geven die de verwachte invoerwaarde beschrijft. Bij"
+" het maken van een vast keuzeveld, interpreteren als expressie inschakelen "
+"en een lijst retourneren om meerdere keuzes terug te geven."
+
+#: authentik/stages/prompt/models.py:132
+msgid ""
+"Optionally pre-fill the input with an initial value. When creating a fixed "
+"choice field, enable interpreting as expression and return a list to return "
+"multiple default choices."
+msgstr ""
+"Optioneel de invoer vooraf invullen met een initiële waarde. Bij het maken "
+"van een vast keuzeveld, interpreteren als expressie inschakelen en een lijst"
+" retourneren om meerdere standaardkeuzes terug te geven."
+
+#: authentik/stages/prompt/models.py:321
+msgid "Prompt"
+msgstr "Prompt"
+
+#: authentik/stages/prompt/models.py:322
+msgid "Prompts"
+msgstr "Prompts"
+
+#: authentik/stages/prompt/models.py:349
+msgid "Prompt Stage"
+msgstr "Promptstadium"
+
+#: authentik/stages/prompt/models.py:350
+msgid "Prompt Stages"
+msgstr "Promptstadia"
+
+#: authentik/stages/prompt/stage.py:108
+msgid "Passwords don't match."
+msgstr "Wachtwoorden komen niet overeen."
+
+#: authentik/stages/user_delete/models.py:31
+msgid "User Delete Stage"
+msgstr "Gebruikersverwijderingsstadium"
+
+#: authentik/stages/user_delete/models.py:32
+msgid "User Delete Stages"
+msgstr "Gebruikersverwijderingsstadia"
+
+#: authentik/stages/user_delete/stage.py:22
+msgid "No Pending User."
+msgstr "Geen in behandeling zijnde gebruiker."
+
+#: authentik/stages/user_login/models.py:19
+msgid ""
+"Determines how long a session lasts. Default of 0 means that the sessions "
+"lasts until the browser is closed. (Format: hours=-1;minutes=-2;seconds=-3)"
+msgstr ""
+"Bepaalt hoe lang een sessie duurt. Standaardwaarde van 0 betekent dat de "
+"sessies duren tot de browser wordt gesloten. (Indeling: "
+"uren=-1;minuten=-2;seconden=-3)"
+
+#: authentik/stages/user_login/models.py:25
+msgid "Terminate all other sessions of the user logging in."
+msgstr "Beëindig alle andere sessies van de gebruiker die inlogt."
+
+#: authentik/stages/user_login/models.py:31
+msgid ""
+"Offset the session will be extended by when the user picks the remember me "
+"option. Default of 0 means that the remember me option will not be shown. "
+"(Format: hours=-1;minutes=-2;seconds=-3)"
+msgstr ""
+"De sessie zal worden verlengd met het opgegeven aantal uren, minuten en "
+"seconden wanneer de gebruiker de optie 'Onthoud mij' kiest. De "
+"standaardwaarde van 0 betekent dat de optie 'Onthoud mij' niet wordt "
+"getoond. (Indeling: uren=-1;minuten=-2;seconden=-3)"
+
+#: authentik/stages/user_login/models.py:54
+msgid "User Login Stage"
+msgstr "Inlogstadium voor gebruikers"
+
+#: authentik/stages/user_login/models.py:55
+msgid "User Login Stages"
+msgstr "Inlogstadia voor gebruikers"
+
+#: authentik/stages/user_login/stage.py:63
+msgid "No Pending user to login."
+msgstr "Geen in behandeling zijnde gebruiker om in te loggen."
+
+#: authentik/stages/user_login/stage.py:96
+msgid "Successfully logged in!"
+msgstr "Succesvol ingelogd!"
+
+#: authentik/stages/user_logout/models.py:30
+msgid "User Logout Stage"
+msgstr "Gebruikersafmeldingsfase"
+
+#: authentik/stages/user_logout/models.py:31
+msgid "User Logout Stages"
+msgstr "Gebruikersafmeldingsfasen"
+
+#: authentik/stages/user_write/models.py:31
+msgid "When set, newly created users are inactive and cannot login."
+msgstr ""
+"Wanneer ingesteld, zijn nieuw aangemaakte gebruikers inactief en kunnen ze "
+"niet inloggen."
+
+#: authentik/stages/user_write/models.py:39
+msgid "Optionally add newly created users to this group."
+msgstr "Voeg indien gewenst nieuw aangemaakte gebruikers toe aan deze groep."
+
+#: authentik/stages/user_write/models.py:64
+msgid "User Write Stage"
+msgstr "Gebruikersschrijffase"
+
+#: authentik/stages/user_write/models.py:65
+msgid "User Write Stages"
+msgstr "Gebruikersschrijffasen"
+
+#: authentik/stages/user_write/stage.py:134
+msgid "No Pending data."
+msgstr "Geen in behandeling zijnde gegevens."
+
+#: authentik/stages/user_write/stage.py:140
+msgid "No user found and can't create new user."
+msgstr "Geen gebruiker gevonden en kan geen nieuwe gebruiker aanmaken."
+
+#: authentik/stages/user_write/stage.py:157
+#: authentik/stages/user_write/stage.py:171
+msgid "Failed to update user. Please try again later."
+msgstr "Het bijwerken van de gebruiker is mislukt. Probeer het later opnieuw."
+
+#: authentik/tenants/models.py:23
+msgid ""
+"Domain that activates this tenant. Can be a superset, i.e. `a.b` for `aa.b` "
+"and `ba.b`"
+msgstr ""
+"Domein dat deze tenant activeert. Kan een superset zijn, bijvoorbeeld `a.b` "
+"voor `aa.b` en `ba.b`."
+
+#: authentik/tenants/models.py:58
+msgid ""
+"Events will be deleted after this duration.(Format: "
+"weeks=3;days=2;hours=3,seconds=2)."
+msgstr ""
+"Gebeurtenissen worden verwijderd na deze duur. (Indeling: "
+"weken=3;dagen=2;uren=3;seconden=2)."
+
+#: authentik/tenants/models.py:67
+msgid "Web Certificate used by the authentik Core webserver."
+msgstr "Webcertificaat gebruikt door de authentik Core-webserver."
+
+#: authentik/tenants/models.py:93
+msgid "Tenant"
+msgstr "Tenant"
+
+#: authentik/tenants/models.py:94
+msgid "Tenants"
+msgstr "Tenants"
diff --git a/poetry.lock b/poetry.lock
index 2efa45073..013bbaa51 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1,4 +1,4 @@
-# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand.
+# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand.
[[package]]
name = "aiohttp"
@@ -150,6 +150,17 @@ files = [
[package.dependencies]
vine = ">=5.0.0"
+[[package]]
+name = "annotated-types"
+version = "0.5.0"
+description = "Reusable constraint types to use with typing.Annotated"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "annotated_types-0.5.0-py3-none-any.whl", hash = "sha256:58da39888f92c276ad970249761ebea80ba544b77acddaa1a4d6cf78287d45fd"},
+ {file = "annotated_types-0.5.0.tar.gz", hash = "sha256:47cdc3490d9ac1506ce92c7aaa76c579dc3509ff11e098fc867e5130ab7be802"},
+]
+
[[package]]
name = "anyio"
version = "3.7.1"
@@ -2674,56 +2685,141 @@ files = [
[[package]]
name = "pydantic"
-version = "1.10.12"
-description = "Data validation and settings management using python type hints"
+version = "2.3.0"
+description = "Data validation using Python type hints"
optional = false
python-versions = ">=3.7"
files = [
- {file = "pydantic-1.10.12-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a1fcb59f2f355ec350073af41d927bf83a63b50e640f4dbaa01053a28b7a7718"},
- {file = "pydantic-1.10.12-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b7ccf02d7eb340b216ec33e53a3a629856afe1c6e0ef91d84a4e6f2fb2ca70fe"},
- {file = "pydantic-1.10.12-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8fb2aa3ab3728d950bcc885a2e9eff6c8fc40bc0b7bb434e555c215491bcf48b"},
- {file = "pydantic-1.10.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:771735dc43cf8383959dc9b90aa281f0b6092321ca98677c5fb6125a6f56d58d"},
- {file = "pydantic-1.10.12-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ca48477862372ac3770969b9d75f1bf66131d386dba79506c46d75e6b48c1e09"},
- {file = "pydantic-1.10.12-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a5e7add47a5b5a40c49b3036d464e3c7802f8ae0d1e66035ea16aa5b7a3923ed"},
- {file = "pydantic-1.10.12-cp310-cp310-win_amd64.whl", hash = "sha256:e4129b528c6baa99a429f97ce733fff478ec955513630e61b49804b6cf9b224a"},
- {file = "pydantic-1.10.12-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b0d191db0f92dfcb1dec210ca244fdae5cbe918c6050b342d619c09d31eea0cc"},
- {file = "pydantic-1.10.12-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:795e34e6cc065f8f498c89b894a3c6da294a936ee71e644e4bd44de048af1405"},
- {file = "pydantic-1.10.12-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69328e15cfda2c392da4e713443c7dbffa1505bc9d566e71e55abe14c97ddc62"},
- {file = "pydantic-1.10.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2031de0967c279df0d8a1c72b4ffc411ecd06bac607a212892757db7462fc494"},
- {file = "pydantic-1.10.12-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:ba5b2e6fe6ca2b7e013398bc7d7b170e21cce322d266ffcd57cca313e54fb246"},
- {file = "pydantic-1.10.12-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2a7bac939fa326db1ab741c9d7f44c565a1d1e80908b3797f7f81a4f86bc8d33"},
- {file = "pydantic-1.10.12-cp311-cp311-win_amd64.whl", hash = "sha256:87afda5539d5140cb8ba9e8b8c8865cb5b1463924d38490d73d3ccfd80896b3f"},
- {file = "pydantic-1.10.12-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:549a8e3d81df0a85226963611950b12d2d334f214436a19537b2efed61b7639a"},
- {file = "pydantic-1.10.12-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:598da88dfa127b666852bef6d0d796573a8cf5009ffd62104094a4fe39599565"},
- {file = "pydantic-1.10.12-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba5c4a8552bff16c61882db58544116d021d0b31ee7c66958d14cf386a5b5350"},
- {file = "pydantic-1.10.12-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c79e6a11a07da7374f46970410b41d5e266f7f38f6a17a9c4823db80dadf4303"},
- {file = "pydantic-1.10.12-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ab26038b8375581dc832a63c948f261ae0aa21f1d34c1293469f135fa92972a5"},
- {file = "pydantic-1.10.12-cp37-cp37m-win_amd64.whl", hash = "sha256:e0a16d274b588767602b7646fa05af2782576a6cf1022f4ba74cbb4db66f6ca8"},
- {file = "pydantic-1.10.12-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6a9dfa722316f4acf4460afdf5d41d5246a80e249c7ff475c43a3a1e9d75cf62"},
- {file = "pydantic-1.10.12-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a73f489aebd0c2121ed974054cb2759af8a9f747de120acd2c3394cf84176ccb"},
- {file = "pydantic-1.10.12-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b30bcb8cbfccfcf02acb8f1a261143fab622831d9c0989707e0e659f77a18e0"},
- {file = "pydantic-1.10.12-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2fcfb5296d7877af406ba1547dfde9943b1256d8928732267e2653c26938cd9c"},
- {file = "pydantic-1.10.12-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:2f9a6fab5f82ada41d56b0602606a5506aab165ca54e52bc4545028382ef1c5d"},
- {file = "pydantic-1.10.12-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:dea7adcc33d5d105896401a1f37d56b47d443a2b2605ff8a969a0ed5543f7e33"},
- {file = "pydantic-1.10.12-cp38-cp38-win_amd64.whl", hash = "sha256:1eb2085c13bce1612da8537b2d90f549c8cbb05c67e8f22854e201bde5d98a47"},
- {file = "pydantic-1.10.12-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ef6c96b2baa2100ec91a4b428f80d8f28a3c9e53568219b6c298c1125572ebc6"},
- {file = "pydantic-1.10.12-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6c076be61cd0177a8433c0adcb03475baf4ee91edf5a4e550161ad57fc90f523"},
- {file = "pydantic-1.10.12-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d5a58feb9a39f481eda4d5ca220aa8b9d4f21a41274760b9bc66bfd72595b86"},
- {file = "pydantic-1.10.12-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5f805d2d5d0a41633651a73fa4ecdd0b3d7a49de4ec3fadf062fe16501ddbf1"},
- {file = "pydantic-1.10.12-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:1289c180abd4bd4555bb927c42ee42abc3aee02b0fb2d1223fb7c6e5bef87dbe"},
- {file = "pydantic-1.10.12-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5d1197e462e0364906cbc19681605cb7c036f2475c899b6f296104ad42b9f5fb"},
- {file = "pydantic-1.10.12-cp39-cp39-win_amd64.whl", hash = "sha256:fdbdd1d630195689f325c9ef1a12900524dceb503b00a987663ff4f58669b93d"},
- {file = "pydantic-1.10.12-py3-none-any.whl", hash = "sha256:b749a43aa51e32839c9d71dc67eb1e4221bb04af1033a32e3923d46f9effa942"},
- {file = "pydantic-1.10.12.tar.gz", hash = "sha256:0fe8a415cea8f340e7a9af9c54fc71a649b43e8ca3cc732986116b3cb135d303"},
+ {file = "pydantic-2.3.0-py3-none-any.whl", hash = "sha256:45b5e446c6dfaad9444819a293b921a40e1db1aa61ea08aede0522529ce90e81"},
+ {file = "pydantic-2.3.0.tar.gz", hash = "sha256:1607cc106602284cd4a00882986570472f193fde9cb1259bceeaedb26aa79a6d"},
]
[package.dependencies]
-email-validator = {version = ">=1.0.3", optional = true, markers = "extra == \"email\""}
-typing-extensions = ">=4.2.0"
+annotated-types = ">=0.4.0"
+email-validator = {version = ">=2.0.0", optional = true, markers = "extra == \"email\""}
+pydantic-core = "2.6.3"
+typing-extensions = ">=4.6.1"
[package.extras]
-dotenv = ["python-dotenv (>=0.10.4)"]
-email = ["email-validator (>=1.0.3)"]
+email = ["email-validator (>=2.0.0)"]
+
+[[package]]
+name = "pydantic-core"
+version = "2.6.3"
+description = ""
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "pydantic_core-2.6.3-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:1a0ddaa723c48af27d19f27f1c73bdc615c73686d763388c8683fe34ae777bad"},
+ {file = "pydantic_core-2.6.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5cfde4fab34dd1e3a3f7f3db38182ab6c95e4ea91cf322242ee0be5c2f7e3d2f"},
+ {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5493a7027bfc6b108e17c3383959485087d5942e87eb62bbac69829eae9bc1f7"},
+ {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:84e87c16f582f5c753b7f39a71bd6647255512191be2d2dbf49458c4ef024588"},
+ {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:522a9c4a4d1924facce7270c84b5134c5cabcb01513213662a2e89cf28c1d309"},
+ {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aaafc776e5edc72b3cad1ccedb5fd869cc5c9a591f1213aa9eba31a781be9ac1"},
+ {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a750a83b2728299ca12e003d73d1264ad0440f60f4fc9cee54acc489249b728"},
+ {file = "pydantic_core-2.6.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9e8b374ef41ad5c461efb7a140ce4730661aadf85958b5c6a3e9cf4e040ff4bb"},
+ {file = "pydantic_core-2.6.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b594b64e8568cf09ee5c9501ede37066b9fc41d83d58f55b9952e32141256acd"},
+ {file = "pydantic_core-2.6.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:2a20c533cb80466c1d42a43a4521669ccad7cf2967830ac62c2c2f9cece63e7e"},
+ {file = "pydantic_core-2.6.3-cp310-none-win32.whl", hash = "sha256:04fe5c0a43dec39aedba0ec9579001061d4653a9b53a1366b113aca4a3c05ca7"},
+ {file = "pydantic_core-2.6.3-cp310-none-win_amd64.whl", hash = "sha256:6bf7d610ac8f0065a286002a23bcce241ea8248c71988bda538edcc90e0c39ad"},
+ {file = "pydantic_core-2.6.3-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:6bcc1ad776fffe25ea5c187a028991c031a00ff92d012ca1cc4714087e575973"},
+ {file = "pydantic_core-2.6.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:df14f6332834444b4a37685810216cc8fe1fe91f447332cd56294c984ecbff1c"},
+ {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0b7486d85293f7f0bbc39b34e1d8aa26210b450bbd3d245ec3d732864009819"},
+ {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a892b5b1871b301ce20d40b037ffbe33d1407a39639c2b05356acfef5536d26a"},
+ {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:883daa467865e5766931e07eb20f3e8152324f0adf52658f4d302242c12e2c32"},
+ {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d4eb77df2964b64ba190eee00b2312a1fd7a862af8918ec70fc2d6308f76ac64"},
+ {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ce8c84051fa292a5dc54018a40e2a1926fd17980a9422c973e3ebea017aa8da"},
+ {file = "pydantic_core-2.6.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:22134a4453bd59b7d1e895c455fe277af9d9d9fbbcb9dc3f4a97b8693e7e2c9b"},
+ {file = "pydantic_core-2.6.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:02e1c385095efbd997311d85c6021d32369675c09bcbfff3b69d84e59dc103f6"},
+ {file = "pydantic_core-2.6.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d79f1f2f7ebdb9b741296b69049ff44aedd95976bfee38eb4848820628a99b50"},
+ {file = "pydantic_core-2.6.3-cp311-none-win32.whl", hash = "sha256:430ddd965ffd068dd70ef4e4d74f2c489c3a313adc28e829dd7262cc0d2dd1e8"},
+ {file = "pydantic_core-2.6.3-cp311-none-win_amd64.whl", hash = "sha256:84f8bb34fe76c68c9d96b77c60cef093f5e660ef8e43a6cbfcd991017d375950"},
+ {file = "pydantic_core-2.6.3-cp311-none-win_arm64.whl", hash = "sha256:5a2a3c9ef904dcdadb550eedf3291ec3f229431b0084666e2c2aa8ff99a103a2"},
+ {file = "pydantic_core-2.6.3-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:8421cf496e746cf8d6b677502ed9a0d1e4e956586cd8b221e1312e0841c002d5"},
+ {file = "pydantic_core-2.6.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bb128c30cf1df0ab78166ded1ecf876620fb9aac84d2413e8ea1594b588c735d"},
+ {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37a822f630712817b6ecc09ccc378192ef5ff12e2c9bae97eb5968a6cdf3b862"},
+ {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:240a015102a0c0cc8114f1cba6444499a8a4d0333e178bc504a5c2196defd456"},
+ {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f90e5e3afb11268628c89f378f7a1ea3f2fe502a28af4192e30a6cdea1e7d5e"},
+ {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:340e96c08de1069f3d022a85c2a8c63529fd88709468373b418f4cf2c949fb0e"},
+ {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1480fa4682e8202b560dcdc9eeec1005f62a15742b813c88cdc01d44e85308e5"},
+ {file = "pydantic_core-2.6.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f14546403c2a1d11a130b537dda28f07eb6c1805a43dae4617448074fd49c282"},
+ {file = "pydantic_core-2.6.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:a87c54e72aa2ef30189dc74427421e074ab4561cf2bf314589f6af5b37f45e6d"},
+ {file = "pydantic_core-2.6.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:f93255b3e4d64785554e544c1c76cd32f4a354fa79e2eeca5d16ac2e7fdd57aa"},
+ {file = "pydantic_core-2.6.3-cp312-none-win32.whl", hash = "sha256:f70dc00a91311a1aea124e5f64569ea44c011b58433981313202c46bccbec0e1"},
+ {file = "pydantic_core-2.6.3-cp312-none-win_amd64.whl", hash = "sha256:23470a23614c701b37252618e7851e595060a96a23016f9a084f3f92f5ed5881"},
+ {file = "pydantic_core-2.6.3-cp312-none-win_arm64.whl", hash = "sha256:1ac1750df1b4339b543531ce793b8fd5c16660a95d13aecaab26b44ce11775e9"},
+ {file = "pydantic_core-2.6.3-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:a53e3195f134bde03620d87a7e2b2f2046e0e5a8195e66d0f244d6d5b2f6d31b"},
+ {file = "pydantic_core-2.6.3-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:f2969e8f72c6236c51f91fbb79c33821d12a811e2a94b7aa59c65f8dbdfad34a"},
+ {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:672174480a85386dd2e681cadd7d951471ad0bb028ed744c895f11f9d51b9ebe"},
+ {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:002d0ea50e17ed982c2d65b480bd975fc41086a5a2f9c924ef8fc54419d1dea3"},
+ {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3ccc13afee44b9006a73d2046068d4df96dc5b333bf3509d9a06d1b42db6d8bf"},
+ {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:439a0de139556745ae53f9cc9668c6c2053444af940d3ef3ecad95b079bc9987"},
+ {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d63b7545d489422d417a0cae6f9898618669608750fc5e62156957e609e728a5"},
+ {file = "pydantic_core-2.6.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b44c42edc07a50a081672e25dfe6022554b47f91e793066a7b601ca290f71e42"},
+ {file = "pydantic_core-2.6.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:1c721bfc575d57305dd922e6a40a8fe3f762905851d694245807a351ad255c58"},
+ {file = "pydantic_core-2.6.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:5e4a2cf8c4543f37f5dc881de6c190de08096c53986381daebb56a355be5dfe6"},
+ {file = "pydantic_core-2.6.3-cp37-none-win32.whl", hash = "sha256:d9b4916b21931b08096efed090327f8fe78e09ae8f5ad44e07f5c72a7eedb51b"},
+ {file = "pydantic_core-2.6.3-cp37-none-win_amd64.whl", hash = "sha256:a8acc9dedd304da161eb071cc7ff1326aa5b66aadec9622b2574ad3ffe225525"},
+ {file = "pydantic_core-2.6.3-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:5e9c068f36b9f396399d43bfb6defd4cc99c36215f6ff33ac8b9c14ba15bdf6b"},
+ {file = "pydantic_core-2.6.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e61eae9b31799c32c5f9b7be906be3380e699e74b2db26c227c50a5fc7988698"},
+ {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d85463560c67fc65cd86153a4975d0b720b6d7725cf7ee0b2d291288433fc21b"},
+ {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9616567800bdc83ce136e5847d41008a1d602213d024207b0ff6cab6753fe645"},
+ {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9e9b65a55bbabda7fccd3500192a79f6e474d8d36e78d1685496aad5f9dbd92c"},
+ {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f468d520f47807d1eb5d27648393519655eadc578d5dd862d06873cce04c4d1b"},
+ {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9680dd23055dd874173a3a63a44e7f5a13885a4cfd7e84814be71be24fba83db"},
+ {file = "pydantic_core-2.6.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9a718d56c4d55efcfc63f680f207c9f19c8376e5a8a67773535e6f7e80e93170"},
+ {file = "pydantic_core-2.6.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8ecbac050856eb6c3046dea655b39216597e373aa8e50e134c0e202f9c47efec"},
+ {file = "pydantic_core-2.6.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:788be9844a6e5c4612b74512a76b2153f1877cd845410d756841f6c3420230eb"},
+ {file = "pydantic_core-2.6.3-cp38-none-win32.whl", hash = "sha256:07a1aec07333bf5adebd8264047d3dc518563d92aca6f2f5b36f505132399efc"},
+ {file = "pydantic_core-2.6.3-cp38-none-win_amd64.whl", hash = "sha256:621afe25cc2b3c4ba05fff53525156d5100eb35c6e5a7cf31d66cc9e1963e378"},
+ {file = "pydantic_core-2.6.3-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:813aab5bfb19c98ae370952b6f7190f1e28e565909bfc219a0909db168783465"},
+ {file = "pydantic_core-2.6.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:50555ba3cb58f9861b7a48c493636b996a617db1a72c18da4d7f16d7b1b9952b"},
+ {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19e20f8baedd7d987bd3f8005c146e6bcbda7cdeefc36fad50c66adb2dd2da48"},
+ {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b0a5d7edb76c1c57b95df719af703e796fc8e796447a1da939f97bfa8a918d60"},
+ {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f06e21ad0b504658a3a9edd3d8530e8cea5723f6ea5d280e8db8efc625b47e49"},
+ {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea053cefa008fda40f92aab937fb9f183cf8752e41dbc7bc68917884454c6362"},
+ {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:171a4718860790f66d6c2eda1d95dd1edf64f864d2e9f9115840840cf5b5713f"},
+ {file = "pydantic_core-2.6.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5ed7ceca6aba5331ece96c0e328cd52f0dcf942b8895a1ed2642de50800b79d3"},
+ {file = "pydantic_core-2.6.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:acafc4368b289a9f291e204d2c4c75908557d4f36bd3ae937914d4529bf62a76"},
+ {file = "pydantic_core-2.6.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1aa712ba150d5105814e53cb141412217146fedc22621e9acff9236d77d2a5ef"},
+ {file = "pydantic_core-2.6.3-cp39-none-win32.whl", hash = "sha256:44b4f937b992394a2e81a5c5ce716f3dcc1237281e81b80c748b2da6dd5cf29a"},
+ {file = "pydantic_core-2.6.3-cp39-none-win_amd64.whl", hash = "sha256:9b33bf9658cb29ac1a517c11e865112316d09687d767d7a0e4a63d5c640d1b17"},
+ {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:d7050899026e708fb185e174c63ebc2c4ee7a0c17b0a96ebc50e1f76a231c057"},
+ {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:99faba727727b2e59129c59542284efebbddade4f0ae6a29c8b8d3e1f437beb7"},
+ {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fa159b902d22b283b680ef52b532b29554ea2a7fc39bf354064751369e9dbd7"},
+ {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:046af9cfb5384f3684eeb3f58a48698ddab8dd870b4b3f67f825353a14441418"},
+ {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:930bfe73e665ebce3f0da2c6d64455098aaa67e1a00323c74dc752627879fc67"},
+ {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:85cc4d105747d2aa3c5cf3e37dac50141bff779545ba59a095f4a96b0a460e70"},
+ {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:b25afe9d5c4f60dcbbe2b277a79be114e2e65a16598db8abee2a2dcde24f162b"},
+ {file = "pydantic_core-2.6.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:e49ce7dc9f925e1fb010fc3d555250139df61fa6e5a0a95ce356329602c11ea9"},
+ {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-macosx_10_7_x86_64.whl", hash = "sha256:2dd50d6a1aef0426a1d0199190c6c43ec89812b1f409e7fe44cb0fbf6dfa733c"},
+ {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c6595b0d8c8711e8e1dc389d52648b923b809f68ac1c6f0baa525c6440aa0daa"},
+ {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ef724a059396751aef71e847178d66ad7fc3fc969a1a40c29f5aac1aa5f8784"},
+ {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3c8945a105f1589ce8a693753b908815e0748f6279959a4530f6742e1994dcb6"},
+ {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:c8c6660089a25d45333cb9db56bb9e347241a6d7509838dbbd1931d0e19dbc7f"},
+ {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:692b4ff5c4e828a38716cfa92667661a39886e71136c97b7dac26edef18767f7"},
+ {file = "pydantic_core-2.6.3-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:f1a5d8f18877474c80b7711d870db0eeef9442691fcdb00adabfc97e183ee0b0"},
+ {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:3796a6152c545339d3b1652183e786df648ecdf7c4f9347e1d30e6750907f5bb"},
+ {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:b962700962f6e7a6bd77e5f37320cabac24b4c0f76afeac05e9f93cf0c620014"},
+ {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:56ea80269077003eaa59723bac1d8bacd2cd15ae30456f2890811efc1e3d4413"},
+ {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75c0ebbebae71ed1e385f7dfd9b74c1cff09fed24a6df43d326dd7f12339ec34"},
+ {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:252851b38bad3bfda47b104ffd077d4f9604a10cb06fe09d020016a25107bf98"},
+ {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:6656a0ae383d8cd7cc94e91de4e526407b3726049ce8d7939049cbfa426518c8"},
+ {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:d9140ded382a5b04a1c030b593ed9bf3088243a0a8b7fa9f071a5736498c5483"},
+ {file = "pydantic_core-2.6.3-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:d38bbcef58220f9c81e42c255ef0bf99735d8f11edef69ab0b499da77105158a"},
+ {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:c9d469204abcca28926cbc28ce98f28e50e488767b084fb3fbdf21af11d3de26"},
+ {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:48c1ed8b02ffea4d5c9c220eda27af02b8149fe58526359b3c07eb391cb353a2"},
+ {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b2b1bfed698fa410ab81982f681f5b1996d3d994ae8073286515ac4d165c2e7"},
+ {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf9d42a71a4d7a7c1f14f629e5c30eac451a6fc81827d2beefd57d014c006c4a"},
+ {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4292ca56751aebbe63a84bbfc3b5717abb09b14d4b4442cc43fd7c49a1529efd"},
+ {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:7dc2ce039c7290b4ef64334ec7e6ca6494de6eecc81e21cb4f73b9b39991408c"},
+ {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:615a31b1629e12445c0e9fc8339b41aaa6cc60bd53bf802d5fe3d2c0cda2ae8d"},
+ {file = "pydantic_core-2.6.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:1fa1f6312fb84e8c281f32b39affe81984ccd484da6e9d65b3d18c202c666149"},
+ {file = "pydantic_core-2.6.3.tar.gz", hash = "sha256:1508f37ba9e3ddc0189e6ff4e2228bd2d3c3a4641cbe8c07177162f76ed696c7"},
+]
+
+[package.dependencies]
+typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0"
[[package]]
name = "pydantic-scim"
@@ -3309,28 +3405,28 @@ pyasn1 = ">=0.1.3"
[[package]]
name = "ruff"
-version = "0.0.285"
+version = "0.0.286"
description = "An extremely fast Python linter, written in Rust."
optional = false
python-versions = ">=3.7"
files = [
- {file = "ruff-0.0.285-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:72a3a0936369b986b0e959f9090206ed3c18f9e5e439ea5b8e6867c6707aded5"},
- {file = "ruff-0.0.285-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:0d9ab6ad16742eb78919e0fba09f914f042409df40ad63423c34bb20d350162a"},
- {file = "ruff-0.0.285-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c48926156288b8ac005eb1db5e77c15e8a37309ae49d9fb6771d5cf5f777590"},
- {file = "ruff-0.0.285-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1d2a60c102e7a5e147b58fc2cbea12a563c565383effc527c987ea2086a05742"},
- {file = "ruff-0.0.285-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b02aae62f922d088bb01943e1dbd861688ada13d735b78b8348a7d90121fd292"},
- {file = "ruff-0.0.285-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:f572c4296d8c7ddd22c3204de4031965be524fdd1fdaaef273945932912b28c5"},
- {file = "ruff-0.0.285-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:80effdf4fe69763d69eb4ab9443e186fd09e668b59fe70ba4b49f4c077d15a1b"},
- {file = "ruff-0.0.285-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5977ce304da35c263f5e082901bd7ac0bd2be845a8fcfd1a29e4d6680cddb307"},
- {file = "ruff-0.0.285-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72a087712d474fa17b915d7cb9ef807e1256182b12ddfafb105eb00aeee48d1a"},
- {file = "ruff-0.0.285-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:7ce67736cd8dfe97162d1e7adfc2d9a1bac0efb9aaaff32e4042c7cde079f54b"},
- {file = "ruff-0.0.285-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:5473a4c6cac34f583bff08c5f63b8def5599a0ea4dc96c0302fbd2cc0b3ecbad"},
- {file = "ruff-0.0.285-py3-none-musllinux_1_2_i686.whl", hash = "sha256:e6b1c961d608d373a032f047a20bf3c55ad05f56c32e7b96dcca0830a2a72348"},
- {file = "ruff-0.0.285-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:2933cc9631f453305399c7b8fb72b113ad76b49ae1d7103cc4afd3a423bed164"},
- {file = "ruff-0.0.285-py3-none-win32.whl", hash = "sha256:770c5eb6376de024111443022cda534fb28980a9dd3b4abc83992a8770167ba6"},
- {file = "ruff-0.0.285-py3-none-win_amd64.whl", hash = "sha256:a8c6ad6b9cd77489bf6d1510950cbbe47a843aa234adff0960bae64bd06c3b6d"},
- {file = "ruff-0.0.285-py3-none-win_arm64.whl", hash = "sha256:de44fbc6c3b25fccee473ddf851416fd4e246fc6027b2197c395b1b3b3897921"},
- {file = "ruff-0.0.285.tar.gz", hash = "sha256:45866048d1dcdcc80855998cb26c4b2b05881f9e043d2e3bfe1aa36d9a2e8f28"},
+ {file = "ruff-0.0.286-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:8e22cb557e7395893490e7f9cfea1073d19a5b1dd337f44fd81359b2767da4e9"},
+ {file = "ruff-0.0.286-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:68ed8c99c883ae79a9133cb1a86d7130feee0397fdf5ba385abf2d53e178d3fa"},
+ {file = "ruff-0.0.286-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8301f0bb4ec1a5b29cfaf15b83565136c47abefb771603241af9d6038f8981e8"},
+ {file = "ruff-0.0.286-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:acc4598f810bbc465ce0ed84417ac687e392c993a84c7eaf3abf97638701c1ec"},
+ {file = "ruff-0.0.286-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88c8e358b445eb66d47164fa38541cfcc267847d1e7a92dd186dddb1a0a9a17f"},
+ {file = "ruff-0.0.286-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:0433683d0c5dbcf6162a4beb2356e820a593243f1fa714072fec15e2e4f4c939"},
+ {file = "ruff-0.0.286-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddb61a0c4454cbe4623f4a07fef03c5ae921fe04fede8d15c6e36703c0a73b07"},
+ {file = "ruff-0.0.286-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:47549c7c0be24c8ae9f2bce6f1c49fbafea83bca80142d118306f08ec7414041"},
+ {file = "ruff-0.0.286-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:559aa793149ac23dc4310f94f2c83209eedb16908a0343663be19bec42233d25"},
+ {file = "ruff-0.0.286-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:d73cfb1c3352e7aa0ce6fb2321f36fa1d4a2c48d2ceac694cb03611ddf0e4db6"},
+ {file = "ruff-0.0.286-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:3dad93b1f973c6d1db4b6a5da8690c5625a3fa32bdf38e543a6936e634b83dc3"},
+ {file = "ruff-0.0.286-py3-none-musllinux_1_2_i686.whl", hash = "sha256:26afc0851f4fc3738afcf30f5f8b8612a31ac3455cb76e611deea80f5c0bf3ce"},
+ {file = "ruff-0.0.286-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:9b6b116d1c4000de1b9bf027131dbc3b8a70507788f794c6b09509d28952c512"},
+ {file = "ruff-0.0.286-py3-none-win32.whl", hash = "sha256:556e965ac07c1e8c1c2d759ac512e526ecff62c00fde1a046acb088d3cbc1a6c"},
+ {file = "ruff-0.0.286-py3-none-win_amd64.whl", hash = "sha256:5d295c758961376c84aaa92d16e643d110be32add7465e197bfdaec5a431a107"},
+ {file = "ruff-0.0.286-py3-none-win_arm64.whl", hash = "sha256:1d6142d53ab7f164204b3133d053c4958d4d11ec3a39abf23a40b13b0784e3f0"},
+ {file = "ruff-0.0.286.tar.gz", hash = "sha256:f1e9d169cce81a384a26ee5bb8c919fe9ae88255f39a1a69fd1ebab233a85ed2"},
]
[[package]]
@@ -3552,22 +3648,22 @@ files = [
[[package]]
name = "tornado"
-version = "6.3.2"
+version = "6.3.3"
description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed."
optional = false
python-versions = ">= 3.8"
files = [
- {file = "tornado-6.3.2-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:c367ab6c0393d71171123ca5515c61ff62fe09024fa6bf299cd1339dc9456829"},
- {file = "tornado-6.3.2-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:b46a6ab20f5c7c1cb949c72c1994a4585d2eaa0be4853f50a03b5031e964fc7c"},
- {file = "tornado-6.3.2-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c2de14066c4a38b4ecbbcd55c5cc4b5340eb04f1c5e81da7451ef555859c833f"},
- {file = "tornado-6.3.2-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:05615096845cf50a895026f749195bf0b10b8909f9be672f50b0fe69cba368e4"},
- {file = "tornado-6.3.2-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b17b1cf5f8354efa3d37c6e28fdfd9c1c1e5122f2cb56dac121ac61baa47cbe"},
- {file = "tornado-6.3.2-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:29e71c847a35f6e10ca3b5c2990a52ce38b233019d8e858b755ea6ce4dcdd19d"},
- {file = "tornado-6.3.2-cp38-abi3-musllinux_1_1_i686.whl", hash = "sha256:834ae7540ad3a83199a8da8f9f2d383e3c3d5130a328889e4cc991acc81e87a0"},
- {file = "tornado-6.3.2-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:6a0848f1aea0d196a7c4f6772197cbe2abc4266f836b0aac76947872cd29b411"},
- {file = "tornado-6.3.2-cp38-abi3-win32.whl", hash = "sha256:7efcbcc30b7c654eb6a8c9c9da787a851c18f8ccd4a5a3a95b05c7accfa068d2"},
- {file = "tornado-6.3.2-cp38-abi3-win_amd64.whl", hash = "sha256:0c325e66c8123c606eea33084976c832aa4e766b7dff8aedd7587ea44a604cdf"},
- {file = "tornado-6.3.2.tar.gz", hash = "sha256:4b927c4f19b71e627b13f3db2324e4ae660527143f9e1f2e2fb404f3a187e2ba"},
+ {file = "tornado-6.3.3-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:502fba735c84450974fec147340016ad928d29f1e91f49be168c0a4c18181e1d"},
+ {file = "tornado-6.3.3-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:805d507b1f588320c26f7f097108eb4023bbaa984d63176d1652e184ba24270a"},
+ {file = "tornado-6.3.3-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1bd19ca6c16882e4d37368e0152f99c099bad93e0950ce55e71daed74045908f"},
+ {file = "tornado-6.3.3-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7ac51f42808cca9b3613f51ffe2a965c8525cb1b00b7b2d56828b8045354f76a"},
+ {file = "tornado-6.3.3-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:71a8db65160a3c55d61839b7302a9a400074c9c753040455494e2af74e2501f2"},
+ {file = "tornado-6.3.3-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:ceb917a50cd35882b57600709dd5421a418c29ddc852da8bcdab1f0db33406b0"},
+ {file = "tornado-6.3.3-cp38-abi3-musllinux_1_1_i686.whl", hash = "sha256:7d01abc57ea0dbb51ddfed477dfe22719d376119844e33c661d873bf9c0e4a16"},
+ {file = "tornado-6.3.3-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:9dc4444c0defcd3929d5c1eb5706cbe1b116e762ff3e0deca8b715d14bf6ec17"},
+ {file = "tornado-6.3.3-cp38-abi3-win32.whl", hash = "sha256:65ceca9500383fbdf33a98c0087cb975b2ef3bfb874cb35b8de8740cf7f41bd3"},
+ {file = "tornado-6.3.3-cp38-abi3-win_amd64.whl", hash = "sha256:22d3c2fa10b5793da13c807e6fc38ff49a4f6e1e3868b0a6f4164768bb8e20f5"},
+ {file = "tornado-6.3.3.tar.gz", hash = "sha256:e7d8db41c0181c80d76c982aacc442c0783a2c54d6400fe028954201a2e032fe"},
]
[[package]]
@@ -3607,13 +3703,13 @@ wsproto = ">=0.14"
[[package]]
name = "twilio"
-version = "8.5.0"
+version = "8.7.0"
description = "Twilio API client and TwiML generator"
optional = false
python-versions = ">=3.7.0"
files = [
- {file = "twilio-8.5.0-py2.py3-none-any.whl", hash = "sha256:a6fdea2252cb7a8a47b5750d58abe1888bba9777482bac8e9bc3be47970facc7"},
- {file = "twilio-8.5.0.tar.gz", hash = "sha256:f55da9b485f9070aef09836e56230d0e6fd83811d2e6668f20d9057dd3668143"},
+ {file = "twilio-8.7.0-py2.py3-none-any.whl", hash = "sha256:0e8db896c8a2adefa0c1f8e725443e0da928db1de02a40687782e5f704738f98"},
+ {file = "twilio-8.7.0.tar.gz", hash = "sha256:ffc38ccf05cffe050670f211e872c5d8bfcad420f2ea3dcb361cb42e228b27fa"},
]
[package.dependencies]
@@ -4347,4 +4443,4 @@ files = [
[metadata]
lock-version = "2.0"
python-versions = "^3.11"
-content-hash = "5a15115f5ec615e5d2e34924b676df3efc4e8de83f8cdedb7eab055d41338121"
+content-hash = "8604e4dac9b0dcc55daccab83d4c182981d21201ef9901cf9c1acdc24288f979"
diff --git a/proxy.Dockerfile b/proxy.Dockerfile
index 863f920ad..3043031f9 100644
--- a/proxy.Dockerfile
+++ b/proxy.Dockerfile
@@ -8,7 +8,7 @@ WORKDIR /static
RUN npm ci --include=dev && npm run build-proxy
# Stage 2: Build
-FROM docker.io/golang:1.21.0-bullseye AS builder
+FROM docker.io/golang:1.21.0-bookworm AS builder
WORKDIR /go/src/goauthentik.io
diff --git a/pyproject.toml b/pyproject.toml
index 4daeaada4..8c88bed32 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -152,7 +152,7 @@ packaging = "*"
paramiko = "*"
psycopg = { extras = ["c"], version = "*" }
pycryptodome = "*"
-pydantic = "<2.0.0"
+pydantic = "<3.0.0"
pydantic-scim = "^0.0.7"
pyjwt = "*"
python = "^3.11"
diff --git a/radius.Dockerfile b/radius.Dockerfile
index fa58efd30..23c6b548a 100644
--- a/radius.Dockerfile
+++ b/radius.Dockerfile
@@ -1,5 +1,5 @@
# Stage 1: Build
-FROM docker.io/golang:1.21.0-bullseye AS builder
+FROM docker.io/golang:1.21.0-bookworm AS builder
WORKDIR /go/src/goauthentik.io
diff --git a/schema.yml b/schema.yml
index aa6e27f1a..af6ce96f0 100644
--- a/schema.yml
+++ b/schema.yml
@@ -31747,7 +31747,7 @@ components:
type: string
format: date-time
readOnly: true
- users:
+ internal_users:
type: integer
readOnly: true
external_users:
@@ -31756,27 +31756,27 @@ components:
required:
- expiry
- external_users
+ - internal_users
- key
- license_uuid
- name
- - users
LicenseForecast:
type: object
description: Serializer for license forecast
properties:
- users:
+ internal_users:
type: integer
external_users:
type: integer
- forecasted_users:
+ forecasted_internal_users:
type: integer
forecasted_external_users:
type: integer
required:
- external_users
- forecasted_external_users
- - forecasted_users
- - users
+ - forecasted_internal_users
+ - internal_users
LicenseRequest:
type: object
description: License Serializer
@@ -31790,7 +31790,7 @@ components:
type: object
description: Serializer for license status
properties:
- users:
+ internal_users:
type: integer
external_users:
type: integer
@@ -31810,11 +31810,11 @@ components:
required:
- external_users
- has_license
+ - internal_users
- latest_valid
- read_only
- show_admin_warning
- show_user_warning
- - users
- valid
Link:
type: object
diff --git a/scripts/generate_config.py b/scripts/generate_config.py
index 63333188e..187eb3ba5 100644
--- a/scripts/generate_config.py
+++ b/scripts/generate_config.py
@@ -16,9 +16,6 @@ with open("local.env.yml", "w", encoding="utf-8") as _config:
"container_image_base": "ghcr.io/goauthentik/dev-%(type)s:gh-%(build_hash)s",
},
"blueprints_dir": "./blueprints",
- "web": {
- "outpost_port_offset": 100,
- },
"cert_discovery_dir": "./certs",
"geoip": "tests/GeoLite2-City-Test.mmdb",
},
diff --git a/web/.eslintrc.json b/web/.eslintrc.json
index 0a30b79eb..fdae375c6 100644
--- a/web/.eslintrc.json
+++ b/web/.eslintrc.json
@@ -16,6 +16,7 @@
"sourceType": "module"
},
"plugins": ["@typescript-eslint", "lit", "custom-elements"],
+ "ignorePatterns": ["authentik-live-tests/**"],
"rules": {
"indent": "off",
"linebreak-style": ["error", "unix"],
diff --git a/web/package-lock.json b/web/package-lock.json
index 020a90c5a..6614acacd 100644
--- a/web/package-lock.json
+++ b/web/package-lock.json
@@ -10,24 +10,24 @@
"license": "MIT",
"dependencies": {
"@codemirror/lang-html": "^6.4.5",
- "@codemirror/lang-javascript": "^6.1.9",
+ "@codemirror/lang-javascript": "^6.2.0",
"@codemirror/lang-python": "^6.1.3",
"@codemirror/lang-xml": "^6.0.2",
"@codemirror/legacy-modes": "^6.3.3",
"@codemirror/theme-one-dark": "^6.1.2",
"@formatjs/intl-listformat": "^7.4.0",
"@fortawesome/fontawesome-free": "^6.4.2",
- "@goauthentik/api": "^2023.6.1-1692308915",
+ "@goauthentik/api": "^2023.6.1-1692789666",
"@lit-labs/context": "^0.4.0",
"@lit-labs/task": "^3.0.1",
"@lit/localize": "^0.11.4",
- "@patternfly/elements": "^2.3.2",
+ "@patternfly/elements": "^2.4.0",
"@patternfly/patternfly": "^4.224.2",
"@sentry/browser": "^7.64.0",
"@sentry/tracing": "^7.64.0",
"@webcomponents/webcomponentsjs": "^2.8.0",
"base64-js": "^1.5.1",
- "chart.js": "^4.3.3",
+ "chart.js": "^4.4.0",
"chartjs-adapter-moment": "^1.0.1",
"codemirror": "^6.0.1",
"construct-style-sheets-polyfill": "^3.1.0",
@@ -35,30 +35,31 @@
"country-flag-icons": "^1.5.7",
"fuse.js": "^6.6.2",
"lit": "^2.8.0",
- "mermaid": "^10.3.1",
+ "mermaid": "^10.4.0",
"rapidoc": "^9.3.4",
- "style-mod": "^4.0.3",
+ "style-mod": "^4.1.0",
"webcomponent-qr-code": "^1.2.0",
"yaml": "^2.3.1"
},
"devDependencies": {
- "@babel/core": "^7.22.10",
+ "@babel/core": "^7.22.11",
"@babel/plugin-proposal-class-properties": "^7.18.6",
"@babel/plugin-proposal-decorators": "^7.22.10",
"@babel/plugin-proposal-private-methods": "^7.18.6",
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"@babel/plugin-transform-runtime": "^7.22.10",
"@babel/preset-env": "^7.22.10",
- "@babel/preset-typescript": "^7.22.5",
+ "@babel/preset-typescript": "^7.22.11",
"@hcaptcha/types": "^1.0.3",
"@jackfranklin/rollup-plugin-markdown": "^0.4.0",
"@jeysal/storybook-addon-css-user-preferences": "^0.2.0",
"@lit/localize-tools": "^0.6.9",
"@rollup/plugin-babel": "^6.0.3",
"@rollup/plugin-commonjs": "^25.0.4",
- "@rollup/plugin-node-resolve": "^15.2.0",
+ "@rollup/plugin-node-resolve": "^15.2.1",
"@rollup/plugin-replace": "^5.0.2",
- "@rollup/plugin-typescript": "^11.1.2",
+ "@rollup/plugin-terser": "^0.4.3",
+ "@rollup/plugin-typescript": "^11.1.3",
"@storybook/addon-essentials": "^7.3.2",
"@storybook/addon-links": "^7.3.2",
"@storybook/blocks": "^7.1.1",
@@ -66,13 +67,13 @@
"@storybook/web-components-vite": "^7.3.2",
"@trivago/prettier-plugin-sort-imports": "^4.2.0",
"@types/chart.js": "^2.9.37",
- "@types/codemirror": "5.60.8",
+ "@types/codemirror": "5.60.9",
"@types/grecaptcha": "^3.0.4",
- "@typescript-eslint/eslint-plugin": "^6.4.0",
- "@typescript-eslint/parser": "^6.4.0",
+ "@typescript-eslint/eslint-plugin": "^6.4.1",
+ "@typescript-eslint/parser": "^6.4.1",
"babel-plugin-macros": "^3.1.0",
"babel-plugin-tsconfig-paths": "^1.0.3",
- "eslint": "^8.47.0",
+ "eslint": "^8.48.0",
"eslint-config-google": "^0.14.0",
"eslint-plugin-custom-elements": "0.0.8",
"eslint-plugin-lit": "^1.9.1",
@@ -80,21 +81,19 @@
"lit-analyzer": "^1.2.1",
"npm-run-all": "^4.1.5",
"prettier": "^3.0.2",
- "pyright": "^1.1.323",
+ "pyright": "^1.1.324",
"react": "^18.2.0",
"react-dom": "^18.2.0",
- "rollup": "^2.79.1",
+ "rollup": "^3.28.1",
"rollup-plugin-copy": "^3.4.0",
"rollup-plugin-cssimport": "^1.0.3",
- "rollup-plugin-minify-html-literals": "^1.2.6",
"rollup-plugin-postcss-lit": "^2.1.0",
- "rollup-plugin-terser": "^7.0.2",
"storybook": "^7.3.2",
"storybook-addon-mock": "^4.2.1",
"ts-lit-plugin": "^1.2.1",
"tslib": "^2.6.2",
"turnstile-types": "^1.1.2",
- "typescript": "^5.1.6",
+ "typescript": "^5.2.2",
"vite-tsconfig-paths": "^4.2.0"
},
"optionalDependencies": {
@@ -168,9 +167,9 @@
}
},
"node_modules/@babel/core": {
- "version": "7.22.10",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.10.tgz",
- "integrity": "sha512-fTmqbbUBAwCcre6zPzNngvsI0aNrPZe77AeqvDxWM9Nm+04RrJ3CAmGHA9f7lJQY6ZMhRztNemy4uslDxTX4Qw==",
+ "version": "7.22.11",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.22.11.tgz",
+ "integrity": "sha512-lh7RJrtPdhibbxndr6/xx0w8+CVlY5FJZiaSz908Fpy+G0xkBFTvwLcKJFF4PJxVfGhVWNebikpWGnOoC71juQ==",
"dev": true,
"dependencies": {
"@ampproject/remapping": "^2.2.0",
@@ -178,15 +177,15 @@
"@babel/generator": "^7.22.10",
"@babel/helper-compilation-targets": "^7.22.10",
"@babel/helper-module-transforms": "^7.22.9",
- "@babel/helpers": "^7.22.10",
- "@babel/parser": "^7.22.10",
+ "@babel/helpers": "^7.22.11",
+ "@babel/parser": "^7.22.11",
"@babel/template": "^7.22.5",
- "@babel/traverse": "^7.22.10",
- "@babel/types": "^7.22.10",
+ "@babel/traverse": "^7.22.11",
+ "@babel/types": "^7.22.11",
"convert-source-map": "^1.7.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.2",
- "json5": "^2.2.2",
+ "json5": "^2.2.3",
"semver": "^6.3.1"
},
"engines": {
@@ -253,9 +252,9 @@
}
},
"node_modules/@babel/helper-create-class-features-plugin": {
- "version": "7.22.10",
- "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.10.tgz",
- "integrity": "sha512-5IBb77txKYQPpOEdUdIhBx8VrZyDCQ+H82H0+5dX1TmuscP5vJKEE3cKurjtIw/vFwzbVH48VweE78kVDBrqjA==",
+ "version": "7.22.11",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.11.tgz",
+ "integrity": "sha512-y1grdYL4WzmUDBRGK0pDbIoFd7UZKoDurDzWEoNMYoj1EL+foGRQNyPWDcC+YyegN5y1DUsFFmzjGijB3nSVAQ==",
"dev": true,
"dependencies": {
"@babel/helper-annotate-as-pure": "^7.22.5",
@@ -518,14 +517,14 @@
}
},
"node_modules/@babel/helpers": {
- "version": "7.22.10",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.10.tgz",
- "integrity": "sha512-a41J4NW8HyZa1I1vAndrraTlPZ/eZoga2ZgS7fEr0tZJGVU4xqdE80CEm0CcNjha5EZ8fTBYLKHF0kqDUuAwQw==",
+ "version": "7.22.11",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.22.11.tgz",
+ "integrity": "sha512-vyOXC8PBWaGc5h7GMsNx68OH33cypkEDJCHvYVVgVbbxJDROYVtexSk0gK5iCF1xNjRIN2s8ai7hwkWDq5szWg==",
"dev": true,
"dependencies": {
"@babel/template": "^7.22.5",
- "@babel/traverse": "^7.22.10",
- "@babel/types": "^7.22.10"
+ "@babel/traverse": "^7.22.11",
+ "@babel/types": "^7.22.11"
},
"engines": {
"node": ">=6.9.0"
@@ -546,9 +545,9 @@
}
},
"node_modules/@babel/parser": {
- "version": "7.22.10",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.10.tgz",
- "integrity": "sha512-lNbdGsQb9ekfsnjFGhEiF4hfFqGgfOP3H3d27re3n+CGhNuTSUEQdfWk556sTLNTloczcdM5TYF2LhzmDQKyvQ==",
+ "version": "7.22.11",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.22.11.tgz",
+ "integrity": "sha512-R5zb8eJIBPJriQtbH/htEQy4k7E2dHWlD2Y2VT07JCzwYZHBxV5ZYtM0UhXSNMT74LyxuM+b1jdL7pSesXbC/g==",
"dev": true,
"bin": {
"parser": "bin/babel-parser.js"
@@ -1359,12 +1358,12 @@
}
},
"node_modules/@babel/plugin-transform-modules-commonjs": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.22.5.tgz",
- "integrity": "sha512-B4pzOXj+ONRmuaQTg05b3y/4DuFz3WcCNAXPLb2Q0GT0TrGKGxNKV4jwsXts+StaM0LQczZbOpj8o1DLPDJIiA==",
+ "version": "7.22.11",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.22.11.tgz",
+ "integrity": "sha512-o2+bg7GDS60cJMgz9jWqRUsWkMzLCxp+jFDeDUT5sjRlAxcJWZ2ylNdI7QQ2+CH5hWu7OnN+Cv3htt7AkSf96g==",
"dev": true,
"dependencies": {
- "@babel/helper-module-transforms": "^7.22.5",
+ "@babel/helper-module-transforms": "^7.22.9",
"@babel/helper-plugin-utils": "^7.22.5",
"@babel/helper-simple-access": "^7.22.5"
},
@@ -1732,13 +1731,13 @@
}
},
"node_modules/@babel/plugin-transform-typescript": {
- "version": "7.22.9",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.22.9.tgz",
- "integrity": "sha512-BnVR1CpKiuD0iobHPaM1iLvcwPYN2uVFAqoLVSpEDKWuOikoCv5HbKLxclhKYUXlWkX86DoZGtqI4XhbOsyrMg==",
+ "version": "7.22.11",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.22.11.tgz",
+ "integrity": "sha512-0E4/L+7gfvHub7wsbTv03oRtD69X31LByy44fGmFzbZScpupFByMcgCJ0VbBTkzyjSJKuRoGN8tcijOWKTmqOA==",
"dev": true,
"dependencies": {
"@babel/helper-annotate-as-pure": "^7.22.5",
- "@babel/helper-create-class-features-plugin": "^7.22.9",
+ "@babel/helper-create-class-features-plugin": "^7.22.11",
"@babel/helper-plugin-utils": "^7.22.5",
"@babel/plugin-syntax-typescript": "^7.22.5"
},
@@ -1950,16 +1949,16 @@
}
},
"node_modules/@babel/preset-typescript": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.22.5.tgz",
- "integrity": "sha512-YbPaal9LxztSGhmndR46FmAbkJ/1fAsw293tSU+I5E5h+cnJ3d4GTwyUgGYmOXJYdGA+uNePle4qbaRzj2NISQ==",
+ "version": "7.22.11",
+ "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.22.11.tgz",
+ "integrity": "sha512-tWY5wyCZYBGY7IlalfKI1rLiGlIfnwsRHZqlky0HVv8qviwQ1Uo/05M6+s+TcTCVa6Bmoo2uJW5TMFX6Wa4qVg==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.22.5",
"@babel/helper-validator-option": "^7.22.5",
"@babel/plugin-syntax-jsx": "^7.22.5",
- "@babel/plugin-transform-modules-commonjs": "^7.22.5",
- "@babel/plugin-transform-typescript": "^7.22.5"
+ "@babel/plugin-transform-modules-commonjs": "^7.22.11",
+ "@babel/plugin-transform-typescript": "^7.22.11"
},
"engines": {
"node": ">=6.9.0"
@@ -2150,9 +2149,9 @@
}
},
"node_modules/@babel/traverse": {
- "version": "7.22.10",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.10.tgz",
- "integrity": "sha512-Q/urqV4pRByiNNpb/f5OSv28ZlGJiFiiTh+GAHktbIrkPhPbl90+uW6SmpoLyZqutrg9AEaEf3Q/ZBRHBXgxig==",
+ "version": "7.22.11",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.22.11.tgz",
+ "integrity": "sha512-mzAenteTfomcB7mfPtyi+4oe5BZ6MXxWcn4CX+h4IRJ+OOGXBrWU6jDQavkQI9Vuc5P+donFabBfFCcmWka9lQ==",
"dev": true,
"dependencies": {
"@babel/code-frame": "^7.22.10",
@@ -2161,8 +2160,8 @@
"@babel/helper-function-name": "^7.22.5",
"@babel/helper-hoist-variables": "^7.22.5",
"@babel/helper-split-export-declaration": "^7.22.6",
- "@babel/parser": "^7.22.10",
- "@babel/types": "^7.22.10",
+ "@babel/parser": "^7.22.11",
+ "@babel/types": "^7.22.11",
"debug": "^4.1.0",
"globals": "^11.1.0"
},
@@ -2171,9 +2170,9 @@
}
},
"node_modules/@babel/types": {
- "version": "7.22.10",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.10.tgz",
- "integrity": "sha512-obaoigiLrlDZ7TUQln/8m4mSqIW2QFeOrCQc9r+xsaHGNoplVNYlRVpsfE8Vj35GEm2ZH4ZhrNYogs/3fj85kg==",
+ "version": "7.22.11",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.22.11.tgz",
+ "integrity": "sha512-siazHiGuZRz9aB9NpHy9GOs9xiQPKnMzgdr493iI1M67vRXpnEq8ZOOKzezC5q7zwuQ6sDhdSp4SD9ixKSqKZg==",
"dev": true,
"dependencies": {
"@babel/helper-string-parser": "^7.22.5",
@@ -2246,9 +2245,9 @@
}
},
"node_modules/@codemirror/lang-javascript": {
- "version": "6.1.9",
- "resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.1.9.tgz",
- "integrity": "sha512-z3jdkcqOEBT2txn2a87A0jSy6Te3679wg/U8QzMeftFt+4KA6QooMwfdFzJiuC3L6fXKfTXZcDocoaxMYfGz0w==",
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.2.0.tgz",
+ "integrity": "sha512-E01GVTFTDSiXyrnHq+NwGxr/BqvNoAFRp1Wz+C6v2nU8rzjF0lHy7WG8kLCGowNyuk6YgfcmfuXHNxlLXgqQqQ==",
"dependencies": {
"@codemirror/autocomplete": "^6.0.0",
"@codemirror/language": "^6.6.0",
@@ -2819,9 +2818,9 @@
}
},
"node_modules/@eslint/js": {
- "version": "8.47.0",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.47.0.tgz",
- "integrity": "sha512-P6omY1zv5MItm93kLM8s2vr1HICJH8v0dvddDhysbIuZ+vcjOHg5Zbkf1mTkcmi2JA9oBG2anOkRnW8WJTS8Og==",
+ "version": "8.48.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.48.0.tgz",
+ "integrity": "sha512-ZSjtmelB7IJfWD2Fvb7+Z+ChTIKWq6kjda95fLcQKNS5aheVHn4IkfgRQE3sIIzTcSLwLcLZUD9UBt+V7+h+Pw==",
"dev": true,
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -2905,9 +2904,9 @@
}
},
"node_modules/@goauthentik/api": {
- "version": "2023.6.1-1692308915",
- "resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2023.6.1-1692308915.tgz",
- "integrity": "sha512-veGQrjEJWy/2lVOlfPSXac9g9/LBIVW8buUKNmZOBk+UgMniAMivpKEaYALApJgzG2kAAJdyOZ9vUvGHVMNvHA=="
+ "version": "2023.6.1-1692789666",
+ "resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2023.6.1-1692789666.tgz",
+ "integrity": "sha512-nzHb5P5wLChtDWeKVQZbVo8OayouncrIs4W0WXT9LD62H9fFg/9IUf9bNm/gUW7MjqUre/QF9miHyHZ58sZzXQ=="
},
"node_modules/@hcaptcha/types": {
"version": "1.0.3",
@@ -3590,9 +3589,9 @@
}
},
"node_modules/@patternfly/elements": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/@patternfly/elements/-/elements-2.3.2.tgz",
- "integrity": "sha512-cndt+xxlUKbWU8GxFlOXMNqNeJ792kXUnvcYZbUIA+TUbWD71yw0kdC+EOWql94B4jtzOmDyG7Eq33il3G6ZLQ==",
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/@patternfly/elements/-/elements-2.4.0.tgz",
+ "integrity": "sha512-mA6I76R8aHdBKRX+IbaVuD24OnYUBsjStDwGVq7ytopA0XUKx12xTwgRZGNM7wKBBFYbNKpIxxuaanQSLZTGIQ==",
"dependencies": {
"@patternfly/icons": "^1.0.2",
"@patternfly/pfe-core": "^2.4.0",
@@ -4354,9 +4353,9 @@
}
},
"node_modules/@rollup/plugin-node-resolve": {
- "version": "15.2.0",
- "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.0.tgz",
- "integrity": "sha512-mKur03xNGT8O9ODO6FtT43ITGqHWZbKPdVJHZb+iV9QYcdlhUUB0wgknvA4KCUmC5oHJF6O2W1EgmyOQyVUI4Q==",
+ "version": "15.2.1",
+ "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.2.1.tgz",
+ "integrity": "sha512-nsbUg588+GDSu8/NS8T4UAshO6xeaOfINNuXeVHcKV02LJtoRaM1SiOacClw4kws1SFiNhdLGxlbMY9ga/zs/w==",
"dev": true,
"dependencies": {
"@rollup/pluginutils": "^5.0.1",
@@ -4399,10 +4398,41 @@
}
}
},
+ "node_modules/@rollup/plugin-terser": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.3.tgz",
+ "integrity": "sha512-EF0oejTMtkyhrkwCdg0HJ0IpkcaVg1MMSf2olHb2Jp+1mnLM04OhjpJWGma4HobiDTF0WCyViWuvadyE9ch2XA==",
+ "dev": true,
+ "dependencies": {
+ "serialize-javascript": "^6.0.1",
+ "smob": "^1.0.0",
+ "terser": "^5.17.4"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "rollup": "^2.x || ^3.x"
+ },
+ "peerDependenciesMeta": {
+ "rollup": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@rollup/plugin-terser/node_modules/serialize-javascript": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz",
+ "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==",
+ "dev": true,
+ "dependencies": {
+ "randombytes": "^2.1.0"
+ }
+ },
"node_modules/@rollup/plugin-typescript": {
- "version": "11.1.2",
- "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-11.1.2.tgz",
- "integrity": "sha512-0ghSOCMcA7fl1JM+0gYRf+Q/HWyg+zg7/gDSc+fRLmlJWcW5K1I+CLRzaRhXf4Y3DRyPnnDo4M2ktw+a6JcDEg==",
+ "version": "11.1.3",
+ "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-11.1.3.tgz",
+ "integrity": "sha512-8o6cNgN44kQBcpsUJTbTXMTtb87oR1O0zgP3Dxm71hrNgparap3VujgofEilTYJo+ivf2ke6uy3/E5QEaiRlDA==",
"dev": true,
"dependencies": {
"@rollup/pluginutils": "^5.0.1",
@@ -9572,20 +9602,10 @@
"moment": "^2.10.2"
}
},
- "node_modules/@types/clean-css": {
- "version": "4.2.6",
- "resolved": "https://registry.npmjs.org/@types/clean-css/-/clean-css-4.2.6.tgz",
- "integrity": "sha512-Ze1tf+LnGPmG6hBFMi0B4TEB0mhF7EiMM5oyjLDNPE9hxrPU0W+5+bHvO+eFPA+bt0iC1zkQMoU/iGdRVjcRbw==",
- "dev": true,
- "dependencies": {
- "@types/node": "*",
- "source-map": "^0.6.0"
- }
- },
"node_modules/@types/codemirror": {
- "version": "5.60.8",
- "resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-5.60.8.tgz",
- "integrity": "sha512-VjFgDF/eB+Aklcy15TtOTLQeMjTo07k7KAjql8OK5Dirr7a6sJY4T1uVBDuTVG9VEmn1uUsohOpYnVfgC6/jyw==",
+ "version": "5.60.9",
+ "resolved": "https://registry.npmjs.org/@types/codemirror/-/codemirror-5.60.9.tgz",
+ "integrity": "sha512-8RhLhlGo9bAkytFYKDzezorY2ojvGk+4xFEso/6Hc2oR1oE2P9lI+AEkbUW7cDlKcQAK5WJkJRBLTdjBE7xQPA==",
"dev": true,
"dependencies": {
"@types/tern": "*"
@@ -9719,17 +9739,6 @@
"integrity": "sha512-7l1Y8DTGXkx/r4pwU1nMVAR+yD/QC+MCHKXAyEX/7JZhwcN1IED09aZ9vCjjkcGdhSQiu/eJqcXInpl6eEEEwg==",
"dev": true
},
- "node_modules/@types/html-minifier": {
- "version": "3.5.3",
- "resolved": "https://registry.npmjs.org/@types/html-minifier/-/html-minifier-3.5.3.tgz",
- "integrity": "sha512-j1P/4PcWVVCPEy5lofcHnQ6BtXz9tHGiFPWzqm7TtGuWZEfCHEP446HlkSNc9fQgNJaJZ6ewPtp2aaFla/Uerg==",
- "dev": true,
- "dependencies": {
- "@types/clean-css": "*",
- "@types/relateurl": "*",
- "@types/uglify-js": "*"
- }
- },
"node_modules/@types/http-errors": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.1.tgz",
@@ -9880,12 +9889,6 @@
"csstype": "^3.0.2"
}
},
- "node_modules/@types/relateurl": {
- "version": "0.2.29",
- "resolved": "https://registry.npmjs.org/@types/relateurl/-/relateurl-0.2.29.tgz",
- "integrity": "sha512-QSvevZ+IRww2ldtfv1QskYsqVVVwCKQf1XbwtcyyoRvLIQzfyPhj/C+3+PKzSDRdiyejaiLgnq//XTkleorpLg==",
- "dev": true
- },
"node_modules/@types/resolve": {
"version": "1.20.2",
"resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz",
@@ -9945,15 +9948,6 @@
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.3.tgz",
"integrity": "sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g=="
},
- "node_modules/@types/uglify-js": {
- "version": "3.17.1",
- "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.17.1.tgz",
- "integrity": "sha512-GkewRA4i5oXacU/n4MA9+bLgt5/L3F1mKrYvFGm7r2ouLXhRKjuWwo9XHNnbx6WF3vlGW21S3fCvgqxvxXXc5g==",
- "dev": true,
- "dependencies": {
- "source-map": "^0.6.1"
- }
- },
"node_modules/@types/unist": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.7.tgz",
@@ -9975,16 +9969,16 @@
"dev": true
},
"node_modules/@typescript-eslint/eslint-plugin": {
- "version": "6.4.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.4.0.tgz",
- "integrity": "sha512-62o2Hmc7Gs3p8SLfbXcipjWAa6qk2wZGChXG2JbBtYpwSRmti/9KHLqfbLs9uDigOexG+3PaQ9G2g3201FWLKg==",
+ "version": "6.4.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.4.1.tgz",
+ "integrity": "sha512-3F5PtBzUW0dYlq77Lcqo13fv+58KDwUib3BddilE8ajPJT+faGgxmI9Sw+I8ZS22BYwoir9ZhNXcLi+S+I2bkw==",
"dev": true,
"dependencies": {
"@eslint-community/regexpp": "^4.5.1",
- "@typescript-eslint/scope-manager": "6.4.0",
- "@typescript-eslint/type-utils": "6.4.0",
- "@typescript-eslint/utils": "6.4.0",
- "@typescript-eslint/visitor-keys": "6.4.0",
+ "@typescript-eslint/scope-manager": "6.4.1",
+ "@typescript-eslint/type-utils": "6.4.1",
+ "@typescript-eslint/utils": "6.4.1",
+ "@typescript-eslint/visitor-keys": "6.4.1",
"debug": "^4.3.4",
"graphemer": "^1.4.0",
"ignore": "^5.2.4",
@@ -10043,15 +10037,15 @@
"dev": true
},
"node_modules/@typescript-eslint/parser": {
- "version": "6.4.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.4.0.tgz",
- "integrity": "sha512-I1Ah1irl033uxjxO9Xql7+biL3YD7w9IU8zF+xlzD/YxY6a4b7DYA08PXUUCbm2sEljwJF6ERFy2kTGAGcNilg==",
+ "version": "6.4.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.4.1.tgz",
+ "integrity": "sha512-610G6KHymg9V7EqOaNBMtD1GgpAmGROsmfHJPXNLCU9bfIuLrkdOygltK784F6Crboyd5tBFayPB7Sf0McrQwg==",
"dev": true,
"dependencies": {
- "@typescript-eslint/scope-manager": "6.4.0",
- "@typescript-eslint/types": "6.4.0",
- "@typescript-eslint/typescript-estree": "6.4.0",
- "@typescript-eslint/visitor-keys": "6.4.0",
+ "@typescript-eslint/scope-manager": "6.4.1",
+ "@typescript-eslint/types": "6.4.1",
+ "@typescript-eslint/typescript-estree": "6.4.1",
+ "@typescript-eslint/visitor-keys": "6.4.1",
"debug": "^4.3.4"
},
"engines": {
@@ -10071,13 +10065,13 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
- "version": "6.4.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.4.0.tgz",
- "integrity": "sha512-TUS7vaKkPWDVvl7GDNHFQMsMruD+zhkd3SdVW0d7b+7Zo+bd/hXJQ8nsiUZMi1jloWo6c9qt3B7Sqo+flC1nig==",
+ "version": "6.4.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.4.1.tgz",
+ "integrity": "sha512-p/OavqOQfm4/Hdrr7kvacOSFjwQ2rrDVJRPxt/o0TOWdFnjJptnjnZ+sYDR7fi4OimvIuKp+2LCkc+rt9fIW+A==",
"dev": true,
"dependencies": {
- "@typescript-eslint/types": "6.4.0",
- "@typescript-eslint/visitor-keys": "6.4.0"
+ "@typescript-eslint/types": "6.4.1",
+ "@typescript-eslint/visitor-keys": "6.4.1"
},
"engines": {
"node": "^16.0.0 || >=18.0.0"
@@ -10088,13 +10082,13 @@
}
},
"node_modules/@typescript-eslint/type-utils": {
- "version": "6.4.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.4.0.tgz",
- "integrity": "sha512-TvqrUFFyGY0cX3WgDHcdl2/mMCWCDv/0thTtx/ODMY1QhEiyFtv/OlLaNIiYLwRpAxAtOLOY9SUf1H3Q3dlwAg==",
+ "version": "6.4.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.4.1.tgz",
+ "integrity": "sha512-7ON8M8NXh73SGZ5XvIqWHjgX2f+vvaOarNliGhjrJnv1vdjG0LVIz+ToYfPirOoBi56jxAKLfsLm40+RvxVVXA==",
"dev": true,
"dependencies": {
- "@typescript-eslint/typescript-estree": "6.4.0",
- "@typescript-eslint/utils": "6.4.0",
+ "@typescript-eslint/typescript-estree": "6.4.1",
+ "@typescript-eslint/utils": "6.4.1",
"debug": "^4.3.4",
"ts-api-utils": "^1.0.1"
},
@@ -10115,9 +10109,9 @@
}
},
"node_modules/@typescript-eslint/types": {
- "version": "6.4.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.4.0.tgz",
- "integrity": "sha512-+FV9kVFrS7w78YtzkIsNSoYsnOtrYVnKWSTVXoL1761CsCRv5wpDOINgsXpxD67YCLZtVQekDDyaxfjVWUJmmg==",
+ "version": "6.4.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.4.1.tgz",
+ "integrity": "sha512-zAAopbNuYu++ijY1GV2ylCsQsi3B8QvfPHVqhGdDcbx/NK5lkqMnCGU53amAjccSpk+LfeONxwzUhDzArSfZJg==",
"dev": true,
"engines": {
"node": "^16.0.0 || >=18.0.0"
@@ -10128,13 +10122,13 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
- "version": "6.4.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.4.0.tgz",
- "integrity": "sha512-iDPJArf/K2sxvjOR6skeUCNgHR/tCQXBsa+ee1/clRKr3olZjZ/dSkXPZjG6YkPtnW6p5D1egeEPMCW6Gn4yLA==",
+ "version": "6.4.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.4.1.tgz",
+ "integrity": "sha512-xF6Y7SatVE/OyV93h1xGgfOkHr2iXuo8ip0gbfzaKeGGuKiAnzS+HtVhSPx8Www243bwlW8IF7X0/B62SzFftg==",
"dev": true,
"dependencies": {
- "@typescript-eslint/types": "6.4.0",
- "@typescript-eslint/visitor-keys": "6.4.0",
+ "@typescript-eslint/types": "6.4.1",
+ "@typescript-eslint/visitor-keys": "6.4.1",
"debug": "^4.3.4",
"globby": "^11.1.0",
"is-glob": "^4.0.3",
@@ -10188,17 +10182,17 @@
"dev": true
},
"node_modules/@typescript-eslint/utils": {
- "version": "6.4.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.4.0.tgz",
- "integrity": "sha512-BvvwryBQpECPGo8PwF/y/q+yacg8Hn/2XS+DqL/oRsOPK+RPt29h5Ui5dqOKHDlbXrAeHUTnyG3wZA0KTDxRZw==",
+ "version": "6.4.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.4.1.tgz",
+ "integrity": "sha512-F/6r2RieNeorU0zhqZNv89s9bDZSovv3bZQpUNOmmQK1L80/cV4KEu95YUJWi75u5PhboFoKUJBnZ4FQcoqhDw==",
"dev": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.4.0",
"@types/json-schema": "^7.0.12",
"@types/semver": "^7.5.0",
- "@typescript-eslint/scope-manager": "6.4.0",
- "@typescript-eslint/types": "6.4.0",
- "@typescript-eslint/typescript-estree": "6.4.0",
+ "@typescript-eslint/scope-manager": "6.4.1",
+ "@typescript-eslint/types": "6.4.1",
+ "@typescript-eslint/typescript-estree": "6.4.1",
"semver": "^7.5.4"
},
"engines": {
@@ -10246,12 +10240,12 @@
"dev": true
},
"node_modules/@typescript-eslint/visitor-keys": {
- "version": "6.4.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.4.0.tgz",
- "integrity": "sha512-yJSfyT+uJm+JRDWYRYdCm2i+pmvXJSMtPR9Cq5/XQs4QIgNoLcoRtDdzsLbLsFM/c6um6ohQkg/MLxWvoIndJA==",
+ "version": "6.4.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.4.1.tgz",
+ "integrity": "sha512-y/TyRJsbZPkJIZQXrHfdnxVnxyKegnpEvnRGNam7s3TRR2ykGefEWOhaef00/UUN3IZxizS7BTO3svd3lCOJRQ==",
"dev": true,
"dependencies": {
- "@typescript-eslint/types": "6.4.0",
+ "@typescript-eslint/types": "6.4.1",
"eslint-visitor-keys": "^3.4.1"
},
"engines": {
@@ -11182,16 +11176,6 @@
"node": ">=6"
}
},
- "node_modules/camel-case": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz",
- "integrity": "sha512-+MbKztAYHXPr1jNTSKQF52VpcFjwY5RkR7fxksV8Doo4KAYc5Fl4UJRgthBbTmEx8C54DqahhbLJkDwjI3PI/w==",
- "dev": true,
- "dependencies": {
- "no-case": "^2.2.0",
- "upper-case": "^1.1.1"
- }
- },
"node_modules/camelcase": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
@@ -11245,9 +11229,9 @@
}
},
"node_modules/chart.js": {
- "version": "4.3.3",
- "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.3.3.tgz",
- "integrity": "sha512-aTk7pBw+x6sQYhon/NR3ikfUJuym/LdgpTlgZRe2PaEhjUMKBKyNaFCMVRAyTEWYFNO7qRu7iQVqOw/OqzxZxQ==",
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.0.tgz",
+ "integrity": "sha512-vQEj6d+z0dcsKLlQvbKIMYFHd3t8W/7L2vfJIbYcfyPcRx92CsHqECpueN8qVGNlKyDcr5wBrYAYKnfu/9Q1hQ==",
"dependencies": {
"@kurkle/color": "^0.3.0"
},
@@ -11431,18 +11415,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/clean-css": {
- "version": "4.2.4",
- "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz",
- "integrity": "sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==",
- "dev": true,
- "dependencies": {
- "source-map": "~0.6.0"
- },
- "engines": {
- "node": ">= 4.0"
- }
- },
"node_modules/clean-stack": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
@@ -13057,15 +13029,15 @@
}
},
"node_modules/eslint": {
- "version": "8.47.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.47.0.tgz",
- "integrity": "sha512-spUQWrdPt+pRVP1TTJLmfRNJJHHZryFmptzcafwSvHsceV81djHOdnEeDmkdotZyLNjDhrOasNK8nikkoG1O8Q==",
+ "version": "8.48.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.48.0.tgz",
+ "integrity": "sha512-sb6DLeIuRXxeM1YljSe1KEx9/YYeZFQWcV8Rq9HfigmdDEugjLEVEa1ozDjL6YDjBpQHPJxJzze+alxi4T3OLg==",
"dev": true,
"dependencies": {
"@eslint-community/eslint-utils": "^4.2.0",
"@eslint-community/regexpp": "^4.6.1",
"@eslint/eslintrc": "^2.1.2",
- "@eslint/js": "^8.47.0",
+ "@eslint/js": "8.48.0",
"@humanwhocodes/config-array": "^0.11.10",
"@humanwhocodes/module-importer": "^1.0.1",
"@nodelib/fs.walk": "^1.2.8",
@@ -14932,15 +14904,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/he": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
- "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
- "dev": true,
- "bin": {
- "he": "bin/he"
- }
- },
"node_modules/heap": {
"version": "0.2.7",
"resolved": "https://registry.npmjs.org/heap/-/heap-0.2.7.tgz",
@@ -14952,33 +14915,6 @@
"integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
"dev": true
},
- "node_modules/html-minifier": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-4.0.0.tgz",
- "integrity": "sha512-aoGxanpFPLg7MkIl/DDFYtb0iWz7jMFGqFhvEDZga6/4QTjneiD8I/NXL1x5aaoCp7FSIT6h/OhykDdPsbtMig==",
- "dev": true,
- "dependencies": {
- "camel-case": "^3.0.0",
- "clean-css": "^4.2.1",
- "commander": "^2.19.0",
- "he": "^1.2.0",
- "param-case": "^2.1.1",
- "relateurl": "^0.2.7",
- "uglify-js": "^3.5.1"
- },
- "bin": {
- "html-minifier": "cli.js"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/html-minifier/node_modules/commander": {
- "version": "2.20.3",
- "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
- "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
- "dev": true
- },
"node_modules/http-errors": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
@@ -16644,12 +16580,6 @@
"loose-envify": "cli.js"
}
},
- "node_modules/lower-case": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz",
- "integrity": "sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==",
- "dev": true
- },
"node_modules/lru-cache": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
@@ -16860,9 +16790,9 @@
}
},
"node_modules/mermaid": {
- "version": "10.3.1",
- "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-10.3.1.tgz",
- "integrity": "sha512-hkenh7WkuRWPcob3oJtrN3W+yzrrIYuWF1OIfk/d0xGE8UWlvDhfexaHmDwwe8DKQgqMLI8DWEPwGprxkumjuw==",
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-10.4.0.tgz",
+ "integrity": "sha512-4QCQLp79lvz7UZxow5HUX7uWTPJOaQBVExduo91tliXC7v78i6kssZOPHxLL+Xs30KU72cpPn3g3imw/xm/gaw==",
"dependencies": {
"@braintree/sanitize-url": "^6.0.1",
"@types/d3-scale": "^4.0.3",
@@ -17381,28 +17311,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/minify-html-literals": {
- "version": "1.3.5",
- "resolved": "https://registry.npmjs.org/minify-html-literals/-/minify-html-literals-1.3.5.tgz",
- "integrity": "sha512-p8T8ryePRR8FVfJZLVFmM53WY25FL0moCCTycUDuAu6rf9GMLwy0gNjXBGNin3Yun7Y+tIWd28axOf0t2EpAlQ==",
- "dev": true,
- "dependencies": {
- "@types/html-minifier": "^3.5.3",
- "clean-css": "^4.2.1",
- "html-minifier": "^4.0.0",
- "magic-string": "^0.25.0",
- "parse-literals": "^1.2.1"
- }
- },
- "node_modules/minify-html-literals/node_modules/magic-string": {
- "version": "0.25.9",
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz",
- "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==",
- "dev": true,
- "dependencies": {
- "sourcemap-codec": "^1.4.8"
- }
- },
"node_modules/minim": {
"version": "0.23.8",
"resolved": "https://registry.npmjs.org/minim/-/minim-0.23.8.tgz",
@@ -17757,15 +17665,6 @@
"integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
"dev": true
},
- "node_modules/no-case": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz",
- "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==",
- "dev": true,
- "dependencies": {
- "lower-case": "^1.1.1"
- }
- },
"node_modules/node-abi": {
"version": "3.45.0",
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.45.0.tgz",
@@ -18406,15 +18305,6 @@
"integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==",
"dev": true
},
- "node_modules/param-case": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz",
- "integrity": "sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w==",
- "dev": true,
- "dependencies": {
- "no-case": "^2.2.0"
- }
- },
"node_modules/parent-module": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
@@ -18445,28 +18335,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/parse-literals": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/parse-literals/-/parse-literals-1.2.1.tgz",
- "integrity": "sha512-Ml0w104Ph2wwzuRdxrg9booVWsngXbB4bZ5T2z6WyF8b5oaNkUmBiDtahi34yUIpXD8Y13JjAK6UyIyApJ73RQ==",
- "dev": true,
- "dependencies": {
- "typescript": "^2.9.2 || ^3.0.0 || ^4.0.0"
- }
- },
- "node_modules/parse-literals/node_modules/typescript": {
- "version": "4.9.5",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
- "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
- "dev": true,
- "bin": {
- "tsc": "bin/tsc",
- "tsserver": "bin/tsserver"
- },
- "engines": {
- "node": ">=4.2.0"
- }
- },
"node_modules/parse5": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
@@ -18981,9 +18849,9 @@
}
},
"node_modules/pyright": {
- "version": "1.1.323",
- "resolved": "https://registry.npmjs.org/pyright/-/pyright-1.1.323.tgz",
- "integrity": "sha512-H6CnGjaL/2lJJPFcV4G0zFP7s7jJPzVsPhQnbnS9m6JWJpb7OssX7y94icPpnZs4574oHergGH2zLvF8OZp5ag==",
+ "version": "1.1.324",
+ "resolved": "https://registry.npmjs.org/pyright/-/pyright-1.1.324.tgz",
+ "integrity": "sha512-/Ng8G2Gb17dzQEHKgPa+Z5a6LPCLYNA4BVno1UdpDjnC9iLw0VAn5k/RNuaGkB/mhA82lV0OBcd5JEdaWcA3qg==",
"dev": true,
"bin": {
"pyright": "index.js",
@@ -19575,15 +19443,6 @@
"jsesc": "bin/jsesc"
}
},
- "node_modules/relateurl": {
- "version": "0.2.7",
- "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz",
- "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==",
- "dev": true,
- "engines": {
- "node": ">= 0.10"
- }
- },
"node_modules/remark-external-links": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/remark-external-links/-/remark-external-links-8.0.0.tgz",
@@ -19773,15 +19632,16 @@
"integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg=="
},
"node_modules/rollup": {
- "version": "2.79.1",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.1.tgz",
- "integrity": "sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==",
+ "version": "3.28.1",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.28.1.tgz",
+ "integrity": "sha512-R9OMQmIHJm9znrU3m3cpE8uhN0fGdXiawME7aZIpQqvpS/85+Vt1Hq1/yVIcYfOmaQiHjvXkQAoJukvLpau6Yw==",
"dev": true,
"bin": {
"rollup": "dist/bin/rollup"
},
"engines": {
- "node": ">=10.0.0"
+ "node": ">=14.18.0",
+ "npm": ">=8.0.0"
},
"optionalDependencies": {
"fsevents": "~2.3.2"
@@ -19906,19 +19766,6 @@
"node": ">= 8.0.0"
}
},
- "node_modules/rollup-plugin-minify-html-literals": {
- "version": "1.2.6",
- "resolved": "https://registry.npmjs.org/rollup-plugin-minify-html-literals/-/rollup-plugin-minify-html-literals-1.2.6.tgz",
- "integrity": "sha512-JRq2fjlCTiw0zu+1Sy3ClHGCxA79dWGr4HLHWSQgd060StVW9fBVksuj8Xw/suPkNSGClJf/4xNQ1MF6JeXPaw==",
- "dev": true,
- "dependencies": {
- "minify-html-literals": "^1.3.5",
- "rollup-pluginutils": "^2.8.2"
- },
- "peerDependencies": {
- "rollup": "^0.65.2 || ^1.0.0 || ^2.0.0"
- }
- },
"node_modules/rollup-plugin-postcss-lit": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/rollup-plugin-postcss-lit/-/rollup-plugin-postcss-lit-2.1.0.tgz",
@@ -19929,57 +19776,6 @@
"transform-ast": "^2.4.4"
}
},
- "node_modules/rollup-plugin-terser": {
- "version": "7.0.2",
- "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz",
- "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==",
- "deprecated": "This package has been deprecated and is no longer maintained. Please use @rollup/plugin-terser",
- "dev": true,
- "dependencies": {
- "@babel/code-frame": "^7.10.4",
- "jest-worker": "^26.2.1",
- "serialize-javascript": "^4.0.0",
- "terser": "^5.0.0"
- },
- "peerDependencies": {
- "rollup": "^2.0.0"
- }
- },
- "node_modules/rollup-plugin-terser/node_modules/has-flag": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
- "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/rollup-plugin-terser/node_modules/jest-worker": {
- "version": "26.6.2",
- "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz",
- "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==",
- "dev": true,
- "dependencies": {
- "@types/node": "*",
- "merge-stream": "^2.0.0",
- "supports-color": "^7.0.0"
- },
- "engines": {
- "node": ">= 10.13.0"
- }
- },
- "node_modules/rollup-plugin-terser/node_modules/supports-color": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
- "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
- "dev": true,
- "dependencies": {
- "has-flag": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/rollup-pluginutils": {
"version": "2.8.2",
"resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz",
@@ -20162,15 +19958,6 @@
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"dev": true
},
- "node_modules/serialize-javascript": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz",
- "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==",
- "dev": true,
- "dependencies": {
- "randombytes": "^2.1.0"
- }
- },
"node_modules/serve-favicon": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/serve-favicon/-/serve-favicon-2.5.0.tgz",
@@ -20453,6 +20240,12 @@
"node": ">=8"
}
},
+ "node_modules/smob": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/smob/-/smob-1.4.0.tgz",
+ "integrity": "sha512-MqR3fVulhjWuRNSMydnTlweu38UhQ0HXM4buStD/S3mc/BzX3CuM9OmhyQpmtYCvoYdl5ris6TI0ZqH355Ymqg==",
+ "dev": true
+ },
"node_modules/snapdragon": {
"version": "0.8.2",
"resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
@@ -21160,9 +20953,9 @@
}
},
"node_modules/style-mod": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.0.3.tgz",
- "integrity": "sha512-78Jv8kYJdjbvRwwijtCevYADfsI0lGzYJe4mMFdceO8l75DFFDoqBhR1jVDicDRRaX4//g1u9wKeo+ztc2h1Rw=="
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.0.tgz",
+ "integrity": "sha512-Ca5ib8HrFn+f+0n4N4ScTIA9iTOQ7MaGS1ylHcoVqW9J7w2w8PzN6g9gKmTYgGEBH8e120+RCmhpje6jC5uGWA=="
},
"node_modules/stylis": {
"version": "4.3.0",
@@ -21932,9 +21725,9 @@
}
},
"node_modules/typescript": {
- "version": "5.1.6",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz",
- "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==",
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
+ "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==",
"dev": true,
"bin": {
"tsc": "bin/tsc",
@@ -21949,6 +21742,7 @@
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz",
"integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==",
"dev": true,
+ "optional": true,
"bin": {
"uglifyjs": "bin/uglifyjs"
},
@@ -22217,12 +22011,6 @@
"browserslist": ">= 4.21.0"
}
},
- "node_modules/upper-case": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz",
- "integrity": "sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA==",
- "dev": true
- },
"node_modules/uri-js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
@@ -22473,23 +22261,6 @@
}
}
},
- "node_modules/vite/node_modules/rollup": {
- "version": "3.26.3",
- "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.26.3.tgz",
- "integrity": "sha512-7Tin0C8l86TkpcMtXvQu6saWH93nhG3dGQ1/+l5V2TDMceTxO7kDiK6GzbfLWNNxqJXm591PcEZUozZm51ogwQ==",
- "dev": true,
- "peer": true,
- "bin": {
- "rollup": "dist/bin/rollup"
- },
- "engines": {
- "node": ">=14.18.0",
- "npm": ">=8.0.0"
- },
- "optionalDependencies": {
- "fsevents": "~2.3.2"
- }
- },
"node_modules/vscode-css-languageservice": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/vscode-css-languageservice/-/vscode-css-languageservice-4.3.0.tgz",
diff --git a/web/package.json b/web/package.json
index 9368f94be..3d8176b9a 100644
--- a/web/package.json
+++ b/web/package.json
@@ -8,8 +8,8 @@
"build-locales": "run-s build-locales:build",
"build-locales:build": "lit-localize build",
"build-locales:repair": "prettier --write ./src/locale-codes.ts",
- "rollup:build": "node --max-old-space-size=4096 node_modules/.bin/rollup -c ./rollup.config.js",
- "rollup:build-proxy": "node --max-old-space-size=4096 node_modules/.bin/rollup -c ./rollup.proxy.js",
+ "rollup:build": "node --max-old-space-size=4096 node_modules/.bin/rollup -c ./rollup.config.mjs",
+ "rollup:build-proxy": "node --max-old-space-size=4096 node_modules/.bin/rollup -c ./rollup.proxy.mjs",
"rollup:watch": "node --max-old-space-size=8192 node_modules/.bin/rollup -c -w",
"build": "run-s build-locales rollup:build",
"build-proxy": "run-s build-locales rollup:build-proxy",
@@ -27,24 +27,24 @@
},
"dependencies": {
"@codemirror/lang-html": "^6.4.5",
- "@codemirror/lang-javascript": "^6.1.9",
+ "@codemirror/lang-javascript": "^6.2.0",
"@codemirror/lang-python": "^6.1.3",
"@codemirror/lang-xml": "^6.0.2",
"@codemirror/legacy-modes": "^6.3.3",
"@codemirror/theme-one-dark": "^6.1.2",
"@formatjs/intl-listformat": "^7.4.0",
"@fortawesome/fontawesome-free": "^6.4.2",
- "@goauthentik/api": "^2023.6.1-1692308915",
+ "@goauthentik/api": "^2023.6.1-1692789666",
"@lit-labs/context": "^0.4.0",
"@lit-labs/task": "^3.0.1",
"@lit/localize": "^0.11.4",
- "@patternfly/elements": "^2.3.2",
+ "@patternfly/elements": "^2.4.0",
"@patternfly/patternfly": "^4.224.2",
"@sentry/browser": "^7.64.0",
"@sentry/tracing": "^7.64.0",
"@webcomponents/webcomponentsjs": "^2.8.0",
"base64-js": "^1.5.1",
- "chart.js": "^4.3.3",
+ "chart.js": "^4.4.0",
"chartjs-adapter-moment": "^1.0.1",
"codemirror": "^6.0.1",
"construct-style-sheets-polyfill": "^3.1.0",
@@ -52,30 +52,31 @@
"country-flag-icons": "^1.5.7",
"fuse.js": "^6.6.2",
"lit": "^2.8.0",
- "mermaid": "^10.3.1",
+ "mermaid": "^10.4.0",
"rapidoc": "^9.3.4",
- "style-mod": "^4.0.3",
+ "style-mod": "^4.1.0",
"webcomponent-qr-code": "^1.2.0",
"yaml": "^2.3.1"
},
"devDependencies": {
- "@babel/core": "^7.22.10",
+ "@babel/core": "^7.22.11",
"@babel/plugin-proposal-class-properties": "^7.18.6",
"@babel/plugin-proposal-decorators": "^7.22.10",
"@babel/plugin-proposal-private-methods": "^7.18.6",
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
"@babel/plugin-transform-runtime": "^7.22.10",
"@babel/preset-env": "^7.22.10",
- "@babel/preset-typescript": "^7.22.5",
+ "@babel/preset-typescript": "^7.22.11",
"@hcaptcha/types": "^1.0.3",
"@jackfranklin/rollup-plugin-markdown": "^0.4.0",
"@jeysal/storybook-addon-css-user-preferences": "^0.2.0",
"@lit/localize-tools": "^0.6.9",
"@rollup/plugin-babel": "^6.0.3",
"@rollup/plugin-commonjs": "^25.0.4",
- "@rollup/plugin-node-resolve": "^15.2.0",
+ "@rollup/plugin-node-resolve": "^15.2.1",
"@rollup/plugin-replace": "^5.0.2",
- "@rollup/plugin-typescript": "^11.1.2",
+ "@rollup/plugin-typescript": "^11.1.3",
+ "@rollup/plugin-terser": "^0.4.3",
"@storybook/addon-essentials": "^7.3.2",
"@storybook/addon-links": "^7.3.2",
"@storybook/blocks": "^7.1.1",
@@ -83,13 +84,13 @@
"@storybook/web-components-vite": "^7.3.2",
"@trivago/prettier-plugin-sort-imports": "^4.2.0",
"@types/chart.js": "^2.9.37",
- "@types/codemirror": "5.60.8",
+ "@types/codemirror": "5.60.9",
"@types/grecaptcha": "^3.0.4",
- "@typescript-eslint/eslint-plugin": "^6.4.0",
- "@typescript-eslint/parser": "^6.4.0",
+ "@typescript-eslint/eslint-plugin": "^6.4.1",
+ "@typescript-eslint/parser": "^6.4.1",
"babel-plugin-macros": "^3.1.0",
"babel-plugin-tsconfig-paths": "^1.0.3",
- "eslint": "^8.47.0",
+ "eslint": "^8.48.0",
"eslint-config-google": "^0.14.0",
"eslint-plugin-custom-elements": "0.0.8",
"eslint-plugin-lit": "^1.9.1",
@@ -97,21 +98,19 @@
"lit-analyzer": "^1.2.1",
"npm-run-all": "^4.1.5",
"prettier": "^3.0.2",
- "pyright": "^1.1.323",
+ "pyright": "^1.1.324",
"react": "^18.2.0",
"react-dom": "^18.2.0",
- "rollup": "^2.79.1",
+ "rollup": "^3.28.1",
"rollup-plugin-copy": "^3.4.0",
"rollup-plugin-cssimport": "^1.0.3",
- "rollup-plugin-minify-html-literals": "^1.2.6",
"rollup-plugin-postcss-lit": "^2.1.0",
- "rollup-plugin-terser": "^7.0.2",
"storybook": "^7.3.2",
"storybook-addon-mock": "^4.2.1",
"ts-lit-plugin": "^1.2.1",
"tslib": "^2.6.2",
"turnstile-types": "^1.1.2",
- "typescript": "^5.1.6",
+ "typescript": "^5.2.2",
"vite-tsconfig-paths": "^4.2.0"
},
"optionalDependencies": {
diff --git a/web/rollup.config.js b/web/rollup.config.mjs
similarity index 99%
rename from web/rollup.config.js
rename to web/rollup.config.mjs
index 8e3a5c696..db9caf6ee 100644
--- a/web/rollup.config.js
+++ b/web/rollup.config.mjs
@@ -3,10 +3,10 @@ import babel from "@rollup/plugin-babel";
import commonjs from "@rollup/plugin-commonjs";
import { nodeResolve } from "@rollup/plugin-node-resolve";
import replace from "@rollup/plugin-replace";
+import terser from "@rollup/plugin-terser";
import { cwd } from "process";
import copy from "rollup-plugin-copy";
import cssimport from "rollup-plugin-cssimport";
-import { terser } from "rollup-plugin-terser";
// https://github.com/d3/d3-interpolate/issues/58
const IGNORED_WARNINGS = /Circular dependency(.*d3-[interpolate|selection])|(.*@lit\/localize.*)/;
diff --git a/web/rollup.proxy.js b/web/rollup.proxy.js
deleted file mode 100644
index 3599f5916..000000000
--- a/web/rollup.proxy.js
+++ /dev/null
@@ -1,3 +0,0 @@
-import { POLY, standalone } from "./rollup.config";
-
-export default [POLY, ...standalone];
diff --git a/web/rollup.proxy.mjs b/web/rollup.proxy.mjs
new file mode 100644
index 000000000..feef35604
--- /dev/null
+++ b/web/rollup.proxy.mjs
@@ -0,0 +1,3 @@
+import { POLY, standalone } from "./rollup.config.mjs";
+
+export default [POLY, ...standalone];
diff --git a/web/src/admin/admin-overview/cards/VersionStatusCard.ts b/web/src/admin/admin-overview/cards/VersionStatusCard.ts
index 304eddf5a..77b075467 100644
--- a/web/src/admin/admin-overview/cards/VersionStatusCard.ts
+++ b/web/src/admin/admin-overview/cards/VersionStatusCard.ts
@@ -12,7 +12,6 @@ import { AdminApi, Version } from "@goauthentik/api";
@customElement("ak-admin-status-version")
export class VersionStatusCard extends AdminStatusCard {
- headerLink = "https://goauthentik.io/docs/releases";
icon = "pf-icon pf-icon-bundle";
getPrimaryValue(): Promise {
@@ -43,16 +42,12 @@ export class VersionStatusCard extends AdminStatusCard {
}
renderValue(): TemplateResult {
+ let text = this.value?.versionCurrent;
+ let link = `https://goauthentik.io/docs/releases/${this.value?.versionCurrent}`;
if (this.value?.buildHash) {
- return html`
-
- ${this.value.buildHash?.substring(0, 7)}
-
- `;
+ text = this.value.buildHash?.substring(0, 7);
+ link = `https://github.com/goauthentik/authentik/commit/${this.value.buildHash}`;
}
- return html`${this.value?.versionCurrent}`;
+ return html`${text} `;
}
}
diff --git a/web/src/admin/enterprise/EnterpriseLicenseListPage.ts b/web/src/admin/enterprise/EnterpriseLicenseListPage.ts
index 248691708..27a0c1b67 100644
--- a/web/src/admin/enterprise/EnterpriseLicenseListPage.ts
+++ b/web/src/admin/enterprise/EnterpriseLicenseListPage.ts
@@ -170,11 +170,11 @@ export class EnterpriseLicenseListPage extends TablePage {
icon="pf-icon pf-icon-user"
header=${msg("Forecast internal users")}
subtext=${msg(
- str`Estimated user count one year from now based on ${this.forecast?.users} current internal users and ${this.forecast?.forecastedUsers} forecasted internal users.`,
+ str`Estimated user count one year from now based on ${this.forecast?.internalUsers} current internal users and ${this.forecast?.forecastedInternalUsers} forecasted internal users.`,
)}
>
- ~ ${(this.forecast?.users || 0) +
- (this.forecast?.forecastedUsers || 0)}
+ ~ ${(this.forecast?.internalUsers || 0) +
+ (this.forecast?.forecastedInternalUsers || 0)}
{
}
return [
html`${item.name}
`,
- html`
- 0 / ${item.users}
- 0 / ${item.externalUsers}
-
`,
+ html`${msg(str`Internal: ${item.internalUsers}`)}
+ ${msg(str`External: ${item.externalUsers}`)}
`,
html` ${item.expiry?.toLocaleString()} `,
html`
${msg("Update")}
diff --git a/web/src/admin/providers/oauth2/OAuth2ProviderForm.ts b/web/src/admin/providers/oauth2/OAuth2ProviderForm.ts
index a8d2f64f6..e20c63d9a 100644
--- a/web/src/admin/providers/oauth2/OAuth2ProviderForm.ts
+++ b/web/src/admin/providers/oauth2/OAuth2ProviderForm.ts
@@ -246,8 +246,8 @@ export class OAuth2ProviderFormPage extends ModelForm {
+
diff --git a/web/src/admin/tokens/TokenForm.ts b/web/src/admin/tokens/TokenForm.ts
index 766667070..88023488c 100644
--- a/web/src/admin/tokens/TokenForm.ts
+++ b/web/src/admin/tokens/TokenForm.ts
@@ -8,16 +8,21 @@ import "@goauthentik/elements/forms/SearchSelect";
import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit";
-import { customElement } from "lit/decorators.js";
+import { customElement, state } from "lit/decorators.js";
import { CoreApi, CoreUsersListRequest, IntentEnum, Token, User } from "@goauthentik/api";
@customElement("ak-token-form")
export class TokenForm extends ModelForm {
- loadInstance(pk: string): Promise {
- return new CoreApi(DEFAULT_CONFIG).coreTokensRetrieve({
+ @state()
+ showExpiry = true;
+
+ async loadInstance(pk: string): Promise {
+ const token = await new CoreApi(DEFAULT_CONFIG).coreTokensRetrieve({
identifier: pk,
});
+ this.showExpiry = token.expiring || true;
+ return token;
}
getSuccessMessage(): string {
@@ -41,6 +46,17 @@ export class TokenForm extends ModelForm {
}
}
+ renderExpiry(): TemplateResult {
+ return html`
+
+ `;
+ }
+
renderForm(): TemplateResult {
return html`
-
-
-
+ ${this.showExpiry ? this.renderExpiry() : html``}
`;
}
}
diff --git a/web/src/admin/users/UserForm.ts b/web/src/admin/users/UserForm.ts
index c46b205c1..b2cdef833 100644
--- a/web/src/admin/users/UserForm.ts
+++ b/web/src/admin/users/UserForm.ts
@@ -17,6 +17,10 @@ import { CoreApi, User } from "@goauthentik/api";
@customElement("ak-user-form")
export class UserForm extends ModelForm {
+ static get defaultUserAttributes(): { [key: string]: unknown } {
+ return {};
+ }
+
static get styles(): CSSResult[] {
return super.styles.concat(css`
.pf-c-button.pf-m-control {
@@ -43,6 +47,9 @@ export class UserForm extends ModelForm {
}
async send(data: User): Promise {
+ if (data.attributes === null) {
+ data.attributes = UserForm.defaultUserAttributes;
+ }
if (this.instance?.pk) {
return new CoreApi(DEFAULT_CONFIG).coreUsersPartialUpdate({
id: this.instance.pk,
@@ -145,12 +152,14 @@ export class UserForm extends ModelForm {
diff --git a/web/src/common/api/config.ts b/web/src/common/api/config.ts
index 4e120a38e..6276ec8a5 100644
--- a/web/src/common/api/config.ts
+++ b/web/src/common/api/config.ts
@@ -63,7 +63,7 @@ export function getMetaContent(key: string): string {
}
export const DEFAULT_CONFIG = new Configuration({
- basePath: process.env.AK_API_BASE_PATH + "/api/v3",
+ basePath: (process.env.AK_API_BASE_PATH || window.location.origin) + "/api/v3",
headers: {
"sentry-trace": getMetaContent("sentry-trace"),
},
diff --git a/web/src/common/api/middleware.ts b/web/src/common/api/middleware.ts
index b6f77ec47..745a5d1c9 100644
--- a/web/src/common/api/middleware.ts
+++ b/web/src/common/api/middleware.ts
@@ -25,8 +25,13 @@ export class LoggingMiddleware implements Middleware {
post(context: ResponseContext): Promise {
let msg = `authentik/api[${this.tenant.matchedDomain}]: `;
- msg += `${context.response.status} ${context.init.method} ${context.url}`;
- console.debug(msg);
+ // https://developer.mozilla.org/en-US/docs/Web/API/console#styling_console_output
+ msg += `%c${context.response.status}%c ${context.init.method} ${context.url}`;
+ let style = "";
+ if (context.response.status >= 400) {
+ style = "color: red; font-weight: bold;";
+ }
+ console.debug(msg, style, "");
return Promise.resolve(context.response);
}
}
diff --git a/web/src/elements/table/Table.ts b/web/src/elements/table/Table.ts
index f671e7b37..b9cf20b14 100644
--- a/web/src/elements/table/Table.ts
+++ b/web/src/elements/table/Table.ts
@@ -23,7 +23,7 @@ import PFToolbar from "@patternfly/patternfly/components/Toolbar/toolbar.css";
import PFBullseye from "@patternfly/patternfly/layouts/Bullseye/bullseye.css";
import PFBase from "@patternfly/patternfly/patternfly-base.css";
-import { Pagination } from "@goauthentik/api";
+import { Pagination, ResponseError } from "@goauthentik/api";
export class TableColumn {
title: string;
@@ -260,7 +260,9 @@ export abstract class Table extends AKElement {
renderError(): TemplateResult {
return html`
- ${this.hasError?.toString()}
+ ${this.hasError instanceof ResponseError
+ ? html` ${this.hasError.message}
`
+ : html`${this.hasError?.toString()}
`}
`;
}
@@ -268,8 +270,8 @@ export abstract class Table extends AKElement {
if (this.hasError) {
return [this.renderEmpty(this.renderError())];
}
- if (!this.data) {
- return;
+ if (!this.data || this.isLoading) {
+ return [this.renderLoading()];
}
if (this.data.pagination.count === 0) {
return [this.renderEmpty()];
@@ -499,7 +501,7 @@ export abstract class Table extends AKElement {
${this.columns().map((col) => col.render(this))}
- ${this.isLoading || !this.data ? this.renderLoading() : this.renderRows()}
+ ${this.renderRows()}
${this.paginated
? html` `;
}
}
diff --git a/web/src/user/user-settings/UserSettingsPage.ts b/web/src/user/user-settings/UserSettingsPage.ts
index 8f447c4df..cd9718066 100644
--- a/web/src/user/user-settings/UserSettingsPage.ts
+++ b/web/src/user/user-settings/UserSettingsPage.ts
@@ -116,43 +116,63 @@ export class UserSettingsPage extends AKElement {
data-tab-title="${msg("Sessions")}"
class="pf-c-page__main-section pf-m-no-padding-mobile"
>
- ()?.me?.user.username,
- )}
- >
+
+
+
()?.me?.user.username,
+ )}
+ >
+
+
- ()?.me?.user.pk)}
- >
+
+
+
()?.me?.user.pk)}
+ >
+
+
diff --git a/web/xliff/de.xlf b/web/xliff/de.xlf
index 5299c3cdc..0c20576ee 100644
--- a/web/xliff/de.xlf
+++ b/web/xliff/de.xlf
@@ -5806,7 +5806,7 @@ Bindings to groups/users are checked against the user of the event.
Forecast internal users
- Estimated user count one year from now based on current internal users and forecasted internal users.
+ Estimated user count one year from now based on current internal users and forecasted internal users.
Forecast external users
@@ -5888,6 +5888,12 @@ Bindings to groups/users are checked against the user of the event.
The length of the individual generated tokens. Can be increased to improve security.
+
+
+ Internal:
+
+
+ External: