mirror of
https://github.com/ansible/awx.git
synced 2026-05-20 15:27:47 -02:30
Added accessible_by/objects support for Team
This commit is contained in:
@@ -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])})
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user