Compare commits

..

5 Commits

Author SHA1 Message Date
57a38c93fc cleanup and fix tests
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-04-25 22:57:41 +02:00
93b9dae178 fix logic
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-04-25 20:32:58 +02:00
589c123dc1 update in models too
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-04-25 20:19:31 +02:00
a4d9f08095 also default to entryDN for new sources
(this will also help us with a future migration to better save association with ldap sources)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2024-04-25 20:01:27 +02:00
d856e403f8 sources/ldap: allow using entryDN as uniqueness field 2024-04-25 19:59:11 +02:00
120 changed files with 2732 additions and 4078 deletions

View File

@ -1,5 +1,5 @@
[bumpversion]
current_version = 2024.4.1
current_version = 2024.4.0
tag = True
commit = True
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(?:-(?P<rc_t>[a-zA-Z-]+)(?P<rc_n>[1-9]\\d*))?

View File

@ -54,9 +54,9 @@ image_main_tag = image_tags[0]
image_tags_rendered = ",".join(image_tags)
with open(os.environ["GITHUB_OUTPUT"], "a+", encoding="utf-8") as _output:
print(f"shouldBuild={should_build}", file=_output)
print(f"sha={sha}", file=_output)
print(f"version={version}", file=_output)
print(f"prerelease={prerelease}", file=_output)
print(f"imageTags={image_tags_rendered}", file=_output)
print(f"imageMainTag={image_main_tag}", file=_output)
print("shouldBuild=%s" % should_build, file=_output)
print("sha=%s" % sha, file=_output)
print("version=%s" % version, file=_output)
print("prerelease=%s" % prerelease, file=_output)
print("imageTags=%s" % image_tags_rendered, file=_output)
print("imageMainTag=%s" % image_main_tag, file=_output)

View File

@ -155,8 +155,8 @@ jobs:
- uses: actions/checkout@v4
- name: Run test suite in final docker images
run: |
echo "PG_PASS=$(openssl rand 32 | base64)" >> .env
echo "AUTHENTIK_SECRET_KEY=$(openssl rand 32 | base64)" >> .env
echo "PG_PASS=$(openssl rand -base64 32)" >> .env
echo "AUTHENTIK_SECRET_KEY=$(openssl rand -base64 32)" >> .env
docker compose pull -q
docker compose up --no-start
docker compose start postgresql redis

View File

@ -14,8 +14,8 @@ jobs:
- uses: actions/checkout@v4
- name: Pre-release test
run: |
echo "PG_PASS=$(openssl rand 32 | base64)" >> .env
echo "AUTHENTIK_SECRET_KEY=$(openssl rand 32 | base64)" >> .env
echo "PG_PASS=$(openssl rand -base64 32)" >> .env
echo "AUTHENTIK_SECRET_KEY=$(openssl rand -base64 32)" >> .env
docker buildx install
mkdir -p ./gen-ts-api
docker build -t testing:latest .

View File

@ -1,7 +1,7 @@
# syntax=docker/dockerfile:1
# Stage 1: Build website
FROM --platform=${BUILDPLATFORM} docker.io/node:22 as website-builder
FROM --platform=${BUILDPLATFORM} docker.io/node:21 as website-builder
ENV NODE_ENV=production
@ -20,7 +20,7 @@ COPY ./SECURITY.md /work/
RUN npm run build-bundled
# Stage 2: Build webui
FROM --platform=${BUILDPLATFORM} docker.io/node:22 as web-builder
FROM --platform=${BUILDPLATFORM} docker.io/node:21 as web-builder
ENV NODE_ENV=production

View File

@ -46,8 +46,8 @@ test-go:
go test -timeout 0 -v -race -cover ./...
test-docker: ## Run all tests in a docker-compose
echo "PG_PASS=$(shell openssl rand 32 | base64)" >> .env
echo "AUTHENTIK_SECRET_KEY=$(shell openssl rand 32 | base64)" >> .env
echo "PG_PASS=$(openssl rand -base64 32)" >> .env
echo "AUTHENTIK_SECRET_KEY=$(openssl rand -base64 32)" >> .env
docker compose pull -q
docker compose up --no-start
docker compose start postgresql redis

View File

@ -2,7 +2,7 @@
from os import environ
__version__ = "2024.4.1"
__version__ = "2024.4.0"
ENV_GIT_HASH_KEY = "GIT_BUILD_HASH"

View File

@ -154,18 +154,12 @@ class GroupViewSet(UsedByMixin, ModelViewSet):
pk = IntegerField(required=True)
queryset = Group.objects.none()
queryset = Group.objects.all().select_related("parent").prefetch_related("users")
serializer_class = GroupSerializer
search_fields = ["name", "is_superuser"]
filterset_class = GroupFilter
ordering = ["name"]
def get_queryset(self):
base_qs = Group.objects.all().select_related("parent").prefetch_related("roles")
if self.serializer_class(context={"request": self.request})._should_include_users:
base_qs = base_qs.prefetch_related("users")
return base_qs
@extend_schema(
parameters=[
OpenApiParameter("include_users", bool, default=True),

View File

@ -407,11 +407,8 @@ class UserViewSet(UsedByMixin, ModelViewSet):
search_fields = ["username", "name", "is_active", "email", "uuid"]
filterset_class = UsersFilter
def get_queryset(self):
base_qs = User.objects.all().exclude_anonymous()
if self.serializer_class(context={"request": self.request})._should_include_groups:
base_qs = base_qs.prefetch_related("ak_groups")
return base_qs
def get_queryset(self): # pragma: no cover
return User.objects.all().exclude_anonymous().prefetch_related("ak_groups")
@extend_schema(
parameters=[

View File

@ -632,7 +632,7 @@ class UserSourceConnection(SerializerModel, CreatedUpdatedModel):
raise NotImplementedError
def __str__(self) -> str:
return f"User-source connection (user={self.user_id}, source={self.source_id})"
return f"User-source connection (user={self.user.username}, source={self.source.slug})"
class Meta:
unique_together = (("user", "source"),)

View File

@ -5,7 +5,7 @@ from guardian.shortcuts import assign_perm
from rest_framework.test import APITestCase
from authentik.core.models import Group, User
from authentik.core.tests.utils import create_test_admin_user, create_test_user
from authentik.core.tests.utils import create_test_user
from authentik.lib.generators import generate_id
@ -16,13 +16,6 @@ class TestGroupsAPI(APITestCase):
self.login_user = create_test_user()
self.user = User.objects.create(username="test-user")
def test_list_with_users(self):
"""Test listing with users"""
admin = create_test_admin_user()
self.client.force_login(admin)
response = self.client.get(reverse("authentik_api:group-list"), {"include_users": "true"})
self.assertEqual(response.status_code, 200)
def test_add_user(self):
"""Test add_user"""
group = Group.objects.create(name=generate_id())

View File

@ -66,11 +66,14 @@ class TestPropertyMappings(TestCase):
expression="return request.http_request.path",
)
http_request = self.factory.get("/")
tmpl = f"""
res = ak_call_policy('{expr.name}')
tmpl = (
"""
res = ak_call_policy('%s')
result = [request.http_request.path, res.raw_result]
return result
"""
% expr.name
)
evaluator = PropertyMapping(expression=tmpl, name=generate_id())
res = evaluator.evaluate(self.user, http_request)
self.assertEqual(res, ["/", "/"])

View File

@ -41,12 +41,6 @@ class TestUsersAPI(APITestCase):
)
self.assertEqual(response.status_code, 200)
def test_list_with_groups(self):
"""Test listing with groups"""
self.client.force_login(self.admin)
response = self.client.get(reverse("authentik_api:user-list"), {"include_groups": "true"})
self.assertEqual(response.status_code, 200)
def test_metrics(self):
"""Test user's metrics"""
self.client.force_login(self.admin)

View File

@ -8,6 +8,7 @@ from rest_framework.test import APITestCase
from authentik.core.models import User
from authentik.core.tests.utils import create_test_admin_user
from authentik.lib.config import CONFIG
from authentik.tenants.utils import get_current_tenant
@ -24,6 +25,7 @@ class TestUsersAvatars(APITestCase):
tenant.avatars = mode
tenant.save()
@CONFIG.patch("avatars", "none")
def test_avatars_none(self):
"""Test avatars none"""
self.set_avatar_mode("none")

View File

@ -4,7 +4,7 @@ from django.utils.text import slugify
from authentik.brands.models import Brand
from authentik.core.models import Group, User
from authentik.crypto.builder import CertificateBuilder, PrivateKeyAlg
from authentik.crypto.builder import CertificateBuilder
from authentik.crypto.models import CertificateKeyPair
from authentik.flows.models import Flow, FlowDesignation
from authentik.lib.generators import generate_id
@ -50,10 +50,12 @@ def create_test_brand(**kwargs) -> Brand:
return Brand.objects.create(domain=uid, default=True, **kwargs)
def create_test_cert(alg=PrivateKeyAlg.RSA) -> CertificateKeyPair:
def create_test_cert(use_ec_private_key=False) -> CertificateKeyPair:
"""Generate a certificate for testing"""
builder = CertificateBuilder(f"{generate_id()}.self-signed.goauthentik.io")
builder.alg = alg
builder = CertificateBuilder(
name=f"{generate_id()}.self-signed.goauthentik.io",
use_ec_private_key=use_ec_private_key,
)
builder.build(
subject_alt_names=[f"{generate_id()}.self-signed.goauthentik.io"],
validity_days=360,

View File

@ -14,13 +14,7 @@ from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import OpenApiParameter, OpenApiResponse, extend_schema
from rest_framework.decorators import action
from rest_framework.exceptions import ValidationError
from rest_framework.fields import (
CharField,
ChoiceField,
DateTimeField,
IntegerField,
SerializerMethodField,
)
from rest_framework.fields import CharField, DateTimeField, IntegerField, SerializerMethodField
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.request import Request
from rest_framework.response import Response
@ -32,7 +26,7 @@ from authentik.api.authorization import SecretKeyFilter
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import PassiveSerializer
from authentik.crypto.apps import MANAGED_KEY
from authentik.crypto.builder import CertificateBuilder, PrivateKeyAlg
from authentik.crypto.builder import CertificateBuilder
from authentik.crypto.models import CertificateKeyPair
from authentik.events.models import Event, EventAction
from authentik.rbac.decorators import permission_required
@ -184,7 +178,6 @@ class CertificateGenerationSerializer(PassiveSerializer):
common_name = CharField()
subject_alt_name = CharField(required=False, allow_blank=True, label=_("Subject-alt name"))
validity_days = IntegerField(initial=365)
alg = ChoiceField(default=PrivateKeyAlg.RSA, choices=PrivateKeyAlg.choices)
class CertificateKeyPairFilter(FilterSet):
@ -247,7 +240,6 @@ class CertificateKeyPairViewSet(UsedByMixin, ModelViewSet):
raw_san = data.validated_data.get("subject_alt_name", "")
sans = raw_san.split(",") if raw_san != "" else []
builder = CertificateBuilder(data.validated_data["common_name"])
builder.alg = data.validated_data["alg"]
builder.build(
subject_alt_names=sans,
validity_days=int(data.validated_data["validity_days"]),

View File

@ -9,28 +9,20 @@ from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import ec, rsa
from cryptography.hazmat.primitives.asymmetric.types import PrivateKeyTypes
from cryptography.x509.oid import NameOID
from django.db import models
from django.utils.translation import gettext_lazy as _
from authentik import __version__
from authentik.crypto.models import CertificateKeyPair
class PrivateKeyAlg(models.TextChoices):
"""Algorithm to create private key with"""
RSA = "rsa", _("rsa")
ECDSA = "ecdsa", _("ecdsa")
class CertificateBuilder:
"""Build self-signed certificates"""
common_name: str
alg: PrivateKeyAlg
def __init__(self, name: str):
self.alg = PrivateKeyAlg.RSA
_use_ec_private_key: bool
def __init__(self, name: str, use_ec_private_key=False):
self._use_ec_private_key = use_ec_private_key
self.__public_key = None
self.__private_key = None
self.__builder = None
@ -50,13 +42,11 @@ class CertificateBuilder:
def generate_private_key(self) -> PrivateKeyTypes:
"""Generate private key"""
if self.alg == PrivateKeyAlg.ECDSA:
if self._use_ec_private_key:
return ec.generate_private_key(curve=ec.SECP256R1())
if self.alg == PrivateKeyAlg.RSA:
return rsa.generate_private_key(
public_exponent=65537, key_size=4096, backend=default_backend()
)
raise ValueError(f"Invalid alg: {self.alg}")
return rsa.generate_private_key(
public_exponent=65537, key_size=4096, backend=default_backend()
)
def build(
self,

View File

@ -201,7 +201,10 @@ class ConnectionToken(ExpiringModel):
return settings
def __str__(self):
return f"RAC Connection token {self.session_id} to {self.provider_id}/{self.endpoint_id}"
return (
f"RAC Connection token {self.session.user} to "
f"{self.endpoint.provider.name}/{self.endpoint.name}"
)
class Meta:
verbose_name = _("RAC Connection token")

View File

@ -116,12 +116,12 @@ class AuditMiddleware:
return user
user = getattr(request, "user", self.anonymous_user)
if not user.is_authenticated:
self._ensure_fallback_user()
return self.anonymous_user
return user
def connect(self, request: HttpRequest):
"""Connect signal for automatic logging"""
self._ensure_fallback_user()
if not hasattr(request, "request_id"):
return
post_save.connect(

View File

@ -556,7 +556,7 @@ class Notification(SerializerModel):
if len(self.body) > NOTIFICATION_SUMMARY_LENGTH
else self.body
)
return f"Notification for user {self.user_id}: {body_trunc}"
return f"Notification for user {self.user}: {body_trunc}"
class Meta:
verbose_name = _("Notification")

View File

@ -1,35 +0,0 @@
"""authentik event models tests"""
from collections.abc import Callable
from django.db.models import Model
from django.test import TestCase
from authentik.core.models import default_token_key
from authentik.lib.utils.reflection import get_apps
class TestModels(TestCase):
"""Test Models"""
def model_tester_factory(test_model: type[Model]) -> Callable:
"""Test models' __str__ and __repr__"""
def tester(self: TestModels):
allowed = 0
# Token-like objects need to lookup the current tenant to get the default token length
for field in test_model._meta.fields:
if field.default == default_token_key:
allowed += 1
with self.assertNumQueries(allowed):
str(test_model())
with self.assertNumQueries(allowed):
repr(test_model())
return tester
for app in get_apps():
for model in app.get_models():
setattr(TestModels, f"test_{app.label}_{model.__name__}", model_tester_factory(model))

View File

@ -278,7 +278,7 @@ class FlowViewSet(UsedByMixin, ModelViewSet):
},
)
@action(detail=True, pagination_class=None, filter_backends=[])
def execute(self, request: Request, slug: str):
def execute(self, request: Request, _slug: str):
"""Execute flow for current user"""
# Because we pre-plan the flow here, and not in the planner, we need to manually clear
# the history of the inspector

View File

@ -6,7 +6,6 @@ from rest_framework.test import APITestCase
from authentik.core.tests.utils import create_test_admin_user
from authentik.flows.api.stages import StageSerializer, StageViewSet
from authentik.flows.models import Flow, FlowDesignation, FlowStageBinding, Stage
from authentik.lib.generators import generate_id
from authentik.policies.dummy.models import DummyPolicy
from authentik.policies.models import PolicyBinding
from authentik.stages.dummy.models import DummyStage
@ -102,21 +101,3 @@ class TestFlowsAPI(APITestCase):
reverse("authentik_api:stage-types"),
)
self.assertEqual(response.status_code, 200)
def test_execute(self):
"""Test execute endpoint"""
user = create_test_admin_user()
self.client.force_login(user)
flow = Flow.objects.create(
name=generate_id(),
slug=generate_id(),
designation=FlowDesignation.AUTHENTICATION,
)
FlowStageBinding.objects.create(
target=flow, stage=DummyStage.objects.create(name=generate_id()), order=0
)
response = self.client.get(
reverse("authentik_api:flow-execute", kwargs={"slug": flow.slug})
)
self.assertEqual(response.status_code, 200)

View File

@ -96,13 +96,16 @@ class TestEvaluator(TestCase):
execution_logging=True,
expression="ak_message(request.http_request.path)\nreturn True",
)
tmpl = f"""
tmpl = (
"""
ak_message(request.http_request.path)
res = ak_call_policy('{expr.name}')
res = ak_call_policy('%s')
ak_message(request.http_request.path)
for msg in res.messages:
ak_message(msg)
"""
% expr.name
)
evaluator = PolicyEvaluator("test")
evaluator.set_policy_request(self.request)
res = evaluator.evaluate(tmpl)

View File

@ -326,7 +326,7 @@ class AuthorizationCode(SerializerModel, ExpiringModel, BaseGrantModel):
verbose_name_plural = _("Authorization Codes")
def __str__(self):
return f"Authorization code for {self.provider_id} for user {self.user_id}"
return f"Authorization code for {self.provider} for user {self.user}"
@property
def serializer(self) -> Serializer:
@ -356,7 +356,7 @@ class AccessToken(SerializerModel, ExpiringModel, BaseGrantModel):
verbose_name_plural = _("OAuth2 Access Tokens")
def __str__(self):
return f"Access Token for {self.provider_id} for user {self.user_id}"
return f"Access Token for {self.provider} for user {self.user}"
@property
def id_token(self) -> IDToken:
@ -399,7 +399,7 @@ class RefreshToken(SerializerModel, ExpiringModel, BaseGrantModel):
verbose_name_plural = _("OAuth2 Refresh Tokens")
def __str__(self):
return f"Refresh Token for {self.provider_id} for user {self.user_id}"
return f"Refresh Token for {self.provider} for user {self.user}"
@property
def id_token(self) -> IDToken:
@ -443,4 +443,4 @@ class DeviceToken(ExpiringModel):
verbose_name_plural = _("Device Tokens")
def __str__(self):
return f"Device Token for {self.provider_id}"
return f"Device Token for {self.provider}"

View File

@ -10,7 +10,6 @@ from jwt import PyJWKSet
from authentik.core.models import Application
from authentik.core.tests.utils import create_test_cert, create_test_flow
from authentik.crypto.builder import PrivateKeyAlg
from authentik.crypto.models import CertificateKeyPair
from authentik.lib.generators import generate_id
from authentik.providers.oauth2.models import OAuth2Provider
@ -83,7 +82,7 @@ class TestJWKS(OAuthTestCase):
client_id="test",
authorization_flow=create_test_flow(),
redirect_uris="http://local.invalid",
signing_key=create_test_cert(PrivateKeyAlg.ECDSA),
signing_key=create_test_cert(use_ec_private_key=True),
)
app = Application.objects.create(name="test", slug="test", provider=provider)
response = self.client.get(

View File

@ -1,44 +0,0 @@
# Generated by Django 5.0.4 on 2024-05-01 15:32
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_providers_saml", "0013_samlprovider_default_relay_state"),
]
operations = [
migrations.AlterField(
model_name="samlprovider",
name="digest_algorithm",
field=models.TextField(
choices=[
("http://www.w3.org/2000/09/xmldsig#sha1", "SHA1"),
("http://www.w3.org/2001/04/xmlenc#sha256", "SHA256"),
("http://www.w3.org/2001/04/xmldsig-more#sha384", "SHA384"),
("http://www.w3.org/2001/04/xmlenc#sha512", "SHA512"),
],
default="http://www.w3.org/2001/04/xmlenc#sha256",
),
),
migrations.AlterField(
model_name="samlprovider",
name="signature_algorithm",
field=models.TextField(
choices=[
("http://www.w3.org/2000/09/xmldsig#rsa-sha1", "RSA-SHA1"),
("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", "RSA-SHA256"),
("http://www.w3.org/2001/04/xmldsig-more#rsa-sha384", "RSA-SHA384"),
("http://www.w3.org/2001/04/xmldsig-more#rsa-sha512", "RSA-SHA512"),
("http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1", "ECDSA-SHA1"),
("http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256", "ECDSA-SHA256"),
("http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384", "ECDSA-SHA384"),
("http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512", "ECDSA-SHA512"),
("http://www.w3.org/2000/09/xmldsig#dsa-sha1", "DSA-SHA1"),
],
default="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256",
),
),
]

View File

@ -11,10 +11,6 @@ from authentik.crypto.models import CertificateKeyPair
from authentik.lib.utils.time import timedelta_string_validator
from authentik.sources.saml.processors.constants import (
DSA_SHA1,
ECDSA_SHA1,
ECDSA_SHA256,
ECDSA_SHA384,
ECDSA_SHA512,
RSA_SHA1,
RSA_SHA256,
RSA_SHA384,
@ -96,7 +92,8 @@ class SAMLProvider(Provider):
),
)
digest_algorithm = models.TextField(
digest_algorithm = models.CharField(
max_length=50,
choices=(
(SHA1, _("SHA1")),
(SHA256, _("SHA256")),
@ -105,16 +102,13 @@ class SAMLProvider(Provider):
),
default=SHA256,
)
signature_algorithm = models.TextField(
signature_algorithm = models.CharField(
max_length=50,
choices=(
(RSA_SHA1, _("RSA-SHA1")),
(RSA_SHA256, _("RSA-SHA256")),
(RSA_SHA384, _("RSA-SHA384")),
(RSA_SHA512, _("RSA-SHA512")),
(ECDSA_SHA1, _("ECDSA-SHA1")),
(ECDSA_SHA256, _("ECDSA-SHA256")),
(ECDSA_SHA384, _("ECDSA-SHA384")),
(ECDSA_SHA512, _("ECDSA-SHA512")),
(DSA_SHA1, _("DSA-SHA1")),
),
default=RSA_SHA256,

View File

@ -7,14 +7,13 @@ from lxml import etree # nosec
from authentik.core.models import Application
from authentik.core.tests.utils import create_test_cert, create_test_flow
from authentik.crypto.builder import PrivateKeyAlg
from authentik.lib.generators import generate_id
from authentik.lib.tests.utils import load_fixture
from authentik.lib.xml import lxml_from_string
from authentik.providers.saml.models import SAMLBindings, SAMLPropertyMapping, SAMLProvider
from authentik.providers.saml.processors.metadata import MetadataProcessor
from authentik.providers.saml.processors.metadata_parser import ServiceProviderMetadataParser
from authentik.sources.saml.processors.constants import ECDSA_SHA256, NS_MAP, NS_SAML_METADATA
from authentik.sources.saml.processors.constants import NS_MAP, NS_SAML_METADATA
class TestServiceProviderMetadataParser(TestCase):
@ -108,41 +107,12 @@ class TestServiceProviderMetadataParser(TestCase):
load_fixture("fixtures/cert.xml").replace("/apps/user_saml", "")
)
def test_signature_rsa(self):
"""Test signature validation (RSA)"""
def test_signature(self):
"""Test signature validation"""
provider = SAMLProvider.objects.create(
name=generate_id(),
authorization_flow=self.flow,
signing_kp=create_test_cert(PrivateKeyAlg.RSA),
)
Application.objects.create(
name=generate_id(),
slug=generate_id(),
provider=provider,
)
request = self.factory.get("/")
metadata = MetadataProcessor(provider, request).build_entity_descriptor()
root = fromstring(metadata.encode())
xmlsec.tree.add_ids(root, ["ID"])
signature_nodes = root.xpath("/md:EntityDescriptor/ds:Signature", namespaces=NS_MAP)
signature_node = signature_nodes[0]
ctx = xmlsec.SignatureContext()
key = xmlsec.Key.from_memory(
provider.signing_kp.certificate_data,
xmlsec.constants.KeyDataFormatCertPem,
None,
)
ctx.key = key
ctx.verify(signature_node)
def test_signature_ecdsa(self):
"""Test signature validation (ECDSA)"""
provider = SAMLProvider.objects.create(
name=generate_id(),
authorization_flow=self.flow,
signing_kp=create_test_cert(PrivateKeyAlg.ECDSA),
signature_algorithm=ECDSA_SHA256,
signing_kp=create_test_cert(),
)
Application.objects.create(
name=generate_id(),

View File

@ -3,7 +3,7 @@
from structlog.stdlib import get_logger
from authentik.providers.scim.models import SCIMProvider
from authentik.providers.scim.tasks import scim_task_wrapper
from authentik.providers.scim.tasks import scim_sync
from authentik.tenants.management import TenantCommand
LOGGER = get_logger()
@ -21,4 +21,4 @@ class Command(TenantCommand):
if not provider:
LOGGER.warning("Provider does not exist", name=provider_name)
continue
scim_task_wrapper(provider.pk).get()
scim_sync.delay(provider.pk).get()

View File

@ -105,7 +105,7 @@ class SCIMUser(models.Model):
unique_together = (("id", "user", "provider"),)
def __str__(self) -> str:
return f"SCIM User {self.user_id} to {self.provider_id}"
return f"SCIM User {self.user.username} to {self.provider.name}"
class SCIMGroup(models.Model):
@ -119,4 +119,4 @@ class SCIMGroup(models.Model):
unique_together = (("id", "group", "provider"),)
def __str__(self) -> str:
return f"SCIM Group {self.group_id} to {self.provider_id}"
return f"SCIM Group {self.group.name} to {self.provider.name}"

View File

@ -9,7 +9,7 @@ from structlog.stdlib import get_logger
from authentik.core.models import Group, User
from authentik.lib.utils.reflection import class_to_path
from authentik.providers.scim.models import SCIMProvider
from authentik.providers.scim.tasks import scim_signal_direct, scim_signal_m2m, scim_task_wrapper
from authentik.providers.scim.tasks import scim_signal_direct, scim_signal_m2m, scim_sync
LOGGER = get_logger()
@ -17,7 +17,7 @@ LOGGER = get_logger()
@receiver(post_save, sender=SCIMProvider)
def post_save_provider(sender: type[Model], instance, created: bool, **_):
"""Trigger sync when SCIM provider is saved"""
scim_task_wrapper(instance.pk)
scim_sync.delay(instance.pk)
@receiver(post_save, sender=User)

View File

@ -38,23 +38,7 @@ def client_for_model(provider: SCIMProvider, model: Model) -> SCIMClient:
def scim_sync_all():
"""Run sync for all providers"""
for provider in SCIMProvider.objects.filter(backchannel_application__isnull=False):
scim_task_wrapper(provider.pk)
def scim_task_wrapper(provider_pk: int):
"""Wrap scim_sync to set the correct timeouts"""
provider: SCIMProvider = SCIMProvider.objects.filter(
pk=provider_pk, backchannel_application__isnull=False
).first()
if not provider:
return
users_paginator = Paginator(provider.get_user_qs(), PAGE_SIZE)
groups_paginator = Paginator(provider.get_group_qs(), PAGE_SIZE)
soft_time_limit = (users_paginator.num_pages + groups_paginator.num_pages) * PAGE_TIMEOUT
time_limit = soft_time_limit * 1.5
return scim_sync.apply_async(
(provider.pk,), time_limit=int(time_limit), soft_time_limit=int(soft_time_limit)
)
scim_sync.delay(provider.pk)
@CELERY_APP.task(bind=True, base=SystemTask)
@ -76,7 +60,7 @@ def scim_sync(self: SystemTask, provider_pk: int) -> None:
users_paginator = Paginator(provider.get_user_qs(), PAGE_SIZE)
groups_paginator = Paginator(provider.get_group_qs(), PAGE_SIZE)
self.soft_time_limit = self.time_limit = (
users_paginator.num_pages + groups_paginator.num_pages
users_paginator.count + groups_paginator.count
) * PAGE_TIMEOUT
with allow_join_result():
try:

View File

@ -8,7 +8,7 @@ from authentik.core.models import Application, Group, User
from authentik.lib.generators import generate_id
from authentik.providers.scim.clients.schema import ServiceProviderConfiguration
from authentik.providers.scim.models import SCIMMapping, SCIMProvider
from authentik.providers.scim.tasks import scim_task_wrapper
from authentik.providers.scim.tasks import scim_sync
from authentik.tenants.models import Tenant
@ -79,7 +79,7 @@ class SCIMMembershipTests(TestCase):
)
self.configure()
scim_task_wrapper(self.provider.pk).get()
scim_sync.delay(self.provider.pk).get()
self.assertEqual(mocker.call_count, 6)
self.assertEqual(mocker.request_history[0].method, "GET")
@ -169,7 +169,7 @@ class SCIMMembershipTests(TestCase):
)
self.configure()
scim_task_wrapper(self.provider.pk).get()
scim_sync.delay(self.provider.pk).get()
self.assertEqual(mocker.call_count, 6)
self.assertEqual(mocker.request_history[0].method, "GET")

View File

@ -10,7 +10,7 @@ from authentik.blueprints.tests import apply_blueprint
from authentik.core.models import Application, Group, User
from authentik.lib.generators import generate_id
from authentik.providers.scim.models import SCIMMapping, SCIMProvider
from authentik.providers.scim.tasks import scim_task_wrapper
from authentik.providers.scim.tasks import scim_sync
from authentik.tenants.models import Tenant
@ -236,7 +236,7 @@ class SCIMUserTests(TestCase):
email=f"{uid}@goauthentik.io",
)
scim_task_wrapper(self.provider.pk).get()
scim_sync.delay(self.provider.pk).get()
self.assertEqual(mock.call_count, 5)
self.assertEqual(mock.request_history[0].method, "GET")

View File

@ -76,7 +76,7 @@ class S3Storage(BaseS3Storage):
return safe_join(self.location, connection.schema_name, name)
except ValueError:
raise SuspiciousOperation(f"Attempted access to '{name}' denied.") from None
raise SuspiciousOperation("Attempted access to '%s' denied." % name) from None
# This is a fix for https://github.com/jschneier/django-storages/pull/839
def url(self, name, parameters=None, expire=None, http_method=None):

View File

@ -153,7 +153,7 @@ class Migration(migrations.Migration):
(
"object_uniqueness_field",
models.TextField(
default="objectSid", help_text="Field which contains a unique Identifier."
default="entryDN", help_text="Field which contains a unique Identifier."
),
),
("sync_groups", models.BooleanField(default=True)),

View File

@ -88,7 +88,7 @@ class LDAPSource(Source):
help_text=_("Consider Objects matching this filter to be Groups."),
)
object_uniqueness_field = models.TextField(
default="objectSid", help_text=_("Field which contains a unique Identifier.")
default="entryDN", help_text=_("Field which contains a unique Identifier.")
)
property_mappings_group = models.ManyToManyField(

View File

@ -47,6 +47,15 @@ class BaseLDAPSynchronizer:
"""UI name for the type of object this class synchronizes"""
raise NotImplementedError
def get_unique_identifier(self, ldap_object: dict) -> str | None:
"""Get unique identifier"""
attributes = ldap_object.get("attributes", {})
if self._source.object_uniqueness_field in attributes:
return flatten(attributes[self._source.object_uniqueness_field])
if self._source.object_uniqueness_field in ldap_object:
return flatten(ldap_object.get(self._source.object_uniqueness_field))
return None
def sync_full(self):
"""Run full sync, this function should only be used in tests"""
if not settings.TEST: # noqa
@ -134,20 +143,22 @@ class BaseLDAPSynchronizer:
cookie = None
yield self._connection.response
def build_user_properties(self, user_dn: str, **kwargs) -> dict[str, Any]:
def build_user_properties(self, user_dn: str, uniq: str, **kwargs) -> dict[str, Any]:
"""Build attributes for User object based on property mappings."""
props = self._build_object_properties(user_dn, self._source.property_mappings, **kwargs)
props = self._build_object_properties(
user_dn, self._source.property_mappings, uniq, **kwargs
)
props.setdefault("path", self._source.get_user_path())
return props
def build_group_properties(self, group_dn: str, **kwargs) -> dict[str, Any]:
def build_group_properties(self, group_dn: str, uniq: str, **kwargs) -> dict[str, Any]:
"""Build attributes for Group object based on property mappings."""
return self._build_object_properties(
group_dn, self._source.property_mappings_group, **kwargs
group_dn, self._source.property_mappings_group, uniq, **kwargs
)
def _build_object_properties(
self, object_dn: str, mappings: QuerySet, **kwargs
self, object_dn: str, mappings: QuerySet, uniq: str, **kwargs
) -> dict[str, dict[Any, Any]]:
properties = {"attributes": {}}
for mapping in mappings.all().select_subclasses():
@ -180,10 +191,7 @@ class BaseLDAPSynchronizer:
).save()
self._logger.warning("Mapping failed to evaluate", exc=exc, mapping=mapping)
continue
if self._source.object_uniqueness_field in kwargs:
properties["attributes"][LDAP_UNIQUENESS] = flatten(
kwargs.get(self._source.object_uniqueness_field)
)
properties["attributes"][LDAP_UNIQUENESS] = uniq
properties["attributes"][LDAP_DISTINGUISHED_NAME] = object_dn
return properties

View File

@ -41,16 +41,16 @@ class GroupLDAPSynchronizer(BaseLDAPSynchronizer):
continue
attributes = group.get("attributes", {})
group_dn = flatten(flatten(group.get("entryDN", group.get("dn"))))
if self._source.object_uniqueness_field not in attributes:
uniq = self.get_unique_identifier(group)
if not uniq:
self.message(
f"Cannot find uniqueness field in attributes: '{group_dn}'",
attributes=attributes.keys(),
dn=group_dn,
)
continue
uniq = flatten(attributes[self._source.object_uniqueness_field])
try:
defaults = self.build_group_properties(group_dn, **attributes)
defaults = self.build_group_properties(group_dn, uniq, **attributes)
defaults["parent"] = self._source.sync_parent_group
if "name" not in defaults:
raise IntegrityError("Name was not set by propertymappings")

View File

@ -4,7 +4,7 @@ from collections.abc import Generator
from typing import Any
from django.db.models import Q
from ldap3 import SUBTREE
from ldap3 import ALL_ATTRIBUTES, ALL_OPERATIONAL_ATTRIBUTES, SUBTREE
from authentik.core.models import Group, User
from authentik.sources.ldap.auth import LDAP_DISTINGUISHED_NAME
@ -33,11 +33,7 @@ class MembershipLDAPSynchronizer(BaseLDAPSynchronizer):
search_base=self.base_dn_groups,
search_filter=self._source.group_object_filter,
search_scope=SUBTREE,
attributes=[
self._source.group_membership_field,
self._source.object_uniqueness_field,
LDAP_DISTINGUISHED_NAME,
],
attributes=[ALL_ATTRIBUTES, ALL_OPERATIONAL_ATTRIBUTES],
**kwargs,
)
@ -80,7 +76,7 @@ class MembershipLDAPSynchronizer(BaseLDAPSynchronizer):
def get_group(self, group_dict: dict[str, Any]) -> Group | None:
"""Check if we fetched the group already, and if not cache it for later"""
group_dn = group_dict.get("attributes", {}).get(LDAP_DISTINGUISHED_NAME, [])
group_uniq = group_dict.get("attributes", {}).get(self._source.object_uniqueness_field, [])
group_uniq = self.get_unique_identifier(group_dict)
# group_uniq might be a single string or an array with (hopefully) a single string
if isinstance(group_uniq, list):
if len(group_uniq) < 1:

View File

@ -43,16 +43,16 @@ class UserLDAPSynchronizer(BaseLDAPSynchronizer):
continue
attributes = user.get("attributes", {})
user_dn = flatten(user.get("entryDN", user.get("dn")))
if self._source.object_uniqueness_field not in attributes:
uniq = self.get_unique_identifier(user)
if not uniq:
self.message(
f"Cannot find uniqueness field in attributes: '{user_dn}'",
attributes=attributes.keys(),
dn=user_dn,
)
continue
uniq = flatten(attributes[self._source.object_uniqueness_field])
try:
defaults = self.build_user_properties(user_dn, **attributes)
defaults = self.build_user_properties(user_dn, uniq, **attributes)
self._logger.debug("Writing user with attributes", **defaults)
if "username" not in defaults:
raise IntegrityError("Username was not set by propertymappings")

View File

@ -41,7 +41,7 @@ def mock_ad_connection(password: str) -> Connection:
connection.strategy.add_entry(
"cn=group2,ou=groups,dc=goauthentik,dc=io",
{
"name": "test-group",
"name": "test-group2",
"objectClass": "group",
"distinguishedName": "cn=group2,ou=groups,dc=goauthentik,dc=io",
},
@ -61,18 +61,6 @@ def mock_ad_connection(password: str) -> Connection:
),
},
)
# User without SID
connection.strategy.add_entry(
"cn=user1,ou=users,dc=goauthentik,dc=io",
{
"userPassword": "test1111",
"sAMAccountName": "user2_sn",
"name": "user1_sn",
"revision": 0,
"objectClass": "person",
"distinguishedName": "cn=user1,ou=users,dc=goauthentik,dc=io",
},
)
# Duplicate users
connection.strategy.add_entry(
"cn=user2,ou=users,dc=goauthentik,dc=io",
@ -87,7 +75,7 @@ def mock_ad_connection(password: str) -> Connection:
},
)
connection.strategy.add_entry(
"cn=user3,ou=users,dc=goauthentik,dc=io",
"cn=user2,ou=users,dc=goauthentik,dc=io",
{
"userPassword": "test2222",
"sAMAccountName": "user2_sn",
@ -95,7 +83,7 @@ def mock_ad_connection(password: str) -> Connection:
"revision": 0,
"objectSid": "unique-test2222",
"objectClass": "person",
"distinguishedName": "cn=user3,ou=users,dc=goauthentik,dc=io",
"distinguishedName": "cn=user2,ou=users,dc=goauthentik,dc=io",
},
)
connection.bind()

View File

@ -108,12 +108,7 @@ class LDAPSyncTests(TestCase):
user = User.objects.create(
username="user0_sn",
attributes={
"ldap_uniq": (
"S-117-6648368-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-"
"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-"
"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-"
"0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0"
),
"ldap_uniq": "cn=user0,ou=foo,ou=users,dc=goauthentik,dc=io",
"foo": "bar",
},
)

View File

@ -80,7 +80,7 @@ class OAuth2Client(BaseOAuthClient):
access_token_url = self.source.source_type.access_token_url or ""
if self.source.source_type.urls_customizable and self.source.access_token_url:
access_token_url = self.source.access_token_url
response = self.do_request(
response = self.session.request(
"post", access_token_url, data=args, headers=self._default_headers, **request_kwargs
)
response.raise_for_status()

View File

@ -1,44 +0,0 @@
# Generated by Django 5.0.4 on 2024-05-01 15:44
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_sources_saml", "0013_samlsource_verification_kp_and_more"),
]
operations = [
migrations.AlterField(
model_name="samlsource",
name="digest_algorithm",
field=models.TextField(
choices=[
("http://www.w3.org/2000/09/xmldsig#sha1", "SHA1"),
("http://www.w3.org/2001/04/xmlenc#sha256", "SHA256"),
("http://www.w3.org/2001/04/xmldsig-more#sha384", "SHA384"),
("http://www.w3.org/2001/04/xmlenc#sha512", "SHA512"),
],
default="http://www.w3.org/2001/04/xmlenc#sha256",
),
),
migrations.AlterField(
model_name="samlsource",
name="signature_algorithm",
field=models.TextField(
choices=[
("http://www.w3.org/2000/09/xmldsig#rsa-sha1", "RSA-SHA1"),
("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256", "RSA-SHA256"),
("http://www.w3.org/2001/04/xmldsig-more#rsa-sha384", "RSA-SHA384"),
("http://www.w3.org/2001/04/xmldsig-more#rsa-sha512", "RSA-SHA512"),
("http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1", "ECDSA-SHA1"),
("http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256", "ECDSA-SHA256"),
("http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384", "ECDSA-SHA384"),
("http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512", "ECDSA-SHA512"),
("http://www.w3.org/2000/09/xmldsig#dsa-sha1", "DSA-SHA1"),
],
default="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256",
),
),
]

View File

@ -15,10 +15,6 @@ from authentik.flows.models import Flow
from authentik.lib.utils.time import timedelta_string_validator
from authentik.sources.saml.processors.constants import (
DSA_SHA1,
ECDSA_SHA1,
ECDSA_SHA256,
ECDSA_SHA384,
ECDSA_SHA512,
RSA_SHA1,
RSA_SHA256,
RSA_SHA384,
@ -147,7 +143,8 @@ class SAMLSource(Source):
verbose_name=_("Signing Keypair"),
)
digest_algorithm = models.TextField(
digest_algorithm = models.CharField(
max_length=50,
choices=(
(SHA1, _("SHA1")),
(SHA256, _("SHA256")),
@ -156,16 +153,13 @@ class SAMLSource(Source):
),
default=SHA256,
)
signature_algorithm = models.TextField(
signature_algorithm = models.CharField(
max_length=50,
choices=(
(RSA_SHA1, _("RSA-SHA1")),
(RSA_SHA256, _("RSA-SHA256")),
(RSA_SHA384, _("RSA-SHA384")),
(RSA_SHA512, _("RSA-SHA512")),
(ECDSA_SHA1, _("ECDSA-SHA1")),
(ECDSA_SHA256, _("ECDSA-SHA256")),
(ECDSA_SHA384, _("ECDSA-SHA384")),
(ECDSA_SHA512, _("ECDSA-SHA512")),
(DSA_SHA1, _("DSA-SHA1")),
),
default=RSA_SHA256,

View File

@ -26,16 +26,9 @@ SAML_BINDING_REDIRECT = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
DSA_SHA1 = "http://www.w3.org/2000/09/xmldsig#dsa-sha1"
RSA_SHA1 = "http://www.w3.org/2000/09/xmldsig#rsa-sha1"
# https://datatracker.ietf.org/doc/html/rfc4051#section-2.3.2
RSA_SHA256 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"
RSA_SHA384 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha384"
RSA_SHA512 = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha512"
# https://datatracker.ietf.org/doc/html/rfc4051#section-2.3.6
ECDSA_SHA1 = "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1"
ECDSA_SHA224 = "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha224"
ECDSA_SHA256 = "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256"
ECDSA_SHA384 = "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384"
ECDSA_SHA512 = "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512"
SHA1 = "http://www.w3.org/2000/09/xmldsig#sha1"
SHA256 = "http://www.w3.org/2001/04/xmlenc#sha256"
@ -48,11 +41,6 @@ SIGN_ALGORITHM_TRANSFORM_MAP = {
RSA_SHA256: xmlsec.constants.TransformRsaSha256,
RSA_SHA384: xmlsec.constants.TransformRsaSha384,
RSA_SHA512: xmlsec.constants.TransformRsaSha512,
ECDSA_SHA1: xmlsec.constants.TransformEcdsaSha1,
ECDSA_SHA224: xmlsec.constants.TransformEcdsaSha224,
ECDSA_SHA256: xmlsec.constants.TransformEcdsaSha256,
ECDSA_SHA384: xmlsec.constants.TransformEcdsaSha384,
ECDSA_SHA512: xmlsec.constants.TransformEcdsaSha512,
}
DIGEST_ALGORITHM_TRANSLATION_MAP = {

View File

@ -60,7 +60,7 @@ class SCIMSourceUser(SerializerModel):
unique_together = (("id", "user", "source"),)
def __str__(self) -> str:
return f"SCIM User {self.user_id} to {self.source_id}"
return f"SCIM User {self.user.username} to {self.source.name}"
class SCIMSourceGroup(SerializerModel):
@ -81,4 +81,4 @@ class SCIMSourceGroup(SerializerModel):
unique_together = (("id", "group", "source"),)
def __str__(self) -> str:
return f"SCIM Group {self.group_id} to {self.source_id}"
return f"SCIM Group {self.group.name} to {self.source.name}"

View File

@ -2,11 +2,9 @@ from django.db.models import Model
from django.db.models.signals import pre_delete, pre_save
from django.dispatch import receiver
from authentik.core.models import USER_PATH_SYSTEM_PREFIX, Token, TokenIntents, User, UserTypes
from authentik.core.models import Token, TokenIntents, User, UserTypes
from authentik.sources.scim.models import SCIMSource
USER_PATH_SOURCE_SCIM = USER_PATH_SYSTEM_PREFIX + "/sources/scim"
@receiver(pre_save, sender=SCIMSource)
def scim_source_pre_save(sender: type[Model], instance: SCIMSource, **_):
@ -18,7 +16,6 @@ def scim_source_pre_save(sender: type[Model], instance: SCIMSource, **_):
username=identifier,
name=f"SCIM Source {instance.name} Service-Account",
type=UserTypes.INTERNAL_SERVICE_ACCOUNT,
path=USER_PATH_SOURCE_SCIM,
)
token = Token.objects.create(
user=user,

View File

@ -96,7 +96,7 @@ class DuoDevice(SerializerModel, Device):
return DuoDeviceSerializer
def __str__(self):
return str(self.name) or str(self.user_id)
return str(self.name) or str(self.user)
class Meta:
verbose_name = _("Duo Device")

View File

@ -221,7 +221,7 @@ class SMSDevice(SerializerModel, SideChannelDevice):
return valid
def __str__(self):
return str(self.name) or str(self.user_id)
return str(self.name) or str(self.user)
class Meta:
verbose_name = _("SMS Device")

File diff suppressed because one or more lines are too long

View File

@ -155,7 +155,7 @@ class WebAuthnDevice(SerializerModel, Device):
return WebAuthnDeviceSerializer
def __str__(self):
return str(self.name) or str(self.user_id)
return str(self.name) or str(self.user)
class Meta:
verbose_name = _("WebAuthn Device")

View File

@ -65,7 +65,7 @@ class UserConsent(SerializerModel, ExpiringModel):
return UserConsentSerializer
def __str__(self):
return f"User Consent {self.application_id} by {self.user_id}"
return f"User Consent {self.application} by {self.user}"
class Meta:
unique_together = (("user", "application", "permissions"),)

View File

@ -79,7 +79,7 @@ class Invitation(SerializerModel, ExpiringModel):
return InvitationSerializer
def __str__(self):
return f"Invitation {str(self.invite_uuid)} created by {self.created_by_id}"
return f"Invitation {str(self.invite_uuid)} created by {self.created_by}"
class Meta:
verbose_name = _("Invitation")

View File

@ -1,23 +0,0 @@
# Generated by Django 5.0.4 on 2024-05-01 15:32
import authentik.lib.utils.time
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("authentik_tenants", "0002_tenant_default_token_duration_and_more"),
]
operations = [
migrations.AlterField(
model_name="tenant",
name="default_token_duration",
field=models.TextField(
default="days=1",
help_text="Default token duration",
validators=[authentik.lib.utils.time.timedelta_string_validator],
),
),
]

View File

@ -2,7 +2,7 @@
"$schema": "http://json-schema.org/draft-07/schema",
"$id": "https://goauthentik.io/blueprints/schema.json",
"type": "object",
"title": "authentik 2024.4.1 Blueprint schema",
"title": "authentik 2024.4.0 Blueprint schema",
"required": [
"version",
"entries"
@ -4131,10 +4131,6 @@
"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256",
"http://www.w3.org/2001/04/xmldsig-more#rsa-sha384",
"http://www.w3.org/2001/04/xmldsig-more#rsa-sha512",
"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1",
"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256",
"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384",
"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512",
"http://www.w3.org/2000/09/xmldsig#dsa-sha1"
],
"title": "Signature algorithm"
@ -4939,10 +4935,6 @@
"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256",
"http://www.w3.org/2001/04/xmldsig-more#rsa-sha384",
"http://www.w3.org/2001/04/xmldsig-more#rsa-sha512",
"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1",
"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256",
"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384",
"http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512",
"http://www.w3.org/2000/09/xmldsig#dsa-sha1"
],
"title": "Signature algorithm"

View File

@ -32,7 +32,7 @@ services:
volumes:
- redis:/data
server:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2024.4.1}
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2024.4.0}
restart: unless-stopped
command: server
environment:
@ -53,7 +53,7 @@ services:
- postgresql
- redis
worker:
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2024.4.1}
image: ${AUTHENTIK_IMAGE:-ghcr.io/goauthentik/server}:${AUTHENTIK_TAG:-2024.4.0}
restart: unless-stopped
command: worker
environment:

2
go.mod
View File

@ -28,7 +28,7 @@ require (
github.com/spf13/cobra v1.8.0
github.com/stretchr/testify v1.9.0
github.com/wwt/guac v1.3.2
goauthentik.io/api/v3 v3.2024041.2
goauthentik.io/api/v3 v3.2024040.1
golang.org/x/exp v0.0.0-20230210204819-062eb4c674ab
golang.org/x/oauth2 v0.19.0
golang.org/x/sync v0.7.0

4
go.sum
View File

@ -294,8 +294,8 @@ go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4=
goauthentik.io/api/v3 v3.2024041.2 h1:gbquIA8RU+9jJbFdGckQTtJzOfWVp2+QdF4LuNVTAWM=
goauthentik.io/api/v3 v3.2024041.2/go.mod h1:zz+mEZg8rY/7eEjkMGWJ2DnGqk+zqxuybGCGrR2O4Kw=
goauthentik.io/api/v3 v3.2024040.1 h1:0Mp8XLYuscQEWVTR2lNk74WLKDpOVHX0mlbvbvcC6fw=
goauthentik.io/api/v3 v3.2024040.1/go.mod h1:zz+mEZg8rY/7eEjkMGWJ2DnGqk+zqxuybGCGrR2O4Kw=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=

View File

@ -29,4 +29,4 @@ func UserAgent() string {
return fmt.Sprintf("authentik@%s", FullVersion())
}
const VERSION = "2024.4.1"
const VERSION = "2024.4.0"

View File

@ -117,8 +117,6 @@ def run_migrations():
)
finally:
release_lock(curr)
curr.close()
conn.close()
if __name__ == "__main__":

View File

@ -3,6 +3,7 @@
import authentik. This is done by the dockerfile."""
from sys import exit as sysexit
from time import sleep
from urllib.parse import quote_plus
from psycopg import OperationalError, connect
from redis import Redis
@ -34,7 +35,7 @@ def check_postgres():
def check_redis():
url = CONFIG.get("cache.url") or redis_url(CONFIG.get("redis.db"))
url = redis_url(CONFIG.get("redis.db"))
while True:
try:
redis = Redis.from_url(url)
@ -42,7 +43,10 @@ def check_redis():
break
except RedisError as exc:
sleep(1)
CONFIG.log("info", f"Redis Connection failed, retrying... ({exc})")
sanitized_url = url.replace(quote_plus(CONFIG.get("redis.password")), "******")
CONFIG.log(
"info", f"Redis Connection failed, retrying... ({exc})", redis_url=sanitized_url
)
CONFIG.log("info", "Redis Connection successful")

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-05-03 00:08+0000\n"
"POT-Creation-Date: 2024-04-16 00:07+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -363,14 +363,6 @@ msgstr ""
msgid "Subject-alt name"
msgstr ""
#: authentik/crypto/builder.py
msgid "rsa"
msgstr ""
#: authentik/crypto/builder.py
msgid "ecdsa"
msgstr ""
#: authentik/crypto/models.py
msgid "PEM-encoded Certificate data"
msgstr ""
@ -1557,22 +1549,6 @@ msgstr ""
msgid "RSA-SHA512"
msgstr ""
#: authentik/providers/saml/models.py authentik/sources/saml/models.py
msgid "ECDSA-SHA1"
msgstr ""
#: authentik/providers/saml/models.py authentik/sources/saml/models.py
msgid "ECDSA-SHA256"
msgstr ""
#: authentik/providers/saml/models.py authentik/sources/saml/models.py
msgid "ECDSA-SHA384"
msgstr ""
#: authentik/providers/saml/models.py authentik/sources/saml/models.py
msgid "ECDSA-SHA512"
msgstr ""
#: authentik/providers/saml/models.py authentik/sources/saml/models.py
msgid "DSA-SHA1"
msgstr ""

Binary file not shown.

Binary file not shown.

2030
poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
# syntax=docker/dockerfile:1
# Stage 1: Build website
FROM --platform=${BUILDPLATFORM} docker.io/node:22 as web-builder
FROM --platform=${BUILDPLATFORM} docker.io/node:21 as web-builder
ENV NODE_ENV=production
WORKDIR /static

View File

@ -1,6 +1,6 @@
[tool.poetry]
name = "authentik"
version = "2024.4.1"
version = "2024.4.0"
description = ""
authors = ["authentik Team <hello@goauthentik.io>"]
@ -89,7 +89,6 @@ channels = { version = "*", extras = ["daphne"] }
channels-redis = "*"
codespell = "*"
colorama = "*"
cryptography = "*"
dacite = "*"
deepmerge = "*"
defusedxml = "*"
@ -102,7 +101,7 @@ django-redis = "*"
django-storages = { extras = ["s3"], version = "*" }
# See https://github.com/django-tenants/django-tenants/pull/997
django-tenants = { git = "https://github.com/rissson/django-tenants.git", branch="authentik-fixes" }
djangorestframework = "3.14.0"
djangorestframework = "*"
djangorestframework-guardian = "*"
docker = "*"
drf-spectacular = "*"
@ -116,11 +115,17 @@ gunicorn = "*"
jsonpatch = "*"
kubernetes = "*"
ldap3 = "*"
lxml = "*"
lxml = [
# 5.0.0 works with libxml2 2.11.x, which is standard on brew
{ version = "5.0.0", platform = "darwin" },
# 4.9.x works with previous libxml2 versions, which is what we get on linux
{ version = "4.9.4", platform = "linux" },
]
opencontainers = { extras = ["reggie"], version = "*" }
packaging = "*"
paramiko = "*"
psycopg = { extras = ["c"], version = "*" }
pycryptodome = "*"
pydantic = "*"
pydantic-scim = "*"
pyjwt = "*"

View File

@ -18,7 +18,7 @@ RUN --mount=type=cache,sharing=locked,target=/go/pkg/mod \
go build -o /go/rac ./cmd/rac
# Stage 2: Run
FROM ghcr.io/beryju/guacd:1.5.5
FROM ghcr.io/beryju/guacd:1.5.3
ARG GIT_BUILD_HASH
ENV GIT_BUILD_HASH=$GIT_BUILD_HASH

View File

@ -1,7 +1,7 @@
openapi: 3.0.3
info:
title: authentik
version: 2024.4.1
version: 2024.4.0
description: Making authentication simple.
contact:
email: hello@goauthentik.io
@ -17051,10 +17051,6 @@ paths:
enum:
- http://www.w3.org/2000/09/xmldsig#dsa-sha1
- http://www.w3.org/2000/09/xmldsig#rsa-sha1
- http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1
- http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256
- http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384
- http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512
- http://www.w3.org/2001/04/xmldsig-more#rsa-sha256
- http://www.w3.org/2001/04/xmldsig-more#rsa-sha384
- http://www.w3.org/2001/04/xmldsig-more#rsa-sha512
@ -20914,10 +20910,6 @@ paths:
enum:
- http://www.w3.org/2000/09/xmldsig#dsa-sha1
- http://www.w3.org/2000/09/xmldsig#rsa-sha1
- http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1
- http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256
- http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384
- http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512
- http://www.w3.org/2001/04/xmldsig-more#rsa-sha256
- http://www.w3.org/2001/04/xmldsig-more#rsa-sha384
- http://www.w3.org/2001/04/xmldsig-more#rsa-sha512
@ -30458,11 +30450,6 @@ components:
- pending_user
- pending_user_avatar
- type
AlgEnum:
enum:
- rsa
- ecdsa
type: string
App:
type: object
description: Serialize Application info
@ -32120,10 +32107,6 @@ components:
type: string
validity_days:
type: integer
alg:
allOf:
- $ref: '#/components/schemas/AlgEnum'
default: rsa
required:
- common_name
- validity_days
@ -43675,10 +43658,6 @@ components:
- http://www.w3.org/2001/04/xmldsig-more#rsa-sha256
- http://www.w3.org/2001/04/xmldsig-more#rsa-sha384
- http://www.w3.org/2001/04/xmldsig-more#rsa-sha512
- http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1
- http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256
- http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha384
- http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha512
- http://www.w3.org/2000/09/xmldsig#dsa-sha1
type: string
Source:

File diff suppressed because it is too large Load Diff

View File

@ -32,6 +32,6 @@
"node": ">=20"
},
"dependencies": {
"chromedriver": "^124.0.1"
"chromedriver": "^123.0.4"
}
}

439
web/package-lock.json generated
View File

@ -11,13 +11,13 @@
"dependencies": {
"@codemirror/lang-html": "^6.4.9",
"@codemirror/lang-javascript": "^6.2.2",
"@codemirror/lang-python": "^6.1.6",
"@codemirror/lang-python": "^6.1.5",
"@codemirror/lang-xml": "^6.1.0",
"@codemirror/legacy-modes": "^6.4.0",
"@codemirror/theme-one-dark": "^6.1.2",
"@formatjs/intl-listformat": "^7.5.5",
"@fortawesome/fontawesome-free": "^6.5.2",
"@goauthentik/api": "^2024.4.1-1714655911",
"@goauthentik/api": "^2024.4.0-1713978791",
"@lit-labs/task": "^3.1.0",
"@lit/context": "^1.1.1",
"@lit/localize": "^0.12.1",
@ -25,7 +25,7 @@
"@open-wc/lit-helpers": "^0.7.0",
"@patternfly/elements": "^3.0.1",
"@patternfly/patternfly": "^4.224.2",
"@sentry/browser": "^7.113.0",
"@sentry/browser": "^7.112.2",
"@webcomponents/webcomponentsjs": "^2.8.0",
"base64-js": "^1.5.1",
"chart.js": "^4.4.2",
@ -44,16 +44,16 @@
"style-mod": "^4.1.2",
"ts-pattern": "^5.1.1",
"webcomponent-qr-code": "^1.2.0",
"yaml": "^2.4.2"
"yaml": "^2.4.1"
},
"devDependencies": {
"@babel/core": "^7.24.5",
"@babel/core": "^7.24.4",
"@babel/plugin-proposal-class-properties": "^7.18.6",
"@babel/plugin-proposal-decorators": "^7.24.1",
"@babel/plugin-transform-private-methods": "^7.24.1",
"@babel/plugin-transform-private-property-in-object": "^7.24.5",
"@babel/plugin-transform-private-property-in-object": "^7.24.1",
"@babel/plugin-transform-runtime": "^7.24.3",
"@babel/preset-env": "^7.24.5",
"@babel/preset-env": "^7.24.4",
"@babel/preset-typescript": "^7.24.1",
"@hcaptcha/types": "^1.0.3",
"@jeysal/storybook-addon-css-user-preferences": "^0.2.0",
@ -93,7 +93,7 @@
"prettier": "^3.2.5",
"pseudolocale": "^2.0.0",
"react": "^18.2.0",
"react-dom": "^18.3.1",
"react-dom": "^18.2.0",
"rollup-plugin-modify": "^3.0.0",
"rollup-plugin-postcss-lit": "^2.1.0",
"storybook": "^8.0.9",
@ -111,9 +111,9 @@
"@esbuild/darwin-arm64": "^0.20.1",
"@esbuild/linux-amd64": "^0.18.11",
"@esbuild/linux-arm64": "^0.20.1",
"@rollup/rollup-darwin-arm64": "4.17.2",
"@rollup/rollup-linux-arm64-gnu": "4.17.2",
"@rollup/rollup-linux-x64-gnu": "4.17.2"
"@rollup/rollup-darwin-arm64": "4.16.4",
"@rollup/rollup-linux-arm64-gnu": "4.16.4",
"@rollup/rollup-linux-x64-gnu": "4.16.4"
}
},
"node_modules/@aashutoshrathi/word-wrap": {
@ -185,21 +185,21 @@
}
},
"node_modules/@babel/core": {
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.5.tgz",
"integrity": "sha512-tVQRucExLQ02Boi4vdPp49svNGcfL2GhdTCT9aldhXgCJVAI21EtRfBettiuLUwce/7r6bFdgs6JFkcdTiFttA==",
"version": "7.24.4",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.4.tgz",
"integrity": "sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==",
"dev": true,
"dependencies": {
"@ampproject/remapping": "^2.2.0",
"@babel/code-frame": "^7.24.2",
"@babel/generator": "^7.24.5",
"@babel/generator": "^7.24.4",
"@babel/helper-compilation-targets": "^7.23.6",
"@babel/helper-module-transforms": "^7.24.5",
"@babel/helpers": "^7.24.5",
"@babel/parser": "^7.24.5",
"@babel/helper-module-transforms": "^7.23.3",
"@babel/helpers": "^7.24.4",
"@babel/parser": "^7.24.4",
"@babel/template": "^7.24.0",
"@babel/traverse": "^7.24.5",
"@babel/types": "^7.24.5",
"@babel/traverse": "^7.24.1",
"@babel/types": "^7.24.0",
"convert-source-map": "^2.0.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.2",
@ -215,12 +215,12 @@
}
},
"node_modules/@babel/generator": {
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.5.tgz",
"integrity": "sha512-x32i4hEXvr+iI0NEoEfDKzlemF8AmtOP8CcrRaEcpzysWuoEb1KknpcvMsHKPONoKZiDuItklgWhB18xEhr9PA==",
"version": "7.24.4",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.4.tgz",
"integrity": "sha512-Xd6+v6SnjWVx/nus+y0l1sxMOTOMBkyL4+BIdbALyatQnAe/SRVjANeDPSCYaX+i1iJmuGSKf3Z+E+V/va1Hvw==",
"dev": true,
"dependencies": {
"@babel/types": "^7.24.5",
"@babel/types": "^7.24.0",
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.25",
"jsesc": "^2.5.1"
@ -272,19 +272,19 @@
}
},
"node_modules/@babel/helper-create-class-features-plugin": {
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.5.tgz",
"integrity": "sha512-uRc4Cv8UQWnE4NXlYTIIdM7wfFkOqlFztcC/gVXDKohKoVB3OyonfelUBaJzSwpBntZ2KYGF/9S7asCHsXwW6g==",
"version": "7.24.4",
"resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.4.tgz",
"integrity": "sha512-lG75yeuUSVu0pIcbhiYMXBXANHrpUPaOfu7ryAzskCgKUHuAxRQI5ssrtmF0X9UXldPlvT0XM/A4F44OXRt6iQ==",
"dev": true,
"dependencies": {
"@babel/helper-annotate-as-pure": "^7.22.5",
"@babel/helper-environment-visitor": "^7.22.20",
"@babel/helper-function-name": "^7.23.0",
"@babel/helper-member-expression-to-functions": "^7.24.5",
"@babel/helper-member-expression-to-functions": "^7.23.0",
"@babel/helper-optimise-call-expression": "^7.22.5",
"@babel/helper-replace-supers": "^7.24.1",
"@babel/helper-skip-transparent-expression-wrappers": "^7.22.5",
"@babel/helper-split-export-declaration": "^7.24.5",
"@babel/helper-split-export-declaration": "^7.22.6",
"semver": "^6.3.1"
},
"engines": {
@ -366,12 +366,13 @@
}
},
"node_modules/@babel/helper-member-expression-to-functions": {
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.5.tgz",
"integrity": "sha512-4owRteeihKWKamtqg4JmWSsEZU445xpFRXPEwp44HbgbxdWlUV1b4Agg4lkA806Lil5XM/e+FJyS0vj5T6vmcA==",
"version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz",
"integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/types": "^7.24.5"
"@babel/types": "^7.23.0"
},
"engines": {
"node": ">=6.9.0"
@ -390,16 +391,17 @@
}
},
"node_modules/@babel/helper-module-transforms": {
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.5.tgz",
"integrity": "sha512-9GxeY8c2d2mdQUP1Dye0ks3VDyIMS98kt/llQ2nUId8IsWqTF0l1LkSX0/uP7l7MCDrzXS009Hyhe2gzTiGW8A==",
"version": "7.23.3",
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz",
"integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/helper-environment-visitor": "^7.22.20",
"@babel/helper-module-imports": "^7.24.3",
"@babel/helper-simple-access": "^7.24.5",
"@babel/helper-split-export-declaration": "^7.24.5",
"@babel/helper-validator-identifier": "^7.24.5"
"@babel/helper-module-imports": "^7.22.15",
"@babel/helper-simple-access": "^7.22.5",
"@babel/helper-split-export-declaration": "^7.22.6",
"@babel/helper-validator-identifier": "^7.22.20"
},
"engines": {
"node": ">=6.9.0"
@ -422,10 +424,11 @@
}
},
"node_modules/@babel/helper-plugin-utils": {
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.5.tgz",
"integrity": "sha512-xjNLDopRzW2o6ba0gKbkZq5YWEBaK3PCyTOY1K2P/O07LGMhMqlMXPxwN4S5/RhWuCobT8z0jrlKGlYmeR1OhQ==",
"version": "7.24.0",
"resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz",
"integrity": "sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6.9.0"
}
@ -465,12 +468,13 @@
}
},
"node_modules/@babel/helper-simple-access": {
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.5.tgz",
"integrity": "sha512-uH3Hmf5q5n7n8mz7arjUlDOCbttY/DW4DYhE6FUsjKJ/oYC1kQQUvwEQWxRwUpX9qQKRXeqLwWxrqilMrf32sQ==",
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz",
"integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/types": "^7.24.5"
"@babel/types": "^7.22.5"
},
"engines": {
"node": ">=6.9.0"
@ -490,31 +494,34 @@
}
},
"node_modules/@babel/helper-split-export-declaration": {
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.5.tgz",
"integrity": "sha512-5CHncttXohrHk8GWOFCcCl4oRD9fKosWlIRgWm4ql9VYioKm52Mk2xsmoohvm7f3JoiLSM5ZgJuRaf5QZZYd3Q==",
"version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
"integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/types": "^7.24.5"
"@babel/types": "^7.22.5"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-string-parser": {
"version": "7.24.1",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz",
"integrity": "sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==",
"version": "7.23.4",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz",
"integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-validator-identifier": {
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz",
"integrity": "sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==",
"version": "7.22.20",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
"integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6.9.0"
}
@ -544,14 +551,14 @@
}
},
"node_modules/@babel/helpers": {
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.5.tgz",
"integrity": "sha512-CiQmBMMpMQHwM5m01YnrM6imUG1ebgYJ+fAIW4FZe6m4qHTPaRHti+R8cggAwkdz4oXhtO4/K9JWlh+8hIfR2Q==",
"version": "7.24.4",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.4.tgz",
"integrity": "sha512-FewdlZbSiwaVGlgT1DPANDuCHaDMiOo+D/IDYRFYjHOuv66xMSJ7fQwwODwRNAPkADIO/z1EoF/l2BCWlWABDw==",
"dev": true,
"dependencies": {
"@babel/template": "^7.24.0",
"@babel/traverse": "^7.24.5",
"@babel/types": "^7.24.5"
"@babel/traverse": "^7.24.1",
"@babel/types": "^7.24.0"
},
"engines": {
"node": ">=6.9.0"
@ -573,9 +580,9 @@
}
},
"node_modules/@babel/parser": {
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.5.tgz",
"integrity": "sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==",
"version": "7.24.4",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.4.tgz",
"integrity": "sha512-zTvEBcghmeBma9QIGunWevvBAp4/Qu9Bdq+2k0Ot4fVMD6v3dsC9WOcRSKk7tRRyBM/53yKMJko9xOatGQAwSg==",
"dev": true,
"bin": {
"parser": "bin/babel-parser.js"
@ -585,13 +592,13 @@
}
},
"node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": {
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.5.tgz",
"integrity": "sha512-LdXRi1wEMTrHVR4Zc9F8OewC3vdm5h4QB6L71zy6StmYeqGi1b3ttIO8UC+BfZKcH9jdr4aI249rBkm+3+YvHw==",
"version": "7.24.4",
"resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.4.tgz",
"integrity": "sha512-qpl6vOOEEzTLLcsuqYYo8yDtrTocmu2xkGvgNebvPjT9DTtfFYGmgDqY+rBYXNlqL4s9qLDn6xkrJv4RxAPiTA==",
"dev": true,
"dependencies": {
"@babel/helper-environment-visitor": "^7.22.20",
"@babel/helper-plugin-utils": "^7.24.5"
"@babel/helper-plugin-utils": "^7.24.0"
},
"engines": {
"node": ">=6.9.0"
@ -1063,12 +1070,12 @@
}
},
"node_modules/@babel/plugin-transform-block-scoping": {
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.5.tgz",
"integrity": "sha512-sMfBc3OxghjC95BkYrYocHL3NaOplrcaunblzwXhGmlPwpmfsxr4vK+mBBt49r+S240vahmv+kUxkeKgs+haCw==",
"version": "7.24.4",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.4.tgz",
"integrity": "sha512-nIFUZIpGKDf9O9ttyRXpHFpKC+X3Y5mtshZONuEUYBomAKoM4y029Jr+uB1bHGPhNmK8YXHevDtKDOLmtRrp6g==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.24.5"
"@babel/helper-plugin-utils": "^7.24.0"
},
"engines": {
"node": ">=6.9.0"
@ -1111,18 +1118,18 @@
}
},
"node_modules/@babel/plugin-transform-classes": {
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.5.tgz",
"integrity": "sha512-gWkLP25DFj2dwe9Ck8uwMOpko4YsqyfZJrOmqqcegeDYEbp7rmn4U6UQZNj08UF6MaX39XenSpKRCvpDRBtZ7Q==",
"version": "7.24.1",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.1.tgz",
"integrity": "sha512-ZTIe3W7UejJd3/3R4p7ScyyOoafetUShSf4kCqV0O7F/RiHxVj/wRaRnQlrGwflvcehNA8M42HkAiEDYZu2F1Q==",
"dev": true,
"dependencies": {
"@babel/helper-annotate-as-pure": "^7.22.5",
"@babel/helper-compilation-targets": "^7.23.6",
"@babel/helper-environment-visitor": "^7.22.20",
"@babel/helper-function-name": "^7.23.0",
"@babel/helper-plugin-utils": "^7.24.5",
"@babel/helper-plugin-utils": "^7.24.0",
"@babel/helper-replace-supers": "^7.24.1",
"@babel/helper-split-export-declaration": "^7.24.5",
"@babel/helper-split-export-declaration": "^7.22.6",
"globals": "^11.1.0"
},
"engines": {
@ -1149,12 +1156,12 @@
}
},
"node_modules/@babel/plugin-transform-destructuring": {
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.5.tgz",
"integrity": "sha512-SZuuLyfxvsm+Ah57I/i1HVjveBENYK9ue8MJ7qkc7ndoNjqquJiElzA7f5yaAXjyW2hKojosOTAQQRX50bPSVg==",
"version": "7.24.1",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.1.tgz",
"integrity": "sha512-ow8jciWqNxR3RYbSNVuF4U2Jx130nwnBnhRw6N6h1bOejNkABmcI5X5oz29K4alWX7vf1C+o6gtKXikzRKkVdw==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.24.5"
"@babel/helper-plugin-utils": "^7.24.0"
},
"engines": {
"node": ">=6.9.0"
@ -1485,15 +1492,15 @@
}
},
"node_modules/@babel/plugin-transform-object-rest-spread": {
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.5.tgz",
"integrity": "sha512-7EauQHszLGM3ay7a161tTQH7fj+3vVM/gThlz5HpFtnygTxjrlvoeq7MPVA1Vy9Q555OB8SnAOsMkLShNkkrHA==",
"version": "7.24.1",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.1.tgz",
"integrity": "sha512-XjD5f0YqOtebto4HGISLNfiNMTTs6tbkFf2TOqJlYKYmbo+mN9Dnpl4SRoofiziuOWMIyq3sZEUqLo3hLITFEA==",
"dev": true,
"dependencies": {
"@babel/helper-compilation-targets": "^7.23.6",
"@babel/helper-plugin-utils": "^7.24.5",
"@babel/helper-plugin-utils": "^7.24.0",
"@babel/plugin-syntax-object-rest-spread": "^7.8.3",
"@babel/plugin-transform-parameters": "^7.24.5"
"@babel/plugin-transform-parameters": "^7.24.1"
},
"engines": {
"node": ">=6.9.0"
@ -1535,12 +1542,12 @@
}
},
"node_modules/@babel/plugin-transform-optional-chaining": {
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.5.tgz",
"integrity": "sha512-xWCkmwKT+ihmA6l7SSTpk8e4qQl/274iNbSKRRS8mpqFR32ksy36+a+LWY8OXCCEefF8WFlnOHVsaDI2231wBg==",
"version": "7.24.1",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.1.tgz",
"integrity": "sha512-n03wmDt+987qXwAgcBlnUUivrZBPZ8z1plL0YvgQalLm+ZE5BMhGm94jhxXtA1wzv1Cu2aaOv1BM9vbVttrzSg==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.24.5",
"@babel/helper-plugin-utils": "^7.24.0",
"@babel/helper-skip-transparent-expression-wrappers": "^7.22.5",
"@babel/plugin-syntax-optional-chaining": "^7.8.3"
},
@ -1552,12 +1559,12 @@
}
},
"node_modules/@babel/plugin-transform-parameters": {
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.5.tgz",
"integrity": "sha512-9Co00MqZ2aoky+4j2jhofErthm6QVLKbpQrvz20c3CH9KQCLHyNB+t2ya4/UrRpQGR+Wrwjg9foopoeSdnHOkA==",
"version": "7.24.1",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.1.tgz",
"integrity": "sha512-8Jl6V24g+Uw5OGPeWNKrKqXPDw2YDjLc53ojwfMcKwlEoETKU9rU0mHUtcg9JntWI/QYzGAXNWEcVHZ+fR+XXg==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.24.5"
"@babel/helper-plugin-utils": "^7.24.0"
},
"engines": {
"node": ">=6.9.0"
@ -1583,14 +1590,14 @@
}
},
"node_modules/@babel/plugin-transform-private-property-in-object": {
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.5.tgz",
"integrity": "sha512-JM4MHZqnWR04jPMujQDTBVRnqxpLLpx2tkn7iPn+Hmsc0Gnb79yvRWOkvqFOx3Z7P7VxiRIR22c4eGSNj87OBQ==",
"version": "7.24.1",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.1.tgz",
"integrity": "sha512-pTHxDVa0BpUbvAgX3Gat+7cSciXqUcY9j2VZKTbSB6+VQGpNgNO9ailxTGHSXlqOnX1Hcx1Enme2+yv7VqP9bg==",
"dev": true,
"dependencies": {
"@babel/helper-annotate-as-pure": "^7.22.5",
"@babel/helper-create-class-features-plugin": "^7.24.5",
"@babel/helper-plugin-utils": "^7.24.5",
"@babel/helper-create-class-features-plugin": "^7.24.1",
"@babel/helper-plugin-utils": "^7.24.0",
"@babel/plugin-syntax-private-property-in-object": "^7.14.5"
},
"engines": {
@ -1728,12 +1735,12 @@
}
},
"node_modules/@babel/plugin-transform-typeof-symbol": {
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.5.tgz",
"integrity": "sha512-UTGnhYVZtTAjdwOTzT+sCyXmTn8AhaxOS/MjG9REclZ6ULHWF9KoCZur0HSGU7hk8PdBFKKbYe6+gqdXWz84Jg==",
"version": "7.24.1",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.1.tgz",
"integrity": "sha512-CBfU4l/A+KruSUoW+vTQthwcAdwuqbpRNB8HQKlZABwHRhsdHZ9fezp4Sn18PeAlYxTNiLMlx4xUBV3AWfg1BA==",
"dev": true,
"dependencies": {
"@babel/helper-plugin-utils": "^7.24.5"
"@babel/helper-plugin-utils": "^7.24.0"
},
"engines": {
"node": ">=6.9.0"
@ -1824,16 +1831,16 @@
}
},
"node_modules/@babel/preset-env": {
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.5.tgz",
"integrity": "sha512-UGK2ifKtcC8i5AI4cH+sbLLuLc2ktYSFJgBAXorKAsHUZmrQ1q6aQ6i3BvU24wWs2AAKqQB6kq3N9V9Gw1HiMQ==",
"version": "7.24.4",
"resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.24.4.tgz",
"integrity": "sha512-7Kl6cSmYkak0FK/FXjSEnLJ1N9T/WA2RkMhu17gZ/dsxKJUuTYNIylahPTzqpLyJN4WhDif8X0XK1R8Wsguo/A==",
"dev": true,
"dependencies": {
"@babel/compat-data": "^7.24.4",
"@babel/helper-compilation-targets": "^7.23.6",
"@babel/helper-plugin-utils": "^7.24.5",
"@babel/helper-plugin-utils": "^7.24.0",
"@babel/helper-validator-option": "^7.23.5",
"@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.24.5",
"@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.24.4",
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.24.1",
"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.1",
"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.24.1",
@ -1860,12 +1867,12 @@
"@babel/plugin-transform-async-generator-functions": "^7.24.3",
"@babel/plugin-transform-async-to-generator": "^7.24.1",
"@babel/plugin-transform-block-scoped-functions": "^7.24.1",
"@babel/plugin-transform-block-scoping": "^7.24.5",
"@babel/plugin-transform-block-scoping": "^7.24.4",
"@babel/plugin-transform-class-properties": "^7.24.1",
"@babel/plugin-transform-class-static-block": "^7.24.4",
"@babel/plugin-transform-classes": "^7.24.5",
"@babel/plugin-transform-classes": "^7.24.1",
"@babel/plugin-transform-computed-properties": "^7.24.1",
"@babel/plugin-transform-destructuring": "^7.24.5",
"@babel/plugin-transform-destructuring": "^7.24.1",
"@babel/plugin-transform-dotall-regex": "^7.24.1",
"@babel/plugin-transform-duplicate-keys": "^7.24.1",
"@babel/plugin-transform-dynamic-import": "^7.24.1",
@ -1885,13 +1892,13 @@
"@babel/plugin-transform-new-target": "^7.24.1",
"@babel/plugin-transform-nullish-coalescing-operator": "^7.24.1",
"@babel/plugin-transform-numeric-separator": "^7.24.1",
"@babel/plugin-transform-object-rest-spread": "^7.24.5",
"@babel/plugin-transform-object-rest-spread": "^7.24.1",
"@babel/plugin-transform-object-super": "^7.24.1",
"@babel/plugin-transform-optional-catch-binding": "^7.24.1",
"@babel/plugin-transform-optional-chaining": "^7.24.5",
"@babel/plugin-transform-parameters": "^7.24.5",
"@babel/plugin-transform-optional-chaining": "^7.24.1",
"@babel/plugin-transform-parameters": "^7.24.1",
"@babel/plugin-transform-private-methods": "^7.24.1",
"@babel/plugin-transform-private-property-in-object": "^7.24.5",
"@babel/plugin-transform-private-property-in-object": "^7.24.1",
"@babel/plugin-transform-property-literals": "^7.24.1",
"@babel/plugin-transform-regenerator": "^7.24.1",
"@babel/plugin-transform-reserved-words": "^7.24.1",
@ -1899,7 +1906,7 @@
"@babel/plugin-transform-spread": "^7.24.1",
"@babel/plugin-transform-sticky-regex": "^7.24.1",
"@babel/plugin-transform-template-literals": "^7.24.1",
"@babel/plugin-transform-typeof-symbol": "^7.24.5",
"@babel/plugin-transform-typeof-symbol": "^7.24.1",
"@babel/plugin-transform-unicode-escapes": "^7.24.1",
"@babel/plugin-transform-unicode-property-regex": "^7.24.1",
"@babel/plugin-transform-unicode-regex": "^7.24.1",
@ -2155,19 +2162,19 @@
}
},
"node_modules/@babel/traverse": {
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.5.tgz",
"integrity": "sha512-7aaBLeDQ4zYcUFDUD41lJc1fG8+5IU9DaNSJAgal866FGvmD5EbWQgnEC6kO1gGLsX0esNkfnJSndbTXA3r7UA==",
"version": "7.24.1",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.1.tgz",
"integrity": "sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==",
"dev": true,
"dependencies": {
"@babel/code-frame": "^7.24.2",
"@babel/generator": "^7.24.5",
"@babel/code-frame": "^7.24.1",
"@babel/generator": "^7.24.1",
"@babel/helper-environment-visitor": "^7.22.20",
"@babel/helper-function-name": "^7.23.0",
"@babel/helper-hoist-variables": "^7.22.5",
"@babel/helper-split-export-declaration": "^7.24.5",
"@babel/parser": "^7.24.5",
"@babel/types": "^7.24.5",
"@babel/helper-split-export-declaration": "^7.22.6",
"@babel/parser": "^7.24.1",
"@babel/types": "^7.24.0",
"debug": "^4.3.1",
"globals": "^11.1.0"
},
@ -2176,13 +2183,14 @@
}
},
"node_modules/@babel/types": {
"version": "7.24.5",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.5.tgz",
"integrity": "sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ==",
"version": "7.24.0",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.0.tgz",
"integrity": "sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/helper-string-parser": "^7.24.1",
"@babel/helper-validator-identifier": "^7.24.5",
"@babel/helper-string-parser": "^7.23.4",
"@babel/helper-validator-identifier": "^7.22.20",
"to-fast-properties": "^2.0.0"
},
"engines": {
@ -2270,9 +2278,9 @@
}
},
"node_modules/@codemirror/lang-python": {
"version": "6.1.6",
"resolved": "https://registry.npmjs.org/@codemirror/lang-python/-/lang-python-6.1.6.tgz",
"integrity": "sha512-ai+01WfZhWqM92UqjnvorkxosZ2aq2u28kHvr+N3gu012XqY2CThD67JPMHnGceRfXPDBmn1HnyqowdpF57bNg==",
"version": "6.1.5",
"resolved": "https://registry.npmjs.org/@codemirror/lang-python/-/lang-python-6.1.5.tgz",
"integrity": "sha512-hCm+8X6wrnXJCGf+QhmFu1AXkdTVG7dHy0Ly6SI1N3SRPptaMvwX6oNQonOXOMPvmcjiB0xq342KAxX3BYpijw==",
"dependencies": {
"@codemirror/autocomplete": "^6.3.2",
"@codemirror/language": "^6.8.0",
@ -2663,9 +2671,9 @@
}
},
"node_modules/@goauthentik/api": {
"version": "2024.4.1-1714655911",
"resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2024.4.1-1714655911.tgz",
"integrity": "sha512-x7ViXuDh928e7B4dbQlOJXCtFnWJGGmOQcGI4IG6eWafUcq9+jgDnFrd0qqkDGcipqjKiY52B4RSdRNRxRsucA=="
"version": "2024.4.0-1713978791",
"resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2024.4.0-1713978791.tgz",
"integrity": "sha512-+pcTx4PLOlwEaR7ZswGd74lVULis0JZhs6j6FNgzt7Vd2vWuORnuhXBSzDh33MAitSblrvjtxdgf2YSuIsICFQ=="
},
"node_modules/@hcaptcha/types": {
"version": "1.0.3",
@ -4027,9 +4035,9 @@
"peer": true
},
"node_modules/@rollup/rollup-darwin-arm64": {
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.17.2.tgz",
"integrity": "sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw==",
"version": "4.16.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.16.4.tgz",
"integrity": "sha512-i5d64MlnYBO9EkCOGe5vPR/EeDwjnKOGGdd7zKFhU5y8haKhQZTN2DgVtpODDMxUr4t2K90wTUJg7ilgND6bXw==",
"cpu": [
"arm64"
],
@ -4067,9 +4075,9 @@
"peer": true
},
"node_modules/@rollup/rollup-linux-arm64-gnu": {
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.17.2.tgz",
"integrity": "sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==",
"version": "4.16.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.16.4.tgz",
"integrity": "sha512-7dy1BzQkgYlUTapDTvK997cgi0Orh5Iu7JlZVBy1MBURk7/HSbHkzRnXZa19ozy+wwD8/SlpJnOOckuNZtJR9w==",
"cpu": [
"arm64"
],
@ -4135,9 +4143,9 @@
"peer": true
},
"node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.17.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.17.2.tgz",
"integrity": "sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==",
"version": "4.16.4",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.16.4.tgz",
"integrity": "sha512-LuOGGKAJ7dfRtxVnO1i3qWc6N9sh0Em/8aZ3CezixSTM+E9Oq3OvTsvC4sm6wWjzpsIlOCnZjdluINKESflJLA==",
"cpu": [
"x64"
],
@ -4203,83 +4211,83 @@
"peer": true
},
"node_modules/@sentry-internal/feedback": {
"version": "7.113.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-7.113.0.tgz",
"integrity": "sha512-eEmL8QXauUnM3FXGv0GT29RpL0Jo0pkn/uMu3aqjhQo7JKNqUGVYIUxJxiGWbVMbDXqPQ7L66bjjMS3FR1GM2g==",
"version": "7.112.2",
"resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-7.112.2.tgz",
"integrity": "sha512-z+XP8BwB8B3pa+i8xqbrPsbtDWUFUS6wo+FJbmOYUqOusJJbVFDAhBoEdKoo5ZjOcsAZG7XR6cA9zrhJynIWBA==",
"dependencies": {
"@sentry/core": "7.113.0",
"@sentry/types": "7.113.0",
"@sentry/utils": "7.113.0"
"@sentry/core": "7.112.2",
"@sentry/types": "7.112.2",
"@sentry/utils": "7.112.2"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@sentry-internal/replay-canvas": {
"version": "7.113.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-7.113.0.tgz",
"integrity": "sha512-K8uA42aobNF/BAXf14el15iSAi9fonLBUrjZi6nPDq7zaA8rPvfcTL797hwCbqkETz2zDf52Jz7I3WFCshDoUw==",
"version": "7.112.2",
"resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-7.112.2.tgz",
"integrity": "sha512-BCCCxrZ1wJvN6La5gg1JJbKitAhJI5MATCnhtklsZbUcHkHB9iZoj19J65+P56gwssvHz5xh63AjNiITaetIRg==",
"dependencies": {
"@sentry/core": "7.113.0",
"@sentry/replay": "7.113.0",
"@sentry/types": "7.113.0",
"@sentry/utils": "7.113.0"
"@sentry/core": "7.112.2",
"@sentry/replay": "7.112.2",
"@sentry/types": "7.112.2",
"@sentry/utils": "7.112.2"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@sentry-internal/tracing": {
"version": "7.113.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.113.0.tgz",
"integrity": "sha512-8MDnYENRMnEfQjvN4gkFYFaaBSiMFSU/6SQZfY9pLI3V105z6JQ4D0PGMAUVowXilwNZVpKNYohE7XByuhEC7Q==",
"version": "7.112.2",
"resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.112.2.tgz",
"integrity": "sha512-fT1Y46J4lfXZkgFkb03YMNeIEs2xS6jdKMoukMFQfRfVvL9fSWEbTgZpHPd/YTT8r2i082XzjtAoQNgklm/0Hw==",
"dependencies": {
"@sentry/core": "7.113.0",
"@sentry/types": "7.113.0",
"@sentry/utils": "7.113.0"
"@sentry/core": "7.112.2",
"@sentry/types": "7.112.2",
"@sentry/utils": "7.112.2"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/browser": {
"version": "7.113.0",
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.113.0.tgz",
"integrity": "sha512-PdyVHPOprwoxGfKGsP2dXDWO0MBDW1eyP7EZlfZvM1A4hjk6ZRNfCv30g+TrqX4hiZDKzyqN3+AdP7N/J2IX0Q==",
"version": "7.112.2",
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.112.2.tgz",
"integrity": "sha512-wULwavCch84+d0bueAdFm6CDm1u0TfOjN91VgY+sj/vxUV2vesvDgI8zRZfmbZEor3MYA90zerkZT3ehZQKbYw==",
"dependencies": {
"@sentry-internal/feedback": "7.113.0",
"@sentry-internal/replay-canvas": "7.113.0",
"@sentry-internal/tracing": "7.113.0",
"@sentry/core": "7.113.0",
"@sentry/integrations": "7.113.0",
"@sentry/replay": "7.113.0",
"@sentry/types": "7.113.0",
"@sentry/utils": "7.113.0"
"@sentry-internal/feedback": "7.112.2",
"@sentry-internal/replay-canvas": "7.112.2",
"@sentry-internal/tracing": "7.112.2",
"@sentry/core": "7.112.2",
"@sentry/integrations": "7.112.2",
"@sentry/replay": "7.112.2",
"@sentry/types": "7.112.2",
"@sentry/utils": "7.112.2"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/core": {
"version": "7.113.0",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.113.0.tgz",
"integrity": "sha512-pg75y3C5PG2+ur27A0Re37YTCEnX0liiEU7EOxWDGutH17x3ySwlYqLQmZsFZTSnvzv7t3MGsNZ8nT5O0746YA==",
"version": "7.112.2",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.112.2.tgz",
"integrity": "sha512-gHPCcJobbMkk0VR18J65WYQTt3ED4qC6X9lHKp27Ddt63E+MDGkG6lvYBU1LS8cV7CdyBGC1XXDCfor61GvLsA==",
"dependencies": {
"@sentry/types": "7.113.0",
"@sentry/utils": "7.113.0"
"@sentry/types": "7.112.2",
"@sentry/utils": "7.112.2"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/integrations": {
"version": "7.113.0",
"resolved": "https://registry.npmjs.org/@sentry/integrations/-/integrations-7.113.0.tgz",
"integrity": "sha512-w0sspGBQ+6+V/9bgCkpuM3CGwTYoQEVeTW6iNebFKbtN7MrM3XsGAM9I2cW1jVxFZROqCBPFtd2cs5n0j14aAg==",
"version": "7.112.2",
"resolved": "https://registry.npmjs.org/@sentry/integrations/-/integrations-7.112.2.tgz",
"integrity": "sha512-ioC2yyU6DqtLkdmWnm87oNvdn2+9oKctJeA4t+jkS6JaJ10DcezjCwiLscX4rhB9aWJV3IWF7Op0O6K3w0t2Hg==",
"dependencies": {
"@sentry/core": "7.113.0",
"@sentry/types": "7.113.0",
"@sentry/utils": "7.113.0",
"@sentry/core": "7.112.2",
"@sentry/types": "7.112.2",
"@sentry/utils": "7.112.2",
"localforage": "^1.8.1"
},
"engines": {
@ -4287,33 +4295,33 @@
}
},
"node_modules/@sentry/replay": {
"version": "7.113.0",
"resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.113.0.tgz",
"integrity": "sha512-UD2IaphOWKFdeGR+ZiaNAQ+wFsnwbJK6PNwcW6cHmWKv9COlKufpFt06lviaqFZ8jmNrM4H+r+R8YVTrqCuxgg==",
"version": "7.112.2",
"resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.112.2.tgz",
"integrity": "sha512-7Ns/8D54WPsht1nlVj93Inf6rXyve2AZoibYN0YfcM2w3lI4NO51gPPHJU0lFEfMwzwK4ZBJWzOeW9098a+uEg==",
"dependencies": {
"@sentry-internal/tracing": "7.113.0",
"@sentry/core": "7.113.0",
"@sentry/types": "7.113.0",
"@sentry/utils": "7.113.0"
"@sentry-internal/tracing": "7.112.2",
"@sentry/core": "7.112.2",
"@sentry/types": "7.112.2",
"@sentry/utils": "7.112.2"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@sentry/types": {
"version": "7.113.0",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.113.0.tgz",
"integrity": "sha512-PJbTbvkcPu/LuRwwXB1He8m+GjDDLKBtu3lWg5xOZaF5IRdXQU2xwtdXXsjge4PZR00tF7MO7X8ZynTgWbYaew==",
"version": "7.112.2",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.112.2.tgz",
"integrity": "sha512-kCMLt7yhY5OkWE9MeowlTNmox9pqDxcpvqguMo4BDNZM5+v9SEb1AauAdR78E1a1V8TyCzjBD7JDfXWhvpYBcQ==",
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/utils": {
"version": "7.113.0",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.113.0.tgz",
"integrity": "sha512-nzKsErwmze1mmEsbW2AwL2oB+I5v6cDEJY4sdfLekA4qZbYZ8pV5iWza6IRl4XfzGTE1qpkZmEjPU9eyo0yvYw==",
"version": "7.112.2",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.112.2.tgz",
"integrity": "sha512-OjLh0hx0t1EcL4ZIjf+4svlmmP+tHUDGcr5qpFWH78tjmkPW4+cqPuZCZfHSuWcDdeiaXi8TnYoVRqDcJKK/eQ==",
"dependencies": {
"@sentry/types": "7.113.0"
"@sentry/types": "7.112.2"
},
"engines": {
"node": ">=8"
@ -16862,10 +16870,11 @@
}
},
"node_modules/react": {
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz",
"integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"loose-envify": "^1.1.0"
},
@ -16885,16 +16894,17 @@
}
},
"node_modules/react-dom": {
"version": "18.3.1",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
"integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==",
"dev": true,
"license": "MIT",
"dependencies": {
"loose-envify": "^1.1.0",
"scheduler": "^0.23.2"
"scheduler": "^0.23.0"
},
"peerDependencies": {
"react": "^18.3.1"
"react": "^18.2.0"
}
},
"node_modules/react-is": {
@ -17639,10 +17649,11 @@
"license": "MIT"
},
"node_modules/scheduler": {
"version": "0.23.2",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
"integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
"version": "0.23.0",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz",
"integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==",
"dev": true,
"license": "MIT",
"dependencies": {
"loose-envify": "^1.1.0"
}
@ -20057,9 +20068,9 @@
"license": "ISC"
},
"node_modules/yaml": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.2.tgz",
"integrity": "sha512-B3VqDZ+JAg1nZpaEmWtTXUlBneoGx6CPM9b0TENK6aoSu5t73dItudwdgmi6tHlIZZId4dZ9skcAQ2UbcyAeVA==",
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.1.tgz",
"integrity": "sha512-pIXzoImaqmfOrL7teGUBt/T7ZDnyeGBWyXQBvOVhLkWLN37GXv8NMLK406UY6dS51JfcQHsmcW5cJ441bHg6Lg==",
"bin": {
"yaml": "bin.mjs"
},

View File

@ -14,8 +14,8 @@
"build": "run-s build-locales esbuild:build",
"build-proxy": "run-s build-locales esbuild:build-proxy",
"watch": "run-s build-locales esbuild:watch",
"lint": "cross-env NODE_OPTIONS='--max_old_space_size=65536' eslint . --max-warnings 0 --fix",
"lint:precommit": "cross-env NODE_OPTIONS='--max_old_space_size=65536' node scripts/eslint-precommit.mjs",
"lint": "cross-env NODE_OPTIONS='--max_old_space_size=16384' eslint . --max-warnings 0 --fix",
"lint:precommit": "cross-env NODE_OPTIONS='--max_old_space_size=16384' node scripts/eslint-precommit.mjs",
"lint:spelling": "node scripts/check-spelling.mjs",
"lit-analyse": "lit-analyzer src",
"precommit": "npm-run-all --parallel tsc lit-analyse lint:spelling --sequential lint:precommit prettier",
@ -32,13 +32,13 @@
"dependencies": {
"@codemirror/lang-html": "^6.4.9",
"@codemirror/lang-javascript": "^6.2.2",
"@codemirror/lang-python": "^6.1.6",
"@codemirror/lang-python": "^6.1.5",
"@codemirror/lang-xml": "^6.1.0",
"@codemirror/legacy-modes": "^6.4.0",
"@codemirror/theme-one-dark": "^6.1.2",
"@formatjs/intl-listformat": "^7.5.5",
"@fortawesome/fontawesome-free": "^6.5.2",
"@goauthentik/api": "^2024.4.1-1714655911",
"@goauthentik/api": "^2024.4.0-1713978791",
"@lit-labs/task": "^3.1.0",
"@lit/context": "^1.1.1",
"@lit/localize": "^0.12.1",
@ -46,7 +46,7 @@
"@open-wc/lit-helpers": "^0.7.0",
"@patternfly/elements": "^3.0.1",
"@patternfly/patternfly": "^4.224.2",
"@sentry/browser": "^7.113.0",
"@sentry/browser": "^7.112.2",
"@webcomponents/webcomponentsjs": "^2.8.0",
"base64-js": "^1.5.1",
"chart.js": "^4.4.2",
@ -65,16 +65,16 @@
"style-mod": "^4.1.2",
"ts-pattern": "^5.1.1",
"webcomponent-qr-code": "^1.2.0",
"yaml": "^2.4.2"
"yaml": "^2.4.1"
},
"devDependencies": {
"@babel/core": "^7.24.5",
"@babel/core": "^7.24.4",
"@babel/plugin-proposal-class-properties": "^7.18.6",
"@babel/plugin-proposal-decorators": "^7.24.1",
"@babel/plugin-transform-private-methods": "^7.24.1",
"@babel/plugin-transform-private-property-in-object": "^7.24.5",
"@babel/plugin-transform-private-property-in-object": "^7.24.1",
"@babel/plugin-transform-runtime": "^7.24.3",
"@babel/preset-env": "^7.24.5",
"@babel/preset-env": "^7.24.4",
"@babel/preset-typescript": "^7.24.1",
"@hcaptcha/types": "^1.0.3",
"@jeysal/storybook-addon-css-user-preferences": "^0.2.0",
@ -114,7 +114,7 @@
"prettier": "^3.2.5",
"pseudolocale": "^2.0.0",
"react": "^18.2.0",
"react-dom": "^18.3.1",
"react-dom": "^18.2.0",
"rollup-plugin-modify": "^3.0.0",
"rollup-plugin-postcss-lit": "^2.1.0",
"storybook": "^8.0.9",
@ -129,9 +129,9 @@
"@esbuild/darwin-arm64": "^0.20.1",
"@esbuild/linux-amd64": "^0.18.11",
"@esbuild/linux-arm64": "^0.20.1",
"@rollup/rollup-darwin-arm64": "4.17.2",
"@rollup/rollup-linux-arm64-gnu": "4.17.2",
"@rollup/rollup-linux-x64-gnu": "4.17.2"
"@rollup/rollup-darwin-arm64": "4.16.4",
"@rollup/rollup-linux-arm64-gnu": "4.16.4",
"@rollup/rollup-linux-x64-gnu": "4.16.4"
},
"engines": {
"node": ">=20"

View File

@ -29,9 +29,5 @@ export const signatureAlgorithmOptions = toOptions([
["RSA-SHA256", SignatureAlgorithmEnum._200104XmldsigMorersaSha256, true],
["RSA-SHA384", SignatureAlgorithmEnum._200104XmldsigMorersaSha384],
["RSA-SHA512", SignatureAlgorithmEnum._200104XmldsigMorersaSha512],
["ECDSA-SHA1", SignatureAlgorithmEnum._200104XmldsigMoreecdsaSha1],
["ECDSA-SHA256", SignatureAlgorithmEnum._200104XmldsigMoreecdsaSha256],
["ECDSA-SHA384", SignatureAlgorithmEnum._200104XmldsigMoreecdsaSha384],
["ECDSA-SHA512", SignatureAlgorithmEnum._200104XmldsigMoreecdsaSha512],
["DSA-SHA1", SignatureAlgorithmEnum._200009XmldsigdsaSha1],
]);

View File

@ -6,12 +6,7 @@ import { msg } from "@lit/localize";
import { TemplateResult, html } from "lit";
import { customElement } from "lit/decorators.js";
import {
AlgEnum,
CertificateGenerationRequest,
CertificateKeyPair,
CryptoApi,
} from "@goauthentik/api";
import { CertificateGenerationRequest, CertificateKeyPair, CryptoApi } from "@goauthentik/api";
@customElement("ak-crypto-certificate-generate-form")
export class CertificateKeyPairForm extends Form<CertificateGenerationRequest> {
@ -45,29 +40,6 @@ export class CertificateKeyPairForm extends Form<CertificateGenerationRequest> {
?required=${true}
>
<input class="pf-c-form-control" type="number" value="365" />
</ak-form-element-horizontal>
<ak-form-element-horizontal
label=${msg("Private key Algorithm")}
?required=${true}
name="alg"
>
<ak-radio
.options=${[
{
label: msg("RSA"),
value: AlgEnum.Rsa,
default: true,
},
{
label: msg("ECDSA"),
value: AlgEnum.Ecdsa,
},
]}
>
</ak-radio>
<p class="pf-c-form__helper-text">
${msg("Algorithm used to generate the private key.")}
</p>
</ak-form-element-horizontal> `;
</ak-form-element-horizontal>`;
}
}

View File

@ -470,7 +470,7 @@ export class LDAPSourceForm extends BaseSourceForm<LDAPSource> {
>
<input
type="text"
value="${this.instance?.objectUniquenessField || "objectSid"}"
value="${this.instance?.objectUniquenessField || "entryDN"}"
class="pf-c-form-control"
required
/>

View File

@ -128,14 +128,6 @@ export class UserForm extends ModelForm<User, number> {
"Service accounts should be used for machine-to-machine authentication or other automations.",
)}`,
},
{
label: "Internal Service account",
value: UserTypeEnum.InternalServiceAccount,
disabled: true,
description: html`${msg(
"Internal Service accounts are created and managed by authentik and cannot be created manually.",
)}`,
},
]}
.value=${this.instance?.type}
>

View File

@ -3,7 +3,7 @@ export const SUCCESS_CLASS = "pf-m-success";
export const ERROR_CLASS = "pf-m-danger";
export const PROGRESS_CLASS = "pf-m-in-progress";
export const CURRENT_CLASS = "pf-m-current";
export const VERSION = "2024.4.1";
export const VERSION = "2024.4.0";
export const TITLE_DEFAULT = "authentik";
export const ROUTE_SEPARATOR = ";";

View File

@ -187,9 +187,6 @@ input[type="date"]::-webkit-calendar-picker-indicator {
.pf-c-select__menu-item.pf-m-focus {
--pf-c-select__menu-item--focus--BackgroundColor: var(--ak-dark-background-light-ish);
}
.pf-c-button:disabled {
color: var(--ak-dark-background-lighter);
}
.pf-c-button.pf-m-plain:hover {
color: var(--ak-dark-foreground);
}

View File

@ -18,7 +18,7 @@ export function me(): Promise<SessionUser> {
if (!user.user.settings || !("locale" in user.user.settings)) {
return user;
}
const locale: string | undefined = user.user.settings.locale;
const locale = user.user.settings.locale;
if (locale && locale !== "") {
console.debug(
`authentik/locale: Activating user's configured locale '${locale}'`,

View File

@ -12,8 +12,4 @@ export const authentikEnterpriseContext = createContext<LicenseSummary>(
export const authentikBrandContext = createContext<CurrentBrand>(Symbol("authentik-brand-context"));
export const authentikLocalStoreContext = createContext<unknown>(
Symbol("authentik-local-store-context"),
);
export default authentikConfigContext;

View File

@ -2,7 +2,7 @@ import { EVENT_LOCALE_CHANGE, EVENT_LOCALE_REQUEST } from "@goauthentik/common/c
import { customEvent } from "@goauthentik/elements/utils/customEvents";
import { LitElement, html } from "lit";
import { customElement, property } from "lit/decorators.js";
import { customElement, property, state } from "lit/decorators.js";
import { WithBrandConfig } from "../Interface/brandProvider";
import { initializeLocalization } from "./configureLocale";
@ -38,6 +38,9 @@ export class LocaleContext extends LocaleContextBase {
setLocale: LocaleSetter;
@state()
userLocale = "";
constructor(code = DEFAULT_LOCALE) {
super();
this.notifyApplication = this.notifyApplication.bind(this);
@ -56,22 +59,30 @@ export class LocaleContext extends LocaleContextBase {
connectedCallback() {
super.connectedCallback();
// Commenting out until we can come up with a better way of separating the
// "request user identity" with the session expiration heartbeat.
/*
new CoreApi(DEFAULT_CONFIG)
.coreUsersMeRetrieve()
.then((user) => (this.userLocale = user?.user?.settings?.locale ?? ""))
.catch(() => {});
*/
this.updateLocale();
window.addEventListener(EVENT_LOCALE_REQUEST, this.updateLocaleHandler as EventListener);
window.addEventListener(EVENT_LOCALE_REQUEST, this.updateLocaleHandler);
}
disconnectedCallback() {
window.removeEventListener(EVENT_LOCALE_REQUEST, this.updateLocaleHandler as EventListener);
window.removeEventListener(EVENT_LOCALE_REQUEST, this.updateLocaleHandler);
super.disconnectedCallback();
}
updateLocaleHandler(ev: CustomEvent<{ locale: string }>) {
updateLocaleHandler(_ev: Event) {
console.debug("authentik/locale: Locale update request received.");
this.updateLocale(ev.detail.locale);
this.updateLocale();
}
updateLocale(requestedLocale: string | undefined = undefined) {
const localeRequest = autoDetectLanguage(requestedLocale, this.brand?.defaultLocale);
updateLocale() {
const localeRequest = autoDetectLanguage(this.userLocale, this.brand?.defaultLocale);
const locale = getBestMatchLocale(localeRequest);
if (!locale) {
console.warn(`authentik/locale: failed to find locale for code ${localeRequest}`);

View File

@ -16,7 +16,6 @@ export interface RadioOption<T> {
description?: TemplateResult;
default?: boolean;
value: T;
disabled?: boolean;
}
@customElement("ak-radio")
@ -78,9 +77,6 @@ export class Radio<T> extends CustomEmitterElement(AKElement) {
// This is a controlled input. Stop the native event from escaping or affecting the
// value. We'll do that ourselves.
ev.stopPropagation();
if (option.disabled) {
return;
}
this.value = option.value;
this.dispatchCustomEvent("change", { value: option.value });
this.dispatchCustomEvent("input", { value: option.value });
@ -97,7 +93,6 @@ export class Radio<T> extends CustomEmitterElement(AKElement) {
name="${this.name}"
id=${elId}
.checked=${option.value === this.value}
.disabled=${option.disabled}
/>
<label class="pf-c-radio__label" for=${elId}>${option.label}</label>
${option.description

View File

@ -1,31 +0,0 @@
type TryFn<T> = () => T;
type CatchFn<T> = (error: unknown) => T;
type TryCatchArgs<T> = {
tryFn: TryFn<T>;
catchFn?: CatchFn<T>;
};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const isTryCatchArgs = <T>(t: any): t is TryCatchArgs<T> =>
typeof t === "object" && "tryFn" in t && "catchFn" in t;
export function tryCatch<T>({ tryFn, catchFn }: TryCatchArgs<T>): T;
export function tryCatch<T>(tryFn: TryFn<T>): T;
export function tryCatch<T>(tryFn: TryFn<T>, catchFn: CatchFn<T>): T;
export function tryCatch<T>(tryFn: TryFn<T> | TryCatchArgs<T>, catchFn?: CatchFn<T>): T {
if (isTryCatchArgs(tryFn)) {
catchFn = tryFn.catchFn;
tryFn = tryFn.tryFn;
}
if (catchFn === undefined) {
catchFn = () => null as T;
}
try {
return tryFn();
} catch (error) {
return catchFn(error);
}
}

View File

@ -441,10 +441,7 @@ export class FlowExecutor extends Interface implements StageHost {
renderChallengeWrapper(): TemplateResult {
const logo = html`<div class="pf-c-login__main-header pf-c-brand ak-brand">
<img
src="${first(this.brand?.brandingLogo, globalAK()?.brand.brandingLogo, "")}"
alt="authentik Logo"
/>
<img src="${first(this.brand?.brandingLogo, "")}" alt="authentik Logo" />
</div>`;
if (!this.challenge) {
return html`${logo}<ak-empty-state ?loading=${true} header=${msg("Loading")}>

View File

@ -8,7 +8,7 @@ import "@goauthentik/elements/EmptyState";
import { BaseStage } from "@goauthentik/flow/stages/base";
import { msg, str } from "@lit/localize";
import { CSSResult, PropertyValues, TemplateResult, css, html, nothing } from "lit";
import { CSSResult, TemplateResult, css, html, nothing } from "lit";
import { customElement, property } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js";
@ -115,16 +115,14 @@ export class WebAuthnAuthenticatorRegisterStage extends BaseStage<
});
}
updated(changedProperties: PropertyValues<this>) {
if (changedProperties.has("challenge") && this.challenge !== undefined) {
// convert certain members of the PublicKeyCredentialCreateOptions into
// byte arrays as expected by the spec.
this.publicKeyCredentialCreateOptions = transformCredentialCreateOptions(
this.challenge?.registration as PublicKeyCredentialCreationOptions,
this.challenge?.registration.user.id,
);
this.registerWrapper();
}
firstUpdated(): void {
// convert certain members of the PublicKeyCredentialCreateOptions into
// byte arrays as expected by the spec.
this.publicKeyCredentialCreateOptions = transformCredentialCreateOptions(
this.challenge?.registration as PublicKeyCredentialCreationOptions,
this.challenge?.registration.user.id,
);
this.registerWrapper();
}
render(): TemplateResult {

View File

@ -1,95 +0,0 @@
import { LayoutType } from "@goauthentik/common/ui/config";
import { AKElement } from "@goauthentik/elements/Base";
import { css, html } from "lit";
import { customElement, property } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js";
import PFContent from "@patternfly/patternfly/components/Content/content.css";
import PFEmptyState from "@patternfly/patternfly/components/EmptyState/empty-state.css";
import PFGrid from "@patternfly/patternfly/layouts/Grid/grid.css";
import PFBase from "@patternfly/patternfly/patternfly-base.css";
import type { Application } from "@goauthentik/api";
import type { AppGroupEntry, AppGroupList } from "./types";
type Pair = [string, string];
// prettier-ignore
const LAYOUTS = new Map<string, [string, string]>([
[
"row",
["pf-m-12-col", "pf-m-all-6-col-on-sm pf-m-all-4-col-on-md pf-m-all-5-col-on-lg pf-m-all-2-col-on-xl"]],
[
"2-column",
["pf-m-6-col", "pf-m-all-12-col-on-sm pf-m-all-12-col-on-md pf-m-all-4-col-on-lg pf-m-all-4-col-on-xl"],
],
[
"3-column",
["pf-m-4-col", "pf-m-all-12-col-on-sm pf-m-all-12-col-on-md pf-m-all-6-col-on-lg pf-m-all-6-col-on-xl"],
],
]);
@customElement("ak-library-application-cards")
export class LibraryPageApplicationCards extends AKElement {
static get styles() {
return [
PFBase,
PFEmptyState,
PFContent,
PFGrid,
css`
.app-group-header {
margin-bottom: 1em;
margin-top: 1.2em;
}
`,
];
}
@property({ attribute: true })
layout = "row" as LayoutType;
@property({ attribute: true })
background: string | undefined = undefined;
@property({ attribute: true })
selected = "";
@property({ attribute: false })
apps: AppGroupList = [];
get currentLayout(): Pair {
const layout = LAYOUTS.get(this.layout);
if (!layout) {
console.warn(`Unrecognized layout: ${this.layout || "-undefined-"}`);
return LAYOUTS.get("row") as Pair;
}
return layout;
}
render() {
const [groupClass, groupGrid] = this.currentLayout;
return html`<div class="pf-l-grid pf-m-gutter">
${this.apps.map(([group, apps]: AppGroupEntry) => {
return html`<div class="pf-l-grid__item ${groupClass}">
<div class="pf-c-content app-group-header">
<h2>${group}</h2>
</div>
<div class="pf-l-grid pf-m-gutter ${groupGrid}">
${apps.map((app: Application) => {
return html`<ak-library-app
class="pf-l-grid__item"
.application=${app}
background=${ifDefined(this.background)}
?selected=${app.slug === this.selected}
></ak-library-app>`;
})}
</div>
</div> `;
})}
</div>`;
}
}

View File

@ -1,34 +1,48 @@
import { PFSize } from "@goauthentik/common/enums.js";
import { LayoutType } from "@goauthentik/common/ui/config";
import { AKElement, rootInterface } from "@goauthentik/elements/Base";
import { UserInterface } from "@goauthentik/user/UserInterface";
import { AKElement } from "@goauthentik/elements/Base";
import { msg } from "@lit/localize";
import { css, html, nothing } from "lit";
import { css, html } from "lit";
import { customElement, property } from "lit/decorators.js";
import { classMap } from "lit/directives/class-map.js";
import { ifDefined } from "lit/directives/if-defined.js";
import PFButton from "@patternfly/patternfly/components/Button/button.css";
import PFContent from "@patternfly/patternfly/components/Content/content.css";
import PFEmptyState from "@patternfly/patternfly/components/EmptyState/empty-state.css";
import PFTable from "@patternfly/patternfly/components/Table/table.css";
import PFGrid from "@patternfly/patternfly/layouts/Grid/grid.css";
import PFBase from "@patternfly/patternfly/patternfly-base.css";
import type { Application } from "@goauthentik/api";
import type { AppGroupEntry, AppGroupList } from "./types";
type Pair = [string, string];
// prettier-ignore
const LAYOUTS = new Map<string, [string, string]>([
[
"row",
["pf-m-12-col", "pf-m-all-6-col-on-sm pf-m-all-4-col-on-md pf-m-all-5-col-on-lg pf-m-all-2-col-on-xl"]],
[
"2-column",
["pf-m-6-col", "pf-m-all-12-col-on-sm pf-m-all-12-col-on-md pf-m-all-4-col-on-lg pf-m-all-4-col-on-xl"],
],
[
"3-column",
["pf-m-4-col", "pf-m-all-12-col-on-sm pf-m-all-12-col-on-md pf-m-all-6-col-on-lg pf-m-all-6-col-on-xl"],
],
]);
@customElement("ak-library-application-list")
export class LibraryPageApplicationList extends AKElement {
static get styles() {
return [
PFBase,
PFTable,
PFButton,
PFEmptyState,
PFContent,
PFGrid,
css`
.app-row a {
font-weight: bold;
.app-group-header {
margin-bottom: 1em;
margin-top: 1.2em;
}
`,
];
@ -46,110 +60,36 @@ export class LibraryPageApplicationList extends AKElement {
@property({ attribute: false })
apps: AppGroupList = [];
expanded = new Set<string>();
get currentLayout(): Pair {
const layout = LAYOUTS.get(this.layout);
if (!layout) {
console.warn(`Unrecognized layout: ${this.layout || "-undefined-"}`);
return LAYOUTS.get("row") as Pair;
}
return layout;
}
render() {
const me = rootInterface<UserInterface>()?.me;
const canEdit =
rootInterface()?.uiConfig?.enabledFeatures.applicationEdit && me?.user.isSuperuser;
const [groupClass, groupGrid] = this.currentLayout;
const toggleExpansion = (pk: string) => {
if (this.expanded.has(pk)) {
this.expanded.delete(pk);
} else {
this.expanded.add(pk);
}
this.requestUpdate();
};
const expandedClass = (pk: string) => ({
"pf-m-expanded": this.expanded.has(pk),
});
const renderExpansionCell = (app: Application) =>
app.metaDescription
? html`<td class="pf-c-table__toggle" role="cell">
<button
class="pf-c-button pf-m-plain ${classMap(expandedClass(app.pk))}"
@click=${() => toggleExpansion(app.pk)}
>
<div class="pf-c-table__toggle-icon">
&nbsp;<i class="fas fa-angle-down" aria-hidden="true"></i>&nbsp;
</div>
</button>
</td>`
: nothing;
const renderAppIcon = (app: Application) =>
html`<a
href="${ifDefined(app.launchUrl ?? "")}"
target="${ifDefined(app.openInNewTab ? "_blank" : undefined)}"
>
<ak-app-icon size=${PFSize.Small} .app=${app}></ak-app-icon>
</a>`;
const renderAppUrl = (app: Application) =>
app.launchUrl === "goauthentik.io://providers/rac/launch"
? html`<ak-library-rac-endpoint-launch .app=${app}>
<a slot="trigger"> ${app.name} </a>
</ak-library-rac-endpoint-launch>`
: html`<a
href="${ifDefined(app.launchUrl ?? "")}"
target="${ifDefined(app.openInNewTab ? "_blank" : undefined)}"
>${app.name}</a
>`;
const renderAppDescription = (app: Application) =>
app.metaDescription
? html` <tr
class="pf-c-table__expandable-row ${classMap(expandedClass(app.pk))}"
role="row"
>
<td></td>
<td></td>
<td colspan="3">${app.metaDescription}</td>
</tr>`
: nothing;
const renderGroup = ([group, apps]: AppGroupEntry) => html`
${group
? html`<tr>
<td colspan="5"><h2>${group}</h2></td>
</tr>`
: nothing}
${apps.map(
(app: Application) =>
html`<tr>
<td>${renderExpansionCell(app)}</td>
<td>${renderAppIcon(app)}</td>
<td class="app-row">${renderAppUrl(app)}</td>
<td>${app.metaPublisher ?? ""}</td>
<td>
<a
class="pf-c-button pf-m-control pf-m-small pf-m-block"
href="/if/admin/#/core/applications/${app?.slug}"
>
<i class="fas fa-edit"></i>&nbsp;${msg("Edit")}
</a>
</td>
</tr>
${this.expanded.has(app.pk) ? renderAppDescription(app) : nothing} `,
)}
`;
return html`<table class="pf-c-table pf-m-compact pf-m-grid-sm pf-m-expandable">
<thead>
<tr role="row">
<th></th>
<th></th>
<th>${msg("Application")}</th>
<th>${msg("Publisher")}</th>
${canEdit ? html`<th>${msg("Edit")}</th>` : nothing}
</tr>
</thead>
<tbody>
${this.apps.map(renderGroup)}
</tbody>
</table> `;
return html`<div class="pf-l-grid pf-m-gutter">
${this.apps.map(([group, apps]: AppGroupEntry) => {
return html`<div class="pf-l-grid__item ${groupClass}">
<div class="pf-c-content app-group-header">
<h2>${group}</h2>
</div>
<div class="pf-l-grid pf-m-gutter ${groupGrid}">
${apps.map((app: Application) => {
return html`<ak-library-app
class="pf-l-grid__item"
.application=${app}
background=${ifDefined(this.background)}
?selected=${app.slug === this.selected}
></ak-library-app>`;
})}
</div>
</div> `;
})}
</div>`;
}
}

View File

@ -34,30 +34,6 @@ export const styles = [PFBase, PFDisplay, PFEmptyState, PFPage, PFContent].conca
.pf-c-page__main-section {
background-color: transparent;
}
#library-page-title {
display: flex;
flex-direction: row;
gap: 0.5rem;
}
#library-page-title h1 {
padding-right: 0.5rem;
}
#library-page-title i {
display: inline-block;
padding: 0.25rem;
}
#library-page-title i[checked] {
border: 3px solid var(--pf-global--BorderColor--100);
}
#library-page-title a,
#library-page-title i {
vertical-align: bottom;
}
`);
export default styles;

View File

@ -1,7 +1,6 @@
import { groupBy } from "@goauthentik/common/utils";
import { AKElement } from "@goauthentik/elements/Base";
import "@goauthentik/elements/EmptyState";
import { tryCatch } from "@goauthentik/elements/utils/tryCatch.js";
import "@goauthentik/user/LibraryApplication";
import { msg } from "@lit/localize";
@ -13,7 +12,6 @@ import styles from "./LibraryPageImpl.css";
import type { Application } from "@goauthentik/api";
import "./ApplicationCards";
import "./ApplicationEmptyState";
import "./ApplicationList";
import "./ApplicationSearch";
@ -22,8 +20,6 @@ import { SEARCH_ITEM_SELECTED, SEARCH_UPDATED } from "./constants";
import { isCustomEvent, loading } from "./helpers";
import type { AppGroupList, PageUIConfig } from "./types";
const VIEW_KEY = "ak-library-page-view-preference";
/**
* List of Applications available
*
@ -57,9 +53,6 @@ export class LibraryPage extends AKElement {
@state()
filteredApps: Application[] = [];
@property()
viewPreference?: string;
constructor() {
super();
this.searchUpdated = this.searchUpdated.bind(this);
@ -73,12 +66,6 @@ export class LibraryPage extends AKElement {
connectedCallback() {
super.connectedCallback();
this.filteredApps = this.apps;
this.viewPreference =
this.viewPreference ??
tryCatch(
() => window.localStorage.getItem(VIEW_KEY) ?? undefined,
(e) => "card",
);
if (this.filteredApps === undefined) {
throw new Error(
"Application.results should never be undefined when passed to the Library Page.",
@ -123,13 +110,6 @@ export class LibraryPage extends AKElement {
return groupBy(this.filteredApps.filter(appHasLaunchUrl), (app) => app.group || "");
}
setView(view: string) {
this.viewPreference = view;
tryCatch(() => {
window.localStorage.setItem(VIEW_KEY, view);
});
}
renderEmptyState() {
return html`<ak-library-application-empty-list
?isadmin=${this.isAdmin}
@ -142,17 +122,12 @@ export class LibraryPage extends AKElement {
const layout = this.uiConfig.layout as string;
const background = this.uiConfig.background;
return this.viewPreference === "list"
? html`<ak-library-application-list
selected="${ifDefined(selected)}"
.apps=${apps}
></ak-library-application-list>`
: html`<ak-library-application-cards
layout="${layout}"
background="${ifDefined(background)}"
selected="${ifDefined(selected)}"
.apps=${apps}
></ak-library-application-cards>`;
return html`<ak-library-application-list
layout="${layout}"
background="${ifDefined(background)}"
selected="${ifDefined(selected)}"
.apps=${apps}
></ak-library-application-list>`;
}
renderSearch() {
@ -162,15 +137,9 @@ export class LibraryPage extends AKElement {
render() {
return html`<main role="main" class="pf-c-page__main" tabindex="-1" id="main-content">
<div class="pf-c-content header">
<div id="library-page-title">
<h1 role="heading" aria-level="1">${msg("My applications")}</h1>
<a id="card-view" @click=${() => this.setView("card")}
><i ?checked=${this.viewPreference === "card"} class="fas fa-th-large"></i
></a>
<a id="list-view" @click=${() => this.setView("list")}
><i ?checked=${this.viewPreference === "list"} class="fas fa-list"></i
></a>
</div>
<h1 role="heading" aria-level="1" id="library-page-title">
${msg("My applications")}
</h1>
${this.uiConfig.searchEnabled ? this.renderSearch() : html``}
</div>
<section class="pf-c-page__main-section">

View File

@ -6540,21 +6540,6 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="sa59d53ee922c08b5">
<source>Selected Roles</source>
</trans-unit>
<trans-unit id="s7bfbf84a8ad5883f">
<source>Internal Service accounts are created and managed by authentik and cannot be created manually.</source>
</trans-unit>
<trans-unit id="sb0680e5f8782db1e">
<source>Private key Algorithm</source>
</trans-unit>
<trans-unit id="sa03cbf19feebd249">
<source>RSA</source>
</trans-unit>
<trans-unit id="sfbfccbd3e395c147">
<source>ECDSA</source>
</trans-unit>
<trans-unit id="sebea299e52db4242">
<source>Algorithm used to generate the private key.</source>
</trans-unit>
</body>
</file>

View File

@ -6809,21 +6809,6 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="sa59d53ee922c08b5">
<source>Selected Roles</source>
</trans-unit>
<trans-unit id="s7bfbf84a8ad5883f">
<source>Internal Service accounts are created and managed by authentik and cannot be created manually.</source>
</trans-unit>
<trans-unit id="sb0680e5f8782db1e">
<source>Private key Algorithm</source>
</trans-unit>
<trans-unit id="sa03cbf19feebd249">
<source>RSA</source>
</trans-unit>
<trans-unit id="sfbfccbd3e395c147">
<source>ECDSA</source>
</trans-unit>
<trans-unit id="sebea299e52db4242">
<source>Algorithm used to generate the private key.</source>
</trans-unit>
</body>
</file>

View File

@ -6457,21 +6457,6 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="sa59d53ee922c08b5">
<source>Selected Roles</source>
</trans-unit>
<trans-unit id="s7bfbf84a8ad5883f">
<source>Internal Service accounts are created and managed by authentik and cannot be created manually.</source>
</trans-unit>
<trans-unit id="sb0680e5f8782db1e">
<source>Private key Algorithm</source>
</trans-unit>
<trans-unit id="sa03cbf19feebd249">
<source>RSA</source>
</trans-unit>
<trans-unit id="sfbfccbd3e395c147">
<source>ECDSA</source>
</trans-unit>
<trans-unit id="sebea299e52db4242">
<source>Algorithm used to generate the private key.</source>
</trans-unit>
</body>
</file>

View File

@ -8605,21 +8605,6 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti
</trans-unit>
<trans-unit id="sa59d53ee922c08b5">
<source>Selected Roles</source>
</trans-unit>
<trans-unit id="s7bfbf84a8ad5883f">
<source>Internal Service accounts are created and managed by authentik and cannot be created manually.</source>
</trans-unit>
<trans-unit id="sb0680e5f8782db1e">
<source>Private key Algorithm</source>
</trans-unit>
<trans-unit id="sa03cbf19feebd249">
<source>RSA</source>
</trans-unit>
<trans-unit id="sfbfccbd3e395c147">
<source>ECDSA</source>
</trans-unit>
<trans-unit id="sebea299e52db4242">
<source>Algorithm used to generate the private key.</source>
</trans-unit>
</body>
</file>

View File

@ -8395,21 +8395,6 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="sa59d53ee922c08b5">
<source>Selected Roles</source>
</trans-unit>
<trans-unit id="s7bfbf84a8ad5883f">
<source>Internal Service accounts are created and managed by authentik and cannot be created manually.</source>
</trans-unit>
<trans-unit id="sb0680e5f8782db1e">
<source>Private key Algorithm</source>
</trans-unit>
<trans-unit id="sa03cbf19feebd249">
<source>RSA</source>
</trans-unit>
<trans-unit id="sfbfccbd3e395c147">
<source>ECDSA</source>
</trans-unit>
<trans-unit id="sebea299e52db4242">
<source>Algorithm used to generate the private key.</source>
</trans-unit>
</body>
</file>

View File

@ -8239,21 +8239,6 @@ Bindingen naar groepen/gebruikers worden gecontroleerd tegen de gebruiker van de
</trans-unit>
<trans-unit id="sa59d53ee922c08b5">
<source>Selected Roles</source>
</trans-unit>
<trans-unit id="s7bfbf84a8ad5883f">
<source>Internal Service accounts are created and managed by authentik and cannot be created manually.</source>
</trans-unit>
<trans-unit id="sb0680e5f8782db1e">
<source>Private key Algorithm</source>
</trans-unit>
<trans-unit id="sa03cbf19feebd249">
<source>RSA</source>
</trans-unit>
<trans-unit id="sfbfccbd3e395c147">
<source>ECDSA</source>
</trans-unit>
<trans-unit id="sebea299e52db4242">
<source>Algorithm used to generate the private key.</source>
</trans-unit>
</body>
</file>

View File

@ -6661,21 +6661,6 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="sa59d53ee922c08b5">
<source>Selected Roles</source>
</trans-unit>
<trans-unit id="s7bfbf84a8ad5883f">
<source>Internal Service accounts are created and managed by authentik and cannot be created manually.</source>
</trans-unit>
<trans-unit id="sb0680e5f8782db1e">
<source>Private key Algorithm</source>
</trans-unit>
<trans-unit id="sa03cbf19feebd249">
<source>RSA</source>
</trans-unit>
<trans-unit id="sfbfccbd3e395c147">
<source>ECDSA</source>
</trans-unit>
<trans-unit id="sebea299e52db4242">
<source>Algorithm used to generate the private key.</source>
</trans-unit>
</body>
</file>

Some files were not shown because too many files have changed in this diff Show More