# @author: Gunnar Schaefer import logging log = logging.getLogger('nimsapi') import bson.json_util import base class Users(base.RequestHandler): """/nimsapi/users """ json_schema = { '$schema': 'http://json-schema.org/draft-04/schema#', 'title': 'User List', 'type': 'array', 'items': { 'title': 'User', 'type': 'object', 'properties': { '_id': { 'title': 'Database ID', 'type': 'string', }, 'firstname': { 'title': 'First Name', 'type': 'string', 'default': '', }, 'lastname': { 'title': 'Last Name', 'type': 'string', 'default': '', }, 'email': { 'title': 'Email', 'type': 'string', 'format': 'email', 'default': '', }, 'email_hash': { 'type': 'string', 'default': '', }, } } } def count(self): """Return the number of Users.""" if self.request.method == 'OPTIONS': return self.options() self.response.write(self.app.db.users.count()) def post(self): """Create a new User""" self.response.write('users post\n') def get(self): """Return the list of Users.""" if self.uid == '@public': self.abort(403, 'must be logged in to retrieve User list') users = list(self.app.db.users.find({}, ['firstname', 'lastname', 'email_hash'])) if self.debug: for user in users: user['metadata'] = self.uri_for('user', _id=str(user['_id']), _full=True) + '?' + self.request.query_string return users def put(self): """Update many Users.""" self.response.write('users put\n') class User(base.RequestHandler): """/nimsapi/users/<_id> """ json_schema = { '$schema': 'http://json-schema.org/draft-04/schema#', 'title': 'User', 'type': 'object', 'properties': { '_id': { 'title': 'Database ID', 'type': 'string', }, 'firstname': { 'title': 'First Name', 'type': 'string', 'default': '', }, 'lastname': { 'title': 'Last Name', 'type': 'string', 'default': '', }, 'email': { 'title': 'Email', 'type': 'string', 'format': 'email', 'default': '', }, 'email_hash': { 'type': 'string', 'default': '', }, 'superuser': { 'title': 'Superuser', 'type': 'boolean', }, }, 'required': ['_id'], } def get(self, _id): """Return User details.""" if self.uid == '@public': self.abort(403, 'must be logged in to retrieve User info') projection = [] if self.request.get('remotes') in ('1', 'true'): projection += ['remotes'] if self.request.get('status') in ('1', 'true'): projection += ['status'] user = self.app.db.users.find_one({'_id': _id}, projection or None) if not user: self.abort(404, 'no such User') if self.debug: user['groups'] = self.uri_for('groups', _id=_id, _full=True) + '?' + self.request.query_string return user def put(self, _id): """Update an existing User.""" user = self.app.db.users.find_one({'_id': _id}) if not user: self.abort(404) if _id == self.uid or self.user_is_superuser: # users can only update their own info updates = {'$set': {'_id': _id}, '$unset': {'__null__': ''}} for k, v in self.request.params.iteritems(): if k != 'superuser' and k in []:#user_fields: updates['$set'][k] = v # FIXME: do appropriate type conversion elif k == 'superuser' and _id == self.uid and self.user_is_superuser is not None: # toggle superuser for requesting user updates['$set'][k] = v.lower() in ('1', 'true') elif k == 'superuser' and _id != self.uid and self.user_is_superuser: # enable/disable superuser for other user if v.lower() in ('1', 'true') and user.get('superuser') is None: updates['$set'][k] = False # superuser is tri-state: False indicates granted, but disabled, superuser privileges elif v.lower() not in ('1', 'true'): updates['$unset'][k] = '' self.app.db.users.update({'_id': _id}, updates) else: self.abort(403) def delete(self, _id): """Delete an User.""" self.response.write('user %s delete, %s\n' % (_id, self.request.params)) class Groups(base.RequestHandler): """/nimsapi/groups """ json_schema = { '$schema': 'http://json-schema.org/draft-04/schema#', 'title': 'Group List', 'type': 'array', 'items': { 'title': 'Group', 'type': 'object', 'properties': { '_id': { 'title': 'Database ID', 'type': 'string', }, } } } def count(self): """Return the number of Groups.""" if self.request.method == 'OPTIONS': return self.options() self.response.write(self.app.db.groups.count()) def post(self): """Create a new Group""" self.response.write('groups post\n') def get(self, _id=None): """Return the list of Groups.""" query = None if _id is not None: if _id != self.uid and not self.user_is_superuser: self.abort(403, 'User ' + self.uid + ' may not see the Groups of User ' + _id) query = {'roles.uid': _id} else: if not self.user_is_superuser: if self.request.get('admin').lower() in ('1', 'true'): query = {'roles': {'$elemMatch': {'uid': self.uid, 'role': 'admin'}}} else: query = {'roles.uid': self.uid} groups = list(self.app.db.groups.find(query, ['name'])) if self.debug: for group in groups: group['metadata'] = self.uri_for('group', _id=str(group['_id']), _full=True) + '?' + self.request.query_string return groups def put(self): """Update many Groups.""" self.response.write('groups put\n') class Group(base.RequestHandler): """/nimsapi/groups/<_id>""" json_schema = { '$schema': 'http://json-schema.org/draft-04/schema#', 'title': 'Group', 'type': 'object', 'properties': { '_id': { 'title': 'Database ID', 'type': 'string', }, 'name': { 'title': 'Name', 'type': 'string', 'maxLength': 32, }, 'roles': { 'title': 'Roles', 'type': 'array', 'default': [], 'items': { 'type': 'object', 'properties': { 'uid': { 'type': 'string', }, 'role': { 'type': 'string', 'enum': [k for k, v in sorted(base.INTEGER_ROLES.iteritems(), key=lambda (k, v): v)], }, }, }, 'uniqueItems': True, }, }, 'required': ['_id'], } def get(self, _id): """Return Group details.""" group = self.app.db.groups.find_one({'_id': _id}) if not group: self.abort(404, 'no such Group: ' + _id) if not self.user_is_superuser: group = self.app.db.groups.find_one({'_id': _id, 'roles': {'$elemMatch': {'uid': self.uid, 'role': 'admin'}}}) if not group: self.abort(403, 'User ' + self.uid + ' is not an admin on Group ' + _id) return group def put(self, _id): """Update an existing Group.""" self.response.write('group %s put, %s\n' % (_id, self.request.params)) def delete(self, _id): """Delete an Group."""