Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
155 changes: 149 additions & 6 deletions src/presentation/http/router/note.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1787,6 +1787,83 @@ describe('Note API', () => {
expect(response?.json().parentNote.id).toBe(newParentNote.publicId);
});

test.each([
/** Returns 403 if user is not in the team of the new parent note */
{
role: null,
},

/** Returns 403 if user is team member of the new parent note with a Read role */
{
role: MemberRole.Read,
},
])
('Returns 403 when user can not edit the new parent note', async ({ role }) => {
/* create test user - creator of the new parent note */
const owner = await global.db.insertUser();

/* create test child note */
const childNote = await global.db.insertNote({
creatorId: user.id,
});

/* create test parent note */
const parentNote = await global.db.insertNote({
creatorId: user.id,
});

/* create test note of another user, that will be new parent for the child note */
const newParentNote = await global.db.insertNote({
creatorId: owner.id,
});

/* create note settings for child note */
await global.db.insertNoteSetting({
noteId: childNote.id,
isPublic: true,
});

/* create test relation */
await global.db.insertNoteRelation({
noteId: childNote.id,
parentId: parentNote.id,
});

/* create test team of the new parent note */
if (role !== null) {
await global.db.insertNoteTeam({
noteId: newParentNote.id,
userId: user.id,
role: role,
});
}

let response = await global.api?.fakeRequest({
method: 'PATCH',
headers: {
authorization: `Bearer ${accessToken}`,
},
body: {
parentNoteId: newParentNote.publicId,
},
url: `/note/${childNote.publicId}/relation`,
});

expect(response?.statusCode).toBe(403);

expect(response?.json().message).toStrictEqual('You don\'t have permission to edit the parent note');

response = await global.api?.fakeRequest({
method: 'GET',
headers: {
authorization: `Bearer ${accessToken}`,
},
url: `/note/${childNote.publicId}`,
});

expect(response?.json().parentNote.id).toBe(parentNote.publicId);
});

test('Returns 400 when parent is the same as child', async () => {
/* create test child note */
const childNote = await global.db.insertNote({
Expand Down Expand Up @@ -1820,7 +1897,7 @@ describe('Note API', () => {
expect(response?.json().message).toStrictEqual(`Forbidden relation. Note can't be a child of own child`);
});

test('Return 400 when parent note does not exist', async () => {
test('Return 406 when parent note does not exist', async () => {
const nonExistentParentId = '47L43yY7dp';

const childNote = await global.db.insertNote({
Expand All @@ -1838,9 +1915,9 @@ describe('Note API', () => {
url: `/note/${childNote.publicId}/relation`,
});

expect(response?.statusCode).toBe(400);
expect(response?.statusCode).toBe(406);

expect(response?.json().message).toStrictEqual('Incorrect parent note');
expect(response?.json().message).toStrictEqual('Parent note not found');
});

test('Return 400 when circular reference occurs', async () => {
Expand Down Expand Up @@ -1925,6 +2002,72 @@ describe('Note API', () => {
expect(response?.json().parentNote.id).toBe(parentNote.publicId);
});

test.each([
/** Returns 403 if user is not in the team of the parent note */
{
role: null,
},

/** Returns 403 if user is team member of the parent note with a Read role */
{
role: MemberRole.Read,
},
])
('Returns 403 when user can not edit the parent note', async ({ role }) => {
/* create test user - creator of the parent note */
const owner = await global.db.insertUser();

/* create test child note */
const childNote = await global.db.insertNote({
creatorId: user.id,
});

/* create test note of another user, that will be parent for the child note */
const parentNote = await global.db.insertNote({
creatorId: owner.id,
});

/* create note settings for child note */
await global.db.insertNoteSetting({
noteId: childNote.id,
isPublic: true,
});

/* create test team of the parent note */
if (role !== null) {
await global.db.insertNoteTeam({
noteId: parentNote.id,
userId: user.id,
role: role,
});
}

let response = await global.api?.fakeRequest({
method: 'POST',
headers: {
authorization: `Bearer ${accessToken}`,
},
body: {
parentNoteId: parentNote.publicId,
},
url: `/note/${childNote.publicId}/relation`,
});

expect(response?.statusCode).toBe(403);

expect(response?.json().message).toStrictEqual('You don\'t have permission to edit the parent note');

response = await global.api?.fakeRequest({
method: 'GET',
headers: {
authorization: `Bearer ${accessToken}`,
},
url: `/note/${childNote.publicId}`,
});

expect(response?.json().parentNote).toBeUndefined();
});

test('Returns 400 when note already has parent note', async () => {
/* create test child note */
const childNote = await global.db.insertNote({
Expand Down Expand Up @@ -1985,7 +2128,7 @@ describe('Note API', () => {
expect(response?.json().message).toStrictEqual(`Forbidden relation. Note can't be a child of own child`);
});

test('Return 400 when parent note does not exist', async () => {
test('Return 406 when parent note does not exist', async () => {
const nonExistentParentId = '47L43yY7dp';

const childNote = await global.db.insertNote({
Expand All @@ -2003,9 +2146,9 @@ describe('Note API', () => {
url: `/note/${childNote.publicId}/relation`,
});

expect(response?.statusCode).toBe(400);
expect(response?.statusCode).toBe(406);

expect(response?.json().message).toStrictEqual('Incorrect parent note Id');
expect(response?.json().message).toStrictEqual('Parent note not found');
});

test('Return 400 when circular reference occurs', async () => {
Expand Down
4 changes: 4 additions & 0 deletions src/presentation/http/router/note.ts
Original file line number Diff line number Diff line change
Expand Up @@ -442,10 +442,12 @@ const NoteRouter: FastifyPluginCallback<NoteRouterOptions> = (fastify, opts, don
policy: [
'authRequired',
'userCanEdit',
'userCanEditParentNote',
],
},
preHandler: [
noteResolver,
parentNoteResolver,
],
}, async (request, reply) => {
const noteId = request.note?.id as number;
Expand Down Expand Up @@ -497,10 +499,12 @@ const NoteRouter: FastifyPluginCallback<NoteRouterOptions> = (fastify, opts, don
policy: [
'authRequired',
'userCanEdit',
'userCanEditParentNote',
],
},
preHandler: [
noteResolver,
parentNoteResolver,
],
}, async (request, reply) => {
const noteId = request.note?.id as number;
Expand Down
Loading