mirror of
https://github.com/danny-avila/LibreChat.git
synced 2025-12-21 19:00:13 +01:00
🛂 feat: Role as Permission Principal Type
WIP: Role as Permission Principal Type WIP: add user role check optimization to user principal check, update type comparisons WIP: cover edge cases for string vs ObjectId handling in permission granting and checking chore: Update people picker access middleware to use PrincipalType constants feat: Enhance people picker access control to include roles permissions chore: add missing default role schema values for people picker perms, cleanup typing feat: Enhance PeoplePicker component with role-specific UI and localization updates chore: Add missing `VIEW_ROLES` permission to role schema
This commit is contained in:
parent
28d63dab71
commit
39346d6b8e
49 changed files with 2879 additions and 258 deletions
|
|
@ -21,8 +21,8 @@ let methods: ReturnType<typeof createUserGroupMethods>;
|
|||
beforeAll(async () => {
|
||||
mongoServer = await MongoMemoryServer.create();
|
||||
const mongoUri = mongoServer.getUri();
|
||||
Group = mongoose.models.Group || mongoose.model('Group', groupSchema);
|
||||
User = mongoose.models.User || mongoose.model('User', userSchema);
|
||||
Group = mongoose.models.Group || mongoose.model<t.IGroup>('Group', groupSchema);
|
||||
User = mongoose.models.User || mongoose.model<t.IUser>('User', userSchema);
|
||||
methods = createUserGroupMethods(mongoose);
|
||||
await mongoose.connect(mongoUri);
|
||||
});
|
||||
|
|
@ -325,10 +325,12 @@ describe('User Group Methods Tests', () => {
|
|||
);
|
||||
|
||||
/** Get user principals */
|
||||
const principals = await methods.getUserPrincipals(testUser1._id as mongoose.Types.ObjectId);
|
||||
const principals = await methods.getUserPrincipals({
|
||||
userId: testUser1._id as mongoose.Types.ObjectId,
|
||||
});
|
||||
|
||||
/** Should include user, group, and public principals */
|
||||
expect(principals).toHaveLength(3);
|
||||
/** Should include user, role (default USER), group, and public principals */
|
||||
expect(principals).toHaveLength(4);
|
||||
|
||||
/** Check principal types */
|
||||
const userPrincipal = principals.find((p) => p.principalType === PrincipalType.USER);
|
||||
|
|
@ -349,7 +351,9 @@ describe('User Group Methods Tests', () => {
|
|||
|
||||
test('should return user and public principals for non-existent user in getUserPrincipals', async () => {
|
||||
const nonExistentId = new mongoose.Types.ObjectId();
|
||||
const principals = await methods.getUserPrincipals(nonExistentId);
|
||||
const principals = await methods.getUserPrincipals({
|
||||
userId: nonExistentId,
|
||||
});
|
||||
|
||||
/** Should still return user and public principals even for non-existent user */
|
||||
expect(principals).toHaveLength(2);
|
||||
|
|
@ -358,6 +362,61 @@ describe('User Group Methods Tests', () => {
|
|||
expect(principals[1].principalType).toBe(PrincipalType.PUBLIC);
|
||||
expect(principals[1].principalId).toBeUndefined();
|
||||
});
|
||||
|
||||
test('should convert string userId to ObjectId in getUserPrincipals', async () => {
|
||||
/** Add user to a group */
|
||||
await methods.addUserToGroup(
|
||||
testUser1._id as mongoose.Types.ObjectId,
|
||||
testGroup._id as mongoose.Types.ObjectId,
|
||||
);
|
||||
|
||||
/** Get user principals with string userId */
|
||||
const principals = await methods.getUserPrincipals({
|
||||
userId: (testUser1._id as mongoose.Types.ObjectId).toString(),
|
||||
});
|
||||
|
||||
/** Should include user, role (default USER), group, and public principals */
|
||||
expect(principals).toHaveLength(4);
|
||||
|
||||
/** Check that USER principal has ObjectId */
|
||||
const userPrincipal = principals.find((p) => p.principalType === PrincipalType.USER);
|
||||
expect(userPrincipal).toBeDefined();
|
||||
expect(userPrincipal?.principalId).toBeInstanceOf(mongoose.Types.ObjectId);
|
||||
expect(userPrincipal?.principalId?.toString()).toBe(
|
||||
(testUser1._id as mongoose.Types.ObjectId).toString(),
|
||||
);
|
||||
|
||||
/** Check that GROUP principal has ObjectId */
|
||||
const groupPrincipal = principals.find((p) => p.principalType === PrincipalType.GROUP);
|
||||
expect(groupPrincipal).toBeDefined();
|
||||
expect(groupPrincipal?.principalId).toBeInstanceOf(mongoose.Types.ObjectId);
|
||||
expect(groupPrincipal?.principalId?.toString()).toBe(testGroup._id.toString());
|
||||
});
|
||||
|
||||
test('should include role principal as string in getUserPrincipals', async () => {
|
||||
/** Create user with specific role */
|
||||
const userWithRole = await User.create({
|
||||
name: 'Admin User',
|
||||
email: 'admin@example.com',
|
||||
password: 'password123',
|
||||
provider: 'local',
|
||||
role: 'ADMIN',
|
||||
});
|
||||
|
||||
/** Get user principals */
|
||||
const principals = await methods.getUserPrincipals({
|
||||
userId: userWithRole._id as mongoose.Types.ObjectId,
|
||||
});
|
||||
|
||||
/** Should include user, role, and public principals */
|
||||
expect(principals).toHaveLength(3);
|
||||
|
||||
/** Check that ROLE principal has string ID */
|
||||
const rolePrincipal = principals.find((p) => p.principalType === PrincipalType.ROLE);
|
||||
expect(rolePrincipal).toBeDefined();
|
||||
expect(typeof rolePrincipal?.principalId).toBe('string');
|
||||
expect(rolePrincipal?.principalId).toBe('ADMIN');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Entra ID Synchronization', () => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue