interpret absent related field as a unchanged state in permissions check

This commit is contained in:
AlanCoding
2016-11-02 11:11:37 -04:00
parent 5c2c46c5aa
commit db890b5759

View File

@@ -206,6 +206,7 @@ class BaseAccess(object):
''' '''
new = None new = None
new_pk = None new_pk = None
changed = True
if data and 'reference_obj' in data: if data and 'reference_obj' in data:
# Use reference object's related fields, if given # Use reference object's related fields, if given
new = getattr(data['reference_obj'], field) new = getattr(data['reference_obj'], field)
@@ -219,21 +220,22 @@ class BaseAccess(object):
if type(raw_value) == Model: if type(raw_value) == Model:
new = raw_value new = raw_value
new_pk = getattr(new, 'pk', None) new_pk = getattr(new, 'pk', None)
elif data is None or field not in data:
changed = False
# Obtain existing related resource # Obtain existing related resource
current = None current = None
current_pk = None current_pk = None
if obj: if obj and (changed or mandatory):
current = getattr(obj, field) current = getattr(obj, field)
current_pk = getattr(obj, '%s_id' % field, None) current_pk = getattr(obj, '%s_id' % field, None)
# Define special case where resource is not changed # Define special case where resource is not changed, for example, a PUT request
changed = True if (current_pk and new_pk == current_pk) or (obj is None and new_pk is None):
if (new_pk is None or new_pk == current_pk) and (new is None or new == current):
changed = False changed = False
# Get the new resource from the database # Get the new resource from the database
if new is None and new_pk is not None: if (new is None and changed) or (obj is None and mandatory):
if fail_on_missing: if fail_on_missing:
new = get_object_or_400(Model, pk=new_pk) new = get_object_or_400(Model, pk=new_pk)
else: else:
@@ -916,7 +918,7 @@ class ProjectAccess(BaseAccess):
def can_add(self, data): def can_add(self, data):
if not data: # So the browseable API will work if not data: # So the browseable API will work
return Organization.accessible_objects(self.user, 'admin_role').exists() return Organization.accessible_objects(self.user, 'admin_role').exists()
return self.check_related('organization', Organization, data, mandatory=True) return self.check_related('organization', Organization, data, mandatory=True, fail_on_missing=False)
@check_superuser @check_superuser
def can_change(self, obj, data): def can_change(self, obj, data):
@@ -1978,17 +1980,13 @@ class LabelAccess(BaseAccess):
def can_add(self, data): def can_add(self, data):
if not data: # So the browseable API will work if not data: # So the browseable API will work
return True return True
return self.check_related('organization', Organization, data, role_field='member_role', mandatory=True)
org_pk = get_pk_from_dict(data, 'organization')
org = get_object_or_400(Organization, pk=org_pk)
return self.user in org.member_role
@check_superuser @check_superuser
def can_change(self, obj, data): def can_change(self, obj, data):
if self.can_add(data) is False: if self.can_add(data) is False:
return False return False
return self.check_related('organization', Organization, data, obj=obj, mandatory=True)
return self.user in obj.organization.admin_role
def can_delete(self, obj): def can_delete(self, obj):
return self.can_change(obj, None) return self.can_change(obj, None)