From 3ad75667ad317d882d7da43c3353acac343fcad2 Mon Sep 17 00:00:00 2001
From: Nathaniel Kofalt <nathaniel@kofalt.com>
Date: Thu, 3 Mar 2016 16:56:17 -0600
Subject: [PATCH] Move endpoint, authorize, copy permissions

---
 api/api.py                  |  2 +-
 api/handlers/listhandler.py | 30 ++++++++++++++++++++++++++----
 api/placer.py               | 15 ++++++++++++++-
 api/upload.py               |  4 ----
 4 files changed, 41 insertions(+), 10 deletions(-)

diff --git a/api/api.py b/api/api.py
index 49ce1210..11589df1 100644
--- a/api/api.py
+++ b/api/api.py
@@ -73,7 +73,6 @@ routes = [
         webapp2.Route(r'/download',         download.Download, handler_method='download', methods=['GET', 'POST'], name='download'),
         webapp2.Route(r'/reaper',           upload.Upload, handler_method='reaper', methods=['POST']),
         webapp2.Route(r'/uploader',         upload.Upload, handler_method='uploader', methods=['POST']),
-        webapp2.Route(r'/packfile',         upload.Upload, handler_method='packfile', methods=['POST']),
         webapp2.Route(r'/engine',           upload.Upload, handler_method='engine', methods=['POST']),
         webapp2.Route(r'/sites',            centralclient.CentralClient, handler_method='sites', methods=['GET']),
         webapp2.Route(r'/register',         centralclient.CentralClient, handler_method='register', methods=['POST']),
@@ -118,6 +117,7 @@ routes = [
     webapp2.Route(_format(r'/api/<cont_name:{cont_name_re}>/<cid:{cid_re}>/<list_name:tags>'),                                      listhandler.ListHandler, methods=['POST'], name='tags_post'),
     webapp2.Route(_format(r'/api/<cont_name:{cont_name_re}>/<cid:{cid_re}>/<list_name:tags>/<value:{tag_re}>'),                     listhandler.ListHandler, name='tags'),
 
+    webapp2.Route(_format(r'/api/<cont_name:{cont_name_re}>/<cid:{cid_re}>/packfile'),                                     listhandler.FileListHandler, name='packfile', handler_method='packfile', methods=['POST']),
     webapp2.Route(_format(r'/api/<cont_name:{cont_name_re}>/<cid:{cid_re}>/<list_name:files>'),                                     listhandler.FileListHandler, name='files_post', methods=['POST']),
     webapp2.Route(_format(r'/api/<cont_name:{cont_name_re}>/<cid:{cid_re}>/<list_name:files>/<name:{filename_re}>'),            listhandler.FileListHandler, name='files'),
 
diff --git a/api/handlers/listhandler.py b/api/handlers/listhandler.py
index 46fc97d7..453580ce 100644
--- a/api/handlers/listhandler.py
+++ b/api/handlers/listhandler.py
@@ -355,10 +355,6 @@ class FileListHandler(ListHandler):
         return result
 
     def post(self, cont_name, list_name, **kwargs):
-
-        # TODO: plural consistency
-        cont_name = cont_name[:-1]
-
         _id = kwargs.pop('cid')
 
         # Authorize
@@ -366,3 +362,29 @@ class FileListHandler(ListHandler):
         permchecker(noop)('POST', _id=_id)
 
         return upload.process_upload(self.request, upload.Strategy.targeted, cont_name, _id)
+
+    def packfile(self, cont_name, **kwargs):
+        _id = kwargs.pop('cid')
+
+        if cont_name != 'projects':
+            raise Exception('Packfiles can only be targeted at projects')
+
+        # Authorize: confirm project exists
+        project = config.db['projects'].find_one({ '_id': bson.ObjectId(_id)})
+
+        print project
+
+        if project is None:
+            raise Exception('Project ' + _id + ' does not exist')
+
+        # Authorize: confirm user has admin/write perms
+        if not self.superuser_request:
+            perms = project.get('permissions', [])
+
+            for p in perms:
+                if p['_id'] == self.uid and p['access'] in ('rw', 'admin'):
+                    break
+            else:
+                raise Exception('Not authorized')
+
+        return upload.process_upload(self.request, upload.Strategy.packfile)
diff --git a/api/placer.py b/api/placer.py
index 5dbe5428..6c1b322d 100644
--- a/api/placer.py
+++ b/api/placer.py
@@ -166,6 +166,10 @@ class PackfilePlacer(Placer):
         self.s_label = self.metadata['session']['label']
         self.a_label = self.metadata['acquisition']['label']
 
+        # Get project permissions
+        project = config.db['projects'].find_one({ '_id': bson.ObjectId(self.p_id)})
+        self.permissions = project.get('permissions', {})
+
         # If a timestamp was provided, use that for zip files. Otherwise use a set date.
         # Normally we'd use epoch, but zips cannot support years older than 1980, so let's use that instead.
         # Then, given the ISO string, convert it to an epoch integer.
@@ -238,11 +242,17 @@ class PackfilePlacer(Placer):
             'label': self.s_label
         }
 
+        # self.permissions
+
         # Add the subject if one was provided
         new_s = copy.deepcopy(s)
         subject = self.metadata['session'].get('subject')
         if subject is not None:
             new_s['subject'] = subject
+        new_s = util.mongo_dict(new_s)
+
+        # Permissions should always be an exact copy
+        new_s['permissions'] = self.permissions
 
         session = config.db['session' + 's'].find_one_and_update(s, {
                 '$set': new_s
@@ -257,8 +267,11 @@ class PackfilePlacer(Placer):
             'label': self.a_label
         }
 
+        new_a = copy.deepcopy(fields)
+        new_a['permissions'] = self.permissions
+
         acquisition = config.db['acquisition' + 's'].find_one_and_update(fields, {
-                '$set': fields
+                '$set': new_a
             },
             upsert=True,
             return_document=pymongo.collection.ReturnDocument.AFTER
diff --git a/api/upload.py b/api/upload.py
index 28d0ae07..55f23589 100644
--- a/api/upload.py
+++ b/api/upload.py
@@ -266,7 +266,3 @@ class Upload(base.RequestHandler):
                     rules.create_jobs(config.db, acquisition_obj, 'acquisition', file_)
             return [{'name': k, 'hash': v.info.get('hash'), 'size': v.info.get('size')} for k, v in merged_files.items()]
 
-    def packfile(self):
-        # TODO: Perm check
-
-        return process_upload(self.request, Strategy.packfile)
-- 
GitLab