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

Revise delete permissions

parent 5ef0951d
No related branches found
No related tags found
No related merge requests found
......@@ -26,9 +26,12 @@ def default_container(handler, container=None, target_parent_container=None):
required_perm = 'admin'
has_access = _get_access(handler.uid, target_parent_container) >= INTEGER_PERMISSIONS[required_perm]
elif method == 'DELETE':
# Container deletion always requires admin
required_perm = 'admin'
has_access = _get_access(handler.uid, target_parent_container) >= INTEGER_PERMISSIONS[required_perm]
# Project delete requires admin, others require rw
if container['cont_name'] == 'project' or container.get('has_original_data', False):
required_perm = 'admin'
else:
required_perm = 'rw'
has_access = _get_access(handler.uid, container) >= INTEGER_PERMISSIONS[required_perm]
elif method == 'PUT' and target_parent_container is not None:
has_access = (
_get_access(handler.uid, container) >= INTEGER_PERMISSIONS['admin'] and
......
......@@ -6,6 +6,7 @@ Purpose of this module is to define all the permissions checker decorators for t
import sys
from .. import config
from ..types import Origin
from . import _get_access, INTEGER_PERMISSIONS
log = config.log
......@@ -36,6 +37,34 @@ def default_sublist(handler, container):
return f
return g
def files_sublist(handler, container):
"""
Files have slightly modified permissions centered around origin.
Admin is required to remove files with an origin type other than engine or user.
"""
access = _get_access(handler.uid, container)
def g(exec_op):
def f(method, _id, query_params=None, payload=None, exclude_params=None):
if method == 'GET' and container.get('public', False):
min_access = -1
elif method == 'GET':
min_access = INTEGER_PERMISSIONS['ro']
elif method in ['POST', 'PUT']:
min_access = INTEGER_PERMISSIONS['rw']
elif method =='DELETE':
min_access = INTEGER_PERMISSIONS['admin']
if container.get('origin',{}).get('type') in [str(Origin.user), str(Origin.job)]:
min_access = INTEGER_PERMISSIONS['rw']
else:
min_access = sys.maxint
if access >= min_access:
return exec_op(method, _id, query_params, payload, exclude_params)
else:
handler.abort(403, 'user not authorized to perform a {} operation on the list'.format(method))
return f
return g
def group_permissions_sublist(handler, container):
"""
This is the customized permissions checker for group permissions operations.
......
......@@ -3,6 +3,7 @@ import copy
from .. import config
from ..auth import has_access
from ..types import Origin
from ..web.errors import APINotFoundException, APIPermissionException
......@@ -163,6 +164,24 @@ def get_referring_analyses(cont_name, cont_id, filename=None):
return list(analyses)
def container_has_original_data(container, child_cont_name=None):
"""
Given a container, creates a list of all origin types
for all files in the container and it's children, if provided.
If the set only includes user and job uploaded files, the container
is not considered to have "original data".
"""
origin_types = set()
for f in container.get('files', []):
origin_types.add(f['origin']['type'])
if child_cont_name:
for c in container.get(child_cont_name, []):
for f in c.get('files', []):
origin_types.add(f['origin']['type'])
return origin_types.issubset(set(str(Origin.user, Origin.job)))
class ContainerReference(object):
# pylint: disable=redefined-builtin
# TODO: refactor to resolve pylint warning
......
......@@ -531,14 +531,11 @@ class ContainerHandler(base.RequestHandler):
_id = kwargs.pop('cid')
self.config = self.container_handler_configurations[cont_name]
self.storage = self.config['storage']
container = self._get_container(_id)
if self.config.get('children_cont'):
container['has_children'] = bool(self.storage.get_children(_id))
else:
container['has_children'] = False
if container.get('files') or container.get('analyses'):
container['has_children'] = True
container = self._get_container(_id, get_children=True)
container['cont_name'] = containerutil.singularize(cont_name)
if cont_name in ['sessions', 'acquisitions']:
container['has_original_data'] = containerutil.container_origin_types(container, child_cont_name=self.config.get('children_cont'))
if cont_name == 'acquisitions':
analyses = containerutil.get_referring_analyses(cont_name, _id)
if analyses:
......
......@@ -3,7 +3,7 @@ import datetime
from ..web import base
from .. import util
from .. import validators
from ..auth import groupauth
from ..auth import groupauth, require_admin
from ..dao import containerstorage
from .containerhandler import ContainerHandler
......@@ -24,6 +24,7 @@ class GroupHandler(base.RequestHandler):
ContainerHandler.join_user_info([result])
return result
@require_admin
def delete(self, _id):
if _id == 'unknown':
self.abort(400, 'The group "unknown" can\'t be deleted as it is integral within the API')
......
......@@ -38,7 +38,7 @@ def initialize_list_configurations():
},
'files': {
'storage': liststorage.FileStorage,
'permchecker': listauth.default_sublist,
'permchecker': listauth.files_sublist,
'use_object_id': True,
'storage_schema_file': 'file.json',
'input_schema_file': 'file.json'
......@@ -380,44 +380,6 @@ class FileListHandler(ListHandler):
return info
def get(self, cont_name, list_name, **kwargs):
"""
.. http:get:: /api/(cont_name)/(cid)/files/(file_name)
Gets the ticket used to download the file when the ticket is not provided.
Downloads the file when the ticket is provided.
:query ticket: should be empty
:param cont_name: one of ``projects``, ``sessions``, ``acquisitions``, ``collections``
:type cont_name: string
:param cid: Container ID
:type cid: string
:statuscode 200: no error
:statuscode 400: explain...
:statuscode 409: explain...
**Example request**:
.. sourcecode:: http
GET /api/acquisitions/57081d06b386a6dc79ca383c/files/fMRI%20Loc%20Word%20Face%20Obj.zip?ticket= HTTP/1.1
Host: demo.flywheel.io
Accept: */*
**Example response**:
.. sourcecode:: http
HTTP/1.1 200 OK
Vary: Accept-Encoding
Content-Type: application/json; charset=utf-8
{"ticket": "1e975e3d-21e9-41f4-bb97-261f03d35ba1"}
"""
_id = kwargs.pop('cid')
permchecker, storage, _, _, keycheck = self._initialize_request(cont_name, list_name, _id)
list_name = storage.list_name
......
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