Skip to content

Commit

Permalink
groups: fetch async to improve login performance
Browse files Browse the repository at this point in the history
  • Loading branch information
ntarocco authored and zzacharo committed Aug 18, 2023
1 parent 69a211a commit 64d4952
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 29 deletions.
3 changes: 3 additions & 0 deletions invenio.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ SECURITY_SEND_REGISTER_EMAIL = False
# See https://github.com/inveniosoftware/invenio-oauthclient/blob/master/invenio_oauthclient/config.py
from invenio_oauthclient.contrib.keycloak import KeycloakSettingsHelper
from cds_rdm.oidc import (
cern_info_handler,
cern_info_serializer,
confirm_registration_form,
cern_groups_serializer,
Expand Down Expand Up @@ -240,6 +241,7 @@ OAUTHCLIENT_CERN_USER_INFO_FROM_ENDPOINT = True
handlers = _keycloak_helper.get_handlers()
handlers["signup_handler"] = {
**handlers["signup_handler"],
"info": cern_info_handler,
"info_serializer": cern_info_serializer,
"groups_serializer": cern_groups_serializer,
"groups": cern_groups_handler,
Expand All @@ -248,6 +250,7 @@ handlers["signup_handler"] = {
rest_handlers = _keycloak_helper.get_rest_handlers()
rest_handlers["signup_handler"] = {
**rest_handlers["signup_handler"],
"info": cern_info_handler,
"info_serializer": cern_info_serializer,
"groups_serializer": cern_groups_serializer,
"groups": cern_groups_handler,
Expand Down
8 changes: 0 additions & 8 deletions site/cds_rdm/ext.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@

"""CDS-RDM exceptions."""

from flask_principal import identity_loaded

from .oidc import load_user_role_needs


class CDS_RDM_App(object):
"""CDS-RDM App."""
Expand All @@ -19,10 +15,6 @@ def __init__(self, app):
"""Constructor."""
self.app = app

@identity_loaded.connect_via(app)
def on_identity_loaded(_, identity):
load_user_role_needs(identity)


class CDS_RDM_UI(object):
"""CDS-RDM extension."""
Expand Down
41 changes: 20 additions & 21 deletions site/cds_rdm/oidc.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@

"""OIDC settings."""

from flask import current_app, session
from flask_login import current_user
from flask_principal import RoleNeed, UserNeed
from flask import current_app, g
from invenio_db import db
from invenio_oauthclient import current_oauthclient, oauth_link_external_id
from invenio_oauthclient.contrib.keycloak.handlers import get_user_info
Expand All @@ -35,7 +33,8 @@ class _Form(Form):
def cern_groups_serializer(remote, groups, **kwargs):
"""Serialize the groups response object."""
serialized_groups = []
# E-groups do have unique names and this name cannot be updated, therefore the name can act as an ID for invenio
# E-groups do have unique names and this name cannot be updated,
# therefore the name can act as an ID for invenio
for group_name in groups:
serialized_groups.append({"id": group_name, "name": group_name})

Expand Down Expand Up @@ -63,14 +62,28 @@ def cern_setup_handler(remote, token, resp):


def cern_groups_handler(remote, resp):
"""Retrieves groups from remote account."""
token_user_info, _ = get_user_info(remote, resp)
groups = token_user_info.get("groups", [])
"""Retrieves groups from remote account.
Groups are already part of the response token
"""
groups = g.pop("_cern_groups", [])
handlers = current_oauthclient.signup_handlers[remote.name]
# `remote` param automatically injected via `make_handler` helper
return handlers["groups_serializer"](groups)


def cern_info_handler(remote, resp):
"""Info handler."""
token_user_info, user_info = get_user_info(remote, resp)

# Add the user_info to the request, so it can be used in the groups handler
# to avoid yet another request to the user info endpoint
g._cern_groups = user_info.get("groups", [])

handlers = current_oauthclient.signup_handlers[remote.name]
return handlers["info_serializer"](resp, token_user_info, user_info)


def cern_info_serializer(remote, resp, token_user_info, user_info):
"""Info serializer."""
user_info = user_info or {}
Expand Down Expand Up @@ -98,17 +111,3 @@ def cern_info_serializer(remote, resp, token_user_info, user_info):
"external_id": external_id,
"external_method": remote.name,
}


def load_user_role_needs(identity):
"""Store roles in session whenever identity is loaded."""
if identity.id is None:
# no user is logged in
return

needs = set()
needs.add(UserNeed(current_user.email))
roles_ids = session.get("unmanaged_roles_ids", [])
for role_id in roles_ids:
needs.add(RoleNeed(role_id))
identity.provides |= needs

0 comments on commit 64d4952

Please sign in to comment.