split api into smaller files, only import urls when tenants is enabled

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
Jens Langhammer 2024-01-16 11:28:54 +01:00
parent e6febf1e8b
commit 15b0952f1b
No known key found for this signature in database
8 changed files with 105 additions and 97 deletions

View File

@ -94,8 +94,14 @@ dev-reset: dev-drop-db dev-create-db migrate ## Drop and restore the Authentik
######################### #########################
gen-build: ## Extract the schema from the database gen-build: ## Extract the schema from the database
AUTHENTIK_DEBUG=true ak make_blueprint_schema > blueprints/schema.json AUTHENTIK_DEBUG=true \
AUTHENTIK_DEBUG=true ak spectacular --file schema.yml AUTHENTIK_TENANTS__ENABLED=true \
AUTHENTIK_OUTPOSTS__DISABLE_EMBEDDED_OUTPOST=true \
ak make_blueprint_schema > blueprints/schema.json
AUTHENTIK_DEBUG=true \
AUTHENTIK_TENANTS__ENABLED=true \
AUTHENTIK_OUTPOSTS__DISABLE_EMBEDDED_OUTPOST=true \
ak spectacular --file schema.yml
gen-changelog: ## (Release) generate the changelog based from the commits since the last tag gen-changelog: ## (Release) generate the changelog based from the commits since the last tag
git log --pretty=format:" - %s" $(shell git describe --tags $(shell git rev-list --tags --max-count=1))...$(shell git branch --show-current) | sort > changelog.md git log --pretty=format:" - %s" $(shell git describe --tags $(shell git rev-list --tags --max-count=1))...$(shell git branch --show-current) | sort > changelog.md

View File

View File

@ -0,0 +1,32 @@
"""Serializer for tenants models"""
from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet
from authentik.tenants.api.tenants import TenantApiKeyPermission
from authentik.tenants.models import Domain
class DomainSerializer(ModelSerializer):
"""Domain Serializer"""
class Meta:
model = Domain
fields = "__all__"
class DomainViewSet(ModelViewSet):
"""Domain ViewSet"""
queryset = Domain.objects.all()
serializer_class = DomainSerializer
search_fields = [
"domain",
"tenant__name",
"tenant__schema_name",
]
ordering = ["domain"]
authentication_classes = []
permission_classes = [TenantApiKeyPermission]
filter_backends = [OrderingFilter, SearchFilter]
filterset_fields = []

View File

@ -0,0 +1,51 @@
"""Serializer for tenants models"""
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.rbac.permissions import HasPermission
from authentik.tenants.models import Tenant
class SettingsSerializer(ModelSerializer):
"""Settings Serializer"""
class Meta:
model = Tenant
fields = [
"avatars",
"default_user_change_name",
"default_user_change_email",
"default_user_change_username",
"event_retention",
"footer_links",
"gdpr_compliance",
"impersonation",
]
class SettingsView(RetrieveUpdateAPIView):
"""Settings view"""
queryset = Tenant.objects.filter(ready=True)
serializer_class = SettingsSerializer
filter_backends = []
def get_permissions(self):
return [
HasPermission(
"authentik_rbac.view_system_settings"
if self.request.method in SAFE_METHODS
else "authentik_rbac.edit_system_settings"
)()
]
def get_object(self):
obj = self.request.tenant
self.check_object_permissions(self.request, obj)
return obj
def perform_update(self, serializer):
# We need to be in the public schema to actually modify a tenant
with Tenant.objects.get(schema_name=get_public_schema_name()):
super().perform_update(serializer)

View File

@ -5,15 +5,12 @@ from hmac import compare_digest
from django.http import HttpResponseNotFound from django.http import HttpResponseNotFound
from django.http.request import urljoin from django.http.request import urljoin
from django.utils.timezone import now from django.utils.timezone import now
from django_tenants.utils import get_public_schema_name
from drf_spectacular.utils import OpenApiResponse, extend_schema from drf_spectacular.utils import OpenApiResponse, extend_schema
from rest_framework import permissions from rest_framework import permissions
from rest_framework.authentication import get_authorization_header from rest_framework.authentication import get_authorization_header
from rest_framework.decorators import action from rest_framework.decorators import action
from rest_framework.fields import CharField, IntegerField from rest_framework.fields import CharField, IntegerField
from rest_framework.filters import OrderingFilter, SearchFilter from rest_framework.filters import OrderingFilter, SearchFilter
from rest_framework.generics import RetrieveUpdateAPIView
from rest_framework.permissions import SAFE_METHODS
from rest_framework.request import Request from rest_framework.request import Request
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.serializers import DateTimeField, ModelSerializer from rest_framework.serializers import DateTimeField, ModelSerializer
@ -24,9 +21,8 @@ from authentik.api.authentication import validate_auth
from authentik.core.api.utils import PassiveSerializer from authentik.core.api.utils import PassiveSerializer
from authentik.core.models import User from authentik.core.models import User
from authentik.lib.config import CONFIG from authentik.lib.config import CONFIG
from authentik.rbac.permissions import HasPermission
from authentik.recovery.lib import create_admin_group, create_recovery_token from authentik.recovery.lib import create_admin_group, create_recovery_token
from authentik.tenants.models import Domain, Tenant from authentik.tenants.models import Tenant
class TenantApiKeyPermission(permissions.BasePermission): class TenantApiKeyPermission(permissions.BasePermission):
@ -91,11 +87,6 @@ class TenantViewSet(ModelViewSet):
filter_backends = [OrderingFilter, SearchFilter] filter_backends = [OrderingFilter, SearchFilter]
filterset_fields = [] filterset_fields = []
def dispatch(self, request, *args, **kwargs):
if not CONFIG.get_bool("tenants.enabled", True):
return HttpResponseNotFound()
return super().dispatch(request, *args, **kwargs)
@extend_schema( @extend_schema(
request=TenantAdminGroupRequestSerializer(), request=TenantAdminGroupRequestSerializer(),
responses={ responses={
@ -150,76 +141,3 @@ class TenantViewSet(ModelViewSet):
serializer = TenantRecoveryKeyResponseSerializer({"expiry": token.expires, "url": url}) serializer = TenantRecoveryKeyResponseSerializer({"expiry": token.expires, "url": url})
return Response(serializer.data) return Response(serializer.data)
class DomainSerializer(ModelSerializer):
"""Domain Serializer"""
class Meta:
model = Domain
fields = "__all__"
class DomainViewSet(ModelViewSet):
"""Domain ViewSet"""
queryset = Domain.objects.all()
serializer_class = DomainSerializer
search_fields = [
"domain",
"tenant__name",
"tenant__schema_name",
]
ordering = ["domain"]
authentication_classes = []
permission_classes = [TenantApiKeyPermission]
filter_backends = [OrderingFilter, SearchFilter]
filterset_fields = []
def dispatch(self, request, *args, **kwargs):
if not CONFIG.get_bool("tenants.enabled", True):
return HttpResponseNotFound()
return super().dispatch(request, *args, **kwargs)
class SettingsSerializer(ModelSerializer):
"""Settings Serializer"""
class Meta:
model = Tenant
fields = [
"avatars",
"default_user_change_name",
"default_user_change_email",
"default_user_change_username",
"event_retention",
"footer_links",
"gdpr_compliance",
"impersonation",
]
class SettingsView(RetrieveUpdateAPIView):
"""Settings view"""
queryset = Tenant.objects.filter(ready=True)
serializer_class = SettingsSerializer
filter_backends = []
def get_permissions(self):
return [
HasPermission(
"authentik_rbac.view_system_settings"
if self.request.method in SAFE_METHODS
else "authentik_rbac.edit_system_settings"
)()
]
def get_object(self):
obj = self.request.tenant
self.check_object_permissions(self.request, obj)
return obj
def perform_update(self, serializer):
# We need to be in the public schema to actually modify a tenant
with Tenant.objects.get(schema_name=get_public_schema_name()):
super().perform_update(serializer)

View File

@ -14,7 +14,7 @@ def check_embedded_outpost_disabled(app_configs, **kwargs):
Error( Error(
"Embedded outpost must be disabled when tenants API is enabled.", "Embedded outpost must be disabled when tenants API is enabled.",
hint="Disable embedded outpost by setting outposts.disable_embedded_outpost to " hint="Disable embedded outpost by setting outposts.disable_embedded_outpost to "
"False, or disable the tenants API by setting tenants.enabled to False", "True, or disable the tenants API by setting tenants.enabled to False",
) )
] ]
return [] return []

View File

@ -93,7 +93,7 @@ class Tenant(TenantMixin, SerializerModel):
@property @property
def serializer(self) -> Serializer: def serializer(self) -> Serializer:
from authentik.tenants.api import TenantSerializer from authentik.tenants.api.tenants import TenantSerializer
return TenantSerializer return TenantSerializer
@ -117,7 +117,7 @@ class Domain(DomainMixin, SerializerModel):
@property @property
def serializer(self) -> Serializer: def serializer(self) -> Serializer:
from authentik.tenants.api import DomainSerializer from authentik.tenants.api.domains import DomainSerializer
return DomainSerializer return DomainSerializer

View File

@ -1,16 +1,17 @@
"""API URLs""" """API URLs"""
from django.urls import path from django.urls import path
from authentik.lib.config import CONFIG
from authentik.tenants.api import DomainViewSet, SettingsView, TenantViewSet from authentik.tenants.api.tenants import TenantViewSet
from authentik.tenants.api.domains import DomainViewSet
from authentik.tenants.api.settings import SettingsView
api_urlpatterns = [ api_urlpatterns = [
path("admin/settings/", SettingsView.as_view(), name="tenant_settings"), path("admin/settings/", SettingsView.as_view(), name="tenant_settings"),
(
"tenants/tenants",
TenantViewSet,
),
(
"tenants/domains",
DomainViewSet,
),
] ]
if CONFIG.get_bool("tenants.enabled", True):
api_urlpatterns += [
("tenants/tenants", TenantViewSet),
("tenants/domains", DomainViewSet),
]