mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-20 10:20:15 +01:00
fix: role initialization
This commit is contained in:
parent
350d709763
commit
b71d773f01
3 changed files with 143 additions and 10 deletions
|
|
@ -132,6 +132,7 @@ async function updateAccessPermissions(roleName, permissionsUpdate) {
|
||||||
/**
|
/**
|
||||||
* Initialize default roles in the system.
|
* Initialize default roles in the system.
|
||||||
* Creates the default roles (ADMIN, USER) if they don't exist in the database.
|
* Creates the default roles (ADMIN, USER) if they don't exist in the database.
|
||||||
|
* Updates existing roles with new permission types if they're missing.
|
||||||
*
|
*
|
||||||
* @returns {Promise<void>}
|
* @returns {Promise<void>}
|
||||||
*/
|
*/
|
||||||
|
|
@ -139,14 +140,27 @@ const initializeRoles = async function () {
|
||||||
const defaultRoles = [SystemRoles.ADMIN, SystemRoles.USER];
|
const defaultRoles = [SystemRoles.ADMIN, SystemRoles.USER];
|
||||||
|
|
||||||
for (const roleName of defaultRoles) {
|
for (const roleName of defaultRoles) {
|
||||||
let role = await Role.findOne({ name: roleName }).select('name').lean();
|
let role = await Role.findOne({ name: roleName });
|
||||||
|
|
||||||
if (!role) {
|
if (!role) {
|
||||||
|
// Create new role if it doesn't exist
|
||||||
role = new Role(roleDefaults[roleName]);
|
role = new Role(roleDefaults[roleName]);
|
||||||
|
} else {
|
||||||
|
// Add missing permission types
|
||||||
|
let isUpdated = false;
|
||||||
|
for (const permType of Object.values(PermissionTypes)) {
|
||||||
|
if (!role[permType]) {
|
||||||
|
role[permType] = roleDefaults[roleName][permType];
|
||||||
|
isUpdated = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (isUpdated) {
|
||||||
await role.save();
|
await role.save();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
await role.save();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
getRoleByName,
|
getRoleByName,
|
||||||
initializeRoles,
|
initializeRoles,
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,14 @@
|
||||||
const mongoose = require('mongoose');
|
const mongoose = require('mongoose');
|
||||||
const { MongoMemoryServer } = require('mongodb-memory-server');
|
const { MongoMemoryServer } = require('mongodb-memory-server');
|
||||||
const { SystemRoles, PermissionTypes } = require('librechat-data-provider');
|
const {
|
||||||
const Role = require('~/models/schema/roleSchema');
|
SystemRoles,
|
||||||
const { updateAccessPermissions } = require('~/models/Role');
|
PermissionTypes,
|
||||||
|
roleDefaults,
|
||||||
|
Permissions,
|
||||||
|
} = require('librechat-data-provider');
|
||||||
|
const { updateAccessPermissions, initializeRoles } = require('~/models/Role');
|
||||||
const getLogStores = require('~/cache/getLogStores');
|
const getLogStores = require('~/cache/getLogStores');
|
||||||
|
const Role = require('~/models/schema/roleSchema');
|
||||||
|
|
||||||
// Mock the cache
|
// Mock the cache
|
||||||
jest.mock('~/cache/getLogStores', () => {
|
jest.mock('~/cache/getLogStores', () => {
|
||||||
|
|
@ -195,3 +200,117 @@ describe('updateAccessPermissions', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('initializeRoles', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
await Role.deleteMany({});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create default roles if they do not exist', async () => {
|
||||||
|
await initializeRoles();
|
||||||
|
|
||||||
|
const adminRole = await Role.findOne({ name: SystemRoles.ADMIN }).lean();
|
||||||
|
const userRole = await Role.findOne({ name: SystemRoles.USER }).lean();
|
||||||
|
|
||||||
|
expect(adminRole).toBeTruthy();
|
||||||
|
expect(userRole).toBeTruthy();
|
||||||
|
|
||||||
|
// Check if all permission types exist
|
||||||
|
Object.values(PermissionTypes).forEach((permType) => {
|
||||||
|
expect(adminRole[permType]).toBeDefined();
|
||||||
|
expect(userRole[permType]).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check if permissions match defaults (example for ADMIN role)
|
||||||
|
expect(adminRole[PermissionTypes.PROMPTS].SHARED_GLOBAL).toBe(true);
|
||||||
|
expect(adminRole[PermissionTypes.BOOKMARKS].USE).toBe(true);
|
||||||
|
expect(adminRole[PermissionTypes.AGENTS].CREATE).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not modify existing permissions for existing roles', async () => {
|
||||||
|
const customUserRole = {
|
||||||
|
name: SystemRoles.USER,
|
||||||
|
[PermissionTypes.PROMPTS]: {
|
||||||
|
[Permissions.USE]: false,
|
||||||
|
[Permissions.CREATE]: true,
|
||||||
|
[Permissions.SHARED_GLOBAL]: true,
|
||||||
|
},
|
||||||
|
[PermissionTypes.BOOKMARKS]: {
|
||||||
|
[Permissions.USE]: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
await new Role(customUserRole).save();
|
||||||
|
|
||||||
|
await initializeRoles();
|
||||||
|
|
||||||
|
const userRole = await Role.findOne({ name: SystemRoles.USER }).lean();
|
||||||
|
|
||||||
|
expect(userRole[PermissionTypes.PROMPTS]).toEqual(customUserRole[PermissionTypes.PROMPTS]);
|
||||||
|
expect(userRole[PermissionTypes.BOOKMARKS]).toEqual(customUserRole[PermissionTypes.BOOKMARKS]);
|
||||||
|
expect(userRole[PermissionTypes.AGENTS]).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add new permission types to existing roles', async () => {
|
||||||
|
const partialUserRole = {
|
||||||
|
name: SystemRoles.USER,
|
||||||
|
[PermissionTypes.PROMPTS]: roleDefaults[SystemRoles.USER][PermissionTypes.PROMPTS],
|
||||||
|
[PermissionTypes.BOOKMARKS]: roleDefaults[SystemRoles.USER][PermissionTypes.BOOKMARKS],
|
||||||
|
};
|
||||||
|
|
||||||
|
await new Role(partialUserRole).save();
|
||||||
|
|
||||||
|
await initializeRoles();
|
||||||
|
|
||||||
|
const userRole = await Role.findOne({ name: SystemRoles.USER }).lean();
|
||||||
|
|
||||||
|
expect(userRole[PermissionTypes.AGENTS]).toBeDefined();
|
||||||
|
expect(userRole[PermissionTypes.AGENTS].CREATE).toBeDefined();
|
||||||
|
expect(userRole[PermissionTypes.AGENTS].USE).toBeDefined();
|
||||||
|
expect(userRole[PermissionTypes.AGENTS].SHARED_GLOBAL).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle multiple runs without duplicating or modifying data', async () => {
|
||||||
|
await initializeRoles();
|
||||||
|
await initializeRoles();
|
||||||
|
|
||||||
|
const adminRoles = await Role.find({ name: SystemRoles.ADMIN });
|
||||||
|
const userRoles = await Role.find({ name: SystemRoles.USER });
|
||||||
|
|
||||||
|
expect(adminRoles).toHaveLength(1);
|
||||||
|
expect(userRoles).toHaveLength(1);
|
||||||
|
|
||||||
|
const adminRole = adminRoles[0].toObject();
|
||||||
|
const userRole = userRoles[0].toObject();
|
||||||
|
|
||||||
|
// Check if all permission types exist
|
||||||
|
Object.values(PermissionTypes).forEach((permType) => {
|
||||||
|
expect(adminRole[permType]).toBeDefined();
|
||||||
|
expect(userRole[permType]).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should update roles with missing permission types from roleDefaults', async () => {
|
||||||
|
const partialAdminRole = {
|
||||||
|
name: SystemRoles.ADMIN,
|
||||||
|
[PermissionTypes.PROMPTS]: {
|
||||||
|
[Permissions.USE]: false,
|
||||||
|
[Permissions.CREATE]: false,
|
||||||
|
[Permissions.SHARED_GLOBAL]: false,
|
||||||
|
},
|
||||||
|
[PermissionTypes.BOOKMARKS]: roleDefaults[SystemRoles.ADMIN][PermissionTypes.BOOKMARKS],
|
||||||
|
};
|
||||||
|
|
||||||
|
await new Role(partialAdminRole).save();
|
||||||
|
|
||||||
|
await initializeRoles();
|
||||||
|
|
||||||
|
const adminRole = await Role.findOne({ name: SystemRoles.ADMIN }).lean();
|
||||||
|
|
||||||
|
expect(adminRole[PermissionTypes.PROMPTS]).toEqual(partialAdminRole[PermissionTypes.PROMPTS]);
|
||||||
|
expect(adminRole[PermissionTypes.AGENTS]).toBeDefined();
|
||||||
|
expect(adminRole[PermissionTypes.AGENTS].CREATE).toBeDefined();
|
||||||
|
expect(adminRole[PermissionTypes.AGENTS].USE).toBeDefined();
|
||||||
|
expect(adminRole[PermissionTypes.AGENTS].SHARED_GLOBAL).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ export const promptPermissionsSchema = z.object({
|
||||||
[Permissions.SHARED_GLOBAL]: z.boolean().default(false),
|
[Permissions.SHARED_GLOBAL]: z.boolean().default(false),
|
||||||
[Permissions.USE]: z.boolean().default(true),
|
[Permissions.USE]: z.boolean().default(true),
|
||||||
[Permissions.CREATE]: z.boolean().default(true),
|
[Permissions.CREATE]: z.boolean().default(true),
|
||||||
[Permissions.SHARE]: z.boolean().default(false),
|
// [Permissions.SHARE]: z.boolean().default(false),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const bookmarkPermissionsSchema = z.object({
|
export const bookmarkPermissionsSchema = z.object({
|
||||||
|
|
@ -57,7 +57,7 @@ export const agentPermissionsSchema = z.object({
|
||||||
[Permissions.SHARED_GLOBAL]: z.boolean().default(false),
|
[Permissions.SHARED_GLOBAL]: z.boolean().default(false),
|
||||||
[Permissions.USE]: z.boolean().default(true),
|
[Permissions.USE]: z.boolean().default(true),
|
||||||
[Permissions.CREATE]: z.boolean().default(true),
|
[Permissions.CREATE]: z.boolean().default(true),
|
||||||
[Permissions.SHARE]: z.boolean().default(false),
|
// [Permissions.SHARE]: z.boolean().default(false),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const roleSchema = z.object({
|
export const roleSchema = z.object({
|
||||||
|
|
@ -79,7 +79,7 @@ const defaultRolesSchema = z.object({
|
||||||
[Permissions.SHARED_GLOBAL]: z.boolean().default(true),
|
[Permissions.SHARED_GLOBAL]: z.boolean().default(true),
|
||||||
[Permissions.USE]: z.boolean().default(true),
|
[Permissions.USE]: z.boolean().default(true),
|
||||||
[Permissions.CREATE]: z.boolean().default(true),
|
[Permissions.CREATE]: z.boolean().default(true),
|
||||||
[Permissions.SHARE]: z.boolean().default(true),
|
// [Permissions.SHARE]: z.boolean().default(true),
|
||||||
}),
|
}),
|
||||||
[PermissionTypes.BOOKMARKS]: bookmarkPermissionsSchema.extend({
|
[PermissionTypes.BOOKMARKS]: bookmarkPermissionsSchema.extend({
|
||||||
[Permissions.USE]: z.boolean().default(true),
|
[Permissions.USE]: z.boolean().default(true),
|
||||||
|
|
@ -88,7 +88,7 @@ const defaultRolesSchema = z.object({
|
||||||
[Permissions.SHARED_GLOBAL]: z.boolean().default(true),
|
[Permissions.SHARED_GLOBAL]: z.boolean().default(true),
|
||||||
[Permissions.USE]: z.boolean().default(true),
|
[Permissions.USE]: z.boolean().default(true),
|
||||||
[Permissions.CREATE]: z.boolean().default(true),
|
[Permissions.CREATE]: z.boolean().default(true),
|
||||||
[Permissions.SHARE]: z.boolean().default(true),
|
// [Permissions.SHARE]: z.boolean().default(true),
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
[SystemRoles.USER]: roleSchema.extend({
|
[SystemRoles.USER]: roleSchema.extend({
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue