Skip to content

Commit fe6515e

Browse files
committed
fix(identity): create the identity when missing
- when the identity is missing, the sync will not create it without failing
1 parent 3903b1a commit fe6515e

3 files changed

Lines changed: 50 additions & 13 deletions

File tree

.github/workflows/pypi-publish.yml

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
# Invenio-CERN-sync is free software; you can redistribute it and/or modify it
66
# under the terms of the MIT License; see LICENSE file for more details.
77

8-
98
name: Publish
109

1110
on:
@@ -17,7 +16,7 @@ jobs:
1716
build-n-publish:
1817
runs-on: ubuntu-latest
1918
steps:
20-
- uses: actions/checkout@v4
19+
- uses: actions/checkout@v5
2120
- name: Set up Python 3.12
2221
uses: actions/setup-python@v5
2322
with:
@@ -30,9 +29,8 @@ jobs:
3029
run: |
3130
python setup.py sdist bdist_wheel
3231
- name: pypi-publish
33-
uses: pypa/gh-action-pypi-publish@v1.3.1
32+
uses: pypa/gh-action-pypi-publish@v1.13
3433
with:
3534
user: __token__
3635

3736
password: ${{ secrets.pypi_token }}
38-

invenio_cern_sync/users/sync.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from ..ldap.client import LdapClient
2222
from ..ldap.serializer import serialize_ldap_users
2323
from ..logging import log_info, log_warning
24+
from ..sso import cern_remote_app_name
2425
from .api import create_user, update_existing_user
2526

2627

@@ -131,16 +132,17 @@ def _update_existing(users, serializer_fn, log_uuid, log_name, persist_every=500
131132
)
132133
invenio_user["remote_account_extra_data"]["changes"] = ra_extra_data
133134
elif user and (not user_identity or user_identity.id_user != user.id):
134-
# The `identity_id` changed.
135-
# The `identity_id` of the UserIdentity associated to the User
136-
# will have to be updated.
135+
# The `identity_id` changed or it does not exist yet.
137136
try:
138137
user_identity = UserIdentity.query.filter_by(id_user=user.id).one()
139138
except NoResultFound:
140-
current_app.logger.error(
141-
f"UserIdentity not found for user.id={user.id}. Skipping this user..."
139+
UserIdentity.create(
140+
user,
141+
cern_remote_app_name,
142+
invenio_user["user_identity_id"],
142143
)
143-
continue
144+
db.session.flush()
145+
user_identity = UserIdentity.query.filter_by(id_user=user.id).one()
144146

145147
_ra_extra_data = invenio_user["remote_account_extra_data"].get(
146148
"changes", []
@@ -211,7 +213,7 @@ def _insert_missing(invenio_users, log_uuid, log_name, persist_every=500):
211213
db.session.commit()
212214

213215
except Exception as e:
214-
current_app.logger.error(
216+
current_app.logger.warning(
215217
f"Error creating user from CERN data: {e}. Skipping this user... User: {invenio_user}"
216218
)
217219
continue

tests/test_sync_users.py

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,44 @@ def test_sync_person_id_change(
259259
"users-sync",
260260
dict(action="updating-existing-users", msg=expected_log_msg),
261261
log_uuid=mock.ANY,
262-
),
262+
)
263+
264+
265+
@patch("invenio_cern_sync.users.sync.KeycloakService")
266+
@patch("invenio_cern_sync.users.sync.AuthZService")
267+
@patch("invenio_cern_sync.users.sync.log_warning")
268+
def test_sync_identity_missing(
269+
mock_log_warning,
270+
MockAuthZService,
271+
MockKeycloakService,
272+
app,
273+
cern_identities,
274+
db,
275+
):
276+
"""Test sync identity missing."""
277+
# prepare the db with the initial data
278+
client_id = app.config["CERN_APP_CREDENTIALS"]["consumer_key"]
279+
280+
MockAuthZService.return_value.get_identities.return_value = cern_identities
281+
sync(method="AuthZ")
282+
283+
# delete the first identity from the DB
284+
first = cern_identities[0]
285+
previous_person_id = first["personId"]
286+
UserIdentity.query.filter_by(id=first["personId"]).delete()
287+
db.session.commit()
288+
MockAuthZService.return_value.get_identities.return_value = cern_identities
289+
sync(method="AuthZ")
290+
291+
# check that the user identity was updated, but the user was not duplicated
292+
assert UserIdentity.query.filter_by(id=first["personId"]).one()
293+
user = User.query.filter_by(email=first["primaryAccountEmail"]).one()
294+
expected_log_msg = f"Identity Id changed for User `{user.username}` `{user.email}`. Previous UserIdentity.id in the local DB: `{previous_person_id}` - New Identity Id from CERN DB: `{first['personId']}`."
295+
mock_log_warning.assert_any_call(
296+
"users-sync",
297+
dict(action="updating-existing-users", msg=expected_log_msg),
298+
log_uuid=mock.ANY,
299+
)
263300

264301

265302
@patch("invenio_cern_sync.users.sync.KeycloakService")
@@ -308,4 +345,4 @@ def test_sync_username_email_change(
308345
"users-sync",
309346
dict(action="updating-existing-users", msg=expected_log_msg),
310347
log_uuid=mock.ANY,
311-
),
348+
)

0 commit comments

Comments
 (0)