mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-05-13 22:54:42 -04:00
Move permission update functions to permissions controller
Signed-off-by: Yannick Bungers <git@innay.de>
This commit is contained in:
parent
e1e3138561
commit
70d7ca5475
6 changed files with 888 additions and 865 deletions
|
@ -34,6 +34,7 @@ import { Note } from '../../../notes/note.entity';
|
||||||
import { NoteMediaDeletionDto } from '../../../notes/note.media-deletion.dto';
|
import { NoteMediaDeletionDto } from '../../../notes/note.media-deletion.dto';
|
||||||
import { NotesService } from '../../../notes/notes.service';
|
import { NotesService } from '../../../notes/notes.service';
|
||||||
import { Permission } from '../../../permissions/permissions.enum';
|
import { Permission } from '../../../permissions/permissions.enum';
|
||||||
|
import { PermissionsService } from '../../../permissions/permissions.service';
|
||||||
import { RevisionMetadataDto } from '../../../revisions/revision-metadata.dto';
|
import { RevisionMetadataDto } from '../../../revisions/revision-metadata.dto';
|
||||||
import { RevisionDto } from '../../../revisions/revision.dto';
|
import { RevisionDto } from '../../../revisions/revision.dto';
|
||||||
import { RevisionsService } from '../../../revisions/revisions.service';
|
import { RevisionsService } from '../../../revisions/revisions.service';
|
||||||
|
@ -61,6 +62,7 @@ export class NotesController {
|
||||||
private revisionsService: RevisionsService,
|
private revisionsService: RevisionsService,
|
||||||
private historyService: HistoryService,
|
private historyService: HistoryService,
|
||||||
private mediaService: MediaService,
|
private mediaService: MediaService,
|
||||||
|
private permissionService: PermissionsService,
|
||||||
) {
|
) {
|
||||||
this.logger.setContext(NotesController.name);
|
this.logger.setContext(NotesController.name);
|
||||||
}
|
}
|
||||||
|
@ -224,7 +226,7 @@ export class NotesController {
|
||||||
@Body() updateDto: NotePermissionsUpdateDto,
|
@Body() updateDto: NotePermissionsUpdateDto,
|
||||||
): Promise<NotePermissionsDto> {
|
): Promise<NotePermissionsDto> {
|
||||||
return await this.noteService.toNotePermissionsDto(
|
return await this.noteService.toNotePermissionsDto(
|
||||||
await this.noteService.updateNotePermissions(note, updateDto),
|
await this.permissionService.updateNotePermissions(note, updateDto),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,22 +268,13 @@ export class NotesController {
|
||||||
@Param('userName') username: string,
|
@Param('userName') username: string,
|
||||||
@Body() canEdit: boolean,
|
@Body() canEdit: boolean,
|
||||||
): Promise<NotePermissionsDto> {
|
): Promise<NotePermissionsDto> {
|
||||||
try {
|
const permissionUser = await this.userService.getUserByUsername(username);
|
||||||
const permissionUser = await this.userService.getUserByUsername(username);
|
const returnedNote = await this.permissionService.setUserPermission(
|
||||||
const returnedNote = await this.noteService.setUserPermission(
|
note,
|
||||||
note,
|
permissionUser,
|
||||||
permissionUser,
|
canEdit,
|
||||||
canEdit,
|
);
|
||||||
);
|
return await this.noteService.toNotePermissionsDto(returnedNote);
|
||||||
return await this.noteService.toNotePermissionsDto(returnedNote);
|
|
||||||
} catch (e) {
|
|
||||||
if (e instanceof NotInDBError) {
|
|
||||||
throw new BadRequestException(
|
|
||||||
"Can't add user to permissions. User not known.",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@UseInterceptors(GetNoteInterceptor)
|
@UseInterceptors(GetNoteInterceptor)
|
||||||
|
@ -304,7 +297,7 @@ export class NotesController {
|
||||||
): Promise<NotePermissionsDto> {
|
): Promise<NotePermissionsDto> {
|
||||||
try {
|
try {
|
||||||
const permissionUser = await this.userService.getUserByUsername(username);
|
const permissionUser = await this.userService.getUserByUsername(username);
|
||||||
const returnedNote = await this.noteService.removeUserPermission(
|
const returnedNote = await this.permissionService.removeUserPermission(
|
||||||
note,
|
note,
|
||||||
permissionUser,
|
permissionUser,
|
||||||
);
|
);
|
||||||
|
@ -338,22 +331,13 @@ export class NotesController {
|
||||||
@Param('groupName') groupName: string,
|
@Param('groupName') groupName: string,
|
||||||
@Body() canEdit: boolean,
|
@Body() canEdit: boolean,
|
||||||
): Promise<NotePermissionsDto> {
|
): Promise<NotePermissionsDto> {
|
||||||
try {
|
const permissionGroup = await this.groupService.getGroupByName(groupName);
|
||||||
const permissionGroup = await this.groupService.getGroupByName(groupName);
|
const returnedNote = await this.permissionService.setGroupPermission(
|
||||||
const returnedNote = await this.noteService.setGroupPermission(
|
note,
|
||||||
note,
|
permissionGroup,
|
||||||
permissionGroup,
|
canEdit,
|
||||||
canEdit,
|
);
|
||||||
);
|
return await this.noteService.toNotePermissionsDto(returnedNote);
|
||||||
return await this.noteService.toNotePermissionsDto(returnedNote);
|
|
||||||
} catch (e) {
|
|
||||||
if (e instanceof NotInDBError) {
|
|
||||||
throw new BadRequestException(
|
|
||||||
"Can't add group to permissions. Group not known.",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@UseInterceptors(GetNoteInterceptor)
|
@UseInterceptors(GetNoteInterceptor)
|
||||||
|
@ -374,21 +358,12 @@ export class NotesController {
|
||||||
@RequestNote() note: Note,
|
@RequestNote() note: Note,
|
||||||
@Param('groupName') groupName: string,
|
@Param('groupName') groupName: string,
|
||||||
): Promise<NotePermissionsDto> {
|
): Promise<NotePermissionsDto> {
|
||||||
try {
|
const permissionGroup = await this.groupService.getGroupByName(groupName);
|
||||||
const permissionGroup = await this.groupService.getGroupByName(groupName);
|
const returnedNote = await this.permissionService.removeGroupPermission(
|
||||||
const returnedNote = await this.noteService.removeGroupPermission(
|
note,
|
||||||
note,
|
permissionGroup,
|
||||||
permissionGroup,
|
);
|
||||||
);
|
return await this.noteService.toNotePermissionsDto(returnedNote);
|
||||||
return await this.noteService.toNotePermissionsDto(returnedNote);
|
|
||||||
} catch (e) {
|
|
||||||
if (e instanceof NotInDBError) {
|
|
||||||
throw new BadRequestException(
|
|
||||||
"Can't remove group from permissions. Group not known.",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@UseInterceptors(GetNoteInterceptor)
|
@UseInterceptors(GetNoteInterceptor)
|
||||||
|
@ -409,17 +384,10 @@ export class NotesController {
|
||||||
@RequestNote() note: Note,
|
@RequestNote() note: Note,
|
||||||
@Body() newOwner: string,
|
@Body() newOwner: string,
|
||||||
): Promise<NoteDto> {
|
): Promise<NoteDto> {
|
||||||
try {
|
const owner = await this.userService.getUserByUsername(newOwner);
|
||||||
const owner = await this.userService.getUserByUsername(newOwner);
|
return await this.noteService.toNoteDto(
|
||||||
return await this.noteService.toNoteDto(
|
await this.permissionService.changeOwner(note, owner),
|
||||||
await this.noteService.changeOwner(note, owner),
|
);
|
||||||
);
|
|
||||||
} catch (e) {
|
|
||||||
if (e instanceof NotInDBError) {
|
|
||||||
throw new BadRequestException("Can't set new owner. User not known.");
|
|
||||||
}
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@UseInterceptors(GetNoteInterceptor)
|
@UseInterceptors(GetNoteInterceptor)
|
||||||
|
|
|
@ -16,7 +16,6 @@ import {
|
||||||
AlreadyInDBError,
|
AlreadyInDBError,
|
||||||
ForbiddenIdError,
|
ForbiddenIdError,
|
||||||
NotInDBError,
|
NotInDBError,
|
||||||
PermissionsUpdateInconsistentError,
|
|
||||||
} from '../errors/errors';
|
} from '../errors/errors';
|
||||||
import { Group } from '../groups/group.entity';
|
import { Group } from '../groups/group.entity';
|
||||||
import { GroupsModule } from '../groups/groups.module';
|
import { GroupsModule } from '../groups/groups.module';
|
||||||
|
@ -32,10 +31,6 @@ import { User } from '../users/user.entity';
|
||||||
import { UsersModule } from '../users/users.module';
|
import { UsersModule } from '../users/users.module';
|
||||||
import { Alias } from './alias.entity';
|
import { Alias } from './alias.entity';
|
||||||
import { AliasService } from './alias.service';
|
import { AliasService } from './alias.service';
|
||||||
import {
|
|
||||||
NoteGroupPermissionUpdateDto,
|
|
||||||
NoteUserPermissionUpdateDto,
|
|
||||||
} from './note-permissions.dto';
|
|
||||||
import { Note } from './note.entity';
|
import { Note } from './note.entity';
|
||||||
import { NotesService } from './notes.service';
|
import { NotesService } from './notes.service';
|
||||||
import { Tag } from './tag.entity';
|
import { Tag } from './tag.entity';
|
||||||
|
@ -45,7 +40,6 @@ describe('NotesService', () => {
|
||||||
let noteRepo: Repository<Note>;
|
let noteRepo: Repository<Note>;
|
||||||
let revisionRepo: Repository<Revision>;
|
let revisionRepo: Repository<Revision>;
|
||||||
let userRepo: Repository<User>;
|
let userRepo: Repository<User>;
|
||||||
let groupRepo: Repository<Group>;
|
|
||||||
let forbiddenNoteId: string;
|
let forbiddenNoteId: string;
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
|
@ -122,8 +116,6 @@ describe('NotesService', () => {
|
||||||
revisionRepo = module.get<Repository<Revision>>(
|
revisionRepo = module.get<Repository<Revision>>(
|
||||||
getRepositoryToken(Revision),
|
getRepositoryToken(Revision),
|
||||||
);
|
);
|
||||||
userRepo = module.get<Repository<User>>(getRepositoryToken(User));
|
|
||||||
groupRepo = module.get<Repository<Group>>(getRepositoryToken(Group));
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should be defined', () => {
|
it('should be defined', () => {
|
||||||
|
@ -357,536 +349,6 @@ describe('NotesService', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('updateNotePermissions', () => {
|
|
||||||
const userPermissionUpdate = new NoteUserPermissionUpdateDto();
|
|
||||||
userPermissionUpdate.username = 'hardcoded';
|
|
||||||
userPermissionUpdate.canEdit = true;
|
|
||||||
const groupPermissionUpate = new NoteGroupPermissionUpdateDto();
|
|
||||||
groupPermissionUpate.groupName = 'testGroup';
|
|
||||||
groupPermissionUpate.canEdit = false;
|
|
||||||
const user = User.create(userPermissionUpdate.username, 'Testy') as User;
|
|
||||||
const group = Group.create(
|
|
||||||
groupPermissionUpate.groupName,
|
|
||||||
groupPermissionUpate.groupName,
|
|
||||||
false,
|
|
||||||
) as Group;
|
|
||||||
const note = Note.create(user) as Note;
|
|
||||||
describe('works', () => {
|
|
||||||
it('with empty GroupPermissions and with empty UserPermissions', async () => {
|
|
||||||
jest
|
|
||||||
.spyOn(noteRepo, 'save')
|
|
||||||
.mockImplementationOnce(async (entry: Note) => {
|
|
||||||
return entry;
|
|
||||||
});
|
|
||||||
const savedNote = await service.updateNotePermissions(note, {
|
|
||||||
sharedToUsers: [],
|
|
||||||
sharedToGroups: [],
|
|
||||||
});
|
|
||||||
expect(await savedNote.userPermissions).toHaveLength(0);
|
|
||||||
expect(await savedNote.groupPermissions).toHaveLength(0);
|
|
||||||
});
|
|
||||||
it('with empty GroupPermissions and with new UserPermissions', async () => {
|
|
||||||
jest
|
|
||||||
.spyOn(noteRepo, 'save')
|
|
||||||
.mockImplementationOnce(async (entry: Note) => {
|
|
||||||
return entry;
|
|
||||||
});
|
|
||||||
jest.spyOn(userRepo, 'findOne').mockResolvedValueOnce(user);
|
|
||||||
const savedNote = await service.updateNotePermissions(note, {
|
|
||||||
sharedToUsers: [userPermissionUpdate],
|
|
||||||
sharedToGroups: [],
|
|
||||||
});
|
|
||||||
expect(await savedNote.userPermissions).toHaveLength(1);
|
|
||||||
expect((await savedNote.userPermissions)[0].user.username).toEqual(
|
|
||||||
userPermissionUpdate.username,
|
|
||||||
);
|
|
||||||
expect((await savedNote.userPermissions)[0].canEdit).toEqual(
|
|
||||||
userPermissionUpdate.canEdit,
|
|
||||||
);
|
|
||||||
expect(await savedNote.groupPermissions).toHaveLength(0);
|
|
||||||
});
|
|
||||||
it('with empty GroupPermissions and with existing UserPermissions', async () => {
|
|
||||||
const noteWithPreexistingPermissions: Note = { ...note };
|
|
||||||
noteWithPreexistingPermissions.userPermissions = Promise.resolve([
|
|
||||||
{
|
|
||||||
note: noteWithPreexistingPermissions,
|
|
||||||
user: user,
|
|
||||||
canEdit: !userPermissionUpdate.canEdit,
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
jest
|
|
||||||
.spyOn(noteRepo, 'save')
|
|
||||||
.mockImplementationOnce(async (entry: Note) => {
|
|
||||||
return entry;
|
|
||||||
});
|
|
||||||
jest.spyOn(userRepo, 'findOne').mockResolvedValueOnce(user);
|
|
||||||
const savedNote = await service.updateNotePermissions(note, {
|
|
||||||
sharedToUsers: [userPermissionUpdate],
|
|
||||||
sharedToGroups: [],
|
|
||||||
});
|
|
||||||
expect(await savedNote.userPermissions).toHaveLength(1);
|
|
||||||
expect((await savedNote.userPermissions)[0].user.username).toEqual(
|
|
||||||
userPermissionUpdate.username,
|
|
||||||
);
|
|
||||||
expect((await savedNote.userPermissions)[0].canEdit).toEqual(
|
|
||||||
userPermissionUpdate.canEdit,
|
|
||||||
);
|
|
||||||
expect(await savedNote.groupPermissions).toHaveLength(0);
|
|
||||||
});
|
|
||||||
it('with new GroupPermissions and with empty UserPermissions', async () => {
|
|
||||||
jest
|
|
||||||
.spyOn(noteRepo, 'save')
|
|
||||||
.mockImplementationOnce(async (entry: Note) => {
|
|
||||||
return entry;
|
|
||||||
});
|
|
||||||
jest.spyOn(groupRepo, 'findOne').mockResolvedValueOnce(group);
|
|
||||||
const savedNote = await service.updateNotePermissions(note, {
|
|
||||||
sharedToUsers: [],
|
|
||||||
sharedToGroups: [groupPermissionUpate],
|
|
||||||
});
|
|
||||||
expect(await savedNote.userPermissions).toHaveLength(0);
|
|
||||||
expect((await savedNote.groupPermissions)[0].group.name).toEqual(
|
|
||||||
groupPermissionUpate.groupName,
|
|
||||||
);
|
|
||||||
expect((await savedNote.groupPermissions)[0].canEdit).toEqual(
|
|
||||||
groupPermissionUpate.canEdit,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
it('with new GroupPermissions and with new UserPermissions', async () => {
|
|
||||||
jest
|
|
||||||
.spyOn(noteRepo, 'save')
|
|
||||||
.mockImplementationOnce(async (entry: Note) => {
|
|
||||||
return entry;
|
|
||||||
});
|
|
||||||
jest.spyOn(userRepo, 'findOne').mockResolvedValueOnce(user);
|
|
||||||
jest.spyOn(groupRepo, 'findOne').mockResolvedValueOnce(group);
|
|
||||||
const savedNote = await service.updateNotePermissions(note, {
|
|
||||||
sharedToUsers: [userPermissionUpdate],
|
|
||||||
sharedToGroups: [groupPermissionUpate],
|
|
||||||
});
|
|
||||||
expect((await savedNote.userPermissions)[0].user.username).toEqual(
|
|
||||||
userPermissionUpdate.username,
|
|
||||||
);
|
|
||||||
expect((await savedNote.userPermissions)[0].canEdit).toEqual(
|
|
||||||
userPermissionUpdate.canEdit,
|
|
||||||
);
|
|
||||||
expect((await savedNote.groupPermissions)[0].group.name).toEqual(
|
|
||||||
groupPermissionUpate.groupName,
|
|
||||||
);
|
|
||||||
expect((await savedNote.groupPermissions)[0].canEdit).toEqual(
|
|
||||||
groupPermissionUpate.canEdit,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
it('with new GroupPermissions and with existing UserPermissions', async () => {
|
|
||||||
const noteWithUserPermission: Note = { ...note };
|
|
||||||
noteWithUserPermission.userPermissions = Promise.resolve([
|
|
||||||
{
|
|
||||||
note: noteWithUserPermission,
|
|
||||||
user: user,
|
|
||||||
canEdit: !userPermissionUpdate.canEdit,
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
jest
|
|
||||||
.spyOn(noteRepo, 'save')
|
|
||||||
.mockImplementationOnce(async (entry: Note) => {
|
|
||||||
return entry;
|
|
||||||
});
|
|
||||||
jest.spyOn(userRepo, 'findOne').mockResolvedValueOnce(user);
|
|
||||||
jest.spyOn(groupRepo, 'findOne').mockResolvedValueOnce(group);
|
|
||||||
const savedNote = await service.updateNotePermissions(
|
|
||||||
noteWithUserPermission,
|
|
||||||
{
|
|
||||||
sharedToUsers: [userPermissionUpdate],
|
|
||||||
sharedToGroups: [groupPermissionUpate],
|
|
||||||
},
|
|
||||||
);
|
|
||||||
expect((await savedNote.userPermissions)[0].user.username).toEqual(
|
|
||||||
userPermissionUpdate.username,
|
|
||||||
);
|
|
||||||
expect((await savedNote.userPermissions)[0].canEdit).toEqual(
|
|
||||||
userPermissionUpdate.canEdit,
|
|
||||||
);
|
|
||||||
expect((await savedNote.groupPermissions)[0].group.name).toEqual(
|
|
||||||
groupPermissionUpate.groupName,
|
|
||||||
);
|
|
||||||
expect((await savedNote.groupPermissions)[0].canEdit).toEqual(
|
|
||||||
groupPermissionUpate.canEdit,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
it('with existing GroupPermissions and with empty UserPermissions', async () => {
|
|
||||||
const noteWithPreexistingPermissions: Note = { ...note };
|
|
||||||
noteWithPreexistingPermissions.groupPermissions = Promise.resolve([
|
|
||||||
{
|
|
||||||
note: noteWithPreexistingPermissions,
|
|
||||||
group: group,
|
|
||||||
canEdit: !groupPermissionUpate.canEdit,
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
jest.spyOn(groupRepo, 'findOne').mockResolvedValueOnce(group);
|
|
||||||
jest
|
|
||||||
.spyOn(noteRepo, 'save')
|
|
||||||
.mockImplementationOnce(async (entry: Note) => {
|
|
||||||
return entry;
|
|
||||||
});
|
|
||||||
const savedNote = await service.updateNotePermissions(
|
|
||||||
noteWithPreexistingPermissions,
|
|
||||||
{
|
|
||||||
sharedToUsers: [],
|
|
||||||
sharedToGroups: [groupPermissionUpate],
|
|
||||||
},
|
|
||||||
);
|
|
||||||
expect(await savedNote.userPermissions).toHaveLength(0);
|
|
||||||
expect((await savedNote.groupPermissions)[0].group.name).toEqual(
|
|
||||||
groupPermissionUpate.groupName,
|
|
||||||
);
|
|
||||||
expect((await savedNote.groupPermissions)[0].canEdit).toEqual(
|
|
||||||
groupPermissionUpate.canEdit,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
it('with existing GroupPermissions and with new UserPermissions', async () => {
|
|
||||||
const noteWithPreexistingPermissions: Note = { ...note };
|
|
||||||
noteWithPreexistingPermissions.groupPermissions = Promise.resolve([
|
|
||||||
{
|
|
||||||
note: noteWithPreexistingPermissions,
|
|
||||||
group: group,
|
|
||||||
canEdit: !groupPermissionUpate.canEdit,
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
jest
|
|
||||||
.spyOn(noteRepo, 'save')
|
|
||||||
.mockImplementationOnce(async (entry: Note) => {
|
|
||||||
return entry;
|
|
||||||
});
|
|
||||||
jest.spyOn(userRepo, 'findOne').mockResolvedValueOnce(user);
|
|
||||||
jest.spyOn(groupRepo, 'findOne').mockResolvedValueOnce(group);
|
|
||||||
const savedNote = await service.updateNotePermissions(
|
|
||||||
noteWithPreexistingPermissions,
|
|
||||||
{
|
|
||||||
sharedToUsers: [userPermissionUpdate],
|
|
||||||
sharedToGroups: [groupPermissionUpate],
|
|
||||||
},
|
|
||||||
);
|
|
||||||
expect((await savedNote.userPermissions)[0].user.username).toEqual(
|
|
||||||
userPermissionUpdate.username,
|
|
||||||
);
|
|
||||||
expect((await savedNote.userPermissions)[0].canEdit).toEqual(
|
|
||||||
userPermissionUpdate.canEdit,
|
|
||||||
);
|
|
||||||
expect((await savedNote.groupPermissions)[0].group.name).toEqual(
|
|
||||||
groupPermissionUpate.groupName,
|
|
||||||
);
|
|
||||||
expect((await savedNote.groupPermissions)[0].canEdit).toEqual(
|
|
||||||
groupPermissionUpate.canEdit,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
it('with existing GroupPermissions and with existing UserPermissions', async () => {
|
|
||||||
const noteWithPreexistingPermissions: Note = { ...note };
|
|
||||||
noteWithPreexistingPermissions.groupPermissions = Promise.resolve([
|
|
||||||
{
|
|
||||||
note: noteWithPreexistingPermissions,
|
|
||||||
group: group,
|
|
||||||
canEdit: !groupPermissionUpate.canEdit,
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
noteWithPreexistingPermissions.userPermissions = Promise.resolve([
|
|
||||||
{
|
|
||||||
note: noteWithPreexistingPermissions,
|
|
||||||
user: user,
|
|
||||||
canEdit: !userPermissionUpdate.canEdit,
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
jest
|
|
||||||
.spyOn(noteRepo, 'save')
|
|
||||||
.mockImplementationOnce(async (entry: Note) => {
|
|
||||||
return entry;
|
|
||||||
});
|
|
||||||
jest.spyOn(userRepo, 'findOne').mockResolvedValueOnce(user);
|
|
||||||
jest.spyOn(groupRepo, 'findOne').mockResolvedValueOnce(group);
|
|
||||||
const savedNote = await service.updateNotePermissions(
|
|
||||||
noteWithPreexistingPermissions,
|
|
||||||
{
|
|
||||||
sharedToUsers: [userPermissionUpdate],
|
|
||||||
sharedToGroups: [groupPermissionUpate],
|
|
||||||
},
|
|
||||||
);
|
|
||||||
expect((await savedNote.userPermissions)[0].user.username).toEqual(
|
|
||||||
userPermissionUpdate.username,
|
|
||||||
);
|
|
||||||
expect((await savedNote.userPermissions)[0].canEdit).toEqual(
|
|
||||||
userPermissionUpdate.canEdit,
|
|
||||||
);
|
|
||||||
expect((await savedNote.groupPermissions)[0].group.name).toEqual(
|
|
||||||
groupPermissionUpate.groupName,
|
|
||||||
);
|
|
||||||
expect((await savedNote.groupPermissions)[0].canEdit).toEqual(
|
|
||||||
groupPermissionUpate.canEdit,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
describe('fails:', () => {
|
|
||||||
it('userPermissions has duplicate entries', async () => {
|
|
||||||
await expect(
|
|
||||||
service.updateNotePermissions(note, {
|
|
||||||
sharedToUsers: [userPermissionUpdate, userPermissionUpdate],
|
|
||||||
sharedToGroups: [],
|
|
||||||
}),
|
|
||||||
).rejects.toThrow(PermissionsUpdateInconsistentError);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('groupPermissions has duplicate entries', async () => {
|
|
||||||
await expect(
|
|
||||||
service.updateNotePermissions(note, {
|
|
||||||
sharedToUsers: [],
|
|
||||||
sharedToGroups: [groupPermissionUpate, groupPermissionUpate],
|
|
||||||
}),
|
|
||||||
).rejects.toThrow(PermissionsUpdateInconsistentError);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('userPermissions and groupPermissions have duplicate entries', async () => {
|
|
||||||
await expect(
|
|
||||||
service.updateNotePermissions(note, {
|
|
||||||
sharedToUsers: [userPermissionUpdate, userPermissionUpdate],
|
|
||||||
sharedToGroups: [groupPermissionUpate, groupPermissionUpate],
|
|
||||||
}),
|
|
||||||
).rejects.toThrow(PermissionsUpdateInconsistentError);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('setUserPermission', () => {
|
|
||||||
describe('works', () => {
|
|
||||||
it('with user not added before and editable', async () => {
|
|
||||||
jest
|
|
||||||
.spyOn(noteRepo, 'save')
|
|
||||||
.mockImplementationOnce(async (entry: Note) => {
|
|
||||||
return entry;
|
|
||||||
});
|
|
||||||
const note = Note.create(null) as Note;
|
|
||||||
const user = User.create('test', 'Testy') as User;
|
|
||||||
const resultNote = await service.setUserPermission(note, user, true);
|
|
||||||
const noteUserPermission = NoteUserPermission.create(user, note, true);
|
|
||||||
expect((await resultNote.userPermissions)[0]).toStrictEqual(
|
|
||||||
noteUserPermission,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
it('with user not added before and not editable', async () => {
|
|
||||||
jest
|
|
||||||
.spyOn(noteRepo, 'save')
|
|
||||||
.mockImplementationOnce(async (entry: Note) => {
|
|
||||||
return entry;
|
|
||||||
});
|
|
||||||
const note = Note.create(null) as Note;
|
|
||||||
const user = User.create('test', 'Testy') as User;
|
|
||||||
const resultNote = await service.setUserPermission(note, user, false);
|
|
||||||
const noteUserPermission = NoteUserPermission.create(user, note, false);
|
|
||||||
expect((await resultNote.userPermissions)[0]).toStrictEqual(
|
|
||||||
noteUserPermission,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
it('with user added before and editable', async () => {
|
|
||||||
jest
|
|
||||||
.spyOn(noteRepo, 'save')
|
|
||||||
.mockImplementationOnce(async (entry: Note) => {
|
|
||||||
return entry;
|
|
||||||
});
|
|
||||||
const note = Note.create(null) as Note;
|
|
||||||
const user = User.create('test', 'Testy') as User;
|
|
||||||
note.userPermissions = Promise.resolve([
|
|
||||||
NoteUserPermission.create(user, note, false),
|
|
||||||
]);
|
|
||||||
|
|
||||||
const resultNote = await service.setUserPermission(note, user, true);
|
|
||||||
const noteUserPermission = NoteUserPermission.create(user, note, true);
|
|
||||||
expect((await resultNote.userPermissions)[0]).toStrictEqual(
|
|
||||||
noteUserPermission,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
it('with user added before and not editable', async () => {
|
|
||||||
jest
|
|
||||||
.spyOn(noteRepo, 'save')
|
|
||||||
.mockImplementationOnce(async (entry: Note) => {
|
|
||||||
return entry;
|
|
||||||
});
|
|
||||||
const note = Note.create(null) as Note;
|
|
||||||
const user = User.create('test', 'Testy') as User;
|
|
||||||
note.userPermissions = Promise.resolve([
|
|
||||||
NoteUserPermission.create(user, note, true),
|
|
||||||
]);
|
|
||||||
const resultNote = await service.setUserPermission(note, user, false);
|
|
||||||
const noteUserPermission = NoteUserPermission.create(user, note, false);
|
|
||||||
expect((await resultNote.userPermissions)[0]).toStrictEqual(
|
|
||||||
noteUserPermission,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('removeUserPermission', () => {
|
|
||||||
describe('works', () => {
|
|
||||||
it('with user added before and editable', async () => {
|
|
||||||
jest
|
|
||||||
.spyOn(noteRepo, 'save')
|
|
||||||
.mockImplementationOnce(async (entry: Note) => {
|
|
||||||
return entry;
|
|
||||||
});
|
|
||||||
const note = Note.create(null) as Note;
|
|
||||||
const user = User.create('test', 'Testy') as User;
|
|
||||||
note.userPermissions = Promise.resolve([
|
|
||||||
NoteUserPermission.create(user, note, true),
|
|
||||||
]);
|
|
||||||
|
|
||||||
const resultNote = await service.removeUserPermission(note, user);
|
|
||||||
expect((await resultNote.userPermissions).length).toStrictEqual(0);
|
|
||||||
});
|
|
||||||
it('with user not added before and not editable', async () => {
|
|
||||||
jest
|
|
||||||
.spyOn(noteRepo, 'save')
|
|
||||||
.mockImplementationOnce(async (entry: Note) => {
|
|
||||||
return entry;
|
|
||||||
});
|
|
||||||
const note = Note.create(null) as Note;
|
|
||||||
const user = User.create('test', 'Testy') as User;
|
|
||||||
note.userPermissions = Promise.resolve([
|
|
||||||
NoteUserPermission.create(user, note, false),
|
|
||||||
]);
|
|
||||||
const resultNote = await service.removeUserPermission(note, user);
|
|
||||||
expect((await resultNote.userPermissions).length).toStrictEqual(0);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('setGroupPermission', () => {
|
|
||||||
describe('works', () => {
|
|
||||||
it('with group not added before and editable', async () => {
|
|
||||||
jest
|
|
||||||
.spyOn(noteRepo, 'save')
|
|
||||||
.mockImplementationOnce(async (entry: Note) => {
|
|
||||||
return entry;
|
|
||||||
});
|
|
||||||
const note = Note.create(null) as Note;
|
|
||||||
const group = Group.create('test', 'Testy', false) as Group;
|
|
||||||
const resultNote = await service.setGroupPermission(note, group, true);
|
|
||||||
const noteGroupPermission = NoteGroupPermission.create(
|
|
||||||
group,
|
|
||||||
note,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
expect((await resultNote.groupPermissions)[0]).toStrictEqual(
|
|
||||||
noteGroupPermission,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
it('with group not added before and not editable', async () => {
|
|
||||||
jest
|
|
||||||
.spyOn(noteRepo, 'save')
|
|
||||||
.mockImplementationOnce(async (entry: Note) => {
|
|
||||||
return entry;
|
|
||||||
});
|
|
||||||
const note = Note.create(null) as Note;
|
|
||||||
const group = Group.create('test', 'Testy', false) as Group;
|
|
||||||
const resultNote = await service.setGroupPermission(note, group, false);
|
|
||||||
const noteGroupPermission = NoteGroupPermission.create(
|
|
||||||
group,
|
|
||||||
note,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
expect((await resultNote.groupPermissions)[0]).toStrictEqual(
|
|
||||||
noteGroupPermission,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
it('with group added before and editable', async () => {
|
|
||||||
jest
|
|
||||||
.spyOn(noteRepo, 'save')
|
|
||||||
.mockImplementationOnce(async (entry: Note) => {
|
|
||||||
return entry;
|
|
||||||
});
|
|
||||||
const note = Note.create(null) as Note;
|
|
||||||
const group = Group.create('test', 'Testy', false) as Group;
|
|
||||||
note.groupPermissions = Promise.resolve([
|
|
||||||
NoteGroupPermission.create(group, note, false),
|
|
||||||
]);
|
|
||||||
|
|
||||||
const resultNote = await service.setGroupPermission(note, group, true);
|
|
||||||
const noteGroupPermission = NoteGroupPermission.create(
|
|
||||||
group,
|
|
||||||
note,
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
expect((await resultNote.groupPermissions)[0]).toStrictEqual(
|
|
||||||
noteGroupPermission,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
it('with group added before and not editable', async () => {
|
|
||||||
jest
|
|
||||||
.spyOn(noteRepo, 'save')
|
|
||||||
.mockImplementationOnce(async (entry: Note) => {
|
|
||||||
return entry;
|
|
||||||
});
|
|
||||||
const note = Note.create(null) as Note;
|
|
||||||
const group = Group.create('test', 'Testy', false) as Group;
|
|
||||||
note.groupPermissions = Promise.resolve([
|
|
||||||
NoteGroupPermission.create(group, note, true),
|
|
||||||
]);
|
|
||||||
const resultNote = await service.setGroupPermission(note, group, false);
|
|
||||||
const noteGroupPermission = NoteGroupPermission.create(
|
|
||||||
group,
|
|
||||||
note,
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
expect((await resultNote.groupPermissions)[0]).toStrictEqual(
|
|
||||||
noteGroupPermission,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('removeGroupPermission', () => {
|
|
||||||
describe('works', () => {
|
|
||||||
it('with user added before and editable', async () => {
|
|
||||||
jest
|
|
||||||
.spyOn(noteRepo, 'save')
|
|
||||||
.mockImplementationOnce(async (entry: Note) => {
|
|
||||||
return entry;
|
|
||||||
});
|
|
||||||
const note = Note.create(null) as Note;
|
|
||||||
const group = Group.create('test', 'Testy', false) as Group;
|
|
||||||
note.groupPermissions = Promise.resolve([
|
|
||||||
NoteGroupPermission.create(group, note, true),
|
|
||||||
]);
|
|
||||||
|
|
||||||
const resultNote = await service.removeGroupPermission(note, group);
|
|
||||||
expect((await resultNote.groupPermissions).length).toStrictEqual(0);
|
|
||||||
});
|
|
||||||
it('with user not added before and not editable', async () => {
|
|
||||||
jest
|
|
||||||
.spyOn(noteRepo, 'save')
|
|
||||||
.mockImplementationOnce(async (entry: Note) => {
|
|
||||||
return entry;
|
|
||||||
});
|
|
||||||
const note = Note.create(null) as Note;
|
|
||||||
const group = Group.create('test', 'Testy', false) as Group;
|
|
||||||
note.groupPermissions = Promise.resolve([
|
|
||||||
NoteGroupPermission.create(group, note, false),
|
|
||||||
]);
|
|
||||||
const resultNote = await service.removeGroupPermission(note, group);
|
|
||||||
expect((await resultNote.groupPermissions).length).toStrictEqual(0);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('changeOwner', () => {
|
|
||||||
it('works', async () => {
|
|
||||||
const note = Note.create(null) as Note;
|
|
||||||
const user = User.create('test', 'Testy') as User;
|
|
||||||
jest
|
|
||||||
.spyOn(noteRepo, 'save')
|
|
||||||
.mockImplementationOnce(async (entry: Note) => {
|
|
||||||
return entry;
|
|
||||||
});
|
|
||||||
const resultNote = await service.changeOwner(note, user);
|
|
||||||
expect(await resultNote.owner).toStrictEqual(user);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('toTagList', () => {
|
describe('toTagList', () => {
|
||||||
it('works', async () => {
|
it('works', async () => {
|
||||||
const note = {} as Note;
|
const note = {} as Note;
|
||||||
|
|
|
@ -12,26 +12,18 @@ import {
|
||||||
AlreadyInDBError,
|
AlreadyInDBError,
|
||||||
ForbiddenIdError,
|
ForbiddenIdError,
|
||||||
NotInDBError,
|
NotInDBError,
|
||||||
PermissionsUpdateInconsistentError,
|
|
||||||
} from '../errors/errors';
|
} from '../errors/errors';
|
||||||
import { Group } from '../groups/group.entity';
|
|
||||||
import { GroupsService } from '../groups/groups.service';
|
import { GroupsService } from '../groups/groups.service';
|
||||||
import { HistoryEntry } from '../history/history-entry.entity';
|
import { HistoryEntry } from '../history/history-entry.entity';
|
||||||
import { ConsoleLoggerService } from '../logger/console-logger.service';
|
import { ConsoleLoggerService } from '../logger/console-logger.service';
|
||||||
import { NoteGroupPermission } from '../permissions/note-group-permission.entity';
|
|
||||||
import { NoteUserPermission } from '../permissions/note-user-permission.entity';
|
|
||||||
import { Revision } from '../revisions/revision.entity';
|
import { Revision } from '../revisions/revision.entity';
|
||||||
import { RevisionsService } from '../revisions/revisions.service';
|
import { RevisionsService } from '../revisions/revisions.service';
|
||||||
import { User } from '../users/user.entity';
|
import { User } from '../users/user.entity';
|
||||||
import { UsersService } from '../users/users.service';
|
import { UsersService } from '../users/users.service';
|
||||||
import { checkArrayForDuplicates } from '../utils/arrayDuplicatCheck';
|
|
||||||
import { Alias } from './alias.entity';
|
import { Alias } from './alias.entity';
|
||||||
import { AliasService } from './alias.service';
|
import { AliasService } from './alias.service';
|
||||||
import { NoteMetadataDto } from './note-metadata.dto';
|
import { NoteMetadataDto } from './note-metadata.dto';
|
||||||
import {
|
import { NotePermissionsDto } from './note-permissions.dto';
|
||||||
NotePermissionsDto,
|
|
||||||
NotePermissionsUpdateDto,
|
|
||||||
} from './note-permissions.dto';
|
|
||||||
import { NoteDto } from './note.dto';
|
import { NoteDto } from './note.dto';
|
||||||
import { Note } from './note.entity';
|
import { Note } from './note.entity';
|
||||||
import { Tag } from './tag.entity';
|
import { Tag } from './tag.entity';
|
||||||
|
@ -271,182 +263,6 @@ export class NotesService {
|
||||||
return await this.noteRepository.save(note);
|
return await this.noteRepository.save(note);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @async
|
|
||||||
* Update a notes permissions.
|
|
||||||
* @param {Note} note - the note
|
|
||||||
* @param {NotePermissionsUpdateDto} newPermissions - the permissions the not should be set to
|
|
||||||
* @return {Note} the note with the new permissions
|
|
||||||
* @throws {NotInDBError} there is no note with this id or alias
|
|
||||||
* @throws {PermissionsUpdateInconsistentError} the new permissions specify a user or group twice.
|
|
||||||
*/
|
|
||||||
async updateNotePermissions(
|
|
||||||
note: Note,
|
|
||||||
newPermissions: NotePermissionsUpdateDto,
|
|
||||||
): Promise<Note> {
|
|
||||||
const users = newPermissions.sharedToUsers.map(
|
|
||||||
(userPermission) => userPermission.username,
|
|
||||||
);
|
|
||||||
|
|
||||||
const groups = newPermissions.sharedToGroups.map(
|
|
||||||
(groupPermission) => groupPermission.groupName,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (checkArrayForDuplicates(users) || checkArrayForDuplicates(groups)) {
|
|
||||||
this.logger.debug(
|
|
||||||
`The PermissionUpdate requested specifies the same user or group multiple times.`,
|
|
||||||
'updateNotePermissions',
|
|
||||||
);
|
|
||||||
throw new PermissionsUpdateInconsistentError(
|
|
||||||
'The PermissionUpdate requested specifies the same user or group multiple times.',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
note.userPermissions = Promise.resolve([]);
|
|
||||||
note.groupPermissions = Promise.resolve([]);
|
|
||||||
|
|
||||||
// Create new userPermissions
|
|
||||||
for (const newUserPermission of newPermissions.sharedToUsers) {
|
|
||||||
const user = await this.usersService.getUserByUsername(
|
|
||||||
newUserPermission.username,
|
|
||||||
);
|
|
||||||
const createdPermission = NoteUserPermission.create(
|
|
||||||
user,
|
|
||||||
note,
|
|
||||||
newUserPermission.canEdit,
|
|
||||||
);
|
|
||||||
createdPermission.note = note;
|
|
||||||
(await note.userPermissions).push(createdPermission);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create groupPermissions
|
|
||||||
for (const newGroupPermission of newPermissions.sharedToGroups) {
|
|
||||||
const group = await this.groupsService.getGroupByName(
|
|
||||||
newGroupPermission.groupName,
|
|
||||||
);
|
|
||||||
const createdPermission = NoteGroupPermission.create(
|
|
||||||
group,
|
|
||||||
note,
|
|
||||||
newGroupPermission.canEdit,
|
|
||||||
);
|
|
||||||
createdPermission.note = note;
|
|
||||||
(await note.groupPermissions).push(createdPermission);
|
|
||||||
}
|
|
||||||
|
|
||||||
return await this.noteRepository.save(note);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @async
|
|
||||||
* Set permission for a specific user on a note.
|
|
||||||
* @param {Note} note - the note
|
|
||||||
* @param {User} permissionUser - the user for which the permission should be set
|
|
||||||
* @param {boolean} canEdit - specifies if the user can edit the note
|
|
||||||
* @return {Note} the note with the new permission
|
|
||||||
*/
|
|
||||||
async setUserPermission(
|
|
||||||
note: Note,
|
|
||||||
permissionUser: User,
|
|
||||||
canEdit: boolean,
|
|
||||||
): Promise<Note> {
|
|
||||||
const permissions = await note.userPermissions;
|
|
||||||
const permission = permissions.find(
|
|
||||||
(value: NoteUserPermission, index: number) => {
|
|
||||||
if (value.user.id == permissionUser.id) {
|
|
||||||
if (value.canEdit != canEdit) {
|
|
||||||
value.canEdit = canEdit;
|
|
||||||
permissions[index] = value;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
if (permission == undefined) {
|
|
||||||
const noteUserPermission = NoteUserPermission.create(
|
|
||||||
permissionUser,
|
|
||||||
note,
|
|
||||||
canEdit,
|
|
||||||
);
|
|
||||||
(await note.userPermissions).push(noteUserPermission);
|
|
||||||
}
|
|
||||||
return await this.noteRepository.save(note);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @async
|
|
||||||
* Remove permission for a specific user on a note.
|
|
||||||
* @param {Note} note - the note
|
|
||||||
* @param {User} permissionUser - the user for which the permission should be set
|
|
||||||
* @return {Note} the note with the new permission
|
|
||||||
*/
|
|
||||||
async removeUserPermission(note: Note, permissionUser: User): Promise<Note> {
|
|
||||||
const permissions = await note.userPermissions;
|
|
||||||
const permissionsFiltered = permissions.filter(
|
|
||||||
(value: NoteUserPermission) => {
|
|
||||||
return value.user.id != permissionUser.id;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
note.userPermissions = Promise.resolve(permissionsFiltered);
|
|
||||||
return await this.noteRepository.save(note);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @async
|
|
||||||
* Set permission for a specific group on a note.
|
|
||||||
* @param {Note} note - the note
|
|
||||||
* @param {Group} permissionGroup - the group for which the permission should be set
|
|
||||||
* @param {boolean} canEdit - specifies if the group can edit the note
|
|
||||||
* @return {Note} the note with the new permission
|
|
||||||
*/
|
|
||||||
async setGroupPermission(
|
|
||||||
note: Note,
|
|
||||||
permissionGroup: Group,
|
|
||||||
canEdit: boolean,
|
|
||||||
): Promise<Note> {
|
|
||||||
const permissions = await note.groupPermissions;
|
|
||||||
const permission = permissions.find(
|
|
||||||
(value: NoteGroupPermission, index: number) => {
|
|
||||||
if (value.group.id == permissionGroup.id) {
|
|
||||||
if (value.canEdit != canEdit) {
|
|
||||||
value.canEdit = canEdit;
|
|
||||||
permissions[index] = value;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
if (permission == undefined) {
|
|
||||||
const noteGroupPermission = NoteGroupPermission.create(
|
|
||||||
permissionGroup,
|
|
||||||
note,
|
|
||||||
canEdit,
|
|
||||||
);
|
|
||||||
(await note.groupPermissions).push(noteGroupPermission);
|
|
||||||
}
|
|
||||||
return await this.noteRepository.save(note);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @async
|
|
||||||
* Remove permission for a specific group on a note.
|
|
||||||
* @param {Note} note - the note
|
|
||||||
* @param {Group} permissionGroup - the group for which the permission should be set
|
|
||||||
* @return {Note} the note with the new permission
|
|
||||||
*/
|
|
||||||
async removeGroupPermission(
|
|
||||||
note: Note,
|
|
||||||
permissionGroup: Group,
|
|
||||||
): Promise<Note> {
|
|
||||||
const permissions = await note.groupPermissions;
|
|
||||||
const permissionsFiltered = permissions.filter(
|
|
||||||
(value: NoteGroupPermission) => {
|
|
||||||
return value.group.id != permissionGroup.id;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
note.groupPermissions = Promise.resolve(permissionsFiltered);
|
|
||||||
return await this.noteRepository.save(note);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @async
|
* @async
|
||||||
* Calculate the updateUser (for the NoteDto) for a Note.
|
* Calculate the updateUser (for the NoteDto) for a Note.
|
||||||
|
@ -529,18 +345,6 @@ export class NotesService {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @async
|
|
||||||
* Updates the owner of a note.
|
|
||||||
* @param {Note} note - the note to use
|
|
||||||
* @param {User} owner - the new owner
|
|
||||||
* @return {Note} the updated note
|
|
||||||
*/
|
|
||||||
async changeOwner(note: Note, owner: User): Promise<Note> {
|
|
||||||
note.owner = Promise.resolve(owner);
|
|
||||||
return await this.noteRepository.save(note);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @async
|
* @async
|
||||||
* Build NoteDto from a note.
|
* Build NoteDto from a note.
|
||||||
|
|
|
@ -1,13 +1,26 @@
|
||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
import { Module } from '@nestjs/common';
|
import { Module } from '@nestjs/common';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
|
||||||
|
import { GroupsModule } from '../groups/groups.module';
|
||||||
|
import { LoggerModule } from '../logger/logger.module';
|
||||||
|
import { Note } from '../notes/note.entity';
|
||||||
|
import { NotesModule } from '../notes/notes.module';
|
||||||
|
import { UsersModule } from '../users/users.module';
|
||||||
import { PermissionsService } from './permissions.service';
|
import { PermissionsService } from './permissions.service';
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
|
imports: [
|
||||||
|
TypeOrmModule.forFeature([Note]),
|
||||||
|
NotesModule,
|
||||||
|
UsersModule,
|
||||||
|
GroupsModule,
|
||||||
|
LoggerModule,
|
||||||
|
],
|
||||||
exports: [PermissionsService],
|
exports: [PermissionsService],
|
||||||
providers: [PermissionsService],
|
providers: [PermissionsService],
|
||||||
})
|
})
|
||||||
|
|
|
@ -6,16 +6,23 @@
|
||||||
import { ConfigModule } from '@nestjs/config';
|
import { ConfigModule } from '@nestjs/config';
|
||||||
import { Test, TestingModule } from '@nestjs/testing';
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
import { getRepositoryToken } from '@nestjs/typeorm';
|
import { getRepositoryToken } from '@nestjs/typeorm';
|
||||||
|
import { Repository } from 'typeorm';
|
||||||
|
|
||||||
import { AuthToken } from '../auth/auth-token.entity';
|
import { AuthToken } from '../auth/auth-token.entity';
|
||||||
import { Author } from '../authors/author.entity';
|
import { Author } from '../authors/author.entity';
|
||||||
import appConfigMock from '../config/mock/app.config.mock';
|
import appConfigMock from '../config/mock/app.config.mock';
|
||||||
import noteConfigMock from '../config/mock/note.config.mock';
|
import noteConfigMock from '../config/mock/note.config.mock';
|
||||||
|
import { PermissionsUpdateInconsistentError } from '../errors/errors';
|
||||||
import { Group } from '../groups/group.entity';
|
import { Group } from '../groups/group.entity';
|
||||||
|
import { GroupsModule } from '../groups/groups.module';
|
||||||
import { SpecialGroup } from '../groups/groups.special';
|
import { SpecialGroup } from '../groups/groups.special';
|
||||||
import { Identity } from '../identity/identity.entity';
|
import { Identity } from '../identity/identity.entity';
|
||||||
import { LoggerModule } from '../logger/logger.module';
|
import { LoggerModule } from '../logger/logger.module';
|
||||||
import { Alias } from '../notes/alias.entity';
|
import { Alias } from '../notes/alias.entity';
|
||||||
|
import {
|
||||||
|
NoteGroupPermissionUpdateDto,
|
||||||
|
NoteUserPermissionUpdateDto,
|
||||||
|
} from '../notes/note-permissions.dto';
|
||||||
import { Note } from '../notes/note.entity';
|
import { Note } from '../notes/note.entity';
|
||||||
import { NotesModule } from '../notes/notes.module';
|
import { NotesModule } from '../notes/notes.module';
|
||||||
import { Tag } from '../notes/tag.entity';
|
import { Tag } from '../notes/tag.entity';
|
||||||
|
@ -30,25 +37,54 @@ import { PermissionsModule } from './permissions.module';
|
||||||
import { GuestPermission, PermissionsService } from './permissions.service';
|
import { GuestPermission, PermissionsService } from './permissions.service';
|
||||||
|
|
||||||
describe('PermissionsService', () => {
|
describe('PermissionsService', () => {
|
||||||
let permissionsService: PermissionsService;
|
let service: PermissionsService;
|
||||||
let notes: Note[];
|
let notes: Note[];
|
||||||
|
let noteRepo: Repository<Note>;
|
||||||
|
let userRepo: Repository<User>;
|
||||||
|
let groupRepo: Repository<Group>;
|
||||||
|
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
|
/**
|
||||||
|
* We need to have *one* userRepo and *one* noteRepo for both the providers
|
||||||
|
* array and the overrideProvider call, as otherwise we have two instances
|
||||||
|
* and the mock of createQueryBuilder replaces the wrong one
|
||||||
|
* **/
|
||||||
|
userRepo = new Repository<User>();
|
||||||
|
noteRepo = new Repository<Note>();
|
||||||
const module: TestingModule = await Test.createTestingModule({
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
providers: [PermissionsService],
|
providers: [
|
||||||
|
PermissionsService,
|
||||||
|
{
|
||||||
|
provide: getRepositoryToken(Note),
|
||||||
|
useValue: noteRepo,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: getRepositoryToken(Group),
|
||||||
|
useClass: Repository,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
provide: getRepositoryToken(User),
|
||||||
|
useValue: userRepo,
|
||||||
|
},
|
||||||
|
],
|
||||||
imports: [
|
imports: [
|
||||||
|
ConfigModule.forRoot({
|
||||||
|
isGlobal: true,
|
||||||
|
load: [appConfigMock],
|
||||||
|
}),
|
||||||
|
LoggerModule,
|
||||||
PermissionsModule,
|
PermissionsModule,
|
||||||
UsersModule,
|
UsersModule,
|
||||||
LoggerModule,
|
|
||||||
NotesModule,
|
NotesModule,
|
||||||
ConfigModule.forRoot({
|
ConfigModule.forRoot({
|
||||||
isGlobal: true,
|
isGlobal: true,
|
||||||
load: [appConfigMock, noteConfigMock],
|
load: [appConfigMock, noteConfigMock],
|
||||||
}),
|
}),
|
||||||
|
GroupsModule,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
.overrideProvider(getRepositoryToken(User))
|
.overrideProvider(getRepositoryToken(User))
|
||||||
.useValue({})
|
.useValue(userRepo)
|
||||||
.overrideProvider(getRepositoryToken(AuthToken))
|
.overrideProvider(getRepositoryToken(AuthToken))
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(Identity))
|
.overrideProvider(getRepositoryToken(Identity))
|
||||||
|
@ -58,7 +94,7 @@ describe('PermissionsService', () => {
|
||||||
.overrideProvider(getRepositoryToken(Revision))
|
.overrideProvider(getRepositoryToken(Revision))
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(Note))
|
.overrideProvider(getRepositoryToken(Note))
|
||||||
.useValue({})
|
.useValue(noteRepo)
|
||||||
.overrideProvider(getRepositoryToken(Tag))
|
.overrideProvider(getRepositoryToken(Tag))
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(NoteGroupPermission))
|
.overrideProvider(getRepositoryToken(NoteGroupPermission))
|
||||||
|
@ -66,7 +102,7 @@ describe('PermissionsService', () => {
|
||||||
.overrideProvider(getRepositoryToken(NoteUserPermission))
|
.overrideProvider(getRepositoryToken(NoteUserPermission))
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(Group))
|
.overrideProvider(getRepositoryToken(Group))
|
||||||
.useValue({})
|
.useClass(Repository)
|
||||||
.overrideProvider(getRepositoryToken(Session))
|
.overrideProvider(getRepositoryToken(Session))
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.overrideProvider(getRepositoryToken(Author))
|
.overrideProvider(getRepositoryToken(Author))
|
||||||
|
@ -74,8 +110,10 @@ describe('PermissionsService', () => {
|
||||||
.overrideProvider(getRepositoryToken(Alias))
|
.overrideProvider(getRepositoryToken(Alias))
|
||||||
.useValue({})
|
.useValue({})
|
||||||
.compile();
|
.compile();
|
||||||
permissionsService = module.get<PermissionsService>(PermissionsService);
|
service = module.get<PermissionsService>(PermissionsService);
|
||||||
notes = await createNoteUserPermissionNotes();
|
notes = await createNoteUserPermissionNotes();
|
||||||
|
groupRepo = module.get<Repository<Group>>(getRepositoryToken(Group));
|
||||||
|
noteRepo = module.get<Repository<Note>>(getRepositoryToken(Note));
|
||||||
});
|
});
|
||||||
|
|
||||||
// The two users we test with:
|
// The two users we test with:
|
||||||
|
@ -85,7 +123,7 @@ describe('PermissionsService', () => {
|
||||||
user1.id = '1';
|
user1.id = '1';
|
||||||
|
|
||||||
it('should be defined', () => {
|
it('should be defined', () => {
|
||||||
expect(permissionsService).toBeDefined();
|
expect(service).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
function createNote(owner: User): Note {
|
function createNote(owner: User): Note {
|
||||||
|
@ -176,78 +214,78 @@ describe('PermissionsService', () => {
|
||||||
|
|
||||||
describe('mayRead works with', () => {
|
describe('mayRead works with', () => {
|
||||||
it('Owner', async () => {
|
it('Owner', async () => {
|
||||||
permissionsService.guestPermission = GuestPermission.DENY;
|
service.guestPermission = GuestPermission.DENY;
|
||||||
expect(await permissionsService.mayRead(user1, notes[0])).toBeTruthy();
|
expect(await service.mayRead(user1, notes[0])).toBeTruthy();
|
||||||
expect(await permissionsService.mayRead(user1, notes[7])).toBeFalsy();
|
expect(await service.mayRead(user1, notes[7])).toBeFalsy();
|
||||||
});
|
});
|
||||||
it('userPermission read', async () => {
|
it('userPermission read', async () => {
|
||||||
permissionsService.guestPermission = GuestPermission.DENY;
|
service.guestPermission = GuestPermission.DENY;
|
||||||
expect(await permissionsService.mayRead(user1, notes[1])).toBeTruthy();
|
expect(await service.mayRead(user1, notes[1])).toBeTruthy();
|
||||||
expect(await permissionsService.mayRead(user1, notes[2])).toBeTruthy();
|
expect(await service.mayRead(user1, notes[2])).toBeTruthy();
|
||||||
expect(await permissionsService.mayRead(user1, notes[3])).toBeTruthy();
|
expect(await service.mayRead(user1, notes[3])).toBeTruthy();
|
||||||
});
|
});
|
||||||
it('userPermission write', async () => {
|
it('userPermission write', async () => {
|
||||||
permissionsService.guestPermission = GuestPermission.DENY;
|
service.guestPermission = GuestPermission.DENY;
|
||||||
expect(await permissionsService.mayRead(user1, notes[4])).toBeTruthy();
|
expect(await service.mayRead(user1, notes[4])).toBeTruthy();
|
||||||
expect(await permissionsService.mayRead(user1, notes[5])).toBeTruthy();
|
expect(await service.mayRead(user1, notes[5])).toBeTruthy();
|
||||||
expect(await permissionsService.mayRead(user1, notes[6])).toBeTruthy();
|
expect(await service.mayRead(user1, notes[6])).toBeTruthy();
|
||||||
expect(await permissionsService.mayRead(user1, notes[7])).toBeFalsy();
|
expect(await service.mayRead(user1, notes[7])).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('guest permission', () => {
|
describe('guest permission', () => {
|
||||||
it('CREATE_ALIAS', async () => {
|
it('CREATE_ALIAS', async () => {
|
||||||
permissionsService.guestPermission = GuestPermission.CREATE_ALIAS;
|
service.guestPermission = GuestPermission.CREATE_ALIAS;
|
||||||
expect(await permissionsService.mayRead(null, notes[8])).toBeTruthy();
|
expect(await service.mayRead(null, notes[8])).toBeTruthy();
|
||||||
});
|
});
|
||||||
it('CREATE', async () => {
|
it('CREATE', async () => {
|
||||||
permissionsService.guestPermission = GuestPermission.CREATE;
|
service.guestPermission = GuestPermission.CREATE;
|
||||||
expect(await permissionsService.mayRead(null, notes[8])).toBeTruthy();
|
expect(await service.mayRead(null, notes[8])).toBeTruthy();
|
||||||
});
|
});
|
||||||
it('WRITE', async () => {
|
it('WRITE', async () => {
|
||||||
permissionsService.guestPermission = GuestPermission.WRITE;
|
service.guestPermission = GuestPermission.WRITE;
|
||||||
expect(await permissionsService.mayRead(null, notes[8])).toBeTruthy();
|
expect(await service.mayRead(null, notes[8])).toBeTruthy();
|
||||||
});
|
});
|
||||||
it('READ', async () => {
|
it('READ', async () => {
|
||||||
permissionsService.guestPermission = GuestPermission.READ;
|
service.guestPermission = GuestPermission.READ;
|
||||||
expect(await permissionsService.mayRead(null, notes[8])).toBeTruthy();
|
expect(await service.mayRead(null, notes[8])).toBeTruthy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('mayWrite works with', () => {
|
describe('mayWrite works with', () => {
|
||||||
it('Owner', async () => {
|
it('Owner', async () => {
|
||||||
permissionsService.guestPermission = GuestPermission.DENY;
|
service.guestPermission = GuestPermission.DENY;
|
||||||
expect(await permissionsService.mayWrite(user1, notes[0])).toBeTruthy();
|
expect(await service.mayWrite(user1, notes[0])).toBeTruthy();
|
||||||
expect(await permissionsService.mayWrite(user1, notes[7])).toBeFalsy();
|
expect(await service.mayWrite(user1, notes[7])).toBeFalsy();
|
||||||
});
|
});
|
||||||
it('userPermission read', async () => {
|
it('userPermission read', async () => {
|
||||||
permissionsService.guestPermission = GuestPermission.DENY;
|
service.guestPermission = GuestPermission.DENY;
|
||||||
expect(await permissionsService.mayWrite(user1, notes[1])).toBeFalsy();
|
expect(await service.mayWrite(user1, notes[1])).toBeFalsy();
|
||||||
expect(await permissionsService.mayWrite(user1, notes[2])).toBeFalsy();
|
expect(await service.mayWrite(user1, notes[2])).toBeFalsy();
|
||||||
expect(await permissionsService.mayWrite(user1, notes[3])).toBeFalsy();
|
expect(await service.mayWrite(user1, notes[3])).toBeFalsy();
|
||||||
});
|
});
|
||||||
it('userPermission write', async () => {
|
it('userPermission write', async () => {
|
||||||
permissionsService.guestPermission = GuestPermission.DENY;
|
service.guestPermission = GuestPermission.DENY;
|
||||||
expect(await permissionsService.mayWrite(user1, notes[4])).toBeTruthy();
|
expect(await service.mayWrite(user1, notes[4])).toBeTruthy();
|
||||||
expect(await permissionsService.mayWrite(user1, notes[5])).toBeTruthy();
|
expect(await service.mayWrite(user1, notes[5])).toBeTruthy();
|
||||||
expect(await permissionsService.mayWrite(user1, notes[6])).toBeTruthy();
|
expect(await service.mayWrite(user1, notes[6])).toBeTruthy();
|
||||||
expect(await permissionsService.mayWrite(user1, notes[7])).toBeFalsy();
|
expect(await service.mayWrite(user1, notes[7])).toBeFalsy();
|
||||||
});
|
});
|
||||||
describe('guest permission', () => {
|
describe('guest permission', () => {
|
||||||
it('CREATE_ALIAS', async () => {
|
it('CREATE_ALIAS', async () => {
|
||||||
permissionsService.guestPermission = GuestPermission.CREATE_ALIAS;
|
service.guestPermission = GuestPermission.CREATE_ALIAS;
|
||||||
expect(await permissionsService.mayWrite(null, notes[9])).toBeTruthy();
|
expect(await service.mayWrite(null, notes[9])).toBeTruthy();
|
||||||
});
|
});
|
||||||
it('CREATE', async () => {
|
it('CREATE', async () => {
|
||||||
permissionsService.guestPermission = GuestPermission.CREATE;
|
service.guestPermission = GuestPermission.CREATE;
|
||||||
expect(await permissionsService.mayWrite(null, notes[9])).toBeTruthy();
|
expect(await service.mayWrite(null, notes[9])).toBeTruthy();
|
||||||
});
|
});
|
||||||
it('WRITE', async () => {
|
it('WRITE', async () => {
|
||||||
permissionsService.guestPermission = GuestPermission.WRITE;
|
service.guestPermission = GuestPermission.WRITE;
|
||||||
expect(await permissionsService.mayWrite(null, notes[9])).toBeTruthy();
|
expect(await service.mayWrite(null, notes[9])).toBeTruthy();
|
||||||
});
|
});
|
||||||
it('READ', async () => {
|
it('READ', async () => {
|
||||||
permissionsService.guestPermission = GuestPermission.READ;
|
service.guestPermission = GuestPermission.READ;
|
||||||
expect(await permissionsService.mayWrite(null, notes[9])).toBeFalsy();
|
expect(await service.mayWrite(null, notes[9])).toBeFalsy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -512,14 +550,14 @@ describe('PermissionsService', () => {
|
||||||
permissionString += ` ${perm.group.name}:${String(perm.canEdit)}`;
|
permissionString += ` ${perm.group.name}:${String(perm.canEdit)}`;
|
||||||
}
|
}
|
||||||
it(`mayWrite - test #${i}:${permissionString}`, async () => {
|
it(`mayWrite - test #${i}:${permissionString}`, async () => {
|
||||||
permissionsService.guestPermission = guestPermission;
|
service.guestPermission = guestPermission;
|
||||||
expect(await permissionsService.mayWrite(user1, note)).toEqual(
|
expect(await service.mayWrite(user1, note)).toEqual(
|
||||||
permission.allowsWrite,
|
permission.allowsWrite,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
it(`mayRead - test #${i}:${permissionString}`, async () => {
|
it(`mayRead - test #${i}:${permissionString}`, async () => {
|
||||||
permissionsService.guestPermission = guestPermission;
|
service.guestPermission = guestPermission;
|
||||||
expect(await permissionsService.mayRead(user1, note)).toEqual(
|
expect(await service.mayRead(user1, note)).toEqual(
|
||||||
permission.allowsRead,
|
permission.allowsRead,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -529,39 +567,569 @@ describe('PermissionsService', () => {
|
||||||
|
|
||||||
describe('mayCreate works for', () => {
|
describe('mayCreate works for', () => {
|
||||||
it('logged in', () => {
|
it('logged in', () => {
|
||||||
permissionsService.guestPermission = GuestPermission.DENY;
|
service.guestPermission = GuestPermission.DENY;
|
||||||
expect(permissionsService.mayCreate(user1)).toBeTruthy();
|
expect(service.mayCreate(user1)).toBeTruthy();
|
||||||
});
|
});
|
||||||
it('guest denied', () => {
|
it('guest denied', () => {
|
||||||
permissionsService.guestPermission = GuestPermission.DENY;
|
service.guestPermission = GuestPermission.DENY;
|
||||||
expect(permissionsService.mayCreate(null)).toBeFalsy();
|
expect(service.mayCreate(null)).toBeFalsy();
|
||||||
});
|
});
|
||||||
it('guest read', () => {
|
it('guest read', () => {
|
||||||
permissionsService.guestPermission = GuestPermission.READ;
|
service.guestPermission = GuestPermission.READ;
|
||||||
expect(permissionsService.mayCreate(null)).toBeFalsy();
|
expect(service.mayCreate(null)).toBeFalsy();
|
||||||
});
|
});
|
||||||
it('guest write', () => {
|
it('guest write', () => {
|
||||||
permissionsService.guestPermission = GuestPermission.WRITE;
|
service.guestPermission = GuestPermission.WRITE;
|
||||||
expect(permissionsService.mayCreate(null)).toBeFalsy();
|
expect(service.mayCreate(null)).toBeFalsy();
|
||||||
});
|
});
|
||||||
it('guest create', () => {
|
it('guest create', () => {
|
||||||
permissionsService.guestPermission = GuestPermission.CREATE;
|
service.guestPermission = GuestPermission.CREATE;
|
||||||
expect(permissionsService.mayCreate(null)).toBeTruthy();
|
expect(service.mayCreate(null)).toBeTruthy();
|
||||||
});
|
});
|
||||||
it('guest create alias', () => {
|
it('guest create alias', () => {
|
||||||
permissionsService.guestPermission = GuestPermission.CREATE_ALIAS;
|
service.guestPermission = GuestPermission.CREATE_ALIAS;
|
||||||
expect(permissionsService.mayCreate(null)).toBeTruthy();
|
expect(service.mayCreate(null)).toBeTruthy();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('isOwner works', () => {
|
describe('isOwner works', () => {
|
||||||
it('for positive case', async () => {
|
it('for positive case', async () => {
|
||||||
permissionsService.guestPermission = GuestPermission.DENY;
|
service.guestPermission = GuestPermission.DENY;
|
||||||
expect(await permissionsService.isOwner(user1, notes[0])).toBeTruthy();
|
expect(await service.isOwner(user1, notes[0])).toBeTruthy();
|
||||||
});
|
});
|
||||||
it('for negative case', async () => {
|
it('for negative case', async () => {
|
||||||
permissionsService.guestPermission = GuestPermission.DENY;
|
service.guestPermission = GuestPermission.DENY;
|
||||||
expect(await permissionsService.isOwner(user1, notes[1])).toBeFalsy();
|
expect(await service.isOwner(user1, notes[1])).toBeFalsy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('updateNotePermissions', () => {
|
||||||
|
const userPermissionUpdate = new NoteUserPermissionUpdateDto();
|
||||||
|
userPermissionUpdate.username = 'hardcoded';
|
||||||
|
userPermissionUpdate.canEdit = true;
|
||||||
|
const groupPermissionUpdate = new NoteGroupPermissionUpdateDto();
|
||||||
|
groupPermissionUpdate.groupName = 'testGroup';
|
||||||
|
groupPermissionUpdate.canEdit = false;
|
||||||
|
const user = User.create(userPermissionUpdate.username, 'Testy') as User;
|
||||||
|
const group = Group.create(
|
||||||
|
groupPermissionUpdate.groupName,
|
||||||
|
groupPermissionUpdate.groupName,
|
||||||
|
false,
|
||||||
|
) as Group;
|
||||||
|
const note = Note.create(user) as Note;
|
||||||
|
describe('works', () => {
|
||||||
|
it('with empty GroupPermissions and with empty UserPermissions', async () => {
|
||||||
|
jest
|
||||||
|
.spyOn(noteRepo, 'save')
|
||||||
|
.mockImplementationOnce(async (entry: Note) => {
|
||||||
|
return entry;
|
||||||
|
});
|
||||||
|
const savedNote = await service.updateNotePermissions(note, {
|
||||||
|
sharedToUsers: [],
|
||||||
|
sharedToGroups: [],
|
||||||
|
});
|
||||||
|
expect(await savedNote.userPermissions).toHaveLength(0);
|
||||||
|
expect(await savedNote.groupPermissions).toHaveLength(0);
|
||||||
|
});
|
||||||
|
it('with empty GroupPermissions and with new UserPermissions', async () => {
|
||||||
|
jest
|
||||||
|
.spyOn(noteRepo, 'save')
|
||||||
|
.mockImplementationOnce(async (entry: Note) => {
|
||||||
|
return entry;
|
||||||
|
});
|
||||||
|
jest.spyOn(userRepo, 'findOne').mockResolvedValueOnce(user);
|
||||||
|
const savedNote = await service.updateNotePermissions(note, {
|
||||||
|
sharedToUsers: [userPermissionUpdate],
|
||||||
|
sharedToGroups: [],
|
||||||
|
});
|
||||||
|
expect(await savedNote.userPermissions).toHaveLength(1);
|
||||||
|
expect((await savedNote.userPermissions)[0].user.username).toEqual(
|
||||||
|
userPermissionUpdate.username,
|
||||||
|
);
|
||||||
|
expect((await savedNote.userPermissions)[0].canEdit).toEqual(
|
||||||
|
userPermissionUpdate.canEdit,
|
||||||
|
);
|
||||||
|
expect(await savedNote.groupPermissions).toHaveLength(0);
|
||||||
|
});
|
||||||
|
it('with empty GroupPermissions and with existing UserPermissions', async () => {
|
||||||
|
const noteWithPreexistingPermissions: Note = { ...note };
|
||||||
|
noteWithPreexistingPermissions.userPermissions = Promise.resolve([
|
||||||
|
{
|
||||||
|
note: noteWithPreexistingPermissions,
|
||||||
|
user: user,
|
||||||
|
canEdit: !userPermissionUpdate.canEdit,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
jest
|
||||||
|
.spyOn(noteRepo, 'save')
|
||||||
|
.mockImplementationOnce(async (entry: Note) => {
|
||||||
|
return entry;
|
||||||
|
});
|
||||||
|
jest.spyOn(userRepo, 'findOne').mockResolvedValueOnce(user);
|
||||||
|
const savedNote = await service.updateNotePermissions(note, {
|
||||||
|
sharedToUsers: [userPermissionUpdate],
|
||||||
|
sharedToGroups: [],
|
||||||
|
});
|
||||||
|
expect(await savedNote.userPermissions).toHaveLength(1);
|
||||||
|
expect((await savedNote.userPermissions)[0].user.username).toEqual(
|
||||||
|
userPermissionUpdate.username,
|
||||||
|
);
|
||||||
|
expect((await savedNote.userPermissions)[0].canEdit).toEqual(
|
||||||
|
userPermissionUpdate.canEdit,
|
||||||
|
);
|
||||||
|
expect(await savedNote.groupPermissions).toHaveLength(0);
|
||||||
|
});
|
||||||
|
it('with new GroupPermissions and with empty UserPermissions', async () => {
|
||||||
|
jest
|
||||||
|
.spyOn(noteRepo, 'save')
|
||||||
|
.mockImplementationOnce(async (entry: Note) => {
|
||||||
|
return entry;
|
||||||
|
});
|
||||||
|
jest.spyOn(groupRepo, 'findOne').mockResolvedValueOnce(group);
|
||||||
|
const savedNote = await service.updateNotePermissions(note, {
|
||||||
|
sharedToUsers: [],
|
||||||
|
sharedToGroups: [groupPermissionUpdate],
|
||||||
|
});
|
||||||
|
expect(await savedNote.userPermissions).toHaveLength(0);
|
||||||
|
expect((await savedNote.groupPermissions)[0].group.name).toEqual(
|
||||||
|
groupPermissionUpdate.groupName,
|
||||||
|
);
|
||||||
|
expect((await savedNote.groupPermissions)[0].canEdit).toEqual(
|
||||||
|
groupPermissionUpdate.canEdit,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('with new GroupPermissions and with new UserPermissions', async () => {
|
||||||
|
jest
|
||||||
|
.spyOn(noteRepo, 'save')
|
||||||
|
.mockImplementationOnce(async (entry: Note) => {
|
||||||
|
return entry;
|
||||||
|
});
|
||||||
|
jest.spyOn(userRepo, 'findOne').mockResolvedValueOnce(user);
|
||||||
|
jest.spyOn(groupRepo, 'findOne').mockResolvedValueOnce(group);
|
||||||
|
const savedNote = await service.updateNotePermissions(note, {
|
||||||
|
sharedToUsers: [userPermissionUpdate],
|
||||||
|
sharedToGroups: [groupPermissionUpdate],
|
||||||
|
});
|
||||||
|
expect((await savedNote.userPermissions)[0].user.username).toEqual(
|
||||||
|
userPermissionUpdate.username,
|
||||||
|
);
|
||||||
|
expect((await savedNote.userPermissions)[0].canEdit).toEqual(
|
||||||
|
userPermissionUpdate.canEdit,
|
||||||
|
);
|
||||||
|
expect((await savedNote.groupPermissions)[0].group.name).toEqual(
|
||||||
|
groupPermissionUpdate.groupName,
|
||||||
|
);
|
||||||
|
expect((await savedNote.groupPermissions)[0].canEdit).toEqual(
|
||||||
|
groupPermissionUpdate.canEdit,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('with new GroupPermissions and with existing UserPermissions', async () => {
|
||||||
|
const noteWithUserPermission: Note = { ...note };
|
||||||
|
noteWithUserPermission.userPermissions = Promise.resolve([
|
||||||
|
{
|
||||||
|
note: noteWithUserPermission,
|
||||||
|
user: user,
|
||||||
|
canEdit: !userPermissionUpdate.canEdit,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
jest
|
||||||
|
.spyOn(noteRepo, 'save')
|
||||||
|
.mockImplementationOnce(async (entry: Note) => {
|
||||||
|
return entry;
|
||||||
|
});
|
||||||
|
jest.spyOn(userRepo, 'findOne').mockResolvedValueOnce(user);
|
||||||
|
jest.spyOn(groupRepo, 'findOne').mockResolvedValueOnce(group);
|
||||||
|
const savedNote = await service.updateNotePermissions(
|
||||||
|
noteWithUserPermission,
|
||||||
|
{
|
||||||
|
sharedToUsers: [userPermissionUpdate],
|
||||||
|
sharedToGroups: [groupPermissionUpdate],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
expect((await savedNote.userPermissions)[0].user.username).toEqual(
|
||||||
|
userPermissionUpdate.username,
|
||||||
|
);
|
||||||
|
expect((await savedNote.userPermissions)[0].canEdit).toEqual(
|
||||||
|
userPermissionUpdate.canEdit,
|
||||||
|
);
|
||||||
|
expect((await savedNote.groupPermissions)[0].group.name).toEqual(
|
||||||
|
groupPermissionUpdate.groupName,
|
||||||
|
);
|
||||||
|
expect((await savedNote.groupPermissions)[0].canEdit).toEqual(
|
||||||
|
groupPermissionUpdate.canEdit,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('with existing GroupPermissions and with empty UserPermissions', async () => {
|
||||||
|
const noteWithPreexistingPermissions: Note = { ...note };
|
||||||
|
noteWithPreexistingPermissions.groupPermissions = Promise.resolve([
|
||||||
|
{
|
||||||
|
note: noteWithPreexistingPermissions,
|
||||||
|
group: group,
|
||||||
|
canEdit: !groupPermissionUpdate.canEdit,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
jest.spyOn(groupRepo, 'findOne').mockResolvedValueOnce(group);
|
||||||
|
jest
|
||||||
|
.spyOn(noteRepo, 'save')
|
||||||
|
.mockImplementationOnce(async (entry: Note) => {
|
||||||
|
return entry;
|
||||||
|
});
|
||||||
|
const savedNote = await service.updateNotePermissions(
|
||||||
|
noteWithPreexistingPermissions,
|
||||||
|
{
|
||||||
|
sharedToUsers: [],
|
||||||
|
sharedToGroups: [groupPermissionUpdate],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
expect(await savedNote.userPermissions).toHaveLength(0);
|
||||||
|
expect((await savedNote.groupPermissions)[0].group.name).toEqual(
|
||||||
|
groupPermissionUpdate.groupName,
|
||||||
|
);
|
||||||
|
expect((await savedNote.groupPermissions)[0].canEdit).toEqual(
|
||||||
|
groupPermissionUpdate.canEdit,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('with existing GroupPermissions and with new UserPermissions', async () => {
|
||||||
|
const noteWithPreexistingPermissions: Note = { ...note };
|
||||||
|
noteWithPreexistingPermissions.groupPermissions = Promise.resolve([
|
||||||
|
{
|
||||||
|
note: noteWithPreexistingPermissions,
|
||||||
|
group: group,
|
||||||
|
canEdit: !groupPermissionUpdate.canEdit,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
jest
|
||||||
|
.spyOn(noteRepo, 'save')
|
||||||
|
.mockImplementationOnce(async (entry: Note) => {
|
||||||
|
return entry;
|
||||||
|
});
|
||||||
|
jest.spyOn(userRepo, 'findOne').mockResolvedValueOnce(user);
|
||||||
|
jest.spyOn(groupRepo, 'findOne').mockResolvedValueOnce(group);
|
||||||
|
const savedNote = await service.updateNotePermissions(
|
||||||
|
noteWithPreexistingPermissions,
|
||||||
|
{
|
||||||
|
sharedToUsers: [userPermissionUpdate],
|
||||||
|
sharedToGroups: [groupPermissionUpdate],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
expect((await savedNote.userPermissions)[0].user.username).toEqual(
|
||||||
|
userPermissionUpdate.username,
|
||||||
|
);
|
||||||
|
expect((await savedNote.userPermissions)[0].canEdit).toEqual(
|
||||||
|
userPermissionUpdate.canEdit,
|
||||||
|
);
|
||||||
|
expect((await savedNote.groupPermissions)[0].group.name).toEqual(
|
||||||
|
groupPermissionUpdate.groupName,
|
||||||
|
);
|
||||||
|
expect((await savedNote.groupPermissions)[0].canEdit).toEqual(
|
||||||
|
groupPermissionUpdate.canEdit,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('with existing GroupPermissions and with existing UserPermissions', async () => {
|
||||||
|
const noteWithPreexistingPermissions: Note = { ...note };
|
||||||
|
noteWithPreexistingPermissions.groupPermissions = Promise.resolve([
|
||||||
|
{
|
||||||
|
note: noteWithPreexistingPermissions,
|
||||||
|
group: group,
|
||||||
|
canEdit: !groupPermissionUpdate.canEdit,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
noteWithPreexistingPermissions.userPermissions = Promise.resolve([
|
||||||
|
{
|
||||||
|
note: noteWithPreexistingPermissions,
|
||||||
|
user: user,
|
||||||
|
canEdit: !userPermissionUpdate.canEdit,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
jest
|
||||||
|
.spyOn(noteRepo, 'save')
|
||||||
|
.mockImplementationOnce(async (entry: Note) => {
|
||||||
|
return entry;
|
||||||
|
});
|
||||||
|
jest.spyOn(userRepo, 'findOne').mockResolvedValueOnce(user);
|
||||||
|
jest.spyOn(groupRepo, 'findOne').mockResolvedValueOnce(group);
|
||||||
|
const savedNote = await service.updateNotePermissions(
|
||||||
|
noteWithPreexistingPermissions,
|
||||||
|
{
|
||||||
|
sharedToUsers: [userPermissionUpdate],
|
||||||
|
sharedToGroups: [groupPermissionUpdate],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
expect((await savedNote.userPermissions)[0].user.username).toEqual(
|
||||||
|
userPermissionUpdate.username,
|
||||||
|
);
|
||||||
|
expect((await savedNote.userPermissions)[0].canEdit).toEqual(
|
||||||
|
userPermissionUpdate.canEdit,
|
||||||
|
);
|
||||||
|
expect((await savedNote.groupPermissions)[0].group.name).toEqual(
|
||||||
|
groupPermissionUpdate.groupName,
|
||||||
|
);
|
||||||
|
expect((await savedNote.groupPermissions)[0].canEdit).toEqual(
|
||||||
|
groupPermissionUpdate.canEdit,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('fails:', () => {
|
||||||
|
it('userPermissions has duplicate entries', async () => {
|
||||||
|
await expect(
|
||||||
|
service.updateNotePermissions(note, {
|
||||||
|
sharedToUsers: [userPermissionUpdate, userPermissionUpdate],
|
||||||
|
sharedToGroups: [],
|
||||||
|
}),
|
||||||
|
).rejects.toThrow(PermissionsUpdateInconsistentError);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('groupPermissions has duplicate entries', async () => {
|
||||||
|
await expect(
|
||||||
|
service.updateNotePermissions(note, {
|
||||||
|
sharedToUsers: [],
|
||||||
|
sharedToGroups: [groupPermissionUpdate, groupPermissionUpdate],
|
||||||
|
}),
|
||||||
|
).rejects.toThrow(PermissionsUpdateInconsistentError);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('userPermissions and groupPermissions have duplicate entries', async () => {
|
||||||
|
await expect(
|
||||||
|
service.updateNotePermissions(note, {
|
||||||
|
sharedToUsers: [userPermissionUpdate, userPermissionUpdate],
|
||||||
|
sharedToGroups: [groupPermissionUpdate, groupPermissionUpdate],
|
||||||
|
}),
|
||||||
|
).rejects.toThrow(PermissionsUpdateInconsistentError);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('setUserPermission', () => {
|
||||||
|
describe('works', () => {
|
||||||
|
it('with user not added before and editable', async () => {
|
||||||
|
jest
|
||||||
|
.spyOn(noteRepo, 'save')
|
||||||
|
.mockImplementationOnce(async (entry: Note) => {
|
||||||
|
return entry;
|
||||||
|
});
|
||||||
|
const note = Note.create(null) as Note;
|
||||||
|
const user = User.create('test', 'Testy') as User;
|
||||||
|
const resultNote = await service.setUserPermission(note, user, true);
|
||||||
|
const noteUserPermission = NoteUserPermission.create(user, note, true);
|
||||||
|
expect((await resultNote.userPermissions)[0]).toStrictEqual(
|
||||||
|
noteUserPermission,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('with user not added before and not editable', async () => {
|
||||||
|
jest
|
||||||
|
.spyOn(noteRepo, 'save')
|
||||||
|
.mockImplementationOnce(async (entry: Note) => {
|
||||||
|
return entry;
|
||||||
|
});
|
||||||
|
const note = Note.create(null) as Note;
|
||||||
|
const user = User.create('test', 'Testy') as User;
|
||||||
|
const resultNote = await service.setUserPermission(note, user, false);
|
||||||
|
const noteUserPermission = NoteUserPermission.create(user, note, false);
|
||||||
|
expect((await resultNote.userPermissions)[0]).toStrictEqual(
|
||||||
|
noteUserPermission,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('with user added before and editable', async () => {
|
||||||
|
jest
|
||||||
|
.spyOn(noteRepo, 'save')
|
||||||
|
.mockImplementationOnce(async (entry: Note) => {
|
||||||
|
return entry;
|
||||||
|
});
|
||||||
|
const note = Note.create(null) as Note;
|
||||||
|
const user = User.create('test', 'Testy') as User;
|
||||||
|
note.userPermissions = Promise.resolve([
|
||||||
|
NoteUserPermission.create(user, note, false),
|
||||||
|
]);
|
||||||
|
|
||||||
|
const resultNote = await service.setUserPermission(note, user, true);
|
||||||
|
const noteUserPermission = NoteUserPermission.create(user, note, true);
|
||||||
|
expect((await resultNote.userPermissions)[0]).toStrictEqual(
|
||||||
|
noteUserPermission,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('with user added before and not editable', async () => {
|
||||||
|
jest
|
||||||
|
.spyOn(noteRepo, 'save')
|
||||||
|
.mockImplementationOnce(async (entry: Note) => {
|
||||||
|
return entry;
|
||||||
|
});
|
||||||
|
const note = Note.create(null) as Note;
|
||||||
|
const user = User.create('test', 'Testy') as User;
|
||||||
|
note.userPermissions = Promise.resolve([
|
||||||
|
NoteUserPermission.create(user, note, true),
|
||||||
|
]);
|
||||||
|
const resultNote = await service.setUserPermission(note, user, false);
|
||||||
|
const noteUserPermission = NoteUserPermission.create(user, note, false);
|
||||||
|
expect((await resultNote.userPermissions)[0]).toStrictEqual(
|
||||||
|
noteUserPermission,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('removeUserPermission', () => {
|
||||||
|
describe('works', () => {
|
||||||
|
it('with user added before and editable', async () => {
|
||||||
|
jest
|
||||||
|
.spyOn(noteRepo, 'save')
|
||||||
|
.mockImplementationOnce(async (entry: Note) => {
|
||||||
|
return entry;
|
||||||
|
});
|
||||||
|
const note = Note.create(null) as Note;
|
||||||
|
const user = User.create('test', 'Testy') as User;
|
||||||
|
note.userPermissions = Promise.resolve([
|
||||||
|
NoteUserPermission.create(user, note, true),
|
||||||
|
]);
|
||||||
|
|
||||||
|
const resultNote = await service.removeUserPermission(note, user);
|
||||||
|
expect((await resultNote.userPermissions).length).toStrictEqual(0);
|
||||||
|
});
|
||||||
|
it('with user not added before and not editable', async () => {
|
||||||
|
jest
|
||||||
|
.spyOn(noteRepo, 'save')
|
||||||
|
.mockImplementationOnce(async (entry: Note) => {
|
||||||
|
return entry;
|
||||||
|
});
|
||||||
|
const note = Note.create(null) as Note;
|
||||||
|
const user = User.create('test', 'Testy') as User;
|
||||||
|
note.userPermissions = Promise.resolve([
|
||||||
|
NoteUserPermission.create(user, note, false),
|
||||||
|
]);
|
||||||
|
const resultNote = await service.removeUserPermission(note, user);
|
||||||
|
expect((await resultNote.userPermissions).length).toStrictEqual(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('setGroupPermission', () => {
|
||||||
|
describe('works', () => {
|
||||||
|
it('with group not added before and editable', async () => {
|
||||||
|
jest
|
||||||
|
.spyOn(noteRepo, 'save')
|
||||||
|
.mockImplementationOnce(async (entry: Note) => {
|
||||||
|
return entry;
|
||||||
|
});
|
||||||
|
const note = Note.create(null) as Note;
|
||||||
|
const group = Group.create('test', 'Testy', false) as Group;
|
||||||
|
const resultNote = await service.setGroupPermission(note, group, true);
|
||||||
|
const noteGroupPermission = NoteGroupPermission.create(
|
||||||
|
group,
|
||||||
|
note,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
expect((await resultNote.groupPermissions)[0]).toStrictEqual(
|
||||||
|
noteGroupPermission,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('with group not added before and not editable', async () => {
|
||||||
|
jest
|
||||||
|
.spyOn(noteRepo, 'save')
|
||||||
|
.mockImplementationOnce(async (entry: Note) => {
|
||||||
|
return entry;
|
||||||
|
});
|
||||||
|
const note = Note.create(null) as Note;
|
||||||
|
const group = Group.create('test', 'Testy', false) as Group;
|
||||||
|
const resultNote = await service.setGroupPermission(note, group, false);
|
||||||
|
const noteGroupPermission = NoteGroupPermission.create(
|
||||||
|
group,
|
||||||
|
note,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
expect((await resultNote.groupPermissions)[0]).toStrictEqual(
|
||||||
|
noteGroupPermission,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('with group added before and editable', async () => {
|
||||||
|
jest
|
||||||
|
.spyOn(noteRepo, 'save')
|
||||||
|
.mockImplementationOnce(async (entry: Note) => {
|
||||||
|
return entry;
|
||||||
|
});
|
||||||
|
const note = Note.create(null) as Note;
|
||||||
|
const group = Group.create('test', 'Testy', false) as Group;
|
||||||
|
note.groupPermissions = Promise.resolve([
|
||||||
|
NoteGroupPermission.create(group, note, false),
|
||||||
|
]);
|
||||||
|
|
||||||
|
const resultNote = await service.setGroupPermission(note, group, true);
|
||||||
|
const noteGroupPermission = NoteGroupPermission.create(
|
||||||
|
group,
|
||||||
|
note,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
expect((await resultNote.groupPermissions)[0]).toStrictEqual(
|
||||||
|
noteGroupPermission,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
it('with group added before and not editable', async () => {
|
||||||
|
jest
|
||||||
|
.spyOn(noteRepo, 'save')
|
||||||
|
.mockImplementationOnce(async (entry: Note) => {
|
||||||
|
return entry;
|
||||||
|
});
|
||||||
|
const note = Note.create(null) as Note;
|
||||||
|
const group = Group.create('test', 'Testy', false) as Group;
|
||||||
|
note.groupPermissions = Promise.resolve([
|
||||||
|
NoteGroupPermission.create(group, note, true),
|
||||||
|
]);
|
||||||
|
const resultNote = await service.setGroupPermission(note, group, false);
|
||||||
|
const noteGroupPermission = NoteGroupPermission.create(
|
||||||
|
group,
|
||||||
|
note,
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
expect((await resultNote.groupPermissions)[0]).toStrictEqual(
|
||||||
|
noteGroupPermission,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('removeGroupPermission', () => {
|
||||||
|
describe('works', () => {
|
||||||
|
it('with user added before and editable', async () => {
|
||||||
|
jest
|
||||||
|
.spyOn(noteRepo, 'save')
|
||||||
|
.mockImplementationOnce(async (entry: Note) => {
|
||||||
|
return entry;
|
||||||
|
});
|
||||||
|
const note = Note.create(null) as Note;
|
||||||
|
const group = Group.create('test', 'Testy', false) as Group;
|
||||||
|
note.groupPermissions = Promise.resolve([
|
||||||
|
NoteGroupPermission.create(group, note, true),
|
||||||
|
]);
|
||||||
|
|
||||||
|
const resultNote = await service.removeGroupPermission(note, group);
|
||||||
|
expect((await resultNote.groupPermissions).length).toStrictEqual(0);
|
||||||
|
});
|
||||||
|
it('with user not added before and not editable', async () => {
|
||||||
|
jest
|
||||||
|
.spyOn(noteRepo, 'save')
|
||||||
|
.mockImplementationOnce(async (entry: Note) => {
|
||||||
|
return entry;
|
||||||
|
});
|
||||||
|
const note = Note.create(null) as Note;
|
||||||
|
const group = Group.create('test', 'Testy', false) as Group;
|
||||||
|
note.groupPermissions = Promise.resolve([
|
||||||
|
NoteGroupPermission.create(group, note, false),
|
||||||
|
]);
|
||||||
|
const resultNote = await service.removeGroupPermission(note, group);
|
||||||
|
expect((await resultNote.groupPermissions).length).toStrictEqual(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('changeOwner', () => {
|
||||||
|
it('works', async () => {
|
||||||
|
const note = Note.create(null) as Note;
|
||||||
|
const user = User.create('test', 'Testy') as User;
|
||||||
|
jest
|
||||||
|
.spyOn(noteRepo, 'save')
|
||||||
|
.mockImplementationOnce(async (entry: Note) => {
|
||||||
|
return entry;
|
||||||
|
});
|
||||||
|
const resultNote = await service.changeOwner(note, user);
|
||||||
|
expect(await resultNote.owner).toStrictEqual(user);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,13 +1,25 @@
|
||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
* SPDX-FileCopyrightText: 2022 The HedgeDoc developers (see AUTHORS file)
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
|
import { Repository } from 'typeorm';
|
||||||
|
|
||||||
|
import { PermissionsUpdateInconsistentError } from '../errors/errors';
|
||||||
|
import { Group } from '../groups/group.entity';
|
||||||
|
import { GroupsService } from '../groups/groups.service';
|
||||||
import { SpecialGroup } from '../groups/groups.special';
|
import { SpecialGroup } from '../groups/groups.special';
|
||||||
|
import { ConsoleLoggerService } from '../logger/console-logger.service';
|
||||||
|
import { NotePermissionsUpdateDto } from '../notes/note-permissions.dto';
|
||||||
import { Note } from '../notes/note.entity';
|
import { Note } from '../notes/note.entity';
|
||||||
|
import { NotesService } from '../notes/notes.service';
|
||||||
import { User } from '../users/user.entity';
|
import { User } from '../users/user.entity';
|
||||||
|
import { UsersService } from '../users/users.service';
|
||||||
|
import { checkArrayForDuplicates } from '../utils/arrayDuplicatCheck';
|
||||||
|
import { NoteGroupPermission } from './note-group-permission.entity';
|
||||||
|
import { NoteUserPermission } from './note-user-permission.entity';
|
||||||
|
|
||||||
// TODO move to config or remove
|
// TODO move to config or remove
|
||||||
export enum GuestPermission {
|
export enum GuestPermission {
|
||||||
|
@ -20,6 +32,14 @@ export enum GuestPermission {
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class PermissionsService {
|
export class PermissionsService {
|
||||||
|
constructor(
|
||||||
|
public notesService: NotesService,
|
||||||
|
public usersService: UsersService,
|
||||||
|
public groupsService: GroupsService,
|
||||||
|
@InjectRepository(Note) private noteRepository: Repository<Note>,
|
||||||
|
private readonly logger: ConsoleLoggerService,
|
||||||
|
) {}
|
||||||
|
|
||||||
public guestPermission: GuestPermission; // TODO change to configOption
|
public guestPermission: GuestPermission; // TODO change to configOption
|
||||||
async mayRead(user: User | null, note: Note): Promise<boolean> {
|
async mayRead(user: User | null, note: Note): Promise<boolean> {
|
||||||
if (await this.isOwner(user, note)) return true;
|
if (await this.isOwner(user, note)) return true;
|
||||||
|
@ -126,4 +146,192 @@ export class PermissionsService {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @async
|
||||||
|
* Update a notes permissions.
|
||||||
|
* @param {Note} note - the note
|
||||||
|
* @param {NotePermissionsUpdateDto} newPermissions - the permissions the not should be set to
|
||||||
|
* @return {Note} the note with the new permissions
|
||||||
|
* @throws {NotInDBError} there is no note with this id or alias
|
||||||
|
* @throws {PermissionsUpdateInconsistentError} the new permissions specify a user or group twice.
|
||||||
|
*/
|
||||||
|
async updateNotePermissions(
|
||||||
|
note: Note,
|
||||||
|
newPermissions: NotePermissionsUpdateDto,
|
||||||
|
): Promise<Note> {
|
||||||
|
const users = newPermissions.sharedToUsers.map(
|
||||||
|
(userPermission) => userPermission.username,
|
||||||
|
);
|
||||||
|
|
||||||
|
const groups = newPermissions.sharedToGroups.map(
|
||||||
|
(groupPermission) => groupPermission.groupName,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (checkArrayForDuplicates(users) || checkArrayForDuplicates(groups)) {
|
||||||
|
this.logger.debug(
|
||||||
|
`The PermissionUpdate requested specifies the same user or group multiple times.`,
|
||||||
|
'updateNotePermissions',
|
||||||
|
);
|
||||||
|
throw new PermissionsUpdateInconsistentError(
|
||||||
|
'The PermissionUpdate requested specifies the same user or group multiple times.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
note.userPermissions = Promise.resolve([]);
|
||||||
|
note.groupPermissions = Promise.resolve([]);
|
||||||
|
|
||||||
|
// Create new userPermissions
|
||||||
|
for (const newUserPermission of newPermissions.sharedToUsers) {
|
||||||
|
const user = await this.usersService.getUserByUsername(
|
||||||
|
newUserPermission.username,
|
||||||
|
);
|
||||||
|
const createdPermission = NoteUserPermission.create(
|
||||||
|
user,
|
||||||
|
note,
|
||||||
|
newUserPermission.canEdit,
|
||||||
|
);
|
||||||
|
createdPermission.note = note;
|
||||||
|
(await note.userPermissions).push(createdPermission);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create groupPermissions
|
||||||
|
for (const newGroupPermission of newPermissions.sharedToGroups) {
|
||||||
|
const group = await this.groupsService.getGroupByName(
|
||||||
|
newGroupPermission.groupName,
|
||||||
|
);
|
||||||
|
const createdPermission = NoteGroupPermission.create(
|
||||||
|
group,
|
||||||
|
note,
|
||||||
|
newGroupPermission.canEdit,
|
||||||
|
);
|
||||||
|
createdPermission.note = note;
|
||||||
|
(await note.groupPermissions).push(createdPermission);
|
||||||
|
}
|
||||||
|
|
||||||
|
return await this.noteRepository.save(note);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @async
|
||||||
|
* Set permission for a specific user on a note.
|
||||||
|
* @param {Note} note - the note
|
||||||
|
* @param {User} permissionUser - the user for which the permission should be set
|
||||||
|
* @param {boolean} canEdit - specifies if the user can edit the note
|
||||||
|
* @return {Note} the note with the new permission
|
||||||
|
*/
|
||||||
|
async setUserPermission(
|
||||||
|
note: Note,
|
||||||
|
permissionUser: User,
|
||||||
|
canEdit: boolean,
|
||||||
|
): Promise<Note> {
|
||||||
|
const permissions = await note.userPermissions;
|
||||||
|
const permission = permissions.find(
|
||||||
|
(value: NoteUserPermission, index: number) => {
|
||||||
|
if (value.user.id == permissionUser.id) {
|
||||||
|
if (value.canEdit != canEdit) {
|
||||||
|
value.canEdit = canEdit;
|
||||||
|
permissions[index] = value;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (permission == undefined) {
|
||||||
|
const noteUserPermission = NoteUserPermission.create(
|
||||||
|
permissionUser,
|
||||||
|
note,
|
||||||
|
canEdit,
|
||||||
|
);
|
||||||
|
(await note.userPermissions).push(noteUserPermission);
|
||||||
|
}
|
||||||
|
return await this.noteRepository.save(note);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @async
|
||||||
|
* Remove permission for a specific user on a note.
|
||||||
|
* @param {Note} note - the note
|
||||||
|
* @param {User} permissionUser - the user for which the permission should be set
|
||||||
|
* @return {Note} the note with the new permission
|
||||||
|
*/
|
||||||
|
async removeUserPermission(note: Note, permissionUser: User): Promise<Note> {
|
||||||
|
const permissions = await note.userPermissions;
|
||||||
|
const permissionsFiltered = permissions.filter(
|
||||||
|
(value: NoteUserPermission) => {
|
||||||
|
return value.user.id != permissionUser.id;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
note.userPermissions = Promise.resolve(permissionsFiltered);
|
||||||
|
return await this.noteRepository.save(note);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @async
|
||||||
|
* Set permission for a specific group on a note.
|
||||||
|
* @param {Note} note - the note
|
||||||
|
* @param {Group} permissionGroup - the group for which the permission should be set
|
||||||
|
* @param {boolean} canEdit - specifies if the group can edit the note
|
||||||
|
* @return {Note} the note with the new permission
|
||||||
|
*/
|
||||||
|
async setGroupPermission(
|
||||||
|
note: Note,
|
||||||
|
permissionGroup: Group,
|
||||||
|
canEdit: boolean,
|
||||||
|
): Promise<Note> {
|
||||||
|
const permissions = await note.groupPermissions;
|
||||||
|
const permission = permissions.find(
|
||||||
|
(value: NoteGroupPermission, index: number) => {
|
||||||
|
if (value.group.id == permissionGroup.id) {
|
||||||
|
if (value.canEdit != canEdit) {
|
||||||
|
value.canEdit = canEdit;
|
||||||
|
permissions[index] = value;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
if (permission == undefined) {
|
||||||
|
const noteGroupPermission = NoteGroupPermission.create(
|
||||||
|
permissionGroup,
|
||||||
|
note,
|
||||||
|
canEdit,
|
||||||
|
);
|
||||||
|
(await note.groupPermissions).push(noteGroupPermission);
|
||||||
|
}
|
||||||
|
return await this.noteRepository.save(note);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @async
|
||||||
|
* Remove permission for a specific group on a note.
|
||||||
|
* @param {Note} note - the note
|
||||||
|
* @param {Group} permissionGroup - the group for which the permission should be set
|
||||||
|
* @return {Note} the note with the new permission
|
||||||
|
*/
|
||||||
|
async removeGroupPermission(
|
||||||
|
note: Note,
|
||||||
|
permissionGroup: Group,
|
||||||
|
): Promise<Note> {
|
||||||
|
const permissions = await note.groupPermissions;
|
||||||
|
const permissionsFiltered = permissions.filter(
|
||||||
|
(value: NoteGroupPermission) => {
|
||||||
|
return value.group.id != permissionGroup.id;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
note.groupPermissions = Promise.resolve(permissionsFiltered);
|
||||||
|
return await this.noteRepository.save(note);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @async
|
||||||
|
* Updates the owner of a note.
|
||||||
|
* @param {Note} note - the note to use
|
||||||
|
* @param {User} owner - the new owner
|
||||||
|
* @return {Note} the updated note
|
||||||
|
*/
|
||||||
|
async changeOwner(note: Note, owner: User): Promise<Note> {
|
||||||
|
note.owner = Promise.resolve(owner);
|
||||||
|
return await this.noteRepository.save(note);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue