core: add API to test property mapping
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
parent
6916c59483
commit
f206baf3f0
|
@ -1,17 +1,34 @@
|
||||||
"""PropertyMapping API Views"""
|
"""PropertyMapping API Views"""
|
||||||
|
from json import dumps
|
||||||
|
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from drf_yasg.utils import swagger_auto_schema
|
from drf_yasg.utils import swagger_auto_schema
|
||||||
|
from guardian.shortcuts import get_objects_for_user
|
||||||
from rest_framework import mixins
|
from rest_framework import mixins
|
||||||
from rest_framework.decorators import action
|
from rest_framework.decorators import action
|
||||||
|
from rest_framework.exceptions import PermissionDenied
|
||||||
|
from rest_framework.fields import CharField
|
||||||
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 ModelSerializer, SerializerMethodField
|
from rest_framework.serializers import ModelSerializer, SerializerMethodField
|
||||||
from rest_framework.viewsets import GenericViewSet
|
from rest_framework.viewsets import GenericViewSet
|
||||||
|
|
||||||
from authentik.core.api.utils import MetaNameSerializer, TypeCreateSerializer
|
from authentik.api.decorators import permission_required
|
||||||
|
from authentik.core.api.utils import (
|
||||||
|
MetaNameSerializer,
|
||||||
|
PassiveSerializer,
|
||||||
|
TypeCreateSerializer,
|
||||||
|
)
|
||||||
from authentik.core.models import PropertyMapping
|
from authentik.core.models import PropertyMapping
|
||||||
from authentik.lib.templatetags.authentik_utils import verbose_name
|
from authentik.lib.templatetags.authentik_utils import verbose_name
|
||||||
from authentik.lib.utils.reflection import all_subclasses
|
from authentik.lib.utils.reflection import all_subclasses
|
||||||
|
from authentik.policies.api.exec import PolicyTestSerializer
|
||||||
|
|
||||||
|
|
||||||
|
class PropertyMappingTestResultSerializer(PassiveSerializer):
|
||||||
|
"""Result of a Property-mapping test"""
|
||||||
|
|
||||||
|
result = CharField(read_only=True)
|
||||||
|
|
||||||
|
|
||||||
class PropertyMappingSerializer(ModelSerializer, MetaNameSerializer):
|
class PropertyMappingSerializer(ModelSerializer, MetaNameSerializer):
|
||||||
|
@ -76,3 +93,37 @@ class PropertyMappingViewSet(
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
return Response(TypeCreateSerializer(data, many=True).data)
|
return Response(TypeCreateSerializer(data, many=True).data)
|
||||||
|
|
||||||
|
@permission_required("authentik_core.view_propertymapping")
|
||||||
|
@swagger_auto_schema(
|
||||||
|
request_body=PolicyTestSerializer(),
|
||||||
|
responses={200: PropertyMappingTestResultSerializer},
|
||||||
|
)
|
||||||
|
@action(detail=True, methods=["POST"])
|
||||||
|
# pylint: disable=unused-argument, invalid-name
|
||||||
|
def test(self, request: Request, pk: str) -> Response:
|
||||||
|
"""Test Property Mapping"""
|
||||||
|
mapping: PropertyMapping = self.get_object()
|
||||||
|
test_params = PolicyTestSerializer(data=request.data)
|
||||||
|
if not test_params.is_valid():
|
||||||
|
return Response(test_params.errors, status=400)
|
||||||
|
|
||||||
|
# User permission check, only allow mapping testing for users that are readable
|
||||||
|
users = get_objects_for_user(request.user, "authentik_core.view_user").filter(
|
||||||
|
pk=test_params.validated_data["user"].pk
|
||||||
|
)
|
||||||
|
if not users.exists():
|
||||||
|
raise PermissionDenied()
|
||||||
|
|
||||||
|
response_data = {}
|
||||||
|
try:
|
||||||
|
result = mapping.evaluate(
|
||||||
|
users.first(),
|
||||||
|
self.request,
|
||||||
|
**test_params.validated_data.get("context", {}),
|
||||||
|
)
|
||||||
|
response_data["result"] = dumps(result)
|
||||||
|
except Exception as exc: # pylint: disable=broad-except
|
||||||
|
response_data["result"] = str(exc)
|
||||||
|
response = PropertyMappingTestResultSerializer(response_data)
|
||||||
|
return Response(response.data)
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
"""Test property mappings API"""
|
||||||
|
from json import dumps
|
||||||
|
|
||||||
|
from django.urls import reverse
|
||||||
|
from rest_framework.test import APITestCase
|
||||||
|
|
||||||
|
from authentik.core.models import PropertyMapping, User
|
||||||
|
|
||||||
|
|
||||||
|
class TestPropertyMappingAPI(APITestCase):
|
||||||
|
"""Test property mappings API"""
|
||||||
|
|
||||||
|
def setUp(self) -> None:
|
||||||
|
super().setUp()
|
||||||
|
self.mapping = PropertyMapping.objects.create(
|
||||||
|
name="dummy", expression="""return {'foo': 'bar'}"""
|
||||||
|
)
|
||||||
|
self.user = User.objects.get(username="akadmin")
|
||||||
|
self.client.force_login(self.user)
|
||||||
|
|
||||||
|
def test_test_call(self):
|
||||||
|
"""Test Policy's test endpoint"""
|
||||||
|
response = self.client.post(
|
||||||
|
reverse(
|
||||||
|
"authentik_api:propertymapping-test", kwargs={"pk": self.mapping.pk}
|
||||||
|
),
|
||||||
|
data={
|
||||||
|
"user": self.user.pk,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
self.assertJSONEqual(
|
||||||
|
response.content.decode(), {"result": dumps({"foo": "bar"})}
|
||||||
|
)
|
45
swagger.yaml
45
swagger.yaml
|
@ -7984,6 +7984,43 @@ paths:
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
format: uuid
|
format: uuid
|
||||||
|
/propertymappings/all/{pm_uuid}/test/:
|
||||||
|
post:
|
||||||
|
operationId: propertymappings_all_test
|
||||||
|
description: Test Property Mapping
|
||||||
|
parameters:
|
||||||
|
- name: data
|
||||||
|
in: body
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/PolicyTest'
|
||||||
|
responses:
|
||||||
|
'200':
|
||||||
|
description: ''
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/PropertyMappingTestResult'
|
||||||
|
'400':
|
||||||
|
description: Invalid input.
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/ValidationError'
|
||||||
|
'403':
|
||||||
|
description: Authentication credentials were invalid, absent or insufficient.
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/GenericError'
|
||||||
|
'404':
|
||||||
|
description: Object does not exist or caller has insufficient permissions
|
||||||
|
to access it.
|
||||||
|
schema:
|
||||||
|
$ref: '#/definitions/APIException'
|
||||||
|
tags:
|
||||||
|
- propertymappings
|
||||||
|
parameters:
|
||||||
|
- name: pm_uuid
|
||||||
|
in: path
|
||||||
|
description: A UUID string identifying this Property Mapping.
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
format: uuid
|
||||||
/propertymappings/ldap/:
|
/propertymappings/ldap/:
|
||||||
get:
|
get:
|
||||||
operationId: propertymappings_ldap_list
|
operationId: propertymappings_ldap_list
|
||||||
|
@ -16843,6 +16880,14 @@ definitions:
|
||||||
title: Verbose name plural
|
title: Verbose name plural
|
||||||
type: string
|
type: string
|
||||||
readOnly: true
|
readOnly: true
|
||||||
|
PropertyMappingTestResult:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
result:
|
||||||
|
title: Result
|
||||||
|
type: string
|
||||||
|
readOnly: true
|
||||||
|
minLength: 1
|
||||||
LDAPPropertyMapping:
|
LDAPPropertyMapping:
|
||||||
required:
|
required:
|
||||||
- name
|
- name
|
||||||
|
|
Reference in New Issue