Merge branch 'main' into dev

* main: (23 commits)
  providers/oauth2: fix interactive device flow (#9076)
  website/docs: fix transports example (#9074)
  events: fix log_capture (#9075)
  web: bump the sentry group in /web with 2 updates (#9065)
  core: bump goauthentik.io/api/v3 from 3.2024022.6 to 3.2024022.7 (#9064)
  web: bump @codemirror/lang-python from 6.1.4 to 6.1.5 in /web (#9068)
  web: bump the eslint group in /web with 1 update (#9066)
  web: bump glob from 10.3.10 to 10.3.12 in /web (#9069)
  web: bump the rollup group in /web with 3 updates (#9067)
  web: bump the eslint group in /tests/wdio with 1 update (#9071)
  core: bump webauthn from 2.0.0 to 2.1.0 (#9070)
  core: bump sentry-sdk from 1.43.0 to 1.44.0 (#9073)
  core: bump requests-mock from 1.12.0 to 1.12.1 (#9072)
  web: bump API Client version (#9061)
  events: rework log messages returned from API and their rendering (#8770)
  website/docs: update airgapped config (#9049)
  website: bump @types/react from 18.2.72 to 18.2.73 in /website (#9052)
  web: bump the rollup group in /web with 3 updates (#9053)
  core: bump django-filter from 24.1 to 24.2 (#9055)
  core: bump requests-mock from 1.11.0 to 1.12.0 (#9056)
  ...
This commit is contained in:
Ken Sternberg
2024-03-29 08:35:41 -07:00
38 changed files with 552 additions and 334 deletions

View File

@ -19,8 +19,6 @@ from guardian.models import UserObjectPermission
from rest_framework.exceptions import ValidationError
from rest_framework.serializers import BaseSerializer, Serializer
from structlog.stdlib import BoundLogger, get_logger
from structlog.testing import capture_logs
from structlog.types import EventDict
from yaml import load
from authentik.blueprints.v1.common import (
@ -42,6 +40,7 @@ from authentik.core.models import (
from authentik.enterprise.license import LicenseKey
from authentik.enterprise.models import LicenseUsage
from authentik.enterprise.providers.rac.models import ConnectionToken
from authentik.events.logs import LogEvent, capture_logs
from authentik.events.models import SystemTask
from authentik.events.utils import cleanse_dict
from authentik.flows.models import FlowToken, Stage
@ -161,7 +160,7 @@ class Importer:
def updater(value) -> Any:
if value in self.__pk_map:
self.logger.debug("updating reference in entry", value=value)
self.logger.debug("Updating reference in entry", value=value)
return self.__pk_map[value]
return value
@ -250,7 +249,7 @@ class Importer:
model_instance = existing_models.first()
if not isinstance(model(), BaseMetaModel) and model_instance:
self.logger.debug(
"initialise serializer with instance",
"Initialise serializer with instance",
model=model,
instance=model_instance,
pk=model_instance.pk,
@ -260,14 +259,14 @@ class Importer:
elif model_instance and entry.state == BlueprintEntryDesiredState.MUST_CREATED:
raise EntryInvalidError.from_entry(
(
f"state is set to {BlueprintEntryDesiredState.MUST_CREATED} "
f"State is set to {BlueprintEntryDesiredState.MUST_CREATED} "
"and object exists already",
),
entry,
)
else:
self.logger.debug(
"initialised new serializer instance",
"Initialised new serializer instance",
model=model,
**cleanse_dict(updated_identifiers),
)
@ -324,7 +323,7 @@ class Importer:
model: type[SerializerModel] = registry.get_model(model_app_label, model_name)
except LookupError:
self.logger.warning(
"app or model does not exist", app=model_app_label, model=model_name
"App or Model does not exist", app=model_app_label, model=model_name
)
return False
# Validate each single entry
@ -336,7 +335,7 @@ class Importer:
if entry.get_state(self._import) == BlueprintEntryDesiredState.ABSENT:
serializer = exc.serializer
else:
self.logger.warning(f"entry invalid: {exc}", entry=entry, error=exc)
self.logger.warning(f"Entry invalid: {exc}", entry=entry, error=exc)
if raise_errors:
raise exc
return False
@ -356,14 +355,14 @@ class Importer:
and state == BlueprintEntryDesiredState.CREATED
):
self.logger.debug(
"instance exists, skipping",
"Instance exists, skipping",
model=model,
instance=instance,
pk=instance.pk,
)
else:
instance = serializer.save()
self.logger.debug("updated model", model=instance)
self.logger.debug("Updated model", model=instance)
if "pk" in entry.identifiers:
self.__pk_map[entry.identifiers["pk"]] = instance.pk
entry._state = BlueprintEntryState(instance)
@ -371,12 +370,12 @@ class Importer:
instance: Model | None = serializer.instance
if instance.pk:
instance.delete()
self.logger.debug("deleted model", mode=instance)
self.logger.debug("Deleted model", mode=instance)
continue
self.logger.debug("entry to delete with no instance, skipping")
self.logger.debug("Entry to delete with no instance, skipping")
return True
def validate(self, raise_validation_errors=False) -> tuple[bool, list[EventDict]]:
def validate(self, raise_validation_errors=False) -> tuple[bool, list[LogEvent]]:
"""Validate loaded blueprint export, ensure all models are allowed
and serializers have no errors"""
self.logger.debug("Starting blueprint import validation")
@ -390,9 +389,7 @@ class Importer:
):
successful = self._apply_models(raise_errors=raise_validation_errors)
if not successful:
self.logger.debug("Blueprint validation failed")
for log in logs:
getattr(self.logger, log.get("log_level"))(**log)
self.logger.warning("Blueprint validation failed")
self.logger.debug("Finished blueprint import validation")
self._import = orig_import
return successful, logs

View File

@ -30,6 +30,7 @@ from authentik.blueprints.v1.common import BlueprintLoader, BlueprintMetadata, E
from authentik.blueprints.v1.importer import Importer
from authentik.blueprints.v1.labels import LABEL_AUTHENTIK_INSTANTIATE
from authentik.blueprints.v1.oci import OCI_PREFIX
from authentik.events.logs import capture_logs
from authentik.events.models import TaskStatus
from authentik.events.system_tasks import SystemTask, prefill_task
from authentik.events.utils import sanitize_dict
@ -211,14 +212,15 @@ def apply_blueprint(self: SystemTask, instance_pk: str):
if not valid:
instance.status = BlueprintInstanceStatus.ERROR
instance.save()
self.set_status(TaskStatus.ERROR, *[x["event"] for x in logs])
return
applied = importer.apply()
if not applied:
instance.status = BlueprintInstanceStatus.ERROR
instance.save()
self.set_status(TaskStatus.ERROR, "Failed to apply")
self.set_status(TaskStatus.ERROR, *logs)
return
with capture_logs() as logs:
applied = importer.apply()
if not applied:
instance.status = BlueprintInstanceStatus.ERROR
instance.save()
self.set_status(TaskStatus.ERROR, *logs)
return
instance.status = BlueprintInstanceStatus.SUCCESSFUL
instance.last_applied_hash = file_hash
instance.last_applied = now()

View File

@ -20,15 +20,14 @@ from rest_framework.response import Response
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet
from structlog.stdlib import get_logger
from structlog.testing import capture_logs
from authentik.admin.api.metrics import CoordinateSerializer
from authentik.blueprints.v1.importer import SERIALIZER_CONTEXT_BLUEPRINT
from authentik.core.api.providers import ProviderSerializer
from authentik.core.api.used_by import UsedByMixin
from authentik.core.models import Application, User
from authentik.events.logs import LogEventSerializer, capture_logs
from authentik.events.models import EventAction
from authentik.events.utils import sanitize_dict
from authentik.lib.utils.file import (
FilePathSerializer,
FileUploadSerializer,
@ -182,9 +181,9 @@ class ApplicationViewSet(UsedByMixin, ModelViewSet):
if request.user.is_superuser:
log_messages = []
for log in logs:
if log.get("process", "") == "PolicyProcess":
if log.attributes.get("process", "") == "PolicyProcess":
continue
log_messages.append(sanitize_dict(log))
log_messages.append(LogEventSerializer(log).data)
result.log_messages = log_messages
response = PolicyTestResultSerializer(result)
return Response(response.data)

View File

@ -12,7 +12,6 @@ from rest_framework.fields import (
ChoiceField,
DateTimeField,
FloatField,
ListField,
SerializerMethodField,
)
from rest_framework.request import Request
@ -21,6 +20,7 @@ from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ReadOnlyModelViewSet
from structlog.stdlib import get_logger
from authentik.events.logs import LogEventSerializer
from authentik.events.models import SystemTask, TaskStatus
from authentik.rbac.decorators import permission_required
@ -39,7 +39,7 @@ class SystemTaskSerializer(ModelSerializer):
duration = FloatField(read_only=True)
status = ChoiceField(choices=[(x.value, x.name) for x in TaskStatus])
messages = ListField(child=CharField())
messages = LogEventSerializer(many=True)
def get_full_name(self, instance: SystemTask) -> str:
"""Get full name with UID"""

82
authentik/events/logs.py Normal file
View File

@ -0,0 +1,82 @@
from collections.abc import Generator
from contextlib import contextmanager
from dataclasses import dataclass, field
from datetime import datetime
from typing import Any
from django.utils.timezone import now
from rest_framework.fields import CharField, ChoiceField, DateTimeField, DictField
from structlog import configure, get_config
from structlog.stdlib import NAME_TO_LEVEL, ProcessorFormatter
from structlog.testing import LogCapture
from structlog.types import EventDict
from authentik.core.api.utils import PassiveSerializer
from authentik.events.utils import sanitize_dict
@dataclass()
class LogEvent:
event: str
log_level: str
logger: str
timestamp: datetime = field(default_factory=now)
attributes: dict[str, Any] = field(default_factory=dict)
@staticmethod
def from_event_dict(item: EventDict) -> "LogEvent":
event = item.pop("event")
log_level = item.pop("level").lower()
timestamp = datetime.fromisoformat(item.pop("timestamp"))
item.pop("pid", None)
# Sometimes log entries have both `level` and `log_level` set, but `level` is always set
item.pop("log_level", None)
return LogEvent(
event, log_level, item.pop("logger"), timestamp, attributes=sanitize_dict(item)
)
class LogEventSerializer(PassiveSerializer):
"""Single log message with all context logged."""
timestamp = DateTimeField()
log_level = ChoiceField(choices=tuple((x, x) for x in NAME_TO_LEVEL.keys()))
logger = CharField()
event = CharField()
attributes = DictField()
# TODO(2024.6?): This is a migration helper to return a correct API response for logs that
# have been saved in an older format (mostly just list[str] with just the messages)
def to_representation(self, instance):
if isinstance(instance, str):
instance = LogEvent(instance, "", "")
elif isinstance(instance, list):
instance = [LogEvent(x, "", "") for x in instance]
return super().to_representation(instance)
@contextmanager
def capture_logs(log_default_output=True) -> Generator[list[LogEvent], None, None]:
"""Capture log entries created"""
logs = []
cap = LogCapture()
# Modify `_Configuration.default_processors` set via `configure` but always
# keep the list instance intact to not break references held by bound
# loggers.
processors: list = get_config()["processors"]
old_processors = processors.copy()
try:
# clear processors list and use LogCapture for testing
if ProcessorFormatter.wrap_for_formatter in processors:
processors.remove(ProcessorFormatter.wrap_for_formatter)
processors.append(cap)
configure(processors=processors)
yield logs
for raw_log in cap.entries:
logs.append(LogEvent.from_event_dict(raw_log))
finally:
# remove LogCapture and restore original processors
processors.clear()
processors.extend(old_processors)
configure(processors=processors)

View File

@ -9,6 +9,7 @@ from django.utils.translation import gettext_lazy as _
from structlog.stdlib import get_logger
from tenant_schemas_celery.task import TenantTask
from authentik.events.logs import LogEvent
from authentik.events.models import Event, EventAction, TaskStatus
from authentik.events.models import SystemTask as DBSystemTask
from authentik.events.utils import sanitize_item
@ -24,7 +25,7 @@ class SystemTask(TenantTask):
save_on_success: bool
_status: TaskStatus
_messages: list[str]
_messages: list[LogEvent]
_uid: str | None
# Precise start time from perf_counter
@ -44,15 +45,20 @@ class SystemTask(TenantTask):
"""Set UID, so in the case of an unexpected error its saved correctly"""
self._uid = uid
def set_status(self, status: TaskStatus, *messages: str):
def set_status(self, status: TaskStatus, *messages: LogEvent):
"""Set result for current run, will overwrite previous result."""
self._status = status
self._messages = messages
self._messages = list(messages)
for idx, msg in enumerate(self._messages):
if not isinstance(msg, LogEvent):
self._messages[idx] = LogEvent(msg, logger=self.__name__, log_level="info")
def set_error(self, exception: Exception):
"""Set result to error and save exception"""
self._status = TaskStatus.ERROR
self._messages = [exception_to_string(exception)]
self._messages = [
LogEvent(exception_to_string(exception), logger=self.__name__, log_level="error")
]
def before_start(self, task_id, args, kwargs):
self._start_precise = perf_counter()
@ -98,8 +104,7 @@ class SystemTask(TenantTask):
def on_failure(self, exc, task_id, args, kwargs, einfo):
super().on_failure(exc, task_id, args, kwargs, einfo=einfo)
if not self._status:
self._status = TaskStatus.ERROR
self._messages = exception_to_string(exc)
self.set_error(exc)
DBSystemTask.objects.update_or_create(
name=self.__name__,
uid=self._uid,

View File

@ -7,7 +7,7 @@ from django.utils.translation import gettext as _
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import OpenApiResponse, extend_schema
from rest_framework.decorators import action
from rest_framework.fields import BooleanField, CharField, DictField, ListField, ReadOnlyField
from rest_framework.fields import BooleanField, CharField, ReadOnlyField
from rest_framework.parsers import MultiPartParser
from rest_framework.request import Request
from rest_framework.response import Response
@ -19,7 +19,7 @@ from authentik.blueprints.v1.exporter import FlowExporter
from authentik.blueprints.v1.importer import SERIALIZER_CONTEXT_BLUEPRINT, Importer
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import CacheSerializer, LinkSerializer, PassiveSerializer
from authentik.events.utils import sanitize_dict
from authentik.events.logs import LogEventSerializer
from authentik.flows.api.flows_diagram import FlowDiagram, FlowDiagramSerializer
from authentik.flows.exceptions import FlowNonApplicableException
from authentik.flows.models import Flow
@ -107,7 +107,7 @@ class FlowSetSerializer(FlowSerializer):
class FlowImportResultSerializer(PassiveSerializer):
"""Logs of an attempted flow import"""
logs = ListField(child=DictField(), read_only=True)
logs = LogEventSerializer(many=True, read_only=True)
success = BooleanField(read_only=True)
@ -184,7 +184,7 @@ class FlowViewSet(UsedByMixin, ModelViewSet):
importer = Importer.from_string(file.read().decode())
valid, logs = importer.validate()
import_response.initial_data["logs"] = [sanitize_dict(log) for log in logs]
import_response.initial_data["logs"] = [LogEventSerializer(log).data for log in logs]
import_response.initial_data["success"] = valid
import_response.is_valid()
if not valid:

View File

@ -59,11 +59,11 @@ class FlowPlan:
markers: list[StageMarker] = field(default_factory=list)
def append_stage(self, stage: Stage, marker: StageMarker | None = None):
"""Append `stage` to all stages, optionally with stage marker"""
"""Append `stage` to the end of the plan, optionally with stage marker"""
return self.append(FlowStageBinding(stage=stage), marker)
def append(self, binding: FlowStageBinding, marker: StageMarker | None = None):
"""Append `stage` to all stages, optionally with stage marker"""
"""Append `stage` to the end of the plan, optionally with stage marker"""
self.bindings.append(binding)
self.markers.append(marker or StageMarker())

View File

@ -450,7 +450,7 @@ class FlowExecutorView(APIView):
return to_stage_response(self.request, challenge_view.get(self.request))
def cancel(self):
"""Cancel current execution and return a redirect"""
"""Cancel current flow execution"""
keys_to_delete = [
SESSION_KEY_APPLICATION_PRE,
SESSION_KEY_PLAN,

View File

@ -3,9 +3,9 @@
from dataclasses import dataclass
from structlog.stdlib import get_logger
from structlog.testing import capture_logs
from authentik import __version__, get_build_hash
from authentik.events.logs import LogEvent, capture_logs
from authentik.lib.config import CONFIG
from authentik.lib.sentry import SentryIgnoredException
from authentik.outposts.models import (
@ -63,21 +63,21 @@ class BaseController:
"""Called by scheduled task to reconcile deployment/service/etc"""
raise NotImplementedError
def up_with_logs(self) -> list[str]:
def up_with_logs(self) -> list[LogEvent]:
"""Call .up() but capture all log output and return it."""
with capture_logs() as logs:
self.up()
return [x["event"] for x in logs]
return logs
def down(self):
"""Handler to delete everything we've created"""
raise NotImplementedError
def down_with_logs(self) -> list[str]:
def down_with_logs(self) -> list[LogEvent]:
"""Call .down() but capture all log output and return it."""
with capture_logs() as logs:
self.down()
return [x["event"] for x in logs]
return logs
def __enter__(self):
return self

View File

@ -9,10 +9,10 @@ from kubernetes.client.exceptions import OpenApiException
from kubernetes.config.config_exception import ConfigException
from kubernetes.config.incluster_config import load_incluster_config
from kubernetes.config.kube_config import load_kube_config_from_dict
from structlog.testing import capture_logs
from urllib3.exceptions import HTTPError
from yaml import dump_all
from authentik.events.logs import LogEvent, capture_logs
from authentik.outposts.controllers.base import BaseClient, BaseController, ControllerException
from authentik.outposts.controllers.k8s.base import KubernetesObjectReconciler
from authentik.outposts.controllers.k8s.deployment import DeploymentReconciler
@ -91,7 +91,7 @@ class KubernetesController(BaseController):
except (OpenApiException, HTTPError, ServiceConnectionInvalid) as exc:
raise ControllerException(str(exc)) from exc
def up_with_logs(self) -> list[str]:
def up_with_logs(self) -> list[LogEvent]:
try:
all_logs = []
for reconcile_key in self.reconcile_order:
@ -104,7 +104,9 @@ class KubernetesController(BaseController):
continue
reconciler = reconciler_cls(self)
reconciler.up()
all_logs += [f"{reconcile_key.title()}: {x['event']}" for x in logs]
for log in logs:
log.logger = reconcile_key.title()
all_logs.extend(logs)
return all_logs
except (OpenApiException, HTTPError, ServiceConnectionInvalid) as exc:
raise ControllerException(str(exc)) from exc
@ -122,7 +124,7 @@ class KubernetesController(BaseController):
except (OpenApiException, HTTPError, ServiceConnectionInvalid) as exc:
raise ControllerException(str(exc)) from exc
def down_with_logs(self) -> list[str]:
def down_with_logs(self) -> list[LogEvent]:
try:
all_logs = []
for reconcile_key in self.reconcile_order:
@ -135,7 +137,9 @@ class KubernetesController(BaseController):
continue
reconciler = reconciler_cls(self)
reconciler.down()
all_logs += [f"{reconcile_key.title()}: {x['event']}" for x in logs]
for log in logs:
log.logger = reconcile_key.title()
all_logs.extend(logs)
return all_logs
except (OpenApiException, HTTPError, ServiceConnectionInvalid) as exc:
raise ControllerException(str(exc)) from exc

View File

@ -149,10 +149,8 @@ def outpost_controller(
if not controller_type:
return
with controller_type(outpost, outpost.service_connection) as controller:
logs = getattr(controller, f"{action}_with_logs")()
LOGGER.debug("---------------Outpost Controller logs starting----------------")
for log in logs:
LOGGER.debug(log)
logs = getattr(controller, f"{action}_with_logs")()
LOGGER.debug("-----------------Outpost Controller logs end-------------------")
except (ControllerException, ServiceConnectionInvalid) as exc:
self.set_error(exc)

View File

@ -1,10 +1,11 @@
"""Serializer for policy execution"""
from rest_framework.fields import BooleanField, CharField, DictField, ListField
from rest_framework.fields import BooleanField, CharField, ListField
from rest_framework.relations import PrimaryKeyRelatedField
from authentik.core.api.utils import JSONDictField, PassiveSerializer
from authentik.core.models import User
from authentik.events.logs import LogEventSerializer
class PolicyTestSerializer(PassiveSerializer):
@ -19,4 +20,4 @@ class PolicyTestResultSerializer(PassiveSerializer):
passing = BooleanField()
messages = ListField(child=CharField(), read_only=True)
log_messages = ListField(child=DictField(), read_only=True)
log_messages = LogEventSerializer(many=True, read_only=True)

View File

@ -11,12 +11,11 @@ from rest_framework.response import Response
from rest_framework.serializers import ModelSerializer, SerializerMethodField
from rest_framework.viewsets import GenericViewSet
from structlog.stdlib import get_logger
from structlog.testing import capture_logs
from authentik.core.api.applications import user_app_cache_key
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import CacheSerializer, MetaNameSerializer, TypeCreateSerializer
from authentik.events.utils import sanitize_dict
from authentik.events.logs import LogEventSerializer, capture_logs
from authentik.lib.utils.reflection import all_subclasses
from authentik.policies.api.exec import PolicyTestResultSerializer, PolicyTestSerializer
from authentik.policies.models import Policy, PolicyBinding
@ -166,9 +165,9 @@ class PolicyViewSet(
result = proc.execute()
log_messages = []
for log in logs:
if log.get("process", "") == "PolicyProcess":
if log.attributes.get("process", "") == "PolicyProcess":
continue
log_messages.append(sanitize_dict(log))
log_messages.append(LogEventSerializer(log).data)
result.log_messages = log_messages
response = PolicyTestResultSerializer(result)
return Response(response.data)

View File

@ -13,6 +13,7 @@ from authentik.events.context_processors.base import get_context_processors
if TYPE_CHECKING:
from authentik.core.models import User
from authentik.events.logs import LogEvent
from authentik.policies.models import PolicyBinding
LOGGER = get_logger()
@ -74,7 +75,7 @@ class PolicyResult:
source_binding: PolicyBinding | None
source_results: list[PolicyResult] | None
log_messages: list[dict] | None
log_messages: list[LogEvent] | None
def __init__(self, passing: bool, *messages: str):
self.passing = passing

View File

@ -25,7 +25,7 @@ class OAuthDeviceCodeFinishChallengeResponse(ChallengeResponse):
class OAuthDeviceCodeFinishStage(ChallengeStageView):
"""Stage show at the end of a device flow"""
"""Stage to finish the OAuth device code flow"""
response_class = OAuthDeviceCodeFinishChallengeResponse

View File

@ -3,7 +3,7 @@
from django.http import HttpRequest, HttpResponse
from django.utils.translation import gettext as _
from django.views import View
from rest_framework.exceptions import ErrorDetail
from rest_framework.exceptions import ValidationError
from rest_framework.fields import CharField, IntegerField
from structlog.stdlib import get_logger
@ -57,6 +57,7 @@ def validate_code(code: int, request: HttpRequest) -> HttpResponse | None:
scope_descriptions = UserInfoView().get_scope_descriptions(token.scope, token.provider)
planner = FlowPlanner(token.provider.authorization_flow)
planner.allow_empty_flows = True
planner.use_cache = False
try:
plan = planner.plan(
request,
@ -128,6 +129,13 @@ class OAuthDeviceCodeChallengeResponse(ChallengeResponse):
code = IntegerField()
component = CharField(default="ak-provider-oauth2-device-code")
def validate_code(self, code: int) -> HttpResponse | None:
"""Validate code and save the returned http response"""
response = validate_code(code, self.stage.request)
if not response:
raise ValidationError("Invalid code", "invalid")
return response
class OAuthDeviceCodeStage(ChallengeStageView):
"""Flow challenge for users to enter device codes"""
@ -143,12 +151,4 @@ class OAuthDeviceCodeStage(ChallengeStageView):
)
def challenge_valid(self, response: ChallengeResponse) -> HttpResponse:
code = response.validated_data["code"]
validation = validate_code(code, self.request)
if not validation:
response._errors.setdefault("code", [])
response._errors["code"].append(ErrorDetail(_("Invalid code"), "invalid"))
return self.challenge_invalid(response)
# Run cancel to cleanup the current flow
self.executor.cancel()
return validation
return response.validated_data["code"]

2
go.mod
View File

@ -30,7 +30,7 @@ require (
github.com/spf13/cobra v1.8.0
github.com/stretchr/testify v1.9.0
github.com/wwt/guac v1.3.2
goauthentik.io/api/v3 v3.2024022.6
goauthentik.io/api/v3 v3.2024022.7
golang.org/x/exp v0.0.0-20230210204819-062eb4c674ab
golang.org/x/oauth2 v0.18.0
golang.org/x/sync v0.6.0

4
go.sum
View File

@ -280,8 +280,8 @@ go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4=
goauthentik.io/api/v3 v3.2024022.6 h1:Fs6+EEKw8Z1mgmKGMxOqZnepJoRXPXR/QS01FC0JPJ8=
goauthentik.io/api/v3 v3.2024022.6/go.mod h1:zz+mEZg8rY/7eEjkMGWJ2DnGqk+zqxuybGCGrR2O4Kw=
goauthentik.io/api/v3 v3.2024022.7 h1:VR9OmcZvTzPSjit2Dx2EoHrLc9v9XRyjPXNpnGISWWM=
goauthentik.io/api/v3 v3.2024022.7/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=

36
poetry.lock generated
View File

@ -1142,13 +1142,13 @@ bcrypt = ["bcrypt"]
[[package]]
name = "django-filter"
version = "24.1"
version = "24.2"
description = "Django-filter is a reusable Django application for allowing users to filter querysets dynamically."
optional = false
python-versions = ">=3.8"
files = [
{file = "django-filter-24.1.tar.gz", hash = "sha256:65cb43ce272077e5ac6aae1054d76c121cd6b552e296a82a13921e9371baf8c1"},
{file = "django_filter-24.1-py3-none-any.whl", hash = "sha256:335bcae6cbd3e984b024841070f567b22faea57594f27d37c52f8f131f8d8621"},
{file = "django-filter-24.2.tar.gz", hash = "sha256:48e5fc1da3ccd6ca0d5f9bb550973518ce977a4edde9d2a8a154a7f4f0b9f96e"},
{file = "django_filter-24.2-py3-none-any.whl", hash = "sha256:df2ee9857e18d38bed203c8745f62a803fa0f31688c9fe6f8e868120b1848e48"},
]
[package.dependencies]
@ -3332,22 +3332,20 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
[[package]]
name = "requests-mock"
version = "1.11.0"
version = "1.12.1"
description = "Mock out responses from the requests package"
optional = false
python-versions = "*"
python-versions = ">=3.5"
files = [
{file = "requests-mock-1.11.0.tar.gz", hash = "sha256:ef10b572b489a5f28e09b708697208c4a3b2b89ef80a9f01584340ea357ec3c4"},
{file = "requests_mock-1.11.0-py2.py3-none-any.whl", hash = "sha256:f7fae383f228633f6bececebdab236c478ace2284d6292c6e7e2867b9ab74d15"},
{file = "requests-mock-1.12.1.tar.gz", hash = "sha256:e9e12e333b525156e82a3c852f22016b9158220d2f47454de9cae8a77d371401"},
{file = "requests_mock-1.12.1-py2.py3-none-any.whl", hash = "sha256:b1e37054004cdd5e56c84454cc7df12b25f90f382159087f4b6915aaeef39563"},
]
[package.dependencies]
requests = ">=2.3,<3"
six = "*"
requests = ">=2.22,<3"
[package.extras]
fixture = ["fixtures"]
test = ["fixtures", "mock", "purl", "pytest", "requests-futures", "sphinx", "testtools"]
[[package]]
name = "requests-oauthlib"
@ -3552,13 +3550,13 @@ crt = ["botocore[crt] (>=1.33.2,<2.0a.0)"]
[[package]]
name = "selenium"
version = "4.18.1"
version = "4.19.0"
description = ""
optional = false
python-versions = ">=3.8"
files = [
{file = "selenium-4.18.1-py3-none-any.whl", hash = "sha256:b24a3cdd2d47c29832e81345bfcde0c12bb608738013e53c781b211b418df241"},
{file = "selenium-4.18.1.tar.gz", hash = "sha256:a11f67afa8bfac6b77e148c987b33f6b14eb1cae4d352722a75de1f26e3f0ae2"},
{file = "selenium-4.19.0-py3-none-any.whl", hash = "sha256:5b4f49240d61e687a73f7968ae2517d403882aae3550eae2a229c745e619f1d9"},
{file = "selenium-4.19.0.tar.gz", hash = "sha256:d9dfd6d0b021d71d0a48b865fe7746490ba82b81e9c87b212360006629eb1853"},
]
[package.dependencies]
@ -3570,13 +3568,13 @@ urllib3 = {version = ">=1.26,<3", extras = ["socks"]}
[[package]]
name = "sentry-sdk"
version = "1.43.0"
version = "1.44.0"
description = "Python client for Sentry (https://sentry.io)"
optional = false
python-versions = "*"
files = [
{file = "sentry-sdk-1.43.0.tar.gz", hash = "sha256:41df73af89d22921d8733714fb0fc5586c3461907e06688e6537d01a27e0e0f6"},
{file = "sentry_sdk-1.43.0-py2.py3-none-any.whl", hash = "sha256:8d768724839ca18d7b4c7463ef7528c40b7aa2bfbf7fe554d5f9a7c044acfd36"},
{file = "sentry-sdk-1.44.0.tar.gz", hash = "sha256:f7125a9235795811962d52ff796dc032cd1d0dd98b59beaced8380371cd9c13c"},
{file = "sentry_sdk-1.44.0-py2.py3-none-any.whl", hash = "sha256:eb65289da013ca92fad2694851ad2f086aa3825e808dc285bd7dcaf63602bb18"},
]
[package.dependencies]
@ -4203,13 +4201,13 @@ files = [
[[package]]
name = "webauthn"
version = "2.0.0"
version = "2.1.0"
description = "Pythonic WebAuthn"
optional = false
python-versions = "*"
files = [
{file = "webauthn-2.0.0-py3-none-any.whl", hash = "sha256:644dc68af5caaade06be6a2a2278775e85116e92dd755ad7a49d992d51c82033"},
{file = "webauthn-2.0.0.tar.gz", hash = "sha256:12cc1759da98668b8242badc37c4129df300f89d89f5c183fac80e7b33c41dfd"},
{file = "webauthn-2.1.0-py3-none-any.whl", hash = "sha256:9e1cf916e5ed7c01d54a6dfcc19dacbd2b87b81d2648f001b1fcbcb7aa2ff130"},
{file = "webauthn-2.1.0.tar.gz", hash = "sha256:b196a4246c2818820857ba195c6e6e5398c761117f2269e3d2deab11c7995fc4"},
]
[package.dependencies]

View File

@ -33782,8 +33782,7 @@ components:
logs:
type: array
items:
type: object
additionalProperties: {}
$ref: '#/components/schemas/LogEvent'
readOnly: true
success:
type: boolean
@ -35515,6 +35514,48 @@ components:
type: string
required:
- link
LogEvent:
type: object
description: Single log message with all context logged.
properties:
timestamp:
type: string
format: date-time
log_level:
$ref: '#/components/schemas/LogLevelEnum'
logger:
type: string
event:
type: string
attributes:
type: object
additionalProperties: {}
required:
- attributes
- event
- log_level
- logger
- timestamp
LogLevelEnum:
enum:
- critical
- exception
- error
- warn
- warning
- info
- debug
- notset
type: string
description: |-
* `critical` - critical
* `exception` - exception
* `error` - error
* `warn` - warn
* `warning` - warning
* `info` - info
* `debug` - debug
* `notset` - notset
LoginChallengeTypes:
oneOf:
- $ref: '#/components/schemas/RedirectChallenge'
@ -41309,8 +41350,7 @@ components:
log_messages:
type: array
items:
type: object
additionalProperties: {}
$ref: '#/components/schemas/LogEvent'
readOnly: true
required:
- log_messages
@ -44324,7 +44364,7 @@ components:
messages:
type: array
items:
type: string
$ref: '#/components/schemas/LogEvent'
required:
- description
- duration

View File

@ -26,12 +26,6 @@ class TestProxyKubernetes(TestCase):
outpost_connection_discovery()
self.controller = None
def tearDown(self) -> None:
if self.controller:
for log in self.controller.down_with_logs():
LOGGER.info(log)
return super().tearDown()
@pytest.mark.timeout(120)
def test_kubernetes_controller_static(self):
"""Test Kubernetes Controller"""

View File

@ -6,7 +6,7 @@
"": {
"name": "@goauthentik/web-tests",
"dependencies": {
"chromedriver": "^123.0.0"
"chromedriver": "^123.0.1"
},
"devDependencies": {
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
@ -18,7 +18,7 @@
"@wdio/spec-reporter": "^8.32.4",
"eslint": "^8.57.0",
"eslint-config-google": "^0.14.0",
"eslint-plugin-sonarjs": "^0.24.0",
"eslint-plugin-sonarjs": "^0.25.0",
"npm-run-all": "^4.1.5",
"prettier": "^3.2.5",
"ts-node": "^10.9.2",
@ -2084,9 +2084,9 @@
}
},
"node_modules/chromedriver": {
"version": "123.0.0",
"resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-123.0.0.tgz",
"integrity": "sha512-OE9mpxXwbFy5LncAisqXm1aEzuLPtEMORIxyYIn9uT7N8rquJWyoip6w9Rytub3o2gnynW9+PFOTPVTldaYrtw==",
"version": "123.0.1",
"resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-123.0.1.tgz",
"integrity": "sha512-YQUIP/zdlzDIRCZNCv6rEVDSY4RAxo/tDL0OiGPPuai+z8unRNqJr/9V6XTBypVFyDheXNalKt9QxEqdMPuLAQ==",
"hasInstallScript": true,
"dependencies": {
"@testim/chrome-version": "^1.1.4",
@ -3114,9 +3114,9 @@
}
},
"node_modules/eslint-plugin-sonarjs": {
"version": "0.24.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.24.0.tgz",
"integrity": "sha512-87zp50mbbNrSTuoEOebdRQBPa0mdejA5UEjyuScyIw8hEpEjfWP89Qhkq5xVZfVyVSRQKZc9alVm7yRKQvvUmg==",
"version": "0.25.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.25.0.tgz",
"integrity": "sha512-DaZOtpUucEZbvowgKxVFwICV6r0h7jSCAx0IHICvCowP+etFussnhtaiCPSnYAuwVJ+P/6UFUhkv7QJklpXFyA==",
"dev": true,
"engines": {
"node": ">=16"

View File

@ -12,7 +12,7 @@
"@wdio/spec-reporter": "^8.32.4",
"eslint": "^8.57.0",
"eslint-config-google": "^0.14.0",
"eslint-plugin-sonarjs": "^0.24.0",
"eslint-plugin-sonarjs": "^0.25.0",
"npm-run-all": "^4.1.5",
"prettier": "^3.2.5",
"ts-node": "^10.9.2",
@ -32,6 +32,6 @@
"node": ">=20"
},
"dependencies": {
"chromedriver": "^123.0.0"
"chromedriver": "^123.0.1"
}
}

193
web/package-lock.json generated
View File

@ -11,13 +11,13 @@
"dependencies": {
"@codemirror/lang-html": "^6.4.8",
"@codemirror/lang-javascript": "^6.2.2",
"@codemirror/lang-python": "^6.1.4",
"@codemirror/lang-python": "^6.1.5",
"@codemirror/lang-xml": "^6.1.0",
"@codemirror/legacy-modes": "^6.3.3",
"@codemirror/theme-one-dark": "^6.1.2",
"@formatjs/intl-listformat": "^7.5.5",
"@fortawesome/fontawesome-free": "^6.5.1",
"@goauthentik/api": "^2024.2.2-1711460547",
"@goauthentik/api": "^2024.2.2-1711643691",
"@lit-labs/task": "^3.1.0",
"@lit/context": "^1.1.0",
"@lit/localize": "^0.12.1",
@ -25,7 +25,7 @@
"@open-wc/lit-helpers": "^0.7.0",
"@patternfly/elements": "^2.4.0",
"@patternfly/patternfly": "^4.224.2",
"@sentry/browser": "^7.108.0",
"@sentry/browser": "^7.109.0",
"@webcomponents/webcomponentsjs": "^2.8.0",
"base64-js": "^1.5.1",
"chart.js": "^4.4.2",
@ -59,7 +59,7 @@
"@jeysal/storybook-addon-css-user-preferences": "^0.2.0",
"@lit/localize-tools": "^0.7.2",
"@rollup/plugin-replace": "^5.0.5",
"@spotlightjs/spotlight": "^1.2.15",
"@spotlightjs/spotlight": "^1.2.16",
"@storybook/addon-essentials": "^7.6.17",
"@storybook/addon-links": "^7.6.17",
"@storybook/api": "^7.6.17",
@ -84,10 +84,10 @@
"eslint-config-google": "^0.14.0",
"eslint-plugin-custom-elements": "0.0.8",
"eslint-plugin-lit": "^1.11.0",
"eslint-plugin-sonarjs": "^0.24.0",
"eslint-plugin-sonarjs": "^0.25.0",
"eslint-plugin-storybook": "^0.8.0",
"github-slugger": "^2.0.0",
"glob": "^10.3.10",
"glob": "^10.3.12",
"lit-analyzer": "^2.0.3",
"npm-run-all": "^4.1.5",
"prettier": "^3.2.5",
@ -111,9 +111,9 @@
"@esbuild/darwin-arm64": "^0.20.1",
"@esbuild/linux-amd64": "^0.18.11",
"@esbuild/linux-arm64": "^0.20.1",
"@rollup/rollup-darwin-arm64": "4.13.0",
"@rollup/rollup-linux-arm64-gnu": "4.13.0",
"@rollup/rollup-linux-x64-gnu": "4.13.0"
"@rollup/rollup-darwin-arm64": "4.13.2",
"@rollup/rollup-linux-arm64-gnu": "4.13.2",
"@rollup/rollup-linux-x64-gnu": "4.13.2"
}
},
"node_modules/@aashutoshrathi/word-wrap": {
@ -2164,8 +2164,9 @@
}
},
"node_modules/@codemirror/lang-python": {
"version": "6.1.4",
"license": "MIT",
"version": "6.1.5",
"resolved": "https://registry.npmjs.org/@codemirror/lang-python/-/lang-python-6.1.5.tgz",
"integrity": "sha512-hCm+8X6wrnXJCGf+QhmFu1AXkdTVG7dHy0Ly6SI1N3SRPptaMvwX6oNQonOXOMPvmcjiB0xq342KAxX3BYpijw==",
"dependencies": {
"@codemirror/autocomplete": "^6.3.2",
"@codemirror/language": "^6.8.0",
@ -2820,9 +2821,9 @@
}
},
"node_modules/@goauthentik/api": {
"version": "2024.2.2-1711460547",
"resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2024.2.2-1711460547.tgz",
"integrity": "sha512-MnU9SVpMtg+Tu0xASgPh0TXVLKo1n7W74z5Yh0WccirsrqlhBTNBgDFbAJKV4/EVt0b+c0/GEa9JxkSt3+DxaA=="
"version": "2024.2.2-1711643691",
"resolved": "https://registry.npmjs.org/@goauthentik/api/-/api-2024.2.2-1711643691.tgz",
"integrity": "sha512-QHe+3gaNRkId54AuqndYNL0e5kG8nPlH4OjOYOPqOr3u70rxby63PBSPgSRKgqsigBpZufhQGsUBAPmpR8Hv0w=="
},
"node_modules/@hcaptcha/types": {
"version": "1.0.3",
@ -4259,9 +4260,9 @@
"peer": true
},
"node_modules/@rollup/rollup-darwin-arm64": {
"version": "4.13.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.13.0.tgz",
"integrity": "sha512-Ovf2evVaP6sW5Ut0GHyUSOqA6tVKfrTHddtmxGQc1CTQa1Cw3/KMCDEEICZBbyppcwnhMwcDce9ZRxdWRpVd6g==",
"version": "4.13.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.13.2.tgz",
"integrity": "sha512-mCMlpzlBgOTdaFs83I4XRr8wNPveJiJX1RLfv4hggyIVhfB5mJfN4P8Z6yKh+oE4Luz+qq1P3kVdWrCKcMYrrA==",
"cpu": [
"arm64"
],
@ -4299,9 +4300,9 @@
"peer": true
},
"node_modules/@rollup/rollup-linux-arm64-gnu": {
"version": "4.13.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.13.0.tgz",
"integrity": "sha512-Iu0Kno1vrD7zHQDxOmvweqLkAzjxEVqNhUIXBsZ8hu8Oak7/5VTPrxOEZXYC1nmrBVJp0ZcL2E7lSuuOVaE3+w==",
"version": "4.13.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.13.2.tgz",
"integrity": "sha512-L1+D8/wqGnKQIlh4Zre9i4R4b4noxzH5DDciyahX4oOz62CphY7WDWqJoQ66zNR4oScLNOqQJfNSIAe/6TPUmQ==",
"cpu": [
"arm64"
],
@ -4339,9 +4340,9 @@
"peer": true
},
"node_modules/@rollup/rollup-linux-x64-gnu": {
"version": "4.13.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.13.0.tgz",
"integrity": "sha512-yUD/8wMffnTKuiIsl6xU+4IA8UNhQ/f1sAnQebmE/lyQ8abjsVyDkyRkWop0kdMhKMprpNIhPmYlCxgHrPoXoA==",
"version": "4.13.2",
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.13.2.tgz",
"integrity": "sha512-xXMLUAMzrtsvh3cZ448vbXqlUa7ZL8z0MwHp63K2IIID2+DeP5iWIT6g1SN7hg1VxPzqx0xZdiDM9l4n9LRU1A==",
"cpu": [
"x64"
],
@ -4407,102 +4408,102 @@
"peer": true
},
"node_modules/@sentry-internal/feedback": {
"version": "7.108.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-7.108.0.tgz",
"integrity": "sha512-8JcgZEnk1uWrXJhsd3iRvFtEiVeaWOEhN0NZwhwQXHfvODqep6JtrkY1yCIyxbpA37aZmrPc2JhyotRERGfUjg==",
"version": "7.109.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/feedback/-/feedback-7.109.0.tgz",
"integrity": "sha512-EL7N++poxvJP9rYvh6vSu24tsKkOveNCcCj4IM7+irWPjsuD2GLYYlhp/A/Mtt9l7iqO4plvtiQU5HGk7smcTQ==",
"dependencies": {
"@sentry/core": "7.108.0",
"@sentry/types": "7.108.0",
"@sentry/utils": "7.108.0"
"@sentry/core": "7.109.0",
"@sentry/types": "7.109.0",
"@sentry/utils": "7.109.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@sentry-internal/replay-canvas": {
"version": "7.108.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-7.108.0.tgz",
"integrity": "sha512-R5tvjGqWUV5vSk0N1eBgVW7wIADinrkfDEBZ9FyKP2mXHBobsyNGt30heJDEqYmVqluRqjU2NuIRapsnnrpGnA==",
"version": "7.109.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/replay-canvas/-/replay-canvas-7.109.0.tgz",
"integrity": "sha512-Lh/K60kmloR6lkPUcQP0iamw7B/MdEUEx/ImAx4tUSMrLj+IoUEcq/ECgnnVyQkJq59+8nPEKrVLt7x6PUPEjw==",
"dependencies": {
"@sentry/core": "7.108.0",
"@sentry/replay": "7.108.0",
"@sentry/types": "7.108.0",
"@sentry/utils": "7.108.0"
"@sentry/core": "7.109.0",
"@sentry/replay": "7.109.0",
"@sentry/types": "7.109.0",
"@sentry/utils": "7.109.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@sentry-internal/tracing": {
"version": "7.108.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.108.0.tgz",
"integrity": "sha512-zuK5XsTsb+U+hgn3SPetYDAogrXsM16U/LLoMW7+TlC6UjlHGYQvmX3o+M2vntejoU1QZS8m1bCAZSMWEypAEw==",
"version": "7.109.0",
"resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.109.0.tgz",
"integrity": "sha512-PzK/joC5tCuh2R/PRh+7dp+uuZl7pTsBIjPhVZHMTtb9+ls65WkdZJ1/uKXPouyz8NOo9Xok7aEvEo9seongyw==",
"dependencies": {
"@sentry/core": "7.108.0",
"@sentry/types": "7.108.0",
"@sentry/utils": "7.108.0"
"@sentry/core": "7.109.0",
"@sentry/types": "7.109.0",
"@sentry/utils": "7.109.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/browser": {
"version": "7.108.0",
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.108.0.tgz",
"integrity": "sha512-FNpzsdTvGvdHJMUelqEouUXMZU7jC+dpN7CdT6IoHVVFEkoAgrjMVUhXZoQ/dmCkdKWHmFSQhJ8Fm6V+e9Aq0A==",
"version": "7.109.0",
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-7.109.0.tgz",
"integrity": "sha512-yx+OFG+Ab9qUDDgV9ZDv8M9O9Mqr0fjKta/LMlWALYLjzkMvxsPlRPFj7oMBlHqOTVLDeg7lFYmsA8wyWQ8Z8g==",
"dependencies": {
"@sentry-internal/feedback": "7.108.0",
"@sentry-internal/replay-canvas": "7.108.0",
"@sentry-internal/tracing": "7.108.0",
"@sentry/core": "7.108.0",
"@sentry/replay": "7.108.0",
"@sentry/types": "7.108.0",
"@sentry/utils": "7.108.0"
"@sentry-internal/feedback": "7.109.0",
"@sentry-internal/replay-canvas": "7.109.0",
"@sentry-internal/tracing": "7.109.0",
"@sentry/core": "7.109.0",
"@sentry/replay": "7.109.0",
"@sentry/types": "7.109.0",
"@sentry/utils": "7.109.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/core": {
"version": "7.108.0",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.108.0.tgz",
"integrity": "sha512-I/VNZCFgLASxHZaD0EtxZRM34WG9w2gozqgrKGNMzAymwmQ3K9g/1qmBy4e6iS3YRptb7J5UhQkZQHrcwBbjWQ==",
"version": "7.109.0",
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.109.0.tgz",
"integrity": "sha512-xwD4U0IlvvlE/x/g/W1I8b4Cfb16SsCMmiEuBf6XxvAa3OfWBxKoqLifb3GyrbxMC4LbIIZCN/SvLlnGJPgszA==",
"dependencies": {
"@sentry/types": "7.108.0",
"@sentry/utils": "7.108.0"
"@sentry/types": "7.109.0",
"@sentry/utils": "7.109.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/replay": {
"version": "7.108.0",
"resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.108.0.tgz",
"integrity": "sha512-jo8fDOzcZJclP1+4n9jUtVxTlBFT9hXwxhAMrhrt70FV/nfmCtYQMD3bzIj79nwbhUtFP6pN39JH1o7Xqt1hxQ==",
"version": "7.109.0",
"resolved": "https://registry.npmjs.org/@sentry/replay/-/replay-7.109.0.tgz",
"integrity": "sha512-hCDjbTNO7ErW/XsaBXlyHFsUhneyBUdTec1Swf98TFEfVqNsTs6q338aUcaR8dGRLbLrJ9YU9D1qKq++v5h2CA==",
"dependencies": {
"@sentry-internal/tracing": "7.108.0",
"@sentry/core": "7.108.0",
"@sentry/types": "7.108.0",
"@sentry/utils": "7.108.0"
"@sentry-internal/tracing": "7.109.0",
"@sentry/core": "7.109.0",
"@sentry/types": "7.109.0",
"@sentry/utils": "7.109.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@sentry/types": {
"version": "7.108.0",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.108.0.tgz",
"integrity": "sha512-bKtHITmBN3kqtqE5eVvL8mY8znM05vEodENwRpcm6TSrrBjC2RnwNWVwGstYDdHpNfFuKwC8mLY9bgMJcENo8g==",
"version": "7.109.0",
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.109.0.tgz",
"integrity": "sha512-egCBnDv3YpVFoNzRLdP0soVrxVLCQ+rovREKJ1sw3rA2/MFH9WJ+DZZexsX89yeAFzy1IFsCp7/dEqudusml6g==",
"engines": {
"node": ">=8"
}
},
"node_modules/@sentry/utils": {
"version": "7.108.0",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.108.0.tgz",
"integrity": "sha512-a45yEFD5qtgZaIFRAcFkG8C8lnDzn6t4LfLXuV4OafGAy/3ZAN3XN8wDnrruHkiUezSSANGsLg3bXaLW/JLvJw==",
"version": "7.109.0",
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.109.0.tgz",
"integrity": "sha512-3RjxMOLMBwZ5VSiH84+o/3NY2An4Zldjz0EbfEQNRY9yffRiCPJSQiCJID8EoylCFOh/PAhPimBhqbtWJxX6iw==",
"dependencies": {
"@sentry/types": "7.108.0"
"@sentry/types": "7.109.0"
},
"engines": {
"node": ">=8"
@ -4514,9 +4515,9 @@
"license": "MIT"
},
"node_modules/@spotlightjs/overlay": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/@spotlightjs/overlay/-/overlay-1.8.1.tgz",
"integrity": "sha512-t8S2b6AxgDfDoPls3CU7uABLdKx3g8cCXQWEHOICC1i7MYUSQLFMDpWzFWTEjN0XA8MGwNf/QKNlZ/HhaKTzJw==",
"version": "1.8.2",
"resolved": "https://registry.npmjs.org/@spotlightjs/overlay/-/overlay-1.8.2.tgz",
"integrity": "sha512-g3pzaJFKK67pBIl72qSNoFJIfP/dmdFoSPWZZQW6MKAdU7IOY5yf3BB52xEc6iSfeLGG/KpYNThefpobX3hb7Q==",
"dev": true
},
"node_modules/@spotlightjs/sidecar": {
@ -4528,12 +4529,12 @@
}
},
"node_modules/@spotlightjs/spotlight": {
"version": "1.2.15",
"resolved": "https://registry.npmjs.org/@spotlightjs/spotlight/-/spotlight-1.2.15.tgz",
"integrity": "sha512-M0VTAyameAsK9kjI9k31CehTLJMqUdOvv7DSOr27dcioytBV0uC0l8w7ngHWxdqCOTpbruEs8EIrbQ0T9b4YZQ==",
"version": "1.2.16",
"resolved": "https://registry.npmjs.org/@spotlightjs/spotlight/-/spotlight-1.2.16.tgz",
"integrity": "sha512-grqK7Qwzz0zJKaM4+u/0DS81gEGKkUsKwXGY1kA07rXsbp6ilT62JWI1tQDgYHb1i3MbR2ch0EuMT476CAtA+A==",
"dev": true,
"dependencies": {
"@spotlightjs/overlay": "1.8.1",
"@spotlightjs/overlay": "1.8.2",
"@spotlightjs/sidecar": "1.4.0"
},
"bin": {
@ -10089,9 +10090,10 @@
"license": "MIT"
},
"node_modules/eslint-plugin-sonarjs": {
"version": "0.24.0",
"version": "0.25.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.25.0.tgz",
"integrity": "sha512-DaZOtpUucEZbvowgKxVFwICV6r0h7jSCAx0IHICvCowP+etFussnhtaiCPSnYAuwVJ+P/6UFUhkv7QJklpXFyA==",
"dev": true,
"license": "LGPL-3.0-only",
"engines": {
"node": ">=16"
},
@ -11234,16 +11236,16 @@
"license": "ISC"
},
"node_modules/glob": {
"version": "10.3.10",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz",
"integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==",
"version": "10.3.12",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz",
"integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==",
"dev": true,
"dependencies": {
"foreground-child": "^3.1.0",
"jackspeak": "^2.3.5",
"jackspeak": "^2.3.6",
"minimatch": "^9.0.1",
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0",
"path-scurry": "^1.10.1"
"minipass": "^7.0.4",
"path-scurry": "^1.10.2"
},
"bin": {
"glob": "dist/esm/bin.mjs"
@ -11271,6 +11273,15 @@
"dev": true,
"license": "BSD-2-Clause"
},
"node_modules/glob/node_modules/minipass": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz",
"integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==",
"dev": true,
"engines": {
"node": ">=16 || 14 >=14.17"
}
},
"node_modules/globals": {
"version": "11.12.0",
"dev": true,
@ -14569,11 +14580,12 @@
"license": "MIT"
},
"node_modules/path-scurry": {
"version": "1.10.1",
"version": "1.10.2",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz",
"integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==",
"dev": true,
"license": "BlueOak-1.0.0",
"dependencies": {
"lru-cache": "^9.1.1 || ^10.0.0",
"lru-cache": "^10.2.0",
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
},
"engines": {
@ -14585,8 +14597,9 @@
},
"node_modules/path-scurry/node_modules/lru-cache": {
"version": "10.2.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz",
"integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==",
"dev": true,
"license": "ISC",
"engines": {
"node": "14 || >=16.14"
}

View File

@ -32,13 +32,13 @@
"dependencies": {
"@codemirror/lang-html": "^6.4.8",
"@codemirror/lang-javascript": "^6.2.2",
"@codemirror/lang-python": "^6.1.4",
"@codemirror/lang-python": "^6.1.5",
"@codemirror/lang-xml": "^6.1.0",
"@codemirror/legacy-modes": "^6.3.3",
"@codemirror/theme-one-dark": "^6.1.2",
"@formatjs/intl-listformat": "^7.5.5",
"@fortawesome/fontawesome-free": "^6.5.1",
"@goauthentik/api": "^2024.2.2-1711460547",
"@goauthentik/api": "^2024.2.2-1711643691",
"@lit-labs/task": "^3.1.0",
"@lit/context": "^1.1.0",
"@lit/localize": "^0.12.1",
@ -46,7 +46,7 @@
"@open-wc/lit-helpers": "^0.7.0",
"@patternfly/elements": "^2.4.0",
"@patternfly/patternfly": "^4.224.2",
"@sentry/browser": "^7.108.0",
"@sentry/browser": "^7.109.0",
"@webcomponents/webcomponentsjs": "^2.8.0",
"base64-js": "^1.5.1",
"chart.js": "^4.4.2",
@ -80,7 +80,7 @@
"@jeysal/storybook-addon-css-user-preferences": "^0.2.0",
"@lit/localize-tools": "^0.7.2",
"@rollup/plugin-replace": "^5.0.5",
"@spotlightjs/spotlight": "^1.2.15",
"@spotlightjs/spotlight": "^1.2.16",
"@storybook/addon-essentials": "^7.6.17",
"@storybook/addon-links": "^7.6.17",
"@storybook/api": "^7.6.17",
@ -105,10 +105,10 @@
"eslint-config-google": "^0.14.0",
"eslint-plugin-custom-elements": "0.0.8",
"eslint-plugin-lit": "^1.11.0",
"eslint-plugin-sonarjs": "^0.24.0",
"eslint-plugin-sonarjs": "^0.25.0",
"eslint-plugin-storybook": "^0.8.0",
"github-slugger": "^2.0.0",
"glob": "^10.3.10",
"glob": "^10.3.12",
"lit-analyzer": "^2.0.3",
"npm-run-all": "^4.1.5",
"prettier": "^3.2.5",
@ -129,9 +129,9 @@
"@esbuild/darwin-arm64": "^0.20.1",
"@esbuild/linux-amd64": "^0.18.11",
"@esbuild/linux-arm64": "^0.20.1",
"@rollup/rollup-darwin-arm64": "4.13.0",
"@rollup/rollup-linux-arm64-gnu": "4.13.0",
"@rollup/rollup-linux-x64-gnu": "4.13.0"
"@rollup/rollup-darwin-arm64": "4.13.2",
"@rollup/rollup-linux-arm64-gnu": "4.13.2",
"@rollup/rollup-linux-x64-gnu": "4.13.2"
},
"engines": {
"node": ">=20"

View File

@ -1,5 +1,6 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import "@goauthentik/components/ak-status-label";
import "@goauthentik/elements/events/LogViewer";
import { Form } from "@goauthentik/elements/forms/Form";
import "@goauthentik/elements/forms/HorizontalFormElement";
import "@goauthentik/elements/forms/SearchSelect";
@ -83,28 +84,7 @@ export class ApplicationCheckAccessForm extends Form<{ forUser: number }> {
<div class="pf-c-form__group-label">
<div class="c-form__horizontal-group">
<dl class="pf-c-description-list pf-m-horizontal">
${(this.result?.logMessages || []).length > 0
? this.result?.logMessages?.map((m) => {
return html`<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text"
>${m.log_level}</span
>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
${m.event}
</div>
</dd>
</div>`;
})
: html`<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text"
>${msg("No log messages.")}</span
>
</dt>
</div>`}
<ak-log-viewer .logs=${this.result?.logMessages}></ak-log-viewer>
</dl>
</div>
</div>

View File

@ -1,6 +1,7 @@
import { DEFAULT_CONFIG } from "@goauthentik/common/api/config";
import { SentryIgnoredError } from "@goauthentik/common/errors";
import "@goauthentik/components/ak-status-label";
import "@goauthentik/elements/events/LogViewer";
import { Form } from "@goauthentik/elements/forms/Form";
import "@goauthentik/elements/forms/HorizontalFormElement";
@ -55,28 +56,7 @@ export class FlowImportForm extends Form<Flow> {
<div class="pf-c-form__group-label">
<div class="c-form__horizontal-group">
<dl class="pf-c-description-list pf-m-horizontal">
${(this.result?.logs || []).length > 0
? this.result?.logs?.map((m) => {
return html`<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text"
>${m.log_level}</span
>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
${m.event}
</div>
</dd>
</div>`;
})
: html`<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text"
>${msg("No log messages.")}</span
>
</dt>
</div>`}
<ak-log-viewer .logs=${this.result?.logs}></ak-log-viewer>
</dl>
</div>
</div>

View File

@ -3,6 +3,7 @@ import { first } from "@goauthentik/common/utils";
import "@goauthentik/components/ak-status-label";
import "@goauthentik/elements/CodeMirror";
import { CodeMirrorMode } from "@goauthentik/elements/CodeMirror";
import "@goauthentik/elements/events/LogViewer";
import { Form } from "@goauthentik/elements/forms/Form";
import "@goauthentik/elements/forms/HorizontalFormElement";
import "@goauthentik/elements/forms/SearchSelect";
@ -85,28 +86,7 @@ export class PolicyTestForm extends Form<PolicyTestRequest> {
<div class="pf-c-form__group-label">
<div class="c-form__horizontal-group">
<dl class="pf-c-description-list pf-m-horizontal">
${(this.result?.logMessages || []).length > 0
? this.result?.logMessages?.map((m) => {
return html`<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text"
>${m.log_level}</span
>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
${m.event}
</div>
</dd>
</div>`;
})
: html`<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text"
>${msg("No log messages.")}</span
>
</dt>
</div>`}
<ak-log-viewer .logs=${this.result?.logMessages}></ak-log-viewer>
</dl>
</div>
</div>

View File

@ -5,6 +5,7 @@ import { getRelativeTime } from "@goauthentik/common/utils";
import { PFColor } from "@goauthentik/elements/Label";
import "@goauthentik/elements/buttons/ActionButton";
import "@goauthentik/elements/buttons/SpinnerButton";
import "@goauthentik/elements/events/LogViewer";
import { PaginatedResponse } from "@goauthentik/elements/table/Table";
import { TableColumn } from "@goauthentik/elements/table/Table";
import { TablePage } from "@goauthentik/elements/table/TablePage";
@ -95,9 +96,7 @@ export class SystemTaskListPage extends TablePage<SystemTask> {
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
${item.messages.map((m) => {
return html`<li>${m}</li>`;
})}
<ak-log-viewer .logs=${item?.messages}></ak-log-viewer>
</div>
</dd>
</div>

View File

@ -0,0 +1,114 @@
import { getRelativeTime } from "@goauthentik/common/utils";
import "@goauthentik/components/ak-status-label";
import "@goauthentik/elements/EmptyState";
import { PaginatedResponse, Table, TableColumn } from "@goauthentik/elements/table/Table";
import { msg } from "@lit/localize";
import { CSSResult, TemplateResult, html } from "lit";
import { customElement, property } from "lit/decorators.js";
import PFDescriptionList from "@patternfly/patternfly/components/DescriptionList/description-list.css";
import { LogEvent, LogLevelEnum } from "@goauthentik/api";
@customElement("ak-log-viewer")
export class LogViewer extends Table<LogEvent> {
@property({ attribute: false })
logs?: LogEvent[] = [];
expandable = true;
paginated = false;
static get styles(): CSSResult[] {
return super.styles.concat(PFDescriptionList);
}
async apiEndpoint(_page: number): Promise<PaginatedResponse<LogEvent>> {
return {
pagination: {
next: 0,
previous: 0,
count: 1,
current: 1,
totalPages: 1,
startIndex: 1,
endIndex: 1,
},
results: this.logs || [],
};
}
renderEmpty(): TemplateResult {
return super.renderEmpty(
html`<ak-empty-state header=${msg("No log messages.")}> </ak-empty-state>`,
);
}
renderExpanded(item: LogEvent): TemplateResult {
return html`<td role="cell" colspan="4">
<div class="pf-c-table__expandable-row-content">
<dl class="pf-c-description-list pf-m-horizontal">
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${msg("Timestamp")}</span>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
${item.timestamp.toLocaleString()}
</div>
</dd>
</div>
<div class="pf-c-description-list__group">
<dt class="pf-c-description-list__term">
<span class="pf-c-description-list__text">${msg("Attributes")}</span>
</dt>
<dd class="pf-c-description-list__description">
<div class="pf-c-description-list__text">
<pre>${JSON.stringify(item.attributes, null, 4)}</pre>
</div>
</dd>
</div>
</dl>
</div>
</td>`;
}
renderToolbarContainer(): TemplateResult {
return html``;
}
columns(): TableColumn[] {
return [
new TableColumn(msg("Time")),
new TableColumn(msg("Level")),
new TableColumn(msg("Event")),
new TableColumn(msg("Logger")),
];
}
statusForItem(item: LogEvent): string {
switch (item.logLevel) {
case LogLevelEnum.Critical:
case LogLevelEnum.Error:
case LogLevelEnum.Exception:
return "error";
case LogLevelEnum.Warn:
case LogLevelEnum.Warning:
return "warning";
default:
return "info";
}
}
row(item: LogEvent): TemplateResult[] {
return [
html`${getRelativeTime(item.timestamp)}`,
html`<ak-status-label
type=${this.statusForItem(item)}
bad-label=${item.logLevel}
></ak-status-label>`,
html`${item.event}`,
html`${item.logger}`,
];
}
}

View File

@ -27,7 +27,7 @@ Starting in 2021.9, you can also select a Notification mapping. This allows you
```python
return {
"foo": context['notification'].body,
"foo": request.context['notification'].body,
}
```

View File

@ -1,39 +0,0 @@
---
title: Air-gapped environments
---
## Outbound connections
By default, authentik creates outbound connections to the following URLs:
- https://version.goauthentik.io: Periodic update check
- https://goauthentik.io: Anonymous analytics on startup
- https://secure.gravatar.com: Avatars for users
- https://authentik.error-reporting.a7k.io: Error reporting
To disable these outbound connections, set the following in your `.env` file:
```
AUTHENTIK_DISABLE_UPDATE_CHECK=true
AUTHENTIK_ERROR_REPORTING__ENABLED=false
AUTHENTIK_DISABLE_STARTUP_ANALYTICS=true
AUTHENTIK_AVATARS=initials
```
For a Helm-based install, set the following in your values.yaml file:
```yaml
authentik:
avatars: none
error_reporting:
enabled: false
disable_update_check: true
disable_startup_analytics: true
```
## Container images
Container images can be pulled from the following URLs:
- ghcr.io/goauthentik/server (https://ghcr.io)
- beryju/authentik (https://index.docker.io)

View File

@ -0,0 +1,68 @@
---
title: Air-gapped environments
---
## Outbound connections
By default, authentik creates outbound connections to the following URLs:
- https://version.goauthentik.io: Periodic update check
- https://goauthentik.io: Anonymous analytics on startup
- https://secure.gravatar.com: Avatars for users
- https://authentik.error-reporting.a7k.io: Error reporting
To disable these outbound connections, set the following in your `.env` file:
## Configuration options
To see a list of all configuration options, see [here](./configuration.mdx).
import Tabs from "@theme/Tabs";
import TabItem from "@theme/TabItem";
<Tabs
defaultValue="docker-compose"
values={[
{label: 'docker-compose', value: 'docker-compose'},
{label: 'Kubernetes', value: 'kubernetes'},
]}>
<TabItem value="docker-compose">
Add the following block to your `.env` file:
```shell
AUTHENTIK_DISABLE_STARTUP_ANALYTICS=true
AUTHENTIK_DISABLE_UPDATE_CHECK=true
AUTHENTIK_ERROR_REPORTING__ENABLED=false
```
Afterwards, run the upgrade commands from the latest release notes.
</TabItem>
<TabItem value="kubernetes">
Add the following block to your `values.yml` file:
```yaml
authentik:
error_reporting:
enabled: false
disable_update_check: true
disable_startup_analytics: true
```
Afterwards, run the upgrade commands from the latest release notes.
</TabItem>
</Tabs>
## Settings
In addition to the configuration options above, the following [System settings](../core/settings.md) need to also be adjusted:
- **Avatars**: By default this setting uses [Gravatar](https://secure.gravatar.com/). The option can be set to a combination of any of the other options, for example `initials`
## Container images
Container images can be pulled from the following URLs:
- ghcr.io/goauthentik/server (https://ghcr.io)
- beryju/authentik (https://index.docker.io)

View File

@ -32,7 +32,10 @@ The following placeholders will be used:
- **Redirect URIs/Origins (RegEx)**:
:::note
Please note that the following URIs are just examples. Be sure to include all of the domains / URLs that you will use to access Immich.
::: - app.immich:/ - https://immich.company/auth/login - https://immich.company/user-settings
:::
- app.immich:/
- https://immich.company/auth/login
- https://immich.company/user-settings
- **Signing Key**: authentik Self-signed Certificate
- Leave everything else as default
2. Open the new provider you've just created.

View File

@ -49,8 +49,8 @@ environment: OAUTH2_ENABLED=true
OAUTH2_USERINFO_ENDPOINT=/application/o/userinfo/
OAUTH2_TOKEN_ENDPOINT=/application/o/token/
OAUTH2_SECRET=<Client Secret from above>
OAUTH2_ID_MAP=preferred_username
OAUTH2_USERNAME_MAP=preferred_username
OAUTH2_ID_MAP=sub
OAUTH2_USERNAME_MAP=email
OAUTH2_FULLNAME_MAP=given_name
OAUTH2_EMAIL_MAP=email
```
@ -70,8 +70,8 @@ edit `.env` and add the following:
OAUTH2_USERINFO_ENDPOINT='/application/o/userinfo/'
OAUTH2_TOKEN_ENDPOINT='/application/o/token/'
OAUTH2_SECRET='<Client Secret from above>'
OAUTH2_ID_MAP='preferred_username'
OAUTH2_USERNAME_MAP='preferred_username'
OAUTH2_ID_MAP='sub'
OAUTH2_USERNAME_MAP='email'
OAUTH2_FULLNAME_MAP='given_name'
OAUTH2_EMAIL_MAP='email'
```

View File

@ -33,7 +33,7 @@
"@docusaurus/module-type-aliases": "3.1.1",
"@docusaurus/tsconfig": "3.1.1",
"@docusaurus/types": "3.1.1",
"@types/react": "^18.2.72",
"@types/react": "^18.2.73",
"prettier": "3.2.5",
"typescript": "~5.4.3"
},
@ -3999,9 +3999,9 @@
"integrity": "sha512-+0autS93xyXizIYiyL02FCY8N+KkKPhILhcUSA276HxzreZ16kl+cmwvV2qAM/PuCCwPXzOXOWhiPcw20uSFcA=="
},
"node_modules/@types/react": {
"version": "18.2.72",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.72.tgz",
"integrity": "sha512-/e7GWxGzXQF7OJAua7UAYqYi/4VpXEfbGtmYQcAQwP3SjjjAXfybTf/JK5S+SaetB/ChXl8Y2g1hCsj7jDXxcg==",
"version": "18.2.73",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.2.73.tgz",
"integrity": "sha512-XcGdod0Jjv84HOC7N5ziY3x+qL0AfmubvKOZ9hJjJ2yd5EE+KYjWhdOjt387e9HPheHkdggF9atTifMRtyAaRA==",
"dependencies": {
"@types/prop-types": "*",
"csstype": "^3.0.2"

View File

@ -52,7 +52,7 @@
"@docusaurus/module-type-aliases": "3.1.1",
"@docusaurus/tsconfig": "3.1.1",
"@docusaurus/types": "3.1.1",
"@types/react": "^18.2.72",
"@types/react": "^18.2.73",
"prettier": "3.2.5",
"typescript": "~5.4.3"
},