2
0
mirror of https://github.com/inventree/InvenTree.git synced 2025-06-17 20:45:44 +00:00

Added owner model to admin page and added test cases

This commit is contained in:
eeintech
2021-01-13 11:38:37 -05:00
parent 0a0a47a5e4
commit 28fb1b5fab
11 changed files with 1125 additions and 929 deletions

View File

@ -11,7 +11,7 @@ from django.contrib.auth.models import Group
from django.contrib.auth.admin import UserAdmin
from django.utils.safestring import mark_safe
from users.models import RuleSet
from users.models import RuleSet, Owner
User = get_user_model()
@ -206,8 +206,17 @@ class InvenTreeUserAdmin(UserAdmin):
)
class OwnerAdmin(admin.ModelAdmin):
"""
Custom admin interface for the Owner model
"""
pass
admin.site.unregister(Group)
admin.site.register(Group, RoleGroupAdmin)
admin.site.unregister(User)
admin.site.register(User, InvenTreeUserAdmin)
admin.site.register(Owner, OwnerAdmin)

View File

@ -39,6 +39,14 @@ class UsersConfig(AppConfig):
def update_owners(self):
from users.models import create_owner
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group
from users.models import Owner
create_owner(full_update=True)
# Create group owners
for group in Group.objects.all():
Owner.create(group)
# Create user owners
for user in get_user_model().objects.all():
Owner.create(user)

View File

@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-
from django.contrib.auth.models import User, Group, Permission
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group, Permission
from django.contrib.contenttypes.fields import GenericForeignKey
from django.contrib.contenttypes.models import ContentType
from django.db.models import UniqueConstraint, Q
@ -9,7 +10,7 @@ from django.db import models
from django.utils.translation import gettext_lazy as _
from django.dispatch import receiver
from django.db.models.signals import post_save
from django.db.models.signals import post_save, post_delete
class RuleSet(models.Model):
@ -393,32 +394,42 @@ def check_user_role(user, role, permission):
class Owner(models.Model):
"""
An owner is either a group or user.
Owner can be associated to any InvenTree model (part, stock, etc.)
The Owner class is a proxy for a Group or User instance.
Owner can be associated to any InvenTree model (part, stock, build, etc.)
owner_type: Model type (Group or User)
owner_id: Group or User instance primary key
owner: Returns the Group or User instance combining the owner_type and owner_id fields
"""
class Meta:
# Ensure all owners are unique
constraints = [
UniqueConstraint(fields=['owner_type', 'owner_id'],
name='unique_owner')
]
owner_type = models.ForeignKey(ContentType, on_delete=models.CASCADE, null=True, blank=True)
owner_id = models.PositiveIntegerField(null=True, blank=True)
owner = GenericForeignKey('owner_type', 'owner_id')
def __str__(self):
""" Defines the owner string representation """
return f'{self.owner} ({self.owner_type.name})'
@classmethod
def create(cls, owner):
def create(cls, obj):
""" Check if owner exist then create new owner entry """
existing_owner = cls.get_owner(owner)
# Check for existing owner
existing_owner = cls.get_owner(obj)
if not existing_owner:
# Create new owner
try:
return cls.objects.create(owner=owner)
return cls.objects.create(owner=obj)
except IntegrityError:
return None
@ -426,16 +437,18 @@ class Owner(models.Model):
@classmethod
def get_owner(cls, user_or_group):
""" Get owner instance for a group or user """
user_model = get_user_model()
owner = None
content_type_id = 0
content_type_id_list = [ContentType.objects.get_for_model(Group).id,
ContentType.objects.get_for_model(User).id]
ContentType.objects.get_for_model(user_model).id]
# If instance type is obvious: set content type
if type(user_or_group) is Group:
content_type_id = content_type_id_list[0]
elif type(user_or_group) is User:
elif type(user_or_group) is get_user_model():
content_type_id = content_type_id_list[1]
if content_type_id:
@ -462,8 +475,8 @@ class Owner(models.Model):
# Check whether user_or_group is a User instance
try:
user = User.objects.get(pk=user_or_group.id)
except User.DoesNotExist:
user = user_model.objects.get(pk=user_or_group.id)
except user_model.DoesNotExist:
user = None
if user:
@ -478,45 +491,50 @@ class Owner(models.Model):
return owner
def get_related_owners(self, include_group=False):
"""
Get all owners "related" to an owner.
This method is useful to retrieve all "user-type" owners linked to a "group-type" owner
"""
owner_users = None
user_model = get_user_model()
related_owners = None
if type(self.owner) is Group:
users = User.objects.filter(groups__name=self.owner.name)
users = user_model.objects.filter(groups__name=self.owner.name)
if include_group:
query = Q(owner_id__in=users, owner_type=ContentType.objects.get_for_model(User).id) | \
# Include "group-type" owner in the query
query = Q(owner_id__in=users, owner_type=ContentType.objects.get_for_model(user_model).id) | \
Q(owner_id=self.owner.id, owner_type=ContentType.objects.get_for_model(Group).id)
else:
query = Q(owner_id__in=users, owner_type=ContentType.objects.get_for_model(User).id)
query = Q(owner_id__in=users, owner_type=ContentType.objects.get_for_model(user_model).id)
owner_users = Owner.objects.filter(query)
related_owners = Owner.objects.filter(query)
elif type(self.owner) is User:
owner_users = [self]
elif type(self.owner) is user_model:
related_owners = [self]
return owner_users
return related_owners
def create_owner(full_update=False, owner=None):
""" Create all owners """
if full_update:
# Create group owners
for group in Group.objects.all():
Owner.create(owner=group)
@receiver(post_save, sender=Group, dispatch_uid='create_owner')
@receiver(post_save, sender=get_user_model(), dispatch_uid='create_owner')
def create_owner(sender, instance, **kwargs):
"""
Callback function to create a new owner instance
after either a new group or user instance is saved.
"""
# Create user owners
for user in User.objects.all():
Owner.create(owner=user)
else:
if owner:
Owner.create(owner=owner)
Owner.create(obj=instance)
@receiver(post_save, sender=Group, dispatch_uid='create_missing_owner')
@receiver(post_save, sender=User, dispatch_uid='create_missing_owner')
def create_missing_owner(sender, instance, created, **kwargs):
""" Create owner instance after either user or group object is saved. """
@receiver(post_delete, sender=Group, dispatch_uid='delete_owner')
@receiver(post_delete, sender=get_user_model(), dispatch_uid='delete_owner')
def delete_owner(sender, instance, **kwargs):
"""
Callback function to delete an owner instance
after either a new group or user instance is deleted.
"""
create_owner(owner=instance)
owner = Owner.get_owner(instance)
owner.delete()

View File

@ -3,9 +3,10 @@ from __future__ import unicode_literals
from django.test import TestCase
from django.apps import apps
from django.contrib.auth import get_user_model
from django.contrib.auth.models import Group
from users.models import RuleSet
from users.models import RuleSet, Owner
class RuleSetModelTest(TestCase):
@ -157,3 +158,48 @@ class RuleSetModelTest(TestCase):
# There should now not be any permissions assigned to this group
self.assertEqual(group.permissions.count(), 0)
class OwnerModelTest(TestCase):
"""
Some simplistic tests to ensure the Owner model is setup correctly.
"""
def setUp(self):
""" Add users and groups """
# Create a new user
self.user = get_user_model().objects.create_user(
username='john',
email='john@email.com',
password='custom123',
)
# Put the user into a new group
self.group = Group.objects.create(name='new_group')
self.user.groups.add(self.group)
def test_owner(self):
# Check that owner was created for user
user_as_owner = Owner.get_owner(self.user)
self.assertEqual(type(user_as_owner), Owner)
# Check that owner was created for group
group_as_owner = Owner.get_owner(self.group)
self.assertEqual(type(group_as_owner), Owner)
# Get related owners (user + group)
related_owners = group_as_owner.get_related_owners(include_group=True)
self.assertTrue(user_as_owner in related_owners)
self.assertTrue(group_as_owner in related_owners)
# Delete user and verify owner was deleted too
self.user.delete()
user_as_owner = Owner.get_owner(self.user)
self.assertEqual(user_as_owner, None)
# Delete group and verify owner was deleted too
self.group.delete()
group_as_owner = Owner.get_owner(self.group)
self.assertEqual(group_as_owner, None)