diff --git a/crc/api.yml b/crc/api.yml index 6501cebb..e032ccd5 100644 --- a/crc/api.yml +++ b/crc/api.yml @@ -1372,6 +1372,27 @@ paths: application/json: schema: $ref: "#/components/schemas/DataStore" + /datastore/file/{file_id}: + parameters: + - name: file_id + in: path + required: true + description: The file id we are concerned with + schema: + type: string + format: string + get: + operationId: crc.api.data_store.file_multi_get + summary: Gets all datastore items by file_id + tags: + - DataStore + responses: + '200': + description: Get all values from the data store for a file_id + content: + application/json: + schema: + $ref: "#/components/schemas/DataStore" components: securitySchemes: jwt: diff --git a/crc/api/data_store.py b/crc/api/data_store.py index a87ff938..327ba939 100644 --- a/crc/api/data_store.py +++ b/crc/api/data_store.py @@ -30,6 +30,16 @@ def user_multi_get(user_id): return results +def file_multi_get(file_id): + """Get all data values in the data store for a file_id""" + if file_id is None: + raise ApiError(code='unknown_file', message='Please provide a valid file id.') + dsb = DataStoreBase() + retval = dsb.get_multi_common(None, None, file_id=file_id) + results = DataStoreSchema(many=True).dump(retval) + return results + + def datastore_del(id): """Delete a data store item for a key""" session.query(DataStoreModel).filter_by(id=id).delete() diff --git a/crc/models/data_store.py b/crc/models/data_store.py index 07017cee..a156e004 100644 --- a/crc/models/data_store.py +++ b/crc/models/data_store.py @@ -25,4 +25,5 @@ class DataStoreSchema(SQLAlchemyAutoSchema): class Meta: model = DataStoreModel load_instance = True + include_fk = True sqla_session = db.session diff --git a/tests/test_datastore_api.py b/tests/test_datastore_api.py index 8e8ca8ef..1a3d8657 100644 --- a/tests/test_datastore_api.py +++ b/tests/test_datastore_api.py @@ -6,6 +6,7 @@ from tests.base_test import BaseTest from datetime import datetime, timezone from unittest.mock import patch from crc.models.data_store import DataStoreModel, DataStoreSchema +from crc.models.file import FileModel from crc import session, app @@ -20,6 +21,13 @@ class DataStoreTest(BaseTest): "spec_id": "My Spec Name", "value": "Some Value" } + TEST_FILE_ITEM = { + "key": "MyKey", + "workflow_id": 12, + "task_id": "MyTask", + "spec_id": "My Spec Name", + "value": "Some Value" + } def add_test_study_data(self): study_data = DataStoreSchema().dump(self.TEST_STUDY_ITEM) @@ -42,7 +50,16 @@ class DataStoreTest(BaseTest): self.assert_success(rv) return json.loads(rv.get_data(as_text=True)) - + def add_test_file_data(self, file_id, value): + file_data = DataStoreSchema().dump(self.TEST_FILE_ITEM) + file_data['file_id'] = file_id + file_data['value'] = value + rv = self.app.post('/v1.0/datastore', + content_type="application/json", + headers=self.logged_in_headers(), + data=json.dumps(file_data)) + self.assert_success(rv) + return json.loads(rv.get_data(as_text=True)) def test_get_study_data(self): """Generic test, but pretty detailed, in that the study should return a categorized list of workflows @@ -112,3 +129,62 @@ class DataStoreTest(BaseTest): self.assert_success(api_response) d = json.loads(api_response.get_data(as_text=True)) self.assertEqual(d[0]['value'],'Some Value') + + def test_datastore_file(self): + self.load_example_data() + test_file = session.query(FileModel).first() + + # make sure we don't already have a datastore + api_response = self.app.get(f'/v1.0/datastore/file/{test_file.id}', + headers=self.logged_in_headers(), + content_type="application/json") + self.assert_success(api_response) + data = json.loads(api_response.get_data(as_text=True)) + self.assertEqual(0, len(data)) + + # add datastore + self.add_test_file_data(test_file.id, 'Some File Data Value') + + # make sure we can get the datastore + api_response = self.app.get(f'/v1.0/datastore/file/{test_file.id}', + headers=self.logged_in_headers(), + content_type="application/json") + self.assert_success(api_response) + data = json.loads(api_response.get_data(as_text=True)) + + self.assertEqual(1, len(data)) + self.assertEqual('MyKey', data[0]['key']) + self.assertEqual('Some File Data Value', data[0]['value']) + + def test_datastore_files(self): + self.load_example_data() + test_file = session.query(FileModel).first() + + # add datastore + value_1 = 'Some File Data Value 1' + self.add_test_file_data(test_file.id, value_1) + + # make sure we have 1 item in the datastore + api_response_1 = self.app.get(f'/v1.0/datastore/file/{test_file.id}', + headers=self.logged_in_headers(), content_type="application/json") + self.assert_success(api_response_1) + data_1 = json.loads(api_response_1.get_data(as_text=True)) + + self.assertEqual(1, len(data_1)) + self.assertEqual('MyKey', data_1[0]['key']) + self.assertEqual(value_1, data_1[0]['value']) + + # add second datastore + value_2 = 'Some File Data Value 2' + self.add_test_file_data(test_file.id, value_2) + + # make sure we have 2 items in the datastore + api_response_2 = self.app.get(f'/v1.0/datastore/file/{test_file.id}', + headers=self.logged_in_headers(), content_type="application/json") + self.assert_success(api_response_2) + data_2 = json.loads(api_response_2.get_data(as_text=True)) + self.assertEqual(2, len(data_2)) + self.assertEqual(value_1, data_2[0]['value']) + self.assertEqual(value_2, data_2[1]['value']) + + print('test_datastore_files')