Compare commits

..

39 Commits

Author SHA1 Message Date
0f2ddb1997 Merge branch 'main' into providers/oauth2/conformance-automated-tests 2025-06-25 00:44:30 +02:00
b6ab7d9db2 fix duplicate artifact
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-04 16:39:04 +02:00
691c60f4be fix waiting for compete on error
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-01 21:01:01 +02:00
56630b0b4c fix offline_access tests
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-01 20:24:12 +02:00
9503c8d2e2 split up
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-01 20:00:46 +02:00
cecaea28c8 only run basic+implicit for now, fix other tests
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-01 20:00:46 +02:00
e4e2067c94 fix missing offline_access, use scoped issuer
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-01 20:00:46 +02:00
b43b9b8682 use actual timestamp
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-01 20:00:46 +02:00
0343999e52 add custom profile scope that includes standard scopes to return number of warnings
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-01 20:00:46 +02:00
5c856d6d06 add implicit test
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-01 20:00:46 +02:00
3c92b0e137 another actual fix; don't return access_token when using response_type id_token
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-01 20:00:45 +02:00
1a39f1902b fix basic suite?
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-01 20:00:45 +02:00
e3f5058cbe fix some
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-01 20:00:45 +02:00
ad872379e3 check authorize request param earlier
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-01 20:00:45 +02:00
005c2440de Revert "attempt to switch to generated"
This reverts commit 6f851e021d305a93be9cfbb4a9b6783231b6d7cf.

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-01 20:00:45 +02:00
49f306cd94 Revert "make it work generated?"
This reverts commit 4e29d2c5737ee9aaad6c0f4701caf7e0fb110e15.
2025-06-01 20:00:45 +02:00
9c394a03e6 Revert "fix teardown"
This reverts commit cb96b0cb988acedec1fe72ec437b68e2c38ed6b1.
2025-06-01 20:00:45 +02:00
f1755652eb Revert "re-add implicit and fix?"
This reverts commit 6a4d15fc22cf4b27ffa428be9ecc9a0e778961c6.
2025-06-01 20:00:45 +02:00
873dd95641 re-add implicit and fix?
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-01 20:00:44 +02:00
0ca4775600 fix teardown
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-01 20:00:44 +02:00
7e4c9bed3d make it work generated?
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-01 20:00:44 +02:00
573c7a09e6 attempt to switch to generated
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-01 20:00:44 +02:00
bf1d80d265 test
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-01 20:00:44 +02:00
107e9b789d upload cert exports
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-01 20:00:44 +02:00
3e2c1a9501 fix network and cookie deletion
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-01 20:00:43 +02:00
cefb99ec7d dont hardcode IP
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-01 20:00:43 +02:00
35391dcd3b maybe run in CI?
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-01 20:00:43 +02:00
e76071b79f properly install subtests
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-01 20:00:43 +02:00
0184f8cbba refactor conformance helper to requests (thanks chatgpt)
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-01 20:00:43 +02:00
e42c6c6fea cleanup, restart loop when we finished an operation
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-01 20:00:43 +02:00
ef779294bf sleep a bit before checking again
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-01 20:00:42 +02:00
ad159d9a3f remove debugging
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-01 20:00:42 +02:00
125cfe938d smaller screenshots?
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-01 20:00:42 +02:00
ad376de981 make tests mostly work
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-01 20:00:42 +02:00
9f1670f965 revert more debugging stuff
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-01 20:00:42 +02:00
8dd4709981 make it kinda work
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-01 20:00:41 +02:00
b25e68486a remove some previous debugging things
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-01 20:00:41 +02:00
80186fc625 somewhat working?
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-01 20:00:41 +02:00
ce19332450 some progress
Signed-off-by: Jens Langhammer <jens@goauthentik.io>
2025-06-01 20:00:41 +02:00
82 changed files with 1303 additions and 2544 deletions

View File

@ -226,6 +226,61 @@ jobs:
flags: e2e
file: unittest.xml
token: ${{ secrets.CODECOV_TOKEN }}
test-conformance:
name: test-conformance (${{ matrix.job.name }})
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
job:
- name: basic
glob: tests/openid_conformance/test_basic.py
- name: implicit
glob: tests/openid_conformance/test_implicit.py
steps:
- uses: actions/checkout@v4
- name: Setup authentik env
uses: ./.github/actions/setup
- name: Setup e2e env (chrome, etc)
run: |
docker compose -f tests/e2e/docker-compose.yml up -d --quiet-pull
- name: Setup conformance suite
run: |
docker compose -f tests/openid_conformance/compose.yml up -d --quiet-pull
- id: cache-web
uses: actions/cache@v4
with:
path: web/dist
key: ${{ runner.os }}-web-${{ hashFiles('web/package-lock.json', 'web/src/**', 'web/packages/sfe/src/**') }}-b
- name: prepare web ui
if: steps.cache-web.outputs.cache-hit != 'true'
working-directory: web
run: |
npm ci
make -C .. gen-client-ts
npm run build
npm run build:sfe
- name: run conformance
run: |
uv run coverage run manage.py test ${{ matrix.job.glob }}
uv run coverage xml
- if: ${{ always() }}
uses: codecov/codecov-action@v5
with:
flags: conformance
token: ${{ secrets.CODECOV_TOKEN }}
- if: ${{ !cancelled() }}
uses: codecov/test-results-action@v1
with:
flags: conformance
file: unittest.xml
token: ${{ secrets.CODECOV_TOKEN }}
- if: ${{ !cancelled() }}
uses: actions/upload-artifact@v4
with:
name: conformance-certification-${{ matrix.job.glob }}
path: tests/openid_conformance/exports/
ci-core-mark:
if: always()
needs:
@ -235,6 +290,7 @@ jobs:
- test-unittest
- test-integration
- test-e2e
- test-conformance
runs-on: ubuntu-latest
steps:
- uses: re-actors/alls-green@release/v1

1
.gitignore vendored
View File

@ -217,3 +217,4 @@ source_docs/
### Docker ###
docker-compose.override.yml
tests/openid_conformance/exports/*.zip

View File

@ -6,15 +6,13 @@
"!Context scalar",
"!Enumerate sequence",
"!Env scalar",
"!Env sequence",
"!Find sequence",
"!Format sequence",
"!If sequence",
"!Index scalar",
"!KeyOf scalar",
"!Value scalar",
"!AtIndex scalar",
"!ParseJSON scalar"
"!AtIndex scalar"
],
"typescript.preferences.importModuleSpecifier": "non-relative",
"typescript.preferences.importModuleSpecifierEnding": "index",

View File

@ -75,7 +75,7 @@ RUN --mount=type=secret,id=GEOIPUPDATE_ACCOUNT_ID \
/bin/sh -c "GEOIPUPDATE_LICENSE_KEY_FILE=/run/secrets/GEOIPUPDATE_LICENSE_KEY /usr/bin/entry.sh || echo 'Failed to get GeoIP database, disabling'; exit 0"
# Stage 4: Download uv
FROM ghcr.io/astral-sh/uv:0.7.15 AS uv
FROM ghcr.io/astral-sh/uv:0.7.14 AS uv
# Stage 5: Base python image
FROM ghcr.io/goauthentik/fips-python:3.13.5-slim-bookworm-fips AS python-base

View File

@ -150,9 +150,9 @@ gen-client-ts: gen-clean-ts ## Build and install the authentik API for Typescri
--additional-properties=npmVersion=${NPM_VERSION} \
--git-repo-id authentik \
--git-user-id goauthentik
cd ${PWD}/${GEN_API_TS} && npm link
cd ${PWD}/web && npm link @goauthentik/api
mkdir -p web/node_modules/@goauthentik/api
cd ${PWD}/${GEN_API_TS} && npm i
\cp -rf ${PWD}/${GEN_API_TS}/* web/node_modules/@goauthentik/api
gen-client-py: gen-clean-py ## Build and install the authentik API for Python
docker run \

View File

@ -37,7 +37,6 @@ entries:
- attrs:
attributes:
env_null: !Env [bar-baz, null]
json_parse: !ParseJSON '{"foo": "bar"}'
policy_pk1:
!Format [
"%s-%s",

View File

@ -215,7 +215,6 @@ class TestBlueprintsV1(TransactionTestCase):
},
"nested_context": "context-nested-value",
"env_null": None,
"json_parse": {"foo": "bar"},
"at_index_sequence": "foo",
"at_index_sequence_default": "non existent",
"at_index_mapping": 2,

View File

@ -6,7 +6,6 @@ from copy import copy
from dataclasses import asdict, dataclass, field, is_dataclass
from enum import Enum
from functools import reduce
from json import JSONDecodeError, loads
from operator import ixor
from os import getenv
from typing import Any, Literal, Union
@ -292,22 +291,6 @@ class Context(YAMLTag):
return value
class ParseJSON(YAMLTag):
"""Parse JSON from context/env/etc value"""
raw: str
def __init__(self, loader: "BlueprintLoader", node: ScalarNode) -> None:
super().__init__()
self.raw = node.value
def resolve(self, entry: BlueprintEntry, blueprint: Blueprint) -> Any:
try:
return loads(self.raw)
except JSONDecodeError as exc:
raise EntryInvalidError.from_entry(exc, entry) from exc
class Format(YAMLTag):
"""Format a string"""
@ -683,7 +666,6 @@ class BlueprintLoader(SafeLoader):
self.add_constructor("!Value", Value)
self.add_constructor("!Index", Index)
self.add_constructor("!AtIndex", AtIndex)
self.add_constructor("!ParseJSON", ParseJSON)
class EntryInvalidError(SentryIgnoredException):

View File

@ -407,7 +407,7 @@ class UserViewSet(UsedByMixin, ModelViewSet):
StrField(User, "path"),
BoolField(User, "is_active", nullable=True),
ChoiceSearchField(User, "type"),
JSONSearchField(User, "attributes", suggest_nested=False),
JSONSearchField(User, "attributes"),
]
def get_queryset(self):

View File

@ -2,7 +2,6 @@
from typing import Any
from django.db import models
from django.db.models import Model
from drf_spectacular.extensions import OpenApiSerializerFieldExtension
from drf_spectacular.plumbing import build_basic_type
@ -31,27 +30,7 @@ def is_dict(value: Any):
raise ValidationError("Value must be a dictionary, and not have any duplicate keys.")
class JSONDictField(JSONField):
"""JSON Field which only allows dictionaries"""
default_validators = [is_dict]
class JSONExtension(OpenApiSerializerFieldExtension):
"""Generate API Schema for JSON fields as"""
target_class = "authentik.core.api.utils.JSONDictField"
def map_serializer_field(self, auto_schema, direction):
return build_basic_type(OpenApiTypes.OBJECT)
class ModelSerializer(BaseModelSerializer):
# By default, JSON fields we have are used to store dictionaries
serializer_field_mapping = BaseModelSerializer.serializer_field_mapping.copy()
serializer_field_mapping[models.JSONField] = JSONDictField
def create(self, validated_data):
instance = super().create(validated_data)
@ -92,6 +71,21 @@ class ModelSerializer(BaseModelSerializer):
return instance
class JSONDictField(JSONField):
"""JSON Field which only allows dictionaries"""
default_validators = [is_dict]
class JSONExtension(OpenApiSerializerFieldExtension):
"""Generate API Schema for JSON fields as"""
target_class = "authentik.core.api.utils.JSONDictField"
def map_serializer_field(self, auto_schema, direction):
return build_basic_type(OpenApiTypes.OBJECT)
class PassiveSerializer(Serializer):
"""Base serializer class which doesn't implement create/update methods"""

View File

@ -193,32 +193,17 @@ class Event(SerializerModel, ExpiringModel):
brand: Brand = request.brand
self.brand = sanitize_dict(model_to_dict(brand))
if hasattr(request, "user"):
self.user = get_user(request.user)
original_user = None
if hasattr(request, "session"):
original_user = request.session.get(SESSION_KEY_IMPERSONATE_ORIGINAL_USER, None)
self.user = get_user(request.user, original_user)
if user:
self.user = get_user(user)
# Check if we're currently impersonating, and add that user
if hasattr(request, "session"):
from authentik.flows.views.executor import SESSION_KEY_PLAN
# Check if we're currently impersonating, and add that user
if SESSION_KEY_IMPERSONATE_ORIGINAL_USER in request.session:
self.user = get_user(request.session[SESSION_KEY_IMPERSONATE_ORIGINAL_USER])
self.user["on_behalf_of"] = get_user(request.session[SESSION_KEY_IMPERSONATE_USER])
# Special case for events that happen during a flow, the user might not be authenticated
# yet but is a pending user instead
if SESSION_KEY_PLAN in request.session:
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER, FlowPlan
plan: FlowPlan = request.session[SESSION_KEY_PLAN]
pending_user = plan.context.get(PLAN_CONTEXT_PENDING_USER, None)
# Only save `authenticated_as` if there's a different pending user in the flow
# than the user that is authenticated
if pending_user and (
(pending_user.pk and pending_user.pk != self.user.get("pk"))
or (not pending_user.pk)
):
orig_user = self.user.copy()
self.user = {"authenticated_as": orig_user, **get_user(pending_user)}
# User 255.255.255.255 as fallback if IP cannot be determined
self.client_ip = ClientIPMiddleware.get_client_ip(request)
# Enrich event data

View File

@ -8,11 +8,9 @@ from django.views.debug import SafeExceptionReporterFilter
from guardian.shortcuts import get_anonymous_user
from authentik.brands.models import Brand
from authentik.core.models import Group, User
from authentik.core.tests.utils import create_test_user
from authentik.core.models import Group
from authentik.events.models import Event
from authentik.flows.planner import PLAN_CONTEXT_PENDING_USER, FlowPlan
from authentik.flows.views.executor import QS_QUERY, SESSION_KEY_PLAN
from authentik.flows.views.executor import QS_QUERY
from authentik.lib.generators import generate_id
from authentik.policies.dummy.models import DummyPolicy
@ -118,92 +116,3 @@ class TestEvents(TestCase):
"pk": brand.pk.hex,
},
)
def test_from_http_flow_pending_user(self):
"""Test request from flow request with a pending user"""
user = create_test_user()
session = self.client.session
plan = FlowPlan(generate_id())
plan.context[PLAN_CONTEXT_PENDING_USER] = user
session[SESSION_KEY_PLAN] = plan
session.save()
request = self.factory.get("/")
request.session = session
request.user = user
event = Event.new("unittest").from_http(request)
self.assertEqual(
event.user,
{
"email": user.email,
"pk": user.pk,
"username": user.username,
},
)
def test_from_http_flow_pending_user_anon(self):
"""Test request from flow request with a pending user"""
user = create_test_user()
anon = get_anonymous_user()
session = self.client.session
plan = FlowPlan(generate_id())
plan.context[PLAN_CONTEXT_PENDING_USER] = user
session[SESSION_KEY_PLAN] = plan
session.save()
request = self.factory.get("/")
request.session = session
request.user = anon
event = Event.new("unittest").from_http(request)
self.assertEqual(
event.user,
{
"authenticated_as": {
"pk": anon.pk,
"is_anonymous": True,
"username": "AnonymousUser",
"email": "",
},
"email": user.email,
"pk": user.pk,
"username": user.username,
},
)
def test_from_http_flow_pending_user_fake(self):
"""Test request from flow request with a pending user"""
user = User(
username=generate_id(),
email=generate_id(),
)
anon = get_anonymous_user()
session = self.client.session
plan = FlowPlan(generate_id())
plan.context[PLAN_CONTEXT_PENDING_USER] = user
session[SESSION_KEY_PLAN] = plan
session.save()
request = self.factory.get("/")
request.session = session
request.user = anon
event = Event.new("unittest").from_http(request)
self.assertEqual(
event.user,
{
"authenticated_as": {
"pk": anon.pk,
"is_anonymous": True,
"username": "AnonymousUser",
"email": "",
},
"email": user.email,
"pk": user.pk,
"username": user.username,
},
)

View File

@ -74,8 +74,8 @@ def model_to_dict(model: Model) -> dict[str, Any]:
}
def get_user(user: User | AnonymousUser) -> dict[str, Any]:
"""Convert user object to dictionary"""
def get_user(user: User | AnonymousUser, original_user: User | None = None) -> dict[str, Any]:
"""Convert user object to dictionary, optionally including the original user"""
if isinstance(user, AnonymousUser):
try:
user = get_anonymous_user()
@ -88,6 +88,10 @@ def get_user(user: User | AnonymousUser) -> dict[str, Any]:
}
if user.username == settings.ANONYMOUS_USER_NAME:
user_data["is_anonymous"] = True
if original_user:
original_data = get_user(original_user)
original_data["on_behalf_of"] = user_data
return original_data
return user_data

View File

@ -104,6 +104,7 @@ def get_logger_config():
"hpack": "WARNING",
"httpx": "WARNING",
"azure": "WARNING",
"httpcore": "WARNING",
}
for handler_name, level in handler_level_map.items():
base_config["loggers"][handler_name] = {

View File

@ -1,7 +1,6 @@
"""Serializer for tenants models"""
from django_tenants.utils import get_public_schema_name
from rest_framework.fields import JSONField
from rest_framework.generics import RetrieveUpdateAPIView
from rest_framework.permissions import SAFE_METHODS
@ -13,8 +12,6 @@ from authentik.tenants.models import Tenant
class SettingsSerializer(ModelSerializer):
"""Settings Serializer"""
footer_links = JSONField(required=False)
class Meta:
model = Tenant
fields = [

4
go.mod
View File

@ -23,13 +23,13 @@ require (
github.com/nmcclain/asn1-ber v0.0.0-20170104154839-2661553a0484
github.com/pires/go-proxyproto v0.8.1
github.com/prometheus/client_golang v1.22.0
github.com/redis/go-redis/v9 v9.11.0
github.com/redis/go-redis/v9 v9.10.0
github.com/sethvargo/go-envconfig v1.3.0
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.9.1
github.com/stretchr/testify v1.10.0
github.com/wwt/guac v1.3.2
goauthentik.io/api/v3 v3.2025062.6
goauthentik.io/api/v3 v3.2025062.4
golang.org/x/exp v0.0.0-20230210204819-062eb4c674ab
golang.org/x/oauth2 v0.30.0
golang.org/x/sync v0.15.0

8
go.sum
View File

@ -251,8 +251,8 @@ github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ
github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I=
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
github.com/redis/go-redis/v9 v9.11.0 h1:E3S08Gl/nJNn5vkxd2i78wZxWAPNZgUNTp8WIJUAiIs=
github.com/redis/go-redis/v9 v9.11.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw=
github.com/redis/go-redis/v9 v9.10.0 h1:FxwK3eV8p/CQa0Ch276C7u2d0eNC9kCmAYQ7mCXCzVs=
github.com/redis/go-redis/v9 v9.10.0/go.mod h1:huWgSWd8mW6+m0VPhJjSSQ+d6Nh1VICQ6Q5lHuCH/Iw=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
@ -298,8 +298,8 @@ go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
goauthentik.io/api/v3 v3.2025062.6 h1:rlChhGP2vJufYCaTMb4sbRBEE1p2uL5T4HzMqF1AJ4A=
goauthentik.io/api/v3 v3.2025062.6/go.mod h1:zz+mEZg8rY/7eEjkMGWJ2DnGqk+zqxuybGCGrR2O4Kw=
goauthentik.io/api/v3 v3.2025062.4 h1:HuyL12kKserXT2w+wCDUYNRSeyCCGX81wU9SRCPuxDo=
goauthentik.io/api/v3 v3.2025062.4/go.mod h1:zz+mEZg8rY/7eEjkMGWJ2DnGqk+zqxuybGCGrR2O4Kw=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=

View File

@ -9,7 +9,7 @@
"version": "0.0.0",
"license": "MIT",
"devDependencies": {
"aws-cdk": "^2.1019.2",
"aws-cdk": "^2.1019.1",
"cross-env": "^7.0.3"
},
"engines": {
@ -17,9 +17,9 @@
}
},
"node_modules/aws-cdk": {
"version": "2.1019.2",
"resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1019.2.tgz",
"integrity": "sha512-LkWZ3IKBkfCPTCu60t4Wb9JMSkb+0Uzk+HIxZeW5sFohq8bxDGV0OP1hcqEC2+KbVYRn7q+YhMeSJ/FOQcgpiw==",
"version": "2.1019.1",
"resolved": "https://registry.npmjs.org/aws-cdk/-/aws-cdk-2.1019.1.tgz",
"integrity": "sha512-G2jxKuTsYTrYZX80CDApCrKcZ+AuFxxd+b0dkb0KEkfUsela7RqrDGLm5wOzSCIc3iH6GocR8JDVZuJ+0nNuKg==",
"dev": true,
"license": "Apache-2.0",
"bin": {

View File

@ -10,7 +10,7 @@
"node": ">=20"
},
"devDependencies": {
"aws-cdk": "^2.1019.2",
"aws-cdk": "^2.1019.1",
"cross-env": "^7.0.3"
}
}

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2025-06-25 00:10+0000\n"
"POT-Creation-Date: 2025-06-19 00:10+0000\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -109,6 +109,10 @@ msgstr ""
msgid "User does not have access to application."
msgstr ""
#: authentik/core/api/devices.py
msgid "Extra description not available"
msgstr ""
#: authentik/core/api/groups.py
msgid "Cannot set group as parent of itself."
msgstr ""

Binary file not shown.

View File

@ -2,11 +2,8 @@
* @file Prettier configuration for authentik.
*
* @import { Config as PrettierConfig } from "prettier";
*/
import { importsPlugin } from "./imports.js";
/**
* @import { PluginConfig as SortPluginConfig } from "@trivago/prettier-plugin-sort-imports";
*
* @typedef {object} PackageJSONPluginConfig
* @property {string[]} [packageSortOrder] Custom ordering array.
*/
@ -14,7 +11,7 @@ import { importsPlugin } from "./imports.js";
/**
* authentik Prettier configuration.
*
* @type {PrettierConfig & PackageJSONPluginConfig}
* @type {PrettierConfig & SortPluginConfig & PackageJSONPluginConfig}
* @internal
*/
export const AuthentikPrettierConfig = {
@ -37,8 +34,32 @@ export const AuthentikPrettierConfig = {
plugins: [
// ---
"prettier-plugin-packagejson",
importsPlugin(),
"@trivago/prettier-plugin-sort-imports",
],
importOrder: [
// ---
"^(@goauthentik/|#)common.+",
"^(@goauthentik/|#)elements.+",
"^(@goauthentik/|#)components.+",
"^(@goauthentik/|#)user.+",
"^(@goauthentik/|#)admin.+",
"^(@goauthentik/|#)flow.+",
"^#.+",
"^@goauthentik.+",
"<THIRD_PARTY_MODULES>",
"^(@?)lit(.*)$",
"\\.css$",
"^@goauthentik/api$",
"^[./]",
],
importOrderSideEffects: false,
importOrderSeparation: true,
importOrderSortSpecifiers: true,
importOrderParserPlugins: ["typescript", "jsx", "classProperties", "decorators-legacy"],
overrides: [
{
files: "schemas/**/*.json",

View File

@ -1,172 +0,0 @@
import { createRequire } from "node:module";
import { formatSourceFromFile } from "format-imports";
import { parsers as babelParsers } from "prettier/plugins/babel";
/**
* @file Prettier import plugin.
*
* @import { Plugin, ParserOptions } from "prettier";
*/
import { parsers as typescriptParsers } from "prettier/plugins/typescript";
const require = createRequire(process.cwd() + "/");
/**
* @param {string} name
* @returns {string | null}
*/
function resolveModule(name) {
try {
return require.resolve(name);
} catch (error) {
return null;
}
}
const webSubmodules = [
// ---
"common",
"elements",
"components",
"user",
"admin",
"flow",
];
/**
* Ensure that every import without an extension adds one.
* @param {string} input
* @returns {string}
*/
function normalizeExtensions(input) {
return input.replace(/(?:import|from)\s*["']((?:\.\.?\/).*?)(?<!\.\w+)["']/gm, (line, path) => {
return line.replace(path, `${path}.js`);
});
}
/**
* @param {string} filepath
* @param {string} input
* @returns {string}
*/
function normalizeImports(filepath, input) {
let output = input;
// Replace all TypeScript imports with the paths resolved by Node/Browser import maps.
for (const submodule of webSubmodules) {
const legacyPattern = new RegExp(
[
// ---
`(?:import|from)`,
`\\\(?\\n?\\s*`,
`"(?<suffix>@goauthentik\/${submodule}\/)`,
`(?<path>[^"'.]+)`,
`(?:.[^"']+)?["']`,
`\\n?\\s*\\\)?;`,
].join(""),
"gm",
);
output = output.replace(
legacyPattern,
/**
* @param {string} line
* @param {string} suffix
* @param {string} path
*/
(line, suffix, path) => {
const exported = `@goauthentik/web/${submodule}/${path}`;
let imported = `#${submodule}/${path}`;
let module = resolveModule(`${exported}.ts`);
if (!module) {
module = resolveModule(`${exported}/index.ts`);
imported += "/index";
}
if (imported.endsWith(".css")) {
imported += ".js";
}
if (!module) {
console.warn(`\nCannot resolve module ${exported} from ${filepath}`, {
line,
path,
exported,
imported,
module,
});
process.exit(1);
}
return (
line
// ---
.replace(suffix + path, imported)
.replace(`${imported}.js`, imported)
);
},
);
}
return output;
}
/**
* @returns {Plugin}
*/
export function importsPlugin({
useLegacyCleanup = process.env.AK_FIX_LEGACY_IMPORTS === "true",
} = {}) {
/**
* @param {string} input
* @param {ParserOptions} options
*/
const preprocess = (input, { filepath, printWidth }) => {
let output = input;
if (useLegacyCleanup) {
output = normalizeExtensions(input);
output = normalizeImports(filepath, output);
}
const value = formatSourceFromFile.sync(output, filepath, {
nodeProtocol: "always",
maxLineLength: printWidth,
wrappingStyle: "prettier",
groupRules: [
"^node:",
...webSubmodules.map((submodule) => `^(@goauthentik/|#)${submodule}.+`),
"^#.+",
"^@goauthentik.+",
{}, // Other imports.
"^(@?)lit(.*)$",
"\\.css$",
"^@goauthentik/api$",
"^[./]",
],
});
return value || input;
};
return {
parsers: {
typescript: {
...typescriptParsers.typescript,
preprocess,
},
babel: {
...babelParsers.babel,
preprocess,
},
},
};
}

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{
"name": "@goauthentik/prettier-config",
"version": "3.0.0",
"version": "2.0.1",
"description": "authentik's Prettier config",
"license": "MIT",
"scripts": {
@ -10,19 +10,19 @@
},
"type": "module",
"exports": "./index.js",
"dependencies": {
"format-imports": "^4.0.7"
},
"devDependencies": {
"@goauthentik/tsconfig": "^1.0.1",
"@types/node": "^24.0.4",
"prettier": "^3.6.1",
"prettier-plugin-packagejson": "^2.5.16",
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
"prettier": "^3.5.3",
"prettier-plugin-organize-imports": "^4.1.0",
"prettier-plugin-packagejson": "^2.5.15",
"typescript": "^5.8.3"
},
"peerDependencies": {
"prettier": "^3.6.1",
"prettier-plugin-packagejson": "^2.5.16"
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
"prettier": "^3.5.3",
"prettier-plugin-organize-imports": "^4.1.0",
"prettier-plugin-packagejson": "^2.5.15"
},
"engines": {
"node": ">=22"

View File

@ -17,10 +17,10 @@ dependencies = [
"django-countries==7.6.1",
"django-cte==2.0.0",
"django-filter==25.1",
"django-guardian==3.0.3",
"django-guardian==3.0.0",
"django-model-utils==5.0.0",
"django-pglock==1.7.2",
"django-prometheus==2.4.1",
"django-prometheus==2.4.0",
"django-redis==6.0.0",
"django-storages[s3]==1.14.6",
"django-tenants==3.8.0",
@ -36,7 +36,7 @@ dependencies = [
"flower==2.0.1",
"geoip2==5.1.0",
"geopy==2.4.1",
"google-api-python-client==2.174.0",
"google-api-python-client==2.173.0",
"gssapi==1.9.0",
"gunicorn==23.0.0",
"jsonpatch==1.33",
@ -44,7 +44,7 @@ dependencies = [
"kubernetes==33.1.0",
"ldap3==2.9.1",
"lxml==5.4.0",
"msgraph-sdk==1.35.0",
"msgraph-sdk==1.34.0",
"opencontainers==0.0.14",
"packaging==25.0",
"paramiko==3.5.1",
@ -57,7 +57,7 @@ dependencies = [
"pyyaml==6.0.2",
"requests-oauthlib==2.0.0",
"scim2-filter-parser==0.7.0",
"sentry-sdk==2.31.0",
"sentry-sdk==2.30.0",
"service-identity==24.2.0",
"setproctitle==1.3.6",
"structlog==25.4.0",
@ -96,6 +96,7 @@ dev = [
"pytest-django==4.11.1",
"pytest-github-actions-annotate-failures==0.3.0",
"pytest-randomly==3.16.0",
"pytest-subtests>=0.14.1",
"pytest-timeout==2.4.0",
"requests-mock==1.12.1",
"ruff==0.11.9",

View File

@ -41338,9 +41338,7 @@ components:
app:
type: string
format: uuid
attributes:
type: object
additionalProperties: {}
attributes: {}
required:
- app
- name
@ -41355,9 +41353,7 @@ components:
app:
type: string
format: uuid
attributes:
type: object
additionalProperties: {}
attributes: {}
required:
- app
- name
@ -41946,9 +41942,7 @@ components:
friendly_name:
type: string
nullable: true
credentials:
type: object
additionalProperties: {}
credentials: {}
required:
- component
- credentials
@ -41978,9 +41972,7 @@ components:
type: string
nullable: true
minLength: 1
credentials:
type: object
additionalProperties: {}
credentials: {}
required:
- credentials
- name
@ -42785,9 +42777,7 @@ components:
path:
type: string
default: ''
context:
type: object
additionalProperties: {}
context: {}
last_applied:
type: string
format: date-time
@ -42807,8 +42797,6 @@ components:
type: string
readOnly: true
metadata:
type: object
additionalProperties: {}
readOnly: true
content:
type: string
@ -42830,9 +42818,7 @@ components:
path:
type: string
default: ''
context:
type: object
additionalProperties: {}
context: {}
enabled:
type: boolean
content:
@ -42912,9 +42898,7 @@ components:
type: string
format: uuid
description: Certificates used for client authentication.
attributes:
type: object
additionalProperties: {}
attributes: {}
required:
- brand_uuid
- domain
@ -42984,9 +42968,7 @@ components:
type: string
format: uuid
description: Certificates used for client authentication.
attributes:
type: object
additionalProperties: {}
attributes: {}
required:
- domain
Cache:
@ -44627,9 +44609,7 @@ components:
$ref: '#/components/schemas/ProtocolEnum'
host:
type: string
settings:
type: object
additionalProperties: {}
settings: {}
property_mappings:
type: array
items:
@ -44700,9 +44680,7 @@ components:
host:
type: string
minLength: 1
settings:
type: object
additionalProperties: {}
settings: {}
property_mappings:
type: array
items:
@ -44766,16 +44744,12 @@ components:
format: uuid
readOnly: true
title: Event uuid
user:
type: object
additionalProperties: {}
user: {}
action:
$ref: '#/components/schemas/EventActions'
app:
type: string
context:
type: object
additionalProperties: {}
context: {}
client_ip:
type: string
nullable: true
@ -44786,9 +44760,7 @@ components:
expires:
type: string
format: date-time
brand:
type: object
additionalProperties: {}
brand: {}
required:
- action
- app
@ -44933,17 +44905,13 @@ components:
type: object
description: Event Serializer
properties:
user:
type: object
additionalProperties: {}
user: {}
action:
$ref: '#/components/schemas/EventActions'
app:
type: string
minLength: 1
context:
type: object
additionalProperties: {}
context: {}
client_ip:
type: string
nullable: true
@ -44951,9 +44919,7 @@ components:
expires:
type: string
format: date-time
brand:
type: object
additionalProperties: {}
brand: {}
required:
- action
- app
@ -45928,9 +45894,7 @@ components:
type: string
format: email
maxLength: 254
credentials:
type: object
additionalProperties: {}
credentials: {}
scopes:
type: string
exclude_users_service_account:
@ -45981,8 +45945,6 @@ components:
provider:
type: integer
attributes:
type: object
additionalProperties: {}
readOnly: true
required:
- attributes
@ -46097,9 +46059,7 @@ components:
format: email
minLength: 1
maxLength: 254
credentials:
type: object
additionalProperties: {}
credentials: {}
scopes:
type: string
minLength: 1
@ -46144,8 +46104,6 @@ components:
provider:
type: integer
attributes:
type: object
additionalProperties: {}
readOnly: true
required:
- attributes
@ -47474,8 +47432,6 @@ components:
description: Return internal model name
readOnly: true
kubeconfig:
type: object
additionalProperties: {}
description: Paste your kubeconfig here. authentik will automatically use
the currently selected context.
verify_ssl:
@ -47500,8 +47456,6 @@ components:
description: If enabled, use the local connection. Required Docker socket/Kubernetes
Integration
kubeconfig:
type: object
additionalProperties: {}
description: Paste your kubeconfig here. authentik will automatically use
the currently selected context.
verify_ssl:
@ -48438,8 +48392,6 @@ components:
provider:
type: integer
attributes:
type: object
additionalProperties: {}
readOnly: true
required:
- attributes
@ -48596,8 +48548,6 @@ components:
provider:
type: integer
attributes:
type: object
additionalProperties: {}
readOnly: true
required:
- attributes
@ -49510,9 +49460,7 @@ components:
type: string
oidc_jwks_url:
type: string
oidc_jwks:
type: object
additionalProperties: {}
oidc_jwks: {}
authorization_code_auth_method:
allOf:
- $ref: '#/components/schemas/AuthorizationCodeAuthMethodEnum'
@ -49686,9 +49634,7 @@ components:
type: string
oidc_jwks_url:
type: string
oidc_jwks:
type: object
additionalProperties: {}
oidc_jwks: {}
authorization_code_auth_method:
allOf:
- $ref: '#/components/schemas/AuthorizationCodeAuthMethodEnum'
@ -52373,9 +52319,7 @@ components:
app:
type: string
format: uuid
attributes:
type: object
additionalProperties: {}
attributes: {}
PatchedApplicationRequest:
type: object
description: Application Serializer
@ -52527,9 +52471,7 @@ components:
type: string
nullable: true
minLength: 1
credentials:
type: object
additionalProperties: {}
credentials: {}
PatchedAuthenticatorSMSStageRequest:
type: object
description: AuthenticatorSMSStage Serializer
@ -52716,9 +52658,7 @@ components:
path:
type: string
default: ''
context:
type: object
additionalProperties: {}
context: {}
enabled:
type: boolean
content:
@ -52789,9 +52729,7 @@ components:
type: string
format: uuid
description: Certificates used for client authentication.
attributes:
type: object
additionalProperties: {}
attributes: {}
PatchedCaptchaStageRequest:
type: object
description: CaptchaStage Serializer
@ -53067,9 +53005,7 @@ components:
host:
type: string
minLength: 1
settings:
type: object
additionalProperties: {}
settings: {}
property_mappings:
type: array
items:
@ -53121,17 +53057,13 @@ components:
type: object
description: Event Serializer
properties:
user:
type: object
additionalProperties: {}
user: {}
action:
$ref: '#/components/schemas/EventActions'
app:
type: string
minLength: 1
context:
type: object
additionalProperties: {}
context: {}
client_ip:
type: string
nullable: true
@ -53139,9 +53071,7 @@ components:
expires:
type: string
format: date-time
brand:
type: object
additionalProperties: {}
brand: {}
PatchedExpressionPolicyRequest:
type: object
description: Group Membership Policy Serializer
@ -53324,9 +53254,7 @@ components:
format: email
minLength: 1
maxLength: 254
credentials:
type: object
additionalProperties: {}
credentials: {}
scopes:
type: string
minLength: 1
@ -53710,8 +53638,6 @@ components:
description: If enabled, use the local connection. Required Docker socket/Kubernetes
Integration
kubeconfig:
type: object
additionalProperties: {}
description: Paste your kubeconfig here. authentik will automatically use
the currently selected context.
verify_ssl:
@ -54295,9 +54221,7 @@ components:
type: string
oidc_jwks_url:
type: string
oidc_jwks:
type: object
additionalProperties: {}
oidc_jwks: {}
authorization_code_auth_method:
allOf:
- $ref: '#/components/schemas/AuthorizationCodeAuthMethodEnum'
@ -54776,9 +54700,7 @@ components:
items:
type: string
format: uuid
settings:
type: object
additionalProperties: {}
settings: {}
connection_expiry:
type: string
minLength: 1
@ -55235,9 +55157,7 @@ components:
source:
type: string
format: uuid
attributes:
type: object
additionalProperties: {}
attributes: {}
PatchedSCIMSourcePropertyMappingRequest:
type: object
description: SCIMSourcePropertyMapping Serializer
@ -55298,9 +55218,7 @@ components:
source:
type: string
format: uuid
attributes:
type: object
additionalProperties: {}
attributes: {}
PatchedSMSDeviceRequest:
type: object
description: Serializer for sms authenticator devices
@ -55387,7 +55305,9 @@ components:
minimum: 0
description: Reputation cannot increase higher than this value. Zero or
positive.
footer_links: {}
footer_links:
description: The option configures the footer links on the flow executor
pages.
gdpr_compliance:
type: boolean
description: When enabled, all the events caused by a user will be deleted
@ -57199,9 +57119,7 @@ components:
type: string
description: Return internal model name
readOnly: true
settings:
type: object
additionalProperties: {}
settings: {}
outpost_set:
type: array
items:
@ -57249,9 +57167,7 @@ components:
items:
type: string
format: uuid
settings:
type: object
additionalProperties: {}
settings: {}
connection_expiry:
type: string
minLength: 1
@ -57661,12 +57577,8 @@ components:
type: string
ip:
type: string
ip_geo_data:
type: object
additionalProperties: {}
ip_asn_data:
type: object
additionalProperties: {}
ip_geo_data: {}
ip_asn_data: {}
score:
type: integer
maximum: 9223372036854775807
@ -58739,8 +58651,6 @@ components:
provider:
type: integer
attributes:
type: object
additionalProperties: {}
readOnly: true
required:
- attributes
@ -58831,8 +58741,6 @@ components:
provider:
type: integer
attributes:
type: object
additionalProperties: {}
readOnly: true
required:
- attributes
@ -58947,9 +58855,7 @@ components:
source:
type: string
format: uuid
attributes:
type: object
additionalProperties: {}
attributes: {}
required:
- group
- group_obj
@ -58968,9 +58874,7 @@ components:
source:
type: string
format: uuid
attributes:
type: object
additionalProperties: {}
attributes: {}
required:
- group
- id
@ -59089,9 +58993,7 @@ components:
source:
type: string
format: uuid
attributes:
type: object
additionalProperties: {}
attributes: {}
required:
- id
- source
@ -59109,9 +59011,7 @@ components:
source:
type: string
format: uuid
attributes:
type: object
additionalProperties: {}
attributes: {}
required:
- id
- source
@ -59504,7 +59404,9 @@ components:
minimum: 0
description: Reputation cannot increase higher than this value. Zero or
positive.
footer_links: {}
footer_links:
description: The option configures the footer links on the flow executor
pages.
gdpr_compliance:
type: boolean
description: When enabled, all the events caused by a user will be deleted
@ -59556,7 +59458,9 @@ components:
minimum: 0
description: Reputation cannot increase higher than this value. Zero or
positive.
footer_links: {}
footer_links:
description: The option configures the footer links on the flow executor
pages.
gdpr_compliance:
type: boolean
description: When enabled, all the events caused by a user will be deleted

View File

@ -9,8 +9,8 @@
"strict": true,
"newLine": "lf",
"target": "ESNext",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"module": "ESNext",
"moduleResolution": "bundler",
"outDir": "dist",
"skipDefaultLibCheck": true,
"skipLibCheck": true,

View File

@ -6,6 +6,8 @@ services:
- /dev/shm:/dev/shm
network_mode: host
restart: always
extra_hosts:
- "host.docker.internal:host-gateway"
mailpit:
image: docker.io/axllent/mailpit:v1.26.2
ports:

View File

@ -165,6 +165,7 @@ class SeleniumTestCase(DockerTestCase, StaticLiveServerTestCase):
def _get_driver(self) -> WebDriver:
count = 0
opts = webdriver.ChromeOptions()
opts.accept_insecure_certs = True
opts.add_argument("--disable-search-engine-choice-screen")
# This breaks selenium when running remotely...?
# opts.set_capability("goog:loggingPrefs", {"browser": "ALL"})
@ -249,7 +250,6 @@ class SeleniumTestCase(DockerTestCase, StaticLiveServerTestCase):
def login(self, shadow_dom=True):
"""Do entire login flow"""
if shadow_dom:
flow_executor = self.get_shadow_root("ak-flow-executor")
identification_stage = self.get_shadow_root("ak-stage-identification", flow_executor)

View File

View File

@ -0,0 +1,156 @@
from json import dumps
from os import makedirs
from pathlib import Path
from time import sleep
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as ec
from authentik.blueprints.tests import apply_blueprint, reconcile_app
from authentik.providers.oauth2.models import OAuth2Provider
from tests.e2e.utils import SeleniumTestCase
from tests.openid_conformance.conformance import Conformance
class TestOpenIDConformance(SeleniumTestCase):
conformance: Conformance
@apply_blueprint(
"default/flow-default-authentication-flow.yaml",
"default/flow-default-invalidation-flow.yaml",
)
@apply_blueprint(
"default/flow-default-provider-authorization-implicit-consent.yaml",
"default/flow-default-provider-invalidation.yaml",
)
@apply_blueprint("system/providers-oauth2.yaml")
@reconcile_app("authentik_crypto")
@apply_blueprint("testing/oidc-conformance.yaml")
def setUp(self):
super().setUp()
makedirs(Path(__file__).parent / "exports", exist_ok=True)
provider_a = OAuth2Provider.objects.get(
client_id="4054d882aff59755f2f279968b97ce8806a926e1"
)
provider_b = OAuth2Provider.objects.get(
client_id="ad64aeaf1efe388ecf4d28fcc537e8de08bcae26"
)
self.test_plan_config = {
"alias": "authentik",
"description": "authentik",
"server": {
"discoveryUrl": self.url(
"authentik_providers_oauth2:provider-info",
application_slug="oidc-conformance-1",
),
},
"client": {
"client_id": "4054d882aff59755f2f279968b97ce8806a926e1",
"client_secret": provider_a.client_secret,
},
"client_secret_post": {
"client_id": "4054d882aff59755f2f279968b97ce8806a926e1",
"client_secret": provider_a.client_secret,
},
"client2": {
"client_id": "ad64aeaf1efe388ecf4d28fcc537e8de08bcae26",
"client_secret": provider_b.client_secret,
},
"consent": {},
}
self.test_variant = {
"server_metadata": "discovery",
"client_registration": "static_client",
}
def run_test(self, test_plan: str, test_plan_config: dict):
# Create a Conformance instance...
self.conformance = Conformance(f"https://{self.host}:8443/", None, verify_ssl=False)
test_plan = self.conformance.create_test_plan(
test_plan,
dumps(test_plan_config),
self.test_variant,
)
plan_id = test_plan["id"]
for test in test_plan["modules"]:
with self.subTest(test["testModule"], **test["variant"]):
# Fetch name and variant of the next test to run
module_name = test["testModule"]
variant = test["variant"]
module_instance = self.conformance.create_test_from_plan_with_variant(
plan_id, module_name, variant
)
module_id = module_instance["id"]
self.run_single_test(module_id)
self.conformance.wait_for_state(module_id, ["FINISHED"], timeout=self.wait_timeout)
sleep(2)
self.conformance.exporthtml(plan_id, Path(__file__).parent / "exports")
def run_single_test(self, module_id: str):
"""Process instructions for a single test, navigate to browser URLs and take screenshots"""
tested_browser_url = 0
uploaded_image = 0
cleared_cookies = False
while True:
# Fetch all info
test_status = self.conformance.get_test_status(module_id)
test_log = self.conformance.get_test_log(module_id)
test_info = self.conformance.get_module_info(module_id)
# Check status early, if we're finished already we don't want to do anything extra
if test_info["status"] in ["INTERRUPTED", "FINISHED"]:
return
# Check if we need to clear cookies - tests only indicates this in their written summary
# so this check is a bit brittle
if "cookies" in test_info["summary"] and not cleared_cookies:
# Navigate to our origin to delete cookies in the right context
self.driver.get(self.url("authentik_api:user-me") + "?format=json")
self.driver.delete_all_cookies()
cleared_cookies = True
# Check if we need deal with any browser URLs
browser_urls = test_status.get("browser", {}).get("urls", [])
if len(browser_urls) > tested_browser_url:
self.do_browser(browser_urls[tested_browser_url])
tested_browser_url += 1
continue
# Check if we need to upload any items
upload_items = [x for x in test_log if "upload" in x]
if len(upload_items) > uploaded_image:
screenshot = self.get_screenshot()
self.conformance.upload_image(
module_id, upload_items[uploaded_image]["upload"], screenshot
)
sleep(3)
uploaded_image += 1
continue
sleep(0.1)
def get_screenshot(self):
"""Get a screenshot, but resize the window first so we don't exceed 500kb"""
self.driver.set_window_size(800, 600)
screenshot = f"data:image/jpeg;base64,{self.driver.get_screenshot_as_base64()}"
self.driver.maximize_window()
return screenshot
def do_browser(self, url):
"""For any specific OpenID Conformance test, execute the operations required"""
self.driver.get(url)
should_expect_completion = False
if "if/flow/default-authentication-flow" in self.driver.current_url:
self.logger.debug("Logging in")
self.login()
should_expect_completion = True
if "prompt=consent" in url or "offline_access" in url:
self.logger.debug("Authorizing")
self.wait.until(ec.presence_of_element_located((By.CSS_SELECTOR, "ak-flow-executor")))
sleep(1)
flow_executor = self.get_shadow_root("ak-flow-executor")
consent_stage = self.get_shadow_root("ak-stage-consent", flow_executor)
consent_stage.find_element(
By.CSS_SELECTOR,
"[type=submit]",
).click()
should_expect_completion = True
if should_expect_completion:
self.wait.until(ec.presence_of_element_located((By.CSS_SELECTOR, "#complete")))

View File

@ -0,0 +1,192 @@
import json
import os
import re
import time
import zipfile
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
class Conformance:
HTTP_OK = 200
HTTP_CREATED = 201
def __init__(self, api_url_base, api_token, verify_ssl):
if not api_url_base.endswith("/"):
api_url_base += "/"
self.api_url_base = api_url_base
self.session = requests.Session()
self.session.verify = verify_ssl
retries = Retry(
total=5,
backoff_factor=1,
status_forcelist=[500, 502, 503, 504],
allowed_methods=["GET", "POST"],
)
self.session.mount("https://", HTTPAdapter(max_retries=retries))
self.session.mount("http://", HTTPAdapter(max_retries=retries))
self.session.headers.update({"Content-Type": "application/json"})
if api_token is not None:
self.session.headers.update({"Authorization": f"Bearer {api_token}"})
def get_all_test_modules(self):
url = f"{self.api_url_base}api/runner/available"
response = self.session.get(url)
if response.status_code != Conformance.HTTP_OK:
raise Exception(
f"get_all_test_modules failed - HTTP {response.status_code} {response.content}"
)
return response.json()
def get_test_status(self, module_id):
url = f"{self.api_url_base}api/runner/{module_id}"
response = self.session.get(url)
if response.status_code != Conformance.HTTP_OK:
raise Exception(
f"get_test_status failed - HTTP {response.status_code} {response.content}"
)
return response.json()
def exporthtml(self, plan_id, path):
for _ in range(5):
url = f"{self.api_url_base}api/plan/exporthtml/{plan_id}"
try:
with self.session.get(url, stream=True) as response:
if response.status_code != Conformance.HTTP_OK:
raise Exception(
f"exporthtml failed - HTTP {response.status_code} {response.content}"
)
cd = response.headers.get("content-disposition", "")
local_filename = re.findall('filename="(.+)"', cd)[0]
full_path = os.path.join(path, local_filename)
with open(full_path, "wb") as f:
for chunk in response.iter_content(chunk_size=8192):
f.write(chunk)
zip_file = zipfile.ZipFile(full_path)
ret = zip_file.testzip()
if ret is not None:
raise Exception(f"exporthtml returned corrupt zip file: {ret}")
return full_path
except Exception as e:
print(f"requests {url} exception {e} caught - retrying")
time.sleep(1)
raise Exception(f"exporthtml for {plan_id} failed even after retries")
def create_certification_package(
self, plan_id, conformance_pdf_path, rp_logs_zip_path=None, output_zip_directory="./"
):
with (
open(conformance_pdf_path, "rb") as cert_pdf,
open(rp_logs_zip_path, "rb") if rp_logs_zip_path else open(os.devnull, "rb") as rp_logs,
):
files = {
"certificationOfConformancePdf": cert_pdf,
"clientSideData": rp_logs,
}
headers = self.session.headers.copy()
headers.pop("Content-Type", None)
url = f"{self.api_url_base}api/plan/{plan_id}/certificationpackage"
response = self.session.post(url, files=files, headers=headers)
if response.status_code != Conformance.HTTP_OK:
raise Exception(
f"certificationpackage failed - HTTP {response.status_code} {response.content}"
)
cd = response.headers.get("content-disposition", "")
local_filename = re.findall('filename="(.+)"', cd)[0]
full_path = os.path.join(output_zip_directory, local_filename)
with open(full_path, "wb") as f:
f.write(response.content)
print(f"Certification package zip for plan id {plan_id} written to {full_path}")
def create_test_plan(self, name, configuration, variant=None):
url = f"{self.api_url_base}api/plan"
payload = {"planName": name}
if variant is not None:
payload["variant"] = json.dumps(variant)
response = self.session.post(url, params=payload, data=configuration)
if response.status_code != Conformance.HTTP_CREATED:
raise Exception(
f"create_test_plan failed - HTTP {response.status_code} {response.content}"
)
return response.json()
def create_test(self, test_name, configuration):
url = f"{self.api_url_base}api/runner"
payload = {"test": test_name}
response = self.session.post(url, params=payload, data=configuration)
if response.status_code != Conformance.HTTP_CREATED:
raise Exception(f"create_test failed - HTTP {response.status_code} {response.content}")
return response.json()
def create_test_from_plan(self, plan_id, test_name):
url = f"{self.api_url_base}api/runner"
payload = {"test": test_name, "plan": plan_id}
response = self.session.post(url, params=payload)
if response.status_code != Conformance.HTTP_CREATED:
raise Exception(
f"create_test_from_plan failed - HTTP {response.status_code} {response.content}"
)
return response.json()
def create_test_from_plan_with_variant(self, plan_id, test_name, variant):
url = f"{self.api_url_base}api/runner"
payload = {"test": test_name, "plan": plan_id}
if variant is not None:
payload["variant"] = json.dumps(variant)
response = self.session.post(url, params=payload)
if response.status_code != Conformance.HTTP_CREATED:
raise Exception(
"create_test_from_plan_with_variant failed - "
f"HTTP {response.status_code} {response.content}"
)
return response.json()
def get_module_info(self, module_id):
url = f"{self.api_url_base}api/info/{module_id}"
response = self.session.get(url)
if response.status_code != Conformance.HTTP_OK:
raise Exception(
f"get_module_info failed - HTTP {response.status_code} {response.content}"
)
return response.json()
def get_test_log(self, module_id):
url = f"{self.api_url_base}api/log/{module_id}"
response = self.session.get(url)
if response.status_code != Conformance.HTTP_OK:
raise Exception(f"get_test_log failed - HTTP {response.status_code} {response.content}")
return response.json()
def upload_image(self, log_id, placeholder, data):
url = f"{self.api_url_base}api/log/{log_id}/images/{placeholder}"
response = self.session.post(url, data=data, headers={"Content-Type": "text/plain"})
if response.status_code != Conformance.HTTP_OK:
raise Exception(f"upload_image failed - HTTP {response.status_code} {response.content}")
def start_test(self, module_id):
url = f"{self.api_url_base}api/runner/{module_id}"
response = self.session.post(url)
if response.status_code != Conformance.HTTP_OK:
raise Exception(f"start_test failed - HTTP {response.status_code} {response.content}")
return response.json()
def wait_for_state(self, module_id, required_states, timeout=240):
timeout_at = time.time() + timeout
while time.time() < timeout_at:
info = self.get_module_info(module_id)
status = info.get("status")
if status in required_states:
return status
if status == "INTERRUPTED":
raise Exception(f"Test module {module_id} has moved to INTERRUPTED")
time.sleep(1)
raise Exception(
f"Timed out waiting for test module {module_id} "
f"to be in one of states: {required_states}"
)

View File

@ -0,0 +1,10 @@
from tests.e2e.utils import retry
from tests.openid_conformance.base import TestOpenIDConformance
class TestOpenIDConformanceBasic(TestOpenIDConformance):
@retry()
def test_oidcc_basic_certification_test(self):
test_plan_name = "oidcc-basic-certification-test-plan"
self.run_test(test_plan_name, self.test_plan_config)

View File

@ -0,0 +1,10 @@
from tests.e2e.utils import retry
from tests.openid_conformance.base import TestOpenIDConformance
class TestOpenIDConformanceBasic(TestOpenIDConformance):
@retry()
def test_oidcc_basic_certification_test(self):
test_plan_name = "oidcc-basic-certification-test-plan"
self.run_test(test_plan_name, self.test_plan_config)

166
uv.lock generated
View File

@ -259,6 +259,7 @@ dev = [
{ name = "pytest-django" },
{ name = "pytest-github-actions-annotate-failures" },
{ name = "pytest-randomly" },
{ name = "pytest-subtests" },
{ name = "pytest-timeout" },
{ name = "requests-mock" },
{ name = "ruff" },
@ -279,10 +280,10 @@ requires-dist = [
{ name = "django-countries", specifier = "==7.6.1" },
{ name = "django-cte", specifier = "==2.0.0" },
{ name = "django-filter", specifier = "==25.1" },
{ name = "django-guardian", specifier = "==3.0.3" },
{ name = "django-guardian", specifier = "==3.0.0" },
{ name = "django-model-utils", specifier = "==5.0.0" },
{ name = "django-pglock", specifier = "==1.7.2" },
{ name = "django-prometheus", specifier = "==2.4.1" },
{ name = "django-prometheus", specifier = "==2.4.0" },
{ name = "django-redis", specifier = "==6.0.0" },
{ name = "django-storages", extras = ["s3"], specifier = "==1.14.6" },
{ name = "django-tenants", specifier = "==3.8.0" },
@ -298,7 +299,7 @@ requires-dist = [
{ name = "flower", specifier = "==2.0.1" },
{ name = "geoip2", specifier = "==5.1.0" },
{ name = "geopy", specifier = "==2.4.1" },
{ name = "google-api-python-client", specifier = "==2.174.0" },
{ name = "google-api-python-client", specifier = "==2.173.0" },
{ name = "gssapi", specifier = "==1.9.0" },
{ name = "gunicorn", specifier = "==23.0.0" },
{ name = "jsonpatch", specifier = "==1.33" },
@ -306,7 +307,7 @@ requires-dist = [
{ name = "kubernetes", specifier = "==33.1.0" },
{ name = "ldap3", specifier = "==2.9.1" },
{ name = "lxml", specifier = "==5.4.0" },
{ name = "msgraph-sdk", specifier = "==1.35.0" },
{ name = "msgraph-sdk", specifier = "==1.34.0" },
{ name = "opencontainers", git = "https://github.com/vsoch/oci-python?rev=ceb4fcc090851717a3069d78e85ceb1e86c2740c" },
{ name = "packaging", specifier = "==25.0" },
{ name = "paramiko", specifier = "==3.5.1" },
@ -319,7 +320,7 @@ requires-dist = [
{ name = "pyyaml", specifier = "==6.0.2" },
{ name = "requests-oauthlib", specifier = "==2.0.0" },
{ name = "scim2-filter-parser", specifier = "==0.7.0" },
{ name = "sentry-sdk", specifier = "==2.31.0" },
{ name = "sentry-sdk", specifier = "==2.30.0" },
{ name = "service-identity", specifier = "==24.2.0" },
{ name = "setproctitle", specifier = "==1.3.6" },
{ name = "structlog", specifier = "==25.4.0" },
@ -358,6 +359,7 @@ dev = [
{ name = "pytest-django", specifier = "==4.11.1" },
{ name = "pytest-github-actions-annotate-failures", specifier = "==0.3.0" },
{ name = "pytest-randomly", specifier = "==3.16.0" },
{ name = "pytest-subtests", specifier = ">=0.14.1" },
{ name = "pytest-timeout", specifier = "==2.4.0" },
{ name = "requests-mock", specifier = "==1.12.1" },
{ name = "ruff", specifier = "==0.11.9" },
@ -574,30 +576,30 @@ wheels = [
[[package]]
name = "boto3"
version = "1.38.43"
version = "1.38.38"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "botocore" },
{ name = "jmespath" },
{ name = "s3transfer" },
]
sdist = { url = "https://files.pythonhosted.org/packages/90/96/c99c9dac902faae3896558809d130b1bf02df8abb6e4553ad87d018910f9/boto3-1.38.43.tar.gz", hash = "sha256:9b0ff0b34c9cf7328546c532c20b081f09055ff485f4d57c19146c36877048c5", size = 111845, upload-time = "2025-06-24T19:29:02.978Z" }
sdist = { url = "https://files.pythonhosted.org/packages/98/a1/f2b68cba5d1907e004f4d88a028eda35a4f619c1e81d764e5cf58491eb46/boto3-1.38.38.tar.gz", hash = "sha256:0fe6b7d1974851588ec1edd39c66d9525d539133e02c7f985f9ebec5e222c0db", size = 111847, upload-time = "2025-06-17T19:33:03.097Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/de/67/42355b452a5aa622205c321217cba61a85746f0d93984788116a43120821/boto3-1.38.43-py3-none-any.whl", hash = "sha256:2e3411bb43285caad1c8e1a3186d025ba65a6342e26bad493f6b8feb3d1a1680", size = 139922, upload-time = "2025-06-24T19:29:01.545Z" },
{ url = "https://files.pythonhosted.org/packages/e4/dc/43d4ab839b84876bdf7baeba0a3ffcef4c3d52d81f3ce1979b4195c0e213/boto3-1.38.38-py3-none-any.whl", hash = "sha256:6f4163cd9e030afd1059e8a6daa178835165b79eb0b5325a8cd447020b895921", size = 139934, upload-time = "2025-06-17T19:33:00.621Z" },
]
[[package]]
name = "botocore"
version = "1.38.43"
version = "1.38.38"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "jmespath" },
{ name = "python-dateutil" },
{ name = "urllib3" },
]
sdist = { url = "https://files.pythonhosted.org/packages/1d/ff/8ace3f46fa1a32c09ee994b5401c7853613a283e134449fdc136bb753b40/botocore-1.38.43.tar.gz", hash = "sha256:c453c5c16c157c5427058bb3cc2c5ad35ee2e43336f0ccbfcc6092c5635505c6", size = 14044468, upload-time = "2025-06-24T19:28:52.803Z" }
sdist = { url = "https://files.pythonhosted.org/packages/22/f5/d05258ac4ae68769a956779192bfbd322e571ef9fc17a27f02d35c026b4b/botocore-1.38.38.tar.gz", hash = "sha256:acf9ae5b2d99c1f416f94fa5b4f8c044ecb76ffcb7fb1b1daec583f36892a8e2", size = 14009715, upload-time = "2025-06-17T19:32:52.705Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/15/12/0ebcfb91738d0cf9560220ee4e0db351acab14026fac74bbce9ab3881fd9/botocore-1.38.43-py3-none-any.whl", hash = "sha256:2ee60ac0b08e80e9be2aa2841d42e438d5bc4f82549560a682837655097a3db7", size = 13706448, upload-time = "2025-06-24T19:28:47.877Z" },
{ url = "https://files.pythonhosted.org/packages/7b/c6/74f27ffe941dc1438b7fef620b402b982a9f9ab90a04ee47bd0314a02384/botocore-1.38.38-py3-none-any.whl", hash = "sha256:aa5cc63bf885819d862852edb647d6276fe423c60113e8db375bb7ad8d88a5d9", size = 13669107, upload-time = "2025-06-17T19:32:47.503Z" },
]
[[package]]
@ -777,14 +779,14 @@ wheels = [
[[package]]
name = "click-plugins"
version = "1.1.1.2"
version = "1.1.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "click" },
]
sdist = { url = "https://files.pythonhosted.org/packages/c3/a4/34847b59150da33690a36da3681d6bbc2ec14ee9a846bc30a6746e5984e4/click_plugins-1.1.1.2.tar.gz", hash = "sha256:d7af3984a99d243c131aa1a828331e7630f4a88a9741fd05c927b204bcf92261", size = 8343, upload-time = "2025-06-25T00:47:37.555Z" }
sdist = { url = "https://files.pythonhosted.org/packages/5f/1d/45434f64ed749540af821fd7e42b8e4d23ac04b1eda7c26613288d6cd8a8/click-plugins-1.1.1.tar.gz", hash = "sha256:46ab999744a9d831159c3411bb0c79346d94a444df9a3a3742e9ed63645f264b", size = 8164, upload-time = "2019-04-04T04:27:04.82Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/3d/9a/2abecb28ae875e39c8cad711eb1186d8d14eab564705325e77e4e6ab9ae5/click_plugins-1.1.1.2-py2.py3-none-any.whl", hash = "sha256:008d65743833ffc1f5417bf0e78e8d2c23aab04d9745ba817bd3e71b0feb6aa6", size = 11051, upload-time = "2025-06-25T00:47:36.731Z" },
{ url = "https://files.pythonhosted.org/packages/e9/da/824b92d9942f4e472702488857914bdd50f73021efea15b4cad9aca8ecef/click_plugins-1.1.1-py2.py3-none-any.whl", hash = "sha256:5d262006d3222f5057fd81e1623d4443e41dcda5dc815c06b442aa3c02889fc8", size = 7497, upload-time = "2019-04-04T04:27:03.36Z" },
]
[[package]]
@ -1021,14 +1023,14 @@ wheels = [
[[package]]
name = "django-guardian"
version = "3.0.3"
version = "3.0.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "django" },
]
sdist = { url = "https://files.pythonhosted.org/packages/30/c2/3ed43813dd7313f729dbaa829b4f9ed4a647530151f672cfb5f843c12edf/django_guardian-3.0.3.tar.gz", hash = "sha256:4e59eab4d836da5a027cf0c176d14bc2a4e22cbbdf753159a03946c08c8a196d", size = 85410, upload-time = "2025-06-25T20:42:17.475Z" }
sdist = { url = "https://files.pythonhosted.org/packages/30/82/2c76cdf77eae3cb0c3df394686daf8f84bcd604c0da7a26fa19f5fe74ed4/django_guardian-3.0.0.tar.gz", hash = "sha256:0c79d55c4af2cfc14fbd19539846a1ebfed2a38198b7697e0f5177b7f654e1cd", size = 79895, upload-time = "2025-05-07T19:33:23.328Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/8b/13/e6f629a978ef5fab8b8d2760cacc3e451016cef952cf4c049d672c5c6b07/django_guardian-3.0.3-py3-none-any.whl", hash = "sha256:d2164cea9f03c369d7ade21802710f3ab23ca6734bcc7dfcfb385906783916c7", size = 118198, upload-time = "2025-06-25T20:42:15.377Z" },
{ url = "https://files.pythonhosted.org/packages/a5/81/a2f3d3245d1f4cf446d78863526fba0b1b140d60784095a5cc2d4e8ac709/django_guardian-3.0.0-py3-none-any.whl", hash = "sha256:f3ebe3cc7f486e267041b780c3429ad5db72c909df40c2f74adb1b059582a3cd", size = 112672, upload-time = "2025-05-07T19:33:21.719Z" },
]
[[package]]
@ -1070,15 +1072,14 @@ wheels = [
[[package]]
name = "django-prometheus"
version = "2.4.1"
version = "2.4.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "django" },
{ name = "prometheus-client" },
]
sdist = { url = "https://files.pythonhosted.org/packages/98/f4/cb39ddd2a41e07a274c4e162c076e906ae232d63b66bbabdea0300878877/django_prometheus-2.4.1.tar.gz", hash = "sha256:073628243d2a6de6a8a8c20e5b512872dfb85d66e1b60b28bcf1eca0155dad95", size = 24464, upload-time = "2025-06-25T15:45:37.149Z" }
sdist = { url = "https://files.pythonhosted.org/packages/e8/b9/c758675671d71a1800feaad5c5fbcdecbd8d34296b63f9dc5662db39abda/django_prometheus-2.4.0.tar.gz", hash = "sha256:67da5c73d8e859aa73f6e11f52341c482691b17f8bd9844157cff6cdf51ce9bc", size = 24393, upload-time = "2025-06-18T18:06:28.673Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/01/50/9c5e022fa92574e5d20606687f15a2aa255e10512a17d11a8216fa117f72/django_prometheus-2.4.1-py2.py3-none-any.whl", hash = "sha256:7fe5af7f7c9ad9cd8a429fe0f3f1bf651f0e244f77162147869eab7ec09cc5e7", size = 29541, upload-time = "2025-06-25T15:45:35.433Z" },
{ url = "https://files.pythonhosted.org/packages/38/05/d980950fb8c3f6f96c644599b1a025fb50e827477b1acf36daef72aa7e76/django_prometheus-2.4.0-py2.py3-none-any.whl", hash = "sha256:5b46b5f07b02ba8dd7abdb03a3c39073e8fd9120e2293a1ecb949bbb865378ac", size = 29528, upload-time = "2025-06-18T18:06:27.079Z" },
]
[[package]]
@ -1403,7 +1404,7 @@ wheels = [
[[package]]
name = "google-api-python-client"
version = "2.174.0"
version = "2.173.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "google-api-core" },
@ -1412,9 +1413,9 @@ dependencies = [
{ name = "httplib2" },
{ name = "uritemplate" },
]
sdist = { url = "https://files.pythonhosted.org/packages/1a/fd/860fef0cf3edbad828e2ab4d2ddee5dfe8e595b6da748ac6c77e95bc7bef/google_api_python_client-2.174.0.tar.gz", hash = "sha256:9eb7616a820b38a9c12c5486f9b9055385c7feb18b20cbafc5c5a688b14f3515", size = 13127872, upload-time = "2025-06-25T19:27:12.977Z" }
sdist = { url = "https://files.pythonhosted.org/packages/8f/7e/7c6e43e54f611f0f97f1678ea567fe06fecd545bd574db05e204e5b136fe/google_api_python_client-2.173.0.tar.gz", hash = "sha256:b537bc689758f4be3e6f40d59a6c0cd305abafdea91af4bc66ec31d40c08c804", size = 13091318, upload-time = "2025-06-19T19:39:05.881Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/16/2d/4250b81e8f5309b58650660f403584db6f64067acac74475893a8f33348d/google_api_python_client-2.174.0-py3-none-any.whl", hash = "sha256:f695205ceec97bfaa1590a14282559c4109326c473b07352233a3584cdbf4b89", size = 13650466, upload-time = "2025-06-25T19:27:10.426Z" },
{ url = "https://files.pythonhosted.org/packages/e6/c9/dc9ca0537ee2ddac0f0b1e458903afe3f490a0f90dfd4b1b16eb339cdfbb/google_api_python_client-2.173.0-py3-none-any.whl", hash = "sha256:16a8e81c772dd116f5c4ee47d83643149e1367dc8fb4f47cb471fbcb5c7d7ac7", size = 13612778, upload-time = "2025-06-19T19:39:03.283Z" },
]
[[package]]
@ -2072,7 +2073,7 @@ wheels = [
[[package]]
name = "msgraph-sdk"
version = "1.35.0"
version = "1.34.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "azure-identity" },
@ -2082,50 +2083,54 @@ dependencies = [
{ name = "microsoft-kiota-serialization-text" },
{ name = "msgraph-core" },
]
sdist = { url = "https://files.pythonhosted.org/packages/33/49/25df000defb136542400bbe3096b3e1dab384e5b02fec4c6c4cb4a433296/msgraph_sdk-1.35.0.tar.gz", hash = "sha256:513f77d3332618af35d2f456ff26e2050f136abc8856858a69d63e811480eddd", size = 5967030, upload-time = "2025-06-25T10:28:30.599Z" }
sdist = { url = "https://files.pythonhosted.org/packages/92/7a/c69b4fc4b9c02a6d14eddc96b91319dd7e91f0987245d4243a74b9c17fcf/msgraph_sdk-1.34.0.tar.gz", hash = "sha256:f71a81d3291f49d3610220de47bbbb6321aa62f7129d17a958f301b9acadfe99", size = 5968516, upload-time = "2025-06-18T11:43:33.287Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/72/ae/a0ea8742af0c99c9f53d82bca19f027f10d747874f725fa2f8d165eb60b3/msgraph_sdk-1.35.0-py3-none-any.whl", hash = "sha256:0e2305a0d6d8343f3a29aa227183c6acc6191f4dfda8522ea41d97e7fe25a0d1", size = 24490922, upload-time = "2025-06-25T10:28:28.127Z" },
{ url = "https://files.pythonhosted.org/packages/f2/0c/75f8066eca60fe9b2d5e1dd868b592533671b7b5cc711e655afd5c44d259/msgraph_sdk-1.34.0-py3-none-any.whl", hash = "sha256:d6daea012b78a7a4dd07fabb782ae00e4a9fe4f8d6016e8037769962533aa8ae", size = 24491410, upload-time = "2025-06-18T11:43:30.824Z" },
]
[[package]]
name = "multidict"
version = "6.5.1"
version = "6.5.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/5c/43/2d90c414d9efc4587d6e7cebae9f2c2d8001bcb4f89ed514ae837e9dcbe6/multidict-6.5.1.tar.gz", hash = "sha256:a835ea8103f4723915d7d621529c80ef48db48ae0c818afcabe0f95aa1febc3a", size = 98690, upload-time = "2025-06-24T22:16:05.117Z" }
sdist = { url = "https://files.pythonhosted.org/packages/46/b5/59f27b4ce9951a4bce56b88ba5ff5159486797ab18863f2b4c1c5e8465bd/multidict-6.5.0.tar.gz", hash = "sha256:942bd8002492ba819426a8d7aefde3189c1b87099cdf18aaaefefcf7f3f7b6d2", size = 98512, upload-time = "2025-06-17T14:15:56.556Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/19/3f/c2e07031111d2513d260157933a8697ad52a935d8a2a2b8b7b317ddd9a96/multidict-6.5.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:98011312f36d1e496f15454a95578d1212bc2ffc25650a8484752b06d304fd9b", size = 73588, upload-time = "2025-06-24T22:14:54.332Z" },
{ url = "https://files.pythonhosted.org/packages/95/bb/f47aa21827202a9f889fd66de9a1db33d0e4bbaaa2567156e4efb3cc0e5e/multidict-6.5.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:bae589fb902b47bd94e6f539b34eefe55a1736099f616f614ec1544a43f95b05", size = 43756, upload-time = "2025-06-24T22:14:55.748Z" },
{ url = "https://files.pythonhosted.org/packages/9f/ec/24549de092c9b0bc3167e0beb31a11be58e8595dbcfed2b7821795bb3923/multidict-6.5.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6eb3bf26cd94eb306e4bc776d0964cc67a7967e4ad9299309f0ff5beec3c62be", size = 42222, upload-time = "2025-06-24T22:14:57.418Z" },
{ url = "https://files.pythonhosted.org/packages/13/45/54452027ebc0ba660667aab67ae11afb9aaba91f4b5d63cddef045279d94/multidict-6.5.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e5e1a5a99c72d1531501406fcc06b6bf699ebd079dacd6807bb43fc0ff260e5c", size = 253014, upload-time = "2025-06-24T22:14:58.738Z" },
{ url = "https://files.pythonhosted.org/packages/97/3c/76e7b4c0ce3a8bb43efca679674fba421333fbc8429134072db80e13dcb8/multidict-6.5.1-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:38755bcba18720cb2338bea23a5afcff234445ee75fa11518f6130e22f2ab970", size = 235939, upload-time = "2025-06-24T22:15:00.138Z" },
{ url = "https://files.pythonhosted.org/packages/86/ce/48e3123a9af61ff2f60e3764b0b15cf4fca22b1299aac281252ac3a590d6/multidict-6.5.1-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f42fef9bcba3c32fd4e4a23c5757fc807d218b249573aaffa8634879f95feb73", size = 262940, upload-time = "2025-06-24T22:15:01.52Z" },
{ url = "https://files.pythonhosted.org/packages/b3/ab/bccd739faf87051b55df619a0967c8545b4d4a4b90258c5f564ab1752f15/multidict-6.5.1-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:071b962f4cc87469cda90c7cc1c077b76496878b39851d7417a3d994e27fe2c6", size = 260652, upload-time = "2025-06-24T22:15:02.988Z" },
{ url = "https://files.pythonhosted.org/packages/9a/9c/01f654aad28a5d0d74f2678c1541ae15e711f99603fd84c780078205966e/multidict-6.5.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:627ba4b7ce7c0115981f0fd91921f5d101dfb9972622178aeef84ccce1c2bbf3", size = 250011, upload-time = "2025-06-24T22:15:04.317Z" },
{ url = "https://files.pythonhosted.org/packages/5c/bc/edf08906e1db7385c6bf36e4179957307f50c44a889493e9b251255be79c/multidict-6.5.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:05dcaed3e5e54f0d0f99a39762b0195274b75016cbf246f600900305581cf1a2", size = 248242, upload-time = "2025-06-24T22:15:06.035Z" },
{ url = "https://files.pythonhosted.org/packages/b7/c3/1ad054b88b889fda8b62ea9634ac7082567e8dc42b9b794a2c565ef102ab/multidict-6.5.1-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:11f5ecf3e741a18c578d118ad257c5588ca33cc7c46d51c0487d7ae76f072c32", size = 244683, upload-time = "2025-06-24T22:15:07.731Z" },
{ url = "https://files.pythonhosted.org/packages/57/63/119a76b2095e1bb765816175cafeac7b520f564691abef2572fb80f4f246/multidict-6.5.1-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:b948eb625411c20b15088fca862c51a39140b9cf7875b5fb47a72bb249fa2f42", size = 257626, upload-time = "2025-06-24T22:15:09.013Z" },
{ url = "https://files.pythonhosted.org/packages/26/a9/b91a76af5ff49bd088ee76d11eb6134227f5ea50bcd5f6738443b2fe8e05/multidict-6.5.1-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:fc993a96dfc8300befd03d03df46efdb1d8d5a46911b014e956a4443035f470d", size = 251077, upload-time = "2025-06-24T22:15:10.366Z" },
{ url = "https://files.pythonhosted.org/packages/2a/fe/b1dc57aaa4de9f5a27543e28bd1f8bff00a316888b7344b5d33258b14b0a/multidict-6.5.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ee2d333380f22d35a56c6461f4579cfe186e143cd0b010b9524ac027de2a34cd", size = 244715, upload-time = "2025-06-24T22:15:11.76Z" },
{ url = "https://files.pythonhosted.org/packages/51/55/47a82690f71d0141eea49a623bbcc00a4d28770efc7cba8ead75602c9b90/multidict-6.5.1-cp313-cp313-win32.whl", hash = "sha256:5891e3327e6a426ddd443c87339b967c84feb8c022dd425e0c025fa0fcd71e68", size = 41156, upload-time = "2025-06-24T22:15:13.139Z" },
{ url = "https://files.pythonhosted.org/packages/25/b3/43306e4d7d3a9898574d1dc156b9607540dad581b1d767c992030751b82d/multidict-6.5.1-cp313-cp313-win_amd64.whl", hash = "sha256:fcdaa72261bff25fad93e7cb9bd7112bd4bac209148e698e380426489d8ed8a9", size = 44933, upload-time = "2025-06-24T22:15:14.639Z" },
{ url = "https://files.pythonhosted.org/packages/30/e2/34cb83c8a4e01b28e2abf30dc90178aa63c9db042be22fa02472cb744b86/multidict-6.5.1-cp313-cp313-win_arm64.whl", hash = "sha256:84292145303f354a35558e601c665cdf87059d87b12777417e2e57ba3eb98903", size = 41967, upload-time = "2025-06-24T22:15:15.856Z" },
{ url = "https://files.pythonhosted.org/packages/64/08/17d2de9cf749ea9589ecfb7532ab4988e8b113b7624826dba6b7527a58f3/multidict-6.5.1-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:f8316e58db799a1972afbc46770dfaaf20b0847003ab80de6fcb9861194faa3f", size = 80513, upload-time = "2025-06-24T22:15:16.946Z" },
{ url = "https://files.pythonhosted.org/packages/3e/b9/c9392465a21f7dff164633348b4cf66eef55c4ee48bdcdc00f0a71792779/multidict-6.5.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:d3468f0db187aca59eb56e0aa9f7c8c5427bcb844ad1c86557b4886aeb4484d8", size = 46854, upload-time = "2025-06-24T22:15:18.116Z" },
{ url = "https://files.pythonhosted.org/packages/2e/24/d79cbed5d0573304bc907dff0e5ad8788a4de891eec832809812b319930e/multidict-6.5.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:228533a5f99f1248cd79f6470779c424d63bc3e10d47c82511c65cc294458445", size = 45724, upload-time = "2025-06-24T22:15:19.241Z" },
{ url = "https://files.pythonhosted.org/packages/ec/22/232be6c077183719c78131f0e3c3d7134eb2d839e6e50e1c1e69e5ef5965/multidict-6.5.1-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:527076fdf5854901b1246c589af9a8a18b4a308375acb0020b585f696a10c794", size = 251895, upload-time = "2025-06-24T22:15:20.564Z" },
{ url = "https://files.pythonhosted.org/packages/57/80/85985e1441864b946e79538355b7b47f36206bf6bbaa2fa6d74d8232f2ab/multidict-6.5.1-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:9a17a17bad5c22f43e6a6b285dd9c16b1e8f8428202cd9bc22adaac68d0bbfed", size = 229357, upload-time = "2025-06-24T22:15:21.949Z" },
{ url = "https://files.pythonhosted.org/packages/b1/14/0024d1428b05aedaeea211da232aa6b6ad5c556a8a38b0942df1e54e1fa5/multidict-6.5.1-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:efd1951edab4a6cb65108d411867811f2b283f4b972337fb4269e40142f7f6a6", size = 259262, upload-time = "2025-06-24T22:15:23.455Z" },
{ url = "https://files.pythonhosted.org/packages/b1/cc/3fe63d61ffc9a48d62f36249e228e330144d990ac01f61169b615a3be471/multidict-6.5.1-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c07d5f38b39acb4f8f61a7aa4166d140ed628245ff0441630df15340532e3b3c", size = 257998, upload-time = "2025-06-24T22:15:24.907Z" },
{ url = "https://files.pythonhosted.org/packages/e8/e4/46b38b9a565ccc5d86f55787090670582d51ab0a0d37cfeaf4313b053f7b/multidict-6.5.1-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8a6605dc74cd333be279e1fcb568ea24f7bdf1cf09f83a77360ce4dd32d67f14", size = 247951, upload-time = "2025-06-24T22:15:26.274Z" },
{ url = "https://files.pythonhosted.org/packages/af/78/58a9bc0674401f1f26418cd58a5ebf35ce91ead76a22b578908acfe0f4e2/multidict-6.5.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:8d64e30ae9ba66ce303a567548a06d64455d97c5dff7052fe428d154274d7174", size = 246786, upload-time = "2025-06-24T22:15:27.695Z" },
{ url = "https://files.pythonhosted.org/packages/66/24/51142ccee295992e22881cccc54b291308423bbcc836fcf4d2edef1a88d0/multidict-6.5.1-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:2fb5dde79a7f6d98ac5e26a4c9de77ccd2c5224a7ce89aeac6d99df7bbe06464", size = 235030, upload-time = "2025-06-24T22:15:29.391Z" },
{ url = "https://files.pythonhosted.org/packages/4b/9a/a6f7b75460d3e35b16bf7745c9e3ebb3293324a4295e586563bf50d361f4/multidict-6.5.1-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:8a0d22e8b07cf620e9aeb1582340d00f0031e6a1f3e39d9c2dcbefa8691443b4", size = 253964, upload-time = "2025-06-24T22:15:31.689Z" },
{ url = "https://files.pythonhosted.org/packages/3d/f8/0b690674bf8f78604eb0a2b0a85d1380ff3003f270440d40def2a3de8cf4/multidict-6.5.1-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:0120ed5cff2082c7a0ed62a8f80f4f6ac266010c722381816462f279bfa19487", size = 247370, upload-time = "2025-06-24T22:15:33.114Z" },
{ url = "https://files.pythonhosted.org/packages/7f/7d/ca55049d1041c517f294c1755c786539cb7a8dc5033361f20ce3a3d817be/multidict-6.5.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:3dea06ba27401c4b54317aa04791182dc9295e7aa623732dd459071a0e0f65db", size = 242920, upload-time = "2025-06-24T22:15:34.669Z" },
{ url = "https://files.pythonhosted.org/packages/1e/65/f4afa14f0921751864bb3ef80267f15ecae423483e8da9bc5d3757632bfa/multidict-6.5.1-cp313-cp313t-win32.whl", hash = "sha256:93b21be44f3cfee3be68ed5cd8848a3c0420d76dbd12d74f7776bde6b29e5f33", size = 46968, upload-time = "2025-06-24T22:15:36.023Z" },
{ url = "https://files.pythonhosted.org/packages/00/0a/13d08be1ca1523df515fb4efd3cf10f153e62d533f55c53f543cd73041e8/multidict-6.5.1-cp313-cp313t-win_amd64.whl", hash = "sha256:c5c18f8646a520cc34d00f65f9f6f77782b8a8c59fd8de10713e0de7f470b5d0", size = 52353, upload-time = "2025-06-24T22:15:37.247Z" },
{ url = "https://files.pythonhosted.org/packages/4b/dd/84aaf725b236677597a9570d8c1c99af0ba03712149852347969e014d826/multidict-6.5.1-cp313-cp313t-win_arm64.whl", hash = "sha256:eb27128141474a1d545f0531b496c7c2f1c4beff50cb5a828f36eb62fef16c67", size = 44500, upload-time = "2025-06-24T22:15:38.445Z" },
{ url = "https://files.pythonhosted.org/packages/07/9f/d4719ce55a1d8bf6619e8bb92f1e2e7399026ea85ae0c324ec77ee06c050/multidict-6.5.1-py3-none-any.whl", hash = "sha256:895354f4a38f53a1df2cc3fa2223fa714cff2b079a9f018a76cad35e7f0f044c", size = 12185, upload-time = "2025-06-24T22:16:03.816Z" },
{ url = "https://files.pythonhosted.org/packages/1a/c9/092c4e9402b6d16de761cff88cb842a5c8cc50ccecaf9c4481ba53264b9e/multidict-6.5.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:53d92df1752df67a928fa7f884aa51edae6f1cf00eeb38cbcf318cf841c17456", size = 73486, upload-time = "2025-06-17T14:14:37.238Z" },
{ url = "https://files.pythonhosted.org/packages/08/f9/6f7ddb8213f5fdf4db48d1d640b78e8aef89b63a5de8a2313286db709250/multidict-6.5.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:680210de2c38eef17ce46b8df8bf2c1ece489261a14a6e43c997d49843a27c99", size = 43745, upload-time = "2025-06-17T14:14:38.32Z" },
{ url = "https://files.pythonhosted.org/packages/f3/a7/b9be0163bfeee3bb08a77a1705e24eb7e651d594ea554107fac8a1ca6a4d/multidict-6.5.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e279259bcb936732bfa1a8eec82b5d2352b3df69d2fa90d25808cfc403cee90a", size = 42135, upload-time = "2025-06-17T14:14:39.897Z" },
{ url = "https://files.pythonhosted.org/packages/8e/30/93c8203f943a417bda3c573a34d5db0cf733afdfffb0ca78545c7716dbd8/multidict-6.5.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d1c185fc1069781e3fc8b622c4331fb3b433979850392daa5efbb97f7f9959bb", size = 238585, upload-time = "2025-06-17T14:14:41.332Z" },
{ url = "https://files.pythonhosted.org/packages/9d/fe/2582b56a1807604774f566eeef183b0d6b148f4b89d1612cd077567b2e1e/multidict-6.5.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:6bb5f65ff91daf19ce97f48f63585e51595539a8a523258b34f7cef2ec7e0617", size = 236174, upload-time = "2025-06-17T14:14:42.602Z" },
{ url = "https://files.pythonhosted.org/packages/9b/c4/d8b66d42d385bd4f974cbd1eaa8b265e6b8d297249009f312081d5ded5c7/multidict-6.5.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d8646b4259450c59b9286db280dd57745897897284f6308edbdf437166d93855", size = 250145, upload-time = "2025-06-17T14:14:43.944Z" },
{ url = "https://files.pythonhosted.org/packages/bc/64/62feda5093ee852426aae3df86fab079f8bf1cdbe403e1078c94672ad3ec/multidict-6.5.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d245973d4ecc04eea0a8e5ebec7882cf515480036e1b48e65dffcfbdf86d00be", size = 243470, upload-time = "2025-06-17T14:14:45.343Z" },
{ url = "https://files.pythonhosted.org/packages/67/dc/9f6fa6e854625cf289c0e9f4464b40212a01f76b2f3edfe89b6779b4fb93/multidict-6.5.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a133e7ddc9bc7fb053733d0ff697ce78c7bf39b5aec4ac12857b6116324c8d75", size = 236968, upload-time = "2025-06-17T14:14:46.609Z" },
{ url = "https://files.pythonhosted.org/packages/46/ae/4b81c6e3745faee81a156f3f87402315bdccf04236f75c03e37be19c94ff/multidict-6.5.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:80d696fa38d738fcebfd53eec4d2e3aeb86a67679fd5e53c325756682f152826", size = 236575, upload-time = "2025-06-17T14:14:47.929Z" },
{ url = "https://files.pythonhosted.org/packages/8a/fa/4089d7642ea344226e1bfab60dd588761d4791754f8072e911836a39bedf/multidict-6.5.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:20d30c9410ac3908abbaa52ee5967a754c62142043cf2ba091e39681bd51d21a", size = 247632, upload-time = "2025-06-17T14:14:49.525Z" },
{ url = "https://files.pythonhosted.org/packages/16/ee/a353dac797de0f28fb7f078cc181c5f2eefe8dd16aa11a7100cbdc234037/multidict-6.5.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:6c65068cc026f217e815fa519d8e959a7188e94ec163ffa029c94ca3ef9d4a73", size = 243520, upload-time = "2025-06-17T14:14:50.83Z" },
{ url = "https://files.pythonhosted.org/packages/50/ec/560deb3d2d95822d6eb1bcb1f1cb728f8f0197ec25be7c936d5d6a5d133c/multidict-6.5.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:e355ac668a8c3e49c2ca8daa4c92f0ad5b705d26da3d5af6f7d971e46c096da7", size = 248551, upload-time = "2025-06-17T14:14:52.229Z" },
{ url = "https://files.pythonhosted.org/packages/10/85/ddf277e67c78205f6695f2a7639be459bca9cc353b962fd8085a492a262f/multidict-6.5.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:08db204213d0375a91a381cae0677ab95dd8c67a465eb370549daf6dbbf8ba10", size = 258362, upload-time = "2025-06-17T14:14:53.934Z" },
{ url = "https://files.pythonhosted.org/packages/02/fc/d64ee1df9b87c5210f2d4c419cab07f28589c81b4e5711eda05a122d0614/multidict-6.5.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:ffa58e3e215af8f6536dc837a990e456129857bb6fd546b3991be470abd9597a", size = 253862, upload-time = "2025-06-17T14:14:55.323Z" },
{ url = "https://files.pythonhosted.org/packages/c9/7c/a2743c00d9e25f4826d3a77cc13d4746398872cf21c843eef96bb9945665/multidict-6.5.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:3e86eb90015c6f21658dbd257bb8e6aa18bdb365b92dd1fba27ec04e58cdc31b", size = 247391, upload-time = "2025-06-17T14:14:57.293Z" },
{ url = "https://files.pythonhosted.org/packages/9b/03/7773518db74c442904dbd349074f1e7f2a854cee4d9529fc59e623d3949e/multidict-6.5.0-cp313-cp313-win32.whl", hash = "sha256:f34a90fbd9959d0f857323bd3c52b3e6011ed48f78d7d7b9e04980b8a41da3af", size = 41115, upload-time = "2025-06-17T14:14:59.33Z" },
{ url = "https://files.pythonhosted.org/packages/eb/9a/6fc51b1dc11a7baa944bc101a92167d8b0f5929d376a8c65168fc0d35917/multidict-6.5.0-cp313-cp313-win_amd64.whl", hash = "sha256:fcb2aa79ac6aef8d5b709bbfc2fdb1d75210ba43038d70fbb595b35af470ce06", size = 44768, upload-time = "2025-06-17T14:15:00.427Z" },
{ url = "https://files.pythonhosted.org/packages/82/2d/0d010be24b663b3c16e3d3307bbba2de5ae8eec496f6027d5c0515b371a8/multidict-6.5.0-cp313-cp313-win_arm64.whl", hash = "sha256:6dcee5e7e92060b4bb9bb6f01efcbb78c13d0e17d9bc6eec71660dd71dc7b0c2", size = 41770, upload-time = "2025-06-17T14:15:01.854Z" },
{ url = "https://files.pythonhosted.org/packages/aa/d1/a71711a5f32f84b7b036e82182e3250b949a0ce70d51a2c6a4079e665449/multidict-6.5.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:cbbc88abea2388fde41dd574159dec2cda005cb61aa84950828610cb5010f21a", size = 80450, upload-time = "2025-06-17T14:15:02.968Z" },
{ url = "https://files.pythonhosted.org/packages/0f/a2/953a9eede63a98fcec2c1a2c1a0d88de120056219931013b871884f51b43/multidict-6.5.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:70b599f70ae6536e5976364d3c3cf36f40334708bd6cebdd1e2438395d5e7676", size = 46971, upload-time = "2025-06-17T14:15:04.149Z" },
{ url = "https://files.pythonhosted.org/packages/44/61/60250212953459edda2c729e1d85130912f23c67bd4f585546fe4bdb1578/multidict-6.5.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:828bab777aa8d29d59700018178061854e3a47727e0611cb9bec579d3882de3b", size = 45548, upload-time = "2025-06-17T14:15:05.666Z" },
{ url = "https://files.pythonhosted.org/packages/11/b6/e78ee82e96c495bc2582b303f68bed176b481c8d81a441fec07404fce2ca/multidict-6.5.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a9695fc1462f17b131c111cf0856a22ff154b0480f86f539d24b2778571ff94d", size = 238545, upload-time = "2025-06-17T14:15:06.88Z" },
{ url = "https://files.pythonhosted.org/packages/5a/0f/6132ca06670c8d7b374c3a4fd1ba896fc37fbb66b0de903f61db7d1020ec/multidict-6.5.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:0b5ac6ebaf5d9814b15f399337ebc6d3a7f4ce9331edd404e76c49a01620b68d", size = 229931, upload-time = "2025-06-17T14:15:08.24Z" },
{ url = "https://files.pythonhosted.org/packages/c0/63/d9957c506e6df6b3e7a194f0eea62955c12875e454b978f18262a65d017b/multidict-6.5.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84a51e3baa77ded07be4766a9e41d977987b97e49884d4c94f6d30ab6acaee14", size = 248181, upload-time = "2025-06-17T14:15:09.907Z" },
{ url = "https://files.pythonhosted.org/packages/43/3f/7d5490579640db5999a948e2c41d4a0efd91a75989bda3e0a03a79c92be2/multidict-6.5.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8de67f79314d24179e9b1869ed15e88d6ba5452a73fc9891ac142e0ee018b5d6", size = 241846, upload-time = "2025-06-17T14:15:11.596Z" },
{ url = "https://files.pythonhosted.org/packages/e1/f7/252b1ce949ece52bba4c0de7aa2e3a3d5964e800bce71fb778c2e6c66f7c/multidict-6.5.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17f78a52c214481d30550ec18208e287dfc4736f0c0148208334b105fd9e0887", size = 232893, upload-time = "2025-06-17T14:15:12.946Z" },
{ url = "https://files.pythonhosted.org/packages/45/7e/0070bfd48c16afc26e056f2acce49e853c0d604a69c7124bc0bbdb1bcc0a/multidict-6.5.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2966d0099cb2e2039f9b0e73e7fd5eb9c85805681aa2a7f867f9d95b35356921", size = 228567, upload-time = "2025-06-17T14:15:14.267Z" },
{ url = "https://files.pythonhosted.org/packages/2a/31/90551c75322113ebf5fd9c5422e8641d6952f6edaf6b6c07fdc49b1bebdd/multidict-6.5.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:86fb42ed5ed1971c642cc52acc82491af97567534a8e381a8d50c02169c4e684", size = 246188, upload-time = "2025-06-17T14:15:15.985Z" },
{ url = "https://files.pythonhosted.org/packages/cc/e2/aa4b02a55e7767ff292871023817fe4db83668d514dab7ccbce25eaf7659/multidict-6.5.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:4e990cbcb6382f9eae4ec720bcac6a1351509e6fc4a5bb70e4984b27973934e6", size = 235178, upload-time = "2025-06-17T14:15:17.395Z" },
{ url = "https://files.pythonhosted.org/packages/7d/5c/f67e726717c4b138b166be1700e2b56e06fbbcb84643d15f9a9d7335ff41/multidict-6.5.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:d99a59d64bb1f7f2117bec837d9e534c5aeb5dcedf4c2b16b9753ed28fdc20a3", size = 243422, upload-time = "2025-06-17T14:15:18.939Z" },
{ url = "https://files.pythonhosted.org/packages/e5/1c/15fa318285e26a50aa3fa979bbcffb90f9b4d5ec58882d0590eda067d0da/multidict-6.5.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:e8ef15cc97c9890212e1caf90f0d63f6560e1e101cf83aeaf63a57556689fb34", size = 254898, upload-time = "2025-06-17T14:15:20.31Z" },
{ url = "https://files.pythonhosted.org/packages/ad/3d/d6c6d1c2e9b61ca80313912d30bb90d4179335405e421ef0a164eac2c0f9/multidict-6.5.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:b8a09aec921b34bd8b9f842f0bcfd76c6a8c033dc5773511e15f2d517e7e1068", size = 247129, upload-time = "2025-06-17T14:15:21.665Z" },
{ url = "https://files.pythonhosted.org/packages/29/15/1568258cf0090bfa78d44be66247cfdb16e27dfd935c8136a1e8632d3057/multidict-6.5.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ff07b504c23b67f2044533244c230808a1258b3493aaf3ea2a0785f70b7be461", size = 243841, upload-time = "2025-06-17T14:15:23.38Z" },
{ url = "https://files.pythonhosted.org/packages/65/57/64af5dbcfd61427056e840c8e520b502879d480f9632fbe210929fd87393/multidict-6.5.0-cp313-cp313t-win32.whl", hash = "sha256:9232a117341e7e979d210e41c04e18f1dc3a1d251268df6c818f5334301274e1", size = 46761, upload-time = "2025-06-17T14:15:24.733Z" },
{ url = "https://files.pythonhosted.org/packages/26/a8/cac7f7d61e188ff44f28e46cb98f9cc21762e671c96e031f06c84a60556e/multidict-6.5.0-cp313-cp313t-win_amd64.whl", hash = "sha256:44cb5c53fb2d4cbcee70a768d796052b75d89b827643788a75ea68189f0980a1", size = 52112, upload-time = "2025-06-17T14:15:25.906Z" },
{ url = "https://files.pythonhosted.org/packages/51/9f/076533feb1b5488d22936da98b9c217205cfbf9f56f7174e8c5c86d86fe6/multidict-6.5.0-cp313-cp313t-win_arm64.whl", hash = "sha256:51d33fafa82640c0217391d4ce895d32b7e84a832b8aee0dcc1b04d8981ec7f4", size = 44358, upload-time = "2025-06-17T14:15:27.117Z" },
{ url = "https://files.pythonhosted.org/packages/44/d8/45e8fc9892a7386d074941429e033adb4640e59ff0780d96a8cf46fe788e/multidict-6.5.0-py3-none-any.whl", hash = "sha256:5634b35f225977605385f56153bd95a7133faffc0ffe12ad26e10517537e8dfc", size = 12181, upload-time = "2025-06-17T14:15:55.156Z" },
]
[[package]]
@ -2148,11 +2153,11 @@ wheels = [
[[package]]
name = "oauthlib"
version = "3.3.1"
version = "3.3.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/0b/5f/19930f824ffeb0ad4372da4812c50edbd1434f678c90c2733e1188edfc63/oauthlib-3.3.1.tar.gz", hash = "sha256:0f0f8aa759826a193cf66c12ea1af1637f87b9b4622d46e866952bb022e538c9", size = 185918, upload-time = "2025-06-19T22:48:08.269Z" }
sdist = { url = "https://files.pythonhosted.org/packages/98/8a/6ea75ff7acf89f43afb157604429af4661a9840b1f2cece602b6a13c1893/oauthlib-3.3.0.tar.gz", hash = "sha256:4e707cf88d7dfc22a8cce22ca736a2eef9967c1dd3845efc0703fc922353eeb2", size = 190292, upload-time = "2025-06-17T23:19:18.309Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/be/9c/92789c596b8df838baa98fa71844d84283302f7604ed565dafe5a6b5041a/oauthlib-3.3.1-py3-none-any.whl", hash = "sha256:88119c938d2b8fb88561af5f6ee0eec8cc8d552b7bb1f712743136eb7523b7a1", size = 160065, upload-time = "2025-06-19T22:48:06.508Z" },
{ url = "https://files.pythonhosted.org/packages/e1/3d/760b1456010ed11ce87c0109007f0166078dfdada7597f0091ae76eb7305/oauthlib-3.3.0-py3-none-any.whl", hash = "sha256:a2b3a0a2a4ec2feb4b9110f56674a39b2cc2f23e14713f4ed20441dfba14e934", size = 165155, upload-time = "2025-06-17T23:19:16.771Z" },
]
[[package]]
@ -2547,11 +2552,11 @@ wheels = [
[[package]]
name = "pygments"
version = "2.19.2"
version = "2.19.1"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" }
sdist = { url = "https://files.pythonhosted.org/packages/7c/2d/c3338d48ea6cc0feb8446d8e6937e1408088a72a39937982cc6111d17f84/pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f", size = 4968581, upload-time = "2025-01-06T17:26:30.443Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" },
{ url = "https://files.pythonhosted.org/packages/8a/0b/9fcc47d19c48b59121088dd6da2488a49d5f72dacf8262e2790a1d2c7d15/pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c", size = 1225293, upload-time = "2025-01-06T17:26:25.553Z" },
]
[[package]]
@ -2682,6 +2687,19 @@ wheels = [
{ url = "https://files.pythonhosted.org/packages/22/70/b31577d7c46d8e2f9baccfed5067dd8475262a2331ffb0bfdf19361c9bde/pytest_randomly-3.16.0-py3-none-any.whl", hash = "sha256:8633d332635a1a0983d3bba19342196807f6afb17c3eef78e02c2f85dade45d6", size = 8396, upload-time = "2024-10-25T15:45:32.78Z" },
]
[[package]]
name = "pytest-subtests"
version = "0.14.1"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "attrs" },
{ name = "pytest" },
]
sdist = { url = "https://files.pythonhosted.org/packages/c0/4c/ba9eab21a2250c2d46c06c0e3cd316850fde9a90da0ac8d0202f074c6817/pytest_subtests-0.14.1.tar.gz", hash = "sha256:350c00adc36c3aff676a66135c81aed9e2182e15f6c3ec8721366918bbbf7580", size = 17632, upload-time = "2024-12-10T00:21:04.856Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/a9/b7/7ca948d35642ae72500efda6ba6fa61dcb6683feb596d19c4747c63c0789/pytest_subtests-0.14.1-py3-none-any.whl", hash = "sha256:e92a780d98b43118c28a16044ad9b841727bd7cb6a417073b38fd2d7ccdf052d", size = 8833, upload-time = "2024-12-10T00:20:58.873Z" },
]
[[package]]
name = "pytest-timeout"
version = "2.4.0"
@ -2708,11 +2726,11 @@ wheels = [
[[package]]
name = "python-dotenv"
version = "1.1.1"
version = "1.1.0"
source = { registry = "https://pypi.org/simple" }
sdist = { url = "https://files.pythonhosted.org/packages/f6/b0/4bc07ccd3572a2f9df7e6782f52b0c6c90dcbb803ac4a167702d7d0dfe1e/python_dotenv-1.1.1.tar.gz", hash = "sha256:a8a6399716257f45be6a007360200409fce5cda2661e3dec71d23dc15f6189ab", size = 41978, upload-time = "2025-06-24T04:21:07.341Z" }
sdist = { url = "https://files.pythonhosted.org/packages/88/2c/7bb1416c5620485aa793f2de31d3df393d3686aa8a8506d11e10e13c5baf/python_dotenv-1.1.0.tar.gz", hash = "sha256:41f90bc6f5f177fb41f53e87666db362025010eb28f60a01c9143bfa33a2b2d5", size = 39920, upload-time = "2025-03-25T10:14:56.835Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/5f/ed/539768cf28c661b5b068d66d96a2f155c4971a5d55684a514c1a0e0dec2f/python_dotenv-1.1.1-py3-none-any.whl", hash = "sha256:31f23644fe2602f88ff55e1f5c79ba497e01224ee7737937930c448e4d0e24dc", size = 20556, upload-time = "2025-06-24T04:21:06.073Z" },
{ url = "https://files.pythonhosted.org/packages/1e/18/98a99ad95133c6a6e2005fe89faedf294a748bd5dc803008059409ac9b1e/python_dotenv-1.1.0-py3-none-any.whl", hash = "sha256:d7c01d9e2293916c18baf562d95698754b0dbbb5e74d457c45d4f6561fb9d55d", size = 20256, upload-time = "2025-03-25T10:14:55.034Z" },
]
[[package]]
@ -2961,15 +2979,15 @@ wheels = [
[[package]]
name = "sentry-sdk"
version = "2.31.0"
version = "2.30.0"
source = { registry = "https://pypi.org/simple" }
dependencies = [
{ name = "certifi" },
{ name = "urllib3" },
]
sdist = { url = "https://files.pythonhosted.org/packages/d0/45/c7ef7e12d8434fda8b61cdab432d8af64fb832480c93cdaf4bdcab7f5597/sentry_sdk-2.31.0.tar.gz", hash = "sha256:fed6d847f15105849cdf5dfdc64dcec356f936d41abb8c9d66adae45e60959ec", size = 334167, upload-time = "2025-06-24T16:36:26.066Z" }
sdist = { url = "https://files.pythonhosted.org/packages/04/4c/af31e0201b48469786ddeb1bf6fd3dfa3a291cc613a0fe6a60163a7535f9/sentry_sdk-2.30.0.tar.gz", hash = "sha256:436369b02afef7430efb10300a344fb61a11fe6db41c2b11f41ee037d2dd7f45", size = 326767, upload-time = "2025-06-12T10:34:34.733Z" }
wheels = [
{ url = "https://files.pythonhosted.org/packages/7d/a2/9b6d8cc59f03251c583b3fec9d2f075dc09c0f6e030e0e0a3b223c6e64b2/sentry_sdk-2.31.0-py2.py3-none-any.whl", hash = "sha256:e953f5ab083e6599bab255b75d6829b33b3ddf9931a27ca00b4ab0081287e84f", size = 355638, upload-time = "2025-06-24T16:36:24.306Z" },
{ url = "https://files.pythonhosted.org/packages/5a/99/31ac6faaae33ea698086692638f58d14f121162a8db0039e68e94135e7f1/sentry_sdk-2.30.0-py2.py3-none-any.whl", hash = "sha256:59391db1550662f746ea09b483806a631c3ae38d6340804a1a4c0605044f6877", size = 343149, upload-time = "2025-06-12T10:34:32.896Z" },
]
[[package]]

268
web/package-lock.json generated
View File

@ -22,7 +22,7 @@
"@floating-ui/dom": "^1.6.11",
"@formatjs/intl-listformat": "^7.7.11",
"@fortawesome/fontawesome-free": "^6.7.2",
"@goauthentik/api": "^2025.6.2-1750856752",
"@goauthentik/api": "^2025.6.2-1750801939",
"@lit/context": "^1.1.2",
"@lit/localize": "^0.12.2",
"@lit/reactive-element": "^2.0.4",
@ -34,7 +34,7 @@
"@openlayers-elements/maps": "^0.4.0",
"@patternfly/elements": "^4.1.0",
"@patternfly/patternfly": "^4.224.2",
"@sentry/browser": "^9.32.0",
"@sentry/browser": "^9.31.0",
"@spotlightjs/spotlight": "^3.0.1",
"@webcomponents/webcomponentsjs": "^2.8.0",
"base64-js": "^1.5.1",
@ -75,7 +75,7 @@
"devDependencies": {
"@eslint/js": "^9.27.0",
"@goauthentik/core": "^1.0.0",
"@goauthentik/esbuild-plugin-live-reload": "^1.0.5",
"@goauthentik/esbuild-plugin-live-reload": "^1.0.4",
"@goauthentik/eslint-config": "^1.0.5",
"@goauthentik/prettier-config": "^1.0.5",
"@goauthentik/tsconfig": "^1.0.4",
@ -1716,30 +1716,32 @@
"node": ">=6"
}
},
"node_modules/@gerrit0/mini-shiki": {
"version": "3.4.2",
"resolved": "https://registry.npmjs.org/@gerrit0/mini-shiki/-/mini-shiki-3.4.2.tgz",
"integrity": "sha512-3jXo5bNjvvimvdbIhKGfFxSnKCX+MA8wzHv55ptzk/cx8wOzT+BRcYgj8aFN3yTiTs+zvQQiaZFr7Jce1ZG3fw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@shikijs/engine-oniguruma": "^3.4.2",
"@shikijs/langs": "^3.4.2",
"@shikijs/themes": "^3.4.2",
"@shikijs/types": "^3.4.2",
"@shikijs/vscode-textmate": "^10.0.2"
}
},
"node_modules/@goauthentik/api": {
"version": "2025.6.2-1750856752",
"resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2025.6.2-1750856752.tgz",
"integrity": "sha512-Zf/1wa5Q1CBbfc4EyJYc/JieTnMS9V0k4wGlK3ojC+kTDJhGjYdHPWpOGiAV9GJXQWHXfHLpA9bqPtBx/0ww7A=="
"version": "2025.6.2-1750801939",
"resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2025.6.2-1750801939.tgz",
"integrity": "sha512-3s0pE6enhLEWVMD+zClORktBhUAw1vO/lCG0ATqm6xqbTfqGxPYWj5XMzYuX7+a2axxn1BFE134afWmdzDhThw=="
},
"node_modules/@goauthentik/core": {
"resolved": "packages/core",
"link": true
},
"node_modules/@goauthentik/esbuild-plugin-live-reload": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@goauthentik/esbuild-plugin-live-reload/-/esbuild-plugin-live-reload-1.0.5.tgz",
"integrity": "sha512-MZ/najY+Xn62ijzj7JDS1sVupWI3BNRwJc4kykB/iP9CdLJw+xO71qPTjfCEEOVYMZrOTftD4KOLhRYx3GTqkA==",
"dev": true,
"license": "MIT",
"dependencies": {
"find-free-ports": "^3.1.1"
},
"engines": {
"node": ">=22"
},
"peerDependencies": {
"esbuild": "^0.25.4"
}
"resolved": "packages/esbuild-plugin-live-reload",
"link": true
},
"node_modules/@goauthentik/eslint-config": {
"version": "1.0.5",
@ -4056,7 +4058,6 @@
"integrity": "sha512-ROFF39F6ZrnzSUEmQQZUar0Jt4xVoP9WnDRdWwF4NNcXs3xBTLgBUDoOwW141y1jP+S8nahIbdxbFC7IShw9Iw==",
"dev": true,
"license": "MIT",
"peer": true,
"engines": {
"node": "^12.20.0 || ^14.18.0 || >=16.0.0"
},
@ -4560,75 +4561,75 @@
"dev": true
},
"node_modules/@sentry-internal/browser-utils": {
"version": "9.32.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-9.32.0.tgz",
"integrity": "sha512-mVWdruSWXF+2WgS24jwLhWFyC/nDQbKXseLR8paU9LGSnVtlBlQseIx1GrANbJrhBxiEWSft4WiuxU34wPsbXg==",
"version": "9.31.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/browser-utils/-/browser-utils-9.31.0.tgz",
"integrity": "sha512-rviu/jUmeQbY4rSO8l4pubOtRIhFtH5Gu/ryRNMTlpJRdomp4uxddqthHUDH5g6xCXZsMTyJEIdx0aTqbgr/GQ==",
"license": "MIT",
"dependencies": {
"@sentry/core": "9.32.0"
"@sentry/core": "9.31.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@sentry-internal/feedback": {
"version": "9.32.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-9.32.0.tgz",
"integrity": "sha512-OaXaovXqlhN1sG2wtJMhxMEjyeuK7RwY57o96LgKE0bWM//Fs9WWCOkGa+7l8TOf0+0ib7gfhJZlpN0hlqOgRw==",
"version": "9.31.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-9.31.0.tgz",
"integrity": "sha512-Ygi/8UZ7p2B4DhXQjZDtOc45vNUHkfk2XETBTBGkByEQkE8vygzSiKhgRcnVpzwq+8xKFMRy+PxvpcCo+PNQew==",
"license": "MIT",
"dependencies": {
"@sentry/core": "9.32.0"
"@sentry/core": "9.31.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@sentry-internal/replay": {
"version": "9.32.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-9.32.0.tgz",
"integrity": "sha512-mOHUKjUtHbEwshikrCQPM1ZqWAMUEcpEGashnXQp3KQivvbTxrExiNnt6XK5TjJyGvsI3A907Bp/HvEzgneYgQ==",
"version": "9.31.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/replay/-/replay-9.31.0.tgz",
"integrity": "sha512-V5rvcO/xSj8JMw4ZnZT2cBYC+UOuIiZ2Flj4EoIurxMrTgowE1uMXUBA32EBfuB5/vQSJXB6W5uAudhk7LjBPQ==",
"license": "MIT",
"dependencies": {
"@sentry-internal/browser-utils": "9.32.0",
"@sentry/core": "9.32.0"
"@sentry-internal/browser-utils": "9.31.0",
"@sentry/core": "9.31.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@sentry-internal/replay-canvas": {
"version": "9.32.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-9.32.0.tgz",
"integrity": "sha512-tu+coeTRpJxknmWPMJC2jqmIM5IsVoRn9gEDdkSrcPbgx/GwgE03fSJVBJL1tOEA8yRNIhZPMR86ORE7/7n2ow==",
"version": "9.31.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-9.31.0.tgz",
"integrity": "sha512-VGqfvQCIuXQZeecrBf8bd4sj8lYGzUA/2CffTAkad1nB1Onyz0Kzo54qLWemivCxA3ufHf6DCpNA3Loa/0ywFQ==",
"license": "MIT",
"dependencies": {
"@sentry-internal/replay": "9.32.0",
"@sentry/core": "9.32.0"
"@sentry-internal/replay": "9.31.0",
"@sentry/core": "9.31.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@sentry/browser": {
"version": "9.32.0",
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-9.32.0.tgz",
"integrity": "sha512-BzPogpH87n+sC9VPfXaXkiKJtagLpIB87LGg1hSBURpwGx6Rt2ORmaVYgwwuuFZX8Hia727IIM7pbcbNfrXGRQ==",
"version": "9.31.0",
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-9.31.0.tgz",
"integrity": "sha512-DzG72JJTqHzE0Qo2fHeHm3xgFs97InaSQStmTMxOA59yPqvAXbweNPcsgCNu1q76+jZyaJcoy1qOwahnLuEVDg==",
"license": "MIT",
"dependencies": {
"@sentry-internal/browser-utils": "9.32.0",
"@sentry-internal/feedback": "9.32.0",
"@sentry-internal/replay": "9.32.0",
"@sentry-internal/replay-canvas": "9.32.0",
"@sentry/core": "9.32.0"
"@sentry-internal/browser-utils": "9.31.0",
"@sentry-internal/feedback": "9.31.0",
"@sentry-internal/replay": "9.31.0",
"@sentry-internal/replay-canvas": "9.31.0",
"@sentry/core": "9.31.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@sentry/core": {
"version": "9.32.0",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-9.32.0.tgz",
"integrity": "sha512-1wAXMMmeY4Ny2MJBCuri3b4LMVPjqXdgbVgTxxipGW+gzPsjv+8+LCSnJAR/cRBr8JoXV+qGC2tE06rI1XDj3A==",
"version": "9.31.0",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-9.31.0.tgz",
"integrity": "sha512-6JeoPGvBgT9m2YFIf2CrW+KrrOYzUqb9+Xwr/Dw25kPjVKy+WJjWqK8DKCNLgkBA22OCmSOmHuRwFR0YxGVdZQ==",
"license": "MIT",
"engines": {
"node": ">=18"
@ -4718,6 +4719,55 @@
"node": ">=14.18"
}
},
"node_modules/@shikijs/engine-oniguruma": {
"version": "3.4.2",
"resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.4.2.tgz",
"integrity": "sha512-zcZKMnNndgRa3ORja6Iemsr3DrLtkX3cAF7lTJkdMB6v9alhlBsX9uNiCpqofNrXOvpA3h6lHcLJxgCIhVOU5Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"@shikijs/types": "3.4.2",
"@shikijs/vscode-textmate": "^10.0.2"
}
},
"node_modules/@shikijs/langs": {
"version": "3.4.2",
"resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.4.2.tgz",
"integrity": "sha512-H6azIAM+OXD98yztIfs/KH5H4PU39t+SREhmM8LaNXyUrqj2mx+zVkr8MWYqjceSjDw9I1jawm1WdFqU806rMA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@shikijs/types": "3.4.2"
}
},
"node_modules/@shikijs/themes": {
"version": "3.4.2",
"resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.4.2.tgz",
"integrity": "sha512-qAEuAQh+brd8Jyej2UDDf+b4V2g1Rm8aBIdvt32XhDPrHvDkEnpb7Kzc9hSuHUxz0Iuflmq7elaDuQAP9bHIhg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@shikijs/types": "3.4.2"
}
},
"node_modules/@shikijs/types": {
"version": "3.4.2",
"resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.4.2.tgz",
"integrity": "sha512-zHC1l7L+eQlDXLnxvM9R91Efh2V4+rN3oMVS2swCBssbj2U/FBwybD1eeLaq8yl/iwT+zih8iUbTBCgGZOYlVg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@shikijs/vscode-textmate": "^10.0.2",
"@types/hast": "^3.0.4"
}
},
"node_modules/@shikijs/vscode-textmate": {
"version": "10.0.2",
"resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz",
"integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==",
"dev": true,
"license": "MIT"
},
"node_modules/@sinclair/typebox": {
"version": "0.27.8",
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
@ -13188,7 +13238,6 @@
"integrity": "sha512-Mc7QhQ8s+cLrnUfU/Ji94vG/r8M26m8f++vyres4ZoojaRDpZ1eSIh/EpzLNwlWuvzSZ3UbDFspjFvTDXe6e/g==",
"dev": true,
"license": "MIT",
"peer": true,
"engines": {
"node": ">=12.20"
}
@ -13199,7 +13248,6 @@
"integrity": "sha512-qE3Veg1YXzGHQhlA6jzebZN2qVf6NX+A7m7qlhCGG30dJixrAQhYOsJjsnBjJkCSmuOPpCk30145fr8FV0bzog==",
"dev": true,
"license": "MIT",
"peer": true,
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
@ -15650,7 +15698,6 @@
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/find-free-ports/-/find-free-ports-3.1.1.tgz",
"integrity": "sha512-hQebewth9i5qkf0a0u06iFaxQssk5ZnPBBggsa1vk8zCYaZoz9IZXpoRLTbEOrYdqfrjvcxU00gYoCPgmXugKA==",
"dev": true,
"license": "MIT"
},
"node_modules/find-replace": {
@ -16195,7 +16242,6 @@
"integrity": "sha512-cmP497iLq54AZnv4YRAEMnEyQ1eIn4tGKbmswqwmFV4GBnAqE8NLtWxxdXa++AalfgL5EBH4IxTPyquEuGY/jA==",
"dev": true,
"license": "MIT",
"peer": true,
"funding": {
"url": "https://github.com/fisker/git-hooks-list?sponsor=1"
}
@ -19126,6 +19172,16 @@
"dev": true,
"license": "MIT"
},
"node_modules/linkify-it": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz",
"integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"uc.micro": "^2.0.0"
}
},
"node_modules/lit": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/lit/-/lit-3.3.0.tgz",
@ -19530,6 +19586,13 @@
"node": ">=16.14"
}
},
"node_modules/lunr": {
"version": "2.3.9",
"resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz",
"integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==",
"dev": true,
"license": "MIT"
},
"node_modules/lz-string": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz",
@ -19591,6 +19654,24 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/markdown-it": {
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz",
"integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==",
"dev": true,
"license": "MIT",
"dependencies": {
"argparse": "^2.0.1",
"entities": "^4.4.0",
"linkify-it": "^5.0.0",
"mdurl": "^2.0.0",
"punycode.js": "^2.3.1",
"uc.micro": "^2.1.0"
},
"bin": {
"markdown-it": "bin/markdown-it.mjs"
}
},
"node_modules/markdown-table": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz",
@ -19988,6 +20069,13 @@
"url": "https://opencollective.com/unified"
}
},
"node_modules/mdurl": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz",
"integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==",
"dev": true,
"license": "MIT"
},
"node_modules/media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
@ -22930,7 +23018,6 @@
"integrity": "sha512-h+3tSpr2nVpp+YOK1MDIYtYhHVXr8/0V59UUbJpIJFaqi3w4fvUokJo6eV8W+vELrUXIZzJ+DKm5G7lYzrMcKQ==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"sort-package-json": "3.2.1",
"synckit": "0.11.6"
@ -23178,6 +23265,16 @@
"node": ">=6"
}
},
"node_modules/punycode.js": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz",
"integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/puppeteer-core": {
"version": "22.15.0",
"resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-22.15.0.tgz",
@ -25280,8 +25377,7 @@
"resolved": "https://registry.npmjs.org/sort-object-keys/-/sort-object-keys-1.1.3.tgz",
"integrity": "sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==",
"dev": true,
"license": "MIT",
"peer": true
"license": "MIT"
},
"node_modules/sort-package-json": {
"version": "3.2.1",
@ -25289,7 +25385,6 @@
"integrity": "sha512-rTfRdb20vuoAn7LDlEtCqOkYfl2X+Qze6cLbNOzcDpbmKEhJI30tTN44d5shbKJnXsvz24QQhlCm81Bag7EOKg==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"detect-indent": "^7.0.1",
"detect-newline": "^4.0.1",
@ -25982,7 +26077,6 @@
"integrity": "sha512-2pR2ubZSV64f/vqm9eLPz/KOvR9Dm+Co/5ChLgeHl0yEDRc6h5hXHoxEQH8Y5Ljycozd3p1k5TTSVdzYGkPvLw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@pkgr/core": "^0.2.4"
},
@ -26193,7 +26287,6 @@
"integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"fdir": "^6.4.4",
"picomatch": "^4.0.2"
@ -27063,6 +27156,43 @@
"dev": true,
"license": "MIT"
},
"node_modules/typedoc": {
"version": "0.28.5",
"resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.28.5.tgz",
"integrity": "sha512-5PzUddaA9FbaarUzIsEc4wNXCiO4Ot3bJNeMF2qKpYlTmM9TTaSHQ7162w756ERCkXER/+o2purRG6YOAv6EMA==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"@gerrit0/mini-shiki": "^3.2.2",
"lunr": "^2.3.9",
"markdown-it": "^14.1.0",
"minimatch": "^9.0.5",
"yaml": "^2.7.1"
},
"bin": {
"typedoc": "bin/typedoc"
},
"engines": {
"node": ">= 18",
"pnpm": ">= 10"
},
"peerDependencies": {
"typescript": "5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x"
}
},
"node_modules/typedoc-plugin-markdown": {
"version": "4.6.3",
"resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-4.6.3.tgz",
"integrity": "sha512-86oODyM2zajXwLs4Wok2mwVEfCwCnp756QyhLGX2IfsdRYr1DXLCgJgnLndaMUjJD7FBhnLk2okbNE9PdLxYRw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">= 18"
},
"peerDependencies": {
"typedoc": "0.28.x"
}
},
"node_modules/types-ramda": {
"version": "0.30.1",
"resolved": "https://registry.npmjs.org/types-ramda/-/types-ramda-0.30.1.tgz",
@ -27119,6 +27249,13 @@
"node": ">=8"
}
},
"node_modules/uc.micro": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz",
"integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==",
"dev": true,
"license": "MIT"
},
"node_modules/ufo": {
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.4.tgz",
@ -29330,7 +29467,6 @@
"packages/esbuild-plugin-live-reload": {
"name": "@goauthentik/esbuild-plugin-live-reload",
"version": "1.0.5",
"extraneous": true,
"license": "MIT",
"dependencies": {
"find-free-ports": "^3.1.1"
@ -29354,6 +29490,16 @@
"esbuild": "^0.25.5"
}
},
"packages/esbuild-plugin-live-reload/node_modules/@types/node": {
"version": "22.15.19",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.19.tgz",
"integrity": "sha512-3vMNr4TzNQyjHcRZadojpRaD9Ofr6LsonZAoQ+HMUa/9ORTPoxVIw0e0mpqWpdjj8xybyCM+oKOUH2vwFu/oEw==",
"dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~6.21.0"
}
},
"packages/monorepo": {
"name": "@goauthentik/monorepo",
"version": "1.0.0",

View File

@ -93,7 +93,7 @@
"@floating-ui/dom": "^1.6.11",
"@formatjs/intl-listformat": "^7.7.11",
"@fortawesome/fontawesome-free": "^6.7.2",
"@goauthentik/api": "^2025.6.2-1750856752",
"@goauthentik/api": "^2025.6.2-1750801939",
"@lit/context": "^1.1.2",
"@lit/localize": "^0.12.2",
"@lit/reactive-element": "^2.0.4",
@ -105,7 +105,7 @@
"@openlayers-elements/maps": "^0.4.0",
"@patternfly/elements": "^4.1.0",
"@patternfly/patternfly": "^4.224.2",
"@sentry/browser": "^9.32.0",
"@sentry/browser": "^9.31.0",
"@spotlightjs/spotlight": "^3.0.1",
"@webcomponents/webcomponentsjs": "^2.8.0",
"base64-js": "^1.5.1",
@ -146,7 +146,7 @@
"devDependencies": {
"@eslint/js": "^9.27.0",
"@goauthentik/core": "^1.0.0",
"@goauthentik/esbuild-plugin-live-reload": "^1.0.5",
"@goauthentik/esbuild-plugin-live-reload": "^1.0.4",
"@goauthentik/eslint-config": "^1.0.5",
"@goauthentik/prettier-config": "^1.0.5",
"@goauthentik/tsconfig": "^1.0.4",

View File

@ -1,4 +1,3 @@
README.md
node_modules
_media
!.github/README.md

View File

@ -1,12 +1,12 @@
{
"name": "@goauthentik/esbuild-plugin-live-reload",
"version": "1.0.6",
"version": "1.0.5",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@goauthentik/esbuild-plugin-live-reload",
"version": "1.0.6",
"version": "1.0.5",
"license": "MIT",
"dependencies": {
"find-free-ports": "^3.1.1"

View File

@ -1,6 +1,6 @@
{
"name": "@goauthentik/esbuild-plugin-live-reload",
"version": "1.0.6",
"version": "1.0.5",
"description": "ESBuild + browser refresh. Build completes, page reloads.",
"license": "MIT",
"scripts": {

View File

@ -1,4 +1,4 @@
import { EventGeo, renderEventUser } from "@goauthentik/admin/events/utils";
import { EventGeo, EventUser } from "@goauthentik/admin/events/utils";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { EventWithContext } from "@goauthentik/common/events";
import { actionToLabel } from "@goauthentik/common/labels";
@ -73,7 +73,7 @@ export class RecentEventsCard extends Table<Event> {
return [
html`<div><a href="${`#/events/log/${item.pk}`}">${actionToLabel(item.action)}</a></div>
<small>${item.app}</small>`,
renderEventUser(item),
EventUser(item),
html`<div>${formatElapsedTime(item.created)}</div>
<small>${item.created.toLocaleString()}</small>`,
html` <div>${item.clientIp || msg("-")}</div>

View File

@ -3,7 +3,7 @@ import { WithLicenseSummary } from "#elements/mixins/license";
import { updateURLParams } from "#elements/router/RouteMatch";
import "@goauthentik/admin/events/EventMap";
import "@goauthentik/admin/events/EventVolumeChart";
import { EventGeo, renderEventUser } from "@goauthentik/admin/events/utils";
import { EventGeo, EventUser } from "@goauthentik/admin/events/utils";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { EventWithContext } from "@goauthentik/common/events";
import { actionToLabel } from "@goauthentik/common/labels";
@ -113,7 +113,7 @@ export class EventListPage extends WithLicenseSummary(TablePage<Event>) {
return [
html`<div>${actionToLabel(item.action)}</div>
<small>${item.app}</small>`,
renderEventUser(item),
EventUser(item),
html`<div>${formatElapsedTime(item.created)}</div>
<small>${item.created.toLocaleString()}</small>`,
html`<div>${item.clientIp || msg("-")}</div>

View File

@ -8,7 +8,6 @@ import OlMap from "@openlayers-elements/core/ol-map";
import "@openlayers-elements/maps/ol-layer-openstreetmap";
import "@openlayers-elements/maps/ol-select";
import Feature from "ol/Feature";
import { isEmpty } from "ol/extent";
import { Point } from "ol/geom";
import { fromLonLat } from "ol/proj";
import Icon from "ol/style/Icon";
@ -93,7 +92,7 @@ export class EventMap extends AKElement {
// Re-add them
this.events?.results
.filter((event) => {
if (!Object.hasOwn(event.context || {}, "geo")) {
if (!Object.hasOwn(event.context, "geo")) {
return false;
}
const geo = (event as EventWithContext).context.geo;
@ -125,9 +124,6 @@ export class EventMap extends AKElement {
this.vectorLayer?.source?.addFeature(feature);
});
// Zoom to show points better
if (isEmpty(this.vectorLayer.source.getExtent())) {
return;
}
this.map.map.getView().fit(this.vectorLayer.source.getExtent(), {
padding: [
this.zoomPaddingPx,

View File

@ -1,4 +1,4 @@
import { EventGeo, renderEventUser } from "#admin/events/utils";
import { EventGeo, EventUser } from "#admin/events/utils";
import { DEFAULT_CONFIG } from "#common/api/config";
import { EventWithContext } from "#common/events";
import { actionToLabel } from "#common/labels";
@ -92,7 +92,7 @@ export class EventViewPage extends AKElement {
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
${renderEventUser(this.event)}
${EventUser(this.event)}
</div>
</dd>
</div>

View File

@ -1,9 +1,9 @@
import { EventUser, EventWithContext } from "@goauthentik/common/events";
import { EventWithContext } from "@goauthentik/common/events";
import { truncate } from "@goauthentik/common/utils";
import { SlottedTemplateResult } from "@goauthentik/elements/types";
import { msg, str } from "@lit/localize";
import { TemplateResult, html, nothing } from "lit";
import { html, nothing } from "lit";
/**
* Given event with a geographical context, format it into a string for display.
@ -18,48 +18,31 @@ export function EventGeo(event: EventWithContext): SlottedTemplateResult {
return html`${parts.join(", ")}`;
}
export function renderEventUser(
export function EventUser(
event: EventWithContext,
truncateUsername?: number,
): SlottedTemplateResult {
if (!event.user.username) return html`-`;
const linkOrSpan = (inner: TemplateResult, evu: EventUser) => {
return html`${evu.pk && !evu.is_anonymous
? html`<a href="#/identity/users/${evu.pk}">${inner}</a>`
: html`<span>${inner}</span>`}`;
};
const renderUsername = (evu: EventUser) => {
let username = evu.username;
if (evu.is_anonymous) {
username = msg("Anonymous user");
}
if (truncateUsername) {
return truncate(username, truncateUsername);
}
return username;
};
let body: SlottedTemplateResult = nothing;
body = html`<div>${linkOrSpan(html`${renderUsername(event.user)}`, event.user)}</div>`;
if (event.user.is_anonymous) {
body = html`<div>${msg("Anonymous user")}</div>`;
} else {
body = html`<div>
<a href="#/identity/users/${event.user.pk}"
>${truncateUsername
? truncate(event.user?.username, truncateUsername)
: event.user?.username}</a
>
</div>`;
}
if (event.user.on_behalf_of) {
return html`${body}<small>
${linkOrSpan(
html`${msg(str`On behalf of ${renderUsername(event.user.on_behalf_of)}`)}`,
event.user.on_behalf_of,
)}
</small>`;
}
if (event.user.authenticated_as) {
return html`${body}<small>
${linkOrSpan(
html`${msg(
str`Authenticated as ${renderUsername(event.user.authenticated_as)}`,
)}`,
event.user.authenticated_as,
)}
<a href="#/identity/users/${event.user.on_behalf_of.pk}"
>${msg(str`On behalf of ${event.user.on_behalf_of.username}`)}</a
>
</small>`;
}

View File

@ -4,9 +4,8 @@ export interface EventUser {
pk: number;
email?: string;
username: string;
is_anonymous?: boolean;
on_behalf_of?: EventUser;
authenticated_as?: EventUser;
is_anonymous?: boolean;
}
export interface EventGeo {

View File

@ -1,4 +1,4 @@
import { EventGeo, renderEventUser } from "@goauthentik/admin/events/utils";
import { EventGeo, EventUser } from "@goauthentik/admin/events/utils";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { EventWithContext } from "@goauthentik/common/events";
import { actionToLabel } from "@goauthentik/common/labels";
@ -72,7 +72,7 @@ export class ObjectChangelog extends Table<Event> {
row(item: EventWithContext): SlottedTemplateResult[] {
return [
html`${actionToLabel(item.action)}`,
renderEventUser(item),
EventUser(item),
html`<div>${formatElapsedTime(item.created)}</div>
<small>${item.created.toLocaleString()}</small>`,
html`<div>${item.clientIp || msg("-")}</div>

View File

@ -1,4 +1,4 @@
import { renderEventUser } from "@goauthentik/admin/events/utils";
import { EventUser } from "@goauthentik/admin/events/utils";
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { EventWithContext } from "@goauthentik/common/events";
import { actionToLabel } from "@goauthentik/common/labels";
@ -46,7 +46,7 @@ export class UserEvents extends Table<Event> {
row(item: EventWithContext): SlottedTemplateResult[] {
return [
html`${actionToLabel(item.action)}`,
renderEventUser(item),
EventUser(item),
html`<div>${formatElapsedTime(item.created)}</div>
<small>${item.created.toLocaleString()}</small>`,
html`<span>${item.clientIp || msg("-")}</span>`,

View File

@ -451,7 +451,7 @@
</trans-unit>
<trans-unit id="sc35581d9c1cd67ff">
<source>On behalf of <x id="0" equiv-text="${renderUsername(event.user.on_behalf_of)}"/></source>
<source>On behalf of <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></source>
<target>Im Namen von
<x id="0" equiv-text="${event.user.on_behalf_of.username}"/></target>
@ -8751,6 +8751,9 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s05849efeac672dc7">
<source>No app entitlements created.</source>
</trans-unit>
<trans-unit id="sdc8a8f29af6aa411">
<source>This application does currently not have any application entitlement defined.</source>
</trans-unit>
<trans-unit id="sf0bd204ce3fea1de">
<source>Create Entitlement</source>
</trans-unit>
@ -9253,12 +9256,6 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s8495753cb15e8d8e">
<source>Maximum allowed registration attempts. When set to 0 attempts, attempts are not limited.</source>
</trans-unit>
<trans-unit id="sab4db6a3bd6abc1e">
<source>This application does currently not have any application entitlements defined.</source>
</trans-unit>
<trans-unit id="s7225aacf0eee94d2">
<source>Authenticated as <x id="0" equiv-text="${renderUsername(event.user.authenticated_as)}"/></source>
</trans-unit>
</body>
</file>

View File

@ -363,7 +363,7 @@
<target>Recent events</target>
</trans-unit>
<trans-unit id="sc35581d9c1cd67ff">
<source>On behalf of <x id="0" equiv-text="${renderUsername(event.user.on_behalf_of)}"/></source>
<source>On behalf of <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></source>
<target>On behalf of
<x id="0" equiv-text="${event.user.on_behalf_of.username}"/></target>
</trans-unit>
@ -7263,6 +7263,9 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s05849efeac672dc7">
<source>No app entitlements created.</source>
</trans-unit>
<trans-unit id="sdc8a8f29af6aa411">
<source>This application does currently not have any application entitlement defined.</source>
</trans-unit>
<trans-unit id="sf0bd204ce3fea1de">
<source>Create Entitlement</source>
</trans-unit>
@ -7763,12 +7766,6 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s8495753cb15e8d8e">
<source>Maximum allowed registration attempts. When set to 0 attempts, attempts are not limited.</source>
</trans-unit>
<trans-unit id="sab4db6a3bd6abc1e">
<source>This application does currently not have any application entitlements defined.</source>
</trans-unit>
<trans-unit id="s7225aacf0eee94d2">
<source>Authenticated as <x id="0" equiv-text="${renderUsername(event.user.authenticated_as)}"/></source>
</trans-unit>
</body>
</file>

View File

@ -451,7 +451,7 @@
</trans-unit>
<trans-unit id="sc35581d9c1cd67ff">
<source>On behalf of <x id="0" equiv-text="${renderUsername(event.user.on_behalf_of)}"/></source>
<source>On behalf of <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></source>
<target>En nombre de
<x id="0" equiv-text="${event.user.on_behalf_of.username}"/></target>
@ -8814,6 +8814,9 @@ Las vinculaciones a grupos o usuarios se comparan con el usuario del evento.</ta
<trans-unit id="s05849efeac672dc7">
<source>No app entitlements created.</source>
</trans-unit>
<trans-unit id="sdc8a8f29af6aa411">
<source>This application does currently not have any application entitlement defined.</source>
</trans-unit>
<trans-unit id="sf0bd204ce3fea1de">
<source>Create Entitlement</source>
</trans-unit>
@ -9314,12 +9317,6 @@ Las vinculaciones a grupos o usuarios se comparan con el usuario del evento.</ta
</trans-unit>
<trans-unit id="s8495753cb15e8d8e">
<source>Maximum allowed registration attempts. When set to 0 attempts, attempts are not limited.</source>
</trans-unit>
<trans-unit id="sab4db6a3bd6abc1e">
<source>This application does currently not have any application entitlements defined.</source>
</trans-unit>
<trans-unit id="s7225aacf0eee94d2">
<source>Authenticated as <x id="0" equiv-text="${renderUsername(event.user.authenticated_as)}"/></source>
</trans-unit>
</body>
</file>

View File

@ -451,7 +451,7 @@
</trans-unit>
<trans-unit id="sc35581d9c1cd67ff">
<source>On behalf of <x id="0" equiv-text="${renderUsername(event.user.on_behalf_of)}"/></source>
<source>On behalf of <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></source>
<target>Au nom de
<x id="0" equiv-text="${event.user.on_behalf_of.username}"/></target>
@ -9231,6 +9231,10 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti
<source>No app entitlements created.</source>
<target>Aucun droit applicatif créé.</target>
</trans-unit>
<trans-unit id="sdc8a8f29af6aa411">
<source>This application does currently not have any application entitlement defined.</source>
<target>Cette application n'a actuellement pas de droit applicatif défini.</target>
</trans-unit>
<trans-unit id="sf0bd204ce3fea1de">
<source>Create Entitlement</source>
<target>Créer un droit</target>
@ -9881,12 +9885,6 @@ Les liaisons avec les groupes/utilisateurs sont vérifiées par rapport à l'uti
</trans-unit>
<trans-unit id="s8495753cb15e8d8e">
<source>Maximum allowed registration attempts. When set to 0 attempts, attempts are not limited.</source>
</trans-unit>
<trans-unit id="sab4db6a3bd6abc1e">
<source>This application does currently not have any application entitlements defined.</source>
</trans-unit>
<trans-unit id="s7225aacf0eee94d2">
<source>Authenticated as <x id="0" equiv-text="${renderUsername(event.user.authenticated_as)}"/></source>
</trans-unit>
</body>
</file>

View File

@ -451,7 +451,7 @@
</trans-unit>
<trans-unit id="sc35581d9c1cd67ff">
<source>On behalf of <x id="0" equiv-text="${renderUsername(event.user.on_behalf_of)}"/></source>
<source>On behalf of <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></source>
<target>Per conto di
<x id="0" equiv-text="${event.user.on_behalf_of.username}"/></target>
@ -9232,6 +9232,10 @@ Bindings to groups/users are checked against the user of the event.</source>
<source>No app entitlements created.</source>
<target>Non sono stati creati entitlements per l'app.</target>
</trans-unit>
<trans-unit id="sdc8a8f29af6aa411">
<source>This application does currently not have any application entitlement defined.</source>
<target>Al momento, per questa applicazione non è definito alcun entitlement applicativo.</target>
</trans-unit>
<trans-unit id="sf0bd204ce3fea1de">
<source>Create Entitlement</source>
<target>Crea Privilegio</target>
@ -9901,13 +9905,6 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s8495753cb15e8d8e">
<source>Maximum allowed registration attempts. When set to 0 attempts, attempts are not limited.</source>
<target>Numero massimo di tentativi di registrazione consentiti. Se impostato su 0 tentativi, i tentativi non sono limitati.</target>
</trans-unit>
<trans-unit id="sab4db6a3bd6abc1e">
<source>This application does currently not have any application entitlements defined.</source>
<target>Questa applicazione al momento non ha eventuali diritti applicativi definiti.</target>
</trans-unit>
<trans-unit id="s7225aacf0eee94d2">
<source>Authenticated as <x id="0" equiv-text="${renderUsername(event.user.authenticated_as)}"/></source>
</trans-unit>
</body>
</file>

View File

@ -445,7 +445,7 @@
</trans-unit>
<trans-unit id="sc35581d9c1cd67ff">
<source>On behalf of <x id="0" equiv-text="${renderUsername(event.user.on_behalf_of)}"/></source>
<source>On behalf of <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></source>
</trans-unit>
<trans-unit id="saf63a04c86018698">
@ -8721,6 +8721,9 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s05849efeac672dc7">
<source>No app entitlements created.</source>
</trans-unit>
<trans-unit id="sdc8a8f29af6aa411">
<source>This application does currently not have any application entitlement defined.</source>
</trans-unit>
<trans-unit id="sf0bd204ce3fea1de">
<source>Create Entitlement</source>
</trans-unit>
@ -9221,12 +9224,6 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s8495753cb15e8d8e">
<source>Maximum allowed registration attempts. When set to 0 attempts, attempts are not limited.</source>
</trans-unit>
<trans-unit id="sab4db6a3bd6abc1e">
<source>This application does currently not have any application entitlements defined.</source>
</trans-unit>
<trans-unit id="s7225aacf0eee94d2">
<source>Authenticated as <x id="0" equiv-text="${renderUsername(event.user.authenticated_as)}"/></source>
</trans-unit>
</body>
</file>

View File

@ -447,7 +447,7 @@
</trans-unit>
<trans-unit id="sc35581d9c1cd67ff">
<source>On behalf of <x id="0" equiv-text="${renderUsername(event.user.on_behalf_of)}"/></source>
<source>On behalf of <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></source>
<target>Namens
<x id="0" equiv-text="${event.user.on_behalf_of.username}"/></target>
@ -8625,6 +8625,9 @@ Bindingen naar groepen/gebruikers worden gecontroleerd tegen de gebruiker van de
<trans-unit id="s05849efeac672dc7">
<source>No app entitlements created.</source>
</trans-unit>
<trans-unit id="sdc8a8f29af6aa411">
<source>This application does currently not have any application entitlement defined.</source>
</trans-unit>
<trans-unit id="sf0bd204ce3fea1de">
<source>Create Entitlement</source>
</trans-unit>
@ -9125,12 +9128,6 @@ Bindingen naar groepen/gebruikers worden gecontroleerd tegen de gebruiker van de
</trans-unit>
<trans-unit id="s8495753cb15e8d8e">
<source>Maximum allowed registration attempts. When set to 0 attempts, attempts are not limited.</source>
</trans-unit>
<trans-unit id="sab4db6a3bd6abc1e">
<source>This application does currently not have any application entitlements defined.</source>
</trans-unit>
<trans-unit id="s7225aacf0eee94d2">
<source>Authenticated as <x id="0" equiv-text="${renderUsername(event.user.authenticated_as)}"/></source>
</trans-unit>
</body>
</file>

View File

@ -451,7 +451,7 @@
</trans-unit>
<trans-unit id="sc35581d9c1cd67ff">
<source>On behalf of <x id="0" equiv-text="${renderUsername(event.user.on_behalf_of)}"/></source>
<source>On behalf of <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></source>
<target>W imieniu
<x id="0" equiv-text="${event.user.on_behalf_of.username}"/></target>
@ -9048,6 +9048,9 @@ Powiązania z grupami/użytkownikami są sprawdzane względem użytkownika zdarz
<trans-unit id="s05849efeac672dc7">
<source>No app entitlements created.</source>
</trans-unit>
<trans-unit id="sdc8a8f29af6aa411">
<source>This application does currently not have any application entitlement defined.</source>
</trans-unit>
<trans-unit id="sf0bd204ce3fea1de">
<source>Create Entitlement</source>
</trans-unit>
@ -9548,12 +9551,6 @@ Powiązania z grupami/użytkownikami są sprawdzane względem użytkownika zdarz
</trans-unit>
<trans-unit id="s8495753cb15e8d8e">
<source>Maximum allowed registration attempts. When set to 0 attempts, attempts are not limited.</source>
</trans-unit>
<trans-unit id="sab4db6a3bd6abc1e">
<source>This application does currently not have any application entitlements defined.</source>
</trans-unit>
<trans-unit id="s7225aacf0eee94d2">
<source>Authenticated as <x id="0" equiv-text="${renderUsername(event.user.authenticated_as)}"/></source>
</trans-unit>
</body>
</file>

View File

@ -448,7 +448,7 @@
</trans-unit>
<trans-unit id="sc35581d9c1cd67ff">
<source>On behalf of <x id="0" equiv-text="${renderUsername(event.user.on_behalf_of)}"/></source>
<source>On behalf of <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></source>
<target>Ōń ƀēĥàĺƒ ōƒ <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></target>
</trans-unit>
@ -9056,6 +9056,9 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s05849efeac672dc7">
<source>No app entitlements created.</source>
</trans-unit>
<trans-unit id="sdc8a8f29af6aa411">
<source>This application does currently not have any application entitlement defined.</source>
</trans-unit>
<trans-unit id="sf0bd204ce3fea1de">
<source>Create Entitlement</source>
</trans-unit>
@ -9557,10 +9560,4 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s8495753cb15e8d8e">
<source>Maximum allowed registration attempts. When set to 0 attempts, attempts are not limited.</source>
</trans-unit>
<trans-unit id="sab4db6a3bd6abc1e">
<source>This application does currently not have any application entitlements defined.</source>
</trans-unit>
<trans-unit id="s7225aacf0eee94d2">
<source>Authenticated as <x id="0" equiv-text="${renderUsername(event.user.authenticated_as)}"/></source>
</trans-unit>
</body></file></xliff>

View File

@ -451,7 +451,7 @@
</trans-unit>
<trans-unit id="sc35581d9c1cd67ff">
<source>On behalf of <x id="0" equiv-text="${renderUsername(event.user.on_behalf_of)}"/></source>
<source>On behalf of <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></source>
<target>От имени
<x id="0" equiv-text="${event.user.on_behalf_of.username}"/></target>
@ -9113,6 +9113,9 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s05849efeac672dc7">
<source>No app entitlements created.</source>
</trans-unit>
<trans-unit id="sdc8a8f29af6aa411">
<source>This application does currently not have any application entitlement defined.</source>
</trans-unit>
<trans-unit id="sf0bd204ce3fea1de">
<source>Create Entitlement</source>
</trans-unit>
@ -9640,12 +9643,6 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s8495753cb15e8d8e">
<source>Maximum allowed registration attempts. When set to 0 attempts, attempts are not limited.</source>
</trans-unit>
<trans-unit id="sab4db6a3bd6abc1e">
<source>This application does currently not have any application entitlements defined.</source>
</trans-unit>
<trans-unit id="s7225aacf0eee94d2">
<source>Authenticated as <x id="0" equiv-text="${renderUsername(event.user.authenticated_as)}"/></source>
</trans-unit>
</body>
</file>

View File

@ -447,7 +447,7 @@
</trans-unit>
<trans-unit id="sc35581d9c1cd67ff">
<source>On behalf of <x id="0" equiv-text="${renderUsername(event.user.on_behalf_of)}"/></source>
<source>On behalf of <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></source>
<target><x id="0" equiv-text="${event.user.on_behalf_of.username}"/> adına</target>
</trans-unit>
@ -9112,6 +9112,9 @@ Gruplara/kullanıcılara yapılan bağlamalar, etkinliğin kullanıcısına kar
<trans-unit id="s05849efeac672dc7">
<source>No app entitlements created.</source>
</trans-unit>
<trans-unit id="sdc8a8f29af6aa411">
<source>This application does currently not have any application entitlement defined.</source>
</trans-unit>
<trans-unit id="sf0bd204ce3fea1de">
<source>Create Entitlement</source>
</trans-unit>
@ -9612,12 +9615,6 @@ Gruplara/kullanıcılara yapılan bağlamalar, etkinliğin kullanıcısına kar
</trans-unit>
<trans-unit id="s8495753cb15e8d8e">
<source>Maximum allowed registration attempts. When set to 0 attempts, attempts are not limited.</source>
</trans-unit>
<trans-unit id="sab4db6a3bd6abc1e">
<source>This application does currently not have any application entitlements defined.</source>
</trans-unit>
<trans-unit id="s7225aacf0eee94d2">
<source>Authenticated as <x id="0" equiv-text="${renderUsername(event.user.authenticated_as)}"/></source>
</trans-unit>
</body>
</file>

View File

@ -294,7 +294,7 @@
<source>Recent events</source>
</trans-unit>
<trans-unit id="sc35581d9c1cd67ff">
<source>On behalf of <x id="0" equiv-text="${renderUsername(event.user.on_behalf_of)}"/></source>
<source>On behalf of <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></source>
</trans-unit>
<trans-unit id="saf63a04c86018698">
<source>-</source>
@ -5879,6 +5879,9 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s05849efeac672dc7">
<source>No app entitlements created.</source>
</trans-unit>
<trans-unit id="sdc8a8f29af6aa411">
<source>This application does currently not have any application entitlement defined.</source>
</trans-unit>
<trans-unit id="sf0bd204ce3fea1de">
<source>Create Entitlement</source>
</trans-unit>
@ -6380,12 +6383,6 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s8495753cb15e8d8e">
<source>Maximum allowed registration attempts. When set to 0 attempts, attempts are not limited.</source>
</trans-unit>
<trans-unit id="sab4db6a3bd6abc1e">
<source>This application does currently not have any application entitlements defined.</source>
</trans-unit>
<trans-unit id="s7225aacf0eee94d2">
<source>Authenticated as <x id="0" equiv-text="${renderUsername(event.user.authenticated_as)}"/></source>
</trans-unit>
</body>
</file>
</xliff>

View File

@ -451,7 +451,7 @@
</trans-unit>
<trans-unit id="sc35581d9c1cd67ff">
<source>On behalf of <x id="0" equiv-text="${renderUsername(event.user.on_behalf_of)}"/></source>
<source>On behalf of <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></source>
<target>代表
<x id="0" equiv-text="${event.user.on_behalf_of.username}"/></target>
@ -9232,6 +9232,10 @@ Bindings to groups/users are checked against the user of the event.</source>
<source>No app entitlements created.</source>
<target>未创建应用程序授权。</target>
</trans-unit>
<trans-unit id="sdc8a8f29af6aa411">
<source>This application does currently not have any application entitlement defined.</source>
<target>此应用程序目前没有定义任何应用程序授权。</target>
</trans-unit>
<trans-unit id="sf0bd204ce3fea1de">
<source>Create Entitlement</source>
<target>创建授权</target>
@ -9894,12 +9898,6 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s8495753cb15e8d8e">
<source>Maximum allowed registration attempts. When set to 0 attempts, attempts are not limited.</source>
</trans-unit>
<trans-unit id="sab4db6a3bd6abc1e">
<source>This application does currently not have any application entitlements defined.</source>
</trans-unit>
<trans-unit id="s7225aacf0eee94d2">
<source>Authenticated as <x id="0" equiv-text="${renderUsername(event.user.authenticated_as)}"/></source>
</trans-unit>
</body>
</file>

View File

@ -359,7 +359,7 @@
<source>Recent events</source>
</trans-unit>
<trans-unit id="sc35581d9c1cd67ff">
<source>On behalf of <x id="0" equiv-text="${renderUsername(event.user.on_behalf_of)}"/></source>
<source>On behalf of <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></source>
<target>代表
<x id="0" equiv-text="${event.user.on_behalf_of.username}"/></target>
</trans-unit>
@ -6964,6 +6964,9 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s05849efeac672dc7">
<source>No app entitlements created.</source>
</trans-unit>
<trans-unit id="sdc8a8f29af6aa411">
<source>This application does currently not have any application entitlement defined.</source>
</trans-unit>
<trans-unit id="sf0bd204ce3fea1de">
<source>Create Entitlement</source>
</trans-unit>
@ -7464,12 +7467,6 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s8495753cb15e8d8e">
<source>Maximum allowed registration attempts. When set to 0 attempts, attempts are not limited.</source>
</trans-unit>
<trans-unit id="sab4db6a3bd6abc1e">
<source>This application does currently not have any application entitlements defined.</source>
</trans-unit>
<trans-unit id="s7225aacf0eee94d2">
<source>Authenticated as <x id="0" equiv-text="${renderUsername(event.user.authenticated_as)}"/></source>
</trans-unit>
</body>
</file>

View File

@ -445,7 +445,7 @@
</trans-unit>
<trans-unit id="sc35581d9c1cd67ff">
<source>On behalf of <x id="0" equiv-text="${renderUsername(event.user.on_behalf_of)}"/></source>
<source>On behalf of <x id="0" equiv-text="${event.user.on_behalf_of.username}"/></source>
</trans-unit>
<trans-unit id="saf63a04c86018698">
@ -8700,6 +8700,9 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s05849efeac672dc7">
<source>No app entitlements created.</source>
</trans-unit>
<trans-unit id="sdc8a8f29af6aa411">
<source>This application does currently not have any application entitlement defined.</source>
</trans-unit>
<trans-unit id="sf0bd204ce3fea1de">
<source>Create Entitlement</source>
</trans-unit>
@ -9200,12 +9203,6 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s8495753cb15e8d8e">
<source>Maximum allowed registration attempts. When set to 0 attempts, attempts are not limited.</source>
</trans-unit>
<trans-unit id="sab4db6a3bd6abc1e">
<source>This application does currently not have any application entitlements defined.</source>
</trans-unit>
<trans-unit id="s7225aacf0eee94d2">
<source>Authenticated as <x id="0" equiv-text="${renderUsername(event.user.authenticated_as)}"/></source>
</trans-unit>
</body>
</file>

View File

@ -1,11 +1,25 @@
# authentik documentation source
# Website
This directory contains the source files for the [authentik technical documentation](https://docs.goauthentik.io/docs?utm_source=github) and the [authentik integration guides](https://docs.goauthentik.io/integrations?utm_source=github).
This website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator.
Contributions are welcome! Please refer to our [contributor guidelines](https://docs.goauthentik.io/docs/developer-docs?utm_source=github) for details about contributing code or docs.
## Installation
For instructions to set up your local environment for building docs locally, refer to our [Docs development environment](https://docs.goauthentik.io/docs/developer-docs/setup/website-dev-environment?utm_source=github) page.
```console
npm ci
```
For instructions for writing the docs and then testing in your local build, plus tips on writing, links to our Style Guide and templates, see the [Writing documentation guide](https://docs.goauthentik.io/docs/developer-docs/docs/writing-documentation?utm_source=github).
## Local Development
To ensure a smooth review process, we encourage you to build the documentation locally to preview and test your documentation contributions. Be sure to test locally before opening a pull request. Let us know if you have any questions or want help with any part of the process.
```console
npm run watch
```
This command starts a local development server and open up a browser window. Most changes are reflected live without having to restart the server.
## Build
```console
npm run build
```
This command generates static content into the `build` directory and can be served using any static contents hosting service.

View File

@ -10,10 +10,6 @@ However, any flow can be executed via an API from anywhere, in fact that is what
Because the flow executor stores its state in the HTTP Session, so you need to ensure that cookies between flow executor requests are persisted.
:::
:::info
Note that the HTTP session must be obtained as a cookie before `GET /api/v3/flows/executor/:slug` can be called. If you are using a JWT for authentication, you first have to obtain a session cookie via `GET /api/v3/flows/instances/:slug/execute/` before requesting `GET /api/v3/flows/executor/:slug`.
:::
The main endpoint for flow execution is `/api/v3/flows/executor/:slug`.
This endpoint accepts a query parameter called `query`, in which the flow executor sends the full query-string.

View File

@ -19,7 +19,7 @@ Access your Enterprise features by first [purchasing a license](./manage-enterpr
To open the Customer Portal and buy a license, go to the Admin interface and in the left pane, navigate to **Enterprise -> Licenses**, and then click **Go to Customer Portal**.
Alternatively you can open a new browser window and go directly to the [Customer Portal](https://customers.goauthentik.io/). If you do not yet have an authentik account, there is a [Sign up link](https://customers.goauthentik.io/signup) on the Customer Portal login page.
Alternatively you can open a new browser window and go directly to the [Customer Portal](https://customers.goauthentik.io/). If you do not yet have an authentik account, there is a [Sign up link](https://id.customers.goauthentik.io/signup) on the Customer Portal login page.
In the Customer Portal you [define your organization](./manage-enterprise.mdx#create-an-organization) and its members, manage your [licenses](./manage-enterprise.mdx#license-management) and [billing](./manage-enterprise.mdx#manage-billing), and access our [Support center](./entsupport.md).

View File

@ -50,7 +50,7 @@ Note that a license is associated with a specific Organization in the Customer P
1. To get a license key, log in to your authentik account with your administrator credentials, and then click **Admin interface** in the upper right.
2. On the **Admin interface**, navigate to **Enterprise → Licenses** in the left menu, and then click **Go to Customer Portal** under the **Get a license** section. Alternatively you can open a new browser window and go directly to the [Customer Portal](https://customers.goauthentik.io).
2. On the **Admin interface**, navigate to **Enterprise → Licenses** in the left menu, and then click **Go to Customer Portal** under the **Get a license** section. Alternatively you can open a new browser window and go directly to the [Customer Portal](https://id.customers.goauthentik.io).
3. Log in to the Customer Portal.
@ -138,7 +138,7 @@ Once a subscription is canceled, the associated license will still be valid unti
Billing is based on each individual organization.
1. To manage your billing, go to the [Customer Portal](https://customers.goauthentik.io) and navigate to **Organizations > My organizations**.
1. To manage your billing, go to the [Customer Portal](https://id.customers.goauthentik.io) and click "My organizations" in the top menu bar.
2. Select the organization for which you want to manage billing.

View File

@ -96,15 +96,15 @@ vault write auth/oidc/role/reader \
user_claim="sub" \
policies="reader" \
groups_claim="groups" \
oidc_scopes="openid,profile,email"
oidc_scopes=[ "openid profile email" ]
```
Add a group.
```
vault write identity/group \
vault write identity/group/reader \
name="reader" \
policies="reader" \
policies=["reader"] \
type="external"
```

View File

@ -10,7 +10,10 @@ support_level: community
>
> -- https://sssd.io/
Note that authentik supports _only_ user and group objects. As a consequence, it cannot be used to provide automount or sudo configuration, nor can it provide netgroups or services to `nss`. Kerberos is also not supported.
Note that authentik supports _only_ user and group objects. As
a consequence, it cannot be used to provide automount or sudo
configuration nor can it provide netgroups or services to `nss`.
Kerberos is also not supported.
## Preparation
@ -18,10 +21,15 @@ The following placeholders are used in this guide:
- `authentik.company` is the FQDN of the authentik LDAP outpost installation.
- `ldap.baseDN` is the Base DN you configure in the LDAP provider.
- `ldap.domain` is typically a fully qualified domain name (FQDN) representing your domain. Its often derived from the components of your base DN. For example, if `ldap.baseDN` is `dc=ldap,dc=goauthentik,dc=io`, then the domain would be `ldap.goauthentik.io`.
- `ldap.searchGroup` refers to the "Search Group" that has permission to view all users and groups within authentik.
- `ldap.domain` is (typically) an FQDN for your domain. Usually
it is just the components of your base DN. For example, if
`ldap.baseDN` is `dc=ldap,dc=goauthentik,dc=io` then the domain
might be `ldap.goauthentik.io`.
- `ldap.searchGroup` is the "Search Group" that can can see all
users and groups in authentik.
- `sssd.serviceAccount` is a service account created in authentik
- `sssd.serviceAccountToken` is the service account token generated by authentik.
- `sssd.serviceAccountToken` is the service account token generated
by authentik.
:::note
This documentation lists only the settings that you need to change from their default values. Be aware that any changes other than those explicitly mentioned in this guide could cause issues accessing your application.
@ -37,13 +45,19 @@ Follow [official documentation](/docs/add-secure-apps/outposts/#create-and-confi
## sssd configuration
First, install the necessary sssd packages on your host. Very likely the package is just `sssd`.
First, install the necessary sssd packages on your host. Very likely
the package is just `sssd`.
:::note
This guide will help you configure the `sssd.conf` file for LDAP only. You will likely need to perform other tasks for a usable setup like setting up auto-mounted or auto-created home directories that are beyond the scope of this guide. See the "additional resources" section for some help.
This guide well help you configure the `sssd.conf` for LDAP only. You
will likely need to perform other tasks for a usable setup
like setting up automounted or autocreated home directories that
are beyond the scope of this guide. See the "additional resources"
section for some help.
:::
Create a file at `/etc/sssd/sssd.conf` with contents similar to the following:
Create a file at `/etc/sssd/sssd.conf` with contents similar to
the following:
```ini
[nss]
@ -86,30 +100,29 @@ ldap_default_bind_dn = cn=${sssd.serviceAccount},ou=users,${ldap.baseDN}
ldap_default_authtok = ${sssd.serviceAccountToken}
```
You should now be able to start sssd; however, the system may not yet be set up to use it. Depending on your platform, you might need to use `authconfig` or `pam-auth-update` to configure your system. See the additional resources section for details.
You should now be able to start sssd; however, the system may not
yet be setup to use it. Depending on your platform, you may need to
use `authconfig` or `pam-auth-update` to configure your system. See
the additional resources section for details.
:::note
You can store SSH authorized keys in LDAP by adding the `sshPublicKey` attribute to any user with their public key as the value.
Please note that by default, sssd returns all user accounts; active and disabled. This means that disabled user accounts can still authenticate via `sshPublicKey`. To prevent this, you can filter out disabled user accounts by adding the following lines to the LDAP section of your `sssd.conf` file:
```ini
#ldap_access_order = filter
#ldap_access_filter = ak-active=true
```
You can store SSH authorized keys in LDAP by adding the
`sshPublicKey` attribute to any user with their public key as
the value.
:::
## Additional Resources
The setup of sssd might vary based on Linux distribution and version; here are some resources that can help you get this set up:
The setup of sssd may vary based on Linux distribution and version,
here are some resources that can help you get this setup:
:::note
authentik is providing a simple LDAP server, not an Active Directory domain. Be sure you're looking at the correct sections in these guides.
authentik is providing a simple LDAP server, not an Active Directory
domain. Be sure you're looking at the correct sections in these guides.
:::
- [SSSD Docs - Quick Start LDAP](https://sssd.io/docs/quick-start.html#quick-start-ldap)
- [RedHat Docs - Configuring System Services for SSSD](https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/system-level_authentication_guide/configuring_services)
- [Ubuntu Docs - Introduction to network user authentication with SSSD](https://ubuntu.com/server/docs/service-sssd)
- [Debian Manpages - SSSD LDAP provider](https://manpages.debian.org/unstable/sssd-ldap/sssd-ldap.5.en.html)
- [Arch Linux Wiki - LDAP authentication](https://wiki.archlinux.org/title/LDAP_authentication)
- https://sssd.io/docs/quick-start.html#quick-start-ldap
- https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/system-level_authentication_guide/configuring_services
- https://ubuntu.com/server/docs/service-sssd
- https://manpages.debian.org/unstable/sssd-ldap/sssd-ldap.5.en.html
- https://wiki.archlinux.org/title/LDAP_authentication

View File

@ -19,6 +19,7 @@
"@goauthentik/docusaurus-config": "^1.1.0",
"@goauthentik/tsconfig": "^1.0.4",
"@mdx-js/react": "^3.1.0",
"@swc/html-linux-x64-gnu": "1.12.6",
"clsx": "^2.1.1",
"docusaurus-plugin-openapi-docs": "^4.4.0",
"docusaurus-theme-openapi-docs": "^4.4.0",
@ -40,8 +41,8 @@
"@goauthentik/prettier-config": "^1.0.5",
"@goauthentik/tsconfig": "^1.0.4",
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
"@types/lodash": "^4.17.19",
"@types/node": "^24.0.4",
"@types/lodash": "^4.17.18",
"@types/node": "^24.0.3",
"@types/postman-collection": "^3.5.11",
"@types/react": "^18.3.22",
"@types/semver": "^7.7.0",
@ -52,8 +53,8 @@
"fast-glob": "^3.3.3",
"netlify-plugin-cache": "^1.0.3",
"npm-run-all": "^4.1.5",
"prettier": "^3.6.1",
"prettier-plugin-packagejson": "^2.5.16",
"prettier": "^3.6.0",
"prettier-plugin-packagejson": "^2.5.15",
"typescript": "^5.8.3",
"typescript-eslint": "^8.35.0"
},
@ -64,12 +65,12 @@
"@rspack/binding-darwin-arm64": "1.3.15",
"@rspack/binding-linux-arm64-gnu": "1.3.15",
"@rspack/binding-linux-x64-gnu": "1.3.15",
"@swc/core-darwin-arm64": "1.12.7",
"@swc/core-linux-arm64-gnu": "1.12.7",
"@swc/core-linux-x64-gnu": "1.12.7",
"@swc/html-darwin-arm64": "1.12.7",
"@swc/html-linux-arm64-gnu": "1.12.7",
"@swc/html-linux-x64-gnu": "1.12.7",
"@swc/core-darwin-arm64": "1.12.6",
"@swc/core-linux-arm64-gnu": "1.12.6",
"@swc/core-linux-x64-gnu": "1.12.6",
"@swc/html-darwin-arm64": "1.12.6",
"@swc/html-linux-arm64-gnu": "1.12.6",
"@swc/html-linux-x64-gnu": "1.12.6",
"lightningcss-darwin-arm64": "1.30.1",
"lightningcss-linux-arm64-gnu": "1.30.1",
"lightningcss-linux-x64-gnu": "1.30.1"
@ -5592,9 +5593,9 @@
}
},
"node_modules/@swc/core-darwin-arm64": {
"version": "1.12.7",
"resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.12.7.tgz",
"integrity": "sha512-w6BBT0hBRS56yS+LbReVym0h+iB7/PpCddqrn1ha94ra4rZ4R/A91A/rkv+LnQlPqU/+fhqdlXtCJU9mrhCBtA==",
"version": "1.12.6",
"resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.12.6.tgz",
"integrity": "sha512-yLiw+XzG+MilfFh0ON7qt67bfIr7UxB9JprhYReVOmLTBDmDVQSC3T4/vIuc+GwlX08ydnHy0ud4lIjTNW4uWg==",
"cpu": [
"arm64"
],
@ -5640,9 +5641,9 @@
}
},
"node_modules/@swc/core-linux-arm64-gnu": {
"version": "1.12.7",
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.12.7.tgz",
"integrity": "sha512-N15hKizSSh+hkZ2x3TDVrxq0TDcbvDbkQJi2ZrLb9fK+NdFUV/x+XF16ZDPlbxtrGXl1CT7VD439SNaMN9F7qw==",
"version": "1.12.6",
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.12.6.tgz",
"integrity": "sha512-h8+Ltx0NSEzIFHetkOYoQ+UQ59unYLuJ4wF6kCpxzS4HskRLjcngr1HgN0F/PRpptnrmJUPVQmfms/vjN8ndAQ==",
"cpu": [
"arm64"
],
@ -5672,9 +5673,9 @@
}
},
"node_modules/@swc/core-linux-x64-gnu": {
"version": "1.12.7",
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.12.7.tgz",
"integrity": "sha512-PR4tPVwU1BQBfFDk2XfzXxsEIjF3x/bOV1BzZpYvrlkU0TKUDbR4t2wzvsYwD/coW7/yoQmlL70/qnuPtTp1Zw==",
"version": "1.12.6",
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.12.6.tgz",
"integrity": "sha512-WwJLQFzMW9ufVjM6k3le4HUgBFNunyt2oghjcgn2YjnKj0Ka2LrrBHCxfS7lgFSCQh/shib2wIlKXUnlTEWQJw==",
"cpu": [
"x64"
],
@ -5830,9 +5831,9 @@
}
},
"node_modules/@swc/html-darwin-arm64": {
"version": "1.12.7",
"resolved": "https://registry.npmjs.org/@swc/html-darwin-arm64/-/html-darwin-arm64-1.12.7.tgz",
"integrity": "sha512-4rHV4lW8PXSc7YfJ/c9Cj0xZWSJArkD/Yuax4plH6f4VtEcEAluZI3ryBG3Vh4VawQ1RMkytPQ2S65BbCyDIXg==",
"version": "1.12.6",
"resolved": "https://registry.npmjs.org/@swc/html-darwin-arm64/-/html-darwin-arm64-1.12.6.tgz",
"integrity": "sha512-McW4JsF5wFB5KmHyAaty94kw2hHLbYtrIQvVlshbXM3lpY+rDO0KnS74CcIiAD46p7knV0Y6Xuhint8K3rYfkg==",
"cpu": [
"arm64"
],
@ -5878,9 +5879,9 @@
}
},
"node_modules/@swc/html-linux-arm64-gnu": {
"version": "1.12.7",
"resolved": "https://registry.npmjs.org/@swc/html-linux-arm64-gnu/-/html-linux-arm64-gnu-1.12.7.tgz",
"integrity": "sha512-z66ejXsSwI0mKyDhLimG74+xZyvSQCrceSZv9jLHa23sn/di+07M9njZrj3SQKGfHoJqXsN1iPqDpvkVajNb9Q==",
"version": "1.12.6",
"resolved": "https://registry.npmjs.org/@swc/html-linux-arm64-gnu/-/html-linux-arm64-gnu-1.12.6.tgz",
"integrity": "sha512-2S9hXG5EvDMHdjeiVANft+mZ+dRUrqUqKEAM0GehxsnG/ITT4uTolI3u/upMo7t1leOMWcz85hJZqDbVtfyP5Q==",
"cpu": [
"arm64"
],
@ -5910,9 +5911,9 @@
}
},
"node_modules/@swc/html-linux-x64-gnu": {
"version": "1.12.7",
"resolved": "https://registry.npmjs.org/@swc/html-linux-x64-gnu/-/html-linux-x64-gnu-1.12.7.tgz",
"integrity": "sha512-5KFLil4ELKzCLjjvKpt+SMEU6uBDR/EL4e7eleybtYi1cU8Jzv0xnTvabsVDfpT8fsvJF3Mvach4F/ggH5+CDQ==",
"version": "1.12.6",
"resolved": "https://registry.npmjs.org/@swc/html-linux-x64-gnu/-/html-linux-x64-gnu-1.12.6.tgz",
"integrity": "sha512-nZzjhrya4VFfT2jX2EYe+FF1EzeghHAB5wyOASFN35CxOpJMhr/04COu5uRggZGYD+19s1LrLelKhSOBAPDrOw==",
"cpu": [
"x64"
],
@ -6581,9 +6582,9 @@
"license": "MIT"
},
"node_modules/@types/lodash": {
"version": "4.17.19",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.19.tgz",
"integrity": "sha512-NYqRyg/hIQrYPT9lbOeYc3kIRabJDn/k4qQHIXUpx88CBDww2fD15Sg5kbXlW86zm2XEW4g0QxkTI3/Kfkc7xQ==",
"version": "4.17.18",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.18.tgz",
"integrity": "sha512-KJ65INaxqxmU6EoCiJmRPZC9H9RVWCRd349tXM2M3O5NA7cY6YL7c0bHAHQ93NOfTObEQ004kd2QVHs/r0+m4g==",
"dev": true,
"license": "MIT"
},
@ -6615,9 +6616,9 @@
"license": "MIT"
},
"node_modules/@types/node": {
"version": "24.0.4",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.4.tgz",
"integrity": "sha512-ulyqAkrhnuNq9pB76DRBTkcS6YsmDALy6Ua63V8OhrOBgbcYt6IOdzpw5P1+dyRIyMerzLkeYWBeOXPpA9GMAA==",
"version": "24.0.3",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.0.3.tgz",
"integrity": "sha512-R4I/kzCYAdRLzfiCabn9hxWfbuHS573x+r0dJMkkzThEa7pbrcDWK+9zu3e7aBOouf+rQAciqPFMnxwr0aWgKg==",
"license": "MIT",
"dependencies": {
"undici-types": "~7.8.0"
@ -22265,9 +22266,9 @@
}
},
"node_modules/prettier": {
"version": "3.6.1",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.1.tgz",
"integrity": "sha512-5xGWRa90Sp2+x1dQtNpIpeOQpTDBs9cZDmA/qs2vDNN2i18PdapqY7CmBeyLlMuGqXJRIOPaCaVZTLNQRWUH/A==",
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.0.tgz",
"integrity": "sha512-ujSB9uXHJKzM/2GBuE0hBOUgC77CN3Bnpqa+g80bkv3T3A93wL/xlzDATHhnhkzifz/UE2SNOvmbTz5hSkDlHw==",
"dev": true,
"license": "MIT",
"bin": {
@ -22299,13 +22300,13 @@
}
},
"node_modules/prettier-plugin-packagejson": {
"version": "2.5.16",
"resolved": "https://registry.npmjs.org/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.5.16.tgz",
"integrity": "sha512-1EORN4SahAWU55ll+xp0PXhiUmD93PJlBE88GbWv7X5xtZ7ycj3GNbRGX+r75zWn70KAoYVO08rF2C/TqGCHPA==",
"version": "2.5.15",
"resolved": "https://registry.npmjs.org/prettier-plugin-packagejson/-/prettier-plugin-packagejson-2.5.15.tgz",
"integrity": "sha512-2QSx6y4IT6LTwXtCvXAopENW5IP/aujC8fobEM2pDbs0IGkiVjW/ipPuYAHuXigbNe64aGWF7vIetukuzM3CBw==",
"dev": true,
"license": "MIT",
"dependencies": {
"sort-package-json": "3.2.2",
"sort-package-json": "3.2.1",
"synckit": "0.11.8"
},
"peerDependencies": {
@ -25152,9 +25153,9 @@
"license": "MIT"
},
"node_modules/sort-package-json": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-3.2.2.tgz",
"integrity": "sha512-twAMvmzOcEPsN3N9zKPDpl6zproGU0JcBOQFU4T6e5wrStH8iuPiAjFz9g+cMRC52eQBUbZlFCeGt+F4vginkw==",
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/sort-package-json/-/sort-package-json-3.2.1.tgz",
"integrity": "sha512-rTfRdb20vuoAn7LDlEtCqOkYfl2X+Qze6cLbNOzcDpbmKEhJI30tTN44d5shbKJnXsvz24QQhlCm81Bag7EOKg==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -26056,9 +26057,9 @@
"license": "MIT"
},
"node_modules/tinyglobby": {
"version": "0.2.14",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz",
"integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==",
"version": "0.2.13",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz",
"integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==",
"dev": true,
"license": "MIT",
"dependencies": {
@ -26073,9 +26074,9 @@
}
},
"node_modules/tinyglobby/node_modules/fdir": {
"version": "6.4.6",
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz",
"integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==",
"version": "6.4.4",
"resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz",
"integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==",
"dev": true,
"license": "MIT",
"peerDependencies": {

View File

@ -57,8 +57,8 @@
"@goauthentik/prettier-config": "^1.0.5",
"@goauthentik/tsconfig": "^1.0.4",
"@trivago/prettier-plugin-sort-imports": "^5.2.2",
"@types/lodash": "^4.17.19",
"@types/node": "^24.0.4",
"@types/lodash": "^4.17.18",
"@types/node": "^24.0.3",
"@types/postman-collection": "^3.5.11",
"@types/react": "^18.3.22",
"@types/semver": "^7.7.0",
@ -69,8 +69,8 @@
"fast-glob": "^3.3.3",
"netlify-plugin-cache": "^1.0.3",
"npm-run-all": "^4.1.5",
"prettier": "^3.6.1",
"prettier-plugin-packagejson": "^2.5.16",
"prettier": "^3.6.0",
"prettier-plugin-packagejson": "^2.5.15",
"typescript": "^5.8.3",
"typescript-eslint": "^8.35.0"
},
@ -78,12 +78,12 @@
"@rspack/binding-darwin-arm64": "1.3.15",
"@rspack/binding-linux-arm64-gnu": "1.3.15",
"@rspack/binding-linux-x64-gnu": "1.3.15",
"@swc/core-darwin-arm64": "1.12.7",
"@swc/core-linux-arm64-gnu": "1.12.7",
"@swc/core-linux-x64-gnu": "1.12.7",
"@swc/html-darwin-arm64": "1.12.7",
"@swc/html-linux-arm64-gnu": "1.12.7",
"@swc/html-linux-x64-gnu": "1.12.7",
"@swc/core-darwin-arm64": "1.12.6",
"@swc/core-linux-arm64-gnu": "1.12.6",
"@swc/core-linux-x64-gnu": "1.12.6",
"@swc/html-darwin-arm64": "1.12.6",
"@swc/html-linux-arm64-gnu": "1.12.6",
"@swc/html-linux-x64-gnu": "1.12.6",
"lightningcss-darwin-arm64": "1.30.1",
"lightningcss-linux-arm64-gnu": "1.30.1",
"lightningcss-linux-x64-gnu": "1.30.1"