Projet

Général

Profil

0001-manager-allow-importing-roles-from-different-OUs-588.patch

Valentin Deniaud, 08 décembre 2021 14:50

Télécharger (8,83 ko)

Voir les différences:

Subject: [PATCH] manager: allow importing roles from different OUs (#58826)

 src/authentic2/data_transfer.py      | 11 +++++-
 src/authentic2/manager/forms.py      |  9 +----
 src/authentic2/manager/role_views.py | 18 ++++++---
 tests/test_role_manager.py           | 56 ++++++++++++++++++++--------
 4 files changed, 64 insertions(+), 30 deletions(-)
src/authentic2/data_transfer.py
158 158
        role_attributes_update=True,
159 159
        ou_delete_orphans=False,
160 160
        set_ou=None,
161
        allowed_ous=None,
161 162
    ):
162 163
        self.import_roles = import_roles
163 164
        self.import_ous = import_ous
......
167 168
        self.role_permissions_update = role_permissions_update
168 169
        self.role_attributes_update = role_attributes_update
169 170
        self.set_ou = set_ou
171
        self.allowed_ous = allowed_ous
170 172

  
171 173

  
172 174
def wraps_validationerror(func):
......
210 212
        if self._import_context.set_ou:
211 213
            ou = self._import_context.set_ou
212 214
            has_ou = True
213
        else:
215
        elif 'ou' in self._role_d:
214 216
            ou_d = self._role_d['ou']
215 217
            has_ou = bool(ou_d)
216 218
            ou = None if not has_ou else search_ou(ou_d)
217 219
            if has_ou and not ou:
218 220
                raise ValidationError(_("Can't import role because missing Organizational Unit: %s") % ou_d)
221
            if self._import_context.allowed_ous and ou not in self._import_context.allowed_ous:
222
                raise ValidationError(
223
                    _("Can't import role because missing permissions on Organizational Unit: %s") % ou_d
224
                )
225
        else:
226
            name = self._role_d.get('name') or self._role_d.get('slug') or self._role_d.get('uuid')
227
            raise ValidationError(_("Missing Organizational Unit for role: %s") % name)
219 228

  
220 229
        obj = search_role(self._role_d, ou=self._import_context.set_ou)
221 230

  
src/authentic2/manager/forms.py
691 691
class RolesImportForm(LimitQuerysetFormMixin, SiteImportForm):
692 692
    file_field_label = _('Roles Export File')
693 693

  
694
    def __init__(self, *args, **kwargs):
695
        super().__init__(*args, **kwargs)
696
        if utils.get_ou_count() < 2:
697
            self.fields['ou'].widget = forms.HiddenInput()
698

  
699 694
    ou = forms.ModelChoiceField(
700
        label=_('Organizational unit'),
695
        required=False,
696
        label=_('Force organizational unit'),
701 697
        queryset=OrganizationalUnit.objects,
702
        initial=lambda: get_default_ou().pk,
703 698
    )
704 699

  
705 700

  
src/authentic2/manager/role_views.py
664 664
    def form_valid(self, form):
665 665
        self.ou = form.cleaned_data['ou']
666 666
        try:
667
            context = data_transfer.ImportContext(import_ous=False, set_ou=self.ou)
667
            context = data_transfer.ImportContext(
668
                import_ous=False, set_ou=self.ou, allowed_ous=set(form.fields['ou'].queryset)
669
            )
668 670
            with transaction.atomic():
669 671
                data_transfer.import_site(form.cleaned_data['site_json'], context)
670 672
        except ValidationError as e:
......
674 676
        return super().form_valid(form)
675 677

  
676 678
    def get_success_url(self):
677
        messages.success(
678
            self.request,
679
            _('Roles have been successfully imported inside "%s" organizational unit.') % self.ou,
680
        )
681
        return reverse('a2-manager-roles') + '?search-ou=%s' % self.ou.pk
679
        if self.ou:
680
            message = _('Roles have been successfully imported inside "%s" organizational unit.') % self.ou
681
            querystring = '?search-ou=%s' % self.ou.pk
682
        else:
683
            message = _('Roles have been successfully imported.')
684
            querystring = ''
685

  
686
        messages.success(self.request, message)
687
        return reverse('a2-manager-roles') + querystring
682 688

  
683 689

  
684 690
roles_import = RolesImportView.as_view()
tests/test_role_manager.py
138 138
    assert not 'ous' in export
139 139
    Role.objects.filter(ou__in=[ou1, ou2]).delete()
140 140

  
141
    # import in OUs specified in export file
141 142
    resp = app.get('/manage/roles/')
142 143
    resp = resp.click('Import')
143 144
    resp.form['site_json'] = Upload('export.json', json.dumps(export).encode(), 'application/json')
144 145
    resp = resp.form.submit().follow()
145 146

  
147
    assert Role.objects.filter(name=role_ou1.name, ou=ou1).exists()
148
    assert Role.objects.filter(name=role_ou2.name, ou=ou2).exists()
149
    Role.objects.filter(ou__in=[ou1, ou2]).delete()
150

  
151
    # import in custom OU
152
    resp = app.get('/manage/roles/')
153
    resp = resp.click('Import')
154
    resp.form['site_json'] = Upload('export.json', json.dumps(export).encode(), 'application/json')
155
    resp.form['ou'] = get_default_ou().pk
156
    resp = resp.form.submit().follow()
157

  
146 158
    assert Role.objects.filter(name=role_ou1.name, ou=get_default_ou()).exists()
147 159
    assert Role.objects.filter(name=role_ou2.name, ou=get_default_ou()).exists()
148 160

  
......
155 167
    assert new_export['roles'][0]['uuid'] == export['roles'][0]['uuid']
156 168
    assert new_export['roles'][1]['uuid'] == export['roles'][1]['uuid']
157 169

  
170
    # import in custom OU while roles exist in another OU
158 171
    resp = app.get('/manage/roles/')
159 172
    resp = resp.click('Import')
160 173
    resp.form['site_json'] = Upload('export.json', json.dumps(export).encode(), 'application/json')
......
176 189
    resp = app.get('/manage/roles/')  # unselect ou1
177 190
    resp = resp.click('Import')
178 191
    resp.form['site_json'] = Upload('export.json', json.dumps(export).encode(), 'application/json')
192
    resp.form['ou'] = get_default_ou().pk
179 193
    resp = resp.form.submit().follow()
180 194

  
181 195
    assert not OrganizationalUnit.objects.filter(slug="should_not_exist").exists()
182 196

  
183

  
184
def test_manager_role_import_single_ou(app, admin, simple_role):
185
    assert OrganizationalUnit.objects.count() == 1
186
    response = login(app, admin, 'a2-manager-roles')
187

  
188
    export_response = response.click('Export')
189
    export = export_response.json
190

  
191
    assert len(export['roles']) == 1
192
    simple_role.delete()
193

  
197
    # missing ou in export file
198
    export = {"roles": [{"slug": "agent", "name": "Agent"}]}
194 199
    resp = app.get('/manage/roles/')
195 200
    resp = resp.click('Import')
196
    assert not 'Organizational unit' in resp.text
197
    assert resp.form['ou'].attrs['type'] == 'hidden'
201
    resp.form['site_json'] = Upload('export.json', json.dumps(export).encode(), 'application/json')
202
    resp = resp.form.submit()
203
    assert 'Missing Organizational Unit for role: Agent' in resp.text
198 204

  
205
    resp.form['ou'] = get_default_ou().pk
199 206
    resp.form['site_json'] = Upload('export.json', json.dumps(export).encode(), 'application/json')
200 207
    resp = resp.form.submit().follow()
201

  
202
    imported_role = Role.objects.get(slug=simple_role.slug)
203
    assert imported_role.ou == simple_role.ou
208
    assert Role.objects.get(slug='agent')
204 209

  
205 210

  
206 211
def test_manager_role_import_selected_ou(app, admin, ou1, ou2):
......
211 216
    assert response.pyquery.find('select#id_ou option[selected]')[0].text == 'OU2'
212 217

  
213 218

  
219
def test_manager_role_import_ou_permission(app, admin, ou1, role_ou1, ou2, role_ou2, admin_ou1):
220
    resp = login(app, admin, 'a2-manager-roles')
221
    resp = resp.click('Export')
222
    export = resp.json
223
    assert len(export['roles']) == 2
224
    role_ou1.delete()
225
    role_ou2.delete()
226
    app.session.flush()  # logout
227

  
228
    resp = login(app, admin_ou1, 'a2-manager-roles')
229
    resp = resp.click('Import')
230
    resp.form['ou'] = ''
231
    resp.form['site_json'] = Upload('export.json', json.dumps(export).encode(), 'application/json')
232
    resp = resp.form.submit()
233

  
234
    # importing fails because user has no permission on ou2
235
    assert 'missing permissions on Organizational Unit' in resp.text
236

  
237

  
214 238
def test_manager_role_add_selected_ou(app, admin, ou1, ou2):
215 239
    response = login(app, admin, '/manage/roles/')
216 240
    response = response.click('Add role')
217
-