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"""
|
||||
from json import dumps
|
||||
|
||||
from django.urls import reverse
|
||||
from drf_yasg.utils import swagger_auto_schema
|
||||
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 CharField
|
||||
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.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.lib.templatetags.authentik_utils import verbose_name
|
||||
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):
|
||||
|
@ -76,3 +93,37 @@ class PropertyMappingViewSet(
|
|||
}
|
||||
)
|
||||
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
|
||||
type: string
|
||||
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/:
|
||||
get:
|
||||
operationId: propertymappings_ldap_list
|
||||
|
@ -16843,6 +16880,14 @@ definitions:
|
|||
title: Verbose name plural
|
||||
type: string
|
||||
readOnly: true
|
||||
PropertyMappingTestResult:
|
||||
type: object
|
||||
properties:
|
||||
result:
|
||||
title: Result
|
||||
type: string
|
||||
readOnly: true
|
||||
minLength: 1
|
||||
LDAPPropertyMapping:
|
||||
required:
|
||||
- name
|
||||
|
|
Reference in New Issue