Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions ee/packages/abac/src/subject-attributes-validations.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { ILDAPEntry, IUser, IAbacAttributeDefinition } from '@rocket.chat/core-typings';
import { registerServiceModels, Users } from '@rocket.chat/models';
import { registerModel, Users, UsersRaw, RoomsRaw, AbacAttributesRaw, ServerEventsRaw } from '@rocket.chat/models';
import type { Collection, Db } from 'mongodb';
import { MongoClient } from 'mongodb';
import { MongoMemoryServer } from 'mongodb-memory-server';
Expand Down Expand Up @@ -40,7 +40,12 @@ describe('Subject Attributes validation', () => {
mongo = await MongoMemoryServer.create();
client = await MongoClient.connect(mongo.getUri(), {});
db = client.db('abac_global');
registerServiceModels(db);

// Register only the models we actually need for these tests
registerModel('IUsersModel', () => new UsersRaw(db));
registerModel('IRoomsModel', () => new RoomsRaw(db));
registerModel('IAbacAttributesModel', () => new AbacAttributesRaw(db));
registerModel('IServerEventsModel', () => new ServerEventsRaw(db));

// @ts-expect-error - ignore
await db.collection('abac_dummy_init').insertOne({ _id: 'init', createdAt: new Date() });
Expand Down Expand Up @@ -234,13 +239,16 @@ describe('Subject Attributes validation', () => {
__rooms: user.__rooms || [],
});

beforeEach(async () => {
service = new AbacService();
beforeAll(async () => {
roomsCol = db.collection('rocketchat_room');
usersCol = db.collection('users');
await Promise.all([roomsCol.deleteMany({}), usersCol.deleteMany({})]);
});

beforeEach(() => {
service = new AbacService();
});

it('removes user from rooms whose attributes become non-compliant after losing a value', async () => {
const user: IUser = {
_id: 'u-loss',
Expand Down
60 changes: 15 additions & 45 deletions ee/packages/abac/src/user-auto-removal.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
import type { IAbacAttributeDefinition, IRoom, IUser } from '@rocket.chat/core-typings';
import { registerServiceModels } from '@rocket.chat/models';
import {
registerModel,
Subscriptions,
SubscriptionsRaw,
UsersRaw,
RoomsRaw,
AbacAttributesRaw,
ServerEventsRaw,
} from '@rocket.chat/models';
import type { Collection, Db } from 'mongodb';
import { MongoClient } from 'mongodb';
import { MongoMemoryServer } from 'mongodb-memory-server';
Expand All @@ -12,7 +20,6 @@ jest.mock('@rocket.chat/core-services', () => ({
Room: {
// Mimic the DB side-effects of removing a user from a room (no apps/system messages)
removeUserFromRoom: async (roomId: string, user: any) => {
const { Subscriptions } = await import('@rocket.chat/models');
await Subscriptions.removeByRoomIdAndUserId(roomId, user._id);
},
},
Expand Down Expand Up @@ -85,11 +92,12 @@ describe('AbacService integration (onRoomAttributesChanged)', () => {
client = await MongoClient.connect(mongo.getUri(), {});
db = client.db('abac_integration');

// Hack to register the models in here with a custom database without having to call every model by one
registerServiceModels(db as any);

// @ts-expect-error - ignore
await db.collection('abac_dummy_init').insertOne({ _id: 'init', createdAt: new Date() });
// Register only the models we actually need for these tests
registerModel('IUsersModel', () => new UsersRaw(db));
registerModel('IRoomsModel', () => new RoomsRaw(db));
registerModel('IAbacAttributesModel', () => new AbacAttributesRaw(db));
registerModel('IServerEventsModel', () => new ServerEventsRaw(db));
registerModel('ISubscriptionsModel', () => new SubscriptionsRaw(db));

service = new AbacService();
Comment thread
KevLehman marked this conversation as resolved.
Outdated
debugSpy = jest.spyOn((service as any).logger, 'debug').mockImplementation(() => undefined);
Expand Down Expand Up @@ -156,15 +164,6 @@ describe('AbacService integration (onRoomAttributesChanged)', () => {
expect(auditedUsers).toEqual(['u2_newkey', 'u3_newkey']);
expect(auditedRooms).toEqual(new Set([rid1]));
expect(auditedActions).toEqual(new Set(['room-attributes-change']));

const remaining = await usersCol
.find({ _id: { $in: ['u1_newkey', 'u2_newkey', 'u3_newkey', 'u4_newkey'] } }, { projection: { __rooms: 1 } })
.toArray()
.then((docs) => Object.fromEntries(docs.map((d) => [d._id, d.__rooms || []])));
expect(remaining.u1_newkey).toContain(rid1);
expect(remaining.u4_newkey).toContain(rid1);
expect(remaining.u2_newkey).not.toContain(rid1);
expect(remaining.u3_newkey).not.toContain(rid1);
});

it('handles duplicate values in room attributes equivalently to unique set (logs non compliant and removes them)', async () => {
Expand Down Expand Up @@ -206,14 +205,6 @@ describe('AbacService integration (onRoomAttributesChanged)', () => {
expect(auditSpy.mock.calls[0][0]).toMatchObject({ _id: 'u2_newval', username: 'u2_newval' });
expect(auditSpy.mock.calls[0][1]).toMatchObject({ _id: rid });
expect(auditSpy.mock.calls[0][2]).toBe('room-attributes-change');
Comment thread
KevLehman marked this conversation as resolved.
Outdated

const users = await usersCol
.find({ _id: { $in: ['u1_newval', 'u2_newval', 'u3_newval'] } }, { projection: { __rooms: 1 } })
.toArray()
.then((docs) => Object.fromEntries(docs.map((d) => [d._id, d.__rooms || []])));
expect(users.u1_newval).toContain(rid);
expect(users.u3_newval).toContain(rid);
expect(users.u2_newval).not.toContain(rid);
});

it('produces no evaluation log when only removing values from existing attribute', async () => {
Expand Down Expand Up @@ -311,16 +302,6 @@ describe('AbacService integration (onRoomAttributesChanged)', () => {
expect(auditedRooms).toEqual(new Set([rid]));
const auditedActions = new Set(auditSpy.mock.calls.map((call) => call[2]));
expect(auditedActions).toEqual(new Set(['room-attributes-change']));
Comment thread
KevLehman marked this conversation as resolved.

const memberships = await usersCol
.find({ _id: { $in: ['u1_multi', 'u2_multi', 'u3_multi', 'u4_multi', 'u5_multi'] } }, { projection: { __rooms: 1 } })
.toArray()
.then((docs) => Object.fromEntries(docs.map((d) => [d._id, d.__rooms || []])));
expect(memberships.u1_multi).toContain(rid);
expect(memberships.u4_multi).toContain(rid);
expect(memberships.u2_multi).not.toContain(rid);
expect(memberships.u3_multi).not.toContain(rid);
expect(memberships.u5_multi).not.toContain(rid);
});
});

Expand Down Expand Up @@ -421,14 +402,6 @@ describe('AbacService integration (onRoomAttributesChanged)', () => {
expect(auditedRooms).toEqual(new Set([ridMissingKey]));
const auditedActions = new Set(auditSpy.mock.calls.map((call) => call[2]));
expect(auditedActions).toEqual(new Set(['room-attributes-change']));
Comment thread
KevLehman marked this conversation as resolved.

const memberships = await usersCol
.find({ _id: { $in: ['u1_misskey', 'u2_misskey', 'u3_misskey'] } }, { projection: { __rooms: 1 } })
.toArray()
.then((docs) => Object.fromEntries(docs.map((d) => [d._id, d.__rooms || []])));
expect(memberships.u1_misskey).toContain(ridMissingKey);
expect(memberships.u2_misskey).not.toContain(ridMissingKey);
expect(memberships.u3_misskey).not.toContain(ridMissingKey);
});
});

Expand Down Expand Up @@ -469,9 +442,6 @@ describe('AbacService integration (onRoomAttributesChanged)', () => {
expect(auditedRooms).toEqual(new Set([rid]));
const auditedActions = new Set(auditSpy.mock.calls.map((call) => call[2]));
expect(auditedActions).toEqual(new Set(['room-attributes-change']));

const remainingCount = await usersCol.countDocuments({ __rooms: rid });
expect(remainingCount).toBe(150);
});
});
});
Loading