def test_create_record_check_acl_priority(app, db, es, es_acl_prepare, test_users): with app.test_client() as client: with db.session.begin_nested(): acl1 = DefaultACL(name='default', schemas=[RECORD_SCHEMA], priority=0, originator=test_users.u1, operation='get') actor1 = SystemRoleActor(name='auth', system_role='any_user', acl=acl1, originator=test_users.u1) acl2 = DefaultACL(name='default', schemas=[RECORD_SCHEMA], priority=1, originator=test_users.u1, operation='get') actor2 = SystemRoleActor(name='auth', system_role='authenticated_user', acl=acl2, originator=test_users.u1) db.session.add(acl1) db.session.add(actor1) db.session.add(acl2) db.session.add(actor2) login(client, test_users.u1) response = client.post(records_url(), data=json.dumps({ 'title': 'blah', 'contributors': [] }), content_type='application/json') assert response.status_code == 201 rest_metadata = get_json(response)['metadata'] assert 'control_number' in rest_metadata index, doctype = schema_to_index(RECORD_SCHEMA) rec_md = current_search_client.get( index=index, doc_type=doctype, id=str( PersistentIdentifier.get( 'recid', rest_metadata['control_number']).object_uuid)) clear_timestamp(rec_md) assert rec_md['_source']['_invenio_explicit_acls'] == [{ 'operation': 'get', 'id': acl2.id, 'timestamp': 'cleared', 'system_role': ['authenticated_user'] }]
def test_get_elasticsearch_representation(app, db, es, test_users): with db.session.begin_nested(): actor = SystemRoleActor(name='test', originator=test_users.u1, system_role=ANY_USER) db.session.add(actor) assert [ANY_USER] == actor.get_elasticsearch_representation()
def test_get_es_schema(app, db, es, test_users): with db.session.begin_nested(): actor = SystemRoleActor(name='test', originator=test_users.u1, system_role=ANY_USER) db.session.add(actor) assert {'type': 'keyword'} == actor.get_elasticsearch_schema(ES_VERSION[0])
def test_str(app, db, test_users): with db.session.begin_nested(): actor = SystemRoleActor(name='test', originator=test_users.u1, system_role='authenticated_user') db.session.add(actor) assert 'SystemRoleActor[test]' == str(actor)
def test_get_elasticsearch_query(app, db, es, test_users): with current_app.test_request_context(): assert Term(_invenio_explicit_acls__system_role='any_user' ) == SystemRoleActor.get_elasticsearch_query( AnonymousUser(), {}) set_identity(test_users.u1) assert Terms(_invenio_explicit_acls__system_role=['any_user', 'authenticated_user']) == \ SystemRoleActor.get_elasticsearch_query(test_users.u1, {}) # faked user - different identity in flask.g than user with pytest.raises( AttributeError, message='user whose id does not match Identity in flask.g'): SystemRoleActor.get_elasticsearch_query(test_users.u2, {}) set_identity(test_users.u2) assert Terms(_invenio_explicit_acls__system_role=['any_user', 'authenticated_user']) == \ SystemRoleActor.get_elasticsearch_query(test_users.u2, {})
def test_user_matches(app, db, es, test_users): with db.session.begin_nested(): actor = SystemRoleActor(name='test', originator=test_users.u1, system_role='authenticated_user') db.session.add(actor) with current_app.test_request_context(): assert not actor.user_matches(AnonymousUser(), {'system_roles': [any_user]}) set_identity(test_users.u1) assert actor.user_matches(test_users.u1, {}) # faked user - different identity in flask.g than user set_identity(test_users.u1) with pytest.raises(AttributeError): actor.user_matches(test_users.u2, {}) set_identity(test_users.u2) assert actor.user_matches(test_users.u2, {}) set_identity(test_users.u3) assert actor.user_matches(test_users.u3, {})
def test_get_matching_users(app, db, es, test_users): with db.session.begin_nested(): actor = SystemRoleActor(name='test', originator=test_users.u1, system_role='authenticated_user') actor1 = SystemRoleActor(name='test 1', originator=test_users.u1, system_role='custom_system_role') db.session.add(actor) db.session.add(actor1) assert {test_users.u1.id, test_users.u2.id, test_users.u3.id} == set(actor.get_matching_users()) # custom system role can not return matching roles in this implementation with pytest.raises(NotImplementedError): list(actor1.get_matching_users())
def test_aclrecordsearch_returnall(app, db, es, es_acl_prepare, test_users): with db.session.begin_nested(): acl1 = ElasticsearchACL(name='test', schemas=[RECORD_SCHEMA], priority=0, operation='get', originator=test_users.u1, record_selector={'term': { 'keywords': 'test' }}) actor1 = SystemRoleActor(name='auth', system_role='any_user', acl=acl1, originator=test_users.u1) db.session.add(acl1) db.session.add(actor1) current_explicit_acls.reindex_acl(acl1, delayed=False) with app.test_client() as client: login(client, test_users.u1) response = client.post(records_url(), data=json.dumps({'title': 'blah', 'contributors': [], 'keywords': ['blah']}), content_type='application/json') assert response.status_code == 201 rest_metadata = get_json(response)['metadata'] assert 'control_number' in rest_metadata # make sure indices are flushed current_search_client.indices.refresh() current_search_client.indices.flush() index, doc_type = schema_to_index(RECORD_SCHEMA) record_uuid = PersistentIdentifier.get('recid', rest_metadata['control_number']).object_uuid with app.test_request_context(): login_user(test_users.u1) set_identity(test_users.u1) assert current_user == test_users.u1 # acl1 does not apply to the resource so the search must return no data assert not len( ACLRecordsSearch(index=index, doc_type=doc_type, operation='get').get_record(record_uuid).execute()) # when acl_return_all is specified, return all matching records regardless of ACL with_all = ACLRecordsSearch(index=index, doc_type=doc_type).acl_return_all().get_record( record_uuid).execute().hits assert len(with_all) == 1 assert with_all[0]['_invenio_explicit_acls'] == [] # add another acl, this one maps to the record with db.session.begin_nested(): acl2 = ElasticsearchACL(name='test', schemas=[RECORD_SCHEMA], priority=0, operation='get', originator=test_users.u1, record_selector={'term': { 'keywords': 'blah' }}) actor2 = UserActor(name='u2', users=[test_users.u2], acl=acl2, originator=test_users.u1) db.session.add(acl2) db.session.add(actor2) current_explicit_acls.reindex_acl(acl2, delayed=False) # make sure indices are flushed current_search_client.indices.refresh() current_search_client.indices.flush() # for the same user acl_return_all() must return the record and effective acls with app.test_request_context(): login_user(test_users.u1) set_identity(test_users.u1) # when acl_return_all is specified, return all matching records regardless of ACL with_all = ACLRecordsSearch(index=index, doc_type=doc_type).acl_return_all().get_record( record_uuid).execute().hits assert len(with_all) == 1 assert clear_timestamp(with_all[0].to_dict()['_invenio_explicit_acls']) == [ { 'operation': 'get', 'id': acl2.id, 'timestamp': 'cleared', 'user': [2] } ] # for user2 plain ACLRecordsSearch must return the record and effective acls with app.test_request_context(): login_user(test_users.u2) set_identity(test_users.u2) # when acl_return_all is specified, return all matching records regardless of ACL with_all = ACLRecordsSearch(index=index, doc_type=doc_type).get_record(record_uuid).execute().hits assert len(with_all) == 1 assert clear_timestamp(with_all[0].to_dict()['_invenio_explicit_acls']) == [ { 'operation': 'get', 'id': acl2.id, 'timestamp': 'cleared', 'user': [2] } ]
def test_used_in_records(app, db, es, es_acl_prepare, test_users): with db.session.begin_nested(): acl1 = ElasticsearchACL(name='test', schemas=[RECORD_SCHEMA], priority=0, operation='get', originator=test_users.u1, record_selector={'term': { 'keywords': 'blah' }}) actor1 = SystemRoleActor(name='auth', acl=acl1, originator=test_users.u1, system_role='authenticated_user') db.session.add(acl1) db.session.add(actor1) acl2 = ElasticsearchACL(name='test', schemas=[RECORD_SCHEMA], priority=0, operation='get', originator=test_users.u1, record_selector={'term': { 'keywords': 'test' }}) actor2 = SystemRoleActor(name='noauth', acl=acl2, originator=test_users.u1, system_role='any_user') db.session.add(actor2) db.session.add(acl2) acl1.update() acl2.update() pid1, record1 = create_record( { '$schema': RECORD_SCHEMA, 'keywords': ['blah'] }, clz=SchemaEnforcingRecord) pid2, record2 = create_record( { '$schema': RECORD_SCHEMA, 'keywords': ['test'] }, clz=SchemaEnforcingRecord) ts1 = datetime.datetime.now(datetime.timezone.utc) time.sleep(0.1) RecordIndexer().index(record1) current_search_client.indices.refresh() current_search_client.indices.flush() time.sleep(1) ts2 = datetime.datetime.now(datetime.timezone.utc) time.sleep(0.1) RecordIndexer().index(record2) current_search_client.indices.refresh() current_search_client.indices.flush() time.sleep(1) ts3 = datetime.datetime.now(datetime.timezone.utc) # the records should have cached ACLs, let's check idx, doc_type = schema_to_index(RECORD_SCHEMA) assert clear_timestamp( current_search_client.get( index=idx, doc_type=doc_type, id=str(record1.id))['_source']['_invenio_explicit_acls']) == [{ 'operation': 'get', 'id': acl1.id, 'timestamp': 'cleared', 'system_role': ['authenticated_user'] }] assert clear_timestamp( current_search_client.get( index=idx, doc_type=doc_type, id=str(record2.id))['_source']['_invenio_explicit_acls']) == [{ 'operation': 'get', 'id': acl2.id, 'timestamp': 'cleared', 'system_role': ['any_user'] }] # there should be no resource for acl1 before ts1 assert list(acl1.used_in_records(older_than_timestamp=ts1)) == [] # one record before ts2 and ts3 assert list( acl1.used_in_records(older_than_timestamp=ts2)) == [str(record1.id)] assert list( acl1.used_in_records(older_than_timestamp=ts3)) == [str(record1.id)] # and one record before now assert list(acl1.used_in_records()) == [str(record1.id)] # there should be no resource for acl2 before ts1 and ts2 assert list(acl2.used_in_records(older_than_timestamp=ts1)) == [] assert list(acl2.used_in_records(older_than_timestamp=ts2)) == [] # one record before ts3 assert list( acl2.used_in_records(older_than_timestamp=ts3)) == [str(record2.id)] # and one record before now assert list(acl2.used_in_records()) == [str(record2.id)]
def test_create_acl_after_record(app, db, es, es_acl_prepare, test_users): with app.test_client() as client: login(client, test_users.u1) response = client.post(records_url(), data=json.dumps({ 'title': 'blah', 'contributors': [] }), content_type='application/json') assert response.status_code == 201 rest_metadata = get_json(response)['metadata'] assert 'control_number' in rest_metadata current_search_client.indices.refresh() current_search_client.indices.flush() with db.session.begin_nested(): acl1 = DefaultACL(name='default', schemas=[RECORD_SCHEMA], priority=0, originator=test_users.u1, operation='get') actor1 = SystemRoleActor(name='auth', system_role='any_user', acl=acl1, originator=test_users.u1) db.session.add(acl1) db.session.add(actor1) # reindex all resources that might be affected by the ACL change current_explicit_acls.reindex_acl(acl1, delayed=False) index, doctype = schema_to_index(RECORD_SCHEMA) rec_md = current_search_client.get( index=index, doc_type=doctype, id=str( PersistentIdentifier.get( 'recid', rest_metadata['control_number']).object_uuid)) clear_timestamp(rec_md) assert rec_md['_source']['_invenio_explicit_acls'] == [{ 'operation': 'get', 'id': acl1.id, 'timestamp': 'cleared', 'system_role': ['any_user'] }] # remove the ACL from the database with db.session.begin_nested(): db.session.delete(acl1) # reindex records affected by the removal of ACL current_explicit_acls.reindex_acl_removed(acl1, delayed=False) # make sure all changes had time to propagate and test current_search_client.indices.refresh() current_search_client.indices.flush() rec_md = current_search_client.get( index=index, doc_type=doctype, id=str( PersistentIdentifier.get( 'recid', rest_metadata['control_number']).object_uuid)) # there is no ACL in the database => no acls are defined nor enforced on the record print(json.dumps(rec_md, indent=4)) assert '_invenio_explicit_acls' not in rec_md['_source']