Adds user to example data. Requires login before adding/updating a study.
This commit is contained in:
parent
27d7afb656
commit
f3068e68db
|
@ -12,6 +12,7 @@ from models.protocol_builder import ProtocolBuilderStatus, ProtocolBuilderStudy
|
|||
from crc.models.workflow import WorkflowModel, WorkflowApiSchema, WorkflowSpecModel
|
||||
from crc.services import protocol_builder
|
||||
from crc.services.workflow_processor import WorkflowProcessor
|
||||
from services.protocol_builder import ProtocolBuilderService
|
||||
|
||||
|
||||
@auth.login_required
|
||||
|
@ -19,38 +20,24 @@ def all_studies():
|
|||
user = g.user
|
||||
""":type: crc.models.user.UserModel"""
|
||||
|
||||
# Get studies matching this user from Protocol Builder
|
||||
pb_studies: List[ProtocolBuilderStudy] = protocol_builder.get_studies(user.uid)
|
||||
|
||||
schema = StudyModelSchema(many=True)
|
||||
update_from_protocol_builder()
|
||||
db_studies = session.query(StudyModel).filter_by(user_uid=user.uid).all()
|
||||
db_study_ids = list(map(lambda s: s.id, db_studies))
|
||||
|
||||
for pb_study in pb_studies:
|
||||
if pb_study['HSRNUMBER'] not in db_study_ids:
|
||||
status = ProtocolBuilderStatus.complete._value_ if pb_study['Q_COMPLETE'] else ProtocolBuilderStatus.in_process._value_
|
||||
add_study({
|
||||
'id': pb_study['HSRNUMBER'],
|
||||
'title': pb_study['TITLE'],
|
||||
'protocol_builder_status': status,
|
||||
'user_uid': pb_study['NETBADGEID'],
|
||||
'last_updated': pb_study['DATE_MODIFIED']
|
||||
})
|
||||
|
||||
db_studies = session.query(StudyModel).filter_by(user_uid=user.uid).all()
|
||||
return schema.dump(db_studies)
|
||||
return StudyModelSchema(many=True).dump(db_studies)
|
||||
|
||||
|
||||
@auth.login_required
|
||||
def add_study(body):
|
||||
study = StudyModelSchema().load(body, session=session)
|
||||
session.add(study)
|
||||
session.commit()
|
||||
|
||||
# FIXME: We need to ask the protocol builder what workflows to add to the study, not just add them all.
|
||||
for spec in session.query(WorkflowSpecModel).all():
|
||||
WorkflowProcessor.create(study.id, spec.id)
|
||||
return StudyModelSchema().dump(study)
|
||||
|
||||
|
||||
@auth.login_required
|
||||
def update_study(study_id, body):
|
||||
if study_id is None:
|
||||
error = ApiError('unknown_study', 'Please provide a valid Study ID.')
|
||||
|
@ -68,6 +55,7 @@ def update_study(study_id, body):
|
|||
return StudyModelSchema().dump(study)
|
||||
|
||||
|
||||
@auth.login_required
|
||||
def get_study(study_id):
|
||||
study = session.query(StudyModel).filter_by(id=study_id).first()
|
||||
schema = StudyModelSchema()
|
||||
|
@ -76,12 +64,34 @@ def get_study(study_id):
|
|||
return schema.dump(study)
|
||||
|
||||
|
||||
@auth.login_required
|
||||
def update_from_protocol_builder():
|
||||
"""Call the """
|
||||
"""Updates the list of known studies for a given user based on data received from
|
||||
the protocol builder."""
|
||||
|
||||
user = g.user
|
||||
""":type: crc.models.user.UserModel"""
|
||||
|
||||
# Get studies matching this user from Protocol Builder
|
||||
pb_studies: List[ProtocolBuilderStudy] = ProtocolBuilderService.get_studies(user.uid)
|
||||
|
||||
db_studies = session.query(StudyModel).filter_by(user_uid=user.uid).all()
|
||||
db_study_ids = list(map(lambda s: s.id, db_studies))
|
||||
|
||||
for pb_study in pb_studies:
|
||||
if pb_study['HSRNUMBER'] not in db_study_ids:
|
||||
status = ProtocolBuilderStatus.complete._value_ if pb_study['Q_COMPLETE'] else ProtocolBuilderStatus.in_process._value_
|
||||
add_study({
|
||||
'id': pb_study['HSRNUMBER'],
|
||||
'title': pb_study['TITLE'],
|
||||
'protocol_builder_status': status,
|
||||
'user_uid': pb_study['NETBADGEID'],
|
||||
'last_updated': pb_study['DATE_MODIFIED']
|
||||
})
|
||||
|
||||
|
||||
def post_update_study_from_protocol_builder(study_id):
|
||||
"""This will update the list of known studies based on data received from
|
||||
"""Update a single study based on data received from
|
||||
the protocol builder."""
|
||||
|
||||
# todo: Actually get data from an external service here
|
||||
|
|
|
@ -1,16 +1,31 @@
|
|||
import datetime
|
||||
import glob
|
||||
import os
|
||||
import xml.etree.ElementTree as ElementTree
|
||||
|
||||
from crc import app, db, session
|
||||
from crc.models.file import FileType, FileModel, FileDataModel
|
||||
from crc.models.study import StudyModel
|
||||
from crc.models.user import UserModel
|
||||
from crc.models.workflow import WorkflowSpecModel
|
||||
import xml.etree.ElementTree as ElementTree
|
||||
from crc.services.workflow_processor import WorkflowProcessor
|
||||
|
||||
|
||||
class ExampleDataLoader:
|
||||
def make_data(self):
|
||||
users = [
|
||||
UserModel(
|
||||
uid='dhf8r',
|
||||
email_address='dhf8r@virginia.EDU',
|
||||
display_name='Daniel Harold Funk',
|
||||
affiliation='staff@virginia.edu;member@virginia.edu',
|
||||
eppn='dhf8r@virginia.edu',
|
||||
first_name='Daniel',
|
||||
last_name='Funk',
|
||||
title='SOFTWARE ENGINEER V'
|
||||
)
|
||||
]
|
||||
|
||||
studies = [
|
||||
StudyModel(
|
||||
id=1,
|
||||
|
@ -19,7 +34,8 @@ class ExampleDataLoader:
|
|||
protocol_builder_status='in_process',
|
||||
primary_investigator_id='dhf8r',
|
||||
sponsor='Sartography Pharmaceuticals',
|
||||
ind_number='1234'
|
||||
ind_number='1234',
|
||||
user_uid='dhf8r'
|
||||
),
|
||||
StudyModel(
|
||||
id=2,
|
||||
|
@ -28,7 +44,8 @@ class ExampleDataLoader:
|
|||
protocol_builder_status='in_process',
|
||||
primary_investigator_id='dhf8r',
|
||||
sponsor='Makerspace & Co.',
|
||||
ind_number='5678'
|
||||
ind_number='5678',
|
||||
user_uid='dhf8r'
|
||||
),
|
||||
]
|
||||
|
||||
|
@ -69,11 +86,11 @@ class ExampleDataLoader:
|
|||
description='How to take different paths based on input.')
|
||||
workflow_specifications += \
|
||||
self.create_spec(id="docx",
|
||||
name="docx",
|
||||
display_name="Form with document generation",
|
||||
description='the name says it all')
|
||||
name="docx",
|
||||
display_name="Form with document generation",
|
||||
description='the name says it all')
|
||||
|
||||
all_data = studies + workflow_specifications
|
||||
all_data = users + studies + workflow_specifications
|
||||
return all_data
|
||||
|
||||
def create_spec(self, id, name, display_name="", description="", filepath=None):
|
||||
|
@ -112,7 +129,7 @@ class ExampleDataLoader:
|
|||
try:
|
||||
file = open(file_path, "rb")
|
||||
data = file.read()
|
||||
if(is_primary):
|
||||
if (is_primary):
|
||||
bpmn: ElementTree.Element = ElementTree.fromstring(data)
|
||||
spec.primary_process_id = WorkflowProcessor.get_process_id(bpmn)
|
||||
print("Locating Process Id for " + filename + " " + spec.primary_process_id)
|
||||
|
@ -121,7 +138,6 @@ class ExampleDataLoader:
|
|||
file.close()
|
||||
return models
|
||||
|
||||
|
||||
@staticmethod
|
||||
def clean_db():
|
||||
session.flush() # Clear out any transactions before deleting it all to avoid spurious errors.
|
||||
|
|
|
@ -3,11 +3,13 @@
|
|||
import json
|
||||
import os
|
||||
import unittest
|
||||
import urllib.parse
|
||||
|
||||
os.environ["TESTING"] = "true"
|
||||
|
||||
from crc.models.file import FileModel, FileDataModel
|
||||
from crc.models.workflow import WorkflowSpecModel
|
||||
|
||||
os.environ["TESTING"] = "true"
|
||||
from crc.models.user import UserModel
|
||||
|
||||
from crc import app, db, session
|
||||
from example_data import ExampleDataLoader
|
||||
|
@ -18,14 +20,13 @@ from example_data import ExampleDataLoader
|
|||
# logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Great class to inherit from, as it sets up and tears down
|
||||
# classes efficiently when we have a database in place.
|
||||
class BaseTest(unittest.TestCase):
|
||||
""" Great class to inherit from, as it sets up and tears down classes
|
||||
efficiently when we have a database in place.
|
||||
"""
|
||||
|
||||
auths = {}
|
||||
test_uid = "dhf8r"
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
|
@ -48,6 +49,25 @@ class BaseTest(unittest.TestCase):
|
|||
self.ctx.pop()
|
||||
self.auths = {}
|
||||
|
||||
def logged_in_headers(self, user=None, redirect_url='http://some/frontend/url'):
|
||||
if user is None:
|
||||
uid = self.test_uid
|
||||
user_info = {'uid': self.test_uid, 'first_name': 'Daniel', 'last_name': 'Funk',
|
||||
'email_address': 'dhf8r@virginia.edu'}
|
||||
else:
|
||||
uid = user.uid
|
||||
user_info = {'uid': user.uid, 'first_name': user.first_name, 'last_name': user.last_name,
|
||||
'email_address': user.email_address}
|
||||
|
||||
query_string = self.user_info_to_query_string(user_info, redirect_url)
|
||||
rv = self.app.get("/v1.0/sso_backdoor%s" % query_string, follow_redirects=False)
|
||||
self.assertTrue(rv.status_code == 302)
|
||||
self.assertTrue(str.startswith(rv.location, redirect_url))
|
||||
|
||||
user_model = session.query(UserModel).filter_by(uid=uid).first()
|
||||
self.assertIsNotNone(user_model.display_name)
|
||||
return dict(Authorization='Bearer ' + user_model.encode_auth_token().decode())
|
||||
|
||||
def load_example_data(self):
|
||||
from example_data import ExampleDataLoader
|
||||
ExampleDataLoader.clean_db()
|
||||
|
@ -66,7 +86,8 @@ class BaseTest(unittest.TestCase):
|
|||
self.assertIsNotNone(file_data)
|
||||
self.assertGreater(len(file_data), 0)
|
||||
|
||||
def load_test_spec(self, dir_name):
|
||||
@staticmethod
|
||||
def load_test_spec(dir_name):
|
||||
"""Loads a spec into the database based on a directory in /tests/data"""
|
||||
if session.query(WorkflowSpecModel).filter_by(id=dir_name).count() > 0:
|
||||
return
|
||||
|
@ -81,7 +102,8 @@ class BaseTest(unittest.TestCase):
|
|||
session.flush()
|
||||
return spec
|
||||
|
||||
def protocol_builder_response(self, file_name):
|
||||
@staticmethod
|
||||
def protocol_builder_response(file_name):
|
||||
filepath = os.path.join(app.root_path, '..', 'tests', 'data', 'pb_responses', file_name)
|
||||
with open(filepath, 'r') as myfile:
|
||||
data = myfile.read()
|
||||
|
@ -102,3 +124,16 @@ class BaseTest(unittest.TestCase):
|
|||
"Incorrect Valid Response:" + rv.status + ".")
|
||||
if code != 0:
|
||||
self.assertEqual(code, rv.status_code)
|
||||
|
||||
@staticmethod
|
||||
def user_info_to_query_string(user_info, redirect_url):
|
||||
query_string_list = []
|
||||
items = user_info.items()
|
||||
for key, value in items:
|
||||
query_string_list.append('%s=%s' % (key, urllib.parse.quote(value)))
|
||||
|
||||
query_string_list.append('redirect_url=%s' % redirect_url)
|
||||
|
||||
return '?%s' % '&'.join(query_string_list)
|
||||
|
||||
|
||||
|
|
|
@ -1,31 +1,9 @@
|
|||
import urllib.parse
|
||||
|
||||
from crc import db
|
||||
from crc.models.user import UserModel
|
||||
from tests.base_test import BaseTest
|
||||
|
||||
|
||||
class TestAuthentication(BaseTest):
|
||||
test_uid = "dhf8r"
|
||||
|
||||
def logged_in_headers(self, user=None, redirect_url='http://some/frontend/url'):
|
||||
if user is None:
|
||||
uid = self.test_uid
|
||||
user_info = {'uid': self.test_uid, 'first_name': 'Daniel', 'last_name': 'Funk',
|
||||
'email_address': 'dhf8r@virginia.edu'}
|
||||
else:
|
||||
uid = user.uid
|
||||
user_info = {'uid': user.uid, 'first_name': user.first_name, 'last_name': user.last_name,
|
||||
'email_address': user.email_address}
|
||||
|
||||
query_string = self.user_info_to_query_string(user_info, redirect_url)
|
||||
rv = self.app.get("/v1.0/sso_backdoor%s" % query_string, follow_redirects=False)
|
||||
self.assertTrue(rv.status_code == 302)
|
||||
self.assertTrue(str.startswith(rv.location, redirect_url))
|
||||
|
||||
user_model = UserModel.query.filter_by(uid=uid).first()
|
||||
self.assertIsNotNone(user_model.display_name)
|
||||
return dict(Authorization='Bearer ' + user_model.encode_auth_token().decode())
|
||||
|
||||
def test_auth_token(self):
|
||||
self.load_example_data()
|
||||
|
@ -35,12 +13,13 @@ class TestAuthentication(BaseTest):
|
|||
self.assertEqual("dhf8r", user.decode_auth_token(auth_token))
|
||||
|
||||
def test_auth_creates_user(self):
|
||||
new_uid = 'czn1z';
|
||||
self.load_example_data()
|
||||
user = db.session.query(UserModel).filter(UserModel.uid == self.test_uid).first()
|
||||
user = db.session.query(UserModel).filter(UserModel.uid == new_uid).first()
|
||||
self.assertIsNone(user)
|
||||
|
||||
user_info = {'uid': self.test_uid, 'first_name': 'Daniel', 'last_name': 'Funk',
|
||||
'email_address': 'dhf8r@virginia.edu'}
|
||||
user_info = {'uid': new_uid, 'first_name': 'Cordi', 'last_name': 'Nator',
|
||||
'email_address': 'czn1z@virginia.edu'}
|
||||
redirect_url = 'http://worlds.best.website/admin'
|
||||
query_string = self.user_info_to_query_string(user_info, redirect_url)
|
||||
url = '/v1.0/sso_backdoor%s' % query_string
|
||||
|
@ -48,7 +27,7 @@ class TestAuthentication(BaseTest):
|
|||
self.assertTrue(rv_1.status_code == 302)
|
||||
self.assertTrue(str.startswith(rv_1.location, redirect_url))
|
||||
|
||||
user = db.session.query(UserModel).filter(UserModel.uid == self.test_uid).first()
|
||||
user = db.session.query(UserModel).filter(UserModel.uid == new_uid).first()
|
||||
self.assertIsNotNone(user)
|
||||
self.assertIsNotNone(user.display_name)
|
||||
self.assertIsNotNone(user.email_address)
|
||||
|
@ -69,15 +48,3 @@ class TestAuthentication(BaseTest):
|
|||
user = UserModel(uid="ajl2j", first_name='Aaron', last_name='Louie', email_address='ajl2j@virginia.edu')
|
||||
rv = self.app.get('/v1.0/user', headers=self.logged_in_headers(user, redirect_url='http://omg.edu/lolwut'))
|
||||
self.assert_success(rv)
|
||||
|
||||
def user_info_to_query_string(self, user_info, redirect_url):
|
||||
query_string_list = []
|
||||
items = user_info.items()
|
||||
for key, value in items:
|
||||
query_string_list.append('%s=%s' % (key, urllib.parse.quote(value)))
|
||||
|
||||
query_string_list.append('redirect_url=%s' % redirect_url)
|
||||
|
||||
return '?%s' % '&'.join(query_string_list)
|
||||
|
||||
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
import json
|
||||
from datetime import datetime, tzinfo, timezone
|
||||
from datetime import datetime, timezone
|
||||
|
||||
from crc import session
|
||||
from crc.models.file import FileModel
|
||||
from crc.models.study import StudyModel, StudyModelSchema
|
||||
from models.protocol_builder import ProtocolBuilderStatus
|
||||
from crc.models.workflow import WorkflowSpecModel, WorkflowSpecModelSchema, WorkflowModel, WorkflowStatus, \
|
||||
|
@ -21,7 +20,8 @@ class TestStudyApi(BaseTest):
|
|||
self.load_example_data()
|
||||
study = {
|
||||
"id": 12345,
|
||||
"title": "Phase III Trial of Genuine People Personalities (GPP) Autonomous Intelligent Emotional Agents for Interstellar Spacecraft",
|
||||
"title": "Phase III Trial of Genuine People Personalities (GPP) Autonomous Intelligent Emotional Agents "
|
||||
"for Interstellar Spacecraft",
|
||||
"last_updated": datetime.now(tz=timezone.utc),
|
||||
"protocol_builder_status": ProtocolBuilderStatus.in_process,
|
||||
"primary_investigator_id": "tricia.marie.mcmillan@heartofgold.edu",
|
||||
|
@ -30,6 +30,7 @@ class TestStudyApi(BaseTest):
|
|||
}
|
||||
rv = self.app.post('/v1.0/study',
|
||||
content_type="application/json",
|
||||
headers=self.logged_in_headers(),
|
||||
data=json.dumps(StudyModelSchema().dump(study)))
|
||||
self.assert_success(rv)
|
||||
db_study = session.query(StudyModel).filter_by(id=12345).first()
|
||||
|
@ -41,16 +42,15 @@ class TestStudyApi(BaseTest):
|
|||
self.assertEqual(study["sponsor"], db_study.sponsor)
|
||||
self.assertEqual(study["ind_number"], db_study.ind_number)
|
||||
|
||||
|
||||
|
||||
def test_update_study(self):
|
||||
self.load_example_data()
|
||||
study: StudyModel = session.query(StudyModel).first()
|
||||
study.title = "Pilot Study of Fjord Placement for Single Fraction Outcomes to Cortisol Susceptibility"
|
||||
study.protocol_builder_status = ProtocolBuilderStatus.complete
|
||||
rv = self.app.put('/v1.0/study/%i' % study.id,
|
||||
content_type="application/json",
|
||||
data=json.dumps(StudyModelSchema().dump(study)))
|
||||
content_type="application/json",
|
||||
headers=self.logged_in_headers(),
|
||||
data=json.dumps(StudyModelSchema().dump(study)))
|
||||
self.assert_success(rv)
|
||||
db_study = session.query(StudyModel).filter_by(id=study.id).first()
|
||||
self.assertIsNotNone(db_study)
|
||||
|
@ -62,6 +62,7 @@ class TestStudyApi(BaseTest):
|
|||
study = session.query(StudyModel).first()
|
||||
rv = self.app.get('/v1.0/study/%i' % study.id,
|
||||
follow_redirects=True,
|
||||
headers=self.logged_in_headers(),
|
||||
content_type="application/json")
|
||||
self.assert_success(rv)
|
||||
json_data = json.loads(rv.get_data(as_text=True))
|
||||
|
@ -80,7 +81,9 @@ class TestStudyApi(BaseTest):
|
|||
study = session.query(StudyModel).first()
|
||||
self.assertEqual(0, session.query(WorkflowModel).count())
|
||||
spec = session.query(WorkflowSpecModel).first()
|
||||
rv = self.app.post('/v1.0/study/%i/workflows' % study.id, content_type="application/json",
|
||||
rv = self.app.post('/v1.0/study/%i/workflows' % study.id,
|
||||
content_type="application/json",
|
||||
headers=self.logged_in_headers(),
|
||||
data=json.dumps(WorkflowSpecModelSchema().dump(spec)))
|
||||
self.assert_success(rv)
|
||||
self.assertEqual(1, session.query(WorkflowModel).count())
|
||||
|
@ -98,7 +101,9 @@ class TestStudyApi(BaseTest):
|
|||
self.load_example_data()
|
||||
study = session.query(StudyModel).first()
|
||||
spec = session.query(WorkflowSpecModel).first()
|
||||
rv = self.app.post('/v1.0/study/%i/workflows' % study.id, content_type="application/json",
|
||||
rv = self.app.post('/v1.0/study/%i/workflows' % study.id,
|
||||
content_type="application/json",
|
||||
headers=self.logged_in_headers(),
|
||||
data=json.dumps(WorkflowSpecModelSchema().dump(spec)))
|
||||
self.assertEqual(1, session.query(WorkflowModel).count())
|
||||
json_data = json.loads(rv.get_data(as_text=True))
|
||||
|
|
Loading…
Reference in New Issue