mirror of
https://github.com/hedgedoc/hedgedoc.git
synced 2024-11-27 03:58:02 -05:00
Merge pull request #1284 from hedgedoc/publicId
This commit is contained in:
commit
112e6d8c5d
12 changed files with 109 additions and 58 deletions
|
@ -5,6 +5,7 @@ skinparam nodesep 60
|
||||||
entity "note" {
|
entity "note" {
|
||||||
*id : uuid <<generated>>
|
*id : uuid <<generated>>
|
||||||
--
|
--
|
||||||
|
publicId: text
|
||||||
alias : text
|
alias : text
|
||||||
*viewCount : number
|
*viewCount : number
|
||||||
*ownerId : uuid <<FK user>>
|
*ownerId : uuid <<FK user>>
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
"@types/minio": "7.0.7",
|
"@types/minio": "7.0.7",
|
||||||
"@types/node-fetch": "2.5.10",
|
"@types/node-fetch": "2.5.10",
|
||||||
"@types/passport-http-bearer": "1.0.36",
|
"@types/passport-http-bearer": "1.0.36",
|
||||||
|
"base32-encode": "1.2.0",
|
||||||
"bcrypt": "5.0.1",
|
"bcrypt": "5.0.1",
|
||||||
"class-transformer": "0.4.0",
|
"class-transformer": "0.4.0",
|
||||||
"class-validator": "0.13.1",
|
"class-validator": "0.13.1",
|
||||||
|
|
|
@ -17,6 +17,7 @@ import { NotInDBError, TokenNotValidError } from '../errors/errors';
|
||||||
import { Repository } from 'typeorm';
|
import { Repository } from 'typeorm';
|
||||||
import { ConfigModule } from '@nestjs/config';
|
import { ConfigModule } from '@nestjs/config';
|
||||||
import appConfigMock from '../config/mock/app.config.mock';
|
import appConfigMock from '../config/mock/app.config.mock';
|
||||||
|
import { randomBytes } from 'crypto';
|
||||||
|
|
||||||
describe('AuthService', () => {
|
describe('AuthService', () => {
|
||||||
let service: AuthService;
|
let service: AuthService;
|
||||||
|
@ -79,7 +80,7 @@ describe('AuthService', () => {
|
||||||
.then((result) => expect(result).toBeTruthy());
|
.then((result) => expect(result).toBeTruthy());
|
||||||
});
|
});
|
||||||
it('fails, if secret is too short', async () => {
|
it('fails, if secret is too short', async () => {
|
||||||
const secret = service.bufferToBase64Url(service.randomString(54));
|
const secret = service.bufferToBase64Url(randomBytes(54));
|
||||||
const hash = await service.hashPassword(secret);
|
const hash = await service.hashPassword(secret);
|
||||||
await service
|
await service
|
||||||
.checkPassword(secret, hash)
|
.checkPassword(secret, hash)
|
||||||
|
@ -328,10 +329,4 @@ describe('AuthService', () => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('randomString', () => {
|
|
||||||
it('throws on invalid lenght parameter', () => {
|
|
||||||
expect(() => service.randomString(0)).toThrow();
|
|
||||||
expect(() => service.randomString(-1)).toThrow();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -16,12 +16,12 @@ import {
|
||||||
TokenNotValidError,
|
TokenNotValidError,
|
||||||
TooManyTokensError,
|
TooManyTokensError,
|
||||||
} from '../errors/errors';
|
} from '../errors/errors';
|
||||||
import { randomBytes } from 'crypto';
|
|
||||||
import { InjectRepository } from '@nestjs/typeorm';
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
import { Repository } from 'typeorm';
|
import { Repository } from 'typeorm';
|
||||||
import { ConsoleLoggerService } from '../logger/console-logger.service';
|
import { ConsoleLoggerService } from '../logger/console-logger.service';
|
||||||
import { TimestampMillis } from '../utils/timestamp';
|
import { TimestampMillis } from '../utils/timestamp';
|
||||||
import { Cron, Timeout } from '@nestjs/schedule';
|
import { Cron, Timeout } from '@nestjs/schedule';
|
||||||
|
import { randomBytes } from 'crypto';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AuthService {
|
export class AuthService {
|
||||||
|
@ -62,13 +62,6 @@ export class AuthService {
|
||||||
return await compare(cleartext, password);
|
return await compare(cleartext, password);
|
||||||
}
|
}
|
||||||
|
|
||||||
randomString(length: number): Buffer {
|
|
||||||
if (length <= 0) {
|
|
||||||
throw new Error('randomString cannot have a length < 1');
|
|
||||||
}
|
|
||||||
return randomBytes(length);
|
|
||||||
}
|
|
||||||
|
|
||||||
bufferToBase64Url(text: Buffer): string {
|
bufferToBase64Url(text: Buffer): string {
|
||||||
// This is necessary as the is no base64url encoding in the toString method
|
// This is necessary as the is no base64url encoding in the toString method
|
||||||
// but as can be seen on https://tools.ietf.org/html/rfc4648#page-7
|
// but as can be seen on https://tools.ietf.org/html/rfc4648#page-7
|
||||||
|
@ -93,8 +86,8 @@ export class AuthService {
|
||||||
`User '${user.userName}' has already 200 tokens and can't have anymore`,
|
`User '${user.userName}' has already 200 tokens and can't have anymore`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
const secret = this.bufferToBase64Url(this.randomString(54));
|
const secret = this.bufferToBase64Url(randomBytes(54));
|
||||||
const keyId = this.bufferToBase64Url(this.randomString(8));
|
const keyId = this.bufferToBase64Url(randomBytes(8));
|
||||||
const accessToken = await this.hashPassword(secret);
|
const accessToken = await this.hashPassword(secret);
|
||||||
let token;
|
let token;
|
||||||
// Tokens can only be valid for a maximum of 2 years
|
// Tokens can only be valid for a maximum of 2 years
|
||||||
|
|
|
@ -26,6 +26,8 @@ import { MediaUpload } from '../media/media-upload.entity';
|
||||||
export class Note {
|
export class Note {
|
||||||
@PrimaryGeneratedColumn('uuid')
|
@PrimaryGeneratedColumn('uuid')
|
||||||
id: string;
|
id: string;
|
||||||
|
@Column({ type: 'text' })
|
||||||
|
publicId: string;
|
||||||
@Column({
|
@Column({
|
||||||
unique: true,
|
unique: true,
|
||||||
nullable: true,
|
nullable: true,
|
||||||
|
|
|
@ -684,7 +684,7 @@ describe('NotesService', () => {
|
||||||
];
|
];
|
||||||
revisions[0].createdAt = new Date(1549312452000);
|
revisions[0].createdAt = new Date(1549312452000);
|
||||||
jest.spyOn(revisionRepo, 'findOne').mockResolvedValue(revisions[0]);
|
jest.spyOn(revisionRepo, 'findOne').mockResolvedValue(revisions[0]);
|
||||||
note.id = 'testId';
|
note.publicId = 'testId';
|
||||||
note.alias = 'testAlias';
|
note.alias = 'testAlias';
|
||||||
note.title = 'testTitle';
|
note.title = 'testTitle';
|
||||||
note.description = 'testDescription';
|
note.description = 'testDescription';
|
||||||
|
@ -719,7 +719,7 @@ describe('NotesService', () => {
|
||||||
];
|
];
|
||||||
note.viewCount = 1337;
|
note.viewCount = 1337;
|
||||||
const metadataDto = await service.toNoteMetadataDto(note);
|
const metadataDto = await service.toNoteMetadataDto(note);
|
||||||
expect(metadataDto.id).toEqual(note.id);
|
expect(metadataDto.id).toEqual(note.publicId);
|
||||||
expect(metadataDto.alias).toEqual(note.alias);
|
expect(metadataDto.alias).toEqual(note.alias);
|
||||||
expect(metadataDto.title).toEqual(note.title);
|
expect(metadataDto.title).toEqual(note.title);
|
||||||
expect(metadataDto.createTime).toEqual(revisions[0].createdAt);
|
expect(metadataDto.createTime).toEqual(revisions[0].createdAt);
|
||||||
|
@ -778,7 +778,7 @@ describe('NotesService', () => {
|
||||||
.spyOn(revisionRepo, 'findOne')
|
.spyOn(revisionRepo, 'findOne')
|
||||||
.mockResolvedValue(revisions[0])
|
.mockResolvedValue(revisions[0])
|
||||||
.mockResolvedValue(revisions[0]);
|
.mockResolvedValue(revisions[0]);
|
||||||
note.id = 'testId';
|
note.publicId = 'testId';
|
||||||
note.alias = 'testAlias';
|
note.alias = 'testAlias';
|
||||||
note.title = 'testTitle';
|
note.title = 'testTitle';
|
||||||
note.description = 'testDescription';
|
note.description = 'testDescription';
|
||||||
|
@ -813,7 +813,7 @@ describe('NotesService', () => {
|
||||||
];
|
];
|
||||||
note.viewCount = 1337;
|
note.viewCount = 1337;
|
||||||
const noteDto = await service.toNoteDto(note);
|
const noteDto = await service.toNoteDto(note);
|
||||||
expect(noteDto.metadata.id).toEqual(note.id);
|
expect(noteDto.metadata.id).toEqual(note.publicId);
|
||||||
expect(noteDto.metadata.alias).toEqual(note.alias);
|
expect(noteDto.metadata.alias).toEqual(note.alias);
|
||||||
expect(noteDto.metadata.title).toEqual(note.title);
|
expect(noteDto.metadata.title).toEqual(note.title);
|
||||||
expect(noteDto.metadata.createTime).toEqual(revisions[0].createdAt);
|
expect(noteDto.metadata.createTime).toEqual(revisions[0].createdAt);
|
||||||
|
|
|
@ -32,6 +32,8 @@ import { NoteGroupPermission } from '../permissions/note-group-permission.entity
|
||||||
import { GroupsService } from '../groups/groups.service';
|
import { GroupsService } from '../groups/groups.service';
|
||||||
import { checkArrayForDuplicates } from '../utils/arrayDuplicatCheck';
|
import { checkArrayForDuplicates } from '../utils/arrayDuplicatCheck';
|
||||||
import appConfiguration, { AppConfig } from '../config/app.config';
|
import appConfiguration, { AppConfig } from '../config/app.config';
|
||||||
|
import base32Encode from 'base32-encode';
|
||||||
|
import { randomBytes } from 'crypto';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class NotesService {
|
export class NotesService {
|
||||||
|
@ -92,6 +94,7 @@ export class NotesService {
|
||||||
newNote.revisions = Promise.resolve([
|
newNote.revisions = Promise.resolve([
|
||||||
Revision.create(noteContent, noteContent),
|
Revision.create(noteContent, noteContent),
|
||||||
]);
|
]);
|
||||||
|
newNote.publicId = this.generatePublicId();
|
||||||
if (alias) {
|
if (alias) {
|
||||||
newNote.alias = alias;
|
newNote.alias = alias;
|
||||||
this.checkNoteIdOrAlias(alias);
|
this.checkNoteIdOrAlias(alias);
|
||||||
|
@ -164,7 +167,7 @@ export class NotesService {
|
||||||
const note = await this.noteRepository.findOne({
|
const note = await this.noteRepository.findOne({
|
||||||
where: [
|
where: [
|
||||||
{
|
{
|
||||||
id: noteIdOrAlias,
|
publicId: noteIdOrAlias,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
alias: noteIdOrAlias,
|
alias: noteIdOrAlias,
|
||||||
|
@ -210,6 +213,15 @@ export class NotesService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate publicId for a note.
|
||||||
|
* This is a randomly generated 128-bit value encoded with base32-encode using the crockford variant and converted to lowercase.
|
||||||
|
*/
|
||||||
|
generatePublicId(): string {
|
||||||
|
const randomId = randomBytes(128);
|
||||||
|
return base32Encode(randomId, 'Crockford').toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @async
|
* @async
|
||||||
* Delete a note
|
* Delete a note
|
||||||
|
@ -358,8 +370,7 @@ export class NotesService {
|
||||||
async toNoteMetadataDto(note: Note): Promise<NoteMetadataDto> {
|
async toNoteMetadataDto(note: Note): Promise<NoteMetadataDto> {
|
||||||
const updateUser = await this.calculateUpdateUser(note);
|
const updateUser = await this.calculateUpdateUser(note);
|
||||||
return {
|
return {
|
||||||
// TODO: Convert DB UUID to base64
|
id: note.publicId,
|
||||||
id: note.id,
|
|
||||||
alias: note.alias ?? null,
|
alias: note.alias ?? null,
|
||||||
title: note.title ?? '',
|
title: note.title ?? '',
|
||||||
createTime: (await this.getFirstRevision(note)).createdAt,
|
createTime: (await this.getFirstRevision(note)).createdAt,
|
||||||
|
|
|
@ -111,10 +111,26 @@ describe('Me', () => {
|
||||||
expect(responseBefore.body).toHaveLength(0);
|
expect(responseBefore.body).toHaveLength(0);
|
||||||
|
|
||||||
const testImage = await fs.readFile('test/public-api/fixtures/test.png');
|
const testImage = await fs.readFile('test/public-api/fixtures/test.png');
|
||||||
const url0 = await mediaService.saveFile(testImage, 'hardcoded', note1.id);
|
const url0 = await mediaService.saveFile(
|
||||||
const url1 = await mediaService.saveFile(testImage, 'hardcoded', note1.id);
|
testImage,
|
||||||
const url2 = await mediaService.saveFile(testImage, 'hardcoded', note2.id);
|
'hardcoded',
|
||||||
const url3 = await mediaService.saveFile(testImage, 'hardcoded', note2.id);
|
note1.publicId,
|
||||||
|
);
|
||||||
|
const url1 = await mediaService.saveFile(
|
||||||
|
testImage,
|
||||||
|
'hardcoded',
|
||||||
|
note1.publicId,
|
||||||
|
);
|
||||||
|
const url2 = await mediaService.saveFile(
|
||||||
|
testImage,
|
||||||
|
'hardcoded',
|
||||||
|
note2.alias ?? '',
|
||||||
|
);
|
||||||
|
const url3 = await mediaService.saveFile(
|
||||||
|
testImage,
|
||||||
|
'hardcoded',
|
||||||
|
note2.alias ?? '',
|
||||||
|
);
|
||||||
|
|
||||||
const response = await request(httpServer)
|
const response = await request(httpServer)
|
||||||
.get('/me/media/')
|
.get('/me/media/')
|
||||||
|
@ -147,7 +163,11 @@ describe('Me', () => {
|
||||||
|
|
||||||
it('DELETE /me', async () => {
|
it('DELETE /me', async () => {
|
||||||
const testImage = await fs.readFile('test/public-api/fixtures/test.png');
|
const testImage = await fs.readFile('test/public-api/fixtures/test.png');
|
||||||
const url0 = await mediaService.saveFile(testImage, 'hardcoded', note1.id);
|
const url0 = await mediaService.saveFile(
|
||||||
|
testImage,
|
||||||
|
'hardcoded',
|
||||||
|
note1.publicId,
|
||||||
|
);
|
||||||
const dbUser = await userService.getUserByUsername('hardcoded');
|
const dbUser = await userService.getUserByUsername('hardcoded');
|
||||||
expect(dbUser).toBeInstanceOf(User);
|
expect(dbUser).toBeInstanceOf(User);
|
||||||
const mediaUploads = await mediaService.listUploadsByUser(dbUser);
|
const mediaUploads = await mediaService.listUploadsByUser(dbUser);
|
||||||
|
|
|
@ -261,25 +261,27 @@ describe('Notes', () => {
|
||||||
|
|
||||||
describe('GET /notes/{note}/media', () => {
|
describe('GET /notes/{note}/media', () => {
|
||||||
it('works', async () => {
|
it('works', async () => {
|
||||||
const note = await notesService.createNote(content, 'test6', user);
|
const alias = 'test6';
|
||||||
const extraNote = await notesService.createNote(content, 'test7', user);
|
const extraAlias = 'test7';
|
||||||
|
await notesService.createNote(content, alias, user);
|
||||||
|
await notesService.createNote(content, extraAlias, user);
|
||||||
const httpServer = app.getHttpServer();
|
const httpServer = app.getHttpServer();
|
||||||
const response = await request(httpServer)
|
const response = await request(httpServer)
|
||||||
.get(`/notes/${note.id}/media/`)
|
.get(`/notes/${alias}/media/`)
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect(200);
|
.expect(200);
|
||||||
expect(response.body).toHaveLength(0);
|
expect(response.body).toHaveLength(0);
|
||||||
|
|
||||||
const testImage = await fs.readFile('test/private-api/fixtures/test.png');
|
const testImage = await fs.readFile('test/private-api/fixtures/test.png');
|
||||||
const url0 = await mediaService.saveFile(testImage, 'hardcoded', note.id);
|
const url0 = await mediaService.saveFile(testImage, 'hardcoded', alias);
|
||||||
const url1 = await mediaService.saveFile(
|
const url1 = await mediaService.saveFile(
|
||||||
testImage,
|
testImage,
|
||||||
'hardcoded',
|
'hardcoded',
|
||||||
extraNote.id,
|
extraAlias,
|
||||||
);
|
);
|
||||||
|
|
||||||
const responseAfter = await request(httpServer)
|
const responseAfter = await request(httpServer)
|
||||||
.get(`/notes/${note.id}/media/`)
|
.get(`/notes/${alias}/media/`)
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect(200);
|
.expect(200);
|
||||||
expect(responseAfter.body).toHaveLength(1);
|
expect(responseAfter.body).toHaveLength(1);
|
||||||
|
@ -299,13 +301,10 @@ describe('Notes', () => {
|
||||||
.expect(404);
|
.expect(404);
|
||||||
});
|
});
|
||||||
it("fails, when user can't read note", async () => {
|
it("fails, when user can't read note", async () => {
|
||||||
const note = await notesService.createNote(
|
const alias = 'test11';
|
||||||
'This is a test note.',
|
await notesService.createNote('This is a test note.', alias, user2);
|
||||||
'test11',
|
|
||||||
user2,
|
|
||||||
);
|
|
||||||
await request(app.getHttpServer())
|
await request(app.getHttpServer())
|
||||||
.get(`/notes/${note.id}/media/`)
|
.get(`/notes/${alias}/media/`)
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect(401);
|
.expect(401);
|
||||||
});
|
});
|
||||||
|
|
|
@ -243,10 +243,26 @@ describe('Me', () => {
|
||||||
expect(response1.body).toHaveLength(0);
|
expect(response1.body).toHaveLength(0);
|
||||||
|
|
||||||
const testImage = await fs.readFile('test/public-api/fixtures/test.png');
|
const testImage = await fs.readFile('test/public-api/fixtures/test.png');
|
||||||
const url0 = await mediaService.saveFile(testImage, 'hardcoded', note1.id);
|
const url0 = await mediaService.saveFile(
|
||||||
const url1 = await mediaService.saveFile(testImage, 'hardcoded', note1.id);
|
testImage,
|
||||||
const url2 = await mediaService.saveFile(testImage, 'hardcoded', note2.id);
|
'hardcoded',
|
||||||
const url3 = await mediaService.saveFile(testImage, 'hardcoded', note2.id);
|
note1.publicId,
|
||||||
|
);
|
||||||
|
const url1 = await mediaService.saveFile(
|
||||||
|
testImage,
|
||||||
|
'hardcoded',
|
||||||
|
note1.publicId,
|
||||||
|
);
|
||||||
|
const url2 = await mediaService.saveFile(
|
||||||
|
testImage,
|
||||||
|
'hardcoded',
|
||||||
|
note2.publicId,
|
||||||
|
);
|
||||||
|
const url3 = await mediaService.saveFile(
|
||||||
|
testImage,
|
||||||
|
'hardcoded',
|
||||||
|
note2.publicId,
|
||||||
|
);
|
||||||
|
|
||||||
const response = await request(httpServer)
|
const response = await request(httpServer)
|
||||||
.get('/me/media/')
|
.get('/me/media/')
|
||||||
|
|
|
@ -204,7 +204,9 @@ describe('Notes', () => {
|
||||||
];
|
];
|
||||||
updateNotePermission.sharedToGroups = [];
|
updateNotePermission.sharedToGroups = [];
|
||||||
await notesService.updateNotePermissions(note, updateNotePermission);
|
await notesService.updateNotePermissions(note, updateNotePermission);
|
||||||
const updatedNote = await notesService.getNoteByIdOrAlias(note.alias);
|
const updatedNote = await notesService.getNoteByIdOrAlias(
|
||||||
|
note.alias ?? '',
|
||||||
|
);
|
||||||
expect(updatedNote.userPermissions).toHaveLength(1);
|
expect(updatedNote.userPermissions).toHaveLength(1);
|
||||||
expect(updatedNote.userPermissions[0].canEdit).toEqual(
|
expect(updatedNote.userPermissions[0].canEdit).toEqual(
|
||||||
updateNotePermission.sharedToUsers[0].canEdit,
|
updateNotePermission.sharedToUsers[0].canEdit,
|
||||||
|
@ -391,25 +393,27 @@ describe('Notes', () => {
|
||||||
|
|
||||||
describe('GET /notes/{note}/media', () => {
|
describe('GET /notes/{note}/media', () => {
|
||||||
it('works', async () => {
|
it('works', async () => {
|
||||||
const note = await notesService.createNote(content, 'test9', user);
|
const alias = 'test9';
|
||||||
const extraNote = await notesService.createNote(content, 'test10', user);
|
const extraAlias = 'test10';
|
||||||
|
await notesService.createNote(content, alias, user);
|
||||||
|
await notesService.createNote(content, extraAlias, user);
|
||||||
const httpServer = app.getHttpServer();
|
const httpServer = app.getHttpServer();
|
||||||
const response = await request(httpServer)
|
const response = await request(httpServer)
|
||||||
.get(`/notes/${note.id}/media/`)
|
.get(`/notes/${alias}/media/`)
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect(200);
|
.expect(200);
|
||||||
expect(response.body).toHaveLength(0);
|
expect(response.body).toHaveLength(0);
|
||||||
|
|
||||||
const testImage = await fs.readFile('test/public-api/fixtures/test.png');
|
const testImage = await fs.readFile('test/public-api/fixtures/test.png');
|
||||||
const url0 = await mediaService.saveFile(testImage, 'hardcoded', note.id);
|
const url0 = await mediaService.saveFile(testImage, 'hardcoded', alias);
|
||||||
const url1 = await mediaService.saveFile(
|
const url1 = await mediaService.saveFile(
|
||||||
testImage,
|
testImage,
|
||||||
'hardcoded',
|
'hardcoded',
|
||||||
extraNote.id,
|
extraAlias,
|
||||||
);
|
);
|
||||||
|
|
||||||
const responseAfter = await request(httpServer)
|
const responseAfter = await request(httpServer)
|
||||||
.get(`/notes/${note.id}/media/`)
|
.get(`/notes/${alias}/media/`)
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect(200);
|
.expect(200);
|
||||||
expect(responseAfter.body).toHaveLength(1);
|
expect(responseAfter.body).toHaveLength(1);
|
||||||
|
@ -429,13 +433,10 @@ describe('Notes', () => {
|
||||||
.expect(404);
|
.expect(404);
|
||||||
});
|
});
|
||||||
it("fails, when user can't read note", async () => {
|
it("fails, when user can't read note", async () => {
|
||||||
const note = await notesService.createNote(
|
const alias = 'test11';
|
||||||
'This is a test note.',
|
await notesService.createNote('This is a test note.', alias, user2);
|
||||||
'test11',
|
|
||||||
user2,
|
|
||||||
);
|
|
||||||
await request(app.getHttpServer())
|
await request(app.getHttpServer())
|
||||||
.get(`/notes/${note.id}/media/`)
|
.get(`/notes/${alias}/media/`)
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect(401);
|
.expect(401);
|
||||||
});
|
});
|
||||||
|
|
12
yarn.lock
12
yarn.lock
|
@ -1895,6 +1895,13 @@ balanced-match@^1.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
|
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
|
||||||
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
|
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
|
||||||
|
|
||||||
|
base32-encode@1.2.0:
|
||||||
|
version "1.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/base32-encode/-/base32-encode-1.2.0.tgz#e150573a5e431af0a998e32bdfde7045725ca453"
|
||||||
|
integrity sha512-cHFU8XeRyx0GgmoWi5qHMCVRiqU6J3MHWxVgun7jggCBUpVzm1Ir7M9dYr2whjSNc3tFeXfQ/oZjQu/4u55h9A==
|
||||||
|
dependencies:
|
||||||
|
to-data-view "^1.1.0"
|
||||||
|
|
||||||
base64-js@^1.3.1:
|
base64-js@^1.3.1:
|
||||||
version "1.5.1"
|
version "1.5.1"
|
||||||
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
|
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
|
||||||
|
@ -7061,6 +7068,11 @@ tmpl@1.0.x:
|
||||||
resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1"
|
resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1"
|
||||||
integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=
|
integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=
|
||||||
|
|
||||||
|
to-data-view@^1.1.0:
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/to-data-view/-/to-data-view-1.1.0.tgz#08d6492b0b8deb9b29bdf1f61c23eadfa8994d00"
|
||||||
|
integrity sha512-1eAdufMg6mwgmlojAx3QeMnzB/BTVp7Tbndi3U7ftcT2zCZadjxkkmLmd97zmaxWi+sgGcgWrokmpEoy0Dn0vQ==
|
||||||
|
|
||||||
to-fast-properties@^2.0.0:
|
to-fast-properties@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
|
resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
|
||||||
|
|
Loading…
Reference in a new issue