def test_ingest_without_molecule(server, molecule, user, make_girder_file, fsAssetstore):
    from girder.plugins.molecules.models.calculation import Calculation
    # Upload simulation result
    dir_path = os.path.dirname(os.path.realpath(__file__))

    with open(os.path.join(dir_path, 'data', 'ethane.cjson')) as f:
        file = make_girder_file(fsAssetstore, user, 'ethane.cjson', contents=f.read().encode())

    # Now we can test the ingest
    body = {
        'fileId': str(file['_id']),
        'format': 'cjson',
        'public': True,
        'image': {
            'repository': 'openchemistry/psi4',
            'tag': 'latest'
        }
    }

    r = server.request('/calculations', method='POST', type='application/json',
                       body=json.dumps(body), user=user)
    assertStatus(r, 201)

    calculation =  Calculation().load(r.json['_id'], force=True)
    for prop in ['fileId', 'moleculeId', 'notebooks', 'properties', 'cjson']:
        assert prop in calculation

    # Molecule should be created
    assert calculation['moleculeId'] is not None
Example #2
0
def testReadingSettingsWithUserToken(server, userSettingToken):
    # Non-admin user with this token scope should still not work
    resp = server.request(path='/system/setting',
                          params={'key': SettingKey.SMTP_PORT},
                          token=userSettingToken)
    assertStatus(resp, 403)
    assert resp.json['message'] == 'Administrator access required.'
Example #3
0
def test_ingest_with_molecule(server, molecule, user, make_girder_file,
                              fsAssetstore):
    molecule = molecule(user)
    from molecules.models.calculation import Calculation
    # Upload simulation result
    dir_path = os.path.dirname(os.path.realpath(__file__))

    with open(os.path.join(dir_path, 'data', 'ethane.cjson')) as f:
        file = make_girder_file(fsAssetstore,
                                user,
                                'ethane.cjson',
                                contents=f.read().encode())

    # Now we can test the ingest
    body = {
        'fileId': str(file['_id']),
        'format': 'cjson',
        'moleculeId': str(molecule['_id']),
        'public': True,
        'image': {
            'repository': 'openchemistry/psi4',
            'tag': 'latest'
        }
    }

    r = server.request('/calculations',
                       method='POST',
                       type='application/json',
                       body=json.dumps(body),
                       user=user)
    assertStatus(r, 201)

    calculation = Calculation().load(r.json['_id'], force=True)
    for prop in ['fileId', 'moleculeId', 'notebooks', 'properties', 'cjson']:
        assert prop in calculation
Example #4
0
def test_get(server, project, cycle, batch, make_batch, user, admin,
             cycletest):
    r = server.request(
        '/edp/projects/%s/cycles/%s/batches/%s/tests/%s' %
        (project['_id'], cycle['_id'], batch['_id'], cycletest['_id']),
        method='GET',
        user=user)
    assertStatusOk(r)
    assert cycletest.items() <= r.json.items()

    # Make another project and try to fetch a test that is not associated
    # with it
    body = {
        'startDate': datetime.datetime.utcnow().timestamp(),
        'title': 'another title',
        'experimentalDesign': 'I designed the cool experiment.',
        'experimentalNotes': 'These are my notes.',
        'dataNotes': 'Here are some notes.',
        'motivation': 'I have some.'
    }
    another_batch = make_batch(user, project, cycle, body)
    r = server.request(
        '/edp/projects/%s/cycles/%s/batches/%s/tests/%s' %
        (project['_id'], cycle['_id'], another_batch['_id'], cycletest['_id']),
        method='GET',
        user=user)
    assertStatus(r, 400)
Example #5
0
    def _make_project(user, request):
        r = server.request('/edp/projects', method='POST', body=json.dumps(request),
                           type='application/json', user=user)
        assertStatus(r, 201)
        projects.append(r.json)

        return  r.json
Example #6
0
    def _make_postmortem(user, project, request):
        r = server.request('/edp/projects/%s/postmortems' % project['_id'], method='POST', body=json.dumps(request),
                           type='application/json', user=user)
        assertStatus(r, 201)
        postmortems.append(r.json)

        return  r.json
Example #7
0
def testTokenSessionDeletion(server, token):
    # With the token should succeed
    resp = server.request(path='/token/session', method='DELETE', token=token)
    assertStatusOk(resp)
    # Now the token is gone, so it should fail
    resp = server.request(path='/token/session', method='DELETE', token=token)
    assertStatus(resp, 401)
Example #8
0
def testDisableApiKeysSetting(server, user):
    errMsg = 'API key functionality is disabled on this instance.'

    resp = server.request('/api_key', method='POST', user=user, params={
        'name': 'test key'
    })
    assertStatusOk(resp)

    # Disable API keys
    Setting().set(SettingKey.API_KEYS, False)

    # Key should still exist
    key = ApiKey().load(resp.json['_id'], force=True, exc=True)

    # No longer possible to authenticate with existing key
    resp = server.request('/api_key/token', method='POST', params={
        'key': key['key']
    })
    assertStatus(resp, 400)
    assert resp.json['message'] == errMsg

    # No longer possible to create new keys
    resp = server.request('/api_key', method='POST', user=user, params={
        'name': 'should not work'
    })
    assertStatus(resp, 400)
    assert resp.json['message'] == errMsg

    # Still possible to delete key
    resp = server.request('/api_key/%s' % key['_id'], method='DELETE', user=user)
    assertStatusOk(resp)
    assert ApiKey().load(key['_id'], force=True) is None
Example #9
0
def testUserCannotAccessOtherApiKeys(server, admin, user):
    # Normal users shouldn't be able to request other users' keys
    resp = server.request('/api_key',
                          params={'userId': admin['_id']},
                          user=user)
    assertStatus(resp, 403)
    assert resp.json['message'] == 'Administrator access required.'
Example #10
0
def testGetResourcePathForUser(server, parentChain, user):
    # Test access denied response for access 'hidden folder' for user without access rights
    resp = server.request(path='/resource/%s/path' %
                          parentChain['folder4']['_id'],
                          method='GET',
                          user=user,
                          params={'type': 'folder'})
    assertStatus(resp, 403)
Example #11
0
    def _make_batch(user, project, cycle, request):
        r = server.request('/edp/projects/%s/cycles/%s/batches' % (
                project['_id'], cycle['_id']), method='POST', body=json.dumps(request),
                type='application/json', user=user)
        assertStatus(r, 201)
        batches.append(r.json)

        return  r.json
Example #12
0
def test_create_dandiset_no_name(server, request_auth):
    resp = server.request(
        path=path,
        method="POST",
        params={"description": DESCRIPTION_1},
        **request_auth,
    )
    assertStatus(resp, 400)
Example #13
0
def testGetResourcePathForNoneUser(server, parentChain):
    # Test access denied response for access 'hidden folder' for a none User
    resp = server.request(path='/resource/%s/path' %
                          parentChain['folder4']['_id'],
                          method='GET',
                          user=None,
                          params={'type': 'folder'})
    assertStatus(resp, 401)
def testFolderPositionUserNoAccess(server, makeResources, user):
    resp = server.request(
        '/folder/%s/position' % str(makeResources['folders'][7]['_id']),
        user=user,
        params={
            'parentType': 'folder',
            'parentId': str(makeResources['publicFolder']['_id'])
        })
    assertStatus(resp, 403)
Example #15
0
def testMoveFolderUnderItselfFails(server, admin, hierarchy):
    resp = server.request(
        path='/folder/%s' % hierarchy.folders[0]['_id'], method='PUT',
        user=admin, params={
            'parentId': hierarchy.folders[1]['_id'],
            'parentType': 'folder'
        })
    assertStatus(resp, 400)
    assert resp.json['message'] == 'You may not move a folder underneath itself.'
Example #16
0
def testNoReadme(server, admin, privateFolder):
    # Verify that the readme endpoint returns 204 No Content when there is no README
    resp = server.request(
        path=f'/folder/{privateFolder["_id"]}/readme',
        method='GET',
        user=admin,
        isJson=False,
    )
    assertStatus(resp, 204)
Example #17
0
def testLoadModelDecorator(server, user):
    resp = server.request(
        path='/accesstest/test_loadmodel_plain/%s' % user['_id'], method='GET')
    assertStatusOk(resp)
    assert resp.json['_id'] == str(user['_id'])

    resp = server.request(path='/accesstest/test_loadmodel_query', params={'userId': None})
    assertStatus(resp, 400)
    assert resp.json['message'] == 'Invalid ObjectId: None'
def testDuplicateParameters(server, method):
    # In addition to a dict, the urllib.parse.urlencode used by server.request can accept a list
    # of tuples
    params = [('foo', 'bar'), ('foo', 'baz')]
    # Use /system/setting because it has both GET and PUT endpoints
    path = '/system/version'
    resp = server.request(path=path, method=method, params=params)
    assertStatus(resp, 400)
    assert resp.json['message'] == 'Parameter "foo" must not be specified multiple times.'
Example #19
0
def testServerInfoInErrorPage(server):
    # For security, we want to ensure cherrypy does not appear in server info
    resp = server.request('/girder/api/v1', prefix='', isJson=False)
    assertStatus(resp, 404)
    body = getResponseBody(resp).lower()
    server = resp.headers['Server'].lower()
    assert 'cherrypy' not in body + server
    assert 'girder' in body
    assert 'girder' in server
def test_create_dandiset_empty_description(server, request_auth):
    resp = server.request(path=path,
                          method="POST",
                          params={
                              "name": NAME_1,
                              "description": ""
                          },
                          **request_auth)
    assertStatus(resp, 400)
Example #21
0
def testServerInfoInErrorPage(server):
    # For security, we want to ensure cherrypy does not appear in server info
    resp = server.request('/girder/api/v1', prefix='', isJson=False)
    assertStatus(resp, 404)
    body = getResponseBody(resp).lower()
    server = resp.headers['Server'].lower()
    assert 'cherrypy' not in body + server
    assert 'girder' in body
    assert 'girder' in server
def testExceptionHandlingBasedOnServerMode(exceptionServer, uuidMock, mode, msg, hasTrace):
    with serverMode(mode):
        resp = exceptionServer.request('/item/exception', exception=True)

    assertStatus(resp, 500)
    assert resp.json['message'] == msg
    assert resp.json['type'] == 'internal'
    assert resp.json['uid'] == uuidMock
    assert ('trace' in resp.json) is hasTrace
    assert resp.headers['Girder-Request-Uid'] == uuidMock
def testExceptionHandlingBasedOnServerMode(exceptionServer, uuidMock, mode, msg, hasTrace):
    with serverMode(mode):
        resp = exceptionServer.request('/item/exception', exception=True)

    assertStatus(resp, 500)
    assert resp.json['message'] == msg
    assert resp.json['type'] == 'internal'
    assert resp.json['uid'] == uuidMock
    assert ('trace' in resp.json) is hasTrace
    assert resp.headers['Girder-Request-Uid'] == uuidMock
Example #24
0
    def deleteImage(self,
                    name,
                    responseCodeOK,
                    deleteDockerImage=False,
                    status=4):
        """
        Delete docker image data and test whether a docker
        image can be deleted off the local machine
        """
        job_status = [JobStatus.SUCCESS]
        if deleteDockerImage:
            event = threading.Event()

            def tempListener(self, girderEvent):
                job = girderEvent.info['job']

                if (job['type'] == 'slicer_cli_web_job' and job['status']
                        in (JobStatus.SUCCESS, JobStatus.ERROR)):
                    assert job[
                        'status'] == status, 'The status of the job should match'
                    events.unbind('jobs.job.update.after',
                                  'slicer_cli_web_del')
                    job_status[0] = job['status']
                    event.set()

            self.delHandler = types.MethodType(tempListener, self)

            events.bind('jobs.job.update.after', 'slicer_cli_web_del',
                        self.delHandler)

        resp = self.server.request(path='/slicer_cli_web/docker_image',
                                   user=self.admin,
                                   method='DELETE',
                                   params={
                                       'name': json.dumps(name),
                                       'delete_from_local_repo':
                                       deleteDockerImage
                                   },
                                   isJson=False)
        if responseCodeOK:
            assertStatus(resp, 200)
        else:
            assertStatus(resp, 400)
            # A status ok or code 200 should not have been recieved for
            # deleting the image %s' % str(name))

        if deleteDockerImage:
            if not event.wait(TIMEOUT):
                del self.delHandler
                raise AssertionError('deleting the docker image is taking '
                                     'longer than %d seconds' % TIMEOUT)
            else:
                del self.delHandler
                assert job_status[
                    0] == status, 'The status of the job should match '
def testWorkerDifferentTask(server, models):
    # Test the settings
    resp = server.request('/system/setting', method='PUT', params={
        'key': PluginSettings.API_URL,
        'value': 'bad value'
    }, user=models['admin'])
    assertStatus(resp, 400)
    assert resp.json['message'] == 'API URL must start with http:// or https://.'

    resp = server.request('/system/setting', method='PUT', params={
        'list': json.dumps([{
            'key': PluginSettings.BROKER,
            'value': 'amqp://[email protected]'
        }, {
            'key': PluginSettings.BACKEND,
            'value': 'amqp://[email protected]'
        }])
    }, user=models['admin'])
    assertStatusOk(resp)

    # Create a job to be handled by the worker plugin
    jobModel = Job()
    job = jobModel.createJob(
        title='title', type='foo', handler='worker_handler',
        user=models['admin'], public=False, args=(), kwargs={},
        otherFields={
            'celeryTaskName': 'some_other.task',
            'celeryQueue': 'my_other_q'
        })

    job['kwargs'] = {
        'jobInfo': utils.jobInfoSpec(job),
        'inputs': [
            utils.girderInputSpec(models['adminFolder'], resourceType='folder')
        ],
        'outputs': [
            utils.girderOutputSpec(models['adminFolder'], token=models['adminToken'])
        ]
    }
    job = jobModel.save(job)

    # Schedule the job, make sure it is sent to celery
    app = celery.getCeleryApp()
    with mock.patch.object(app, 'send_task') as sendTask:
        sendTask.return_value = FakeAsyncResult()

        jobModel.scheduleJob(job)

        sendTaskCalls = sendTask.mock_calls
        assert len(sendTaskCalls) == 1
        assert sendTaskCalls[0][1] == (
            'some_other.task', job['args'], job['kwargs'])
        assert 'queue' in sendTaskCalls[0][2]
        assert sendTaskCalls[0][2]['queue'] == 'my_other_q'
Example #26
0
    def addImage(self, name, status, initialStatus=200):
        """
        Test the put endpoint.

        :param name: a string or a list of strings
        :param status: either JobStatus.SUCCESS or JobStatus.ERROR.
        :param initialStatus: 200 if the job should run, otherwise a HTTP error
            code expected if the job will fail.
        """
        event = threading.Event()
        job_status = [JobStatus.SUCCESS]

        def tempListener(self, girderEvent):
            job = girderEvent.info['job']

            if (job['type'] == 'slicer_cli_web_job'
                    and job['status'] in (JobStatus.SUCCESS, JobStatus.ERROR)):
                assert job[
                    'status'] == status, 'The status of the job should match'
                job_status[0] = job['status']

                events.unbind('jobs.job.update.after', 'slicer_cli_web_add')

                # wait 10sec before continue
                threading.Timer(5, lambda: event.set()).start()

        if initialStatus == 200:
            self.addHandler = types.MethodType(tempListener, self)

            events.bind('jobs.job.update.after', 'slicer_cli_web_add',
                        self.addHandler)

        resp = self.server.request(path='/slicer_cli_web/docker_image',
                                   user=self.admin,
                                   method='PUT',
                                   params={
                                       'name': json.dumps(name),
                                       'folder': self.folder['_id']
                                   },
                                   isJson=initialStatus == 200)

        assertStatus(resp, initialStatus)
        if initialStatus != 200:
            return
        # We should have a job ID
        assert resp.json.get('_id') is not None

        if not event.wait(TIMEOUT):
            del self.addHandler
            raise AssertionError('adding the docker image is taking '
                                 'longer than %d seconds' % TIMEOUT)
        else:
            del self.addHandler
            job_status[0] == status, 'The status of the job should match '
Example #27
0
def testMoveFolderUnderItselfFails(server, admin, hierarchy):
    resp = server.request(path='/folder/%s' % hierarchy.folders[0]['_id'],
                          method='PUT',
                          user=admin,
                          params={
                              'parentId': hierarchy.folders[1]['_id'],
                              'parentType': 'folder'
                          })
    assertStatus(resp, 400)
    assert resp.json[
        'message'] == 'You may not move a folder underneath itself.'
Example #28
0
def testLoadModelDecorator(server, user):
    resp = server.request(path='/accesstest/test_loadmodel_plain/%s' %
                          user['_id'],
                          method='GET')
    assertStatusOk(resp)
    assert resp.json['_id'] == str(user['_id'])

    resp = server.request(path='/accesstest/test_loadmodel_query',
                          params={'userId': None})
    assertStatus(resp, 400)
    assert resp.json['message'] == 'Invalid ObjectId: None'
Example #29
0
def cycletest(server, user, project, cycle, batch, create_cycletest_request):
    from girder.plugins.edp.models.cycletest import CycleTest

    r = server.request('/edp/projects/%s/cycles/%s/batches/%s/tests' % (
            project['_id'], cycle['_id'], batch['_id']),
            method='POST', body=json.dumps(create_cycletest_request),
            type='application/json', user=user)
    assertStatus(r, 201)

    yield r.json

    CycleTest().remove(r.json, user)
Example #30
0
def test_update_non_existent(server, user, project):
    from girder.plugins.edp.models.project import Project

    updates = {
        'title': 'Nothing to see here.'
    }

    non_existent = '5ae71e1ff657102b11ce2233'
    r = server.request('/edp/projects/%s' % non_existent,
                       method='PATCH', body=json.dumps(updates),
                       type='application/json', user=user)
    assertStatus(r, 400)
Example #31
0
def postmortemtest(server, user, project, postmortem, create_postmortemtest_request):
    from girder.plugins.edp.models.postmortemtest import PostmortemTest

    r = server.request('/edp/projects/%s/postmortems/%s/tests' % (
            project['_id'], postmortem['_id']),
            method='POST', body=json.dumps(create_postmortemtest_request),
            type='application/json', user=user)
    assertStatus(r, 201)

    yield r.json

    PostmortemTest().remove(r.json, user)
Example #32
0
def test_create_public(server, user, project_request):
    from girder.plugins.edp.models.project import Project

    r = server.request('/edp/projects', method='POST', body=json.dumps(project_request),
                       type='application/json', user=user)
    assertStatus(r, 201)

    assert '_id' in r.json

    project = Project().load(r.json['_id'], force=True)
    assert project['owner'] == user['_id']
    assert project_request.items() <= project.items()
Example #33
0
def testGetResourceByPathForUser(server, parentChain, admin, user):
    # Test access denied response for access 'hidden folder' for user without access rights
    resp = server.request(path='/resource/lookup',
                          method='GET', user=user,
                          params={
                              'path': '/user/%s/%s/%s/%s/%s' % (
                                  admin['login'],
                                  parentChain['folder1']['name'],
                                  parentChain['folder2']['name'],
                                  parentChain['privateFolder']['name'],
                                  parentChain['folder4']['name'])
                          })
    assertStatus(resp, 400)
def testDirectPathSettingValidation(server, models):
    # Test the setting
    resp = server.request('/system/setting', method='PUT', params={
        'key': PluginSettings.DIRECT_PATH,
        'value': 'bad value'
    }, user=models['admin'])
    assertStatus(resp, 400)
    assert resp.json['message'] == 'The direct path setting must be true or false.'
    resp = server.request('/system/setting', method='PUT', params={
        'key': PluginSettings.DIRECT_PATH,
        'value': 'false'
    }, user=models['admin'])
    assertStatusOk(resp)
Example #35
0
def test_update_non_existent(server, user, project, cycle, batch):
    from girder.plugins.edp.models.batch import Batch

    updates = {'title': 'Nothing to see here.', 'dataNotes': 'Notes'}

    non_existent = '5ae71e1ff657102b11ce2233'
    r = server.request('/edp/projects/%s/cycles/%s/batches/%s' %
                       (project['_id'], cycle['_id'], non_existent),
                       method='PATCH',
                       body=json.dumps(updates),
                       type='application/json',
                       user=user)
    assertStatus(r, 400)
Example #36
0
def testDockerAddBadParam(server, admin, folder):
    # test sending bad parameters to the PUT endpoint
    kwargs = {
        'path': '/slicer_cli_web/docker_image',
        'user': admin,
        'method': 'PUT',
        'params': {
            'name': json.dumps(6),
            'folder': folder['_id']
        }
    }
    resp = server.request(**kwargs)
    assertStatus(resp, 400)
    assert 'A valid string' in resp.json['message']

    kwargs['params']['name'] = json.dumps({'abc': 'def'})
    resp = server.request(**kwargs)
    assertStatus(resp, 400)
    assert 'A valid string' in resp.json['message']

    kwargs['params']['name'] = json.dumps([6])
    resp = server.request(**kwargs)
    assertStatus(resp, 400)
    assert 'is not a valid string' in resp.json['message']

    kwargs['params']['name'] = '"not json'
    resp = server.request(**kwargs)
    assertStatus(resp, 400)
    assert 'does not have a tag' in resp.json['message']
Example #37
0
def testInactiveKeysCannotCreateTokens(server, user, apiKey):
    newScopes = [TokenScope.DATA_READ, TokenScope.DATA_WRITE]
    resp = server.request('/api_key/%s' % apiKey['_id'], params={
        'active': False,
        'tokenDuration': 10,
        'scope': json.dumps(newScopes)
    }, method='PUT', user=user)
    assertStatusOk(resp)

    # We should not be able to create tokens for this key anymore
    resp = server.request('/api_key/token', method='POST', params={
        'key': apiKey['key']
    })
    assertStatus(resp, 400)
    assert resp.json['message'] == 'Invalid API key.'
def test_create_calc(server, molecule, user):
    from girder.plugins.molecules.models.calculation import Calculation
    from girder.constants import AccessType

    assert '_id' in molecule

    dir_path = os.path.dirname(os.path.realpath(__file__))

    # This cjson should match the molecule
    with open(dir_path + '/data/ethane.cjson', 'r') as rf:
        ethane_cjson = rf.read()

    # Let's make some properties
    properties = {
        'molecular mass': 30.0690,
        'melting point': -172,
        'boiling point': -88,
        'code': 'nwchem'
    }

    body = {
        'cjson': ethane_cjson,
        'properties': properties,
        'moleculeId': molecule['_id']
    }

    r = server.request('/calculations', method='POST', body=json.dumps(body),
                       type='application/json', user=user)
    assertStatus(r, 201)

    calc = r.json

    assert '_id' in calc
    assert 'moleculeId' in calc
    calc_id = str(calc['_id'])
    molecule_id = calc['moleculeId']

    calc2 = Calculation().load(calc_id, level=AccessType.READ, user=user)

    # It should have an _id and a molecule id, and it should match
    assert '_id' in calc2
    assert 'moleculeId' in calc2

    assert str(calc2['_id']) == calc_id
    assert str(calc2['moleculeId']) == molecule_id
def test_ingest_pending(server, molecule, user, make_girder_file, fsAssetstore):
    body = {
        'moleculeId': molecule['_id'],
        'cjson': None,
        'public': True,
        'properties': {
            'calculationTypes': 'energy;',
            'basisSet': {
                'name': '3-21g'
            },
            'theory': 'b3lyp',
            'pending': True,
            'code': 'nwchem'
        }
    }

    # First create pending calculation
    r = server.request('/calculations', method='POST', type='application/json',
                       body=json.dumps(body), user=user)
    assertStatus(r, 201)
    calculation = r.json

    # Upload simulation result
    dir_path = os.path.dirname(os.path.realpath(__file__))

    with open(os.path.join(dir_path, 'data', 'ethane.cjson')) as f:
        file = make_girder_file(fsAssetstore, user, 'ethane.cjson', contents=f.read().encode())

    # Now we can test the ingest
    body = {
        'fileId': str(file['_id']),
        'format': 'cjson',
        'public': True
    }

    r = server.request('/calculations/%s' % calculation['_id'], method='PUT', type='application/json',
                       body=json.dumps(body), user=user)
    assertStatusOk(r)
    calculation = r.json

    assert 'pending' not in calculation['properties']
Example #40
0
def testRequiredScopeExists(server, user):
    token = Token().createToken(scope=CUSTOM_SCOPE)

    resp = server.request(path='/accesstest/test_required_scope_exists')
    # If not given a user or a valid auth token the status should be 401
    assertStatus(resp, 401)

    resp2 = server.request(path='/accesstest/test_required_scope_exists',
                           user=user)
    # If the token does not have the CUSTOM_SCOPE the status should be 403
    assertStatus(resp2, 403)

    # If user is not given but the token has the correct scope
    # the status should be 200
    resp3 = server.request(path='/accesstest/test_required_scope_exists',
                           token=token)

    assertStatus(resp3, 200)
Example #41
0
def testCookieAuthFailsOnPost(server, user, cookie):
    resp = server.request(path='/accesstest/cookie_auth',
                          method='POST', cookie=cookie)
    assertStatus(resp, 401)
Example #42
0
def testUserCannotAccessOtherApiKeys(server, admin, user):
    # Normal users shouldn't be able to request other users' keys
    resp = server.request('/api_key', params={'userId': admin['_id']},
                          user=user)
    assertStatus(resp, 403)
    assert resp.json['message'] == 'Administrator access required.'
Example #43
0
def testOtpApiWorkflow(server, user):
    # Try to finalize OTP before it's been initialized
    resp = server.request(
        path='/user/%s/otp' % user['_id'], method='PUT', user=user,
        additionalHeaders=[('Girder-OTP', '123456')])
    # This should fail cleanly
    assertStatus(resp, 400)
    assert 'not initialized' in resp.json['message']

    # Try to disable OTP before it's been enabled
    resp = server.request(path='/user/%s/otp' % user['_id'], method='DELETE', user=user)
    # This should fail cleanly
    assertStatus(resp, 400)
    assert 'not enabled' in resp.json['message']

    # Initialize OTP
    resp = server.request(path='/user/%s/otp' % user['_id'], method='POST', user=user)
    assertStatusOk(resp)
    # Save the URI
    totpUri = resp.json['totpUri']

    # Test the logic for server hostname as OTP URI issuer
    assert 'issuer=127.0.0.1' in totpUri

    # Login without an OTP
    resp = server.request(path='/user/authentication', method='GET', basicAuth='user:password')
    # Since OTP has not been finalized, this should still succeed
    assertStatusOk(resp)

    # Finalize without an OTP
    resp = server.request(
        path='/user/%s/otp' % user['_id'], method='PUT', user=user)
    assertStatus(resp, 400)
    assert 'Girder-OTP' in resp.json['message']

    # Finalize with an invalid OTP
    resp = server.request(
        path='/user/%s/otp' % user['_id'], method='PUT', user=user,
        additionalHeaders=[('Girder-OTP', _tokenFromTotpUri(totpUri, False))])
    assertStatus(resp, 403)
    assert 'validation failed' in resp.json['message']

    # Finalize with a valid OTP
    resp = server.request(
        path='/user/%s/otp' % user['_id'], method='PUT', user=user,
        additionalHeaders=[('Girder-OTP', _tokenFromTotpUri(totpUri))])
    assertStatusOk(resp)

    # The valid token from this time period was used to finalize OTP; to prevent having to wait for
    # the next time period, flush the rateLimitBuffer
    from girder.utility._cache import rateLimitBuffer
    rateLimitBuffer.invalidate()

    # Login without an OTP
    resp = server.request(path='/user/authentication', method='GET', basicAuth='user:password')
    assertStatus(resp, 401)
    assert 'Girder-OTP' in resp.json['message']

    # Login with an invalid OTP
    resp = server.request(
        path='/user/authentication', method='GET', basicAuth='user:password',
        additionalHeaders=[('Girder-OTP', _tokenFromTotpUri(totpUri, False))])
    assertStatus(resp, 401)
    assert 'Token did not match' in resp.json['message']

    # Login with a valid OTP
    resp = server.request(
        path='/user/authentication', method='GET', basicAuth='user:password',
        additionalHeaders=[('Girder-OTP', _tokenFromTotpUri(totpUri))])
    assertStatusOk(resp)

    # Disable OTP
    resp = server.request(path='/user/%s/otp' % user['_id'], method='DELETE', user=user)
    assertStatusOk(resp)
Example #44
0
def testInviteNewUser(provisionedServer, smtp):
    # Create a study admin user
    resp = provisionedServer.request(path='/user', method='POST', params={
        'email': '*****@*****.**',
        'login': '******',
        'firstName': 'study admin',
        'lastName': 'user',
        'password': '******'
    })
    assertStatusOk(resp)
    studyAdminUser = User().findOne({'login': '******'})
    assert studyAdminUser is not None

    # Ensure that user doesn't have permission to invite a new user, yet
    resp = provisionedServer.request(path='/user/invite', method='POST', params={
        'login': '******',
        'email': '*****@*****.**',
        'firstName': 'invited',
        'lastName': 'user'
    }, user=studyAdminUser)
    assertStatus(resp, 403)

    # Add the user to the study admins group
    studyAdminsGroup = Group().findOne({'name': 'Study Administrators'})
    assert studyAdminsGroup is not None
    Group().addUser(studyAdminsGroup, studyAdminUser, level=AccessType.READ)

    # Ensure that user can invite a new user
    resp = provisionedServer.request(path='/user/invite', method='POST', params={
        'login': '******',
        'email': '*****@*****.**',
        'firstName': 'invited',
        'lastName': 'user'
    }, user=studyAdminUser)
    assertStatusOk(resp)
    assert 'newUser' in resp.json
    assert 'inviteUrl' in resp.json
    for key in ('login', 'firstName', 'lastName', 'name'):
        assert key in resp.json['newUser']

    assert resp.json['newUser']['login'] == 'invited-user'
    assert resp.json['newUser']['firstName'] == 'invited'
    assert resp.json['newUser']['lastName'] == 'user'
    assert resp.json['newUser']['name']
    assert resp.json['inviteUrl']

    assert smtp.waitForMail()
    assert smtp.getMail()  # pop off the queue for later assertion that the queue is empty

    # Ensure that user can invite a new user and specify the validity period
    resp = provisionedServer.request(path='/user/invite', method='POST', params={
        'login': '******',
        'email': '*****@*****.**',
        'firstName': 'invited',
        'lastName': 'user2',
        'validityPeriod': 15.0
    }, user=studyAdminUser)
    assertStatusOk(resp)
    assert 'newUser' in resp.json
    assert 'inviteUrl' in resp.json
    for key in ('login', 'firstName', 'lastName', 'name'):
        assert key in resp.json['newUser']
    assert resp.json['newUser']['login'] == 'invited-user2'
    assert resp.json['newUser']['firstName'] == 'invited'
    assert resp.json['newUser']['lastName'] == 'user2'
    assert resp.json['newUser']['name']
    assert resp.json['inviteUrl']

    assert smtp.waitForMail()
    assert smtp.getMail()  # pop off the queue for later assertion that the queue is empty

    # Test sending an invalid value for the validity period
    resp = provisionedServer.request(path='/user/invite', method='POST', params={
        'login': '******',
        'email': '*****@*****.**',
        'firstName': 'invited',
        'lastName': 'user3',
        'validityPeriod': 'invalid'
    }, user=studyAdminUser)
    assertStatus(resp, 400)
    assert resp.json['type'] == 'validation'
    assert resp.json.get('field') == 'validityPeriod'
Example #45
0
def testBasicUser(provisionedServer):
    # Create a basic user
    resp = provisionedServer.request(path='/user', method='POST', params={
        'email': '*****@*****.**',
        'login': '******',
        'firstName': 'test',
        'lastName': 'user',
        'password': '******'
    })
    assertStatusOk(resp)
    testUser = User().findOne({'login': '******'})
    assert testUser is not None

    # Ensure creation returns permissions
    negativePermissions = {
        'acceptTerms': False,
        'createDataset': False,
        'reviewDataset': False,
        'segmentationSkill': None,
        'adminStudy': False
    }
    assert resp.json.get('permissions') == negativePermissions

    # Ensure login returns permissions
    resp = provisionedServer.request(path='/user/authentication', method='GET',
                                     basicAuth='test-user:password')
    assertStatusOk(resp)
    assert resp.json['user'].get('permissions') == negativePermissions

    # Ensure get user returns permissions
    resp = provisionedServer.request(path='/user/me', method='GET', user=testUser)
    assertStatusOk(resp)
    assert resp.json.get('permissions') == negativePermissions

    # Ensure get user for anonymous still succeeds
    resp = provisionedServer.request(path='/user/me', method='GET')
    assertStatusOk(resp)
    assert resp.json is None

    # Ensure user is private
    resp = provisionedServer.request(path='/user/%s' % testUser['_id'], method='GET')
    assertStatus(resp, 401)

    # Ensure accept terms works
    resp = provisionedServer.request(path='/user/acceptTerms', method='POST',
                                     user=testUser)
    assertStatusOk(resp)
    assert resp.json.get('extra') == 'hasPermission'

    resp = provisionedServer.request(path='/user/me', method='GET', user=testUser)
    assertStatusOk(resp)
    acceptedTermsPermissions = negativePermissions.copy()
    acceptedTermsPermissions['acceptTerms'] = True
    assert resp.json.get('permissions') == acceptedTermsPermissions

    # Ensure accepting terms twice is idempotent
    testUser = User().findOne({'login': '******'})
    uploaderUserAcceptTermsTime = testUser['acceptTerms']
    resp = provisionedServer.request(path='/user/acceptTerms', method='POST',
                                     user=testUser)
    assertStatusOk(resp)
    assert resp.json.get('extra') == 'hasPermission'
    testUser = User().findOne({'login': '******'})
    assert testUser['acceptTerms'] == uploaderUserAcceptTermsTime
Example #46
0
def testUserCannotAccessAdminEndpoints(server, user, endpoint):
    resp = server.request(path=endpoint, method='GET', user=user)
    assertStatus(resp, 403)
Example #47
0
def testTokenSessionDeletionFailsWithoutToken(server):
    # Trying to delete a token without specifying one results in an error
    resp = server.request(path='/token/session', method='DELETE')
    assertStatus(resp, 401)
Example #48
0
def testUserAccessToken(server, userDataReadToken):
    resp = server.request(path='/accesstest/user_access', token=userDataReadToken)
    assertStatus(resp, 401)
Example #49
0
def testAdminRawDecoratorIsEquivalentToReturnedDecorator(server, adminSettingToken, endpoint):
    resp = server.request(path=endpoint, token=adminSettingToken)
    assertStatus(resp, 401)
Example #50
0
def testReadingAssetstoreWithSettingScopedToken(server, adminSettingToken):
    # The setting-scope token should not grant access to other endpoints
    resp = server.request(path='/assetstore', token=adminSettingToken)
    assertStatus(resp, 401)
Example #51
0
def testReadingSettingsWithUserToken(server, userSettingToken):
    # Non-admin user with this token scope should still not work
    resp = server.request(path='/system/setting', params={
        'key': SettingKey.SMTP_PORT}, token=userSettingToken)
    assertStatus(resp, 403)
    assert resp.json['message'] == 'Administrator access required.'
Example #52
0
def testReadingSettingsWithAdminEmailToken(server, adminEmailToken):
    # Reading settings with an improperly scoped token should fail
    resp = server.request(path='/system/setting', params={
        'key': SettingKey.SMTP_PORT}, token=adminEmailToken)
    assertStatus(resp, 401)
Example #53
0
def testCookieAuthFailsWithNoAuth(server, endpoint, method):
    resp = server.request(path='/accesstest/%s' % endpoint,
                          method=method)
    assertStatus(resp, 401)
Example #54
0
def testPublicCannotAccessNonPublicEndpoints(server, endpoint):
    resp = server.request(path=endpoint, method='GET')
    assertStatus(resp, 401)
Example #55
0
def testListNotificationsAuthError(server):
    resp = server.request(path='/notification')
    assertStatus(resp, 401)
Example #56
0
def testApiRedirect(server):
    resp = server.request('/api', prefix='', isJson=False)
    assertStatus(resp, 303)
    assert urlparse(resp.headers['Location']).path == '/api/v1'
Example #57
0
def testReadingSettingsAsUserShouldFail(server, user):
    # Reading setting as non-admin should fail
    resp = server.request(path='/system/setting', params={
        'key': SettingKey.SMTP_PORT}, user=user)
    assertStatus(resp, 403)
Example #58
0
def testCookieAuthFailsWithNoAuth(server, method):
    resp = server.request(path='/accesstest/cookie_auth', method=method)
    assertStatus(resp, 401)