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
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)
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