# UNDF: UNDF-2026-000000132 --- a/keystone/api/users.py +++ b/keystone/api/users.py @@ -645,13 +645,17 @@ class UserResource(ks_flask.ResourceBase): roles = self._normalize_role_list(app_cred_data['roles']) - # loop over all roles implied by the current role and add it - # explicitly if not already there - for role in roles: + # Build a seen-set to deduplicate in O(1) instead of O(n) list scan. + seen_role_ids = {r['id'] for r in roles} + # Iterate over a snapshot so in-loop appends don't extend the loop. + for role in list(roles): for implied_role in PROVIDERS.role_api.list_implied_roles( role['id'] ): imp_role_obj = PROVIDERS.role_api.get_role( implied_role['implied_role_id'] ) - if imp_role_obj['id'] not in [x['id'] for x in roles]: + if imp_role_obj['id'] not in seen_role_ids: + seen_role_ids.add(imp_role_obj['id']) roles.append(imp_role_obj) - # NOTE(cmurphy): The user is not allowed to add a role that is not - # in their token. - token_roles = [r['id'] for r in token.roles] + token_role_ids = {r['id'] for r in token.roles} for role in roles: - if role['id'] not in token_roles: + if role['id'] not in token_role_ids: detail = _( 'Cannot create an application credential with ' 'unassigned role'