Exemplo n.º 1
0
 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)
Exemplo n.º 2
0
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]
Exemplo n.º 3
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()
Exemplo n.º 4
0
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")