Skip to content
Snippets Groups Projects
Commit af313ca0 authored by Gunnar Schaefer's avatar Gunnar Schaefer
Browse files

first pass at proper group schema

delivered at:
 - GET /schema/group => POST schema
 - GET /schema/group?method=put => PUT schema
parent 0276954d
No related branches found
No related tags found
No related merge requests found
import os
import copy
import json
import webapp2
import bson.json_util
......@@ -23,6 +24,9 @@ routes = [
webapp2.Route(r'/sites', core.Core, handler_method='sites', methods=['GET']),
webapp2.Route(r'/search', core.Core, handler_method='search', methods=['GET', 'POST']),
]),
webapp2_extras.routes.PathPrefixRoute(r'/api/schema', [
webapp2.Route(r'/group', users.Group, handler_method='schema', methods=['GET']),
]),
webapp2.Route(r'/api/users', users.Users),
webapp2_extras.routes.PathPrefixRoute(r'/api/users', [
webapp2.Route(r'/count', users.Users, handler_method='count', methods=['GET']),
......@@ -36,7 +40,6 @@ routes = [
webapp2.Route(r'/api/groups', users.Groups),
webapp2_extras.routes.PathPrefixRoute(r'/api/groups', [
webapp2.Route(r'/count', users.Groups, handler_method='count', methods=['GET']),
webapp2.Route(r'/schema', users.Group, handler_method='schema', methods=['GET']),
webapp2.Route(r'/<:[^/]+>', users.Group, name='group'),
webapp2.Route(r'/<gid:[^/]+>/projects', projects.Projects, name='g_projects'),
webapp2.Route(r'/<gid:[^/]+>/sessions', sessions.Sessions, name='g_sessions', methods=['GET']),
......@@ -93,11 +96,23 @@ routes = [
]),
]
for cls, schema_file in [(cls, os.path.join(os.path.dirname(__file__), schema_file)) for cls, schema_file in [
(users.Group, 'groups.json'),
]]:
with open(schema_file) as fp:
cls.post_schema = json.load(fp)
cls.put_schema = copy.deepcopy(cls.post_schema)
cls.put_schema['properties'].pop('_id')
cls.put_schema.pop('required')
def dispatcher(router, request, response):
rv = router.default_dispatcher(request, response)
if rv is not None:
response.write(json.dumps(rv, default=bson.json_util.default))
response.headers['Content-Type'] = 'application/json; charset=utf-8'
app = webapp2.WSGIApplication(routes)
app.router.set_dispatcher(dispatcher)
{
"$schema": "http://json-schema.org/draft-04/schema#",
"properties": {
"_id": {
"minLength": 2,
"maxLength": 32,
"pattern": "^[0-9a-z_-]*$",
"title": "ID",
"type": "string"
},
"name": {
"minLength": 2,
"maxLength": 32,
"pattern": "^[0-9A-Za-z _-]*$",
"title": "Name",
"type": "string"
},
"roles": {
"default": [],
"items": {
"additionalProperties": false,
"properties": {
"_id": {
"type": "string"
},
"access": {
"enum": [
"ro",
"rw",
"admin"
],
"type": "string"
}
},
"required": [
"access",
"_id"
],
"type": "object"
},
"title": "Roles",
"type": "array",
"uniqueItems": true
}
},
"required": [
"_id"
],
"title": "Group",
"type": "object"
}
......@@ -6,6 +6,7 @@ log = logging.getLogger('scitran.api')
import copy
import hashlib
import pymongo
import datetime
import jsonschema
import base
......@@ -194,7 +195,10 @@ class Groups(base.RequestHandler):
self.abort(403, 'must be logged in and superuser to create new group')
try:
json_body = self.request.json_body
jsonschema.validate(json_body, Group.json_schema)
jsonschema.validate(json_body, Group.post_schema)
json_body['created'] = datetime.datetime.utcnow()
json_body['modified'] = datetime.datetime.utcnow()
json_body.setdefault('roles', [])
self.dbc.insert(json_body)
except (ValueError, jsonschema.ValidationError) as e:
self.abort(400, str(e))
......@@ -218,6 +222,9 @@ class Groups(base.RequestHandler):
query = {'roles._id': self.uid}
projection += ['roles.$']
groups = list(self.app.db.groups.find(query, projection))
#for group in groups:
# group['created'], _ = util.format_timestamp(group['created']) # TODO json serializer should do this
# group['modified'], _ = util.format_timestamp(group['modified']) # TODO json serializer should do this
if self.debug:
for group in groups:
group['debug'] = {}
......@@ -231,48 +238,16 @@ class Group(base.RequestHandler):
"""/groups/<_id>"""
json_schema = {
'$schema': 'http://json-schema.org/draft-04/schema#',
'title': 'Group',
'type': 'object',
'properties': {
'_id': {
'title': 'Group ID',
'type': 'string',
},
'name': {
'title': 'Name',
'type': 'string',
'maxLength': 32,
},
'roles': {
'title': 'Roles',
'type': 'array',
'default': [],
'items': {
'type': 'object',
'properties': {
'access': {
'type': 'string',
'enum': [role['rid'] for role in ROLES],
},
'_id': {
'type': 'string',
},
},
'required': ['access', '_id'],
'additionalProperties': False,
},
'uniqueItems': True,
},
},
'required': ['_id'],
}
def __init__(self, request=None, response=None):
super(Group, self).__init__(request, response)
self.dbc = self.app.db.groups
def schema(self):
method =self.request.GET.get('method', '').lower()
if method == 'put':
return self.put_schema
return self.post_schema
def get(self, _id):
"""Return Group details."""
group = self.app.db.groups.find_one({'_id': _id})
......@@ -282,6 +257,9 @@ class Group(base.RequestHandler):
group = self.app.db.groups.find_one({'_id': _id, 'roles': {'$elemMatch': {'_id': self.uid, 'access': 'admin'}}})
if not group:
self.abort(403, 'User ' + self.uid + ' is not an admin of Group ' + _id)
if 'created' in group and 'modified' in group:
group['created'], _ = util.format_timestamp(group['created']) # TODO json serializer should do this
group['modified'], _ = util.format_timestamp(group['modified']) # TODO json serializer should do this
if self.debug:
group['debug'] = {}
group['debug']['projects'] = self.uri_for('g_projects', gid=group['_id'], _full=True) + '?' + self.request.query_string
......@@ -296,11 +274,9 @@ class Group(base.RequestHandler):
user_perm = util.user_perm(group.get('roles', []), self.uid)
if not self.superuser_request and not user_perm.get('access') == 'admin':
self.abort(403, 'must be superuser or group admin to update group')
schema = copy.deepcopy(self.json_schema)
del schema['required']
try:
json_body = self.request.json_body
jsonschema.validate(json_body, schema)
jsonschema.validate(json_body, self.put_schema)
except (ValueError, jsonschema.ValidationError) as e:
self.abort(400, str(e))
self.dbc.update({'_id': _id}, {'$set': util.mongo_dict(json_body)})
......
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