forked from inventree/InvenTree
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathadmin.py
More file actions
233 lines (177 loc) · 7.75 KB
/
admin.py
File metadata and controls
233 lines (177 loc) · 7.75 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
"""Admin classes for the 'users' app"""
from django import forms
from django.contrib import admin, messages
from django.contrib.admin.widgets import FilteredSelectMultiple
from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import Group
from django.utils.safestring import mark_safe
from django.utils.translation import gettext_lazy as _
from users.models import Owner, RuleSet
User = get_user_model()
class RuleSetInline(admin.TabularInline):
"""Class for displaying inline RuleSet data in the Group admin page."""
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
# TODO: find better way to order inlines
ordering = ['name']
class InvenTreeGroupAdminForm(forms.ModelForm):
"""Custom admin form for the Group model.
Adds the ability for editing user membership directly in the group admin page.
"""
class Meta:
"""Metaclass defines extra fields"""
model = Group
exclude = []
fields = [
'name',
'users',
]
def __init__(self, *args, **kwargs): # pragma: no cover
"""Populate the 'users' field with the users in the current group"""
super().__init__(*args, **kwargs)
if self.instance.pk:
# Populate the users field with the current Group users.
self.fields['users'].initial = self.instance.user_set.all()
# Add the users field.
users = forms.ModelMultipleChoiceField(
queryset=User.objects.all(),
required=False,
widget=FilteredSelectMultiple('users', False),
label=_('Users'),
help_text=_('Select which users are assigned to this group')
)
def save_m2m(self): # pragma: no cover
"""Add the users to the Group"""
self.instance.user_set.set(self.cleaned_data['users'])
def save(self, *args, **kwargs): # pragma: no cover
"""Custom save method for Group admin form"""
# Default save
instance = super().save()
# Save many-to-many data
self.save_m2m()
return instance
class RoleGroupAdmin(admin.ModelAdmin): # pragma: no cover
"""Custom admin interface for the Group model."""
form = InvenTreeGroupAdminForm
inlines = [
RuleSetInline,
]
list_display = ('name', 'admin', 'part_category', 'part', 'stock_location',
'stock_item', 'build', 'purchase_order', 'sales_order')
def get_rule_set(self, obj, rule_set_type):
"""Return list of permissions for the given ruleset."""
# Get all rulesets associated to object
rule_sets = RuleSet.objects.filter(group=obj.pk)
# Select ruleset based on type
for rule_set in rule_sets:
if rule_set.name == rule_set_type:
break
def append_permission_level(permission_level, next_level):
"""Appen permission level"""
if not permission_level:
return next_level
if permission_level[:-1].endswith('|'):
permission_level += next_level
else:
permission_level += ' | ' + next_level
return permission_level
permission_level = ''
if rule_set.can_view:
permission_level = append_permission_level(permission_level, 'V')
if rule_set.can_add:
permission_level = append_permission_level(permission_level, 'A')
if rule_set.can_change:
permission_level = append_permission_level(permission_level, 'C')
if rule_set.can_delete:
permission_level = append_permission_level(permission_level, 'D')
return permission_level
def admin(self, obj):
"""Return the ruleset for the admin role"""
return self.get_rule_set(obj, 'admin')
def part_category(self, obj):
"""Return the ruleset for the PartCategory role"""
return self.get_rule_set(obj, 'part_category')
def part(self, obj):
"""Return the ruleset for the Part role"""
return self.get_rule_set(obj, 'part')
def stock_location(self, obj):
"""Return the ruleset for the StockLocation role"""
return self.get_rule_set(obj, 'stock_location')
def stock_item(self, obj):
"""Return the ruleset for the StockItem role"""
return self.get_rule_set(obj, 'stock')
def build(self, obj):
"""Return the ruleset for the BuildOrder role"""
return self.get_rule_set(obj, 'build')
def purchase_order(self, obj):
"""Return the ruleset for the PurchaseOrder role"""
return self.get_rule_set(obj, 'purchase_order')
def sales_order(self, obj):
"""Return the ruleset for the SalesOrder role"""
return self.get_rule_set(obj, 'sales_order')
def get_formsets_with_inlines(self, request, obj=None):
"""Return all inline formsets"""
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']
def save_model(self, request, obj, form, change):
"""Save overwrite.
This method serves two purposes:
- show warning message whenever the group users belong to multiple groups
- skip saving of the group instance model as inlines needs to be saved before.
"""
# Get form cleaned data
users = form.cleaned_data['users']
# Check for users who are members of multiple groups
warning_message = ''
for user in users:
if user.groups.all().count() > 1:
warning_message += f'<br>- <b>{user.username}</b> is member of: '
for idx, group in enumerate(user.groups.all()):
warning_message += f'<b>{group.name}</b>'
if idx < len(user.groups.all()) - 1:
warning_message += ', '
# If any, display warning message when group is saved
if warning_message:
warning_message = mark_safe(_(f'The following users are members of multiple groups:'
f'{warning_message}'))
messages.add_message(request, messages.WARNING, warning_message)
def save_formset(self, request, form, formset, change):
"""Save the inline formset"""
# Save inline Rulesets
formset.save()
# Save Group instance and update permissions
form.instance.save(update_fields=['name'])
class InvenTreeUserAdmin(UserAdmin):
"""Custom admin page for the User model.
Hides the "permissions" view as this is now handled
entirely by groups and RuleSets.
(And it's confusing!)
"""
list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff', 'last_login') # display last connection for each user in user admin panel.
fieldsets = (
(None, {'fields': ('username', 'password')}),
(_('Personal info'), {'fields': ('first_name', 'last_name', 'email')}),
(_('Permissions'), {
'fields': ('is_active', 'is_staff', 'is_superuser', 'groups'),
}),
(_('Important dates'), {'fields': ('last_login', 'date_joined')}),
)
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)