🔧 refactor: Integrate PrincipalModel Enum for Principal Handling

- Replaced string literals for principal models ('User', 'Group') with the new PrincipalModel enum across various models, services, and tests to enhance type safety and consistency.
- Updated permission handling in multiple files to utilize the PrincipalModel enum, improving maintainability and reducing potential errors.
- Ensured all relevant tests reflect these changes to maintain coverage and functionality.
This commit is contained in:
Danny Avila 2025-08-02 16:14:11 -04:00
parent d79c5d1d21
commit 7c35d17e3d
No known key found for this signature in database
GPG key ID: BF31EEB2C5CA0956
10 changed files with 61 additions and 30 deletions

View file

@ -1,5 +1,5 @@
const mongoose = require('mongoose');
const { ResourceType, PrincipalType } = require('librechat-data-provider');
const { ResourceType, PrincipalType, PrincipalModel } = require('librechat-data-provider');
const { MongoMemoryServer } = require('mongodb-memory-server');
const { canAccessAgentResource } = require('./canAccessAgentResource');
const { User, Role, AclEntry } = require('~/db/models');
@ -99,7 +99,7 @@ describe('canAccessAgentResource middleware', () => {
await AclEntry.create({
principalType: PrincipalType.USER,
principalId: testUser._id,
principalModel: 'User',
principalModel: PrincipalModel.USER,
resourceType: ResourceType.AGENT,
resourceId: agent._id,
permBits: 15, // All permissions (1+2+4+8)
@ -136,7 +136,7 @@ describe('canAccessAgentResource middleware', () => {
await AclEntry.create({
principalType: PrincipalType.USER,
principalId: otherUser._id,
principalModel: 'User',
principalModel: PrincipalModel.USER,
resourceType: ResourceType.AGENT,
resourceId: agent._id,
permBits: 15, // All permissions
@ -177,7 +177,7 @@ describe('canAccessAgentResource middleware', () => {
await AclEntry.create({
principalType: PrincipalType.USER,
principalId: testUser._id,
principalModel: 'User',
principalModel: PrincipalModel.USER,
resourceType: ResourceType.AGENT,
resourceId: agent._id,
permBits: 1, // VIEW permission
@ -214,7 +214,7 @@ describe('canAccessAgentResource middleware', () => {
await AclEntry.create({
principalType: PrincipalType.USER,
principalId: testUser._id,
principalModel: 'User',
principalModel: PrincipalModel.USER,
resourceType: ResourceType.AGENT,
resourceId: agent._id,
permBits: 1, // VIEW permission only
@ -261,7 +261,7 @@ describe('canAccessAgentResource middleware', () => {
await AclEntry.create({
principalType: PrincipalType.USER,
principalId: testUser._id,
principalModel: 'User',
principalModel: PrincipalModel.USER,
resourceType: ResourceType.AGENT,
resourceId: agent._id,
permBits: 15, // All permissions
@ -297,7 +297,7 @@ describe('canAccessAgentResource middleware', () => {
await AclEntry.create({
principalType: PrincipalType.USER,
principalId: testUser._id,
principalModel: 'User',
principalModel: PrincipalModel.USER,
resourceType: ResourceType.AGENT,
resourceId: agent._id,
permBits: 15, // All permissions (1+2+4+8)
@ -357,7 +357,7 @@ describe('canAccessAgentResource middleware', () => {
await AclEntry.create({
principalType: PrincipalType.USER,
principalId: testUser._id,
principalModel: 'User',
principalModel: PrincipalModel.USER,
resourceType: ResourceType.AGENT,
resourceId: agent._id,
permBits: 15, // All permissions

View file

@ -22,6 +22,16 @@ jest.mock('librechat-data-provider', () => ({
GROUP: 'group',
PUBLIC: 'public',
},
PrincipalModel: {
USER: 'User',
GROUP: 'Group',
},
ResourceType: {
AGENT: 'agent',
PROJECT: 'project',
FILE: 'file',
PROMPTGROUP: 'promptGroup',
},
FileContext: { message_attachment: 'message_attachment' },
FileSources: { local: 'local' },
EModelEndpoint: { assistants: 'assistants' },

View file

@ -1,6 +1,6 @@
const mongoose = require('mongoose');
const { isEnabled } = require('@librechat/api');
const { ResourceType, PrincipalType } = require('librechat-data-provider');
const { ResourceType, PrincipalType, PrincipalModel } = require('librechat-data-provider');
const { getTransactionSupport, logger } = require('@librechat/data-schemas');
const {
entraIdPrincipalFeatureEnabled,
@ -627,9 +627,10 @@ const bulkUpdateResourcePermissions = async ({
principalType: principal.type,
resourceType,
resourceId,
...(principal.type !== 'public' && {
...(principal.type !== PrincipalType.PUBLIC && {
principalId: principal.id,
principalModel: principal.type === 'user' ? 'User' : 'Group',
principalModel:
principal.type === PrincipalType.USER ? PrincipalModel.USER : PrincipalModel.GROUP,
}),
},
};

View file

@ -1,7 +1,12 @@
const mongoose = require('mongoose');
const { RoleBits, createModels } = require('@librechat/data-schemas');
const { MongoMemoryServer } = require('mongodb-memory-server');
const { AccessRoleIds, ResourceType, PrincipalType } = require('librechat-data-provider');
const {
ResourceType,
AccessRoleIds,
PrincipalType,
PrincipalModel,
} = require('librechat-data-provider');
const {
bulkUpdateResourcePermissions,
getEffectivePermissions,
@ -87,10 +92,10 @@ describe('PermissionService', () => {
});
expect(entry).toBeDefined();
expect(entry.principalType).toBe('user');
expect(entry.principalType).toBe(PrincipalType.USER);
expect(entry.principalId.toString()).toBe(userId.toString());
expect(entry.principalModel).toBe('User');
expect(entry.resourceType).toBe('agent');
expect(entry.principalModel).toBe(PrincipalModel.USER);
expect(entry.resourceType).toBe(ResourceType.AGENT);
expect(entry.resourceId.toString()).toBe(resourceId.toString());
// Get the role to verify the permission bits are correctly set
@ -114,7 +119,7 @@ describe('PermissionService', () => {
expect(entry).toBeDefined();
expect(entry.principalType).toBe(PrincipalType.GROUP);
expect(entry.principalId.toString()).toBe(groupId.toString());
expect(entry.principalModel).toBe('Group');
expect(entry.principalModel).toBe(PrincipalModel.GROUP);
// Get the role to verify the permission bits are correctly set
const role = await findRoleByIdentifier(AccessRoleIds.AGENT_EDITOR);
@ -433,7 +438,7 @@ describe('PermissionService', () => {
await AclEntry.create({
principalType: PrincipalType.USER,
principalId: userId,
principalModel: 'User',
principalModel: PrincipalModel.USER,
resourceType: ResourceType.AGENT,
resourceId: childResourceId,
permBits: RoleBits.VIEWER,