Пример #1
0
    def test_get_current_user(self, req, db_session, config):
        """
        It should return the authenticated user's exports
        """
        import mock
        from occams_datastore import models as datastore
        from occams_studies import models

        req.registry.settings['studies.export.dir'] = '/tmp'

        blame = datastore.User(key=u'joe')
        db_session.add(blame)
        db_session.add(datastore.User(key='jane'))
        db_session.flush()
        db_session.info['blame'] = blame

        export1 = models.Export(owner_user=(db_session.query(
            datastore.User).filter_by(key='joe').one()),
                                contents=[],
                                status='pending')
        export2 = models.Export(owner_user=(db_session.query(
            datastore.User).filter_by(key='jane').one()),
                                contents=[],
                                status='pending')
        db_session.add_all([export1, export2])
        db_session.flush()

        config.testing_securitypolicy(userid='joe')
        req.redis = mock.Mock()
        context = models.ExportFactory(req)
        export1.__parent__ = context
        export2.__parent__ = context
        res = self._call_fut(models.ExportFactory(req), req)
        exports = res['exports']
        assert len(exports) == 1
Пример #2
0
    def populate(self, request, db_session):
        import os
        import transaction
        from occams_studies import models
        from occams_datastore import models as datastore

        # Any view-dependent data goes here
        # Webtests will use a different scope for its transaction
        with transaction.manager:
            user = datastore.User(key=USERID)
            db_session.info['blame'] = user
            db_session.add(user)
            export = models.Export(name='myexport',
                                   status='complete',
                                   owner_user=user)
            db_session.add(export)
            db_session.flush()
            self.url = self.url_fmt.format(export=export.id)
            with open('/tmp/myexport', 'w+') as fp:
                self.export_file_name = fp.name

        def rm():
            os.unlink(self.export_file_name)

        request.addfinalizer(rm)
Пример #3
0
def db_session(config):
    """
    (Integartion Testing) Instantiates a database session.

    :param config: The pyramid testing configuartion

    :returns: An instantiated sqalchemy database session
    """
    from occams_datastore import models as datastore
    import occams_datastore.models.events
    import zope.sqlalchemy

    db_session = config.registry['dbsession_factory']()
    occams_datastore.models.events.register(db_session)
    zope.sqlalchemy.register(db_session)

    # Pre-configure with a blame user
    blame = datastore.User(key=USERID)
    db_session.add(blame)
    db_session.flush()
    db_session.info['blame'] = blame

    # Other expected settings
    db_session.info['settings'] = config.registry.settings

    return db_session
Пример #4
0
    def test_zip(self):
        """
        It should generate a zip file containing the specified contents
        """
        from zipfile import ZipFile
        from occams.celery import Session
        from occams_datastore import models as datastore
        from occams_studies import models, tasks
        from occams_studies.exports.pid import PidPlan

        owner = datastore.User(key=u'joe')
        Session.info['blame'] = owner
        Session.add(owner)
        Session.flush()

        export = models.Export(owner_user=owner,
                               contents=[{
                                   'name': 'pid',
                                   'title': 'PID',
                                   'versions': []
                               }],
                               status='complete')
        Session.add(export)
        Session.flush()

        tasks.app.settings['studies.export.plans'] = [PidPlan]
        tasks.make_export(export.name)

        # @in_transaction removes the session metadata, so we gotta do this
        export = Session.merge(export)
        with ZipFile(export.path, 'r') as zfp:
            file_names = zfp.namelist()

        assert sorted(['pid.csv', 'codebook.csv']) == sorted(file_names)
Пример #5
0
 def test_not_owner(self, app, db_session):
     import transaction
     from occams_datastore import models as datastore
     with transaction.manager:
         db_session.add(datastore.User(key='somebody_else'))
     environ = make_environ(userid='somebody_else')
     app.get(self.url, extra_environ=environ, status=403)
Пример #6
0
    def test_delete(self, req, db_session, config, check_csrf_token):
        """
        It should allow the owner of the export to cancel/delete the export
        """
        import mock
        from pyramid.httpexceptions import HTTPOk
        from occams_datastore import models as datastore
        from occams_studies import models

        blame = datastore.User(key=u'joe')
        db_session.add(blame)
        db_session.flush()
        db_session.info['blame'] = blame

        export = models.Export(owner_user=(db_session.query(
            datastore.User).filter_by(key='joe').one()),
                               contents=[],
                               status='complete')
        db_session.add(export)
        db_session.flush()
        export_id = export.id
        export_name = export.name
        db_session.expunge_all()

        config.testing_securitypolicy(userid='joe')
        with mock.patch('occams_studies.tasks.app.control.revoke') as revoke:
            res = self._call_fut(export, req)
        check_csrf_token.assert_called_with(req)
        assert isinstance(res, HTTPOk)
        assert db_session.query(models.Export).get(export_id) is None
        revoke.assert_called_with(export_name)
    def populate(self, app, db_session):
        from datetime import date

        import transaction
        from occams_datastore import models as datastore
        from occams_studies import models as studies

        # Any view-dependent data goes here
        with transaction.manager:
            user = datastore.User(key=USERID)
            drsc = studies.Study(name=u'drsc',
                                 title=u'DRSC',
                                 short_title=u'dr',
                                 code=u'drs',
                                 consent_date=date.today(),
                                 is_randomized=False)
            ucsd = studies.Study(name=u'ucsd',
                                 title=u'UCSD',
                                 short_title=u'ucsd',
                                 code=u'ucsd',
                                 consent_date=date.today(),
                                 is_randomized=False)
            db_session.add(user)
            db_session.add(drsc)
            db_session.add(ucsd)
            db_session.flush()
Пример #8
0
    def populate(self, app, db_session):
        import transaction
        from occams_studies import models as studies
        from occams_datastore import models as datastore
        from datetime import date

        # Any view-dependent data goes here
        # Webtests will use a different scope for its transaction
        with transaction.manager:
            user = datastore.User(key=USERID)
            db_session.info['blame'] = user
            db_session.add(user)
            db_session.flush()

            site = studies.Site(name=u'UCSD',
                                title=u'UCSD',
                                description=u'UCSD Campus',
                                create_date=date.today())

            patient = studies.Patient(initials=u'ian',
                                      nurse=u'*****@*****.**',
                                      site=site,
                                      pid=u'123')

            study = studies.Study(
                name=u'test_study',
                code=u'test_code',
                consent_date=date(2014, 12, 23),
                is_randomized=False,
                title=u'test_title',
                short_title=u'test_short',
            )

            db_session.add(study)
            db_session.add(patient)
Пример #9
0
def db_session(config):
    """
    (Integartion Testing) Instantiates a database session.

    :param config: The pyramid testing configuartion

    :returns: An instantiated sqalchemy database session
    """
    from occams_datastore import models as datastore

    db_session = config.registry['db_sessionmaker']()

    # Pre-configure with a blame user
    blame = datastore.User(key=USERID)
    db_session.add(blame)
    db_session.flush()
    db_session.info['blame'] = blame

    # Other expected settings
    db_session.info['settings'] = config.registry.settings

    # Hardcoded workflow
    db_session.add_all([
        datastore.State(name=u'pending-entry', title=u'Pending Entry'),
        datastore.State(name=u'pending-review', title=u'Pending Review'),
        datastore.State(name=u'pending-correction',
                        title=u'Pending Correction'),
        datastore.State(name=u'complete', title=u'Complete')
    ])

    return db_session
Пример #10
0
    def populate(self, app, db_session):
        import transaction
        from occams_datastore import models as datastore

        # Any view-dependent data goes here
        # Webtests will use a different scope for its transaction
        with transaction.manager:
            db_session.add(datastore.User(key=USERID))
Пример #11
0
def db_session(sessionmaker):
    from occams_datastore import models
    session = sessionmaker()
    blame = models.User(key=u'tester')
    session.add(blame)
    session.flush()
    session.info['blame'] = blame
    yield session
    session.rollback()
Пример #12
0
    def populate(self, app, db_session):
        import transaction
        from occams_studies import models as studies
        from occams_datastore import models as datastore
        from datetime import date

        # Any view-dependent data goes here
        # Webtests will use a different scope for its transaction
        with transaction.manager:
            user = datastore.User(key=USERID)
            db_session.info['blame'] = user
            db_session.add(user)
            db_session.flush()

            site = studies.Site(name=u'UCSD',
                                title=u'UCSD',
                                description=u'UCSD Campus',
                                create_date=date.today())

            patient = studies.Patient(initials=u'ian',
                                      nurse=u'*****@*****.**',
                                      site=site,
                                      pid=u'123')

            form = datastore.Schema(name=u'test_schema',
                                    title=u'test_title',
                                    publish_date=date(2015, 1, 1))

            study = studies.Study(name=u'test_study',
                                  code=u'test_code',
                                  consent_date=date(2014, 12, 23),
                                  is_randomized=False,
                                  title=u'test_title',
                                  short_title=u'test_short',
                                  schemata=set([form]))

            cycle = studies.Cycle(name=u'TestCycle',
                                  title=u'TestCycle',
                                  week=39,
                                  study=study)

            visit = studies.Visit(patient=patient,
                                  cycles=[cycle],
                                  visit_date='2015-01-01')

            entity = datastore.Entity(schema=form,
                                      collect_date=date(2015, 1, 1))

            db_session.add(study)
            db_session.add(patient)
            db_session.add(visit)
            db_session.add(entity)
            patient.entities.add(entity)
Пример #13
0
 def test_not_owner(self, app, db_session):
     import transaction
     from occams_datastore import models as datastore
     with transaction.manager:
         db_session.add(datastore.User(key='somebody_else'))
     environ = make_environ(userid='somebody_else')
     csrf_token = get_csrf_token(app, environ)
     app.delete(self.url,
                extra_environ=environ,
                headers={'X-CSRF-Token': csrf_token},
                xhr=True,
                status=403)
Пример #14
0
    def populate(self, app, db_session):
        import transaction
        from occams_datastore import models as datastore
        from occams_studies import models as studies

        # Any view-dependent data goes here
        # Webtests will use a different scope for its transaction
        with transaction.manager:
            blame = datastore.User(key=USERID)
            db_session.info['blame'] = blame
            db_session.add(blame)
            db_session.flush()

            db_session.add(studies.Site(name=u'ucsd', title=u'UCSD'))
            db_session.add(studies.Site(name=u'ucla', title=u'UCSD'))
Пример #15
0
    def populate(self, app, db_session):
        import transaction
        from occams_datastore import models as datastore
        from occams_studies import models

        # Any view-dependent data goes here
        # Webtests will use a different scope for its transaction
        with transaction.manager:
            user = datastore.User(key=USERID)
            db_session.info['blame'] = user
            db_session.add(user)
            export = models.Export(owner_user=user)
            db_session.add(export)
            db_session.flush()
            self.url = self.url_fmt.format(export=export.id)
Пример #16
0
    def populate(self, app, db_session):
        import transaction
        from occams_studies import models as studies
        from occams_datastore import models as datastore
        from datetime import date

        # Any view-dependent data goes here
        # Webtests will use a different scope for its transaction
        with transaction.manager:
            user = datastore.User(key=USERID)
            db_session.info['blame'] = user
            db_session.add(user)
            db_session.flush()
            site = studies.Site(name=u'UCSD',
                                title=u'UCSD',
                                description=u'UCSD Campus',
                                create_date=date.today())

            patient = studies.Patient(initials=u'ian',
                                      nurse=u'*****@*****.**',
                                      site=site,
                                      pid=u'123')

            form = datastore.Schema(name=u'test_schema',
                                    title=u'test_title',
                                    publish_date=date(2015, 1, 1))

            study = studies.Study(name=u'test_study',
                                  code=u'test_code',
                                  consent_date=date(2014, 12, 23),
                                  is_randomized=False,
                                  title=u'test_title',
                                  short_title=u'test_short',
                                  schemata=set([form]))

            state = (db_session.query(
                datastore.State).filter_by(name=u'pending-entry').one())

            db_session.add(
                datastore.Entity(state=state,
                                 schema=form,
                                 collect_date=date(2015, 2, 1)))

            db_session.add(
                studies.Enrollment(patient=patient,
                                   study=study,
                                   consent_date=date(2014, 12, 22)))
Пример #17
0
def app(request, wsgi, db_session):
    """
    (Functional Testing) Initiates a user request against a WSGI stack

    :param request: The pytest context
    :param wsgi: An initialized WSGI stack
    :param db_session: A database session for seting up pre-existing data

    :returns: a test app request against the WSGI instance
    """
    import transaction
    from webtest import TestApp
    from zope.sqlalchemy import mark_changed
    from occams_datastore import models as datastore

    # Save all changes up tho this point (db_session does some configuration)
    with transaction.manager:
        blame = datastore.User(key='workflow@localhost')
        db_session.add(blame)
        db_session.flush()
        db_session.info['blame'] = blame

        db_session.add_all([
            datastore.State(name=u'pending-entry', title=u'Pending Entry'),
            datastore.State(name=u'pending-review', title=u'Pending Review'),
            datastore.State(name=u'pending-correction',
                            title=u'Pending Correction'),
            datastore.State(name=u'complete', title=u'Complete')
        ])

    app = TestApp(wsgi)

    yield app

    with transaction.manager:
        # DELETE is dramatically faster than TRUNCATE
        # http://stackoverflow.com/a/11423886/148781
        # We also have to do this as a raw query becuase SA does
        # not have a way to invoke server-side cascade
        db_session.execute('DELETE FROM "study" CASCADE')
        db_session.execute('DELETE FROM "patient" CASCADE')
        db_session.execute('DELETE FROM "site" CASCADE')
        db_session.execute('DELETE FROM "schema" CASCADE')
        db_session.execute('DELETE FROM "export" CASCADE')
        db_session.execute('DELETE FROM "state" CASCADE')
        db_session.execute('DELETE FROM "user" CASCADE')
        mark_changed(db_session)
Пример #18
0
    def test_ignore_expired(self, req, db_session, config):
        """
        It should not render expired exports.
        """
        from datetime import datetime, timedelta
        import mock
        from occams_datastore import models as datastore
        from occams_studies import models

        EXPIRE_DAYS = 10

        req.registry.settings['studies.export.expire'] = EXPIRE_DAYS
        req.registry.settings['studies.export.dir'] = '/tmp'

        blame = datastore.User(key=u'joe')
        db_session.add(blame)
        db_session.flush()
        db_session.info['blame'] = blame

        now = datetime.now()

        export = models.Export(owner_user=(db_session.query(
            datastore.User).filter_by(key='joe').one()),
                               contents=[],
                               status='pending',
                               create_date=now,
                               modify_date=now)
        db_session.add(export)
        db_session.flush()

        config.testing_securitypolicy(userid='joe')
        req.redis = mock.Mock()
        context = models.ExportFactory(req)
        export.__parent__ = context
        res = self._call_fut(context, req)
        exports = res['exports']
        assert len(exports) == 1

        export.create_date = export.modify_date = \
            now - timedelta(EXPIRE_DAYS + 1)
        db_session.flush()
        context = models.ExportFactory(req)
        export.__parent__ = context
        res = self._call_fut(context, req)
        exports = res['exports']
        assert len(exports) == 0
Пример #19
0
    def populate(self, request, app, db_session):
        import os
        import transaction
        from occams_datastore import models as datastore

        # Any view-dependent data goes here
        # Webtests will use a different scope for its transaction
        with transaction.manager:
            db_session.add(datastore.User(key=USERID))

        # XXX: need to somehow get the settings so we can consitently
        #      get the correct directory
        with open('/tmp/codebook.csv', 'w+') as fp:
            self.codebook_file_name = fp.name

        def rm():
            os.unlink(self.codebook_file_name)

        request.addfinalizer(rm)
Пример #20
0
    def populate(self, app, db_session):
        import transaction
        from occams_studies import models as studies
        from occams_datastore import models as datastore
        from datetime import date

        # Any view-dependent data goes here
        # Webtests will use a different scope for its transaction
        with transaction.manager:
            user = datastore.User(key=USERID)
            db_session.info['blame'] = user
            db_session.add(user)
            db_session.flush()
            db_session.add(
                studies.Site(name=u'UCSD',
                             title=u'UCSD',
                             description=u'UCSD Campus',
                             create_date=date.today()))
            db_session.flush()
Пример #21
0
    def populate(self, app, db_session):
        import transaction
        from occams_studies import models as studies
        from occams_datastore import models as datastore
        from datetime import date

        # Any view-dependent data goes here
        # Webtests will use a different scope for its transaction
        with transaction.manager:
            user = datastore.User(key=USERID)
            db_session.info['blame'] = user
            db_session.add(user)
            db_session.flush()
            db_session.add(studies.Study(
                name=u'test',
                title=u'test',
                short_title=u'test',
                code=u'test',
                consent_date=date.today(),
                is_randomized=False))
Пример #22
0
def celery(request):
    """
    (Function Testing) Sets up a celery application for testing

    :param request: The pytest context
    """
    import shutil
    import tempfile
    import mock
    from redis import StrictRedis
    from sqlalchemy import create_engine
    from occams.celery import Session
    from occams_datastore import models as datastore
    from occams_studies import tasks

    settings = {
        'studies.export.dir': tempfile.mkdtemp(),
        'celery.blame': USERID
    }

    tasks.app.userid = settings['celery.blame']
    tasks.app.redis = StrictRedis.from_url(REDIS_URL)
    tasks.app.settings = settings

    db_url = request.config.getoption('--db')
    engine = create_engine(db_url)
    Session.configure(bind=engine, info={'settings': settings})
    Session.add(datastore.User(key=settings['celery.blame']))

    Session.flush()

    commitmock = mock.patch('occams_imports.tasks.Session.commit')
    commitmock.start()

    def cleanup():
        commitmock.stop()
        shutil.rmtree(settings['studies.export.dir'])
        Session.remove()

    request.addfinalizer(cleanup)
Пример #23
0
    def test_exceed_limit(self, req, db_session, config):
        """
        It should not let the user exceed their allocated export limit
        """
        from datetime import date
        from webob.multidict import MultiDict
        from occams_datastore import models as datastore
        from occams_studies import models
        from occams_studies.exports.schema import SchemaPlan

        config.registry.settings['app.export.limit'] = 0
        req.registry.settings['studies.export.plans'] = [SchemaPlan.list_all]

        blame = datastore.User(key=u'joe')
        db_session.add(blame)
        db_session.flush()
        db_session.info['blame'] = blame

        previous_export = models.Export(owner_user=(db_session.query(
            datastore.User).filter_by(key='joe').one()),
                                        contents=[{
                                            u'name':
                                            u'vitals',
                                            u'title':
                                            u'Vitals',
                                            u'versions': [str(date.today())]
                                        }])
        db_session.add(previous_export)
        db_session.flush()

        # The renderer should know about it
        config.testing_securitypolicy(userid='joe')
        res = self._call_fut(models.ExportFactory(req), req)
        assert res['exceeded']

        # If the user insists, they'll get a validation error as well
        config.testing_securitypolicy(userid='joe')
        req.method = 'POST'
        req.POST = MultiDict([('contents', 'vitals')])
        assert res['exceeded']
Пример #24
0
    def test_valid(self, req, db_session, config, check_csrf_token):
        """
        It should add an export record and initiate an async task
        """
        from datetime import date
        import mock
        from pyramid.httpexceptions import HTTPFound
        from webob.multidict import MultiDict
        from occams_datastore import models as datastore
        from occams_studies import models
        from occams_studies.exports.schema import SchemaPlan

        req.registry.settings['app.export.dir'] = '/tmp'
        req.registry.settings['studies.export.plans'] = [SchemaPlan.list_all]

        blame = datastore.User(key=u'joe')
        db_session.add(blame)
        db_session.flush()
        db_session.info['blame'] = blame

        schema = datastore.Schema(name=u'vitals',
                                  title=u'Vitals',
                                  publish_date=date.today())
        db_session.add(schema)
        db_session.flush()

        config.testing_securitypolicy(userid='joe')
        req.method = 'POST'
        req.POST = MultiDict([('contents', str('vitals'))])

        # Don't invoke subtasks
        with mock.patch('occams_studies.tasks.make_export'):
            res = self._call_fut(models.ExportFactory(req), req)

        check_csrf_token.assert_called_with(req)
        assert isinstance(res, HTTPFound)
        assert res.location == req.route_path('studies.exports_status')
        export = db_session.query(models.Export).one()
        assert export.owner_user.key == 'joe'
Пример #25
0
    def test_get_not_found_status(self, req, db_session, status):
        """
        It should return 404 if the record is not ready
        """
        from pyramid.httpexceptions import HTTPBadRequest
        from occams_datastore import models as datastore
        from occams_studies import models

        blame = datastore.User(key=u'joe')
        db_session.add(blame)
        db_session.flush()
        db_session.info['blame'] = blame

        export = models.Export(id=123,
                               owner_user=(db_session.query(
                                   datastore.User).filter_by(key='joe').one()),
                               contents=[],
                               status=status)
        db_session.add(export)
        db_session.flush()

        with pytest.raises(HTTPBadRequest):
            self._call_fut(export, req)
Пример #26
0
def login(request):

    db_session = request.db_session
    form = LoginForm(request.POST)

    if request.method == 'POST' and form.validate():
        # XXX: Hack for this to work on systems that have not set the
        # environ yet. Pyramid doesn't give us access to the policy
        # publicly, put it's still available throught this private
        # variable and it's usefule in leveraging repoze.who's
        # login mechanisms...
        who_api = request._get_authentication_policy()._getAPI(request)

        authenticated, headers = who_api.login(form.data)

        if not authenticated:
            request.session.flash(_(u'Invalid credentials'), 'danger')
        else:
            user = (db_session.query(
                datastore.User).filter_by(key=form.login.data).first())
            if not user:
                user = datastore.User(key=form.login.data)
                db_session.add(user)

            referrer = request.GET.get('referrer')
            if not referrer or request.route_path(
                    'accounts.login') in referrer:
                # TODO: Maybe send the user to their user dashboard instead?
                referrer = request.route_path('occams.index')

            return HTTPFound(location=referrer, headers=headers)

    # forcefully forget any credentials
    request.response.headerlist.extend(forget(request))

    return {'form': form}