From 9a4d167dcd6f69774ff5d2486a35ddee392e5f74 Mon Sep 17 00:00:00 2001 From: Kelly McDonald Date: Wed, 11 Nov 2020 09:44:58 -0500 Subject: [PATCH] Add in api changes --- crc/api.yml | 143 +++++++++++++++++++- crc/api/data_store.py | 73 ++++++++++ crc/scripts/script.py | 19 ++- crc/scripts/study_data_set.py | 3 +- crc/scripts/user_data_set.py | 3 +- tests/study/test_study_data_store_script.py | 1 + 6 files changed, 232 insertions(+), 10 deletions(-) create mode 100644 crc/api/data_store.py diff --git a/crc/api.yml b/crc/api.yml index 4ebe3cc2..0e561db1 100644 --- a/crc/api.yml +++ b/crc/api.yml @@ -1026,6 +1026,148 @@ paths: type: array items: $ref: "#/components/schemas/Approval" + /datastore/study/get: + parameters: + - name: key + in: query + required: true + description: The key to lookup. + schema: + type: string + format: string + - name: default + in: query + required: false + description: Default Value if key doesn't exist. + schema: + type: string + format: string + - name: study_id + in: query + required: true + description: The study id we are concerned with . + schema: + type: integer + format: int32 + get: + operationId: crc.api.data_store.study_data_get + summary: Provides a single study + tags: + - DataStore + responses: + '200': + description: A value from the data store, or a default if provided, or None if not found. + content: + application/json: + schema: + $ref: "#/components/schemas/Study" + /datastore/study/set: + parameters: + - name: key + in: query + required: true + description: The key to lookup. + schema: + type: string + format: string + - name: value + in: query + required: true + description: Default Value if key doesn't exist. + schema: + type: string + format: string + - name: study_id + in: query + required: true + description: The study id we are concerned with . + schema: + type: integer + format: int32 + get: + operationId: crc.api.data_store.study_data_set + summary: Provides a single study + tags: + - DataStore + responses: + '200': + description: Sets a value in the data store for a study. + content: + application/json: + schema: + $ref: "#/components/schemas/Study" + /datastore/user/get: + parameters: + - name: key + in: query + required: true + description: The key to lookup. + schema: + type: string + format: string + - name: default + in: query + required: false + description: Default Value if key doesn't exist. + schema: + type: string + format: string + - name: user_id + in: query + required: true + description: The study id we are concerned with . + schema: + type: string + format: string + get: + operationId: crc.api.data_store.user_data_get + summary: Provides a single study + tags: + - DataStore + responses: + '200': + description: A value from the data store, or a default if provided, or None if not found. + content: + application/json: + schema: + $ref: "#/components/schemas/Study" + /datastore/user/set: + parameters: + - name: key + in: query + required: true + description: The key to lookup. + schema: + type: string + format: string + - name: value + in: query + required: true + description: Default Value if key doesn't exist. + schema: + type: string + format: string + - name: user_id + in: query + required: true + description: The user id we are concerned with . + schema: + type: string + format: string + get: + operationId: crc.api.data_store.user_data_set + summary: Provides a single study + tags: + - DataStore + responses: + '200': + description: Sets a value in the data store for a study. + content: + application/json: + schema: + $ref: "#/components/schemas/Study" + + components: securitySchemes: jwt: @@ -1495,4 +1637,3 @@ components: type: number format: integer example: 5 - diff --git a/crc/api/data_store.py b/crc/api/data_store.py new file mode 100644 index 00000000..f39c2d88 --- /dev/null +++ b/crc/api/data_store.py @@ -0,0 +1,73 @@ +from datetime import datetime + +from flask import g +from sqlalchemy.exc import IntegrityError +import json +from crc import session +from crc.scripts.script import DataStoreBase +from crc.api.common import ApiError, ApiErrorSchema +from crc.models.data_store import DataStoreModel + + +def study_data_set(study_id,key,value): + """Set a study data value in the data_store, mimic the script endpoint""" + if study_id is None: + raise ApiError('unknown_study', 'Please provide a valid Study ID.') + + if key is None: + raise ApiError('invalid_key', 'Please provide a valid key') + dsb = DataStoreBase() + retval=dsb.set_data_common('api',study_id,None,None,None,'api_study_data_set',key,value) + json_value = json.dumps(retval, ensure_ascii=False, indent=2) + return json_value + +def study_data_get(study_id,key,default=None): + """Set a study data value in the data_store, mimic the script endpoint""" + if study_id is None: + raise ApiError('unknown_study', 'Please provide a valid Study ID.') + + if key is None: + raise ApiError('invalid_key', 'Please provide a valid key') + dsb = DataStoreBase() + retval=dsb.get_data_common(study_id,None,'api_study_data_get',key,default) + json_value = json.dumps(retval, ensure_ascii=False, indent=2) + return json_value + + +def user_data_set(user_id,key,value): + """Set a user data value in the data_store, mimic the script endpoint""" + if user_id is None: + raise ApiError('unknown_study', 'Please provide a valid UserID.') + + if key is None: + raise ApiError('invalid_key', 'Please provide a valid key') + dsb = DataStoreBase() + + retval=dsb.set_data_common('api', + None, + user_id, + None, + None, + 'api_user_data_set', + key,value) + + json_value = json.dumps(retval, ensure_ascii=False, indent=2) + return json_value + + +def user_data_get(user_id,key,default=None): + """Set a user data value in the data_store, mimic the script endpoint""" + if user_id is None: + raise ApiError('unknown_study', 'Please provide a valid UserID.') + + if key is None: + raise ApiError('invalid_key', 'Please provide a valid key') + dsb = DataStoreBase() + retval=dsb.get_data_common(None, + user_id, + 'api_user_data_get', + key,default) + + json_value = json.dumps(retval, ensure_ascii=False, indent=2) + return json_value + diff --git a/crc/scripts/script.py b/crc/scripts/script.py index ff277bc0..0bf9d954 100644 --- a/crc/scripts/script.py +++ b/crc/scripts/script.py @@ -144,25 +144,30 @@ class DataStoreBase(): study = session.query(DataStoreModel).filter_by(study_id=study_id,user_id=user_id,key=key).first() return study - def set_data_common(self, task, study_id, user_id, workflow_id, script_name, *args, **kwargs): + def set_data_common(self, task_id, study_id, user_id, workflow_id, workflow_spec_id, script_name, *args, **kwargs): self.check_args_2(args,script_name=script_name) study = self.get_prev_value(study_id=study_id,user_id=user_id, key=args[0]) - workflow = session.query(WorkflowModel).filter(WorkflowModel.id == workflow_id).first() + if workflow_spec_id is None and workflow_id is not None: + workflow = session.query(WorkflowModel).filter(WorkflowModel.id == workflow_id).first() + workflow_spec_id = workflow.workflow_spec_id if study is not None: - prev_value = study.key + prev_value = study.value else: prev_value = None study = DataStoreModel(key=args[0],value=args[1], study_id=study_id, - task_id=task.id, + task_id=task_id, user_id=user_id, # Make this available to any User workflow_id= workflow_id, - spec_id=workflow.workflow_spec_id) - + spec_id=workflow_spec_id) + study.value = args[1] overwritten = self.overwritten(study.value,prev_value) session.add(study) - return (study.value, prev_value, overwritten) + session.commit() + return {'new_value':study.value, + 'old_value':prev_value, + 'overwritten':overwritten} def get_data_common(self, study_id, user_id, script_name, *args): diff --git a/crc/scripts/study_data_set.py b/crc/scripts/study_data_set.py index b82a5da6..891e1b2b 100644 --- a/crc/scripts/study_data_set.py +++ b/crc/scripts/study_data_set.py @@ -19,10 +19,11 @@ class StudyDataSet(Script,DataStoreBase): def do_task(self, task, study_id, workflow_id, *args, **kwargs): - return self.set_data_common(task, + return self.set_data_common(task.id, study_id, None, workflow_id, + None, 'study_data_set', *args, **kwargs) diff --git a/crc/scripts/user_data_set.py b/crc/scripts/user_data_set.py index 2e45ab1e..0f1f9a0a 100644 --- a/crc/scripts/user_data_set.py +++ b/crc/scripts/user_data_set.py @@ -21,10 +21,11 @@ class UserDataSet(Script,DataStoreBase): def do_task(self, task, study_id, workflow_id, *args, **kwargs): - return self.set_data_common(task, + return self.set_data_common(task.id, None, g.user.uid, workflow_id, + None, 'user_data_set', *args, **kwargs) diff --git a/tests/study/test_study_data_store_script.py b/tests/study/test_study_data_store_script.py index 8e4ec51d..ab24f9a5 100644 --- a/tests/study/test_study_data_store_script.py +++ b/tests/study/test_study_data_store_script.py @@ -17,6 +17,7 @@ class TestSudySponsorsScript(BaseTest): def test_study_sponsors_script_validation(self): + flask.g.user = UserModel(uid='dhf8r') self.load_example_data() # study_info script complains if irb_documents.xls is not loaded # during the validate phase I'm going to assume that we will never # have a case where irb_documents.xls is not loaded ??