0001-role-api-add-extra-role-attributes-21488.patch
src/authentic2/api_views.py | ||
---|---|---|
22 | 22 |
from rest_framework.exceptions import PermissionDenied, AuthenticationFailed |
23 | 23 |
from rest_framework.fields import CreateOnlyDefault |
24 | 24 |
from rest_framework.decorators import list_route, detail_route |
25 |
from rest_framework.utils import model_meta |
|
25 | 26 | |
26 | 27 |
from django_filters.rest_framework import FilterSet |
27 | 28 | |
28 | 29 |
from .custom_user.models import User |
29 | 30 |
from . import utils, decorators, attribute_kinds, app_settings, hooks |
30 | 31 |
from .models import Attribute, PasswordReset |
32 |
from .a2_rbac.models import RoleAttribute |
|
31 | 33 |
from .a2_rbac.utils import get_default_ou |
32 | 34 | |
33 | 35 | |
... | ... | |
444 | 446 |
exclude = ('date_joined', 'user_permissions', 'groups', 'last_login') |
445 | 447 | |
446 | 448 | |
449 |
class RoleAttributeSerializer(serializers.ModelSerializer): |
|
450 |
class Meta: |
|
451 |
model = RoleAttribute |
|
452 |
fields = ('name', 'kind', 'value') |
|
453 | ||
454 | ||
447 | 455 |
class RoleSerializer(serializers.ModelSerializer): |
448 | 456 |
ou = serializers.SlugRelatedField( |
449 | 457 |
many=False, |
... | ... | |
451 | 459 |
default=CreateOnlyDefault(get_default_ou), |
452 | 460 |
queryset=get_ou_model().objects.all(), |
453 | 461 |
slug_field='slug') |
462 |
role_attributes = RoleAttributeSerializer( |
|
463 |
many=True, |
|
464 |
read_only=False, |
|
465 |
required=False) |
|
454 | 466 | |
455 | 467 |
@property |
456 | 468 |
def user(self): |
... | ... | |
463 | 475 | |
464 | 476 |
def create(self, validated_data): |
465 | 477 |
ou = validated_data.get('ou') |
478 |
if 'role_attributes' in validated_data: |
|
479 |
role_attributes_data = validated_data.pop('role_attributes') |
|
480 |
else: |
|
481 |
role_attributes_data = () |
|
466 | 482 |
# Creating roles also means being allowed to within the OU: |
467 | 483 |
if not self.user.has_ou_perm('a2_rbac.add_role', ou): |
468 | 484 |
raise PermissionDenied(u'User %s can\'t create role in OU %s' % (self.user, ou)) |
469 |
return super(RoleSerializer, self).create(validated_data) |
|
485 | ||
486 |
instance = self.Meta.model.objects.create(**validated_data) |
|
487 | ||
488 |
# Create additional RoleAttribute objects: |
|
489 |
for attribute_data in role_attributes_data: |
|
490 |
RoleAttribute.objects.create(role=instance, **attribute_data) |
|
491 |
return instance |
|
470 | 492 | |
471 | 493 |
def update(self, instance, validated_data): |
472 | 494 |
# Check role-updating permissions: |
... | ... | |
484 | 506 | |
485 | 507 |
class Meta: |
486 | 508 |
model = get_role_model() |
487 |
fields = ('uuid', 'name', 'slug', 'ou',) |
|
509 |
fields = ('uuid', 'name', 'slug', 'ou', 'role_attributes')
|
|
488 | 510 |
extra_kwargs = {'uuid': {'read_only': True}} |
489 | 511 | |
490 | 512 |
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 | ||
---|---|---|
10 | 10 |
from django.contrib.auth import get_user_model |
11 | 11 |
from django.contrib.contenttypes.models import ContentType |
12 | 12 |
from authentic2.a2_rbac.utils import get_default_ou |
13 |
from authentic2.a2_rbac.models import RoleAttribute |
|
13 | 14 |
from django_rbac.utils import get_role_model, get_ou_model |
14 | 15 |
from django_rbac.models import SEARCH_OP |
15 | 16 |
from authentic2.models import Service |
... | ... | |
18 | 19 | |
19 | 20 |
from authentic2_idp_oidc.models import OIDCClient |
20 | 21 | |
22 | ||
21 | 23 |
from utils import login, basic_authorization_header, get_link_from_mail |
22 | 24 | |
23 | 25 |
pytestmark = pytest.mark.django_db |
... | ... | |
767 | 769 |
assert role.ou.slug == role_data['ou'] |
768 | 770 | |
769 | 771 | |
772 |
def test_api_role_extra_attributes(app, admin_ou1, ou1): |
|
773 |
app.authorization = ('Basic', (admin_ou1.username, admin_ou1.username)) |
|
774 | ||
775 |
role_data = { |
|
776 |
'slug': 'coffee-manager', |
|
777 |
'name': 'Coffee Manager', |
|
778 |
'ou': 'ou1', |
|
779 |
'role_attributes': [{ |
|
780 |
'name': 'details', |
|
781 |
'kind': 'string', |
|
782 |
'value': 'nodetails' |
|
783 |
}, |
|
784 |
{ |
|
785 |
'name': 'emails', |
|
786 |
'kind': 'string', |
|
787 |
'value': 'foo@email.none' |
|
788 |
}] |
|
789 |
} |
|
790 |
resp = app.post_json('/api/roles/', params=role_data) |
|
791 |
assert isinstance(resp.json, dict) |
|
792 | ||
793 |
uuid = resp.json['uuid'] |
|
794 |
role = get_role_model().objects.get(uuid=uuid) |
|
795 |
role_attributes = RoleAttribute.objects.filter(role=role) |
|
796 | ||
797 |
# Check extra role attributes : |
|
798 |
assert len(role_attributes) == 2 |
|
799 | ||
800 | ||
770 | 801 |
def test_api_post_role_no_ou(app, superuser): |
771 | 802 |
app.authorization = ('Basic', (superuser.username, superuser.username)) |
772 | 803 |
Role = get_role_model() |
... | ... | |
803 | 834 |
assert resp.json['ou'] == 'ou_rando' |
804 | 835 | |
805 | 836 | |
837 |
def test_api_get_role_attributes(app, admin_rando_role, role_random, role_attribute_details, role_attribute_emails): |
|
838 |
app.authorization = ('Basic', (admin_rando_role.username, admin_rando_role.username)) |
|
839 |
resp = app.get('/api/roles/{}/'.format(role_random.uuid)) |
|
840 | ||
841 |
assert len(RoleAttribute.objects.filter(role=role_random)) == 2 |
|
842 | ||
843 | ||
806 | 844 |
def test_api_get_role_not_found(app, superuser): |
807 | 845 |
app.authorization = ('Basic', (superuser.username, superuser.username)) |
808 | 846 |
app.get('/api/roles/thisisnotavalidroleslug/', status=404) |
809 |
- |