mirror of
https://github.com/inventree/InvenTree
synced 2024-08-30 18:33:04 +00:00
Add hook to update group permission roles
(doesn't do anything yet)
This commit is contained in:
parent
bedda66949
commit
16f1b4c784
@ -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)
|
||||
|
@ -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)
|
@ -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)
|
Loading…
Reference in New Issue
Block a user