Skip to content
Snippets Groups Projects
Commit fa1b58a3 authored by Megan Henning's avatar Megan Henning
Browse files

Add more detailed permission errors

parent ed098407
No related branches found
No related tags found
No related merge requests found
...@@ -3,6 +3,8 @@ Purpose of this module is to define all the permissions checker decorators for t ...@@ -3,6 +3,8 @@ Purpose of this module is to define all the permissions checker decorators for t
""" """
from . import _get_access, INTEGER_PERMISSIONS from . import _get_access, INTEGER_PERMISSIONS
from ..web.errors import APIPermissionException
from .. import config
def default_container(handler, container=None, target_parent_container=None): def default_container(handler, container=None, target_parent_container=None):
...@@ -35,8 +37,9 @@ def default_container(handler, container=None, target_parent_container=None): ...@@ -35,8 +37,9 @@ def default_container(handler, container=None, target_parent_container=None):
user_perms = _get_access(handler.uid, container) user_perms = _get_access(handler.uid, container)
has_access = user_perms >= INTEGER_PERMISSIONS[required_perm] has_access = user_perms >= INTEGER_PERMISSIONS[required_perm]
if not has_access and has_original_data and user_perms == INTEGER_PERMISSIONS['rw']: if not has_access and container.get('has_original_data', False) and user_perms == INTEGER_PERMISSIONS['rw']:
# The user was not granted access because the container had original data # The user was not granted access because the container had original data
errors = {'reason': 'original_data_present'} errors = {'reason': 'original_data_present'}
else: else:
errors = {'reason': 'permission_denied'} errors = {'reason': 'permission_denied'}
......
...@@ -171,15 +171,16 @@ def container_has_original_data(container, child_cont_name=None): ...@@ -171,15 +171,16 @@ def container_has_original_data(container, child_cont_name=None):
If the set only includes user and job uploaded files, the container If the set only includes user and job uploaded files, the container
is not considered to have "original data". is not considered to have "original data".
""" """
origin_types = set()
for f in container.get('files', []): for f in container.get('files', []):
origin_types.add(f['origin']['type']) if f['origin']['type'] not in [str(Origin.user), str(Origin.job)]:
return True
if child_cont_name: if child_cont_name:
for c in container.get(child_cont_name, []): for c in container.get(child_cont_name, []):
for f in c.get('files', []): for f in c.get('files', []):
origin_types.add(f['origin']['type']) if f['origin']['type'] not in [str(Origin.user), str(Origin.job)]:
return origin_types.issubset(set(str(Origin.user, Origin.job))) return True
return False
class ContainerReference(object): class ContainerReference(object):
......
...@@ -13,7 +13,7 @@ from ..jobs.jobs import Job ...@@ -13,7 +13,7 @@ from ..jobs.jobs import Job
from ..jobs.queue import Queue from ..jobs.queue import Queue
from ..types import Origin from ..types import Origin
from ..web import base from ..web import base
from ..web.errors import APIStorageException from ..web.errors import APIStorageException, APIPermissionException
from ..web.request import log_access, AccessType from ..web.request import log_access, AccessType
log = config.log log = config.log
...@@ -531,20 +531,29 @@ class ContainerHandler(base.RequestHandler): ...@@ -531,20 +531,29 @@ class ContainerHandler(base.RequestHandler):
_id = kwargs.pop('cid') _id = kwargs.pop('cid')
self.config = self.container_handler_configurations[cont_name] self.config = self.container_handler_configurations[cont_name]
self.storage = self.config['storage'] self.storage = self.config['storage']
container = self._get_container(_id, get_children=True)
if cont_name != 'acquisitions':
get_children = True
else:
get_children = False
container = self._get_container(_id, get_children=get_children)
container['cont_name'] = containerutil.singularize(cont_name) container['cont_name'] = containerutil.singularize(cont_name)
if cont_name in ['sessions', 'acquisitions']: if cont_name in ['sessions', 'acquisitions']:
container['has_original_data'] = containerutil.container_origin_types(container, child_cont_name=self.config.get('children_cont')) container['has_original_data'] = containerutil.container_has_original_data(container, child_cont_name=self.config.get('children_cont'))
if cont_name == 'acquisitions': if cont_name == 'acquisitions':
analyses = containerutil.get_referring_analyses(cont_name, _id) analyses = containerutil.get_referring_analyses(cont_name, _id)
if analyses: if analyses:
analysis_ids = [str(a['_id']) for a in analyses] analysis_ids = [str(a['_id']) for a in analyses]
self.abort(400, 'Cannot delete acquisition {} referenced by analyses {}'.format(_id, analysis_ids)) errors = {'reason': 'analysis_conflict'}
raise APIPermissionException('Cannot delete acquisition {} referenced by analyses {}'.format(_id, analysis_ids), errors=errors)
target_parent_container, _ = self._get_parent_container(container) target_parent_container, _ = self._get_parent_container(container)
permchecker = self._get_permchecker(container, target_parent_container) permchecker = self._get_permchecker(container, target_parent_container)
permchecker(noop)('DELETE', _id) permchecker(noop)('DELETE', _id)
if self.is_true('check'):
# User only wanted to check permissions, respond with 200
return
try: try:
# This line exec the actual delete checking permissions using the decorator permchecker # This line exec the actual delete checking permissions using the decorator permchecker
......
...@@ -345,6 +345,7 @@ class RequestHandler(webapp2.RequestHandler): ...@@ -345,6 +345,7 @@ class RequestHandler(webapp2.RequestHandler):
elif isinstance(exception, errors.APIConsistencyException): elif isinstance(exception, errors.APIConsistencyException):
code = 400 code = 400
elif isinstance(exception, errors.APIPermissionException): elif isinstance(exception, errors.APIPermissionException):
custom_errors = exception.errors
code = 403 code = 403
elif isinstance(exception, errors.APINotFoundException): elif isinstance(exception, errors.APINotFoundException):
code = 404 code = 404
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment