Added accessible_by/objects support for Team

This commit is contained in:
Wayne Witzel III
2016-03-24 10:45:49 -04:00
parent 9d5d3b4131
commit 20aa8c02d1
3 changed files with 50 additions and 7 deletions

View File

@@ -2,11 +2,14 @@
from django.db import models from django.db import models
from django.db.models.aggregates import Max from django.db.models.aggregates import Max
from django.contrib.contenttypes.fields import GenericRelation from django.contrib.contenttypes.fields import GenericRelation
from django.contrib.contenttypes.models import ContentType
from django.contrib.auth.models import User # noqa
# AWX # AWX
from awx.main.models.rbac import ( from awx.main.models.rbac import (
get_user_permissions_on_resource, get_user_permissions_on_resource,
get_role_permissions_on_resource, get_role_permissions_on_resource,
Role,
) )
@@ -20,7 +23,7 @@ class ResourceMixin(models.Model):
role_permissions = GenericRelation('main.RolePermission') role_permissions = GenericRelation('main.RolePermission')
@classmethod @classmethod
def accessible_objects(cls, user, permissions): def accessible_objects(cls, accessor, permissions):
''' '''
Use instead of `MyModel.objects` when you want to only consider Use instead of `MyModel.objects` when you want to only consider
resources that a user has specific permissions for. For example: resources that a user has specific permissions for. For example:
@@ -32,13 +35,22 @@ class ResourceMixin(models.Model):
performant to resolve the resource in question then call performant to resolve the resource in question then call
`myresource.get_permissions(user)`. `myresource.get_permissions(user)`.
''' '''
return ResourceMixin._accessible_objects(cls, user, permissions) return ResourceMixin._accessible_objects(cls, accessor, permissions)
@staticmethod @staticmethod
def _accessible_objects(cls, user, permissions): def _accessible_objects(cls, accessor, permissions):
qs = cls.objects.filter( if type(accessor) == User:
role_permissions__role__ancestors__members=user qs = cls.objects.filter(
) role_permissions__role__ancestors__members=accessor
)
else:
accessor_type = ContentType.objects.get_for_model(accessor)
roles = Role.objects.filter(content_type__pk=accessor_type.id,
object_id=accessor.id)
qs = cls.objects.filter(
role_permissions__role__ancestors__in=roles
)
for perm in permissions: for perm in permissions:
qs = qs.annotate(**{'max_' + perm: Max('role_permissions__' + perm)}) qs = qs.annotate(**{'max_' + perm: Max('role_permissions__' + perm)})
qs = qs.filter(**{'max_' + perm: int(permissions[perm])}) qs = qs.filter(**{'max_' + perm: int(permissions[perm])})

View File

@@ -16,6 +16,7 @@ from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.contenttypes.fields import GenericForeignKey
# AWX # AWX
from django.contrib.auth.models import User # noqa
from awx.main.models.base import * # noqa from awx.main.models.base import * # noqa
__all__ = [ __all__ = [
@@ -195,10 +196,17 @@ def get_user_permissions_on_resource(resource, user):
access. access.
''' '''
if type(user) == User:
roles = user.roles.all()
else:
accessor_type = ContentType.objects.get_for_model(user)
roles = Role.objects.filter(content_type__pk=accessor_type.id,
object_id=user.id)
qs = RolePermission.objects.filter( qs = RolePermission.objects.filter(
content_type=ContentType.objects.get_for_model(resource), content_type=ContentType.objects.get_for_model(resource),
object_id=resource.id, object_id=resource.id,
role__ancestors__in=user.roles.all() role__ancestors__in=roles,
) )
res = qs = qs.aggregate( res = qs = qs.aggregate(

View File

@@ -1,6 +1,7 @@
import pytest import pytest
from awx.main.access import TeamAccess from awx.main.access import TeamAccess
from awx.main.models import Project
@pytest.mark.django_db @pytest.mark.django_db
def test_team_access_superuser(team, user): def test_team_access_superuser(team, user):
@@ -48,3 +49,25 @@ def test_team_access_member(organization, team, user):
assert len(t.member_role.members.all()) == 1 assert len(t.member_role.members.all()) == 1
assert len(t.organization.admin_role.members.all()) == 0 assert len(t.organization.admin_role.members.all()) == 0
@pytest.mark.django_db
def test_team_accessible_by(team, user, project):
u = user('team_member', False)
team.member_role.children.add(project.member_role)
assert project.accessible_by(team, {'read':True})
assert not project.accessible_by(u, {'read':True})
team.member_role.members.add(u)
assert project.accessible_by(u, {'read':True})
@pytest.mark.django_db
def test_team_accessible_objects(team, user, project):
u = user('team_member', False)
team.member_role.children.add(project.member_role)
assert len(Project.accessible_objects(team, {'read':True})) == 1
assert not Project.accessible_objects(u, {'read':True})
team.member_role.members.add(u)
assert len(Project.accessible_objects(u, {'read':True})) == 1