api: include roles in users API (#25645)
gitea/authentic/pipeline/head Build started... Details

This commit is contained in:
Paul Marillonnet 2018-08-30 14:51:56 +02:00 committed by Benjamin Dauvergne
parent 09b618d997
commit 838f38cf72
2 changed files with 101 additions and 45 deletions

View File

@ -310,6 +310,55 @@ def attributes_hash(attributes):
return hash(tuple((at.name, at.required) for at in attributes))
class RoleSerializer(serializers.ModelSerializer):
ou = serializers.SlugRelatedField(
many=False,
required=False,
default=CreateOnlyDefault(get_default_ou),
queryset=get_ou_model().objects.all(),
slug_field='slug')
@property
def user(self):
return self.context['request'].user
def __init__(self, instance=None, **kwargs):
super(RoleSerializer, self).__init__(instance, **kwargs)
if self.instance:
self.fields['ou'].read_only = True
def create(self, validated_data):
ou = validated_data.get('ou')
# Creating roles also means being allowed to within the OU:
if not self.user.has_ou_perm('a2_rbac.add_role', ou):
raise PermissionDenied(u'User %s can\'t create role in OU %s' % (self.user, ou))
return super(RoleSerializer, self).create(validated_data)
def update(self, instance, validated_data):
# Check role-updating permissions:
if not self.user.has_perm('a2_rbac.change_role', obj=instance):
raise PermissionDenied(u'User %s can\'t change role %s' % (self.user, instance))
super(RoleSerializer, self).update(instance, validated_data)
return instance
def partial_update(self, instance, validated_data):
# Check role-updating permissions:
if not self.user.has_perm('a2_rbac.change_role', obj=instance):
raise PermissionDenied(u'User %s can\'t change role %s' % (self.user, instance))
super(RoleSerializer, self).partial_update(instance, validated_data)
return instance
class Meta:
model = get_role_model()
fields = ('uuid', 'name', 'slug', 'ou',)
extra_kwargs = {'uuid': {'read_only': True}}
class RoleCustomField(RoleSerializer):
class Meta(RoleSerializer.Meta):
fields = ('uuid', 'name', 'slug',)
class BaseUserSerializer(serializers.ModelSerializer):
ou = serializers.SlugRelatedField(
queryset=get_ou_model().objects.all(),
@ -324,6 +373,7 @@ class BaseUserSerializer(serializers.ModelSerializer):
default=CreateOnlyDefault(utils.generate_password),
required=False)
force_password_reset = serializers.BooleanField(write_only=True, required=False, default=False)
roles = RoleCustomField(many=True, read_only=True, source='roles_and_parents')
def __init__(self, *args, **kwargs):
super(BaseUserSerializer, self).__init__(*args, **kwargs)
@ -452,50 +502,6 @@ class BaseUserSerializer(serializers.ModelSerializer):
exclude = ('date_joined', 'user_permissions', 'groups', 'last_login')
class RoleSerializer(serializers.ModelSerializer):
ou = serializers.SlugRelatedField(
many=False,
required=False,
default=CreateOnlyDefault(get_default_ou),
queryset=get_ou_model().objects.all(),
slug_field='slug')
@property
def user(self):
return self.context['request'].user
def __init__(self, instance=None, **kwargs):
super(RoleSerializer, self).__init__(instance, **kwargs)
if self.instance:
self.fields['ou'].read_only = True
def create(self, validated_data):
ou = validated_data.get('ou')
# Creating roles also means being allowed to within the OU:
if not self.user.has_ou_perm('a2_rbac.add_role', ou):
raise PermissionDenied(u'User %s can\'t create role in OU %s' % (self.user, ou))
return super(RoleSerializer, self).create(validated_data)
def update(self, instance, validated_data):
# Check role-updating permissions:
if not self.user.has_perm('a2_rbac.change_role', obj=instance):
raise PermissionDenied(u'User %s can\'t change role %s' % (self.user, instance))
super(RoleSerializer, self).update(instance, validated_data)
return instance
def partial_update(self, instance, validated_data):
# Check role-updating permissions:
if not self.user.has_perm('a2_rbac.change_role', obj=instance):
raise PermissionDenied(u'User %s can\'t change role %s' % (self.user, instance))
super(RoleSerializer, self).partial_update(instance, validated_data)
return instance
class Meta:
model = get_role_model()
fields = ('uuid', 'name', 'slug', 'ou',)
extra_kwargs = {'uuid': {'read_only': True}}
class UsersFilter(FilterSet):
class Meta:
model = get_user_model()

View File

@ -251,7 +251,7 @@ def test_api_users_create(settings, app, api_user):
if api_user.is_superuser or api_user.roles.exists():
assert set(['ou', 'id', 'uuid', 'is_staff', 'is_superuser', 'first_name', 'last_name',
'date_joined', 'last_login', 'username', 'password', 'email', 'is_active',
'title', 'modified', 'email_verified']) == set(resp.json.keys())
'title', 'modified', 'email_verified', 'roles']) == set(resp.json.keys())
assert resp.json['first_name'] == payload['first_name']
assert resp.json['last_name'] == payload['last_name']
assert resp.json['email'] == payload['email']
@ -944,3 +944,53 @@ def test_validate_password_regex(app, settings):
assert response.json['checks'][3]['result'] is True
assert response.json['checks'][4]['label'] == 'must contain "ok"'
assert response.json['checks'][4]['result'] is True
def test_roles_in_users_api(app, admin):
User = get_user_model()
user1 = User(username='john.doe', email='john.doe@example.com')
user1.set_password('password')
user1.save()
user2 = User(username='bob.smith', email='bob.smith@example.com')
user2.set_password('password')
user2.save()
Role = get_role_model()
role1 = Role.objects.create(name='Role1')
role1.members.add(user1)
role2 = Role.objects.create(name='Role2')
role2.members.add(user1)
role2.members.add(user2)
role2.add_parent(role1)
role3 = Role.objects.create(name='Role3')
role3.members.add(user2)
role3.add_parent(role1)
app.authorization = ('Basic', (admin.username, admin.username))
response = app.get(u'/api/users/', status=200)
assert len(response.json['results']) == 3
for user in response.json['results']:
assert user['roles']
for role in user['roles']:
keys = ['slug', 'name', 'uuid']
for key, value in role.items():
assert key in keys
assert value
keys.remove(key)
url = u'/api/users/%s/' % admin.uuid
response = app.get(url, status=200)
assert len(response.json['roles']) == 4
assert set(role['slug'] for role in response.json['roles']) == set([
'_a2-manager',
'_a2-manager-of-users',
'_a2-manager-of-roles',
'_a2-manager-of-organizational-units'])
for user in [user1, user2]:
url = u'/api/users/%s/' % user.uuid
response = app.get(url, status=200)
roles = user.roles_and_parents().all()
assert len(response.json['roles']) == roles.count()
assert set(role['name'] for role in response.json['roles']) == set(roles.values_list('name', flat=True))