mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2025-05-18 09:04:44 -04:00
Merge pull request #786 from hedgedoc/refactor/dto
This commit is contained in:
commit
6bce4c241b
11 changed files with 206 additions and 161 deletions
|
@ -78,7 +78,10 @@ export class MeController {
|
||||||
|
|
||||||
@UseGuards(TokenAuthGuard)
|
@UseGuards(TokenAuthGuard)
|
||||||
@Get('notes')
|
@Get('notes')
|
||||||
getMyNotes(@Request() req): NoteMetadataDto[] {
|
async getMyNotes(@Request() req): Promise<NoteMetadataDto[]> {
|
||||||
return this.notesService.getUserNotes(req.user.userName);
|
const notes = await this.notesService.getUserNotes(req.user);
|
||||||
|
return Promise.all(
|
||||||
|
notes.map((note) => this.notesService.toNoteMetadataDto(note)),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ import { MediaService } from '../../../media/media.service';
|
||||||
import { MulterFile } from '../../../media/multer-file.interface';
|
import { MulterFile } from '../../../media/multer-file.interface';
|
||||||
import { TokenAuthGuard } from '../../../auth/token-auth.guard';
|
import { TokenAuthGuard } from '../../../auth/token-auth.guard';
|
||||||
import { ApiSecurity } from '@nestjs/swagger';
|
import { ApiSecurity } from '@nestjs/swagger';
|
||||||
|
import { MediaUploadUrlDto } from '../../../media/media-upload-url.dto';
|
||||||
|
|
||||||
@ApiSecurity('token')
|
@ApiSecurity('token')
|
||||||
@Controller('media')
|
@Controller('media')
|
||||||
|
@ -47,7 +48,7 @@ export class MediaController {
|
||||||
@Request() req,
|
@Request() req,
|
||||||
@UploadedFile() file: MulterFile,
|
@UploadedFile() file: MulterFile,
|
||||||
@Headers('HedgeDoc-Note') noteId: string,
|
@Headers('HedgeDoc-Note') noteId: string,
|
||||||
) {
|
): Promise<MediaUploadUrlDto> {
|
||||||
const username = req.user.userName;
|
const username = req.user.userName;
|
||||||
this.logger.debug(
|
this.logger.debug(
|
||||||
`Recieved filename '${file.originalname}' for note '${noteId}' from user '${username}'`,
|
`Recieved filename '${file.originalname}' for note '${noteId}' from user '${username}'`,
|
||||||
|
@ -59,9 +60,7 @@ export class MediaController {
|
||||||
username,
|
username,
|
||||||
noteId,
|
noteId,
|
||||||
);
|
);
|
||||||
return {
|
return this.mediaService.toMediaUploadUrlDto(url);
|
||||||
link: url,
|
|
||||||
};
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof ClientError || e instanceof NotInDBError) {
|
if (e instanceof ClientError || e instanceof NotInDBError) {
|
||||||
throw new BadRequestException(e.message);
|
throw new BadRequestException(e.message);
|
||||||
|
@ -72,7 +71,10 @@ export class MediaController {
|
||||||
|
|
||||||
@UseGuards(TokenAuthGuard)
|
@UseGuards(TokenAuthGuard)
|
||||||
@Delete(':filename')
|
@Delete(':filename')
|
||||||
async deleteMedia(@Request() req, @Param('filename') filename: string) {
|
async deleteMedia(
|
||||||
|
@Request() req,
|
||||||
|
@Param('filename') filename: string,
|
||||||
|
): Promise<void> {
|
||||||
const username = req.user.userName;
|
const username = req.user.userName;
|
||||||
try {
|
try {
|
||||||
await this.mediaService.deleteFile(filename, username);
|
await this.mediaService.deleteFile(filename, username);
|
||||||
|
|
|
@ -8,6 +8,7 @@ import { Controller, Get, UseGuards } from '@nestjs/common';
|
||||||
import { MonitoringService } from '../../../monitoring/monitoring.service';
|
import { MonitoringService } from '../../../monitoring/monitoring.service';
|
||||||
import { TokenAuthGuard } from '../../../auth/token-auth.guard';
|
import { TokenAuthGuard } from '../../../auth/token-auth.guard';
|
||||||
import { ApiSecurity } from '@nestjs/swagger';
|
import { ApiSecurity } from '@nestjs/swagger';
|
||||||
|
import { ServerStatusDto } from '../../../monitoring/server-status.dto';
|
||||||
|
|
||||||
@ApiSecurity('token')
|
@ApiSecurity('token')
|
||||||
@Controller('monitoring')
|
@Controller('monitoring')
|
||||||
|
@ -16,7 +17,8 @@ export class MonitoringController {
|
||||||
|
|
||||||
@UseGuards(TokenAuthGuard)
|
@UseGuards(TokenAuthGuard)
|
||||||
@Get()
|
@Get()
|
||||||
getStatus() {
|
getStatus(): Promise<ServerStatusDto> {
|
||||||
|
// TODO: toServerStatusDto.
|
||||||
return this.monitoringService.getServerStatus();
|
return this.monitoringService.getServerStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,12 +19,19 @@ import {
|
||||||
} from '@nestjs/common';
|
} from '@nestjs/common';
|
||||||
import { NotInDBError } from '../../../errors/errors';
|
import { NotInDBError } from '../../../errors/errors';
|
||||||
import { ConsoleLoggerService } from '../../../logger/console-logger.service';
|
import { ConsoleLoggerService } from '../../../logger/console-logger.service';
|
||||||
import { NotePermissionsUpdateDto } from '../../../notes/note-permissions.dto';
|
import {
|
||||||
|
NotePermissionsDto,
|
||||||
|
NotePermissionsUpdateDto,
|
||||||
|
} from '../../../notes/note-permissions.dto';
|
||||||
import { NotesService } from '../../../notes/notes.service';
|
import { NotesService } from '../../../notes/notes.service';
|
||||||
import { RevisionsService } from '../../../revisions/revisions.service';
|
import { RevisionsService } from '../../../revisions/revisions.service';
|
||||||
import { MarkdownBody } from '../../utils/markdownbody-decorator';
|
import { MarkdownBody } from '../../utils/markdownbody-decorator';
|
||||||
import { TokenAuthGuard } from '../../../auth/token-auth.guard';
|
import { TokenAuthGuard } from '../../../auth/token-auth.guard';
|
||||||
import { ApiSecurity } from '@nestjs/swagger';
|
import { ApiSecurity } from '@nestjs/swagger';
|
||||||
|
import { NoteDto } from '../../../notes/note.dto';
|
||||||
|
import { NoteMetadataDto } from '../../../notes/note-metadata.dto';
|
||||||
|
import { RevisionMetadataDto } from '../../../revisions/revision-metadata.dto';
|
||||||
|
import { RevisionDto } from '../../../revisions/revision.dto';
|
||||||
|
|
||||||
@ApiSecurity('token')
|
@ApiSecurity('token')
|
||||||
@Controller('notes')
|
@Controller('notes')
|
||||||
|
@ -39,18 +46,42 @@ export class NotesController {
|
||||||
|
|
||||||
@UseGuards(TokenAuthGuard)
|
@UseGuards(TokenAuthGuard)
|
||||||
@Post()
|
@Post()
|
||||||
async createNote(@Request() req, @MarkdownBody() text: string) {
|
async createNote(
|
||||||
|
@Request() req,
|
||||||
|
@MarkdownBody() text: string,
|
||||||
|
): Promise<NoteDto> {
|
||||||
// ToDo: provide user for createNoteDto
|
// ToDo: provide user for createNoteDto
|
||||||
this.logger.debug('Got raw markdown:\n' + text);
|
this.logger.debug('Got raw markdown:\n' + text);
|
||||||
return this.noteService.createNoteDto(text);
|
return this.noteService.toNoteDto(
|
||||||
|
await this.noteService.createNote(text, undefined, req.user),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@UseGuards(TokenAuthGuard)
|
||||||
|
@Post(':noteAlias')
|
||||||
|
async createNamedNote(
|
||||||
|
@Request() req,
|
||||||
|
@Param('noteAlias') noteAlias: string,
|
||||||
|
@MarkdownBody() text: string,
|
||||||
|
): Promise<NoteDto> {
|
||||||
|
// ToDo: check if user is allowed to view this note
|
||||||
|
this.logger.debug('Got raw markdown:\n' + text);
|
||||||
|
return this.noteService.toNoteDto(
|
||||||
|
await this.noteService.createNote(text, noteAlias, req.user),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@UseGuards(TokenAuthGuard)
|
@UseGuards(TokenAuthGuard)
|
||||||
@Get(':noteIdOrAlias')
|
@Get(':noteIdOrAlias')
|
||||||
async getNote(@Request() req, @Param('noteIdOrAlias') noteIdOrAlias: string) {
|
async getNote(
|
||||||
|
@Request() req,
|
||||||
|
@Param('noteIdOrAlias') noteIdOrAlias: string,
|
||||||
|
): Promise<NoteDto> {
|
||||||
// ToDo: check if user is allowed to view this note
|
// ToDo: check if user is allowed to view this note
|
||||||
try {
|
try {
|
||||||
return await this.noteService.getNoteDtoByIdOrAlias(noteIdOrAlias);
|
return this.noteService.toNoteDto(
|
||||||
|
await this.noteService.getNoteByIdOrAlias(noteIdOrAlias),
|
||||||
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof NotInDBError) {
|
if (e instanceof NotInDBError) {
|
||||||
throw new NotFoundException(e.message);
|
throw new NotFoundException(e.message);
|
||||||
|
@ -59,24 +90,12 @@ export class NotesController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@UseGuards(TokenAuthGuard)
|
|
||||||
@Post(':noteAlias')
|
|
||||||
async createNamedNote(
|
|
||||||
@Request() req,
|
|
||||||
@Param('noteAlias') noteAlias: string,
|
|
||||||
@MarkdownBody() text: string,
|
|
||||||
) {
|
|
||||||
// ToDo: check if user is allowed to view this note
|
|
||||||
this.logger.debug('Got raw markdown:\n' + text);
|
|
||||||
return this.noteService.createNoteDto(text, noteAlias);
|
|
||||||
}
|
|
||||||
|
|
||||||
@UseGuards(TokenAuthGuard)
|
@UseGuards(TokenAuthGuard)
|
||||||
@Delete(':noteIdOrAlias')
|
@Delete(':noteIdOrAlias')
|
||||||
async deleteNote(
|
async deleteNote(
|
||||||
@Request() req,
|
@Request() req,
|
||||||
@Param('noteIdOrAlias') noteIdOrAlias: string,
|
@Param('noteIdOrAlias') noteIdOrAlias: string,
|
||||||
) {
|
): Promise<void> {
|
||||||
// ToDo: check if user is allowed to delete this note
|
// ToDo: check if user is allowed to delete this note
|
||||||
this.logger.debug('Deleting note: ' + noteIdOrAlias);
|
this.logger.debug('Deleting note: ' + noteIdOrAlias);
|
||||||
try {
|
try {
|
||||||
|
@ -97,11 +116,13 @@ export class NotesController {
|
||||||
@Request() req,
|
@Request() req,
|
||||||
@Param('noteIdOrAlias') noteIdOrAlias: string,
|
@Param('noteIdOrAlias') noteIdOrAlias: string,
|
||||||
@MarkdownBody() text: string,
|
@MarkdownBody() text: string,
|
||||||
) {
|
): Promise<NoteDto> {
|
||||||
// ToDo: check if user is allowed to change this note
|
// ToDo: check if user is allowed to change this note
|
||||||
this.logger.debug('Got raw markdown:\n' + text);
|
this.logger.debug('Got raw markdown:\n' + text);
|
||||||
try {
|
try {
|
||||||
return await this.noteService.updateNoteByIdOrAlias(noteIdOrAlias, text);
|
return this.noteService.toNoteDto(
|
||||||
|
await this.noteService.updateNoteByIdOrAlias(noteIdOrAlias, text),
|
||||||
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof NotInDBError) {
|
if (e instanceof NotInDBError) {
|
||||||
throw new NotFoundException(e.message);
|
throw new NotFoundException(e.message);
|
||||||
|
@ -116,7 +137,7 @@ export class NotesController {
|
||||||
async getNoteContent(
|
async getNoteContent(
|
||||||
@Request() req,
|
@Request() req,
|
||||||
@Param('noteIdOrAlias') noteIdOrAlias: string,
|
@Param('noteIdOrAlias') noteIdOrAlias: string,
|
||||||
) {
|
): Promise<string> {
|
||||||
// ToDo: check if user is allowed to view this notes content
|
// ToDo: check if user is allowed to view this notes content
|
||||||
try {
|
try {
|
||||||
return await this.noteService.getNoteContent(noteIdOrAlias);
|
return await this.noteService.getNoteContent(noteIdOrAlias);
|
||||||
|
@ -133,10 +154,12 @@ export class NotesController {
|
||||||
async getNoteMetadata(
|
async getNoteMetadata(
|
||||||
@Request() req,
|
@Request() req,
|
||||||
@Param('noteIdOrAlias') noteIdOrAlias: string,
|
@Param('noteIdOrAlias') noteIdOrAlias: string,
|
||||||
) {
|
): Promise<NoteMetadataDto> {
|
||||||
// ToDo: check if user is allowed to view this notes metadata
|
// ToDo: check if user is allowed to view this notes metadata
|
||||||
try {
|
try {
|
||||||
return await this.noteService.getNoteMetadata(noteIdOrAlias);
|
return this.noteService.toNoteMetadataDto(
|
||||||
|
await this.noteService.getNoteByIdOrAlias(noteIdOrAlias),
|
||||||
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof NotInDBError) {
|
if (e instanceof NotInDBError) {
|
||||||
throw new NotFoundException(e.message);
|
throw new NotFoundException(e.message);
|
||||||
|
@ -151,12 +174,11 @@ export class NotesController {
|
||||||
@Request() req,
|
@Request() req,
|
||||||
@Param('noteIdOrAlias') noteIdOrAlias: string,
|
@Param('noteIdOrAlias') noteIdOrAlias: string,
|
||||||
@Body() updateDto: NotePermissionsUpdateDto,
|
@Body() updateDto: NotePermissionsUpdateDto,
|
||||||
) {
|
): Promise<NotePermissionsDto> {
|
||||||
// ToDo: check if user is allowed to view this notes permissions
|
// ToDo: check if user is allowed to view this notes permissions
|
||||||
try {
|
try {
|
||||||
return await this.noteService.updateNotePermissions(
|
return this.noteService.toNotePermissionsDto(
|
||||||
noteIdOrAlias,
|
await this.noteService.updateNotePermissions(noteIdOrAlias, updateDto),
|
||||||
updateDto,
|
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof NotInDBError) {
|
if (e instanceof NotInDBError) {
|
||||||
|
@ -171,12 +193,17 @@ export class NotesController {
|
||||||
async getNoteRevisions(
|
async getNoteRevisions(
|
||||||
@Request() req,
|
@Request() req,
|
||||||
@Param('noteIdOrAlias') noteIdOrAlias: string,
|
@Param('noteIdOrAlias') noteIdOrAlias: string,
|
||||||
) {
|
): Promise<RevisionMetadataDto[]> {
|
||||||
// ToDo: check if user is allowed to view this notes revisions
|
// ToDo: check if user is allowed to view this notes revisions
|
||||||
try {
|
try {
|
||||||
return await this.revisionsService.getNoteRevisionMetadatas(
|
const revisions = await this.revisionsService.getAllRevisions(
|
||||||
noteIdOrAlias,
|
noteIdOrAlias,
|
||||||
);
|
);
|
||||||
|
return Promise.all(
|
||||||
|
revisions.map((revision) =>
|
||||||
|
this.revisionsService.toRevisionMetadataDto(revision),
|
||||||
|
),
|
||||||
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof NotInDBError) {
|
if (e instanceof NotInDBError) {
|
||||||
throw new NotFoundException(e.message);
|
throw new NotFoundException(e.message);
|
||||||
|
@ -191,12 +218,11 @@ export class NotesController {
|
||||||
@Request() req,
|
@Request() req,
|
||||||
@Param('noteIdOrAlias') noteIdOrAlias: string,
|
@Param('noteIdOrAlias') noteIdOrAlias: string,
|
||||||
@Param('revisionId') revisionId: number,
|
@Param('revisionId') revisionId: number,
|
||||||
) {
|
): Promise<RevisionDto> {
|
||||||
// ToDo: check if user is allowed to view this notes revision
|
// ToDo: check if user is allowed to view this notes revision
|
||||||
try {
|
try {
|
||||||
return await this.revisionsService.getNoteRevision(
|
return this.revisionsService.toRevisionDto(
|
||||||
noteIdOrAlias,
|
await this.revisionsService.getRevision(noteIdOrAlias, revisionId),
|
||||||
revisionId,
|
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (e instanceof NotInDBError) {
|
if (e instanceof NotInDBError) {
|
||||||
|
|
|
@ -5,14 +5,20 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { ExecutionContext, Injectable } from '@nestjs/common';
|
import { ExecutionContext, Injectable } from '@nestjs/common';
|
||||||
|
import { UsersService } from '../users/users.service';
|
||||||
|
import { User } from '../users/user.entity';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class MockAuthGuard {
|
export class MockAuthGuard {
|
||||||
canActivate(context: ExecutionContext) {
|
private user: User;
|
||||||
|
constructor(private usersService: UsersService) {}
|
||||||
|
|
||||||
|
async canActivate(context: ExecutionContext) {
|
||||||
const req = context.switchToHttp().getRequest();
|
const req = context.switchToHttp().getRequest();
|
||||||
req.user = {
|
if (!this.user) {
|
||||||
userName: 'hardcoded',
|
this.user = await this.usersService.createUser('hardcoded', 'Testy');
|
||||||
};
|
}
|
||||||
|
req.user = this.user;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
12
src/media/media-upload-url.dto.ts
Normal file
12
src/media/media-upload-url.dto.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2021 The HedgeDoc developers (see AUTHORS file)
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { IsString } from 'class-validator';
|
||||||
|
|
||||||
|
export class MediaUploadUrlDto {
|
||||||
|
@IsString()
|
||||||
|
link: string;
|
||||||
|
}
|
|
@ -18,6 +18,7 @@ import { BackendType } from './backends/backend-type.enum';
|
||||||
import { FilesystemBackend } from './backends/filesystem-backend';
|
import { FilesystemBackend } from './backends/filesystem-backend';
|
||||||
import { MediaBackend } from './media-backend.interface';
|
import { MediaBackend } from './media-backend.interface';
|
||||||
import { MediaUpload } from './media-upload.entity';
|
import { MediaUpload } from './media-upload.entity';
|
||||||
|
import { MediaUploadUrlDto } from './media-upload-url.dto';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class MediaService {
|
export class MediaService {
|
||||||
|
@ -58,7 +59,11 @@ export class MediaService {
|
||||||
return allowedTypes.includes(mimeType);
|
return allowedTypes.includes(mimeType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async saveFile(fileBuffer: Buffer, username: string, noteId: string) {
|
public async saveFile(
|
||||||
|
fileBuffer: Buffer,
|
||||||
|
username: string,
|
||||||
|
noteId: string,
|
||||||
|
): Promise<string> {
|
||||||
this.logger.debug(
|
this.logger.debug(
|
||||||
`Saving file for note '${noteId}' and user '${username}'`,
|
`Saving file for note '${noteId}' and user '${username}'`,
|
||||||
'saveFile',
|
'saveFile',
|
||||||
|
@ -88,7 +93,7 @@ export class MediaService {
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async deleteFile(filename: string, username: string) {
|
public async deleteFile(filename: string, username: string): Promise<void> {
|
||||||
this.logger.debug(
|
this.logger.debug(
|
||||||
`Deleting '${filename}' for user '${username}'`,
|
`Deleting '${filename}' for user '${username}'`,
|
||||||
'deleteFile',
|
'deleteFile',
|
||||||
|
@ -132,4 +137,10 @@ export class MediaService {
|
||||||
return this.moduleRef.get(FilesystemBackend);
|
return this.moduleRef.get(FilesystemBackend);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toMediaUploadUrlDto(url: string): MediaUploadUrlDto {
|
||||||
|
return {
|
||||||
|
link: url,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,48 +35,26 @@ export class NotesService {
|
||||||
this.logger.setContext(NotesService.name);
|
this.logger.setContext(NotesService.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
getUserNotes(username: string): NoteMetadataDto[] {
|
getUserNotes(user: User): Note[] {
|
||||||
this.logger.warn('Using hardcoded data!');
|
this.logger.warn('Using hardcoded data!');
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
alias: null,
|
|
||||||
createTime: new Date(),
|
|
||||||
description: 'Very descriptive text.',
|
|
||||||
editedBy: [],
|
|
||||||
id: 'foobar-barfoo',
|
id: 'foobar-barfoo',
|
||||||
permissions: {
|
alias: null,
|
||||||
owner: {
|
shortid: 'abc',
|
||||||
displayName: 'foo',
|
owner: user,
|
||||||
userName: 'fooUser',
|
description: 'Very descriptive text.',
|
||||||
email: 'foo@example.com',
|
userPermissions: [],
|
||||||
photo: '',
|
groupPermissions: [],
|
||||||
},
|
|
||||||
sharedToUsers: [],
|
|
||||||
sharedToGroups: [],
|
|
||||||
},
|
|
||||||
tags: [],
|
tags: [],
|
||||||
|
revisions: Promise.resolve([]),
|
||||||
|
authorColors: [],
|
||||||
title: 'Title!',
|
title: 'Title!',
|
||||||
updateTime: new Date(),
|
viewcount: 42,
|
||||||
updateUser: {
|
|
||||||
displayName: 'foo',
|
|
||||||
userName: 'fooUser',
|
|
||||||
email: 'foo@example.com',
|
|
||||||
photo: '',
|
|
||||||
},
|
|
||||||
viewCount: 42,
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
async createNoteDto(
|
|
||||||
noteContent: string,
|
|
||||||
alias?: NoteMetadataDto['alias'],
|
|
||||||
owner?: User,
|
|
||||||
): Promise<NoteDto> {
|
|
||||||
const note = await this.createNote(noteContent, alias, owner);
|
|
||||||
return this.toNoteDto(note);
|
|
||||||
}
|
|
||||||
|
|
||||||
async createNote(
|
async createNote(
|
||||||
noteContent: string,
|
noteContent: string,
|
||||||
alias?: NoteMetadataDto['alias'],
|
alias?: NoteMetadataDto['alias'],
|
||||||
|
@ -96,7 +74,7 @@ export class NotesService {
|
||||||
return this.noteRepository.save(newNote);
|
return this.noteRepository.save(newNote);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getCurrentContent(note: Note) {
|
async getCurrentContent(note: Note): Promise<string> {
|
||||||
return (await this.getLatestRevision(note)).content;
|
return (await this.getLatestRevision(note)).content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,42 +86,6 @@ export class NotesService {
|
||||||
return this.revisionsService.getFirstRevision(note.id);
|
return this.revisionsService.getFirstRevision(note.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getMetadata(note: Note): Promise<NoteMetadataDto> {
|
|
||||||
return {
|
|
||||||
// TODO: Convert DB UUID to base64
|
|
||||||
id: note.id,
|
|
||||||
alias: note.alias,
|
|
||||||
title: note.title,
|
|
||||||
createTime: (await this.getFirstRevision(note)).createdAt,
|
|
||||||
description: note.description,
|
|
||||||
editedBy: note.authorColors.map(
|
|
||||||
(authorColor) => authorColor.user.userName,
|
|
||||||
),
|
|
||||||
// TODO: Extract into method
|
|
||||||
permissions: {
|
|
||||||
owner: this.usersService.toUserDto(note.owner),
|
|
||||||
sharedToUsers: note.userPermissions.map((noteUserPermission) => ({
|
|
||||||
user: this.usersService.toUserDto(noteUserPermission.user),
|
|
||||||
canEdit: noteUserPermission.canEdit,
|
|
||||||
})),
|
|
||||||
sharedToGroups: note.groupPermissions.map((noteGroupPermission) => ({
|
|
||||||
group: noteGroupPermission.group,
|
|
||||||
canEdit: noteGroupPermission.canEdit,
|
|
||||||
})),
|
|
||||||
},
|
|
||||||
tags: note.tags.map((tag) => tag.name),
|
|
||||||
updateTime: (await this.getLatestRevision(note)).createdAt,
|
|
||||||
// TODO: Get actual updateUser
|
|
||||||
updateUser: {
|
|
||||||
displayName: 'Hardcoded User',
|
|
||||||
userName: 'hardcoded',
|
|
||||||
email: 'foo@example.com',
|
|
||||||
photo: '',
|
|
||||||
},
|
|
||||||
viewCount: 42,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async getNoteByIdOrAlias(noteIdOrAlias: string): Promise<Note> {
|
async getNoteByIdOrAlias(noteIdOrAlias: string): Promise<Note> {
|
||||||
this.logger.debug(
|
this.logger.debug(
|
||||||
`Trying to find note '${noteIdOrAlias}'`,
|
`Trying to find note '${noteIdOrAlias}'`,
|
||||||
|
@ -178,45 +120,50 @@ export class NotesService {
|
||||||
return note;
|
return note;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getNoteDtoByIdOrAlias(noteIdOrAlias: string): Promise<NoteDto> {
|
|
||||||
const note = await this.getNoteByIdOrAlias(noteIdOrAlias);
|
|
||||||
return this.toNoteDto(note);
|
|
||||||
}
|
|
||||||
|
|
||||||
async deleteNoteByIdOrAlias(noteIdOrAlias: string) {
|
async deleteNoteByIdOrAlias(noteIdOrAlias: string) {
|
||||||
const note = await this.getNoteByIdOrAlias(noteIdOrAlias);
|
const note = await this.getNoteByIdOrAlias(noteIdOrAlias);
|
||||||
return await this.noteRepository.remove(note);
|
return await this.noteRepository.remove(note);
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateNoteByIdOrAlias(noteIdOrAlias: string, noteContent: string) {
|
async updateNoteByIdOrAlias(
|
||||||
|
noteIdOrAlias: string,
|
||||||
|
noteContent: string,
|
||||||
|
): Promise<Note> {
|
||||||
const note = await this.getNoteByIdOrAlias(noteIdOrAlias);
|
const note = await this.getNoteByIdOrAlias(noteIdOrAlias);
|
||||||
const revisions = await note.revisions;
|
const revisions = await note.revisions;
|
||||||
//TODO: Calculate patch
|
//TODO: Calculate patch
|
||||||
revisions.push(Revision.create(noteContent, noteContent));
|
revisions.push(Revision.create(noteContent, noteContent));
|
||||||
note.revisions = Promise.resolve(revisions);
|
note.revisions = Promise.resolve(revisions);
|
||||||
await this.noteRepository.save(note);
|
return this.noteRepository.save(note);
|
||||||
return this.toNoteDto(note);
|
|
||||||
}
|
|
||||||
|
|
||||||
async getNoteMetadata(noteIdOrAlias: string): Promise<NoteMetadataDto> {
|
|
||||||
const note = await this.getNoteByIdOrAlias(noteIdOrAlias);
|
|
||||||
return this.getMetadata(note);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateNotePermissions(
|
updateNotePermissions(
|
||||||
noteIdOrAlias: string,
|
noteIdOrAlias: string,
|
||||||
newPermissions: NotePermissionsUpdateDto,
|
newPermissions: NotePermissionsUpdateDto,
|
||||||
): NotePermissionsDto {
|
): Note {
|
||||||
this.logger.warn('Using hardcoded data!');
|
this.logger.warn('Using hardcoded data!');
|
||||||
return {
|
return {
|
||||||
|
id: 'foobar-barfoo',
|
||||||
|
alias: null,
|
||||||
|
shortid: 'abc',
|
||||||
owner: {
|
owner: {
|
||||||
displayName: 'foo',
|
authTokens: [],
|
||||||
userName: 'fooUser',
|
createdAt: new Date(),
|
||||||
email: 'foo@example.com',
|
displayName: 'hardcoded',
|
||||||
photo: '',
|
id: '1',
|
||||||
|
identities: [],
|
||||||
|
ownedNotes: [],
|
||||||
|
updatedAt: new Date(),
|
||||||
|
userName: 'Testy',
|
||||||
},
|
},
|
||||||
sharedToUsers: [],
|
description: 'Very descriptive text.',
|
||||||
sharedToGroups: [],
|
userPermissions: [],
|
||||||
|
groupPermissions: [],
|
||||||
|
tags: [],
|
||||||
|
revisions: Promise.resolve([]),
|
||||||
|
authorColors: [],
|
||||||
|
title: 'Title!',
|
||||||
|
viewcount: 42,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,10 +172,50 @@ export class NotesService {
|
||||||
return this.getCurrentContent(note);
|
return this.getCurrentContent(note);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async toNotePermissionsDto(note: Note): Promise<NotePermissionsDto> {
|
||||||
|
return {
|
||||||
|
owner: this.usersService.toUserDto(note.owner),
|
||||||
|
sharedToUsers: note.userPermissions.map((noteUserPermission) => ({
|
||||||
|
user: this.usersService.toUserDto(noteUserPermission.user),
|
||||||
|
canEdit: noteUserPermission.canEdit,
|
||||||
|
})),
|
||||||
|
sharedToGroups: note.groupPermissions.map((noteGroupPermission) => ({
|
||||||
|
group: noteGroupPermission.group,
|
||||||
|
canEdit: noteGroupPermission.canEdit,
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async toNoteMetadataDto(note: Note): Promise<NoteMetadataDto> {
|
||||||
|
return {
|
||||||
|
// TODO: Convert DB UUID to base64
|
||||||
|
id: note.id,
|
||||||
|
alias: note.alias,
|
||||||
|
title: note.title,
|
||||||
|
createTime: (await this.getFirstRevision(note)).createdAt,
|
||||||
|
description: note.description,
|
||||||
|
editedBy: note.authorColors.map(
|
||||||
|
(authorColor) => authorColor.user.userName,
|
||||||
|
),
|
||||||
|
// TODO: Extract into method
|
||||||
|
permissions: await this.toNotePermissionsDto(note),
|
||||||
|
tags: note.tags.map((tag) => tag.name),
|
||||||
|
updateTime: (await this.getLatestRevision(note)).createdAt,
|
||||||
|
// TODO: Get actual updateUser
|
||||||
|
updateUser: {
|
||||||
|
displayName: 'Hardcoded User',
|
||||||
|
userName: 'hardcoded',
|
||||||
|
email: 'foo@example.com',
|
||||||
|
photo: '',
|
||||||
|
},
|
||||||
|
viewCount: 42,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
async toNoteDto(note: Note): Promise<NoteDto> {
|
async toNoteDto(note: Note): Promise<NoteDto> {
|
||||||
return {
|
return {
|
||||||
content: await this.getCurrentContent(note),
|
content: await this.getCurrentContent(note),
|
||||||
metadata: await this.getMetadata(note),
|
metadata: await this.toNoteMetadataDto(note),
|
||||||
editedByAtPosition: [],
|
editedByAtPosition: [],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,30 +24,26 @@ export class RevisionsService {
|
||||||
this.logger.setContext(RevisionsService.name);
|
this.logger.setContext(RevisionsService.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getNoteRevisionMetadatas(
|
async getAllRevisions(noteIdOrAlias: string): Promise<Revision[]> {
|
||||||
noteIdOrAlias: string,
|
|
||||||
): Promise<RevisionMetadataDto[]> {
|
|
||||||
const note = await this.notesService.getNoteByIdOrAlias(noteIdOrAlias);
|
const note = await this.notesService.getNoteByIdOrAlias(noteIdOrAlias);
|
||||||
const revisions = await this.revisionRepository.find({
|
return await this.revisionRepository.find({
|
||||||
where: {
|
where: {
|
||||||
note: note.id,
|
note: note,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return revisions.map((revision) => this.toMetadataDto(revision));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getNoteRevision(
|
async getRevision(
|
||||||
noteIdOrAlias: string,
|
noteIdOrAlias: string,
|
||||||
revisionId: number,
|
revisionId: number,
|
||||||
): Promise<RevisionDto> {
|
): Promise<Revision> {
|
||||||
const note = await this.notesService.getNoteByIdOrAlias(noteIdOrAlias);
|
const note = await this.notesService.getNoteByIdOrAlias(noteIdOrAlias);
|
||||||
const revision = await this.revisionRepository.findOne({
|
return await this.revisionRepository.findOne({
|
||||||
where: {
|
where: {
|
||||||
id: revisionId,
|
id: revisionId,
|
||||||
note: note,
|
note: note,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
return this.toDto(revision);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getLatestRevision(noteId: string): Promise<Revision> {
|
getLatestRevision(noteId: string): Promise<Revision> {
|
||||||
|
@ -73,7 +69,7 @@ export class RevisionsService {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
toMetadataDto(revision: Revision): RevisionMetadataDto {
|
toRevisionMetadataDto(revision: Revision): RevisionMetadataDto {
|
||||||
return {
|
return {
|
||||||
id: revision.id,
|
id: revision.id,
|
||||||
length: revision.length,
|
length: revision.length,
|
||||||
|
@ -81,7 +77,7 @@ export class RevisionsService {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
toDto(revision: Revision): RevisionDto {
|
toRevisionDto(revision: Revision): RevisionDto {
|
||||||
return {
|
return {
|
||||||
id: revision.id,
|
id: revision.id,
|
||||||
content: revision.content,
|
content: revision.content,
|
||||||
|
@ -90,7 +86,7 @@ export class RevisionsService {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
createRevision(content: string) {
|
createRevision(content: string): Revision {
|
||||||
// TODO: Add previous revision
|
// TODO: Add previous revision
|
||||||
// TODO: Calculate patch
|
// TODO: Calculate patch
|
||||||
// TODO: Save metadata
|
// TODO: Save metadata
|
||||||
|
|
|
@ -20,7 +20,6 @@ import { MediaService } from '../../src/media/media.service';
|
||||||
import { NotesModule } from '../../src/notes/notes.module';
|
import { NotesModule } from '../../src/notes/notes.module';
|
||||||
import { NotesService } from '../../src/notes/notes.service';
|
import { NotesService } from '../../src/notes/notes.service';
|
||||||
import { PermissionsModule } from '../../src/permissions/permissions.module';
|
import { PermissionsModule } from '../../src/permissions/permissions.module';
|
||||||
import { UsersService } from '../../src/users/users.service';
|
|
||||||
import { AuthModule } from '../../src/auth/auth.module';
|
import { AuthModule } from '../../src/auth/auth.module';
|
||||||
import { TokenAuthGuard } from '../../src/auth/token-auth.guard';
|
import { TokenAuthGuard } from '../../src/auth/token-auth.guard';
|
||||||
import { MockAuthGuard } from '../../src/auth/mock-auth.guard';
|
import { MockAuthGuard } from '../../src/auth/mock-auth.guard';
|
||||||
|
@ -65,8 +64,6 @@ describe('Notes', () => {
|
||||||
app.useLogger(logger);
|
app.useLogger(logger);
|
||||||
const notesService: NotesService = moduleRef.get('NotesService');
|
const notesService: NotesService = moduleRef.get('NotesService');
|
||||||
await notesService.createNote('test content', 'test_upload_media');
|
await notesService.createNote('test content', 'test_upload_media');
|
||||||
const usersService: UsersService = moduleRef.get('UsersService');
|
|
||||||
await usersService.createUser('hardcoded', 'Hard Coded');
|
|
||||||
mediaService = moduleRef.get('MediaService');
|
mediaService = moduleRef.get('MediaService');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ import { PermissionsModule } from '../../src/permissions/permissions.module';
|
||||||
import { AuthModule } from '../../src/auth/auth.module';
|
import { AuthModule } from '../../src/auth/auth.module';
|
||||||
import { TokenAuthGuard } from '../../src/auth/token-auth.guard';
|
import { TokenAuthGuard } from '../../src/auth/token-auth.guard';
|
||||||
import { MockAuthGuard } from '../../src/auth/mock-auth.guard';
|
import { MockAuthGuard } from '../../src/auth/mock-auth.guard';
|
||||||
import { UsersService } from '../../src/users/users.service';
|
import { UsersModule } from '../../src/users/users.module';
|
||||||
|
|
||||||
describe('Notes', () => {
|
describe('Notes', () => {
|
||||||
let app: INestApplication;
|
let app: INestApplication;
|
||||||
|
@ -46,6 +46,7 @@ describe('Notes', () => {
|
||||||
}),
|
}),
|
||||||
LoggerModule,
|
LoggerModule,
|
||||||
AuthModule,
|
AuthModule,
|
||||||
|
UsersModule,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
.overrideGuard(TokenAuthGuard)
|
.overrideGuard(TokenAuthGuard)
|
||||||
|
@ -55,8 +56,6 @@ describe('Notes', () => {
|
||||||
app = moduleRef.createNestApplication();
|
app = moduleRef.createNestApplication();
|
||||||
await app.init();
|
await app.init();
|
||||||
notesService = moduleRef.get(NotesService);
|
notesService = moduleRef.get(NotesService);
|
||||||
const usersService: UsersService = moduleRef.get('UsersService');
|
|
||||||
await usersService.createUser('testy', 'Testy McTestFace');
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it(`POST /notes`, async () => {
|
it(`POST /notes`, async () => {
|
||||||
|
@ -69,8 +68,9 @@ describe('Notes', () => {
|
||||||
.expect(201);
|
.expect(201);
|
||||||
expect(response.body.metadata?.id).toBeDefined();
|
expect(response.body.metadata?.id).toBeDefined();
|
||||||
expect(
|
expect(
|
||||||
(await notesService.getNoteDtoByIdOrAlias(response.body.metadata.id))
|
await notesService.getCurrentContent(
|
||||||
.content,
|
await notesService.getNoteByIdOrAlias(response.body.metadata.id),
|
||||||
|
),
|
||||||
).toEqual(newNote);
|
).toEqual(newNote);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -100,8 +100,9 @@ describe('Notes', () => {
|
||||||
.expect(201);
|
.expect(201);
|
||||||
expect(response.body.metadata?.id).toBeDefined();
|
expect(response.body.metadata?.id).toBeDefined();
|
||||||
return expect(
|
return expect(
|
||||||
(await notesService.getNoteDtoByIdOrAlias(response.body.metadata.id))
|
await notesService.getCurrentContent(
|
||||||
.content,
|
await notesService.getNoteByIdOrAlias(response.body.metadata?.id),
|
||||||
|
),
|
||||||
).toEqual(newNote);
|
).toEqual(newNote);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -125,7 +126,9 @@ describe('Notes', () => {
|
||||||
.send('New note text')
|
.send('New note text')
|
||||||
.expect(200);
|
.expect(200);
|
||||||
await expect(
|
await expect(
|
||||||
(await notesService.getNoteDtoByIdOrAlias('test4')).content,
|
await notesService.getCurrentContent(
|
||||||
|
await notesService.getNoteByIdOrAlias('test4'),
|
||||||
|
),
|
||||||
).toEqual('New note text');
|
).toEqual('New note text');
|
||||||
expect(response.body.content).toEqual('New note text');
|
expect(response.body.content).toEqual('New note text');
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue