mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2024-11-26 19:53:59 -05:00
Add test for permission service
Many tests are generated and not static like in other files. Signed-off-by: Yannick Bungers <git@innay.de>
This commit is contained in:
parent
0ea7991e36
commit
0fc9c11a41
1 changed files with 526 additions and 0 deletions
526
src/permissions/permissions.service.spec.ts
Normal file
526
src/permissions/permissions.service.spec.ts
Normal file
|
@ -0,0 +1,526 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
import { Test, TestingModule } from '@nestjs/testing';
|
||||
import { LoggerModule } from '../logger/logger.module';
|
||||
import { GuestPermission, PermissionsService } from './permissions.service';
|
||||
import { User } from '../users/user.entity';
|
||||
import { Note } from '../notes/note.entity';
|
||||
import { UsersModule } from '../users/users.module';
|
||||
import { NotesModule } from '../notes/notes.module';
|
||||
import { PermissionsModule } from './permissions.module';
|
||||
import { getRepositoryToken } from '@nestjs/typeorm';
|
||||
import { NoteGroupPermission } from './note-group-permission.entity';
|
||||
import { NoteUserPermission } from './note-user-permission.entity';
|
||||
import { Identity } from '../users/identity.entity';
|
||||
import { AuthToken } from '../auth/auth-token.entity';
|
||||
import { Authorship } from '../revisions/authorship.entity';
|
||||
import { AuthorColor } from '../notes/author-color.entity';
|
||||
import { Revision } from '../revisions/revision.entity';
|
||||
import { Tag } from '../notes/tag.entity';
|
||||
import { Group } from '../groups/group.entity';
|
||||
|
||||
jest.mock('../permissions/note-group-permission.entity.ts');
|
||||
jest.mock('../groups/group.entity.ts');
|
||||
jest.mock('../notes/note.entity.ts');
|
||||
jest.mock('../users/user.entity.ts');
|
||||
|
||||
describe('PermissionsService', () => {
|
||||
let permissionsService: PermissionsService;
|
||||
|
||||
beforeAll(async () => {
|
||||
const module: TestingModule = await Test.createTestingModule({
|
||||
providers: [PermissionsService],
|
||||
imports: [PermissionsModule, UsersModule, LoggerModule, NotesModule],
|
||||
})
|
||||
.overrideProvider(getRepositoryToken(User))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(AuthToken))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Identity))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Authorship))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(AuthorColor))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Revision))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Note))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(Tag))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(NoteGroupPermission))
|
||||
.useValue({})
|
||||
.overrideProvider(getRepositoryToken(NoteUserPermission))
|
||||
.useValue({})
|
||||
.compile();
|
||||
permissionsService = module.get<PermissionsService>(PermissionsService);
|
||||
});
|
||||
|
||||
// The two users we test with:
|
||||
const user2 = {} as User;
|
||||
user2.id = '2';
|
||||
const user1 = {} as User;
|
||||
user1.id = '1';
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(permissionsService).toBeDefined();
|
||||
});
|
||||
|
||||
function createNote(owner: User): Note {
|
||||
const note = {} as Note;
|
||||
note.userPermissions = [];
|
||||
note.groupPermissions = [];
|
||||
note.owner = owner;
|
||||
return note;
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates the permission objects for UserPermission for two users with write and with out write permission
|
||||
*/
|
||||
function createNoteUserPermissionNotes(): Note[] {
|
||||
const note0 = createNote(user1);
|
||||
const note1 = createNote(user2);
|
||||
const note2 = createNote(user2);
|
||||
const note3 = createNote(user2);
|
||||
const note4 = createNote(user2);
|
||||
const note5 = createNote(user2);
|
||||
const note6 = createNote(user2);
|
||||
const note7 = createNote(user2);
|
||||
const noteUserPermission1 = {} as NoteUserPermission;
|
||||
noteUserPermission1.user = user1;
|
||||
const noteUserPermission2 = {} as NoteUserPermission;
|
||||
noteUserPermission2.user = user2;
|
||||
const noteUserPermission3 = {} as NoteUserPermission;
|
||||
noteUserPermission3.user = user1;
|
||||
noteUserPermission3.canEdit = true;
|
||||
const noteUserPermission4 = {} as NoteUserPermission;
|
||||
noteUserPermission4.user = user2;
|
||||
noteUserPermission4.canEdit = true;
|
||||
|
||||
note1.userPermissions.push(noteUserPermission1);
|
||||
|
||||
note2.userPermissions.push(noteUserPermission1);
|
||||
note2.userPermissions.push(noteUserPermission2);
|
||||
|
||||
note3.userPermissions.push(noteUserPermission2);
|
||||
note3.userPermissions.push(noteUserPermission1);
|
||||
|
||||
note4.userPermissions.push(noteUserPermission3);
|
||||
|
||||
note5.userPermissions.push(noteUserPermission3);
|
||||
note5.userPermissions.push(noteUserPermission4);
|
||||
|
||||
note6.userPermissions.push(noteUserPermission4);
|
||||
note6.userPermissions.push(noteUserPermission3);
|
||||
|
||||
note7.userPermissions.push(noteUserPermission2);
|
||||
|
||||
const everybody = {} as Group;
|
||||
everybody.name = 'everybody';
|
||||
everybody.special = true;
|
||||
const noteEverybodyRead = createNote(user1);
|
||||
|
||||
const noteGroupPermissionRead = {} as NoteGroupPermission;
|
||||
noteGroupPermissionRead.group = everybody;
|
||||
noteGroupPermissionRead.canEdit = false;
|
||||
noteGroupPermissionRead.note = noteEverybodyRead;
|
||||
noteEverybodyRead.groupPermissions = [noteGroupPermissionRead];
|
||||
|
||||
const noteEverybodyWrite = createNote(user1);
|
||||
|
||||
const noteGroupPermissionWrite = {} as NoteGroupPermission;
|
||||
noteGroupPermissionWrite.group = everybody;
|
||||
noteGroupPermissionWrite.canEdit = true;
|
||||
noteGroupPermissionWrite.note = noteEverybodyWrite;
|
||||
noteEverybodyWrite.groupPermissions = [noteGroupPermissionWrite];
|
||||
|
||||
return [
|
||||
note0,
|
||||
note1,
|
||||
note2,
|
||||
note3,
|
||||
note4,
|
||||
note5,
|
||||
note6,
|
||||
note7,
|
||||
noteEverybodyRead,
|
||||
noteEverybodyWrite,
|
||||
];
|
||||
}
|
||||
const notes = createNoteUserPermissionNotes();
|
||||
|
||||
describe('mayRead works with', () => {
|
||||
it('Owner', () => {
|
||||
permissionsService.guestPermission = GuestPermission.DENY;
|
||||
expect(permissionsService.mayRead(user1, notes[0])).toBeTruthy();
|
||||
expect(permissionsService.mayRead(user1, notes[7])).toBeFalsy();
|
||||
});
|
||||
it('userPermission read', () => {
|
||||
permissionsService.guestPermission = GuestPermission.DENY;
|
||||
expect(permissionsService.mayRead(user1, notes[1])).toBeTruthy();
|
||||
expect(permissionsService.mayRead(user1, notes[2])).toBeTruthy();
|
||||
expect(permissionsService.mayRead(user1, notes[3])).toBeTruthy();
|
||||
});
|
||||
it('userPermission write', () => {
|
||||
permissionsService.guestPermission = GuestPermission.DENY;
|
||||
expect(permissionsService.mayRead(user1, notes[4])).toBeTruthy();
|
||||
expect(permissionsService.mayRead(user1, notes[5])).toBeTruthy();
|
||||
expect(permissionsService.mayRead(user1, notes[6])).toBeTruthy();
|
||||
expect(permissionsService.mayRead(user1, notes[7])).toBeFalsy();
|
||||
});
|
||||
|
||||
describe('guest permission', () => {
|
||||
it('CREATE_ALIAS', () => {
|
||||
permissionsService.guestPermission = GuestPermission.CREATE_ALIAS;
|
||||
expect(permissionsService.mayRead(null, notes[8])).toBeTruthy();
|
||||
});
|
||||
it('CREATE', () => {
|
||||
permissionsService.guestPermission = GuestPermission.CREATE;
|
||||
expect(permissionsService.mayRead(null, notes[8])).toBeTruthy();
|
||||
});
|
||||
it('WRITE', () => {
|
||||
permissionsService.guestPermission = GuestPermission.WRITE;
|
||||
expect(permissionsService.mayRead(null, notes[8])).toBeTruthy();
|
||||
});
|
||||
it('READ', () => {
|
||||
permissionsService.guestPermission = GuestPermission.READ;
|
||||
expect(permissionsService.mayRead(null, notes[8])).toBeTruthy();
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('mayWrite works with', () => {
|
||||
it('Owner', () => {
|
||||
permissionsService.guestPermission = GuestPermission.DENY;
|
||||
expect(permissionsService.mayWrite(user1, notes[0])).toBeTruthy();
|
||||
expect(permissionsService.mayWrite(user1, notes[7])).toBeFalsy();
|
||||
});
|
||||
it('userPermission read', () => {
|
||||
permissionsService.guestPermission = GuestPermission.DENY;
|
||||
expect(permissionsService.mayWrite(user1, notes[1])).toBeFalsy();
|
||||
expect(permissionsService.mayWrite(user1, notes[2])).toBeFalsy();
|
||||
expect(permissionsService.mayWrite(user1, notes[3])).toBeFalsy();
|
||||
});
|
||||
it('userPermission write', () => {
|
||||
permissionsService.guestPermission = GuestPermission.DENY;
|
||||
expect(permissionsService.mayWrite(user1, notes[4])).toBeTruthy();
|
||||
expect(permissionsService.mayWrite(user1, notes[5])).toBeTruthy();
|
||||
expect(permissionsService.mayWrite(user1, notes[6])).toBeTruthy();
|
||||
expect(permissionsService.mayWrite(user1, notes[7])).toBeFalsy();
|
||||
});
|
||||
describe('guest permission', () => {
|
||||
it('CREATE_ALIAS', () => {
|
||||
permissionsService.guestPermission = GuestPermission.CREATE_ALIAS;
|
||||
expect(permissionsService.mayWrite(null, notes[9])).toBeTruthy();
|
||||
});
|
||||
it('CREATE', () => {
|
||||
permissionsService.guestPermission = GuestPermission.CREATE;
|
||||
expect(permissionsService.mayWrite(null, notes[9])).toBeTruthy();
|
||||
});
|
||||
it('WRITE', () => {
|
||||
permissionsService.guestPermission = GuestPermission.WRITE;
|
||||
expect(permissionsService.mayWrite(null, notes[9])).toBeTruthy();
|
||||
});
|
||||
it('READ', () => {
|
||||
permissionsService.guestPermission = GuestPermission.READ;
|
||||
expect(permissionsService.mayWrite(null, notes[9])).toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
/*
|
||||
* Helper Object that arranges a list of GroupPermissions and if they allow a user to read or write a particular note.
|
||||
*/
|
||||
class NoteGroupPermissionWithResultForUser {
|
||||
permissions: NoteGroupPermission[];
|
||||
allowsRead: boolean;
|
||||
allowsWrite: boolean;
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup function to create all the groups we use in the tests.
|
||||
*/
|
||||
function createGroups(): { [id: string]: Group } {
|
||||
const result: { [id: string]: Group } = {};
|
||||
|
||||
const everybody: Group = new Group();
|
||||
everybody.special = true;
|
||||
everybody.name = 'everybody';
|
||||
result['everybody'] = everybody;
|
||||
|
||||
const loggedIn = new Group();
|
||||
loggedIn.special = true;
|
||||
loggedIn.name = 'loggedIn';
|
||||
result['loggedIn'] = loggedIn;
|
||||
|
||||
const user1group = new Group();
|
||||
user1group.name = 'user1group';
|
||||
user1group.members = [user1];
|
||||
result['user1group'] = user1group;
|
||||
|
||||
const user2group = new Group();
|
||||
user2group.name = 'user2group';
|
||||
user2group.members = [user2];
|
||||
result['user2group'] = user2group;
|
||||
|
||||
const user1and2group = new Group();
|
||||
user1and2group.name = 'user1and2group';
|
||||
user1and2group.members = [user1, user2];
|
||||
result['user1and2group'] = user1and2group;
|
||||
|
||||
const user2and1group = new Group();
|
||||
user2and1group.name = 'user2and1group';
|
||||
user2and1group.members = [user2, user1];
|
||||
result['user2and1group'] = user2and1group;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create all GroupPermissions: For each group two GroupPermissions are created one with read permission and one with write permission.
|
||||
*/
|
||||
function createAllNoteGroupPermissions(): NoteGroupPermission[][] {
|
||||
const groups = createGroups();
|
||||
|
||||
/*
|
||||
* Helper function for creating GroupPermissions
|
||||
*/
|
||||
function createNoteGroupPermission(
|
||||
group: Group,
|
||||
write: boolean,
|
||||
): NoteGroupPermission {
|
||||
const noteGroupPermission = new NoteGroupPermission();
|
||||
noteGroupPermission.canEdit = write;
|
||||
noteGroupPermission.group = group;
|
||||
return noteGroupPermission;
|
||||
}
|
||||
|
||||
const everybodyRead = createNoteGroupPermission(groups['everybody'], false);
|
||||
const everybodyWrite = createNoteGroupPermission(groups['everybody'], true);
|
||||
|
||||
const loggedInRead = createNoteGroupPermission(groups['loggedIn'], false);
|
||||
const loggedInWrite = createNoteGroupPermission(groups['loggedIn'], true);
|
||||
|
||||
const user1groupRead = createNoteGroupPermission(
|
||||
groups['user1group'],
|
||||
false,
|
||||
);
|
||||
const user1groupWrite = createNoteGroupPermission(
|
||||
groups['user1group'],
|
||||
true,
|
||||
);
|
||||
|
||||
const user2groupRead = createNoteGroupPermission(
|
||||
groups['user2group'],
|
||||
false,
|
||||
);
|
||||
const user2groupWrite = createNoteGroupPermission(
|
||||
groups['user2group'],
|
||||
true,
|
||||
);
|
||||
|
||||
const user1and2groupRead = createNoteGroupPermission(
|
||||
groups['user1and2group'],
|
||||
false,
|
||||
);
|
||||
const user1and2groupWrite = createNoteGroupPermission(
|
||||
groups['user1and2group'],
|
||||
true,
|
||||
);
|
||||
|
||||
const user2and1groupRead = createNoteGroupPermission(
|
||||
groups['user2and1group'],
|
||||
false,
|
||||
);
|
||||
const user2and1groupWrite = createNoteGroupPermission(
|
||||
groups['user2and1group'],
|
||||
true,
|
||||
);
|
||||
|
||||
return [
|
||||
[user1groupRead, user1and2groupRead, user2and1groupRead, null], // group0: allow user1 to read via group
|
||||
[user2and1groupWrite, user1and2groupWrite, user1groupWrite, null], // group1: allow user1 to write via group
|
||||
[everybodyRead, everybodyWrite, null], // group2: permissions of the special group everybody
|
||||
[loggedInRead, loggedInWrite, null], // group3: permissions of the special group loggedIn
|
||||
[user2groupWrite, user2groupRead, null], // group4: don't allow user1 to read or write via group
|
||||
];
|
||||
}
|
||||
/*
|
||||
* creates the matrix multiplication of group0 to group4 of createAllNoteGroupPermissions
|
||||
*/
|
||||
function createNoteGroupPermissionsCombinations(
|
||||
guestPermission: GuestPermission,
|
||||
): NoteGroupPermissionWithResultForUser[] {
|
||||
// for logged in users
|
||||
const noteGroupPermissions = createAllNoteGroupPermissions();
|
||||
const result: NoteGroupPermissionWithResultForUser[] = [];
|
||||
for (const group0 of noteGroupPermissions[0]) {
|
||||
for (const group1 of noteGroupPermissions[1]) {
|
||||
for (const group2 of noteGroupPermissions[2]) {
|
||||
for (const group3 of noteGroupPermissions[3]) {
|
||||
for (const group4 of noteGroupPermissions[4]) {
|
||||
const insert = [];
|
||||
let readPermission = false;
|
||||
let writePermission = false;
|
||||
if (group0 !== null) {
|
||||
// user1 in ReadGroups
|
||||
readPermission = true;
|
||||
insert.push(group0);
|
||||
}
|
||||
if (group1 !== null) {
|
||||
// user1 in WriteGroups
|
||||
readPermission = true;
|
||||
writePermission = true;
|
||||
insert.push(group1);
|
||||
}
|
||||
|
||||
if (group2 !== null) {
|
||||
// everybody group TODO config options
|
||||
switch (guestPermission) {
|
||||
case GuestPermission.CREATE_ALIAS:
|
||||
case GuestPermission.CREATE:
|
||||
case GuestPermission.WRITE:
|
||||
writePermission = writePermission || group2.canEdit;
|
||||
readPermission = true;
|
||||
break;
|
||||
case GuestPermission.READ:
|
||||
readPermission = true;
|
||||
}
|
||||
insert.push(group2);
|
||||
}
|
||||
if (group3 !== null) {
|
||||
// loggedIn users
|
||||
readPermission = true;
|
||||
writePermission = writePermission || group3.canEdit;
|
||||
insert.push(group3);
|
||||
}
|
||||
if (group4 !== null) {
|
||||
// user not in group
|
||||
insert.push(group4);
|
||||
}
|
||||
result.push({
|
||||
permissions: insert,
|
||||
allowsRead: readPermission,
|
||||
allowsWrite: writePermission,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// inspired by https://stackoverflow.com/questions/9960908/permutations-in-javascript
|
||||
function permutator(
|
||||
inputArr: NoteGroupPermission[],
|
||||
): NoteGroupPermission[][] {
|
||||
const results = [];
|
||||
|
||||
function permute(arr, memo) {
|
||||
let cur;
|
||||
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
cur = arr.splice(i, 1);
|
||||
if (arr.length === 0) {
|
||||
results.push(memo.concat(cur));
|
||||
}
|
||||
permute(arr.slice(), memo.concat(cur));
|
||||
arr.splice(i, 0, cur[0]);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
return permute(inputArr, []);
|
||||
}
|
||||
|
||||
// takes each set of permissions from createNoteGroupPermissionsCombinations, permute them and add them to the list
|
||||
function permuteNoteGroupPermissions(
|
||||
noteGroupPermissions: NoteGroupPermissionWithResultForUser[],
|
||||
): NoteGroupPermissionWithResultForUser[] {
|
||||
const result: NoteGroupPermissionWithResultForUser[] = [];
|
||||
for (const permission of noteGroupPermissions) {
|
||||
const permutations = permutator(permission.permissions);
|
||||
for (const permutation of permutations) {
|
||||
result.push({
|
||||
permissions: permutation,
|
||||
allowsRead: permission.allowsRead,
|
||||
allowsWrite: permission.allowsWrite,
|
||||
});
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
describe('check if groups work with', () => {
|
||||
const guestPermission = GuestPermission.WRITE;
|
||||
const rawPermissions = createNoteGroupPermissionsCombinations(
|
||||
guestPermission,
|
||||
);
|
||||
const permissions = permuteNoteGroupPermissions(rawPermissions);
|
||||
let i = 0;
|
||||
for (const permission of permissions) {
|
||||
const note = createNote(user2);
|
||||
note.groupPermissions = permission.permissions;
|
||||
let permissionString = '';
|
||||
for (const perm of permission.permissions) {
|
||||
permissionString += ' ' + perm.group.name + ':' + perm.canEdit;
|
||||
}
|
||||
it('mayWrite - test #' + i + ':' + permissionString, () => {
|
||||
permissionsService.guestPermission = guestPermission;
|
||||
expect(permissionsService.mayWrite(user1, note)).toEqual(
|
||||
permission.allowsWrite,
|
||||
);
|
||||
});
|
||||
it('mayRead - test #' + i + ':' + permissionString, () => {
|
||||
permissionsService.guestPermission = guestPermission;
|
||||
expect(permissionsService.mayRead(user1, note)).toEqual(
|
||||
permission.allowsRead,
|
||||
);
|
||||
});
|
||||
i++;
|
||||
}
|
||||
});
|
||||
|
||||
describe('mayCreate works for', () => {
|
||||
it('logged in', () => {
|
||||
permissionsService.guestPermission = GuestPermission.DENY;
|
||||
expect(permissionsService.mayCreate(user1)).toBeTruthy();
|
||||
});
|
||||
it('guest denied', () => {
|
||||
permissionsService.guestPermission = GuestPermission.DENY;
|
||||
expect(permissionsService.mayCreate(null)).toBeFalsy();
|
||||
});
|
||||
it('guest read', () => {
|
||||
permissionsService.guestPermission = GuestPermission.READ;
|
||||
expect(permissionsService.mayCreate(null)).toBeFalsy();
|
||||
});
|
||||
it('guest write', () => {
|
||||
permissionsService.guestPermission = GuestPermission.WRITE;
|
||||
expect(permissionsService.mayCreate(null)).toBeFalsy();
|
||||
});
|
||||
it('guest create', () => {
|
||||
permissionsService.guestPermission = GuestPermission.CREATE;
|
||||
expect(permissionsService.mayCreate(null)).toBeTruthy();
|
||||
});
|
||||
it('guest create alias', () => {
|
||||
permissionsService.guestPermission = GuestPermission.CREATE_ALIAS;
|
||||
expect(permissionsService.mayCreate(null)).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('isOwner works', () => {
|
||||
it('for positive case', () => {
|
||||
permissionsService.guestPermission = GuestPermission.DENY;
|
||||
expect(permissionsService.isOwner(user1, notes[0])).toBeTruthy();
|
||||
});
|
||||
it('for negative case', () => {
|
||||
permissionsService.guestPermission = GuestPermission.DENY;
|
||||
expect(permissionsService.isOwner(user1, notes[1])).toBeFalsy();
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in a new issue