def inner(self, person_id, *args, **kwargs): results = ( PatronsSearch().filter("term", person_id=person_id).execute() ) if not len(results.hits.hits): abort(404) patron = results.hits.hits[0]["_source"] return f(self, patron=patron.to_dict(), *args, **kwargs)
def get_user_by_legacy_id(legacy_id): """Get ES object of the patron.""" search = PatronsSearch().query( "bool", filter=[ Q("term", legacy_id=legacy_id), ], ) results = search.execute() hits_total = results.hits.total.value if not results.hits or hits_total < 1: click.secho("no user found with legacy_id {}".format(legacy_id), fg="red") return None elif hits_total > 1: raise UserMigrationError( "found more than one user with legacy_id {}".format(legacy_id)) else: return results.hits[0]
def test_update_users(app, db, testdata, mocker): """Test update users with LDAP.""" ldap_users = [ { "displayName": [b"New user"], "department": [b"A department"], "uidNumber": [b"111"], "mail": [b"*****@*****.**"], "cernAccountType": [b"Primary"], "employeeID": [b"00111"], "postOfficeBox": [b"M12345"] }, { "displayName": [b"A new name"], "department": [b"A new department"], "uidNumber": [b"222"], "mail": [b"*****@*****.**"], "cernAccountType": [b"Primary"], "employeeID": [b"00222"], "postOfficeBox": [b"M12345"] }, { "displayName": [b"Nothing changed"], "department": [b"Same department"], "uidNumber": [b"333"], "mail": [b"*****@*****.**"], "cernAccountType": [b"Primary"], "employeeID": [b"00333"], "postOfficeBox": [b"M12345"] }, { "displayName": [b"Name 1"], "department": [b"Department 1"], "uidNumber": [b"555"], "mail": [b"*****@*****.**"], "cernAccountType": [b"Primary"], "employeeID": [b"00555"], "postOfficeBox": [b"M12345"] }, { "displayName": [b"Name 2"], "department": [b"Department 2"], "uidNumber": [b"666"], "mail": [b"*****@*****.**"], # same email as 555 "cernAccountType": [b"Primary"], "employeeID": [b"00666"], "postOfficeBox": [b"M12345"] }, { "displayName": [b"Name"], "department": [b"Department"], "uidNumber": [b"777"], # missing email, should be skipped "cernAccountType": [b"Primary"], "employeeID": [b"00777"], "postOfficeBox": [b"M12345"] }, { "displayName": [b"Name"], "department": [b"Department"], "uidNumber": [b"999"], # custom emails allowed "mail": [b"*****@*****.**"], "cernAccountType": [b"Primary"], "employeeID": [b"00999"], "postOfficeBox": [b"M12345"] }, { "displayName": [b"Nothing changed"], "department": [b"Same department"], "uidNumber": [b"333"], # same email as 333, different employee ID, should be skipped "mail": [b"*****@*****.**"], "cernAccountType": [b"Primary"], "employeeID": [b"9152364"], "postOfficeBox": [b"M12345"] }, { "displayName": [b"Name"], "department": [b"Department"], "uidNumber": [b"444"], # empty email should be skipped "mail": [b""], "cernAccountType": [b"Primary"], "employeeID": [b"00444"], "postOfficeBox": [b"M12345"] }, ] def _prepare(): """Prepare data.""" importer = LdapUserImporter() # Prepare users in DB. Use `LdapUserImporter` to make it easy # create old users WILL_BE_UPDATED = deepcopy(ldap_users[1]) WILL_BE_UPDATED["displayName"] = [b"Previous name"] WILL_BE_UPDATED["department"] = [b"Old department"] ldap_user = serialize_ldap_user(WILL_BE_UPDATED) importer.import_user(ldap_user) WILL_NOT_CHANGE = deepcopy(ldap_users[2]) ldap_user = serialize_ldap_user(WILL_NOT_CHANGE) importer.import_user(ldap_user) # create a user that does not exist anymore in LDAP, but will not # be deleted for safety COULD_BE_DELETED = { "displayName": [b"old user left CERN"], "department": [b"Department"], "uidNumber": [b"444"], "mail": [b"*****@*****.**"], "cernAccountType": [b"Primary"], "employeeID": [b"00444"], "postOfficeBox": [b"M12345"] } ldap_user = serialize_ldap_user(COULD_BE_DELETED) importer.import_user(ldap_user) db.session.commit() current_app_ils.patron_indexer.reindex_patrons() def _prepare_duplicate(): duplicated = { "displayName": [b"Name 2"], "department": [b"Department 2"], # same id as one of the previous, different emails # should be skipped "uidNumber": [b"555"], "mail": [b"*****@*****.**"], "cernAccountType": [b"Primary"], "employeeID": [b"00555"], "postOfficeBox": [b"M12345"] } importer = LdapUserImporter() ldap_user = serialize_ldap_user(duplicated) importer.import_user(ldap_user) db.session.commit() _prepare() # mock LDAP response mocker.patch( "cds_ils.ldap.api.LdapClient.get_primary_accounts", return_value=ldap_users, ) n_ldap, n_updated, n_added = update_users() current_search.flush_and_refresh(index="*") assert n_ldap == 9 assert n_updated == 1 # 00222 assert n_added == 3 # 00111, 00555, 00999 invenio_users = User.query.all() # 2 are already in test data # 4 in the prepared data # 2 newly added from LDAP assert len(invenio_users) == 8 patrons_search = PatronsSearch() def check_existence(expected_email, expected_name, expected_department, expected_person_id, expected_mailbox): """Assert exist in DB and ES.""" # check if saved in DB user = User.query.filter_by(email=expected_email).one() up = UserProfile.query.filter_by(user_id=user.id).one() assert up.full_name == expected_name ra = RemoteAccount.query.filter_by(user_id=user.id).one() assert ra.extra_data["department"] == expected_department assert ra.extra_data["person_id"] == expected_person_id # check if indexed correctly results = patrons_search.filter("term", id=user.id).execute() assert len(results.hits) == 1 patron_hit = [r for r in results][0] assert patron_hit["email"] == expected_email assert patron_hit["department"] == expected_department assert patron_hit["person_id"] == expected_person_id assert patron_hit["mailbox"] == expected_mailbox check_existence("*****@*****.**", "New user", "A department", "00111", "M12345") check_existence("*****@*****.**", "A new name", "A new department", "00222", "M12345") check_existence("*****@*****.**", "Nothing changed", "Same department", "00333", "M12345") check_existence("*****@*****.**", "old user left CERN", "Department", "00444", "M12345") check_existence("*****@*****.**", "Name 1", "Department 1", "00555", "M12345") # try ot import duplicated userUID with pytest.raises(IntegrityError): _prepare_duplicate()
def test_sync_users(app, db, testdata, mocker): """Test sync users with LDAP.""" ldap_users = [ { "displayName": [b"New user"], "department": [b"A department"], "uidNumber": [b"111"], "mail": [b"*****@*****.**"], "cernAccountType": [b"Primary"], "employeeID": [b"111"], }, { "displayName": [b"A new name"], "department": [b"A new department"], "uidNumber": [b"222"], "mail": [b"*****@*****.**"], "cernAccountType": [b"Primary"], "employeeID": [b"222"], }, { "displayName": [b"Nothing changed"], "department": [b"Same department"], "uidNumber": [b"333"], "mail": [b"*****@*****.**"], "cernAccountType": [b"Primary"], "employeeID": [b"333"], }, { "displayName": [b"Name 1"], "department": [b"Department 1"], "uidNumber": [b"555"], "mail": [b"*****@*****.**"], "cernAccountType": [b"Primary"], "employeeID": [b"555"], }, { "displayName": [b"Name 2"], "department": [b"Department 2"], "uidNumber": [b"666"], "mail": [b"*****@*****.**"], # same email as 555 "cernAccountType": [b"Primary"], "employeeID": [b"666"], }, { "displayName": [b"Name"], "department": [b"Department"], "uidNumber": [b"777"], # missing email "cernAccountType": [b"Primary"], "employeeID": [b"777"], }, ] # mock LDAP response mocker.patch( "cds_ils.ldap.api.LdapClient.get_primary_accounts", return_value=ldap_users, ) def _prepare(): """Prepare data.""" # Prepare users in DB. Use `LdapUserImporter` to make it easy # create old users WILL_BE_UPDATED = deepcopy(ldap_users[1]) WILL_BE_UPDATED["displayName"] = [b"Previous name"] WILL_BE_UPDATED["department"] = [b"Old department"] LdapUserImporter().import_user(WILL_BE_UPDATED) WILL_NOT_CHANGE = deepcopy(ldap_users[2]) LdapUserImporter().import_user(WILL_NOT_CHANGE) # create a user that does not exist anymore in LDAP, but will not # be deleted for safety COULD_BE_DELETED = { "displayName": [b"old user left CERN"], "department": [b"Department"], "uidNumber": [b"444"], "mail": [b"*****@*****.**"], "cernAccountType": [b"Primary"], "employeeID": [b"444"], } LdapUserImporter().import_user(COULD_BE_DELETED) db.session.commit() reindex_patrons() _prepare() n_ldap, n_updated, n_added = update_users() current_search.flush_and_refresh(index="*") assert n_ldap == 6 assert n_updated == 1 assert n_added == 2 invenio_users = User.query.all() assert len(invenio_users) == 6 # 5 from LDAP, 1 was already in test data patrons_search = PatronsSearch() def check_existence(expected_email, expected_name, expected_department): """Assert exist in DB and ES.""" # check if saved in DB user = User.query.filter_by(email=expected_email).one() up = UserProfile.query.filter_by(user_id=user.id).one() assert up.full_name == expected_name ra = RemoteAccount.query.filter_by(user_id=user.id).one() assert ra.extra_data["department"] == expected_department # check if indexed correctly results = patrons_search.filter("term", id=user.id).execute() assert len(results.hits) == 1 patron_hit = [r for r in results][0] assert patron_hit["email"] == expected_email assert patron_hit["department"] == expected_department check_existence("*****@*****.**", "New user", "A department") check_existence("*****@*****.**", "A new name", "A new department") check_existence( "*****@*****.**", "Nothing changed", "Same department" ) check_existence("*****@*****.**", "old user left CERN", "Department") check_existence("*****@*****.**", "Name 1", "Department 1")