From 99e3711bca5dbfd8f828941ad5894e08dc84f7ff Mon Sep 17 00:00:00 2001
From: Nicolas ROCHE <nroche@entrouvert.com>
Date: Mon, 21 Sep 2020 15:20:03 +0200
Subject: [PATCH] manager: use selected ou by default in import roles form
 (#46642)

---
 src/authentic2/manager/role_views.py          | 20 ++++++++++++++++++-
 .../templates/authentic2/manager/roles.html   |  2 +-
 tests/test_role_manager.py                    |  9 +++++++++
 3 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/src/authentic2/manager/role_views.py b/src/authentic2/manager/role_views.py
index 595e2b8d..c7d479c4 100644
--- a/src/authentic2/manager/role_views.py
+++ b/src/authentic2/manager/role_views.py
@@ -12,16 +12,17 @@
 # GNU Affero General Public License for more details.
 #
 # You should have received a copy of the GNU Affero General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 import json
 
 from django.core.exceptions import PermissionDenied, ValidationError
+from django.http import QueryDict
 from django.utils.translation import ugettext_lazy as _
 from django.urls import reverse
 from django.views.generic import FormView, TemplateView
 from django.views.generic.detail import SingleObjectMixin
 from django.contrib import messages
 from django.contrib.contenttypes.models import ContentType
 from django.db import transaction
 from django.db.models.query import Q, Prefetch
@@ -31,16 +32,25 @@ from django.contrib.auth import get_user_model
 from django_rbac.utils import get_role_model, get_permission_model, get_ou_model
 
 from authentic2.utils import redirect
 from authentic2 import hooks, data_transfer
 
 from . import tables, views, resources, forms, app_settings
 from .utils import has_show_username
 
+# https://github.com/MongoEngine/django-mongoengine/blob/master/django_mongoengine/views/edit.py
+import django.views.generic.edit
+
+try:
+    FormMixin = django.views.generic.edit.FormMixinBase
+except AttributeError:
+    # django >= 1.10
+    FormMixin = django.views.generic.edit.FormMixin
+
 
 class RolesMixin(object):
     service_roles = True
     admin_roles = False
 
     def get_queryset(self):
         qs = super(RolesMixin, self).get_queryset()
         qs = qs.select_related('ou')
@@ -509,22 +519,30 @@ class RoleRemoveAdminUserView(views.TitleMixin, views.AjaxFormViewMixin,
         hooks.call_hooks('event', name='remove-remove-admin-role-user', user=self.request.user,
                          role=self.object, admin=self.user)
         return redirect(self.request, self.success_url)
 
 remove_admin_user = RoleRemoveAdminUserView.as_view()
 
 
 class RolesImportView(views.PermissionMixin, views.TitleMixin, views.MediaMixin, views.FormNeedsRequest,
-                      FormView):
+                      FormView, FormMixin):
     form_class = forms.RolesImportForm
     model = get_role_model()
     template_name = 'authentic2/manager/import_form.html'
     title = _('Roles Import')
 
+    def get_initial(self):
+        result = super().get_initial()
+        query_dict = QueryDict(self.request.environ.get('QUERY_STRING'))
+        selected_ou = query_dict.get('search-ou')
+        if selected_ou:
+            result.update({'ou': selected_ou})
+        return result
+
     def post(self, request, *args, **kwargs):
         if not self.can_add:
             raise PermissionDenied
         return super().post(request, *args, **kwargs)
 
     def form_valid(self, form):
         self.ou = form.cleaned_data['ou']
         try:
diff --git a/src/authentic2/manager/templates/authentic2/manager/roles.html b/src/authentic2/manager/templates/authentic2/manager/roles.html
index 15a2acdd..f43a052d 100644
--- a/src/authentic2/manager/templates/authentic2/manager/roles.html
+++ b/src/authentic2/manager/templates/authentic2/manager/roles.html
@@ -10,17 +10,17 @@
   {% if view.can_add %}
     <a href="{% url "a2-manager-role-add" %}" rel="popup">{% trans "Add role" %}</a>
   {% else %}
     <a href="#" class="disabled" rel="popup">{% trans "Add role" %}</a>
   {% endif %}
   <ul class="extra-actions-menu">
     <li><a download href="{% url 'a2-manager-roles-export' format="json" %}?{{ request.GET.urlencode }}">{% trans 'Export' %}</a></li>
     {% if view.can_add %}
-    <li><a href="{% url 'a2-manager-roles-import' %}" rel="popup">{% trans 'Import' %}</a></li>
+    <li><a href="{% url 'a2-manager-roles-import' %}?{{ request.GET.urlencode }}" rel="popup">{% trans 'Import' %}</a></li>
     {% endif %}
   </ul>
   </span>
 {% endblock %}
 
 {% block sidebar %}
   <aside id="sidebar">
     {% include "authentic2/manager/search_form.html" %}
diff --git a/tests/test_role_manager.py b/tests/test_role_manager.py
index b71435de..6afacc66 100644
--- a/tests/test_role_manager.py
+++ b/tests/test_role_manager.py
@@ -156,16 +156,17 @@ def test_manager_role_import(app, admin, ou1, role_ou1, ou2, role_ou2):
     assert Role.objects.filter(ou=ou1).count() == 4
 
     # in case ous are present in export file, they must not be imported
     export['ous'] = [{
         "uuid": "27255f404cb140df9a577da76b59f285",
         "slug": "should_not_exist",
         "name": "should_not_exist",
     }]
+    resp = app.get('/manage/roles/')  # unselect ou1
     resp = resp.click('Import')
     resp.form['site_json'] = Upload('export.json', json.dumps(export).encode(), 'application/json')
     resp = resp.form.submit().follow()
 
     assert not OrganizationalUnit.objects.filter(slug="should_not_exist").exists()
 
 
 def test_manager_role_import_single_ou(app, admin, simple_role):
@@ -183,8 +184,16 @@ def test_manager_role_import_single_ou(app, admin, simple_role):
     assert not 'Organizational unit' in resp.text
     assert resp.form['ou'].attrs['type'] == 'hidden'
 
     resp.form['site_json'] = Upload('export.json', json.dumps(export).encode(), 'application/json')
     resp = resp.form.submit().follow()
 
     imported_role = Role.objects.get(slug=simple_role.slug)
     assert imported_role.ou == simple_role.ou
+
+
+def test_manager_role_import_selected_ou(app, admin, ou1, ou2):
+    response = login(app, admin, 'a2-manager-roles')
+    response.form.set('search-ou', ou2.pk)
+    response = response.form.submit()
+    response = response.click('Import')
+    assert response.pyquery.find('select#id_ou option[selected]')[0].text == 'OU2'
-- 
2.28.0

