Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
collections_.py 7.95 KiB
# @author:  Gunnar Schaefer

import re
import json
import webapp2
import bson.json_util

import logging
log = logging.getLogger('nimsapi')

import nimsapiutil

# curator (later: multiple curators and authorizers)
# name
# permissions
# epochs point to collections

# /collections
# /collections/<cid>/sessions
# /collections/<cid>/epochs?session=<sid>
# /collections/<cid>/sessions/<sid>/epochs

class Collections(nimsapiutil.NIMSRequestHandler):

    """/collections """

    json_schema = {
        '$schema': 'http://json-schema.org/draft-04/schema#',
        'title': 'Collection List',
        'type': 'array',
        'items': {
            'title': 'Collection',
            'type': 'object',
            'properties': {
                '_id': {
                    'title': 'Database ID',
                },
                'site': {
                    'title': 'Site',
                    'type': 'string',
                },
                'group': {
                    'title': 'Group',
                    'type': 'string',
                },
                'name': {
                    'title': 'Name',
                    'type': 'string',
                },
                'permissions': {
                    'title': 'Permissions',
                    'type': 'object',
                },
            }
        }
    }

    def count(self):
        """Return the number of Collections."""
        self.response.write(json.dumps(self.app.db.collections.count()))

    def post(self):
        """Create a new Collection."""
        self.response.write('collections post\n')

    def get(self):
        """Return the list of Collections."""
        query = {'permissions.' + self.userid: {'$exists': 'true'}} if not self.user_is_superuser else None
        projection = ['curator', 'name', 'permissions.'+self.userid, 'notes']
        collections = list(self.app.db.collections.find(query, projection))
        self.response.write(json.dumps(collections, default=bson.json_util.default))

    def put(self):
        """Update many Collections."""
        self.response.write('collections put\n')


class Collection(nimsapiutil.NIMSRequestHandler):

    """/collections/<cid> """

    json_schema = {
        '$schema': 'http://json-schema.org/draft-04/schema#',
        'title': 'Collection',
        'type': 'object',
        'properties': {
            '_id': {
                'title': 'Database ID',
            },
            'site': {
                'title': 'Site',
                'type': 'string',
            },
            'group': {
                'title': 'Group',
                'type': 'string',
            },
            'name': {
                'title': 'Name',
                'type': 'string',
                'maxLength': 32,
            },
            'permissions': {
                'title': 'Permissions',
                'type': 'object',
                'minProperties': 1,
            },
            'files': {
                'title': 'Files',
                'type': 'array',
                'items': nimsapiutil.NIMSRequestHandler.file_schema,
                'uniqueItems': True,
            },
        },
        'required': ['_id', 'group', 'name'], #FIXME
    }

    def get(self, cid):
        """Return one Collection, conditionally with details."""
        collection = self.app.db.collections.find_one({'_id': bson.ObjectId(cid)})
        if not collection:
            self.abort(404)
        if not self.user_is_superuser:
            if self.userid not in collection['permissions']:
                self.abort(403)
            if collection['permissions'][self.userid] != 'admin' and collection['permissions'][self.userid] != 'pi':
                collection['permissions'] = {self.userid: collection['permissions'][self.userid]}
        self.response.write(json.dumps(collection, default=bson.json_util.default))

    def put(self, cid):
        """Update an existing Collection."""
        self.response.write('collection %s put, %s\n' % (exp_id, self.request.params))

    def delete(self, cid):
        """Delete a Collection."""
        self.abort(501)


class Sessions(nimsapiutil.NIMSRequestHandler):

    """/collections/<cid>/sessions """

    json_schema = {
        '$schema': 'http://json-schema.org/draft-04/schema#',
        'title': 'Session List',
        'type': 'array',
        'items': {
            'title': 'Session',
            'type': 'object',
            'properties': {
                '_id': {
                    'title': 'Database ID',
                },
                'name': {
                    'title': 'Session',
                    'type': 'string',
                },
                'subject': {
                    'title': 'Subject',
                    'type': 'string',
                },
                'site': {
                    'title': 'Site',
                    'type': 'string',
                },
            }
        }
    }

    def count(self):
        """Return the number of Sessions."""
        self.response.write(json.dumps(self.app.db.sessions.count()))

    def post(self):
        """Create a new Session"""
        self.response.write('sessions post\n')

    def get(self, cid):
        """Return the list of Session Epochs."""
        collection = self.app.db.collections.find_one({'_id': bson.ObjectId(cid)})
        if not collection:
            self.abort(404)
        if not self.user_is_superuser and self.userid not in collection['permissions']:
            self.abort(403)
        aggregated_epochs = self.app.db.epochs.aggregate([
                {'$match': {'collections': bson.ObjectId(cid)}},
                {'$group': {'_id': '$session'}},
                ])['result']
        query = {'_id': {'$in': [agg_epoch['_id'] for agg_epoch in aggregated_epochs]}}
        projection = ['name', 'subject', 'notes']
        sessions = list(self.app.db.sessions.find(query, projection))
        for sess in sessions:
            sess['site'] = self.app.config['site_id']
        self.response.write(json.dumps(sessions, default=bson.json_util.default))

    def put(self):
        """Update many Sessions."""
        self.response.write('sessions put\n')


class Epochs(nimsapiutil.NIMSRequestHandler):

    """/collections/<cid>/epochs """

    json_schema = {
        '$schema': 'http://json-schema.org/draft-04/schema#',
        'title': 'Epoch List',
        'type': 'array',
        'items': {
            'title': 'Epoch',
            'type': 'object',
            'properties': {
                '_id': {
                    'title': 'Database ID',
                },
                'name': {
                    'title': 'Epoch',
                    'type': 'string',
                },
                'description': {
                    'title': 'Description',
                    'type': 'string',
                },
                'datatype': {
                    'title': 'Datatype',
                    'type': 'string',
                },
            }
        }
    }

    def count(self):
        """Return the number of Epochs."""
        self.response.write(json.dumps(self.app.db.epochs.count()))

    def post(self):
        """Create a new Epoch."""
        self.response.write('epochs post\n')

    def get(self, cid):
        """Return the list of Session Epochs."""
        collection = self.app.db.collections.find_one({'_id': bson.ObjectId(cid)})
        if not collection:
            self.abort(404)
        if not self.user_is_superuser and self.userid not in collection['permissions']:
            self.abort(403)
        query = {'collections': bson.ObjectId(cid)}
        sid = self.request.get('session')
        if re.match(r'^[0-9a-f]{24}$', sid):
            query['session'] = bson.ObjectId(sid)
        elif sid != '':
            self.abort(400)
        projection = ['name', 'description', 'datatype', 'notes']
        epochs = list(self.app.db.epochs.find(query, projection))
        self.response.write(json.dumps(epochs, default=bson.json_util.default))

    def put(self):
        """Update many Epochs."""
        self.response.write('epochs put\n')