Compare commits
93 Commits
healthchec
...
5165-passw
Author | SHA1 | Date | |
---|---|---|---|
5b9bb12822 | |||
8f09955d58 | |||
8f82dac84e | |||
89c08f2588 | |||
113d6cc45f | |||
05cfbca5f2 | |||
385f9bcbac | |||
86bc5b4cdb | |||
8d5d9f35ef | |||
439169d5e7 | |||
e405b33f9f | |||
a9c13d4d10 | |||
12b16b17a2 | |||
3473abee32 | |||
b5a0b3a521 | |||
837a0325ca | |||
b1050e8825 | |||
7bb90b1661 | |||
8f755785ea | |||
adc0ec8ee4 | |||
9379b3d178 | |||
18eef8ae05 | |||
f0e22fd08b | |||
ce5297a6cd | |||
74c8df8782 | |||
2d897fac48 | |||
2eb47c9efa | |||
9852041f38 | |||
7f74936212 | |||
4f40b1e27c | |||
041e407153 | |||
31b891428e | |||
4ab8247847 | |||
af24edf8c1 | |||
f8bfd12e31 | |||
993fc4b77b | |||
3ee2be09bf | |||
b3e3948f44 | |||
117a5cd88d | |||
342a40212e | |||
15ae11d9d5 | |||
e11df56f21 | |||
3771af5282 | |||
0718053c56 | |||
3e5014bfea | |||
78f49ddc04 | |||
744bc54231 | |||
44ba30ad75 | |||
63b991f137 | |||
7f9acb8a2b | |||
ce3ba32044 | |||
25e6a69331 | |||
78d07cc355 | |||
3c4df47fe3 | |||
8ed1805cb8 | |||
4d23db73ca | |||
72783953fb | |||
3b0fdb3dbd | |||
23161eed12 | |||
8918427588 | |||
5d858020f6 | |||
198e8b98a8 | |||
88e9c9b669 | |||
0c652a210d | |||
105a90d2e7 | |||
68f5abe318 | |||
59d4c18636 | |||
b67e2a1144 | |||
fc025651ce | |||
7cedc840b0 | |||
5ba731e48b | |||
c792534a50 | |||
a136fd8b54 | |||
fb63c1f3e9 | |||
0b15ab3f27 | |||
f9fd67c2b8 | |||
4ac19f9d44 | |||
74d3e92bac | |||
207fa13405 | |||
208e4a8bed | |||
ee245ab390 | |||
60c8837082 | |||
6cf418a37e | |||
254761e930 | |||
d85f8758fe | |||
84bfb37b60 | |||
465820b002 | |||
a75c9434d9 | |||
4ea9b69ab5 | |||
c48eee0ebf | |||
0d94373f10 | |||
1c85dc512f | |||
a71778651f |
@ -58,7 +58,7 @@ from authentik.outposts.models import OutpostServiceConnection
|
||||
from authentik.policies.models import Policy, PolicyBindingModel
|
||||
from authentik.policies.reputation.models import Reputation
|
||||
from authentik.providers.oauth2.models import AccessToken, AuthorizationCode, RefreshToken
|
||||
from authentik.providers.scim.models import SCIMGroup, SCIMUser
|
||||
from authentik.providers.scim.models import SCIMProviderGroup, SCIMProviderUser
|
||||
from authentik.sources.scim.models import SCIMSourceGroup, SCIMSourceUser
|
||||
from authentik.stages.authenticator_webauthn.models import WebAuthnDeviceType
|
||||
from authentik.tenants.models import Tenant
|
||||
@ -97,8 +97,8 @@ def excluded_models() -> list[type[Model]]:
|
||||
# FIXME: these shouldn't need to be explicitly listed, but rather based off of a mixin
|
||||
FlowToken,
|
||||
LicenseUsage,
|
||||
SCIMGroup,
|
||||
SCIMUser,
|
||||
SCIMProviderGroup,
|
||||
SCIMProviderUser,
|
||||
Tenant,
|
||||
SystemTask,
|
||||
ConnectionToken,
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
from json import loads
|
||||
|
||||
from django.db.models import Prefetch
|
||||
from django.http import Http404
|
||||
from django_filters.filters import CharFilter, ModelMultipleChoiceFilter
|
||||
from django_filters.filterset import FilterSet
|
||||
@ -166,8 +167,14 @@ class GroupViewSet(UsedByMixin, ModelViewSet):
|
||||
|
||||
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")
|
||||
else:
|
||||
base_qs = base_qs.prefetch_related(
|
||||
Prefetch("users", queryset=User.objects.all().only("id"))
|
||||
)
|
||||
|
||||
return base_qs
|
||||
|
||||
@extend_schema(
|
||||
|
@ -80,8 +80,10 @@ class PropertyMappingViewSet(
|
||||
class PropertyMappingTestSerializer(PolicyTestSerializer):
|
||||
"""Test property mapping execution for a user/group with context"""
|
||||
|
||||
user = PrimaryKeyRelatedField(queryset=User.objects.all(), required=False)
|
||||
group = PrimaryKeyRelatedField(queryset=Group.objects.all(), required=False)
|
||||
user = PrimaryKeyRelatedField(queryset=User.objects.all(), required=False, allow_null=True)
|
||||
group = PrimaryKeyRelatedField(
|
||||
queryset=Group.objects.all(), required=False, allow_null=True
|
||||
)
|
||||
|
||||
queryset = PropertyMapping.objects.select_subclasses()
|
||||
serializer_class = PropertyMappingSerializer
|
||||
|
@ -39,12 +39,12 @@ def get_delete_action(manager: Manager) -> str:
|
||||
"""Get the delete action from the Foreign key, falls back to cascade"""
|
||||
if hasattr(manager, "field"):
|
||||
if manager.field.remote_field.on_delete.__name__ == SET_NULL.__name__:
|
||||
return DeleteAction.SET_NULL.name
|
||||
return DeleteAction.SET_NULL.value
|
||||
if manager.field.remote_field.on_delete.__name__ == SET_DEFAULT.__name__:
|
||||
return DeleteAction.SET_DEFAULT.name
|
||||
return DeleteAction.SET_DEFAULT.value
|
||||
if hasattr(manager, "source_field"):
|
||||
return DeleteAction.CASCADE_MANY.name
|
||||
return DeleteAction.CASCADE.name
|
||||
return DeleteAction.CASCADE_MANY.value
|
||||
return DeleteAction.CASCADE.value
|
||||
|
||||
|
||||
class UsedByMixin:
|
||||
|
@ -241,7 +241,7 @@ class TestCrypto(APITestCase):
|
||||
"model_name": "oauth2provider",
|
||||
"pk": str(provider.pk),
|
||||
"name": str(provider),
|
||||
"action": DeleteAction.SET_NULL.name,
|
||||
"action": DeleteAction.SET_NULL.value,
|
||||
}
|
||||
],
|
||||
)
|
||||
|
@ -19,6 +19,7 @@ class GoogleWorkspaceProviderGroupSerializer(ModelSerializer):
|
||||
model = GoogleWorkspaceProviderGroup
|
||||
fields = [
|
||||
"id",
|
||||
"google_id",
|
||||
"group",
|
||||
"group_obj",
|
||||
"provider",
|
||||
|
@ -19,6 +19,7 @@ class GoogleWorkspaceProviderUserSerializer(ModelSerializer):
|
||||
model = GoogleWorkspaceProviderUser
|
||||
fields = [
|
||||
"id",
|
||||
"google_id",
|
||||
"user",
|
||||
"user_obj",
|
||||
"provider",
|
||||
|
@ -92,12 +92,14 @@ class GoogleWorkspaceGroupClient(
|
||||
google_group = self.to_schema(group, connection)
|
||||
self.check_email_valid(google_group["email"])
|
||||
try:
|
||||
return self._request(
|
||||
response = self._request(
|
||||
self.directory_service.groups().update(
|
||||
groupKey=connection.google_id,
|
||||
body=google_group,
|
||||
)
|
||||
)
|
||||
connection.attributes = response
|
||||
connection.save()
|
||||
except NotFoundSyncException:
|
||||
# Resource missing is handled by self.write, which will re-create the group
|
||||
raise
|
||||
|
@ -88,9 +88,11 @@ class GoogleWorkspaceUserClient(GoogleWorkspaceSyncClient[User, GoogleWorkspaceP
|
||||
self.check_email_valid(
|
||||
google_user["primaryEmail"], *[x["address"] for x in google_user.get("emails", [])]
|
||||
)
|
||||
self._request(
|
||||
response = self._request(
|
||||
self.directory_service.users().update(userKey=connection.google_id, body=google_user)
|
||||
)
|
||||
connection.attributes = response
|
||||
connection.save()
|
||||
|
||||
def discover(self):
|
||||
"""Iterate through all users and connect them with authentik users if possible"""
|
||||
|
@ -19,6 +19,7 @@ class MicrosoftEntraProviderGroupSerializer(ModelSerializer):
|
||||
model = MicrosoftEntraProviderGroup
|
||||
fields = [
|
||||
"id",
|
||||
"microsoft_id",
|
||||
"group",
|
||||
"group_obj",
|
||||
"provider",
|
||||
|
@ -19,6 +19,7 @@ class MicrosoftEntraProviderUserSerializer(ModelSerializer):
|
||||
model = MicrosoftEntraProviderUser
|
||||
fields = [
|
||||
"id",
|
||||
"microsoft_id",
|
||||
"user",
|
||||
"user_obj",
|
||||
"provider",
|
||||
|
@ -23,6 +23,7 @@ from msgraph.graph_service_client import GraphServiceClient
|
||||
from msgraph_core import GraphClientFactory
|
||||
|
||||
from authentik.enterprise.providers.microsoft_entra.models import MicrosoftEntraProvider
|
||||
from authentik.events.utils import sanitize_item
|
||||
from authentik.lib.sync.outgoing import HTTP_CONFLICT
|
||||
from authentik.lib.sync.outgoing.base import BaseOutgoingSyncClient
|
||||
from authentik.lib.sync.outgoing.exceptions import (
|
||||
@ -106,4 +107,4 @@ class MicrosoftEntraSyncClient[TModel: Model, TConnection: Model, TSchema: dict]
|
||||
we can't JSON serialize"""
|
||||
raw_data = asdict(entity)
|
||||
raw_data.pop("backing_store", None)
|
||||
return raw_data
|
||||
return sanitize_item(raw_data)
|
||||
|
@ -1,3 +1,4 @@
|
||||
from deepmerge import always_merger
|
||||
from django.db import transaction
|
||||
from msgraph.generated.groups.groups_request_builder import GroupsRequestBuilder
|
||||
from msgraph.generated.models.group import Group as MSGroup
|
||||
@ -104,9 +105,12 @@ class MicrosoftEntraGroupClient(
|
||||
microsoft_group = self.to_schema(group, connection)
|
||||
microsoft_group.id = connection.microsoft_id
|
||||
try:
|
||||
return self._request(
|
||||
response = self._request(
|
||||
self.client.groups.by_group_id(connection.microsoft_id).patch(microsoft_group)
|
||||
)
|
||||
if response:
|
||||
always_merger.merge(connection.attributes, self.entity_as_dict(response))
|
||||
connection.save()
|
||||
except NotFoundSyncException:
|
||||
# Resource missing is handled by self.write, which will re-create the group
|
||||
raise
|
||||
|
@ -1,3 +1,4 @@
|
||||
from deepmerge import always_merger
|
||||
from django.db import transaction
|
||||
from msgraph.generated.models.user import User as MSUser
|
||||
from msgraph.generated.users.users_request_builder import UsersRequestBuilder
|
||||
@ -110,7 +111,12 @@ class MicrosoftEntraUserClient(MicrosoftEntraSyncClient[User, MicrosoftEntraProv
|
||||
"""Update existing user"""
|
||||
microsoft_user = self.to_schema(user, connection)
|
||||
self.check_email_valid(microsoft_user.user_principal_name)
|
||||
self._request(self.client.users.by_user_id(connection.microsoft_id).patch(microsoft_user))
|
||||
response = self._request(
|
||||
self.client.users.by_user_id(connection.microsoft_id).patch(microsoft_user)
|
||||
)
|
||||
if response:
|
||||
always_merger.merge(connection.attributes, self.entity_as_dict(response))
|
||||
connection.save()
|
||||
|
||||
def discover(self):
|
||||
"""Iterate through all users and connect them with authentik users if possible"""
|
||||
|
@ -102,6 +102,8 @@ def get_logger_config():
|
||||
"gunicorn": "INFO",
|
||||
"requests_mock": "WARNING",
|
||||
"hpack": "WARNING",
|
||||
"httpx": "WARNING",
|
||||
"azure": "WARNING",
|
||||
}
|
||||
for handler_name, level in handler_level_map.items():
|
||||
base_config["loggers"][handler_name] = {
|
||||
|
@ -57,6 +57,8 @@ class PropertyMappingManager:
|
||||
mapping.set_context(user, request, **kwargs)
|
||||
try:
|
||||
value = mapping.evaluate(mapping.model.expression)
|
||||
except PropertyMappingExpressionException as exc:
|
||||
raise exc from exc
|
||||
except Exception as exc:
|
||||
raise PropertyMappingExpressionException(exc, mapping.model) from exc
|
||||
if value is None:
|
||||
|
@ -91,10 +91,9 @@ class BaseOutgoingSyncClient[
|
||||
}
|
||||
eval_kwargs.setdefault("user", None)
|
||||
for value in self.mapper.iter_eval(**eval_kwargs):
|
||||
try:
|
||||
always_merger.merge(raw_final_object, value)
|
||||
except SkipObjectException as exc:
|
||||
raise exc from exc
|
||||
always_merger.merge(raw_final_object, value)
|
||||
except SkipObjectException as exc:
|
||||
raise exc from exc
|
||||
except PropertyMappingExpressionException as exc:
|
||||
# Value error can be raised when assigning invalid data to an attribute
|
||||
Event.new(
|
||||
@ -104,7 +103,7 @@ class BaseOutgoingSyncClient[
|
||||
).save()
|
||||
raise StopSync(exc, obj, exc.mapping) from exc
|
||||
if not raw_final_object:
|
||||
raise StopSync(ValueError("No user mappings configured"), obj)
|
||||
raise StopSync(ValueError("No mappings configured"), obj)
|
||||
for key, value in defaults.items():
|
||||
raw_final_object.setdefault(key, value)
|
||||
return raw_final_object
|
||||
|
@ -14,6 +14,7 @@ from authentik.core.models import Group, User
|
||||
from authentik.events.logs import LogEvent
|
||||
from authentik.events.models import TaskStatus
|
||||
from authentik.events.system_tasks import SystemTask
|
||||
from authentik.events.utils import sanitize_item
|
||||
from authentik.lib.sync.outgoing import PAGE_SIZE, PAGE_TIMEOUT
|
||||
from authentik.lib.sync.outgoing.base import Direction
|
||||
from authentik.lib.sync.outgoing.exceptions import (
|
||||
@ -125,6 +126,7 @@ class SyncTasks:
|
||||
try:
|
||||
client.write(obj)
|
||||
except SkipObjectException:
|
||||
self.logger.debug("skipping object due to SkipObject", obj=obj)
|
||||
continue
|
||||
except BadRequestSyncException as exc:
|
||||
self.logger.warning("failed to sync object", exc=exc, obj=obj)
|
||||
@ -144,8 +146,8 @@ class SyncTasks:
|
||||
)
|
||||
),
|
||||
log_level="warning",
|
||||
logger="",
|
||||
attributes={"arguments": exc.args[1:]},
|
||||
logger=f"{provider._meta.verbose_name}@{object_type}",
|
||||
attributes={"arguments": exc.args[1:], "obj": sanitize_item(obj)},
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -167,7 +169,8 @@ class SyncTasks:
|
||||
)
|
||||
),
|
||||
log_level="warning",
|
||||
logger="",
|
||||
logger=f"{provider._meta.verbose_name}@{object_type}",
|
||||
attributes={"obj": sanitize_item(obj)},
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -184,7 +187,8 @@ class SyncTasks:
|
||||
)
|
||||
),
|
||||
log_level="warning",
|
||||
logger="",
|
||||
logger=f"{provider._meta.verbose_name}@{object_type}",
|
||||
attributes={"obj": sanitize_item(obj)},
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -102,7 +102,7 @@ class EventMatcherPolicy(Policy):
|
||||
result = checker(request, event)
|
||||
if result is None:
|
||||
continue
|
||||
LOGGER.info(
|
||||
LOGGER.debug(
|
||||
"Event matcher check result",
|
||||
checker=checker.__name__,
|
||||
result=result,
|
||||
|
43
authentik/providers/scim/api/groups.py
Normal file
43
authentik/providers/scim/api/groups.py
Normal file
@ -0,0 +1,43 @@
|
||||
"""SCIMProviderGroup API Views"""
|
||||
|
||||
from rest_framework import mixins
|
||||
from rest_framework.serializers import ModelSerializer
|
||||
from rest_framework.viewsets import GenericViewSet
|
||||
|
||||
from authentik.core.api.used_by import UsedByMixin
|
||||
from authentik.core.api.users import UserGroupSerializer
|
||||
from authentik.providers.scim.models import SCIMProviderGroup
|
||||
|
||||
|
||||
class SCIMProviderGroupSerializer(ModelSerializer):
|
||||
"""SCIMProviderGroup Serializer"""
|
||||
|
||||
group_obj = UserGroupSerializer(source="group", read_only=True)
|
||||
|
||||
class Meta:
|
||||
|
||||
model = SCIMProviderGroup
|
||||
fields = [
|
||||
"id",
|
||||
"scim_id",
|
||||
"group",
|
||||
"group_obj",
|
||||
"provider",
|
||||
]
|
||||
|
||||
|
||||
class SCIMProviderGroupViewSet(
|
||||
mixins.CreateModelMixin,
|
||||
mixins.RetrieveModelMixin,
|
||||
mixins.DestroyModelMixin,
|
||||
UsedByMixin,
|
||||
mixins.ListModelMixin,
|
||||
GenericViewSet,
|
||||
):
|
||||
"""SCIMProviderGroup Viewset"""
|
||||
|
||||
queryset = SCIMProviderGroup.objects.all().select_related("group")
|
||||
serializer_class = SCIMProviderGroupSerializer
|
||||
filterset_fields = ["provider__id", "group__name", "group__group_uuid"]
|
||||
search_fields = ["provider__name", "group__name"]
|
||||
ordering = ["group__name"]
|
43
authentik/providers/scim/api/users.py
Normal file
43
authentik/providers/scim/api/users.py
Normal file
@ -0,0 +1,43 @@
|
||||
"""SCIMProviderUser API Views"""
|
||||
|
||||
from rest_framework import mixins
|
||||
from rest_framework.serializers import ModelSerializer
|
||||
from rest_framework.viewsets import GenericViewSet
|
||||
|
||||
from authentik.core.api.groups import GroupMemberSerializer
|
||||
from authentik.core.api.used_by import UsedByMixin
|
||||
from authentik.providers.scim.models import SCIMProviderUser
|
||||
|
||||
|
||||
class SCIMProviderUserSerializer(ModelSerializer):
|
||||
"""SCIMProviderUser Serializer"""
|
||||
|
||||
user_obj = GroupMemberSerializer(source="user", read_only=True)
|
||||
|
||||
class Meta:
|
||||
|
||||
model = SCIMProviderUser
|
||||
fields = [
|
||||
"id",
|
||||
"scim_id",
|
||||
"user",
|
||||
"user_obj",
|
||||
"provider",
|
||||
]
|
||||
|
||||
|
||||
class SCIMProviderUserViewSet(
|
||||
mixins.CreateModelMixin,
|
||||
mixins.RetrieveModelMixin,
|
||||
mixins.DestroyModelMixin,
|
||||
UsedByMixin,
|
||||
mixins.ListModelMixin,
|
||||
GenericViewSet,
|
||||
):
|
||||
"""SCIMProviderUser Viewset"""
|
||||
|
||||
queryset = SCIMProviderUser.objects.all().select_related("user")
|
||||
serializer_class = SCIMProviderUserSerializer
|
||||
filterset_fields = ["provider__id", "user__username", "user__id"]
|
||||
search_fields = ["provider__name", "user__username"]
|
||||
ordering = ["user__username"]
|
@ -19,13 +19,18 @@ from authentik.providers.scim.clients.exceptions import (
|
||||
)
|
||||
from authentik.providers.scim.clients.schema import SCIM_GROUP_SCHEMA, PatchRequest
|
||||
from authentik.providers.scim.clients.schema import Group as SCIMGroupSchema
|
||||
from authentik.providers.scim.models import SCIMGroup, SCIMMapping, SCIMProvider, SCIMUser
|
||||
from authentik.providers.scim.models import (
|
||||
SCIMMapping,
|
||||
SCIMProvider,
|
||||
SCIMProviderGroup,
|
||||
SCIMProviderUser,
|
||||
)
|
||||
|
||||
|
||||
class SCIMGroupClient(SCIMClient[Group, SCIMGroup, SCIMGroupSchema]):
|
||||
class SCIMGroupClient(SCIMClient[Group, SCIMProviderGroup, SCIMGroupSchema]):
|
||||
"""SCIM client for groups"""
|
||||
|
||||
connection_type = SCIMGroup
|
||||
connection_type = SCIMProviderGroup
|
||||
connection_type_query = "group"
|
||||
mapper: PropertyMappingManager
|
||||
|
||||
@ -37,7 +42,7 @@ class SCIMGroupClient(SCIMClient[Group, SCIMGroup, SCIMGroupSchema]):
|
||||
["group", "provider", "connection"],
|
||||
)
|
||||
|
||||
def to_schema(self, obj: Group, connection: SCIMGroup) -> SCIMGroupSchema:
|
||||
def to_schema(self, obj: Group, connection: SCIMProviderGroup) -> SCIMGroupSchema:
|
||||
"""Convert authentik user into SCIM"""
|
||||
raw_scim_group = super().to_schema(
|
||||
obj,
|
||||
@ -52,7 +57,7 @@ class SCIMGroupClient(SCIMClient[Group, SCIMGroup, SCIMGroupSchema]):
|
||||
scim_group.externalId = str(obj.pk)
|
||||
|
||||
users = list(obj.users.order_by("id").values_list("id", flat=True))
|
||||
connections = SCIMUser.objects.filter(provider=self.provider, user__pk__in=users)
|
||||
connections = SCIMProviderUser.objects.filter(provider=self.provider, user__pk__in=users)
|
||||
members = []
|
||||
for user in connections:
|
||||
members.append(
|
||||
@ -66,7 +71,7 @@ class SCIMGroupClient(SCIMClient[Group, SCIMGroup, SCIMGroupSchema]):
|
||||
|
||||
def delete(self, obj: Group):
|
||||
"""Delete group"""
|
||||
scim_group = SCIMGroup.objects.filter(provider=self.provider, group=obj).first()
|
||||
scim_group = SCIMProviderGroup.objects.filter(provider=self.provider, group=obj).first()
|
||||
if not scim_group:
|
||||
self.logger.debug("Group does not exist in SCIM, skipping")
|
||||
return None
|
||||
@ -88,9 +93,11 @@ class SCIMGroupClient(SCIMClient[Group, SCIMGroup, SCIMGroupSchema]):
|
||||
scim_id = response.get("id")
|
||||
if not scim_id or scim_id == "":
|
||||
raise StopSync("SCIM Response with missing or invalid `id`")
|
||||
return SCIMGroup.objects.create(provider=self.provider, group=group, scim_id=scim_id)
|
||||
return SCIMProviderGroup.objects.create(
|
||||
provider=self.provider, group=group, scim_id=scim_id
|
||||
)
|
||||
|
||||
def update(self, group: Group, connection: SCIMGroup):
|
||||
def update(self, group: Group, connection: SCIMProviderGroup):
|
||||
"""Update existing group"""
|
||||
scim_group = self.to_schema(group, connection)
|
||||
scim_group.id = connection.scim_id
|
||||
@ -158,16 +165,16 @@ class SCIMGroupClient(SCIMClient[Group, SCIMGroup, SCIMGroupSchema]):
|
||||
"""Add users in users_set to group"""
|
||||
if len(users_set) < 1:
|
||||
return
|
||||
scim_group = SCIMGroup.objects.filter(provider=self.provider, group=group).first()
|
||||
scim_group = SCIMProviderGroup.objects.filter(provider=self.provider, group=group).first()
|
||||
if not scim_group:
|
||||
self.logger.warning(
|
||||
"could not sync group membership, group does not exist", group=group
|
||||
)
|
||||
return
|
||||
user_ids = list(
|
||||
SCIMUser.objects.filter(user__pk__in=users_set, provider=self.provider).values_list(
|
||||
"scim_id", flat=True
|
||||
)
|
||||
SCIMProviderUser.objects.filter(
|
||||
user__pk__in=users_set, provider=self.provider
|
||||
).values_list("scim_id", flat=True)
|
||||
)
|
||||
if len(user_ids) < 1:
|
||||
return
|
||||
@ -184,16 +191,16 @@ class SCIMGroupClient(SCIMClient[Group, SCIMGroup, SCIMGroupSchema]):
|
||||
"""Remove users in users_set from group"""
|
||||
if len(users_set) < 1:
|
||||
return
|
||||
scim_group = SCIMGroup.objects.filter(provider=self.provider, group=group).first()
|
||||
scim_group = SCIMProviderGroup.objects.filter(provider=self.provider, group=group).first()
|
||||
if not scim_group:
|
||||
self.logger.warning(
|
||||
"could not sync group membership, group does not exist", group=group
|
||||
)
|
||||
return
|
||||
user_ids = list(
|
||||
SCIMUser.objects.filter(user__pk__in=users_set, provider=self.provider).values_list(
|
||||
"scim_id", flat=True
|
||||
)
|
||||
SCIMProviderUser.objects.filter(
|
||||
user__pk__in=users_set, provider=self.provider
|
||||
).values_list("scim_id", flat=True)
|
||||
)
|
||||
if len(user_ids) < 1:
|
||||
return
|
||||
|
@ -9,13 +9,13 @@ from authentik.policies.utils import delete_none_values
|
||||
from authentik.providers.scim.clients.base import SCIMClient
|
||||
from authentik.providers.scim.clients.schema import SCIM_USER_SCHEMA
|
||||
from authentik.providers.scim.clients.schema import User as SCIMUserSchema
|
||||
from authentik.providers.scim.models import SCIMMapping, SCIMProvider, SCIMUser
|
||||
from authentik.providers.scim.models import SCIMMapping, SCIMProvider, SCIMProviderUser
|
||||
|
||||
|
||||
class SCIMUserClient(SCIMClient[User, SCIMUser, SCIMUserSchema]):
|
||||
class SCIMUserClient(SCIMClient[User, SCIMProviderUser, SCIMUserSchema]):
|
||||
"""SCIM client for users"""
|
||||
|
||||
connection_type = SCIMUser
|
||||
connection_type = SCIMProviderUser
|
||||
connection_type_query = "user"
|
||||
mapper: PropertyMappingManager
|
||||
|
||||
@ -27,7 +27,7 @@ class SCIMUserClient(SCIMClient[User, SCIMUser, SCIMUserSchema]):
|
||||
["provider", "connection"],
|
||||
)
|
||||
|
||||
def to_schema(self, obj: User, connection: SCIMUser) -> SCIMUserSchema:
|
||||
def to_schema(self, obj: User, connection: SCIMProviderUser) -> SCIMUserSchema:
|
||||
"""Convert authentik user into SCIM"""
|
||||
raw_scim_user = super().to_schema(
|
||||
obj,
|
||||
@ -44,7 +44,7 @@ class SCIMUserClient(SCIMClient[User, SCIMUser, SCIMUserSchema]):
|
||||
|
||||
def delete(self, obj: User):
|
||||
"""Delete user"""
|
||||
scim_user = SCIMUser.objects.filter(provider=self.provider, user=obj).first()
|
||||
scim_user = SCIMProviderUser.objects.filter(provider=self.provider, user=obj).first()
|
||||
if not scim_user:
|
||||
self.logger.debug("User does not exist in SCIM, skipping")
|
||||
return None
|
||||
@ -66,9 +66,9 @@ class SCIMUserClient(SCIMClient[User, SCIMUser, SCIMUserSchema]):
|
||||
scim_id = response.get("id")
|
||||
if not scim_id or scim_id == "":
|
||||
raise StopSync("SCIM Response with missing or invalid `id`")
|
||||
return SCIMUser.objects.create(provider=self.provider, user=user, scim_id=scim_id)
|
||||
return SCIMProviderUser.objects.create(provider=self.provider, user=user, scim_id=scim_id)
|
||||
|
||||
def update(self, user: User, connection: SCIMUser):
|
||||
def update(self, user: User, connection: SCIMProviderUser):
|
||||
"""Update existing user"""
|
||||
scim_user = self.to_schema(user, connection)
|
||||
scim_user.id = connection.scim_id
|
||||
|
@ -0,0 +1,24 @@
|
||||
# Generated by Django 5.0.6 on 2024-06-04 07:45
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("authentik_core", "0035_alter_group_options_and_more"),
|
||||
("authentik_providers_scim", "0007_scimgroup_scim_id_scimuser_scim_id_and_more"),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RenameModel(
|
||||
old_name="SCIMGroup",
|
||||
new_name="SCIMProviderGroup",
|
||||
),
|
||||
migrations.RenameModel(
|
||||
old_name="SCIMUser",
|
||||
new_name="SCIMProviderUser",
|
||||
),
|
||||
]
|
@ -10,6 +10,7 @@ from django.utils.translation import gettext_lazy as _
|
||||
from rest_framework.serializers import Serializer
|
||||
|
||||
from authentik.core.models import BackchannelProvider, Group, PropertyMapping, User, UserTypes
|
||||
from authentik.lib.models import SerializerModel
|
||||
from authentik.lib.sync.outgoing.base import BaseOutgoingSyncClient
|
||||
from authentik.lib.sync.outgoing.models import OutgoingSyncProvider
|
||||
|
||||
@ -106,7 +107,7 @@ class SCIMMapping(PropertyMapping):
|
||||
verbose_name_plural = _("SCIM Mappings")
|
||||
|
||||
|
||||
class SCIMUser(models.Model):
|
||||
class SCIMProviderUser(SerializerModel):
|
||||
"""Mapping of a user and provider to a SCIM user ID"""
|
||||
|
||||
id = models.UUIDField(primary_key=True, editable=False, default=uuid4)
|
||||
@ -114,14 +115,20 @@ class SCIMUser(models.Model):
|
||||
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
provider = models.ForeignKey(SCIMProvider, on_delete=models.CASCADE)
|
||||
|
||||
@property
|
||||
def serializer(self) -> type[Serializer]:
|
||||
from authentik.providers.scim.api.users import SCIMProviderUserSerializer
|
||||
|
||||
return SCIMProviderUserSerializer
|
||||
|
||||
class Meta:
|
||||
unique_together = (("scim_id", "user", "provider"),)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"SCIM User {self.user_id} to {self.provider_id}"
|
||||
return f"SCIM Provider User {self.user_id} to {self.provider_id}"
|
||||
|
||||
|
||||
class SCIMGroup(models.Model):
|
||||
class SCIMProviderGroup(SerializerModel):
|
||||
"""Mapping of a group and provider to a SCIM user ID"""
|
||||
|
||||
id = models.UUIDField(primary_key=True, editable=False, default=uuid4)
|
||||
@ -129,8 +136,14 @@ class SCIMGroup(models.Model):
|
||||
group = models.ForeignKey(Group, on_delete=models.CASCADE)
|
||||
provider = models.ForeignKey(SCIMProvider, on_delete=models.CASCADE)
|
||||
|
||||
@property
|
||||
def serializer(self) -> type[Serializer]:
|
||||
from authentik.providers.scim.api.groups import SCIMProviderGroupSerializer
|
||||
|
||||
return SCIMProviderGroupSerializer
|
||||
|
||||
class Meta:
|
||||
unique_together = (("scim_id", "group", "provider"),)
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"SCIM Group {self.group_id} to {self.provider_id}"
|
||||
return f"SCIM Provider Group {self.group_id} to {self.provider_id}"
|
||||
|
@ -1,9 +1,17 @@
|
||||
"""API URLs"""
|
||||
|
||||
from authentik.providers.scim.api.groups import (
|
||||
SCIMProviderGroupViewSet,
|
||||
)
|
||||
from authentik.providers.scim.api.property_mappings import SCIMMappingViewSet
|
||||
from authentik.providers.scim.api.providers import SCIMProviderViewSet
|
||||
from authentik.providers.scim.api.users import (
|
||||
SCIMProviderUserViewSet,
|
||||
)
|
||||
|
||||
api_urlpatterns = [
|
||||
("providers/scim", SCIMProviderViewSet),
|
||||
("providers/scim_users", SCIMProviderUserViewSet),
|
||||
("providers/scim_groups", SCIMProviderGroupViewSet),
|
||||
("propertymappings/scim", SCIMMappingViewSet),
|
||||
]
|
||||
|
@ -25,7 +25,7 @@ class ObjectFilter(ObjectPermissionsFilter):
|
||||
# Outposts (which are the only objects using internal service accounts)
|
||||
# except requests to return an empty list when they have no objects
|
||||
# assigned
|
||||
if request.user.type == UserTypes.INTERNAL_SERVICE_ACCOUNT:
|
||||
if getattr(request.user, "type", None) == UserTypes.INTERNAL_SERVICE_ACCOUNT:
|
||||
return queryset
|
||||
if not queryset.exists():
|
||||
# User doesn't have direct permission to all objects
|
||||
|
@ -147,3 +147,11 @@ class TestAPIPerms(APITestCase):
|
||||
},
|
||||
)
|
||||
self.assertEqual(res.status_code, 403)
|
||||
|
||||
def test_anonymous_user_denied(self):
|
||||
"""Test anonymous user denied"""
|
||||
res = self.client.get(reverse("authentik_api:invitation-list"))
|
||||
self.assertEqual(res.status_code, 403)
|
||||
|
||||
res = self.client.get(reverse("authentik_api:user-detail", kwargs={"pk": self.user.pk}))
|
||||
self.assertEqual(res.status_code, 403)
|
||||
|
@ -5,6 +5,7 @@ from hashlib import sha512
|
||||
from time import perf_counter, time
|
||||
from typing import Any
|
||||
|
||||
from channels.exceptions import DenyConnection
|
||||
from django.conf import settings
|
||||
from django.contrib.sessions.backends.base import UpdateError
|
||||
from django.contrib.sessions.exceptions import SessionInterrupted
|
||||
@ -271,7 +272,11 @@ class ChannelsLoggingMiddleware:
|
||||
|
||||
async def __call__(self, scope, receive, send):
|
||||
self.log(scope)
|
||||
return await self.inner(scope, receive, send)
|
||||
try:
|
||||
return await self.inner(scope, receive, send)
|
||||
except Exception as exc:
|
||||
LOGGER.warning("Exception in ASGI application", exc=exc)
|
||||
raise DenyConnection() from None
|
||||
|
||||
def log(self, scope: dict, **kwargs):
|
||||
"""Log request"""
|
||||
|
@ -161,19 +161,18 @@ class BaseLDAPSynchronizer:
|
||||
dn=object_dn,
|
||||
source=self._source,
|
||||
):
|
||||
try:
|
||||
if isinstance(value, (bytes)):
|
||||
self._logger.warning("property mapping returned bytes", mapping=mapping)
|
||||
continue
|
||||
object_field = mapping.object_field
|
||||
if object_field.startswith("attributes."):
|
||||
# Because returning a list might desired, we can't
|
||||
# rely on flatten here. Instead, just save the result as-is
|
||||
set_path_in_dict(properties, object_field, value)
|
||||
else:
|
||||
properties[object_field] = flatten(value)
|
||||
except SkipObjectException as exc:
|
||||
raise exc from exc
|
||||
if isinstance(value, (bytes)):
|
||||
self._logger.warning("property mapping returned bytes", mapping=mapping)
|
||||
continue
|
||||
object_field = mapping.object_field
|
||||
if object_field.startswith("attributes."):
|
||||
# Because returning a list might desired, we can't
|
||||
# rely on flatten here. Instead, just save the result as-is
|
||||
set_path_in_dict(properties, object_field, value)
|
||||
else:
|
||||
properties[object_field] = flatten(value)
|
||||
except SkipObjectException as exc:
|
||||
raise exc from exc
|
||||
except PropertyMappingExpressionException as exc:
|
||||
# Value error can be raised when assigning invalid data to an attribute
|
||||
Event.new(
|
||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -12,7 +12,15 @@ class CaptchaStageSerializer(StageSerializer):
|
||||
|
||||
class Meta:
|
||||
model = CaptchaStage
|
||||
fields = StageSerializer.Meta.fields + ["public_key", "private_key", "js_url", "api_url"]
|
||||
fields = StageSerializer.Meta.fields + [
|
||||
"public_key",
|
||||
"private_key",
|
||||
"js_url",
|
||||
"api_url",
|
||||
"score_min_threshold",
|
||||
"score_max_threshold",
|
||||
"error_on_invalid_score",
|
||||
]
|
||||
extra_kwargs = {"private_key": {"write_only": True}}
|
||||
|
||||
|
||||
|
@ -0,0 +1,31 @@
|
||||
# Generated by Django 5.0.6 on 2024-06-03 15:18
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
("authentik_stages_captcha", "0002_captchastage_api_url_captchastage_js_url_and_more"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name="captchastage",
|
||||
name="error_on_invalid_score",
|
||||
field=models.BooleanField(
|
||||
default=True,
|
||||
help_text="When enabled and the received captcha score is outside of the given threshold, the stage will show an error message. When not enabled, the flow will continue, but the data from the captcha will be available in the context for policy decisions",
|
||||
),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="captchastage",
|
||||
name="score_max_threshold",
|
||||
field=models.FloatField(default=1.0),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name="captchastage",
|
||||
name="score_min_threshold",
|
||||
field=models.FloatField(default=0.5),
|
||||
),
|
||||
]
|
@ -14,6 +14,18 @@ class CaptchaStage(Stage):
|
||||
public_key = models.TextField(help_text=_("Public key, acquired your captcha Provider."))
|
||||
private_key = models.TextField(help_text=_("Private key, acquired your captcha Provider."))
|
||||
|
||||
score_min_threshold = models.FloatField(default=0.5) # Default values for reCaptcha
|
||||
score_max_threshold = models.FloatField(default=1.0) # Default values for reCaptcha
|
||||
|
||||
error_on_invalid_score = models.BooleanField(
|
||||
default=True,
|
||||
help_text=_(
|
||||
"When enabled and the received captcha score is outside of the given threshold, "
|
||||
"the stage will show an error message. When not enabled, the flow will continue, "
|
||||
"but the data from the captcha will be available in the context for policy decisions"
|
||||
),
|
||||
)
|
||||
|
||||
js_url = models.TextField(default="https://www.recaptcha.net/recaptcha/api.js")
|
||||
api_url = models.TextField(default="https://www.recaptcha.net/recaptcha/api/siteverify")
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
"""authentik captcha stage"""
|
||||
|
||||
from django.http.response import HttpResponse
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
from requests import RequestException
|
||||
from rest_framework.fields import CharField
|
||||
from rest_framework.serializers import ValidationError
|
||||
@ -16,6 +17,8 @@ from authentik.lib.utils.http import get_http_session
|
||||
from authentik.root.middleware import ClientIPMiddleware
|
||||
from authentik.stages.captcha.models import CaptchaStage
|
||||
|
||||
PLAN_CONTEXT_CAPTCHA = "captcha"
|
||||
|
||||
|
||||
class CaptchaChallenge(WithUserInfoChallenge):
|
||||
"""Site public key"""
|
||||
@ -48,11 +51,24 @@ class CaptchaChallengeResponse(ChallengeResponse):
|
||||
)
|
||||
response.raise_for_status()
|
||||
data = response.json()
|
||||
if not data.get("success", False):
|
||||
raise ValidationError(f"Failed to validate token: {data.get('error-codes', '')}")
|
||||
except RequestException as exc:
|
||||
raise ValidationError("Failed to validate token") from exc
|
||||
return token
|
||||
if stage.error_on_invalid_score:
|
||||
if not data.get("success", False):
|
||||
raise ValidationError(
|
||||
_(
|
||||
"Failed to validate token: {error}".format(
|
||||
error=data.get("error-codes", _("Unknown error"))
|
||||
)
|
||||
)
|
||||
)
|
||||
if "score" in data:
|
||||
score = float(data.get("score"))
|
||||
if stage.score_max_threshold > -1 and score > stage.score_max_threshold:
|
||||
raise ValidationError(_("Invalid captcha response"))
|
||||
if stage.score_min_threshold > -1 and score < stage.score_min_threshold:
|
||||
raise ValidationError(_("Invalid captcha response"))
|
||||
except (RequestException, TypeError) as exc:
|
||||
raise ValidationError(_("Failed to validate token")) from exc
|
||||
return data
|
||||
|
||||
|
||||
class CaptchaStageView(ChallengeStageView):
|
||||
@ -69,5 +85,10 @@ class CaptchaStageView(ChallengeStageView):
|
||||
}
|
||||
)
|
||||
|
||||
def challenge_valid(self, response: ChallengeResponse) -> HttpResponse:
|
||||
def challenge_valid(self, response: CaptchaChallengeResponse) -> HttpResponse:
|
||||
response = response.validated_data["token"]
|
||||
self.executor.plan.context[PLAN_CONTEXT_CAPTCHA] = {
|
||||
"response": response,
|
||||
"stage": self.executor.current_stage,
|
||||
}
|
||||
return self.executor.stage_ok()
|
||||
|
@ -1,6 +1,7 @@
|
||||
"""captcha tests"""
|
||||
|
||||
from django.urls import reverse
|
||||
from requests_mock import Mocker
|
||||
|
||||
from authentik.core.tests.utils import create_test_admin_user, create_test_flow
|
||||
from authentik.flows.markers import StageMarker
|
||||
@ -30,8 +31,89 @@ class TestCaptchaStage(FlowTestCase):
|
||||
)
|
||||
self.binding = FlowStageBinding.objects.create(target=self.flow, stage=self.stage, order=2)
|
||||
|
||||
def test_valid(self):
|
||||
@Mocker()
|
||||
def test_valid(self, mock: Mocker):
|
||||
"""Test valid captcha"""
|
||||
mock.post(
|
||||
"https://www.recaptcha.net/recaptcha/api/siteverify",
|
||||
json={
|
||||
"success": True,
|
||||
"score": 0.5,
|
||||
},
|
||||
)
|
||||
plan = FlowPlan(flow_pk=self.flow.pk.hex, bindings=[self.binding], markers=[StageMarker()])
|
||||
session = self.client.session
|
||||
session[SESSION_KEY_PLAN] = plan
|
||||
session.save()
|
||||
response = self.client.post(
|
||||
reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug}),
|
||||
{"token": "PASSED"},
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertStageRedirects(response, reverse("authentik_core:root-redirect"))
|
||||
|
||||
@Mocker()
|
||||
def test_invalid_score_high(self, mock: Mocker):
|
||||
"""Test invalid captcha (score too high)"""
|
||||
mock.post(
|
||||
"https://www.recaptcha.net/recaptcha/api/siteverify",
|
||||
json={
|
||||
"success": True,
|
||||
"score": 99,
|
||||
},
|
||||
)
|
||||
plan = FlowPlan(flow_pk=self.flow.pk.hex, bindings=[self.binding], markers=[StageMarker()])
|
||||
session = self.client.session
|
||||
session[SESSION_KEY_PLAN] = plan
|
||||
session.save()
|
||||
response = self.client.post(
|
||||
reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug}),
|
||||
{"token": "PASSED"},
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertStageResponse(
|
||||
response,
|
||||
component="ak-stage-captcha",
|
||||
response_errors={"token": [{"string": "Invalid captcha response", "code": "invalid"}]},
|
||||
)
|
||||
|
||||
@Mocker()
|
||||
def test_invalid_score_low(self, mock: Mocker):
|
||||
"""Test invalid captcha (score too low)"""
|
||||
mock.post(
|
||||
"https://www.recaptcha.net/recaptcha/api/siteverify",
|
||||
json={
|
||||
"success": True,
|
||||
"score": -3,
|
||||
},
|
||||
)
|
||||
plan = FlowPlan(flow_pk=self.flow.pk.hex, bindings=[self.binding], markers=[StageMarker()])
|
||||
session = self.client.session
|
||||
session[SESSION_KEY_PLAN] = plan
|
||||
session.save()
|
||||
response = self.client.post(
|
||||
reverse("authentik_api:flow-executor", kwargs={"flow_slug": self.flow.slug}),
|
||||
{"token": "PASSED"},
|
||||
)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertStageResponse(
|
||||
response,
|
||||
component="ak-stage-captcha",
|
||||
response_errors={"token": [{"string": "Invalid captcha response", "code": "invalid"}]},
|
||||
)
|
||||
|
||||
@Mocker()
|
||||
def test_invalid_score_low_continue(self, mock: Mocker):
|
||||
"""Test invalid captcha (score too low, but continue)"""
|
||||
self.stage.error_on_invalid_score = False
|
||||
self.stage.save()
|
||||
mock.post(
|
||||
"https://www.recaptcha.net/recaptcha/api/siteverify",
|
||||
json={
|
||||
"success": True,
|
||||
"score": -3,
|
||||
},
|
||||
)
|
||||
plan = FlowPlan(flow_pk=self.flow.pk.hex, bindings=[self.binding], markers=[StageMarker()])
|
||||
session = self.client.session
|
||||
session[SESSION_KEY_PLAN] = plan
|
||||
|
@ -96,7 +96,7 @@ class TestEmailStageTemplates(FlowTestCase):
|
||||
"""Test addresses are correctly parsed"""
|
||||
message = TemplateEmailMessage(to=[("foo@bar.baz", "foo@bar.baz")])
|
||||
[sanitize_address(addr, "utf-8") for addr in message.recipients()]
|
||||
self.assertEqual(message.recipients(), ["foo@bar.baz"])
|
||||
self.assertEqual(message.recipients(), ['"foo@bar.baz" <foo@bar.baz>'])
|
||||
message = TemplateEmailMessage(to=[("some-name", "foo@bar.baz")])
|
||||
[sanitize_address(addr, "utf-8") for addr in message.recipients()]
|
||||
self.assertEqual(message.recipients(), ["some-name <foo@bar.baz>"])
|
||||
|
@ -5,6 +5,7 @@ from functools import lru_cache
|
||||
from pathlib import Path
|
||||
|
||||
from django.core.mail import EmailMultiAlternatives
|
||||
from django.core.mail.message import sanitize_address
|
||||
from django.template.exceptions import TemplateDoesNotExist
|
||||
from django.template.loader import render_to_string
|
||||
from django.utils import translation
|
||||
@ -31,10 +32,7 @@ class TemplateEmailMessage(EmailMultiAlternatives):
|
||||
sanitized_to = []
|
||||
# Ensure that all recipients are valid
|
||||
for recipient_name, recipient_email in to:
|
||||
if recipient_name == recipient_email:
|
||||
sanitized_to.append(recipient_email)
|
||||
else:
|
||||
sanitized_to.append(f"{recipient_name} <{recipient_email}>")
|
||||
sanitized_to.append(sanitize_address((recipient_name, recipient_email), "utf-8"))
|
||||
super().__init__(to=sanitized_to, **kwargs)
|
||||
if not template_name:
|
||||
return
|
||||
|
@ -6164,6 +6164,19 @@
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"title": "Api url"
|
||||
},
|
||||
"score_min_threshold": {
|
||||
"type": "number",
|
||||
"title": "Score min threshold"
|
||||
},
|
||||
"score_max_threshold": {
|
||||
"type": "number",
|
||||
"title": "Score max threshold"
|
||||
},
|
||||
"error_on_invalid_score": {
|
||||
"type": "boolean",
|
||||
"title": "Error on invalid score",
|
||||
"description": "When enabled and the received captcha score is outside of the given threshold, the stage will show an error message. When not enabled, the flow will continue, but the data from the captcha will be available in the context for policy decisions"
|
||||
}
|
||||
},
|
||||
"required": []
|
||||
|
@ -9,8 +9,9 @@ entries:
|
||||
model: authentik_providers_google_workspace.googleworkspaceprovidermapping
|
||||
attrs:
|
||||
name: "authentik default Google Workspace Mapping: User"
|
||||
# https://developers.google.com/admin-sdk/directory/reference/rest/v1/users#User
|
||||
expression: |
|
||||
# Field reference:
|
||||
# https://developers.google.com/admin-sdk/directory/reference/rest/v1/users#User
|
||||
# Google require givenName and familyName to be set
|
||||
givenName, familyName = request.user.name, " "
|
||||
formatted = request.user.name + " "
|
||||
@ -20,23 +21,26 @@ entries:
|
||||
if " " in request.user.name:
|
||||
givenName, _, familyName = request.user.name.partition(" ")
|
||||
formatted = request.user.name
|
||||
return {
|
||||
user = {
|
||||
"name": {
|
||||
"fullName": formatted,
|
||||
"familyName": familyName.strip(),
|
||||
"givenName": givenName.strip(),
|
||||
"displayName": formatted,
|
||||
},
|
||||
"password": request.user.password,
|
||||
"suspended": not request.user.is_active,
|
||||
}
|
||||
if not connection:
|
||||
user["password"] = request.user.password
|
||||
return user
|
||||
- identifiers:
|
||||
managed: goauthentik.io/providers/google_workspace/group
|
||||
model: authentik_providers_google_workspace.googleworkspaceprovidermapping
|
||||
attrs:
|
||||
name: "authentik default Google Workspace Mapping: Group"
|
||||
# https://developers.google.com/admin-sdk/directory/reference/rest/v1/groups#Group
|
||||
expression: |
|
||||
# Field reference:
|
||||
# https://developers.google.com/admin-sdk/directory/reference/rest/v1/groups#Group
|
||||
return {
|
||||
"name": group.name,
|
||||
}
|
||||
|
@ -9,8 +9,9 @@ entries:
|
||||
model: authentik_providers_microsoft_entra.microsoftentraprovidermapping
|
||||
attrs:
|
||||
name: "authentik default Microsoft Entra Mapping: User"
|
||||
# https://learn.microsoft.com/en-us/graph/api/resources/user?view=graph-rest-1.0
|
||||
expression: |
|
||||
# Field reference: (note that keys have to converted to snake_case)
|
||||
# https://learn.microsoft.com/en-us/graph/api/resources/user?view=graph-rest-1.0
|
||||
from msgraph.generated.models.password_profile import PasswordProfile
|
||||
|
||||
user = {
|
||||
@ -35,8 +36,9 @@ entries:
|
||||
model: authentik_providers_microsoft_entra.microsoftentraprovidermapping
|
||||
attrs:
|
||||
name: "authentik default Microsoft Entra Mapping: Group"
|
||||
# https://learn.microsoft.com/en-us/graph/api/group-post-groups?view=graph-rest-1.0&tabs=http#request-body
|
||||
expression: |
|
||||
# Field reference: (note that keys have to converted to snake_case)
|
||||
# https://learn.microsoft.com/en-us/graph/api/group-post-groups?view=graph-rest-1.0&tabs=http#request-body
|
||||
return {
|
||||
"display_name": group.name,
|
||||
"mail_enabled": False,
|
||||
|
8
go.mod
8
go.mod
@ -16,21 +16,21 @@ require (
|
||||
github.com/gorilla/mux v1.8.1
|
||||
github.com/gorilla/securecookie v1.1.2
|
||||
github.com/gorilla/sessions v1.2.2
|
||||
github.com/gorilla/websocket v1.5.1
|
||||
github.com/gorilla/websocket v1.5.2
|
||||
github.com/jellydator/ttlcache/v3 v3.2.0
|
||||
github.com/mitchellh/mapstructure v1.5.0
|
||||
github.com/nmcclain/asn1-ber v0.0.0-20170104154839-2661553a0484
|
||||
github.com/pires/go-proxyproto v0.7.0
|
||||
github.com/prometheus/client_golang v1.19.1
|
||||
github.com/redis/go-redis/v9 v9.5.2
|
||||
github.com/redis/go-redis/v9 v9.5.3
|
||||
github.com/sethvargo/go-envconfig v1.0.3
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
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.2024042.9
|
||||
goauthentik.io/api/v3 v3.2024042.11
|
||||
golang.org/x/exp v0.0.0-20230210204819-062eb4c674ab
|
||||
golang.org/x/oauth2 v0.20.0
|
||||
golang.org/x/oauth2 v0.21.0
|
||||
golang.org/x/sync v0.7.0
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
layeh.com/radius v0.0.0-20210819152912-ad72663a72ab
|
||||
|
16
go.sum
16
go.sum
@ -176,8 +176,8 @@ github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/z
|
||||
github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTjY=
|
||||
github.com/gorilla/sessions v1.2.2/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ=
|
||||
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
|
||||
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
|
||||
github.com/gorilla/websocket v1.5.2 h1:qoW6V1GT3aZxybsbC6oLnailWnB+qTMVwMreOso9XUw=
|
||||
github.com/gorilla/websocket v1.5.2/go.mod h1:0n9H61RBAcf5/38py2MCYbxzPIY9rOkpvvMT24Rqs30=
|
||||
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
|
||||
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
@ -242,8 +242,8 @@ github.com/prometheus/common v0.48.0 h1:QO8U2CdOzSn1BBsmXJXduaaW+dY/5QLjfB8svtSz
|
||||
github.com/prometheus/common v0.48.0/go.mod h1:0/KsvlIEfPQCQ5I2iNSAWKPZziNCvRs5EC6ILDTlAPc=
|
||||
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
|
||||
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
|
||||
github.com/redis/go-redis/v9 v9.5.2 h1:L0L3fcSNReTRGyZ6AqAEN0K56wYeYAwapBIhkvh0f3E=
|
||||
github.com/redis/go-redis/v9 v9.5.2/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
|
||||
github.com/redis/go-redis/v9 v9.5.3 h1:fOAp1/uJG+ZtcITgZOfYFmTKPE7n4Vclj1wZFgRciUU=
|
||||
github.com/redis/go-redis/v9 v9.5.3/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
||||
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
|
||||
@ -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.2024042.9 h1:zj3nqmOEHNBsfANTv7Ec4yLZA755GKHU+WLz2t+nfaI=
|
||||
goauthentik.io/api/v3 v3.2024042.9/go.mod h1:zz+mEZg8rY/7eEjkMGWJ2DnGqk+zqxuybGCGrR2O4Kw=
|
||||
goauthentik.io/api/v3 v3.2024042.11 h1:cGgUz1E8rlMphGvv04VI7i+MgT8eidZbxTpza5zd96I=
|
||||
goauthentik.io/api/v3 v3.2024042.11/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=
|
||||
@ -382,8 +382,8 @@ golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4Iltr
|
||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.20.0 h1:4mQdhULixXKP1rwYBW0vAijoXnkTG0BLCDRzfe1idMo=
|
||||
golang.org/x/oauth2 v0.20.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||
golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs=
|
||||
golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -38,7 +38,6 @@ func (cs *CryptoStore) AddKeypair(uuid string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cs.fingerprints[uuid] = cs.getFingerprint(uuid)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -73,6 +72,7 @@ func (cs *CryptoStore) Fetch(uuid string) error {
|
||||
return err
|
||||
}
|
||||
cs.certificates[uuid] = &x509cert
|
||||
cs.fingerprints[uuid] = cfp
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-06-03 00:08+0000\n"
|
||||
"POT-Creation-Date: 2024-06-05 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"
|
||||
@ -2363,6 +2363,14 @@ msgstr ""
|
||||
msgid "Private key, acquired your captcha Provider."
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/captcha/models.py
|
||||
msgid ""
|
||||
"When enabled and the received captcha score is outside of the given "
|
||||
"threshold, the stage will show an error message. When not enabled, the flow "
|
||||
"will continue, but the data from the captcha will be available in the "
|
||||
"context for policy decisions"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/captcha/models.py
|
||||
msgid "Captcha Stage"
|
||||
msgstr ""
|
||||
@ -2371,6 +2379,23 @@ msgstr ""
|
||||
msgid "Captcha Stages"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/captcha/stage.py
|
||||
msgid "Unknown error"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/captcha/stage.py
|
||||
#, python-brace-format
|
||||
msgid "Failed to validate token: {error}"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/captcha/stage.py
|
||||
msgid "Invalid captcha response"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/captcha/stage.py
|
||||
msgid "Failed to validate token"
|
||||
msgstr ""
|
||||
|
||||
#: authentik/stages/consent/models.py
|
||||
msgid ""
|
||||
"Offset after which consent expires. (Format: hours=1;minutes=2;seconds=3)."
|
||||
|
Binary file not shown.
@ -19,7 +19,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-06-05 00:07+0000\n"
|
||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||
"Last-Translator: Marc Schmitt, 2024\n"
|
||||
"Language-Team: French (https://app.transifex.com/authentik/teams/119923/fr/)\n"
|
||||
@ -106,12 +106,14 @@ msgid "Brands"
|
||||
msgstr "Marques"
|
||||
|
||||
#: authentik/core/api/providers.py
|
||||
msgid "SAML Provider from Metadata"
|
||||
msgstr "Fournisseur SAML depuis métadonnées"
|
||||
|
||||
#: authentik/core/api/providers.py
|
||||
msgid "Create a SAML Provider by importing its Metadata."
|
||||
msgstr "Créer un fournisseur SAML en important ses métadonnées."
|
||||
msgid ""
|
||||
"When not set all providers are returned. When set to true, only backchannel "
|
||||
"providers are returned. When set to false, backchannel providers are "
|
||||
"excluded"
|
||||
msgstr ""
|
||||
"Si non défini, tous les fournisseurs sont retournés. Si vrai, seul les "
|
||||
"fournisseurs backchannels sont retournés. Si faux, les fournisseurs "
|
||||
"backchannels sont exclus"
|
||||
|
||||
#: authentik/core/api/users.py
|
||||
msgid "No leading or trailing slashes allowed."
|
||||
@ -466,6 +468,74 @@ msgstr "Entreprise est requis pour accéder à cette fonctionnalité."
|
||||
msgid "Feature only accessible for internal users."
|
||||
msgstr "Fonctionnalité accessible aux utilisateurs internes uniquement."
|
||||
|
||||
#: authentik/enterprise/providers/google_workspace/models.py
|
||||
#: authentik/enterprise/providers/microsoft_entra/models.py
|
||||
#: authentik/providers/scim/models.py authentik/sources/ldap/models.py
|
||||
msgid "Property mappings used for group creation/updating."
|
||||
msgstr ""
|
||||
"Mappages de propriétés utilisés lors de la création et de la mise à jour des"
|
||||
" groupes."
|
||||
|
||||
#: authentik/enterprise/providers/google_workspace/models.py
|
||||
msgid "Google Workspace Provider"
|
||||
msgstr "Fournisseur Google Workspace"
|
||||
|
||||
#: authentik/enterprise/providers/google_workspace/models.py
|
||||
msgid "Google Workspace Providers"
|
||||
msgstr "Fournisseurs Google Workspace"
|
||||
|
||||
#: authentik/enterprise/providers/google_workspace/models.py
|
||||
msgid "Google Workspace Provider Mapping"
|
||||
msgstr "Mappage de propriété Google Workspace"
|
||||
|
||||
#: authentik/enterprise/providers/google_workspace/models.py
|
||||
msgid "Google Workspace Provider Mappings"
|
||||
msgstr "Mappages de propriété Google Workspace"
|
||||
|
||||
#: authentik/enterprise/providers/google_workspace/models.py
|
||||
msgid "Google Workspace Provider User"
|
||||
msgstr "Utilisateur du fournisseur Google Workspace"
|
||||
|
||||
#: authentik/enterprise/providers/google_workspace/models.py
|
||||
msgid "Google Workspace Provider Users"
|
||||
msgstr "Utilisateurs du fournisseur Google Workspace"
|
||||
|
||||
#: authentik/enterprise/providers/google_workspace/models.py
|
||||
msgid "Google Workspace Provider Group"
|
||||
msgstr "Groupe du fournisseur Google Workspace"
|
||||
|
||||
#: authentik/enterprise/providers/google_workspace/models.py
|
||||
msgid "Google Workspace Provider Groups"
|
||||
msgstr "Groupes du fournisseur Google Workspace"
|
||||
|
||||
#: authentik/enterprise/providers/microsoft_entra/models.py
|
||||
msgid "Microsoft Entra Provider"
|
||||
msgstr "Fournisseur Microsoft Entra"
|
||||
|
||||
#: authentik/enterprise/providers/microsoft_entra/models.py
|
||||
msgid "Microsoft Entra Providers"
|
||||
msgstr "Fournisseurs Microsoft Entra"
|
||||
|
||||
#: authentik/enterprise/providers/microsoft_entra/models.py
|
||||
msgid "Microsoft Entra Provider Mapping"
|
||||
msgstr "Mappage de propriété Microsoft Entra"
|
||||
|
||||
#: authentik/enterprise/providers/microsoft_entra/models.py
|
||||
msgid "Microsoft Entra Provider Mappings"
|
||||
msgstr "Mappages de propriété Microsoft Entra"
|
||||
|
||||
#: authentik/enterprise/providers/microsoft_entra/models.py
|
||||
msgid "Microsoft Entra Provider User"
|
||||
msgstr "Utilisateur du fournisseur Microsoft Entra"
|
||||
|
||||
#: authentik/enterprise/providers/microsoft_entra/models.py
|
||||
msgid "Microsoft Entra Provider Group"
|
||||
msgstr "Groupe du fournisseur Microsoft Entra"
|
||||
|
||||
#: authentik/enterprise/providers/microsoft_entra/models.py
|
||||
msgid "Microsoft Entra Provider Groups"
|
||||
msgstr "Groupes du fournisseur Microsoft Entra"
|
||||
|
||||
#: authentik/enterprise/providers/rac/models.py
|
||||
#: authentik/stages/user_login/models.py
|
||||
msgid ""
|
||||
@ -838,6 +908,25 @@ msgstr "Jetons du flux"
|
||||
msgid "Invalid next URL"
|
||||
msgstr "URL suivante invalide"
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
msgid "Starting full provider sync"
|
||||
msgstr "Démarrage d'une synchronisation complète du fournisseur"
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
#, python-format
|
||||
msgid "Syncing page %(page)d of users"
|
||||
msgstr "Synchronisation de la page %(page)d d'utilisateurs"
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
#, python-format
|
||||
msgid "Syncing page %(page)d of groups"
|
||||
msgstr "Synchronisation de la page %(page)d de groupes"
|
||||
|
||||
#: authentik/lib/sync/outgoing/tasks.py
|
||||
#, python-brace-format
|
||||
msgid "Stopping sync due to error: {error}"
|
||||
msgstr "Arrêt de la synchronisation due à l'erreur : {error}"
|
||||
|
||||
#: authentik/lib/utils/time.py
|
||||
#, python-format
|
||||
msgid "%(value)s is not in the correct format of 'hours=3;minutes=1'."
|
||||
@ -1526,10 +1615,6 @@ msgstr "Compatibilité GitHub : accès aux adresses email"
|
||||
msgid "GitHub Compatibility: Access your Groups"
|
||||
msgstr "Compatibilité GitHub : accès aux groupes"
|
||||
|
||||
#: authentik/providers/oauth2/views/userinfo.py
|
||||
msgid "authentik API Access on behalf of your user"
|
||||
msgstr "Accès à l'API authentik au nom des utilisateurs"
|
||||
|
||||
#: authentik/providers/proxy/api.py
|
||||
msgid "User and password attributes must be set when basic auth is enabled."
|
||||
msgstr ""
|
||||
@ -1811,6 +1896,14 @@ msgstr "Mappages de propriétés SAML"
|
||||
msgid "SAML Property Mappings"
|
||||
msgstr "Mappages de propriétés SAML"
|
||||
|
||||
#: authentik/providers/saml/models.py
|
||||
msgid "SAML Provider from Metadata"
|
||||
msgstr "Fournisseur SAML depuis métadonnées"
|
||||
|
||||
#: authentik/providers/saml/models.py
|
||||
msgid "SAML Providers from Metadata"
|
||||
msgstr "Fournisseurs SAML depuis métadonnées"
|
||||
|
||||
#: authentik/providers/scim/models.py
|
||||
msgid "Base URL to SCIM requests, usually ends in /v2"
|
||||
msgstr "URL de base pour les requêtes SCIM, se terminant généralement par /v2"
|
||||
@ -1819,12 +1912,6 @@ msgstr "URL de base pour les requêtes SCIM, se terminant généralement par /v2
|
||||
msgid "Authentication token"
|
||||
msgstr "Jeton d'authentification"
|
||||
|
||||
#: authentik/providers/scim/models.py authentik/sources/ldap/models.py
|
||||
msgid "Property mappings used for group creation/updating."
|
||||
msgstr ""
|
||||
"Mappages de propriétés utilisés lors de la création et de la mise à jour des"
|
||||
" groupes."
|
||||
|
||||
#: authentik/providers/scim/models.py
|
||||
msgid "SCIM Provider"
|
||||
msgstr "Fournisseur SCIM"
|
||||
@ -1841,39 +1928,6 @@ msgstr "Mappage SCIM"
|
||||
msgid "SCIM Mappings"
|
||||
msgstr "Mappages SCIM"
|
||||
|
||||
#: authentik/providers/scim/tasks.py
|
||||
msgid "Starting full SCIM sync"
|
||||
msgstr "Démarrage d'une synchronisation SCIM complète"
|
||||
|
||||
#: authentik/providers/scim/tasks.py
|
||||
#, python-format
|
||||
msgid "Syncing page %(page)d of users"
|
||||
msgstr "Synchronisation de la page %(page)d d'utilisateurs"
|
||||
|
||||
#: authentik/providers/scim/tasks.py
|
||||
#, python-format
|
||||
msgid "Syncing page %(page)d of groups"
|
||||
msgstr "Synchronisation de la page %(page)d de groupes"
|
||||
|
||||
#: authentik/providers/scim/tasks.py
|
||||
#, python-brace-format
|
||||
msgid "Failed to sync user {user_name} due to remote error: {error}"
|
||||
msgstr ""
|
||||
"Échec de synchronisation de l'utilisateur {user_name} dû à une erreur "
|
||||
"distante : {error}"
|
||||
|
||||
#: authentik/providers/scim/tasks.py
|
||||
#, python-brace-format
|
||||
msgid "Stopping sync due to error: {error}"
|
||||
msgstr "Arrêt de la synchronisation due à l'erreur : {error}"
|
||||
|
||||
#: authentik/providers/scim/tasks.py
|
||||
#, python-brace-format
|
||||
msgid "Failed to sync group {group_name} due to remote error: {error}"
|
||||
msgstr ""
|
||||
"Échec de synchronisation du groupe {group_name} dû à une erreur distante : "
|
||||
"{error}"
|
||||
|
||||
#: authentik/rbac/models.py
|
||||
msgid "Role"
|
||||
msgstr "Rôle"
|
||||
@ -1894,14 +1948,6 @@ msgstr "Permissions système"
|
||||
msgid "Can view system info"
|
||||
msgstr "Peut voir les informations du système"
|
||||
|
||||
#: authentik/rbac/models.py
|
||||
msgid "Can view system tasks"
|
||||
msgstr "Peut voir les tâches du système"
|
||||
|
||||
#: authentik/rbac/models.py
|
||||
msgid "Can run system tasks"
|
||||
msgstr "Peut lancer des tâches système"
|
||||
|
||||
#: authentik/rbac/models.py
|
||||
msgid "Can access admin interface"
|
||||
msgstr "Peut accéder à l'interface d'administration"
|
||||
@ -2562,6 +2608,18 @@ msgstr "Clé publique, acquise auprès de votre fournisseur captcha."
|
||||
msgid "Private key, acquired your captcha Provider."
|
||||
msgstr "Clé privée, acquise auprès de votre fournisseur captcha."
|
||||
|
||||
#: authentik/stages/captcha/models.py
|
||||
msgid ""
|
||||
"When enabled and the received captcha score is outside of the given "
|
||||
"threshold, the stage will show an error message. When not enabled, the flow "
|
||||
"will continue, but the data from the captcha will be available in the "
|
||||
"context for policy decisions"
|
||||
msgstr ""
|
||||
"Si activé et le score captcha reçu est hors de la limite donnée, l'étape "
|
||||
"affichera un message d'erreur. Si désactivé, le flux continuera, mais la "
|
||||
"donnée du captcha sera disponible dans le contexte pour décision dans une "
|
||||
"politique."
|
||||
|
||||
#: authentik/stages/captcha/models.py
|
||||
msgid "Captcha Stage"
|
||||
msgstr "Étape de Captcha"
|
||||
@ -2570,6 +2628,23 @@ msgstr "Étape de Captcha"
|
||||
msgid "Captcha Stages"
|
||||
msgstr "Étapes de Captcha"
|
||||
|
||||
#: authentik/stages/captcha/stage.py
|
||||
msgid "Unknown error"
|
||||
msgstr "Erreur inconnue"
|
||||
|
||||
#: authentik/stages/captcha/stage.py
|
||||
#, python-brace-format
|
||||
msgid "Failed to validate token: {error}"
|
||||
msgstr "Échec de validation du jeton : {error}"
|
||||
|
||||
#: authentik/stages/captcha/stage.py
|
||||
msgid "Invalid captcha response"
|
||||
msgstr "Réponse captcha invalide"
|
||||
|
||||
#: authentik/stages/captcha/stage.py
|
||||
msgid "Failed to validate token"
|
||||
msgstr "Échec de validation du jeton"
|
||||
|
||||
#: authentik/stages/consent/models.py
|
||||
msgid ""
|
||||
"Offset after which consent expires. (Format: hours=1;minutes=2;seconds=3)."
|
||||
|
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@ -9,16 +9,16 @@
|
||||
# Nicholas Winterhalter, 2023
|
||||
# Ренат Шарафутдинов, 2023
|
||||
# Stepan Karavaev, 2024
|
||||
# Anton Babenko, 2024
|
||||
# Anton, 2024
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-06-03 00:08+0000\n"
|
||||
"POT-Creation-Date: 2024-06-05 00:07+0000\n"
|
||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||
"Last-Translator: Anton Babenko, 2024\n"
|
||||
"Last-Translator: Anton, 2024\n"
|
||||
"Language-Team: Russian (https://app.transifex.com/authentik/teams/119923/ru/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@ -162,7 +162,7 @@ msgstr "Сбросить пароль"
|
||||
|
||||
#: authentik/core/models.py
|
||||
msgid "Can impersonate other users"
|
||||
msgstr "Может выдавать себя за других пользователей"
|
||||
msgstr "Может имитировать других пользователей"
|
||||
|
||||
#: authentik/core/models.py authentik/rbac/models.py
|
||||
msgid "Can assign permissions to users"
|
||||
@ -2589,6 +2589,18 @@ msgstr "Открытый ключ, полученный от вашего про
|
||||
msgid "Private key, acquired your captcha Provider."
|
||||
msgstr "Закрытый ключ, полученный от вашего провайдера капчи."
|
||||
|
||||
#: authentik/stages/captcha/models.py
|
||||
msgid ""
|
||||
"When enabled and the received captcha score is outside of the given "
|
||||
"threshold, the stage will show an error message. When not enabled, the flow "
|
||||
"will continue, but the data from the captcha will be available in the "
|
||||
"context for policy decisions"
|
||||
msgstr ""
|
||||
"Когда эта опция включена, и полученная оценка капчи находится за пределами "
|
||||
"заданного порогового значения, на этом этапе будет показано сообщение об "
|
||||
"ошибке. Когда эта опция не включена, поток будет продолжаться, но данные "
|
||||
"капчи будут доступны в контексте для принятия решений политики"
|
||||
|
||||
#: authentik/stages/captcha/models.py
|
||||
msgid "Captcha Stage"
|
||||
msgstr "Этап с каптчей"
|
||||
@ -2597,6 +2609,23 @@ msgstr "Этап с каптчей"
|
||||
msgid "Captcha Stages"
|
||||
msgstr "Этапы с каптчей"
|
||||
|
||||
#: authentik/stages/captcha/stage.py
|
||||
msgid "Unknown error"
|
||||
msgstr "Неизвестная ошибка"
|
||||
|
||||
#: authentik/stages/captcha/stage.py
|
||||
#, python-brace-format
|
||||
msgid "Failed to validate token: {error}"
|
||||
msgstr "Ошибка валидации токена: {error}"
|
||||
|
||||
#: authentik/stages/captcha/stage.py
|
||||
msgid "Invalid captcha response"
|
||||
msgstr "Неверный ответ на капчу"
|
||||
|
||||
#: authentik/stages/captcha/stage.py
|
||||
msgid "Failed to validate token"
|
||||
msgstr "Ошибка валидации токена"
|
||||
|
||||
#: authentik/stages/consent/models.py
|
||||
msgid ""
|
||||
"Offset after which consent expires. (Format: hours=1;minutes=2;seconds=3)."
|
||||
@ -3054,7 +3083,7 @@ msgstr "Разделитель: Статическая разделительн
|
||||
#: authentik/stages/prompt/models.py
|
||||
msgid "Hidden: Hidden field, can be used to insert data into form."
|
||||
msgstr ""
|
||||
"Скрытый: Скрытое поле, может быть использовано для вставки данных в форму."
|
||||
"Скрыто: Скрытое поле, может быть использовано для вставки данных в форму."
|
||||
|
||||
#: authentik/stages/prompt/models.py
|
||||
msgid "Static: Static value, displayed as-is."
|
||||
@ -3086,7 +3115,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"По желанию предварительно заполните поле ввода начальным значением. При "
|
||||
"создании поля с фиксированным выбором включите интерпретацию как выражение и"
|
||||
" возврат списка, чтобы вернуть несколько вариантов по умолчанию."
|
||||
" возвращайте список, чтобы вернуть несколько вариантов по умолчанию."
|
||||
|
||||
#: authentik/stages/prompt/models.py
|
||||
msgid "Prompt"
|
||||
|
@ -7,17 +7,17 @@
|
||||
# Chen Zhikai, 2022
|
||||
# 刘松, 2022
|
||||
# Jens L. <jens@goauthentik.io>, 2024
|
||||
# deluxghost, 2024
|
||||
# Tianhao Chai <cth451@gmail.com>, 2024
|
||||
# deluxghost, 2024
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-06-03 00:08+0000\n"
|
||||
"POT-Creation-Date: 2024-06-05 00:07+0000\n"
|
||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||
"Last-Translator: Tianhao Chai <cth451@gmail.com>, 2024\n"
|
||||
"Last-Translator: deluxghost, 2024\n"
|
||||
"Language-Team: Chinese Simplified (https://app.transifex.com/authentik/teams/119923/zh-Hans/)\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
@ -2401,6 +2401,14 @@ msgstr "公钥,从您的验证码提供商处取得。"
|
||||
msgid "Private key, acquired your captcha Provider."
|
||||
msgstr "私钥,从您的验证码提供商处取得。"
|
||||
|
||||
#: authentik/stages/captcha/models.py
|
||||
msgid ""
|
||||
"When enabled and the received captcha score is outside of the given "
|
||||
"threshold, the stage will show an error message. When not enabled, the flow "
|
||||
"will continue, but the data from the captcha will be available in the "
|
||||
"context for policy decisions"
|
||||
msgstr "启用时,如果接收到的验证码分数超出给定的阈值,此阶段将显示错误信息。未启用时,流程会继续,但来自验证码的数据可在上下文中用于策略决定。"
|
||||
|
||||
#: authentik/stages/captcha/models.py
|
||||
msgid "Captcha Stage"
|
||||
msgstr "验证码阶段"
|
||||
@ -2409,6 +2417,23 @@ msgstr "验证码阶段"
|
||||
msgid "Captcha Stages"
|
||||
msgstr "验证码阶段"
|
||||
|
||||
#: authentik/stages/captcha/stage.py
|
||||
msgid "Unknown error"
|
||||
msgstr "未知错误"
|
||||
|
||||
#: authentik/stages/captcha/stage.py
|
||||
#, python-brace-format
|
||||
msgid "Failed to validate token: {error}"
|
||||
msgstr "验证令牌失败:{error}"
|
||||
|
||||
#: authentik/stages/captcha/stage.py
|
||||
msgid "Invalid captcha response"
|
||||
msgstr "验证码响应无效"
|
||||
|
||||
#: authentik/stages/captcha/stage.py
|
||||
msgid "Failed to validate token"
|
||||
msgstr "验证令牌失败"
|
||||
|
||||
#: authentik/stages/consent/models.py
|
||||
msgid ""
|
||||
"Offset after which consent expires. (Format: hours=1;minutes=2;seconds=3)."
|
||||
|
@ -14,7 +14,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2024-06-03 00:08+0000\n"
|
||||
"POT-Creation-Date: 2024-06-05 00:07+0000\n"
|
||||
"PO-Revision-Date: 2022-09-26 16:47+0000\n"
|
||||
"Last-Translator: deluxghost, 2024\n"
|
||||
"Language-Team: Chinese (China) (https://app.transifex.com/authentik/teams/119923/zh_CN/)\n"
|
||||
@ -2400,6 +2400,14 @@ msgstr "公钥,从您的验证码提供商处取得。"
|
||||
msgid "Private key, acquired your captcha Provider."
|
||||
msgstr "私钥,从您的验证码提供商处取得。"
|
||||
|
||||
#: authentik/stages/captcha/models.py
|
||||
msgid ""
|
||||
"When enabled and the received captcha score is outside of the given "
|
||||
"threshold, the stage will show an error message. When not enabled, the flow "
|
||||
"will continue, but the data from the captcha will be available in the "
|
||||
"context for policy decisions"
|
||||
msgstr "启用时,如果接收到的验证码分数超出给定的阈值,此阶段将显示错误信息。未启用时,流程会继续,但来自验证码的数据可在上下文中用于策略决定。"
|
||||
|
||||
#: authentik/stages/captcha/models.py
|
||||
msgid "Captcha Stage"
|
||||
msgstr "验证码阶段"
|
||||
@ -2408,6 +2416,23 @@ msgstr "验证码阶段"
|
||||
msgid "Captcha Stages"
|
||||
msgstr "验证码阶段"
|
||||
|
||||
#: authentik/stages/captcha/stage.py
|
||||
msgid "Unknown error"
|
||||
msgstr "未知错误"
|
||||
|
||||
#: authentik/stages/captcha/stage.py
|
||||
#, python-brace-format
|
||||
msgid "Failed to validate token: {error}"
|
||||
msgstr "验证令牌失败:{error}"
|
||||
|
||||
#: authentik/stages/captcha/stage.py
|
||||
msgid "Invalid captcha response"
|
||||
msgstr "验证码响应无效"
|
||||
|
||||
#: authentik/stages/captcha/stage.py
|
||||
msgid "Failed to validate token"
|
||||
msgstr "验证令牌失败"
|
||||
|
||||
#: authentik/stages/consent/models.py
|
||||
msgid ""
|
||||
"Offset after which consent expires. (Format: hours=1;minutes=2;seconds=3)."
|
||||
|
348
poetry.lock
generated
348
poetry.lock
generated
@ -1,4 +1,4 @@
|
||||
# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand.
|
||||
# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand.
|
||||
|
||||
[[package]]
|
||||
name = "aiohttp"
|
||||
@ -336,13 +336,13 @@ aio = ["aiohttp (>=3.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "azure-identity"
|
||||
version = "1.16.0"
|
||||
version = "1.16.1"
|
||||
description = "Microsoft Azure Identity Library for Python"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "azure-identity-1.16.0.tar.gz", hash = "sha256:6ff1d667cdcd81da1ceab42f80a0be63ca846629f518a922f7317a7e3c844e1b"},
|
||||
{file = "azure_identity-1.16.0-py3-none-any.whl", hash = "sha256:722fdb60b8fdd55fa44dc378b8072f4b419b56a5e54c0de391f644949f3a826f"},
|
||||
{file = "azure-identity-1.16.1.tar.gz", hash = "sha256:6d93f04468f240d59246d8afde3091494a5040d4f141cad0f49fc0c399d0d91e"},
|
||||
{file = "azure_identity-1.16.1-py3-none-any.whl", hash = "sha256:8fb07c25642cd4ac422559a8b50d3e77f73dcc2bbfaba419d06d6c9d7cff6726"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@ -1020,43 +1020,43 @@ toml = ["tomli"]
|
||||
|
||||
[[package]]
|
||||
name = "cryptography"
|
||||
version = "42.0.7"
|
||||
version = "42.0.8"
|
||||
description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "cryptography-42.0.7-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:a987f840718078212fdf4504d0fd4c6effe34a7e4740378e59d47696e8dfb477"},
|
||||
{file = "cryptography-42.0.7-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:bd13b5e9b543532453de08bcdc3cc7cebec6f9883e886fd20a92f26940fd3e7a"},
|
||||
{file = "cryptography-42.0.7-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a79165431551042cc9d1d90e6145d5d0d3ab0f2d66326c201d9b0e7f5bf43604"},
|
||||
{file = "cryptography-42.0.7-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a47787a5e3649008a1102d3df55424e86606c9bae6fb77ac59afe06d234605f8"},
|
||||
{file = "cryptography-42.0.7-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:02c0eee2d7133bdbbc5e24441258d5d2244beb31da5ed19fbb80315f4bbbff55"},
|
||||
{file = "cryptography-42.0.7-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:5e44507bf8d14b36b8389b226665d597bc0f18ea035d75b4e53c7b1ea84583cc"},
|
||||
{file = "cryptography-42.0.7-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:7f8b25fa616d8b846aef64b15c606bb0828dbc35faf90566eb139aa9cff67af2"},
|
||||
{file = "cryptography-42.0.7-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:93a3209f6bb2b33e725ed08ee0991b92976dfdcf4e8b38646540674fc7508e13"},
|
||||
{file = "cryptography-42.0.7-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:e6b8f1881dac458c34778d0a424ae5769de30544fc678eac51c1c8bb2183e9da"},
|
||||
{file = "cryptography-42.0.7-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3de9a45d3b2b7d8088c3fbf1ed4395dfeff79d07842217b38df14ef09ce1d8d7"},
|
||||
{file = "cryptography-42.0.7-cp37-abi3-win32.whl", hash = "sha256:789caea816c6704f63f6241a519bfa347f72fbd67ba28d04636b7c6b7da94b0b"},
|
||||
{file = "cryptography-42.0.7-cp37-abi3-win_amd64.whl", hash = "sha256:8cb8ce7c3347fcf9446f201dc30e2d5a3c898d009126010cbd1f443f28b52678"},
|
||||
{file = "cryptography-42.0.7-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:a3a5ac8b56fe37f3125e5b72b61dcde43283e5370827f5233893d461b7360cd4"},
|
||||
{file = "cryptography-42.0.7-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:779245e13b9a6638df14641d029add5dc17edbef6ec915688f3acb9e720a5858"},
|
||||
{file = "cryptography-42.0.7-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d563795db98b4cd57742a78a288cdbdc9daedac29f2239793071fe114f13785"},
|
||||
{file = "cryptography-42.0.7-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:31adb7d06fe4383226c3e963471f6837742889b3c4caa55aac20ad951bc8ffda"},
|
||||
{file = "cryptography-42.0.7-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:efd0bf5205240182e0f13bcaea41be4fdf5c22c5129fc7ced4a0282ac86998c9"},
|
||||
{file = "cryptography-42.0.7-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a9bc127cdc4ecf87a5ea22a2556cab6c7eda2923f84e4f3cc588e8470ce4e42e"},
|
||||
{file = "cryptography-42.0.7-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:3577d029bc3f4827dd5bf8bf7710cac13527b470bbf1820a3f394adb38ed7d5f"},
|
||||
{file = "cryptography-42.0.7-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2e47577f9b18723fa294b0ea9a17d5e53a227867a0a4904a1a076d1646d45ca1"},
|
||||
{file = "cryptography-42.0.7-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1a58839984d9cb34c855197043eaae2c187d930ca6d644612843b4fe8513c886"},
|
||||
{file = "cryptography-42.0.7-cp39-abi3-win32.whl", hash = "sha256:e6b79d0adb01aae87e8a44c2b64bc3f3fe59515280e00fb6d57a7267a2583cda"},
|
||||
{file = "cryptography-42.0.7-cp39-abi3-win_amd64.whl", hash = "sha256:16268d46086bb8ad5bf0a2b5544d8a9ed87a0e33f5e77dd3c3301e63d941a83b"},
|
||||
{file = "cryptography-42.0.7-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2954fccea107026512b15afb4aa664a5640cd0af630e2ee3962f2602693f0c82"},
|
||||
{file = "cryptography-42.0.7-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:362e7197754c231797ec45ee081f3088a27a47c6c01eff2ac83f60f85a50fe60"},
|
||||
{file = "cryptography-42.0.7-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:4f698edacf9c9e0371112792558d2f705b5645076cc0aaae02f816a0171770fd"},
|
||||
{file = "cryptography-42.0.7-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5482e789294854c28237bba77c4c83be698be740e31a3ae5e879ee5444166582"},
|
||||
{file = "cryptography-42.0.7-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e9b2a6309f14c0497f348d08a065d52f3020656f675819fc405fb63bbcd26562"},
|
||||
{file = "cryptography-42.0.7-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d8e3098721b84392ee45af2dd554c947c32cc52f862b6a3ae982dbb90f577f14"},
|
||||
{file = "cryptography-42.0.7-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c65f96dad14f8528a447414125e1fc8feb2ad5a272b8f68477abbcc1ea7d94b9"},
|
||||
{file = "cryptography-42.0.7-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:36017400817987670037fbb0324d71489b6ead6231c9604f8fc1f7d008087c68"},
|
||||
{file = "cryptography-42.0.7.tar.gz", hash = "sha256:ecbfbc00bf55888edda9868a4cf927205de8499e7fabe6c050322298382953f2"},
|
||||
{file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:81d8a521705787afe7a18d5bfb47ea9d9cc068206270aad0b96a725022e18d2e"},
|
||||
{file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:961e61cefdcb06e0c6d7e3a1b22ebe8b996eb2bf50614e89384be54c48c6b63d"},
|
||||
{file = "cryptography-42.0.8-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3ec3672626e1b9e55afd0df6d774ff0e953452886e06e0f1eb7eb0c832e8902"},
|
||||
{file = "cryptography-42.0.8-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e599b53fd95357d92304510fb7bda8523ed1f79ca98dce2f43c115950aa78801"},
|
||||
{file = "cryptography-42.0.8-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:5226d5d21ab681f432a9c1cf8b658c0cb02533eece706b155e5fbd8a0cdd3949"},
|
||||
{file = "cryptography-42.0.8-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:6b7c4f03ce01afd3b76cf69a5455caa9cfa3de8c8f493e0d3ab7d20611c8dae9"},
|
||||
{file = "cryptography-42.0.8-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:2346b911eb349ab547076f47f2e035fc8ff2c02380a7cbbf8d87114fa0f1c583"},
|
||||
{file = "cryptography-42.0.8-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:ad803773e9df0b92e0a817d22fd8a3675493f690b96130a5e24f1b8fabbea9c7"},
|
||||
{file = "cryptography-42.0.8-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2f66d9cd9147ee495a8374a45ca445819f8929a3efcd2e3df6428e46c3cbb10b"},
|
||||
{file = "cryptography-42.0.8-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:d45b940883a03e19e944456a558b67a41160e367a719833c53de6911cabba2b7"},
|
||||
{file = "cryptography-42.0.8-cp37-abi3-win32.whl", hash = "sha256:a0c5b2b0585b6af82d7e385f55a8bc568abff8923af147ee3c07bd8b42cda8b2"},
|
||||
{file = "cryptography-42.0.8-cp37-abi3-win_amd64.whl", hash = "sha256:57080dee41209e556a9a4ce60d229244f7a66ef52750f813bfbe18959770cfba"},
|
||||
{file = "cryptography-42.0.8-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:dea567d1b0e8bc5764b9443858b673b734100c2871dc93163f58c46a97a83d28"},
|
||||
{file = "cryptography-42.0.8-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4783183f7cb757b73b2ae9aed6599b96338eb957233c58ca8f49a49cc32fd5e"},
|
||||
{file = "cryptography-42.0.8-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0608251135d0e03111152e41f0cc2392d1e74e35703960d4190b2e0f4ca9c70"},
|
||||
{file = "cryptography-42.0.8-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:dc0fdf6787f37b1c6b08e6dfc892d9d068b5bdb671198c72072828b80bd5fe4c"},
|
||||
{file = "cryptography-42.0.8-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:9c0c1716c8447ee7dbf08d6db2e5c41c688544c61074b54fc4564196f55c25a7"},
|
||||
{file = "cryptography-42.0.8-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:fff12c88a672ab9c9c1cf7b0c80e3ad9e2ebd9d828d955c126be4fd3e5578c9e"},
|
||||
{file = "cryptography-42.0.8-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:cafb92b2bc622cd1aa6a1dce4b93307792633f4c5fe1f46c6b97cf67073ec961"},
|
||||
{file = "cryptography-42.0.8-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:31f721658a29331f895a5a54e7e82075554ccfb8b163a18719d342f5ffe5ecb1"},
|
||||
{file = "cryptography-42.0.8-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b297f90c5723d04bcc8265fc2a0f86d4ea2e0f7ab4b6994459548d3a6b992a14"},
|
||||
{file = "cryptography-42.0.8-cp39-abi3-win32.whl", hash = "sha256:2f88d197e66c65be5e42cd72e5c18afbfae3f741742070e3019ac8f4ac57262c"},
|
||||
{file = "cryptography-42.0.8-cp39-abi3-win_amd64.whl", hash = "sha256:fa76fbb7596cc5839320000cdd5d0955313696d9511debab7ee7278fc8b5c84a"},
|
||||
{file = "cryptography-42.0.8-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ba4f0a211697362e89ad822e667d8d340b4d8d55fae72cdd619389fb5912eefe"},
|
||||
{file = "cryptography-42.0.8-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:81884c4d096c272f00aeb1f11cf62ccd39763581645b0812e99a91505fa48e0c"},
|
||||
{file = "cryptography-42.0.8-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c9bb2ae11bfbab395bdd072985abde58ea9860ed84e59dbc0463a5d0159f5b71"},
|
||||
{file = "cryptography-42.0.8-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7016f837e15b0a1c119d27ecd89b3515f01f90a8615ed5e9427e30d9cdbfed3d"},
|
||||
{file = "cryptography-42.0.8-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5a94eccb2a81a309806027e1670a358b99b8fe8bfe9f8d329f27d72c094dde8c"},
|
||||
{file = "cryptography-42.0.8-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:dec9b018df185f08483f294cae6ccac29e7a6e0678996587363dc352dc65c842"},
|
||||
{file = "cryptography-42.0.8-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:343728aac38decfdeecf55ecab3264b015be68fc2816ca800db649607aeee648"},
|
||||
{file = "cryptography-42.0.8-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:013629ae70b40af70c9a7a5db40abe5d9054e6f4380e50ce769947b73bf3caad"},
|
||||
{file = "cryptography-42.0.8.tar.gz", hash = "sha256:8d09d05439ce7baa8e9e95b07ec5b6c886f548deb7e0f69ef25f64b3bce842f2"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@ -1196,13 +1196,13 @@ bcrypt = ["bcrypt"]
|
||||
|
||||
[[package]]
|
||||
name = "django-cte"
|
||||
version = "1.3.2"
|
||||
version = "1.3.3"
|
||||
description = "Common Table Expressions (CTE) for Django"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "django-cte-1.3.2.tar.gz", hash = "sha256:841b264f83417d421393c8c4644f76300962c6c3ddbc37339cf99672eb3696a2"},
|
||||
{file = "django_cte-1.3.2-py2.py3-none-any.whl", hash = "sha256:9ca0a900df4819bbe86447a594f27272d67069f3ef13da61e905b0ace67704e9"},
|
||||
{file = "django-cte-1.3.3.tar.gz", hash = "sha256:0c1aeef067278a22886151c1d27f6f665a303952d058900e5ca82a24cde40697"},
|
||||
{file = "django_cte-1.3.3-py2.py3-none-any.whl", hash = "sha256:85bbc3efb30c2f8c9ae3080ca6f0b9570e43d2cb4b6be10846c8ef9f046873fa"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1707,13 +1707,13 @@ grpcio-gcp = ["grpcio-gcp (>=0.2.2,<1.0.dev0)"]
|
||||
|
||||
[[package]]
|
||||
name = "google-api-python-client"
|
||||
version = "2.131.0"
|
||||
version = "2.133.0"
|
||||
description = "Google API Client Library for Python"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "google-api-python-client-2.131.0.tar.gz", hash = "sha256:1c03e24af62238a8817ecc24e9d4c32ddd4cb1f323b08413652d9a9a592fc00d"},
|
||||
{file = "google_api_python_client-2.131.0-py2.py3-none-any.whl", hash = "sha256:e325409bdcef4604d505d9246ce7199960a010a0569ac503b9f319db8dbdc217"},
|
||||
{file = "google-api-python-client-2.133.0.tar.gz", hash = "sha256:293092905b66a046d3187a99ac454e12b00cc2c70444f26eb2f1f9c1a82720b4"},
|
||||
{file = "google_api_python_client-2.133.0-py2.py3-none-any.whl", hash = "sha256:396fe676ea0dfed066654dcf9f8dea77a1342f9d9bb23bb88e45b7b81e773926"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@ -2172,13 +2172,13 @@ zookeeper = ["kazoo (>=2.8.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "kubernetes"
|
||||
version = "29.0.0"
|
||||
version = "30.1.0"
|
||||
description = "Kubernetes python client"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "kubernetes-29.0.0-py2.py3-none-any.whl", hash = "sha256:ab8cb0e0576ccdfb71886366efb102c6a20f268d817be065ce7f9909c631e43e"},
|
||||
{file = "kubernetes-29.0.0.tar.gz", hash = "sha256:c4812e227ae74d07d53c88293e564e54b850452715a59a927e7e1bc6b9a60459"},
|
||||
{file = "kubernetes-30.1.0-py2.py3-none-any.whl", hash = "sha256:e212e8b7579031dd2e512168b617373bc1e03888d41ac4e04039240a292d478d"},
|
||||
{file = "kubernetes-30.1.0.tar.gz", hash = "sha256:41e4c77af9f28e7a6c314e3bd06a8c6229ddd787cad684e0ab9f69b498e98ebc"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@ -3019,13 +3019,13 @@ attrs = ">=19.2.0"
|
||||
|
||||
[[package]]
|
||||
name = "packaging"
|
||||
version = "24.0"
|
||||
version = "24.1"
|
||||
description = "Core utilities for Python packages"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5"},
|
||||
{file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"},
|
||||
{file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"},
|
||||
{file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3376,19 +3376,19 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "pydantic"
|
||||
version = "2.7.2"
|
||||
version = "2.7.3"
|
||||
description = "Data validation using Python type hints"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "pydantic-2.7.2-py3-none-any.whl", hash = "sha256:834ab954175f94e6e68258537dc49402c4a5e9d0409b9f1b86b7e934a8372de7"},
|
||||
{file = "pydantic-2.7.2.tar.gz", hash = "sha256:71b2945998f9c9b7919a45bde9a50397b289937d215ae141c1d0903ba7149fd7"},
|
||||
{file = "pydantic-2.7.3-py3-none-any.whl", hash = "sha256:ea91b002777bf643bb20dd717c028ec43216b24a6001a280f83877fd2655d0b4"},
|
||||
{file = "pydantic-2.7.3.tar.gz", hash = "sha256:c46c76a40bb1296728d7a8b99aa73dd70a48c3510111ff290034f860c99c419e"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
annotated-types = ">=0.4.0"
|
||||
email-validator = {version = ">=2.0.0", optional = true, markers = "extra == \"email\""}
|
||||
pydantic-core = "2.18.3"
|
||||
pydantic-core = "2.18.4"
|
||||
typing-extensions = ">=4.6.1"
|
||||
|
||||
[package.extras]
|
||||
@ -3396,90 +3396,90 @@ email = ["email-validator (>=2.0.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "pydantic-core"
|
||||
version = "2.18.3"
|
||||
version = "2.18.4"
|
||||
description = "Core functionality for Pydantic validation and serialization"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "pydantic_core-2.18.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:744697428fcdec6be5670460b578161d1ffe34743a5c15656be7ea82b008197c"},
|
||||
{file = "pydantic_core-2.18.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:37b40c05ced1ba4218b14986fe6f283d22e1ae2ff4c8e28881a70fb81fbfcda7"},
|
||||
{file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:544a9a75622357076efb6b311983ff190fbfb3c12fc3a853122b34d3d358126c"},
|
||||
{file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e2e253af04ceaebde8eb201eb3f3e3e7e390f2d275a88300d6a1959d710539e2"},
|
||||
{file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:855ec66589c68aa367d989da5c4755bb74ee92ccad4fdb6af942c3612c067e34"},
|
||||
{file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3d3e42bb54e7e9d72c13ce112e02eb1b3b55681ee948d748842171201a03a98a"},
|
||||
{file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6ac9ffccc9d2e69d9fba841441d4259cb668ac180e51b30d3632cd7abca2b9b"},
|
||||
{file = "pydantic_core-2.18.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c56eca1686539fa0c9bda992e7bd6a37583f20083c37590413381acfc5f192d6"},
|
||||
{file = "pydantic_core-2.18.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:17954d784bf8abfc0ec2a633108207ebc4fa2df1a0e4c0c3ccbaa9bb01d2c426"},
|
||||
{file = "pydantic_core-2.18.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:98ed737567d8f2ecd54f7c8d4f8572ca7c7921ede93a2e52939416170d357812"},
|
||||
{file = "pydantic_core-2.18.3-cp310-none-win32.whl", hash = "sha256:9f9e04afebd3ed8c15d67a564ed0a34b54e52136c6d40d14c5547b238390e779"},
|
||||
{file = "pydantic_core-2.18.3-cp310-none-win_amd64.whl", hash = "sha256:45e4ffbae34f7ae30d0047697e724e534a7ec0a82ef9994b7913a412c21462a0"},
|
||||
{file = "pydantic_core-2.18.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:b9ebe8231726c49518b16b237b9fe0d7d361dd221302af511a83d4ada01183ab"},
|
||||
{file = "pydantic_core-2.18.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b8e20e15d18bf7dbb453be78a2d858f946f5cdf06c5072453dace00ab652e2b2"},
|
||||
{file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c0d9ff283cd3459fa0bf9b0256a2b6f01ac1ff9ffb034e24457b9035f75587cb"},
|
||||
{file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2f7ef5f0ebb77ba24c9970da18b771711edc5feaf00c10b18461e0f5f5949231"},
|
||||
{file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73038d66614d2e5cde30435b5afdced2b473b4c77d4ca3a8624dd3e41a9c19be"},
|
||||
{file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6afd5c867a74c4d314c557b5ea9520183fadfbd1df4c2d6e09fd0d990ce412cd"},
|
||||
{file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bd7df92f28d351bb9f12470f4c533cf03d1b52ec5a6e5c58c65b183055a60106"},
|
||||
{file = "pydantic_core-2.18.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:80aea0ffeb1049336043d07799eace1c9602519fb3192916ff525b0287b2b1e4"},
|
||||
{file = "pydantic_core-2.18.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:aaee40f25bba38132e655ffa3d1998a6d576ba7cf81deff8bfa189fb43fd2bbe"},
|
||||
{file = "pydantic_core-2.18.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9128089da8f4fe73f7a91973895ebf2502539d627891a14034e45fb9e707e26d"},
|
||||
{file = "pydantic_core-2.18.3-cp311-none-win32.whl", hash = "sha256:fec02527e1e03257aa25b1a4dcbe697b40a22f1229f5d026503e8b7ff6d2eda7"},
|
||||
{file = "pydantic_core-2.18.3-cp311-none-win_amd64.whl", hash = "sha256:58ff8631dbab6c7c982e6425da8347108449321f61fe427c52ddfadd66642af7"},
|
||||
{file = "pydantic_core-2.18.3-cp311-none-win_arm64.whl", hash = "sha256:3fc1c7f67f34c6c2ef9c213e0f2a351797cda98249d9ca56a70ce4ebcaba45f4"},
|
||||
{file = "pydantic_core-2.18.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:f0928cde2ae416a2d1ebe6dee324709c6f73e93494d8c7aea92df99aab1fc40f"},
|
||||
{file = "pydantic_core-2.18.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0bee9bb305a562f8b9271855afb6ce00223f545de3d68560b3c1649c7c5295e9"},
|
||||
{file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e862823be114387257dacbfa7d78547165a85d7add33b446ca4f4fae92c7ff5c"},
|
||||
{file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6a36f78674cbddc165abab0df961b5f96b14461d05feec5e1f78da58808b97e7"},
|
||||
{file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba905d184f62e7ddbb7a5a751d8a5c805463511c7b08d1aca4a3e8c11f2e5048"},
|
||||
{file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7fdd362f6a586e681ff86550b2379e532fee63c52def1c666887956748eaa326"},
|
||||
{file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24b214b7ee3bd3b865e963dbed0f8bc5375f49449d70e8d407b567af3222aae4"},
|
||||
{file = "pydantic_core-2.18.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:691018785779766127f531674fa82bb368df5b36b461622b12e176c18e119022"},
|
||||
{file = "pydantic_core-2.18.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:60e4c625e6f7155d7d0dcac151edf5858102bc61bf959d04469ca6ee4e8381bd"},
|
||||
{file = "pydantic_core-2.18.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a4e651e47d981c1b701dcc74ab8fec5a60a5b004650416b4abbef13db23bc7be"},
|
||||
{file = "pydantic_core-2.18.3-cp312-none-win32.whl", hash = "sha256:ffecbb5edb7f5ffae13599aec33b735e9e4c7676ca1633c60f2c606beb17efc5"},
|
||||
{file = "pydantic_core-2.18.3-cp312-none-win_amd64.whl", hash = "sha256:2c8333f6e934733483c7eddffdb094c143b9463d2af7e6bd85ebcb2d4a1b82c6"},
|
||||
{file = "pydantic_core-2.18.3-cp312-none-win_arm64.whl", hash = "sha256:7a20dded653e516a4655f4c98e97ccafb13753987434fe7cf044aa25f5b7d417"},
|
||||
{file = "pydantic_core-2.18.3-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:eecf63195be644b0396f972c82598cd15693550f0ff236dcf7ab92e2eb6d3522"},
|
||||
{file = "pydantic_core-2.18.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2c44efdd3b6125419c28821590d7ec891c9cb0dff33a7a78d9d5c8b6f66b9702"},
|
||||
{file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6e59fca51ffbdd1638b3856779342ed69bcecb8484c1d4b8bdb237d0eb5a45e2"},
|
||||
{file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:70cf099197d6b98953468461d753563b28e73cf1eade2ffe069675d2657ed1d5"},
|
||||
{file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:63081a49dddc6124754b32a3774331467bfc3d2bd5ff8f10df36a95602560361"},
|
||||
{file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:370059b7883485c9edb9655355ff46d912f4b03b009d929220d9294c7fd9fd60"},
|
||||
{file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a64faeedfd8254f05f5cf6fc755023a7e1606af3959cfc1a9285744cc711044"},
|
||||
{file = "pydantic_core-2.18.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:19d2e725de0f90d8671f89e420d36c3dd97639b98145e42fcc0e1f6d492a46dc"},
|
||||
{file = "pydantic_core-2.18.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:67bc078025d70ec5aefe6200ef094576c9d86bd36982df1301c758a9fff7d7f4"},
|
||||
{file = "pydantic_core-2.18.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:adf952c3f4100e203cbaf8e0c907c835d3e28f9041474e52b651761dc248a3c0"},
|
||||
{file = "pydantic_core-2.18.3-cp38-none-win32.whl", hash = "sha256:9a46795b1f3beb167eaee91736d5d17ac3a994bf2215a996aed825a45f897558"},
|
||||
{file = "pydantic_core-2.18.3-cp38-none-win_amd64.whl", hash = "sha256:200ad4e3133cb99ed82342a101a5abf3d924722e71cd581cc113fe828f727fbc"},
|
||||
{file = "pydantic_core-2.18.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:304378b7bf92206036c8ddd83a2ba7b7d1a5b425acafff637172a3aa72ad7083"},
|
||||
{file = "pydantic_core-2.18.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c826870b277143e701c9ccf34ebc33ddb4d072612683a044e7cce2d52f6c3fef"},
|
||||
{file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e201935d282707394f3668380e41ccf25b5794d1b131cdd96b07f615a33ca4b1"},
|
||||
{file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5560dda746c44b48bf82b3d191d74fe8efc5686a9ef18e69bdabccbbb9ad9442"},
|
||||
{file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6b32c2a1f8032570842257e4c19288eba9a2bba4712af542327de9a1204faff8"},
|
||||
{file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:929c24e9dea3990bc8bcd27c5f2d3916c0c86f5511d2caa69e0d5290115344a9"},
|
||||
{file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e1a8376fef60790152564b0eab376b3e23dd6e54f29d84aad46f7b264ecca943"},
|
||||
{file = "pydantic_core-2.18.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:dccf3ef1400390ddd1fb55bf0632209d39140552d068ee5ac45553b556780e06"},
|
||||
{file = "pydantic_core-2.18.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:41dbdcb0c7252b58fa931fec47937edb422c9cb22528f41cb8963665c372caf6"},
|
||||
{file = "pydantic_core-2.18.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:666e45cf071669fde468886654742fa10b0e74cd0fa0430a46ba6056b24fb0af"},
|
||||
{file = "pydantic_core-2.18.3-cp39-none-win32.whl", hash = "sha256:f9c08cabff68704a1b4667d33f534d544b8a07b8e5d039c37067fceb18789e78"},
|
||||
{file = "pydantic_core-2.18.3-cp39-none-win_amd64.whl", hash = "sha256:4afa5f5973e8572b5c0dcb4e2d4fda7890e7cd63329bd5cc3263a25c92ef0026"},
|
||||
{file = "pydantic_core-2.18.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:77319771a026f7c7d29c6ebc623de889e9563b7087911b46fd06c044a12aa5e9"},
|
||||
{file = "pydantic_core-2.18.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:df11fa992e9f576473038510d66dd305bcd51d7dd508c163a8c8fe148454e059"},
|
||||
{file = "pydantic_core-2.18.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d531076bdfb65af593326ffd567e6ab3da145020dafb9187a1d131064a55f97c"},
|
||||
{file = "pydantic_core-2.18.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d33ce258e4e6e6038f2b9e8b8a631d17d017567db43483314993b3ca345dcbbb"},
|
||||
{file = "pydantic_core-2.18.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1f9cd7f5635b719939019be9bda47ecb56e165e51dd26c9a217a433e3d0d59a9"},
|
||||
{file = "pydantic_core-2.18.3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:cd4a032bb65cc132cae1fe3e52877daecc2097965cd3914e44fbd12b00dae7c5"},
|
||||
{file = "pydantic_core-2.18.3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:82f2718430098bcdf60402136c845e4126a189959d103900ebabb6774a5d9fdb"},
|
||||
{file = "pydantic_core-2.18.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c0037a92cf0c580ed14e10953cdd26528e8796307bb8bb312dc65f71547df04d"},
|
||||
{file = "pydantic_core-2.18.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:b95a0972fac2b1ff3c94629fc9081b16371dad870959f1408cc33b2f78ad347a"},
|
||||
{file = "pydantic_core-2.18.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a62e437d687cc148381bdd5f51e3e81f5b20a735c55f690c5be94e05da2b0d5c"},
|
||||
{file = "pydantic_core-2.18.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b367a73a414bbb08507da102dc2cde0fa7afe57d09b3240ce82a16d608a7679c"},
|
||||
{file = "pydantic_core-2.18.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ecce4b2360aa3f008da3327d652e74a0e743908eac306198b47e1c58b03dd2b"},
|
||||
{file = "pydantic_core-2.18.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bd4435b8d83f0c9561a2a9585b1de78f1abb17cb0cef5f39bf6a4b47d19bafe3"},
|
||||
{file = "pydantic_core-2.18.3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:616221a6d473c5b9aa83fa8982745441f6a4a62a66436be9445c65f241b86c94"},
|
||||
{file = "pydantic_core-2.18.3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:7e6382ce89a92bc1d0c0c5edd51e931432202b9080dc921d8d003e616402efd1"},
|
||||
{file = "pydantic_core-2.18.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:ff58f379345603d940e461eae474b6bbb6dab66ed9a851ecd3cb3709bf4dcf6a"},
|
||||
{file = "pydantic_core-2.18.3.tar.gz", hash = "sha256:432e999088d85c8f36b9a3f769a8e2b57aabd817bbb729a90d1fe7f18f6f1f39"},
|
||||
{file = "pydantic_core-2.18.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:f76d0ad001edd426b92233d45c746fd08f467d56100fd8f30e9ace4b005266e4"},
|
||||
{file = "pydantic_core-2.18.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:59ff3e89f4eaf14050c8022011862df275b552caef8082e37b542b066ce1ff26"},
|
||||
{file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a55b5b16c839df1070bc113c1f7f94a0af4433fcfa1b41799ce7606e5c79ce0a"},
|
||||
{file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4d0dcc59664fcb8974b356fe0a18a672d6d7cf9f54746c05f43275fc48636851"},
|
||||
{file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8951eee36c57cd128f779e641e21eb40bc5073eb28b2d23f33eb0ef14ffb3f5d"},
|
||||
{file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4701b19f7e3a06ea655513f7938de6f108123bf7c86bbebb1196eb9bd35cf724"},
|
||||
{file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e00a3f196329e08e43d99b79b286d60ce46bed10f2280d25a1718399457e06be"},
|
||||
{file = "pydantic_core-2.18.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:97736815b9cc893b2b7f663628e63f436018b75f44854c8027040e05230eeddb"},
|
||||
{file = "pydantic_core-2.18.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6891a2ae0e8692679c07728819b6e2b822fb30ca7445f67bbf6509b25a96332c"},
|
||||
{file = "pydantic_core-2.18.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bc4ff9805858bd54d1a20efff925ccd89c9d2e7cf4986144b30802bf78091c3e"},
|
||||
{file = "pydantic_core-2.18.4-cp310-none-win32.whl", hash = "sha256:1b4de2e51bbcb61fdebd0ab86ef28062704f62c82bbf4addc4e37fa4b00b7cbc"},
|
||||
{file = "pydantic_core-2.18.4-cp310-none-win_amd64.whl", hash = "sha256:6a750aec7bf431517a9fd78cb93c97b9b0c496090fee84a47a0d23668976b4b0"},
|
||||
{file = "pydantic_core-2.18.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:942ba11e7dfb66dc70f9ae66b33452f51ac7bb90676da39a7345e99ffb55402d"},
|
||||
{file = "pydantic_core-2.18.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b2ebef0e0b4454320274f5e83a41844c63438fdc874ea40a8b5b4ecb7693f1c4"},
|
||||
{file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a642295cd0c8df1b86fc3dced1d067874c353a188dc8e0f744626d49e9aa51c4"},
|
||||
{file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f09baa656c904807e832cf9cce799c6460c450c4ad80803517032da0cd062e2"},
|
||||
{file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:98906207f29bc2c459ff64fa007afd10a8c8ac080f7e4d5beff4c97086a3dabd"},
|
||||
{file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:19894b95aacfa98e7cb093cd7881a0c76f55731efad31073db4521e2b6ff5b7d"},
|
||||
{file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0fbbdc827fe5e42e4d196c746b890b3d72876bdbf160b0eafe9f0334525119c8"},
|
||||
{file = "pydantic_core-2.18.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f85d05aa0918283cf29a30b547b4df2fbb56b45b135f9e35b6807cb28bc47951"},
|
||||
{file = "pydantic_core-2.18.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e85637bc8fe81ddb73fda9e56bab24560bdddfa98aa64f87aaa4e4b6730c23d2"},
|
||||
{file = "pydantic_core-2.18.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2f5966897e5461f818e136b8451d0551a2e77259eb0f73a837027b47dc95dab9"},
|
||||
{file = "pydantic_core-2.18.4-cp311-none-win32.whl", hash = "sha256:44c7486a4228413c317952e9d89598bcdfb06399735e49e0f8df643e1ccd0558"},
|
||||
{file = "pydantic_core-2.18.4-cp311-none-win_amd64.whl", hash = "sha256:8a7164fe2005d03c64fd3b85649891cd4953a8de53107940bf272500ba8a788b"},
|
||||
{file = "pydantic_core-2.18.4-cp311-none-win_arm64.whl", hash = "sha256:4e99bc050fe65c450344421017f98298a97cefc18c53bb2f7b3531eb39bc7805"},
|
||||
{file = "pydantic_core-2.18.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:6f5c4d41b2771c730ea1c34e458e781b18cc668d194958e0112455fff4e402b2"},
|
||||
{file = "pydantic_core-2.18.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2fdf2156aa3d017fddf8aea5adfba9f777db1d6022d392b682d2a8329e087cef"},
|
||||
{file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4748321b5078216070b151d5271ef3e7cc905ab170bbfd27d5c83ee3ec436695"},
|
||||
{file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:847a35c4d58721c5dc3dba599878ebbdfd96784f3fb8bb2c356e123bdcd73f34"},
|
||||
{file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3c40d4eaad41f78e3bbda31b89edc46a3f3dc6e171bf0ecf097ff7a0ffff7cb1"},
|
||||
{file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:21a5e440dbe315ab9825fcd459b8814bb92b27c974cbc23c3e8baa2b76890077"},
|
||||
{file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01dd777215e2aa86dfd664daed5957704b769e726626393438f9c87690ce78c3"},
|
||||
{file = "pydantic_core-2.18.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4b06beb3b3f1479d32befd1f3079cc47b34fa2da62457cdf6c963393340b56e9"},
|
||||
{file = "pydantic_core-2.18.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:564d7922e4b13a16b98772441879fcdcbe82ff50daa622d681dd682175ea918c"},
|
||||
{file = "pydantic_core-2.18.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:0eb2a4f660fcd8e2b1c90ad566db2b98d7f3f4717c64fe0a83e0adb39766d5b8"},
|
||||
{file = "pydantic_core-2.18.4-cp312-none-win32.whl", hash = "sha256:8b8bab4c97248095ae0c4455b5a1cd1cdd96e4e4769306ab19dda135ea4cdb07"},
|
||||
{file = "pydantic_core-2.18.4-cp312-none-win_amd64.whl", hash = "sha256:14601cdb733d741b8958224030e2bfe21a4a881fb3dd6fbb21f071cabd48fa0a"},
|
||||
{file = "pydantic_core-2.18.4-cp312-none-win_arm64.whl", hash = "sha256:c1322d7dd74713dcc157a2b7898a564ab091ca6c58302d5c7b4c07296e3fd00f"},
|
||||
{file = "pydantic_core-2.18.4-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:823be1deb01793da05ecb0484d6c9e20baebb39bd42b5d72636ae9cf8350dbd2"},
|
||||
{file = "pydantic_core-2.18.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ebef0dd9bf9b812bf75bda96743f2a6c5734a02092ae7f721c048d156d5fabae"},
|
||||
{file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ae1d6df168efb88d7d522664693607b80b4080be6750c913eefb77e34c12c71a"},
|
||||
{file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f9899c94762343f2cc2fc64c13e7cae4c3cc65cdfc87dd810a31654c9b7358cc"},
|
||||
{file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:99457f184ad90235cfe8461c4d70ab7dd2680e28821c29eca00252ba90308c78"},
|
||||
{file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18f469a3d2a2fdafe99296a87e8a4c37748b5080a26b806a707f25a902c040a8"},
|
||||
{file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b7cdf28938ac6b8b49ae5e92f2735056a7ba99c9b110a474473fd71185c1af5d"},
|
||||
{file = "pydantic_core-2.18.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:938cb21650855054dc54dfd9120a851c974f95450f00683399006aa6e8abb057"},
|
||||
{file = "pydantic_core-2.18.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:44cd83ab6a51da80fb5adbd9560e26018e2ac7826f9626bc06ca3dc074cd198b"},
|
||||
{file = "pydantic_core-2.18.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:972658f4a72d02b8abfa2581d92d59f59897d2e9f7e708fdabe922f9087773af"},
|
||||
{file = "pydantic_core-2.18.4-cp38-none-win32.whl", hash = "sha256:1d886dc848e60cb7666f771e406acae54ab279b9f1e4143babc9c2258213daa2"},
|
||||
{file = "pydantic_core-2.18.4-cp38-none-win_amd64.whl", hash = "sha256:bb4462bd43c2460774914b8525f79b00f8f407c945d50881568f294c1d9b4443"},
|
||||
{file = "pydantic_core-2.18.4-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:44a688331d4a4e2129140a8118479443bd6f1905231138971372fcde37e43528"},
|
||||
{file = "pydantic_core-2.18.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a2fdd81edd64342c85ac7cf2753ccae0b79bf2dfa063785503cb85a7d3593223"},
|
||||
{file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:86110d7e1907ab36691f80b33eb2da87d780f4739ae773e5fc83fb272f88825f"},
|
||||
{file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:46387e38bd641b3ee5ce247563b60c5ca098da9c56c75c157a05eaa0933ed154"},
|
||||
{file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:123c3cec203e3f5ac7b000bd82235f1a3eced8665b63d18be751f115588fea30"},
|
||||
{file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dc1803ac5c32ec324c5261c7209e8f8ce88e83254c4e1aebdc8b0a39f9ddb443"},
|
||||
{file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:53db086f9f6ab2b4061958d9c276d1dbe3690e8dd727d6abf2321d6cce37fa94"},
|
||||
{file = "pydantic_core-2.18.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:abc267fa9837245cc28ea6929f19fa335f3dc330a35d2e45509b6566dc18be23"},
|
||||
{file = "pydantic_core-2.18.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:a0d829524aaefdebccb869eed855e2d04c21d2d7479b6cada7ace5448416597b"},
|
||||
{file = "pydantic_core-2.18.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:509daade3b8649f80d4e5ff21aa5673e4ebe58590b25fe42fac5f0f52c6f034a"},
|
||||
{file = "pydantic_core-2.18.4-cp39-none-win32.whl", hash = "sha256:ca26a1e73c48cfc54c4a76ff78df3727b9d9f4ccc8dbee4ae3f73306a591676d"},
|
||||
{file = "pydantic_core-2.18.4-cp39-none-win_amd64.whl", hash = "sha256:c67598100338d5d985db1b3d21f3619ef392e185e71b8d52bceacc4a7771ea7e"},
|
||||
{file = "pydantic_core-2.18.4-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:574d92eac874f7f4db0ca653514d823a0d22e2354359d0759e3f6a406db5d55d"},
|
||||
{file = "pydantic_core-2.18.4-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:1f4d26ceb5eb9eed4af91bebeae4b06c3fb28966ca3a8fb765208cf6b51102ab"},
|
||||
{file = "pydantic_core-2.18.4-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77450e6d20016ec41f43ca4a6c63e9fdde03f0ae3fe90e7c27bdbeaece8b1ed4"},
|
||||
{file = "pydantic_core-2.18.4-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d323a01da91851a4f17bf592faf46149c9169d68430b3146dcba2bb5e5719abc"},
|
||||
{file = "pydantic_core-2.18.4-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:43d447dd2ae072a0065389092a231283f62d960030ecd27565672bd40746c507"},
|
||||
{file = "pydantic_core-2.18.4-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:578e24f761f3b425834f297b9935e1ce2e30f51400964ce4801002435a1b41ef"},
|
||||
{file = "pydantic_core-2.18.4-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:81b5efb2f126454586d0f40c4d834010979cb80785173d1586df845a632e4e6d"},
|
||||
{file = "pydantic_core-2.18.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ab86ce7c8f9bea87b9d12c7f0af71102acbf5ecbc66c17796cff45dae54ef9a5"},
|
||||
{file = "pydantic_core-2.18.4-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:90afc12421df2b1b4dcc975f814e21bc1754640d502a2fbcc6d41e77af5ec312"},
|
||||
{file = "pydantic_core-2.18.4-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:51991a89639a912c17bef4b45c87bd83593aee0437d8102556af4885811d59f5"},
|
||||
{file = "pydantic_core-2.18.4-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:293afe532740370aba8c060882f7d26cfd00c94cae32fd2e212a3a6e3b7bc15e"},
|
||||
{file = "pydantic_core-2.18.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b48ece5bde2e768197a2d0f6e925f9d7e3e826f0ad2271120f8144a9db18d5c8"},
|
||||
{file = "pydantic_core-2.18.4-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:eae237477a873ab46e8dd748e515c72c0c804fb380fbe6c85533c7de51f23a8f"},
|
||||
{file = "pydantic_core-2.18.4-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:834b5230b5dfc0c1ec37b2fda433b271cbbc0e507560b5d1588e2cc1148cf1ce"},
|
||||
{file = "pydantic_core-2.18.4-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e858ac0a25074ba4bce653f9b5d0a85b7456eaddadc0ce82d3878c22489fa4ee"},
|
||||
{file = "pydantic_core-2.18.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2fd41f6eff4c20778d717af1cc50eca52f5afe7805ee530a4fbd0bae284f16e9"},
|
||||
{file = "pydantic_core-2.18.4.tar.gz", hash = "sha256:ec3beeada09ff865c344ff3bc2f427f5e6c26401cc6113d77e372c3fdac73864"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@ -3624,13 +3624,13 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "pytest"
|
||||
version = "8.2.1"
|
||||
version = "8.2.2"
|
||||
description = "pytest: simple powerful testing with Python"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "pytest-8.2.1-py3-none-any.whl", hash = "sha256:faccc5d332b8c3719f40283d0d44aa5cf101cec36f88cde9ed8f2bc0538612b1"},
|
||||
{file = "pytest-8.2.1.tar.gz", hash = "sha256:5046e5b46d8e4cac199c373041f26be56fdb81eb4e67dc11d4e10811fc3408fd"},
|
||||
{file = "pytest-8.2.2-py3-none-any.whl", hash = "sha256:c434598117762e2bd304e526244f67bf66bbd7b5d6cf22138be51ff661980343"},
|
||||
{file = "pytest-8.2.2.tar.gz", hash = "sha256:de4bb8104e201939ccdc688b27a89a7be2079b22e2bd2b07f806b6ba71117977"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@ -4052,28 +4052,28 @@ pyasn1 = ">=0.1.3"
|
||||
|
||||
[[package]]
|
||||
name = "ruff"
|
||||
version = "0.4.7"
|
||||
version = "0.4.8"
|
||||
description = "An extremely fast Python linter and code formatter, written in Rust."
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "ruff-0.4.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:e089371c67892a73b6bb1525608e89a2aca1b77b5440acf7a71dda5dac958f9e"},
|
||||
{file = "ruff-0.4.7-py3-none-macosx_11_0_arm64.whl", hash = "sha256:10f973d521d910e5f9c72ab27e409e839089f955be8a4c8826601a6323a89753"},
|
||||
{file = "ruff-0.4.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:59c3d110970001dfa494bcd95478e62286c751126dfb15c3c46e7915fc49694f"},
|
||||
{file = "ruff-0.4.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fa9773c6c00f4958f73b317bc0fd125295110c3776089f6ef318f4b775f0abe4"},
|
||||
{file = "ruff-0.4.7-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07fc80bbb61e42b3b23b10fda6a2a0f5a067f810180a3760c5ef1b456c21b9db"},
|
||||
{file = "ruff-0.4.7-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:fa4dafe3fe66d90e2e2b63fa1591dd6e3f090ca2128daa0be33db894e6c18648"},
|
||||
{file = "ruff-0.4.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a7c0083febdec17571455903b184a10026603a1de078428ba155e7ce9358c5f6"},
|
||||
{file = "ruff-0.4.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ad1b20e66a44057c326168437d680a2166c177c939346b19c0d6b08a62a37589"},
|
||||
{file = "ruff-0.4.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cbf5d818553add7511c38b05532d94a407f499d1a76ebb0cad0374e32bc67202"},
|
||||
{file = "ruff-0.4.7-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:50e9651578b629baec3d1513b2534de0ac7ed7753e1382272b8d609997e27e83"},
|
||||
{file = "ruff-0.4.7-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8874a9df7766cb956b218a0a239e0a5d23d9e843e4da1e113ae1d27ee420877a"},
|
||||
{file = "ruff-0.4.7-py3-none-musllinux_1_2_i686.whl", hash = "sha256:b9de9a6e49f7d529decd09381c0860c3f82fa0b0ea00ea78409b785d2308a567"},
|
||||
{file = "ruff-0.4.7-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:13a1768b0691619822ae6d446132dbdfd568b700ecd3652b20d4e8bc1e498f78"},
|
||||
{file = "ruff-0.4.7-py3-none-win32.whl", hash = "sha256:769e5a51df61e07e887b81e6f039e7ed3573316ab7dd9f635c5afaa310e4030e"},
|
||||
{file = "ruff-0.4.7-py3-none-win_amd64.whl", hash = "sha256:9e3ab684ad403a9ed1226894c32c3ab9c2e0718440f6f50c7c5829932bc9e054"},
|
||||
{file = "ruff-0.4.7-py3-none-win_arm64.whl", hash = "sha256:10f2204b9a613988e3484194c2c9e96a22079206b22b787605c255f130db5ed7"},
|
||||
{file = "ruff-0.4.7.tar.gz", hash = "sha256:2331d2b051dc77a289a653fcc6a42cce357087c5975738157cd966590b18b5e1"},
|
||||
{file = "ruff-0.4.8-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:7663a6d78f6adb0eab270fa9cf1ff2d28618ca3a652b60f2a234d92b9ec89066"},
|
||||
{file = "ruff-0.4.8-py3-none-macosx_11_0_arm64.whl", hash = "sha256:eeceb78da8afb6de0ddada93112869852d04f1cd0f6b80fe464fd4e35c330913"},
|
||||
{file = "ruff-0.4.8-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aad360893e92486662ef3be0a339c5ca3c1b109e0134fcd37d534d4be9fb8de3"},
|
||||
{file = "ruff-0.4.8-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:284c2e3f3396fb05f5f803c9fffb53ebbe09a3ebe7dda2929ed8d73ded736deb"},
|
||||
{file = "ruff-0.4.8-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7354f921e3fbe04d2a62d46707e569f9315e1a613307f7311a935743c51a764"},
|
||||
{file = "ruff-0.4.8-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:72584676164e15a68a15778fd1b17c28a519e7a0622161eb2debdcdabdc71883"},
|
||||
{file = "ruff-0.4.8-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9678d5c9b43315f323af2233a04d747409d1e3aa6789620083a82d1066a35199"},
|
||||
{file = "ruff-0.4.8-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704977a658131651a22b5ebeb28b717ef42ac6ee3b11e91dc87b633b5d83142b"},
|
||||
{file = "ruff-0.4.8-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d05f8d6f0c3cce5026cecd83b7a143dcad503045857bc49662f736437380ad45"},
|
||||
{file = "ruff-0.4.8-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:6ea874950daca5697309d976c9afba830d3bf0ed66887481d6bca1673fc5b66a"},
|
||||
{file = "ruff-0.4.8-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:fc95aac2943ddf360376be9aa3107c8cf9640083940a8c5bd824be692d2216dc"},
|
||||
{file = "ruff-0.4.8-py3-none-musllinux_1_2_i686.whl", hash = "sha256:384154a1c3f4bf537bac69f33720957ee49ac8d484bfc91720cc94172026ceed"},
|
||||
{file = "ruff-0.4.8-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e9d5ce97cacc99878aa0d084c626a15cd21e6b3d53fd6f9112b7fc485918e1fa"},
|
||||
{file = "ruff-0.4.8-py3-none-win32.whl", hash = "sha256:6d795d7639212c2dfd01991259460101c22aabf420d9b943f153ab9d9706e6a9"},
|
||||
{file = "ruff-0.4.8-py3-none-win_amd64.whl", hash = "sha256:e14a3a095d07560a9d6769a72f781d73259655919d9b396c650fc98a8157555d"},
|
||||
{file = "ruff-0.4.8-py3-none-win_arm64.whl", hash = "sha256:14019a06dbe29b608f6b7cbcec300e3170a8d86efaddb7b23405cb7f7dcaf780"},
|
||||
{file = "ruff-0.4.8.tar.gz", hash = "sha256:16d717b1d57b2e2fd68bd0bf80fb43931b79d05a7131aa477d66fc40fbd86268"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -4130,13 +4130,13 @@ urllib3 = {version = ">=1.26,<3", extras = ["socks"]}
|
||||
|
||||
[[package]]
|
||||
name = "sentry-sdk"
|
||||
version = "2.3.1"
|
||||
version = "2.5.1"
|
||||
description = "Python client for Sentry (https://sentry.io)"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "sentry_sdk-2.3.1-py2.py3-none-any.whl", hash = "sha256:c5aeb095ba226391d337dd42a6f9470d86c9fc236ecc71cfc7cd1942b45010c6"},
|
||||
{file = "sentry_sdk-2.3.1.tar.gz", hash = "sha256:139a71a19f5e9eb5d3623942491ce03cf8ebc14ea2e39ba3e6fe79560d8a5b1f"},
|
||||
{file = "sentry_sdk-2.5.1-py2.py3-none-any.whl", hash = "sha256:1f87acdce4a43a523ae5aa21a3fc37522d73ebd9ec04b1dbf01aa3d173852def"},
|
||||
{file = "sentry_sdk-2.5.1.tar.gz", hash = "sha256:fbc40a78a8a9c6675133031116144f0d0940376fa6e4e1acd5624c90b0aaf58b"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@ -4451,22 +4451,22 @@ celery = "*"
|
||||
|
||||
[[package]]
|
||||
name = "tornado"
|
||||
version = "6.4"
|
||||
version = "6.4.1"
|
||||
description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed."
|
||||
optional = false
|
||||
python-versions = ">= 3.8"
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "tornado-6.4-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:02ccefc7d8211e5a7f9e8bc3f9e5b0ad6262ba2fbb683a6443ecc804e5224ce0"},
|
||||
{file = "tornado-6.4-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:27787de946a9cffd63ce5814c33f734c627a87072ec7eed71f7fc4417bb16263"},
|
||||
{file = "tornado-6.4-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f7894c581ecdcf91666a0912f18ce5e757213999e183ebfc2c3fdbf4d5bd764e"},
|
||||
{file = "tornado-6.4-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e43bc2e5370a6a8e413e1e1cd0c91bedc5bd62a74a532371042a18ef19e10579"},
|
||||
{file = "tornado-6.4-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f0251554cdd50b4b44362f73ad5ba7126fc5b2c2895cc62b14a1c2d7ea32f212"},
|
||||
{file = "tornado-6.4-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:fd03192e287fbd0899dd8f81c6fb9cbbc69194d2074b38f384cb6fa72b80e9c2"},
|
||||
{file = "tornado-6.4-cp38-abi3-musllinux_1_1_i686.whl", hash = "sha256:88b84956273fbd73420e6d4b8d5ccbe913c65d31351b4c004ae362eba06e1f78"},
|
||||
{file = "tornado-6.4-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:71ddfc23a0e03ef2df1c1397d859868d158c8276a0603b96cf86892bff58149f"},
|
||||
{file = "tornado-6.4-cp38-abi3-win32.whl", hash = "sha256:6f8a6c77900f5ae93d8b4ae1196472d0ccc2775cc1dfdc9e7727889145c45052"},
|
||||
{file = "tornado-6.4-cp38-abi3-win_amd64.whl", hash = "sha256:10aeaa8006333433da48dec9fe417877f8bcc21f48dda8d661ae79da357b2a63"},
|
||||
{file = "tornado-6.4.tar.gz", hash = "sha256:72291fa6e6bc84e626589f1c29d90a5a6d593ef5ae68052ee2ef000dfd273dee"},
|
||||
{file = "tornado-6.4.1-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:163b0aafc8e23d8cdc3c9dfb24c5368af84a81e3364745ccb4427669bf84aec8"},
|
||||
{file = "tornado-6.4.1-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:6d5ce3437e18a2b66fbadb183c1d3364fb03f2be71299e7d10dbeeb69f4b2a14"},
|
||||
{file = "tornado-6.4.1-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2e20b9113cd7293f164dc46fffb13535266e713cdb87bd2d15ddb336e96cfc4"},
|
||||
{file = "tornado-6.4.1-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ae50a504a740365267b2a8d1a90c9fbc86b780a39170feca9bcc1787ff80842"},
|
||||
{file = "tornado-6.4.1-cp38-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:613bf4ddf5c7a95509218b149b555621497a6cc0d46ac341b30bd9ec19eac7f3"},
|
||||
{file = "tornado-6.4.1-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:25486eb223babe3eed4b8aecbac33b37e3dd6d776bc730ca14e1bf93888b979f"},
|
||||
{file = "tornado-6.4.1-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:454db8a7ecfcf2ff6042dde58404164d969b6f5d58b926da15e6b23817950fc4"},
|
||||
{file = "tornado-6.4.1-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:a02a08cc7a9314b006f653ce40483b9b3c12cda222d6a46d4ac63bb6c9057698"},
|
||||
{file = "tornado-6.4.1-cp38-abi3-win32.whl", hash = "sha256:d9a566c40b89757c9aa8e6f032bcdb8ca8795d7c1a9762910c722b1635c9de4d"},
|
||||
{file = "tornado-6.4.1-cp38-abi3-win_amd64.whl", hash = "sha256:b24b8982ed444378d7f21d563f4180a2de31ced9d8d84443907a0a64da2072e7"},
|
||||
{file = "tornado-6.4.1.tar.gz", hash = "sha256:92d3ab53183d8c50f8204a51e6f91d18a15d5ef261e84d452800d4ff6fc504e9"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -4505,13 +4505,13 @@ wsproto = ">=0.14"
|
||||
|
||||
[[package]]
|
||||
name = "twilio"
|
||||
version = "9.1.0"
|
||||
version = "9.1.1"
|
||||
description = "Twilio API client and TwiML generator"
|
||||
optional = false
|
||||
python-versions = ">=3.7.0"
|
||||
files = [
|
||||
{file = "twilio-9.1.0-py2.py3-none-any.whl", hash = "sha256:eb4687a9f81dc3118e8981c5a46d9f8184baee135c79afed47c714c759c31bbc"},
|
||||
{file = "twilio-9.1.0.tar.gz", hash = "sha256:ab2eb19c779855bf02cdca8a7e02ebaa64feee47da7b591ac9088ec07a6962e2"},
|
||||
{file = "twilio-9.1.1-py2.py3-none-any.whl", hash = "sha256:cc3e090c3884db7d70e7c647358b9cf1f4d30fd3fbe0412adcae0df8459d29b0"},
|
||||
{file = "twilio-9.1.1.tar.gz", hash = "sha256:cfe72b12cabac2f0997f1060d53cea14bd1196e2cbda14789e53c7dd762c4349"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
|
567
schema.yml
567
schema.yml
@ -19726,6 +19726,403 @@ paths:
|
||||
schema:
|
||||
$ref: '#/components/schemas/GenericError'
|
||||
description: ''
|
||||
/providers/scim_groups/:
|
||||
get:
|
||||
operationId: providers_scim_groups_list
|
||||
description: SCIMProviderGroup Viewset
|
||||
parameters:
|
||||
- in: query
|
||||
name: group__group_uuid
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
- in: query
|
||||
name: group__name
|
||||
schema:
|
||||
type: string
|
||||
- name: ordering
|
||||
required: false
|
||||
in: query
|
||||
description: Which field to use when ordering the results.
|
||||
schema:
|
||||
type: string
|
||||
- name: page
|
||||
required: false
|
||||
in: query
|
||||
description: A page number within the paginated result set.
|
||||
schema:
|
||||
type: integer
|
||||
- name: page_size
|
||||
required: false
|
||||
in: query
|
||||
description: Number of results to return per page.
|
||||
schema:
|
||||
type: integer
|
||||
- in: query
|
||||
name: provider__id
|
||||
schema:
|
||||
type: integer
|
||||
- name: search
|
||||
required: false
|
||||
in: query
|
||||
description: A search term.
|
||||
schema:
|
||||
type: string
|
||||
tags:
|
||||
- providers
|
||||
security:
|
||||
- authentik: []
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/PaginatedSCIMProviderGroupList'
|
||||
description: ''
|
||||
'400':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ValidationError'
|
||||
description: ''
|
||||
'403':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/GenericError'
|
||||
description: ''
|
||||
post:
|
||||
operationId: providers_scim_groups_create
|
||||
description: SCIMProviderGroup Viewset
|
||||
tags:
|
||||
- providers
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/SCIMProviderGroupRequest'
|
||||
required: true
|
||||
security:
|
||||
- authentik: []
|
||||
responses:
|
||||
'201':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/SCIMProviderGroup'
|
||||
description: ''
|
||||
'400':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ValidationError'
|
||||
description: ''
|
||||
'403':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/GenericError'
|
||||
description: ''
|
||||
/providers/scim_groups/{id}/:
|
||||
get:
|
||||
operationId: providers_scim_groups_retrieve
|
||||
description: SCIMProviderGroup Viewset
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
description: A UUID string identifying this scim provider group.
|
||||
required: true
|
||||
tags:
|
||||
- providers
|
||||
security:
|
||||
- authentik: []
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/SCIMProviderGroup'
|
||||
description: ''
|
||||
'400':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ValidationError'
|
||||
description: ''
|
||||
'403':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/GenericError'
|
||||
description: ''
|
||||
delete:
|
||||
operationId: providers_scim_groups_destroy
|
||||
description: SCIMProviderGroup Viewset
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
description: A UUID string identifying this scim provider group.
|
||||
required: true
|
||||
tags:
|
||||
- providers
|
||||
security:
|
||||
- authentik: []
|
||||
responses:
|
||||
'204':
|
||||
description: No response body
|
||||
'400':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ValidationError'
|
||||
description: ''
|
||||
'403':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/GenericError'
|
||||
description: ''
|
||||
/providers/scim_groups/{id}/used_by/:
|
||||
get:
|
||||
operationId: providers_scim_groups_used_by_list
|
||||
description: Get a list of all objects that use this object
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
description: A UUID string identifying this scim provider group.
|
||||
required: true
|
||||
tags:
|
||||
- providers
|
||||
security:
|
||||
- authentik: []
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/UsedBy'
|
||||
description: ''
|
||||
'400':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ValidationError'
|
||||
description: ''
|
||||
'403':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/GenericError'
|
||||
description: ''
|
||||
/providers/scim_users/:
|
||||
get:
|
||||
operationId: providers_scim_users_list
|
||||
description: SCIMProviderUser Viewset
|
||||
parameters:
|
||||
- name: ordering
|
||||
required: false
|
||||
in: query
|
||||
description: Which field to use when ordering the results.
|
||||
schema:
|
||||
type: string
|
||||
- name: page
|
||||
required: false
|
||||
in: query
|
||||
description: A page number within the paginated result set.
|
||||
schema:
|
||||
type: integer
|
||||
- name: page_size
|
||||
required: false
|
||||
in: query
|
||||
description: Number of results to return per page.
|
||||
schema:
|
||||
type: integer
|
||||
- in: query
|
||||
name: provider__id
|
||||
schema:
|
||||
type: integer
|
||||
- name: search
|
||||
required: false
|
||||
in: query
|
||||
description: A search term.
|
||||
schema:
|
||||
type: string
|
||||
- in: query
|
||||
name: user__id
|
||||
schema:
|
||||
type: integer
|
||||
- in: query
|
||||
name: user__username
|
||||
schema:
|
||||
type: string
|
||||
tags:
|
||||
- providers
|
||||
security:
|
||||
- authentik: []
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/PaginatedSCIMProviderUserList'
|
||||
description: ''
|
||||
'400':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ValidationError'
|
||||
description: ''
|
||||
'403':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/GenericError'
|
||||
description: ''
|
||||
post:
|
||||
operationId: providers_scim_users_create
|
||||
description: SCIMProviderUser Viewset
|
||||
tags:
|
||||
- providers
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/SCIMProviderUserRequest'
|
||||
required: true
|
||||
security:
|
||||
- authentik: []
|
||||
responses:
|
||||
'201':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/SCIMProviderUser'
|
||||
description: ''
|
||||
'400':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ValidationError'
|
||||
description: ''
|
||||
'403':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/GenericError'
|
||||
description: ''
|
||||
/providers/scim_users/{id}/:
|
||||
get:
|
||||
operationId: providers_scim_users_retrieve
|
||||
description: SCIMProviderUser Viewset
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
description: A UUID string identifying this scim provider user.
|
||||
required: true
|
||||
tags:
|
||||
- providers
|
||||
security:
|
||||
- authentik: []
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/SCIMProviderUser'
|
||||
description: ''
|
||||
'400':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ValidationError'
|
||||
description: ''
|
||||
'403':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/GenericError'
|
||||
description: ''
|
||||
delete:
|
||||
operationId: providers_scim_users_destroy
|
||||
description: SCIMProviderUser Viewset
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
description: A UUID string identifying this scim provider user.
|
||||
required: true
|
||||
tags:
|
||||
- providers
|
||||
security:
|
||||
- authentik: []
|
||||
responses:
|
||||
'204':
|
||||
description: No response body
|
||||
'400':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ValidationError'
|
||||
description: ''
|
||||
'403':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/GenericError'
|
||||
description: ''
|
||||
/providers/scim_users/{id}/used_by/:
|
||||
get:
|
||||
operationId: providers_scim_users_used_by_list
|
||||
description: Get a list of all objects that use this object
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
schema:
|
||||
type: string
|
||||
format: uuid
|
||||
description: A UUID string identifying this scim provider user.
|
||||
required: true
|
||||
tags:
|
||||
- providers
|
||||
security:
|
||||
- authentik: []
|
||||
responses:
|
||||
'200':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/UsedBy'
|
||||
description: ''
|
||||
'400':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/ValidationError'
|
||||
description: ''
|
||||
'403':
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/GenericError'
|
||||
description: ''
|
||||
/rac/connection_tokens/:
|
||||
get:
|
||||
operationId: rac_connection_tokens_list
|
||||
@ -34067,6 +34464,18 @@ components:
|
||||
type: string
|
||||
api_url:
|
||||
type: string
|
||||
score_min_threshold:
|
||||
type: number
|
||||
format: double
|
||||
score_max_threshold:
|
||||
type: number
|
||||
format: double
|
||||
error_on_invalid_score:
|
||||
type: boolean
|
||||
description: When enabled and the received captcha score is outside of the
|
||||
given threshold, the stage will show an error message. When not enabled,
|
||||
the flow will continue, but the data from the captcha will be available
|
||||
in the context for policy decisions
|
||||
required:
|
||||
- component
|
||||
- meta_model_name
|
||||
@ -34101,6 +34510,18 @@ components:
|
||||
api_url:
|
||||
type: string
|
||||
minLength: 1
|
||||
score_min_threshold:
|
||||
type: number
|
||||
format: double
|
||||
score_max_threshold:
|
||||
type: number
|
||||
format: double
|
||||
error_on_invalid_score:
|
||||
type: boolean
|
||||
description: When enabled and the received captcha score is outside of the
|
||||
given threshold, the stage will show an error message. When not enabled,
|
||||
the flow will continue, but the data from the captcha will be available
|
||||
in the context for policy decisions
|
||||
required:
|
||||
- name
|
||||
- private_key
|
||||
@ -36311,6 +36732,8 @@ components:
|
||||
type: string
|
||||
format: uuid
|
||||
readOnly: true
|
||||
google_id:
|
||||
type: string
|
||||
group:
|
||||
type: string
|
||||
format: uuid
|
||||
@ -36324,6 +36747,7 @@ components:
|
||||
readOnly: true
|
||||
required:
|
||||
- attributes
|
||||
- google_id
|
||||
- group
|
||||
- group_obj
|
||||
- id
|
||||
@ -36332,12 +36756,16 @@ components:
|
||||
type: object
|
||||
description: GoogleWorkspaceProviderGroup Serializer
|
||||
properties:
|
||||
google_id:
|
||||
type: string
|
||||
minLength: 1
|
||||
group:
|
||||
type: string
|
||||
format: uuid
|
||||
provider:
|
||||
type: integer
|
||||
required:
|
||||
- google_id
|
||||
- group
|
||||
- provider
|
||||
GoogleWorkspaceProviderMapping:
|
||||
@ -36460,6 +36888,8 @@ components:
|
||||
type: string
|
||||
format: uuid
|
||||
readOnly: true
|
||||
google_id:
|
||||
type: string
|
||||
user:
|
||||
type: integer
|
||||
user_obj:
|
||||
@ -36472,6 +36902,7 @@ components:
|
||||
readOnly: true
|
||||
required:
|
||||
- attributes
|
||||
- google_id
|
||||
- id
|
||||
- provider
|
||||
- user
|
||||
@ -36480,11 +36911,15 @@ components:
|
||||
type: object
|
||||
description: GoogleWorkspaceProviderUser Serializer
|
||||
properties:
|
||||
google_id:
|
||||
type: string
|
||||
minLength: 1
|
||||
user:
|
||||
type: integer
|
||||
provider:
|
||||
type: integer
|
||||
required:
|
||||
- google_id
|
||||
- provider
|
||||
- user
|
||||
Group:
|
||||
@ -37979,6 +38414,8 @@ components:
|
||||
type: string
|
||||
format: uuid
|
||||
readOnly: true
|
||||
microsoft_id:
|
||||
type: string
|
||||
group:
|
||||
type: string
|
||||
format: uuid
|
||||
@ -37995,11 +38432,15 @@ components:
|
||||
- group
|
||||
- group_obj
|
||||
- id
|
||||
- microsoft_id
|
||||
- provider
|
||||
MicrosoftEntraProviderGroupRequest:
|
||||
type: object
|
||||
description: MicrosoftEntraProviderGroup Serializer
|
||||
properties:
|
||||
microsoft_id:
|
||||
type: string
|
||||
minLength: 1
|
||||
group:
|
||||
type: string
|
||||
format: uuid
|
||||
@ -38007,6 +38448,7 @@ components:
|
||||
type: integer
|
||||
required:
|
||||
- group
|
||||
- microsoft_id
|
||||
- provider
|
||||
MicrosoftEntraProviderMapping:
|
||||
type: object
|
||||
@ -38125,6 +38567,8 @@ components:
|
||||
type: string
|
||||
format: uuid
|
||||
readOnly: true
|
||||
microsoft_id:
|
||||
type: string
|
||||
user:
|
||||
type: integer
|
||||
user_obj:
|
||||
@ -38138,6 +38582,7 @@ components:
|
||||
required:
|
||||
- attributes
|
||||
- id
|
||||
- microsoft_id
|
||||
- provider
|
||||
- user
|
||||
- user_obj
|
||||
@ -38145,11 +38590,15 @@ components:
|
||||
type: object
|
||||
description: MicrosoftEntraProviderUser Serializer
|
||||
properties:
|
||||
microsoft_id:
|
||||
type: string
|
||||
minLength: 1
|
||||
user:
|
||||
type: integer
|
||||
provider:
|
||||
type: integer
|
||||
required:
|
||||
- microsoft_id
|
||||
- provider
|
||||
- user
|
||||
ModelEnum:
|
||||
@ -40142,6 +40591,18 @@ components:
|
||||
required:
|
||||
- pagination
|
||||
- results
|
||||
PaginatedSCIMProviderGroupList:
|
||||
type: object
|
||||
properties:
|
||||
pagination:
|
||||
$ref: '#/components/schemas/Pagination'
|
||||
results:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/SCIMProviderGroup'
|
||||
required:
|
||||
- pagination
|
||||
- results
|
||||
PaginatedSCIMProviderList:
|
||||
type: object
|
||||
properties:
|
||||
@ -40154,6 +40615,18 @@ components:
|
||||
required:
|
||||
- pagination
|
||||
- results
|
||||
PaginatedSCIMProviderUserList:
|
||||
type: object
|
||||
properties:
|
||||
pagination:
|
||||
$ref: '#/components/schemas/Pagination'
|
||||
results:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/SCIMProviderUser'
|
||||
required:
|
||||
- pagination
|
||||
- results
|
||||
PaginatedSCIMSourceGroupList:
|
||||
type: object
|
||||
properties:
|
||||
@ -41182,6 +41655,18 @@ components:
|
||||
api_url:
|
||||
type: string
|
||||
minLength: 1
|
||||
score_min_threshold:
|
||||
type: number
|
||||
format: double
|
||||
score_max_threshold:
|
||||
type: number
|
||||
format: double
|
||||
error_on_invalid_score:
|
||||
type: boolean
|
||||
description: When enabled and the received captcha score is outside of the
|
||||
given threshold, the stage will show an error message. When not enabled,
|
||||
the flow will continue, but the data from the captcha will be available
|
||||
in the context for policy decisions
|
||||
PatchedCertificateKeyPairRequest:
|
||||
type: object
|
||||
description: CertificateKeyPair Serializer
|
||||
@ -44111,12 +44596,14 @@ components:
|
||||
properties:
|
||||
user:
|
||||
type: integer
|
||||
nullable: true
|
||||
context:
|
||||
type: object
|
||||
additionalProperties: {}
|
||||
group:
|
||||
type: string
|
||||
format: uuid
|
||||
nullable: true
|
||||
PropertyMappingTestResult:
|
||||
type: object
|
||||
description: Result of a Property-mapping test
|
||||
@ -45870,6 +46357,47 @@ components:
|
||||
- url
|
||||
- verbose_name
|
||||
- verbose_name_plural
|
||||
SCIMProviderGroup:
|
||||
type: object
|
||||
description: SCIMProviderGroup Serializer
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
format: uuid
|
||||
readOnly: true
|
||||
scim_id:
|
||||
type: string
|
||||
group:
|
||||
type: string
|
||||
format: uuid
|
||||
group_obj:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/UserGroup'
|
||||
readOnly: true
|
||||
provider:
|
||||
type: integer
|
||||
required:
|
||||
- group
|
||||
- group_obj
|
||||
- id
|
||||
- provider
|
||||
- scim_id
|
||||
SCIMProviderGroupRequest:
|
||||
type: object
|
||||
description: SCIMProviderGroup Serializer
|
||||
properties:
|
||||
scim_id:
|
||||
type: string
|
||||
minLength: 1
|
||||
group:
|
||||
type: string
|
||||
format: uuid
|
||||
provider:
|
||||
type: integer
|
||||
required:
|
||||
- group
|
||||
- provider
|
||||
- scim_id
|
||||
SCIMProviderRequest:
|
||||
type: object
|
||||
description: SCIMProvider Serializer
|
||||
@ -45906,6 +46434,45 @@ components:
|
||||
- name
|
||||
- token
|
||||
- url
|
||||
SCIMProviderUser:
|
||||
type: object
|
||||
description: SCIMProviderUser Serializer
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
format: uuid
|
||||
readOnly: true
|
||||
scim_id:
|
||||
type: string
|
||||
user:
|
||||
type: integer
|
||||
user_obj:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/GroupMember'
|
||||
readOnly: true
|
||||
provider:
|
||||
type: integer
|
||||
required:
|
||||
- id
|
||||
- provider
|
||||
- scim_id
|
||||
- user
|
||||
- user_obj
|
||||
SCIMProviderUserRequest:
|
||||
type: object
|
||||
description: SCIMProviderUser Serializer
|
||||
properties:
|
||||
scim_id:
|
||||
type: string
|
||||
minLength: 1
|
||||
user:
|
||||
type: integer
|
||||
provider:
|
||||
type: integer
|
||||
required:
|
||||
- provider
|
||||
- scim_id
|
||||
- user
|
||||
SCIMSource:
|
||||
type: object
|
||||
description: SCIMSource Serializer
|
||||
|
@ -1,5 +1,3 @@
|
||||
version: '3.7'
|
||||
|
||||
services:
|
||||
chrome:
|
||||
image: docker.io/selenium/standalone-chrome:122.0
|
||||
|
168
tests/wdio/package-lock.json
generated
168
tests/wdio/package-lock.json
generated
@ -6,21 +6,21 @@
|
||||
"": {
|
||||
"name": "@goauthentik/web-tests",
|
||||
"dependencies": {
|
||||
"chromedriver": "^125.0.3"
|
||||
"chromedriver": "^126.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
|
||||
"@typescript-eslint/eslint-plugin": "^7.5.0",
|
||||
"@typescript-eslint/parser": "^7.5.0",
|
||||
"@wdio/cli": "^8.38.1",
|
||||
"@wdio/local-runner": "^8.38.0",
|
||||
"@wdio/mocha-framework": "^8.38.0",
|
||||
"@wdio/spec-reporter": "^8.38.0",
|
||||
"@wdio/cli": "^8.38.2",
|
||||
"@wdio/local-runner": "^8.38.2",
|
||||
"@wdio/mocha-framework": "^8.38.2",
|
||||
"@wdio/spec-reporter": "^8.38.2",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-google": "^0.14.0",
|
||||
"eslint-plugin-sonarjs": "^0.25.1",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"prettier": "^3.3.0",
|
||||
"prettier": "^3.3.2",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.4.5",
|
||||
"wdio-wait-for": "^3.0.11"
|
||||
@ -1189,19 +1189,19 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@wdio/cli": {
|
||||
"version": "8.38.1",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/cli/-/cli-8.38.1.tgz",
|
||||
"integrity": "sha512-xif0RvJX+saXVdzrhlEafbEdptNyeyqm0pyilT4H7OI7OMa+23rWB67r2SPoIZbBrVeFv1iqtUx9hR73RRio2A==",
|
||||
"version": "8.38.2",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/cli/-/cli-8.38.2.tgz",
|
||||
"integrity": "sha512-p9y6jxmpmw53OoB9v/uTLwMetmz7Q0K7NewdVONgmeTY/ERpkU15qL3fMw1rXb+E+vrV8dlce4srnXroec6SFA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "^20.1.1",
|
||||
"@vitest/snapshot": "^1.2.1",
|
||||
"@wdio/config": "8.38.0",
|
||||
"@wdio/globals": "8.38.0",
|
||||
"@wdio/config": "8.38.2",
|
||||
"@wdio/globals": "8.38.2",
|
||||
"@wdio/logger": "8.38.0",
|
||||
"@wdio/protocols": "8.38.0",
|
||||
"@wdio/types": "8.37.0",
|
||||
"@wdio/utils": "8.38.0",
|
||||
"@wdio/types": "8.38.2",
|
||||
"@wdio/utils": "8.38.2",
|
||||
"async-exit-hook": "^2.0.1",
|
||||
"chalk": "^5.2.0",
|
||||
"chokidar": "^3.5.3",
|
||||
@ -1216,7 +1216,7 @@
|
||||
"lodash.union": "^4.6.0",
|
||||
"read-pkg-up": "10.0.0",
|
||||
"recursive-readdir": "^2.2.3",
|
||||
"webdriverio": "8.38.0",
|
||||
"webdriverio": "8.38.2",
|
||||
"yargs": "^17.7.2"
|
||||
},
|
||||
"bin": {
|
||||
@ -1239,14 +1239,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@wdio/config": {
|
||||
"version": "8.38.0",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/config/-/config-8.38.0.tgz",
|
||||
"integrity": "sha512-9eMmHYkXw/0htj8Nok2vBa8Q+IS/wj7HXbLczKb5rEmDb57SW5iPMpZutFywGki1D/GIDLvejWaZvlxmS/yfBA==",
|
||||
"version": "8.38.2",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/config/-/config-8.38.2.tgz",
|
||||
"integrity": "sha512-xlnapTr1vOA0h5HsHTIqj47729FbG3WjxmgHweDEQvcT4C1g9l+WKf+N3FM7DNNoIsAqxKi6rOHG02rJADQJtw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@wdio/logger": "8.38.0",
|
||||
"@wdio/types": "8.37.0",
|
||||
"@wdio/utils": "8.38.0",
|
||||
"@wdio/types": "8.38.2",
|
||||
"@wdio/utils": "8.38.2",
|
||||
"decamelize": "^6.0.0",
|
||||
"deepmerge-ts": "^5.0.0",
|
||||
"glob": "^10.2.2",
|
||||
@ -1257,29 +1257,29 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@wdio/globals": {
|
||||
"version": "8.38.0",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/globals/-/globals-8.38.0.tgz",
|
||||
"integrity": "sha512-3Lo7R305gwJrloUolrgSRaMbIFKwnj/SPoYUt94dsTF1oM3TpyWpomcVokElNQiOFx9WYjMmBla2M+YcnoGmgw==",
|
||||
"version": "8.38.2",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/globals/-/globals-8.38.2.tgz",
|
||||
"integrity": "sha512-iIrUF1EODfHLh3V/CSNCqbNNxUTe3ND+c86zDjzJcPFjawLX1plvAApsU/eDmtsFShcOS2KHbfSjiydFoqQG1Q==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": "^16.13 || >=18"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"expect-webdriverio": "^4.11.2",
|
||||
"webdriverio": "8.38.0"
|
||||
"webdriverio": "8.38.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@wdio/local-runner": {
|
||||
"version": "8.38.0",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/local-runner/-/local-runner-8.38.0.tgz",
|
||||
"integrity": "sha512-++eVI+EQapBMRxtLSbeooK02uELAhIXNLzgBlC03s23OTZUUOxzl4WxFuGqaG8gpNHer5Bjg+uAy0rIbSMnklA==",
|
||||
"version": "8.38.2",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/local-runner/-/local-runner-8.38.2.tgz",
|
||||
"integrity": "sha512-syW+R5VUHJ3GBkQGFcNYe6MYwWRgklc9W7A83xQDTvKWFNHCetLvc8AtKZ54vs8MItBejjU+Oh94ZNbNX1pBcg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "^20.1.0",
|
||||
"@wdio/logger": "8.38.0",
|
||||
"@wdio/repl": "8.24.12",
|
||||
"@wdio/runner": "8.38.0",
|
||||
"@wdio/types": "8.37.0",
|
||||
"@wdio/runner": "8.38.2",
|
||||
"@wdio/types": "8.38.2",
|
||||
"async-exit-hook": "^2.0.1",
|
||||
"split2": "^4.1.0",
|
||||
"stream-buffers": "^3.0.2"
|
||||
@ -1316,16 +1316,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@wdio/mocha-framework": {
|
||||
"version": "8.38.0",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/mocha-framework/-/mocha-framework-8.38.0.tgz",
|
||||
"integrity": "sha512-LWwKslKIxqhQNskdffcS6QbxN45PzJN21b5zByELbEYd9PIGNbuXXqueVE09RwEAzBHtL86ZhSpFclAB+ulsBw==",
|
||||
"version": "8.38.2",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/mocha-framework/-/mocha-framework-8.38.2.tgz",
|
||||
"integrity": "sha512-qJmRL5E6/ypjCUACH4hvCAAmTdU4YUrUlp9o/IKvTIAHMnZPE0/HgUFixCeu8Mop+rdzTPVBrbqxpRDdSnraYA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/mocha": "^10.0.0",
|
||||
"@types/node": "^20.1.0",
|
||||
"@wdio/logger": "8.38.0",
|
||||
"@wdio/types": "8.37.0",
|
||||
"@wdio/utils": "8.38.0",
|
||||
"@wdio/types": "8.38.2",
|
||||
"@wdio/utils": "8.38.2",
|
||||
"mocha": "^10.0.0"
|
||||
},
|
||||
"engines": {
|
||||
@ -1351,14 +1351,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@wdio/reporter": {
|
||||
"version": "8.38.0",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/reporter/-/reporter-8.38.0.tgz",
|
||||
"integrity": "sha512-7eyBM06j0PAu2g14wOwJbSmUOaT8q1pmMukzeRl1YDoW2sLpQG0zMZNzQNsQyi7+1KgltTJJnvHCec5MBZrjpw==",
|
||||
"version": "8.38.2",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/reporter/-/reporter-8.38.2.tgz",
|
||||
"integrity": "sha512-R78UdAtAnkaV22NYlCCcbPPhmYweiDURiw64LYhlVIQrKNuXUQcafR2kRlWKy31rZc9thSLs5LzrZDReENUlFQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "^20.1.0",
|
||||
"@wdio/logger": "8.38.0",
|
||||
"@wdio/types": "8.37.0",
|
||||
"@wdio/types": "8.38.2",
|
||||
"diff": "^5.0.0",
|
||||
"object-inspect": "^1.12.0"
|
||||
},
|
||||
@ -1367,35 +1367,35 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@wdio/runner": {
|
||||
"version": "8.38.0",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/runner/-/runner-8.38.0.tgz",
|
||||
"integrity": "sha512-pmoXwRMUxWXhqce64Y3gqoMqJn0YknJ1U9aHOMxp6uB3iHfzoPA+7Mf5ziSc0uDBcEyjXtau9qMfu7iBHUz62Q==",
|
||||
"version": "8.38.2",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/runner/-/runner-8.38.2.tgz",
|
||||
"integrity": "sha512-5lPnKSX2BBLI2AbYW+hoGPiEUAJXj8F8I6NC2LaBVzf1CLN+w2HWZ7lUiqS14XT0b5/hlSUX6+JYwUXlDbpuuw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "^20.11.28",
|
||||
"@wdio/config": "8.38.0",
|
||||
"@wdio/globals": "8.38.0",
|
||||
"@wdio/config": "8.38.2",
|
||||
"@wdio/globals": "8.38.2",
|
||||
"@wdio/logger": "8.38.0",
|
||||
"@wdio/types": "8.37.0",
|
||||
"@wdio/utils": "8.38.0",
|
||||
"@wdio/types": "8.38.2",
|
||||
"@wdio/utils": "8.38.2",
|
||||
"deepmerge-ts": "^5.1.0",
|
||||
"expect-webdriverio": "^4.12.0",
|
||||
"gaze": "^1.1.3",
|
||||
"webdriver": "8.38.0",
|
||||
"webdriverio": "8.38.0"
|
||||
"webdriver": "8.38.2",
|
||||
"webdriverio": "8.38.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^16.13 || >=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@wdio/spec-reporter": {
|
||||
"version": "8.38.0",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/spec-reporter/-/spec-reporter-8.38.0.tgz",
|
||||
"integrity": "sha512-Cuk/mqsBa+YgAL3OCtsYLUxRkGSYeaXM3LSE5muzY1mSqQlK3a/5GdAXlaOosuhYpUgI0A9xTsMiq7PQd75qHA==",
|
||||
"version": "8.38.2",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/spec-reporter/-/spec-reporter-8.38.2.tgz",
|
||||
"integrity": "sha512-Dntk+lmrp+0I3HRRWkkXED+smshvgsW5cdLKwJhEJ1liI48MdBpdNGf9IHTVckE6nfxcWDyFI4icD9qYv/5bFA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@wdio/reporter": "8.38.0",
|
||||
"@wdio/types": "8.37.0",
|
||||
"@wdio/reporter": "8.38.2",
|
||||
"@wdio/types": "8.38.2",
|
||||
"chalk": "^5.1.2",
|
||||
"easy-table": "^1.2.0",
|
||||
"pretty-ms": "^7.0.0"
|
||||
@ -1417,9 +1417,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@wdio/types": {
|
||||
"version": "8.37.0",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/types/-/types-8.37.0.tgz",
|
||||
"integrity": "sha512-36kmSlZcVhsMlbhaSCQUfL51iG81FlbzW4Dfkz4903cDkxmh64bgxydZbRB5aPLnJzzR7tI3chIME8zSVZFR8w==",
|
||||
"version": "8.38.2",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/types/-/types-8.38.2.tgz",
|
||||
"integrity": "sha512-+wj1c1OSLdnN4WO5b44Ih4263dTl/eSwMGSI4/pCgIyXIuYQH38JQ+6WRa+c8vJEskUzboq2cSgEQumVZ39ozQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "^20.1.0"
|
||||
@ -1429,14 +1429,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@wdio/utils": {
|
||||
"version": "8.38.0",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-8.38.0.tgz",
|
||||
"integrity": "sha512-ios7MpyJk4kGW9ZOYxbPpdwVZBI7SzccIgiirqSf8rvJi62VpDA2nfa7i7BY1rs9p7lnenF8phwnuVFGMCoL0w==",
|
||||
"version": "8.38.2",
|
||||
"resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-8.38.2.tgz",
|
||||
"integrity": "sha512-y5AnBwsGcu/XuCBGCgKmlvKdwEIFyzLA+Cr+denySxY3jbWDONtPUcGaVdFALwsIa5jcIjcATqGmZcCPGnkd7g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@puppeteer/browsers": "^1.6.0",
|
||||
"@wdio/logger": "8.38.0",
|
||||
"@wdio/types": "8.37.0",
|
||||
"@wdio/types": "8.38.2",
|
||||
"decamelize": "^6.0.0",
|
||||
"deepmerge-ts": "^5.1.0",
|
||||
"edgedriver": "^5.5.0",
|
||||
@ -1879,12 +1879,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/braces": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
|
||||
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
|
||||
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"fill-range": "^7.0.1"
|
||||
"fill-range": "^7.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
@ -2084,9 +2084,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/chromedriver": {
|
||||
"version": "125.0.3",
|
||||
"resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-125.0.3.tgz",
|
||||
"integrity": "sha512-Qzuk5Wian2o3EVGjtbz6V/jv+pT/AV9246HbG6kUljZXXjsKZLZxqJC+kHR3qEh/wdv4EJD0YwAOWV72v9hogw==",
|
||||
"version": "126.0.0",
|
||||
"resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-126.0.0.tgz",
|
||||
"integrity": "sha512-rzwKp1okI9RmFtSyIzkk9+GTlTK62ai5P3/AS2qMwl86+gw84d2S/IyLkQMm5cqieFs4dgDAuqqPu0AqQACScg==",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@testim/chrome-version": "^1.1.4",
|
||||
@ -3655,9 +3655,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/fill-range": {
|
||||
"version": "7.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
|
||||
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
|
||||
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"to-regex-range": "^5.0.1"
|
||||
@ -6908,9 +6908,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/prettier": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.0.tgz",
|
||||
"integrity": "sha512-J9odKxERhCQ10OC2yb93583f6UnYutOeiV5i0zEDS7UGTdUt0u+y8erxl3lBKvwo/JHyyoEdXjwp4dke9oyZ/g==",
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz",
|
||||
"integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"prettier": "bin/prettier.cjs"
|
||||
@ -8969,18 +8969,18 @@
|
||||
}
|
||||
},
|
||||
"node_modules/webdriver": {
|
||||
"version": "8.38.0",
|
||||
"resolved": "https://registry.npmjs.org/webdriver/-/webdriver-8.38.0.tgz",
|
||||
"integrity": "sha512-BT3sd667AqcZ1lzaOd7lphjnc7MNG3WgduAq4vUUDYlJAbs6SyjYd0EZPIPv9KUUYr0BoSJTDa0Xuyl/6PPW0Q==",
|
||||
"version": "8.38.2",
|
||||
"resolved": "https://registry.npmjs.org/webdriver/-/webdriver-8.38.2.tgz",
|
||||
"integrity": "sha512-NGfjW0BDYwFgOIzeojOcWGn3tYloQdvHr+Y2xKKYVqa9Rs0x1mzlTjU1kWtC4DaV8DltskwaPa7o+s8hTNpuyA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "^20.1.0",
|
||||
"@types/ws": "^8.5.3",
|
||||
"@wdio/config": "8.38.0",
|
||||
"@wdio/config": "8.38.2",
|
||||
"@wdio/logger": "8.38.0",
|
||||
"@wdio/protocols": "8.38.0",
|
||||
"@wdio/types": "8.37.0",
|
||||
"@wdio/utils": "8.38.0",
|
||||
"@wdio/types": "8.38.2",
|
||||
"@wdio/utils": "8.38.2",
|
||||
"deepmerge-ts": "^5.1.0",
|
||||
"got": "^12.6.1",
|
||||
"ky": "^0.33.0",
|
||||
@ -8991,18 +8991,18 @@
|
||||
}
|
||||
},
|
||||
"node_modules/webdriverio": {
|
||||
"version": "8.38.0",
|
||||
"resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-8.38.0.tgz",
|
||||
"integrity": "sha512-PxLtJPK8Aa+f/G/P8YGUwGH80uHowMA8cDHshhog6sKbp1BXEVB8x6PyC1AIswRlTWVijoes7cD0cUoVs6C87A==",
|
||||
"version": "8.38.2",
|
||||
"resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-8.38.2.tgz",
|
||||
"integrity": "sha512-r09y5UfivyYh5JOzT2SpJJ1zDmQl/R4OTH12opUqkjvp21BibCQm/uu1mrxGy4lzSHljrvqSVrrcGI+6UA1O8w==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/node": "^20.1.0",
|
||||
"@wdio/config": "8.38.0",
|
||||
"@wdio/config": "8.38.2",
|
||||
"@wdio/logger": "8.38.0",
|
||||
"@wdio/protocols": "8.38.0",
|
||||
"@wdio/repl": "8.24.12",
|
||||
"@wdio/types": "8.37.0",
|
||||
"@wdio/utils": "8.38.0",
|
||||
"@wdio/types": "8.38.2",
|
||||
"@wdio/utils": "8.38.2",
|
||||
"archiver": "^7.0.0",
|
||||
"aria-query": "^5.0.0",
|
||||
"css-shorthand-properties": "^1.1.1",
|
||||
@ -9020,7 +9020,7 @@
|
||||
"resq": "^1.9.1",
|
||||
"rgb2hex": "0.2.5",
|
||||
"serialize-error": "^11.0.1",
|
||||
"webdriver": "8.38.0"
|
||||
"webdriver": "8.38.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^16.13 || >=18"
|
||||
|
@ -6,15 +6,15 @@
|
||||
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
|
||||
"@typescript-eslint/eslint-plugin": "^7.5.0",
|
||||
"@typescript-eslint/parser": "^7.5.0",
|
||||
"@wdio/cli": "^8.38.1",
|
||||
"@wdio/local-runner": "^8.38.0",
|
||||
"@wdio/mocha-framework": "^8.38.0",
|
||||
"@wdio/spec-reporter": "^8.38.0",
|
||||
"@wdio/cli": "^8.38.2",
|
||||
"@wdio/local-runner": "^8.38.2",
|
||||
"@wdio/mocha-framework": "^8.38.2",
|
||||
"@wdio/spec-reporter": "^8.38.2",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-google": "^0.14.0",
|
||||
"eslint-plugin-sonarjs": "^0.25.1",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"prettier": "^3.3.0",
|
||||
"prettier": "^3.3.2",
|
||||
"ts-node": "^10.9.2",
|
||||
"typescript": "^5.4.5",
|
||||
"wdio-wait-for": "^3.0.11"
|
||||
@ -32,6 +32,6 @@
|
||||
"node": ">=20"
|
||||
},
|
||||
"dependencies": {
|
||||
"chromedriver": "^125.0.3"
|
||||
"chromedriver": "^126.0.0"
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,15 @@
|
||||
This is the default UI for the authentik server. The documentation is going to be a little sparse
|
||||
for awhile, but at least let's get started.
|
||||
|
||||
# Standards
|
||||
|
||||
- Be flexible in what you accept as input, be precise in what you produce as output.
|
||||
- Mis-use is always a crash. A component that takes the ID of an HTMLInputElement as an argument
|
||||
should throw an exception if the element is anything but an HTMLInputElement ("anything" includes
|
||||
non-existent, null, undefined, etc.).
|
||||
- Single Responsibility is ideal, but not always practical. To the best of your obility, every
|
||||
object in the system should do one thing and do it well.
|
||||
|
||||
# The Theory of the authentik UI
|
||||
|
||||
In Peter Naur's 1985 essay [Programming as Theory
|
||||
@ -107,3 +116,7 @@ settings in JSON files, which do not support comments.
|
||||
- `compilerOptions.plugins.ts-lit-plugin.rules.no-incompatible-type-binding: "warn"`: lit-analyzer
|
||||
does not support generics well when parsing a subtype of `HTMLElement`. As a result, this threw
|
||||
too many errors to be supportable.
|
||||
- `package.json`
|
||||
- `prettier` should always be the last thing run in any pre-commit pass. The `precommit` script
|
||||
does this, but if you don't use `precommit`, make sure `prettier` is the _last_ thing you do
|
||||
before a `git commit`.
|
||||
|
8051
web/package-lock.json
generated
8051
web/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -15,7 +15,7 @@
|
||||
"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:precommit": "bun 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",
|
||||
@ -38,15 +38,15 @@
|
||||
"@codemirror/theme-one-dark": "^6.1.2",
|
||||
"@formatjs/intl-listformat": "^7.5.7",
|
||||
"@fortawesome/fontawesome-free": "^6.5.2",
|
||||
"@goauthentik/api": "^2024.4.2-1717033226",
|
||||
"@goauthentik/api": "^2024.4.2-1717645682",
|
||||
"@lit-labs/task": "^3.1.0",
|
||||
"@lit/context": "^1.1.1",
|
||||
"@lit/context": "^1.1.2",
|
||||
"@lit/localize": "^0.12.1",
|
||||
"@lit/reactive-element": "^2.0.4",
|
||||
"@open-wc/lit-helpers": "^0.7.0",
|
||||
"@patternfly/elements": "^3.0.1",
|
||||
"@patternfly/patternfly": "^4.224.2",
|
||||
"@sentry/browser": "^8.7.0",
|
||||
"@sentry/browser": "^8.9.1",
|
||||
"@webcomponents/webcomponentsjs": "^2.8.0",
|
||||
"base64-js": "^1.5.1",
|
||||
"chart.js": "^4.4.3",
|
||||
@ -54,10 +54,10 @@
|
||||
"codemirror": "^6.0.1",
|
||||
"construct-style-sheets-polyfill": "^3.1.0",
|
||||
"core-js": "^3.37.1",
|
||||
"country-flag-icons": "^1.5.11",
|
||||
"country-flag-icons": "^1.5.12",
|
||||
"fuse.js": "^7.0.0",
|
||||
"guacamole-common-js": "^1.5.0",
|
||||
"lit": "^3.1.3",
|
||||
"lit": "^3.1.4",
|
||||
"md-front-matter": "^1.0.4",
|
||||
"mermaid": "^10.9.1",
|
||||
"rapidoc": "^9.3.4",
|
||||
@ -65,42 +65,44 @@
|
||||
"style-mod": "^4.1.2",
|
||||
"ts-pattern": "^5.1.2",
|
||||
"webcomponent-qr-code": "^1.2.0",
|
||||
"yaml": "^2.4.3"
|
||||
"yaml": "^2.4.5",
|
||||
"zxcvbn": "^4.4.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.24.6",
|
||||
"@babel/core": "^7.24.7",
|
||||
"@babel/plugin-proposal-class-properties": "^7.18.6",
|
||||
"@babel/plugin-proposal-decorators": "^7.24.6",
|
||||
"@babel/plugin-transform-private-methods": "^7.24.6",
|
||||
"@babel/plugin-transform-private-property-in-object": "^7.24.6",
|
||||
"@babel/plugin-transform-runtime": "^7.24.6",
|
||||
"@babel/preset-env": "^7.24.6",
|
||||
"@babel/preset-typescript": "^7.24.6",
|
||||
"@babel/plugin-proposal-decorators": "^7.24.7",
|
||||
"@babel/plugin-transform-private-methods": "^7.24.7",
|
||||
"@babel/plugin-transform-private-property-in-object": "^7.24.7",
|
||||
"@babel/plugin-transform-runtime": "^7.24.7",
|
||||
"@babel/preset-env": "^7.24.7",
|
||||
"@babel/preset-typescript": "^7.24.7",
|
||||
"@hcaptcha/types": "^1.0.3",
|
||||
"@jeysal/storybook-addon-css-user-preferences": "^0.2.0",
|
||||
"@lit/localize-tools": "^0.7.2",
|
||||
"@rollup/plugin-replace": "^5.0.5",
|
||||
"@rollup/plugin-replace": "^5.0.7",
|
||||
"@spotlightjs/spotlight": "^1.2.17",
|
||||
"@storybook/addon-essentials": "^8.1.5",
|
||||
"@storybook/addon-links": "^8.1.5",
|
||||
"@storybook/addon-essentials": "^8.1.6",
|
||||
"@storybook/addon-links": "^8.1.6",
|
||||
"@storybook/api": "^7.6.17",
|
||||
"@storybook/blocks": "^8.0.8",
|
||||
"@storybook/manager-api": "^8.1.5",
|
||||
"@storybook/web-components": "^8.1.5",
|
||||
"@storybook/web-components-vite": "^8.1.5",
|
||||
"@storybook/manager-api": "^8.1.6",
|
||||
"@storybook/web-components": "^8.1.6",
|
||||
"@storybook/web-components-vite": "^8.1.6",
|
||||
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
|
||||
"@types/chart.js": "^2.9.41",
|
||||
"@types/codemirror": "5.60.15",
|
||||
"@types/grecaptcha": "^3.0.9",
|
||||
"@types/guacamole-common-js": "1.5.2",
|
||||
"@types/showdown": "^2.0.6",
|
||||
"@types/zxcvbn": "^4.4.4",
|
||||
"@typescript-eslint/eslint-plugin": "^7.5.0",
|
||||
"@typescript-eslint/parser": "^7.5.0",
|
||||
"babel-plugin-macros": "^3.1.0",
|
||||
"babel-plugin-tsconfig-paths": "^1.0.3",
|
||||
"chokidar": "^3.6.0",
|
||||
"cross-env": "^7.0.3",
|
||||
"esbuild": "^0.21.4",
|
||||
"esbuild": "^0.21.5",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-google": "^0.14.0",
|
||||
"eslint-plugin-custom-elements": "0.0.8",
|
||||
@ -111,16 +113,16 @@
|
||||
"glob": "^10.4.1",
|
||||
"lit-analyzer": "^2.0.3",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"prettier": "^3.3.0",
|
||||
"prettier": "^3.3.2",
|
||||
"pseudolocale": "^2.0.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.3.1",
|
||||
"rollup-plugin-modify": "^3.0.0",
|
||||
"rollup-plugin-postcss-lit": "^2.1.0",
|
||||
"storybook": "^8.1.5",
|
||||
"storybook": "^8.1.6",
|
||||
"storybook-addon-mock": "^5.0.0",
|
||||
"ts-lit-plugin": "^2.0.2",
|
||||
"tslib": "^2.6.2",
|
||||
"tslib": "^2.6.3",
|
||||
"turnstile-types": "^1.2.1",
|
||||
"typescript": "^5.4.5",
|
||||
"vite-tsconfig-paths": "^4.3.2"
|
||||
|
@ -126,6 +126,7 @@ export class PolicyTestForm extends Form<PropertyMappingTestRequest> {
|
||||
renderForm(): TemplateResult {
|
||||
return html`<ak-form-element-horizontal label=${msg("User")} name="user">
|
||||
<ak-search-select
|
||||
blankable
|
||||
.fetchObjects=${async (query?: string): Promise<User[]> => {
|
||||
const args: CoreUsersListRequest = {
|
||||
ordering: "username",
|
||||
@ -153,6 +154,7 @@ export class PolicyTestForm extends Form<PropertyMappingTestRequest> {
|
||||
</ak-form-element-horizontal>
|
||||
<ak-form-element-horizontal label=${msg("Group")} name="group">
|
||||
<ak-search-select
|
||||
blankable
|
||||
.fetchObjects=${async (query?: string): Promise<Group[]> => {
|
||||
const args: CoreGroupsListRequest = {
|
||||
ordering: "name",
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { uiConfig } from "@goauthentik/common/ui/config";
|
||||
import "@goauthentik/elements/forms/DeleteBulkForm";
|
||||
import { PaginatedResponse, Table, TableColumn } from "@goauthentik/elements/table/Table";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
@ -19,6 +20,26 @@ export class GoogleWorkspaceProviderGroupList extends Table<GoogleWorkspaceProvi
|
||||
return true;
|
||||
}
|
||||
|
||||
checkbox = true;
|
||||
clearOnRefresh = true;
|
||||
|
||||
renderToolbarSelected(): TemplateResult {
|
||||
const disabled = this.selectedElements.length < 1;
|
||||
return html`<ak-forms-delete-bulk
|
||||
objectLabel=${msg("Google Workspace Group(s)")}
|
||||
.objects=${this.selectedElements}
|
||||
.delete=${(item: GoogleWorkspaceProviderGroup) => {
|
||||
return new ProvidersApi(DEFAULT_CONFIG).providersGoogleWorkspaceGroupsDestroy({
|
||||
id: item.id,
|
||||
});
|
||||
}}
|
||||
>
|
||||
<button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger">
|
||||
${msg("Delete")}
|
||||
</button>
|
||||
</ak-forms-delete-bulk>`;
|
||||
}
|
||||
|
||||
async apiEndpoint(page: number): Promise<PaginatedResponse<GoogleWorkspaceProviderGroup>> {
|
||||
return new ProvidersApi(DEFAULT_CONFIG).providersGoogleWorkspaceGroupsList({
|
||||
page: page,
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { uiConfig } from "@goauthentik/common/ui/config";
|
||||
import "@goauthentik/elements/forms/DeleteBulkForm";
|
||||
import { PaginatedResponse, Table, TableColumn } from "@goauthentik/elements/table/Table";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
@ -19,6 +20,26 @@ export class GoogleWorkspaceProviderUserList extends Table<GoogleWorkspaceProvid
|
||||
|
||||
expandable = true;
|
||||
|
||||
checkbox = true;
|
||||
clearOnRefresh = true;
|
||||
|
||||
renderToolbarSelected(): TemplateResult {
|
||||
const disabled = this.selectedElements.length < 1;
|
||||
return html`<ak-forms-delete-bulk
|
||||
objectLabel=${msg("Google Workspace User(s)")}
|
||||
.objects=${this.selectedElements}
|
||||
.delete=${(item: GoogleWorkspaceProviderUser) => {
|
||||
return new ProvidersApi(DEFAULT_CONFIG).providersGoogleWorkspaceUsersDestroy({
|
||||
id: item.id,
|
||||
});
|
||||
}}
|
||||
>
|
||||
<button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger">
|
||||
${msg("Delete")}
|
||||
</button>
|
||||
</ak-forms-delete-bulk>`;
|
||||
}
|
||||
|
||||
async apiEndpoint(page: number): Promise<PaginatedResponse<GoogleWorkspaceProviderUser>> {
|
||||
return new ProvidersApi(DEFAULT_CONFIG).providersGoogleWorkspaceUsersList({
|
||||
page: page,
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { uiConfig } from "@goauthentik/common/ui/config";
|
||||
import "@goauthentik/elements/forms/DeleteBulkForm";
|
||||
import { PaginatedResponse, Table, TableColumn } from "@goauthentik/elements/table/Table";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
@ -19,6 +20,23 @@ export class MicrosoftEntraProviderGroupList extends Table<MicrosoftEntraProvide
|
||||
return true;
|
||||
}
|
||||
|
||||
renderToolbarSelected(): TemplateResult {
|
||||
const disabled = this.selectedElements.length < 1;
|
||||
return html`<ak-forms-delete-bulk
|
||||
objectLabel=${msg("Microsoft Entra Group(s)")}
|
||||
.objects=${this.selectedElements}
|
||||
.delete=${(item: MicrosoftEntraProviderGroup) => {
|
||||
return new ProvidersApi(DEFAULT_CONFIG).providersMicrosoftEntraGroupsDestroy({
|
||||
id: item.id,
|
||||
});
|
||||
}}
|
||||
>
|
||||
<button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger">
|
||||
${msg("Delete")}
|
||||
</button>
|
||||
</ak-forms-delete-bulk>`;
|
||||
}
|
||||
|
||||
async apiEndpoint(page: number): Promise<PaginatedResponse<MicrosoftEntraProviderGroup>> {
|
||||
return new ProvidersApi(DEFAULT_CONFIG).providersMicrosoftEntraGroupsList({
|
||||
page: page,
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { uiConfig } from "@goauthentik/common/ui/config";
|
||||
import "@goauthentik/elements/forms/DeleteBulkForm";
|
||||
import { PaginatedResponse, Table, TableColumn } from "@goauthentik/elements/table/Table";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
@ -19,6 +20,26 @@ export class MicrosoftEntraProviderUserList extends Table<MicrosoftEntraProvider
|
||||
return true;
|
||||
}
|
||||
|
||||
checkbox = true;
|
||||
clearOnRefresh = true;
|
||||
|
||||
renderToolbarSelected(): TemplateResult {
|
||||
const disabled = this.selectedElements.length < 1;
|
||||
return html`<ak-forms-delete-bulk
|
||||
objectLabel=${msg("Microsoft Entra User(s)")}
|
||||
.objects=${this.selectedElements}
|
||||
.delete=${(item: MicrosoftEntraProviderUser) => {
|
||||
return new ProvidersApi(DEFAULT_CONFIG).providersMicrosoftEntraUsersDestroy({
|
||||
id: item.id,
|
||||
});
|
||||
}}
|
||||
>
|
||||
<button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger">
|
||||
${msg("Delete")}
|
||||
</button>
|
||||
</ak-forms-delete-bulk>`;
|
||||
}
|
||||
|
||||
async apiEndpoint(page: number): Promise<PaginatedResponse<MicrosoftEntraProviderUser>> {
|
||||
return new ProvidersApi(DEFAULT_CONFIG).providersMicrosoftEntraUsersList({
|
||||
page: page,
|
||||
|
63
web/src/admin/providers/scim/SCIMProviderGroupList.ts
Normal file
63
web/src/admin/providers/scim/SCIMProviderGroupList.ts
Normal file
@ -0,0 +1,63 @@
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { uiConfig } from "@goauthentik/common/ui/config";
|
||||
import "@goauthentik/elements/forms/DeleteBulkForm";
|
||||
import { PaginatedResponse, Table, TableColumn } from "@goauthentik/elements/table/Table";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
import { TemplateResult, html } from "lit";
|
||||
import { customElement, property } from "lit/decorators.js";
|
||||
|
||||
import { ProvidersApi, SCIMProviderGroup } from "@goauthentik/api";
|
||||
|
||||
@customElement("ak-provider-scim-groups-list")
|
||||
export class SCIMProviderGroupList extends Table<SCIMProviderGroup> {
|
||||
@property({ type: Number })
|
||||
providerId?: number;
|
||||
|
||||
searchEnabled(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
checkbox = true;
|
||||
clearOnRefresh = true;
|
||||
|
||||
renderToolbarSelected(): TemplateResult {
|
||||
const disabled = this.selectedElements.length < 1;
|
||||
return html`<ak-forms-delete-bulk
|
||||
objectLabel=${msg("SCIM Group(s)")}
|
||||
.objects=${this.selectedElements}
|
||||
.delete=${(item: SCIMProviderGroup) => {
|
||||
return new ProvidersApi(DEFAULT_CONFIG).providersScimGroupsDestroy({
|
||||
id: item.id,
|
||||
});
|
||||
}}
|
||||
>
|
||||
<button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger">
|
||||
${msg("Delete")}
|
||||
</button>
|
||||
</ak-forms-delete-bulk>`;
|
||||
}
|
||||
|
||||
async apiEndpoint(page: number): Promise<PaginatedResponse<SCIMProviderGroup>> {
|
||||
return new ProvidersApi(DEFAULT_CONFIG).providersScimGroupsList({
|
||||
page: page,
|
||||
pageSize: (await uiConfig()).pagination.perPage,
|
||||
ordering: this.order,
|
||||
search: this.search || "",
|
||||
providerId: this.providerId,
|
||||
});
|
||||
}
|
||||
|
||||
columns(): TableColumn[] {
|
||||
return [new TableColumn(msg("Name")), new TableColumn(msg("ID"))];
|
||||
}
|
||||
|
||||
row(item: SCIMProviderGroup): TemplateResult[] {
|
||||
return [
|
||||
html`<a href="#/identity/groups/${item.groupObj.pk}">
|
||||
<div>${item.groupObj.name}</div>
|
||||
</a>`,
|
||||
html`${item.id}`,
|
||||
];
|
||||
}
|
||||
}
|
64
web/src/admin/providers/scim/SCIMProviderUserList.ts
Normal file
64
web/src/admin/providers/scim/SCIMProviderUserList.ts
Normal file
@ -0,0 +1,64 @@
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { uiConfig } from "@goauthentik/common/ui/config";
|
||||
import "@goauthentik/elements/forms/DeleteBulkForm";
|
||||
import { PaginatedResponse, Table, TableColumn } from "@goauthentik/elements/table/Table";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
import { TemplateResult, html } from "lit";
|
||||
import { customElement, property } from "lit/decorators.js";
|
||||
|
||||
import { ProvidersApi, SCIMProviderUser } from "@goauthentik/api";
|
||||
|
||||
@customElement("ak-provider-scim-users-list")
|
||||
export class SCIMProviderUserList extends Table<SCIMProviderUser> {
|
||||
@property({ type: Number })
|
||||
providerId?: number;
|
||||
|
||||
searchEnabled(): boolean {
|
||||
return true;
|
||||
}
|
||||
|
||||
checkbox = true;
|
||||
clearOnRefresh = true;
|
||||
|
||||
renderToolbarSelected(): TemplateResult {
|
||||
const disabled = this.selectedElements.length < 1;
|
||||
return html`<ak-forms-delete-bulk
|
||||
objectLabel=${msg("SCIM User(s)")}
|
||||
.objects=${this.selectedElements}
|
||||
.delete=${(item: SCIMProviderUser) => {
|
||||
return new ProvidersApi(DEFAULT_CONFIG).providersScimUsersDestroy({
|
||||
id: item.id,
|
||||
});
|
||||
}}
|
||||
>
|
||||
<button ?disabled=${disabled} slot="trigger" class="pf-c-button pf-m-danger">
|
||||
${msg("Delete")}
|
||||
</button>
|
||||
</ak-forms-delete-bulk>`;
|
||||
}
|
||||
|
||||
async apiEndpoint(page: number): Promise<PaginatedResponse<SCIMProviderUser>> {
|
||||
return new ProvidersApi(DEFAULT_CONFIG).providersScimUsersList({
|
||||
page: page,
|
||||
pageSize: (await uiConfig()).pagination.perPage,
|
||||
ordering: this.order,
|
||||
search: this.search || "",
|
||||
providerId: this.providerId,
|
||||
});
|
||||
}
|
||||
|
||||
columns(): TableColumn[] {
|
||||
return [new TableColumn(msg("Username")), new TableColumn(msg("ID"))];
|
||||
}
|
||||
|
||||
row(item: SCIMProviderUser): TemplateResult[] {
|
||||
return [
|
||||
html`<a href="#/identity/users/${item.userObj.pk}">
|
||||
<div>${item.userObj.username}</div>
|
||||
<small>${item.userObj.name}</small>
|
||||
</a>`,
|
||||
html`${item.id}`,
|
||||
];
|
||||
}
|
||||
}
|
@ -1,4 +1,6 @@
|
||||
import "@goauthentik/admin/providers/scim/SCIMProviderForm";
|
||||
import "@goauthentik/admin/providers/scim/SCIMProviderGroupList";
|
||||
import "@goauthentik/admin/providers/scim/SCIMProviderUserList";
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { EVENT_REFRESH } from "@goauthentik/common/constants";
|
||||
import "@goauthentik/components/events/ObjectChangelog";
|
||||
@ -102,6 +104,28 @@ export class SCIMProviderViewPage extends AKElement {
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<section
|
||||
slot="page-users"
|
||||
data-tab-title="${msg("Provisioned Users")}"
|
||||
class="pf-c-page__main-section pf-m-no-padding-mobile"
|
||||
>
|
||||
<div class="pf-l-grid pf-m-gutter">
|
||||
<ak-provider-scim-users-list
|
||||
providerId=${this.provider.pk}
|
||||
></ak-provider-scim-users-list>
|
||||
</div>
|
||||
</section>
|
||||
<section
|
||||
slot="page-groups"
|
||||
data-tab-title="${msg("Provisioned Groups")}"
|
||||
class="pf-c-page__main-section pf-m-no-padding-mobile"
|
||||
>
|
||||
<div class="pf-l-grid pf-m-gutter">
|
||||
<ak-provider-scim-groups-list
|
||||
providerId=${this.provider.pk}
|
||||
></ak-provider-scim-groups-list>
|
||||
</div>
|
||||
</section>
|
||||
<ak-rbac-object-permission-page
|
||||
slot="page-permissions"
|
||||
data-tab-title="${msg("Permissions")}"
|
||||
|
@ -1,5 +1,7 @@
|
||||
import { BaseStageForm } from "@goauthentik/admin/stages/BaseStageForm";
|
||||
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
|
||||
import { first } from "@goauthentik/common/utils";
|
||||
import "@goauthentik/components/ak-number-input";
|
||||
import "@goauthentik/elements/forms/FormGroup";
|
||||
import "@goauthentik/elements/forms/HorizontalFormElement";
|
||||
|
||||
@ -78,6 +80,40 @@ export class CaptchaStageForm extends BaseStageForm<CaptchaStage> {
|
||||
)}
|
||||
</p>
|
||||
</ak-form-element-horizontal>
|
||||
<ak-number-input
|
||||
label=${msg("Score minimum threshold")}
|
||||
required
|
||||
name="scoreMinThreshold"
|
||||
value="${ifDefined(this.instance?.scoreMinThreshold || 0.5)}"
|
||||
help=${msg("Minimum required score to allow continuing")}
|
||||
></ak-number-input>
|
||||
<ak-number-input
|
||||
label=${msg("Score maximum threshold")}
|
||||
required
|
||||
name="scoreMaxThreshold"
|
||||
value="${ifDefined(this.instance?.scoreMaxThreshold || -1)}"
|
||||
help=${msg("Maximum allowed score to allow continuing")}
|
||||
></ak-number-input>
|
||||
<ak-form-element-horizontal name="errorOnInvalidScore">
|
||||
<label class="pf-c-switch">
|
||||
<input
|
||||
class="pf-c-switch__input"
|
||||
type="checkbox"
|
||||
?checked=${first(this.instance?.errorOnInvalidScore, true)}
|
||||
/>
|
||||
<span class="pf-c-switch__toggle">
|
||||
<span class="pf-c-switch__toggle-icon">
|
||||
<i class="fas fa-check" aria-hidden="true"></i>
|
||||
</span>
|
||||
</span>
|
||||
<span class="pf-c-switch__label">${msg("Error on invalid score")}</span>
|
||||
</label>
|
||||
<p class="pf-c-form__helper-text">
|
||||
${msg(
|
||||
"When enabled and the resultant score is outside the threshold, the user will not be able to continue. When disabled, the user will be able to continue and the score can be used in policies to customize further stages.",
|
||||
)}
|
||||
</p>
|
||||
</ak-form-element-horizontal>
|
||||
</div>
|
||||
</ak-form-group>
|
||||
<ak-form-group>
|
||||
|
@ -3,7 +3,7 @@ import { PFSize } from "@goauthentik/common/enums.js";
|
||||
import { AKElement } from "@goauthentik/elements/Base";
|
||||
import { CustomEmitterElement } from "@goauthentik/elements/utils/eventEmitter";
|
||||
|
||||
import { Task, TaskStatus } from "@lit/task";
|
||||
import { Task, TaskStatus, initialState } from "@lit/task";
|
||||
import { css, html } from "lit";
|
||||
import { property } from "lit/decorators.js";
|
||||
|
||||
@ -67,7 +67,7 @@ export abstract class BaseTaskButton extends CustomEmitterElement(AKElement) {
|
||||
this.onError = this.onError.bind(this);
|
||||
this.onClick = this.onClick.bind(this);
|
||||
this.actionTask = new Task(this, {
|
||||
task: () => this.callAction(),
|
||||
task: () => this.runCallAction(),
|
||||
args: () => [],
|
||||
autoRun: false,
|
||||
onComplete: (r: unknown) => this.onSuccess(r),
|
||||
@ -77,7 +77,6 @@ export abstract class BaseTaskButton extends CustomEmitterElement(AKElement) {
|
||||
|
||||
onComplete() {
|
||||
setTimeout(() => {
|
||||
this.actionTask.status = TaskStatus.INITIAL;
|
||||
this.dispatchCustomEvent(`${this.eventPrefix}-reset`);
|
||||
this.requestUpdate();
|
||||
}, SPINNER_TIMEOUT);
|
||||
@ -97,10 +96,12 @@ export abstract class BaseTaskButton extends CustomEmitterElement(AKElement) {
|
||||
this.onComplete();
|
||||
}
|
||||
|
||||
async runCallAction() {
|
||||
await this.callAction();
|
||||
return initialState;
|
||||
}
|
||||
|
||||
onClick() {
|
||||
if (this.actionTask.status !== TaskStatus.INITIAL) {
|
||||
return;
|
||||
}
|
||||
this.dispatchCustomEvent(`${this.eventPrefix}-click`);
|
||||
this.actionTask.run();
|
||||
}
|
||||
@ -113,7 +114,7 @@ export abstract class BaseTaskButton extends CustomEmitterElement(AKElement) {
|
||||
return [
|
||||
...this.classList,
|
||||
StatusMap.get(this.actionTask.status),
|
||||
this.actionTask.status === TaskStatus.INITIAL ? "" : "working",
|
||||
this.actionTask.status === TaskStatus.PENDING ? "working" : "",
|
||||
]
|
||||
.join(" ")
|
||||
.trim();
|
||||
|
5
web/src/elements/password-match-indicator/index.ts
Normal file
5
web/src/elements/password-match-indicator/index.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import PasswordMatchIndicator from "./password-match-indicator.js";
|
||||
|
||||
export { PasswordMatchIndicator };
|
||||
|
||||
export default PasswordMatchIndicator;
|
@ -0,0 +1,19 @@
|
||||
import { html } from "lit";
|
||||
|
||||
import ".";
|
||||
|
||||
export default {
|
||||
title: "Elements/Password Match Indicator",
|
||||
};
|
||||
|
||||
export const Primary = () =>
|
||||
html`<div style="background: #fff; padding: 4em">
|
||||
<p>Type some text: <input id="primary-example" style="color:#000" /></p>
|
||||
<p style="margin-top:0.5em">
|
||||
Type some other text: <input id="primary-example_repeat" style="color:#000" />
|
||||
<ak-password-match-indicator
|
||||
first="#primary-example"
|
||||
second="#primary-example_repeat"
|
||||
></ak-password-match-indicator>
|
||||
</p>
|
||||
</div>`;
|
@ -0,0 +1,94 @@
|
||||
import { AKElement } from "@goauthentik/elements/Base";
|
||||
|
||||
import { css, html } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators.js";
|
||||
|
||||
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
||||
|
||||
import findInput from "../password-strength-indicator/findInput.js";
|
||||
|
||||
const ELEMENT = "ak-password-match-indicator";
|
||||
|
||||
@customElement(ELEMENT)
|
||||
export class PasswordMatchIndicator extends AKElement {
|
||||
static styles = [
|
||||
PFBase,
|
||||
css`
|
||||
:host {
|
||||
display: grid;
|
||||
place-items: center center;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
/**
|
||||
* A valid selector for the first input element to observe. Attaching this to anything other
|
||||
* than an HTMLInputElement will throw an exception.
|
||||
*/
|
||||
@property({ attribute: true })
|
||||
first = "";
|
||||
|
||||
/**
|
||||
* A valid selector for the second input element to observe. Attaching this to anything other
|
||||
* than an HTMLInputElement will throw an exception.
|
||||
*/
|
||||
@property({ attribute: true })
|
||||
second = "";
|
||||
|
||||
firstElement?: HTMLInputElement;
|
||||
|
||||
secondElement?: HTMLInputElement;
|
||||
|
||||
@state()
|
||||
match = false;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.checkPasswordMatch = this.checkPasswordMatch.bind(this);
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
this.firstInput.addEventListener("keyup", this.checkPasswordMatch);
|
||||
this.secondInput.addEventListener("keyup", this.checkPasswordMatch);
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
this.secondInput.removeEventListener("keyup", this.checkPasswordMatch);
|
||||
this.firstInput.removeEventListener("keyup", this.checkPasswordMatch);
|
||||
super.disconnectedCallback();
|
||||
}
|
||||
|
||||
checkPasswordMatch() {
|
||||
this.match =
|
||||
this.firstInput.value.length > 0 &&
|
||||
this.secondInput.value.length > 0 &&
|
||||
this.firstInput.value === this.secondInput.value;
|
||||
}
|
||||
|
||||
get firstInput() {
|
||||
if (this.firstElement) {
|
||||
return this.firstElement;
|
||||
}
|
||||
return (this.firstElement = findInput(this.getRootNode() as Element, ELEMENT, this.first));
|
||||
}
|
||||
|
||||
get secondInput() {
|
||||
if (this.secondElement) {
|
||||
return this.secondElement;
|
||||
}
|
||||
return (this.secondElement = findInput(
|
||||
this.getRootNode() as Element,
|
||||
ELEMENT,
|
||||
this.second,
|
||||
));
|
||||
}
|
||||
|
||||
render() {
|
||||
return this.match
|
||||
? html`<i class="pf-icon pf-icon-ok pf-m-success"></i>`
|
||||
: html`<i class="pf-icon pf-icon-warning-triangle pf-m-warning"></i>`;
|
||||
}
|
||||
}
|
||||
|
||||
export default PasswordMatchIndicator;
|
18
web/src/elements/password-strength-indicator/findInput.ts
Normal file
18
web/src/elements/password-strength-indicator/findInput.ts
Normal file
@ -0,0 +1,18 @@
|
||||
export function findInput(root: Element, tag: string, src: string) {
|
||||
const inputs = Array.from(root.querySelectorAll(src));
|
||||
if (inputs.length === 0) {
|
||||
throw new Error(`${tag}: no element found for 'src' ${src}`);
|
||||
}
|
||||
if (inputs.length > 1) {
|
||||
throw new Error(`${tag}: more than one element found for 'src' ${src}`);
|
||||
}
|
||||
const input = inputs[0];
|
||||
if (!(input instanceof HTMLInputElement)) {
|
||||
throw new Error(
|
||||
`${tag}: the 'src' element must be an <input> tag, found ${input.localName}`,
|
||||
);
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
export default findInput;
|
5
web/src/elements/password-strength-indicator/index.ts
Normal file
5
web/src/elements/password-strength-indicator/index.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import PasswordStrengthIndicator from "./password-strength-indicator.js";
|
||||
|
||||
export { PasswordStrengthIndicator };
|
||||
|
||||
export default PasswordStrengthIndicator;
|
@ -0,0 +1,13 @@
|
||||
import { html } from "lit";
|
||||
|
||||
import ".";
|
||||
|
||||
export default {
|
||||
title: "Elements/Password Strength Indicator",
|
||||
};
|
||||
|
||||
export const Primary = () =>
|
||||
html`<div style="background: #fff; padding: 4em">
|
||||
<p>Type some text: <input id="primary-example" style="color:#000" /></p>
|
||||
<ak-password-strength-indicator src="#primary-example"></ak-password-strength-indicator>
|
||||
</div>`;
|
@ -0,0 +1,91 @@
|
||||
import { AKElement } from "@goauthentik/elements/Base";
|
||||
import zxcvbn from "zxcvbn";
|
||||
|
||||
import { css, html } from "lit";
|
||||
import { styleMap } from "lit-html/directives/style-map.js";
|
||||
import { customElement, property, state } from "lit/decorators.js";
|
||||
|
||||
import findInput from "./findInput";
|
||||
|
||||
const styles = css`
|
||||
.password-meter-wrap {
|
||||
margin-top: 5px;
|
||||
height: 0.5em;
|
||||
background-color: #ddd;
|
||||
border-radius: 0.25em;
|
||||
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.password-meter-bar {
|
||||
width: 0;
|
||||
height: 100%;
|
||||
transition: width 400ms ease-in;
|
||||
}
|
||||
`;
|
||||
|
||||
const LEVELS = [
|
||||
["20%", "#dd0000"],
|
||||
["40%", "#ff5500"],
|
||||
["60%", "#ffff00"],
|
||||
["80%", "#a1a841"],
|
||||
["100%", "#339933"],
|
||||
].map(([width, backgroundColor]) => ({ width, backgroundColor }));
|
||||
|
||||
/**
|
||||
* A simple display of the password strength.
|
||||
*/
|
||||
|
||||
const ELEMENT = "ak-password-strength-indicator";
|
||||
|
||||
@customElement(ELEMENT)
|
||||
export class PasswordStrengthIndicator extends AKElement {
|
||||
static styles = styles;
|
||||
|
||||
/**
|
||||
* The input element to observe. Attaching this to anything other than an HTMLInputElement will
|
||||
* throw an exception.
|
||||
*/
|
||||
@property({ attribute: true })
|
||||
src = "";
|
||||
|
||||
sourceInput?: HTMLInputElement;
|
||||
|
||||
@state()
|
||||
strength = LEVELS[0];
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
this.checkPasswordStrength = this.checkPasswordStrength.bind(this);
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
super.connectedCallback();
|
||||
this.input.addEventListener("keyup", this.checkPasswordStrength);
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
this.input.removeEventListener("keyup", this.checkPasswordStrength);
|
||||
super.disconnectedCallback();
|
||||
}
|
||||
|
||||
checkPasswordStrength() {
|
||||
const { score } = zxcvbn(this.input.value);
|
||||
this.strength = LEVELS[score];
|
||||
}
|
||||
|
||||
get input(): HTMLInputElement {
|
||||
if (this.sourceInput) {
|
||||
return this.sourceInput;
|
||||
}
|
||||
return (this.sourceInput = findInput(this.getRootNode() as Element, ELEMENT, this.src));
|
||||
}
|
||||
|
||||
render() {
|
||||
return html` <div class="password-meter-wrap">
|
||||
<div class="password-meter-bar" style=${styleMap(this.strength)}></div>
|
||||
</div>`;
|
||||
}
|
||||
}
|
||||
|
||||
export default PasswordStrengthIndicator;
|
@ -15,7 +15,7 @@ import PFProgressStepper from "@patternfly/patternfly/components/ProgressStepper
|
||||
import PFStack from "@patternfly/patternfly/layouts/Stack/stack.css";
|
||||
import PFBase from "@patternfly/patternfly/patternfly-base.css";
|
||||
|
||||
import { FlowInspection, FlowsApi, Stage } from "@goauthentik/api";
|
||||
import { FlowInspection, FlowsApi, ResponseError, Stage } from "@goauthentik/api";
|
||||
|
||||
@customElement("ak-flow-inspector")
|
||||
export class FlowInspector extends AKElement {
|
||||
@ -25,7 +25,7 @@ export class FlowInspector extends AKElement {
|
||||
state?: FlowInspection;
|
||||
|
||||
@property({ attribute: false })
|
||||
error?: Response;
|
||||
error?: ResponseError;
|
||||
|
||||
static get styles(): CSSResult[] {
|
||||
return [
|
||||
@ -70,6 +70,7 @@ export class FlowInspector extends AKElement {
|
||||
flowSlug: this.flowSlug,
|
||||
})
|
||||
.then((state) => {
|
||||
this.error = undefined;
|
||||
this.state = state;
|
||||
})
|
||||
.catch((exc) => {
|
||||
@ -100,7 +101,7 @@ export class FlowInspector extends AKElement {
|
||||
<div class="pf-l-stack pf-m-gutter">
|
||||
<div class="pf-l-stack__item">
|
||||
<div class="pf-c-card">
|
||||
<div class="pf-c-card__body">${this.error?.statusText}</div>
|
||||
<div class="pf-c-card__body">${this.error?.message}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
108
web/src/flow/stages/prompt/FieldRenderers.stories.ts
Normal file
108
web/src/flow/stages/prompt/FieldRenderers.stories.ts
Normal file
@ -0,0 +1,108 @@
|
||||
import { TemplateResult, html } from "lit";
|
||||
|
||||
import "@patternfly/patternfly/components/Alert/alert.css";
|
||||
import "@patternfly/patternfly/components/Button/button.css";
|
||||
import "@patternfly/patternfly/components/Check/check.css";
|
||||
import "@patternfly/patternfly/components/Form/form.css";
|
||||
import "@patternfly/patternfly/components/FormControl/form-control.css";
|
||||
import "@patternfly/patternfly/components/Login/login.css";
|
||||
import "@patternfly/patternfly/components/Title/title.css";
|
||||
import "@patternfly/patternfly/patternfly-base.css";
|
||||
|
||||
import { PromptTypeEnum } from "@goauthentik/api";
|
||||
import type { StagePrompt } from "@goauthentik/api";
|
||||
|
||||
import promptRenderers from "./FieldRenderers";
|
||||
import { renderContinue, renderPromptHelpText, renderPromptInner } from "./helpers";
|
||||
|
||||
// Storybook stories are meant to show not just that the objects work, but to document good
|
||||
// practices around using them. Because of their uniform signature, the renderers can easily
|
||||
// be encapsulated into containers that show them at their most functional, even without
|
||||
// building Shadow DOMs with which to do it. This is 100% Light DOM work, and they still
|
||||
// work well.
|
||||
|
||||
const baseRenderer = (prompt: TemplateResult) =>
|
||||
html`<div style="background: #fff; padding: 4em; max-width: 24em;">
|
||||
<style>
|
||||
input,
|
||||
textarea,
|
||||
select,
|
||||
button,
|
||||
.pf-c-form__helper-text:not(.pf-m-error),
|
||||
input + label.pf-c-check__label {
|
||||
color: #000;
|
||||
}
|
||||
input[readonly],
|
||||
textarea[readonly] {
|
||||
color: #fff;
|
||||
}
|
||||
</style>
|
||||
${prompt}
|
||||
</div>`;
|
||||
|
||||
function renderer(kind: PromptTypeEnum, prompt: Partial<StagePrompt>) {
|
||||
const renderer = promptRenderers.get(kind);
|
||||
if (!renderer) {
|
||||
throw new Error(`A renderer of type ${kind} does not exist.`);
|
||||
}
|
||||
return baseRenderer(html`${renderer(prompt as StagePrompt)}`);
|
||||
}
|
||||
|
||||
const textPrompt = {
|
||||
fieldKey: "test_text_field",
|
||||
placeholder: "This is the placeholder",
|
||||
required: false,
|
||||
initialValue: "initial value",
|
||||
};
|
||||
|
||||
export const Text = () => renderer(PromptTypeEnum.Text, textPrompt);
|
||||
export const TextArea = () => renderer(PromptTypeEnum.TextArea, textPrompt);
|
||||
export const TextReadOnly = () => renderer(PromptTypeEnum.TextReadOnly, textPrompt);
|
||||
export const TextAreaReadOnly = () => renderer(PromptTypeEnum.TextAreaReadOnly, textPrompt);
|
||||
export const Username = () => renderer(PromptTypeEnum.Username, textPrompt);
|
||||
export const Password = () => renderer(PromptTypeEnum.Password, textPrompt);
|
||||
|
||||
const emailPrompt = { ...textPrompt, initialValue: "example@example.fun" };
|
||||
export const Email = () => renderer(PromptTypeEnum.Email, emailPrompt);
|
||||
|
||||
const numberPrompt = { ...textPrompt, initialValue: "10" };
|
||||
export const Number = () => renderer(PromptTypeEnum.Number, numberPrompt);
|
||||
|
||||
const datePrompt = { ...textPrompt, initialValue: "2018-06-12T19:30" };
|
||||
export const Date = () => renderer(PromptTypeEnum.Date, datePrompt);
|
||||
export const DateTime = () => renderer(PromptTypeEnum.DateTime, datePrompt);
|
||||
|
||||
const separatorPrompt = { placeholder: "😊" };
|
||||
export const Separator = () => renderer(PromptTypeEnum.Separator, separatorPrompt);
|
||||
|
||||
const staticPrompt = { initialValue: "😊" };
|
||||
export const Static = () => renderer(PromptTypeEnum.Static, staticPrompt);
|
||||
|
||||
const choicePrompt = {
|
||||
fieldKey: "test_text_field",
|
||||
placeholder: "This is the placeholder",
|
||||
required: false,
|
||||
initialValue: "first",
|
||||
choices: ["first", "second", "third"],
|
||||
};
|
||||
|
||||
export const Dropdown = () => renderer(PromptTypeEnum.Dropdown, choicePrompt);
|
||||
export const RadioButtonGroup = () => renderer(PromptTypeEnum.RadioButtonGroup, choicePrompt);
|
||||
|
||||
const checkPrompt = { ...textPrompt, label: "Favorite Subtext?", subText: "(Xena & Gabrielle)" };
|
||||
export const Checkbox = () => renderer(PromptTypeEnum.Checkbox, checkPrompt);
|
||||
|
||||
const localePrompt = { ...textPrompt, initialValue: "en" };
|
||||
export const Locale = () => renderer(PromptTypeEnum.AkLocale, localePrompt);
|
||||
|
||||
export const PromptFailure = () =>
|
||||
baseRenderer(renderPromptInner({ type: null } as unknown as StagePrompt));
|
||||
|
||||
export const HelpText = () =>
|
||||
baseRenderer(renderPromptHelpText({ subText: "There is no subtext here." } as StagePrompt));
|
||||
|
||||
export const Continue = () => baseRenderer(renderContinue());
|
||||
|
||||
export default {
|
||||
title: "Flow Components/Field Renderers",
|
||||
};
|
271
web/src/flow/stages/prompt/FieldRenderers.ts
Normal file
271
web/src/flow/stages/prompt/FieldRenderers.ts
Normal file
@ -0,0 +1,271 @@
|
||||
import { rootInterface } from "@goauthentik/elements/Base";
|
||||
import { LOCALES } from "@goauthentik/elements/ak-locale-context/helpers";
|
||||
import "@goauthentik/elements/password-match-indicator";
|
||||
import "@goauthentik/elements/password-strength-indicator";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
import { TemplateResult, html } from "lit";
|
||||
import { unsafeHTML } from "lit/directives/unsafe-html.js";
|
||||
|
||||
import { CapabilitiesEnum, PromptTypeEnum, StagePrompt } from "@goauthentik/api";
|
||||
|
||||
export function password(prompt: StagePrompt) {
|
||||
return html`<input
|
||||
type="password"
|
||||
name="${prompt.fieldKey}"
|
||||
placeholder="${prompt.placeholder}"
|
||||
autocomplete="new-password"
|
||||
class="pf-c-form-control"
|
||||
?required=${prompt.required}
|
||||
/><ak-password-strength-indicator
|
||||
src='input[name="${prompt.fieldKey}"]'
|
||||
></ak-password-strength-indicator>`;
|
||||
}
|
||||
|
||||
const REPEAT = /_repeat/;
|
||||
|
||||
export function repeatPassword(prompt: StagePrompt) {
|
||||
const first = `input[name="${prompt.fieldKey}"]`;
|
||||
const second = `input[name="${prompt.fieldKey.replace(REPEAT, "")}"]`;
|
||||
|
||||
return html` <div style="display:flex; flex-direction:row; gap: 0.5em; align-content: center">
|
||||
<input
|
||||
style="flex:1 0"
|
||||
type="password"
|
||||
name="${prompt.fieldKey}"
|
||||
placeholder="${prompt.placeholder}"
|
||||
autocomplete="new-password"
|
||||
class="pf-c-form-control"
|
||||
?required=${prompt.required}
|
||||
/><ak-password-match-indicator
|
||||
first="${first}"
|
||||
second="${second}"
|
||||
></ak-password-match-indicator>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
export function renderPassword(prompt: StagePrompt) {
|
||||
return REPEAT.test(prompt.fieldKey) ? repeatPassword(prompt) : password(prompt);
|
||||
}
|
||||
|
||||
export function renderText(prompt: StagePrompt) {
|
||||
return html`<input
|
||||
type="text"
|
||||
name="${prompt.fieldKey}"
|
||||
placeholder="${prompt.placeholder}"
|
||||
autocomplete="off"
|
||||
class="pf-c-form-control"
|
||||
?required=${prompt.required}
|
||||
value="${prompt.initialValue}"
|
||||
/>`;
|
||||
}
|
||||
|
||||
export function renderTextArea(prompt: StagePrompt) {
|
||||
return html`<textarea
|
||||
name="${prompt.fieldKey}"
|
||||
placeholder="${prompt.placeholder}"
|
||||
autocomplete="off"
|
||||
class="pf-c-form-control"
|
||||
?required=${prompt.required}
|
||||
>
|
||||
${prompt.initialValue}</textarea
|
||||
>`;
|
||||
}
|
||||
|
||||
export function renderTextReadOnly(prompt: StagePrompt) {
|
||||
return html`<input
|
||||
type="text"
|
||||
name="${prompt.fieldKey}"
|
||||
placeholder="${prompt.placeholder}"
|
||||
class="pf-c-form-control"
|
||||
?readonly=${true}
|
||||
value="${prompt.initialValue}"
|
||||
/>`;
|
||||
}
|
||||
|
||||
export function renderTextAreaReadOnly(prompt: StagePrompt) {
|
||||
return html`<textarea
|
||||
name="${prompt.fieldKey}"
|
||||
placeholder="${prompt.placeholder}"
|
||||
class="pf-c-form-control"
|
||||
readonly
|
||||
>
|
||||
${prompt.initialValue}</textarea
|
||||
>`;
|
||||
}
|
||||
|
||||
export function renderUsername(prompt: StagePrompt) {
|
||||
return html`<input
|
||||
type="text"
|
||||
name="${prompt.fieldKey}"
|
||||
placeholder="${prompt.placeholder}"
|
||||
autocomplete="username"
|
||||
class="pf-c-form-control"
|
||||
?required=${prompt.required}
|
||||
value="${prompt.initialValue}"
|
||||
/>`;
|
||||
}
|
||||
|
||||
export function renderEmail(prompt: StagePrompt) {
|
||||
return html`<input
|
||||
type="email"
|
||||
name="${prompt.fieldKey}"
|
||||
placeholder="${prompt.placeholder}"
|
||||
class="pf-c-form-control"
|
||||
?required=${prompt.required}
|
||||
value="${prompt.initialValue}"
|
||||
/>`;
|
||||
}
|
||||
|
||||
export function renderNumber(prompt: StagePrompt) {
|
||||
return html`<input
|
||||
type="number"
|
||||
name="${prompt.fieldKey}"
|
||||
placeholder="${prompt.placeholder}"
|
||||
class="pf-c-form-control"
|
||||
?required=${prompt.required}
|
||||
value="${prompt.initialValue}"
|
||||
/>`;
|
||||
}
|
||||
|
||||
export function renderDate(prompt: StagePrompt) {
|
||||
return html`<input
|
||||
type="date"
|
||||
name="${prompt.fieldKey}"
|
||||
placeholder="${prompt.placeholder}"
|
||||
class="pf-c-form-control"
|
||||
?required=${prompt.required}
|
||||
value="${prompt.initialValue}"
|
||||
/>`;
|
||||
}
|
||||
|
||||
export function renderDateTime(prompt: StagePrompt) {
|
||||
return html`<input
|
||||
type="datetime"
|
||||
name="${prompt.fieldKey}"
|
||||
placeholder="${prompt.placeholder}"
|
||||
class="pf-c-form-control"
|
||||
?required=${prompt.required}
|
||||
value="${prompt.initialValue}"
|
||||
/>`;
|
||||
}
|
||||
|
||||
export function renderFile(prompt: StagePrompt) {
|
||||
return html`<input
|
||||
type="file"
|
||||
name="${prompt.fieldKey}"
|
||||
placeholder="${prompt.placeholder}"
|
||||
class="pf-c-form-control"
|
||||
?required=${prompt.required}
|
||||
value="${prompt.initialValue}"
|
||||
/>`;
|
||||
}
|
||||
|
||||
export function renderSeparator(prompt: StagePrompt) {
|
||||
return html`<ak-divider>${prompt.placeholder}</ak-divider>`;
|
||||
}
|
||||
|
||||
export function renderHidden(prompt: StagePrompt) {
|
||||
return html`<input
|
||||
type="hidden"
|
||||
name="${prompt.fieldKey}"
|
||||
value="${prompt.initialValue}"
|
||||
class="pf-c-form-control"
|
||||
?required=${prompt.required}
|
||||
/>`;
|
||||
}
|
||||
|
||||
export function renderStatic(prompt: StagePrompt) {
|
||||
return html`<p>${unsafeHTML(prompt.initialValue)}</p>`;
|
||||
}
|
||||
|
||||
export function renderDropdown(prompt: StagePrompt) {
|
||||
return html`<select class="pf-c-form-control" name="${prompt.fieldKey}">
|
||||
${prompt.choices?.map((choice) => {
|
||||
return html`<option value="${choice}" ?selected=${prompt.initialValue === choice}>
|
||||
${choice}
|
||||
</option>`;
|
||||
})}
|
||||
</select>`;
|
||||
}
|
||||
|
||||
export function renderRadioButtonGroup(prompt: StagePrompt) {
|
||||
return html`${(prompt.choices || []).map((choice) => {
|
||||
const id = `${prompt.fieldKey}-${choice}`;
|
||||
return html`<div class="pf-c-check">
|
||||
<input
|
||||
type="radio"
|
||||
class="pf-c-check__input"
|
||||
name="${prompt.fieldKey}"
|
||||
id="${id}"
|
||||
?checked="${prompt.initialValue === choice}"
|
||||
?required="${prompt.required}"
|
||||
value="${choice}"
|
||||
/>
|
||||
<label class="pf-c-check__label" for=${id}>${choice}</label>
|
||||
</div> `;
|
||||
})}`;
|
||||
}
|
||||
|
||||
export function renderCheckbox(prompt: StagePrompt) {
|
||||
return html`<div class="pf-c-check">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="pf-c-check__input"
|
||||
id="${prompt.fieldKey}"
|
||||
name="${prompt.fieldKey}"
|
||||
?checked=${prompt.initialValue !== ""}
|
||||
?required=${prompt.required}
|
||||
/>
|
||||
<label class="pf-c-check__label" for="${prompt.fieldKey}">${prompt.label}</label>
|
||||
${prompt.required
|
||||
? html`<p class="pf-c-form__helper-text">${msg("Required.")}</p>`
|
||||
: html``}
|
||||
<p class="pf-c-form__helper-text">${unsafeHTML(prompt.subText)}</p>
|
||||
</div>`;
|
||||
}
|
||||
|
||||
export function renderAkLocale(prompt: StagePrompt) {
|
||||
// TODO: External reference.
|
||||
const inDebug = rootInterface()?.config?.capabilities.includes(CapabilitiesEnum.CanDebug);
|
||||
const locales = inDebug ? LOCALES : LOCALES.filter((locale) => locale.code !== "debug");
|
||||
|
||||
const options = locales.map(
|
||||
(locale) =>
|
||||
html`<option value=${locale.code} ?selected=${locale.code === prompt.initialValue}>
|
||||
${locale.code.toUpperCase()} - ${locale.label()}
|
||||
</option> `,
|
||||
);
|
||||
|
||||
return html`<select class="pf-c-form-control" name="${prompt.fieldKey}">
|
||||
<option value="" ?selected=${prompt.initialValue === ""}>
|
||||
${msg("Auto-detect (based on your browser)")}
|
||||
</option>
|
||||
${options}
|
||||
</select>`;
|
||||
}
|
||||
|
||||
type Renderer = (prompt: StagePrompt) => TemplateResult;
|
||||
|
||||
export const promptRenderers = new Map<PromptTypeEnum, Renderer>([
|
||||
[PromptTypeEnum.Text, renderText],
|
||||
[PromptTypeEnum.TextArea, renderTextArea],
|
||||
[PromptTypeEnum.TextReadOnly, renderTextReadOnly],
|
||||
[PromptTypeEnum.TextAreaReadOnly, renderTextAreaReadOnly],
|
||||
[PromptTypeEnum.Username, renderUsername],
|
||||
[PromptTypeEnum.Email, renderEmail],
|
||||
[PromptTypeEnum.Password, renderPassword],
|
||||
[PromptTypeEnum.Number, renderNumber],
|
||||
[PromptTypeEnum.Date, renderDate],
|
||||
[PromptTypeEnum.DateTime, renderDateTime],
|
||||
[PromptTypeEnum.File, renderFile],
|
||||
[PromptTypeEnum.Separator, renderSeparator],
|
||||
[PromptTypeEnum.Hidden, renderHidden],
|
||||
[PromptTypeEnum.Static, renderStatic],
|
||||
[PromptTypeEnum.Dropdown, renderDropdown],
|
||||
[PromptTypeEnum.RadioButtonGroup, renderRadioButtonGroup],
|
||||
[PromptTypeEnum.Checkbox, renderCheckbox],
|
||||
[PromptTypeEnum.AkLocale, renderAkLocale],
|
||||
]);
|
||||
|
||||
export default promptRenderers;
|
@ -1,17 +1,12 @@
|
||||
import "@goauthentik/elements/Divider";
|
||||
import "@goauthentik/elements/EmptyState";
|
||||
import {
|
||||
CapabilitiesEnum,
|
||||
WithCapabilitiesConfig,
|
||||
} from "@goauthentik/elements/Interface/capabilitiesProvider";
|
||||
import { LOCALES } from "@goauthentik/elements/ak-locale-context/definitions";
|
||||
import { WithCapabilitiesConfig } from "@goauthentik/elements/Interface/capabilitiesProvider";
|
||||
import "@goauthentik/elements/forms/FormElement";
|
||||
import { BaseStage } from "@goauthentik/flow/stages/base";
|
||||
|
||||
import { msg } from "@lit/localize";
|
||||
import { CSSResult, TemplateResult, css, html } from "lit";
|
||||
import { customElement } from "lit/decorators.js";
|
||||
import { unsafeHTML } from "lit/directives/unsafe-html.js";
|
||||
|
||||
import PFAlert from "@patternfly/patternfly/components/Alert/alert.css";
|
||||
import PFButton from "@patternfly/patternfly/components/Button/button.css";
|
||||
@ -29,6 +24,14 @@ import {
|
||||
StagePrompt,
|
||||
} from "@goauthentik/api";
|
||||
|
||||
import { renderCheckbox } from "./FieldRenderers";
|
||||
import {
|
||||
renderContinue,
|
||||
renderPromptHelpText,
|
||||
renderPromptInner,
|
||||
shouldRenderInWrapper,
|
||||
} from "./helpers";
|
||||
|
||||
@customElement("ak-stage-prompt")
|
||||
export class PromptStage extends WithCapabilitiesConfig(
|
||||
BaseStage<PromptChallenge, PromptChallengeResponseRequest>,
|
||||
@ -53,232 +56,35 @@ export class PromptStage extends WithCapabilitiesConfig(
|
||||
];
|
||||
}
|
||||
|
||||
renderPromptInner(prompt: StagePrompt): TemplateResult {
|
||||
switch (prompt.type) {
|
||||
case PromptTypeEnum.Text:
|
||||
return html`<input
|
||||
type="text"
|
||||
name="${prompt.fieldKey}"
|
||||
placeholder="${prompt.placeholder}"
|
||||
autocomplete="off"
|
||||
class="pf-c-form-control"
|
||||
?required=${prompt.required}
|
||||
value="${prompt.initialValue}"
|
||||
/>`;
|
||||
case PromptTypeEnum.TextArea:
|
||||
return html`<textarea
|
||||
name="${prompt.fieldKey}"
|
||||
placeholder="${prompt.placeholder}"
|
||||
autocomplete="off"
|
||||
class="pf-c-form-control"
|
||||
?required=${prompt.required}
|
||||
>
|
||||
${prompt.initialValue}</textarea
|
||||
>`;
|
||||
case PromptTypeEnum.TextReadOnly:
|
||||
return html`<input
|
||||
type="text"
|
||||
name="${prompt.fieldKey}"
|
||||
placeholder="${prompt.placeholder}"
|
||||
class="pf-c-form-control"
|
||||
?readonly=${true}
|
||||
value="${prompt.initialValue}"
|
||||
/>`;
|
||||
case PromptTypeEnum.TextAreaReadOnly:
|
||||
return html`<textarea
|
||||
name="${prompt.fieldKey}"
|
||||
placeholder="${prompt.placeholder}"
|
||||
class="pf-c-form-control"
|
||||
readonly
|
||||
>
|
||||
${prompt.initialValue}</textarea
|
||||
>`;
|
||||
case PromptTypeEnum.Username:
|
||||
return html`<input
|
||||
type="text"
|
||||
name="${prompt.fieldKey}"
|
||||
placeholder="${prompt.placeholder}"
|
||||
autocomplete="username"
|
||||
class="pf-c-form-control"
|
||||
?required=${prompt.required}
|
||||
value="${prompt.initialValue}"
|
||||
/>`;
|
||||
case PromptTypeEnum.Email:
|
||||
return html`<input
|
||||
type="email"
|
||||
name="${prompt.fieldKey}"
|
||||
placeholder="${prompt.placeholder}"
|
||||
class="pf-c-form-control"
|
||||
?required=${prompt.required}
|
||||
value="${prompt.initialValue}"
|
||||
/>`;
|
||||
case PromptTypeEnum.Password:
|
||||
return html`<input
|
||||
type="password"
|
||||
name="${prompt.fieldKey}"
|
||||
placeholder="${prompt.placeholder}"
|
||||
autocomplete="new-password"
|
||||
class="pf-c-form-control"
|
||||
?required=${prompt.required}
|
||||
/>`;
|
||||
case PromptTypeEnum.Number:
|
||||
return html`<input
|
||||
type="number"
|
||||
name="${prompt.fieldKey}"
|
||||
placeholder="${prompt.placeholder}"
|
||||
class="pf-c-form-control"
|
||||
?required=${prompt.required}
|
||||
value="${prompt.initialValue}"
|
||||
/>`;
|
||||
case PromptTypeEnum.Date:
|
||||
return html`<input
|
||||
type="date"
|
||||
name="${prompt.fieldKey}"
|
||||
placeholder="${prompt.placeholder}"
|
||||
class="pf-c-form-control"
|
||||
?required=${prompt.required}
|
||||
value="${prompt.initialValue}"
|
||||
/>`;
|
||||
case PromptTypeEnum.DateTime:
|
||||
return html`<input
|
||||
type="datetime"
|
||||
name="${prompt.fieldKey}"
|
||||
placeholder="${prompt.placeholder}"
|
||||
class="pf-c-form-control"
|
||||
?required=${prompt.required}
|
||||
value="${prompt.initialValue}"
|
||||
/>`;
|
||||
case PromptTypeEnum.File:
|
||||
return html`<input
|
||||
type="file"
|
||||
name="${prompt.fieldKey}"
|
||||
placeholder="${prompt.placeholder}"
|
||||
class="pf-c-form-control"
|
||||
?required=${prompt.required}
|
||||
value="${prompt.initialValue}"
|
||||
/>`;
|
||||
case PromptTypeEnum.Separator:
|
||||
return html`<ak-divider>${prompt.placeholder}</ak-divider>`;
|
||||
case PromptTypeEnum.Hidden:
|
||||
return html`<input
|
||||
type="hidden"
|
||||
name="${prompt.fieldKey}"
|
||||
value="${prompt.initialValue}"
|
||||
class="pf-c-form-control"
|
||||
?required=${prompt.required}
|
||||
/>`;
|
||||
case PromptTypeEnum.Static:
|
||||
return html`<p>${unsafeHTML(prompt.initialValue)}</p>`;
|
||||
case PromptTypeEnum.Dropdown:
|
||||
return html`<select class="pf-c-form-control" name="${prompt.fieldKey}">
|
||||
${prompt.choices?.map((choice) => {
|
||||
return html`<option
|
||||
value="${choice}"
|
||||
?selected=${prompt.initialValue === choice}
|
||||
>
|
||||
${choice}
|
||||
</option>`;
|
||||
})}
|
||||
</select>`;
|
||||
case PromptTypeEnum.RadioButtonGroup:
|
||||
return html`${(prompt.choices || []).map((choice) => {
|
||||
const id = `${prompt.fieldKey}-${choice}`;
|
||||
return html`<div class="pf-c-check">
|
||||
<input
|
||||
type="radio"
|
||||
class="pf-c-check__input"
|
||||
name="${prompt.fieldKey}"
|
||||
id="${id}"
|
||||
?checked="${prompt.initialValue === choice}"
|
||||
?required="${prompt.required}"
|
||||
value="${choice}"
|
||||
/>
|
||||
<label class="pf-c-check__label" for=${id}>${choice}</label>
|
||||
</div> `;
|
||||
})}`;
|
||||
case PromptTypeEnum.AkLocale: {
|
||||
const locales = this.can(CapabilitiesEnum.CanDebug)
|
||||
? LOCALES
|
||||
: LOCALES.filter((locale) => locale.code !== "debug");
|
||||
const options = locales.map(
|
||||
(locale) =>
|
||||
html`<option
|
||||
value=${locale.code}
|
||||
?selected=${locale.code === prompt.initialValue}
|
||||
>
|
||||
${locale.code.toUpperCase()} - ${locale.label()}
|
||||
</option> `,
|
||||
);
|
||||
/* TODO: Legacy: None of these refer to the `this` field. Static fields are a code smell. */
|
||||
|
||||
return html`<select class="pf-c-form-control" name="${prompt.fieldKey}">
|
||||
<option value="" ?selected=${prompt.initialValue === ""}>
|
||||
${msg("Auto-detect (based on your browser)")}
|
||||
</option>
|
||||
${options}
|
||||
</select>`;
|
||||
}
|
||||
default:
|
||||
return html`<p>invalid type '${prompt.type}'</p>`;
|
||||
}
|
||||
renderPromptInner(prompt: StagePrompt) {
|
||||
return renderPromptInner(prompt);
|
||||
}
|
||||
|
||||
renderPromptHelpText(prompt: StagePrompt): TemplateResult {
|
||||
if (prompt.subText === "") {
|
||||
return html``;
|
||||
}
|
||||
return html`<p class="pf-c-form__helper-text">${unsafeHTML(prompt.subText)}</p>`;
|
||||
renderPromptHelpText(prompt: StagePrompt) {
|
||||
return renderPromptHelpText(prompt);
|
||||
}
|
||||
|
||||
shouldRenderInWrapper(prompt: StagePrompt): boolean {
|
||||
// Special types that aren't rendered in a wrapper
|
||||
if (
|
||||
prompt.type === PromptTypeEnum.Static ||
|
||||
prompt.type === PromptTypeEnum.Hidden ||
|
||||
prompt.type === PromptTypeEnum.Separator
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
shouldRenderInWrapper(prompt: StagePrompt) {
|
||||
return shouldRenderInWrapper(prompt);
|
||||
}
|
||||
|
||||
renderField(prompt: StagePrompt): TemplateResult {
|
||||
// Checkbox is rendered differently
|
||||
// Checkbox has a slightly different layout, so it must be intercepted early.
|
||||
if (prompt.type === PromptTypeEnum.Checkbox) {
|
||||
return html`<div class="pf-c-check">
|
||||
<input
|
||||
type="checkbox"
|
||||
class="pf-c-check__input"
|
||||
id="${prompt.fieldKey}"
|
||||
name="${prompt.fieldKey}"
|
||||
?checked=${prompt.initialValue !== ""}
|
||||
?required=${prompt.required}
|
||||
/>
|
||||
<label class="pf-c-check__label" for="${prompt.fieldKey}">${prompt.label}</label>
|
||||
${prompt.required
|
||||
? html`<p class="pf-c-form__helper-text">${msg("Required.")}</p>`
|
||||
: html``}
|
||||
<p class="pf-c-form__helper-text">${unsafeHTML(prompt.subText)}</p>
|
||||
</div>`;
|
||||
return renderCheckbox(prompt);
|
||||
}
|
||||
if (this.shouldRenderInWrapper(prompt)) {
|
||||
|
||||
if (shouldRenderInWrapper(prompt)) {
|
||||
return html`<ak-form-element
|
||||
label="${prompt.label}"
|
||||
?required="${prompt.required}"
|
||||
class="pf-c-form__group"
|
||||
.errors=${(this.challenge?.responseErrors || {})[prompt.fieldKey]}
|
||||
>
|
||||
${this.renderPromptInner(prompt)} ${this.renderPromptHelpText(prompt)}
|
||||
${renderPromptInner(prompt)} ${renderPromptHelpText(prompt)}
|
||||
</ak-form-element>`;
|
||||
}
|
||||
return html` ${this.renderPromptInner(prompt)} ${this.renderPromptHelpText(prompt)}`;
|
||||
}
|
||||
|
||||
renderContinue(): TemplateResult {
|
||||
return html` <div class="pf-c-form__group pf-m-action">
|
||||
<button type="submit" class="pf-c-button pf-m-primary pf-m-block">
|
||||
${msg("Continue")}
|
||||
</button>
|
||||
</div>`;
|
||||
return html` ${renderPromptInner(prompt)} ${renderPromptHelpText(prompt)}`;
|
||||
}
|
||||
|
||||
render(): TemplateResult {
|
||||
@ -286,6 +92,7 @@ ${prompt.initialValue}</textarea
|
||||
return html`<ak-empty-state ?loading="${true}" header=${msg("Loading")}>
|
||||
</ak-empty-state>`;
|
||||
}
|
||||
|
||||
return html`<header class="pf-c-login__main-header">
|
||||
<h1 class="pf-c-title pf-m-3xl">${this.challenge.flowInfo?.title}</h1>
|
||||
</header>
|
||||
@ -304,7 +111,7 @@ ${prompt.initialValue}</textarea
|
||||
this.challenge?.responseErrors?.non_field_errors || [],
|
||||
)
|
||||
: html``}
|
||||
${this.renderContinue()}
|
||||
${renderContinue()}
|
||||
</form>
|
||||
</div>
|
||||
<footer class="pf-c-login__main-footer">
|
||||
|
37
web/src/flow/stages/prompt/helpers.ts
Normal file
37
web/src/flow/stages/prompt/helpers.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import { msg } from "@lit/localize";
|
||||
import { html } from "lit";
|
||||
import { unsafeHTML } from "lit/directives/unsafe-html.js";
|
||||
|
||||
import { PromptTypeEnum, StagePrompt } from "@goauthentik/api";
|
||||
|
||||
import promptRenderers from "./FieldRenderers";
|
||||
|
||||
export function renderPromptInner(prompt: StagePrompt) {
|
||||
const renderer = promptRenderers.get(prompt.type);
|
||||
if (!renderer) {
|
||||
return html`<p>invalid type '${JSON.stringify(prompt.type, null, 2)}'</p>`;
|
||||
}
|
||||
return renderer(prompt);
|
||||
}
|
||||
|
||||
export function renderPromptHelpText(prompt: StagePrompt) {
|
||||
if (prompt.subText === "") {
|
||||
return html``;
|
||||
}
|
||||
return html`<p class="pf-c-form__helper-text">${unsafeHTML(prompt.subText)}</p>`;
|
||||
}
|
||||
|
||||
export function shouldRenderInWrapper(prompt: StagePrompt) {
|
||||
// Special types that aren't rendered in a wrapper
|
||||
const specialTypes = [PromptTypeEnum.Static, PromptTypeEnum.Hidden, PromptTypeEnum.Separator];
|
||||
const special = specialTypes.find((s) => s === prompt.type);
|
||||
return !special;
|
||||
}
|
||||
|
||||
export function renderContinue() {
|
||||
return html` <div class="pf-c-form__group pf-m-action">
|
||||
<button type="submit" class="pf-c-button pf-m-primary pf-m-block">
|
||||
${msg("Continue")}
|
||||
</button>
|
||||
</div>`;
|
||||
}
|
@ -6641,6 +6641,42 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s001fd928369d4ddc">
|
||||
<source><x id="0" equiv-text="${versionString}"/> (FIPS)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sce17c2bdea3e6ace">
|
||||
<source>Score minimum threshold</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sf2fcb974c62625fc">
|
||||
<source>Minimum required score to allow continuing</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s7452199a73ce8b78">
|
||||
<source>Score maximum threshold</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s2d3a6cd50b46b44d">
|
||||
<source>Maximum allowed score to allow continuing</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s9d6e40d9a9a58fbf">
|
||||
<source>Error on invalid score</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s2af59e2f9f12847a">
|
||||
<source>When enabled and the resultant score is outside the threshold, the user will not be able to continue. When disabled, the user will be able to continue and the score can be used in policies to customize further stages.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s10092327ad833090">
|
||||
<source>Microsoft Entra Group(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s811c45ad24a5feae">
|
||||
<source>Microsoft Entra User(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s7d2d3d298fdccfc8">
|
||||
<source>Google Workspace Group(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s8c9cf2c004755526">
|
||||
<source>Google Workspace User(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sd000b42fea07c34a">
|
||||
<source>SCIM Group(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s146769fb55f1ee50">
|
||||
<source>SCIM User(s)</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
@ -6907,6 +6907,42 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s001fd928369d4ddc">
|
||||
<source><x id="0" equiv-text="${versionString}"/> (FIPS)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sce17c2bdea3e6ace">
|
||||
<source>Score minimum threshold</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sf2fcb974c62625fc">
|
||||
<source>Minimum required score to allow continuing</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s7452199a73ce8b78">
|
||||
<source>Score maximum threshold</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s2d3a6cd50b46b44d">
|
||||
<source>Maximum allowed score to allow continuing</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s9d6e40d9a9a58fbf">
|
||||
<source>Error on invalid score</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s2af59e2f9f12847a">
|
||||
<source>When enabled and the resultant score is outside the threshold, the user will not be able to continue. When disabled, the user will be able to continue and the score can be used in policies to customize further stages.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s10092327ad833090">
|
||||
<source>Microsoft Entra Group(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s811c45ad24a5feae">
|
||||
<source>Microsoft Entra User(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s7d2d3d298fdccfc8">
|
||||
<source>Google Workspace Group(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s8c9cf2c004755526">
|
||||
<source>Google Workspace User(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sd000b42fea07c34a">
|
||||
<source>SCIM Group(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s146769fb55f1ee50">
|
||||
<source>SCIM User(s)</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
@ -6558,6 +6558,42 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s001fd928369d4ddc">
|
||||
<source><x id="0" equiv-text="${versionString}"/> (FIPS)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sce17c2bdea3e6ace">
|
||||
<source>Score minimum threshold</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sf2fcb974c62625fc">
|
||||
<source>Minimum required score to allow continuing</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s7452199a73ce8b78">
|
||||
<source>Score maximum threshold</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s2d3a6cd50b46b44d">
|
||||
<source>Maximum allowed score to allow continuing</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s9d6e40d9a9a58fbf">
|
||||
<source>Error on invalid score</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s2af59e2f9f12847a">
|
||||
<source>When enabled and the resultant score is outside the threshold, the user will not be able to continue. When disabled, the user will be able to continue and the score can be used in policies to customize further stages.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s10092327ad833090">
|
||||
<source>Microsoft Entra Group(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s811c45ad24a5feae">
|
||||
<source>Microsoft Entra User(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s7d2d3d298fdccfc8">
|
||||
<source>Google Workspace Group(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s8c9cf2c004755526">
|
||||
<source>Google Workspace User(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sd000b42fea07c34a">
|
||||
<source>SCIM Group(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s146769fb55f1ee50">
|
||||
<source>SCIM User(s)</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
@ -8604,108 +8604,191 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti
|
||||
</trans-unit>
|
||||
<trans-unit id="s8cfd29891b2c93f0">
|
||||
<source>Google Workspace Provider</source>
|
||||
<target>Fournisseur Google Workspace</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sa817aa9f6f88a991">
|
||||
<source>Credentials</source>
|
||||
<target>Identifiants</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sc668815044e218c2">
|
||||
<source>Delegated Subject</source>
|
||||
<target>Sujet délégué</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="se89a9ecf275e4343">
|
||||
<source>Default group email domain</source>
|
||||
<target>Domaine de courriel de groupe par défaut</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s64a0a6da6ed6d680">
|
||||
<source>Default domain that is used to generate a group's email address. Can be customized using property mappings.</source>
|
||||
<target>Domain par défaut utilisé pour générer le courriel d'un groupe. Peut être personnalisé avec des mappages de propriété.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sd061e65955e036ca">
|
||||
<source>User deletion action</source>
|
||||
<target>Action de suppression d'un utilisateur</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s87f86f65b5e19ea7">
|
||||
<source>User is deleted</source>
|
||||
<target>L'utilisateur est supprimé</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s3906cd4a102867a3">
|
||||
<source>Suspend</source>
|
||||
<target>Suspendre</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s0bf5b364e2c79392">
|
||||
<source>User is suspended, and connection to user in authentik is removed.</source>
|
||||
<target>L'utilisateur est suspendu, et la connection à authentik est supprimée.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s4acb0250d735c2a9">
|
||||
<source>Do Nothing</source>
|
||||
<target>Ne rien faire</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s5fe525d19499ed47">
|
||||
<source>The connection is removed but the user is not modified</source>
|
||||
<target>La connexion est supprimée mais l'utilisateur n'est pas modifié</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s676a0127c35d240a">
|
||||
<source>Determines what authentik will do when a User is deleted.</source>
|
||||
<target>Détermine ce qu'authentik fera si un utilisateur est supprimé.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sd1aa04cc32caf2b0">
|
||||
<source>Group deletion action</source>
|
||||
<target>Action de suppression d'un groupe</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s874c788479481131">
|
||||
<source>Group is deleted</source>
|
||||
<target>Le groupe est supprimé</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s0983fa9b84e4a9f7">
|
||||
<source>The connection is removed but the group is not modified</source>
|
||||
<target>La connexion est supprimée mais le groupe n'est pas modifié</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sdb872a9f425937fa">
|
||||
<source>Determines what authentik will do when a Group is deleted.</source>
|
||||
<target>Détermine ce qu'authentik fera si un groupe est supprimé.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sa5f28f1ad0bee45b">
|
||||
<source>Google Workspace Provider is in preview.</source>
|
||||
<target>Le fournisseur Google Workspace est en aperçu technique.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s958928ab6208d748">
|
||||
<source>Microsoft Entra Provider</source>
|
||||
<target>Fournisseur Microsoft Entra</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sc7d6bc4aebb58fe9">
|
||||
<source>Google Cloud credentials file.</source>
|
||||
<target>Fichier d'identifiants Google Cloud.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s2e707072d5a9615d">
|
||||
<source>Email address of the user the actions of authentik will be delegated to.</source>
|
||||
<target>Courriel de l'utilisateur auquel les actions d'authentik seront déléguées.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s03a759e65ceb722d">
|
||||
<source>Client ID for the app registration.</source>
|
||||
<target>Client ID pour l'enregistrement de l'application.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s479980cf9252628c">
|
||||
<source>Client secret for the app registration.</source>
|
||||
<target>Client secret pour l'enregistrement de l'application.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s25c2392ffcb78df2">
|
||||
<source>Tenant ID</source>
|
||||
<target>Tenant ID</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s89e4e698cdb1187f">
|
||||
<source>ID of the tenant accounts will be synced into.</source>
|
||||
<target>ID du tenant dans lequel les comptes seront synchronisés.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sf341f5dfc7a11633">
|
||||
<source>Microsoft Entra Provider is in preview.</source>
|
||||
<target>Le fournisseur Microsoft Entra est en aperçu technique.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s79dd6df244c05ae9">
|
||||
<source>Update Microsoft Entra Provider</source>
|
||||
<target>Mettre à jour le fournisseur Microsoft Entra</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="saf4b498d81141878">
|
||||
<source>Finished successfully</source>
|
||||
<target>Fini avec succès</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s46f1d86ffec6223c">
|
||||
<source>Finished with errors</source>
|
||||
<target>Fini avec erreurs</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sbd12ed8a1053a108">
|
||||
<source>Finished <x id="0" equiv-text="${getRelativeTime(task.finishTimestamp)}"/> (<x id="1" equiv-text="${task.finishTimestamp.toLocaleString()}"/>)</source>
|
||||
<target>Fini <x id="0" equiv-text="${getRelativeTime(task.finishTimestamp)}"/> (<x id="1" equiv-text="${task.finishTimestamp.toLocaleString()}"/>)</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sc3c334d642866997">
|
||||
<source>Sync currently running</source>
|
||||
<target>Synchronisation en cours</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sd520a4089006ca93">
|
||||
<source>Update Google Workspace Provider</source>
|
||||
<target>Mettre à jour le fournisseur Google Workspace</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sfdfa5bb4ddd99d70">
|
||||
<source>Enterprise only</source>
|
||||
<target>Entreprise uniquement</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="scffa59cfac1951f2">
|
||||
<source><x id="0" equiv-text="${type.name}"/> Icon</source>
|
||||
<target>Icône <x id="0" equiv-text="${type.name}"/></target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s1da3499258024860">
|
||||
<source><x id="0" equiv-text="${versionString}"/> (build <x id="1" equiv-text="${this.outpostHealth.buildHash.substring(0, 8)}"/>)</source>
|
||||
<target><x id="0" equiv-text="${versionString}"/> (build <x id="1" equiv-text="${this.outpostHealth.buildHash.substring(0, 8)}"/>)</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s001fd928369d4ddc">
|
||||
<source><x id="0" equiv-text="${versionString}"/> (FIPS)</source>
|
||||
<target><x id="0" equiv-text="${versionString}"/> (FIPS)</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sce17c2bdea3e6ace">
|
||||
<source>Score minimum threshold</source>
|
||||
<target>Seuil minimum du score</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sf2fcb974c62625fc">
|
||||
<source>Minimum required score to allow continuing</source>
|
||||
<target>Score minimum requis pour continuer</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s7452199a73ce8b78">
|
||||
<source>Score maximum threshold</source>
|
||||
<target>Seuil maximum du score</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s2d3a6cd50b46b44d">
|
||||
<source>Maximum allowed score to allow continuing</source>
|
||||
<target>Score maximum requis pour continuer</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s9d6e40d9a9a58fbf">
|
||||
<source>Error on invalid score</source>
|
||||
<target>Erreur sur score invalide</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s2af59e2f9f12847a">
|
||||
<source>When enabled and the resultant score is outside the threshold, the user will not be able to continue. When disabled, the user will be able to continue and the score can be used in policies to customize further stages.</source>
|
||||
<target>Si activé et que le score résultant est hors des seuils, l'utilisateur ne pourra pas continuer. Si désactivé, l'utilisateur pourra continuer et le score pourra être utilisé dans des politiques pour configurer les étapes suivantes.</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s10092327ad833090">
|
||||
<source>Microsoft Entra Group(s)</source>
|
||||
<target>Groupe(s) du fournisseur Microsoft Entra</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s811c45ad24a5feae">
|
||||
<source>Microsoft Entra User(s)</source>
|
||||
<target>Utilisateur(s) du fournisseur Microsoft Entra</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s7d2d3d298fdccfc8">
|
||||
<source>Google Workspace Group(s)</source>
|
||||
<target>Groupe(s) du fournisseur Google Workspace</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s8c9cf2c004755526">
|
||||
<source>Google Workspace User(s)</source>
|
||||
<target>Utilisateur(s) du fournisseur Google Workspace</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sd000b42fea07c34a">
|
||||
<source>SCIM Group(s)</source>
|
||||
<target>Groupe(s) du fournisseur SCIM</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s146769fb55f1ee50">
|
||||
<source>SCIM User(s)</source>
|
||||
<target>Utilisateur(s) du fournisseur SCIM</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
@ -8487,6 +8487,42 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s001fd928369d4ddc">
|
||||
<source><x id="0" equiv-text="${versionString}"/> (FIPS)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sce17c2bdea3e6ace">
|
||||
<source>Score minimum threshold</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sf2fcb974c62625fc">
|
||||
<source>Minimum required score to allow continuing</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s7452199a73ce8b78">
|
||||
<source>Score maximum threshold</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s2d3a6cd50b46b44d">
|
||||
<source>Maximum allowed score to allow continuing</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s9d6e40d9a9a58fbf">
|
||||
<source>Error on invalid score</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s2af59e2f9f12847a">
|
||||
<source>When enabled and the resultant score is outside the threshold, the user will not be able to continue. When disabled, the user will be able to continue and the score can be used in policies to customize further stages.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s10092327ad833090">
|
||||
<source>Microsoft Entra Group(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s811c45ad24a5feae">
|
||||
<source>Microsoft Entra User(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s7d2d3d298fdccfc8">
|
||||
<source>Google Workspace Group(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s8c9cf2c004755526">
|
||||
<source>Google Workspace User(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sd000b42fea07c34a">
|
||||
<source>SCIM Group(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s146769fb55f1ee50">
|
||||
<source>SCIM User(s)</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
@ -8331,6 +8331,42 @@ Bindingen naar groepen/gebruikers worden gecontroleerd tegen de gebruiker van de
|
||||
</trans-unit>
|
||||
<trans-unit id="s001fd928369d4ddc">
|
||||
<source><x id="0" equiv-text="${versionString}"/> (FIPS)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sce17c2bdea3e6ace">
|
||||
<source>Score minimum threshold</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sf2fcb974c62625fc">
|
||||
<source>Minimum required score to allow continuing</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s7452199a73ce8b78">
|
||||
<source>Score maximum threshold</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s2d3a6cd50b46b44d">
|
||||
<source>Maximum allowed score to allow continuing</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s9d6e40d9a9a58fbf">
|
||||
<source>Error on invalid score</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s2af59e2f9f12847a">
|
||||
<source>When enabled and the resultant score is outside the threshold, the user will not be able to continue. When disabled, the user will be able to continue and the score can be used in policies to customize further stages.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s10092327ad833090">
|
||||
<source>Microsoft Entra Group(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s811c45ad24a5feae">
|
||||
<source>Microsoft Entra User(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s7d2d3d298fdccfc8">
|
||||
<source>Google Workspace Group(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s8c9cf2c004755526">
|
||||
<source>Google Workspace User(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sd000b42fea07c34a">
|
||||
<source>SCIM Group(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s146769fb55f1ee50">
|
||||
<source>SCIM User(s)</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
2110
web/xliff/pl.xlf
2110
web/xliff/pl.xlf
File diff suppressed because it is too large
Load Diff
@ -8602,4 +8602,40 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
<trans-unit id="s001fd928369d4ddc">
|
||||
<source><x id="0" equiv-text="${versionString}"/> (FIPS)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sce17c2bdea3e6ace">
|
||||
<source>Score minimum threshold</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sf2fcb974c62625fc">
|
||||
<source>Minimum required score to allow continuing</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s7452199a73ce8b78">
|
||||
<source>Score maximum threshold</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s2d3a6cd50b46b44d">
|
||||
<source>Maximum allowed score to allow continuing</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s9d6e40d9a9a58fbf">
|
||||
<source>Error on invalid score</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s2af59e2f9f12847a">
|
||||
<source>When enabled and the resultant score is outside the threshold, the user will not be able to continue. When disabled, the user will be able to continue and the score can be used in policies to customize further stages.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s10092327ad833090">
|
||||
<source>Microsoft Entra Group(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s811c45ad24a5feae">
|
||||
<source>Microsoft Entra User(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s7d2d3d298fdccfc8">
|
||||
<source>Google Workspace Group(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s8c9cf2c004755526">
|
||||
<source>Google Workspace User(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sd000b42fea07c34a">
|
||||
<source>SCIM Group(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s146769fb55f1ee50">
|
||||
<source>SCIM User(s)</source>
|
||||
</trans-unit>
|
||||
</body></file></xliff>
|
||||
|
@ -6551,6 +6551,42 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s001fd928369d4ddc">
|
||||
<source><x id="0" equiv-text="${versionString}"/> (FIPS)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sce17c2bdea3e6ace">
|
||||
<source>Score minimum threshold</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sf2fcb974c62625fc">
|
||||
<source>Minimum required score to allow continuing</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s7452199a73ce8b78">
|
||||
<source>Score maximum threshold</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s2d3a6cd50b46b44d">
|
||||
<source>Maximum allowed score to allow continuing</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s9d6e40d9a9a58fbf">
|
||||
<source>Error on invalid score</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s2af59e2f9f12847a">
|
||||
<source>When enabled and the resultant score is outside the threshold, the user will not be able to continue. When disabled, the user will be able to continue and the score can be used in policies to customize further stages.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s10092327ad833090">
|
||||
<source>Microsoft Entra Group(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s811c45ad24a5feae">
|
||||
<source>Microsoft Entra User(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s7d2d3d298fdccfc8">
|
||||
<source>Google Workspace Group(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s8c9cf2c004755526">
|
||||
<source>Google Workspace User(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sd000b42fea07c34a">
|
||||
<source>SCIM Group(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s146769fb55f1ee50">
|
||||
<source>SCIM User(s)</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
@ -5473,6 +5473,42 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
<trans-unit id="s001fd928369d4ddc">
|
||||
<source><x id="0" equiv-text="${versionString}"/> (FIPS)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sce17c2bdea3e6ace">
|
||||
<source>Score minimum threshold</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sf2fcb974c62625fc">
|
||||
<source>Minimum required score to allow continuing</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s7452199a73ce8b78">
|
||||
<source>Score maximum threshold</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s2d3a6cd50b46b44d">
|
||||
<source>Maximum allowed score to allow continuing</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s9d6e40d9a9a58fbf">
|
||||
<source>Error on invalid score</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s2af59e2f9f12847a">
|
||||
<source>When enabled and the resultant score is outside the threshold, the user will not be able to continue. When disabled, the user will be able to continue and the score can be used in policies to customize further stages.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s10092327ad833090">
|
||||
<source>Microsoft Entra Group(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s811c45ad24a5feae">
|
||||
<source>Microsoft Entra User(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s7d2d3d298fdccfc8">
|
||||
<source>Google Workspace Group(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s8c9cf2c004755526">
|
||||
<source>Google Workspace User(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sd000b42fea07c34a">
|
||||
<source>SCIM Group(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s146769fb55f1ee50">
|
||||
<source>SCIM User(s)</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
</xliff>
|
||||
|
@ -8743,6 +8743,54 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
<trans-unit id="s001fd928369d4ddc">
|
||||
<source><x id="0" equiv-text="${versionString}"/> (FIPS)</source>
|
||||
<target><x id="0" equiv-text="${versionString}"/>(FIPS)</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sce17c2bdea3e6ace">
|
||||
<source>Score minimum threshold</source>
|
||||
<target>分数最小阈值</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sf2fcb974c62625fc">
|
||||
<source>Minimum required score to allow continuing</source>
|
||||
<target>允许继续所需的最小分数</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s7452199a73ce8b78">
|
||||
<source>Score maximum threshold</source>
|
||||
<target>分数最大阈值</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s2d3a6cd50b46b44d">
|
||||
<source>Maximum allowed score to allow continuing</source>
|
||||
<target>允许继续所需的最大分数</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s9d6e40d9a9a58fbf">
|
||||
<source>Error on invalid score</source>
|
||||
<target>分数无效时报错</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s2af59e2f9f12847a">
|
||||
<source>When enabled and the resultant score is outside the threshold, the user will not be able to continue. When disabled, the user will be able to continue and the score can be used in policies to customize further stages.</source>
|
||||
<target>启用时,如果结果分数超出阈值,用户将无法继续。禁用时,用户可以继续,分数可用于自定义下一阶段的策略。</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s10092327ad833090">
|
||||
<source>Microsoft Entra Group(s)</source>
|
||||
<target>Microsoft Entra 组</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s811c45ad24a5feae">
|
||||
<source>Microsoft Entra User(s)</source>
|
||||
<target>Microsoft Entra 用户</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s7d2d3d298fdccfc8">
|
||||
<source>Google Workspace Group(s)</source>
|
||||
<target>Google Workspace 组</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s8c9cf2c004755526">
|
||||
<source>Google Workspace User(s)</source>
|
||||
<target>Google Workspace 用户</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sd000b42fea07c34a">
|
||||
<source>SCIM Group(s)</source>
|
||||
<target>SCIM 组</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s146769fb55f1ee50">
|
||||
<source>SCIM User(s)</source>
|
||||
<target>SCIM 用户</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
@ -6599,6 +6599,42 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s001fd928369d4ddc">
|
||||
<source><x id="0" equiv-text="${versionString}"/> (FIPS)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sce17c2bdea3e6ace">
|
||||
<source>Score minimum threshold</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sf2fcb974c62625fc">
|
||||
<source>Minimum required score to allow continuing</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s7452199a73ce8b78">
|
||||
<source>Score maximum threshold</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s2d3a6cd50b46b44d">
|
||||
<source>Maximum allowed score to allow continuing</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s9d6e40d9a9a58fbf">
|
||||
<source>Error on invalid score</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s2af59e2f9f12847a">
|
||||
<source>When enabled and the resultant score is outside the threshold, the user will not be able to continue. When disabled, the user will be able to continue and the score can be used in policies to customize further stages.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s10092327ad833090">
|
||||
<source>Microsoft Entra Group(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s811c45ad24a5feae">
|
||||
<source>Microsoft Entra User(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s7d2d3d298fdccfc8">
|
||||
<source>Google Workspace Group(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s8c9cf2c004755526">
|
||||
<source>Google Workspace User(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sd000b42fea07c34a">
|
||||
<source>SCIM Group(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s146769fb55f1ee50">
|
||||
<source>SCIM User(s)</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
@ -8743,6 +8743,54 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
<trans-unit id="s001fd928369d4ddc">
|
||||
<source><x id="0" equiv-text="${versionString}"/> (FIPS)</source>
|
||||
<target><x id="0" equiv-text="${versionString}"/>(FIPS)</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sce17c2bdea3e6ace">
|
||||
<source>Score minimum threshold</source>
|
||||
<target>分数最小阈值</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sf2fcb974c62625fc">
|
||||
<source>Minimum required score to allow continuing</source>
|
||||
<target>允许继续所需的最小分数</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s7452199a73ce8b78">
|
||||
<source>Score maximum threshold</source>
|
||||
<target>分数最大阈值</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s2d3a6cd50b46b44d">
|
||||
<source>Maximum allowed score to allow continuing</source>
|
||||
<target>允许继续所需的最大分数</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s9d6e40d9a9a58fbf">
|
||||
<source>Error on invalid score</source>
|
||||
<target>分数无效时报错</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s2af59e2f9f12847a">
|
||||
<source>When enabled and the resultant score is outside the threshold, the user will not be able to continue. When disabled, the user will be able to continue and the score can be used in policies to customize further stages.</source>
|
||||
<target>启用时,如果结果分数超出阈值,用户将无法继续。禁用时,用户可以继续,分数可用于自定义下一阶段的策略。</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s10092327ad833090">
|
||||
<source>Microsoft Entra Group(s)</source>
|
||||
<target>Microsoft Entra 组</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s811c45ad24a5feae">
|
||||
<source>Microsoft Entra User(s)</source>
|
||||
<target>Microsoft Entra 用户</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s7d2d3d298fdccfc8">
|
||||
<source>Google Workspace Group(s)</source>
|
||||
<target>Google Workspace 组</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s8c9cf2c004755526">
|
||||
<source>Google Workspace User(s)</source>
|
||||
<target>Google Workspace 用户</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="sd000b42fea07c34a">
|
||||
<source>SCIM Group(s)</source>
|
||||
<target>SCIM 组</target>
|
||||
</trans-unit>
|
||||
<trans-unit id="s146769fb55f1ee50">
|
||||
<source>SCIM User(s)</source>
|
||||
<target>SCIM 用户</target>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
@ -8448,6 +8448,42 @@ Bindings to groups/users are checked against the user of the event.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s001fd928369d4ddc">
|
||||
<source><x id="0" equiv-text="${versionString}"/> (FIPS)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sce17c2bdea3e6ace">
|
||||
<source>Score minimum threshold</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sf2fcb974c62625fc">
|
||||
<source>Minimum required score to allow continuing</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s7452199a73ce8b78">
|
||||
<source>Score maximum threshold</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s2d3a6cd50b46b44d">
|
||||
<source>Maximum allowed score to allow continuing</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s9d6e40d9a9a58fbf">
|
||||
<source>Error on invalid score</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s2af59e2f9f12847a">
|
||||
<source>When enabled and the resultant score is outside the threshold, the user will not be able to continue. When disabled, the user will be able to continue and the score can be used in policies to customize further stages.</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s10092327ad833090">
|
||||
<source>Microsoft Entra Group(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s811c45ad24a5feae">
|
||||
<source>Microsoft Entra User(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s7d2d3d298fdccfc8">
|
||||
<source>Google Workspace Group(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s8c9cf2c004755526">
|
||||
<source>Google Workspace User(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="sd000b42fea07c34a">
|
||||
<source>SCIM Group(s)</source>
|
||||
</trans-unit>
|
||||
<trans-unit id="s146769fb55f1ee50">
|
||||
<source>SCIM User(s)</source>
|
||||
</trans-unit>
|
||||
</body>
|
||||
</file>
|
||||
|
81
website/developer-docs/docs/style-guide.mdx
Normal file
81
website/developer-docs/docs/style-guide.mdx
Normal file
@ -0,0 +1,81 @@
|
||||
---
|
||||
title: Style Guide
|
||||
---
|
||||
|
||||
Here are a few guidelines to ensure that the documentation is easy to read and uses similar phrasing. Remember to use our [docs templates](./templates/index.md) when possible; they are already set up to follow may of the style guidelines below.
|
||||
|
||||
If you find any documentation that doesn't match these guidelines, feel free to either open an [Issue](https://github.com/goauthentik/authentik/issues) or a [PR](https://github.com/goauthentik/authentik/pulls) so they can be fixed.
|
||||
|
||||
To test how the documentation renders use the Netlify Deploy Preview, especially when using Docusaurus-specific features. Or [build it locally and test](./writing-documentation.md#set-up-your-local-build), using the `make website-watch` command.
|
||||
|
||||
:::info
|
||||
Make sure to add any new pages to the appropriate `sidebar` file. Otherwise, the new page will not appear in the table of contents to the left.
|
||||
:::
|
||||
|
||||
## General guidelines
|
||||
|
||||
- Try to order the documentation sections in the order that makes it easiest for the user to follow. That is, order the sections in the same order as the actual workflow used to accomplish the task. Use headings (sub-titles) to break up long documents, and make it easier to find a specific section.
|
||||
|
||||
- You can use standard [Docusaurus-specific features](https://docusaurus.io/docs/next/markdown-features), which include MDX elements such as tabs and admonitions.
|
||||
|
||||
## Terminology
|
||||
|
||||
### authentik names
|
||||
|
||||
- The product name authentik should always start with a lower-case "a" and end with a "k". Even if it is the first word in a sentence. :-)
|
||||
|
||||
- Our company name is Authentik Security, Inc. but in non-legal documentation you can shorten it to Authentik Security.
|
||||
|
||||
### Industry terms, technology, and other tools
|
||||
|
||||
- When referring to external tools, or an industry term or technology, always follow the exact capitalization that the product or company itself uses on their website, in their official documentation, or what the industry uses in consensus.
|
||||
|
||||
- Try to avoid using abbreviations if possible.
|
||||
|
||||
- Use acronyms where it makes sense (for commonly used terms like SAML or RBAC). If an acronym is less-known, spell it out in parentheses after the first use.
|
||||
|
||||
## Writing style
|
||||
|
||||
- authentik documentation strives for a friendly, but not overly so, tone. It's ok to be a little bit conversational, and to address the reader in second person: "Next, you need to configure the log in settings."
|
||||
|
||||
- Our documentation uses American English ("z" not "s").
|
||||
|
||||
- Phrasing should almost always be in present tense and active voice:
|
||||
|
||||
- DON'T: "The Applications page will be loaded."
|
||||
|
||||
- DO: "The Applications page displays."
|
||||
|
||||
- Phrasing should never blame the user, and should be subjective:
|
||||
|
||||
- DON'T: "Never modify the default file."
|
||||
|
||||
- DO: "We recommend that you do not modify the default file, because this can result in unexpected issues."
|
||||
|
||||
## Formatting
|
||||
|
||||
Formatting in documentation is important; it improves comprehension and readability, and allows the brain to more quickly determine what is a command or a configuration setting, what is a field name, or what is a variable.
|
||||
|
||||
- When referring to UI elements or components in the authentik UI, such as field names, labels, etc., use **bold** text.
|
||||
|
||||
- Use `code` format when referring to:
|
||||
|
||||
- commands
|
||||
- file paths
|
||||
- directory names
|
||||
- code snippets (single line or a block of code)
|
||||
|
||||
- For variables or placeholders use _italic_ font for the variable, and use place-holder names that makes it obvious that the user needs to replace it.
|
||||
|
||||
Example: <kbd>https://<em>company-domain</em>/source/oauth/callback/<em>source-slug</em></kbd>
|
||||
|
||||
When using variables in code snippets, make sure to specify if the value is something the user needs to define, is system-defined or generated.
|
||||
|
||||
- When referring to authentik functionality and features, such as flows, stages, sources, or policies, do not capitalize and do not use bold or italic text. When possible link to the corresponding documentation.
|
||||
|
||||
### Titles and headers
|
||||
|
||||
- Both titles and headers (H1, H2, H3) use sentence style capitalization, meaning that only the first word is capitalized. However, if the title or header includes a proper noun (name of a product, etc) then capitalize those words.
|
||||
Examples:
|
||||
- Configure your provider
|
||||
- Configure the Google Workspace provider
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user