def test_patrons_post_without_email(app, client, lib_martigny,
                                    patron_type_children_martigny,
                                    patron_martigny_data_tmp, json_header,
                                    roles, mailbox):
    """Test record retrieval."""
    patron_data = deepcopy(patron_martigny_data_tmp)
    patron_data['email'] = '*****@*****.**'
    patron_data['username'] = '******'
    del patron_data['pid']
    del patron_data['email']
    patron_data['patron']['communication_channel'] = 'mail'
    patron_data = create_user_from_data(patron_data)

    pids = Patron.count()
    assert len(mailbox) == 0

    # Create record / POST
    res, _ = postdata(client, 'invenio_records_rest.ptrn_list', patron_data)

    assert res.status_code == 201
    assert Patron.count() == pids + 1
    assert len(mailbox) == 0

    # Check that the returned record matches the given data
    data = get_json(res)
    data['metadata']['patron']['communication_channel'] = 'mail'

    ds = app.extensions['invenio-accounts'].datastore
    ds.delete_user(ds.find_user(id=patron_data['user_id']))
def test_patron_secure_api_create(app, client, patron_type_children_martigny,
                                  patron_martigny_data, librarian_martigny,
                                  librarian_sion):
    """Test patron secure api create."""
    # Martigny
    login_user_via_session(client, librarian_martigny.user)
    post_entrypoint = 'invenio_records_rest.ptrn_list'

    del patron_martigny_data['pid']
    patron_martigny_data['email'] = '*****@*****.**'
    patron_martigny_data['username'] = '******'
    data = create_user_from_data(patron_martigny_data)
    res, _ = postdata(client, post_entrypoint, data)
    assert res.status_code == 201

    # # Sion
    login_user_via_session(client, librarian_sion.user)

    res, _ = postdata(client, post_entrypoint, data)
    assert res.status_code == 403
    ds = app.extensions['invenio-accounts'].datastore
    ds.delete_user(ds.find_user(id=data['user_id']))
def test_patrons_post_put_delete(app, client, lib_martigny,
                                 patron_type_children_martigny,
                                 patron_martigny_data_tmp, json_header, roles,
                                 mailbox):
    """Test record retrieval."""
    pid_value = 'ptrn_1'
    item_url = url_for('invenio_records_rest.ptrn_item', pid_value=pid_value)
    list_url = url_for('invenio_records_rest.ptrn_list',
                       q='pid:%s' % pid_value)
    patron_data = deepcopy(patron_martigny_data_tmp)
    patron_data['email'] = '*****@*****.**'
    patron_data['username'] = '******'
    patron_data = create_user_from_data(patron_data)

    pids = Patron.count()
    assert len(mailbox) == 0

    # Create record / POST
    patron_data['pid'] = pid_value
    # patron_data['email'] = '*****@*****.**'
    # patron_data['username'] = '******'

    res, _ = postdata(client, 'invenio_records_rest.ptrn_list', patron_data)

    assert res.status_code == 201
    assert Patron.count() == pids + 1
    # assert len(mailbox) == 1
    # assert re.search(r'localhost/lost-password', mailbox[0].body)

    # # Check that the returned record matches the given data
    # data = get_json(res)
    # # remove dynamic property
    # del data['metadata']['user_id']
    # assert data['metadata'] == patron_data

    res = client.get(item_url)
    assert res.status_code == 200
    data = get_json(res)
    # add dynamic property
    patron_data['user_id'] = data['metadata']['user_id']
    data['metadata']['user_id']

    # Update record/PUT
    data = patron_data
    data['patron']['barcode'] = ['barcode_test']
    res = client.put(item_url, data=json.dumps(data), headers=json_header)
    assert res.status_code == 200
    # assert res.headers['ETag'] != '"{}"'.format(ptrnrarie.revision_id)

    # Check that the returned record matches the given data
    data = get_json(res)
    assert data['metadata']['patron']['barcode'][0] == 'barcode_test'

    res = client.get(item_url)
    assert res.status_code == 200

    data = get_json(res)
    assert data['metadata']['patron']['barcode'][0] == 'barcode_test'

    res = client.get(list_url)
    assert res.status_code == 200

    data = get_json(res)['hits']['hits'][0]
    assert data['metadata']['patron']['barcode'][0] == 'barcode_test'

    # Delete record/DELETE
    res = client.delete(item_url)
    assert res.status_code == 204

    res = client.get(item_url)
    assert res.status_code == 410
    ds = app.extensions['invenio-accounts'].datastore
    ds.delete_user(ds.find_user(id=patron_data['user_id']))
def test_librarian_permissions(client, system_librarian_martigny, json_header,
                               patron_martigny, librarian_fully,
                               patron_martigny_data_tmp, lib_saxon):
    """Test librarian permissions."""
    # Login as librarian
    login_user_via_session(client, librarian_fully.user)

    record = {
        "$schema": "https://ils.rero.ch/schemas/patrons/patron-v0.0.1.json",
        "first_name": "first_name",
        "last_name": "Last_name",
        "username": "******",
        "street": "Avenue Leopold-Robert, 132",
        "postal_code": "1920",
        "city": "Martigny",
        "birth_date": "1967-06-07",
        "patron": {
            "expiration_date": "2023-10-07",
            "type": {
                "$ref": "https://ils.rero.ch/api/patron_types/ptty1"
            },
            "communication_channel": "mail",
            "communication_language": "ita"
        },
        "libraries": [{
            "$ref": "https://ils.rero.ch/api/libraries/lib1"
        }],
        "home_phone": "+41324993111"
    }
    record = create_user_from_data(record)
    # can retrieve all type of users.
    list_url = url_for('invenio_records_rest.ptrn_list')
    res = client.get(list_url)
    assert res.status_code == 200
    data = get_json(res)
    assert data['hits']['total']['value'] == 3

    # can manage all types of patron roles
    role_url = url_for('api_patrons.get_roles_management_permissions')
    res = client.get(role_url)
    assert res.status_code == 200
    data = get_json(res)
    assert 'librarian' in data['allowed_roles']
    assert 'system_librarian' not in data['allowed_roles']

    # can create all type of users except system_librarians
    post_entrypoint = 'invenio_records_rest.ptrn_list'
    system_librarian = deepcopy(record)
    librarian = deepcopy(record)
    librarian_saxon = deepcopy(record)
    librarian_saxon['libraries'] = \
        [{"$ref": "https://ils.rero.ch/api/libraries/lib2"}]
    librarian['libraries'] = \
        [{"$ref": "https://ils.rero.ch/api/libraries/lib3"}]
    patron = deepcopy(record)
    patron['libraries'] = \
        [{"$ref": "https://ils.rero.ch/api/libraries/lib3"}]
    counter = 1
    for record in [
        {
            'data': patron,
            'role': 'patron'
        },
        {
            'data': librarian,
            'role': 'librarian'
        },
    ]:
        counter += 1
        data = record['data']
        data['roles'] = [record['role']]
        data['patron']['barcode'] = ['barcode' + str(counter)]

        res, _ = postdata(client, post_entrypoint, data)
        assert res.status_code == 201
        user = get_json(res)['metadata']
        user_pid = user.get('pid')
        record_url = url_for('invenio_records_rest.ptrn_item',
                             pid_value=user_pid)
        res = client.get(record_url)
        assert res.status_code == 200
        user = get_json(res)['metadata']

        # can update all type of user records except system_librarian.
        user['first_name'] = 'New Name' + str(counter)
        res = client.put(record_url,
                         data=json.dumps(user),
                         headers=json_header)
        assert res.status_code == 200

        # can not add the role system_librarian to user
        user['roles'] = ['system_librarian']
        res = client.put(record_url,
                         data=json.dumps(user),
                         headers=json_header)
        assert res.status_code == 403

        # can delete all type of user records except system_librarian.
        record_url = url_for('invenio_records_rest.ptrn_item',
                             pid_value=user_pid)

        res = client.delete(record_url)
        assert res.status_code == 204

    # can not create librarians of same libray.
    counter = 1
    for record in [
        {
            'data': librarian_saxon,
            'role': 'librarian'
        },
    ]:
        counter += 1
        data = record['data']
        data['roles'] = [record['role']]
        data['patron']['barcode'] = ['barcode' + str(counter)]
        res, _ = postdata(client, post_entrypoint, data)
        assert res.status_code == 403

    system_librarian['roles'] = ['system_librarian']
    system_librarian['patron']['barcode'] = ['barcode']

    res, _ = postdata(
        client,
        post_entrypoint,
        system_librarian,
    )
    assert res.status_code == 403

    # can update all type of user records except system_librarian.
    record_url = url_for('invenio_records_rest.ptrn_item',
                         pid_value=system_librarian_martigny.pid)
    system_librarian_martigny['first_name'] = 'New Name'
    res = client.put(record_url,
                     data=json.dumps(system_librarian_martigny),
                     headers=json_header)
    assert res.status_code == 403

    # can delete all type of user records except system_librarian.
    sys_librarian_pid = system_librarian_martigny.get('pid')
    record_url = url_for('invenio_records_rest.ptrn_item',
                         pid_value=sys_librarian_pid)

    res = client.delete(record_url)
    assert res.status_code == 403
Exemple #5
0
def test_patron_create(app, roles, lib_martigny, librarian_martigny_data_tmp,
                       patron_type_adults_martigny, mailbox):
    """Test Patron creation."""
    ds = app.extensions['invenio-accounts'].datastore
    email = librarian_martigny_data_tmp.get('email')

    # sanity checks
    assert len(mailbox) == 0
    assert User.query.count() == 0
    assert UserProfile.query.count() == 0
    l_martigny_data_tmp = librarian_martigny_data_tmp
    librarian_martigny_data_tmp = create_user_from_data(
        librarian_martigny_data_tmp)
    # wrong_librarian_martigny_data_tmp = deepcopy(librarian_martigny_data_tmp)
    # wrong_librarian_martigny_data_tmp.pop('first_name')
    # with pytest.raises(ValidationError):
    #     ptrn = Patron.create(
    #         wrong_librarian_martigny_data_tmp,
    #         dbcommit=True,
    #         delete_pid=True
    #     )

    wrong_librarian_martigny_data_tmp = deepcopy(librarian_martigny_data_tmp)
    wrong_librarian_martigny_data_tmp.pop('libraries')
    with pytest.raises(ValidationError):
        ptrn = Patron.create(wrong_librarian_martigny_data_tmp,
                             dbcommit=True,
                             delete_pid=True)

    wrong_librarian_martigny_data_tmp = deepcopy(librarian_martigny_data_tmp)
    wrong_librarian_martigny_data_tmp.setdefault(
        'patron', {
            'expiration_date': '2023-10-07',
            'barcode': ['2050124311'],
            'type': {
                '$ref': 'https://bib.rero.ch/api/patron_types/ptty2'
            },
            'communication_channel': 'email',
            'communication_language': 'ita'
        })
    wrong_librarian_martigny_data_tmp['patron']['subscriptions'] = [{
        'start_date':
        '2000-01-01',
        'end_date':
        '2001-01-01',
        'patron_type': {
            '$ref': 'https://bib.rero.ch/api/patron_types/xxx'
        },
        'patron_transaction': {
            '$ref': 'https://bib.rero.ch/api/patron_transactions/xxx'
        },
    }]
    with pytest.raises(ValidationError):
        ptrn = Patron.create(wrong_librarian_martigny_data_tmp,
                             dbcommit=True,
                             delete_pid=True)

    # no data has been created
    assert len(mailbox) == 0
    # assert User.query.count() == 0
    # assert UserProfile.query.count() == 0

    ptrn = Patron.create(librarian_martigny_data_tmp,
                         dbcommit=True,
                         delete_pid=False)
    user = User.query.filter_by(id=ptrn.get('user_id')).first()
    user_id = ptrn.get('user_id')
    assert user
    assert user.active
    for field in [
            'first_name', 'last_name', 'street', 'postal_code', 'city',
            'username', 'home_phone'
    ]:
        assert getattr(user.profile, field) == l_martigny_data_tmp.get(field)
    user.profile.birth_date == datetime.strptime(
        l_martigny_data_tmp.get('birth_date'), '%Y-%m-%d')
    user_roles = [r.name for r in user.roles]
    assert set(user_roles) == set(ptrn.get('roles'))
    # TODO: make these checks during the librarian POST creation
    # assert len(mailbox) == 1
    # assert re.search(r'localhost/lost-password', mailbox[0].body)
    # assert re.search(
    #     r'Someone requested that the password' +
    #     ' for your RERO ID account be reset.', mailbox[0].body
    # )
    # assert re.search(
    #     r'Best regards', mailbox[0].body
    # )
    # assert ptrn.get('email') in mailbox[0].recipients
    librarian_martigny_data_tmp['user_id'] = 1
    assert ptrn == librarian_martigny_data_tmp
    assert ptrn.get('pid') == 'ptrn2'

    ptrn = Patron.get_record_by_pid('ptrn2')
    # assert ptrn == librarian_martigny_data_tmp

    fetched_pid = patron_id_fetcher(ptrn.id, ptrn)
    assert fetched_pid.pid_value == 'ptrn2'
    assert fetched_pid.pid_type == 'ptrn'

    # set librarian
    roles = ['librarian']
    ptrn.update({'roles': roles}, dbcommit=True)
    user_roles = [r.name for r in user.roles]
    assert set(user_roles) == set(roles)
    roles = Patron.available_roles
    data = {
        'roles': Patron.available_roles,
        'patron': {
            'expiration_date': '2023-10-07',
            'barcode': ['2050124311'],
            'type': {
                '$ref': 'https://bib.rero.ch/api/patron_types/ptty2'
            },
            'communication_channel': 'email',
            'communication_language': 'ita'
        }
    }
    ptrn.update(data, dbcommit=True)
    user_roles = [r.name for r in user.roles]
    assert set(user_roles) == set(Patron.available_roles)

    # remove patron
    ptrn.delete(False, True, True)
    # user still exist in the invenio db
    user = ds.find_user(email=email)
    assert user
    # all roles has been removed
    assert not user.roles
    # assert len(mailbox) == 1
    # patron does not exists anymore
    ptrn = Patron.get_record_by_pid('ptrn2')
    assert ptrn is None
    ptrn = Patron.get_record_by_pid('ptrn2', with_deleted=True)
    assert ptrn == {}
    assert ptrn.persistent_identifier.pid_value == 'ptrn2'
    # remove patron
    ptrn.delete(True, True, True)
    # clean up the user
    ds.delete_user(user)
Exemple #6
0
def test_patron_create_without_email(app, roles, patron_type_children_martigny,
                                     patron_martigny_data_tmp, mailbox):
    """Test Patron creation without an email."""
    patron_martigny_data_tmp = deepcopy(patron_martigny_data_tmp)

    # no data has been created
    mailbox.clear()
    del patron_martigny_data_tmp['email']

    patron_martigny_data_tmp = \
        create_user_from_data(patron_martigny_data_tmp)

    # comminication channel require at least one email
    patron_martigny_data_tmp['patron']['communication_channel'] = 'email'
    with pytest.raises(ValidationError):
        ptrn = Patron.create(patron_martigny_data_tmp,
                             dbcommit=True,
                             delete_pid=True)

    # create a patron without email
    patron_martigny_data_tmp['patron']['communication_channel'] = 'mail'
    ptrn = Patron.create(patron_martigny_data_tmp,
                         dbcommit=True,
                         delete_pid=True)
    # user has been created
    user = User.query.filter_by(id=ptrn.get('user_id')).first()
    assert user
    assert not user.email
    assert user == ptrn.user
    assert user.active
    assert len(mailbox) == 0

    # # add an email of a non existing user
    # patron_martigny_data_tmp['email'] = '*****@*****.**'
    # ptrn.replace(
    #     data=patron_martigny_data_tmp,
    #     dbcommit=True
    # )
    # # the user remains the same
    # assert user == ptrn.user
    # assert user.email == patron_martigny_data_tmp['email']
    # assert user.active
    # assert len(mailbox) == 0

    # # update with a new email in the system
    # patron_martigny_data_tmp['email'] = '*****@*****.**'
    # ptrn.replace(
    #     data=patron_martigny_data_tmp,
    #     dbcommit=True
    # )
    # # the user remains the same
    # assert user == ptrn.user
    # assert user.email == patron_martigny_data_tmp['email']
    # assert user.active
    # assert len(mailbox) == 0

    # # remove the email
    # del patron_martigny_data_tmp['email']
    # ptrn.replace(
    #     data=patron_martigny_data_tmp,
    #     dbcommit=True
    # )
    # assert user == ptrn.user
    # assert not user.email
    # assert user.active
    # assert len(mailbox) == 0

    # # create a new invenio user in the system
    # rero_id_user = create_test_user(email='*****@*****.**', active=True)

    # # update the patron with the email of the freshed create invenio user
    # patron_martigny_data_tmp['email'] = '*****@*****.**'
    # patron_martigny_data_tmp['username'] = '******'
    # ptrn.replace(
    #     data=patron_martigny_data_tmp,
    #     dbcommit=True
    # )
    # # the user linked with the patron has been changed
    # assert rero_id_user == ptrn.user
    # # the username is updated on both user profile and patron
    # assert rero_id_user.profile.username == ptrn.get('username') == 'reroid'

    # clean up created users
    ds = app.extensions['invenio-accounts'].datastore
    ds.delete_user(user)
def test_system_librarian_permissions(
        client, json_header, system_librarian_martigny,
        patron_martigny, patron_type_adults_martigny,
        librarian_fully):
    """Test system_librarian permissions."""
    # Login as system_librarian
    login_user_via_session(client, system_librarian_martigny.user)

    record = {
        "$schema": "https://bib.rero.ch/schemas/patrons/patron-v0.0.1.json",
        "first_name": "first_name",
        "last_name": "Last_name",
        "username": "******",
        "street": "Avenue Leopold-Robert, 132",
        "postal_code": "1920",
        "city": "Martigny",
        "birth_date": "1967-06-07",
        "home_phone": "+41324993111"
    }

    record = create_user_from_data(record)
    # can retrieve all type of users.
    list_url = url_for('invenio_records_rest.ptrn_list')
    res = client.get(list_url)
    assert res.status_code == 200
    data = get_json(res)
    assert data['hits']['total']['value'] == 3

    # can manage all types of patron roles
    role_url = url_for('api_patrons.get_roles_management_permissions')
    res = client.get(role_url)
    assert res.status_code == 200
    data = get_json(res)
    assert 'system_librarian' in data['allowed_roles']

    # can create all type of users.
    system_librarian = deepcopy(record)
    librarian = deepcopy(record)
    patron = deepcopy(record)
    counter = 1
    records = [{
        'user': patron,
        'patch': {
            'roles': ['patron'],
            'patron': {
                'expiration_date': '2023-10-07',
                'communication_channel': CommunicationChannel.EMAIL,
                'communication_language': 'ita',
                'additional_communication_email': '*****@*****.**',
                'type': {
                    '$ref': 'https://bib.rero.ch/api/patron_types/ptty2'
                }
            }
        }
    }, {
        'user': librarian,
        'patch': {
            'roles': ['librarian'],
            'libraries': [{'$ref': 'https://bib.rero.ch/api/libraries/lib1'}]
        }
    }, {
        'user': system_librarian,
        'patch': {
            'roles': ['librarian', 'system_librarian'],
            'libraries': [{
                '$ref': 'https://bib.rero.ch/api/libraries/lib1'
            }]
        }
    }]
    for record in records:
        counter += 1
        data = record['user']
        data.update(record['patch'])
        if data.get('patron'):
            data['patron']['barcode'] = ['barcode' + str(counter)]
        res, _ = postdata(
            client,
            'invenio_records_rest.ptrn_list',
            data
        )
        assert res.status_code == 201
        user = get_json(res)['metadata']
        user_pid = user.get('pid')
        record_url = url_for('invenio_records_rest.ptrn_item',
                             pid_value=user_pid)
        res = client.get(record_url)
        assert res.status_code == 200
        user = get_json(res)['metadata']

        # can update all type of user records.
        res = client.put(
            record_url,
            data=json.dumps(user),
            headers=json_header
        )
        assert res.status_code == 200

        # can delete all type of user records.
        record_url = url_for('invenio_records_rest.ptrn_item',
                             pid_value=user_pid)

        res = client.delete(record_url)
        assert res.status_code == 204