Merge pull request #1265 from anoek/rbac

Various small fixes and progress on making 'old' tests work again on RBAC
This commit is contained in:
Wayne Witzel III
2016-03-18 11:21:10 -04:00
16 changed files with 121 additions and 344 deletions

View File

@@ -299,7 +299,7 @@ class SubListAPIView(ListAPIView, ParentMixin):
parent = self.get_parent_object() parent = self.get_parent_object()
self.check_parent_access(parent) self.check_parent_access(parent)
qs = self.request.user.get_queryset(self.model).distinct() qs = self.request.user.get_queryset(self.model).distinct()
sublist_qs = getattr(parent, self.relationship).distinct() sublist_qs = getattrd(parent, self.relationship).distinct()
return qs & sublist_qs return qs & sublist_qs
class SubListCreateAPIView(SubListAPIView, ListCreateAPIView): class SubListCreateAPIView(SubListAPIView, ListCreateAPIView):

View File

@@ -117,6 +117,7 @@ class ModelAccessPermission(permissions.BasePermission):
check_method = getattr(self, 'check_%s_permissions' % request.method.lower(), None) check_method = getattr(self, 'check_%s_permissions' % request.method.lower(), None)
result = check_method and check_method(request, view, obj) result = check_method and check_method(request, view, obj)
if not result: if not result:
print('Yarr permission denied: %s %s %s' % (request.method, repr(view), repr(obj),)) # TODO: XXX: This shouldn't have been committed but anoek is sloppy, remove me after we're done fixing bugs
raise PermissionDenied() raise PermissionDenied()
return result return result

View File

@@ -274,7 +274,6 @@ v1_urls = patterns('awx.api.views',
url(r'^me/$', 'user_me_list'), url(r'^me/$', 'user_me_list'),
url(r'^dashboard/$', 'dashboard_view'), url(r'^dashboard/$', 'dashboard_view'),
url(r'^dashboard/graphs/jobs/$', 'dashboard_jobs_graph_view'), url(r'^dashboard/graphs/jobs/$', 'dashboard_jobs_graph_view'),
url(r'^dashboard/graphs/inventory/$', 'dashboard_inventory_graph_view'),
url(r'^settings/', include(settings_urls)), url(r'^settings/', include(settings_urls)),
url(r'^schedules/', include(schedule_urls)), url(r'^schedules/', include(schedule_urls)),
url(r'^organizations/', include(organization_urls)), url(r'^organizations/', include(organization_urls)),

View File

@@ -288,8 +288,7 @@ class DashboardView(APIView):
def get(self, request, format=None): def get(self, request, format=None):
''' Show Dashboard Details ''' ''' Show Dashboard Details '''
data = OrderedDict() data = OrderedDict()
data['related'] = {'jobs_graph': reverse('api:dashboard_jobs_graph_view'), data['related'] = {'jobs_graph': reverse('api:dashboard_jobs_graph_view')}
'inventory_graph': reverse('api:dashboard_inventory_graph_view')}
user_inventory = get_user_queryset(request.user, Inventory) user_inventory = get_user_queryset(request.user, Inventory)
inventory_with_failed_hosts = user_inventory.filter(hosts_with_active_failures__gt=0) inventory_with_failed_hosts = user_inventory.filter(hosts_with_active_failures__gt=0)
user_inventory_external = user_inventory.filter(has_inventory_sources=True) user_inventory_external = user_inventory.filter(has_inventory_sources=True)
@@ -435,49 +434,6 @@ class DashboardJobsGraphView(APIView):
element[1]]) element[1]])
return Response(dashboard_data) return Response(dashboard_data)
class DashboardInventoryGraphView(APIView):
view_name = "Dashboard Inventory Graphs"
new_in_200 = True
def get(self, request, format=None):
period = request.query_params.get('period', 'month')
end_date = now()
if period == 'month':
start_date = end_date - dateutil.relativedelta.relativedelta(months=1)
start_date = start_date.replace(hour=0, minute=0, second=0, microsecond=0)
delta = dateutil.relativedelta.relativedelta(days=1)
elif period == 'week':
start_date = end_date - dateutil.relativedelta.relativedelta(weeks=1)
start_date = start_date.replace(hour=0, minute=0, second=0, microsecond=0)
delta = dateutil.relativedelta.relativedelta(days=1)
elif period == 'day':
start_date = end_date - dateutil.relativedelta.relativedelta(days=1)
start_date = start_date.replace(minute=0, second=0, microsecond=0)
delta = dateutil.relativedelta.relativedelta(hours=1)
else:
raise ParseError(u'Unknown period "%s"' % force_text(period))
host_stats = []
date = start_date
while date < end_date:
next_date = date + delta
# Find all hosts that existed at end of intevral that are still
# active or were deleted after the end of interval. Slow but
# accurate; haven't yet found a better way to do it.
hosts_qs = Host.objects.filter(created__lt=next_date)
hosts_qs = hosts_qs.filter(Q(active=True) | Q(active=False, modified__gte=next_date))
hostnames = set()
for name, active in hosts_qs.values_list('name', 'active').iterator():
if not active:
name = re.sub(r'^_deleted_.*?_', '', name)
hostnames.add(name)
host_stats.append((time.mktime(date.timetuple()), len(hostnames)))
date = next_date
return Response({'hosts': host_stats})
class ScheduleList(ListAPIView): class ScheduleList(ListAPIView):
@@ -633,16 +589,16 @@ class OrganizationUsersList(SubListCreateAttachDetachAPIView):
model = User model = User
serializer_class = UserSerializer serializer_class = UserSerializer
parent_model = Organization parent_model = Organization
relationship = 'users' relationship = 'member_role.members'
class OrganizationAdminsList(SubListCreateAttachDetachAPIView): class OrganizationAdminsList(SubListCreateAttachDetachAPIView):
model = User model = User
serializer_class = UserSerializer serializer_class = UserSerializer
parent_model = Organization parent_model = Organization
relationship = 'admins' relationship = 'admin_role.members'
class OrganizationProjectsList(SubListCreateAttachDetachAPIView): class OrganizationProjectsList(SubListCreateAPIView):
model = Project model = Project
serializer_class = ProjectSerializer serializer_class = ProjectSerializer
@@ -725,7 +681,7 @@ class TeamUsersList(SubListCreateAttachDetachAPIView):
model = User model = User
serializer_class = UserSerializer serializer_class = UserSerializer
parent_model = Team parent_model = Team
relationship = 'users' relationship = 'member_role.members'
class TeamRolesList(SubListCreateAttachDetachAPIView): class TeamRolesList(SubListCreateAttachDetachAPIView):
@@ -1481,7 +1437,7 @@ class GroupAllHostsList(SubListAPIView):
def get_queryset(self): def get_queryset(self):
parent = self.get_parent_object() parent = self.get_parent_object()
self.check_parent_access(parent) self.check_parent_access(parent)
qs = self.request.user.get_queryset(self.model) qs = self.request.user.get_queryset(self.model).distinct() # need distinct for '&' operator
sublist_qs = parent.all_hosts.distinct() sublist_qs = parent.all_hosts.distinct()
return qs & sublist_qs return qs & sublist_qs

View File

@@ -7,10 +7,9 @@ import sys
import logging import logging
# Django # Django
from django.db.models import F, Q from django.db.models import Q
from django.contrib.auth.models import User from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.db.models.aggregates import Max
# Django REST Framework # Django REST Framework
from rest_framework.exceptions import ParseError, PermissionDenied from rest_framework.exceptions import ParseError, PermissionDenied
@@ -67,15 +66,7 @@ def user_admin_role(self):
return Role.objects.get(content_type=ContentType.objects.get_for_model(User), object_id=self.id) return Role.objects.get(content_type=ContentType.objects.get_for_model(User), object_id=self.id)
def user_accessible_objects(user, permissions): def user_accessible_objects(user, permissions):
content_type = ContentType.objects.get_for_model(User) return ResourceMixin._accessible_objects(User, user, permissions)
qs = RolePermission.objects.filter(
content_type=content_type,
role__ancestors__members=user
)
for perm in permissions:
qs = qs.annotate(**{'max_' + perm: Max(perm)})
qs = qs.filter(**{'max_' + perm: int(permissions[perm])})
return qs
def user_accessible_by(instance, user, permissions): def user_accessible_by(instance, user, permissions):
perms = get_user_permissions_on_resource(instance, user) perms = get_user_permissions_on_resource(instance, user)
@@ -222,7 +213,7 @@ class UserAccess(BaseAccess):
model = User model = User
def get_queryset(self): def get_queryset(self):
qs = self.model.accessible_objects(self.user, {'read':True}) qs = User.accessible_objects(self.user, {'read':True})
return qs return qs
def can_add(self, data): def can_add(self, data):
@@ -639,7 +630,7 @@ class ProjectAccess(BaseAccess):
def can_add(self, data): def can_add(self, data):
if self.user.is_superuser: if self.user.is_superuser:
return True return True
qs = Organization.accessible_objects(self.uesr, ALL_PERMISSIONS) qs = Organization.accessible_objects(self.user, ALL_PERMISSIONS)
return bool(qs.count() > 0) return bool(qs.count() > 0)
def can_change(self, obj, data): def can_change(self, obj, data):
@@ -813,47 +804,11 @@ class JobAccess(BaseAccess):
qs = qs.prefetch_related('unified_job_template') qs = qs.prefetch_related('unified_job_template')
if self.user.is_superuser: if self.user.is_superuser:
return qs return qs
credential_ids = self.user.get_queryset(Credential) credential_ids = self.user.get_queryset(Credential)
base_qs = qs.filter( return qs.filter(
credential_id__in=credential_ids, credential_id__in=credential_ids,
) job_template__in=JobTemplate.accessible_objects(self.user, {'read': True})
org_admin_ids = base_qs.filter(
Q(project__organizations__admins__in=[self.user]) |
(Q(project__isnull=True) & Q(job_type=PERM_INVENTORY_SCAN) & Q(inventory__organization__admins__in=[self.user]))
)
allowed_deploy = [PERM_JOBTEMPLATE_CREATE, PERM_INVENTORY_DEPLOY]
allowed_check = [PERM_JOBTEMPLATE_CREATE, PERM_INVENTORY_DEPLOY, PERM_INVENTORY_CHECK]
team_ids = Team.objects.filter(users__in=[self.user])
# TODO: I think the below queries can be combined
deploy_permissions_ids = Permission.objects.filter(
Q(user=self.user) | Q(team__in=team_ids),
permission_type__in=allowed_deploy,
)
check_permissions_ids = Permission.objects.filter(
Q(user=self.user) | Q(team__in=team_ids),
permission_type__in=allowed_check,
)
perm_deploy_ids = base_qs.filter(
job_type=PERM_INVENTORY_DEPLOY,
inventory__permissions__in=deploy_permissions_ids,
project__permissions__in=deploy_permissions_ids,
inventory__permissions__pk=F('project__permissions__pk'),
)
perm_check_ids = base_qs.filter(
job_type=PERM_INVENTORY_CHECK,
inventory__permissions__in=check_permissions_ids,
project__permissions__in=check_permissions_ids,
inventory__permissions__pk=F('project__permissions__pk'),
)
return base_qs.filter(
Q(id__in=org_admin_ids) |
Q(id__in=perm_deploy_ids) |
Q(id__in=perm_check_ids)
) )
def can_add(self, data): def can_add(self, data):
@@ -938,21 +893,11 @@ class AdHocCommandAccess(BaseAccess):
return qs return qs
credential_ids = set(self.user.get_queryset(Credential).values_list('id', flat=True)) credential_ids = set(self.user.get_queryset(Credential).values_list('id', flat=True))
team_ids = set(Team.objects.filter( users__in=[self.user]).values_list('id', flat=True)) inventory_qs = Inventory.accessible_objects(self.user, {'read': True, 'execute': True})
permission_ids = set(Permission.objects.filter(
Q(user=self.user) | Q(team__in=team_ids),
permission_type__in=PERMISSION_TYPES_ALLOWING_INVENTORY_READ,
run_ad_hoc_commands=True,
).values_list('id', flat=True))
inventory_qs = self.user.get_queryset(Inventory)
inventory_qs = inventory_qs.filter(Q(permissions__in=permission_ids) | Q(organization__admins__in=[self.user]))
inventory_ids = set(inventory_qs.values_list('id', flat=True))
qs = qs.filter( qs = qs.filter(
credential_id__in=credential_ids, credential_id__in=credential_ids,
inventory_id__in=inventory_ids, inventory__in=inventory_qs,
) )
return qs return qs
@@ -1183,7 +1128,8 @@ class ScheduleAccess(BaseAccess):
if self.user.is_superuser: if self.user.is_superuser:
return True return True
if obj and obj.unified_job_template: if obj and obj.unified_job_template:
return obj.unified_job_template.accessible_by(self.user, {'read':True}) job_class = obj.unified_job_template
return self.user.can_access(type(job_class), 'read', obj.unified_job_template)
else: else:
return False return False
@@ -1193,7 +1139,7 @@ class ScheduleAccess(BaseAccess):
pk = get_pk_from_dict(data, 'unified_job_template') pk = get_pk_from_dict(data, 'unified_job_template')
obj = get_object_or_400(UnifiedJobTemplate, pk=pk) obj = get_object_or_400(UnifiedJobTemplate, pk=pk)
if obj: if obj:
return obj.accessible_by(self.user, {'read':True, 'update':True, 'write':True}) return self.user.can_access(type(obj), 'change', obj, None)
else: else:
return False return False
@@ -1201,7 +1147,8 @@ class ScheduleAccess(BaseAccess):
if self.user.is_superuser: if self.user.is_superuser:
return True return True
if obj and obj.unified_job_template: if obj and obj.unified_job_template:
return obj.unified_job_template.accessible_by(self.user, {'read':True, 'update':True, 'write':True}) job_class = obj.unified_job_template
return self.user.can_access(type(job_class), 'change', job_class, None)
else: else:
return False return False
@@ -1209,7 +1156,8 @@ class ScheduleAccess(BaseAccess):
if self.user.is_superuser: if self.user.is_superuser:
return True return True
if obj and obj.unified_job_template: if obj and obj.unified_job_template:
return obj.unified_job_template.accessible_by(self.user, {'read':True, 'update':True, 'write':True}) job_class = obj.unified_job_template
return self.user.can_access(type(job_class), 'change', job_class, None)
else: else:
return False return False
@@ -1287,10 +1235,6 @@ class ActivityStreamAccess(BaseAccess):
#Project Update Filter #Project Update Filter
qs.filter(project_update__project__in=project_qs) qs.filter(project_update__project__in=project_qs)
#Permission Filter
permission_qs = self.user.get_queryset(Permission)
qs.filter(permission__in=permission_qs)
#Job Template Filter #Job Template Filter
jobtemplate_qs = self.user.get_queryset(JobTemplate) jobtemplate_qs = self.user.get_queryset(JobTemplate)
qs.filter(job_template__in=jobtemplate_qs) qs.filter(job_template__in=jobtemplate_qs)

View File

@@ -243,18 +243,26 @@ class ImplicitRoleField(models.ForeignKey):
def _calc_original_parents(self, instance): def _calc_original_parents(self, instance):
if not hasattr(self, '__original_parent_roles'): if not hasattr(self, '__original_parent_roles'):
setattr(self, '__original_parent_roles', []) # do not just self.__original_parent_roles=[], it's not the same here setattr(self, '__original_parent_roles', set()) # do not just self.__original_parent_roles=[], it's not the same here, apparently.
paths = self.parent_role if type(self.parent_role) is list else [self.parent_role] # NOTE: The above setattr is required to be called bofore
original_parent_roles = set() # _resolve_parent_roles because we can end up recursing, so the enclosing
for path in paths: # if not hasattr protects against this.
if path.startswith("singleton:"): original_parent_roles = self._resolve_parent_roles(instance)
parents = [Role.singleton(path[10:])]
else:
parents = resolve_role_field(instance, path)
for parent in parents:
original_parent_roles.add(parent)
setattr(self, '__original_parent_roles', original_parent_roles) setattr(self, '__original_parent_roles', original_parent_roles)
def _resolve_parent_roles(self, instance):
paths = self.parent_role if type(self.parent_role) is list else [self.parent_role]
parent_roles = set()
for path in paths:
if path.startswith("singleton:"):
parents = [Role.singleton(path[10:])]
else:
parents = resolve_role_field(instance, path)
for parent in parents:
parent_roles.add(parent)
return parent_roles
def _post_save(self, instance, created, *args, **kwargs): def _post_save(self, instance, created, *args, **kwargs):
# Ensure that our field gets initialized after our first save # Ensure that our field gets initialized after our first save
this_role = getattr(instance, self.name) this_role = getattr(instance, self.name)
@@ -269,16 +277,8 @@ class ImplicitRoleField(models.ForeignKey):
self._calc_original_parents(instance) self._calc_original_parents(instance)
return return
paths = self.parent_role if type(self.parent_role) is list else [self.parent_role]
original_parents = getattr(self, '__original_parent_roles') original_parents = getattr(self, '__original_parent_roles')
new_parents = set() new_parents = self._resolve_parent_roles(instance)
for path in paths:
if path.startswith("singleton:"):
parents = [Role.singleton(path[10:])]
else:
parents = resolve_role_field(instance, path)
for parent in parents:
new_parents.add(parent)
with batch_role_ancestor_rebuilding(): with batch_role_ancestor_rebuilding():
for role in original_parents - new_parents: for role in original_parents - new_parents:

View File

@@ -3,6 +3,7 @@
# Django # Django
from django.conf import settings # noqa from django.conf import settings # noqa
from django.contrib.contenttypes.fields import GenericRelation
# AWX # AWX
from awx.main.models.base import * # noqa from awx.main.models.base import * # noqa
@@ -38,11 +39,13 @@ _PythonSerializer.handle_m2m_field = _new_handle_m2m_field
from django.contrib.auth.models import User # noqa from django.contrib.auth.models import User # noqa
from awx.main.access import * # noqa from awx.main.access import * # noqa
User.add_to_class('get_queryset', get_user_queryset) User.add_to_class('get_queryset', get_user_queryset)
User.add_to_class('can_access', check_user_access) User.add_to_class('can_access', check_user_access)
User.add_to_class('accessible_by', user_accessible_by) User.add_to_class('accessible_by', user_accessible_by)
User.add_to_class('accessible_objects', user_accessible_objects) User.add_to_class('accessible_objects', user_accessible_objects)
User.add_to_class('admin_role', user_admin_role) User.add_to_class('admin_role', user_admin_role)
User.add_to_class('role_permissions', GenericRelation('main.RolePermission'))
# Import signal handlers only after models have been defined. # Import signal handlers only after models have been defined.
import awx.main.signals # noqa import awx.main.signals # noqa

View File

@@ -111,10 +111,12 @@ class Inventory(CommonModel, ResourceMixin):
updater_role = ImplicitRoleField( updater_role = ImplicitRoleField(
role_name='Inventory Updater', role_name='Inventory Updater',
role_description='May update the inventory', role_description='May update the inventory',
permissions = {'read': True, 'update': True}
) )
executor_role = ImplicitRoleField( executor_role = ImplicitRoleField(
role_name='Inventory Executor', role_name='Inventory Executor',
role_description='May execute jobs against this inventory', role_description='May execute jobs against this inventory',
permissions = {'read': True, 'execute': True}
) )
def get_absolute_url(self): def get_absolute_url(self):
@@ -545,6 +547,7 @@ class Group(CommonModelNameNotUnique, ResourceMixin):
@transaction.atomic @transaction.atomic
def delete_recursive(self): def delete_recursive(self):
from awx.main.utils import ignore_inventory_computed_fields from awx.main.utils import ignore_inventory_computed_fields
from awx.main.tasks import update_inventory_computed_fields
from awx.main.signals import disable_activity_stream from awx.main.signals import disable_activity_stream
@@ -1051,7 +1054,7 @@ class InventorySourceOptions(BaseModel):
return ','.join(choices) return ','.join(choices)
class InventorySource(UnifiedJobTemplate, InventorySourceOptions, ResourceMixin): class InventorySource(UnifiedJobTemplate, InventorySourceOptions):
class Meta: class Meta:
app_label = 'main' app_label = 'main'

View File

@@ -32,7 +32,10 @@ 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)
@staticmethod
def _accessible_objects(cls, user, permissions):
qs = cls.objects.filter( qs = cls.objects.filter(
role_permissions__role__ancestors__members=user role_permissions__role__ancestors__members=user
) )

View File

@@ -459,30 +459,19 @@ class AdHocCommandApiTest(BaseAdHocCommandTest):
self.check_get_list(url, 'nobody', qs) self.check_get_list(url, 'nobody', qs)
self.check_get_list(url, None, qs, expect=401) self.check_get_list(url, None, qs, expect=401)
# Explicitly give other user admin permission on the inventory (still # Explicitly give other user updater permission on the inventory (still
# not allowed to run ad hoc commands). # not allowed to run ad hoc commands).
user_perm_url = reverse('api:user_permissions_list', args=(self.other_django_user.pk,)) user_roles_list_url = reverse('api:user_roles_list', args=(self.other_django_user.pk,))
user_perm_data = {
'name': 'Allow Other to Admin Inventory',
'inventory': self.inventory.pk,
'permission_type': 'admin',
}
with self.current_user('admin'): with self.current_user('admin'):
response = self.post(user_perm_url, user_perm_data, expect=201) response = self.post(user_roles_list_url, {"id": self.inventory.updater_role.id}, expect=204)
user_perm_id = response['id']
with self.current_user('other'): with self.current_user('other'):
self.run_test_ad_hoc_command(expect=403) self.run_test_ad_hoc_command(expect=403)
self.check_get_list(url, 'other', qs) self.check_get_list(url, 'other', qs)
# Update permission to allow other user to run ad hoc commands. Fails # Add executor role permissions to other. Fails
# when other user can't read credential. # when other user can't read credential.
user_perm_url = reverse('api:permission_detail', args=(user_perm_id,))
user_perm_data.update({
'name': 'Allow Other to Admin Inventory and Run Ad Hoc Commands',
'run_ad_hoc_commands': True,
})
with self.current_user('admin'): with self.current_user('admin'):
response = self.patch(user_perm_url, user_perm_data, expect=200) response = self.post(user_roles_list_url, {"id": self.inventory.executor_role.id}, expect=204)
with self.current_user('other'): with self.current_user('other'):
self.run_test_ad_hoc_command(expect=403) self.run_test_ad_hoc_command(expect=403)
@@ -496,15 +485,9 @@ class AdHocCommandApiTest(BaseAdHocCommandTest):
self.check_get_list(url, 'other', qs) self.check_get_list(url, 'other', qs)
# Explicitly give nobody user read permission on the inventory. # Explicitly give nobody user read permission on the inventory.
user_perm_url = reverse('api:user_permissions_list', args=(self.nobody_django_user.pk,)) nobody_roles_list_url = reverse('api:user_roles_list', args=(self.nobody_django_user.pk,))
user_perm_data = {
'name': 'Allow Nobody to Read Inventory',
'inventory': self.inventory.pk,
'permission_type': 'read',
}
with self.current_user('admin'): with self.current_user('admin'):
response = self.post(user_perm_url, user_perm_data, expect=201) response = self.post(nobody_roles_list_url, {"id": self.inventory.auditor_role.id}, expect=204)
user_perm_id = response['id']
with self.current_user('nobody'): with self.current_user('nobody'):
self.run_test_ad_hoc_command(credential=other_cred.pk, expect=403) self.run_test_ad_hoc_command(credential=other_cred.pk, expect=403)
self.check_get_list(url, 'other', qs) self.check_get_list(url, 'other', qs)
@@ -520,13 +503,8 @@ class AdHocCommandApiTest(BaseAdHocCommandTest):
# Give the nobody user the run_ad_hoc_commands flag, and can now see # Give the nobody user the run_ad_hoc_commands flag, and can now see
# the one ad hoc command previously run. # the one ad hoc command previously run.
user_perm_url = reverse('api:permission_detail', args=(user_perm_id,))
user_perm_data.update({
'name': 'Allow Nobody to Read Inventory and Run Ad Hoc Commands',
'run_ad_hoc_commands': True,
})
with self.current_user('admin'): with self.current_user('admin'):
response = self.patch(user_perm_url, user_perm_data, expect=200) response = self.post(nobody_roles_list_url, {"id": self.inventory.executor_role.id}, expect=204)
qs = AdHocCommand.objects.filter(credential_id=nobody_cred.pk) qs = AdHocCommand.objects.filter(credential_id=nobody_cred.pk)
self.assertEqual(qs.count(), 1) self.assertEqual(qs.count(), 1)
self.check_get_list(url, 'nobody', qs) self.check_get_list(url, 'nobody', qs)
@@ -947,7 +925,7 @@ class AdHocCommandApiTest(BaseAdHocCommandTest):
self.delete(url, expect=405) self.delete(url, expect=405)
with self.current_user('normal'): with self.current_user('normal'):
response = self.get(url, expect=200) response = self.get(url, expect=200)
#self.assertEqual(response['count'], 1) # FIXME: Enable once activity stream RBAC is fixed. self.assertEqual(response['count'], 1)
self.post(url, {}, expect=405) self.post(url, {}, expect=405)
self.put(url, {}, expect=405) self.put(url, {}, expect=405)
self.patch(url, {}, expect=405) self.patch(url, {}, expect=405)
@@ -1026,29 +1004,17 @@ class AdHocCommandApiTest(BaseAdHocCommandTest):
# Create another unrelated inventory permission with run_ad_hoc_commands # Create another unrelated inventory permission with run_ad_hoc_commands
# set; this tests an edge case in the RBAC query where we'll return # set; this tests an edge case in the RBAC query where we'll return
# can_run_ad_hoc_commands = True when we shouldn't. # can_run_ad_hoc_commands = True when we shouldn't.
nobody_perm_url = reverse('api:user_permissions_list', args=(self.nobody_django_user.pk,)) nobody_roles_list_url = reverse('api:user_roles_list', args=(self.nobody_django_user.pk,))
nobody_perm_data = {
'name': 'Allow Nobody to Read Inventory',
'inventory': self.inventory.pk,
'permission_type': 'read',
'run_ad_hoc_commands': True,
}
with self.current_user('admin'): with self.current_user('admin'):
response = self.post(nobody_perm_url, nobody_perm_data, expect=201) response = self.post(nobody_roles_list_url, {"id": self.inventory.executor_role.id}, expect=204)
# Create a credential for the other user and explicitly give other # Create a credential for the other user and explicitly give other
# user admin permission on the inventory (still not allowed to run ad # user admin permission on the inventory (still not allowed to run ad
# hoc commands; can get the list but can't see any items). # hoc commands; can get the list but can't see any items).
other_cred = self.create_test_credential(user=self.other_django_user) other_cred = self.create_test_credential(user=self.other_django_user)
user_perm_url = reverse('api:user_permissions_list', args=(self.other_django_user.pk,)) user_roles_list_url = reverse('api:user_roles_list', args=(self.other_django_user.pk,))
user_perm_data = {
'name': 'Allow Other to Admin Inventory',
'inventory': self.inventory.pk,
'permission_type': 'admin',
}
with self.current_user('admin'): with self.current_user('admin'):
response = self.post(user_perm_url, user_perm_data, expect=201) response = self.post(user_roles_list_url, {"id": self.inventory.updater_role.id}, expect=204)
user_perm_id = response['id']
with self.current_user('other'): with self.current_user('other'):
response = self.get(url, expect=200) response = self.get(url, expect=200)
self.assertEqual(response['count'], 0) self.assertEqual(response['count'], 0)
@@ -1058,13 +1024,8 @@ class AdHocCommandApiTest(BaseAdHocCommandTest):
# Update permission to allow other user to run ad hoc commands. Can # Update permission to allow other user to run ad hoc commands. Can
# only see his own ad hoc commands (because of credential permission). # only see his own ad hoc commands (because of credential permission).
user_perm_url = reverse('api:permission_detail', args=(user_perm_id,))
user_perm_data.update({
'name': 'Allow Other to Admin Inventory and Run Ad Hoc Commands',
'run_ad_hoc_commands': True,
})
with self.current_user('admin'): with self.current_user('admin'):
response = self.patch(user_perm_url, user_perm_data, expect=200) response = self.post(user_roles_list_url, {"id": self.inventory.executor_role.id}, expect=204)
with self.current_user('other'): with self.current_user('other'):
response = self.get(url, expect=200) response = self.get(url, expect=200)
self.assertEqual(response['count'], 0) self.assertEqual(response['count'], 0)

View File

@@ -2,7 +2,6 @@
# All Rights Reserved. # All Rights Reserved.
# Python # Python
import datetime
import glob import glob
import json import json
import os import os
@@ -14,7 +13,6 @@ import time
from django.conf import settings from django.conf import settings
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.test.utils import override_settings from django.test.utils import override_settings
from django.utils.timezone import now
# AWX # AWX
from awx.main.models import * # noqa from awx.main.models import * # noqa
@@ -47,9 +45,9 @@ class InventoryTest(BaseTest):
self.setup_instances() self.setup_instances()
self.setup_users() self.setup_users()
self.organizations = self.make_organizations(self.super_django_user, 3) self.organizations = self.make_organizations(self.super_django_user, 3)
self.organizations[0].deprecated_admins.add(self.normal_django_user) self.organizations[0].admin_role.members.add(self.normal_django_user)
self.organizations[0].deprecated_users.add(self.other_django_user) self.organizations[0].member_role.members.add(self.other_django_user)
self.organizations[0].deprecated_users.add(self.normal_django_user) self.organizations[0].member_role.members.add(self.normal_django_user)
self.inventory_a = Inventory.objects.create(name='inventory-a', description='foo', organization=self.organizations[0]) self.inventory_a = Inventory.objects.create(name='inventory-a', description='foo', organization=self.organizations[0])
self.inventory_b = Inventory.objects.create(name='inventory-b', description='bar', organization=self.organizations[1]) self.inventory_b = Inventory.objects.create(name='inventory-b', description='bar', organization=self.organizations[1])
@@ -58,10 +56,7 @@ class InventoryTest(BaseTest):
# create a permission here on the 'other' user so they have edit access on the org # create a permission here on the 'other' user so they have edit access on the org
# we may add another permission type later. # we may add another permission type later.
self.perm_read = Permission.objects.create( self.inventory_b.auditor_role.members.add(self.other_django_user)
inventory = self.inventory_b,
user = self.other_django_user,
permission_type = 'read')
def tearDown(self): def tearDown(self):
super(InventoryTest, self).tearDown() super(InventoryTest, self).tearDown()
@@ -78,11 +73,11 @@ class InventoryTest(BaseTest):
self.check_get_list(url, self.super_django_user, qs) self.check_get_list(url, self.super_django_user, qs)
# an org admin can list inventories but is filtered to what he adminsters # an org admin can list inventories but is filtered to what he adminsters
normal_qs = qs.filter(organization__deprecated_admins__in=[self.normal_django_user]) normal_qs = qs.filter(organization__admin_role__members=self.normal_django_user)
self.check_get_list(url, self.normal_django_user, normal_qs) self.check_get_list(url, self.normal_django_user, normal_qs)
# a user who is on a team who has a read permissions on an inventory can see filtered inventories # a user who is on a team who has a read permissions on an inventory can see filtered inventories
other_qs = qs.filter(permissions__user__in=[self.other_django_user]) other_qs = Inventory.accessible_objects(self.other_django_user, {'read': True}).distinct()
self.check_get_list(url, self.other_django_user, other_qs) self.check_get_list(url, self.other_django_user, other_qs)
# a regular user not part of anything cannot see any inventories # a regular user not part of anything cannot see any inventories
@@ -263,24 +258,20 @@ class InventoryTest(BaseTest):
def test_inventory_access_deleted_permissions(self): def test_inventory_access_deleted_permissions(self):
temp_org = self.make_organizations(self.super_django_user, 1)[0] temp_org = self.make_organizations(self.super_django_user, 1)[0]
temp_org.deprecated_admins.add(self.normal_django_user) temp_org.admin_role.members.add(self.normal_django_user)
temp_org.deprecated_users.add(self.other_django_user) temp_org.member_role.members.add(self.other_django_user)
temp_org.deprecated_users.add(self.normal_django_user) temp_org.member_role.members.add(self.normal_django_user)
temp_inv = temp_org.inventories.create(name='Delete Org Inventory') temp_inv = temp_org.inventories.create(name='Delete Org Inventory')
temp_inv.groups.create(name='Delete Org Inventory Group') temp_inv.groups.create(name='Delete Org Inventory Group')
temp_perm_read = Permission.objects.create( temp_inv.auditor_role.members.add(self.other_django_user)
inventory = temp_inv,
user = self.other_django_user,
permission_type = 'read'
)
reverse('api:organization_detail', args=(temp_org.pk,)) reverse('api:organization_detail', args=(temp_org.pk,))
inventory_detail = reverse('api:inventory_detail', args=(temp_inv.pk,)) inventory_detail = reverse('api:inventory_detail', args=(temp_inv.pk,))
permission_detail = reverse('api:permission_detail', args=(temp_perm_read.pk,)) auditor_role_users_list = reverse('api:role_users_list', args=(temp_inv.auditor_role.pk,))
self.get(inventory_detail, expect=200, auth=self.get_other_credentials()) self.get(inventory_detail, expect=200, auth=self.get_other_credentials())
self.delete(permission_detail, expect=204, auth=self.get_super_credentials()) self.post(auditor_role_users_list, data={'disassociate': True, "id": self.other_django_user.id}, expect=204, auth=self.get_super_credentials())
self.get(inventory_detail, expect=403, auth=self.get_other_credentials()) self.get(inventory_detail, expect=403, auth=self.get_other_credentials())
def test_create_inventory_script(self): def test_create_inventory_script(self):
@@ -335,10 +326,8 @@ class InventoryTest(BaseTest):
self.post(hosts, data=new_host_b, expect=403, auth=self.get_nobody_credentials()) self.post(hosts, data=new_host_b, expect=403, auth=self.get_nobody_credentials())
# a normal user with inventory edit permissions (on any inventory) can create hosts # a normal user with inventory edit permissions (on any inventory) can create hosts
Permission.objects.create(
user = self.other_django_user, inv.admin_role.members.add(self.other_django_user)
inventory = Inventory.objects.get(pk=inv.pk),
permission_type = PERM_INVENTORY_WRITE)
host_data3 = self.post(hosts, data=new_host_c, expect=201, auth=self.get_other_credentials()) host_data3 = self.post(hosts, data=new_host_c, expect=201, auth=self.get_other_credentials())
# Port should be split out into host variables, other variables kept intact. # Port should be split out into host variables, other variables kept intact.
@@ -393,11 +382,6 @@ class InventoryTest(BaseTest):
# a normal user with inventory edit permissions (on any inventory) can create groups # a normal user with inventory edit permissions (on any inventory) can create groups
# already done! # already done!
#edit_perm = Permission.objects.create(
# user = self.other_django_user,
# inventory = Inventory.objects.get(pk=inv.pk),
# permission_type = PERM_INVENTORY_WRITE
#)
self.post(groups, data=new_group_c, expect=201, auth=self.get_other_credentials()) self.post(groups, data=new_group_c, expect=201, auth=self.get_other_credentials())
# hostnames must be unique inside an organization # hostnames must be unique inside an organization
@@ -417,9 +401,10 @@ class InventoryTest(BaseTest):
del_children_url = reverse('api:group_children_list', args=(del_group.pk,)) del_children_url = reverse('api:group_children_list', args=(del_group.pk,))
nondel_url = reverse('api:group_detail', nondel_url = reverse('api:group_detail',
args=(Group.objects.get(name='nondel').pk,)) args=(Group.objects.get(name='nondel').pk,))
assert(inv.accessible_by(self.normal_django_user, {'read': True}))
del_group.delete() del_group.delete()
nondel_detail = self.get(nondel_url, expect=200, auth=self.get_normal_credentials()) nondel_detail = self.get(nondel_url, expect=200, auth=self.get_normal_credentials())
self.post(del_children_url, data=nondel_detail, expect=403, auth=self.get_normal_credentials()) self.post(del_children_url, data=nondel_detail, expect=400, auth=self.get_normal_credentials())
################################################# #################################################
@@ -656,11 +641,7 @@ class InventoryTest(BaseTest):
gx5 = Group.objects.create(name='group-X5', inventory=inva) gx5 = Group.objects.create(name='group-X5', inventory=inva)
gx5.parents.add(gx4) gx5.parents.add(gx4)
Permission.objects.create( inva.admin_role.members.add(self.other_django_user)
inventory = inva,
user = self.other_django_user,
permission_type = PERM_INVENTORY_WRITE
)
# data used for testing listing all hosts that are transitive members of a group # data used for testing listing all hosts that are transitive members of a group
g2 = Group.objects.get(name='web4') g2 = Group.objects.get(name='web4')
@@ -1115,59 +1096,6 @@ class InventoryTest(BaseTest):
self.assertEqual(response['hosts']['total'], 8) self.assertEqual(response['hosts']['total'], 8)
self.assertEqual(response['hosts']['failed'], 8) self.assertEqual(response['hosts']['failed'], 8)
def test_dashboard_inventory_graph_view(self):
url = reverse('api:dashboard_inventory_graph_view')
# Test with zero hosts.
with self.current_user(self.super_django_user):
response = self.get(url)
self.assertFalse(sum([x[1] for x in response['hosts']]))
# Create hosts in inventory_a, with created one day apart, and check
# the time series results.
dtnow = now()
hostnames = list('abcdefg')
for x in xrange(len(hostnames) - 1, -1, -1):
hostname = hostnames[x]
created = dtnow - datetime.timedelta(days=x, seconds=60)
self.inventory_a.hosts.create(name=hostname, created=created)
with self.current_user(self.super_django_user):
response = self.get(url)
for n, d in enumerate(reversed(response['hosts'])):
self.assertEqual(d[1], max(len(hostnames) - n, 0))
# Create more hosts a day apart in inventory_b and check the time
# series results.
hostnames2 = list('hijklmnop')
for x in xrange(len(hostnames2) - 1, -1, -1):
hostname = hostnames2[x]
created = dtnow - datetime.timedelta(days=x, seconds=120)
self.inventory_b.hosts.create(name=hostname, created=created)
with self.current_user(self.super_django_user):
response = self.get(url)
for n, d in enumerate(reversed(response['hosts'])):
self.assertEqual(d[1], max(len(hostnames2) - n, 0) + max(len(hostnames) - n, 0))
# Now create some hosts in inventory_a with the same hostnames already
# used in inventory_b; duplicate hostnames should only be counted the
# first time they were seen in inventory_b.
hostnames3 = list('lmnop')
for x in xrange(len(hostnames3) - 1, -1, -1):
hostname = hostnames3[x]
created = dtnow - datetime.timedelta(days=x, seconds=180)
self.inventory_a.hosts.create(name=hostname, created=created)
with self.current_user(self.super_django_user):
response = self.get(url)
for n, d in enumerate(reversed(response['hosts'])):
self.assertEqual(d[1], max(len(hostnames2) - n, 0) + max(len(hostnames) - n, 0))
# Delete recently added hosts and verify the count drops.
hostnames4 = list('defg')
for host in Host.objects.filter(name__in=hostnames4):
host.delete()
with self.current_user(self.super_django_user):
response = self.get(url)
for n, d in enumerate(reversed(response['hosts'])):
count = max(len(hostnames2) - n, 0) + max(len(hostnames) - n, 0)
if n == 0:
count -= 4
self.assertEqual(d[1], count)
@override_settings(CELERY_ALWAYS_EAGER=True, @override_settings(CELERY_ALWAYS_EAGER=True,
CELERY_EAGER_PROPAGATES_EXCEPTIONS=True, CELERY_EAGER_PROPAGATES_EXCEPTIONS=True,
@@ -1181,9 +1109,9 @@ class InventoryUpdatesTest(BaseTransactionTest):
self.setup_instances() self.setup_instances()
self.setup_users() self.setup_users()
self.organization = self.make_organizations(self.super_django_user, 1)[0] self.organization = self.make_organizations(self.super_django_user, 1)[0]
self.organization.deprecated_admins.add(self.normal_django_user) self.organization.admin_role.members.add(self.normal_django_user)
self.organization.deprecated_users.add(self.other_django_user) self.organization.member_role.members.add(self.other_django_user)
self.organization.deprecated_users.add(self.normal_django_user) self.organization.member_role.members.add(self.normal_django_user)
self.inventory = self.organization.inventories.create(name='Cloud Inventory') self.inventory = self.organization.inventories.create(name='Cloud Inventory')
self.group = self.inventory.groups.create(name='Cloud Group') self.group = self.inventory.groups.create(name='Cloud Group')
self.inventory2 = self.organization.inventories.create(name='Cloud Inventory 2') self.inventory2 = self.organization.inventories.create(name='Cloud Inventory 2')
@@ -1256,7 +1184,7 @@ class InventoryUpdatesTest(BaseTransactionTest):
url = reverse('api:inventory_source_hosts_list', args=(inventory_source.pk,)) url = reverse('api:inventory_source_hosts_list', args=(inventory_source.pk,))
response = self.get(url, expect=200) response = self.get(url, expect=200)
self.assertNotEqual(response['count'], 0) self.assertNotEqual(response['count'], 0)
for host in inventory.hosts: for host in inventory.hosts.all():
source_pks = host.inventory_sources.values_list('pk', flat=True) source_pks = host.inventory_sources.values_list('pk', flat=True)
self.assertTrue(inventory_source.pk in source_pks) self.assertTrue(inventory_source.pk in source_pks)
self.assertTrue(host.has_inventory_sources) self.assertTrue(host.has_inventory_sources)
@@ -1270,7 +1198,7 @@ class InventoryUpdatesTest(BaseTransactionTest):
url = reverse('api:host_inventory_sources_list', args=(host.pk,)) url = reverse('api:host_inventory_sources_list', args=(host.pk,))
response = self.get(url, expect=200) response = self.get(url, expect=200)
self.assertNotEqual(response['count'], 0) self.assertNotEqual(response['count'], 0)
for group in inventory.groups: for group in inventory.groups.all():
source_pks = group.inventory_sources.values_list('pk', flat=True) source_pks = group.inventory_sources.values_list('pk', flat=True)
self.assertTrue(inventory_source.pk in source_pks) self.assertTrue(inventory_source.pk in source_pks)
self.assertTrue(group.has_inventory_sources) self.assertTrue(group.has_inventory_sources)
@@ -1293,7 +1221,7 @@ class InventoryUpdatesTest(BaseTransactionTest):
self.assertNotEqual(response['count'], 0) self.assertNotEqual(response['count'], 0)
# Try to set a source on a child group that was imported. Should not # Try to set a source on a child group that was imported. Should not
# be allowed. # be allowed.
for group in inventory_source.group.children: for group in inventory_source.group.children.all():
inv_src_2 = group.inventory_source inv_src_2 = group.inventory_source
inv_src_url2 = reverse('api:inventory_source_detail', args=(inv_src_2.pk,)) inv_src_url2 = reverse('api:inventory_source_detail', args=(inv_src_2.pk,))
with self.current_user(self.super_django_user): with self.current_user(self.super_django_user):
@@ -1540,16 +1468,9 @@ class InventoryUpdatesTest(BaseTransactionTest):
self.post(inv_src_update_url, {}, expect=403) self.post(inv_src_update_url, {}, expect=403)
# If given read permission to the inventory, other user should be able # If given read permission to the inventory, other user should be able
# to see the inventory source and update view, but not start an update. # to see the inventory source and update view, but not start an update.
other_perms_url = reverse('api:user_permissions_list', user_roles_list_url = reverse('api:user_roles_list', args=(self.other_django_user.pk,))
args=(self.other_django_user.pk,))
other_perms_data = {
'name': 'read only inventory permission for other',
'user': self.other_django_user.pk,
'inventory': self.inventory.pk,
'permission_type': 'read',
}
with self.current_user(self.super_django_user): with self.current_user(self.super_django_user):
self.post(other_perms_url, other_perms_data, expect=201) self.post(user_roles_list_url, {"id": self.inventory.auditor_role.id}, expect=204)
with self.current_user(self.other_django_user): with self.current_user(self.other_django_user):
self.get(inv_src_url, expect=200) self.get(inv_src_url, expect=200)
response = self.get(inv_src_update_url, expect=200) response = self.get(inv_src_update_url, expect=200)
@@ -1557,14 +1478,8 @@ class InventoryUpdatesTest(BaseTransactionTest):
self.post(inv_src_update_url, {}, expect=403) self.post(inv_src_update_url, {}, expect=403)
# Once given write permission, the normal user is able to update the # Once given write permission, the normal user is able to update the
# inventory source. # inventory source.
other_perms_data = {
'name': 'read-write inventory permission for other',
'user': self.other_django_user.pk,
'inventory': self.inventory.pk,
'permission_type': 'write',
}
with self.current_user(self.super_django_user): with self.current_user(self.super_django_user):
self.post(other_perms_url, other_perms_data, expect=201) self.post(user_roles_list_url, {"id": self.inventory.admin_role.id}, expect=204)
with self.current_user(self.other_django_user): with self.current_user(self.other_django_user):
self.get(inv_src_url, expect=200) self.get(inv_src_url, expect=200)
response = self.get(inv_src_update_url, expect=200) response = self.get(inv_src_update_url, expect=200)
@@ -1649,7 +1564,7 @@ class InventoryUpdatesTest(BaseTransactionTest):
inventory_source.overwrite = True inventory_source.overwrite = True
inventory_source.save() inventory_source.save()
self.check_inventory_source(inventory_source, initial=False) self.check_inventory_source(inventory_source, initial=False)
for host in self.inventory.hosts: for host in self.inventory.hosts.all():
self.assertEqual(host.variables_dict['ec2_instance_type'], instance_type) self.assertEqual(host.variables_dict['ec2_instance_type'], instance_type)
# Try invalid instance filters that should be ignored: # Try invalid instance filters that should be ignored:

View File

@@ -19,7 +19,7 @@ class LicenseTests(BaseTest):
self.setup_users() self.setup_users()
u = self.super_django_user u = self.super_django_user
org = Organization.objects.create(name='o1', created_by=u) org = Organization.objects.create(name='o1', created_by=u)
org.deprecated_admins.add(self.normal_django_user) org.admin_role.members.add(self.normal_django_user)
self.inventory = Inventory.objects.create(name='hi', organization=org, created_by=u) self.inventory = Inventory.objects.create(name='hi', organization=org, created_by=u)
Host.objects.create(name='a1', inventory=self.inventory, created_by=u) Host.objects.create(name='a1', inventory=self.inventory, created_by=u)
Host.objects.create(name='a2', inventory=self.inventory, created_by=u) Host.objects.create(name='a2', inventory=self.inventory, created_by=u)

View File

@@ -88,12 +88,12 @@ class OrganizationsTest(BaseTest):
# nobody_user is a user not a member of any organizations # nobody_user is a user not a member of any organizations
for x in self.organizations: for x in self.organizations:
x.deprecated_admins.add(self.super_django_user) x.admin_role.members.add(self.super_django_user)
x.deprecated_users.add(self.super_django_user) x.member_role.members.add(self.super_django_user)
x.deprecated_users.add(self.other_django_user) x.member_role.members.add(self.other_django_user)
self.organizations[0].deprecated_users.add(self.normal_django_user) self.organizations[0].member_role.members.add(self.normal_django_user)
self.organizations[1].deprecated_admins.add(self.normal_django_user) self.organizations[1].admin_role.members.add(self.normal_django_user)
def test_get_organization_list(self): def test_get_organization_list(self):
url = reverse('api:organization_list') url = reverse('api:organization_list')

View File

@@ -75,10 +75,10 @@ class ProjectsTest(BaseTransactionTest):
for x in self.organizations: for x in self.organizations:
# NOTE: superuser does not have to be explicitly added to admin group # NOTE: superuser does not have to be explicitly added to admin group
# x.admins.add(self.super_django_user) # x.admins.add(self.super_django_user)
x.deprecated_users.add(self.super_django_user) x.member_role.members.add(self.super_django_user)
self.organizations[0].deprecated_users.add(self.normal_django_user) self.organizations[0].member_role.members.add(self.normal_django_user)
self.organizations[1].deprecated_admins.add(self.normal_django_user) self.organizations[1].admin_role.members.add(self.normal_django_user)
self.team1 = Team.objects.create( self.team1 = Team.objects.create(
name = 'team1', organization = self.organizations[0] name = 'team1', organization = self.organizations[0]
@@ -97,8 +97,8 @@ class ProjectsTest(BaseTransactionTest):
self.team2.projects.add(self.projects[5]) self.team2.projects.add(self.projects[5])
self.team1.save() self.team1.save()
self.team2.save() self.team2.save()
self.team1.deprecated_users.add(self.normal_django_user) self.team1.member_role.members.add(self.normal_django_user)
self.team2.deprecated_users.add(self.other_django_user) self.team2.member_role.members.add(self.other_django_user)
def test_playbooks(self): def test_playbooks(self):
def write_test_file(project, name, content): def write_test_file(project, name, content):
@@ -312,7 +312,7 @@ class ProjectsTest(BaseTransactionTest):
# Verify that creatorship doesn't imply access if access is removed # Verify that creatorship doesn't imply access if access is removed
a_new_proj = self.make_project(created_by=self.other_django_user, playbook_content=TEST_PLAYBOOK) a_new_proj = self.make_project(created_by=self.other_django_user, playbook_content=TEST_PLAYBOOK)
self.organizations[0].deprecated_admins.add(self.other_django_user) self.organizations[0].admin_role.members.add(self.other_django_user)
self.organizations[0].projects.add(a_new_proj) self.organizations[0].projects.add(a_new_proj)
proj_detail = reverse('api:project_detail', args=(a_new_proj.pk,)) proj_detail = reverse('api:project_detail', args=(a_new_proj.pk,))
self.patch(proj_detail, data=dict(description="test"), expect=200, auth=self.get_other_credentials()) self.patch(proj_detail, data=dict(description="test"), expect=200, auth=self.get_other_credentials())
@@ -337,7 +337,7 @@ class ProjectsTest(BaseTransactionTest):
self.assertEquals(got['url'], reverse('api:team_detail', args=(self.team1.pk,))) self.assertEquals(got['url'], reverse('api:team_detail', args=(self.team1.pk,)))
got = self.get(team1, expect=200, auth=self.get_normal_credentials()) got = self.get(team1, expect=200, auth=self.get_normal_credentials())
got = self.get(team1, expect=403, auth=self.get_other_credentials()) got = self.get(team1, expect=403, auth=self.get_other_credentials())
self.team1.deprecated_users.add(User.objects.get(username='other')) self.team1.member_role.members.add(User.objects.get(username='other'))
self.team1.save() self.team1.save()
got = self.get(team1, expect=200, auth=self.get_other_credentials()) got = self.get(team1, expect=200, auth=self.get_other_credentials())
got = self.get(team1, expect=403, auth=self.get_nobody_credentials()) got = self.get(team1, expect=403, auth=self.get_nobody_credentials())
@@ -422,7 +422,7 @@ class ProjectsTest(BaseTransactionTest):
team = Team.objects.filter( organization__pk=self.organizations[1].pk)[0] team = Team.objects.filter( organization__pk=self.organizations[1].pk)[0]
team_users = reverse('api:team_users_list', args=(team.pk,)) team_users = reverse('api:team_users_list', args=(team.pk,))
for x in team.deprecated_users.all(): for x in team.deprecated_users.all():
team.deprecated_users.remove(x) team.member_role.members.remove(x)
team.save() team.save()
# can list uses on teams # can list uses on teams
@@ -787,7 +787,7 @@ class ProjectsTest(BaseTransactionTest):
# User is still a team member # User is still a team member
self.get(reverse('api:project_detail', args=(project.pk,)), expect=200, auth=self.get_other_credentials()) self.get(reverse('api:project_detail', args=(project.pk,)), expect=200, auth=self.get_other_credentials())
team.deprecated_users.remove(self.other_django_user) team.member_role.members.remove(self.other_django_user)
# User is no longer a team member and has no permissions # User is no longer a team member and has no permissions
self.get(reverse('api:project_detail', args=(project.pk,)), expect=403, auth=self.get_other_credentials()) self.get(reverse('api:project_detail', args=(project.pk,)), expect=403, auth=self.get_other_credentials())
@@ -1351,7 +1351,7 @@ class ProjectUpdatesTest(BaseTransactionTest):
'scm_url': scm_url, 'scm_url': scm_url,
} }
org = self.make_organizations(self.super_django_user, 1)[0] org = self.make_organizations(self.super_django_user, 1)[0]
org.deprecated_admins.add(self.normal_django_user) org.admin_role.members.add(self.normal_django_user)
with self.current_user(self.super_django_user): with self.current_user(self.super_django_user):
del_proj = self.post(projects_url, project_data, expect=201) del_proj = self.post(projects_url, project_data, expect=201)
del_proj = Project.objects.get(pk=del_proj["id"]) del_proj = Project.objects.get(pk=del_proj["id"])

View File

@@ -54,12 +54,12 @@ class ScheduleTest(BaseTest):
self.setup_instances() self.setup_instances()
self.setup_users() self.setup_users()
self.organizations = self.make_organizations(self.super_django_user, 2) self.organizations = self.make_organizations(self.super_django_user, 2)
self.organizations[0].deprecated_admins.add(self.normal_django_user) self.organizations[0].admin_role.members.add(self.normal_django_user)
self.organizations[0].deprecated_users.add(self.other_django_user) self.organizations[0].member_role.members.add(self.other_django_user)
self.organizations[0].deprecated_users.add(self.normal_django_user) self.organizations[0].member_role.members.add(self.normal_django_user)
self.diff_org_user = self.make_user('fred') self.diff_org_user = self.make_user('fred')
self.organizations[1].deprecated_users.add(self.diff_org_user) self.organizations[1].member_role.members.add(self.diff_org_user)
self.cloud_source = Credential.objects.create(kind='awx', user=self.super_django_user, self.cloud_source = Credential.objects.create(kind='awx', user=self.super_django_user,
username='Dummy', password='Dummy') username='Dummy', password='Dummy')
@@ -71,11 +71,7 @@ class ScheduleTest(BaseTest):
self.first_inventory_source.source = 'ec2' self.first_inventory_source.source = 'ec2'
self.first_inventory_source.save() self.first_inventory_source.save()
Permission.objects.create( self.first_inventory.auditor_role.members.add(self.other_django_user)
inventory = self.first_inventory,
user = self.other_django_user,
permission_type = 'read'
)
self.second_inventory = Inventory.objects.create(name='test_inventory_2', description='for org 0', organization=self.organizations[0]) self.second_inventory = Inventory.objects.create(name='test_inventory_2', description='for org 0', organization=self.organizations[0])
self.second_inventory.hosts.create(name='host_2') self.second_inventory.hosts.create(name='host_2')
@@ -139,11 +135,7 @@ class ScheduleTest(BaseTest):
self.post(first_url, data=unauth_schedule, expect=403) self.post(first_url, data=unauth_schedule, expect=403)
#give normal user write access and then they can post #give normal user write access and then they can post
Permission.objects.create( self.first_inventory.admin_role.members.add(self.other_django_user)
user = self.other_django_user,
inventory = self.first_inventory,
permission_type = PERM_INVENTORY_WRITE
)
auth_schedule = unauth_schedule auth_schedule = unauth_schedule
with self.current_user(self.other_django_user): with self.current_user(self.other_django_user):
self.post(first_url, data=auth_schedule, expect=201) self.post(first_url, data=auth_schedule, expect=201)

View File

@@ -100,7 +100,7 @@ class AuthTokenProxyTest(BaseTest):
self.setup_users() self.setup_users()
self.setup_instances() self.setup_instances()
self.organizations = self.make_organizations(self.super_django_user, 2) self.organizations = self.make_organizations(self.super_django_user, 2)
self.organizations[0].deprecated_admins.add(self.normal_django_user) self.organizations[0].admin_role.members.add(self.normal_django_user)
self.assertIn('REMOTE_ADDR', settings.REMOTE_HOST_HEADERS) self.assertIn('REMOTE_ADDR', settings.REMOTE_HOST_HEADERS)
self.assertIn('REMOTE_HOST', settings.REMOTE_HOST_HEADERS) self.assertIn('REMOTE_HOST', settings.REMOTE_HOST_HEADERS)
@@ -174,10 +174,10 @@ class UsersTest(BaseTest):
super(UsersTest, self).setUp() super(UsersTest, self).setUp()
self.setup_users() self.setup_users()
self.organizations = self.make_organizations(self.super_django_user, 2) self.organizations = self.make_organizations(self.super_django_user, 2)
self.organizations[0].deprecated_admins.add(self.normal_django_user) self.organizations[0].admin_role.members.add(self.normal_django_user)
self.organizations[0].deprecated_users.add(self.other_django_user) self.organizations[0].member_role.members.add(self.other_django_user)
self.organizations[0].deprecated_users.add(self.normal_django_user) self.organizations[0].member_role.members.add(self.normal_django_user)
self.organizations[1].deprecated_users.add(self.other_django_user) self.organizations[1].member_role.members.add(self.other_django_user)
def test_user_creation_fails_without_password(self): def test_user_creation_fails_without_password(self):
url = reverse('api:user_list') url = reverse('api:user_list')