Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

utils: improve group create or update #343

Merged
merged 2 commits into from
Dec 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
Changes
=======

Version 4.1.3 (release 2024-12-03)

- utils: improve and fix creation/update of groups

Version 4.1.2 (release 2024-11-30)

- setup: pin dependencies
Expand Down
2 changes: 1 addition & 1 deletion invenio_oauthclient/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from .oauth import oauth_link_external_id, oauth_unlink_external_id
from .proxies import current_oauthclient

__version__ = "4.1.2"
__version__ = "4.1.3"

__all__ = (
"__version__",
Expand Down
58 changes: 36 additions & 22 deletions invenio_oauthclient/handlers/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from flask_login import current_user
from invenio_accounts.models import Role
from invenio_accounts.proxies import current_datastore
from invenio_db import db
from werkzeug.utils import import_string

from ..models import RemoteAccount
Expand Down Expand Up @@ -108,49 +109,62 @@ def _role_needs_update(role_obj, new_role_dict):
return False


def create_or_update_roles(groups):
def create_or_update_roles(groups, persist_every=500):
"""Create/update DB roles based on the groups provided."""
roles_ids = set()
processed_count = 0

for group in groups:
try:
current_app.logger.debug(f"Syncing role: {group['name']}")

existing_role = current_datastore.find_role_by_id(group["id"])
if existing_role and existing_role.is_managed:
current_app.logger.exception(
f'Error while syncing roles: A managed role with id: ${group["id"]} already exists'
f'Error while syncing roles: A managed role with id: {group["id"]} already exists'
)
continue

existing_role_by_name = current_datastore.find_role(group["name"])
if existing_role_by_name and existing_role_by_name.is_managed:
current_app.logger.exception(
f'Error while syncing roles: A managed role with name: ${group["name"]} already exists'
f'Error while syncing roles: A managed role with name: {group["name"]} already exists'
)
continue
if not existing_role:
role = current_datastore.create_role(
id=group["id"],
name=group["name"],
description=group.get("description"),
is_managed=False,
)
roles_ids.add(role.id)
elif existing_role and _role_needs_update(existing_role, group):
role_to_update = Role(
id=group["id"],
name=group["name"],
description=group.get("description"),
is_managed=False,
)
role = current_datastore.update_role(role_to_update)
roles_ids.add(role.id)
else:
roles_ids.add(existing_role.id)

with db.session.begin_nested():
if not existing_role:
role = current_datastore.create_role(
id=group["id"],
name=group["name"],
description=group.get("description"),
is_managed=False,
)
roles_ids.add(role.id)
elif existing_role and _role_needs_update(existing_role, group):
role_to_update = Role(
id=group["id"],
name=group["name"],
description=group.get("description"),
is_managed=False,
)
role = current_datastore.update_role(role_to_update)
roles_ids.add(role.id)
else:
roles_ids.add(existing_role.id)

processed_count += 1

# Commit every `persist_every` iterations
if processed_count % persist_every == 0:
current_datastore.commit()

except Exception as e:
current_app.logger.error(
f"Error while syncing roles: {group['name']}. Error: {e}"
)
continue

# Final commit for any remaining uncommitted changes
current_datastore.commit()
return roles_ids