🪺 refactor: Nest Permission fields for Roles (#6487)

* 🏗️ feat: Add Group model and schema with GroupType enum

* 🏗️ feat: Introduce Permissions module and refactor role-based access control

* 🏗️ feat: Refactor permissions handling and consolidate permission schemas

* 🏗️ feat: Refactor role permissions handling and improve role initialization logic

* 🏗️ feat: Update Role.spec.js to improve imports and enhance test structure

* 🏗️ feat: Update access control logic to ensure proper permission checks in role handling

* 🏗️ chore: Bump versions for librechat-data-provider to 0.7.75 and @librechat/data-schemas to 0.0.6

* 🏗️ feat: Improve role permissions handling by ensuring defaults are applied correctly

* 🏗️ feat: Update role permissions schema to comment out unused SHARE permission

* 🏗️ chore: Bump version of librechat-data-provider to 0.7.77 and remove unused groups field from IUser interface

* 🏗️ chore: Downgrade version of librechat-data-provider to 0.7.76

* 🔧 chore: Bump versions for librechat-data-provider to 0.7.77 and data-schemas to 0.0.6

* 🏗️ chore: Update version of librechat-data-provider to 0.7.789

---------

Co-authored-by: Danny Avila <danny@librechat.ai>
This commit is contained in:
Ruben Talstra 2025-04-05 01:47:14 +02:00 committed by GitHub
parent 710fde6a6f
commit 0551a562d8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 394 additions and 411 deletions

View file

@ -15,6 +15,7 @@ export * from './models';
/* mcp */
export * from './mcp';
/* RBAC */
export * from './permissions';
export * from './roles';
/* types (exports schemas from `./types` as they contain needed in other defs) */
export * from './types';

View file

@ -0,0 +1,90 @@
import { z } from 'zod';
/**
* Enum for Permission Types
*/
export enum PermissionTypes {
/**
* Type for Prompt Permissions
*/
PROMPTS = 'PROMPTS',
/**
* Type for Bookmark Permissions
*/
BOOKMARKS = 'BOOKMARKS',
/**
* Type for Agent Permissions
*/
AGENTS = 'AGENTS',
/**
* Type for Multi-Conversation Permissions
*/
MULTI_CONVO = 'MULTI_CONVO',
/**
* Type for Temporary Chat
*/
TEMPORARY_CHAT = 'TEMPORARY_CHAT',
/**
* Type for using the "Run Code" LC Code Interpreter API feature
*/
RUN_CODE = 'RUN_CODE',
}
/**
* Enum for Role-Based Access Control Constants
*/
export enum Permissions {
SHARED_GLOBAL = 'SHARED_GLOBAL',
USE = 'USE',
CREATE = 'CREATE',
UPDATE = 'UPDATE',
READ = 'READ',
READ_AUTHOR = 'READ_AUTHOR',
SHARE = 'SHARE',
}
export const promptPermissionsSchema = z.object({
[Permissions.SHARED_GLOBAL]: z.boolean().default(false),
[Permissions.USE]: z.boolean().default(true),
[Permissions.CREATE]: z.boolean().default(true),
// [Permissions.SHARE]: z.boolean().default(false),
});
export type TPromptPermissions = z.infer<typeof promptPermissionsSchema>;
export const bookmarkPermissionsSchema = z.object({
[Permissions.USE]: z.boolean().default(true),
});
export type TBookmarkPermissions = z.infer<typeof bookmarkPermissionsSchema>;
export const agentPermissionsSchema = z.object({
[Permissions.SHARED_GLOBAL]: z.boolean().default(false),
[Permissions.USE]: z.boolean().default(true),
[Permissions.CREATE]: z.boolean().default(true),
// [Permissions.SHARE]: z.boolean().default(false),
});
export type TAgentPermissions = z.infer<typeof agentPermissionsSchema>;
export const multiConvoPermissionsSchema = z.object({
[Permissions.USE]: z.boolean().default(true),
});
export type TMultiConvoPermissions = z.infer<typeof multiConvoPermissionsSchema>;
export const temporaryChatPermissionsSchema = z.object({
[Permissions.USE]: z.boolean().default(true),
});
export type TTemporaryChatPermissions = z.infer<typeof temporaryChatPermissionsSchema>;
export const runCodePermissionsSchema = z.object({
[Permissions.USE]: z.boolean().default(true),
});
export type TRunCodePermissions = z.infer<typeof runCodePermissionsSchema>;
// Define a single permissions schema that holds all permission types.
export const permissionsSchema = z.object({
[PermissionTypes.PROMPTS]: promptPermissionsSchema,
[PermissionTypes.BOOKMARKS]: bookmarkPermissionsSchema,
[PermissionTypes.AGENTS]: agentPermissionsSchema,
[PermissionTypes.MULTI_CONVO]: multiConvoPermissionsSchema,
[PermissionTypes.TEMPORARY_CHAT]: temporaryChatPermissionsSchema,
[PermissionTypes.RUN_CODE]: runCodePermissionsSchema,
});

View file

@ -1,4 +1,15 @@
import { z } from 'zod';
import {
Permissions,
PermissionTypes,
permissionsSchema,
agentPermissionsSchema,
promptPermissionsSchema,
runCodePermissionsSchema,
bookmarkPermissionsSchema,
multiConvoPermissionsSchema,
temporaryChatPermissionsSchema,
} from './permissions';
/**
* Enum for System Defined Roles
@ -14,153 +25,72 @@ export enum SystemRoles {
USER = 'USER',
}
/**
* Enum for Permission Types
*/
export enum PermissionTypes {
/**
* Type for Prompt Permissions
*/
PROMPTS = 'PROMPTS',
/**
* Type for Bookmark Permissions
*/
BOOKMARKS = 'BOOKMARKS',
/**
* Type for Agent Permissions
*/
AGENTS = 'AGENTS',
/**
* Type for Multi-Conversation Permissions
*/
MULTI_CONVO = 'MULTI_CONVO',
/**
* Type for Temporary Chat
*/
TEMPORARY_CHAT = 'TEMPORARY_CHAT',
/**
* Type for using the "Run Code" LC Code Interpreter API feature
*/
RUN_CODE = 'RUN_CODE',
}
/**
* Enum for Role-Based Access Control Constants
*/
export enum Permissions {
SHARED_GLOBAL = 'SHARED_GLOBAL',
USE = 'USE',
CREATE = 'CREATE',
UPDATE = 'UPDATE',
READ = 'READ',
READ_AUTHOR = 'READ_AUTHOR',
SHARE = 'SHARE',
}
export const promptPermissionsSchema = z.object({
[Permissions.SHARED_GLOBAL]: z.boolean().default(false),
[Permissions.USE]: z.boolean().default(true),
[Permissions.CREATE]: z.boolean().default(true),
// [Permissions.SHARE]: z.boolean().default(false),
});
export const bookmarkPermissionsSchema = z.object({
[Permissions.USE]: z.boolean().default(true),
});
export const agentPermissionsSchema = z.object({
[Permissions.SHARED_GLOBAL]: z.boolean().default(false),
[Permissions.USE]: z.boolean().default(true),
[Permissions.CREATE]: z.boolean().default(true),
// [Permissions.SHARE]: z.boolean().default(false),
});
export const multiConvoPermissionsSchema = z.object({
[Permissions.USE]: z.boolean().default(true),
});
export const temporaryChatPermissionsSchema = z.object({
[Permissions.USE]: z.boolean().default(true),
});
export const runCodePermissionsSchema = z.object({
[Permissions.USE]: z.boolean().default(true),
});
// The role schema now only needs to reference the permissions schema.
export const roleSchema = z.object({
name: z.string(),
[PermissionTypes.PROMPTS]: promptPermissionsSchema,
[PermissionTypes.BOOKMARKS]: bookmarkPermissionsSchema,
[PermissionTypes.AGENTS]: agentPermissionsSchema,
[PermissionTypes.MULTI_CONVO]: multiConvoPermissionsSchema,
[PermissionTypes.TEMPORARY_CHAT]: temporaryChatPermissionsSchema,
[PermissionTypes.RUN_CODE]: runCodePermissionsSchema,
permissions: permissionsSchema,
});
export type TRole = z.infer<typeof roleSchema>;
export type TAgentPermissions = z.infer<typeof agentPermissionsSchema>;
export type TPromptPermissions = z.infer<typeof promptPermissionsSchema>;
export type TBookmarkPermissions = z.infer<typeof bookmarkPermissionsSchema>;
export type TMultiConvoPermissions = z.infer<typeof multiConvoPermissionsSchema>;
export type TTemporaryChatPermissions = z.infer<typeof temporaryChatPermissionsSchema>;
export type TRunCodePermissions = z.infer<typeof runCodePermissionsSchema>;
// Define default roles using the new structure.
const defaultRolesSchema = z.object({
[SystemRoles.ADMIN]: roleSchema.extend({
name: z.literal(SystemRoles.ADMIN),
[PermissionTypes.PROMPTS]: promptPermissionsSchema.extend({
[Permissions.SHARED_GLOBAL]: z.boolean().default(true),
[Permissions.USE]: z.boolean().default(true),
[Permissions.CREATE]: z.boolean().default(true),
// [Permissions.SHARE]: z.boolean().default(true),
}),
[PermissionTypes.BOOKMARKS]: bookmarkPermissionsSchema.extend({
[Permissions.USE]: z.boolean().default(true),
}),
[PermissionTypes.AGENTS]: agentPermissionsSchema.extend({
[Permissions.SHARED_GLOBAL]: z.boolean().default(true),
[Permissions.USE]: z.boolean().default(true),
[Permissions.CREATE]: z.boolean().default(true),
// [Permissions.SHARE]: z.boolean().default(true),
}),
[PermissionTypes.MULTI_CONVO]: multiConvoPermissionsSchema.extend({
[Permissions.USE]: z.boolean().default(true),
}),
[PermissionTypes.TEMPORARY_CHAT]: temporaryChatPermissionsSchema.extend({
[Permissions.USE]: z.boolean().default(true),
}),
[PermissionTypes.RUN_CODE]: runCodePermissionsSchema.extend({
[Permissions.USE]: z.boolean().default(true),
permissions: permissionsSchema.extend({
[PermissionTypes.PROMPTS]: promptPermissionsSchema.extend({
[Permissions.SHARED_GLOBAL]: z.boolean().default(true),
[Permissions.USE]: z.boolean().default(true),
[Permissions.CREATE]: z.boolean().default(true),
// [Permissions.SHARE]: z.boolean().default(true),
}),
[PermissionTypes.BOOKMARKS]: bookmarkPermissionsSchema.extend({
[Permissions.USE]: z.boolean().default(true),
}),
[PermissionTypes.AGENTS]: agentPermissionsSchema.extend({
[Permissions.SHARED_GLOBAL]: z.boolean().default(true),
[Permissions.USE]: z.boolean().default(true),
[Permissions.CREATE]: z.boolean().default(true),
// [Permissions.SHARE]: z.boolean().default(true),
}),
[PermissionTypes.MULTI_CONVO]: multiConvoPermissionsSchema.extend({
[Permissions.USE]: z.boolean().default(true),
}),
[PermissionTypes.TEMPORARY_CHAT]: temporaryChatPermissionsSchema.extend({
[Permissions.USE]: z.boolean().default(true),
}),
[PermissionTypes.RUN_CODE]: runCodePermissionsSchema.extend({
[Permissions.USE]: z.boolean().default(true),
}),
}),
}),
[SystemRoles.USER]: roleSchema.extend({
name: z.literal(SystemRoles.USER),
[PermissionTypes.PROMPTS]: promptPermissionsSchema,
[PermissionTypes.BOOKMARKS]: bookmarkPermissionsSchema,
[PermissionTypes.AGENTS]: agentPermissionsSchema,
[PermissionTypes.MULTI_CONVO]: multiConvoPermissionsSchema,
[PermissionTypes.TEMPORARY_CHAT]: temporaryChatPermissionsSchema,
[PermissionTypes.RUN_CODE]: runCodePermissionsSchema,
permissions: permissionsSchema,
}),
});
export const roleDefaults = defaultRolesSchema.parse({
[SystemRoles.ADMIN]: {
name: SystemRoles.ADMIN,
[PermissionTypes.PROMPTS]: {},
[PermissionTypes.BOOKMARKS]: {},
[PermissionTypes.AGENTS]: {},
[PermissionTypes.MULTI_CONVO]: {},
[PermissionTypes.TEMPORARY_CHAT]: {},
[PermissionTypes.RUN_CODE]: {},
permissions: {
[PermissionTypes.PROMPTS]: {},
[PermissionTypes.BOOKMARKS]: {},
[PermissionTypes.AGENTS]: {},
[PermissionTypes.MULTI_CONVO]: {},
[PermissionTypes.TEMPORARY_CHAT]: {},
[PermissionTypes.RUN_CODE]: {},
},
},
[SystemRoles.USER]: {
name: SystemRoles.USER,
[PermissionTypes.PROMPTS]: {},
[PermissionTypes.BOOKMARKS]: {},
[PermissionTypes.AGENTS]: {},
[PermissionTypes.MULTI_CONVO]: {},
[PermissionTypes.TEMPORARY_CHAT]: {},
[PermissionTypes.RUN_CODE]: {},
permissions: {
[PermissionTypes.PROMPTS]: {},
[PermissionTypes.BOOKMARKS]: {},
[PermissionTypes.AGENTS]: {},
[PermissionTypes.MULTI_CONVO]: {},
[PermissionTypes.TEMPORARY_CHAT]: {},
[PermissionTypes.RUN_CODE]: {},
},
},
});

View file

@ -1,5 +1,6 @@
import * as types from '../types';
import * as r from '../roles';
import * as p from '../permissions';
import {
Tools,
Assistant,
@ -251,9 +252,9 @@ export type UpdatePermVars<T> = {
updates: Partial<T>;
};
export type UpdatePromptPermVars = UpdatePermVars<r.TPromptPermissions>;
export type UpdatePromptPermVars = UpdatePermVars<p.TPromptPermissions>;
export type UpdateAgentPermVars = UpdatePermVars<r.TAgentPermissions>;
export type UpdateAgentPermVars = UpdatePermVars<p.TAgentPermissions>;
export type UpdatePermResponse = r.TRole;