diff --git a/apps/mesh/src/core/context-factory.ts b/apps/mesh/src/core/context-factory.ts index c2f43674e..26aab191a 100644 --- a/apps/mesh/src/core/context-factory.ts +++ b/apps/mesh/src/core/context-factory.ts @@ -473,11 +473,29 @@ async function authenticateRequest( try { const meshJwtPayload = await verifyMeshToken(token); if (meshJwtPayload) { + // Look up user's organization role for admin/owner bypass + let role: string | undefined; + if (meshJwtPayload.sub && meshJwtPayload.metadata?.organizationId) { + const membership = await db + .selectFrom("member") + .select(["member.role"]) + .where("member.userId", "=", meshJwtPayload.sub) + .where( + "member.organizationId", + "=", + meshJwtPayload.metadata.organizationId, + ) + .executeTakeFirst(); + role = membership?.role; + } + return { user: { id: meshJwtPayload.sub, connectionId: meshJwtPayload.metadata?.connectionId, + role, }, + role, permissions: meshJwtPayload.permissions, organization: meshJwtPayload.metadata?.organizationId ? { @@ -505,9 +523,22 @@ async function authenticateRequest( // API keys have permissions stored directly on them const permissions = result.key.permissions as Permission | undefined; + // Look up user's organization role for admin/owner bypass + let role: string | undefined; + if (result.key.userId && orgMetadata?.id) { + const membership = await db + .selectFrom("member") + .select(["member.role"]) + .where("member.userId", "=", result.key.userId) + .where("member.organizationId", "=", orgMetadata.id) + .executeTakeFirst(); + role = membership?.role; + } + return { apiKeyId: result.key.id, - user: { id: result.key.userId }, // Include userId from API key + user: { id: result.key.userId, role }, // Include userId and role from membership + role, permissions, // Store the API key's permissions organization: orgMetadata ? {