Compare commits
10 Commits
version/20
...
version/20
Author | SHA1 | Date | |
---|---|---|---|
0bbbc7def2 | |||
43fd3eecda | |||
631b120e4f | |||
9ea517d606 | |||
7b7a7e3073 | |||
ca3cdc3fd2 | |||
6e12277903 | |||
2f42144b33 | |||
eef02f2892 | |||
b6157ecaf1 |
@ -1,5 +1,5 @@
|
||||
[bumpversion]
|
||||
current_version = 2024.6.0-rc1
|
||||
current_version = 2024.6.0-rc2
|
||||
tag = True
|
||||
commit = True
|
||||
parse = (?P<major>\d+)\.(?P<minor>\d+)\.(?P<patch>\d+)(?:-(?P<rc_t>[a-zA-Z-]+)(?P<rc_n>[1-9]\\d*))?
|
||||
@ -17,6 +17,8 @@ optional_value = final
|
||||
|
||||
[bumpversion:file:pyproject.toml]
|
||||
|
||||
[bumpversion:file:package.json]
|
||||
|
||||
[bumpversion:file:docker-compose.yml]
|
||||
|
||||
[bumpversion:file:schema.yml]
|
||||
|
@ -22,6 +22,8 @@ RUN npm run build-bundled
|
||||
# Stage 2: Build webui
|
||||
FROM --platform=${BUILDPLATFORM} docker.io/node:22 as web-builder
|
||||
|
||||
ARG GIT_BUILD_HASH
|
||||
ENV GIT_BUILD_HASH=$GIT_BUILD_HASH
|
||||
ENV NODE_ENV=production
|
||||
|
||||
WORKDIR /work/web
|
||||
@ -31,6 +33,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
|
||||
|
@ -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 %}
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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 (
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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"""
|
||||
|
||||
|
@ -76,8 +76,11 @@ class PropertyMappingEvaluator(BaseEvaluator):
|
||||
)
|
||||
if "request" in self._context:
|
||||
req: PolicyRequest = self._context["request"]
|
||||
event.from_http(req.http_request, req.user)
|
||||
return
|
||||
if req.http_request:
|
||||
event.from_http(req.http_request, req.user)
|
||||
return
|
||||
elif req.user:
|
||||
event.set_user(req.user)
|
||||
event.save()
|
||||
|
||||
def evaluate(self, *args, **kwargs) -> Any:
|
||||
|
@ -16,3 +16,7 @@ class SkipObjectException(PropertyMappingExpressionException):
|
||||
"""Exception which can be raised in a property mapping to skip syncing an object.
|
||||
Only applies to Property mappings which sync objects, and not on mappings which transitively
|
||||
apply to a single user"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
# For this class only, both of these are set by the function evaluating the property mapping
|
||||
super().__init__(exc=None, mapping=None)
|
||||
|
@ -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 }}" />
|
||||
|
@ -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" %}
|
||||
|
@ -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 }}");
|
||||
|
@ -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" %}
|
||||
|
0
authentik/core/templatetags/__init__.py
Normal file
0
authentik/core/templatetags/__init__.py
Normal file
27
authentik/core/templatetags/authentik_core.py
Normal file
27
authentik/core/templatetags/authentik_core.py
Normal 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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 }}">
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -4,7 +4,10 @@ from django.db.models import QuerySet
|
||||
from django.http import HttpRequest
|
||||
|
||||
from authentik.core.expression.evaluator import PropertyMappingEvaluator
|
||||
from authentik.core.expression.exceptions import PropertyMappingExpressionException
|
||||
from authentik.core.expression.exceptions import (
|
||||
PropertyMappingExpressionException,
|
||||
SkipObjectException,
|
||||
)
|
||||
from authentik.core.models import PropertyMapping, User
|
||||
|
||||
|
||||
@ -57,6 +60,10 @@ class PropertyMappingManager:
|
||||
mapping.set_context(user, request, **kwargs)
|
||||
try:
|
||||
value = mapping.evaluate(mapping.model.expression)
|
||||
except SkipObjectException as exc:
|
||||
exc.exc = exc
|
||||
exc.mapping = mapping
|
||||
raise exc from exc
|
||||
except PropertyMappingExpressionException as exc:
|
||||
raise exc from exc
|
||||
except Exception as exc:
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 (
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
||||
|
@ -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"
|
||||
)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "@goauthentik/authentik",
|
||||
"version": "1.0.0",
|
||||
"private": true
|
||||
"name": "@goauthentik/authentik",
|
||||
"version": "2024.6.0",
|
||||
"private": true
|
||||
}
|
||||
|
@ -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 \
|
||||
|
@ -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)) {
|
||||
|
18
web/package-lock.json
generated
18
web/package-lock.json
generated
@ -18,10 +18,10 @@
|
||||
"@formatjs/intl-listformat": "^7.5.7",
|
||||
"@fortawesome/fontawesome-free": "^6.5.2",
|
||||
"@goauthentik/api": "^2024.4.2-1718378698",
|
||||
"@lit-labs/task": "^3.1.0",
|
||||
"@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/patternfly": "^4.224.2",
|
||||
@ -3333,15 +3333,6 @@
|
||||
"integrity": "sha512-yWJKmpGE6lUURKAaIltoPIE/wrbY3TEkqQt+X0m+7fQNnAv0keydnYvbiJFP1PnMhizmIWRWOG5KLhYyc/xl+g==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/@lit-labs/task": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@lit-labs/task/-/task-3.1.0.tgz",
|
||||
"integrity": "sha512-zMlcUtZeHDT83IiT2+CJBSoFvWDLnPEezhOCgqjxW4DmRHlbgd7jdft97T6dw4S4RvIETfI7OOyvubCV/EzTlg==",
|
||||
"license": "BSD-3-Clause",
|
||||
"dependencies": {
|
||||
"@lit/task": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@lit/context": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@lit/context/-/context-1.1.2.tgz",
|
||||
@ -3403,10 +3394,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@lit/task": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@lit/task/-/task-1.0.0.tgz",
|
||||
"integrity": "sha512-7jocGBh3yGlo3kKxQggZph2txK4X5GYNWp2FAsmV9u2spzUypwrzRzXe8I72icAb02B00+k2nlvxVcrQB6vyrw==",
|
||||
"license": "BSD-3-Clause",
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@lit/task/-/task-1.0.1.tgz",
|
||||
"integrity": "sha512-fVLDtmwCau8NywnFIXaJxsCZjzaIxnVq+cFRKYC1Y4tA4/0rMTvF6DLZZ2JE51BwzOluaKtgJX8x1QDsQtAaIw==",
|
||||
"dependencies": {
|
||||
"@lit/reactive-element": "^1.0.0 || ^2.0.0"
|
||||
}
|
||||
|
@ -39,10 +39,10 @@
|
||||
"@formatjs/intl-listformat": "^7.5.7",
|
||||
"@fortawesome/fontawesome-free": "^6.5.2",
|
||||
"@goauthentik/api": "^2024.4.2-1718378698",
|
||||
"@lit-labs/task": "^3.1.0",
|
||||
"@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/patternfly": "^4.224.2",
|
||||
|
@ -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`);
|
||||
|
@ -25,6 +25,10 @@ The provided Helm chart defaults to PostgreSQL 15. If you are using the Helm cha
|
||||
|
||||
The provided Compose file was updated with PostgreSQL 16. You can follow the procedure [here](../../troubleshooting/postgres/upgrade_docker.md) to upgrade.
|
||||
|
||||
### Group names unicity
|
||||
|
||||
With this release, authentik now enforces unique group names. Existing groups with name collisions that were created in earlier versions can still exist, but any new groups you create will need a unique name. If changing attributes, permission-level, or parent on an existing group with a name collision, you need to also change its name to be unique. Note that changing members or roles associated with the group does not require a rename.
|
||||
|
||||
## New features
|
||||
|
||||
- **Google Workspace Provider** <span class="badge badge--primary">Enterprise</span> <span class="badge badge--info">Preview</span>
|
||||
@ -98,12 +102,14 @@ helm upgrade authentik authentik/authentik -f values.yaml --version ^2024.6
|
||||
- core: add option to select group for property mapping testing (#9834)
|
||||
- core: fix auth_method and auth_method_args being overwritten by password stage (#9782)
|
||||
- core: fix condition in task clean_expiring_models (#9603)
|
||||
- core: fix error when raising SkipObject in mapping (cherry-pick #10153)
|
||||
- core: fix logic for token expiration (#9426)
|
||||
- core: fix source flow_manager not always appending save stage (#9659)
|
||||
- core: fix source_flow_manager saving user-source connection too early (#9559)
|
||||
- core: fix task clean_expiring_models removing valid sessions with using database storage (#9598)
|
||||
- core: groups api: always prefetch users (#9974)
|
||||
- core: groups: optimize recursive children query (#9931)
|
||||
- core: include version in built JS files (cherry-pick #9558) (#10148)
|
||||
- core: only prefetch related objects when required (#9476)
|
||||
- crypto: update fingerprint at same time as certificate (#10036)
|
||||
- enterprise/audit: fix audit logging with m2m relations (#9571)
|
||||
@ -124,6 +130,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: fix existing reputation update (cherry-pick #10124) (#10125)
|
||||
- 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)
|
||||
@ -144,6 +151,7 @@ helm upgrade authentik authentik/authentik -f values.yaml --version ^2024.6
|
||||
- root: docker-compose: remove version top level element (#9631)
|
||||
- root: handle asgi exception (#10085)
|
||||
- root: include task_id in events and logs (#9749)
|
||||
- root: use custom model serializer that saves m2m without bulk (cherry-pick #10139) (#10151)
|
||||
- sources/oauth: ensure all UI sources return a valid source (#9401)
|
||||
- sources/oauth: fix OAuth Client sending token request incorrectly (#9474)
|
||||
- sources/oauth: modernizes discord icon (#9817)
|
||||
@ -176,6 +184,8 @@ helm upgrade authentik authentik/authentik -f values.yaml --version ^2024.6
|
||||
- web: Add resolved and integrity fields back to package-lock.json (#9419)
|
||||
- web: clean up some repetitive types (#9241)
|
||||
- web: clean up the options rendering in PromptForm (#9564)
|
||||
- web: fix docker build for non-release versions (cherry-pick #10154) (#10155)
|
||||
- web: fix needed because recent upgrade to task breaks spinner button (cherry-pick #10142) (#10150)
|
||||
- web: fix value handling inside controlled components (#9648)
|
||||
- web: markdown: display markdown even when frontmatter is missing (#9404)
|
||||
|
||||
|
Reference in New Issue
Block a user