def test_get_dandiset_stats_one_item(server, dandiset_1, request_auth): dandi_id = dandiset_1["_id"] identifier = dandiset_1["name"] mkitem(server, request_auth, "Test Item", dandi_id) resp = server.request(f"/dandi/{identifier}/stats", method="GET") assertStatusOk(resp) assert {"bytes": 0, "folders": 0, "items": 1} == resp.json
def testReviewerUser(provisionedServer): # Create a reviewer user resp = provisionedServer.request(path='/user', method='POST', params={ 'email': '*****@*****.**', 'login': '******', 'firstName': 'reviewer', 'lastName': 'user', 'password': '******' }) assertStatusOk(resp) reviewerUser = User().findOne({'login': '******'}) assert reviewerUser is not None # Add the user to the reviewers group reviewersGroup = Group().findOne({'name': 'Dataset QC Reviewers'}) assert reviewersGroup is not None Group().addUser(reviewersGroup, reviewerUser, level=AccessType.READ) # Ensure they can review datasets resp = provisionedServer.request(path='/user/me', method='GET', user=reviewerUser) assertStatusOk(resp) assert resp.json['permissions']['reviewDataset']
def testStudyAdminUser(provisionedServer): # 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 # 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 they can admin studies resp = provisionedServer.request(path='/user/me', method='GET', user=studyAdminUser) assertStatusOk(resp) assert resp.json['permissions']['adminStudy']
def test_get(server, user, admin, project, postmortem): r = server.request('/edp/projects/%s/postmortems/%s' % (project['_id'], postmortem['_id']), method='GET', user=user) assertStatusOk(r) assert postmortem.items() <= r.json.items()
def testListNotificationsSinceTime(server, user, notifications): resp = server.request(path='/notification', user=user, params={'since': SINCE.isoformat()}) assertStatusOk(resp) assert len(resp.json) == 1 assert resp.json[0]['_id'] == str(notifications[0]['_id'])
def testReadingSettingsAsAdmin(server, admin): # Reading settings as admin should work resp = server.request(path='/system/setting', params={'key': SettingKey.SMTP_PORT}, user=admin) assertStatusOk(resp) assert resp.json == 25
def test_get_dandiset_stats_tree(server, dandiset_1, request_auth, fsAssetstore): # noqa: N803 dandi_id = dandiset_1["_id"] identifier = dandiset_1["name"] folder_a_id = mkfolder(server, request_auth, "Folder A", dandi_id) folder_b_id = mkfolder(server, request_auth, "Folder B", folder_a_id) folder_c_id = mkfolder(server, request_auth, "Folder C", folder_b_id) # noqa: F841 folder_d_id = mkfolder(server, request_auth, "Folder D", folder_b_id) item_a_id = mkitem(server, request_auth, "Item A", dandi_id) item_b_id = mkitem(server, request_auth, "Item B", folder_a_id) item_c_id = mkitem(server, request_auth, "Item C", folder_d_id) # noqa: F841 contents = [ "This is test text.", "Lorem ipsum dolor sit amet", "'Twas brillig, and the slithy toves did gyre and gimble in the wabe.", ] mkfile(server, request_auth, "test.txt", item_a_id, contents[0]) mkfile(server, request_auth, "lorem.txt", item_b_id, contents[1]) mkfile(server, request_auth, "jabberwocky.txt", item_b_id, contents[2]) resp = server.request(f"/dandi/{identifier}/stats", method="GET") assertStatusOk(resp) assert { "bytes": len("".join(contents)), "folders": 4, "items": 3 } == resp.json
def test_find(server, user, project, cycle, batch): r = server.request('/edp/projects/%s/cycles/%s/batches' % (project['_id'], cycle['_id']), method='GET', user=user) assertStatusOk(r) assert len(r.json) == 1
def testReadingSettingsWithAdminScopedToken(server, adminSettingToken): # Reading settings with a properly scoped token should work resp = server.request(path='/system/setting', params={'key': SettingKey.SMTP_PORT}, token=adminSettingToken) assertStatusOk(resp) assert resp.json == 25
def test_get_molecule_inchikey(server, molecule, user): molecule = molecule(user) # The molecule will have been created by the fixture assert '_id' in molecule assert 'inchi' in molecule assert 'inchikey' in molecule assert 'smiles' in molecule # This one is not essential, but we set it ourselves assert 'name' in molecule _id = molecule['_id'] inchi = molecule['inchi'] inchikey = molecule['inchikey'] smiles = molecule['smiles'] name = molecule['name'] # Find the molecule by its inchikey r = server.request('/molecules/inchikey/%s' % inchikey, method='GET', user=user) assertStatusOk(r) mol = r.json assert mol.get('_id') == _id assert mol.get('inchi') == inchi assert mol.get('inchikey') == inchikey assert mol.get('smiles') == smiles assert mol.get('name') == name
def testWorkerStatusEndpoint(server, models): # Create a job to be handled by the worker plugin job = Job().createJob( title='title', type='foo', handler='worker_handler', user=models['admin'], public=False, args=(), kwargs={}) job['kwargs'] = { 'jobInfo': utils.jobInfoSpec(job), 'inputs': [ utils.girderInputSpec(models['adminFolder'], resourceType='folder') ], 'outputs': [ utils.girderOutputSpec(models['adminFolder'], token=models['adminToken']) ] } job = Job().save(job) assert job['status'] == JobStatus.INACTIVE # Schedule the job with mock.patch('celery.Celery') as celeryMock: instance = celeryMock.return_value instance.send_task.return_value = FakeAsyncResult() Job().scheduleJob(job) # Call the worker status endpoint resp = server.request('/worker/status', method='GET', user=models['admin']) assertStatusOk(resp) for key in ['report', 'stats', 'ping', 'active', 'reserved']: assert key in resp.json
def endpointsExist(self, name, present=None, absent=None): """ Test if endpoints for particular image exist. :param name: name of the image used to determine endpoint location. :param present: a list of endpoints within the image that must exist. :param absent: a list of endpoints that should be in the image but not have endpoints. """ present = present or [] absent = absent or [] userAndRepo, tag = splitName(name) data = self.getEndpoint() for cli in present: self.assertHasKeys(data, [userAndRepo]) self.assertHasKeys(data[userAndRepo], [tag]) self.assertHasKeys(data[userAndRepo][tag], [cli]) path = data[userAndRepo][tag][cli]['xmlspec'] resp = self.server.request(path=path, user=self.admin, isJson=False) assertStatusOk(resp) for cli in absent: self.assertHasKeys(data, [userAndRepo]) self.assertHasKeys(data[userAndRepo], [tag]) self.assertNotHasKeys(data[userAndRepo][tag], [cli])
def multi_owner_dandiset(server, admin, user): resp = server.request( path="/dandi", method="POST", user=admin, params={ "name": "multi_owner_dandiset", "description": "Dandiset that has multiple owners.", }, ) assertStatusOk(resp) created_dandiset = resp.json identifier = created_dandiset["meta"]["dandiset"]["identifier"] assertStatusOk( server.request( path=f"/dandi/{identifier}/owners", method="PUT", body=json.dumps([admin, user], default=str), user=admin, type="application/json", ) ) return created_dandiset
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)
def test_delete_with_file(server, user, project, postmortem, postmortemtest, make_girder_file, fsAssetstore): from girder.plugins.edp.models.postmortemtest import PostmortemTest from girder.models.file import File image_file = make_girder_file(fsAssetstore, user, 'data') updates = { 'imageFileId': image_file['_id'], 'comments': 'We now have files.' } r = server.request( '/edp/projects/%s/postmortems/%s/tests/%s' % (project['_id'], postmortem['_id'], postmortemtest['_id']), method='PATCH', body=json.dumps({k: str(v) for (k, v) in updates.items()}), type='application/json', user=user) assertStatusOk(r) r = server.request( '/edp/projects/%s/postmortems/%s/tests/%s' % (project['_id'], postmortem['_id'], postmortemtest['_id']), method='DELETE', user=user) assertStatusOk(r) postmortemtest = PostmortemTest().load(postmortemtest['_id'], force=True) assert postmortemtest is None image_file = File().load(image_file['_id'], force=True) assert image_file is None
def test_get_cube(server, molecule, calculation, user): molecule = molecule(user, 'water') calculation_water = calculation(user, molecule, 'water') assert '_id' in calculation_water assert 'moleculeId' in calculation_water assert 'properties' in calculation_water calc_id = str(calculation_water['_id']) r = server.request('/calculations/%s/cube/%s' % (calc_id, 'h**o'), method='GET', user=user) assertStatusOk(r) cjson = r.json # Should now have a new cube field with orbital data assert 'cube' in cjson assert 'dimensions' in cjson['cube'] assert 'origin' in cjson['cube'] assert 'scalars' in cjson['cube'] assert 'spacing' in cjson['cube'] calc_dims = cjson['cube']['dimensions'] calc_dims_prod = calc_dims[0] * calc_dims[1] * calc_dims[2] calc_scalars_len = len(cjson['cube']['scalars']) assert calc_dims_prod == calc_scalars_len
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
def test_get_cjson(server, molecule, calculation, user): molecule = molecule(user) calculation = calculation(user, molecule) assert '_id' in calculation assert 'moleculeId' in calculation calc_id = str(calculation['_id']) calc_molecule_id = str(calculation['moleculeId']) # Get the cjson for the calculation r = server.request('/calculations/%s/cjson' % calc_id, method='GET', user=user) assertStatusOk(r) cjson = r.json # Should have all the needed cjson components assert 'atoms' in cjson assert 'coords' in cjson['atoms'] assert '3d' in cjson['atoms']['coords'] assert len(cjson['atoms']['coords']['3d']) == 24 # 3 * 8 atoms = 24 assert 'elements' in cjson['atoms'] assert 'number' in cjson['atoms']['elements'] assert cjson['atoms']['elements']['number'].count(1) == 6 assert cjson['atoms']['elements']['number'].count(6) == 2 assert len(cjson['atoms']['elements']['number']) == 8 assert 'bonds' in cjson assert 'connections' in cjson['bonds'] assert 'order' in cjson['bonds'] assert len(cjson['bonds']['order']) == 7
def testItemPosition7(server, makeResources, admin): resp = server.request( '/item/%s/position' % str(makeResources['privateItems'][7]['_id']), user=admin, params={'folderId': str(makeResources['folders'][1]['_id'])}) assertStatusOk(resp) assert resp.json == 17
def testTokenSessionReturnsPassedToken(server, token): # If we ask for another token, passing in the first one, we should get # the first one back resp = server.request(path='/token/session', method='GET', token=token) assertStatusOk(resp) token2 = resp.json['token'] assert token == token2
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)
def test_find(server, user, project): from girder.plugins.edp.models.project import Project r = server.request('/edp/projects', method='GET', user=user) assertStatusOk(r) assert len(r.json) == 1
def testDeleteItemUpdatesSize(server, admin, hierarchy): resp = server.request(path='/item/%s' % hierarchy.items[0]['_id'], method='DELETE', user=admin) assertStatusOk(resp) assertNodeSize(hierarchy.folders[0], Folder, 0) assertNodeSize(hierarchy.folders[1], Folder, 10) assertNodeSize(hierarchy.collections[0], Collection, 10)
def testAdminCanAccessOtherUsersKeys(server, admin, user): # Admins should be able to see other users' keys resp = server.request('/api_key', params={'userId': user['_id']}, user=admin) assertStatusOk(resp) assert resp.json == []
def testCustomWebRoot(route, server): """ Tests the ability of plugins to serve their own custom server roots. """ resp = server.request(route) assertStatusOk(resp) assert resp.json == ['custom REST route']
def test_get_geometry(server, geometry, molecule, user): molecule = molecule(user) geometry = geometry(user, molecule) # The geometry will have been created by the fixture assert '_id' in geometry assert 'moleculeId' in geometry assert 'cjson' in geometry # These are not essential, but we set it ourselves assert 'provenanceType' in geometry assert 'provenanceId' in geometry _id = geometry['_id'] molecule_id = geometry['moleculeId'] cjson = geometry['cjson'] provenance_type = geometry['provenanceType'] provenance_id = geometry['provenanceId'] # Find the geometry by its parent molecule. path = '/molecules/%s/geometries' % molecule_id r = server.request(path, method='GET', user=user) assertStatusOk(r) # There should be exactly one assert len(r.json['results']) == 1 geometry = r.json['results'][0] # Everything should match assert geometry.get('_id') == str(_id) assert geometry.get('moleculeId') == str(molecule_id) assert geometry.get('provenanceType') == provenance_type assert geometry.get('provenanceId') == str(provenance_id)
def testUserCanAccessTheirOwnApiKeys(server, user): # Users should be able to request their own keys resp = server.request('/api_key', params={'userId': user['_id']}, user=user) assertStatusOk(resp) assert resp.json == []
def test_get_calc(server, molecule, calculation, user): assert '_id' in calculation assert 'moleculeId' in calculation calc_id = str(calculation['_id']) calc_molecule_id = str(calculation['moleculeId']) # Find it by molecule id params = {'moleculeId': calc_molecule_id} r = server.request('/calculations', method='GET', params=params, user=user) assertStatusOk(r) # Should just be one calculation assert len(r.json) == 1 calc = r.json[0] assert '_id' in calc assert str(calc['_id']) == calc_id # Find it by its own id r = server.request('/calculations/%s' % calc_id, method='GET', user=user) assertStatusOk(r) calc = r.json assert '_id' in calc assert str(calc['_id']) == calc_id
def test_get(server, user, admin, project, cycle): r = server.request('/edp/projects/%s/cycles/%s' % (project['_id'], cycle['_id']), method='GET', user=user) assertStatusOk(r) assert cycle.items() <= r.json.items()
def test_get_cjson(server, calculation, user): assert '_id' in calculation assert 'moleculeId' in calculation calc_id = str(calculation['_id']) calc_molecule_id = str(calculation['moleculeId']) # Get the cjson for the calculation r = server.request( '/calculations/%s/cjson' % calc_id, method='GET', user=user) assertStatusOk(r) cjson = json.loads(r.json) # Should have all the needed cjson components assert 'atoms' in cjson assert 'coords' in cjson['atoms'] assert '3d' in cjson['atoms']['coords'] assert len(cjson['atoms']['coords']['3d']) == 24 # 3 * 8 atoms = 24 assert 'elements' in cjson['atoms'] assert 'number' in cjson['atoms']['elements'] assert cjson['atoms']['elements']['number'].count(1) == 6 assert cjson['atoms']['elements']['number'].count(6) == 2 assert len(cjson['atoms']['elements']['number']) == 8 assert 'bonds' in cjson assert 'connections' in cjson['bonds'] assert 'order' in cjson['bonds'] assert len(cjson['bonds']['order']) == 7
def test_put_properties(server, molecule, calculation, user): from girder.plugins.molecules.models.calculation import Calculation from girder.constants import AccessType assert '_id' in calculation assert 'moleculeId' in calculation assert 'properties' in calculation calc_id = str(calculation['_id']) calc_molecule_id = str(calculation['moleculeId']) calc_properties = calculation['properties'] # We put these properties in ourselves assert 'molecular mass' in calc_properties assert 'boiling point' in calc_properties assert 'melting point' in calc_properties # Make sure these have the right values assert pytest.approx(calc_properties['molecular mass'], 1.e-4) == 30.0690 assert calc_properties['melting point'] == -172 assert calc_properties['boiling point'] == -88 # Replace these properties with some new properties new_properties = { 'critical temperature': 32.2, 'critical pressure': 49.0 } r = server.request('/calculations/%s/properties' % calc_id, method='PUT', body=json.dumps(new_properties), user=user, type='application/json') assertStatusOk(r) # Grab the new calculation updated_calc = 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 updated_calc assert 'moleculeId' in updated_calc assert 'properties' in updated_calc assert str(updated_calc['_id']) == calc_id assert str(updated_calc['moleculeId']) == calc_molecule_id # Make sure the old properties are no longer here updated_calc_properties = updated_calc['properties'] assert 'molecular mass' not in updated_calc_properties assert 'boiling point' not in updated_calc_properties assert 'melting point' not in updated_calc_properties # The new properties should be here, though assert 'critical temperature' in updated_calc_properties assert 'critical pressure' in updated_calc_properties # Make sure these are correct also assert pytest.approx( updated_calc_properties['critical temperature'], 1.e-1) == new_properties['critical temperature'] assert pytest.approx( updated_calc_properties['critical pressure'], 1.e-1) == new_properties['critical pressure']
def testWorker(server, models): # Test the settings 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={}) 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) assert job['status'] == JobStatus.INACTIVE # Schedule the job, make sure it is sent to celery with mock.patch('celery.Celery') as celeryMock: instance = celeryMock.return_value instance.send_task.return_value = FakeAsyncResult() jobModel.scheduleJob(job) # Make sure we sent the job to celery assert len(celeryMock.mock_calls) == 2 assert celeryMock.mock_calls[0][1] == ('girder_worker',) assert celeryMock.mock_calls[0][2] == { 'broker': 'amqp://[email protected]', 'backend': 'amqp://[email protected]' } sendTaskCalls = celeryMock.return_value.send_task.mock_calls assert len(sendTaskCalls) == 1 assert sendTaskCalls[0][1] == ( 'girder_worker.run', job['args'], job['kwargs']) assert 'headers' in sendTaskCalls[0][2] assert 'jobInfoSpec' in sendTaskCalls[0][2]['headers'] # Make sure we got and saved the celery task id job = jobModel.load(job['_id'], force=True) assert job['celeryTaskId'] == 'fake_id' assert job['status'] == JobStatus.QUEUED
def test_list_dandisets_limit(server, request_auth, dandiset_1, dandiset_2): resp = server.request(path=path, method="GET", params={"limit": 1}, **request_auth) assertStatusOk(resp) assert len(resp.json) == 1 assert_dandisets_are_equal(dandiset_1, resp.json[0])
def testPluginRestRoutes(server): resp = server.request('/describe') assertStatusOk(resp) assert '/other' in resp.json['paths'] resp = server.request('/other') assertStatusOk(resp) assert resp.json == ['custom REST route']
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 apiKey(server, user): # Create a new API key with full access resp = server.request('/api_key', method='POST', params={ 'name': 'test key' }, user=user) assertStatusOk(resp) apiKey = ApiKey().load(resp.json['_id'], force=True) yield apiKey
def testMoveSubfolderToUser(server, admin, hierarchy): resp = server.request( path='/folder/%s' % hierarchy.folders[1]['_id'], method='PUT', user=admin, params={ 'parentId': admin['_id'], 'parentType': 'user' }) assertStatusOk(resp) assertNodeSize(admin, User, 10) assertNodeSize(hierarchy.collections[0], Collection, 1)
def testApiDocsContent(server): """ Test content of API documentation page. """ resp = server.request(path='/api/v1', method='GET', isJson=False, prefix='') assertStatusOk(resp) body = getResponseBody(resp) assert 'Girder REST API Documentation' in body assert 'This is not a sandbox' in body assert 'id="swagger-ui-container"' in body
def testTokenCreationDuration(server, user, apiKey): defaultDuration = Setting().get(SettingKey.COOKIE_LIFETIME) # We should be able to request a duration shorter than default resp = server.request('/api_key/token', method='POST', params={ 'key': apiKey['key'], 'duration': defaultDuration - 1 }) assertStatusOk(resp) token = Token().load( resp.json['authToken']['token'], force=True, objectId=False) duration = token['expires'] - token['created'] assert duration == datetime.timedelta(days=defaultDuration - 1)
def testUploaderUser(provisionedServer, smtp): # Create an uploader admin resp = provisionedServer.request(path='/user', method='POST', params={ 'email': '*****@*****.**', 'login': '******', 'firstName': 'uploader', 'lastName': 'admin', 'password': '******' }) assertStatusOk(resp) uploaderAdmin = User().findOne({'login': '******'}) assert uploaderAdmin is not None contributorsGroup = Group().findOne({'name': 'Dataset Contributors'}) assert contributorsGroup is not None Group().addUser(contributorsGroup, uploaderAdmin, level=AccessType.WRITE) # Create an uploader user resp = provisionedServer.request(path='/user', method='POST', params={ 'email': '*****@*****.**', 'login': '******', 'firstName': 'uploader', 'lastName': 'user', 'password': '******' }) assertStatusOk(resp) uploaderUser = User().findOne({'login': '******'}) assert uploaderUser is not None # TODO: check if a user can upload without agreeing to terms # Ensure request create dataset permission works resp = provisionedServer.request(path='/user/requestCreateDatasetPermission', method='POST', user=uploaderUser) assertStatusOk(resp) assert smtp.waitForMail() assert smtp.getMail() # pop off the queue for later assertion that the queue is empty # Ensure that the user can't create datasets yet resp = provisionedServer.request(path='/user/me', method='GET', user=uploaderUser) assertStatusOk(resp) assert not resp.json['permissions']['createDataset'] # Ensure that a join request is pending contributorsGroup = Group().findOne({'name': 'Dataset Contributors'}) joinRequestUserIds = [user['id'] for user in Group().getFullRequestList(contributorsGroup)] assert uploaderUser['_id'] in joinRequestUserIds assert smtp.isMailQueueEmpty() # Add the user, then ensure they can create datasets Group().inviteUser(contributorsGroup, uploaderUser, level=AccessType.READ) resp = provisionedServer.request(path='/user/me', method='GET', user=uploaderUser) assertStatusOk(resp) assert resp.json['permissions']['createDataset']
def testMoveFolderToNewCollection(server, admin, hierarchy): assertNodeSize(hierarchy.collections[0], Collection, 11) assertNodeSize(hierarchy.collections[1], Collection, 0) resp = server.request( path='/folder/%s' % hierarchy.folders[0]['_id'], method='PUT', user=admin, params={ 'parentId': hierarchy.collections[1]['_id'], 'parentType': 'collection' }) assertStatusOk(resp) assertNodeSize(hierarchy.collections[0], Collection, 0) assertNodeSize(hierarchy.collections[1], Collection, 11)
def testTokenCreatesUniqueTokens(server, user, apiKey): for _ in range(0, 2): resp = server.request('/api_key/token', method='POST', params={ 'key': apiKey['key'] }) assertStatusOk(resp) # We should have two tokens for this key q = { 'userId': user['_id'], 'apiKeyId': apiKey['_id'] } count = Token().find(q).count() assert count == 2
def testApiDocsCustomContent(server): """ Test content of API documentation page that's customized by a plugin. """ resp = server.request(path='/api/v1', method='GET', isJson=False, prefix='') assertStatusOk(resp) body = getResponseBody(resp) assert 'Girder REST API Documentation' not in body assert 'This is not a sandbox' not in body assert 'Girder Web Application Programming Interface' in body assert '<p>Custom API description</p>' in body assert 'id="swagger-ui-container"' in body
def testListScopes(server): resp = server.request('/token/scopes') assertStatusOk(resp) assert resp.json == TokenScope.listScopes() assert 'custom' in resp.json assert isinstance(resp.json['custom'], list) assert 'adminCustom' in resp.json assert isinstance(resp.json['adminCustom'], list) for scope in resp.json['custom'] + resp.json['adminCustom']: assert 'id' in scope assert 'name' in scope assert 'description' in scope
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 testInactiveKeyStructure(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) # Make sure key itself didn't change assert resp.json['key'] == apiKey['key'] apiKey = ApiKey().load(resp.json['_id'], force=True) assert not apiKey['active'] assert apiKey['tokenDuration'] == 10 assert set(apiKey['scope']) == set(newScopes)
def testWebRootProperlyHandlesCustomStaticPublicPath(server): cherrypy.config['server']['static_public_path'] = 'http://my-cdn-url.com/static' resp = server.request(path='/', method='GET', isJson=False, prefix='') assertStatusOk(resp) body = getResponseBody(resp) assert 'href="http://my-cdn-url.com/static/built/Girder_Favicon.png"' in body # Same assertion should hold true for Swagger resp = server.request(path='/', method='GET', isJson=False) assertStatusOk(resp) body = getResponseBody(resp) assert 'href="http://my-cdn-url.com/static/built/Girder_Favicon.png"' in body cherrypy.config['server']['static_public_path'] = '/static'
def testCollectionDeleteMetadata(server, collection, admin): collection = Collection().setMetadata(collection, METADATA) resp = server.request( path='/collection/%s/metadata' % collection['_id'], user=admin, method='DELETE', body=json.dumps(list(METADATA.keys())), type='application/json') assertStatusOk(resp) assert resp.json['meta'] != METADATA assert resp.json['meta'] == {} newDoc = server.request( path='/collection/%s' % collection['_id'], user=admin, method='GET') assert newDoc.json['meta'] != METADATA assert newDoc.json['meta'] == {}
def testCollectionSetMetadata(server, collection, admin): resp = server.request( path='/collection/%s/metadata' % collection['_id'], user=admin, method='PUT', body=json.dumps(METADATA), type='application/json') assertStatusOk(resp) assert resp.json['meta'] == METADATA # Check that fetching the object again yields the same result newDoc = server.request( path='/collection/%s' % collection['_id'], user=admin, method='GET') assert newDoc.json['meta'] == METADATA
def testApiKeyDeletionDeletesAssociatedTokens(server, user, apiKey): resp = server.request('/api_key/token', method='POST', params={ 'key': apiKey['key'] }) assertStatusOk(resp) q = { 'userId': user['_id'], 'apiKeyId': apiKey['_id'] } # Deleting the API key should delete the tokens made with it count = Token().find(q).count() assert count == 1 resp = server.request('/api_key/%s' % apiKey['_id'], method='DELETE', user=user) assertStatusOk(resp) count = Token().find(q).count() assert count == 0
def testMoveItemToSubfolder(server, admin, hierarchy): assertNodeSize(hierarchy.items[0], Item, 1) assertNodeSize(hierarchy.items[1], Item, 10) assertNodeSize(hierarchy.folders[0], Folder, 1) assertNodeSize(hierarchy.folders[1], Folder, 10) assertNodeSize(hierarchy.collections[0], Collection, 11) resp = server.request( path='/item/%s' % hierarchy.items[0]['_id'], method='PUT', user=admin, params={ 'folderId': hierarchy.folders[1]['_id'] }) assertStatusOk(resp) assertNodeSize(hierarchy.items[0], Item, 1) assertNodeSize(hierarchy.items[1], Item, 10) assertNodeSize(hierarchy.folders[0], Folder, 0) assertNodeSize(hierarchy.folders[1], Folder, 11) assertNodeSize(hierarchy.collections[0], Collection, 11)
def testWebRootProperlyHandlesStaticRouteUrls(server, db): Setting().set(SettingKey.ROUTE_TABLE, { GIRDER_ROUTE_ID: '/', GIRDER_STATIC_ROUTE_ID: 'http://my-cdn-url.com/static' }) resp = server.request(path='/', method='GET', isJson=False, prefix='') assertStatusOk(resp) body = getResponseBody(resp) assert 'href="http://my-cdn-url.com/static/img/Girder_Favicon.png"' in body # Same assertion should hold true for Swagger resp = server.request(path='/', method='GET', isJson=False) assertStatusOk(resp) body = getResponseBody(resp) assert 'href="http://my-cdn-url.com/static/img/Girder_Favicon.png"' in body
def testTokenCreation(server, user, apiKey): defaultDuration = Setting().get(SettingKey.COOKIE_LIFETIME) # Create a token using the key resp = server.request('/api_key/token', method='POST', params={ 'key': apiKey['key'], 'duration': defaultDuration + 1000 }) assertStatusOk(resp) token = Token().load( resp.json['authToken']['token'], force=True, objectId=False) # Make sure token has full user auth access assert token['userId'] == user['_id'] assert token['scope'] == [TokenScope.USER_AUTH] # Make sure the token references the API key used to create it assert token['apiKeyId'] == apiKey['_id'] # Make sure the token duration is not longer than the default duration = token['expires'] - token['created'] assert duration == datetime.timedelta(days=defaultDuration)
def testRouteTableBehavior(server, admin): Setting().set(SettingKey.ROUTE_TABLE, { GIRDER_ROUTE_ID: '/', 'has_webroot': '/has_webroot' }) # /has_webroot should serve our plugin webroot resp = server.request('/has_webroot', prefix='', isJson=False, appPrefix='/has_webroot') assertStatusOk(resp) assert 'some webroot' in getResponseBody(resp) # girder should be at / resp = server.request('/', prefix='', isJson=False) assertStatusOk(resp) assert 'g-global-info-apiroot' in getResponseBody(resp) table = Setting().get(SettingKey.ROUTE_TABLE) assert 'has_webroot' in table assert table['has_webroot'] == '/has_webroot'
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']
def testDeactivatingKeyDeletesAssociatedTokens(server, user, apiKey): resp = server.request('/api_key/token', method='POST', params={ 'key': apiKey['key'] }) assertStatusOk(resp) 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) # This should have deleted all corresponding tokens q = { 'userId': user['_id'], 'apiKeyId': apiKey['_id'] } count = Token().find(q).count() assert count == 0