Skip to content

Commit

Permalink
Add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
gabriellsh committed Jan 27, 2025
1 parent a9b4da0 commit de1ff5c
Show file tree
Hide file tree
Showing 3 changed files with 238 additions and 1 deletion.
1 change: 1 addition & 0 deletions apps/meteor/jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export default {
'<rootDir>/ee/server/patches/**/*.spec.ts',
'<rootDir>/app/cloud/server/functions/supportedVersionsToken/**.spec.ts',
'<rootDir>/app/utils/lib/**.spec.ts',
'<rootDir>/server/lib/auditServerEvents/**.spec.ts',
],
},
],
Expand Down
236 changes: 236 additions & 0 deletions apps/meteor/server/lib/auditServerEvents/userChanged.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,236 @@
import { faker } from '@faker-js/faker';
import type { IAuditServerUserActor, IUser } from '@rocket.chat/core-typings';

import { UserChangedLogStore } from './userChanged';
import { createFakeUser } from '../../../tests/mocks/data';

const createChangedUserAndActor = (
changes: Partial<IUser>,
overrides?: Partial<IUser>,
): [IUser, IUser, Omit<IAuditServerUserActor, 'type'>] => {
const originalUser = createFakeUser(overrides);
const currentUser: IUser = {
...originalUser,
...changes,
};

const actor: Omit<IAuditServerUserActor, 'type'> = {
ip: 'actorIp',
useragent: 'actorUserAgent',
_id: 'actorId',
username: 'actorUsername',
};

return [originalUser, currentUser, actor];
};

const createEmailsField = (address?: string, verified = true) => {
return {
emails: [
{
address: address || faker.internet.email(),
verified,
},
],
};
};

const createObfuscatedFields = (_2faEnabled = true): Pick<IUser, 'services' | 'e2e' | 'oauth'> => {
return {
services: {
password: {
bcrypt: faker.string.uuid(),
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore this field is not in IUser, but is present in DB
enroll: {
token: faker.string.uuid(),
email: faker.internet.email(),
when: faker.date.past(),
reason: 'enroll',
},
},
email2fa: {
enabled: _2faEnabled,
changedAt: faker.date.past(),
},
email: {
verificationTokens: [
{
token: faker.string.uuid(),
address: faker.internet.email(),
when: faker.date.past(),
},
],
},
resume: {
loginTokens: [
{
when: faker.date.past(),
hashedToken: faker.string.uuid(),
twoFactorAuthorizedHash: faker.string.uuid(),
twoFactorAuthorizedUntil: faker.date.past(),
},
],
},
},
e2e: {
private_key: faker.string.uuid(),
public_key: faker.string.uuid(),
},
inviteToken: faker.string.uuid(),
oauth: { authorizedClients: [faker.string.uuid(), faker.string.uuid()] },
};
};

const getObfuscatedFields = (email2faState: { enabled: boolean; changedAt: Date }) => ({
e2e: '***',
oauth: '***',
inviteToken: '***',
services: {
password: '***',
email2fa: email2faState,
email: '***',
resume: '***',
},
});

describe('userChanged audit module', () => {
it('should build event with only name and username fields', async () => {
const store = new UserChangedLogStore();

const [originalUser, currentUser, actor] = createChangedUserAndActor(
{
username: 'newUsername',
name: 'newName',
},
{ ...createEmailsField() },
);

store.setOriginalUser(originalUser as IUser);
store.setCurrentUser(currentUser as IUser);
store.setActor(actor);

const event = store.buildEvent();

expect(event).toEqual([
'user.changed',
{
user: { _id: currentUser._id, username: currentUser.username },
previous: { username: originalUser.username, name: originalUser.name },
current: { username: currentUser.username, name: currentUser.name },
},
{
ip: 'actorIp',
useragent: 'actorUserAgent',
_id: 'actorId',
username: 'actorUsername',
type: 'user',
},
]);
});
it('should build event with only emails field', async () => {
const store = new UserChangedLogStore();

const [originalUser, currentUser, actor] = createChangedUserAndActor(
{
...createEmailsField(),
},
{ ...createEmailsField() },
);

store.setOriginalUser(originalUser as IUser);
store.setCurrentUser(currentUser as IUser);
store.setActor(actor);

const event = store.buildEvent();

expect(event).toEqual([
'user.changed',
{
user: { _id: currentUser._id, username: currentUser.username },
previous: { emails: originalUser.emails },
current: { emails: currentUser.emails },
},
{
ip: 'actorIp',
useragent: 'actorUserAgent',
_id: 'actorId',
username: 'actorUsername',
type: 'user',
},
]);
});
it('should build event with every changed field', async () => {
const store = new UserChangedLogStore();

const [originalUser, currentUser, actor] = createChangedUserAndActor(
{
...createFakeUser(),
...createEmailsField(),
type: 'bot',
active: true,
roles: ['user', 'bot'],
},
{ ...createEmailsField(), active: false },
);

store.setOriginalUser(originalUser as IUser);
store.setCurrentUser(currentUser as IUser);
store.setActor(actor);

const event = store.buildEvent();

expect(event).toEqual([
'user.changed',
{
user: { _id: currentUser._id, username: currentUser.username },
previous: originalUser,
current: currentUser,
},
{
ip: 'actorIp',
useragent: 'actorUserAgent',
_id: 'actorId',
username: 'actorUsername',
type: 'user',
},
]);
});
it('should obfuscate sensitive fields', async () => {
const store = new UserChangedLogStore();

const [originalUser, currentUser, actor] = createChangedUserAndActor(
{
...createFakeUser(),
...createEmailsField(),
...createObfuscatedFields(true),
type: 'bot',
active: true,
roles: ['user', 'bot'],
},
{ ...createEmailsField(), ...createObfuscatedFields(false), active: false },
);

store.setOriginalUser(originalUser as IUser);
store.setCurrentUser(currentUser as IUser);
store.setActor(actor);

const event = store.buildEvent();

expect(event).toEqual([
'user.changed',
{
user: { _id: currentUser._id, username: currentUser.username },
previous: { ...originalUser, ...getObfuscatedFields(originalUser.services?.email2fa as any) },
current: { ...currentUser, ...getObfuscatedFields(currentUser.services?.email2fa as any) },
},
{
ip: 'actorIp',
useragent: 'actorUserAgent',
_id: 'actorId',
username: 'actorUsername',
type: 'user',
},
]);
});
});
2 changes: 1 addition & 1 deletion apps/meteor/server/lib/auditServerEvents/userChanged.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ const buildUserRecord = (

return record;
};
class UserChangedLogStore {
export class UserChangedLogStore {
private originalUser: IUser | undefined;

private currentUser: IUser | undefined;
Expand Down

0 comments on commit de1ff5c

Please sign in to comment.