Add hook to update group permission roles

(doesn't do anything yet)
This commit is contained in:
Oliver Walters 2020-10-03 23:45:24 +10:00
parent bedda66949
commit 16f1b4c784
4 changed files with 225 additions and 1 deletions

View File

@ -11,6 +11,20 @@ from django.contrib.auth.models import Group
User = get_user_model()
from users.models import RuleSet
class RuleSetInline(admin.TabularInline):
model = RuleSet
can_delete = False
verbose_name = 'Ruleset'
verbose_plural_name = 'Rulesets'
fields = ['name'] + [option for option in RuleSet.RULE_OPTIONS]
readonly_fields = ['name']
max_num = len(RuleSet.RULESET_CHOICES)
min_num = 1
extra = 0
class InvenTreeGroupAdminForm(forms.ModelForm):
@ -18,6 +32,7 @@ class InvenTreeGroupAdminForm(forms.ModelForm):
model = Group
exclude = []
fields = [
'name',
'users',
'permissions',
]
@ -35,6 +50,7 @@ class InvenTreeGroupAdminForm(forms.ModelForm):
required=False,
widget=FilteredSelectMultiple('users', False),
label=_('Users'),
help_text=_('Select which users are assigned to this group')
)
def save_m2m(self):
@ -59,8 +75,31 @@ class RoleGroupAdmin(admin.ModelAdmin):
form = InvenTreeGroupAdminForm
inlines = [
RuleSetInline,
]
def get_formsets_with_inlines(self, request, obj=None):
for inline in self.get_inline_instances(request, obj):
# Hide RuleSetInline in the 'Add role' view
if not isinstance(inline, RuleSetInline) or obj is not None:
yield inline.get_formset(request, obj), inline
filter_horizontal = ['permissions']
# Save inlines before model
# https://stackoverflow.com/a/14860703/12794913
def save_model(self, request, obj, form, change):
if obj is not None:
# Save model immediately only if in 'Add role' view
super().save_model(request, obj, form, change)
else:
pass # don't actually save the parent instance
def save_formset(self, request, form, formset, change):
formset.save() # this will save the children
form.instance.save() # form.instance is the parent
admin.site.unregister(Group)
admin.site.register(Group, RoleGroupAdmin)

View File

@ -1,8 +1,33 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db.utils import OperationalError, ProgrammingError
from django.apps import AppConfig
class UsersConfig(AppConfig):
name = 'users'
def ready(self):
try:
self.assign_permissions()
except (OperationalError, ProgrammingError):
pass
def assign_permissions(self):
from django.contrib.auth.models import Group
from users.models import RuleSet, update_group_roles
# First, delete any rule_set objects which have become outdated!
for rule in RuleSet.objects.all():
if rule.name not in RuleSet.RULESET_NAMES:
print("need to delete:", rule.name)
rule.delete()
# Update group permission assignments for all groups
for group in Group.objects.all():
update_group_roles(group)

View File

@ -1 +1,160 @@
# -*- coding: utf-8 -*-
from django.contrib.auth.models import Group
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
class RuleSet(models.Model):
"""
A RuleSet is somewhat like a superset of the django permission class,
in that in encapsulates a bunch of permissions.
There are *many* apps models used within InvenTree,
so it makes sense to group them into "roles".
These roles translate (roughly) to the menu options available.
Each role controls permissions for a number of database tables,
which are then handled using the normal django permissions approach.
"""
RULESET_CHOICES = [
('general', _('General')),
('admin', _('Admin')),
('part', _('Parts')),
('stock', _('Stock')),
('build', _('Build Orders')),
('supplier', _('Suppliers')),
('purchase_order', _('Purchase Orders')),
('customer', _('Customers')),
('sales_order', _('Sales Orders')),
]
RULESET_NAMES = [
choice[0] for choice in RULESET_CHOICES
]
RULESET_MODELS = {
'general': [
'part.partstar',
],
'admin': [
'auth.group',
'auth.user',
'auth.permission',
'authtoken.token',
],
'part': [
'part.part',
'part.bomitem',
'part.partcategory',
'part.partattachment',
'part.partsellpricebreak',
'part.parttesttemplate',
'part.partparametertemplate',
'part.partparameter',
],
'stock': [
'stock.stockitem',
'stock.stocklocation',
'stock.stockitemattachment',
'stock.stockitemtracking',
'stock.stockitemtestresult',
],
'build': [
'part.part',
'part.partcategory',
'part.bomitem',
'build.build',
'build.builditem',
'stock.stockitem',
'stock.stocklocation',
]
}
RULE_OPTIONS = [
'can_view',
'can_add',
'can_change',
'can_delete',
]
class Meta:
unique_together = (
('name', 'group'),
)
name = models.CharField(
max_length=50,
choices=RULESET_CHOICES,
blank=False,
help_text=_('Permission set')
)
group = models.ForeignKey(
Group,
related_name='rule_sets',
blank=False, null=False,
on_delete=models.CASCADE,
help_text=_('Group'),
)
can_view = models.BooleanField(verbose_name=_('View'), default=True, help_text=_('Permission to view items'))
can_add = models.BooleanField(verbose_name=_('Create'), default=False, help_text=_('Permission to add items'))
can_change = models.BooleanField(verbose_name=_('Update'), default=False, help_text=_('Permissions to edit items'))
can_delete = models.BooleanField(verbose_name=_('Delete'), default=False, help_text=_('Permission to delete items'))
def __str__(self):
return self.name
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
def get_models(self):
models = {
''
}
def update_group_roles(group):
"""
Update group roles:
a) Ensure default roles are assigned to each group.
b) Ensure group permissions are correctly updated and assigned
"""
# List of permissions which must be added to the group
permissions_to_add = []
# List of permissions which must be removed from the group
permissions_to_delete = []
# Get all the rulesets associated with this group
for r in RuleSet.RULESET_CHOICES:
rulename = r[0]
try:
ruleset = RuleSet.objects.get(group=group, name=rulename)
except RuleSet.DoesNotExist:
# Create the ruleset with default values (if it does not exist)
ruleset = RuleSet.objects.create(group=group, name=rulename)
# TODO - Update permissions here
# TODO - Update group permissions
@receiver(post_save, sender=Group)
def create_missing_rule_sets(sender, instance, **kwargs):
update_group_roles(instance)

View File

@ -22,7 +22,8 @@ def apps():
'part',
'report',
'stock',
'InvenTree'
'InvenTree',
'users',
]
def localDir():