diff --git a/Dockerfile b/Dockerfile index e715c0931..3b7beb6f0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -35,7 +35,7 @@ COPY ./gen-ts-api /work/web/node_modules/@goauthentik/api RUN npm run build # Stage 3: Build go proxy -FROM --platform=${BUILDPLATFORM} docker.io/golang:1.21.4-bookworm AS go-builder +FROM --platform=${BUILDPLATFORM} docker.io/golang:1.21.5-bookworm AS go-builder ARG TARGETOS ARG TARGETARCH diff --git a/authentik/events/api/events.py b/authentik/events/api/events.py index e3226c407..d2e89ae5b 100644 --- a/authentik/events/api/events.py +++ b/authentik/events/api/events.py @@ -5,7 +5,7 @@ from json import loads import django_filters from django.db.models.aggregates import Count from django.db.models.fields.json import KeyTextTransform, KeyTransform -from django.db.models.functions import ExtractDay +from django.db.models.functions import ExtractDay, ExtractHour from drf_spectacular.types import OpenApiTypes from drf_spectacular.utils import OpenApiParameter, extend_schema from guardian.shortcuts import get_objects_for_user @@ -149,7 +149,15 @@ class EventViewSet(ModelViewSet): return Response(EventTopPerUserSerializer(instance=events, many=True).data) @extend_schema( - methods=["GET"], + responses={200: CoordinateSerializer(many=True)}, + ) + @action(detail=False, methods=["GET"], pagination_class=None) + def volume(self, request: Request) -> Response: + """Get event volume for specified filters and timeframe""" + queryset = self.filter_queryset(self.get_queryset()) + return Response(queryset.get_events_per(timedelta(days=7), ExtractHour, 7 * 3)) + + @extend_schema( responses={200: CoordinateSerializer(many=True)}, filters=[], parameters=[ diff --git a/internal/outpost/ldap/search/memory/memory.go b/internal/outpost/ldap/search/memory/memory.go index 2b80bbbbb..198739122 100644 --- a/internal/outpost/ldap/search/memory/memory.go +++ b/internal/outpost/ldap/search/memory/memory.go @@ -147,7 +147,11 @@ func (ms *MemorySearcher) Search(req *search.Request) (ldap.ServerSearchResult, fg := api.NewGroup(g.Pk, g.NumPk, g.Name, g.ParentName, []api.GroupMember{u}, []api.Role{}) fg.SetUsers([]int32{flag.UserPk}) if g.Parent.IsSet() { - fg.SetParent(*g.Parent.Get()) + if p := g.Parent.Get(); p != nil { + fg.SetParent(*p) + } else { + fg.SetParentNil() + } } fg.SetAttributes(g.Attributes) fg.SetIsSuperuser(*g.IsSuperuser) diff --git a/ldap.Dockerfile b/ldap.Dockerfile index 6bb161a97..7b1b9fbb1 100644 --- a/ldap.Dockerfile +++ b/ldap.Dockerfile @@ -1,5 +1,5 @@ # Stage 1: Build -FROM --platform=${BUILDPLATFORM} docker.io/golang:1.21.4-bookworm AS builder +FROM --platform=${BUILDPLATFORM} docker.io/golang:1.21.5-bookworm AS builder ARG TARGETOS ARG TARGETARCH diff --git a/locale/en/LC_MESSAGES/django.po b/locale/en/LC_MESSAGES/django.po index 597f17cc9..07031190c 100644 --- a/locale/en/LC_MESSAGES/django.po +++ b/locale/en/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2023-10-02 12:46+0000\n" +"POT-Creation-Date: 2023-12-06 16:55+0000\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -18,7 +18,7 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -#: authentik/admin/api/tasks.py:125 +#: authentik/admin/api/tasks.py:127 #, python-format msgid "Successfully re-scheduled Task %(name)s!" msgstr "" @@ -31,16 +31,16 @@ msgstr "" msgid "Validation Error" msgstr "" -#: authentik/blueprints/api.py:44 +#: authentik/blueprints/api.py:43 msgid "Blueprint file does not exist" msgstr "" -#: authentik/blueprints/api.py:55 +#: authentik/blueprints/api.py:54 #, python-format msgid "Failed to validate blueprint: %(logs)s" msgstr "" -#: authentik/blueprints/api.py:60 +#: authentik/blueprints/api.py:59 msgid "Either path or content must be set." msgstr "" @@ -82,11 +82,11 @@ msgstr "" msgid "Create a SAML Provider by importing its Metadata." msgstr "" -#: authentik/core/api/users.py:158 +#: authentik/core/api/users.py:156 msgid "No leading or trailing slashes allowed." msgstr "" -#: authentik/core/api/users.py:161 +#: authentik/core/api/users.py:159 msgid "No empty segments in user path allowed." msgstr "" @@ -98,151 +98,180 @@ msgstr "" msgid "Users added to this group will be superusers." msgstr "" -#: authentik/core/models.py:142 +#: authentik/core/models.py:162 +msgid "Group" +msgstr "" + +#: authentik/core/models.py:163 +msgid "Groups" +msgstr "" + +#: authentik/core/models.py:178 msgid "User's display name." msgstr "" -#: authentik/core/models.py:268 authentik/providers/oauth2/models.py:295 +#: authentik/core/models.py:274 authentik/providers/oauth2/models.py:295 msgid "User" msgstr "" -#: authentik/core/models.py:269 +#: authentik/core/models.py:275 msgid "Users" msgstr "" -#: authentik/core/models.py:282 +#: authentik/core/models.py:277 +#: authentik/stages/email/templates/email/password_reset.html:28 +msgid "Reset Password" +msgstr "" + +#: authentik/core/models.py:278 +msgid "Can impersonate other users" +msgstr "" + +#: authentik/core/models.py:279 authentik/rbac/models.py:54 +msgid "Can assign permissions to users" +msgstr "" + +#: authentik/core/models.py:280 authentik/rbac/models.py:55 +msgid "Can unassign permissions from users" +msgstr "" + +#: authentik/core/models.py:294 msgid "" "Flow used for authentication when the associated application is accessed by " "an un-authenticated user." msgstr "" -#: authentik/core/models.py:292 +#: authentik/core/models.py:304 msgid "Flow used when authorizing this provider." msgstr "" -#: authentik/core/models.py:304 +#: authentik/core/models.py:316 msgid "" "Accessed from applications; optional backchannel providers for protocols " "like LDAP and SCIM." msgstr "" -#: authentik/core/models.py:359 +#: authentik/core/models.py:371 msgid "Application's display Name." msgstr "" -#: authentik/core/models.py:360 +#: authentik/core/models.py:372 msgid "Internal application name, used in URLs." msgstr "" -#: authentik/core/models.py:372 +#: authentik/core/models.py:384 msgid "Open launch URL in a new browser tab or window." msgstr "" -#: authentik/core/models.py:436 +#: authentik/core/models.py:448 msgid "Application" msgstr "" -#: authentik/core/models.py:437 +#: authentik/core/models.py:449 msgid "Applications" msgstr "" -#: authentik/core/models.py:443 +#: authentik/core/models.py:455 msgid "Use the source-specific identifier" msgstr "" -#: authentik/core/models.py:445 +#: authentik/core/models.py:457 msgid "" "Link to a user with identical email address. Can have security implications " "when a source doesn't validate email addresses." msgstr "" -#: authentik/core/models.py:449 +#: authentik/core/models.py:461 msgid "" "Use the user's email address, but deny enrollment when the email address " "already exists." msgstr "" -#: authentik/core/models.py:452 +#: authentik/core/models.py:464 msgid "" "Link to a user with identical username. Can have security implications when " "a username is used with another source." msgstr "" -#: authentik/core/models.py:456 +#: authentik/core/models.py:468 msgid "" "Use the user's username, but deny enrollment when the username already " "exists." msgstr "" -#: authentik/core/models.py:463 +#: authentik/core/models.py:475 msgid "Source's display Name." msgstr "" -#: authentik/core/models.py:464 +#: authentik/core/models.py:476 msgid "Internal source name, used in URLs." msgstr "" -#: authentik/core/models.py:483 +#: authentik/core/models.py:495 msgid "Flow to use when authenticating existing users." msgstr "" -#: authentik/core/models.py:492 +#: authentik/core/models.py:504 msgid "Flow to use when enrolling new users." msgstr "" -#: authentik/core/models.py:500 +#: authentik/core/models.py:512 msgid "" "How the source determines if an existing user should be authenticated or a " "new user enrolled." msgstr "" -#: authentik/core/models.py:672 +#: authentik/core/models.py:684 msgid "Token" msgstr "" -#: authentik/core/models.py:673 +#: authentik/core/models.py:685 msgid "Tokens" msgstr "" -#: authentik/core/models.py:714 +#: authentik/core/models.py:690 +msgid "View token's key" +msgstr "" + +#: authentik/core/models.py:726 msgid "Property Mapping" msgstr "" -#: authentik/core/models.py:715 +#: authentik/core/models.py:727 msgid "Property Mappings" msgstr "" -#: authentik/core/models.py:750 +#: authentik/core/models.py:762 msgid "Authenticated Session" msgstr "" -#: authentik/core/models.py:751 +#: authentik/core/models.py:763 msgid "Authenticated Sessions" msgstr "" -#: authentik/core/sources/flow_manager.py:189 +#: authentik/core/sources/flow_manager.py:190 #, python-format msgid "" "Request to authenticate with %(source)s has been denied. Please authenticate " "with the source you've previously signed up with." msgstr "" -#: authentik/core/sources/flow_manager.py:241 +#: authentik/core/sources/flow_manager.py:242 msgid "Configured flow does not exist." msgstr "" -#: authentik/core/sources/flow_manager.py:271 -#: authentik/core/sources/flow_manager.py:323 +#: authentik/core/sources/flow_manager.py:272 +#: authentik/core/sources/flow_manager.py:324 #, python-format msgid "Successfully authenticated with %(source)s!" msgstr "" -#: authentik/core/sources/flow_manager.py:295 +#: authentik/core/sources/flow_manager.py:296 #, python-format msgid "Successfully linked %(source)s!" msgstr "" -#: authentik/core/sources/flow_manager.py:314 +#: authentik/core/sources/flow_manager.py:315 msgid "Source is not configured for enrollment." msgstr "" @@ -262,8 +291,8 @@ msgstr "" msgid "" "\n" " You've logged out of %(application)s. You can go back to the " -"overview to launch another application, or log out of your authentik " -"account.\n" +"overview to launch another application, or log out of your " +"%(branding_title)s account.\n" " " msgstr "" @@ -325,113 +354,121 @@ msgstr "" msgid "Certificate-Key Pairs" msgstr "" -#: authentik/enterprise/models.py:193 +#: authentik/enterprise/models.py:183 +msgid "License" +msgstr "" + +#: authentik/enterprise/models.py:184 +msgid "Licenses" +msgstr "" + +#: authentik/enterprise/models.py:206 msgid "License Usage" msgstr "" -#: authentik/enterprise/models.py:194 +#: authentik/enterprise/models.py:207 msgid "License Usage Records" msgstr "" -#: authentik/events/models.py:290 +#: authentik/events/models.py:291 msgid "Event" msgstr "" -#: authentik/events/models.py:291 +#: authentik/events/models.py:292 msgid "Events" msgstr "" -#: authentik/events/models.py:297 +#: authentik/events/models.py:298 msgid "authentik inbuilt notifications" msgstr "" -#: authentik/events/models.py:298 +#: authentik/events/models.py:299 msgid "Generic Webhook" msgstr "" -#: authentik/events/models.py:299 +#: authentik/events/models.py:300 msgid "Slack Webhook (Slack/Discord)" msgstr "" -#: authentik/events/models.py:300 +#: authentik/events/models.py:301 msgid "Email" msgstr "" -#: authentik/events/models.py:318 +#: authentik/events/models.py:319 msgid "" "Only send notification once, for example when sending a webhook into a chat " "channel." msgstr "" -#: authentik/events/models.py:383 +#: authentik/events/models.py:384 msgid "Severity" msgstr "" -#: authentik/events/models.py:388 +#: authentik/events/models.py:389 msgid "Dispatched for user" msgstr "" -#: authentik/events/models.py:397 +#: authentik/events/models.py:398 msgid "Event user" msgstr "" -#: authentik/events/models.py:491 +#: authentik/events/models.py:492 msgid "Notification Transport" msgstr "" -#: authentik/events/models.py:492 +#: authentik/events/models.py:493 msgid "Notification Transports" msgstr "" -#: authentik/events/models.py:498 +#: authentik/events/models.py:499 msgid "Notice" msgstr "" -#: authentik/events/models.py:499 +#: authentik/events/models.py:500 msgid "Warning" msgstr "" -#: authentik/events/models.py:500 +#: authentik/events/models.py:501 msgid "Alert" msgstr "" -#: authentik/events/models.py:525 +#: authentik/events/models.py:526 msgid "Notification" msgstr "" -#: authentik/events/models.py:526 +#: authentik/events/models.py:527 msgid "Notifications" msgstr "" -#: authentik/events/models.py:536 +#: authentik/events/models.py:537 msgid "" "Select which transports should be used to notify the user. If none are " "selected, the notification will only be shown in the authentik UI." msgstr "" -#: authentik/events/models.py:544 +#: authentik/events/models.py:545 msgid "Controls which severity level the created notifications will have." msgstr "" -#: authentik/events/models.py:549 +#: authentik/events/models.py:550 msgid "" "Define which group of users this notification should be sent and shown to. " "If left empty, Notification won't ben sent." msgstr "" -#: authentik/events/models.py:567 +#: authentik/events/models.py:568 msgid "Notification Rule" msgstr "" -#: authentik/events/models.py:568 +#: authentik/events/models.py:569 msgid "Notification Rules" msgstr "" -#: authentik/events/models.py:588 +#: authentik/events/models.py:589 msgid "Webhook Mapping" msgstr "" -#: authentik/events/models.py:589 +#: authentik/events/models.py:590 msgid "Webhook Mappings" msgstr "" @@ -541,15 +578,31 @@ msgstr "" msgid "Flows" msgstr "" -#: authentik/flows/models.py:215 +#: authentik/flows/models.py:197 +msgid "Can export a Flow" +msgstr "" + +#: authentik/flows/models.py:198 +msgid "Can inspect a Flow's execution" +msgstr "" + +#: authentik/flows/models.py:199 +msgid "View Flow's cache metrics" +msgstr "" + +#: authentik/flows/models.py:200 +msgid "Clear Flow's cache metrics" +msgstr "" + +#: authentik/flows/models.py:216 msgid "Evaluate policies during the Flow planning process." msgstr "" -#: authentik/flows/models.py:219 +#: authentik/flows/models.py:220 msgid "Evaluate policies when the Stage is present to the user." msgstr "" -#: authentik/flows/models.py:226 +#: authentik/flows/models.py:227 msgid "" "Configure how the flow executor should handle an invalid response to a " "challenge. RETRY returns the error message and a similar challenge to the " @@ -557,25 +610,25 @@ msgid "" "RESTART_WITH_CONTEXT restarts the flow while keeping the current context." msgstr "" -#: authentik/flows/models.py:249 +#: authentik/flows/models.py:250 msgid "Flow Stage Binding" msgstr "" -#: authentik/flows/models.py:250 +#: authentik/flows/models.py:251 msgid "Flow Stage Bindings" msgstr "" -#: authentik/flows/models.py:265 +#: authentik/flows/models.py:266 msgid "" "Flow used by an authenticated user to configure this Stage. If empty, user " "will not be able to configure this stage." msgstr "" -#: authentik/flows/models.py:305 +#: authentik/flows/models.py:306 msgid "Flow Token" msgstr "" -#: authentik/flows/models.py:306 +#: authentik/flows/models.py:307 msgid "Flow Tokens" msgstr "" @@ -584,6 +637,11 @@ msgstr "" msgid "%(value)s is not in the correct format of 'hours=3;minutes=1'." msgstr "" +#: authentik/lib/validators.py:16 +#, python-brace-format +msgid "The fields {field_names} must be used together." +msgstr "" + #: authentik/outposts/api/service_connections.py:127 msgid "" "You can only use an empty kubeconfig when connecting to a local cluster." @@ -657,6 +715,14 @@ msgid "" "empty if authentik should not handle the deployment." msgstr "" +#: authentik/outposts/models.py:419 +msgid "Outpost" +msgstr "" + +#: authentik/outposts/models.py:420 +msgid "Outposts" +msgstr "" + #: authentik/policies/denied.py:24 msgid "Access denied" msgstr "" @@ -782,6 +848,14 @@ msgstr "" msgid "Policies" msgstr "" +#: authentik/policies/models.py:193 +msgid "View Policy's cache metrics" +msgstr "" + +#: authentik/policies/models.py:194 +msgid "Clear Policy's cache metrics" +msgstr "" + #: authentik/policies/password/models.py:27 msgid "Field key to check, field keys defined in Prompt stages are available." msgstr "" @@ -899,6 +973,7 @@ msgid "" msgstr "" #: authentik/providers/ldap/models.py:76 +#: authentik/providers/radius/models.py:34 msgid "" "When enabled, code-based multi-factor authentication can be used by " "appending a semicolon and the TOTP code to the password. This should only be " @@ -1258,19 +1333,19 @@ msgid "" "specified CIDR will be dropped." msgstr "" -#: authentik/providers/radius/models.py:49 +#: authentik/providers/radius/models.py:60 msgid "Radius Provider" msgstr "" -#: authentik/providers/radius/models.py:50 +#: authentik/providers/radius/models.py:61 msgid "Radius Providers" msgstr "" -#: authentik/providers/saml/api/providers.py:257 +#: authentik/providers/saml/api/providers.py:258 msgid "Invalid XML Syntax" msgstr "" -#: authentik/providers/saml/api/providers.py:267 +#: authentik/providers/saml/api/providers.py:268 #, python-format msgid "Failed to import Metadata: %(message)s" msgstr "" @@ -1381,19 +1456,23 @@ msgstr "" msgid "Signing Keypair" msgstr "" -#: authentik/providers/saml/models.py:167 +#: authentik/providers/saml/models.py:142 +msgid "Default relay_state value for IDP-initiated logins" +msgstr "" + +#: authentik/providers/saml/models.py:171 msgid "SAML Provider" msgstr "" -#: authentik/providers/saml/models.py:168 +#: authentik/providers/saml/models.py:172 msgid "SAML Providers" msgstr "" -#: authentik/providers/saml/models.py:192 +#: authentik/providers/saml/models.py:196 msgid "SAML Property Mapping" msgstr "" -#: authentik/providers/saml/models.py:193 +#: authentik/providers/saml/models.py:197 msgid "SAML Property Mappings" msgstr "" @@ -1405,7 +1484,7 @@ msgstr "" msgid "Authentication token" msgstr "" -#: authentik/providers/scim/models.py:27 authentik/sources/ldap/models.py:94 +#: authentik/providers/scim/models.py:27 authentik/sources/ldap/models.py:98 msgid "Property mappings used for group creation/updating." msgstr "" @@ -1454,6 +1533,38 @@ msgstr "" msgid "Failed to sync group %(group_name)s due to remote error: %(error)s" msgstr "" +#: authentik/rbac/models.py:51 +msgid "Role" +msgstr "" + +#: authentik/rbac/models.py:52 +msgid "Roles" +msgstr "" + +#: authentik/rbac/models.py:66 +msgid "System permission" +msgstr "" + +#: authentik/rbac/models.py:67 +msgid "System permissions" +msgstr "" + +#: authentik/rbac/models.py:69 +msgid "Can view system info" +msgstr "" + +#: authentik/rbac/models.py:70 +msgid "Can view system tasks" +msgstr "" + +#: authentik/rbac/models.py:71 +msgid "Can run system tasks" +msgstr "" + +#: authentik/rbac/models.py:72 +msgid "Can access admin interface" +msgstr "" + #: authentik/recovery/management/commands/create_admin_group.py:11 msgid "Create admin group if the default group gets deleted." msgstr "" @@ -1466,92 +1577,92 @@ msgstr "" msgid "Used recovery-link to authenticate." msgstr "" -#: authentik/sources/ldap/models.py:37 +#: authentik/sources/ldap/models.py:41 msgid "Server URI" msgstr "" -#: authentik/sources/ldap/models.py:46 +#: authentik/sources/ldap/models.py:50 msgid "" "Optionally verify the LDAP Server's Certificate against the CA Chain in this " "keypair." msgstr "" -#: authentik/sources/ldap/models.py:55 +#: authentik/sources/ldap/models.py:59 msgid "" "Client certificate to authenticate against the LDAP Server's Certificate." msgstr "" -#: authentik/sources/ldap/models.py:58 +#: authentik/sources/ldap/models.py:62 msgid "Bind CN" msgstr "" -#: authentik/sources/ldap/models.py:60 +#: authentik/sources/ldap/models.py:64 msgid "Enable Start TLS" msgstr "" -#: authentik/sources/ldap/models.py:61 +#: authentik/sources/ldap/models.py:65 msgid "Use Server URI for SNI verification" msgstr "" -#: authentik/sources/ldap/models.py:63 +#: authentik/sources/ldap/models.py:67 msgid "Base DN" msgstr "" -#: authentik/sources/ldap/models.py:65 +#: authentik/sources/ldap/models.py:69 msgid "Prepended to Base DN for User-queries." msgstr "" -#: authentik/sources/ldap/models.py:66 +#: authentik/sources/ldap/models.py:70 msgid "Addition User DN" msgstr "" -#: authentik/sources/ldap/models.py:70 +#: authentik/sources/ldap/models.py:74 msgid "Prepended to Base DN for Group-queries." msgstr "" -#: authentik/sources/ldap/models.py:71 +#: authentik/sources/ldap/models.py:75 msgid "Addition Group DN" msgstr "" -#: authentik/sources/ldap/models.py:77 +#: authentik/sources/ldap/models.py:81 msgid "Consider Objects matching this filter to be Users." msgstr "" -#: authentik/sources/ldap/models.py:80 +#: authentik/sources/ldap/models.py:84 msgid "Field which contains members of a group." msgstr "" -#: authentik/sources/ldap/models.py:84 +#: authentik/sources/ldap/models.py:88 msgid "Consider Objects matching this filter to be Groups." msgstr "" -#: authentik/sources/ldap/models.py:87 +#: authentik/sources/ldap/models.py:91 msgid "Field which contains a unique Identifier." msgstr "" -#: authentik/sources/ldap/models.py:101 +#: authentik/sources/ldap/models.py:105 msgid "" "When a user changes their password, sync it back to LDAP. This can only be " "enabled on a single LDAP source." msgstr "" -#: authentik/sources/ldap/models.py:190 +#: authentik/sources/ldap/models.py:248 msgid "LDAP Source" msgstr "" -#: authentik/sources/ldap/models.py:191 +#: authentik/sources/ldap/models.py:249 msgid "LDAP Sources" msgstr "" -#: authentik/sources/ldap/models.py:213 +#: authentik/sources/ldap/models.py:271 msgid "LDAP Property Mapping" msgstr "" -#: authentik/sources/ldap/models.py:214 +#: authentik/sources/ldap/models.py:272 msgid "LDAP Property Mappings" msgstr "" -#: authentik/sources/ldap/signals.py:50 +#: authentik/sources/ldap/signals.py:52 msgid "Password does not match Active Directory Complexity." msgstr "" @@ -1596,123 +1707,123 @@ msgstr "" msgid "Additional Scopes" msgstr "" -#: authentik/sources/oauth/models.py:108 +#: authentik/sources/oauth/models.py:107 msgid "OAuth Source" msgstr "" -#: authentik/sources/oauth/models.py:109 +#: authentik/sources/oauth/models.py:108 msgid "OAuth Sources" msgstr "" -#: authentik/sources/oauth/models.py:117 +#: authentik/sources/oauth/models.py:116 msgid "GitHub OAuth Source" msgstr "" -#: authentik/sources/oauth/models.py:118 +#: authentik/sources/oauth/models.py:117 msgid "GitHub OAuth Sources" msgstr "" -#: authentik/sources/oauth/models.py:126 +#: authentik/sources/oauth/models.py:125 msgid "Twitch OAuth Source" msgstr "" -#: authentik/sources/oauth/models.py:127 +#: authentik/sources/oauth/models.py:126 msgid "Twitch OAuth Sources" msgstr "" -#: authentik/sources/oauth/models.py:135 +#: authentik/sources/oauth/models.py:134 msgid "Mailcow OAuth Source" msgstr "" -#: authentik/sources/oauth/models.py:136 +#: authentik/sources/oauth/models.py:135 msgid "Mailcow OAuth Sources" msgstr "" -#: authentik/sources/oauth/models.py:144 +#: authentik/sources/oauth/models.py:143 msgid "Twitter OAuth Source" msgstr "" -#: authentik/sources/oauth/models.py:145 +#: authentik/sources/oauth/models.py:144 msgid "Twitter OAuth Sources" msgstr "" -#: authentik/sources/oauth/models.py:153 +#: authentik/sources/oauth/models.py:152 msgid "Facebook OAuth Source" msgstr "" -#: authentik/sources/oauth/models.py:154 +#: authentik/sources/oauth/models.py:153 msgid "Facebook OAuth Sources" msgstr "" -#: authentik/sources/oauth/models.py:162 +#: authentik/sources/oauth/models.py:161 msgid "Discord OAuth Source" msgstr "" -#: authentik/sources/oauth/models.py:163 +#: authentik/sources/oauth/models.py:162 msgid "Discord OAuth Sources" msgstr "" -#: authentik/sources/oauth/models.py:171 +#: authentik/sources/oauth/models.py:170 msgid "Patreon OAuth Source" msgstr "" -#: authentik/sources/oauth/models.py:172 +#: authentik/sources/oauth/models.py:171 msgid "Patreon OAuth Sources" msgstr "" -#: authentik/sources/oauth/models.py:180 +#: authentik/sources/oauth/models.py:179 msgid "Google OAuth Source" msgstr "" -#: authentik/sources/oauth/models.py:181 +#: authentik/sources/oauth/models.py:180 msgid "Google OAuth Sources" msgstr "" -#: authentik/sources/oauth/models.py:189 +#: authentik/sources/oauth/models.py:188 msgid "Azure AD OAuth Source" msgstr "" -#: authentik/sources/oauth/models.py:190 +#: authentik/sources/oauth/models.py:189 msgid "Azure AD OAuth Sources" msgstr "" -#: authentik/sources/oauth/models.py:198 +#: authentik/sources/oauth/models.py:197 msgid "OpenID OAuth Source" msgstr "" -#: authentik/sources/oauth/models.py:199 +#: authentik/sources/oauth/models.py:198 msgid "OpenID OAuth Sources" msgstr "" -#: authentik/sources/oauth/models.py:207 +#: authentik/sources/oauth/models.py:206 msgid "Apple OAuth Source" msgstr "" -#: authentik/sources/oauth/models.py:208 +#: authentik/sources/oauth/models.py:207 msgid "Apple OAuth Sources" msgstr "" -#: authentik/sources/oauth/models.py:216 +#: authentik/sources/oauth/models.py:215 msgid "Okta OAuth Source" msgstr "" -#: authentik/sources/oauth/models.py:217 +#: authentik/sources/oauth/models.py:216 msgid "Okta OAuth Sources" msgstr "" -#: authentik/sources/oauth/models.py:225 +#: authentik/sources/oauth/models.py:224 msgid "Reddit OAuth Source" msgstr "" -#: authentik/sources/oauth/models.py:226 +#: authentik/sources/oauth/models.py:225 msgid "Reddit OAuth Sources" msgstr "" -#: authentik/sources/oauth/models.py:248 +#: authentik/sources/oauth/models.py:247 msgid "User OAuth Source Connection" msgstr "" -#: authentik/sources/oauth/models.py:249 +#: authentik/sources/oauth/models.py:248 msgid "User OAuth Source Connections" msgstr "" @@ -1885,13 +1996,13 @@ msgstr "" msgid "SMS Devices" msgstr "" -#: authentik/stages/authenticator_sms/stage.py:55 +#: authentik/stages/authenticator_sms/stage.py:57 #: authentik/stages/authenticator_totp/stage.py:41 #: authentik/stages/authenticator_totp/stage.py:44 msgid "Code does not match" msgstr "" -#: authentik/stages/authenticator_sms/stage.py:71 +#: authentik/stages/authenticator_sms/stage.py:73 msgid "Invalid phone number" msgstr "" @@ -1904,11 +2015,19 @@ msgid "Static Authenticator Stages" msgstr "" #: authentik/stages/authenticator_static/models.py:98 -msgid "Static device" +msgid "Static Device" msgstr "" #: authentik/stages/authenticator_static/models.py:99 -msgid "Static devices" +msgid "Static Devices" +msgstr "" + +#: authentik/stages/authenticator_static/models.py:129 +msgid "Static Token" +msgstr "" + +#: authentik/stages/authenticator_static/models.py:130 +msgid "Static Tokens" msgstr "" #: authentik/stages/authenticator_totp/models.py:25 @@ -1928,11 +2047,11 @@ msgid "TOTP Authenticator Setup Stages" msgstr "" #: authentik/stages/authenticator_totp/models.py:244 -msgid "TOTP device" +msgid "TOTP Device" msgstr "" #: authentik/stages/authenticator_totp/models.py:245 -msgid "TOTP devices" +msgid "TOTP Devices" msgstr "" #: authentik/stages/authenticator_validate/challenge.py:131 @@ -2041,11 +2160,11 @@ msgstr "" msgid "User Consents" msgstr "" -#: authentik/stages/deny/models.py:30 +#: authentik/stages/deny/models.py:32 msgid "Deny Stage" msgstr "" -#: authentik/stages/deny/models.py:31 +#: authentik/stages/deny/models.py:33 msgid "Deny Stages" msgstr "" @@ -2087,18 +2206,26 @@ msgstr "" msgid "Email Stages" msgstr "" -#: authentik/stages/email/stage.py:117 +#: authentik/stages/email/stage.py:126 +msgid "Exception occurred while rendering E-mail template" +msgstr "" + +#: authentik/stages/email/stage.py:140 msgid "Successfully verified Email." msgstr "" -#: authentik/stages/email/stage.py:124 authentik/stages/email/stage.py:146 +#: authentik/stages/email/stage.py:147 authentik/stages/email/stage.py:173 msgid "No pending user." msgstr "" -#: authentik/stages/email/stage.py:136 +#: authentik/stages/email/stage.py:163 msgid "Email sent." msgstr "" +#: authentik/stages/email/stage.py:176 +msgid "Email Successfully sent." +msgstr "" + #: authentik/stages/email/templates/email/account_confirmation.html:10 msgid "Welcome!" msgstr "" @@ -2147,10 +2274,6 @@ msgid "" " " msgstr "" -#: authentik/stages/email/templates/email/password_reset.html:28 -msgid "Reset Password" -msgstr "" - #: authentik/stages/email/templates/email/password_reset.html:39 #, python-format msgid "" @@ -2193,27 +2316,33 @@ msgid "" "user entered will be shown" msgstr "" -#: authentik/stages/identification/models.py:65 +#: authentik/stages/identification/models.py:60 +msgid "" +"When enabled, the stage will succeed and continue even when incorrect user " +"info is entered." +msgstr "" + +#: authentik/stages/identification/models.py:72 msgid "Optional enrollment flow, which is linked at the bottom of the page." msgstr "" -#: authentik/stages/identification/models.py:74 +#: authentik/stages/identification/models.py:81 msgid "Optional recovery flow, which is linked at the bottom of the page." msgstr "" -#: authentik/stages/identification/models.py:83 +#: authentik/stages/identification/models.py:90 msgid "Optional passwordless flow, which is linked at the bottom of the page." msgstr "" -#: authentik/stages/identification/models.py:87 +#: authentik/stages/identification/models.py:94 msgid "Specify which sources should be shown." msgstr "" -#: authentik/stages/identification/models.py:108 +#: authentik/stages/identification/models.py:115 msgid "Identification Stage" msgstr "" -#: authentik/stages/identification/models.py:109 +#: authentik/stages/identification/models.py:116 msgid "Identification Stages" msgstr "" @@ -2459,24 +2588,24 @@ msgstr "" msgid "Optionally add newly created users to this group." msgstr "" -#: authentik/stages/user_write/models.py:64 +#: authentik/stages/user_write/models.py:68 msgid "User Write Stage" msgstr "" -#: authentik/stages/user_write/models.py:65 +#: authentik/stages/user_write/models.py:69 msgid "User Write Stages" msgstr "" -#: authentik/stages/user_write/stage.py:130 +#: authentik/stages/user_write/stage.py:141 msgid "No Pending data." msgstr "" -#: authentik/stages/user_write/stage.py:136 +#: authentik/stages/user_write/stage.py:147 msgid "No user found and can't create new user." msgstr "" -#: authentik/stages/user_write/stage.py:153 -#: authentik/stages/user_write/stage.py:167 +#: authentik/stages/user_write/stage.py:164 +#: authentik/stages/user_write/stage.py:178 msgid "Failed to update user. Please try again later." msgstr "" diff --git a/proxy.Dockerfile b/proxy.Dockerfile index e8bb5a3f8..ca4f7bc1a 100644 --- a/proxy.Dockerfile +++ b/proxy.Dockerfile @@ -15,7 +15,7 @@ COPY web . RUN npm run build-proxy # Stage 2: Build -FROM --platform=${BUILDPLATFORM} docker.io/golang:1.21.4-bookworm AS builder +FROM --platform=${BUILDPLATFORM} docker.io/golang:1.21.5-bookworm AS builder ARG TARGETOS ARG TARGETARCH diff --git a/radius.Dockerfile b/radius.Dockerfile index 7e6b8fd42..bef91e084 100644 --- a/radius.Dockerfile +++ b/radius.Dockerfile @@ -1,5 +1,5 @@ # Stage 1: Build -FROM --platform=${BUILDPLATFORM} docker.io/golang:1.21.4-bookworm AS builder +FROM --platform=${BUILDPLATFORM} docker.io/golang:1.21.5-bookworm AS builder ARG TARGETOS ARG TARGETARCH diff --git a/schema.yml b/schema.yml index 5f0be7c2d..d36ee5d28 100644 --- a/schema.yml +++ b/schema.yml @@ -6276,6 +6276,86 @@ paths: schema: $ref: '#/components/schemas/GenericError' description: '' + /events/events/volume/: + get: + operationId: events_events_volume_list + description: Get event volume for specified filters and timeframe + parameters: + - in: query + name: action + schema: + type: string + - in: query + name: client_ip + schema: + type: string + - in: query + name: context_authorized_app + schema: + type: string + description: Context Authorized application + - in: query + name: context_model_app + schema: + type: string + description: Context Model App + - in: query + name: context_model_name + schema: + type: string + description: Context Model Name + - in: query + name: context_model_pk + schema: + type: string + description: Context Model Primary Key + - name: ordering + required: false + in: query + description: Which field to use when ordering the results. + schema: + type: string + - name: search + required: false + in: query + description: A search term. + schema: + type: string + - in: query + name: tenant_name + schema: + type: string + description: Tenant name + - in: query + name: username + schema: + type: string + description: Username + tags: + - events + security: + - authentik: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Coordinate' + description: '' + '400': + content: + application/json: + schema: + $ref: '#/components/schemas/ValidationError' + description: '' + '403': + content: + application/json: + schema: + $ref: '#/components/schemas/GenericError' + description: '' /events/notifications/: get: operationId: events_notifications_list diff --git a/tests/wdio/package-lock.json b/tests/wdio/package-lock.json index a7fe0761d..483c15312 100644 --- a/tests/wdio/package-lock.json +++ b/tests/wdio/package-lock.json @@ -7,12 +7,12 @@ "name": "@goauthentik/web-tests", "devDependencies": { "@trivago/prettier-plugin-sort-imports": "^4.3.0", - "@typescript-eslint/eslint-plugin": "^6.13.1", - "@typescript-eslint/parser": "^6.13.1", - "@wdio/cli": "^8.24.6", - "@wdio/local-runner": "^8.24.6", - "@wdio/mocha-framework": "^8.24.6", - "@wdio/spec-reporter": "^8.24.2", + "@typescript-eslint/eslint-plugin": "^6.13.2", + "@typescript-eslint/parser": "^6.13.2", + "@wdio/cli": "^8.24.13", + "@wdio/local-runner": "^8.24.12", + "@wdio/mocha-framework": "^8.24.12", + "@wdio/spec-reporter": "^8.24.12", "eslint": "^8.55.0", "eslint-config-google": "^0.14.0", "eslint-plugin-sonarjs": "^0.23.0", @@ -946,16 +946,16 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.13.1.tgz", - "integrity": "sha512-5bQDGkXaxD46bPvQt08BUz9YSaO4S0fB1LB5JHQuXTfkGPI3+UUeS387C/e9jRie5GqT8u5kFTrMvAjtX4O5kA==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.13.2.tgz", + "integrity": "sha512-3+9OGAWHhk4O1LlcwLBONbdXsAhLjyCFogJY/cWy2lxdVJ2JrcTF2pTGMaLl2AE7U1l31n8Py4a8bx5DLf/0dQ==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.13.1", - "@typescript-eslint/type-utils": "6.13.1", - "@typescript-eslint/utils": "6.13.1", - "@typescript-eslint/visitor-keys": "6.13.1", + "@typescript-eslint/scope-manager": "6.13.2", + "@typescript-eslint/type-utils": "6.13.2", + "@typescript-eslint/utils": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -981,15 +981,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.13.1.tgz", - "integrity": "sha512-fs2XOhWCzRhqMmQf0eicLa/CWSaYss2feXsy7xBD/pLyWke/jCIVc2s1ikEAtSW7ina1HNhv7kONoEfVNEcdDQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.13.2.tgz", + "integrity": "sha512-MUkcC+7Wt/QOGeVlM8aGGJZy1XV5YKjTpq9jK6r6/iLsGXhBVaGP5N0UYvFsu9BFlSpwY9kMretzdBH01rkRXg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.13.1", - "@typescript-eslint/types": "6.13.1", - "@typescript-eslint/typescript-estree": "6.13.1", - "@typescript-eslint/visitor-keys": "6.13.1", + "@typescript-eslint/scope-manager": "6.13.2", + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/typescript-estree": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2", "debug": "^4.3.4" }, "engines": { @@ -1009,13 +1009,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.1.tgz", - "integrity": "sha512-BW0kJ7ceiKi56GbT2KKzZzN+nDxzQK2DS6x0PiSMPjciPgd/JRQGMibyaN2cPt2cAvuoH0oNvn2fwonHI+4QUQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.2.tgz", + "integrity": "sha512-CXQA0xo7z6x13FeDYCgBkjWzNqzBn8RXaE3QVQVIUm74fWJLkJkaHmHdKStrxQllGh6Q4eUGyNpMe0b1hMkXFA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.13.1", - "@typescript-eslint/visitor-keys": "6.13.1" + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1026,13 +1026,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.13.1.tgz", - "integrity": "sha512-A2qPlgpxx2v//3meMqQyB1qqTg1h1dJvzca7TugM3Yc2USDY+fsRBiojAEo92HO7f5hW5mjAUF6qobOPzlBCBQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.13.2.tgz", + "integrity": "sha512-Qr6ssS1GFongzH2qfnWKkAQmMUyZSyOr0W54nZNU1MDfo+U4Mv3XveeLZzadc/yq8iYhQZHYT+eoXJqnACM1tw==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.13.1", - "@typescript-eslint/utils": "6.13.1", + "@typescript-eslint/typescript-estree": "6.13.2", + "@typescript-eslint/utils": "6.13.2", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -1053,9 +1053,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.1.tgz", - "integrity": "sha512-gjeEskSmiEKKFIbnhDXUyiqVma1gRCQNbVZ1C8q7Zjcxh3WZMbzWVfGE9rHfWd1msQtPS0BVD9Jz9jded44eKg==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.2.tgz", + "integrity": "sha512-7sxbQ+EMRubQc3wTfTsycgYpSujyVbI1xw+3UMRUcrhSy+pN09y/lWzeKDbvhoqcRbHdc+APLs/PWYi/cisLPg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1066,13 +1066,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.1.tgz", - "integrity": "sha512-sBLQsvOC0Q7LGcUHO5qpG1HxRgePbT6wwqOiGLpR8uOJvPJbfs0mW3jPA3ujsDvfiVwVlWUDESNXv44KtINkUQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.2.tgz", + "integrity": "sha512-SuD8YLQv6WHnOEtKv8D6HZUzOub855cfPnPMKvdM/Bh1plv1f7Q/0iFUDLKKlxHcEstQnaUU4QZskgQq74t+3w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.13.1", - "@typescript-eslint/visitor-keys": "6.13.1", + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1093,17 +1093,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.13.1.tgz", - "integrity": "sha512-ouPn/zVoan92JgAegesTXDB/oUp6BP1v8WpfYcqh649ejNc9Qv+B4FF2Ff626kO1xg0wWwwG48lAJ4JuesgdOw==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.13.2.tgz", + "integrity": "sha512-b9Ptq4eAZUym4idijCRzl61oPCwwREcfDI8xGk751Vhzig5fFZR9CyzDz4Sp/nxSLBYxUPyh4QdIDqWykFhNmQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.13.1", - "@typescript-eslint/types": "6.13.1", - "@typescript-eslint/typescript-estree": "6.13.1", + "@typescript-eslint/scope-manager": "6.13.2", + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/typescript-estree": "6.13.2", "semver": "^7.5.4" }, "engines": { @@ -1118,12 +1118,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.1.tgz", - "integrity": "sha512-NDhQUy2tg6XGNBGDRm1XybOHSia8mcXmlbKWoQP+nm1BIIMxa55shyJfZkHpEBN62KNPLrocSM2PdPcaLgDKMQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.2.tgz", + "integrity": "sha512-OGznFs0eAQXJsp+xSd6k/O1UbFi/K/L7WjqeRoFE7vadjAF9y0uppXhYNQNEqygjou782maGClOoZwPqF0Drlw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.13.1", + "@typescript-eslint/types": "6.13.2", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1141,34 +1141,33 @@ "dev": true }, "node_modules/@wdio/cli": { - "version": "8.24.6", - "resolved": "https://registry.npmjs.org/@wdio/cli/-/cli-8.24.6.tgz", - "integrity": "sha512-QXRiP1FeGaSmUO24pFhyzP6lZY/FsZAhXyofl3r6TGwTlnw9i4S7C4Te2qQcccgAQq03rdSK058YURPwbiKhmg==", + "version": "8.24.13", + "resolved": "https://registry.npmjs.org/@wdio/cli/-/cli-8.24.13.tgz", + "integrity": "sha512-UG4dvnT6KfnKDsNVn/GeUidi21Pso6N6eu1O5oin9+fP612zpPFrx3/TuYrAfjJb+qmy1QkKq3zX99y+xlp7og==", "dev": true, "dependencies": { "@types/node": "^20.1.1", - "@wdio/config": "8.24.6", - "@wdio/globals": "8.24.6", - "@wdio/logger": "8.16.17", - "@wdio/protocols": "8.23.0", - "@wdio/types": "8.24.2", - "@wdio/utils": "8.24.6", + "@wdio/config": "8.24.12", + "@wdio/globals": "8.24.12", + "@wdio/logger": "8.24.12", + "@wdio/protocols": "8.24.12", + "@wdio/types": "8.24.12", + "@wdio/utils": "8.24.12", "async-exit-hook": "^2.0.1", "chalk": "^5.2.0", "chokidar": "^3.5.3", "cli-spinners": "^2.9.0", - "detect-package-manager": "^3.0.1", "dotenv": "^16.3.1", "ejs": "^3.1.9", "execa": "^8.0.1", - "import-meta-resolve": "^3.0.0", + "import-meta-resolve": "^4.0.0", "inquirer": "9.2.12", "lodash.flattendeep": "^4.4.0", "lodash.pickby": "^4.6.0", "lodash.union": "^4.6.0", "read-pkg-up": "^10.0.0", "recursive-readdir": "^2.2.3", - "webdriverio": "8.24.6", + "webdriverio": "8.24.12", "yargs": "^17.7.2" }, "bin": { @@ -1191,47 +1190,47 @@ } }, "node_modules/@wdio/config": { - "version": "8.24.6", - "resolved": "https://registry.npmjs.org/@wdio/config/-/config-8.24.6.tgz", - "integrity": "sha512-ZFmd6rB1kgL4k/SjLXbtFTCxvxSf1qzdt/losiTqkqFBYznkTRUBGSoGaVTlkMtHAReiVSK92sICc15JWaCdEA==", + "version": "8.24.12", + "resolved": "https://registry.npmjs.org/@wdio/config/-/config-8.24.12.tgz", + "integrity": "sha512-3HW7qG1rIHzOIybV6oHR1CqLghsN0G3Xzs90ZciGL8dYhtcLtYCHwuWmBw4mkaB5xViU4AmZDuj7ChiG8Cr6Qw==", "dev": true, "dependencies": { - "@wdio/logger": "8.16.17", - "@wdio/types": "8.24.2", - "@wdio/utils": "8.24.6", + "@wdio/logger": "8.24.12", + "@wdio/types": "8.24.12", + "@wdio/utils": "8.24.12", "decamelize": "^6.0.0", "deepmerge-ts": "^5.0.0", "glob": "^10.2.2", - "import-meta-resolve": "^3.0.0" + "import-meta-resolve": "^4.0.0" }, "engines": { "node": "^16.13 || >=18" } }, "node_modules/@wdio/globals": { - "version": "8.24.6", - "resolved": "https://registry.npmjs.org/@wdio/globals/-/globals-8.24.6.tgz", - "integrity": "sha512-v5Sjyix9ddrxPM8DCf0vADUxr21Fx7nWVYS6Z/gkTEhuQbi5svjs6EGjMmErO6tp3CY4SNTUiz+ZFJw9YH4Swg==", + "version": "8.24.12", + "resolved": "https://registry.npmjs.org/@wdio/globals/-/globals-8.24.12.tgz", + "integrity": "sha512-uF26a89Q+6DdqzSfK9suXJNdWYJnsazjzPuq4Xtz6nKdjgmBufSeX1JHV4LxErEu5b/IdzVcMCUKKEvsZPc9vA==", "dev": true, "engines": { "node": "^16.13 || >=18" }, "optionalDependencies": { "expect-webdriverio": "^4.6.1", - "webdriverio": "8.24.6" + "webdriverio": "8.24.12" } }, "node_modules/@wdio/local-runner": { - "version": "8.24.6", - "resolved": "https://registry.npmjs.org/@wdio/local-runner/-/local-runner-8.24.6.tgz", - "integrity": "sha512-fd91CxlVpOpSxg+QuqgdFl66kEtY7R/ohdKBXNhdMXtXFb4EQIGp/igiMBvuTHcHUMHOw3N8KaHfe6YXo+6Qyw==", + "version": "8.24.12", + "resolved": "https://registry.npmjs.org/@wdio/local-runner/-/local-runner-8.24.12.tgz", + "integrity": "sha512-Q1lfdSPDEgKwuE1gNucJrkVfgOJLTjtnYGb7Fe7oYUHGDwjkudjSBJYmyx30qFZKfZ4zRqXtaEdys54/0TxibA==", "dev": true, "dependencies": { "@types/node": "^20.1.0", - "@wdio/logger": "8.16.17", - "@wdio/repl": "8.23.1", - "@wdio/runner": "8.24.6", - "@wdio/types": "8.24.2", + "@wdio/logger": "8.24.12", + "@wdio/repl": "8.24.12", + "@wdio/runner": "8.24.12", + "@wdio/types": "8.24.12", "async-exit-hook": "^2.0.1", "split2": "^4.1.0", "stream-buffers": "^3.0.2" @@ -1241,9 +1240,9 @@ } }, "node_modules/@wdio/logger": { - "version": "8.16.17", - "resolved": "https://registry.npmjs.org/@wdio/logger/-/logger-8.16.17.tgz", - "integrity": "sha512-zeQ41z3T+b4IsrriZZipayXxLNDuGsm7TdExaviNGojPVrIsQUCSd/FvlLHM32b7ZrMyInHenu/zx1cjAZO71g==", + "version": "8.24.12", + "resolved": "https://registry.npmjs.org/@wdio/logger/-/logger-8.24.12.tgz", + "integrity": "sha512-QisOiVIWKTUCf1H7S+DOtC+gruhlpimQrUXfWMTeeh672PvAJYnTpOJDWA+BtXfsikkUYFAzAaq8SeMJk8rqKg==", "dev": true, "dependencies": { "chalk": "^5.1.2", @@ -1268,16 +1267,16 @@ } }, "node_modules/@wdio/mocha-framework": { - "version": "8.24.6", - "resolved": "https://registry.npmjs.org/@wdio/mocha-framework/-/mocha-framework-8.24.6.tgz", - "integrity": "sha512-qTRU7trzPJKjdlO6r4+YnyauEQ/cTvCJYRl5t2jqsG8y2OoCRsw4qUydzGTxX3YEkmgZjSN845hMNtyWuZUjcg==", + "version": "8.24.12", + "resolved": "https://registry.npmjs.org/@wdio/mocha-framework/-/mocha-framework-8.24.12.tgz", + "integrity": "sha512-SHN7CYZnDkVUNYxLp8iMV92xcmU/4gq5dqA0pRrK4m5nIU7BoL0flm0kA+ydYUQyNedQh2ru1V63uNyTOyCKAg==", "dev": true, "dependencies": { "@types/mocha": "^10.0.0", "@types/node": "^20.1.0", - "@wdio/logger": "8.16.17", - "@wdio/types": "8.24.2", - "@wdio/utils": "8.24.6", + "@wdio/logger": "8.24.12", + "@wdio/types": "8.24.12", + "@wdio/utils": "8.24.12", "mocha": "^10.0.0" }, "engines": { @@ -1285,15 +1284,15 @@ } }, "node_modules/@wdio/protocols": { - "version": "8.23.0", - "resolved": "https://registry.npmjs.org/@wdio/protocols/-/protocols-8.23.0.tgz", - "integrity": "sha512-2XTzD+lqQP3g8BWn+Bn5BTFzjHqzZNwq7DjlYrb27Bq8nOA+1DEcj3WzQ6V6CktTnKI/LAYKA1IFAF//Azrp/Q==", + "version": "8.24.12", + "resolved": "https://registry.npmjs.org/@wdio/protocols/-/protocols-8.24.12.tgz", + "integrity": "sha512-QnVj3FkapmVD3h2zoZk+ZQ8gevSj9D9MiIQIy8eOnY4FAneYZ9R9GvoW+mgNcCZO8S8++S/jZHetR8n+8Q808g==", "dev": true }, "node_modules/@wdio/repl": { - "version": "8.23.1", - "resolved": "https://registry.npmjs.org/@wdio/repl/-/repl-8.23.1.tgz", - "integrity": "sha512-u6zG2cgBm67V5/WlQzadWqLGXs3moH8MOsgoljULQncelSBBZGZ5DyLB4p7jKcUAsKtMjgmFQmIvpQoqmyvdfg==", + "version": "8.24.12", + "resolved": "https://registry.npmjs.org/@wdio/repl/-/repl-8.24.12.tgz", + "integrity": "sha512-321F3sWafnlw93uRTSjEBVuvWCxTkWNDs7ektQS15drrroL3TMeFOynu4rDrIz0jXD9Vas0HCD2Tq/P0uxFLdw==", "dev": true, "dependencies": { "@types/node": "^20.1.0" @@ -1303,14 +1302,14 @@ } }, "node_modules/@wdio/reporter": { - "version": "8.24.2", - "resolved": "https://registry.npmjs.org/@wdio/reporter/-/reporter-8.24.2.tgz", - "integrity": "sha512-10hTEk4JIIXW8hnwyxTNgby1ZxoJAbXH9d/eMbkEoAwxx/eqaM+ghPs1GSrzOIjjZ3lwz369POEYfJcLkw3g2w==", + "version": "8.24.12", + "resolved": "https://registry.npmjs.org/@wdio/reporter/-/reporter-8.24.12.tgz", + "integrity": "sha512-FtLzDTBXdgxXf4T9HJQ2bNpYYSKEw//jojFm9XzB4fPwzPeFY3HC+dbePucVW1SSLrVzVxqIOyHiwCLqQ/4cQw==", "dev": true, "dependencies": { "@types/node": "^20.1.0", - "@wdio/logger": "8.16.17", - "@wdio/types": "8.24.2", + "@wdio/logger": "8.24.12", + "@wdio/types": "8.24.12", "diff": "^5.0.0", "object-inspect": "^1.12.0" }, @@ -1319,35 +1318,35 @@ } }, "node_modules/@wdio/runner": { - "version": "8.24.6", - "resolved": "https://registry.npmjs.org/@wdio/runner/-/runner-8.24.6.tgz", - "integrity": "sha512-2dt5F9scy0klYwB/E4JztLo04OaPsqcuZP9WKn+NSIBNug0UrgUcBv5ARJEuE3iUyPWpTeczWkU3UtcdMmjagQ==", + "version": "8.24.12", + "resolved": "https://registry.npmjs.org/@wdio/runner/-/runner-8.24.12.tgz", + "integrity": "sha512-wiwXZWG12YDe7GCYBnZ1xEg3UKi18Rvh4RNQiumjypDOErJit1hOCppbJ37LqLqQu+tfWGfN73j46yR7fQOCHw==", "dev": true, "dependencies": { "@types/node": "^20.1.0", - "@wdio/config": "8.24.6", - "@wdio/globals": "8.24.6", - "@wdio/logger": "8.16.17", - "@wdio/types": "8.24.2", - "@wdio/utils": "8.24.6", + "@wdio/config": "8.24.12", + "@wdio/globals": "8.24.12", + "@wdio/logger": "8.24.12", + "@wdio/types": "8.24.12", + "@wdio/utils": "8.24.12", "deepmerge-ts": "^5.0.0", "expect-webdriverio": "^4.6.1", "gaze": "^1.1.2", - "webdriver": "8.24.6", - "webdriverio": "8.24.6" + "webdriver": "8.24.12", + "webdriverio": "8.24.12" }, "engines": { "node": "^16.13 || >=18" } }, "node_modules/@wdio/spec-reporter": { - "version": "8.24.2", - "resolved": "https://registry.npmjs.org/@wdio/spec-reporter/-/spec-reporter-8.24.2.tgz", - "integrity": "sha512-FJ1+/kgxlw4ong+5PJJcOzLf8B/TzPL9hGeOF2xoWkk2uMsmNBJN2r27pjtfFxA41lw4q+Oav0Vb/RhdCB601Q==", + "version": "8.24.12", + "resolved": "https://registry.npmjs.org/@wdio/spec-reporter/-/spec-reporter-8.24.12.tgz", + "integrity": "sha512-Ng3ErWK8eESamCYwIr2Uv49+46RvmT8FnmGaJ6irJoAp101K8zENEs1pyqYHJReucN+ka/wM87blfc2k8NEHCA==", "dev": true, "dependencies": { - "@wdio/reporter": "8.24.2", - "@wdio/types": "8.24.2", + "@wdio/reporter": "8.24.12", + "@wdio/types": "8.24.12", "chalk": "^5.1.2", "easy-table": "^1.2.0", "pretty-ms": "^7.0.0" @@ -1369,9 +1368,9 @@ } }, "node_modules/@wdio/types": { - "version": "8.24.2", - "resolved": "https://registry.npmjs.org/@wdio/types/-/types-8.24.2.tgz", - "integrity": "sha512-x7iWF5NM8NfVxziGwLdQ+3sstgSxRoqfmmFEDTDps0oFrN5CgkqcoLkqXJ5u166gvpxpEq0gxZwxkbPC/Lp0cw==", + "version": "8.24.12", + "resolved": "https://registry.npmjs.org/@wdio/types/-/types-8.24.12.tgz", + "integrity": "sha512-SaD3OacDiW06DvSgAQ7sDBbpiI9qZRg7eoVYeBg3uSGVtUq84vTETRhhV7D6xTC00IqZu+mmN2TY5/q+7Gqy7w==", "dev": true, "dependencies": { "@types/node": "^20.1.0" @@ -1381,21 +1380,20 @@ } }, "node_modules/@wdio/utils": { - "version": "8.24.6", - "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-8.24.6.tgz", - "integrity": "sha512-qwcshLH9iKnhK0jXoXjPw3G02UhyShT0I+ljC0hMybJEBsra92TYFa47Cp6n1fdvM3+/BTuhsgtzRz0anObicQ==", + "version": "8.24.12", + "resolved": "https://registry.npmjs.org/@wdio/utils/-/utils-8.24.12.tgz", + "integrity": "sha512-uzwZyBVgqz0Wz1KL3aOUaQsxT8TNkzxti4NNTSMrU256qAPqc/n75rB7V73QASapCMpy70mZZTsuPgQYYj4ytQ==", "dev": true, "dependencies": { "@puppeteer/browsers": "^1.6.0", - "@wdio/logger": "8.16.17", - "@wdio/types": "8.24.2", + "@wdio/logger": "8.24.12", + "@wdio/types": "8.24.12", "decamelize": "^6.0.0", "deepmerge-ts": "^5.1.0", "edgedriver": "^5.3.5", "geckodriver": "^4.2.0", "get-port": "^7.0.0", - "got": "^13.0.0", - "import-meta-resolve": "^3.0.0", + "import-meta-resolve": "^4.0.0", "locate-app": "^2.1.0", "safaridriver": "^0.1.0", "split2": "^4.2.0", @@ -2457,129 +2455,10 @@ "node": ">=6" } }, - "node_modules/detect-package-manager": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/detect-package-manager/-/detect-package-manager-3.0.1.tgz", - "integrity": "sha512-qoHDH6+lMcpJPAScE7+5CYj91W0mxZNXTwZPrCqi1KMk+x+AoQScQ2V1QyqTln1rHU5Haq5fikvOGHv+leKD8A==", - "dev": true, - "dependencies": { - "execa": "^5.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/detect-package-manager/node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/detect-package-manager/node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/detect-package-manager/node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/detect-package-manager/node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/detect-package-manager/node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/detect-package-manager/node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/detect-package-manager/node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/detect-package-manager/node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/detect-package-manager/node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/devtools-protocol": { - "version": "0.0.1213968", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1213968.tgz", - "integrity": "sha512-o4n/beY+3CcZwFctYapjGelKptR4AuQT5gXS1Kvgbig+ArwkxK7f8wDVuD1wsoswiJWCwV6OK+Qb7vhNzNmABQ==", + "version": "0.0.1233178", + "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.1233178.tgz", + "integrity": "sha512-jmMfyaqlzddwmDaSR1AQ+5ek+f7rupZdxKuPdkRcoxrZoF70Idg/4dTgXA08TLPmwAwB54gh49Wm2l/gRM0eUg==", "dev": true }, "node_modules/diff": { @@ -4008,43 +3887,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/got": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/got/-/got-13.0.0.tgz", - "integrity": "sha512-XfBk1CxOOScDcMr9O1yKkNaQyy865NbYs+F7dr4H0LZMVgCj2Le59k6PqbNHoL5ToeaEQUYh6c6yMfVcc6SJxA==", - "dev": true, - "dependencies": { - "@sindresorhus/is": "^5.2.0", - "@szmarczak/http-timer": "^5.0.1", - "cacheable-lookup": "^7.0.0", - "cacheable-request": "^10.2.8", - "decompress-response": "^6.0.0", - "form-data-encoder": "^2.1.2", - "get-stream": "^6.0.1", - "http2-wrapper": "^2.1.10", - "lowercase-keys": "^3.0.0", - "p-cancelable": "^3.0.0", - "responselike": "^3.0.0" - }, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sindresorhus/got?sponsor=1" - } - }, - "node_modules/got/node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -4271,9 +4113,9 @@ } }, "node_modules/import-meta-resolve": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-3.0.0.tgz", - "integrity": "sha512-4IwhLhNNA8yy445rPjD/lWh++7hMDOml2eHtd58eG7h+qK3EryMuuRbsHGPikCoAgIkkDnckKfWSk2iDla/ejg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.0.0.tgz", + "integrity": "sha512-okYUR7ZQPH+efeuMJGlq4f8ubUgO50kByRPyt/Cy1Io4PSRsPjxME+YlVaCOx+NIToW7hCsZNFJyTPFFKepRSA==", "dev": true, "funding": { "type": "github", @@ -8616,20 +8458,20 @@ } }, "node_modules/webdriver": { - "version": "8.24.6", - "resolved": "https://registry.npmjs.org/webdriver/-/webdriver-8.24.6.tgz", - "integrity": "sha512-k5XI2/SHd/14h4ElPQH8EzSUXujZIGbBEi+3dTS2H457KFR5Q8QYfIazDs/YnEdooOp8b6Oe9N7qI99LP8K6bQ==", + "version": "8.24.12", + "resolved": "https://registry.npmjs.org/webdriver/-/webdriver-8.24.12.tgz", + "integrity": "sha512-03DQIClHoaAqTsmDkxGwo4HwHfkn9LzJ1wfNyUerzKg8DnyXeiT6ILqj6EXLfsvh5zddU2vhYGLFXSerPgkuOQ==", "dev": true, "dependencies": { "@types/node": "^20.1.0", "@types/ws": "^8.5.3", - "@wdio/config": "8.24.6", - "@wdio/logger": "8.16.17", - "@wdio/protocols": "8.23.0", - "@wdio/types": "8.24.2", - "@wdio/utils": "8.24.6", + "@wdio/config": "8.24.12", + "@wdio/logger": "8.24.12", + "@wdio/protocols": "8.24.12", + "@wdio/types": "8.24.12", + "@wdio/utils": "8.24.12", "deepmerge-ts": "^5.1.0", - "got": "^ 12.6.1", + "got": "^12.6.1", "ky": "^0.33.0", "ws": "^8.8.0" }, @@ -8675,25 +8517,25 @@ } }, "node_modules/webdriverio": { - "version": "8.24.6", - "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-8.24.6.tgz", - "integrity": "sha512-gJMAJiErbXe/oFJbV+H9lXp9GPxnUgHrbtxkG6SCKQlk1zPFho9FZ3fQWl/ty84w5n9ZMhAdnQIfZM9aytxIBQ==", + "version": "8.24.12", + "resolved": "https://registry.npmjs.org/webdriverio/-/webdriverio-8.24.12.tgz", + "integrity": "sha512-Ddu0NNRMVkTzRzqvm3m0wt2eLUn+Plz2Cj+1QXDnVpddYJvk9J3elZC2hqNyscEtecQ+h2y3r36OcJqkl9jPag==", "dev": true, "dependencies": { "@types/node": "^20.1.0", - "@wdio/config": "8.24.6", - "@wdio/logger": "8.16.17", - "@wdio/protocols": "8.23.0", - "@wdio/repl": "8.23.1", - "@wdio/types": "8.24.2", - "@wdio/utils": "8.24.6", + "@wdio/config": "8.24.12", + "@wdio/logger": "8.24.12", + "@wdio/protocols": "8.24.12", + "@wdio/repl": "8.24.12", + "@wdio/types": "8.24.12", + "@wdio/utils": "8.24.12", "archiver": "^6.0.0", "aria-query": "^5.0.0", "css-shorthand-properties": "^1.1.1", "css-value": "^0.0.1", - "devtools-protocol": "^0.0.1213968", + "devtools-protocol": "^0.0.1233178", "grapheme-splitter": "^1.0.2", - "import-meta-resolve": "^3.0.0", + "import-meta-resolve": "^4.0.0", "is-plain-obj": "^4.1.0", "lodash.clonedeep": "^4.5.0", "lodash.zip": "^4.2.0", @@ -8703,7 +8545,7 @@ "resq": "^1.9.1", "rgb2hex": "0.2.5", "serialize-error": "^11.0.1", - "webdriver": "8.24.6" + "webdriver": "8.24.12" }, "engines": { "node": "^16.13 || >=18" diff --git a/tests/wdio/package.json b/tests/wdio/package.json index b07587713..6b9b5c1a2 100644 --- a/tests/wdio/package.json +++ b/tests/wdio/package.json @@ -4,12 +4,12 @@ "type": "module", "devDependencies": { "@trivago/prettier-plugin-sort-imports": "^4.3.0", - "@typescript-eslint/eslint-plugin": "^6.13.1", - "@typescript-eslint/parser": "^6.13.1", - "@wdio/cli": "^8.24.6", - "@wdio/local-runner": "^8.24.6", - "@wdio/mocha-framework": "^8.24.6", - "@wdio/spec-reporter": "^8.24.2", + "@typescript-eslint/eslint-plugin": "^6.13.2", + "@typescript-eslint/parser": "^6.13.2", + "@wdio/cli": "^8.24.13", + "@wdio/local-runner": "^8.24.12", + "@wdio/mocha-framework": "^8.24.12", + "@wdio/spec-reporter": "^8.24.12", "eslint": "^8.55.0", "eslint-config-google": "^0.14.0", "eslint-plugin-sonarjs": "^0.23.0", diff --git a/web/package-lock.json b/web/package-lock.json index a60c60e3f..a8be14feb 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -17,22 +17,22 @@ "@codemirror/theme-one-dark": "^6.1.2", "@formatjs/intl-listformat": "^7.5.3", "@fortawesome/fontawesome-free": "^6.5.1", - "@goauthentik/api": "^2023.10.4-1700591367", + "@goauthentik/api": "^2023.10.4-1701882394", "@lit-labs/context": "^0.4.0", "@lit-labs/task": "^3.1.0", "@lit/localize": "^0.11.4", "@open-wc/lit-helpers": "^0.6.0", "@patternfly/elements": "^2.4.0", "@patternfly/patternfly": "^4.224.2", - "@sentry/browser": "^7.84.0", - "@sentry/tracing": "^7.84.0", + "@sentry/browser": "^7.85.0", + "@sentry/tracing": "^7.85.0", "@webcomponents/webcomponentsjs": "^2.8.0", "base64-js": "^1.5.1", - "chart.js": "^4.4.0", + "chart.js": "^4.4.1", "chartjs-adapter-moment": "^1.0.1", "codemirror": "^6.0.1", "construct-style-sheets-polyfill": "^3.1.0", - "core-js": "^3.33.3", + "core-js": "^3.34.0", "country-flag-icons": "^1.5.9", "fuse.js": "^7.0.0", "lit": "^2.8.0", @@ -70,8 +70,8 @@ "@types/chart.js": "^2.9.41", "@types/codemirror": "5.60.15", "@types/grecaptcha": "^3.0.7", - "@typescript-eslint/eslint-plugin": "^6.13.1", - "@typescript-eslint/parser": "^6.13.1", + "@typescript-eslint/eslint-plugin": "^6.13.2", + "@typescript-eslint/parser": "^6.13.2", "babel-plugin-macros": "^3.1.0", "babel-plugin-tsconfig-paths": "^1.0.3", "cross-env": "^7.0.3", @@ -2944,9 +2944,9 @@ } }, "node_modules/@goauthentik/api": { - "version": "2023.10.4-1700591367", - "resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2023.10.4-1700591367.tgz", - "integrity": "sha512-ljC/SHH6ZgGC2qjvuA3gley8sRz9wVzr5FgRGKeqd1mi6G6TfnFYeA7tuuqgQc6WGN2MVMG17FnBraTI77Rl/A==" + "version": "2023.10.4-1701882394", + "resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2023.10.4-1701882394.tgz", + "integrity": "sha512-rYfJRl4IGQN6OGdWy6f+yMuNRPgmPjkPTI+6V1otR5NwgKrvZeEzy/8Vx1tEkz3CIix8rgZCmu3SmJVsep0ggQ==" }, "node_modules/@hcaptcha/types": { "version": "1.0.3", @@ -4768,85 +4768,99 @@ "win32" ] }, - "node_modules/@sentry-internal/tracing": { - "version": "7.84.0", - "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.84.0.tgz", - "integrity": "sha512-y9bGYA0OM6PEREfd+nk4UURZy29tpIw+7vQwpxWfEVs2fqq0/5TBFX/tKFb8AKUI9lVM8v0bcF0bNSCnuPQZHQ==", + "node_modules/@sentry-internal/feedback": { + "version": "7.85.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-7.85.0.tgz", + "integrity": "sha512-MlbIN+N8CWFJBjbqMmARe4+UPo9QRhRar0YoOfmNA2Xqk/EwXcjHWkealosHznXH7tqVbjB25QJpHtDystft/Q==", "dependencies": { - "@sentry/core": "7.84.0", - "@sentry/types": "7.84.0", - "@sentry/utils": "7.84.0" + "@sentry/core": "7.85.0", + "@sentry/types": "7.85.0", + "@sentry/utils": "7.85.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@sentry-internal/tracing": { + "version": "7.85.0", + "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.85.0.tgz", + "integrity": "sha512-p3YMUwkPCy2su9cm/3+7QYR4RiMI0+07DU1BZtht9NLTzY2O87/yvUbn1v2yHR3vJQTy/+7N0ud9/mPBFznRQQ==", + "dependencies": { + "@sentry/core": "7.85.0", + "@sentry/types": "7.85.0", + "@sentry/utils": "7.85.0" }, "engines": { "node": ">=8" } }, "node_modules/@sentry/browser": { - "version": "7.84.0", - "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.84.0.tgz", - "integrity": "sha512-X50TlTKY9WzAnHsYc4FYrCWgm+CdVo0h02ggmodVBUpRLUBjj+cs5Q1plov/v/XeorSwmorNEMUu/n+XZNSsrA==", + "version": "7.85.0", + "resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.85.0.tgz", + "integrity": "sha512-x4sH7vTQnZQgy1U7NuN8XwhleAw7YMQitccHeC5m+kpIKGUO7w4Mdvu8rD3dnjmVmZvASpnwocAxy57/vCU6Ww==", "dependencies": { - "@sentry-internal/tracing": "7.84.0", - "@sentry/core": "7.84.0", - "@sentry/replay": "7.84.0", - "@sentry/types": "7.84.0", - "@sentry/utils": "7.84.0" + "@sentry-internal/feedback": "7.85.0", + "@sentry-internal/tracing": "7.85.0", + "@sentry/core": "7.85.0", + "@sentry/replay": "7.85.0", + "@sentry/types": "7.85.0", + "@sentry/utils": "7.85.0" }, "engines": { "node": ">=8" } }, "node_modules/@sentry/core": { - "version": "7.84.0", - "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.84.0.tgz", - "integrity": "sha512-tbuwunbBx2kSex15IHCqHDnrMfIlqPc6w/76fwkGqokz3oh9GSEGlLICwmBWL8AypWimUg13IDtFpD0TJTriWA==", + "version": "7.85.0", + "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.85.0.tgz", + "integrity": "sha512-DFDAc4tWmHN5IWhr7XbHCiyF1Xgb95jz8Uj/JTX9atlgodId1UIbER77qpEmH3eQGid/QBdqrlR98zCixgSbwg==", "dependencies": { - "@sentry/types": "7.84.0", - "@sentry/utils": "7.84.0" + "@sentry/types": "7.85.0", + "@sentry/utils": "7.85.0" }, "engines": { "node": ">=8" } }, "node_modules/@sentry/replay": { - "version": "7.84.0", - "resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.84.0.tgz", - "integrity": "sha512-c4PxT0ZpvkR9zXNfmAk3ojkm6eZ9+NlDze09RFBOCNo69QwIN90hnvbjXFC1+vRIJsfgo78Zr0ya/Wzb3Rog7Q==", + "version": "7.85.0", + "resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.85.0.tgz", + "integrity": "sha512-zVtTKfO+lu5qTwHpETI/oGo8hU3rdKHr3CdI1vRLw+d60PcAa/pWVlXsQeLRTw8PFwE358gHcpFZezj/11afew==", "dependencies": { - "@sentry-internal/tracing": "7.84.0", - "@sentry/core": "7.84.0", - "@sentry/types": "7.84.0", - "@sentry/utils": "7.84.0" + "@sentry-internal/tracing": "7.85.0", + "@sentry/core": "7.85.0", + "@sentry/types": "7.85.0", + "@sentry/utils": "7.85.0" }, "engines": { "node": ">=12" } }, "node_modules/@sentry/tracing": { - "version": "7.84.0", - "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.84.0.tgz", - "integrity": "sha512-NhBX28vUmCu/5avyGKX6B4UTm4MTOfbdg9ZzCnS7hPuWDfEAUIVHZVryi2q8bqp2DNGJvS9qIq/TSf39JIpdJg==", + "version": "7.85.0", + "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-7.85.0.tgz", + "integrity": "sha512-L3bpqiM+zu5f3o6zh6hx3xEzVENyhrkuMlpUOyDo0mUytqp763HqF1xz+R+trzze7R5VWrxJaRPARsCKlXu4Ig==", "dependencies": { - "@sentry-internal/tracing": "7.84.0" + "@sentry-internal/tracing": "7.85.0" }, "engines": { "node": ">=8" } }, "node_modules/@sentry/types": { - "version": "7.84.0", - "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.84.0.tgz", - "integrity": "sha512-VqGLIF3JOUrk7yIXjLXJvAORkZL1e3dDX0Q1okRehwyt/5CRE+mdUTeJZkBo9P9mBwgMyvtwklzOGGrzjb4eMA==", + "version": "7.85.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.85.0.tgz", + "integrity": "sha512-R5jR4XkK5tBU2jDiPdSVqzkmjYRr666bcGaFGUHB/xDQCjPsjk+pEmCCL+vpuWoaZmQJUE1hVU7rgnVX81w8zg==", "engines": { "node": ">=8" } }, "node_modules/@sentry/utils": { - "version": "7.84.0", - "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.84.0.tgz", - "integrity": "sha512-qdUVuxnRBvaf05AU+28R+xYtZmi/Ymf8os3Njq9g4XuA+QEkZLbzmIpRK5W9Ja7vUtjOeg29Xgg43A8znde9LQ==", + "version": "7.85.0", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.85.0.tgz", + "integrity": "sha512-JZ7seNOLvhjAQ8GeB3GYknPQJkuhF88xAYOaESZP3xPOWBMFUN+IO4RqjMqMLFDniOwsVQS7GB/MfP+hxufieg==", "dependencies": { - "@sentry/types": "7.84.0" + "@sentry/types": "7.85.0" }, "engines": { "node": ">=8" @@ -10526,16 +10540,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.13.1.tgz", - "integrity": "sha512-5bQDGkXaxD46bPvQt08BUz9YSaO4S0fB1LB5JHQuXTfkGPI3+UUeS387C/e9jRie5GqT8u5kFTrMvAjtX4O5kA==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.13.2.tgz", + "integrity": "sha512-3+9OGAWHhk4O1LlcwLBONbdXsAhLjyCFogJY/cWy2lxdVJ2JrcTF2pTGMaLl2AE7U1l31n8Py4a8bx5DLf/0dQ==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.13.1", - "@typescript-eslint/type-utils": "6.13.1", - "@typescript-eslint/utils": "6.13.1", - "@typescript-eslint/visitor-keys": "6.13.1", + "@typescript-eslint/scope-manager": "6.13.2", + "@typescript-eslint/type-utils": "6.13.2", + "@typescript-eslint/utils": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -10594,15 +10608,15 @@ "dev": true }, "node_modules/@typescript-eslint/parser": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.13.1.tgz", - "integrity": "sha512-fs2XOhWCzRhqMmQf0eicLa/CWSaYss2feXsy7xBD/pLyWke/jCIVc2s1ikEAtSW7ina1HNhv7kONoEfVNEcdDQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.13.2.tgz", + "integrity": "sha512-MUkcC+7Wt/QOGeVlM8aGGJZy1XV5YKjTpq9jK6r6/iLsGXhBVaGP5N0UYvFsu9BFlSpwY9kMretzdBH01rkRXg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.13.1", - "@typescript-eslint/types": "6.13.1", - "@typescript-eslint/typescript-estree": "6.13.1", - "@typescript-eslint/visitor-keys": "6.13.1", + "@typescript-eslint/scope-manager": "6.13.2", + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/typescript-estree": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2", "debug": "^4.3.4" }, "engines": { @@ -10622,13 +10636,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.1.tgz", - "integrity": "sha512-BW0kJ7ceiKi56GbT2KKzZzN+nDxzQK2DS6x0PiSMPjciPgd/JRQGMibyaN2cPt2cAvuoH0oNvn2fwonHI+4QUQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.13.2.tgz", + "integrity": "sha512-CXQA0xo7z6x13FeDYCgBkjWzNqzBn8RXaE3QVQVIUm74fWJLkJkaHmHdKStrxQllGh6Q4eUGyNpMe0b1hMkXFA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.13.1", - "@typescript-eslint/visitor-keys": "6.13.1" + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -10639,13 +10653,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.13.1.tgz", - "integrity": "sha512-A2qPlgpxx2v//3meMqQyB1qqTg1h1dJvzca7TugM3Yc2USDY+fsRBiojAEo92HO7f5hW5mjAUF6qobOPzlBCBQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.13.2.tgz", + "integrity": "sha512-Qr6ssS1GFongzH2qfnWKkAQmMUyZSyOr0W54nZNU1MDfo+U4Mv3XveeLZzadc/yq8iYhQZHYT+eoXJqnACM1tw==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.13.1", - "@typescript-eslint/utils": "6.13.1", + "@typescript-eslint/typescript-estree": "6.13.2", + "@typescript-eslint/utils": "6.13.2", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -10666,9 +10680,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.1.tgz", - "integrity": "sha512-gjeEskSmiEKKFIbnhDXUyiqVma1gRCQNbVZ1C8q7Zjcxh3WZMbzWVfGE9rHfWd1msQtPS0BVD9Jz9jded44eKg==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.13.2.tgz", + "integrity": "sha512-7sxbQ+EMRubQc3wTfTsycgYpSujyVbI1xw+3UMRUcrhSy+pN09y/lWzeKDbvhoqcRbHdc+APLs/PWYi/cisLPg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -10679,13 +10693,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.1.tgz", - "integrity": "sha512-sBLQsvOC0Q7LGcUHO5qpG1HxRgePbT6wwqOiGLpR8uOJvPJbfs0mW3jPA3ujsDvfiVwVlWUDESNXv44KtINkUQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.13.2.tgz", + "integrity": "sha512-SuD8YLQv6WHnOEtKv8D6HZUzOub855cfPnPMKvdM/Bh1plv1f7Q/0iFUDLKKlxHcEstQnaUU4QZskgQq74t+3w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.13.1", - "@typescript-eslint/visitor-keys": "6.13.1", + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/visitor-keys": "6.13.2", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -10739,17 +10753,17 @@ "dev": true }, "node_modules/@typescript-eslint/utils": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.13.1.tgz", - "integrity": "sha512-ouPn/zVoan92JgAegesTXDB/oUp6BP1v8WpfYcqh649ejNc9Qv+B4FF2Ff626kO1xg0wWwwG48lAJ4JuesgdOw==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.13.2.tgz", + "integrity": "sha512-b9Ptq4eAZUym4idijCRzl61oPCwwREcfDI8xGk751Vhzig5fFZR9CyzDz4Sp/nxSLBYxUPyh4QdIDqWykFhNmQ==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.13.1", - "@typescript-eslint/types": "6.13.1", - "@typescript-eslint/typescript-estree": "6.13.1", + "@typescript-eslint/scope-manager": "6.13.2", + "@typescript-eslint/types": "6.13.2", + "@typescript-eslint/typescript-estree": "6.13.2", "semver": "^7.5.4" }, "engines": { @@ -10797,12 +10811,12 @@ "dev": true }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.1.tgz", - "integrity": "sha512-NDhQUy2tg6XGNBGDRm1XybOHSia8mcXmlbKWoQP+nm1BIIMxa55shyJfZkHpEBN62KNPLrocSM2PdPcaLgDKMQ==", + "version": "6.13.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.13.2.tgz", + "integrity": "sha512-OGznFs0eAQXJsp+xSd6k/O1UbFi/K/L7WjqeRoFE7vadjAF9y0uppXhYNQNEqygjou782maGClOoZwPqF0Drlw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.13.1", + "@typescript-eslint/types": "6.13.2", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -11687,9 +11701,9 @@ } }, "node_modules/chart.js": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.0.tgz", - "integrity": "sha512-vQEj6d+z0dcsKLlQvbKIMYFHd3t8W/7L2vfJIbYcfyPcRx92CsHqECpueN8qVGNlKyDcr5wBrYAYKnfu/9Q1hQ==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.1.tgz", + "integrity": "sha512-C74QN1bxwV1v2PEujhmKjOZ7iUM4w6BWs23Md/6aOZZSlwMzeCIDGuZay++rBgChYru7/+QFeoQW0fQoP534Dg==", "dependencies": { "@kurkle/color": "^0.3.0" }, @@ -12092,9 +12106,9 @@ "dev": true }, "node_modules/core-js": { - "version": "3.33.3", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.33.3.tgz", - "integrity": "sha512-lo0kOocUlLKmm6kv/FswQL8zbkH7mVsLJ/FULClOhv8WRVmKLVcs6XPNQAzstfeJTCHMyButEwG+z1kHxHoDZw==", + "version": "3.34.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.34.0.tgz", + "integrity": "sha512-aDdvlDder8QmY91H88GzNi9EtQi2TjvQhpCX6B1v/dAZHU1AuLgHvRh54RiOerpEhEW46Tkf+vgAViB/CWC0ag==", "hasInstallScript": true, "funding": { "type": "opencollective", diff --git a/web/package.json b/web/package.json index 645bf3319..7ad4ace20 100644 --- a/web/package.json +++ b/web/package.json @@ -38,22 +38,22 @@ "@codemirror/theme-one-dark": "^6.1.2", "@formatjs/intl-listformat": "^7.5.3", "@fortawesome/fontawesome-free": "^6.5.1", - "@goauthentik/api": "^2023.10.4-1700591367", + "@goauthentik/api": "^2023.10.4-1701882394", "@lit-labs/context": "^0.4.0", "@lit-labs/task": "^3.1.0", "@lit/localize": "^0.11.4", "@open-wc/lit-helpers": "^0.6.0", "@patternfly/elements": "^2.4.0", "@patternfly/patternfly": "^4.224.2", - "@sentry/browser": "^7.84.0", - "@sentry/tracing": "^7.84.0", + "@sentry/browser": "^7.85.0", + "@sentry/tracing": "^7.85.0", "@webcomponents/webcomponentsjs": "^2.8.0", "base64-js": "^1.5.1", - "chart.js": "^4.4.0", + "chart.js": "^4.4.1", "chartjs-adapter-moment": "^1.0.1", "codemirror": "^6.0.1", "construct-style-sheets-polyfill": "^3.1.0", - "core-js": "^3.33.3", + "core-js": "^3.34.0", "country-flag-icons": "^1.5.9", "fuse.js": "^7.0.0", "lit": "^2.8.0", @@ -91,8 +91,8 @@ "@types/chart.js": "^2.9.41", "@types/codemirror": "5.60.15", "@types/grecaptcha": "^3.0.7", - "@typescript-eslint/eslint-plugin": "^6.13.1", - "@typescript-eslint/parser": "^6.13.1", + "@typescript-eslint/eslint-plugin": "^6.13.2", + "@typescript-eslint/parser": "^6.13.2", "babel-plugin-macros": "^3.1.0", "babel-plugin-tsconfig-paths": "^1.0.3", "cross-env": "^7.0.3", diff --git a/web/src/admin/applications/ApplicationListPage.ts b/web/src/admin/applications/ApplicationListPage.ts index 928e48b9b..fd8306c3f 100644 --- a/web/src/admin/applications/ApplicationListPage.ts +++ b/web/src/admin/applications/ApplicationListPage.ts @@ -89,17 +89,15 @@ export class ApplicationListPage extends TablePage { ]; } + renderSectionBefore(): TemplateResult { + return html``; + } + renderSidebarAfter(): TemplateResult { // Rendering the wizard with .open here, as if we set the attribute in // renderObjectCreate() it'll open two wizards, since that function gets called twice - /* Re-enable the wizard later: - */ - - return html`
+ return html`
diff --git a/web/src/admin/applications/wizard/BasePanel.ts b/web/src/admin/applications/wizard/BasePanel.ts index a395fc4b3..1b2db5bd4 100644 --- a/web/src/admin/applications/wizard/BasePanel.ts +++ b/web/src/admin/applications/wizard/BasePanel.ts @@ -1,5 +1,7 @@ import { WizardPanel } from "@goauthentik/components/ak-wizard-main/types"; import { AKElement } from "@goauthentik/elements/Base"; +import { KeyUnknown, serializeForm } from "@goauthentik/elements/forms/Form"; +import { HorizontalFormElement } from "@goauthentik/elements/forms/HorizontalFormElement"; import { CustomEmitterElement } from "@goauthentik/elements/utils/eventEmitter"; import { consume } from "@lit-labs/context"; @@ -10,6 +12,15 @@ import { styles as AwadStyles } from "./BasePanel.css"; import { applicationWizardContext } from "./ContextIdentity"; import type { ApplicationWizardState, ApplicationWizardStateUpdate } from "./types"; +/** + * Application Wizard Base Panel + * + * All of the displays in our system inherit from this object, which supplies the basic CSS for all + * the inputs we display, as well as the values and validity state for the form currently being + * displayed. + * + */ + export class ApplicationWizardPageBase extends CustomEmitterElement(AKElement) implements WizardPanel @@ -18,15 +29,41 @@ export class ApplicationWizardPageBase return AwadStyles; } - @query("form") - form!: HTMLFormElement; - - rendered = false; - @consume({ context: applicationWizardContext }) public wizard!: ApplicationWizardState; - // This used to be more complex; now it just establishes the event name. + @query("form") + form!: HTMLFormElement; + + /** + * Provide access to the values on the current form. Child implementations use this to craft the + * update that will be sent using `dispatchWizardUpdate` below. + */ + get formValues(): KeyUnknown | undefined { + const elements = [ + ...Array.from( + this.form.querySelectorAll("ak-form-element-horizontal"), + ), + ...Array.from(this.form.querySelectorAll("[data-ak-control=true]")), + ]; + return serializeForm(elements as unknown as NodeListOf); + } + + /** + * Provide access to the validity of the current form. Child implementations use this to craft + * the update that will be sent using `dispatchWizardUpdate` below. + */ + get valid() { + return this.form.checkValidity(); + } + + rendered = false; + + /** + * Provide a single source of truth for the token used to notify the orchestrator that an event + * happens. The token `ak-wizard-update` is used by the Wizard framework's reactive controller + * to route "data on the current step has changed" events to the orchestrator. + */ dispatchWizardUpdate(update: ApplicationWizardStateUpdate) { this.dispatchCustomEvent("ak-wizard-update", update); } diff --git a/web/src/admin/applications/wizard/ContextIdentity.ts b/web/src/admin/applications/wizard/ContextIdentity.ts index f03f147a6..629b65cd8 100644 --- a/web/src/admin/applications/wizard/ContextIdentity.ts +++ b/web/src/admin/applications/wizard/ContextIdentity.ts @@ -5,5 +5,3 @@ import { ApplicationWizardState } from "./types"; export const applicationWizardContext = createContext( Symbol("ak-application-wizard-state-context"), ); - -export default applicationWizardContext; diff --git a/web/src/admin/applications/wizard/ak-application-wizard.ts b/web/src/admin/applications/wizard/ak-application-wizard.ts index d15570f13..50cf750d7 100644 --- a/web/src/admin/applications/wizard/ak-application-wizard.ts +++ b/web/src/admin/applications/wizard/ak-application-wizard.ts @@ -1,4 +1,3 @@ -import { merge } from "@goauthentik/common/merge"; import { AkWizard } from "@goauthentik/components/ak-wizard-main/AkWizard"; import { CustomListenerElement } from "@goauthentik/elements/utils/eventEmitter"; @@ -6,7 +5,7 @@ import { ContextProvider } from "@lit-labs/context"; import { msg } from "@lit/localize"; import { customElement, state } from "lit/decorators.js"; -import applicationWizardContext from "./ContextIdentity"; +import { applicationWizardContext } from "./ContextIdentity"; import { newSteps } from "./steps"; import { ApplicationStep, @@ -15,10 +14,11 @@ import { OneOfProvider, } from "./types"; -const freshWizardState = () => ({ +const freshWizardState = (): ApplicationWizardState => ({ providerModel: "", app: {}, provider: {}, + errors: {}, }); @customElement("ak-application-wizard") @@ -56,28 +56,6 @@ export class ApplicationWizard extends CustomListenerElement( */ providerCache: Map = new Map(); - maybeProviderSwap(providerModel: string | undefined): boolean { - if ( - providerModel === undefined || - typeof providerModel !== "string" || - providerModel === this.wizardState.providerModel - ) { - return false; - } - - this.providerCache.set(this.wizardState.providerModel, this.wizardState.provider); - const prevProvider = this.providerCache.get(providerModel); - this.wizardState.provider = prevProvider ?? { - name: `Provider for ${this.wizardState.app.name}`, - }; - const method = this.steps.find(({ id }) => id === "provider-details"); - if (!method) { - throw new Error("Could not find Authentication Method page?"); - } - method.disabled = false; - return true; - } - // And this is where all the special cases go... handleUpdate(detail: ApplicationWizardStateUpdate) { if (detail.status === "submitted") { @@ -87,17 +65,26 @@ export class ApplicationWizard extends CustomListenerElement( } this.step.valid = this.step.valid || detail.status === "valid"; - const update = detail.update; + if (!update) { return; } - if (this.maybeProviderSwap(update.providerModel)) { - this.requestUpdate(); + // When the providerModel enum changes, retrieve the customer's prior work for *this* wizard + // session (and only this wizard session) or provide an empty model with a default provider + // name. + if (update.providerModel && update.providerModel !== this.wizardState.providerModel) { + const requestedProvider = this.providerCache.get(update.providerModel) ?? { + name: `Provider for ${this.wizardState.app.name}`, + }; + if (this.wizardState.providerModel) { + this.providerCache.set(this.wizardState.providerModel, this.wizardState.provider); + } + update.provider = requestedProvider; } - this.wizardState = merge(this.wizardState, update) as ApplicationWizardState; + this.wizardState = update as ApplicationWizardState; this.wizardStateProvider.setValue(this.wizardState); this.requestUpdate(); } diff --git a/web/src/admin/applications/wizard/ak-wizard-title.ts b/web/src/admin/applications/wizard/ak-wizard-title.ts new file mode 100644 index 000000000..cd2157a69 --- /dev/null +++ b/web/src/admin/applications/wizard/ak-wizard-title.ts @@ -0,0 +1,30 @@ +import { AKElement } from "@goauthentik/elements/Base"; + +import { css, html } from "lit"; +import { customElement } from "lit/decorators.js"; + +import PFContent from "@patternfly/patternfly/components/Content/content.css"; +import PFTitle from "@patternfly/patternfly/components/Title/title.css"; + +@customElement("ak-wizard-title") +export class AkWizardTitle extends AKElement { + static get styles() { + return [ + PFContent, + PFTitle, + css` + .ak-bottom-spacing { + padding-bottom: var(--pf-global--spacer--lg); + } + `, + ]; + } + + render() { + return html`
+

+
`; + } +} + +export default AkWizardTitle; diff --git a/web/src/admin/applications/wizard/application/ak-application-wizard-application-details.ts b/web/src/admin/applications/wizard/application/ak-application-wizard-application-details.ts index 13e439d76..c89c555a0 100644 --- a/web/src/admin/applications/wizard/application/ak-application-wizard-application-details.ts +++ b/web/src/admin/applications/wizard/application/ak-application-wizard-application-details.ts @@ -5,7 +5,6 @@ import "@goauthentik/components/ak-slug-input"; import "@goauthentik/components/ak-switch-input"; import "@goauthentik/components/ak-text-input"; import "@goauthentik/elements/forms/FormGroup"; -import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/HorizontalFormElement"; import { msg } from "@lit/localize"; @@ -17,28 +16,20 @@ import BasePanel from "../BasePanel"; @customElement("ak-application-wizard-application-details") export class ApplicationWizardApplicationDetails extends BasePanel { - handleChange(ev: Event) { - if (!ev.target) { - console.warn(`Received event with no target: ${ev}`); - return; + handleChange(_ev: Event) { + const formValues = this.formValues; + if (!formValues) { + throw new Error("No application values on form?"); } - - const target = ev.target as HTMLInputElement; - const value = target.type === "checkbox" ? target.checked : target.value; this.dispatchWizardUpdate({ update: { - app: { - [target.name]: value, - }, + ...this.wizard, + app: formValues, }, - status: this.form.checkValidity() ? "valid" : "invalid", + status: this.valid ? "valid" : "invalid", }); } - validator() { - return this.form.reportValidity(); - } - render(): TemplateResult { return html`
${msg("UI Settings")} @@ -82,6 +77,7 @@ export class ApplicationWizardApplicationDetails extends BasePanel { help=${msg( "If left empty, authentik will try to extract the launch URL based on the selected provider.", )} + .errorMessages=${this.wizard.errors.app?.metaLaunchUrl ?? []} > TemplateResult; type ModelConverter = (provider: OneOfProvider) => ModelRequest; +/** + * There's an internal key and an API key because "Proxy" has three different subtypes. + */ +// prettier-ignore type ProviderType = [ - string, - string, - string, - ProviderRenderer, - ProviderModelEnumType, - ModelConverter, + string, // internal key used by the wizard to distinguish between providers + string, // Name of the provider + string, // Description + ProviderRenderer, // Function that returns the provider's wizard panel as a TemplateResult + ProviderModelEnumType, // key used by the API to distinguish between providers + ModelConverter, // Handler that takes a generic provider and returns one specifically typed to its panel ]; export type LocalTypeCreate = TypeCreate & { diff --git a/web/src/admin/applications/wizard/auth-method-choice/ak-application-wizard-authentication-method-choice.ts b/web/src/admin/applications/wizard/auth-method-choice/ak-application-wizard-authentication-method-choice.ts index 593406d66..e13e11eca 100644 --- a/web/src/admin/applications/wizard/auth-method-choice/ak-application-wizard-authentication-method-choice.ts +++ b/web/src/admin/applications/wizard/auth-method-choice/ak-application-wizard-authentication-method-choice.ts @@ -25,19 +25,15 @@ export class ApplicationWizardAuthenticationMethodChoice extends BasePanel { handleChoice(ev: InputEvent) { const target = ev.target as HTMLInputElement; this.dispatchWizardUpdate({ - update: { providerModel: target.value }, - status: this.validator() ? "valid" : "invalid", + update: { + ...this.wizard, + providerModel: target.value, + errors: {}, + }, + status: this.valid ? "valid" : "invalid", }); } - validator() { - const radios = Array.from(this.form.querySelectorAll('input[type="radio"]')); - const chosen = radios.find( - (radio: Element) => radio instanceof HTMLInputElement && radio.checked, - ); - return !!chosen; - } - renderProvider(type: LocalTypeCreate) { const method = this.wizard.providerModel; diff --git a/web/src/admin/applications/wizard/commit/ak-application-wizard-commit-application.ts b/web/src/admin/applications/wizard/commit/ak-application-wizard-commit-application.ts index aa21bd073..2258aa7b2 100644 --- a/web/src/admin/applications/wizard/commit/ak-application-wizard-commit-application.ts +++ b/web/src/admin/applications/wizard/commit/ak-application-wizard-commit-application.ts @@ -18,12 +18,14 @@ import PFTitle from "@patternfly/patternfly/components/Title/title.css"; import PFBullseye from "@patternfly/patternfly/layouts/Bullseye/bullseye.css"; import { - ApplicationRequest, + type ApplicationRequest, CoreApi, - TransactionApplicationRequest, - TransactionApplicationResponse, + type ModelRequest, + type TransactionApplicationRequest, + type TransactionApplicationResponse, + ValidationError, + ValidationErrorFromJSON, } from "@goauthentik/api"; -import type { ModelRequest } from "@goauthentik/api"; import BasePanel from "../BasePanel"; import providerModelsList from "../auth-method-choice/ak-application-wizard-authentication-method-choice.choices"; @@ -88,7 +90,7 @@ export class ApplicationWizardCommitApplication extends BasePanel { commitState: State = idleState; @state() - errors: string[] = []; + errors?: ValidationError; response?: TransactionApplicationResponse; @@ -121,27 +123,10 @@ export class ApplicationWizardCommitApplication extends BasePanel { } } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - decodeErrors(body: Record) { - const spaceify = (src: Record) => - Object.values(src).map((msg) => `\u00a0\u00a0\u00a0\u00a0${msg}`); - - let errs: string[] = []; - if (body["app"] !== undefined) { - errs = [...errs, msg("In the Application:"), ...spaceify(body["app"])]; - } - if (body["provider"] !== undefined) { - errs = [...errs, msg("In the Provider:"), ...spaceify(body["provider"])]; - } - console.log(body, errs); - return errs; - } - async send( data: TransactionApplicationRequest, ): Promise { - this.errors = []; - + this.errors = undefined; new CoreApi(DEFAULT_CONFIG) .coreTransactionalApplicationsUpdate({ transactionApplicationRequest: data, @@ -153,18 +138,57 @@ export class ApplicationWizardCommitApplication extends BasePanel { this.commitState = successState; }) // eslint-disable-next-line @typescript-eslint/no-explicit-any - .catch((resolution: any) => { - resolution.response.json().then( - // eslint-disable-next-line @typescript-eslint/no-explicit-any - (body: Record) => { - this.errors = this.decodeErrors(body); + .catch(async (resolution: any) => { + const errors = (this.errors = ValidationErrorFromJSON( + await resolution.response.json(), + )); + this.dispatchWizardUpdate({ + update: { + ...this.wizard, + errors, }, - ); + status: "failed", + }); this.commitState = errorState; }); } - render(): TemplateResult { + renderErrors(errors?: ValidationError) { + if (!errors) { + return nothing; + } + + const navTo = (step: number) => () => + this.dispatchCustomEvent("ak-wizard-nav", { + command: "goto", + step, + }); + + if (errors.app) { + return html`

${msg("There was an error in the application.")}

+

${msg("Review the application.")}

`; + } + if (errors.provider) { + return html`

${msg("There was an error in the provider.")}

+

${msg("Review the provider.")}

`; + } + if (errors.detail) { + return html`

${msg("There was an error")}: ${errors.detail}

`; + } + if ((errors?.nonFieldErrors ?? []).length > 0) { + return html`

$(msg("There was an error")}:

+
    + ${(errors.nonFieldErrors ?? []).map((e: string) => html`
  • ${e}
  • `)} +
`; + } + return html`

+ ${msg( + "There was an error creating the application, but no error message was sent. Please review the server logs.", + )} +

`; + } + + render() { const icon = classMap( this.commitState.icon.reduce((acc, icon) => ({ ...acc, [icon]: true }), {}), ); @@ -184,13 +208,7 @@ export class ApplicationWizardCommitApplication extends BasePanel { > ${this.commitState.label} - ${this.errors.length > 0 - ? html`
    - ${this.errors.map( - (msg) => html`
  • ${msg}
  • `, - )} -
` - : nothing} + ${this.renderErrors(this.errors)}
diff --git a/web/src/admin/applications/wizard/methods/BaseProviderPanel.ts b/web/src/admin/applications/wizard/methods/BaseProviderPanel.ts index ce60213e1..a8044c981 100644 --- a/web/src/admin/applications/wizard/methods/BaseProviderPanel.ts +++ b/web/src/admin/applications/wizard/methods/BaseProviderPanel.ts @@ -1,26 +1,19 @@ import BasePanel from "../BasePanel"; export class ApplicationWizardProviderPageBase extends BasePanel { - handleChange(ev: InputEvent) { - if (!ev.target) { - console.warn(`Received event with no target: ${ev}`); - return; + handleChange(_ev: InputEvent) { + const formValues = this.formValues; + if (!formValues) { + throw new Error("No provider values on form?"); } - const target = ev.target as HTMLInputElement; - const value = target.type === "checkbox" ? target.checked : target.value; this.dispatchWizardUpdate({ update: { - provider: { - [target.name]: value, - }, + ...this.wizard, + provider: formValues, }, - status: this.form.checkValidity() ? "valid" : "invalid", + status: this.valid ? "valid" : "invalid", }); } - - validator() { - return this.form.reportValidity(); - } } export default ApplicationWizardProviderPageBase; diff --git a/web/src/admin/applications/wizard/methods/ldap/ak-application-wizard-authentication-by-ldap.ts b/web/src/admin/applications/wizard/methods/ldap/ak-application-wizard-authentication-by-ldap.ts index 5b23e06b7..be17d7849 100644 --- a/web/src/admin/applications/wizard/methods/ldap/ak-application-wizard-authentication-by-ldap.ts +++ b/web/src/admin/applications/wizard/methods/ldap/ak-application-wizard-authentication-by-ldap.ts @@ -1,3 +1,4 @@ +import "@goauthentik/admin/applications/wizard/ak-wizard-title"; import "@goauthentik/admin/common/ak-core-group-search"; import "@goauthentik/admin/common/ak-crypto-certificate-search"; import "@goauthentik/admin/common/ak-flow-search/ak-tenanted-flow-search"; @@ -34,112 +35,132 @@ import { export class ApplicationWizardApplicationDetails extends WithTenantConfig(BaseProviderPanel) { render() { const provider = this.wizard.provider as LDAPProvider | undefined; + const errors = this.wizard.errors.provider; - return html` - - - - ${msg("Configure LDAP Provider")} + + -

${msg("Flow used for users to authenticate.")}

-
+ help=${msg("Method's display Name.")} + > - - + +

+ ${msg("Flow used for users to authenticate.")} +

+
+ + -

${groupHelp}

-
+ .errorMessages=${errors?.searchGroup ?? []} + > + +

${groupHelp}

+ - - + + - - + + - - + + - - ${msg("Protocol settings")} -
- - - - - + ${msg("Protocol settings")} +
+ - -

${cryptoCertificateHelp}

- +
- + + + +

${cryptoCertificateHelp}

+
- + - -
- - `; + + + +
+
+ `; } } diff --git a/web/src/admin/applications/wizard/methods/oauth/ak-application-wizard-authentication-by-oauth.ts b/web/src/admin/applications/wizard/methods/oauth/ak-application-wizard-authentication-by-oauth.ts index 62893a6af..d9e23e4a2 100644 --- a/web/src/admin/applications/wizard/methods/oauth/ak-application-wizard-authentication-by-oauth.ts +++ b/web/src/admin/applications/wizard/methods/oauth/ak-application-wizard-authentication-by-oauth.ts @@ -1,3 +1,4 @@ +import "@goauthentik/admin/applications/wizard/ak-wizard-title"; import "@goauthentik/admin/common/ak-crypto-certificate-search"; import "@goauthentik/admin/common/ak-flow-search/ak-tenanted-flow-search"; import { @@ -27,10 +28,10 @@ import { PropertymappingsApi, SourcesApi, } from "@goauthentik/api"; -import type { - OAuth2Provider, - PaginatedOAuthSourceList, - PaginatedScopeMappingList, +import { + type OAuth2Provider, + type PaginatedOAuthSourceList, + type PaginatedScopeMappingList, } from "@goauthentik/api"; import BaseProviderPanel from "../BaseProviderPanel"; @@ -38,7 +39,7 @@ import BaseProviderPanel from "../BaseProviderPanel"; @customElement("ak-application-wizard-authentication-by-oauth") export class ApplicationWizardAuthenticationByOauth extends BaseProviderPanel { @state() - showClientSecret = false; + showClientSecret = true; @state() propertyMappings?: PaginatedScopeMappingList; @@ -68,234 +69,254 @@ export class ApplicationWizardAuthenticationByOauth extends BaseProviderPanel { render() { const provider = this.wizard.provider as OAuth2Provider | undefined; + const errors = this.wizard.errors.provider; - return html`
- - - - ${msg("Configure OAuth2/OpenId Provider")} + + -

- ${msg("Flow used when a user access this provider and is not authenticated.")} -

-
+ > - - -

- ${msg("Flow used when authorizing this provider.")} -

-
- - - ${msg("Protocol settings")} -
- + ) => { - this.showClientSecret = ev.detail.value !== ClientTypeEnum.Public; - }} - .options=${clientTypeOptions} - > - - - +

+ ${msg( + "Flow used when a user access this provider and is not authenticated.", + )} +

+ + + -
+ > +

+ ${msg("Flow used when authorizing this provider.")} +

+ - - - - - - - - + ${msg("Protocol settings")} +
+ ) => { + this.showClientSecret = ev.detail.value !== ClientTypeEnum.Public; + }} + .options=${clientTypeOptions} > - -

${msg("Key used to sign the tokens.")}

- -
- + - - ${msg("Advanced protocol settings")} -
- - ${msg("Configure how long access codes are valid for.")} + + + + + + + + + + + + +

+ ${msg("Key used to sign the tokens.")}

- `} - > -
+ +
+
- - ${msg("Configure how long access tokens are valid for.")} + + ${msg("Advanced protocol settings")} +
+ + ${msg("Configure how long access codes are valid for.")} +

+ `} + > +
+ + + ${msg("Configure how long access tokens are valid for.")} +

+ `} + > +
+ + + ${msg("Configure how long refresh tokens are valid for.")} +

+ `} + > +
+ + + +

+ ${msg( + "Select which scopes can be used by the client. The client still has to specify the scope to access the data.", + )}

- `} - > - - - - ${msg("Configure how long refresh tokens are valid for.")} +

+ ${msg("Hold control/command to select multiple items.")}

- `} - > -
+
- - + ${this.oauthSources?.results.map((source) => { + const selected = (provider?.jwksSources || []).some((su) => { + return su == source.pk; }); - } - return html``; - })} - -

- ${msg( - "Select which scopes can be used by the client. The client still has to specify the scope to access the data.", - )} -

-

- ${msg("Hold control/command to select multiple items.")} -

-
- - - - - - -
-
- - - ${msg("Machine-to-Machine authentication settings")} -
- - -

- ${msg( - "JWTs signed by certificates configured in the selected sources can be used to authenticate to this provider.", - )} -

-

- ${msg("Hold control/command to select multiple items.")} -

-
-
-
- `; + return html``; + })} + +

+ ${msg( + "JWTs signed by certificates configured in the selected sources can be used to authenticate to this provider.", + )} +

+

+ ${msg("Hold control/command to select multiple items.")} +

+
+
+
+ `; } } diff --git a/web/src/admin/applications/wizard/methods/proxy/AuthenticationByProxyPage.ts b/web/src/admin/applications/wizard/methods/proxy/AuthenticationByProxyPage.ts index 4b32fe2d7..90d0f7580 100644 --- a/web/src/admin/applications/wizard/methods/proxy/AuthenticationByProxyPage.ts +++ b/web/src/admin/applications/wizard/methods/proxy/AuthenticationByProxyPage.ts @@ -1,3 +1,4 @@ +import "@goauthentik/admin/applications/wizard/ak-wizard-title"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { first } from "@goauthentik/common/utils"; import "@goauthentik/components/ak-switch-input"; @@ -61,11 +62,11 @@ export class AkTypeProxyApplicationWizardPage extends BaseProviderPanel { return nothing; } - renderProxyMode() { - return html`

This space intentionally left blank

`; + renderProxyMode(): TemplateResult { + throw new Error("Must be implemented in a child class."); } - renderHttpBasic(): TemplateResult { + renderHttpBasic() { return html``; } + scopeMappingConfiguration(provider?: ProxyProvider) { + const propertyMappings = this.propertyMappings?.results ?? []; + + const defaultScopes = () => + propertyMappings + .filter((scope) => !(scope?.managed ?? "").startsWith("goauthentik.io/providers")) + .map((pm) => pm.pk); + + const configuredScopes = (providerMappings: string[]) => + propertyMappings.map((scope) => scope.pk).filter((pk) => providerMappings.includes(pk)); + + const scopeValues = provider?.propertyMappings + ? configuredScopes(provider?.propertyMappings ?? []) + : defaultScopes(); + + const scopePairs = propertyMappings.map((scope) => [scope.pk, scope.name]); + + return { scopePairs, scopeValues }; + } + render() { - return html`
- ${this.renderModeDescription()} - + const errors = this.wizard.errors.provider; + const { scopePairs, scopeValues } = this.scopeMappingConfiguration(this.instance); - - ${msg("Configure Proxy Provider")} + + ${this.renderModeDescription()} + -

- ${msg("Flow used when a user access this provider and is not authenticated.")} -

-
+ .errorMessages=${errors?.name ?? []} + label=${msg("Name")} + > - - -

- ${msg("Flow used when authorizing this provider.")} -

-
+ + +

+ ${msg( + "Flow used when a user access this provider and is not authenticated.", + )} +

+
- ${this.renderProxyMode()} + + +

+ ${msg("Flow used when authorizing this provider.")} +

+
- + ${this.renderProxyMode()} - - ${msg("Advanced protocol settings")} -
- - - + - - + ${this.oauthSources?.results.map((source) => { + const selected = (this.instance?.jwksSources || []).some( (su) => { - return su == scope.pk; + return su == source.pk; }, ); - return html``; })} - -

- ${msg("Additional scope mappings, which are passed to the proxy.")} -

-

- ${msg("Hold control/command to select multiple items.")} -

-
- - + +

${msg( - "Regular expressions for which authentication is not required. Each new line is interpreted as a new expression.", + "JWTs signed by certificates configured in the selected sources can be used to authenticate to this provider.", )}

- ${msg( - "When using proxy or forward auth (single application) mode, the requested URL Path is checked against the regular expressions. When using forward auth (domain mode), the full requested URL including scheme and host is matched against the regular expressions.", - )} -

`} - > -
-
-
- - ${msg("Authentication settings")} -
- - - { - const el = ev.target as HTMLInputElement; - this.showHttpBasic = el.checked; - }} - label=${msg("Send HTTP-Basic Authentication")} - help=${msg( - "Send a custom HTTP-Basic Authentication header based on values from authentik.", - )} - > - - ${this.showHttpBasic ? this.renderHttpBasic() : html``} - - - -

- ${msg( - "JWTs signed by certificates configured in the selected sources can be used to authenticate to this provider.", - )} -

-

- ${msg("Hold control/command to select multiple items.")} -

-
-
-
-
`; + ${msg("Hold control/command to select multiple items.")} +

+ +
+ + `; } } diff --git a/web/src/admin/applications/wizard/methods/proxy/ak-application-wizard-authentication-for-forward-domain-proxy.ts b/web/src/admin/applications/wizard/methods/proxy/ak-application-wizard-authentication-for-forward-domain-proxy.ts index e794cd7d4..63510ad11 100644 --- a/web/src/admin/applications/wizard/methods/proxy/ak-application-wizard-authentication-for-forward-domain-proxy.ts +++ b/web/src/admin/applications/wizard/methods/proxy/ak-application-wizard-authentication-for-forward-domain-proxy.ts @@ -5,6 +5,8 @@ import { customElement } from "@lit/reactive-element/decorators.js"; import { html } from "lit"; import { ifDefined } from "lit/directives/if-defined.js"; +import { ProxyProvider } from "@goauthentik/api"; + import AkTypeProxyApplicationWizardPage from "./AuthenticationByProxyPage"; @customElement("ak-application-wizard-authentication-for-forward-proxy-domain") @@ -28,11 +30,15 @@ export class AkForwardDomainProxyApplicationWizardPage extends AkTypeProxyApplic } renderProxyMode() { + const provider = this.wizard.provider as ProxyProvider | undefined; + const errors = this.wizard.errors.provider; + return html` diff --git a/web/src/admin/applications/wizard/methods/proxy/ak-application-wizard-authentication-for-single-forward-proxy.ts b/web/src/admin/applications/wizard/methods/proxy/ak-application-wizard-authentication-for-single-forward-proxy.ts index 0840c698f..5680d1e59 100644 --- a/web/src/admin/applications/wizard/methods/proxy/ak-application-wizard-authentication-for-single-forward-proxy.ts +++ b/web/src/admin/applications/wizard/methods/proxy/ak-application-wizard-authentication-for-single-forward-proxy.ts @@ -5,6 +5,8 @@ import { customElement } from "@lit/reactive-element/decorators.js"; import { html } from "lit"; import { ifDefined } from "lit/directives/if-defined.js"; +import { ProxyProvider } from "@goauthentik/api"; + import AkTypeProxyApplicationWizardPage from "./AuthenticationByProxyPage"; @customElement("ak-application-wizard-authentication-for-single-forward-proxy") @@ -21,11 +23,15 @@ export class AkForwardSingleProxyApplicationWizardPage extends AkTypeProxyApplic } renderProxyMode() { + const provider = this.wizard.provider as ProxyProvider | undefined; + const errors = this.wizard.errors.provider; + return html` - - - - - ${msg("Configure Radius Provider")} +
+ -

${msg("Flow used for users to authenticate.")}

- + > +
- - ${msg("Protocol settings")} -
- + - +

+ ${msg("Flow used for users to authenticate.")} +

+ + + + ${msg("Protocol settings")} +
+ + -
-
- `; + >
+
+
+ `; } } diff --git a/web/src/admin/applications/wizard/methods/saml/ak-application-wizard-authentication-by-saml-configuration.ts b/web/src/admin/applications/wizard/methods/saml/ak-application-wizard-authentication-by-saml-configuration.ts index f25c995ef..68041c7c1 100644 --- a/web/src/admin/applications/wizard/methods/saml/ak-application-wizard-authentication-by-saml-configuration.ts +++ b/web/src/admin/applications/wizard/methods/saml/ak-application-wizard-authentication-by-saml-configuration.ts @@ -1,7 +1,10 @@ +import "@goauthentik/admin/applications/wizard/ak-wizard-title"; +import "@goauthentik/admin/applications/wizard/ak-wizard-title"; import "@goauthentik/admin/common/ak-core-group-search"; import "@goauthentik/admin/common/ak-crypto-certificate-search"; import "@goauthentik/admin/common/ak-flow-search/ak-tenanted-flow-search"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; +import "@goauthentik/components/ak-multi-select"; import "@goauthentik/components/ak-number-input"; import "@goauthentik/components/ak-radio-input"; import "@goauthentik/components/ak-switch-input"; @@ -10,7 +13,7 @@ import "@goauthentik/elements/forms/FormGroup"; import "@goauthentik/elements/forms/HorizontalFormElement"; import { msg } from "@lit/localize"; -import { customElement } from "@lit/reactive-element/decorators/custom-element.js"; +import { customElement, state } from "@lit/reactive-element/decorators.js"; import { html } from "lit"; import { ifDefined } from "lit/directives/if-defined.js"; @@ -27,9 +30,11 @@ import { signatureAlgorithmOptions, spBindingOptions, } from "./SamlProviderOptions"; +import "./saml-property-mappings-search"; @customElement("ak-application-wizard-authentication-by-saml-configuration") export class ApplicationWizardProviderSamlConfiguration extends BaseProviderPanel { + @state() propertyMappings?: PaginatedSAMLPropertyMappingList; constructor() { @@ -43,207 +48,229 @@ export class ApplicationWizardProviderSamlConfiguration extends BaseProviderPane }); } + propertyMappingConfiguration(provider?: SAMLProvider) { + const propertyMappings = this.propertyMappings?.results ?? []; + + const configuredMappings = (providerMappings: string[]) => + propertyMappings.map((pm) => pm.pk).filter((pmpk) => providerMappings.includes(pmpk)); + + const managedMappings = () => + propertyMappings + .filter((pm) => (pm?.managed ?? "").startsWith("goauthentik.io/providers/saml")) + .map((pm) => pm.pk); + + const pmValues = provider?.propertyMappings + ? configuredMappings(provider?.propertyMappings ?? []) + : managedMappings(); + + const propertyPairs = propertyMappings.map((pm) => [pm.pk, pm.name]); + + return { pmValues, propertyPairs }; + } + render() { const provider = this.wizard.provider as SAMLProvider | undefined; + const errors = this.wizard.errors.provider; - return html`
- + const { pmValues, propertyPairs } = this.propertyMappingConfiguration(provider); - - ${msg("Configure SAML Provider")} + + -

- ${msg("Flow used when a user access this provider and is not authenticated.")} -

-
+ label=${msg("Name")} + .errorMessages=${errors?.name ?? []} + > - - -

- ${msg("Flow used when authorizing this provider.")} -

-
- - - ${msg("Protocol settings")} -
- + - - - - +

+ ${msg( + "Flow used when a user access this provider and is not authenticated.", )} - > - +

+ - -
-
+ + +

+ ${msg("Flow used when authorizing this provider.")} +

+
- - ${msg("Advanced protocol settings")} -
- - -

- ${msg( - "Certificate used to sign outgoing Responses going to the Service Provider.", + + ${msg("Protocol settings")} +

+ + + + + - + > + - - -

- ${msg( - "When selected, incoming assertion's Signatures will be validated against this certificate. To allow unsigned Requests, leave on default.", - )} -

-
+ +
+ - - -

- ${msg("Hold control/command to select multiple items.")} -

-
+ + ${msg("Advanced protocol settings")} +
+ + +

+ ${msg( + "Certificate used to sign outgoing Responses going to the Service Provider.", + )} +

+
- - + +

+ ${msg( + "When selected, incoming assertion's Signatures will be validated against this certificate. To allow unsigned Requests, leave on default.", + )} +

+
+ + + ${msg("Property mappings used for user mapping.")} +

+

+ ${msg("Hold control/command to select multiple items.")} +

`} + >
+ + -

- ${msg( - "Configure how the NameID value will be created. When left empty, the NameIDPolicy of the incoming request will be respected.", + > + +

+ ${msg( + "Configure how the NameID value will be created. When left empty, the NameIDPolicy of the incoming request will be respected.", + )} +

+
+ + - + .errorMessages=${errors?.assertionValidNotBefore ?? []} + > - + - + - + + - - - - - -
-
- `; + + +
+
+ `; } } diff --git a/web/src/admin/applications/wizard/methods/saml/ak-application-wizard-authentication-by-saml-import.ts b/web/src/admin/applications/wizard/methods/saml/ak-application-wizard-authentication-by-saml-import.ts deleted file mode 100644 index 924aead76..000000000 --- a/web/src/admin/applications/wizard/methods/saml/ak-application-wizard-authentication-by-saml-import.ts +++ /dev/null @@ -1,81 +0,0 @@ -import "@goauthentik/admin/common/ak-flow-search/ak-flow-search-no-default"; -import "@goauthentik/components/ak-file-input"; -import { AkFileInput } from "@goauthentik/components/ak-file-input"; -import "@goauthentik/components/ak-text-input"; -import "@goauthentik/elements/forms/HorizontalFormElement"; - -import { msg } from "@lit/localize"; -import { customElement } from "@lit/reactive-element/decorators/custom-element.js"; -import { html } from "lit"; -import { query } from "lit/decorators.js"; -import { ifDefined } from "lit/directives/if-defined.js"; - -import { - FlowsInstancesListDesignationEnum, - ProvidersSamlImportMetadataCreateRequest, -} from "@goauthentik/api"; - -import BaseProviderPanel from "../BaseProviderPanel"; - -@customElement("ak-application-wizard-authentication-by-saml-import") -export class ApplicationWizardProviderSamlImport extends BaseProviderPanel { - @query('ak-file-input[name="metadata"]') - fileInput!: AkFileInput; - - handleChange(ev: InputEvent) { - if (!ev.target) { - console.warn(`Received event with no target: ${ev}`); - return; - } - const target = ev.target as HTMLInputElement; - if (target.type === "file") { - const file = this.fileInput.files?.[0] ?? null; - if (file) { - this.dispatchWizardUpdate({ - update: { - provider: { - file, - }, - }, - status: this.form.checkValidity() ? "valid" : "invalid", - }); - } - return; - } - super.handleChange(ev); - } - - render() { - const provider = this.wizard.provider as - | ProvidersSamlImportMetadataCreateRequest - | undefined; - - return html`
- - - - -

- ${msg("Flow used when authorizing this provider.")} -

-
- - -
`; - } -} - -export default ApplicationWizardProviderSamlImport; diff --git a/web/src/admin/applications/wizard/methods/scim/ak-application-wizard-authentication-by-scim.ts b/web/src/admin/applications/wizard/methods/scim/ak-application-wizard-authentication-by-scim.ts index 493c740d1..832e7348a 100644 --- a/web/src/admin/applications/wizard/methods/scim/ak-application-wizard-authentication-by-scim.ts +++ b/web/src/admin/applications/wizard/methods/scim/ak-application-wizard-authentication-by-scim.ts @@ -1,7 +1,10 @@ +import "@goauthentik/admin/applications/wizard/ak-wizard-title"; +import "@goauthentik/admin/common/ak-core-group-search"; import "@goauthentik/admin/common/ak-crypto-certificate-search"; import "@goauthentik/admin/common/ak-flow-search/ak-tenanted-flow-search"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { first } from "@goauthentik/common/utils"; +import "@goauthentik/components/ak-multi-select"; import "@goauthentik/components/ak-switch-input"; import "@goauthentik/components/ak-text-input"; import "@goauthentik/elements/forms/FormGroup"; @@ -12,14 +15,7 @@ import { customElement, state } from "@lit/reactive-element/decorators.js"; import { html } from "lit"; import { ifDefined } from "lit/directives/if-defined.js"; -import { - CoreApi, - CoreGroupsListRequest, - type Group, - PaginatedSCIMMappingList, - PropertymappingsApi, - type SCIMProvider, -} from "@goauthentik/api"; +import { PaginatedSCIMMappingList, PropertymappingsApi, type SCIMProvider } from "@goauthentik/api"; import BaseProviderPanel from "../BaseProviderPanel"; @@ -31,158 +27,129 @@ export class ApplicationWizardAuthenticationBySCIM extends BaseProviderPanel { constructor() { super(); new PropertymappingsApi(DEFAULT_CONFIG) - .propertymappingsScopeList({ - ordering: "scope_name", + .propertymappingsScimList({ + ordering: "managed", }) .then((propertyMappings: PaginatedSCIMMappingList) => { this.propertyMappings = propertyMappings; }); } + propertyMappingConfiguration(provider?: SCIMProvider) { + const propertyMappings = this.propertyMappings?.results ?? []; + + const configuredMappings = (providerMappings: string[]) => + propertyMappings.map((pm) => pm.pk).filter((pmpk) => providerMappings.includes(pmpk)); + + const managedMappings = (key: string) => + propertyMappings + .filter((pm) => pm.managed === `goauthentik.io/providers/scim/${key}`) + .map((pm) => pm.pk); + + const pmUserValues = provider?.propertyMappings + ? configuredMappings(provider?.propertyMappings ?? []) + : managedMappings("user"); + + const pmGroupValues = provider?.propertyMappingsGroup + ? configuredMappings(provider?.propertyMappingsGroup ?? []) + : managedMappings("group"); + + const propertyPairs = propertyMappings.map((pm) => [pm.pk, pm.name]); + + return { pmUserValues, pmGroupValues, propertyPairs }; + } + render() { const provider = this.wizard.provider as SCIMProvider | undefined; + const errors = this.wizard.errors.provider; - return html`
- - - ${msg("Protocol settings")} -
- - - - -
-
- - ${msg("User filtering")} -
- - - => { - const args: CoreGroupsListRequest = { - ordering: "name", - }; - if (query !== undefined) { - args.search = query; - } - const groups = await new CoreApi(DEFAULT_CONFIG).coreGroupsList( - args, - ); - return groups.results; - }} - .renderElement=${(group: Group): string => { - return group.name; - }} - .value=${(group: Group | undefined): string | undefined => { - return group ? group.pk : undefined; - }} - .selected=${(group: Group): boolean => { - return group.pk === provider?.filterGroup; - }} - ?blankable=${true} + const { pmUserValues, pmGroupValues, propertyPairs } = + this.propertyMappingConfiguration(provider); + + return html`${msg("Configure SCIM Provider")} + + + + ${msg("Protocol settings")} +
+ - -

- ${msg("Only sync users within the selected group.")} -

- -
-
- - ${msg("Attribute mapping")} -
- - -

- ${msg("Property mappings used to user mapping.")} -

-

- ${msg("Hold control/command to select multiple items.")} -

-
- - -

- ${msg("Property mappings used to group creation.")} -

-

- ${msg("Hold control/command to select multiple items.")} -

-
-
-
- `; + + + +
+
+ + ${msg("User filtering")} +
+ + + +

+ ${msg("Only sync users within the selected group.")} +

+
+
+
+ + ${msg("Attribute mapping")} +
+ + ${msg("Property mappings used for user mapping.")} +

+

+ ${msg("Hold control/command to select multiple items.")} +

`} + >
+ + ${msg("Property mappings used for group creation.")} +

+

+ ${msg("Hold control/command to select multiple items.")} +

`} + >
+
+
+ `; } } diff --git a/web/src/admin/applications/wizard/steps.ts b/web/src/admin/applications/wizard/steps.ts index 451367bf8..fc427ed08 100644 --- a/web/src/admin/applications/wizard/steps.ts +++ b/web/src/admin/applications/wizard/steps.ts @@ -15,6 +15,12 @@ import "./commit/ak-application-wizard-commit-application"; import "./methods/ak-application-wizard-authentication-method"; import { ApplicationStep as ApplicationStepType } from "./types"; +/** + * In the current implementation, all of the child forms have access to the wizard's + * global context, into which all data is written, and which is updated by events + * flowing into the top-level orchestrator. + */ + class ApplicationStep implements ApplicationStepType { id = "application"; label = "Application Details"; diff --git a/web/src/admin/applications/wizard/stories/ak-application-context-display-for-test.ts b/web/src/admin/applications/wizard/stories/ak-application-context-display-for-test.ts index fa418199e..c21eb4199 100644 --- a/web/src/admin/applications/wizard/stories/ak-application-context-display-for-test.ts +++ b/web/src/admin/applications/wizard/stories/ak-application-context-display-for-test.ts @@ -3,7 +3,7 @@ import { customElement } from "@lit/reactive-element/decorators/custom-element.j import { state } from "@lit/reactive-element/decorators/state.js"; import { LitElement, html } from "lit"; -import applicationWizardContext from "../ContextIdentity"; +import { applicationWizardContext } from "../ContextIdentity"; import type { ApplicationWizardState } from "../types"; @customElement("ak-application-context-display-for-test") diff --git a/web/src/admin/applications/wizard/types.ts b/web/src/admin/applications/wizard/types.ts index 0ebe7aa8a..a6e86cac1 100644 --- a/web/src/admin/applications/wizard/types.ts +++ b/web/src/admin/applications/wizard/types.ts @@ -9,6 +9,7 @@ import { type RadiusProviderRequest, type SAMLProviderRequest, type SCIMProviderRequest, + type ValidationError, } from "@goauthentik/api"; export type OneOfProvider = @@ -24,12 +25,13 @@ export interface ApplicationWizardState { providerModel: string; app: Partial; provider: OneOfProvider; + errors: ValidationError; } type StatusType = "invalid" | "valid" | "submitted" | "failed"; export type ApplicationWizardStateUpdate = { - update?: Partial; + update?: ApplicationWizardState; status?: StatusType; }; diff --git a/web/src/admin/events/EventListPage.ts b/web/src/admin/events/EventListPage.ts index 4d42e8c74..7ba75da8f 100644 --- a/web/src/admin/events/EventListPage.ts +++ b/web/src/admin/events/EventListPage.ts @@ -1,3 +1,4 @@ +import "@goauthentik/admin/events/EventVolumeChart"; import { EventGeo } from "@goauthentik/admin/events/utils"; import { DEFAULT_CONFIG } from "@goauthentik/common/api/config"; import { EventWithContext } from "@goauthentik/common/events"; @@ -10,7 +11,7 @@ import { TablePage } from "@goauthentik/elements/table/TablePage"; import "@patternfly/elements/pf-tooltip/pf-tooltip.js"; import { msg, str } from "@lit/localize"; -import { TemplateResult, html } from "lit"; +import { CSSResult, TemplateResult, css, html } from "lit"; import { customElement, property } from "lit/decorators.js"; import { Event, EventsApi } from "@goauthentik/api"; @@ -35,6 +36,14 @@ export class EventListPage extends TablePage { @property() order = "-created"; + static get styles(): CSSResult[] { + return super.styles.concat(css` + .pf-m-no-padding-bottom { + padding-bottom: 0; + } + `); + } + async apiEndpoint(page: number): Promise> { return new EventsApi(DEFAULT_CONFIG).eventsEventsList({ ordering: this.order, @@ -55,6 +64,19 @@ export class EventListPage extends TablePage { ]; } + renderSectionBefore(): TemplateResult { + return html` +
+ +
+ `; + } + row(item: EventWithContext): TemplateResult[] { return [ html`
${actionToLabel(item.action)}
diff --git a/web/src/admin/events/EventVolumeChart.ts b/web/src/admin/events/EventVolumeChart.ts new file mode 100644 index 000000000..da1710af0 --- /dev/null +++ b/web/src/admin/events/EventVolumeChart.ts @@ -0,0 +1,63 @@ +import { DEFAULT_CONFIG } from "@goauthentik/app/common/api/config"; +import { AKChart } from "@goauthentik/app/elements/charts/Chart"; +import { ChartData } from "chart.js"; + +import { msg } from "@lit/localize"; +import { CSSResult, TemplateResult, css, html } from "lit"; +import { customElement, property } from "lit/decorators.js"; + +import PFCard from "@patternfly/patternfly/components/Card/card.css"; + +import { Coordinate, EventsApi, EventsEventsListRequest } from "@goauthentik/api"; + +@customElement("ak-events-volume-chart") +export class EventVolumeChart extends AKChart { + _query?: EventsEventsListRequest; + + @property({ attribute: false }) + set query(value: EventsEventsListRequest | undefined) { + this._query = value; + this.refreshHandler(); + } + + static get styles(): CSSResult[] { + return super.styles.concat( + PFCard, + css` + .pf-c-card__body { + height: 12rem; + } + `, + ); + } + + apiRequest(): Promise { + return new EventsApi(DEFAULT_CONFIG).eventsEventsVolumeList(this._query); + } + + getChartData(data: Coordinate[]): ChartData { + return { + datasets: [ + { + label: msg("Events"), + backgroundColor: "rgba(189, 229, 184, .5)", + spanGaps: true, + data: + data.map((cord) => { + return { + x: cord.xCord || 0, + y: cord.yCord || 0, + }; + }) || [], + }, + ], + }; + } + + render(): TemplateResult { + return html`
+
${msg("Event volume")}
+
${super.render()}
+
`; + } +} diff --git a/web/src/common/merge.ts b/web/src/common/merge.ts deleted file mode 100644 index 4e60e856c..000000000 --- a/web/src/common/merge.ts +++ /dev/null @@ -1,120 +0,0 @@ -/** Taken from: https://github.com/zellwk/javascript/tree/master - * - * We have added some typescript annotations, but this is such a rich feature with deep nesting - * we'll just have to watch it closely for any issues. So far there don't seem to be any. - * - */ - -function objectType(value: T) { - return Object.prototype.toString.call(value); -} - -// Creates a deep clone for each value -// eslint-disable-next-line @typescript-eslint/no-explicit-any -function cloneDescriptorValue(value: any) { - // Arrays - if (objectType(value) === "[object Array]") { - const array = []; - for (let v of value) { - v = cloneDescriptorValue(v); - array.push(v); - } - return array; - } - - // Objects - if (objectType(value) === "[object Object]") { - const obj = {}; - const props = Object.keys(value); - for (const prop of props) { - const descriptor = Object.getOwnPropertyDescriptor(value, prop); - if (!descriptor) { - continue; - } - - if (descriptor.value) { - descriptor.value = cloneDescriptorValue(descriptor.value); - } - Object.defineProperty(obj, prop, descriptor); - } - return obj; - } - - // Other Types of Objects - if (objectType(value) === "[object Date]") { - return new Date(value.getTime()); - } - - if (objectType(value) === "[object Map]") { - const map = new Map(); - for (const entry of value) { - map.set(entry[0], cloneDescriptorValue(entry[1])); - } - return map; - } - - if (objectType(value) === "[object Set]") { - const set = new Set(); - for (const entry of value.entries()) { - set.add(cloneDescriptorValue(entry[0])); - } - return set; - } - - // Types we don't need to clone or cannot clone. - // Examples: - // - Primitives don't need to clone - // - Functions cannot clone - return value; -} - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -function _merge(output: Record, input: Record) { - const props = Object.keys(input); - - for (const prop of props) { - // Prevents Prototype Pollution - if (prop === "__proto__") continue; - - const descriptor = Object.getOwnPropertyDescriptor(input, prop); - if (!descriptor) { - continue; - } - - const value = descriptor.value; - if (value) descriptor.value = cloneDescriptorValue(value); - - // If don't have prop => Define property - // [ken@goauthentik] Using `hasOwn` is preferable over - // the basic identity test, according to Typescript. - if (!Object.hasOwn(output, prop)) { - Object.defineProperty(output, prop, descriptor); - continue; - } - - // If have prop, but type is not object => Overwrite by redefining property - if (typeof output[prop] !== "object") { - Object.defineProperty(output, prop, descriptor); - continue; - } - - // If have prop, but type is Object => Concat the arrays together. - if (objectType(descriptor.value) === "[object Array]") { - output[prop] = output[prop].concat(descriptor.value); - continue; - } - - // If have prop, but type is Object => Merge. - _merge(output[prop], descriptor.value); - } -} - -export function merge(...sources: Array) { - const result = {}; - for (const source of sources) { - _merge(result, source); - } - return result; -} - -export default merge; diff --git a/web/src/common/utils.ts b/web/src/common/utils.ts index 1ae395b4e..2b88f43dd 100644 --- a/web/src/common/utils.ts +++ b/web/src/common/utils.ts @@ -54,6 +54,13 @@ export function camelToSnake(key: string): string { return result.split(" ").join("_").toLowerCase(); } +const capitalize = (key: string) => (key.length === 0 ? "" : key[0].toUpperCase() + key.slice(1)); + +export function snakeToCamel(key: string) { + const [start, ...rest] = key.split("_"); + return [start, ...rest.map(capitalize)].join(""); +} + export function groupBy(objects: T[], callback: (obj: T) => string): Array<[string, T[]]> { const m = new Map(); objects.forEach((obj) => { diff --git a/web/src/components/HorizontalLightComponent.ts b/web/src/components/HorizontalLightComponent.ts new file mode 100644 index 000000000..7d34c833d --- /dev/null +++ b/web/src/components/HorizontalLightComponent.ts @@ -0,0 +1,72 @@ +import { AKElement } from "@goauthentik/elements/Base"; + +import { TemplateResult, html, nothing } from "lit"; +import { property } from "lit/decorators.js"; + +type HelpType = TemplateResult | typeof nothing; + +export class HorizontalLightComponent extends AKElement { + // Render into the lightDOM. This effectively erases the shadowDOM nature of this component, but + // we're not actually using that and, for the meantime, we need the form handlers to be able to + // find the children of this component. + // + // TODO: This abstraction is wrong; it's putting *more* layers in as a way of managing the + // visual clutter and legibility issues of ak-form-elemental-horizontal and patternfly in + // general. + protected createRenderRoot() { + return this; + } + + @property({ type: String }) + name!: string; + + @property({ type: String }) + label = ""; + + @property({ type: Boolean }) + required = false; + + @property({ type: String }) + help = ""; + + @property({ type: Object }) + bighelp?: TemplateResult | TemplateResult[]; + + @property({ type: Boolean }) + hidden = false; + + @property({ type: Boolean }) + invalid = false; + + @property({ attribute: false }) + errorMessages: string[] = []; + + renderControl() { + throw new Error("Must be implemented in a subclass"); + } + + renderHelp(): HelpType[] { + const bigHelp: HelpType[] = Array.isArray(this.bighelp) + ? this.bighelp + : [this.bighelp ?? nothing]; + return [ + this.help ? html`

${this.help}

` : nothing, + ...bigHelp, + ]; + } + + render() { + // prettier-ignore + return html` + ${this.renderControl()} + ${this.renderHelp()} + `; + } +} diff --git a/web/src/components/ak-multi-select.ts b/web/src/components/ak-multi-select.ts new file mode 100644 index 000000000..9efddd079 --- /dev/null +++ b/web/src/components/ak-multi-select.ts @@ -0,0 +1,150 @@ +import "@goauthentik/app/elements/forms/HorizontalFormElement"; +import { AKElement } from "@goauthentik/elements/Base"; + +import { TemplateResult, css, html, nothing } from "lit"; +import { customElement, property } from "lit/decorators.js"; +import { ifDefined } from "lit/directives/if-defined.js"; +import { map } from "lit/directives/map.js"; +import { Ref, createRef, ref } from "lit/directives/ref.js"; + +import PFForm from "@patternfly/patternfly/components/Form/form.css"; +import PFFormControl from "@patternfly/patternfly/components/FormControl/form-control.css"; +import PFBase from "@patternfly/patternfly/patternfly-base.css"; + +type Pair = [string, string]; + +const selectStyles = css` + select[multiple] { + min-height: 15rem; + } +`; + +/** + * Horizontal layout control with a multi-select. + * + * @part select - The select itself, to override the height specified above. + */ +@customElement("ak-multi-select") +export class AkMultiSelect extends AKElement { + constructor() { + super(); + this.dataset.akControl = "true"; + } + + static get styles() { + return [PFBase, PFForm, PFFormControl, selectStyles]; + } + + /** + * The [name] attribute, which is also distributed to the layout manager and the input control. + */ + @property({ type: String }) + name!: string; + + /** + * The text label to display on the control + */ + @property({ type: String }) + label = ""; + + /** + * The values to be displayed in the select. The format is [Value, Label], where the label is + * what will be displayed. + */ + @property({ attribute: false }) + options: Pair[] = []; + + /** + * If true, at least one object must be selected + */ + @property({ type: Boolean }) + required = false; + + /** + * Supporting a simple help string + */ + @property({ type: String }) + help = ""; + + /** + * For more complex help instructions, provide a template result. + */ + @property({ type: Object }) + bighelp!: TemplateResult | TemplateResult[]; + + /** + * An array of strings representing the objects currently selected. + */ + @property({ type: Array }) + values: string[] = []; + + /** + * Helper accessor for older code + */ + get value() { + return this.values; + } + + /** + * One of two criteria (the other being the data-ak-control flag) that specifies this as a + * control that produces values of specific interest to our REST API. This is our modern + * accessor name. + */ + json() { + return this.values; + } + + renderHelp() { + return [ + this.help ? html`

${this.help}

` : nothing, + this.bighelp ? this.bighelp : nothing, + ]; + } + + handleChange(ev: Event) { + if (ev.type === "change") { + this.values = Array.from(this.selectRef.value!.querySelectorAll("option")) + .filter((option) => option.selected) + .map((option) => option.value); + this.dispatchEvent( + new CustomEvent("ak-select", { + detail: this.values, + composed: true, + bubbles: true, + }), + ); + } + } + + selectRef: Ref = createRef(); + + render() { + return html`
+ + + ${this.renderHelp()} + +
`; + } +} + +export default AkMultiSelect; diff --git a/web/src/components/ak-number-input.ts b/web/src/components/ak-number-input.ts index dcfef1541..65fc10b0e 100644 --- a/web/src/components/ak-number-input.ts +++ b/web/src/components/ak-number-input.ts @@ -1,51 +1,21 @@ -import { AKElement } from "@goauthentik/elements/Base"; - -import { html, nothing } from "lit"; +import { html } from "lit"; import { customElement, property } from "lit/decorators.js"; import { ifDefined } from "lit/directives/if-defined.js"; +import { HorizontalLightComponent } from "./HorizontalLightComponent"; + @customElement("ak-number-input") -export class AkNumberInput extends AKElement { - // Render into the lightDOM. This effectively erases the shadowDOM nature of this component, but - // we're not actually using that and, for the meantime, we need the form handlers to be able to - // find the children of this component. - // - // TODO: This abstraction is wrong; it's putting *more* layers in as a way of managing the - // visual clutter and legibility issues of ak-form-elemental-horizontal and patternfly in - // general. - protected createRenderRoot() { - return this; - } - - @property({ type: String }) - name!: string; - - @property({ type: String }) - label = ""; - +export class AkNumberInput extends HorizontalLightComponent { @property({ type: Number, reflect: true }) value = 0; - @property({ type: Boolean }) - required = false; - - @property({ type: String }) - help = ""; - - render() { - return html` - - ${this.help ? html`

${this.help}

` : nothing} -
`; + />`; } } diff --git a/web/src/components/ak-radio-input.ts b/web/src/components/ak-radio-input.ts index c65b8f1ae..b4899cfc5 100644 --- a/web/src/components/ak-radio-input.ts +++ b/web/src/components/ak-radio-input.ts @@ -1,35 +1,13 @@ -import { AKElement } from "@goauthentik/elements/Base"; import { RadioOption } from "@goauthentik/elements/forms/Radio"; import "@goauthentik/elements/forms/Radio"; import { html, nothing } from "lit"; import { customElement, property } from "lit/decorators.js"; +import { HorizontalLightComponent } from "./HorizontalLightComponent"; + @customElement("ak-radio-input") -export class AkRadioInput extends AKElement { - // Render into the lightDOM. This effectively erases the shadowDOM nature of this component, but - // we're not actually using that and, for the meantime, we need the form handlers to be able to - // find the children of this component. - // - // TODO: This abstraction is wrong; it's putting *more* layers in as a way of managing the - // visual clutter and legibility issues of ak-form-elemental-horizontal and patternfly in - // general. - protected createRenderRoot() { - return this; - } - - @property({ type: String }) - name!: string; - - @property({ type: String }) - label = ""; - - @property({ type: String }) - help = ""; - - @property({ type: Boolean }) - required = false; - +export class AkRadioInput extends HorizontalLightComponent { @property({ type: Object }) value!: T; @@ -37,24 +15,25 @@ export class AkRadioInput extends AKElement { options: RadioOption[] = []; handleInput(ev: CustomEvent) { - this.value = ev.detail.value; + if ("detail" in ev) { + this.value = ev.detail.value; + } } - render() { - return html` - ${this.help.trim() ? html`

${this.help}

` - : nothing} -
`; + : nothing}`; } } diff --git a/web/src/components/ak-slug-input.ts b/web/src/components/ak-slug-input.ts index b4fac3380..161a00c87 100644 --- a/web/src/components/ak-slug-input.ts +++ b/web/src/components/ak-slug-input.ts @@ -1,44 +1,16 @@ import { convertToSlug } from "@goauthentik/common/utils"; -import { AKElement } from "@goauthentik/elements/Base"; -import { TemplateResult, html, nothing } from "lit"; +import { html } from "lit"; import { customElement, property, query } from "lit/decorators.js"; import { ifDefined } from "lit/directives/if-defined.js"; +import { HorizontalLightComponent } from "./HorizontalLightComponent"; + @customElement("ak-slug-input") -export class AkSlugInput extends AKElement { - // Render into the lightDOM. This effectively erases the shadowDOM nature of this component, but - // we're not actually using that and, for the meantime, we need the form handlers to be able to - // find the children of this component. - // - // TODO: This abstraction is wrong; it's putting *more* layers in as a way of managing the - // visual clutter and legibility issues of ak-form-elemental-horizontal and patternfly in - // general. - protected createRenderRoot() { - return this; - } - - @property({ type: String }) - name!: string; - - @property({ type: String }) - label = ""; - +export class AkSlugInput extends HorizontalLightComponent { @property({ type: String, reflect: true }) value = ""; - @property({ type: Boolean }) - required = false; - - @property({ type: String }) - help = ""; - - @property({ type: Boolean }) - hidden = false; - - @property({ type: Object }) - bighelp!: TemplateResult | TemplateResult[]; - @property({ type: String }) source = ""; @@ -59,13 +31,6 @@ export class AkSlugInput extends AKElement { this.input.addEventListener("input", this.handleTouch); } - renderHelp() { - return [ - this.help ? html`

${this.help}

` : nothing, - this.bighelp ? this.bighelp : nothing, - ]; - } - // Do not stop propagation of this event; it must be sent up the tree so that a parent // component, such as a custom forms manager, may receive it. handleTouch(ev: Event) { @@ -150,21 +115,13 @@ export class AkSlugInput extends AKElement { super.disconnectedCallback(); } - render() { - return html` - - ${this.renderHelp()} - `; + />`; } } diff --git a/web/src/components/ak-text-input.ts b/web/src/components/ak-text-input.ts index 2e7a9dd63..545ff9018 100644 --- a/web/src/components/ak-text-input.ts +++ b/web/src/components/ak-text-input.ts @@ -1,65 +1,21 @@ -import { AKElement } from "@goauthentik/elements/Base"; - -import { TemplateResult, html, nothing } from "lit"; +import { html } from "lit"; import { customElement, property } from "lit/decorators.js"; import { ifDefined } from "lit/directives/if-defined.js"; +import { HorizontalLightComponent } from "./HorizontalLightComponent"; + @customElement("ak-text-input") -export class AkTextInput extends AKElement { - // Render into the lightDOM. This effectively erases the shadowDOM nature of this component, but - // we're not actually using that and, for the meantime, we need the form handlers to be able to - // find the children of this component. - // - // TODO: This abstraction is wrong; it's putting *more* layers in as a way of managing the - // visual clutter and legibility issues of ak-form-elemental-horizontal and patternfly in - // general. - protected createRenderRoot() { - return this; - } - - @property({ type: String }) - name!: string; - - @property({ type: String }) - label = ""; - +export class AkTextInput extends HorizontalLightComponent { @property({ type: String, reflect: true }) value = ""; - @property({ type: Boolean }) - required = false; - - @property({ type: String }) - help = ""; - - @property({ type: Boolean }) - hidden = false; - - @property({ type: Object }) - bighelp!: TemplateResult | TemplateResult[]; - - renderHelp() { - return [ - this.help ? html`

${this.help}

` : nothing, - this.bighelp ? this.bighelp : nothing, - ]; - } - - render() { - return html` - - ${this.renderHelp()} - `; + />`; } } diff --git a/web/src/components/ak-textarea-input.ts b/web/src/components/ak-textarea-input.ts index 95b138550..9ca2efc4f 100644 --- a/web/src/components/ak-textarea-input.ts +++ b/web/src/components/ak-textarea-input.ts @@ -1,57 +1,22 @@ -import { AKElement } from "@goauthentik/elements/Base"; - -import { TemplateResult, html, nothing } from "lit"; +import { html } from "lit"; import { customElement, property } from "lit/decorators.js"; +import { HorizontalLightComponent } from "./HorizontalLightComponent"; + @customElement("ak-textarea-input") -export class AkTextareaInput extends AKElement { - // Render into the lightDOM. This effectively erases the shadowDOM nature of this component, but - // we're not actually using that and, for the meantime, we need the form handlers to be able to - // find the children of this component. - // - // TODO: This abstraction is wrong; it's putting *more* layers in as a way of managing the - // visual clutter and legibility issues of ak-form-elemental-horizontal and patternfly in - // general. - protected createRenderRoot() { - return this; - } - - @property({ type: String }) - name!: string; - - @property({ type: String }) - label = ""; - - @property({ type: String }) +export class AkTextareaInput extends HorizontalLightComponent { + @property({ type: String, reflect: true }) value = ""; - @property({ type: Boolean }) - required = false; - - @property({ type: String }) - help = ""; - - @property({ type: Object }) - bighelp!: TemplateResult | TemplateResult[]; - - renderHelp() { - return [ - this.help ? html`

${this.help}

` : nothing, - this.bighelp ? this.bighelp : nothing, - ]; - } - - render() { - return html` - - ${this.renderHelp()} - `; + >${this.value !== undefined ? this.value : ""} `; } } diff --git a/web/src/components/stories/ak-multi-select.stories.ts b/web/src/components/stories/ak-multi-select.stories.ts new file mode 100644 index 000000000..a3115c560 --- /dev/null +++ b/web/src/components/stories/ak-multi-select.stories.ts @@ -0,0 +1,79 @@ +import "@goauthentik/elements/messages/MessageContainer"; +import { Meta } from "@storybook/web-components"; + +import { TemplateResult, html, render } from "lit"; + +import "../ak-multi-select"; +import AkMultiSelect from "../ak-multi-select"; + +const metadata: Meta = { + title: "Components / MultiSelect", + component: "ak-multi-select", + parameters: { + docs: { + description: { + component: "A stylized value control for multi-select displays", + }, + }, + }, +}; + +export default metadata; + +const container = (testItem: TemplateResult) => + html`
+ + + ${testItem} + +
+
`; + +const testOptions = [ + ["funky", "Option One: Funky"], + ["strange", "Option Two: Strange"], + ["weird", "Option Three: Weird"], +]; + +export const RadioInput = () => { + const result = ""; + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const displayChange = (ev: any) => { + const messagePad = document.getElementById("message-pad"); + const component: AkMultiSelect | null = document.querySelector( + 'ak-multi-select[name="ak-test-multi-select"]', + ); + + const results = html` +

Results from event:

+
    + ${ev.target.value.map((v: string) => html`
  • ${v}
  • `)} +
+

Results from component:

+
    + ${component!.json().map((v: string) => html`
  • ${v}
  • `)} +
+ `; + + render(results, messagePad!); + }; + + return container( + html` +
${result}
`, + ); +}; diff --git a/web/src/elements/forms/Form.ts b/web/src/elements/forms/Form.ts index 0c4590fac..d465a2435 100644 --- a/web/src/elements/forms/Form.ts +++ b/web/src/elements/forms/Form.ts @@ -31,10 +31,15 @@ export interface KeyUnknown { [key: string]: unknown; } +// Literally the only field `assignValue()` cares about. +type HTMLNamedElement = Pick; + +type AkControlElement = HTMLInputElement & { json: () => string | string[] }; + /** * Recursively assign `value` into `json` while interpreting the dot-path of `element.name` */ -function assignValue(element: HTMLInputElement, value: unknown, json: KeyUnknown): void { +function assignValue(element: HTMLNamedElement, value: unknown, json: KeyUnknown): void { let parent = json; if (!element.name?.includes(".")) { parent[element.name] = value; @@ -60,6 +65,16 @@ export function serializeForm( const json: { [key: string]: unknown } = {}; elements.forEach((element) => { element.requestUpdate(); + if (element.hidden) { + return; + } + + // TODO: Tighten up the typing so that we can handle both. + if ("akControl" in element.dataset) { + assignValue(element, (element as unknown as AkControlElement).json(), json); + return; + } + const inputElement = element.querySelector("[name]"); if (element.hidden || !inputElement) { return; diff --git a/web/xliff/de.xlf b/web/xliff/de.xlf index cacf5580c..85e253602 100644 --- a/web/xliff/de.xlf +++ b/web/xliff/de.xlf @@ -5800,12 +5800,6 @@ Bindings to groups/users are checked against the user of the event. Your application has been saved - - In the Application: - - - In the Provider: - Method's display Name. @@ -6075,6 +6069,54 @@ Bindings to groups/users are checked against the user of the event. When enabled, the stage will always accept the given user identifier and continue. + + + There was an error in the application. + + + Review the application. + + + There was an error in the provider. + + + Review the provider. + + + There was an error + + + There was an error creating the application, but no error message was sent. Please review the server logs. + + + Configure LDAP Provider + + + Configure OAuth2/OpenId Provider + + + Configure Proxy Provider + + + AdditionalScopes + + + Configure Radius Provider + + + Configure SAML Provider + + + Property mappings used for user mapping. + + + Configure SCIM Provider + + + Property mappings used for group creation. + + + Event volume diff --git a/web/xliff/en.xlf b/web/xliff/en.xlf index 11d8ee1a5..2b236521f 100644 --- a/web/xliff/en.xlf +++ b/web/xliff/en.xlf @@ -6077,12 +6077,6 @@ Bindings to groups/users are checked against the user of the event. Your application has been saved - - In the Application: - - - In the Provider: - Method's display Name. @@ -6352,6 +6346,54 @@ Bindings to groups/users are checked against the user of the event. When enabled, the stage will always accept the given user identifier and continue. + + + There was an error in the application. + + + Review the application. + + + There was an error in the provider. + + + Review the provider. + + + There was an error + + + There was an error creating the application, but no error message was sent. Please review the server logs. + + + Configure LDAP Provider + + + Configure OAuth2/OpenId Provider + + + Configure Proxy Provider + + + AdditionalScopes + + + Configure Radius Provider + + + Configure SAML Provider + + + Property mappings used for user mapping. + + + Configure SCIM Provider + + + Property mappings used for group creation. + + + Event volume diff --git a/web/xliff/es.xlf b/web/xliff/es.xlf index b5708c7ac..d9564b6ad 100644 --- a/web/xliff/es.xlf +++ b/web/xliff/es.xlf @@ -5716,12 +5716,6 @@ Bindings to groups/users are checked against the user of the event. Your application has been saved - - In the Application: - - - In the Provider: - Method's display Name. @@ -5991,6 +5985,54 @@ Bindings to groups/users are checked against the user of the event. When enabled, the stage will always accept the given user identifier and continue. + + + There was an error in the application. + + + Review the application. + + + There was an error in the provider. + + + Review the provider. + + + There was an error + + + There was an error creating the application, but no error message was sent. Please review the server logs. + + + Configure LDAP Provider + + + Configure OAuth2/OpenId Provider + + + Configure Proxy Provider + + + AdditionalScopes + + + Configure Radius Provider + + + Configure SAML Provider + + + Property mappings used for user mapping. + + + Configure SCIM Provider + + + Property mappings used for group creation. + + + Event volume diff --git a/web/xliff/fr.xlf b/web/xliff/fr.xlf index 37dfc4bce..3c0fd9f4d 100644 --- a/web/xliff/fr.xlf +++ b/web/xliff/fr.xlf @@ -7617,14 +7617,6 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti Your application has been saved L'application a été sauvegardée - - In the Application: - Dans l'application : - - - In the Provider: - Dans le fournisseur : - Method's display Name. Nom d'affichage de la méthode. @@ -7986,6 +7978,54 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti When enabled, the stage will always accept the given user identifier and continue. Lorsqu'activé, l'étape acceptera toujours l'identifiant utilisateur donné et continuera. + + + There was an error in the application. + + + Review the application. + + + There was an error in the provider. + + + Review the provider. + + + There was an error + + + There was an error creating the application, but no error message was sent. Please review the server logs. + + + Configure LDAP Provider + + + Configure OAuth2/OpenId Provider + + + Configure Proxy Provider + + + AdditionalScopes + + + Configure Radius Provider + + + Configure SAML Provider + + + Property mappings used for user mapping. + + + Configure SCIM Provider + + + Property mappings used for group creation. + + + Event volume diff --git a/web/xliff/pl.xlf b/web/xliff/pl.xlf index 0c8118ae8..7aae5340d 100644 --- a/web/xliff/pl.xlf +++ b/web/xliff/pl.xlf @@ -5924,12 +5924,6 @@ Bindings to groups/users are checked against the user of the event. Your application has been saved - - In the Application: - - - In the Provider: - Method's display Name. @@ -6199,6 +6193,54 @@ Bindings to groups/users are checked against the user of the event. When enabled, the stage will always accept the given user identifier and continue. + + + There was an error in the application. + + + Review the application. + + + There was an error in the provider. + + + Review the provider. + + + There was an error + + + There was an error creating the application, but no error message was sent. Please review the server logs. + + + Configure LDAP Provider + + + Configure OAuth2/OpenId Provider + + + Configure Proxy Provider + + + AdditionalScopes + + + Configure Radius Provider + + + Configure SAML Provider + + + Property mappings used for user mapping. + + + Configure SCIM Provider + + + Property mappings used for group creation. + + + Event volume diff --git a/web/xliff/pseudo-LOCALE.xlf b/web/xliff/pseudo-LOCALE.xlf index 78b560613..3839422ba 100644 --- a/web/xliff/pseudo-LOCALE.xlf +++ b/web/xliff/pseudo-LOCALE.xlf @@ -7556,14 +7556,6 @@ Bindings to groups/users are checked against the user of the event. Your application has been saved Ŷōũŕ àƥƥĺĩćàţĩōń ĥàś ƀēēń śàvēď - - In the Application: - Ĩń ţĥē Àƥƥĺĩćàţĩōń: - - - In the Provider: - Ĩń ţĥē Ƥŕōvĩďēŕ: - Method's display Name. Mēţĥōď'ś ďĩśƥĺàŷ Ńàmē. @@ -7732,149 +7724,261 @@ Bindings to groups/users are checked against the user of the event. Create With Wizard + Ćŕēàţē Ŵĩţĥ Ŵĩźàŕď One hint, 'New Application Wizard', is currently hidden + Ōńē ĥĩńţ, 'Ńēŵ Àƥƥĺĩćàţĩōń Ŵĩźàŕď', ĩś ćũŕŕēńţĺŷ ĥĩďďēń External applications that use authentik as an identity provider via protocols like OAuth2 and SAML. All applications are shown here, even ones you cannot access. + Ēxţēŕńàĺ àƥƥĺĩćàţĩōńś ţĥàţ ũśē àũţĥēńţĩķ àś àń ĩďēńţĩţŷ ƥŕōvĩďēŕ vĩà ƥŕōţōćōĺś ĺĩķē ŌÀũţĥ2 àńď ŚÀMĹ. Àĺĺ àƥƥĺĩćàţĩōńś àŕē śĥōŵń ĥēŕē, ēvēń ōńēś ŷōũ ćàńńōţ àććēśś. Deny message + Ďēńŷ mēśśàĝē Message shown when this stage is run. + Mēśśàĝē śĥōŵń ŵĥēń ţĥĩś śţàĝē ĩś ŕũń. Open Wizard + Ōƥēń Ŵĩźàŕď Demo Wizard + Ďēmō Ŵĩźàŕď Run the demo wizard + Ŕũń ţĥē ďēmō ŵĩźàŕď OAuth2/OIDC (Open Authorization/OpenID Connect) + ŌÀũţĥ2/ŌĨĎĆ (Ōƥēń Àũţĥōŕĩźàţĩōń/ŌƥēńĨĎ Ćōńńēćţ) LDAP (Lightweight Directory Access Protocol) + ĹĎÀƤ (Ĺĩĝĥţŵēĩĝĥţ Ďĩŕēćţōŕŷ Àććēśś Ƥŕōţōćōĺ) Forward Auth (Single Application) + Ƒōŕŵàŕď Àũţĥ (Śĩńĝĺē Àƥƥĺĩćàţĩōń) Forward Auth (Domain Level) + Ƒōŕŵàŕď Àũţĥ (Ďōmàĩń Ĺēvēĺ) SAML (Security Assertion Markup Language) + ŚÀMĹ (Śēćũŕĩţŷ Àśśēŕţĩōń Màŕķũƥ Ĺàńĝũàĝē) RADIUS (Remote Authentication Dial-In User Service) + ŔÀĎĨŨŚ (Ŕēmōţē Àũţĥēńţĩćàţĩōń Ďĩàĺ-Ĩń Ũśēŕ Śēŕvĩćē) SCIM (System for Cross-domain Identity Management) + ŚĆĨM (Śŷśţēm ƒōŕ Ćŕōśś-ďōmàĩń Ĩďēńţĩţŷ Màńàĝēmēńţ) The token has been copied to your clipboard + Ţĥē ţōķēń ĥàś ƀēēń ćōƥĩēď ţō ŷōũŕ ćĺĩƥƀōàŕď The token was displayed because authentik does not have permission to write to the clipboard + Ţĥē ţōķēń ŵàś ďĩśƥĺàŷēď ƀēćàũśē àũţĥēńţĩķ ďōēś ńōţ ĥàvē ƥēŕmĩśśĩōń ţō ŵŕĩţē ţō ţĥē ćĺĩƥƀōàŕď A copy of this recovery link has been placed in your clipboard + À ćōƥŷ ōƒ ţĥĩś ŕēćōvēŕŷ ĺĩńķ ĥàś ƀēēń ƥĺàćēď ĩń ŷōũŕ ćĺĩƥƀōàŕď The current tenant must have a recovery flow configured to use a recovery link + Ţĥē ćũŕŕēńţ ţēńàńţ mũśţ ĥàvē à ŕēćōvēŕŷ ƒĺōŵ ćōńƒĩĝũŕēď ţō ũśē à ŕēćōvēŕŷ ĺĩńķ Create recovery link + Ćŕēàţē ŕēćōvēŕŷ ĺĩńķ Create Recovery Link + Ćŕēàţē Ŕēćōvēŕŷ Ĺĩńķ External + Ēxţēŕńàĺ Service account + Śēŕvĩćē àććōũńţ Service account (internal) + Śēŕvĩćē àććōũńţ (ĩńţēŕńàĺ) Check the release notes + Ćĥēćķ ţĥē ŕēĺēàśē ńōţēś User Statistics + Ũśēŕ Śţàţĩśţĩćś <No name set> + <Ńō ńàmē śēţ> For nginx's auth_request or traefik's forwardAuth + Ƒōŕ ńĝĩńx'ś àũţĥ_ŕēǫũēśţ ōŕ ţŕàēƒĩķ'ś ƒōŕŵàŕďÀũţĥ For nginx's auth_request or traefik's forwardAuth per root domain + Ƒōŕ ńĝĩńx'ś àũţĥ_ŕēǫũēśţ ōŕ ţŕàēƒĩķ'ś ƒōŕŵàŕďÀũţĥ ƥēŕ ŕōōţ ďōmàĩń RBAC is in preview. + ŔßÀĆ ĩś ĩń ƥŕēvĩēŵ. User type used for newly created users. + Ũśēŕ ţŷƥē ũśēď ƒōŕ ńēŵĺŷ ćŕēàţēď ũśēŕś. Users created + Ũśēŕś ćŕēàţēď Failed logins + Ƒàĩĺēď ĺōĝĩńś Also known as Client ID. + Àĺśō ķńōŵń àś Ćĺĩēńţ ĨĎ. Also known as Client Secret. + Àĺśō ķńōŵń àś Ćĺĩēńţ Śēćŕēţ. Global status + Ĝĺōƀàĺ śţàţũś Vendor + Vēńďōŕ No sync status. + Ńō śŷńć śţàţũś. Sync currently running. + Śŷńć ćũŕŕēńţĺŷ ŕũńńĩńĝ. Connectivity + Ćōńńēćţĩvĩţŷ 0: Too guessable: risky password. (guesses &lt; 10^3) + 0: Ţōō ĝũēśśàƀĺē: ŕĩśķŷ ƥàśśŵōŕď. (ĝũēśśēś &ĺţ; 10^3) 1: Very guessable: protection from throttled online attacks. (guesses &lt; 10^6) + 1: Vēŕŷ ĝũēśśàƀĺē: ƥŕōţēćţĩōń ƒŕōm ţĥŕōţţĺēď ōńĺĩńē àţţàćķś. (ĝũēśśēś &ĺţ; 10^6) 2: Somewhat guessable: protection from unthrottled online attacks. (guesses &lt; 10^8) + 2: Śōmēŵĥàţ ĝũēśśàƀĺē: ƥŕōţēćţĩōń ƒŕōm ũńţĥŕōţţĺēď ōńĺĩńē àţţàćķś. (ĝũēśśēś &ĺţ; 10^8) 3: Safely unguessable: moderate protection from offline slow-hash scenario. (guesses &lt; 10^10) + 3: Śàƒēĺŷ ũńĝũēśśàƀĺē: mōďēŕàţē ƥŕōţēćţĩōń ƒŕōm ōƒƒĺĩńē śĺōŵ-ĥàśĥ śćēńàŕĩō. (ĝũēśśēś &ĺţ; 10^10) 4: Very unguessable: strong protection from offline slow-hash scenario. (guesses &gt;= 10^10) + 4: Vēŕŷ ũńĝũēśśàƀĺē: śţŕōńĝ ƥŕōţēćţĩōń ƒŕōm ōƒƒĺĩńē śĺōŵ-ĥàśĥ śćēńàŕĩō. (ĝũēśśēś &ĝţ;= 10^10) Successfully created user and added to group + Śũććēśśƒũĺĺŷ ćŕēàţēď ũśēŕ àńď àďďēď ţō ĝŕōũƥ This user will be added to the group "". + Ţĥĩś ũśēŕ ŵĩĺĺ ƀē àďďēď ţō ţĥē ĝŕōũƥ "". Pretend user exists + Ƥŕēţēńď ũśēŕ ēxĩśţś When enabled, the stage will always accept the given user identifier and continue. + Ŵĥēń ēńàƀĺēď, ţĥē śţàĝē ŵĩĺĺ àĺŵàŷś àććēƥţ ţĥē ĝĩvēń ũśēŕ ĩďēńţĩƒĩēŕ àńď ćōńţĩńũē. + + + There was an error in the application. + Ţĥēŕē ŵàś àń ēŕŕōŕ ĩń ţĥē àƥƥĺĩćàţĩōń. + + + Review the application. + Ŕēvĩēŵ ţĥē àƥƥĺĩćàţĩōń. + + + There was an error in the provider. + Ţĥēŕē ŵàś àń ēŕŕōŕ ĩń ţĥē ƥŕōvĩďēŕ. + + + Review the provider. + Ŕēvĩēŵ ţĥē ƥŕōvĩďēŕ. + + + There was an error + Ţĥēŕē ŵàś àń ēŕŕōŕ + + + There was an error creating the application, but no error message was sent. Please review the server logs. + Ţĥēŕē ŵàś àń ēŕŕōŕ ćŕēàţĩńĝ ţĥē àƥƥĺĩćàţĩōń, ƀũţ ńō ēŕŕōŕ mēśśàĝē ŵàś śēńţ. Ƥĺēàśē ŕēvĩēŵ ţĥē śēŕvēŕ ĺōĝś. + + + Configure LDAP Provider + Ćōńƒĩĝũŕē ĹĎÀƤ Ƥŕōvĩďēŕ + + + Configure OAuth2/OpenId Provider + Ćōńƒĩĝũŕē ŌÀũţĥ2/ŌƥēńĨď Ƥŕōvĩďēŕ + + + Configure Proxy Provider + Ćōńƒĩĝũŕē Ƥŕōxŷ Ƥŕōvĩďēŕ + + + AdditionalScopes + ÀďďĩţĩōńàĺŚćōƥēś + + + Configure Radius Provider + Ćōńƒĩĝũŕē Ŕàďĩũś Ƥŕōvĩďēŕ + + + Configure SAML Provider + Ćōńƒĩĝũŕē ŚÀMĹ Ƥŕōvĩďēŕ + + + Property mappings used for user mapping. + Ƥŕōƥēŕţŷ màƥƥĩńĝś ũśēď ƒōŕ ũśēŕ màƥƥĩńĝ. + + + Configure SCIM Provider + Ćōńƒĩĝũŕē ŚĆĨM Ƥŕōvĩďēŕ + + + Property mappings used for group creation. + Ƥŕōƥēŕţŷ màƥƥĩńĝś ũśēď ƒōŕ ĝŕōũƥ ćŕēàţĩōń. + + + Event volume diff --git a/web/xliff/tr.xlf b/web/xliff/tr.xlf index f2eb13ba5..188474957 100644 --- a/web/xliff/tr.xlf +++ b/web/xliff/tr.xlf @@ -5709,12 +5709,6 @@ Bindings to groups/users are checked against the user of the event. Your application has been saved - - In the Application: - - - In the Provider: - Method's display Name. @@ -5984,6 +5978,54 @@ Bindings to groups/users are checked against the user of the event. When enabled, the stage will always accept the given user identifier and continue. + + + There was an error in the application. + + + Review the application. + + + There was an error in the provider. + + + Review the provider. + + + There was an error + + + There was an error creating the application, but no error message was sent. Please review the server logs. + + + Configure LDAP Provider + + + Configure OAuth2/OpenId Provider + + + Configure Proxy Provider + + + AdditionalScopes + + + Configure Radius Provider + + + Configure SAML Provider + + + Property mappings used for user mapping. + + + Configure SCIM Provider + + + Property mappings used for group creation. + + + Event volume diff --git a/web/xliff/zh-Hans.xlf b/web/xliff/zh-Hans.xlf index 96bfb9808..ad0d2c265 100644 --- a/web/xliff/zh-Hans.xlf +++ b/web/xliff/zh-Hans.xlf @@ -7619,14 +7619,6 @@ Bindings to groups/users are checked against the user of the event. Your application has been saved 您的应用程序已保存 - - In the Application: - 在应用程序中: - - - In the Provider: - 在提供程序中: - Method's display Name. 方法的显示名称。 @@ -7988,6 +7980,54 @@ Bindings to groups/users are checked against the user of the event. When enabled, the stage will always accept the given user identifier and continue. 启用时,此阶段总是会接受指定的用户 ID 并继续。 + + + There was an error in the application. + + + Review the application. + + + There was an error in the provider. + + + Review the provider. + + + There was an error + + + There was an error creating the application, but no error message was sent. Please review the server logs. + + + Configure LDAP Provider + + + Configure OAuth2/OpenId Provider + + + Configure Proxy Provider + + + AdditionalScopes + + + Configure Radius Provider + + + Configure SAML Provider + + + Property mappings used for user mapping. + + + Configure SCIM Provider + + + Property mappings used for group creation. + + + Event volume diff --git a/web/xliff/zh-Hant.xlf b/web/xliff/zh-Hant.xlf index e836104f2..1b85d0ee3 100644 --- a/web/xliff/zh-Hant.xlf +++ b/web/xliff/zh-Hant.xlf @@ -5757,12 +5757,6 @@ Bindings to groups/users are checked against the user of the event. Your application has been saved - - In the Application: - - - In the Provider: - Method's display Name. @@ -6032,6 +6026,54 @@ Bindings to groups/users are checked against the user of the event. When enabled, the stage will always accept the given user identifier and continue. + + + There was an error in the application. + + + Review the application. + + + There was an error in the provider. + + + Review the provider. + + + There was an error + + + There was an error creating the application, but no error message was sent. Please review the server logs. + + + Configure LDAP Provider + + + Configure OAuth2/OpenId Provider + + + Configure Proxy Provider + + + AdditionalScopes + + + Configure Radius Provider + + + Configure SAML Provider + + + Property mappings used for user mapping. + + + Configure SCIM Provider + + + Property mappings used for group creation. + + + Event volume diff --git a/web/xliff/zh_TW.xlf b/web/xliff/zh_TW.xlf index eccaef9f7..05818f770 100644 --- a/web/xliff/zh_TW.xlf +++ b/web/xliff/zh_TW.xlf @@ -7555,14 +7555,6 @@ Bindings to groups/users are checked against the user of the event. Your application has been saved 已經儲存您的應用程式 - - In the Application: - 在應用程式: - - - In the Provider: - 在供應商: - Method's display Name. 方法的顯示名稱。 @@ -7925,6 +7917,54 @@ Bindings to groups/users are checked against the user of the event. Are you sure you want to remove the selected users from the group ? + + + There was an error in the application. + + + Review the application. + + + There was an error in the provider. + + + Review the provider. + + + There was an error + + + There was an error creating the application, but no error message was sent. Please review the server logs. + + + Configure LDAP Provider + + + Configure OAuth2/OpenId Provider + + + Configure Proxy Provider + + + AdditionalScopes + + + Configure Radius Provider + + + Configure SAML Provider + + + Property mappings used for user mapping. + + + Configure SCIM Provider + + + Property mappings used for group creation. + + + Event volume diff --git a/website/docs/installation/docker-compose.md b/website/docs/installation/docker-compose.md index 39ada87ad..527058c8a 100644 --- a/website/docs/installation/docker-compose.md +++ b/website/docs/installation/docker-compose.md @@ -5,7 +5,7 @@ title: Docker Compose installation This installation method is for test-setups and small-scale production setups. :::info -You can also [view a video walk-through](https://youtu.be/owk1a_1xYe4) of the installation process on Docker (with bonus details about email configuration and other important options). +You can also [view a video walk-through](https://www.youtube.com/watch?v=O1qUbrk4Yc8) of the installation process on Docker (with bonus details about email configuration and other important options). ::: ## Requirements diff --git a/website/docs/installation/kubernetes.md b/website/docs/installation/kubernetes.md index 1c3f3dd85..e7caa73e0 100644 --- a/website/docs/installation/kubernetes.md +++ b/website/docs/installation/kubernetes.md @@ -5,7 +5,7 @@ title: Kubernetes installation You can install authentik to run on Kubernetes using Helm Chart. :::info -You can also [view a video walk-through](https://youtu.be/owk1a_1xYe4) of the installation process on Kubernetes (with bonus details about email configuration and other important options). +You can also [view a video walk-through](https://www.youtube.com/watch?v=O1qUbrk4Yc8) of the installation process on Kubernetes (with bonus details about email configuration and other important options). ::: ### Requirements diff --git a/website/package-lock.json b/website/package-lock.json index 8439e4996..58c698705 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -26,14 +26,14 @@ "react-dom": "^18.2.0", "react-feather": "^2.0.10", "react-toggle": "^4.1.3", - "react-tooltip": "^5.24.0", + "react-tooltip": "^5.25.0", "remark-github": "^12.0.0" }, "devDependencies": { "@docusaurus/module-type-aliases": "3.0.1", "@docusaurus/tsconfig": "3.0.1", "@docusaurus/types": "3.0.1", - "@types/react": "^18.2.41", + "@types/react": "^18.2.42", "prettier": "3.1.0", "typescript": "~5.3.2" }, @@ -4373,9 +4373,9 @@ "integrity": "sha512-+0autS93xyXizIYiyL02FCY8N+KkKPhILhcUSA276HxzreZ16kl+cmwvV2qAM/PuCCwPXzOXOWhiPcw20uSFcA==" }, "node_modules/@types/react": { - "version": "18.2.41", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.41.tgz", - "integrity": "sha512-CwOGr/PiLiNBxEBqpJ7fO3kocP/2SSuC9fpH5K7tusrg4xPSRT/193rzolYwQnTN02We/ATXKnb6GqA5w4fRxw==", + "version": "18.2.42", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.42.tgz", + "integrity": "sha512-c1zEr96MjakLYus/wPnuWDo1/zErfdU9rNsIGmE+NV71nx88FG9Ttgo5dqorXTu/LImX2f63WBP986gJkMPNbA==", "dependencies": { "@types/prop-types": "*", "@types/scheduler": "*", @@ -14365,9 +14365,9 @@ } }, "node_modules/react-tooltip": { - "version": "5.24.0", - "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.24.0.tgz", - "integrity": "sha512-HjstgpOrUwP4eN6mHU4EThpbxVuKO5SvqumRt1aAcPq0ya+pIVVxlwltndtdIIMBJ7w3jnN05vNfcfh2sxE2mQ==", + "version": "5.25.0", + "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.25.0.tgz", + "integrity": "sha512-/eGhmlwbHlJrVoUe75fb58rJfAy9aZnTvQAK9ZUPM0n9mmBGpEk13vDPiQVCeUuax+fBej+7JPsUXlhzaySc7w==", "dependencies": { "@floating-ui/dom": "^1.0.0", "classnames": "^2.3.0" diff --git a/website/package.json b/website/package.json index 09bee0260..8153abbb2 100644 --- a/website/package.json +++ b/website/package.json @@ -32,7 +32,7 @@ "react-dom": "^18.2.0", "react-feather": "^2.0.10", "react-toggle": "^4.1.3", - "react-tooltip": "^5.24.0", + "react-tooltip": "^5.25.0", "react": "^18.2.0", "remark-github": "^12.0.0" }, @@ -52,7 +52,7 @@ "@docusaurus/module-type-aliases": "3.0.1", "@docusaurus/tsconfig": "3.0.1", "@docusaurus/types": "3.0.1", - "@types/react": "^18.2.41", + "@types/react": "^18.2.42", "prettier": "3.1.0", "typescript": "~5.3.2" },