mirror of
https://github.com/ansible/awx.git
synced 2026-01-18 13:11:19 -03:30
Some hacks to make organizational user object creation possible by posting directly to the subcollection. This is a little complex due to the user (being a Django object) not having any FKs
to our objects. This should be refactored later but is at least sufficiently operational for the two cases it is used here.
This commit is contained in:
parent
69a9916423
commit
21f4e3a680
@ -124,8 +124,12 @@ class BaseSubList(BaseList):
|
||||
return Response(status=status.HTTP_400_BAD_REQUEST, data=ser.errors)
|
||||
|
||||
# ask the usual access control settings
|
||||
if not self.__class__.model.can_user_add(request.user, ser.init_data):
|
||||
raise PermissionDenied()
|
||||
if self.__class__.model in [ User ]:
|
||||
if not UserHelper.can_user_add(request.user, ser.init_data):
|
||||
raise PermissionDenied()
|
||||
else:
|
||||
if not self.__class__.model.can_user_add(request.user, ser.init_data):
|
||||
raise PermissionDenied()
|
||||
|
||||
# save the object through the serializer, reload and returned the saved object deserialized
|
||||
obj = ser.save()
|
||||
@ -140,10 +144,42 @@ class BaseSubList(BaseList):
|
||||
|
||||
|
||||
if self.__class__.parent_model != User:
|
||||
if not obj.__class__.can_user_read(request.user, obj):
|
||||
raise PermissionDenied()
|
||||
|
||||
# FIXME: refactor into smaller functions
|
||||
|
||||
if obj.__class__ in [ User]:
|
||||
if self.__class__.parent_model == Organization:
|
||||
# user can't inject an organization because it's not part of the user
|
||||
# model so we have to cheat here. This may happen for other cases
|
||||
# where we are creating a user immediately on a subcollection
|
||||
# when that user does not already exist. Relations will work post-save.
|
||||
organization = Organization.objects.get(pk=request.DATA[inject_primary_key])
|
||||
if not request.user.is_superuser:
|
||||
if not organization.admins.filter(pk=request.user.pk).count() > 0:
|
||||
raise PermissionDenied()
|
||||
else:
|
||||
raise exceptions.NotImplementedError()
|
||||
else:
|
||||
if not obj.__class__.can_user_read(request.user, obj):
|
||||
raise PermissionDenied()
|
||||
if not self.__class__.parent_model.can_user_attach(request.user, main, obj, self.__class__.relationship, request.DATA):
|
||||
raise PermissionDenied()
|
||||
|
||||
# FIXME: manual attachment code neccessary for users here, move this into the main code.
|
||||
# this is because users don't have FKs into what they are attaching. (also refactor)
|
||||
|
||||
if self.__class__.parent_model == Organization:
|
||||
organization = Organization.objects.get(pk=request.DATA[inject_primary_key])
|
||||
import lib.main.views
|
||||
if self.__class__ == lib.main.views.OrganizationsUsersList:
|
||||
organization.users.add(obj)
|
||||
organization.save()
|
||||
elif self.__class__ == lib.main.views.OrganizationsAdminsList:
|
||||
organization.admins.add(obj)
|
||||
organization.save()
|
||||
|
||||
|
||||
|
||||
else:
|
||||
if not UserHelper.can_user_read(request.user, obj):
|
||||
raise PermissionDenied()
|
||||
|
||||
@ -130,6 +130,14 @@ class UserHelper(object):
|
||||
matching_orgs = obj.organizations.filter(admins__in = [user]).count()
|
||||
return matching_orgs
|
||||
|
||||
@classmethod
|
||||
def can_user_add(cls, user, data):
|
||||
# TODO: reuse. make helper functions like "is user an org admin"
|
||||
# apply throughout permissions code
|
||||
if user.is_superuser:
|
||||
return True
|
||||
return user.admin_of_organizations.count() > 0
|
||||
|
||||
@classmethod
|
||||
def can_user_attach(cls, user, obj, sub_obj, relationship_type, data):
|
||||
if type(sub_obj) != User:
|
||||
@ -193,7 +201,9 @@ class PrimordialModel(models.Model):
|
||||
|
||||
# in order to attach something you also be able to read what you are attaching
|
||||
if type(sub_obj) == User:
|
||||
return UserHelper.can_user_read(user, sub_obj)
|
||||
# we already check that the user is an admin or org admin up in base_views.py
|
||||
# because the user doesn't have the attributes on it directly to tie it to the org
|
||||
return True
|
||||
else:
|
||||
return sub_obj.__class__.can_user_read(user, sub_obj)
|
||||
|
||||
|
||||
@ -270,6 +270,15 @@ class OrganizationsTest(BaseTest):
|
||||
users = self.get(url, expect=200, auth=self.get_normal_credentials())
|
||||
self.assertEqual(users['count'], 1)
|
||||
|
||||
# post a completely new user to verify we can add users to the subcollection directly
|
||||
new_user = dict(username='NewUser9000')
|
||||
which_org = self.normal_django_user.admin_of_organizations.all()[0]
|
||||
url = '/api/v1/organizations/%s/users/' % (which_org.pk)
|
||||
posted = self.post(url, new_user, expect=201, auth=self.get_normal_credentials())
|
||||
|
||||
all_users = self.get(url, expect=200, auth=self.get_normal_credentials())
|
||||
self.assertEqual(all_users['count'], 2)
|
||||
|
||||
def test_post_item_subobjects_admins(self):
|
||||
|
||||
url = '/api/v1/organizations/2/admins/'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user