diff --git a/netbox/netbox/views/generic/mixins.py b/netbox/netbox/views/generic/mixins.py index 8e363f0a5..a55f01509 100644 --- a/netbox/netbox/views/generic/mixins.py +++ b/netbox/netbox/views/generic/mixins.py @@ -22,6 +22,7 @@ class ActionsMixin: Return a tuple of actions for which the given user is permitted to do. """ model = model or self.queryset.model + return [ action for action in self.actions if user.has_perms([ get_permission_for_model(model, name) for name in self.action_perms[action] diff --git a/netbox/users/forms/filtersets.py b/netbox/users/forms/filtersets.py index 30b6bd832..473bddac9 100644 --- a/netbox/users/forms/filtersets.py +++ b/netbox/users/forms/filtersets.py @@ -20,36 +20,27 @@ class UserFilterForm(ContactModelFilterForm, NetBoxModelFilterSetForm): model = NetBoxUser fieldsets = ( (None, ('q', 'filter_id',)), - ('Location', ('region_id', 'site_group_id', 'site_id')), - ('ASN', ('asn',)), - ('Contacts', ('contact', 'contact_role', 'contact_group')), + ('Name', ('username', 'first_name', 'last_name')), + ('Security', ('is_superuser', 'is_staff', 'is_active')), ) - region_id = DynamicModelMultipleChoiceField( - queryset=Region.objects.all(), + username = forms.CharField( + required=False + ) + first_name = forms.CharField( + required=False + ) + last_name = forms.CharField( + required=False + ) + is_superuser = forms.BooleanField( required=False, - label=_('Region') + label='Is Superuser', ) - site_group_id = DynamicModelMultipleChoiceField( - queryset=SiteGroup.objects.all(), + is_staff = forms.BooleanField( required=False, - label=_('Site group') + label='Is Staff', ) - site_id = DynamicModelMultipleChoiceField( - queryset=Site.objects.all(), + is_active = forms.BooleanField( required=False, - query_params={ - 'region_id': '$region_id', - 'site_group_id': '$site_group_id', - }, - label=_('Site') + label='Is Active', ) - asn = forms.IntegerField( - required=False, - label=_('ASN (legacy)') - ) - asn_id = DynamicModelMultipleChoiceField( - queryset=ASN.objects.all(), - required=False, - label=_('ASNs') - ) - tag = TagFilterField(model) diff --git a/netbox/users/forms/model_forms.py b/netbox/users/forms/model_forms.py index 265a66cc8..fbf55ffa8 100644 --- a/netbox/users/forms/model_forms.py +++ b/netbox/users/forms/model_forms.py @@ -2,6 +2,7 @@ from django import forms from django.conf import settings from django.contrib.auth import get_user_model from django.contrib.auth.forms import AuthenticationForm, PasswordChangeForm as DjangoPasswordChangeForm +from django.contrib.auth.models import Group from django.contrib.postgres.forms import SimpleArrayField from django.utils.html import mark_safe from django.utils.translation import gettext as _ @@ -10,6 +11,7 @@ from ipam.formfields import IPNetworkFormField from ipam.validators import prefix_validator from netbox.preferences import PREFERENCES from utilities.forms import BootstrapMixin +from utilities.forms.fields import DynamicModelChoiceField, DynamicModelMultipleChoiceField from utilities.forms.widgets import DateTimePicker from utilities.utils import flatten_dict from users.models import * @@ -141,13 +143,20 @@ class TokenForm(BootstrapMixin, forms.ModelForm): class UserForm(BootstrapMixin, forms.ModelForm): + groups = DynamicModelMultipleChoiceField( + queryset=Group.objects.all() + ) fieldsets = ( - ('User', ('username', )), + ('User', ('username', 'first_name', 'last_name', 'email', )), + ('Groups', ('groups', )), + ('Status', ('is_active', 'is_staff', 'is_superuser', )), + ('Important Dates', ('last_login', 'date_joined', )), ) class Meta: model = NetBoxUser fields = [ - 'username', + 'username', 'first_name', 'last_name', 'email', 'groups', + 'is_active', 'is_staff', 'is_superuser', 'last_login', 'date_joined', ] diff --git a/netbox/users/tables.py b/netbox/users/tables.py index f7c27ff63..45a87e7ac 100644 --- a/netbox/users/tables.py +++ b/netbox/users/tables.py @@ -1,4 +1,5 @@ import django_tables2 as tables +from django_tables2.utils import A from .models import Token from netbox.tables import NetBoxTable, columns from users.models import NetBoxUser @@ -56,7 +57,7 @@ class TokenTable(NetBoxTable): class UserTable(NetBoxTable): - username = tables.Column() + username = tables.LinkColumn('users:netboxuser', args=[A('pk')]) actions = columns.ActionsColumn( actions=('edit', 'delete'), ) @@ -64,6 +65,6 @@ class UserTable(NetBoxTable): class Meta(NetBoxTable.Meta): model = NetBoxUser fields = ( - 'pk', 'id', 'username', 'email', 'first_name', 'last_name' + 'pk', 'id', 'username', 'email', 'first_name', 'last_name', 'is_superuser', 'is_staff', 'is_active' ) - default_columns = ('pk', 'username', 'email', 'first_name', 'last_name') + default_columns = ('pk', 'username', 'email', 'first_name', 'last_name', 'is_superuser') diff --git a/netbox/users/urls.py b/netbox/users/urls.py index 03c1bf9b4..12c4e6e66 100644 --- a/netbox/users/urls.py +++ b/netbox/users/urls.py @@ -14,6 +14,7 @@ urlpatterns = [ # Users path('users/', views.NetBoxUserListView.as_view(), name='user_list'), path('users/add/', views.NetBoxUserEditView.as_view(), name='user_add'), + path('users/add/', views.NetBoxUserEditView.as_view(), name='netboxuser_add'), path('users/import/', views.NetBoxUserBulkImportView.as_view(), name='netboxuser_import'), path('users/edit/', views.NetBoxUserBulkEditView.as_view(), name='netboxuser_bulk_edit'), path('users/delete/', views.NetBoxUserBulkDeleteView.as_view(), name='netboxuser_bulk_delete'), diff --git a/netbox/users/views.py b/netbox/users/views.py index 5c0dc1af3..d114deb7a 100644 --- a/netbox/users/views.py +++ b/netbox/users/views.py @@ -346,9 +346,22 @@ class NetBoxUserListView(generic.ObjectListView): table = tables.UserTable -@register_model_view(get_user_model()) +@register_model_view(NetBoxUser) class NetBoxUserView(generic.ObjectView): queryset = get_user_model().objects.all() + template_name = 'users/user.html' + + def get_extra_context(self, request, instance): + # Compile changelog table + changelog = ObjectChange.objects.restrict(request.user, 'view').filter(user=request.user).prefetch_related( + 'changed_object_type' + )[:20] + changelog_table = ObjectChangeTable(changelog) + + return { + 'changelog_table': changelog_table, + 'active_tab': 'user', + } @register_model_view(NetBoxUser, 'edit')