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:
parent
e6febf1e8b
commit
15b0952f1b
10
Makefile
10
Makefile
|
@ -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
|
||||||
|
|
|
@ -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 = []
|
|
@ -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)
|
|
@ -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)
|
|
|
@ -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 []
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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),
|
||||||
|
]
|
||||||
|
|
Reference in New Issue