diff --git a/apps/static/js/jumpserver.js b/apps/static/js/jumpserver.js index 367e51d05..a4c8930b6 100644 --- a/apps/static/js/jumpserver.js +++ b/apps/static/js/jumpserver.js @@ -297,6 +297,7 @@ jumpserver.initDataTable = function (options) { url: options.i18n_url || "/static/js/plugins/dataTables/i18n/zh-hans.json" }, order: options.order || [[ 1, 'asc' ]], + select: options.select || 'multi', buttons: options.buttons || [ {extend: 'excel', exportOptions: { @@ -323,9 +324,6 @@ jumpserver.initDataTable = function (options) { } ], columnDefs: columnDefs, - // select: 'single', - // select: options.select || {style: 'single'}, - // select: false, ajax: { url: options.ajax_url , dataSrc: "" @@ -333,16 +331,16 @@ jumpserver.initDataTable = function (options) { columns: options.columns || [], lengthMenu: [[15, 25, 50, -1], [15, 25, 50, "All"]] }); - // table.on('select', function(e, dt, type, indexes) { - // var $node = table[ type ]( indexes ).nodes().to$(); - // $node.find('input.ipt_check').prop('checked', true); - // }).on('deselect', function(e, dt, type, indexes) { - // var $node = table[ type ]( indexes ).nodes().to$(); - // $node.find('input.ipt_check').prop('checked', false); - // }).on('draw', function(){ - // $('#op').html(options.op_html || ''); - // $('#uc').html(options.uc_html || ''); - // }); + table.on('select', function(e, dt, type, indexes) { + var $node = table[ type ]( indexes ).nodes().to$(); + $node.find('input.ipt_check').prop('checked', true); + }).on('deselect', function(e, dt, type, indexes) { + var $node = table[ type ]( indexes ).nodes().to$(); + $node.find('input.ipt_check').prop('checked', false); + }).on('draw', function(){ + $('#op').html(options.op_html || ''); + $('#uc').html(options.uc_html || ''); + }); $('.ipt_check_all').on('click', function() { if (!jumpserver.checked) { $(this).closest('table').find('.ipt_check').prop('checked', true); @@ -354,5 +352,6 @@ jumpserver.initDataTable = function (options) { table.rows().deselect(); } }); + return table; }; diff --git a/apps/users/api.py b/apps/users/api.py index aedf0635b..bc881d9b4 100644 --- a/apps/users/api.py +++ b/apps/users/api.py @@ -30,9 +30,9 @@ class UserViewSet(BulkModelViewSet): permission_classes = (IsSuperUser,) -class UserAndGroupEditApi(generics.RetrieveUpdateAPIView): +class UserUpdateGroupApi(generics.RetrieveUpdateAPIView): queryset = User.objects.all() - serializer_class = serializers.UserAndGroupSerializer + serializer_class = serializers.UserUpdateGroupSerializer permission_classes = (IsSuperUser,) @@ -72,7 +72,17 @@ class UserUpdatePKApi(generics.UpdateAPIView): user.public_key = serializer.validated_data['_public_key'] user.save() -# + +class UserGroupViewSet(viewsets.ModelViewSet): + queryset = UserGroup.objects.all() + serializer_class = serializers.UserGroupSerializer + + +class UserGroupUpdateUserApi(generics.RetrieveUpdateAPIView): + queryset = UserGroup.objects.all() + serializer_class = serializers.UserGroupUpdateMemeberSerializer + permission_classes = (IsSuperUser,) + # class GroupDetailApi(generics.RetrieveUpdateDestroyAPIView): # queryset = UserGroup.objects.all() # serializer_class = serializers.GroupDetailSerializer diff --git a/apps/users/serializers.py b/apps/users/serializers.py index 9d148aa20..48fc820c6 100644 --- a/apps/users/serializers.py +++ b/apps/users/serializers.py @@ -16,8 +16,7 @@ from .models import User, UserGroup class UserSerializer(BulkSerializerMixin, serializers.ModelSerializer): - group_display = serializers.SerializerMethodField() - active_display = serializers.SerializerMethodField() + groups_display = serializers.SerializerMethodField() groups = serializers.PrimaryKeyRelatedField(many=True, queryset=UserGroup.objects.all()) class Meta: @@ -27,17 +26,16 @@ class UserSerializer(BulkSerializerMixin, serializers.ModelSerializer): def get_field_names(self, declared_fields, info): fields = super(UserSerializer, self).get_field_names(declared_fields, info) - fields.extend(['group_display', 'get_role_display']) + fields.extend(['groups_display', 'get_role_display', 'is_valid']) return fields @staticmethod - def get_group_display(obj): + def get_groups_display(obj): return " ".join([group.name for group in obj.groups.all()]) - @staticmethod - def get_active_display(obj): - # TODO: user active state - return not (obj.is_expired and obj.is_active) + # @staticmethod + # def get_active_display(obj): + # return not (obj.is_expired and obj.is_active) class UserPKUpdateSerializer(serializers.ModelSerializer): @@ -54,7 +52,7 @@ class UserPKUpdateSerializer(serializers.ModelSerializer): return value -class UserAndGroupSerializer(serializers.ModelSerializer): +class UserUpdateGroupSerializer(serializers.ModelSerializer): groups = serializers.PrimaryKeyRelatedField(many=True, queryset=UserGroup.objects.all()) class Meta: @@ -62,6 +60,26 @@ class UserAndGroupSerializer(serializers.ModelSerializer): fields = ['id', 'groups'] +class UserGroupSerializer(BulkSerializerMixin, serializers.ModelSerializer): + user_amount = serializers.SerializerMethodField() + + class Meta: + model = UserGroup + list_serializer_class = BulkListSerializer + + @staticmethod + def get_user_amount(obj): + return obj.users.count() + + +class UserGroupUpdateMemeberSerializer(serializers.ModelSerializer): + users = serializers.PrimaryKeyRelatedField(many=True, queryset=User.objects.all()) + + class Meta: + model = UserGroup + fields = ['id', 'users'] + + # class GroupDetailSerializer(serializers.ModelSerializer): # class Meta: # model = UserGroup diff --git a/apps/users/templates/users/user_detail.html b/apps/users/templates/users/user_detail.html index 49e9fb62e..9b7a48761 100644 --- a/apps/users/templates/users/user_detail.html +++ b/apps/users/templates/users/user_detail.html @@ -224,9 +224,8 @@ jumpserver.selected_groups = {}; function updateUserGroups(user_groups) { - var the_url = "{% url 'users:group-user-edit-api' pk=user.id %}"; + var the_url = "{% url 'users:api-user-update-group' pk=user.id %}"; var body = { - id: {{ user.id }}, groups: Object.assign([], user_groups) }; var success = function(data) { @@ -245,13 +244,11 @@ function updateUserGroups(user_groups) { }); // clear jumpserver.selected_groups jumpserver.selected_groups = {}; - toastr.success('{% trans "UserGroup Update Success!" %}') }; APIUpdateAttr({ url: the_url, body: JSON.stringify(body), - success: success, - method: 'PUT' + success: success }); } $(document).ready(function() { diff --git a/apps/users/templates/users/user_group_detail.html b/apps/users/templates/users/user_group_detail.html index 3e00d0055..349233efc 100644 --- a/apps/users/templates/users/user_group_detail.html +++ b/apps/users/templates/users/user_group_detail.html @@ -11,52 +11,52 @@ {% endblock %} {% block content %} @@ -67,7 +67,7 @@ dd {
@@ -75,7 +75,7 @@ dd {
- {{ object.name }} + {{ user_group.name }}
-
-
{% trans 'Name' %}:
-
{{ object.name }}
-
-
-
{% trans 'Comment' %}:
-
{{ object.comment }}
-
-
-
{% trans 'Created at' %}:
-
{{ object.date_created }}
-
-
-
{% trans 'Users' %}:
-
- {% for user in object.users.all %} - - {% endfor %} -
-
+ + + + + + + + + + + + + + + + + + + +
{% trans 'Name' %}:{{ user_group.name }}
{% trans 'Create by' %}:{{ user_group.created_by }}
{% trans 'Date created' %}:{{ user_group.date_created }}
{% trans 'Comment' %}:{{ user_group.comment }}
-
+
- {% trans 'Quick modify' %} + {% trans 'User' %}
- +
+ - - - - + + + {% for user in user_group.users.all %} + + + + + {% endfor %}
{% trans 'Add User' %}: - - - + +
{% trans 'Delete' %}: - - - + +
{{ user.name }} + +
@@ -147,35 +156,63 @@ dd { {% endblock %} {% block custom_foot_js %} diff --git a/apps/users/templates/users/user_group_list.html b/apps/users/templates/users/user_group_list.html index 43101fd87..2ff66b848 100644 --- a/apps/users/templates/users/user_group_list.html +++ b/apps/users/templates/users/user_group_list.html @@ -11,7 +11,6 @@ {% trans 'Name' %} {% trans 'User Amount' %} - {% trans 'Asset Amount' %} {% trans 'Comment' %} {% trans 'Action' %} @@ -43,11 +42,11 @@ $(document).ready(function() { var detail_btn = '' + cellData + ''; $(td).html(detail_btn.replace('99991937', rowData.id)); }}, - {targets: 4, createdCell: function (td, cellData) { - var innerHtml = cellData.length > 18 ? cellData.substring(0, 18) + '...': cellData; - $(td).html('' + innerHtml + ''); + {targets: 3, createdCell: function (td, cellData) { + var innerHtml = cellData.length > 30 ? cellData.substring(0, 30) + '...': cellData; + $(td).html('' + innerHtml + ''); }}, - {targets: 5, createdCell: function (td, cellData, rowData) { + {targets: 4, createdCell: function (td, cellData, rowData) { var update_btn = '{% trans "Update" %}'.replace('99991937', cellData); var del_btn = '{% trans "Delete" %}'.replace('99991937', cellData); if (rowData.id === 1) { @@ -56,9 +55,9 @@ $(document).ready(function() { $(td).html(update_btn + del_btn) } }}], - ajax_url: '{% url "users:user-group-bulk-update-api" %}', + ajax_url: '{% url "users:api-user-group-list" %}', columns: [{data: function(){return ""}}, {data: "name" }, {data: "user_amount"}, - {data: function(){return 999}}, {data: "comment"}, {data: "id" }], + {data: "comment"}, {data: "id" }], op_html: $('#actions').html() }; jumpserver.initDataTable(options); @@ -66,7 +65,7 @@ $(document).ready(function() { var $this = $(this); function doDelete() { var group_id = $this.data('gid'); - var the_url = "{% url 'users:user-group-detail-api' 99991937 %}".replace('99991937', group_id); + var the_url = "{% url 'users:api-user-group-detail' pk=99991937 %}".replace('99991937', group_id); var body = {}; var success = function() { var msg = "{% trans 'Group Deleted.' %}"; @@ -76,7 +75,7 @@ $(document).ready(function() { var fail = function() { var msg = "{% trans 'Group Deleting failed.' %}"; swal("{% trans 'Group Delete' %}", msg, "error"); - } + }; APIUpdateAttr({ url: the_url, body: JSON.stringify(body), @@ -105,8 +104,8 @@ $(document).ready(function() { }); if (plain_id_list === []) { return false; - }; - var the_url = "{% url 'users:user-group-bulk-update-api' %}"; + } + var the_url = "{% url 'users:api-user-group-list' %}"; function doDelete() { swal({ title: "{% trans 'Are you sure?' %}", diff --git a/apps/users/templates/users/user_list.html b/apps/users/templates/users/user_list.html index d38e1183b..c260bd25b 100644 --- a/apps/users/templates/users/user_list.html +++ b/apps/users/templates/users/user_list.html @@ -15,7 +15,6 @@ {% trans 'Username' %} {% trans 'Role' %} {% trans 'User group' %} - {% trans 'Asset num' %} {% trans 'Active' %} {% trans 'Action' %} @@ -56,14 +55,14 @@ $(document).ready(function(){ var innerHtml = cellData.length > 20 ? cellData.substring(0, 20) + '...': cellData; $(td).html('' + innerHtml + ''); }}, - {targets: 6, createdCell: function (td, cellData) { + {targets: 5, createdCell: function (td, cellData) { if (!cellData) { $(td).html('') } else { $(td).html('') } }}, - {targets: 7, createdCell: function (td, cellData, rowData) { + {targets: 6, createdCell: function (td, cellData, rowData) { var update_btn = '{% trans "Update" %}'.replace('99991937', cellData); var del_btn = '{% trans "Delete" %}'.replace('99991937', cellData); if (rowData.id === 1 || rowData.username == "admin") { @@ -73,8 +72,8 @@ $(document).ready(function(){ } }}], ajax_url: '{% url "users:api-user-list" %}', - columns: [{data: function(){return ""}}, {data: "username" }, {data: "name" }, {data: "get_role_display" }, {data: "group_display" }, - {data: function(){return 999}}, {data: "active_display" }, {data: "id" }], + columns: [{data: function(){return ""}}, {data: "username" }, {data: "name" }, {data: "get_role_display" }, + {data: "groups_display" }, {data: "is_valid" }, {data: "id" }], op_html: $('#actions').html() }; jumpserver.initDataTable(options); @@ -224,6 +223,8 @@ $(document).ready(function(){ $form.ajaxSubmit({success: success}); }).on('change', '#id_excel', function() { $(this).siblings('.help-block').remove(); +}).on('click', '.ipt_check', function () { + console.log('Hello') }) {% endblock %} diff --git a/apps/users/urls.py b/apps/users/urls.py index 07561e3ff..a4af64bd1 100644 --- a/apps/users/urls.py +++ b/apps/users/urls.py @@ -39,6 +39,7 @@ urlpatterns = [ router = BulkRouter() router.register(r'v1/users', api.UserViewSet, 'api-user') +router.register(r'v1/user-groups', api.UserGroupViewSet, 'api-user-group') # router.register(r'v1/user-groups', api.AssetViewSet, 'api-groups') @@ -53,7 +54,9 @@ urlpatterns += [ # url(r'^v1/user-groups/(?P\d+)/user/(?P\d+)/$', # api.DeleteUserFromGroupApi.as_view(), name='delete-user-from-group-api'), url(r'^v1/users/(?P\d+)/groups/$', - api.UserAndGroupEditApi.as_view(), name='group-user-edit-api'), + api.UserUpdateGroupApi.as_view(), name='api-user-update-group'), + url(r'^v1/user-groups/(?P\d+)/users/$', + api.UserGroupUpdateUserApi.as_view(), name='api-user-group-update-user'), ] urlpatterns += router.urls diff --git a/apps/users/views.py b/apps/users/views.py index 12a71df21..90468e5bb 100644 --- a/apps/users/views.py +++ b/apps/users/views.py @@ -216,10 +216,16 @@ class UserGroupUpdateView(AdminUserRequiredMixin, UpdateView): class UserGroupDetailView(AdminUserRequiredMixin, DetailView): model = UserGroup + context_object_name = 'user_group' template_name = 'users/user_group_detail.html' def get_context_data(self, **kwargs): - context = {'app': _('Users'), 'action': _('User Group Detail')} + users = User.objects.exclude(id__in=self.object.users.all()) + context = { + 'app': _('Users'), + 'action': _('User Group Detail'), + 'users': users, + } kwargs.update(context) return super(UserGroupDetailView, self).get_context_data(**kwargs)