Restore users & groups fields on ObjectPermission serializer

This commit is contained in:
Jeremy Stretch 2024-03-29 14:43:19 -04:00
parent a673015f86
commit 37a003afea
4 changed files with 44 additions and 19 deletions

View File

@ -81,8 +81,9 @@ class ValidatedModelSerializer(BaseModelSerializer):
attrs.pop('custom_fields', None) attrs.pop('custom_fields', None)
# Skip ManyToManyFields # Skip ManyToManyFields
opts = self.Meta.model._meta
m2m_values = {} m2m_values = {}
for field in self.Meta.model._meta.local_many_to_many: for field in [*opts.local_many_to_many, *opts.related_objects]:
if field.name in attrs: if field.name in attrs:
m2m_values[field.name] = attrs.pop(field.name) m2m_values[field.name] = attrs.pop(field.name)

View File

@ -1,9 +1,10 @@
from rest_framework import serializers from rest_framework import serializers
from core.models import ObjectType from core.models import ObjectType
from netbox.api.fields import ContentTypeField from netbox.api.fields import ContentTypeField, SerializedPKRelatedField
from netbox.api.serializers import ValidatedModelSerializer from netbox.api.serializers import ValidatedModelSerializer
from users.models import ObjectPermission from users.api.nested_serializers import NestedGroupSerializer, NestedUserSerializer
from users.models import Group, ObjectPermission, User
__all__ = ( __all__ = (
'ObjectPermissionSerializer', 'ObjectPermissionSerializer',
@ -16,11 +17,26 @@ class ObjectPermissionSerializer(ValidatedModelSerializer):
queryset=ObjectType.objects.all(), queryset=ObjectType.objects.all(),
many=True many=True
) )
groups = SerializedPKRelatedField(
queryset=Group.objects.all(),
serializer=NestedGroupSerializer,
nested=True,
required=False,
many=True
)
users = SerializedPKRelatedField(
queryset=User.objects.all(),
serializer=NestedUserSerializer,
nested=True,
required=False,
many=True
)
class Meta: class Meta:
model = ObjectPermission model = ObjectPermission
fields = ( fields = (
'id', 'url', 'display', 'name', 'description', 'enabled', 'object_types', 'actions', 'constraints', 'id', 'url', 'display', 'name', 'description', 'enabled', 'object_types', 'actions', 'constraints',
'groups', 'users',
) )
brief_fields = ( brief_fields = (
'id', 'url', 'display', 'name', 'description', 'enabled', 'object_types', 'actions', 'id', 'url', 'display', 'name', 'description', 'enabled', 'object_types', 'actions',

View File

@ -41,25 +41,25 @@ class UserTest(APIViewTestCases.APIViewTestCase):
permissions[2].object_types.add(ObjectType.objects.get_by_natural_key('dcim', 'rack')) permissions[2].object_types.add(ObjectType.objects.get_by_natural_key('dcim', 'rack'))
users = ( users = (
User(username='User_1', password='password1'), User(username='User1', password='password1'),
User(username='User_2', password='password2'), User(username='User2', password='password2'),
User(username='User_3', password='password3'), User(username='User3', password='password3'),
) )
User.objects.bulk_create(users) User.objects.bulk_create(users)
cls.create_data = [ cls.create_data = [
{ {
'username': 'User_4', 'username': 'User4',
'password': 'password4', 'password': 'password4',
'permissions': [permissions[0].pk], 'permissions': [permissions[0].pk],
}, },
{ {
'username': 'User_5', 'username': 'User5',
'password': 'password5', 'password': 'password5',
'permissions': [permissions[1].pk], 'permissions': [permissions[1].pk],
}, },
{ {
'username': 'User_6', 'username': 'User6',
'password': 'password6', 'password': 'password6',
'permissions': [permissions[2].pk], 'permissions': [permissions[2].pk],
}, },
@ -79,7 +79,7 @@ class UserTest(APIViewTestCases.APIViewTestCase):
obj_perm.object_types.add(ObjectType.objects.get_for_model(self.model)) obj_perm.object_types.add(ObjectType.objects.get_for_model(self.model))
user_credentials = { user_credentials = {
'username': 'user1', 'username': 'newuser',
'password': 'abc123', 'password': 'abc123',
} }
user = User.objects.create_user(**user_credentials) user = User.objects.create_user(**user_credentials)
@ -169,9 +169,9 @@ class TokenTest(
@classmethod @classmethod
def setUpTestData(cls): def setUpTestData(cls):
users = ( users = (
create_test_user('User 1'), create_test_user('User1'),
create_test_user('User 2'), create_test_user('User2'),
create_test_user('User 3'), create_test_user('User3'),
) )
tokens = ( tokens = (
@ -280,9 +280,9 @@ class ObjectPermissionTest(
Group.objects.bulk_create(groups) Group.objects.bulk_create(groups)
users = ( users = (
User(username='User 1', is_active=True), User(username='User1', is_active=True),
User(username='User 2', is_active=True), User(username='User2', is_active=True),
User(username='User 3', is_active=True), User(username='User3', is_active=True),
) )
User.objects.bulk_create(users) User.objects.bulk_create(users)
@ -303,18 +303,24 @@ class ObjectPermissionTest(
{ {
'name': 'Permission 4', 'name': 'Permission 4',
'object_types': ['dcim.site'], 'object_types': ['dcim.site'],
'groups': [groups[0].pk],
'users': [users[0].pk],
'actions': ['view', 'add', 'change', 'delete'], 'actions': ['view', 'add', 'change', 'delete'],
'constraints': {'name': 'TEST4'}, 'constraints': {'name': 'TEST4'},
}, },
{ {
'name': 'Permission 5', 'name': 'Permission 5',
'object_types': ['dcim.site'], 'object_types': ['dcim.site'],
'groups': [groups[1].pk],
'users': [users[1].pk],
'actions': ['view', 'add', 'change', 'delete'], 'actions': ['view', 'add', 'change', 'delete'],
'constraints': {'name': 'TEST5'}, 'constraints': {'name': 'TEST5'},
}, },
{ {
'name': 'Permission 6', 'name': 'Permission 6',
'object_types': ['dcim.site'], 'object_types': ['dcim.site'],
'groups': [groups[2].pk],
'users': [users[2].pk],
'actions': ['view', 'add', 'change', 'delete'], 'actions': ['view', 'add', 'change', 'delete'],
'constraints': {'name': 'TEST6'}, 'constraints': {'name': 'TEST6'},
}, },

View File

@ -4,7 +4,7 @@ from django.contrib.auth import get_user_model
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.contrib.postgres.fields import ArrayField from django.contrib.postgres.fields import ArrayField
from django.core.exceptions import FieldDoesNotExist from django.core.exceptions import FieldDoesNotExist
from django.db.models import ManyToManyField, JSONField from django.db.models import ManyToManyField, ManyToManyRel, JSONField
from django.forms.models import model_to_dict from django.forms.models import model_to_dict
from django.test import Client, TestCase as _TestCase from django.test import Client, TestCase as _TestCase
from netaddr import IPNetwork from netaddr import IPNetwork
@ -111,8 +111,10 @@ class ModelTestCase(TestCase):
continue continue
# Handle ManyToManyFields # Handle ManyToManyFields
if value and type(field) in (ManyToManyField, TaggableManager): if value and type(field) in (ManyToManyField, ManyToManyRel, TaggableManager):
# Resolve reverse M2M relationships
if isinstance(field, ManyToManyRel):
value = getattr(instance, field.related_name).all()
if field.related_model in (ContentType, ObjectType) and api: if field.related_model in (ContentType, ObjectType) and api:
model_dict[key] = sorted([object_type_identifier(ot) for ot in value]) model_dict[key] = sorted([object_type_identifier(ot) for ot in value])
else: else: