refactor: Address OpenID role-sync review feedback

- role.ts: reuse the shared escapeRegExp util instead of a local escapeRegex
  duplicate, matching prompt/skill/user/userGroup methods (Copilot).
- openidStrategy.js / remoteAgentAuth.ts: make the tenantStorage.run callbacks
  async so the documented ALS contract is satisfied and tenant context cannot
  be lost during Mongoose execution; the wrapped lookups/updates are already
  async, so behavior is unchanged (codex P2).
This commit is contained in:
Danny Avila 2026-05-30 11:38:18 -04:00
parent a7821e2080
commit c3cc330a19
3 changed files with 5 additions and 8 deletions

View file

@ -526,7 +526,7 @@ async function applyOpenIdRoleSync({
/** Role definitions are tenant-scoped, so validate configured roles in the matched user's tenant. */
const { rolePriority, fallbackRole } = user?.tenantId
? await tenantStorage.run({ tenantId: user.tenantId }, () =>
? await tenantStorage.run({ tenantId: user.tenantId }, async () =>
getLibreChatRolesForOpenIdSync(libreChatRoles),
)
: await getLibreChatRolesForOpenIdSync(libreChatRoles);

View file

@ -487,7 +487,7 @@ async function selectOpenIdRoleForOpenIdSync(
return;
}
const loadLibreChatRoles = () =>
const loadLibreChatRoles = async () =>
getLibreChatRolesForOpenIdSync({
getRolesByNames,
rolePriority: options.rolePriority,
@ -523,7 +523,7 @@ async function updateResolvedUser(
return;
}
const update = () => updateUser(userResolution.user.id, userResolution.updateData);
const update = async () => updateUser(userResolution.user.id, userResolution.updateData);
if (userResolution.user.tenantId && getTenantId() !== userResolution.user.tenantId) {
await tenantStorage.run({ tenantId: userResolution.user.tenantId }, update);
return;

View file

@ -8,6 +8,7 @@ import {
import type { Model } from 'mongoose';
import type { IRole, IUser } from '~/types';
import { scopedCacheKey } from '~/config/tenantContext';
import { escapeRegExp } from '~/utils/string';
import logger from '~/config/winston';
const systemRoleValues = new Set<string>(Object.values(SystemRoles));
@ -17,10 +18,6 @@ function isSystemRoleName(name: string): boolean {
return systemRoleValues.has(name.toUpperCase());
}
function escapeRegex(value: string): string {
return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
export class RoleConflictError extends Error {
constructor(message: string) {
super(message);
@ -146,7 +143,7 @@ export function createRoleMethods(mongoose: typeof import('mongoose'), deps: Rol
const Role = mongoose.models.Role;
let query = Role.find({
$or: uniqueRoleNames.map((roleName) => ({
name: new RegExp(`^${escapeRegex(roleName)}$`, 'i'),
name: new RegExp(`^${escapeRegExp(roleName)}$`, 'i'),
})),
});
if (fieldsToSelect) {