diff --git a/api/config.py b/api/config.py index b4af832c4cd3e52d5cbec34fcfed50a6fdec54b3..f2acf5e9c765789afc6c75fa237232a7ffdbf0a7 100644 --- a/api/config.py +++ b/api/config.py @@ -104,6 +104,7 @@ schema_path = __config['persistent']['schema_path'] expected_mongo_schemas = set([ 'acquisition.json', + 'analysis.json', 'collection.json', 'container.json', 'file.json', @@ -119,6 +120,7 @@ expected_mongo_schemas = set([ ]) expected_input_schemas = set([ 'acquisition.json', + 'analysis.json', 'collection.json', 'container.json', 'file.json', diff --git a/api/handlers/listhandler.py b/api/handlers/listhandler.py index d1de460d0ae281b856e1919b9592b361e9d21408..cff21c7bc4d8fca905f068ab2f55130108b705b6 100644 --- a/api/handlers/listhandler.py +++ b/api/handlers/listhandler.py @@ -65,7 +65,9 @@ def initialize_list_configurations(): 'analyses': { 'storage': liststorage.AnalysesStorage, 'permchecker': listauth.default_sublist, - 'use_object_id': True + 'use_object_id': True, + 'storage_schema_file': 'analysis.json', + 'input_schema_file': 'analysis.json' } } list_container_configurations = { @@ -202,17 +204,11 @@ class ListHandler(base.RequestHandler): else: self.abort(404, 'Element {} not found in container {}'.format(_id, storage.cont_name)) - mongo_validator = None - input_validator = None - keycheck = None - - if conf.get('storage_schema_file'): - mongo_schema_uri = validators.schema_uri('mongo', conf.get('storage_schema_file')) - mongo_validator = validators.decorator_from_schema_path(mongo_schema_uri) - keycheck = validators.key_check(mongo_schema_uri) - if conf.get('input_schema_file'): - input_schema_uri = validators.schema_uri('input', conf.get('input_schema_file')) - input_validator = validators.from_schema_path(input_schema_uri) + mongo_schema_uri = validators.schema_uri('mongo', conf.get('storage_schema_file')) + mongo_validator = validators.decorator_from_schema_path(mongo_schema_uri) + keycheck = validators.key_check(mongo_schema_uri) + input_schema_uri = validators.schema_uri('input', conf.get('input_schema_file')) + input_validator = validators.from_schema_path(input_schema_uri) return permchecker, storage, mongo_validator, input_validator, keycheck @@ -674,12 +670,14 @@ class AnalysesHandler(ListHandler): """ _id = kwargs.pop('cid') - permchecker, storage, _, _, _ = self._initialize_request(cont_name, list_name, _id) + permchecker, storage, _, payload_validator, _ = self._initialize_request(cont_name, list_name, _id) permchecker(noop)('POST', _id=_id) if self.is_true('job'): if cont_name == 'sessions': - return self._create_job_and_analysis(cont_name, _id, storage) + payload = self.request.json_body + payload_validator(payload.get('analysis',{}), 'POST') + return self._create_job_and_analysis(cont_name, _id, storage, payload) else: self.abort(400, 'Analysis created via a job must be at the session level') @@ -692,8 +690,7 @@ class AnalysesHandler(ListHandler): else: self.abort(500, 'Element not added in list analyses of container {} {}'.format(cont_name, _id)) - def _create_job_and_analysis(self, cont_name, cid, storage): - payload = self.request.json_body + def _create_job_and_analysis(self, cont_name, cid, storage, payload): analysis = payload.get('analysis') job = payload.get('job') if job is None or analysis is None: @@ -918,9 +915,14 @@ class AnalysesHandler(ListHandler): def add_note(self, cont_name, list_name, **kwargs): _id = kwargs.pop('cid') analysis_id = kwargs.get('_id') - permchecker, storage, _, input_validator, _ = self._initialize_request(cont_name, list_name, _id) + permchecker, storage, _, _, _ = self._initialize_request(cont_name, list_name, _id) payload = self.request.json_body + + notes_schema_file = list_handler_configurations[cont_name]['notes']['storage_schema_file'] + input_schema_uri = validators.schema_uri('input', notes_schema_file) + input_validator = validators.from_schema_path(input_schema_uri) input_validator(payload, 'POST') + payload['_id'] = str(bson.objectid.ObjectId()) payload['user'] = payload.get('user', self.uid) payload['created'] = datetime.datetime.utcnow() diff --git a/api/placer.py b/api/placer.py index 6dc1b21c3124690a338f0b49b220f406b976c806..37c28d0523fbd6d3a49ab9c8e539169535f827fb 100644 --- a/api/placer.py +++ b/api/placer.py @@ -506,7 +506,7 @@ class AnalysisPlacer(Placer): def check(self): self.requireMetadata() - #validators.validate_data(self.metadata, 'analysis.json', 'input', 'POST', optional=True) + validators.validate_data(self.metadata, 'analysis.json', 'input', 'POST', optional=True) def process_file_field(self, field, info): self.save_file(field) @@ -533,7 +533,6 @@ class AnalysisJobPlacer(Placer): def check(self): if self.id_ is None: raise Exception('Must specify a target analysis') - #validators.validate_data(self.metadata, 'analysis.json', 'input', 'POST', optional=True) def process_file_field(self, field, info): if self.metadata is not None: diff --git a/api/schemas/input/analysis.json b/api/schemas/input/analysis.json new file mode 100644 index 0000000000000000000000000000000000000000..3b598eac1a75989e9e25dca678f66e34e19dc390 --- /dev/null +++ b/api/schemas/input/analysis.json @@ -0,0 +1,26 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Analysis", + "type": "object", + "properties": { + "inputs": { + "type": ["array", "null"], + "items": { + "$ref": "file.json" + } + }, + "outputs": { + "type": ["array", "null"], + "items": { + "$ref": "file.json" + } + }, + "notes": {"type": "array", "items": {"$ref": "note.json"}}, + "description" : {"type": "string"}, + "job": {"type": "string"}, + "label": {"type": "string", "minLength": 1, "maxLength": 256}, + "user": {"type": "string"} + }, + "required": ["label"], + "additionalProperties": false +} diff --git a/api/schemas/mongo/analysis.json b/api/schemas/mongo/analysis.json new file mode 100644 index 0000000000000000000000000000000000000000..ab39251273ad32681166b936e5d1a68fae7b4134 --- /dev/null +++ b/api/schemas/mongo/analysis.json @@ -0,0 +1,24 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Analysis", + "type": "object", + "properties": { + "_id": {"type": "string"}, + "created": {}, + "modified": {}, + "notes": {"type": "array", "items": {"$ref": "note.json"}}, + "files": { + "type": ["array", "null"], + "items": { + "$ref": "file.json", + "additionalProperties": { + "output": {"type": "boolean"}, + "input": {"type": "boolean"} + } + } + }, + "job": {"type": "string"}, + "label": {"type": "string", "minLength": 1, "maxLength": 256}, + "user": {"type": "string"} + } +}