From 13ec69cf187bf89426b4acab13de89d99703617e Mon Sep 17 00:00:00 2001
From: Harsha Kethineni <harshakethineni@flywheel.io>
Date: Wed, 6 Dec 2017 11:58:20 -0600
Subject: [PATCH] Sub_containers in url to filter analyses

---
 api/api.py                                    |  2 ++
 api/handlers/refererhandler.py                | 32 +++++++++++++++----
 .../python/test_containers.py                 | 20 +++++++++---
 3 files changed, 43 insertions(+), 11 deletions(-)

diff --git a/api/api.py b/api/api.py
index 97334aa9..21f6e9d5 100644
--- a/api/api.py
+++ b/api/api.py
@@ -192,6 +192,7 @@ endpoints = [
 
             route('/<cid:{gid}>/<list_name:tags>',                           TagsListHandler, m=['POST']),
             route('/<cid:{gid}>/<list_name:tags>/<value:{tag}>',             TagsListHandler, m=['GET', 'PUT', 'DELETE']),
+            route('/<cid:{gid}>/<sub_cont_name:{cname}|all>/analyses',       AnalysesHandler, h='get_all',       m=['GET']),
         ]),
 
 
@@ -270,6 +271,7 @@ endpoints = [
                 route('/<list_name:files>/<name:{fname}>/info', FileListHandler, h='get_info',       m=['GET']),
                 route('/<list_name:files>/<name:{fname}>/info', FileListHandler, h='modify_info',    m=['POST']),
 
+                route( '/<sub_cont_name:{cname}|all>/analyses',         AnalysesHandler, h='get_all',       m=['GET']),
                 route( '/analyses',                                     AnalysesHandler, h='get_all',       m=['GET']),
                 route( '/analyses',                                     AnalysesHandler,                    m=['POST']),
                 prefix('/analyses', [
diff --git a/api/handlers/refererhandler.py b/api/handlers/refererhandler.py
index 01ec481e..568620a1 100644
--- a/api/handlers/refererhandler.py
+++ b/api/handlers/refererhandler.py
@@ -139,20 +139,40 @@ class AnalysesHandler(RefererHandler):
         self.log_user_access(AccessType.view_container, cont_name=analysis['parent']['type'], cont_id=analysis['parent']['id'])
         return analysis
 
-    def get_all(self, cont_name, cid):
-        cid = bson.ObjectId(cid)
+    def get_all(self, cont_name, cid, **kwargs):
+        """
+        The possible endpoints for this method are:
+        /{cont_name}/{id}/analyses
+        /{cont_name}/{id}/{sub_cont_name}/analyses
+        /{cont_name}/{id}/all/analyses
+        """
+        if not cont_name == 'groups':
+            cid = bson.ObjectId(cid)
         # Check that user has permission to container
         container = ContainerStorage.factory(cont_name).get_container(cid)
         if not container:
             self.abort(404, 'Element not found in container {} {}'.format(cont_name, cid))
         permchecker = self.get_permchecker(container)
         permchecker(noop)('GET')
-
-        if self.is_true("children"):
+        # cont_level is the sub_container name for which the analysis.parent.type should be
+        cont_level = kwargs.get('sub_cont_name')
+        cont_names = {'groups':0, 'projects':1, 'sessions':2, 'acquisitions':3}
+        sub_cont_names = {'projects':0, 'sessions':1, 'acquisitions':2, 'all':3}
+
+        # Check that the url is valid
+        if cont_name not in cont_names.keys():
+            self.abort(400, "Analysis lists not supported for {}.".format(cont_name))
+        elif cont_level:
+            if cont_names[cont_name] > sub_cont_names.get(cont_level, -1):
+                self.abort(400, "{} not a child of {} or 'all'.".format(cont_level, cont_name))
+
+        if cont_level:
             parent_tree = ContainerStorage.get_top_down_hierarchy(cont_name, cid)
             # We only need a list of all the ids, no need for the tree anymore
-            parents = [pid for parent in parent_tree.keys() for pid in parent_tree[parent]]
-
+            if cont_level == 'all':
+                parents = [pid for parent in parent_tree.keys() for pid in parent_tree[parent]]
+            else:
+                parents = [pid for pid in parent_tree[cont_level]]
             # We set User to None because we check for permission when finding the parents
             analyses = containerstorage.AnalysisStorage().get_all_el({'parent.id':{'$in':parents}},None,{'info': 0, 'files.info': 0})
         else:
diff --git a/tests/integration_tests/python/test_containers.py b/tests/integration_tests/python/test_containers.py
index 0b475abb..965e73fb 100644
--- a/tests/integration_tests/python/test_containers.py
+++ b/tests/integration_tests/python/test_containers.py
@@ -175,6 +175,7 @@ def test_project_template(data_builder, file_form, as_admin):
 
 
 def test_get_all_containers(data_builder, as_admin, as_user, as_public, file_form):
+    group = data_builder.create_group()
     project_1 = data_builder.create_project()
     project_2 = data_builder.create_project()
     session = data_builder.create_session(project=project_1)
@@ -210,7 +211,7 @@ def test_get_all_containers(data_builder, as_admin, as_user, as_public, file_for
     assert r.ok
 
     # Test get_all analyses
-    project_3 = data_builder.create_project(public=False)
+    project_3 = data_builder.create_project(group=group, public=False)
     session_2 = data_builder.create_session(project=project_3, public=False)
 
     analysis_1 = as_admin.post('/sessions/' + session_2 + '/analyses', files=file_form(
@@ -221,19 +222,28 @@ def test_get_all_containers(data_builder, as_admin, as_user, as_public, file_for
     analysis_2 = as_admin.post('/acquisitions/' + acquisition + '/analyses', files=file_form(
         'analysis.csv', meta={'label': 'no-job', 'inputs': [{'name': 'analysis.csv'}]})).json()["_id"]
 
-    r = as_admin.get('/projects/' + project_3 + '/analyses', params={'children':True})
+
+    r = as_admin.get('/groups/' + group + '/sessions/analyses')
+    assert r.ok
+    assert len(r.json()) == 1
+
+    r = as_admin.get('/projects/' + project_3 + '/sessions/analyses')
+    assert r.ok
+    assert len(r.json()) == 1
+
+    r = as_admin.get('/projects/' + project_3 + '/all/analyses')
     assert r.ok
     assert len(r.json()) == 2
 
-    r = as_user.get('/projects/' + project_3 + '/analyses', params={'children':True})
+    r = as_user.get('/projects/' + project_3 + '/all/analyses')
     assert r.status_code == 403
 
 
-    r = as_admin.get('/sessions/' + session_2 + '/analyses', params={'children':False})
+    r = as_admin.get('/sessions/' + session_2 + '/analyses')
     assert r.ok
     assert len(r.json()) == 1
 
-    r = as_user.get('/sessions/' + session_2 + '/analyses', params={'children':False})
+    r = as_user.get('/sessions/' + session_2 + '/analyses')
     assert r.status_code == 403
 
 
-- 
GitLab