def test_delete_collection(api, collection_batch, scopes, collection_auth): authorized = ODPScope.COLLECTION_ADMIN in scopes and \ collection_auth in (CollectionAuth.NONE, CollectionAuth.MATCH) if collection_auth == CollectionAuth.MATCH: api_client_collection = collection_batch[2] elif collection_auth == CollectionAuth.MISMATCH: api_client_collection = collection_batch[1] else: api_client_collection = None modified_collection_batch = collection_batch.copy() del modified_collection_batch[2] r = api(scopes, api_client_collection).delete( f'/collection/{(collection_id := collection_batch[2].id)}') if authorized: assert_empty_result(r) assert_db_state(modified_collection_batch) assert_audit_log('delete', collection_id=collection_id) else: assert_forbidden(r) assert_db_state(collection_batch) assert_no_audit_log()
def test_create_collection_conflict(api, collection_batch, collection_auth): scopes = [ODPScope.COLLECTION_ADMIN] authorized = collection_auth == CollectionAuth.NONE if collection_auth == CollectionAuth.NONE: api_client_collection = None else: api_client_collection = collection_batch[2] collection = collection_build(id=collection_batch[2].id) r = api(scopes, api_client_collection).post('/collection/', json=dict( id=collection.id, name=collection.name, doi_key=collection.doi_key, provider_id=collection.provider_id, )) if authorized: assert_conflict(r, 'Collection id is already in use') else: assert_forbidden(r) assert_db_state(collection_batch) assert_no_audit_log()
def test_update_collection_not_found(api, collection_batch_no_projects, collection_auth): scopes = [ODPScope.COLLECTION_ADMIN] authorized = collection_auth == CollectionAuth.NONE if collection_auth == CollectionAuth.NONE: api_client_collection = None else: api_client_collection = collection_batch_no_projects[2] collection = collection_build(id='foo') r = api(scopes, api_client_collection).put('/collection/', json=dict( id=collection.id, name=collection.name, doi_key=collection.doi_key, provider_id=collection.provider_id, )) if authorized: assert_not_found(r) else: assert_forbidden(r) assert_db_state(collection_batch_no_projects) assert_no_audit_log()
def test_update_role(api, role_batch, scopes, collection_auth): authorized = ODPScope.ROLE_ADMIN in scopes and \ collection_auth in (CollectionAuth.NONE, CollectionAuth.MATCH) if collection_auth == CollectionAuth.MATCH: api_client_collection = role_batch[2].collection elif collection_auth == CollectionAuth.MISMATCH: api_client_collection = role_batch[1].collection else: api_client_collection = None if collection_auth in (CollectionAuth.MATCH, CollectionAuth.MISMATCH): modified_role_collection = role_batch[2].collection else: modified_role_collection = None modified_role_batch = role_batch.copy() modified_role_batch[2] = (role := role_build( id=role_batch[2].id, collection=modified_role_collection, )) r = api(scopes, api_client_collection).put('/role/', json=dict( id=role.id, scope_ids=scope_ids(role), collection_id=role.collection_id, )) if authorized: assert_empty_result(r) assert_db_state(modified_role_batch) else: assert_forbidden(r) assert_db_state(role_batch)
def test_create_collection(api, collection_batch, scopes, collection_auth): # note that collection-specific auth will never allow creating a new collection authorized = ODPScope.COLLECTION_ADMIN in scopes and \ collection_auth == CollectionAuth.NONE if collection_auth == CollectionAuth.NONE: api_client_collection = None else: api_client_collection = collection_batch[2] modified_collection_batch = collection_batch + [ collection := collection_build() ] r = api(scopes, api_client_collection).post('/collection/', json=dict( id=collection.id, name=collection.name, doi_key=collection.doi_key, provider_id=collection.provider_id, )) if authorized: assert_empty_result(r) assert_db_state(modified_collection_batch) assert_audit_log('insert', collection) else: assert_forbidden(r) assert_db_state(collection_batch) assert_no_audit_log()
def test_create_role_conflict(api, role_batch, collection_auth): scopes = [ODPScope.ROLE_ADMIN] authorized = collection_auth in (CollectionAuth.NONE, CollectionAuth.MATCH) if collection_auth == CollectionAuth.MATCH: api_client_collection = role_batch[2].collection elif collection_auth == CollectionAuth.MISMATCH: api_client_collection = role_batch[1].collection else: api_client_collection = None if collection_auth in (CollectionAuth.MATCH, CollectionAuth.MISMATCH): new_role_collection = role_batch[2].collection else: new_role_collection = None role = role_build( id=role_batch[2].id, collection=new_role_collection, ) r = api(scopes, api_client_collection).post('/role/', json=dict( id=role.id, scope_ids=scope_ids(role), collection_id=role.collection_id, )) if authorized: assert_conflict(r, 'Role id is already in use') else: assert_forbidden(r) assert_db_state(role_batch)
def test_update_role_not_found(api, role_batch, collection_auth): scopes = [ODPScope.ROLE_ADMIN] authorized = collection_auth in (CollectionAuth.NONE, CollectionAuth.MATCH) if collection_auth == CollectionAuth.MATCH: api_client_collection = role_batch[2].collection elif collection_auth == CollectionAuth.MISMATCH: api_client_collection = role_batch[1].collection else: api_client_collection = None if collection_auth in (CollectionAuth.MATCH, CollectionAuth.MISMATCH): modified_role_collection = role_batch[2].collection else: modified_role_collection = None role = role_build( id='foo', collection=modified_role_collection, ) r = api(scopes, api_client_collection).put('/role/', json=dict( id=role.id, scope_ids=scope_ids(role), collection_id=role.collection_id, )) if authorized: assert_not_found(r) else: assert_forbidden(r) assert_db_state(role_batch)
def test_untag_record(api, record_batch_no_tags, admin_route, scopes, collection_auth, tag_cardinality, same_user): route = '/record/admin/' if admin_route else '/record/' authorized = admin_route and ODPScope.RECORD_ADMIN in scopes or \ not admin_route and ODPScope.RECORD_QC in scopes authorized = authorized and collection_auth in (CollectionAuth.NONE, CollectionAuth.MATCH) if collection_auth == CollectionAuth.MATCH: api_client_collection = record_batch_no_tags[2].collection elif collection_auth == CollectionAuth.MISMATCH: api_client_collection = record_batch_no_tags[1].collection else: api_client_collection = None client = api(scopes, api_client_collection) record = record_batch_no_tags[2] record_tags = RecordTagFactory.create_batch(randint(1, 3), record=record) tag = new_generic_tag(tag_cardinality) if same_user: record_tag_1 = RecordTagFactory( record=record, tag=tag, user=None, ) else: record_tag_1 = RecordTagFactory( record=record, tag=tag, ) record_tag_1_dict = { 'tag_id': record_tag_1.tag_id, 'user_id': record_tag_1.user_id, 'data': record_tag_1.data, } r = client.delete(f'{route}{record.id}/tag/{record_tag_1.id}') if authorized: if not admin_route and not same_user: assert_forbidden(r) assert_db_tag_state(record.id, *record_tags, record_tag_1) assert_tag_audit_log() else: assert_empty_result(r) assert_db_tag_state(record.id, *record_tags) assert_tag_audit_log( dict(command='delete', record_id=record.id, record_tag=record_tag_1_dict), ) else: assert_forbidden(r) assert_db_tag_state(record.id, *record_tags, record_tag_1) assert_tag_audit_log() assert_db_state(record_batch_no_tags) assert_no_audit_log()
def test_update_record_doi_change(api, record_batch_with_ids, admin, collection_auth, doi_change, published_doi): route = '/record/admin/' if admin else '/record/' scopes = [ODPScope.RECORD_ADMIN] if admin else [ODPScope.RECORD_WRITE] authorized = collection_auth in (CollectionAuth.NONE, CollectionAuth.MATCH) if collection_auth == CollectionAuth.MATCH: api_client_collection = record_batch_with_ids[2].collection elif collection_auth == CollectionAuth.MISMATCH: api_client_collection = record_batch_with_ids[1].collection else: api_client_collection = None if collection_auth in (CollectionAuth.MATCH, CollectionAuth.MISMATCH): modified_record_collection = record_batch_with_ids[2].collection else: modified_record_collection = None # new collection if published_doi: PublishedDOI(doi=record_batch_with_ids[2].doi).save() modified_record_batch = record_batch_with_ids.copy() if doi_change == 'change': modified_record_batch[2] = (record := record_build( identifiers='doi', id=record_batch_with_ids[2].id, collection=modified_record_collection, )) elif doi_change == 'remove': modified_record_batch[2] = (record := record_build( identifiers='sid', id=record_batch_with_ids[2].id, collection=modified_record_collection, )) r = api(scopes, api_client_collection).put(route + record.id, json=dict( doi=record.doi, sid=record.sid, collection_id=record.collection_id, schema_id=record.schema_id, metadata=record.metadata_, )) if authorized: if published_doi: assert_unprocessable( r, 'The DOI has been published and cannot be modified.') assert_db_state(record_batch_with_ids) assert_no_audit_log() else: assert_json_record_result(r, r.json(), record) assert_db_state(modified_record_batch) assert_audit_log('update', record) else: assert_forbidden(r) assert_db_state(record_batch_with_ids) assert_no_audit_log()
def test_get_user(api, user_batch, scopes): authorized = ODPScope.USER_READ in scopes r = api(scopes).get(f'/user/{user_batch[2].id}') if authorized: assert_json_result(r, r.json(), user_batch[2]) else: assert_forbidden(r) assert_db_state(user_batch)
def test_get_catalog(api, catalog_batch, scopes): authorized = ODPScope.CATALOG_READ in scopes r = api(scopes).get(f'/catalog/{catalog_batch[2].id}') if authorized: assert_json_result(r, r.json(), catalog_batch[2]) else: assert_forbidden(r) assert_db_state(catalog_batch)
def test_get_schema(api, schema_batch, scopes): authorized = ODPScope.SCHEMA_READ in scopes r = api(scopes).get(f'/schema/{schema_batch[2].id}') if authorized: assert_json_result(r, r.json(), schema_batch[2]) else: assert_forbidden(r) assert_db_state(schema_batch)
def test_list_catalogs(api, catalog_batch, scopes): authorized = ODPScope.CATALOG_READ in scopes r = api(scopes).get('/catalog/') if authorized: assert_json_results(r, r.json(), catalog_batch) else: assert_forbidden(r) assert_db_state(catalog_batch)
def test_list_users(api, user_batch, scopes): authorized = ODPScope.USER_READ in scopes r = api(scopes).get('/user/') if authorized: assert_json_results(r, r.json(), user_batch) else: assert_forbidden(r) assert_db_state(user_batch)
def test_list_providers(api, provider_batch, scopes): authorized = ODPScope.PROVIDER_READ in scopes r = api(scopes).get('/provider/') if authorized: assert_json_results(r, r.json(), provider_batch) else: assert_forbidden(r) assert_db_state(provider_batch)
def test_get_tag(api, tag_batch, scopes): authorized = ODPScope.TAG_READ in scopes r = api(scopes).get(f'/tag/{tag_batch[2].id}') if authorized: assert_json_result(r, r.json(), tag_batch[2]) else: assert_forbidden(r) assert_db_state(tag_batch)
def test_get_provider(api, provider_batch, scopes): authorized = ODPScope.PROVIDER_READ in scopes r = api(scopes).get(f'/provider/{provider_batch[2].id}') if authorized: assert_json_result(r, r.json(), provider_batch[2]) else: assert_forbidden(r) assert_db_state(provider_batch)
def test_list_tags(api, tag_batch, scopes): authorized = ODPScope.TAG_READ in scopes r = api(scopes).get('/tag/') if authorized: assert_json_results(r, r.json(), tag_batch) else: assert_forbidden(r) assert_db_state(tag_batch)
def test_list_schemas(api, schema_batch, scopes): authorized = ODPScope.SCHEMA_READ in scopes r = api(scopes).get('/schema/') if authorized: assert_json_results(r, r.json(), schema_batch) else: assert_forbidden(r) assert_db_state(schema_batch)
def test_update_record_conflict(api, record_batch_with_ids, admin, collection_auth, conflict): route = '/record/admin/' if admin else '/record/' scopes = [ODPScope.RECORD_ADMIN] if admin else [ODPScope.RECORD_WRITE] authorized = collection_auth in (CollectionAuth.NONE, CollectionAuth.MATCH) if collection_auth == CollectionAuth.MATCH: api_client_collection = record_batch_with_ids[2].collection elif collection_auth == CollectionAuth.MISMATCH: api_client_collection = record_batch_with_ids[1].collection else: api_client_collection = None if collection_auth in (CollectionAuth.MATCH, CollectionAuth.MISMATCH): modified_record_collection = record_batch_with_ids[2].collection else: modified_record_collection = None # new collection if conflict == 'doi': record = record_build( id=record_batch_with_ids[2].id, doi=record_batch_with_ids[0].doi, collection=modified_record_collection, ) elif conflict == 'sid': record = record_build( id=record_batch_with_ids[2].id, sid=record_batch_with_ids[0].sid, collection=modified_record_collection, ) else: record = record_build( id=record_batch_with_ids[2].id, doi=record_batch_with_ids[0].doi, sid=record_batch_with_ids[1].sid, collection=modified_record_collection, ) r = api(scopes, api_client_collection).put(route + record.id, json=dict( doi=record.doi, sid=record.sid, collection_id=record.collection_id, schema_id=record.schema_id, metadata=record.metadata_, )) if authorized: if conflict in ('doi', 'both'): assert_conflict(r, 'DOI is already in use') else: assert_conflict(r, 'SID is already in use') else: assert_forbidden(r) assert_db_state(record_batch_with_ids) assert_no_audit_log()
def test_update_record(api, record_batch, admin_route, scopes, collection_tags, collection_auth): route = '/record/admin/' if admin_route else '/record/' authorized = admin_route and ODPScope.RECORD_ADMIN in scopes or \ not admin_route and ODPScope.RECORD_WRITE in scopes authorized = authorized and collection_auth in (CollectionAuth.NONE, CollectionAuth.MATCH) if collection_auth == CollectionAuth.MATCH: api_client_collection = record_batch[2].collection elif collection_auth == CollectionAuth.MISMATCH: api_client_collection = record_batch[1].collection else: api_client_collection = None if collection_auth in (CollectionAuth.MATCH, CollectionAuth.MISMATCH): modified_record_collection = record_batch[2].collection else: modified_record_collection = None # new collection modified_record_batch = record_batch.copy() modified_record_batch[2] = (record := record_build( id=record_batch[2].id, doi=record_batch[2].doi, collection=modified_record_collection, collection_tags=collection_tags, )) r = api(scopes, api_client_collection).put(route + record.id, json=dict( doi=record.doi, sid=record.sid, collection_id=record.collection_id, schema_id=record.schema_id, metadata=record.metadata_, )) if authorized: if not admin_route and set(collection_tags) & { ODPCollectionTag.FROZEN, ODPCollectionTag.READY }: assert_unprocessable( r, 'Cannot update a record belonging to a ready or frozen collection' ) assert_db_state(record_batch) assert_no_audit_log() else: assert_json_record_result(r, r.json(), record) assert_db_state(modified_record_batch) assert_audit_log('update', record) else: assert_forbidden(r) assert_db_state(record_batch) assert_no_audit_log()
def test_delete_user(api, user_batch, scopes): authorized = ODPScope.USER_ADMIN in scopes modified_user_batch = user_batch.copy() del modified_user_batch[2] r = api(scopes).delete(f'/user/{user_batch[2].id}') if authorized: assert_empty_result(r) assert_db_state(modified_user_batch) else: assert_forbidden(r) assert_db_state(user_batch)
def test_delete_record(api, record_batch_with_ids, admin_route, scopes, collection_tags, collection_auth, published_doi): route = '/record/admin/' if admin_route else '/record/' authorized = admin_route and ODPScope.RECORD_ADMIN in scopes or \ not admin_route and ODPScope.RECORD_WRITE in scopes authorized = authorized and collection_auth in (CollectionAuth.NONE, CollectionAuth.MATCH) if collection_auth == CollectionAuth.MATCH: api_client_collection = record_batch_with_ids[2].collection elif collection_auth == CollectionAuth.MISMATCH: api_client_collection = record_batch_with_ids[1].collection else: api_client_collection = None for ct in collection_tags: CollectionTagFactory( collection=record_batch_with_ids[2].collection, tag=TagFactory(id=ct, type='collection'), ) if published_doi: PublishedDOI(doi=record_batch_with_ids[2].doi).save() modified_record_batch = record_batch_with_ids.copy() del modified_record_batch[2] r = api(scopes, api_client_collection).delete( f'{route}{(record_id := record_batch_with_ids[2].id)}') if authorized: if not admin_route and set(collection_tags) & { ODPCollectionTag.FROZEN, ODPCollectionTag.READY }: assert_unprocessable( r, 'Cannot delete a record belonging to a ready or frozen collection' ) assert_db_state(record_batch_with_ids) assert_no_audit_log() elif published_doi: assert_unprocessable( r, 'The DOI has been published and cannot be deleted.') assert_db_state(record_batch_with_ids) assert_no_audit_log() else: assert_empty_result(r) assert_db_state(modified_record_batch) assert_audit_log('delete', record_id=record_id) else: assert_forbidden(r) assert_db_state(record_batch_with_ids) assert_no_audit_log()
def test_delete_provider(api, provider_batch, scopes): authorized = ODPScope.PROVIDER_ADMIN in scopes modified_provider_batch = provider_batch.copy() del modified_provider_batch[2] r = api(scopes).delete(f'/provider/{provider_batch[2].id}') if authorized: assert_empty_result(r) assert_db_state(modified_provider_batch) else: assert_forbidden(r) assert_db_state(provider_batch)
def test_list_scopes(api, scope_batch, scopes): authorized = ODPScope.SCOPE_READ in scopes # add the parameterized scopes to the batch of expected scopes, # as they will be created by the api fixture scope_batch += [ScopeFactory.build(id=s.value, type='odp') for s in scopes] r = api(scopes).get('/scope/') if authorized: assert_json_results(r, r.json(), scope_batch) else: assert_forbidden(r) assert_db_state(scope_batch)
def test_create_record(api, record_batch, admin_route, scopes, collection_tags, collection_auth): route = '/record/admin/' if admin_route else '/record/' authorized = admin_route and ODPScope.RECORD_ADMIN in scopes or \ not admin_route and ODPScope.RECORD_WRITE in scopes authorized = authorized and collection_auth in (CollectionAuth.NONE, CollectionAuth.MATCH) if collection_auth == CollectionAuth.MATCH: api_client_collection = record_batch[2].collection elif collection_auth == CollectionAuth.MISMATCH: api_client_collection = record_batch[1].collection else: api_client_collection = None if collection_auth in (CollectionAuth.MATCH, CollectionAuth.MISMATCH): new_record_collection = record_batch[2].collection else: new_record_collection = None # new collection modified_record_batch = record_batch + [ record := record_build( collection=new_record_collection, collection_tags=collection_tags, ) ] r = api(scopes, api_client_collection).post(route, json=dict( doi=record.doi, sid=record.sid, collection_id=record.collection_id, schema_id=record.schema_id, metadata=record.metadata_, )) if authorized: if not admin_route and ODPCollectionTag.FROZEN in collection_tags: assert_unprocessable( r, 'A record cannot be added to a frozen collection') assert_db_state(record_batch) assert_no_audit_log() else: record.id = r.json().get('id') assert_json_record_result(r, r.json(), record) assert_db_state(modified_record_batch) assert_audit_log('insert', record) else: assert_forbidden(r) assert_db_state(record_batch) assert_no_audit_log()
def test_create_provider(api, provider_batch, scopes): authorized = ODPScope.PROVIDER_ADMIN in scopes modified_provider_batch = provider_batch + [provider := provider_build()] r = api(scopes).post('/provider/', json=dict( id=provider.id, name=provider.name, )) if authorized: assert_empty_result(r) assert_db_state(modified_provider_batch) else: assert_forbidden(r) assert_db_state(provider_batch)
def test_create_project(api, project_batch, scopes): authorized = ODPScope.PROJECT_ADMIN in scopes modified_project_batch = project_batch + [project := project_build()] r = api(scopes).post('/project/', json=dict( id=project.id, name=project.name, collection_ids=collection_ids(project), )) if authorized: assert_empty_result(r) assert_db_state(modified_project_batch) else: assert_forbidden(r) assert_db_state(project_batch)
def test_update_record_not_found(api, record_batch, admin, collection_auth): # if not found on the admin route, the record is created! route = '/record/admin/' if admin else '/record/' scopes = [ODPScope.RECORD_ADMIN] if admin else [ODPScope.RECORD_WRITE] authorized = collection_auth in (CollectionAuth.NONE, CollectionAuth.MATCH) if collection_auth == CollectionAuth.MATCH: api_client_collection = record_batch[2].collection elif collection_auth == CollectionAuth.MISMATCH: api_client_collection = record_batch[1].collection else: api_client_collection = None if collection_auth in (CollectionAuth.MATCH, CollectionAuth.MISMATCH): modified_record_collection = record_batch[2].collection else: modified_record_collection = None # new collection modified_record_batch = record_batch + [ record := record_build( id=str(uuid.uuid4()), collection=modified_record_collection, ) ] r = api(scopes, api_client_collection).put(route + record.id, json=dict( doi=record.doi, sid=record.sid, collection_id=record.collection_id, schema_id=record.schema_id, metadata=record.metadata_, )) if authorized: if admin: assert_json_record_result(r, r.json(), record) assert_db_state(modified_record_batch) assert_audit_log('insert', record) else: assert_not_found(r) assert_db_state(record_batch) assert_no_audit_log() else: assert_forbidden(r) assert_db_state(record_batch) assert_no_audit_log()
def test_update_client(api, client_batch, scopes, collection_auth): authorized = ODPScope.CLIENT_ADMIN in scopes and \ collection_auth in (CollectionAuth.NONE, CollectionAuth.MATCH) if collection_auth == CollectionAuth.MATCH: api_client_collection = client_batch[2].collection elif collection_auth == CollectionAuth.MISMATCH: api_client_collection = client_batch[1].collection else: api_client_collection = None if collection_auth in (CollectionAuth.MATCH, CollectionAuth.MISMATCH): modified_client_collection = client_batch[2].collection else: modified_client_collection = None modified_client_batch = client_batch.copy() modified_client_batch[2] = (client := client_build( id=client_batch[2].id, collection=modified_client_collection, )) r = api(scopes, api_client_collection).put( '/client/', json=dict( id=client.id, name=fake.catch_phrase(), secret=fake.password(), scope_ids=scope_ids(client), collection_id=client.collection_id, grant_types=[], response_types=[], redirect_uris=[], post_logout_redirect_uris=[], token_endpoint_auth_method=TokenEndpointAuthMethod. CLIENT_SECRET_BASIC, allowed_cors_origins=[], )) if authorized: assert_empty_result(r) assert_db_state(modified_client_batch) else: assert_forbidden(r) assert_db_state(client_batch)