Эх сурвалжийг харах

[useradmin] Bulk delete backend API

Update tests.
Romain Rigaux 11 жил өмнө
parent
commit
66044afbe9

+ 0 - 32
apps/useradmin/src/useradmin/templates/delete_group.mako

@@ -1,32 +0,0 @@
-## Licensed to Cloudera, Inc. under one
-## or more contributor license agreements.  See the NOTICE file
-## distributed with this work for additional information
-## regarding copyright ownership.  Cloudera, Inc. licenses this file
-## to you under the Apache License, Version 2.0 (the
-## "License"); you may not use this file except in compliance
-## with the License.  You may obtain a copy of the License at
-##
-##     http://www.apache.org/licenses/LICENSE-2.0
-##
-## Unless required by applicable law or agreed to in writing, software
-## distributed under the License is distributed on an "AS IS" BASIS,
-## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-## See the License for the specific language governing permissions and
-## limitations under the License.
-<%!
-from django.utils.translation import ugettext as _
-%>
-<form id="deleteGroupForm" action="${ url('useradmin.views.delete_group') }" method="POST">
-  <div class="modal-header">
-      <a href="#" class="close" data-dismiss="modal">&times;</a>
-      <h3 id="deleteGroupMessage">${_("Are you sure you want to delete the selected group(s)?")}</h3>
-  </div>
-  <div class="modal-footer">
-      <a href="javascript:void(0);" class="btn" data-dismiss="modal">${_('No')}</a>
-      <input type="submit" class="btn btn-danger" value="${_('Yes')}"/>
-  </div>
-  <div class="hide">
-    <select name="group_ids" data-bind="options: availableUsers, selectedOptions: chosenUsers"
-            multiple="true"></select>
-  </div>
-</form>

+ 28 - 27
apps/useradmin/src/useradmin/templates/list_groups.mako

@@ -14,8 +14,9 @@
 ## See the License for the specific language governing permissions and
 ## See the License for the specific language governing permissions and
 ## limitations under the License.
 ## limitations under the License.
 <%!
 <%!
-from desktop.views import commonheader, commonfooter
 import urllib
 import urllib
+
+from desktop.views import commonheader, commonfooter
 from django.utils.translation import ugettext as _
 from django.utils.translation import ugettext as _
 from useradmin.models import group_permissions
 from useradmin.models import group_permissions
 %>
 %>
@@ -74,16 +75,14 @@ ${layout.menubar(section='groups')}
           <tr class="tableRow"
           <tr class="tableRow"
               data-search="${group.name}${', '.join([group_user.username for group_user in group.user_set.all()])}">
               data-search="${group.name}${', '.join([group_user.username for group_user in group.user_set.all()])}">
           %if user.is_superuser:
           %if user.is_superuser:
-              <td data-row-selector-exclude="true">
-                <div class="hueCheckbox groupCheck fa" data-group="${group.name}"
-                     data-confirmation-url="${ url('useradmin.views.delete_group', name=urllib.quote(group.name))}"
-                     data-row-selector-exclude="true"></div>
-              </td>
+            <td data-row-selector-exclude="true">
+              <div class="hueCheckbox groupCheck fa" data-name="${group.name}" data-row-selector-exclude="true"></div>
+            </td>
           %endif
           %endif
           <td>
           <td>
             %if user.is_superuser:
             %if user.is_superuser:
-              <strong><a title="${_('Edit %(groupname)s') % dict(groupname=group.name)}"
-                         href="${ url('useradmin.views.edit_group', name=urllib.quote(group.name))}"
+              <strong><a title="${ _('Edit %(groupname)s') % dict(groupname=group.name) }"
+                         href="${ url('useradmin.views.edit_group', name=urllib.quote(group.name)) }"
                          data-row-selector="true">${group.name}</a></strong>
                          data-row-selector="true">${group.name}</a></strong>
             %else:
             %else:
               <strong>${group.name}</strong>
               <strong>${group.name}</strong>
@@ -107,12 +106,29 @@ ${layout.menubar(section='groups')}
   </div>
   </div>
 </div>
 </div>
 
 
-<div id="deleteGroup" class="modal hide fade groupModal"></div>
+<div id="deleteGroup" class="modal hide fade groupModal">
+  <form id="deleteGroupForm" action="${ url('useradmin.views.delete_group') }" method="POST">
+    <div class="modal-header">
+      <a href="#" class="close" data-dismiss="modal">&times;</a>
+      <h3 id="deleteGroupMessage">${_("Are you sure you want to delete the selected group(s)?")}</h3>
+    </div>
+    <div class="modal-footer">
+      <a href="javascript:void(0);" class="btn" data-dismiss="modal">${_('No')}</a>
+      <input type="submit" class="btn btn-danger" value="${_('Yes')}"/>
+    </div>
+    <div class="hide">
+      <select name="group_names" data-bind="options: availableUsers, selectedOptions: chosenUsers" multiple="true"></select>
+    </div>
+  </form>
+</div>
 
 
 <script src="/static/ext/js/knockout-min.js" type="text/javascript" charset="utf-8"></script>
 <script src="/static/ext/js/knockout-min.js" type="text/javascript" charset="utf-8"></script>
+
 <script type="text/javascript" charset="utf-8">
 <script type="text/javascript" charset="utf-8">
+  var viewModel;
+
   $(document).ready(function () {
   $(document).ready(function () {
-    var viewModel = {
+    viewModel = {
       availableUsers: ko.observableArray(${ groups_json | n }),
       availableUsers: ko.observableArray(${ groups_json | n }),
       chosenUsers: ko.observableArray([])
       chosenUsers: ko.observableArray([])
     };
     };
@@ -142,21 +158,6 @@ ${layout.menubar(section='groups')}
     $(".dataTables_wrapper").css("min-height", "0");
     $(".dataTables_wrapper").css("min-height", "0");
     $(".dataTables_filter").hide();
     $(".dataTables_filter").hide();
 
 
-    $(".confirmationModal").click(function () {
-      var _this = $(this);
-      $.ajax({
-        url: _this.data("confirmation-url"),
-        beforeSend: function (xhr) {
-          xhr.setRequestHeader("X-Requested-With", "Hue");
-        },
-        dataType: "html",
-        success: function (data) {
-          $("#deleteGroup").html(data);
-          $("#deleteGroup").modal("show");
-        }
-      });
-    });
-
     $("#selectAll").click(function () {
     $("#selectAll").click(function () {
       if ($(this).attr("checked")) {
       if ($(this).attr("checked")) {
         $(this).removeAttr("checked");
         $(this).removeAttr("checked");
@@ -181,7 +182,7 @@ ${layout.menubar(section='groups')}
 
 
     function toggleActions() {
     function toggleActions() {
       if ($(".groupCheck[checked='checked']").length > 0) {
       if ($(".groupCheck[checked='checked']").length > 0) {
-        $("#deleteGroupBtn").removeAttr("disabled").data("confirmation-url", $(".groupCheck[checked='checked']").data("confirmation-url"));
+        $("#deleteGroupBtn").removeAttr("disabled");
       }
       }
       else {
       else {
         $("#deleteGroupBtn").attr("disabled", "disabled");
         $("#deleteGroupBtn").attr("disabled", "disabled");
@@ -192,7 +193,7 @@ ${layout.menubar(section='groups')}
       viewModel.chosenUsers.removeAll();
       viewModel.chosenUsers.removeAll();
 
 
       $(".hueCheckbox[checked='checked']").each(function (index) {
       $(".hueCheckbox[checked='checked']").each(function (index) {
-        viewModel.chosenUsers.push($(this).data("id"));
+        viewModel.chosenUsers.push($(this).data("name"));
       });
       });
 
 
       $("#deleteGroup").modal("show");
       $("#deleteGroup").modal("show");

+ 6 - 3
apps/useradmin/src/useradmin/tests.py

@@ -280,13 +280,13 @@ def test_default_group():
 
 
   # Try deleting the default group
   # Try deleting the default group
   assert_true(Group.objects.filter(name='test_default').exists())
   assert_true(Group.objects.filter(name='test_default').exists())
-  response = c.post('/useradmin/groups/delete/test_default')
+  response = c.post('/useradmin/groups/delete', {'group_names': ['test_default']})
   assert_true('default user group may not be deleted' in response.content)
   assert_true('default user group may not be deleted' in response.content)
   assert_true(Group.objects.filter(name='test_default').exists())
   assert_true(Group.objects.filter(name='test_default').exists())
 
 
   # Change the name of the default group, and try deleting again
   # Change the name of the default group, and try deleting again
   useradmin.conf.DEFAULT_USER_GROUP.set_for_testing('new_default')
   useradmin.conf.DEFAULT_USER_GROUP.set_for_testing('new_default')
-  response = c.post('/useradmin/groups/delete/test_default')
+  response = c.post('/useradmin/groups/delete' , {'group_names': ['test_default']})
   assert_false(Group.objects.filter(name='test_default').exists())
   assert_false(Group.objects.filter(name='test_default').exists())
   assert_true(Group.objects.filter(name='new_default').exists())
   assert_true(Group.objects.filter(name='new_default').exists())
 
 
@@ -353,7 +353,7 @@ def test_group_admin():
   assert_true("You must be a superuser" in response.content)
   assert_true("You must be a superuser" in response.content)
 
 
   # Should be one group left, because we created the other group
   # Should be one group left, because we created the other group
-  response = c.post('/useradmin/groups/delete/testgroup')
+  response = c.post('/useradmin/groups/delete', {'group_names': ['testgroup']})
   assert_true(len(Group.objects.all()) == 1)
   assert_true(len(Group.objects.all()) == 1)
 
 
   group_count = len(Group.objects.all())
   group_count = len(Group.objects.all())
@@ -548,6 +548,9 @@ def test_ensure_home_directory():
   assert_equal('40755', '%o' % dir_stat.mode)
   assert_equal('40755', '%o' % dir_stat.mode)
 
 
 def test_list_for_autocomplete():
 def test_list_for_autocomplete():
+  reset_all_users()
+  reset_all_groups()
+
   # Now the autocomplete has access to all the users and groups
   # Now the autocomplete has access to all the users and groups
   c1 = make_logged_in_client('test_list_for_autocomplete', is_superuser=False, groupname='test_list_for_autocomplete')
   c1 = make_logged_in_client('test_list_for_autocomplete', is_superuser=False, groupname='test_list_for_autocomplete')
   c2_same_group = make_logged_in_client('test_list_for_autocomplete2', is_superuser=False, groupname='test_list_for_autocomplete')
   c2_same_group = make_logged_in_client('test_list_for_autocomplete2', is_superuser=False, groupname='test_list_for_autocomplete')

+ 1 - 1
apps/useradmin/src/useradmin/urls.py

@@ -36,5 +36,5 @@ urlpatterns = patterns('useradmin.views',
   url(r'^users/new$', 'edit_user', name="useradmin.new"),
   url(r'^users/new$', 'edit_user', name="useradmin.new"),
   url(r'^groups/new$', 'edit_group', name="useradmin.new_group"),
   url(r'^groups/new$', 'edit_group', name="useradmin.new_group"),
   url(r'^users/delete', 'delete_user'),
   url(r'^users/delete', 'delete_user'),
-  url(r'^groups/delete/(?P<name>%s)$' % (groupname_re,), 'delete_group'),
+  url(r'^groups/delete$', 'delete_group'),
 )
 )

+ 12 - 17
apps/useradmin/src/useradmin/views.py

@@ -65,6 +65,7 @@ def list_groups(request):
   is_ldap_setup = bool(LDAP.LDAP_SERVERS.get()) or LDAP.LDAP_URL.get() is not None
   is_ldap_setup = bool(LDAP.LDAP_SERVERS.get()) or LDAP.LDAP_URL.get() is not None
   return render("list_groups.mako", request, {
   return render("list_groups.mako", request, {
       'groups': Group.objects.all(),
       'groups': Group.objects.all(),
+      'groups_json': json.dumps(list(Group.objects.values_list('name', flat=True))),
       'is_ldap_setup': is_ldap_setup
       'is_ldap_setup': is_ldap_setup
   })
   })
 
 
@@ -134,32 +135,26 @@ def delete_user(request):
   return redirect(reverse(list_users))
   return redirect(reverse(list_users))
 
 
 
 
-def delete_group(request, name):
+def delete_group(request):
   if not request.user.is_superuser:
   if not request.user.is_superuser:
     raise PopupException(_("You must be a superuser to delete groups."), error_code=401)
     raise PopupException(_("You must be a superuser to delete groups."), error_code=401)
 
 
   if request.method == 'POST':
   if request.method == 'POST':
     try:
     try:
-      global groups_lock
-      __groups_lock.acquire()
-      try:
-        # Get the default group before getting the group, because we may be
-        # trying to delete the default group, and it may not have been created
-        # yet
-        default_group = get_default_user_group()
-        group = Group.objects.get(name=name)
-        if default_group is not None and default_group.name == name:
-          raise PopupException(_("The default user group may not be deleted."), error_code=401)
-        group.delete()
-      finally:
-        __groups_lock.release()
-
-      request.info(_('The group was deleted.'))
+      group_names = request.POST.getlist('group_names')
+      # Get the default group before getting the group, because we may be
+      # trying to delete the default group, and it may not have been created yet.
+      default_group = get_default_user_group()
+      if default_group is not None and default_group.name in group_names:
+        raise PopupException(_("The default user group may not be deleted."), error_code=401)
+      Group.objects.filter(name__in=group_names).delete()
+
+      request.info(_('The groups were deleted.'))
       return redirect(reverse(list_groups))
       return redirect(reverse(list_groups))
     except Group.DoesNotExist:
     except Group.DoesNotExist:
       raise PopupException(_("Group not found."), error_code=404)
       raise PopupException(_("Group not found."), error_code=404)
   else:
   else:
-    return render("delete_group.mako", request, dict(path=request.path, groupname=name))
+    return render("delete_group.mako", request, {'path': request.path})
 
 
 
 
 def edit_user(request, username=None):
 def edit_user(request, username=None):