1
0
mirror of https://github.com/ansible/awx.git synced 2024-10-30 05:25:29 +03:00

Start of group support.

This commit is contained in:
Michael DeHaan 2013-03-26 16:57:08 -04:00
parent 2d3ff081c1
commit 3625039d47
4 changed files with 145 additions and 26 deletions

View File

@ -142,7 +142,7 @@ class PrimordialModel(models.Model):
active = models.BooleanField(default=True)
def __unicode__(self):
return unicode(self.name)
return unicode("%s-%s"% (self.name, self.id))
@classmethod
def can_user_administrate(cls, user, obj):
@ -284,6 +284,7 @@ class Inventory(CommonModel):
class Meta:
app_label = 'main'
verbose_name_plural = _('inventories')
unique_together = (("name", "organization"),)
organization = models.ForeignKey(Organization, null=False, related_name='inventories')
@ -291,12 +292,6 @@ class Inventory(CommonModel):
import lib.urls
return reverse(lib.urls.views_InventoryDetail, args=(self.pk,))
def __unicode__(self):
if self.organization:
return u'%s (%s)' % (self.name, self.organization)
else:
return self.name
@classmethod
def _has_permission_types(cls, user, obj, allowed):
if user.is_superuser:
@ -370,6 +365,7 @@ class Host(CommonModelNameNotUnique):
class Meta:
app_label = 'main'
unique_together = (("name", "inventory"),)
inventory = models.ForeignKey('Inventory', null=False, related_name='hosts')
@ -395,6 +391,7 @@ class Group(CommonModelNameNotUnique):
class Meta:
app_label = 'main'
unique_together = (("name", "inventory"),)
inventory = models.ForeignKey('Inventory', null=False, related_name='groups')
parents = models.ManyToManyField('self', symmetrical=False, related_name='children', blank=True)
@ -410,10 +407,14 @@ class Group(CommonModelNameNotUnique):
inventory = Inventory.objects.get(pk=data['inventory'])
return Inventory._has_permission_types(user, inventory, PERMISSION_TYPES_ALLOWING_INVENTORY_WRITE)
def get_absolute_url(self):
import lib.urls
return reverse(lib.urls.views_GroupsDetail, args=(self.pk,))
# FIXME: audit nullables
# FIXME: audit cascades
class VariableData(CommonModel):
class VariableData(CommonModelNameNotUnique):
'''
A set of host or group variables
'''
@ -421,6 +422,7 @@ class VariableData(CommonModel):
class Meta:
app_label = 'main'
verbose_name_plural = _('variable data')
unique_together = (("host", "group"),)
host = models.ForeignKey('Host', null=True, default=None, blank=True, on_delete=SET_NULL, related_name='variable_data')
group = models.ForeignKey('Group', null=True, default=None, blank=True, on_delete=SET_NULL, related_name='variable_data')
@ -526,8 +528,16 @@ class Permission(CommonModelNameNotUnique):
# the project parameter is not used when dealing with READ, WRITE, or ADMIN permissions.
permission_type = models.CharField(max_length=64, choices=PERMISSION_TYPE_CHOICES)
def __unicode__(self):
return unicode("Permission(name=%s,ON(user=%s,team=%s),FOR(project=%s,inventory=%s,type=%s))" % (
self.name,
self.user,
self.team,
self.project,
self.inventory,
self.permission_type
))
# TODO: other job types (later)

View File

@ -129,13 +129,12 @@ class InventoryTest(BaseTest):
new_host_b = dict(name='asdf1.example.com', inventory=inv.pk)
new_host_c = dict(name='asdf2.example.com', inventory=inv.pk)
new_host_d = dict(name='asdf3.example.com', inventory=inv.pk)
# FIXME: should raise 400 not 201, look into required fields in rest_framework
print hosts
new_host_e = dict(name='asdf4.example.com', inventory=inv.pk)
data0 = self.post(hosts, data=invalid, expect=400, auth=self.get_super_credentials())
data0 = self.post(hosts, data=new_host_a, expect=201, auth=self.get_super_credentials())
# an org admin can add hosts
data1 = self.post(hosts, data=new_host_a, expect=201, auth=self.get_normal_credentials())
data1 = self.post(hosts, data=new_host_e, expect=201, auth=self.get_normal_credentials())
# a normal user cannot add hosts
data2 = self.post(hosts, data=new_host_b, expect=403, auth=self.get_nobody_credentials())
@ -143,24 +142,46 @@ class InventoryTest(BaseTest):
# a normal user with inventory edit permissions (on any inventory) can create hosts
edit_perm = Permission.objects.create(
user = self.other_django_user,
inventory = Inventory.objects.get(pk=1),
inventory = Inventory.objects.get(pk=inv.pk),
permission_type = PERM_INVENTORY_WRITE
)
data3 = self.post(hosts, data=new_host_c, expect=201, auth=self.get_other_credentials())
# hostnames must be unique -- posting a duplicate just returns the previous
data4 = self.post(hosts, data=new_host_c, expect=200, auth=self.get_other_credentials())
self.assertEqual(data1['id'], data4['id'])
# hostnames must be unique inside an organization
data4 = self.post(hosts, data=new_host_c, expect=400, auth=self.get_other_credentials())
# a super user can add groups
###########################################
# GROUPS
# an org admin can create groups
invalid = dict(name='web1')
new_group_a = dict(name='web2', inventory=inv.pk)
new_group_b = dict(name='web3', inventory=inv.pk)
new_group_c = dict(name='web4', inventory=inv.pk)
new_group_d = dict(name='web5', inventory=inv.pk)
new_group_e = dict(name='web6', inventory=inv.pk)
data0 = self.post(groups, data=invalid, expect=400, auth=self.get_super_credentials())
data0 = self.post(groups, data=new_group_a, expect=201, auth=self.get_super_credentials())
# a normal user cannot create groups
# an org admin can add hosts
data1 = self.post(groups, data=new_group_e, expect=201, auth=self.get_normal_credentials())
# a normal user with inventory edit permissions can create groups
# group names must be unique for each inventory record
# a normal user cannot add hosts
data2 = self.post(groups, data=new_group_b, expect=403, auth=self.get_nobody_credentials())
# a normal user with inventory edit permissions (on any inventory) can create hosts
# already done!
#edit_perm = Permission.objects.create(
# user = self.other_django_user,
# inventory = Inventory.objects.get(pk=inv.pk),
# permission_type = PERM_INVENTORY_WRITE
#)
data3 = self.post(groups, data=new_group_c, expect=201, auth=self.get_other_credentials())
# hostnames must be unique inside an organization
data4 = self.post(groups, data=new_group_c, expect=400, auth=self.get_other_credentials())
#################################################
# HOSTS->inventories
# a super user can associate hosts with inventories
@ -170,13 +191,19 @@ class InventoryTest(BaseTest):
# a normal user with edit permission on the inventory can associate hosts with inventories
##################################################
# GROUPS->inventories
# a super user can associate groups with inventories
# an org admin can associate groups with inventories
# a normal user cannot associate hosts with inventories
# a normal user cannot associate groups with inventories
# a normal user with edit permissions on the inventory can associate hosts with inventories
# a normal user with edit permissions on the inventory can associate groups with inventories
###################################################
# VARIABLES
# a super user can create variable objects
@ -186,6 +213,9 @@ class InventoryTest(BaseTest):
# a normal user with at least one inventory edit permission can create variable objects
###################################################
# VARIABLES -> GROUPS
# a super user can associate variable objects with groups
# an org admin can associate variable objects with groups
@ -194,6 +224,9 @@ class InventoryTest(BaseTest):
# a normal user with inventory edit permissions can associate variable objects with groups
####################################################
# VARIABLES -> HOSTS
# a super user can associate variable objects with hosts
# an org admin can associate variable objects with hosts
@ -202,6 +235,9 @@ class InventoryTest(BaseTest):
# a normal user with inventory edit permissions can associate variable objects with hosts
####################################################
# SUBGROUPS
# a super user can set subgroups
# an org admin can set subgroups
@ -210,6 +246,9 @@ class InventoryTest(BaseTest):
# a normal user with inventory edit permissions can associate subgroups
######################################################
# GROUP ACCESS
# a super user can get a group record
# an org admin can get a group record
@ -218,6 +257,9 @@ class InventoryTest(BaseTest):
# a regular user cannot read any group records
########################################################
# HOST ACCESS
# a super user can get a host record
# an org admin can get a host record
@ -226,13 +268,19 @@ class InventoryTest(BaseTest):
# a regular user cannot get a host record
#########################################################
# GROUP VARIABLE ACCESS
# a super user can see the variables attached to a group
# a org admin can see the variables attached to a group
# a user who is on a team who has read permissions on an inventory can see the variables attached to a group
# a regular user cannot get a host record
# a regular user cannot get a group variable record
#########################################################
# HOST VARIABLE ACCESS
# a super user can see the variables attached to a host
@ -241,6 +289,9 @@ class InventoryTest(BaseTest):
# a user who is on a team who has read permissions on an inventory can see the variables attached to a host
# a regular user cannot see variables attached to a host
#########################################################
# GROUP CHILDREN ACCESS
# a super user can see the children attached to a group
@ -249,6 +300,9 @@ class InventoryTest(BaseTest):
# a user who is on a team who has read permissions on an inventory can see the children attached to a group
# a regular user cannot see children attached to a group
#########################################################
# VARIABLE RESOURCE ACCESS
# a super user can see a variable record
@ -257,6 +311,9 @@ class InventoryTest(BaseTest):
# a user who is on a team who has read permissions on an inventory can see the variable record
# a regular user cannot see a variable record
#########################################################
# SUPER USER DISASSOCIATION
# a super user can disassociate...
@ -267,6 +324,9 @@ class InventoryTest(BaseTest):
# subgroups from groups
# the inventory task code returns valid inventory JSON.
#########################################################
# ORG ADMIN DISASSOCIATION
# an org admin user can disassociate...
@ -276,6 +336,9 @@ class InventoryTest(BaseTest):
# subgroups from groups
#########################################################
# USER DISASSOCIATION
# a user with inventory edit permission disassociate...
# hosts from inventory
@ -283,6 +346,9 @@ class InventoryTest(BaseTest):
# groups from inventory
# subgroups from groups
#########################################################
# USER DISASSOCIATION (2)
# a regular user cannot disassociate....
@ -292,6 +358,9 @@ class InventoryTest(BaseTest):
# subgroups from inventory
#########################################################
# TAGS
# the following objects can be tagged
# inventory
@ -322,6 +391,9 @@ class InventoryTest(BaseTest):
# variable records
#########################################################
# RELATED FIELDS
# on an inventory resource, I can see related resources for hosts and groups and permissions
# and these work

View File

@ -315,4 +315,37 @@ class HostsDetail(BaseDetail):
serializer_class = HostSerializer
permission_classes = (CustomRbac,)
class GroupsList(BaseList):
model = Group
serializer_class = GroupSerializer
permission_classes = (CustomRbac,)
def _get_queryset(self):
'''
I can see groups when:
I'm a superuser,
or an organization admin of an inventory they are in
or when I have allowing read permissions via a user or team on an inventory they are in
'''
base = Groups.objects
if self.request.user.is_superuser:
return base.all()
admin_of = base.filter(inventory__organization__admins__in = [ self.request.user ]).distinct()
has_user_perms = base.filter(
inventory__permissions__user__in = [ self.request.user ],
inventory__permissions__permission_type__in = PERMISSION_TYPES_ALLOWING_INVENTORY_READ,
).distinct()
has_team_perms = base.filter(
inventory__permissions__team__in = self.request.user.teams.all(),
inventory__permissions__permission_type__in = PERMISSION_TYPES_ALLOWING_INVENTORY_READ,
).distinct()
return admin_of | has_user_perms | has_team_perms
class GroupsDetail(BaseDetail):
model = Group
serializer_class = GroupSerializer
permission_classes = (CustomRbac,)

View File

@ -48,6 +48,8 @@ views_InventoryList = views.InventoryList.as_view()
views_InventoryDetail = views.InventoryDetail.as_view()
# group service
views_GroupsList = views.GroupsList.as_view()
views_GroupsDetail = views.GroupsDetail.as_view()
# host service
views_HostsList = views.HostsList.as_view()
@ -99,6 +101,8 @@ urlpatterns = patterns('',
url(r'^api/v1/hosts/(?P<pk>[0-9]+)/$', views_HostsDetail),
# group service
url(r'^api/v1/groups/$', views_GroupsList),
url(r'^api/v1/groups/(?P<pk>[0-9]+)/$', views_GroupsDetail),
# inventory variable service