Projet

Général

Profil

0001-manager-always-check-role-s-name-uniqueness-33944.patch

Benjamin Dauvergne, 03 juillet 2019 10:09

Télécharger (5,59 ko)

Voir les différences:

Subject: [PATCH 1/2] manager: always check role's name uniqueness (#33944)

 src/authentic2/a2_rbac/models.py | 27 +++++++++++++++++++--------
 src/authentic2/manager/forms.py  | 19 +++----------------
 tests/test_role_manager.py       | 32 ++++++++++++++++++++++++++++++++
 3 files changed, 54 insertions(+), 24 deletions(-)
src/authentic2/a2_rbac/models.py
27 27
                                CHANGE_OP, Operation)
28 28
from django_rbac import utils as rbac_utils
29 29

  
30
from authentic2.decorators import errorcollector
31

  
30 32
try:
31 33
    from django.contrib.contenttypes.fields import GenericForeignKey, \
32 34
        GenericRelation
......
213 215
            self_administered=True)
214 216
        return admin_role
215 217

  
216
    def clean(self):
217
        super(Role, self).clean()
218
        if not self.service and not self.admin_scope_ct_id:
219
            if not self.id and self.__class__.objects.filter(
220
                    name=self.name, ou=self.ou):
221
                raise ValidationError(
222
                    {'name': _('This name is not unique over this '
223
                               'organizational unit.')})
218
    def validate_unique(self, exclude=None):
219
        errors = {}
220

  
221
        with errorcollector(errors):
222
            super(Role, self).validate_unique(exclude=exclude)
223

  
224
        exclude = exclude or []
225

  
226
        if 'name' not in exclude:
227
            qs = self.__class__.objects.filter(name=self.name, ou=self.ou)
228
            if self.pk:
229
                qs = qs.exclude(pk=self.pk)
230
            if qs.exists():
231
                errors.setdefault('name', []).append(_('Name already used'))
232

  
233
        if errors:
234
            raise ValidationError(errors)
224 235

  
225 236
    def save(self, *args, **kwargs):
226 237
        # Service roles can only be part of the same ou as the service
src/authentic2/manager/forms.py
241 241
                raise forms.ValidationError({
242 242
                    'email': _('Email already used.')
243 243
                })
244
        return super(UserEditForm, self).clean()
244 245

  
245 246
    class Meta:
246 247
        model = User
......
437 438
        if utils.get_ou_count() < 2:
438 439
            del self.fields['ou']
439 440

  
440
    def save(self, *args, **kwargs):
441
    def clean(self):
441 442
        if 'ou' not in self.fields:
442 443
            self.instance.ou = get_default_ou()
443
        return super(HideOUFieldMixin, self).save(*args, **kwargs)
444
        return super(HideOUFieldMixin, self).clean()
444 445

  
445 446

  
446 447
class OUSearchForm(FormWithRequest):
......
650 651
    ou = forms.ModelChoiceField(queryset=get_ou_model().objects,
651 652
                                required=True, label=_('Organizational unit'))
652 653

  
653
    def clean_name(self):
654
        qs = get_role_model().objects.all()
655
        if self.instance and self.instance.pk:
656
            qs = qs.exclude(pk=self.instance.pk)
657
        ou = self.cleaned_data.get('ou')
658
        # Test unicity of name for an OU and globally if no OU is present
659
        name = self.cleaned_data.get('name')
660
        if name and ou:
661
            query = Q(name=name) & (Q(ou__isnull=True) | Q(ou=ou))
662
            if qs.filter(query).exists():
663
                raise ValidationError(
664
                    {'name': _('This name is not unique over this organizational unit.')})
665
        return name
666

  
667 654
    class Meta:
668 655
        model = get_role_model()
669 656
        fields = ('name', 'ou', 'description')
tests/test_role_manager.py
35 35
    assert export.keys() == ['roles']
36 36
    assert len(export['roles']) == 1
37 37
    assert export['roles'][0]['slug'] == 'role_ou1'
38

  
39

  
40
def test_manager_role_name_uniqueness_single_ou(app, admin):
41
    response = login(app, admin, 'a2-manager-roles')
42

  
43
    response = response.click('Add')
44
    response.form.set('name', 'Role1')
45
    response = response.form.submit('Save').follow()
46
    response = response.click('Roles')
47
    assert response.pyquery('td.name').text() == 'Role1'
48

  
49
    response = response.click('Add')
50
    response.form.set('name', 'Role1')
51
    response = response.form.submit('Save')
52
    assert response.pyquery('.errorlist').eq(1).text() == 'Name already used'
53

  
54

  
55
def test_manager_role_name_uniqueness_multiple_ou(app, admin, ou1):
56
    response = login(app, admin, 'a2-manager-roles')
57

  
58
    response = response.click('Add')
59
    response.form.set('ou', str(ou1.id))
60
    response.form.set('name', 'Role1')
61
    response = response.form.submit('Save').follow()
62
    response = response.click('Roles')
63
    assert response.pyquery('td.name').text() == 'Role1'
64

  
65
    response = response.click('Add')
66
    response.form.set('ou', str(ou1.id))
67
    response.form.set('name', 'Role1')
68
    response = response.form.submit('Save')
69
    assert response.pyquery('.errorlist').eq(1).text() == 'Name already used'
38
-