Coverage for src/backend/InvenTree/users/admin.py: 66%
64 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 17:47 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 17:47 +0000
1"""Admin classes for the 'users' app."""
3from django import forms
4from django.contrib import admin
5from django.contrib.admin.widgets import FilteredSelectMultiple
6from django.contrib.auth import get_user_model
7from django.contrib.auth.admin import UserAdmin
8from django.contrib.auth.models import Group
9from django.utils.translation import gettext_lazy as _
11from users.models import ApiToken, Owner, RuleSet
12from users.ruleset import RULESET_CHOICES
14User = get_user_model()
17@admin.register(ApiToken)
18class ApiTokenAdmin(admin.ModelAdmin):
19 """Admin class for the ApiToken model."""
21 list_display = ('token', 'user', 'name', 'expiry', 'active')
22 list_filter = ('user', 'revoked')
23 fields = (
24 'token',
25 'user',
26 'name',
27 'created',
28 'last_seen',
29 'revoked',
30 'expiry',
31 'metadata',
32 )
34 def get_fields(self, request, obj=None):
35 """Return list of fields to display."""
36 fields = ['token'] if obj else ['key']
38 fields += [
39 'user',
40 'name',
41 'created',
42 'last_seen',
43 'revoked',
44 'expiry',
45 'metadata',
46 ]
48 return fields
50 def get_readonly_fields(self, request, obj=None):
51 """Some fields are read-only after creation."""
52 ro = ['created', 'last_seen']
54 if obj:
55 ro += ['token', 'user', 'expiry', 'name']
57 return ro
60class RuleSetInline(admin.TabularInline):
61 """Class for displaying inline RuleSet data in the Group admin page."""
63 model = RuleSet
64 can_delete = False
65 verbose_name = 'Ruleset'
66 verbose_plural_name = 'Rulesets'
67 fields = ['name', *list(RuleSet.RULE_OPTIONS)]
68 readonly_fields = ['name']
69 max_num = len(RULESET_CHOICES)
70 min_num = 1
71 extra = 0
72 ordering = ['name']
75class InvenTreeGroupAdminForm(forms.ModelForm):
76 """Custom admin form for the Group model.
78 Adds the ability for editing user membership directly in the group admin page.
79 """
81 class Meta:
82 """Metaclass defines extra fields."""
84 model = Group
85 exclude = []
86 fields = ['name', 'users']
88 def __init__(self, *args, **kwargs): # pragma: no cover
89 """Populate the 'users' field with the users in the current group."""
90 super().__init__(*args, **kwargs)
92 if self.instance.pk:
93 # Populate the users field with the current Group users.
94 self.fields['users'].initial = self.instance.user_set.all()
96 # Add the users field.
97 users = forms.ModelMultipleChoiceField(
98 queryset=User.objects.all(),
99 required=False,
100 widget=FilteredSelectMultiple('users', False),
101 label=_('Users'),
102 help_text=_('Select which users are assigned to this group'),
103 )
105 def save_m2m(self): # pragma: no cover
106 """Add the users to the Group."""
107 self.instance.user_set.set(self.cleaned_data['users'])
109 def save(self, *args, **kwargs): # pragma: no cover
110 """Custom save method for Group admin form."""
111 # Default save
112 instance = super().save()
113 # Save many-to-many data
114 self.save_m2m()
115 return instance
118class InvenTreeUserAdmin(UserAdmin):
119 """Custom admin page for the User model.
121 - Restrict user creation and editing to superuser accounts
122 - Hides the "permissions" view as this is handled by RuleSets
123 """
125 list_display = (
126 'username',
127 'email',
128 'first_name',
129 'last_name',
130 'is_staff',
131 'last_login',
132 ) # display last connection for each user in user admin panel.
134 fieldsets = (
135 (None, {'fields': ('username', 'password')}),
136 (_('Personal info'), {'fields': ('first_name', 'last_name', 'email')}),
137 (
138 _('Permissions'),
139 {'fields': ('is_active', 'is_staff', 'is_superuser', 'groups')},
140 ),
141 (_('Important dates'), {'fields': ('last_login', 'date_joined')}),
142 )
144 def get_readonly_fields(self, request, obj=None):
145 """Make all fields read-only for non-superusers."""
146 fields = super().get_readonly_fields(request, obj)
148 if not request.user.is_superuser:
149 fields += ('is_staff', 'is_superuser')
151 return fields
154@admin.register(Owner)
155class OwnerAdmin(admin.ModelAdmin):
156 """Custom admin interface for the Owner model."""
158 search_fields = ['name']
161admin.site.unregister(User)
162admin.site.register(User, InvenTreeUserAdmin)