0001-WIP-role-api-add-extra-role-attributes-21488.patch
src/authentic2/api_views.py | ||
---|---|---|
28 | 28 |
from .custom_user.models import User |
29 | 29 |
from . import utils, decorators, attribute_kinds, app_settings, hooks |
30 | 30 |
from .models import Attribute, PasswordReset |
31 |
from .a2_rbac.models import RoleAttribute |
|
31 | 32 |
from .a2_rbac.utils import get_default_ou |
32 | 33 | |
33 | 34 | |
... | ... | |
444 | 445 |
exclude = ('date_joined', 'user_permissions', 'groups', 'last_login') |
445 | 446 | |
446 | 447 | |
448 |
class RoleAttributeSerializer(serializers.ModelSerializer): |
|
449 |
class Meta: |
|
450 |
model = RoleAttribute |
|
451 |
fields = ('name', 'kind', 'value') |
|
452 | ||
453 | ||
447 | 454 |
class RoleSerializer(serializers.ModelSerializer): |
448 | 455 |
ou = serializers.SlugRelatedField( |
449 | 456 |
many=False, |
... | ... | |
451 | 458 |
default=CreateOnlyDefault(get_default_ou), |
452 | 459 |
queryset=get_ou_model().objects.all(), |
453 | 460 |
slug_field='slug') |
461 |
role_attributes = RoleAttributeSerializer( |
|
462 |
many=True, |
|
463 |
read_only=False, |
|
464 |
required=False) |
|
454 | 465 | |
455 | 466 |
@property |
456 | 467 |
def user(self): |
... | ... | |
466 | 477 |
# Creating roles also means being allowed to within the OU: |
467 | 478 |
if not self.user.has_ou_perm('a2_rbac.add_role', ou): |
468 | 479 |
raise PermissionDenied(u'User %s can\'t create role in OU %s' % (self.user, ou)) |
469 |
return super(RoleSerializer, self).create(validated_data) |
|
480 |
instance = super(RoleSerializer, self).create(validated_data) |
|
481 | ||
482 |
# Create additional RoleAttribute objects: |
|
483 |
if 'role_attributes' in validated_data: |
|
484 |
role_attributes_data = validated_data.pop('role_attributes') |
|
485 |
for role_attribute_data in role_attributes_data: |
|
486 |
RoleAttribute.create(role=instance, **role_attributes_data) |
|
487 |
return instance |
|
470 | 488 | |
471 | 489 |
def update(self, instance, validated_data): |
472 | 490 |
# Check role-updating permissions: |
... | ... | |
484 | 502 | |
485 | 503 |
class Meta: |
486 | 504 |
model = get_role_model() |
487 |
fields = ('uuid', 'name', 'slug', 'ou',) |
|
505 |
fields = ('uuid', 'name', 'slug', 'ou', 'role_attributes')
|
|
488 | 506 |
extra_kwargs = {'uuid': {'read_only': True}} |
489 | 507 | |
490 | 508 |
tests/conftest.py | ||
---|---|---|
13 | 13 |
from pytest_django.migrations import DisableMigrations |
14 | 14 | |
15 | 15 |
from authentic2.a2_rbac.utils import get_default_ou |
16 |
from authentic2.a2_rbac.models import RoleAttribute |
|
16 | 17 |
from authentic2_idp_oidc.models import OIDCClient |
17 | 18 |
from authentic2.authentication import OIDCUser |
18 | 19 | |
... | ... | |
144 | 145 |
return Role.objects.create(name='rando', slug='rando', ou=ou_rando) |
145 | 146 | |
146 | 147 | |
148 |
@pytest.fixture |
|
149 |
def role_attribute_details(db, role_random): |
|
150 |
return RoleAttribute.objects.create(role=role_random, name='details', |
|
151 |
kind='string', value='list') |
|
152 | ||
153 | ||
154 |
@pytest.fixture |
|
155 |
def role_attribute_emails(db, role_random): |
|
156 |
return RoleAttribute.objects.create(role=role_random, name='emails', |
|
157 |
kind='string', value='list') |
|
158 | ||
159 | ||
147 | 160 |
@pytest.fixture |
148 | 161 |
def role_ou1(db, ou1): |
149 | 162 |
return Role.objects.create(name='role_ou1', slug='role_ou1', ou=ou1) |
tests/test_api.py | ||
---|---|---|
767 | 767 |
assert role.ou.slug == role_data['ou'] |
768 | 768 | |
769 | 769 | |
770 |
def test_api_role_extra_attributes(app, admin_ou1, ou1): |
|
771 |
app.authorization = ('Basic', (admin_ou1.username, admin_ou1.username)) |
|
772 | ||
773 |
role_data = { |
|
774 |
'slug': 'coffee-manager', |
|
775 |
'name': 'Coffee Manager', |
|
776 |
'ou': 'ou1', |
|
777 |
'role_attributes': ({ |
|
778 |
'name': 'details', |
|
779 |
'kind': 'string', |
|
780 |
'value': 'nodetails' |
|
781 |
}, |
|
782 |
{ |
|
783 |
'name': 'emails', |
|
784 |
'kind': 'string', |
|
785 |
'value': 'foo@email.none' |
|
786 |
}) |
|
787 |
} |
|
788 |
resp = app.post_json('/api/roles/', params=role_data) |
|
789 |
assert isinstance(resp.json, dict) |
|
790 |
uuid = resp.json['uuid'] |
|
791 | ||
792 |
# Check attributes values against the DB: |
|
793 |
role = get_role_model().objects.get(uuid=uuid) |
|
794 |
assert role.slug == role_data['slug'] |
|
795 |
assert role.name == role_data['name'] |
|
796 |
assert role.ou.slug == role_data['ou'] |
|
797 | ||
798 | ||
770 | 799 |
def test_api_post_role_no_ou(app, superuser): |
771 | 800 |
app.authorization = ('Basic', (superuser.username, superuser.username)) |
772 | 801 |
Role = get_role_model() |
... | ... | |
803 | 832 |
assert resp.json['ou'] == 'ou_rando' |
804 | 833 | |
805 | 834 | |
835 |
def test_api_get_role_attributes(app, admin_rando_role, role_random, role_attribute_details, role_attribute_emails): |
|
836 |
app.authorization = ('Basic', (admin_rando_role.username, admin_rando_role.username)) |
|
837 |
resp = app.get('/api/roles/{}/'.format(role_random.uuid)) |
|
838 | ||
839 |
assert len(RoleAttribute.objects.filter(role=role_random)) == 2 |
|
840 | ||
841 | ||
806 | 842 |
def test_api_get_role_not_found(app, superuser): |
807 | 843 |
app.authorization = ('Basic', (superuser.username, superuser.username)) |
808 | 844 |
app.get('/api/roles/thisisnotavalidroleslug/', status=404) |
809 |
- |