Exemple #1
0
    def test_study_sponsors_script_ensure_delete(self, mock_get):
        mock_get.return_value.ok = True
        mock_get.return_value.text = self.protocol_builder_response(
            'sponsors.json')
        flask.g.user = UserModel(uid='dhf8r')
        app.config['PB_ENABLED'] = True

        self.load_example_data()
        study = session.query(StudyModel).first()
        workflow_spec_model = self.load_test_spec(
            "study_sponsors_associates_delete")
        workflow_model = StudyService._create_workflow_model(
            study, workflow_spec_model)
        WorkflowService.test_spec("study_sponsors_associates_delete")
        processor = WorkflowProcessor(workflow_model)
        processor.do_engine_steps()
        # change user and make sure we can access the study
        flask.g.user = UserModel(uid='lb3dp')
        flask.g.token = 'my spiffy token'
        app.config['PB_ENABLED'] = False
        output = user_studies()
        self.assertEqual(len(output), 0)
        flask.g.token = 'my spiffy token'
        app.config['PB_ENABLED'] = False
        output = user_studies()
        self.assertEqual(len(output), 0)
Exemple #2
0
def verify_token(token=None):
    """
        Verifies the token for the user (if provided). If in production environment and token is not provided,
        gets user from the SSO headers and returns their token.

        Args:
            token: Optional[str]

        Returns:
            token: str

        Raises:
            ApiError.  If not on production and token is not valid, returns an 'invalid_token' 403 error.
            If on production and user is not authenticated, returns a 'no_user' 403 error.
   """

    failure_error = ApiError(
        "invalid_token",
        "Unable to decode the token you provided.  Please re-authenticate",
        status_code=403)

    if not _is_production() and (token is None or 'user' not in g):
        g.user = UserModel.query.first()
        token = g.user.encode_auth_token()

    if token:
        try:
            token_info = UserModel.decode_auth_token(token)
            g.user = UserModel.query.filter_by(uid=token_info['sub']).first()
        except:
            raise failure_error
        if g.user is not None:
            return token_info
        else:
            raise failure_error

    # If there's no token and we're in production, get the user from the SSO headers and return their token
    if not token and _is_production():
        uid = _get_request_uid(request)

        if uid is not None:
            db_user = UserModel.query.filter_by(uid=uid).first()

            if db_user is not None:
                g.user = db_user
                token = g.user.encode_auth_token().decode()
                token_info = UserModel.decode_auth_token(token)
                return token_info

            else:
                raise ApiError(
                    "no_user",
                    "User not found. Please login via the frontend app before accessing this feature.",
                    status_code=403)
Exemple #3
0
    def load_example_data(self, use_crc_data=False, use_rrt_data=False):
        """use_crc_data will cause this to load the mammoth collection of documents
        we built up developing crc, use_rrt_data will do the same for hte rrt project,
         otherwise it depends on a small setup for running tests."""
        from example_data import ExampleDataLoader
        ExampleDataLoader.clean_db()
        # If in production mode, only add the first user.
        if app.config['PRODUCTION']:
            ldap_info = LdapService.user_info(self.users[0]['uid'])
            session.add(
                UserModel(uid=self.users[0]['uid'], ldap_info=ldap_info))
        else:
            for user_json in self.users:
                ldap_info = LdapService.user_info(user_json['uid'])
                session.add(
                    UserModel(uid=user_json['uid'], ldap_info=ldap_info))

        if use_crc_data:
            ExampleDataLoader().load_all()
        elif use_rrt_data:
            ExampleDataLoader().load_rrt()
        else:
            ExampleDataLoader().load_test_data()

        session.commit()
        for study_json in self.studies:
            study_model = StudyModel(**study_json)
            session.add(study_model)
            StudyService._add_all_workflow_specs_to_study(study_model)
            session.commit()
            update_seq = f"ALTER SEQUENCE %s RESTART WITH %s" % (
                StudyModel.__tablename__ + '_id_seq', study_model.id + 1)
            print("Update Sequence." + update_seq)
            session.execute(update_seq)
        session.flush()

        specs = session.query(WorkflowSpecModel).all()
        self.assertIsNotNone(specs)

        for spec in specs:
            files = session.query(FileModel).filter_by(
                workflow_spec_id=spec.id).all()
            self.assertIsNotNone(files)
            self.assertGreater(len(files), 0)
            for file in files:
                # file_data = session.query(FileDataModel).filter_by(file_model_id=file.id).all()
                file_data = SpecFileService().get_spec_file_data(file.id).data
                self.assertIsNotNone(file_data)
                self.assertGreater(len(file_data), 0)
def _upsert_user(ldap_info):
    user = session.query(UserModel).filter(UserModel.uid == ldap_info.uid).first()

    if user is None:
        # Add new user
        user = UserModel()
    else:
        user = session.query(UserModel).filter(UserModel.uid == ldap_info.uid).with_for_update().first()

    user.uid = ldap_info.uid
    user.ldap_info = ldap_info

    session.add(user)
    session.commit()
    return user
Exemple #5
0
    def test_auth_token(self):
        # Save the orginal timeout setting
        orig_ttl = float(app.config['TOKEN_AUTH_TTL_HOURS'])

        self.load_example_data()

        # Set the timeout to something else
        new_ttl = 4.0
        app.config['TOKEN_AUTH_TTL_HOURS'] = new_ttl
        user_1 = UserModel(uid="dhf8r")
        expected_exp_1 = timegm(
            (datetime.utcnow() + timedelta(hours=new_ttl)).utctimetuple())
        auth_token_1 = user_1.encode_auth_token()
        self.assertTrue(isinstance(auth_token_1, str))
        self.assertEqual("dhf8r",
                         user_1.decode_auth_token(auth_token_1).get("sub"))
Exemple #6
0
 def create_user(self,
                 uid="dhf8r",
                 email="*****@*****.**",
                 display_name="Hoopy Frood"):
     user = session.query(UserModel).filter(UserModel.uid == uid).first()
     if user is None:
         ldap_user = LdapService.user_info(uid)
         user = UserModel(uid=uid, ldap_info=ldap_user)
         session.add(user)
         session.commit()
     return user
    def test_study_sponsors_script_validation(self, mock_get):
        mock_get.return_value.ok = True
        mock_get.return_value.text = self.protocol_builder_response('sponsors.json')
        app.config['PB_ENABLED'] = True
        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 ??

        self.load_test_spec("study_sponsors_data_store")
        WorkflowService.test_spec("study_sponsors_data_store")  # This would raise errors if it didn't validate
Exemple #8
0
 def create_user(self,
                 uid="dhf8r",
                 email="*****@*****.**",
                 display_name="Hoopy Frood"):
     user = session.query(UserModel).filter(UserModel.uid == uid).first()
     if user is None:
         user = UserModel(uid=uid,
                          email_address=email,
                          display_name=display_name)
         db.session.add(user)
         db.session.commit()
     return user
Exemple #9
0
 def make_test_workflow(spec_id):
     user = db.session.query(UserModel).filter_by(uid="test").first()
     if not user:
         db.session.add(UserModel(uid="test"))
     study = db.session.query(StudyModel).filter_by(user_uid="test").first()
     if not study:
         db.session.add(StudyModel(user_uid="test", title="test"))
         db.session.commit()
     workflow_model = WorkflowModel(status=WorkflowStatus.not_started,
                                    workflow_spec_id=spec_id,
                                    last_updated=datetime.now(),
                                    study=study)
     return workflow_model
Exemple #10
0
    def test_current_user_status(self):
        self.load_example_data()
        rv = self.app.get('/v1.0/user')
        self.assert_failure(rv, 401)

        rv = self.app.get('/v1.0/user', headers=self.logged_in_headers())
        self.assert_success(rv)

        # User must exist in the mock ldap responses.
        user = UserModel(uid="dhf8r", ldap_info=LdapService.user_info("dhf8r"))
        rv = self.app.get('/v1.0/user',
                          headers=self.logged_in_headers(
                              user, redirect_url='http://omg.edu/lolwut'))
        self.assert_success(rv)
        user_data = json.loads(rv.get_data(as_text=True))
        self.assertTrue(user_data['is_admin'])
def verify_token_admin(token=None):
    """
        Verifies the token for the user (if provided) in non-production environment.
        If in production environment, checks that the user is in the list of authorized admins

        Args:
            token: Optional[str]

        Returns:
            token: str
   """
    verify_token(token)
    if "user" in g and g.user.is_admin():
        token = g.user.encode_auth_token()
        token_info = UserModel.decode_auth_token(token)
        return token_info
Exemple #12
0
    def test_current_user_status(self):
        self.load_example_data()
        rv = self.app.get('/v1.0/user')
        self.assert_failure(rv, 401)

        rv = self.app.get('/v1.0/user', headers=self.logged_in_headers())
        self.assert_success(rv)

        # User must exist in the mock ldap responses.
        user = UserModel(uid="dhf8r",
                         first_name='Dan',
                         last_name='Funk',
                         email_address='*****@*****.**')
        rv = self.app.get('/v1.0/user',
                          headers=self.logged_in_headers(
                              user, redirect_url='http://omg.edu/lolwut'))
        self.assert_success(rv)
Exemple #13
0
    def test_study_sponsors_script_fail(self, mock_get):
        mock_get.return_value.ok = True
        mock_get.return_value.text = self.protocol_builder_response(
            'sponsors.json')
        flask.g.user = UserModel(uid='dhf8r')
        app.config['PB_ENABLED'] = True

        self.load_example_data()
        study = session.query(StudyModel).first()
        workflow_spec_model = self.load_test_spec(
            "study_sponsors_associate_fail")
        workflow_model = StudyService._create_workflow_model(
            study, workflow_spec_model)
        WorkflowService.test_spec("study_sponsors_associate_fail")
        processor = WorkflowProcessor(workflow_model)
        with self.assertRaises(ApiError):
            processor.do_engine_steps()
Exemple #14
0
    def create_user_with_study_and_workflow(self):

        # clear it all out.
        from example_data import ExampleDataLoader
        ExampleDataLoader.clean_db()

        # Assure some basic models are in place, This is a damn mess.  Our database models need an overhaul to make
        # this easier - better relationship modeling is now critical.
        self.load_test_spec("top_level_workflow", master_spec=True)
        user = db.session.query(UserModel).filter(
            UserModel.uid == "dhf8r").first()
        if not user:
            user = UserModel(uid="dhf8r",
                             email_address="*****@*****.**",
                             display_name="Stayathome Smellalots")
            db.session.add(user)
            db.session.commit()
        else:
            for study in db.session.query(StudyModel).all():
                StudyService().delete_study(study.id)

        study = StudyModel(
            title="My title",
            protocol_builder_status=ProtocolBuilderStatus.ACTIVE,
            user_uid=user.uid)
        db.session.add(study)
        cat = WorkflowSpecCategoryModel(name="approvals",
                                        display_name="Approvals",
                                        display_order=0)
        db.session.add(cat)
        db.session.commit()

        self.assertIsNotNone(cat.id)
        self.load_test_spec("random_fact", category_id=cat.id)

        self.assertIsNotNone(study.id)
        workflow = WorkflowModel(workflow_spec_id="random_fact",
                                 study_id=study.id,
                                 status=WorkflowStatus.not_started,
                                 last_updated=datetime.now())
        db.session.add(workflow)
        db.session.commit()
        # Assure there is a master specification, one standard spec, and lookup tables.
        ExampleDataLoader().load_reference_documents()
        return user
Exemple #15
0
    def load_example_data(self, use_crc_data=False, use_rrt_data=False):
        """use_crc_data will cause this to load the mammoth collection of documents
        we built up developing crc, use_rrt_data will do the same for hte rrt project,
         otherwise it depends on a small setup for running tests."""
        from example_data import ExampleDataLoader
        ExampleDataLoader.clean_db()
        if use_crc_data:
            ExampleDataLoader().load_all()
        elif use_rrt_data:
            ExampleDataLoader().load_rrt()
        else:
            ExampleDataLoader().load_test_data()

        for user_json in self.users:
            db.session.add(UserModel(**user_json))
        db.session.commit()
        for study_json in self.studies:
            study_model = StudyModel(**study_json)
            db.session.add(study_model)
            StudyService._add_all_workflow_specs_to_study(study_model)
            db.session.execute(Sequence(StudyModel.__tablename__ + '_id_seq'))
        db.session.commit()
        db.session.flush()

        specs = session.query(WorkflowSpecModel).all()
        self.assertIsNotNone(specs)

        for spec in specs:
            files = session.query(FileModel).filter_by(
                workflow_spec_id=spec.id).all()
            self.assertIsNotNone(files)
            self.assertGreater(len(files), 0)

        for spec in specs:
            files = session.query(FileModel).filter_by(
                workflow_spec_id=spec.id).all()
            self.assertIsNotNone(files)
            self.assertGreater(len(files), 0)
            for file in files:
                file_data = session.query(FileDataModel).filter_by(
                    file_model_id=file.id).all()
                self.assertIsNotNone(file_data)
                self.assertGreater(len(file_data), 0)
    def test_study_sponsors_script(self, mock_get):

        mock_get.return_value.ok = True
        mock_get.return_value.text = self.protocol_builder_response('sponsors.json')
        flask.g.user = UserModel(uid='dhf8r')
        app.config['PB_ENABLED'] = True

        self.load_example_data()
        study = session.query(StudyModel).first()
        workflow_spec_model = self.load_test_spec("study_sponsors_data_store")
        workflow_model = StudyService._create_workflow_model(study, workflow_spec_model)
        WorkflowService.test_spec("study_sponsors_data_store")
        processor = WorkflowProcessor(workflow_model)
        processor.do_engine_steps()
        self.assertTrue(processor.bpmn_workflow.is_completed())
        data = processor.next_task().data
        self.assertIn('sponsors', data)
        self.assertIn('out', data)
        self.assertEqual('empty', data['empty'])
        self.assertEqual('newval', data['out'])
        self.assertEqual(3, len(data['sponsors']))
Exemple #17
0
    def test_study_sponsors_script_primary_user(self, mock_get):
        mock_get.return_value.ok = True
        mock_get.return_value.text = self.protocol_builder_response(
            'sponsors.json')
        flask.g.user = UserModel(uid='dhf8r')
        app.config['PB_ENABLED'] = True

        self.load_example_data()
        study = session.query(StudyModel).first()
        workflow_spec_model = self.load_test_spec(
            "study_sponsors_associate_switch_user")
        workflow_model = StudyService._create_workflow_model(
            study, workflow_spec_model)
        WorkflowService.test_spec("study_sponsors_associate_switch_user")
        processor = WorkflowProcessor(workflow_model)
        processor.do_engine_steps()
        tasks = processor.next_user_tasks()
        self.assertEqual(len(tasks), 1)
        processor.complete_task(tasks[0])
        processor.do_engine_steps()
        self.assertTrue(processor.bpmn_workflow.is_completed())
Exemple #18
0
def _upsert_user(user_info):
    user = db.session.query(UserModel).filter(
        UserModel.uid == user_info.uid).first()

    if user is None:
        # Add new user
        user = UserModel()
    else:
        user = db.session.query(UserModel).filter(
            UserModel.uid == user_info.uid).with_for_update().first()

    user.uid = user_info.uid
    user.display_name = user_info.display_name
    user.email_address = user_info.email_address
    user.affiliation = user_info.affiliation
    user.title = user_info.title

    db.session.add(user)
    db.session.commit()
    return user
Exemple #19
0
    def test_study_sponsors_script_valid_users(self, mock_get):
        mock_get.return_value.ok = True
        mock_get.return_value.text = self.protocol_builder_response(
            'sponsors.json')
        flask.g.user = UserModel(uid='dhf8r')
        app.config['PB_ENABLED'] = True

        self.load_example_data()
        study = session.query(StudyModel).first()
        workflow_spec_model = self.load_test_spec(
            "study_sponsors_associate_switch_user")
        workflow_model = StudyService._create_workflow_model(
            study, workflow_spec_model)
        WorkflowService.test_spec("study_sponsors_associate_switch_user")
        processor = WorkflowProcessor(workflow_model)
        processor.do_engine_steps()
        tasks = processor.next_user_tasks()
        self.assertEqual(len(tasks), 1)
        users = WorkflowService.get_users_assigned_to_task(processor, tasks[0])
        self.assertFalse('cah3us' in users)
        self.assertFalse('lje5u' in users)
        self.assertTrue('lb3dp' in users)
        self.assertTrue('dhf8r' in users)
 def load_default_user(self):
     ldap_info = LdapModel(uid="dhf8r", email_address="*****@*****.**", display_name="Development User")
     user = UserModel(uid="dhf8r", ldap_info=ldap_info)
     db.session.add(ldap_info)
     db.session.add(user)
     db.session.commit()
Exemple #21
0
    def test_auth_token(self):
        # Save the orginal timeout setting
        orig_ttl = float(app.config['TOKEN_AUTH_TTL_HOURS'])

        self.load_example_data()

        # Set the timeout to something else
        new_ttl = 4.0
        app.config['TOKEN_AUTH_TTL_HOURS'] = new_ttl
        user_1 = UserModel(uid="dhf8r")
        expected_exp_1 = timegm(
            (datetime.utcnow() + timedelta(hours=new_ttl)).utctimetuple())
        auth_token_1 = user_1.encode_auth_token()
        self.assertTrue(isinstance(auth_token_1, bytes))
        self.assertEqual("dhf8r",
                         user_1.decode_auth_token(auth_token_1).get("sub"))
        actual_exp_1 = user_1.decode_auth_token(auth_token_1).get("exp")
        self.assertTrue(
            expected_exp_1 - 1000 <= actual_exp_1 <= expected_exp_1 + 1000)

        # Set the timeout to something else
        neg_ttl = -0.01
        app.config['TOKEN_AUTH_TTL_HOURS'] = neg_ttl
        user_2 = UserModel(uid="dhf8r")
        expected_exp_2 = timegm(
            (datetime.utcnow() + timedelta(hours=neg_ttl)).utctimetuple())
        auth_token_2 = user_2.encode_auth_token()
        self.assertTrue(isinstance(auth_token_2, bytes))
        with self.assertRaises(ApiError) as api_error:
            with self.assertRaises(jwt.exceptions.ExpiredSignatureError):
                user_2.decode_auth_token(auth_token_2)
        self.assertEqual(api_error.exception.status_code, 400,
                         'Should raise an API Error if token is expired')

        # Set the timeout back to where it was
        app.config['TOKEN_AUTH_TTL_HOURS'] = orig_ttl
        user_3 = UserModel(uid="dhf8r")
        expected_exp_3 = timegm(
            (datetime.utcnow() + timedelta(hours=new_ttl)).utctimetuple())
        auth_token_3 = user_3.encode_auth_token()
        self.assertTrue(isinstance(auth_token_3, bytes))
        actual_exp_3 = user_3.decode_auth_token(auth_token_1).get("exp")
        self.assertTrue(
            expected_exp_3 - 1000 <= actual_exp_3 <= expected_exp_3 + 1000)
Exemple #22
0
    def test_study_sponsors_script(self, mock_get):
        mock_get.return_value.ok = True
        mock_get.return_value.text = self.protocol_builder_response(
            'sponsors.json')
        flask.g.user = UserModel(uid='dhf8r')
        app.config['PB_ENABLED'] = True

        self.load_example_data()
        study = session.query(StudyModel).first()
        workflow_spec_model = self.load_test_spec("study_sponsors_associate")
        workflow_model = StudyService._create_workflow_model(
            study, workflow_spec_model)
        WorkflowService.test_spec("study_sponsors_associate")
        processor = WorkflowProcessor(workflow_model)
        processor.do_engine_steps()
        self.assertTrue(processor.bpmn_workflow.is_completed())
        data = processor.next_task().data
        self.assertIn('sponsors', data)
        self.assertIn('out', data)
        print(data['out'])
        dhf8r_info = LdapSchema().dump(LdapService.user_info('dhf8r'))
        lb3dp_info = LdapSchema().dump(LdapService.user_info('lb3dp'))

        self.assertDictEqual(
            {
                'uid': 'dhf8r',
                'role': 'owner',
                'send_email': True,
                'access': True,
                'ldap_info': dhf8r_info
            }, data['out'][1])
        self.assertDictEqual(
            {
                'uid': 'lb3dp',
                'role': 'SuperDude',
                'send_email': False,
                'access': True,
                'ldap_info': lb3dp_info
            }, data['out'][0])
        self.assertDictEqual(
            {
                'uid': 'lb3dp',
                'role': 'SuperDude',
                'send_email': False,
                'access': True,
                'ldap_info': lb3dp_info
            }, data['out2'])
        self.assertDictEqual(
            {
                'uid': 'dhf8r',
                'role': 'owner',
                'send_email': True,
                'access': True,
                'ldap_info': dhf8r_info
            }, data['out3'][1])
        self.assertDictEqual(
            {
                'uid': 'lb3dp',
                'role': 'SuperGal',
                'send_email': False,
                'access': True,
                'ldap_info': lb3dp_info
            }, data['out3'][0])
        self.assertDictEqual(
            {
                'uid': 'lb3dp',
                'role': 'SuperGal',
                'send_email': False,
                'access': True,
                'ldap_info': lb3dp_info
            }, data['out4'])
        self.assertEqual(3, len(data['sponsors']))
def verify_token(token=None):
    """
        Verifies the token for the user (if provided). If in production environment and token is not provided,
        gets user from the SSO headers and returns their token.

        Args:
            token: Optional[str]

        Returns:
            token: str

        Raises:
            ApiError.  If not on production and token is not valid, returns an 'invalid_token' 403 error.
            If on production and user is not authenticated, returns a 'no_user' 403 error.
   """

    failure_error = ApiError("invalid_token", "Unable to decode the token you provided.  Please re-authenticate",
                             status_code=403)

    if token:
        try:
            token_info = UserModel.decode_auth_token(token)
            g.user = UserModel.query.filter_by(uid=token_info['sub']).first()

            # If the user is valid, store the token for this session
            if g.user:
                g.token = token
        except:
            raise failure_error
        if g.user is not None:
            return token_info
        else:
            raise failure_error

    # If there's no token and we're in production, get the user from the SSO headers and return their token
    elif _is_production():
        uid = _get_request_uid(request)

        if uid is not None:
            db_user = UserModel.query.filter_by(uid=uid).first()

            # If the user is valid, store the user and token for this session
            if db_user is not None:
                g.user = db_user
                token = g.user.encode_auth_token().decode()
                g.token = token
                token_info = UserModel.decode_auth_token(token)
                return token_info

            else:
                raise ApiError("no_user",
                               "User not found. Please login via the frontend app before accessing this feature.",
                               status_code=403)

    else:
        # Fall back to a default user if this is not production.
        g.user = UserModel.query.first()
        if not g.user:
            raise ApiError("no_user", "You are in development mode, but there are no users in the database.  Add one, and it will use it.")
        token = g.user.encode_auth_token()
        token_info = UserModel.decode_auth_token(token)
        return token_info