Exemple #1
0
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']
        }]
Exemple #2
0
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()
Exemple #3
0
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])
Exemple #4
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)
Exemple #5
0
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, {})
Exemple #6
0
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, {})
Exemple #7
0
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())
Exemple #8
0
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]
            }
        ]
Exemple #9
0
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)]
Exemple #10
0
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']