From eac6cca61dfbb0095f50c94fd7dd7f98295ff617 Mon Sep 17 00:00:00 2001
From: Nicolas ROCHE <nroche@entrouvert.com>
Date: Tue, 22 Sep 2020 12:35:31 +0200
Subject: [PATCH] manager: allow ou slug edition (#46655)

---
 src/authentic2/manager/forms.py    |  2 +-
 src/authentic2/manager/ou_views.py |  5 +++++
 tests/test_manager.py              | 10 ++++++++++
 3 files changed, 16 insertions(+), 1 deletion(-)

diff --git a/src/authentic2/manager/forms.py b/src/authentic2/manager/forms.py
index 3e5dbd25..0635479d 100644
--- a/src/authentic2/manager/forms.py
+++ b/src/authentic2/manager/forms.py
@@ -617,17 +617,17 @@ class RoleEditForm(SlugMixin, HideOUFieldMixin, LimitQuerysetFormMixin, CssClass
 class OUEditForm(SlugMixin, CssClass, forms.ModelForm):
     def __init__(self, *args, **kwargs):
         super(OUEditForm, self).__init__(*args, **kwargs)
         self.fields['name'].label = _('label').title()
 
     class Meta:
         model = get_ou_model()
         fields = (
-            'name', 'default', 'username_is_unique', 'email_is_unique', 'validate_emails',
+            'name', 'slug', 'default', 'username_is_unique', 'email_is_unique', 'validate_emails',
             'show_username', 'user_can_reset_password', 'user_add_password_policy',
             'clean_unused_accounts_alert', 'clean_unused_accounts_deletion'
         )
 
 
 def get_role_form_class():
     if app_settings.ROLE_FORM_CLASS:
         return import_module_or_class(app_settings.ROLE_FORM_CLASS)
diff --git a/src/authentic2/manager/ou_views.py b/src/authentic2/manager/ou_views.py
index 8c319c2d..7f3d78d3 100644
--- a/src/authentic2/manager/ou_views.py
+++ b/src/authentic2/manager/ou_views.py
@@ -42,16 +42,21 @@ class OrganizationalUnitView(views.BaseTableView):
 listing = OrganizationalUnitView.as_view()
 
 
 class OrganizationalUnitAddView(views.BaseAddView):
     model = get_ou_model()
     permissions = ['a2_rbac.add_organizationalunit']
     form_class = forms.OUEditForm
     title = _('Add organizational unit')
+    exclude_fields = ('slug',)
+
+    def get_fields(self):
+        return [x for x in self.form_class.base_fields.keys()
+                if x not in self.exclude_fields]
 
     def get_success_url(self):
         return '..'
 
 add = OrganizationalUnitAddView.as_view()
 
 
 class OrganizationalUnitDetailView(views.BaseDetailView):
diff --git a/tests/test_manager.py b/tests/test_manager.py
index bdf6c0fa..20d8e33f 100644
--- a/tests/test_manager.py
+++ b/tests/test_manager.py
@@ -55,16 +55,18 @@ def test_manager_login(superuser_or_admin, app):
     for section in sections:
         path = reverse('a2-manager-%s' % section)
         assert manager_home_page.pyquery.remove_namespaces()('.apps a[href=\'%s\']' % path)
 
 
 def test_manager_create_ou(superuser_or_admin, app):
     ou_add = login(app, superuser_or_admin, path=reverse('a2-manager-ou-add'))
     form = ou_add.form
+    with pytest.raises(AssertionError):
+        form.get('slug')
     form.set('name', 'New OU')
     response = form.submit().follow()
     assert 'New OU' in response
     assert OU.objects.count() == 2
     assert OU.objects.get(name='New OU').slug == 'new-ou'
 
     # Test slug collision
     OU.objects.filter(name='New OU').update(name='Old OU')
@@ -760,16 +762,24 @@ def test_manager_ou(app, superuser_or_admin, ou1):
     assert old_default_detail_page.pyquery('input[name="default"][checked="checked"]')
     # check ou homepage has changed too
     ou_homepage = old_default_detail_page.click('Organizational unit')
     assert set([e.text for e in ou_homepage.pyquery('td.name')]) == set(['Default organizational unit', 'ou2'])
     assert len(ou_homepage.pyquery('span.true')) == 1
     assert len(ou_homepage.pyquery('tr[data-pk="%s"] td.default span.true' % ou2.pk)) == 0
     assert len(ou_homepage.pyquery('tr[data-pk="%s"] td.default span.true' % old_default.pk)) == 1
 
+    # edit ou slug
+    assert OU.objects.get(name='ou2').slug == 'ou2'
+    ou2_detail_page = app.get(reverse('a2-manager-ou-edit', kwargs={'pk': ou2.pk}))
+    assert ou2_detail_page.html.find('label', {'for': 'id_slug'})
+    ou2_detail_page.form.set('slug', 'new-ou2-slug')
+    ou_homepage = ou2_detail_page.form.submit().follow()
+    assert OU.objects.get(name='ou2').slug == 'new-ou2-slug'
+
 
 def test_return_on_logout(superuser, app):
     '''Verify we will return to /manage/ after logout/login cycle'''
     manager_home_page = login(app, superuser, reverse('a2-manager-homepage'))
     response = manager_home_page.click(href='logout').maybe_follow()
     assert response.request.query_string == 'next=/manage/'
 
 
-- 
2.28.0

