Merge branch 'feature/hotfixes' of gitlab.com:mayan-edms/mayan-edms into feature/hotfixes

This commit is contained in:
Roberto Rosario
2017-02-02 00:44:11 -04:00
26 changed files with 596 additions and 54 deletions

View File

@@ -0,0 +1,16 @@
from __future__ import unicode_literals
from django.contrib.contenttypes.models import ContentType
from rest_framework import generics
from .serializers import ContentTypeSerializer
class APIContentTypeList(generics.ListAPIView):
"""
Returns a list of all the available content types.
"""
serializer_class = ContentTypeSerializer
queryset = ContentType.objects.order_by('app_label', 'model')

View File

@@ -15,6 +15,7 @@ from django.db.models.signals import post_save
from django.utils.translation import ugettext_lazy as _
from mayan.celery import app
from rest_api.classes import APIEndPoint
from .classes import Package
from .handlers import (
@@ -74,6 +75,8 @@ class CommonApp(MayanAppConfig):
def ready(self):
super(CommonApp, self).ready()
APIEndPoint(app=self, version_string='1')
Package(label='Django', license_text='''
Copyright (c) Django Software Foundation and individual contributors.
All rights reserved.

View File

@@ -0,0 +1,11 @@
from __future__ import unicode_literals
from django.contrib.contenttypes.models import ContentType
from rest_framework import serializers
class ContentTypeSerializer(serializers.ModelSerializer):
class Meta:
fields = ('app_label', 'id', 'model')
model = ContentType

View File

@@ -1,5 +1,5 @@
def skip_file_descriptor_check(func):
def func_wrapper(item):
item._skip_file_descriptor_test = True
return func(item)
return func_wrapper
def func_wrapper(item):
item._skip_file_descriptor_test = True
return func(item)
return func_wrapper

View File

@@ -66,7 +66,7 @@ class TempfileCheckMixin(object):
msg='Orphan temporary file. The number of temporary files and/or '
'directories at the start and at the end of the test are not the '
'same. Orphan entries: {}'.format(
','.join(final_temporary_items-self._temporary_items)
','.join(final_temporary_items - self._temporary_items)
)
)
super(TempfileCheckMixin, self).tearDown()

View File

@@ -0,0 +1,11 @@
from __future__ import unicode_literals
from django.core.urlresolvers import reverse
from rest_framework.test import APITestCase
class CommonAPITestCase(APITestCase):
def test_content_type_list_view(self):
response = self.client.get(reverse('rest_api:content-type-list'))
self.assertEqual(response.status_code, 200)

View File

@@ -6,7 +6,6 @@ from django.contrib.auth.models import Group
from django.core.urlresolvers import clear_url_caches, reverse
from django.http import HttpResponse
from django.template import Context, Template
from django.test import TestCase
from permissions import Permission
from permissions.models import Role

View File

@@ -5,6 +5,7 @@ from django.contrib.staticfiles.templatetags.staticfiles import static
from django.views.generic import RedirectView
from django.views.i18n import javascript_catalog
from api_views import APIContentTypeList
from .views import (
AboutView, CurrentUserDetailsView, CurrentUserEditView,
CurrentUserLocaleProfileDetailsView, CurrentUserLocaleProfileEditView,
@@ -66,3 +67,7 @@ urlpatterns += patterns(
name='set_language'
),
)
api_urls = [
url(r'^content_types/$', APIContentTypeList.as_view(), name='content-type-list'),
]

View File

@@ -29,6 +29,7 @@ from events.permissions import permission_events_view
from mayan.celery import app
from navigation import SourceColumn
from rest_api.classes import APIEndPoint
from rest_api.fields import DynamicSerializerField
from statistics.classes import StatisticNamespace, CharJSLine
from .handlers import create_default_document_type
@@ -94,6 +95,10 @@ class DocumentsApp(MayanAppConfig):
DocumentTypeFilename = self.get_model('DocumentTypeFilename')
DocumentVersion = self.get_model('DocumentVersion')
DynamicSerializerField.add_serializer(
klass=Document,
serializer_class='documents.serializers.DocumentSerializer'
)
MissingItem(
label=_('Create a document type'),
description=_(

View File

@@ -150,6 +150,7 @@ class DocumentSerializer(serializers.HyperlinkedModelSerializer):
'latest_version', 'url', 'uuid', 'versions',
)
model = Document
read_only_fields = ('document_type',)
class NewDocumentSerializer(serializers.ModelSerializer):

View File

@@ -0,0 +1,72 @@
from __future__ import absolute_import, unicode_literals
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import PermissionDenied
from django.http import Http404
from django.shortcuts import get_object_or_404
from actstream.models import Action, any_stream
from rest_framework import generics
from acls.models import AccessControlList
from permissions import Permission
from rest_api.permissions import MayanPermission
from .classes import Event
from .permissions import permission_events_view
from .serializers import EventSerializer, EventTypeSerializer
class APIObjectEventListView(generics.ListAPIView):
"""
Return a list of events for the specified object.
"""
serializer_class = EventSerializer
def get_object(self):
content_type = get_object_or_404(
ContentType, app_label=self.kwargs['app_label'],
model=self.kwargs['model']
)
try:
return content_type.get_object_for_this_type(
pk=self.kwargs['object_id']
)
except content_type.model_class().DoesNotExist:
raise Http404
def get_queryset(self):
object = self.get_object()
try:
Permission.check_permissions(
self.request.user, permissions=(permission_events_view,)
)
except PermissionDenied:
AccessControlList.objects.check_access(
permission_events_view, self.request.user, object
)
return any_stream(object)
class APIEventTypeListView(generics.ListAPIView):
"""
Returns a list of all the available event types.
"""
serializer_class = EventTypeSerializer
queryset = sorted(Event.all(), key=lambda event: event.name)
class APIEventListView(generics.ListAPIView):
"""
Returns a list of all the available events.
"""
mayan_view_permissions = {'GET': (permission_events_view,)}
permission_classes = (MayanPermission,)
queryset = Action.objects.all()
serializer_class = EventSerializer

View File

@@ -6,8 +6,8 @@ from actstream.models import Action
from common import MayanAppConfig, menu_tools
from common.classes import Package
from navigation import SourceColumn
from rest_api.classes import APIEndPoint
from .links import link_events_list
from .widgets import event_type_link
@@ -21,6 +21,8 @@ class EventsApp(MayanAppConfig):
def ready(self):
super(EventsApp, self).ready()
APIEndPoint(app=self, version_string='1')
Package(label='django-activity-stream', license_text='''
Copyright (c) 2010-2015, Justin Quick
All rights reserved.

View File

@@ -7,26 +7,48 @@ from actstream import action
class Event(object):
_labels = {}
_registry = {}
@classmethod
def all(cls):
return cls._registry.values()
@classmethod
def get(cls, name):
try:
return cls._registry[name]
except KeyError:
raise KeyError(
_('Unknown or obsolete event type: {0}'.format(name))
)
@classmethod
def get_label(cls, name):
try:
return cls._labels[name]
except KeyError:
return _('Unknown or obsolete event type: {0}'.format(name))
return cls.get(name=name).label
except KeyError as exception:
return unicode(exception)
def __init__(self, name, label):
self.name = name
self.label = label
self.event_type = None
self.__class__._labels[name] = label
self.__class__._registry[name] = self
def get_type(self):
if not self.event_type:
EventType = apps.get_model('events', 'EventType')
self.event_type, created = EventType.objects.get_or_create(
name=self.name
)
return self.event_type
def commit(self, actor=None, action_object=None, target=None):
model = apps.get_model('events', 'EventType')
if not self.event_type:
self.event_type, created = model.objects.get_or_create(
EventType = apps.get_model('events', 'EventType')
self.event_type, created = EventType.objects.get_or_create(
name=self.name
)

View File

@@ -13,9 +13,12 @@ class EventType(models.Model):
max_length=64, unique=True, verbose_name=_('Name')
)
def __str__(self):
return unicode(Event.get_label(self.name))
class Meta:
verbose_name = _('Event type')
verbose_name_plural = _('Event types')
def __str__(self):
return self.get_class().label
def get_class(self):
return Event.get_label(self.name)

View File

@@ -0,0 +1,45 @@
from __future__ import unicode_literals
from django.utils.six import string_types
from actstream.models import Action
from rest_framework import serializers
from common.serializers import ContentTypeSerializer
from rest_api.fields import DynamicSerializerField
from .classes import Event
from .models import EventType
class EventTypeSerializer(serializers.Serializer):
label = serializers.CharField()
name = serializers.CharField()
def to_representation(self, instance):
if isinstance(instance, Event):
return super(EventTypeSerializer, self).to_representation(
instance
)
elif isinstance(instance, EventType):
return super(EventTypeSerializer, self).to_representation(
instance.get_class()
)
elif isinstance(instance, string_types):
return super(EventTypeSerializer, self).to_representation(
Event.get(name=instance)
)
class EventSerializer(serializers.ModelSerializer):
actor = DynamicSerializerField(read_only=True)
target = DynamicSerializerField(read_only=True)
actor_content_type = ContentTypeSerializer(read_only=True)
target_content_type = ContentTypeSerializer(read_only=True)
verb = EventTypeSerializer(read_only=True)
class Meta:
exclude = (
'action_object_content_type', 'action_object_object_id'
)
model = Action

View File

@@ -0,0 +1,11 @@
from __future__ import unicode_literals
from django.core.urlresolvers import reverse
from rest_framework.test import APITestCase
class EventAPITestCase(APITestCase):
def test_evet_type_list_view(self):
response = self.client.get(reverse('rest_api:event-type-list'))
self.assertEqual(response.status_code, 200)

View File

@@ -2,7 +2,6 @@ from __future__ import absolute_import, unicode_literals
from django.contrib.contenttypes.models import ContentType
from acls.models import AccessControlList
from documents.tests.test_views import GenericDocumentViewTestCase
from user_management.tests import (
TEST_USER_USERNAME, TEST_USER_PASSWORD

View File

@@ -2,6 +2,9 @@ from __future__ import unicode_literals
from django.conf.urls import patterns, url
from .api_views import (
APIEventListView, APIEventTypeListView, APIObjectEventListView
)
from .views import EventListView, ObjectEventListView, VerbEventListView
urlpatterns = patterns(
@@ -16,3 +19,12 @@ urlpatterns = patterns(
name='events_by_verb'
),
)
api_urls = [
url(r'^types/$', APIEventTypeListView.as_view(), name='event-type-list'),
url(r'^events/$', APIEventListView.as_view(), name='event-list'),
url(
r'^object/(?P<app_label>[-\w]+)/(?P<model>[-\w]+)/(?P<object_id>\d+)/events/$',
APIObjectEventListView.as_view(), name='object-event-list'
),
]

View File

@@ -5,22 +5,35 @@ from rest_framework import generics
from rest_api.filters import MayanObjectPermissionsFilter
from rest_api.permissions import MayanPermission
from .classes import Permission
from .models import Role
from .permissions import (
permission_role_create, permission_role_delete, permission_role_edit,
permission_role_view
)
from .serializers import RoleSerializer
from .serializers import (
PermissionSerializer, RoleSerializer, WritableRoleSerializer
)
class APIPermissionList(generics.ListAPIView):
serializer_class = PermissionSerializer
queryset = Permission.all()
def get(self, *args, **kwargs):
"""
Returns a list of all the available permissions.
"""
return super(APIPermissionList, self).get(*args, **kwargs)
class APIRoleListView(generics.ListCreateAPIView):
serializer_class = RoleSerializer
queryset = Role.objects.all()
permission_classes = (MayanPermission,)
filter_backends = (MayanObjectPermissionsFilter,)
mayan_object_permissions = {'GET': (permission_role_view,)}
mayan_view_permissions = {'POST': (permission_role_create,)}
permission_classes = (MayanPermission,)
queryset = Role.objects.all()
def get(self, *args, **kwargs):
"""
@@ -29,6 +42,12 @@ class APIRoleListView(generics.ListCreateAPIView):
return super(APIRoleListView, self).get(*args, **kwargs)
def get_serializer_class(self):
if self.request.method == 'GET':
return RoleSerializer
elif self.request.method == 'POST':
return WritableRoleSerializer
def post(self, *args, **kwargs):
"""
Create a new role.
@@ -38,16 +57,14 @@ class APIRoleListView(generics.ListCreateAPIView):
class APIRoleView(generics.RetrieveUpdateDestroyAPIView):
serializer_class = RoleSerializer
queryset = Role.objects.all()
permission_classes = (MayanPermission,)
mayan_object_permissions = {
'GET': (permission_role_view,),
'PUT': (permission_role_edit,),
'PATCH': (permission_role_edit,),
'DELETE': (permission_role_delete,)
}
permission_classes = (MayanPermission,)
queryset = Role.objects.all()
def delete(self, *args, **kwargs):
"""
@@ -63,6 +80,12 @@ class APIRoleView(generics.RetrieveUpdateDestroyAPIView):
return super(APIRoleView, self).get(*args, **kwargs)
def get_serializer_class(self):
if self.request.method == 'GET':
return RoleSerializer
elif self.request.method in ('PATCH', 'PUT'):
return WritableRoleSerializer
def patch(self, *args, **kwargs):
"""
Edit the selected role.

View File

@@ -45,12 +45,15 @@ class PermissionNamespace(object):
class Permission(object):
_stored_permissions_cache = {}
_permissions = {}
_stored_permissions_cache = {}
@classmethod
def invalidate_cache(cls):
cls._stored_permissions_cache = {}
def all(cls):
# Return sorted permisions by namespace.name
return sorted(
cls._permissions.values(), key=lambda x: x.namespace.name
)
@classmethod
def check_permissions(cls, requester, permissions):
@@ -62,6 +65,14 @@ class Permission(object):
raise PermissionDenied(_('Insufficient permissions.'))
@classmethod
def get(cls, get_dict, proxy_only=False):
if 'pk' in get_dict:
if proxy_only:
return cls._permissions[get_dict['pk']]
else:
return cls._permissions[get_dict['pk']].stored_permission
@classmethod
def get_for_holder(cls, holder):
StoredPermission = apps.get_model(
@@ -71,19 +82,8 @@ class Permission(object):
return StoredPermission.get_for_holder(holder)
@classmethod
def all(cls):
# Return sorted permisions by namespace.name
return sorted(
cls._permissions.values(), key=lambda x: x.namespace.name
)
@classmethod
def get(cls, get_dict, proxy_only=False):
if 'pk' in get_dict:
if proxy_only:
return cls._permissions[get_dict['pk']]
else:
return cls._permissions[get_dict['pk']].stored_permission
def invalidate_cache(cls):
cls._stored_permissions_cache = {}
def __init__(self, namespace, name, label):
self.namespace = namespace
@@ -92,16 +92,15 @@ class Permission(object):
self.pk = self.uuid
self.__class__._permissions[self.uuid] = self
def __repr__(self):
return self.pk
def __unicode__(self):
return unicode(self.label)
def __str__(self):
return str(self.__unicode__())
@property
def uuid(self):
return '%s.%s' % (self.namespace.name, self.name)
@property
def stored_permission(self):
StoredPermission = apps.get_model(
@@ -120,3 +119,7 @@ class Permission(object):
self.uuid
] = stored_permission
return stored_permission
@property
def uuid(self):
return '%s.%s' % (self.namespace.name, self.name)

View File

@@ -8,6 +8,7 @@ from django.db import models
from django.utils.encoding import python_2_unicode_compatible
from django.utils.translation import ugettext_lazy as _
from .classes import Permission
from .managers import RoleManager, StoredPermissionManager
logger = logging.getLogger(__name__)
@@ -21,8 +22,6 @@ class StoredPermission(models.Model):
objects = StoredPermissionManager()
def __init__(self, *args, **kwargs):
from .classes import Permission
super(StoredPermission, self).__init__(*args, **kwargs)
try:
self.volatile_permission = Permission.get(

View File

@@ -1,11 +1,110 @@
from __future__ import unicode_literals
from django.contrib.auth.models import Group
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from .models import Role
from user_management.serializers import GroupSerializer
from .classes import Permission
from .models import Role, StoredPermission
class RoleSerializer(serializers.ModelSerializer):
class PermissionSerializer(serializers.Serializer):
namespace = serializers.CharField()
pk = serializers.CharField()
label = serializers.CharField()
def to_representation(self, instance):
if isinstance(instance, StoredPermission):
return super(PermissionSerializer, self).to_representation(
instance.volatile_permission
)
else:
return super(PermissionSerializer, self).to_representation(
instance
)
class RoleSerializer(serializers.HyperlinkedModelSerializer):
groups = GroupSerializer(many=True)
class Meta:
fields = ('id', 'label')
fields = ('groups', 'id', 'label')
model = Role
class WritableRoleSerializer(serializers.HyperlinkedModelSerializer):
groups_pk_list = serializers.CharField(
help_text=_(
'Comma separated list of groups primary keys to add to, or replace'
' in this role.'
), required=False
)
permissions_pk_list = serializers.CharField(
help_text=_(
'Comma separated list of permission primary keys to grant to this '
'role.'
), required=False
)
class Meta:
fields = ('groups_pk_list', 'id', 'label', 'permissions_pk_list')
model = Role
def create(self, validated_data):
result = validated_data.copy()
self.groups_pk_list = validated_data.pop('groups_pk_list', '')
self.permissions_pk_list = validated_data.pop(
'permissions_pk_list', ''
)
instance = super(WritableRoleSerializer, self).create(validated_data)
if self.groups_pk_list:
self._add_groups(instance=instance)
if self.permissions_pk_list:
self._add_permissions(instance=instance)
return result
def _add_groups(self, instance):
instance.groups.add(
*Group.objects.filter(pk__in=self.groups_pk_list.split(','))
)
def _add_permissions(self, instance):
for pk in self.permissions_pk_list.split(','):
try:
stored_permission = Permission.get(get_dict={'pk': pk})
instance.permissions.add(stored_permission)
instance.save()
except KeyError:
raise ValidationError(_('No such permission: %s') % pk)
def update(self, instance, validated_data):
result = validated_data.copy()
self.groups_pk_list = validated_data.pop('groups_pk_list', '')
self.permissions_pk_list = validated_data.pop(
'permissions_pk_list', ''
)
result = super(WritableRoleSerializer, self).update(
instance, validated_data
)
if self.groups_pk_list:
instance.groups.clear()
self._add_groups(instance=instance)
if self.permissions_pk_list:
instance.permissions.clear()
self._add_permissions(instance=instance)
return result

View File

@@ -0,0 +1,165 @@
from __future__ import unicode_literals
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group
from django.core.urlresolvers import reverse
from rest_framework.test import APITestCase
from user_management.tests.literals import (
TEST_ADMIN_EMAIL, TEST_ADMIN_PASSWORD, TEST_ADMIN_USERNAME, TEST_GROUP
)
from ..classes import Permission
from ..models import Role
from ..permissions import permission_role_view
from .literals import TEST_ROLE_LABEL, TEST_ROLE_LABEL_EDITED
class PermissionAPITestCase(APITestCase):
def setUp(self):
super(PermissionAPITestCase, self).setUp()
self.admin_user = get_user_model().objects.create_superuser(
username=TEST_ADMIN_USERNAME, email=TEST_ADMIN_EMAIL,
password=TEST_ADMIN_PASSWORD
)
self.client.login(
username=TEST_ADMIN_USERNAME, password=TEST_ADMIN_PASSWORD
)
Permission.invalidate_cache()
def test_permissions_list_view(self):
response = self.client.get(reverse('rest_api:permission-list'))
self.assertEqual(response.status_code, 200)
def _create_role(self):
self.role = Role.objects.create(label=TEST_ROLE_LABEL)
def test_roles_list_view(self):
self._create_role()
response = self.client.get(reverse('rest_api:role-list'))
self.assertEqual(response.status_code, 200)
self.assertEqual(response.data['results'][0]['label'], TEST_ROLE_LABEL)
def _role_create_request(self, extra_data=None):
data = {
'label': TEST_ROLE_LABEL
}
if extra_data:
data.update(extra_data)
return self.client.post(
reverse('rest_api:role-list'), data=data
)
def test_role_create_view(self):
response = self._role_create_request()
self.assertEqual(response.status_code, 201)
self.assertEqual(Role.objects.count(), 1)
self.assertEqual(Role.objects.first().label, TEST_ROLE_LABEL)
def _create_group(self):
self.group = Group.objects.create(name=TEST_GROUP)
def test_role_create_complex_view(self):
self._create_group()
response = self._role_create_request(
extra_data={
'groups_pk_list': '{}'.format(self.group.pk),
'permissions_pk_list': '{}'.format(permission_role_view.pk)
}
)
self.assertEqual(response.status_code, 201)
self.assertEqual(Role.objects.count(), 1)
self.assertEqual(Role.objects.first().label, TEST_ROLE_LABEL)
self.assertQuerysetEqual(
Role.objects.first().groups.all(), (repr(self.group),)
)
self.assertQuerysetEqual(
Role.objects.first().permissions.all(),
(repr(permission_role_view.stored_permission),)
)
def _role_edit_request(self, extra_data=None, request_type='patch'):
data = {
'label': TEST_ROLE_LABEL_EDITED
}
if extra_data:
data.update(extra_data)
return getattr(self.client, request_type)(
reverse('rest_api:role-detail', args=(self.role.pk,)), data=data
)
def test_role_edit_via_patch(self):
self._create_role()
response = self._role_edit_request()
self.assertEqual(response.status_code, 200)
self.assertEqual(Role.objects.first().label, TEST_ROLE_LABEL_EDITED)
def test_role_edit_complex_via_patch(self):
Role.objects.all().delete()
Group.objects.all().delete()
self._create_role()
self._create_group()
response = self._role_edit_request(
extra_data={
'groups_pk_list': '{}'.format(self.group.pk),
'permissions_pk_list': '{}'.format(permission_role_view.pk)
}
)
self.assertEqual(response.status_code, 200)
self.assertEqual(Role.objects.first().label, TEST_ROLE_LABEL_EDITED)
self.assertQuerysetEqual(
Role.objects.first().groups.all(), (repr(self.group),)
)
self.assertQuerysetEqual(
Role.objects.first().permissions.all(),
(repr(permission_role_view.stored_permission),)
)
def test_role_edit_via_put(self):
self._create_role()
response = self._role_edit_request(request_type='put')
self.assertEqual(response.status_code, 200)
self.assertEqual(Role.objects.first().label, TEST_ROLE_LABEL_EDITED)
def test_role_edit_complex_via_put(self):
Role.objects.all().delete()
Group.objects.all().delete()
self._create_role()
self._create_group()
response = self._role_edit_request(
extra_data={
'groups_pk_list': '{}'.format(self.group.pk),
'permissions_pk_list': '{}'.format(permission_role_view.pk)
}, request_type='put'
)
self.assertEqual(response.status_code, 200)
self.assertEqual(Role.objects.first().label, TEST_ROLE_LABEL_EDITED)
self.assertQuerysetEqual(
Role.objects.first().groups.all(), (repr(self.group),)
)
self.assertQuerysetEqual(
Role.objects.first().permissions.all(),
(repr(permission_role_view.stored_permission),)
)
def test_role_delete_view(self):
self._create_role()
response = self.client.delete(
reverse('rest_api:role-detail', args=(self.role.pk,))
)
self.assertEqual(response.status_code, 204)
self.assertEqual(Role.objects.count(), 0)

View File

@@ -2,7 +2,7 @@ from __future__ import unicode_literals
from django.conf.urls import patterns, url
from .api_views import APIRoleListView, APIRoleView
from .api_views import APIPermissionList, APIRoleListView, APIRoleView
from .views import (
RoleCreateView, RoleDeleteView, RoleEditView, RoleListView,
SetupRoleMembersView, SetupRolePermissionsView
@@ -29,6 +29,7 @@ urlpatterns = patterns(
api_urls = patterns(
'',
url(r'^permissions/$', APIPermissionList.as_view(), name='permission-list'),
url(r'^roles/$', APIRoleListView.as_view(), name='role-list'),
url(r'^roles/(?P<pk>[0-9]+)/$', APIRoleView.as_view(), name='role-detail'),
)

View File

@@ -0,0 +1,30 @@
from __future__ import unicode_literals
from django.utils.module_loading import import_string
from django.utils.six import string_types
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers
class DynamicSerializerField(serializers.ReadOnlyField):
serializers = {}
@classmethod
def add_serializer(cls, klass, serializer_class):
if isinstance(klass, string_types):
klass = import_string(klass)
if isinstance(serializer_class, string_types):
serializer_class = import_string(serializer_class)
cls.serializers[klass] = serializer_class
def to_representation(self, value):
for klass, serializer_class in self.serializers.items():
if isinstance(value, klass):
return serializer_class(
context={'request': self.context['request']}
).to_representation(instance=value)
return _('Unable to find serializer class for: %s') % value

View File

@@ -12,6 +12,7 @@ from common.widgets import two_state_template
from metadata import MetadataLookup
from navigation import SourceColumn
from rest_api.classes import APIEndPoint
from rest_api.fields import DynamicSerializerField
from .links import (
link_group_add, link_group_delete, link_group_edit, link_group_list,
@@ -42,6 +43,10 @@ class UserManagementApp(MayanAppConfig):
User = get_user_model()
APIEndPoint(app=self, version_string='1')
DynamicSerializerField.add_serializer(
klass=get_user_model(),
serializer_class='user_management.serializers.UserSerializer'
)
MetadataLookup(
description=_('All the groups.'), name='groups',