Merge branch 'main' into dev

* main: (27 commits)
  root: use custom model serializer that saves m2m without bulk (#10139)
  core: bump urllib3 from 2.2.1 to 2.2.2 (#10143)
  ci: bump docker/build-push-action from 5 to 6 (#10144)
  web: bump the storybook group in /web with 7 updates (#10147)
  web: bump ws from 8.16.0 to 8.17.1 in /web (#10149)
  web: fix needed because recent upgrade to task breaks spinner button (#10142)
  core: include version in built JS files (#9558)
  website/integations/services: Slack integration docs (#9933)
  web: fix early modal stack depletion (#10068)
  website: bump react-tooltip from 5.26.4 to 5.27.0 in /website (#10129)
  web: bump @patternfly/elements from 3.0.1 to 3.0.2 in /web (#10132)
  core: bump github.com/gorilla/sessions from 1.2.2 to 1.3.0 (#10135)
  web: bump chromedriver from 126.0.0 to 126.0.1 in /tests/wdio (#10136)
  core: bump github.com/spf13/cobra from 1.8.0 to 1.8.1 (#10133)
  core, web: update translations (#10127)
  core: bump ruff from 0.4.8 to 0.4.9 (#10128)
  core: bump goauthentik.io/api/v3 from 3.2024042.11 to 3.2024042.13 (#10134)
  core, web: update translations (#10118)
  translate: Updates for file web/xliff/en.xlf in zh-Hans (#10121)
  translate: Updates for file web/xliff/en.xlf in zh_CN (#10120)
  ...
This commit is contained in:
Ken Sternberg
2024-06-18 09:22:00 -07:00
94 changed files with 916 additions and 708 deletions

View File

@ -17,6 +17,8 @@ optional_value = final
[bumpversion:file:pyproject.toml]
[bumpversion:file:package.json]
[bumpversion:file:docker-compose.yml]
[bumpversion:file:schema.yml]

View File

@ -240,7 +240,7 @@ jobs:
- name: generate ts client
run: make gen-client-ts
- name: Build Docker Image
uses: docker/build-push-action@v5
uses: docker/build-push-action@v6
with:
context: .
secrets: |

View File

@ -96,7 +96,7 @@ jobs:
- name: Generate API
run: make gen-client-go
- name: Build Docker Image
uses: docker/build-push-action@v5
uses: docker/build-push-action@v6
with:
tags: ${{ steps.ev.outputs.imageTags }}
file: ${{ matrix.type }}.Dockerfile

View File

@ -40,7 +40,7 @@ jobs:
mkdir -p ./gen-ts-api
mkdir -p ./gen-go-api
- name: Build Docker Image
uses: docker/build-push-action@v5
uses: docker/build-push-action@v6
with:
context: .
push: true
@ -94,7 +94,7 @@ jobs:
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build Docker Image
uses: docker/build-push-action@v5
uses: docker/build-push-action@v6
with:
push: true
tags: ${{ steps.ev.outputs.imageTags }}

View File

@ -31,6 +31,7 @@ RUN --mount=type=bind,target=/work/web/package.json,src=./web/package.json \
--mount=type=cache,id=npm-web,sharing=shared,target=/root/.npm \
npm ci --include=dev
COPY ./package.json /work
COPY ./web /work/web/
COPY ./website /work/website/
COPY ./gen-ts-api /work/web/node_modules/@goauthentik/api

View File

@ -33,7 +33,7 @@ class RuntimeDict(TypedDict):
platform: str
uname: str
openssl_version: str
openssl_fips_mode: bool | None
openssl_fips_enabled: bool | None
authentik_version: str

View File

@ -1,13 +1,13 @@
{% extends "base/skeleton.html" %}
{% load static %}
{% load authentik_core %}
{% block title %}
API Browser - {{ brand.branding_title }}
{% endblock %}
{% block head %}
<script src="{% static 'dist/standalone/api-browser/index.js' %}?version={{ version }}" type="module"></script>
{% versioned_script "dist/standalone/api-browser/index-%v.js" %}
<meta name="theme-color" content="#151515" media="(prefers-color-scheme: light)">
<meta name="theme-color" content="#151515" media="(prefers-color-scheme: dark)">
{% endblock %}

View File

@ -11,14 +11,13 @@ from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.permissions import AllowAny
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import ModelSerializer
from rest_framework.validators import UniqueValidator
from rest_framework.viewsets import ModelViewSet
from authentik.api.authorization import SecretKeyFilter
from authentik.brands.models import Brand
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import PassiveSerializer
from authentik.core.api.utils import ModelSerializer, PassiveSerializer
from authentik.tenants.utils import get_current_tenant

View File

@ -17,7 +17,6 @@ from rest_framework.fields import CharField, ReadOnlyField, SerializerMethodFiel
from rest_framework.parsers import MultiPartParser
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet
from structlog.stdlib import get_logger
@ -26,6 +25,7 @@ from authentik.api.pagination import Pagination
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.api.utils import ModelSerializer
from authentik.core.models import Application, User
from authentik.events.logs import LogEventSerializer, capture_logs
from authentik.events.models import EventAction

View File

@ -8,12 +8,12 @@ from rest_framework import mixins
from rest_framework.fields import SerializerMethodField
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.request import Request
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import GenericViewSet
from ua_parser import user_agent_parser
from authentik.api.authorization import OwnerSuperuserPermissions
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import ModelSerializer
from authentik.core.models import AuthenticatedSession
from authentik.events.context_processors.asn import ASN_CONTEXT_PROCESSOR, ASNDict
from authentik.events.context_processors.geoip import GEOIP_CONTEXT_PROCESSOR, GeoIPDict

View File

@ -17,12 +17,12 @@ from rest_framework.decorators import action
from rest_framework.fields import CharField, IntegerField, SerializerMethodField
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import ListSerializer, ModelSerializer, ValidationError
from rest_framework.serializers import ListSerializer, ValidationError
from rest_framework.validators import UniqueValidator
from rest_framework.viewsets import ModelViewSet
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import JSONDictField, PassiveSerializer
from authentik.core.api.utils import JSONDictField, ModelSerializer, PassiveSerializer
from authentik.core.models import Group, User
from authentik.rbac.api.roles import RoleSerializer
from authentik.rbac.decorators import permission_required

View File

@ -8,11 +8,10 @@ from guardian.shortcuts import get_objects_for_user
from rest_framework import mixins
from rest_framework.decorators import action
from rest_framework.exceptions import PermissionDenied
from rest_framework.fields import BooleanField, CharField
from rest_framework.fields import BooleanField, CharField, SerializerMethodField
from rest_framework.relations import PrimaryKeyRelatedField
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import ModelSerializer, SerializerMethodField
from rest_framework.viewsets import GenericViewSet
from authentik.blueprints.api import ManagedSerializer
@ -20,6 +19,7 @@ from authentik.core.api.object_types import TypesMixin
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import (
MetaNameSerializer,
ModelSerializer,
PassiveSerializer,
)
from authentik.core.expression.evaluator import PropertyMappingEvaluator

View File

@ -6,13 +6,12 @@ from django.utils.translation import gettext_lazy as _
from django_filters.filters import BooleanFilter
from django_filters.filterset import FilterSet
from rest_framework import mixins
from rest_framework.fields import ReadOnlyField
from rest_framework.serializers import ModelSerializer, SerializerMethodField
from rest_framework.fields import ReadOnlyField, SerializerMethodField
from rest_framework.viewsets import GenericViewSet
from authentik.core.api.object_types import TypesMixin
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import MetaNameSerializer
from authentik.core.api.utils import MetaNameSerializer, ModelSerializer
from authentik.core.models import Provider

View File

@ -11,7 +11,6 @@ from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.parsers import MultiPartParser
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import GenericViewSet
from structlog.stdlib import get_logger
@ -19,7 +18,7 @@ from authentik.api.authorization import OwnerFilter, OwnerSuperuserPermissions
from authentik.blueprints.v1.importer import SERIALIZER_CONTEXT_BLUEPRINT
from authentik.core.api.object_types import TypesMixin
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import MetaNameSerializer
from authentik.core.api.utils import MetaNameSerializer, ModelSerializer
from authentik.core.models import Source, UserSourceConnection
from authentik.core.types import UserSettingSerializer
from authentik.lib.utils.file import (

View File

@ -12,7 +12,6 @@ from rest_framework.fields import CharField
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet
from authentik.api.authorization import OwnerSuperuserPermissions
@ -20,7 +19,7 @@ from authentik.blueprints.api import ManagedSerializer
from authentik.blueprints.v1.importer import SERIALIZER_CONTEXT_BLUEPRINT
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.users import UserSerializer
from authentik.core.api.utils import PassiveSerializer
from authentik.core.api.utils import ModelSerializer, PassiveSerializer
from authentik.core.models import (
USER_ATTRIBUTE_TOKEN_EXPIRING,
USER_ATTRIBUTE_TOKEN_MAXIMUM_LIFETIME,

View File

@ -40,7 +40,6 @@ from rest_framework.serializers import (
BooleanField,
DateTimeField,
ListSerializer,
ModelSerializer,
PrimaryKeyRelatedField,
ValidationError,
)
@ -52,7 +51,12 @@ from authentik.admin.api.metrics import CoordinateSerializer
from authentik.blueprints.v1.importer import SERIALIZER_CONTEXT_BLUEPRINT
from authentik.brands.models import Brand
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import JSONDictField, LinkSerializer, PassiveSerializer
from authentik.core.api.utils import (
JSONDictField,
LinkSerializer,
ModelSerializer,
PassiveSerializer,
)
from authentik.core.middleware import (
SESSION_KEY_IMPERSONATE_ORIGINAL_USER,
SESSION_KEY_IMPERSONATE_USER,

View File

@ -12,9 +12,12 @@ from rest_framework.fields import (
JSONField,
SerializerMethodField,
)
from rest_framework.serializers import ModelSerializer as BaseModelSerializer
from rest_framework.serializers import (
Serializer,
ValidationError,
model_meta,
raise_errors_on_nested_writes,
)
@ -25,6 +28,39 @@ def is_dict(value: Any):
raise ValidationError("Value must be a dictionary, and not have any duplicate keys.")
class ModelSerializer(BaseModelSerializer):
def update(self, instance: Model, validated_data):
raise_errors_on_nested_writes("update", self, validated_data)
info = model_meta.get_field_info(instance)
# Simply set each attribute on the instance, and then save it.
# Note that unlike `.create()` we don't need to treat many-to-many
# relationships as being a special case. During updates we already
# have an instance pk for the relationships to be associated with.
m2m_fields = []
for attr, value in validated_data.items():
if attr in info.relations and info.relations[attr].to_many:
m2m_fields.append((attr, value))
else:
setattr(instance, attr, value)
instance.save()
# Note that many-to-many fields are set after updating instance.
# Setting m2m fields triggers signals which could potentially change
# updated instance and we do not want it to collide with .update()
for attr, value in m2m_fields:
field = getattr(instance, attr)
# We can't check for inheritance here as m2m managers are generated dynamically
if field.__class__.__name__ == "RelatedManager":
field.set(value, bulk=False)
else:
field.set(value)
return instance
class JSONDictField(JSONField):
"""JSON Field which only allows dictionaries"""

View File

@ -1,5 +1,6 @@
{% load static %}
{% load i18n %}
{% load authentik_core %}
<!DOCTYPE html>
@ -14,8 +15,8 @@
{% endblock %}
<link rel="stylesheet" type="text/css" href="{% static 'dist/authentik.css' %}">
<link rel="stylesheet" type="text/css" href="{% static 'dist/custom.css' %}" data-inject>
<script src="{% static 'dist/poly.js' %}?version={{ version }}" type="module"></script>
<script src="{% static 'dist/standalone/loading/index.js' %}?version={{ version }}" type="module"></script>
{% versioned_script "dist/poly-%v.js" %}
{% versioned_script "dist/standalone/loading/index-%v.js" %}
{% block head %}
{% endblock %}
<meta name="sentry-trace" content="{{ sentry_trace }}" />

View File

@ -1,9 +1,9 @@
{% extends "base/skeleton.html" %}
{% load static %}
{% load authentik_core %}
{% block head %}
<script src="{% static 'dist/admin/AdminInterface.js' %}?version={{ version }}" type="module"></script>
{% versioned_script "dist/admin/AdminInterface-%v.js" %}
<meta name="theme-color" content="#18191a" media="(prefers-color-scheme: dark)">
<meta name="theme-color" content="#ffffff" media="(prefers-color-scheme: light)">
{% include "base/header_js.html" %}

View File

@ -1,6 +1,7 @@
{% extends "base/skeleton.html" %}
{% load static %}
{% load authentik_core %}
{% block head_before %}
{{ block.super }}
@ -17,7 +18,7 @@ window.authentik.flow = {
{% endblock %}
{% block head %}
<script src="{% static 'dist/flow/FlowInterface.js' %}?version={{ version }}" type="module"></script>
{% versioned_script "dist/flow/FlowInterface-%v.js" %}
<style>
:root {
--ak-flow-background: url("{{ flow.background_url }}");

View File

@ -1,9 +1,9 @@
{% extends "base/skeleton.html" %}
{% load static %}
{% load authentik_core %}
{% block head %}
<script src="{% static 'dist/user/UserInterface.js' %}?version={{ version }}" type="module"></script>
{% versioned_script "dist/user/UserInterface-%v.js" %}
<meta name="theme-color" content="#1c1e21" media="(prefers-color-scheme: light)">
<meta name="theme-color" content="#1c1e21" media="(prefers-color-scheme: dark)">
{% include "base/header_js.html" %}

View File

View File

@ -0,0 +1,27 @@
"""authentik core tags"""
from django import template
from django.templatetags.static import static as static_loader
from django.utils.safestring import mark_safe
from authentik import get_full_version
register = template.Library()
@register.simple_tag()
def versioned_script(path: str) -> str:
"""Wrapper around {% static %} tag that supports setting the version"""
returned_lines = [
(
f'<script src="{static_loader(path.replace("%v", get_full_version()))}'
'" type="module"></script>'
),
# Legacy method of loading scripts used as a fallback, without the version in the filename
# TODO: Remove after 2024.6 or later
(
f'<script src="{static_loader(path.replace("-%v", ""))}?'
f'version={get_full_version()}" type="module"></script>'
),
]
return mark_safe("".join(returned_lines)) # nosec

View File

@ -24,13 +24,12 @@ from rest_framework.fields import (
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.request import Request
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 authentik.api.authorization import SecretKeyFilter
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import PassiveSerializer
from authentik.core.api.utils import ModelSerializer, PassiveSerializer
from authentik.crypto.apps import MANAGED_KEY
from authentik.crypto.builder import CertificateBuilder, PrivateKeyAlg
from authentik.crypto.models import CertificateKeyPair

View File

@ -13,11 +13,10 @@ from rest_framework.fields import CharField, IntegerField
from rest_framework.permissions import IsAuthenticated
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import PassiveSerializer
from authentik.core.api.utils import ModelSerializer, PassiveSerializer
from authentik.core.models import User, UserTypes
from authentik.enterprise.license import LicenseKey, LicenseSummarySerializer
from authentik.enterprise.models import License

View File

@ -1,11 +1,11 @@
"""GoogleWorkspaceProviderGroup API Views"""
from rest_framework import mixins
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import GenericViewSet
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.users import UserGroupSerializer
from authentik.core.api.utils import ModelSerializer
from authentik.enterprise.providers.google_workspace.models import GoogleWorkspaceProviderGroup
from authentik.lib.sync.outgoing.api import OutgoingSyncConnectionCreateMixin

View File

@ -1,11 +1,11 @@
"""GoogleWorkspaceProviderUser API Views"""
from rest_framework import mixins
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import GenericViewSet
from authentik.core.api.groups import GroupMemberSerializer
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import ModelSerializer
from authentik.enterprise.providers.google_workspace.models import GoogleWorkspaceProviderUser
from authentik.lib.sync.outgoing.api import OutgoingSyncConnectionCreateMixin

View File

@ -1,11 +1,11 @@
"""MicrosoftEntraProviderGroup API Views"""
from rest_framework import mixins
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import GenericViewSet
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.users import UserGroupSerializer
from authentik.core.api.utils import ModelSerializer
from authentik.enterprise.providers.microsoft_entra.models import MicrosoftEntraProviderGroup
from authentik.lib.sync.outgoing.api import OutgoingSyncConnectionCreateMixin

View File

@ -1,11 +1,11 @@
"""MicrosoftEntraProviderUser API Views"""
from rest_framework import mixins
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import GenericViewSet
from authentik.core.api.groups import GroupMemberSerializer
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import ModelSerializer
from authentik.enterprise.providers.microsoft_entra.models import MicrosoftEntraProviderUser
from authentik.lib.sync.outgoing.api import OutgoingSyncConnectionCreateMixin

View File

@ -3,12 +3,12 @@
from django_filters.rest_framework.backends import DjangoFilterBackend
from rest_framework import mixins
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import GenericViewSet
from authentik.api.authorization import OwnerFilter, OwnerSuperuserPermissions
from authentik.core.api.groups import GroupMemberSerializer
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import ModelSerializer
from authentik.enterprise.api import EnterpriseRequiredMixin
from authentik.enterprise.providers.rac.api.endpoints import EndpointSerializer
from authentik.enterprise.providers.rac.api.providers import RACProviderSerializer

View File

@ -8,11 +8,11 @@ from drf_spectacular.utils import OpenApiParameter, OpenApiResponse, extend_sche
from rest_framework.fields import SerializerMethodField
from rest_framework.request import Request
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 authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import ModelSerializer
from authentik.core.models import Provider
from authentik.enterprise.api import EnterpriseRequiredMixin
from authentik.enterprise.providers.rac.api.providers import RACProviderSerializer

View File

@ -1,9 +1,9 @@
{% extends "base/skeleton.html" %}
{% load static %}
{% load authentik_core %}
{% block head %}
<script src="{% static 'dist/enterprise/rac/index.js' %}?version={{ version }}" type="module"></script>
{% versioned_script "dist/enterprise/rac/index-%v.js" %}
<meta name="theme-color" content="#18191a" media="(prefers-color-scheme: dark)">
<meta name="theme-color" content="#ffffff" media="(prefers-color-scheme: light)">
<link rel="icon" href="{{ tenant.branding_favicon }}">

View File

@ -15,12 +15,11 @@ from rest_framework.decorators import action
from rest_framework.fields import DictField, IntegerField
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet
from authentik.admin.api.metrics import CoordinateSerializer
from authentik.core.api.object_types import TypeCreateSerializer
from authentik.core.api.utils import PassiveSerializer
from authentik.core.api.utils import ModelSerializer, PassiveSerializer
from authentik.events.models import Event, EventAction

View File

@ -1,9 +1,9 @@
"""NotificationWebhookMapping API Views"""
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import ModelSerializer
from authentik.events.models import NotificationWebhookMapping

View File

@ -1,10 +1,10 @@
"""NotificationRule API Views"""
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet
from authentik.core.api.groups import GroupSerializer
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import ModelSerializer
from authentik.events.models import NotificationRule

View File

@ -9,11 +9,10 @@ from rest_framework.exceptions import ValidationError
from rest_framework.fields import CharField, ListField, SerializerMethodField
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import PassiveSerializer
from authentik.core.api.utils import ModelSerializer, PassiveSerializer
from authentik.events.models import (
Event,
Notification,

View File

@ -9,11 +9,11 @@ from rest_framework.fields import ReadOnlyField
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import GenericViewSet
from authentik.api.authorization import OwnerFilter, OwnerPermissions
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import ModelSerializer
from authentik.events.api.events import EventSerializer
from authentik.events.models import Notification

View File

@ -16,10 +16,10 @@ from rest_framework.fields import (
)
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ReadOnlyModelViewSet
from structlog.stdlib import get_logger
from authentik.core.api.utils import ModelSerializer
from authentik.events.logs import LogEventSerializer
from authentik.events.models import SystemTask, TaskStatus
from authentik.rbac.decorators import permission_required

View File

@ -3,10 +3,10 @@
from typing import Any
from rest_framework.exceptions import ValidationError
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import ModelSerializer
from authentik.flows.api.stages import StageSerializer
from authentik.flows.models import FlowStageBinding

View File

@ -7,18 +7,22 @@ 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, ReadOnlyField
from rest_framework.fields import BooleanField, CharField, ReadOnlyField, SerializerMethodField
from rest_framework.parsers import MultiPartParser
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import ModelSerializer, SerializerMethodField
from rest_framework.viewsets import ModelViewSet
from structlog.stdlib import get_logger
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.core.api.utils import (
CacheSerializer,
LinkSerializer,
ModelSerializer,
PassiveSerializer,
)
from authentik.events.logs import LogEventSerializer
from authentik.flows.api.flows_diagram import FlowDiagram, FlowDiagramSerializer
from authentik.flows.exceptions import FlowNonApplicableException

View File

@ -4,15 +4,15 @@ from django.urls.base import reverse
from drf_spectacular.utils import extend_schema
from rest_framework import mixins
from rest_framework.decorators import action
from rest_framework.fields import SerializerMethodField
from rest_framework.request import Request
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 authentik.core.api.object_types import TypesMixin
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import MetaNameSerializer
from authentik.core.api.utils import MetaNameSerializer, ModelSerializer
from authentik.core.types import UserSettingSerializer
from authentik.flows.api.flows import FlowSetSerializer
from authentik.flows.models import ConfigurableStage, Stage

View File

@ -7,9 +7,8 @@ from rest_framework.decorators import action
from rest_framework.fields import BooleanField
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import ModelSerializer
from authentik.core.api.utils import PassiveSerializer
from authentik.core.api.utils import ModelSerializer, PassiveSerializer
from authentik.events.api.tasks import SystemTaskSerializer
from authentik.lib.sync.outgoing.models import OutgoingSyncProvider

View File

@ -6,17 +6,17 @@ from django_filters.filters import ModelMultipleChoiceFilter
from django_filters.filterset import FilterSet
from drf_spectacular.utils import extend_schema
from rest_framework.decorators import action
from rest_framework.exceptions import ValidationError
from rest_framework.fields import BooleanField, CharField, DateTimeField, SerializerMethodField
from rest_framework.relations import PrimaryKeyRelatedField
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import ModelSerializer, ValidationError
from rest_framework.viewsets import ModelViewSet
from authentik import get_build_hash
from authentik.core.api.providers import ProviderSerializer
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import JSONDictField, PassiveSerializer
from authentik.core.api.utils import JSONDictField, ModelSerializer, PassiveSerializer
from authentik.core.models import Provider
from authentik.enterprise.license import LicenseKey
from authentik.enterprise.providers.rac.models import RACProvider

View File

@ -12,13 +12,13 @@ from rest_framework.decorators import action
from rest_framework.fields import BooleanField, CharField, ReadOnlyField
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import GenericViewSet, ModelViewSet
from authentik.core.api.object_types import TypesMixin
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import (
MetaNameSerializer,
ModelSerializer,
PassiveSerializer,
)
from authentik.outposts.models import (

View File

@ -5,13 +5,15 @@ from collections import OrderedDict
from django.core.exceptions import ObjectDoesNotExist
from django_filters.filters import BooleanFilter, ModelMultipleChoiceFilter
from django_filters.filterset import FilterSet
from rest_framework.serializers import ModelSerializer, PrimaryKeyRelatedField, ValidationError
from rest_framework.exceptions import ValidationError
from rest_framework.serializers import PrimaryKeyRelatedField
from rest_framework.viewsets import ModelViewSet
from structlog.stdlib import get_logger
from authentik.core.api.groups import GroupSerializer
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.users import UserSerializer
from authentik.core.api.utils import ModelSerializer
from authentik.policies.api.policies import PolicySerializer
from authentik.policies.models import PolicyBinding, PolicyBindingModel

View File

@ -6,9 +6,9 @@ from drf_spectacular.utils import OpenApiResponse, extend_schema
from guardian.shortcuts import get_objects_for_user
from rest_framework import mixins
from rest_framework.decorators import action
from rest_framework.fields import SerializerMethodField
from rest_framework.request import Request
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
@ -18,6 +18,7 @@ from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import (
CacheSerializer,
MetaNameSerializer,
ModelSerializer,
)
from authentik.events.logs import LogEventSerializer, capture_logs
from authentik.policies.api.exec import PolicyTestResultSerializer, PolicyTestSerializer

View File

@ -3,10 +3,10 @@
from django.utils.translation import gettext_lazy as _
from rest_framework import mixins
from rest_framework.exceptions import ValidationError
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import GenericViewSet, ModelViewSet
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import ModelSerializer
from authentik.policies.api.policies import PolicySerializer
from authentik.policies.reputation.models import Reputation, ReputationPolicy

View File

@ -1,6 +1,8 @@
"""authentik reputation request signals"""
from django.contrib.auth.signals import user_logged_in
from django.db import transaction
from django.db.models import F
from django.dispatch import receiver
from django.http import HttpRequest
from structlog.stdlib import get_logger
@ -19,16 +21,21 @@ def update_score(request: HttpRequest, identifier: str, amount: int):
"""Update score for IP and User"""
remote_ip = ClientIPMiddleware.get_client_ip(request)
Reputation.objects.update_or_create(
ip=remote_ip,
identifier=identifier,
defaults={
"score": amount,
"ip_geo_data": GEOIP_CONTEXT_PROCESSOR.city_dict(remote_ip) or {},
"ip_asn_data": ASN_CONTEXT_PROCESSOR.asn_dict(remote_ip) or {},
"expires": reputation_expiry(),
},
)
with transaction.atomic():
reputation, created = Reputation.objects.select_for_update().get_or_create(
ip=remote_ip,
identifier=identifier,
defaults={
"score": amount,
"ip_geo_data": GEOIP_CONTEXT_PROCESSOR.city_dict(remote_ip) or {},
"ip_asn_data": ASN_CONTEXT_PROCESSOR.asn_dict(remote_ip) or {},
"expires": reputation_expiry(),
},
)
if not created:
reputation.score = F("score") + amount
reputation.save()
LOGGER.debug("Updated score", amount=amount, for_user=identifier, for_ip=remote_ip)

View File

@ -39,6 +39,15 @@ class TestReputationPolicy(TestCase):
)
self.assertEqual(Reputation.objects.get(identifier=self.test_username).score, -1)
def test_update_reputation(self):
"""test reputation update"""
Reputation.objects.create(identifier=self.test_username, ip=self.test_ip, score=43)
# Trigger negative reputation
authenticate(
self.request, self.backends, username=self.test_username, password=self.test_username
)
self.assertEqual(Reputation.objects.get(identifier=self.test_username).score, 42)
def test_policy(self):
"""Test Policy"""
request = PolicyRequest(user=self.user)

View File

@ -5,11 +5,11 @@ from django.db.models.query import Q
from django_filters.filters import BooleanFilter
from django_filters.filterset import FilterSet
from rest_framework.fields import CharField, ListField, SerializerMethodField
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet
from authentik.core.api.providers import ProviderSerializer
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import ModelSerializer
from authentik.providers.ldap.models import LDAPProvider

View File

@ -7,12 +7,11 @@ from guardian.utils import get_anonymous_user
from rest_framework import mixins
from rest_framework.fields import CharField, ListField, SerializerMethodField
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import GenericViewSet
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.users import UserSerializer
from authentik.core.api.utils import MetaNameSerializer
from authentik.core.api.utils import MetaNameSerializer, ModelSerializer
from authentik.providers.oauth2.api.providers import OAuth2ProviderSerializer
from authentik.providers.oauth2.models import AccessToken, AuthorizationCode, RefreshToken

View File

@ -6,12 +6,11 @@ from django.utils.translation import gettext_lazy as _
from drf_spectacular.utils import extend_schema_field
from rest_framework.exceptions import ValidationError
from rest_framework.fields import CharField, ListField, ReadOnlyField, SerializerMethodField
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet
from authentik.core.api.providers import ProviderSerializer
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import PassiveSerializer
from authentik.core.api.utils import ModelSerializer, PassiveSerializer
from authentik.lib.utils.time import timedelta_from_string
from authentik.providers.oauth2.models import ScopeMapping
from authentik.providers.oauth2.views.provider import ProviderInfoView

View File

@ -1,11 +1,11 @@
"""RadiusProvider API Views"""
from rest_framework.fields import CharField, ListField
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet
from authentik.core.api.providers import ProviderSerializer
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import ModelSerializer
from authentik.providers.radius.models import RadiusProvider

View File

@ -1,11 +1,11 @@
"""SCIMProviderGroup API Views"""
from rest_framework import mixins
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import GenericViewSet
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.users import UserGroupSerializer
from authentik.core.api.utils import ModelSerializer
from authentik.lib.sync.outgoing.api import OutgoingSyncConnectionCreateMixin
from authentik.providers.scim.models import SCIMProviderGroup

View File

@ -1,11 +1,11 @@
"""SCIMProviderUser API Views"""
from rest_framework import mixins
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import GenericViewSet
from authentik.core.api.groups import GroupMemberSerializer
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import ModelSerializer
from authentik.lib.sync.outgoing.api import OutgoingSyncConnectionCreateMixin
from authentik.providers.scim.models import SCIMProviderUser

View File

@ -13,10 +13,9 @@ from rest_framework.fields import (
ReadOnlyField,
SerializerMethodField,
)
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ReadOnlyModelViewSet
from authentik.core.api.utils import PassiveSerializer
from authentik.core.api.utils import ModelSerializer, PassiveSerializer
from authentik.core.models import User
from authentik.lib.validators import RequiredTogetherValidator
from authentik.policies.event_matcher.models import model_choices

View File

@ -12,10 +12,9 @@ from rest_framework.fields import CharField, ReadOnlyField
from rest_framework.mixins import ListModelMixin
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import GenericViewSet
from authentik.core.api.utils import PassiveSerializer
from authentik.core.api.utils import ModelSerializer, PassiveSerializer
from authentik.policies.event_matcher.models import model_choices
from authentik.rbac.api.rbac import PermissionAssignSerializer
from authentik.rbac.decorators import permission_required

View File

@ -13,10 +13,10 @@ from rest_framework.fields import BooleanField, ReadOnlyField
from rest_framework.mixins import ListModelMixin
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import GenericViewSet
from authentik.core.api.groups import GroupMemberSerializer
from authentik.core.api.utils import ModelSerializer
from authentik.core.models import User, UserTypes
from authentik.policies.event_matcher.models import model_choices
from authentik.rbac.api.rbac import PermissionAssignSerializer

View File

@ -1,9 +1,9 @@
"""RBAC Roles"""
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import ModelSerializer
from authentik.rbac.models import Role

View File

@ -1,7 +1,6 @@
"""root settings for authentik"""
import importlib
import os
from collections import OrderedDict
from hashlib import sha512
from pathlib import Path
@ -10,7 +9,7 @@ from celery.schedules import crontab
from django.conf import ImproperlyConfigured
from sentry_sdk import set_tag
from authentik import ENV_GIT_HASH_KEY, __version__
from authentik import __version__
from authentik.lib.config import CONFIG, redis_url
from authentik.lib.logging import get_logger_config, structlog_configure
from authentik.lib.sentry import sentry_init
@ -511,7 +510,6 @@ def _update_settings(app_path: str):
if DEBUG:
CELERY["task_always_eager"] = True
os.environ[ENV_GIT_HASH_KEY] = "dev"
REST_FRAMEWORK["DEFAULT_RENDERER_CLASSES"].append(
"rest_framework.renderers.BrowsableAPIRenderer"
)

View File

@ -12,12 +12,12 @@ from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.permissions import IsAdminUser
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import GenericViewSet, ModelViewSet
from structlog.stdlib import get_logger
from authentik.api.authorization import OwnerFilter, OwnerPermissions
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import ModelSerializer
from authentik.flows.api.stages import StageSerializer
from authentik.rbac.decorators import permission_required
from authentik.stages.authenticator_duo.models import AuthenticatorDuoStage, DuoDevice

View File

@ -4,11 +4,11 @@ from django_filters.rest_framework.backends import DjangoFilterBackend
from rest_framework import mixins
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.permissions import IsAdminUser
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import GenericViewSet, ModelViewSet
from authentik.api.authorization import OwnerFilter, OwnerPermissions
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import ModelSerializer
from authentik.flows.api.stages import StageSerializer
from authentik.stages.authenticator_sms.models import AuthenticatorSMSStage, SMSDevice

View File

@ -4,11 +4,11 @@ from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import mixins
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.permissions import IsAdminUser
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import GenericViewSet, ModelViewSet
from authentik.api.authorization import OwnerFilter, OwnerPermissions
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import ModelSerializer
from authentik.flows.api.stages import StageSerializer
from authentik.stages.authenticator_static.models import (
AuthenticatorStaticStage,

View File

@ -5,11 +5,11 @@ from rest_framework import mixins
from rest_framework.fields import ChoiceField
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.permissions import IsAdminUser
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import GenericViewSet, ModelViewSet
from authentik.api.authorization import OwnerFilter, OwnerPermissions
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import ModelSerializer
from authentik.flows.api.stages import StageSerializer
from authentik.stages.authenticator_totp.models import (
AuthenticatorTOTPStage,

View File

@ -4,11 +4,11 @@ from django_filters.rest_framework.backends import DjangoFilterBackend
from rest_framework import mixins
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.permissions import IsAdminUser
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import GenericViewSet, ModelViewSet
from authentik.api.authorization import OwnerFilter, OwnerPermissions
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import ModelSerializer
from authentik.stages.authenticator_webauthn.api.device_types import WebAuthnDeviceTypeSerializer
from authentik.stages.authenticator_webauthn.models import WebAuthnDevice

File diff suppressed because one or more lines are too long

View File

@ -2,12 +2,11 @@
from django_filters.filters import BooleanFilter
from django_filters.filterset import FilterSet
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet
from authentik.core.api.groups import GroupMemberSerializer
from authentik.core.api.used_by import UsedByMixin
from authentik.core.api.utils import JSONDictField
from authentik.core.api.utils import JSONDictField, ModelSerializer
from authentik.flows.api.flows import FlowSerializer
from authentik.flows.api.stages import StageSerializer
from authentik.stages.invitation.models import Invitation, InvitationStage

View File

@ -3,9 +3,9 @@
from django.apps import apps
from django.http import HttpResponseNotFound
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet
from authentik.core.api.utils import ModelSerializer
from authentik.tenants.api.tenants import TenantApiKeyPermission
from authentik.tenants.models import Domain

View File

@ -3,8 +3,8 @@
from django_tenants.utils import get_public_schema_name
from rest_framework.generics import RetrieveUpdateAPIView
from rest_framework.permissions import SAFE_METHODS
from rest_framework.serializers import ModelSerializer
from authentik.core.api.utils import ModelSerializer
from authentik.rbac.permissions import HasPermission
from authentik.tenants.models import Tenant

6
go.mod
View File

@ -15,7 +15,7 @@ require (
github.com/gorilla/handlers v1.5.2
github.com/gorilla/mux v1.8.1
github.com/gorilla/securecookie v1.1.2
github.com/gorilla/sessions v1.2.2
github.com/gorilla/sessions v1.3.0
github.com/gorilla/websocket v1.5.3
github.com/jellydator/ttlcache/v3 v3.2.0
github.com/mitchellh/mapstructure v1.5.0
@ -25,10 +25,10 @@ require (
github.com/redis/go-redis/v9 v9.5.3
github.com/sethvargo/go-envconfig v1.0.3
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.8.0
github.com/spf13/cobra v1.8.1
github.com/stretchr/testify v1.9.0
github.com/wwt/guac v1.3.2
goauthentik.io/api/v3 v3.2024042.11
goauthentik.io/api/v3 v3.2024042.13
golang.org/x/exp v0.0.0-20230210204819-062eb4c674ab
golang.org/x/oauth2 v0.21.0
golang.org/x/sync v0.7.0

14
go.sum
View File

@ -57,7 +57,7 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/coreos/go-oidc v2.2.1+incompatible h1:mh48q/BqXqgjVHpy2ZY7WnWAbenxRjsz9N1i1YxjHAk=
github.com/coreos/go-oidc v2.2.1+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -173,8 +173,8 @@ github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+
github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA=
github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTjY=
github.com/gorilla/sessions v1.2.2/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ=
github.com/gorilla/sessions v1.3.0 h1:XYlkq7KcpOB2ZhHBPv5WpjMIxrQosiZanfoy1HLZFzg=
github.com/gorilla/sessions v1.3.0/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
@ -253,8 +253,8 @@ github.com/sethvargo/go-envconfig v1.0.3/go.mod h1:JLd0KFWQYzyENqnEPWWZ49i4vzZo/
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0=
github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho=
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@ -294,8 +294,8 @@ go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4=
goauthentik.io/api/v3 v3.2024042.11 h1:cGgUz1E8rlMphGvv04VI7i+MgT8eidZbxTpza5zd96I=
goauthentik.io/api/v3 v3.2024042.11/go.mod h1:zz+mEZg8rY/7eEjkMGWJ2DnGqk+zqxuybGCGrR2O4Kw=
goauthentik.io/api/v3 v3.2024042.13 h1:eklVXXLH0tV+02puhxzWJZ8l6HhxmeVMYp/M6sdaji8=
goauthentik.io/api/v3 v3.2024042.13/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

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-06-05 00:07+0000\n"
"POT-Creation-Date: 2024-06-16 00:08+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"
@ -415,6 +415,22 @@ msgstr ""
msgid "Feature only accessible for internal users."
msgstr ""
#: authentik/enterprise/providers/google_workspace/models.py
msgid "Google Workspace Provider User"
msgstr ""
#: authentik/enterprise/providers/google_workspace/models.py
msgid "Google Workspace Provider Users"
msgstr ""
#: authentik/enterprise/providers/google_workspace/models.py
msgid "Google Workspace Provider Group"
msgstr ""
#: authentik/enterprise/providers/google_workspace/models.py
msgid "Google Workspace Provider Groups"
msgstr ""
#: authentik/enterprise/providers/google_workspace/models.py
#: authentik/enterprise/providers/microsoft_entra/models.py
#: authentik/providers/scim/models.py authentik/sources/ldap/models.py
@ -437,20 +453,16 @@ msgstr ""
msgid "Google Workspace Provider Mappings"
msgstr ""
#: authentik/enterprise/providers/google_workspace/models.py
msgid "Google Workspace Provider User"
#: authentik/enterprise/providers/microsoft_entra/models.py
msgid "Microsoft Entra Provider User"
msgstr ""
#: authentik/enterprise/providers/google_workspace/models.py
msgid "Google Workspace Provider Users"
#: authentik/enterprise/providers/microsoft_entra/models.py
msgid "Microsoft Entra Provider Group"
msgstr ""
#: authentik/enterprise/providers/google_workspace/models.py
msgid "Google Workspace Provider Group"
msgstr ""
#: authentik/enterprise/providers/google_workspace/models.py
msgid "Google Workspace Provider Groups"
#: authentik/enterprise/providers/microsoft_entra/models.py
msgid "Microsoft Entra Provider Groups"
msgstr ""
#: authentik/enterprise/providers/microsoft_entra/models.py
@ -469,18 +481,6 @@ msgstr ""
msgid "Microsoft Entra Provider Mappings"
msgstr ""
#: authentik/enterprise/providers/microsoft_entra/models.py
msgid "Microsoft Entra Provider User"
msgstr ""
#: authentik/enterprise/providers/microsoft_entra/models.py
msgid "Microsoft Entra Provider Group"
msgstr ""
#: authentik/enterprise/providers/microsoft_entra/models.py
msgid "Microsoft Entra Provider Groups"
msgstr ""
#: authentik/enterprise/providers/rac/models.py
#: authentik/stages/user_login/models.py
msgid ""

Binary file not shown.

View File

@ -1,5 +1,5 @@
{
"name": "@goauthentik/authentik",
"version": "1.0.0",
"version": "2024.4.2",
"private": true
}

42
poetry.lock generated
View File

@ -4052,28 +4052,28 @@ pyasn1 = ">=0.1.3"
[[package]]
name = "ruff"
version = "0.4.8"
version = "0.4.9"
description = "An extremely fast Python linter and code formatter, written in Rust."
optional = false
python-versions = ">=3.7"
files = [
{file = "ruff-0.4.8-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:7663a6d78f6adb0eab270fa9cf1ff2d28618ca3a652b60f2a234d92b9ec89066"},
{file = "ruff-0.4.8-py3-none-macosx_11_0_arm64.whl", hash = "sha256:eeceb78da8afb6de0ddada93112869852d04f1cd0f6b80fe464fd4e35c330913"},
{file = "ruff-0.4.8-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aad360893e92486662ef3be0a339c5ca3c1b109e0134fcd37d534d4be9fb8de3"},
{file = "ruff-0.4.8-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:284c2e3f3396fb05f5f803c9fffb53ebbe09a3ebe7dda2929ed8d73ded736deb"},
{file = "ruff-0.4.8-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7354f921e3fbe04d2a62d46707e569f9315e1a613307f7311a935743c51a764"},
{file = "ruff-0.4.8-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:72584676164e15a68a15778fd1b17c28a519e7a0622161eb2debdcdabdc71883"},
{file = "ruff-0.4.8-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9678d5c9b43315f323af2233a04d747409d1e3aa6789620083a82d1066a35199"},
{file = "ruff-0.4.8-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704977a658131651a22b5ebeb28b717ef42ac6ee3b11e91dc87b633b5d83142b"},
{file = "ruff-0.4.8-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d05f8d6f0c3cce5026cecd83b7a143dcad503045857bc49662f736437380ad45"},
{file = "ruff-0.4.8-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:6ea874950daca5697309d976c9afba830d3bf0ed66887481d6bca1673fc5b66a"},
{file = "ruff-0.4.8-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:fc95aac2943ddf360376be9aa3107c8cf9640083940a8c5bd824be692d2216dc"},
{file = "ruff-0.4.8-py3-none-musllinux_1_2_i686.whl", hash = "sha256:384154a1c3f4bf537bac69f33720957ee49ac8d484bfc91720cc94172026ceed"},
{file = "ruff-0.4.8-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e9d5ce97cacc99878aa0d084c626a15cd21e6b3d53fd6f9112b7fc485918e1fa"},
{file = "ruff-0.4.8-py3-none-win32.whl", hash = "sha256:6d795d7639212c2dfd01991259460101c22aabf420d9b943f153ab9d9706e6a9"},
{file = "ruff-0.4.8-py3-none-win_amd64.whl", hash = "sha256:e14a3a095d07560a9d6769a72f781d73259655919d9b396c650fc98a8157555d"},
{file = "ruff-0.4.8-py3-none-win_arm64.whl", hash = "sha256:14019a06dbe29b608f6b7cbcec300e3170a8d86efaddb7b23405cb7f7dcaf780"},
{file = "ruff-0.4.8.tar.gz", hash = "sha256:16d717b1d57b2e2fd68bd0bf80fb43931b79d05a7131aa477d66fc40fbd86268"},
{file = "ruff-0.4.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b262ed08d036ebe162123170b35703aaf9daffecb698cd367a8d585157732991"},
{file = "ruff-0.4.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:98ec2775fd2d856dc405635e5ee4ff177920f2141b8e2d9eb5bd6efd50e80317"},
{file = "ruff-0.4.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4555056049d46d8a381f746680db1c46e67ac3b00d714606304077682832998e"},
{file = "ruff-0.4.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e91175fbe48f8a2174c9aad70438fe9cb0a5732c4159b2a10a3565fea2d94cde"},
{file = "ruff-0.4.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0e8e7b95673f22e0efd3571fb5b0cf71a5eaaa3cc8a776584f3b2cc878e46bff"},
{file = "ruff-0.4.9-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:2d45ddc6d82e1190ea737341326ecbc9a61447ba331b0a8962869fcada758505"},
{file = "ruff-0.4.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:78de3fdb95c4af084087628132336772b1c5044f6e710739d440fc0bccf4d321"},
{file = "ruff-0.4.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:06b60f91bfa5514bb689b500a25ba48e897d18fea14dce14b48a0c40d1635893"},
{file = "ruff-0.4.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88bffe9c6a454bf8529f9ab9091c99490578a593cc9f9822b7fc065ee0712a06"},
{file = "ruff-0.4.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:673bddb893f21ab47a8334c8e0ea7fd6598ecc8e698da75bcd12a7b9d0a3206e"},
{file = "ruff-0.4.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8c1aff58c31948cc66d0b22951aa19edb5af0a3af40c936340cd32a8b1ab7438"},
{file = "ruff-0.4.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:784d3ec9bd6493c3b720a0b76f741e6c2d7d44f6b2be87f5eef1ae8cc1d54c84"},
{file = "ruff-0.4.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:732dd550bfa5d85af8c3c6cbc47ba5b67c6aed8a89e2f011b908fc88f87649db"},
{file = "ruff-0.4.9-py3-none-win32.whl", hash = "sha256:8064590fd1a50dcf4909c268b0e7c2498253273309ad3d97e4a752bb9df4f521"},
{file = "ruff-0.4.9-py3-none-win_amd64.whl", hash = "sha256:e0a22c4157e53d006530c902107c7f550b9233e9706313ab57b892d7197d8e52"},
{file = "ruff-0.4.9-py3-none-win_arm64.whl", hash = "sha256:5d5460f789ccf4efd43f265a58538a2c24dbce15dbf560676e430375f20a8198"},
{file = "ruff-0.4.9.tar.gz", hash = "sha256:f1cb0828ac9533ba0135d148d214e284711ede33640465e706772645483427e3"},
]
[[package]]
@ -4649,13 +4649,13 @@ files = [
[[package]]
name = "urllib3"
version = "2.2.1"
version = "2.2.2"
description = "HTTP library with thread-safe connection pooling, file post, and more."
optional = false
python-versions = ">=3.8"
files = [
{file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"},
{file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"},
{file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"},
{file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"},
]
[package.dependencies]

View File

@ -1,11 +1,12 @@
# syntax=docker/dockerfile:1
# Stage 1: Build website
# Stage 1: Build web
FROM --platform=${BUILDPLATFORM} docker.io/node:22 as web-builder
ENV NODE_ENV=production
WORKDIR /static
COPY package.json /
COPY web/package.json .
COPY web/package-lock.json .
RUN --mount=type=bind,target=/static/package.json,src=./web/package.json \

View File

@ -47406,7 +47406,7 @@ components:
type: string
openssl_version:
type: string
openssl_fips_mode:
openssl_fips_enabled:
type: boolean
nullable: true
authentik_version:
@ -47415,7 +47415,7 @@ components:
- architecture
- authentik_version
- environment
- openssl_fips_mode
- openssl_fips_enabled
- openssl_version
- platform
- python_version

View File

@ -6,7 +6,7 @@
"": {
"name": "@goauthentik/web-tests",
"dependencies": {
"chromedriver": "^126.0.0"
"chromedriver": "^126.0.1"
},
"devDependencies": {
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
@ -2084,9 +2084,9 @@
}
},
"node_modules/chromedriver": {
"version": "126.0.0",
"resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-126.0.0.tgz",
"integrity": "sha512-rzwKp1okI9RmFtSyIzkk9+GTlTK62ai5P3/AS2qMwl86+gw84d2S/IyLkQMm5cqieFs4dgDAuqqPu0AqQACScg==",
"version": "126.0.1",
"resolved": "https://registry.npmjs.org/chromedriver/-/chromedriver-126.0.1.tgz",
"integrity": "sha512-uV4xIvpPimKmV1/Hn9oX0C57tjsBbVtOeKFX9JzzPYpsu8xiSUAdqa3A8mgZE5DMJKDDoDyDIrA656QncVWRzg==",
"hasInstallScript": true,
"dependencies": {
"@testim/chrome-version": "^1.1.4",

View File

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

View File

@ -1,3 +1,4 @@
import { execFileSync } from "child_process";
import * as chokidar from "chokidar";
import esbuild from "esbuild";
import fs from "fs";
@ -9,12 +10,25 @@ import { fileURLToPath } from "url";
const __dirname = fileURLToPath(new URL(".", import.meta.url));
let authentikProjectRoot = __dirname + "../";
try {
// Use the package.json file in the root folder, as it has the current version information.
authentikProjectRoot = execFileSync("git", ["rev-parse", "--show-toplevel"], {
encoding: "utf8",
}).replace("\n", "");
} catch (exc) {
// We probably don't have a .git folder, which could happen in container builds
}
const rootPackage = JSON.parse(fs.readFileSync(path.join(authentikProjectRoot, "./package.json")));
// eslint-disable-next-line no-undef
const isProdBuild = process.env.NODE_ENV === "production";
// eslint-disable-next-line no-undef
const apiBasePath = process.env.AK_API_BASE_PATH || "";
const envGitHashKey = "GIT_BUILD_HASH";
const definitions = {
"process.env.NODE_ENV": JSON.stringify(isProdBuild ? "production" : "development"),
"process.env.CWD": JSON.stringify(cwd()),
@ -80,8 +94,17 @@ const baseArgs = {
format: "esm",
};
function getVersion() {
let version = rootPackage.version;
if (process.env[envGitHashKey]) {
version = `${version}.${process.env[envGitHashKey]}`;
}
return version;
}
async function buildOneSource(source, dest) {
const DIST = path.join(__dirname, "./dist", dest);
// eslint-disable-next-line no-console
console.log(`[${new Date(Date.now()).toISOString()}] Starting build for target ${source}`);
try {
@ -89,13 +112,13 @@ async function buildOneSource(source, dest) {
await esbuild.build({
...baseArgs,
entryPoints: [`./src/${source}`],
entryNames: `[dir]/[name]-${getVersion()}`,
outdir: DIST,
});
const end = Date.now();
// eslint-disable-next-line no-console
console.log(
`[${new Date(end).toISOString()}] Finished build for target ${source} in ${
Date.now() - start
}ms`,
`[${new Date(end).toISOString()}] Finished build for target ${source} in ${Date.now() - start}ms`,
);
} catch (exc) {
console.error(`[${new Date(Date.now()).toISOString()}] Failed to build ${source}: ${exc}`);
@ -112,12 +135,14 @@ function debouncedBuild() {
clearTimeout(timeoutId);
}
timeoutId = setTimeout(() => {
// eslint-disable-next-line no-console
console.clear();
buildAuthentik(interfaces);
}, 250);
}
if (process.argv.length > 2 && (process.argv[2] === "-h" || process.argv[2] === "--help")) {
// eslint-disable-next-line no-console
console.log(`Build the authentikUI
options:
@ -129,6 +154,7 @@ options:
}
if (process.argv.length > 2 && (process.argv[2] === "-w" || process.argv[2] === "--watch")) {
// eslint-disable-next-line no-console
console.log("Watching ./src for changes");
chokidar.watch("./src").on("all", (event, path) => {
if (!["add", "change", "unlink"].includes(event)) {

1003
web/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -38,13 +38,13 @@
"@codemirror/theme-one-dark": "^6.1.2",
"@formatjs/intl-listformat": "^7.5.7",
"@fortawesome/fontawesome-free": "^6.5.2",
"@goauthentik/api": "^2024.4.2-1718362364",
"@lit-labs/task": "^3.1.0",
"@goauthentik/api": "^2024.4.2-1718378698",
"@lit/context": "^1.1.2",
"@lit/localize": "^0.12.1",
"@lit/reactive-element": "^2.0.4",
"@lit/task": "^1.0.1",
"@open-wc/lit-helpers": "^0.7.0",
"@patternfly/elements": "^3.0.1",
"@patternfly/elements": "^3.0.2",
"@patternfly/patternfly": "^4.224.2",
"@sentry/browser": "^8.9.2",
"@webcomponents/webcomponentsjs": "^2.8.0",
@ -81,13 +81,13 @@
"@lit/localize-tools": "^0.7.2",
"@rollup/plugin-replace": "^5.0.7",
"@spotlightjs/spotlight": "^2.0.0",
"@storybook/addon-essentials": "^8.1.9",
"@storybook/addon-links": "^8.1.9",
"@storybook/addon-essentials": "^8.1.10",
"@storybook/addon-links": "^8.1.10",
"@storybook/api": "^7.6.17",
"@storybook/blocks": "^8.0.8",
"@storybook/manager-api": "^8.1.9",
"@storybook/web-components": "^8.1.9",
"@storybook/web-components-vite": "^8.1.9",
"@storybook/manager-api": "^8.1.10",
"@storybook/web-components": "^8.1.10",
"@storybook/web-components-vite": "^8.1.10",
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
"@types/chart.js": "^2.9.41",
"@types/codemirror": "5.60.15",
@ -117,7 +117,7 @@
"react-dom": "^18.3.1",
"rollup-plugin-modify": "^3.0.0",
"rollup-plugin-postcss-lit": "^2.1.0",
"storybook": "^8.1.9",
"storybook": "^8.1.10",
"storybook-addon-mock": "^5.0.0",
"ts-lit-plugin": "^2.0.2",
"tslib": "^2.6.3",

View File

@ -29,7 +29,7 @@ export class FipsStatusCard extends AdminStatusCard<SystemInfo> {
}
getStatus(value: SystemInfo): Promise<AdminStatus> {
return value.runtime.opensslFipsMode
return value.runtime.opensslFipsEnabled
? this.setStatus(msg("OK"), {
icon: "fa fa-check-circle pf-m-success",
message: html`${msg("FIPS compliance: passing")}`,

View File

@ -66,7 +66,11 @@ export abstract class BaseTaskButton extends CustomEmitterElement(AKElement) {
this.onSuccess = this.onSuccess.bind(this);
this.onError = this.onError.bind(this);
this.onClick = this.onClick.bind(this);
this.actionTask = new Task(this, {
this.actionTask = this.buildTask();
}
buildTask() {
return new Task(this, {
task: () => this.callAction(),
args: () => [],
autoRun: false,
@ -77,8 +81,9 @@ export abstract class BaseTaskButton extends CustomEmitterElement(AKElement) {
onComplete() {
setTimeout(() => {
this.actionTask.status = TaskStatus.INITIAL;
this.dispatchCustomEvent(`${this.eventPrefix}-reset`);
// set-up for the next task...
this.actionTask = this.buildTask();
this.requestUpdate();
}, SPINNER_TIMEOUT);
}
@ -98,7 +103,8 @@ export abstract class BaseTaskButton extends CustomEmitterElement(AKElement) {
}
onClick() {
if (this.actionTask.status !== TaskStatus.INITIAL) {
// Don't accept clicks when a task is in progress..
if (this.actionTask.status === TaskStatus.PENDING) {
return;
}
this.dispatchCustomEvent(`${this.eventPrefix}-click`);

View File

@ -94,22 +94,25 @@ export class ModalOrchestrationController implements ReactiveController {
}
removeTopmostModal() {
let checking = true;
while (checking) {
const modal = this.knownModals.pop();
const knownModals = [...this.knownModals];
// Pop off modals until you find the first live one, schedule it to be closed, and make that
// cleaned list the current state. Since this is our *only* state object, this has the
// effect of creating a new "knownModals" collection with some semantics.
// eslint-disable-next-line no-constant-condition
while (true) {
const modal = knownModals.pop();
if (!modal) {
break;
}
if (!modalIsLive(modal)) {
continue;
}
if (modal.closeModal() !== false) {
this.scheduleCleanup(modal);
}
checking = false;
break;
}
this.knownModals = knownModals;
}
@bound

View File

@ -8794,15 +8794,19 @@ Bindings to groups/users are checked against the user of the event.</source>
</trans-unit>
<trans-unit id="s35f47dbd321aaf15">
<source>FIPS compliance: passing</source>
<target>FIPS 合规性:通过</target>
</trans-unit>
<trans-unit id="sc94578030c702562">
<source>Unverified</source>
<target>未验证</target>
</trans-unit>
<trans-unit id="s16749cce7c4c1589">
<source>FIPS compliance: unverified</source>
<target>FIPS 合规性:未验证</target>
</trans-unit>
<trans-unit id="s0b2ad58c3deaa8dd">
<source>FIPS Status</source>
<target>FIPS 状态</target>
</trans-unit>
</body>
</file>

View File

@ -8791,6 +8791,22 @@ Bindings to groups/users are checked against the user of the event.</source>
<trans-unit id="s146769fb55f1ee50">
<source>SCIM User(s)</source>
<target>SCIM 用户</target>
</trans-unit>
<trans-unit id="s35f47dbd321aaf15">
<source>FIPS compliance: passing</source>
<target>FIPS 合规性:通过</target>
</trans-unit>
<trans-unit id="sc94578030c702562">
<source>Unverified</source>
<target>未验证</target>
</trans-unit>
<trans-unit id="s16749cce7c4c1589">
<source>FIPS compliance: unverified</source>
<target>FIPS 合规性:未验证</target>
</trans-unit>
<trans-unit id="s0b2ad58c3deaa8dd">
<source>FIPS Status</source>
<target>FIPS 状态</target>
</trans-unit>
</body>
</file>

View File

@ -81,19 +81,21 @@ All PostgreSQL settings, apart from `USE_PGBOUNCER` and `USE_PGPOOL`, support ho
### Read replicas
Additional databases used only for read operations can be configured. Increase the number (by default `0`) in the following configuration settings for each read replica.
You can configure additional read replica databases that are used only for read operations. To configure authentik to use replicas, add the settings below to your [configuration file](./configuration.mdx#set-your-environment-variables). If you have multiple replicas, add additional settings for each replica, replacing the default `0` with a unique value for each additional replica.
If read replicas are configured, the main database is not used for reads. If you'd like the main database to be included for reads, add it as a read replica.
- `AUTHENTIK_POSTGRESQL__READ_REPLICAS__0__HOST`: same as above
- `AUTHENTIK_POSTGRESQL__READ_REPLICAS__0__NAME`: same as above
- `AUTHENTIK_POSTGRESQL__READ_REPLICAS__0__USER`: same as above
- `AUTHENTIK_POSTGRESQL__READ_REPLICAS__0__PORT`: same as above
- `AUTHENTIK_POSTGRESQL__READ_REPLICAS__0__PASSWORD`: same as above
- `AUTHENTIK_POSTGRESQL__READ_REPLICAS__0__SSLMODE`: same as above
- `AUTHENTIK_POSTGRESQL__READ_REPLICAS__0__SSLROOTCERT`: same as above
- `AUTHENTIK_POSTGRESQL__READ_REPLICAS__0__SSLCERT`: same as above
- `AUTHENTIK_POSTGRESQL__READ_REPLICAS__0__SSLKEY`: same as above
The same PostgreSQL settings as described above are used for each read replica.
- `AUTHENTIK_POSTGRESQL__READ_REPLICAS__0__HOST`
- `AUTHENTIK_POSTGRESQL__READ_REPLICAS__0__NAME`
- `AUTHENTIK_POSTGRESQL__READ_REPLICAS__0__USER`
- `AUTHENTIK_POSTGRESQL__READ_REPLICAS__0__PORT`
- `AUTHENTIK_POSTGRESQL__READ_REPLICAS__0__PASSWORD`
- `AUTHENTIK_POSTGRESQL__READ_REPLICAS__0__SSLMODE`
- `AUTHENTIK_POSTGRESQL__READ_REPLICAS__0__SSLROOTCERT`
- `AUTHENTIK_POSTGRESQL__READ_REPLICAS__0__SSLCERT`
- `AUTHENTIK_POSTGRESQL__READ_REPLICAS__0__SSLKEY`
Note that `USE_PGBOUNCER` and `USE_PGPOOL` are inherited from the main database configuration and are _not_ overridable on read replicas.

View File

@ -92,6 +92,7 @@ helm upgrade authentik authentik/authentik -f values.yaml --version ^2024.6
## Minor changes/fixes
- admin: system api: do not show FIPS status if no valid license (#10091)
- admin: system api: fix FIPS status schema (#10110)
- core: FIPS (#9683)
- core: add include_users flag to single group retrieval (#9721)
- core: add option to select group for property mapping testing (#9834)
@ -110,6 +111,7 @@ helm upgrade authentik authentik/authentik -f values.yaml --version ^2024.6
- enterprise/providers/google_workspace: ensure no group is created when no property mappings are set (#9783)
- enterprise/providers/microsoft_entra: fix error when updating connection attributes (#10039)
- enterprise/providers/microsoft_entra: initial account sync to microsoft entra (#9632)
- enterprise/providers: import user/group data when manually linking objects (#10089)
- enterprise/stages/source: fix error when creating source stage from blueprint (#9810)
- events: ensure all models' **str** can be called without any further lookups (#9480)
- events: fix geoip enrich context not converting to json-seriazable data (#9885)
@ -122,6 +124,7 @@ helm upgrade authentik authentik/authentik -f values.yaml --version ^2024.6
- lifecycle: always try custom redis URL (#9441)
- lifecycle: close database connection after migrating (#9516)
- lifecycle: fix ak test-all command
- policies/reputation: save to database directly (#10059)
- policies: fix ak_call_policy failing when used in testing (#9853)
- providers/oauth2: don't handle api scope as special scope (#9910)
- providers/proxy: rework redirect mechanism (#8594)

View File

@ -0,0 +1,77 @@
---
title: Slack
---
<span class="badge badge--primary">Support level: authentik</span>
## What is Slack
> Slack is a platform for collaboration, with chat and real-time video capabilities. To learn more, visit https://slack.com.
## Preparation
The following placeholder will be used:
- You can use <kbd>slack.<em>company</em>></kbd> or <kbd><em>my-workspace</em>.slack.com</kbd> as the FQDN of your Slack instance.
- You can use <kbd>authentik.company</kbd> as the FQDN of the authentik install.
For additional information about integrating with Slack, refer to their [documentation](https://slack.com/help/articles/205168057-Custom-SAML-single-sign-on).
## authentik configuration
### Step 1. Create custom property mappings
Your Slack integration requires two property mappings, one each for `User.Email` and `User.Username`, so that authentik can retrieve and map these values from Slack.
1. Log in as admin to your authentik instance and then click **Admin interface**.
2. Navigate to **Customization -> Property Mappings**.
3. Create the property mapping for `User.Email`.
1. On the **Property Mappings** page, click **Create**.
2. On the **New property mapping** modal, select **SAML Property Mapping** and then click **Next**.
3. Define the required values. In the **Expression** field, define `User.Email` as `return request.user.email`.
4. Click **Finish**.
5. Create the property mapping for `User.Username`.
1. On the **Property Mappings** page, click **Create**.
2. On the **New property mapping** modal, select **SAML Property Mapping** and then click **Next**.
3. Define the required values. In the **Expression** field, define `User.Username` as `return request.user.username`.
6. Click **Finish**.
### Step 2. Create a new authentication provider
1. Navigate to **Applications -> Providers** and then click **Create**.
2. On the **New provider** modal, select **SAML Provider** and then click **Next**.
3. Define the following values (values not listed below can be left as default or empty):
- **Name**: provide a clear name, such as "slack".
- **Authorization flow**: Authorize Application (`default-provider-authorization-implicit-consent`).
- **Protocol settings** define the following values:
- **ACS URL**: `https://_workspace-name_.slack.com/sso/saml`
- **Issuer**: `https://slack.com`.
- **Service Provider Binding**: select **Post**
- **Advanced protocol settings**
- **Signing Certificate**: select the appproriate certificate for Slack.
- **Property mappings**: Select the property mappings that you created in Step 1. You can leave the default property mappings and other settings.
4. Click **Finish** to create the provider.
### Step 3. Create a new application
1. Navigate to **Applications -> Applications** and then click **Create**.
2. Provide a name for the new application.
3. Set the provider to the one you just created.
4. Click **Create**.
:::info
After you have created the provider and application, and the application is connected to the provider (Step 3 above) the **Overview** tab on the provider's detail page in the Admin UI will display additional information that you will need to configure Slack, using the following steps.
:::
## Slack configuration
### Step 4. Configure Slack
1. Log in to the Slack Admin Dashboard.
2. Navigate to the **Configure SAML Authentication** page.
3. Enter the following values:
- **SAML 2.0 Endpoint (HTTP)**: copy/paste in the **SSO URL (Redirect)** URL from the provider that you created in authentik. **Example**: `https://_authentik.company_/applications/saml/slack/sso/binding/redirect/`
- **Identity Provider Issuer**: set to `https://slack.com`
- **Public Certificate**: add the certificate, which you can download from the authentik provider, under **Download signing certificate**.
4. Optionally, configure the other settings and customize the Sign in button label.
5. Click **Save**.

View File

@ -46,6 +46,7 @@ To configure Synology DSM to utilize authentik as an OpenID Connect 1.0 Provider
3. Configure the following values:
- Profile: OIDC
- Account type: Domain/LDAP/local
- Name: authentik
- Well Known URL: Copy this from the 'OpenID Configuration URL' in the authentik provider (URL ends with '/.well-known/openid-configuration')
- Application ID: The 'Client ID' from the authentik provider

View File

@ -27,7 +27,7 @@
"react-dom": "^18.3.1",
"react-feather": "^2.0.10",
"react-toggle": "^4.1.3",
"react-tooltip": "^5.26.4",
"react-tooltip": "^5.27.0",
"remark-github": "^12.0.0"
},
"devDependencies": {
@ -16306,9 +16306,9 @@
}
},
"node_modules/react-tooltip": {
"version": "5.26.4",
"resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.26.4.tgz",
"integrity": "sha512-5WyDrsfw1+6qNVSr3IjqElqJ+cCwE8+44b+HpJ8qRLv7v0a3mcKf8wvv+NfgALFS6QpksGFqTLV2JQ60c+okZQ==",
"version": "5.27.0",
"resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.27.0.tgz",
"integrity": "sha512-JXROcdfCEbCqkAkh8LyTSP3guQ0dG53iY2E2o4fw3D8clKzziMpE6QG6CclDaHELEKTzpMSeAOsdtg0ahoQosw==",
"dependencies": {
"@floating-ui/dom": "^1.6.1",
"classnames": "^2.3.0"

View File

@ -34,7 +34,7 @@
"react-dom": "^18.3.1",
"react-feather": "^2.0.10",
"react-toggle": "^4.1.3",
"react-tooltip": "^5.26.4",
"react-tooltip": "^5.27.0",
"remark-github": "^12.0.0"
},
"browserslist": {

View File

@ -40,6 +40,7 @@ module.exports = {
"services/rocketchat/index",
"services/roundcube/index",
"services/sharepoint-se/index",
"services/slack/index",
"services/vikunja/index",
"services/wekan/index",
"services/wiki-js/index",