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
38 changes: 12 additions & 26 deletions src/services/account/errors.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,17 @@
import { StatusCodes } from 'http-status-codes';

import { ErrorFactory, FAILURE_MESSAGES } from '@graasp/sdk';
import { createError } from '@fastify/error';

export const GraaspAccountError = ErrorFactory('graasp-plugin-account');
import { FAILURE_MESSAGES } from '@graasp/sdk';

export class AccountNotFound extends GraaspAccountError {
constructor(data?: unknown) {
super(
{
code: 'GPAECCRR001',
statusCode: StatusCodes.NOT_FOUND,
message: FAILURE_MESSAGES.ACCOUNT_NOT_FOUND,
},
data,
);
}
}
export const AccountNotFound = createError(
'GPAECCRR001',
FAILURE_MESSAGES.ACCOUNT_NOT_FOUND,
StatusCodes.NOT_FOUND,
);

export class NotMemberOrGuest extends GraaspAccountError {
constructor(data?: unknown) {
super(
{
code: 'GPAECCRR002',
statusCode: StatusCodes.FORBIDDEN,
message: FAILURE_MESSAGES.NOT_MEMBER_OR_GUEST,
},
data,
);
}
}
export const NotMemberOrGuest = createError(
'GPAECCRR002',
FAILURE_MESSAGES.NOT_MEMBER_OR_GUEST,
StatusCodes.FORBIDDEN,
);
22 changes: 6 additions & 16 deletions src/services/action/utils/errors.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,9 @@
import { StatusCodes } from 'http-status-codes';

import { ErrorFactory } from '@graasp/sdk';
import { createError } from '@fastify/error';

import { PLUGIN_NAME } from '../constants';

export const GraaspActionError = ErrorFactory(PLUGIN_NAME);
export class CannotWriteFileError extends GraaspActionError {
constructor(data?: unknown) {
super(
{
code: 'GPAERR001',
statusCode: StatusCodes.NOT_FOUND,
message: 'A file was not created properly for the requested archive',
},
data,
);
}
}
export const CannotWriteFileError = createError(
'GPAERR001',
'A file was not created properly for the requested archive',
StatusCodes.NOT_FOUND,
);
19 changes: 6 additions & 13 deletions src/services/auth/plugins/captcha/errors.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
import { StatusCodes } from 'http-status-codes';

import { CoreError } from '../../../../utils/errors';
import { createError } from '@fastify/error';

export class AuthenticationError extends CoreError {
constructor(data?: unknown) {
super(
{
code: 'GERR028',
statusCode: StatusCodes.UNAUTHORIZED,
message: 'The authentication failed',
},
data,
);
}
}
export const AuthenticationError = createError(
'GERR028',
'The authentication failed',
StatusCodes.UNAUTHORIZED,
);
56 changes: 17 additions & 39 deletions src/services/auth/plugins/password/errors.ts
Original file line number Diff line number Diff line change
@@ -1,44 +1,22 @@
import { StatusCodes } from 'http-status-codes';

import { ErrorFactory, FAILURE_MESSAGES } from '@graasp/sdk';
import { createError } from '@fastify/error';
import { FAILURE_MESSAGES } from '@graasp/sdk';

export const GraaspPasswordError = ErrorFactory('graasp-plugin-password');
export const PasswordNotDefined = createError(
'GPPWDERR001',
FAILURE_MESSAGES.PASSWORD_NOT_DEFINED_ERROR,
StatusCodes.BAD_REQUEST,
);

export class PasswordNotDefined extends GraaspPasswordError {
constructor(data?: unknown) {
super(
{
code: 'GPPWDERR001',
statusCode: StatusCodes.BAD_REQUEST,
message: FAILURE_MESSAGES.PASSWORD_NOT_DEFINED_ERROR,
},
data,
);
}
}
export const PasswordNotStrong = createError(
'GPPWDERR002',
FAILURE_MESSAGES.PASSWORD_WEAK_ERROR,
StatusCodes.BAD_REQUEST,
);

export class PasswordNotStrong extends GraaspPasswordError {
constructor(data?: unknown) {
super(
{
code: 'GPPWDERR002',
statusCode: StatusCodes.BAD_REQUEST,
message: FAILURE_MESSAGES.PASSWORD_WEAK_ERROR,
},
data,
);
}
}

export class PasswordConflict extends GraaspPasswordError {
constructor(data?: unknown) {
super(
{
code: 'GPPWDERR003',
statusCode: StatusCodes.CONFLICT,
message: FAILURE_MESSAGES.PASSWORD_CONFLICT_ERROR,
},
data,
);
}
}
export const PasswordConflict = createError(
'GPPWDERR003',
FAILURE_MESSAGES.PASSWORD_CONFLICT_ERROR,
StatusCodes.CONFLICT,
);
19 changes: 12 additions & 7 deletions src/services/authentication.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { StatusCodes } from 'http-status-codes';

import { createError } from '@fastify/error';
import { FAILURE_MESSAGES } from '@graasp/sdk';
import type { AccountRaw, MemberRaw } from '../drizzle/types';
import {
AccountType,
Expand All @@ -8,7 +10,6 @@ import {
type MinimalMember,
} from '../types';
import { NotMemberOrGuest } from './account/errors';
import { NotMember } from './member/error';

// TODO: allow AccountRow or apply DTO on all relations?
export function isMember(account: AuthenticatedUser | AccountRaw): account is MinimalMember {
Expand All @@ -20,6 +21,14 @@ export function isGuest(account: AuthenticatedUser | AccountRaw): account is Min
return account.type === AccountType.Guest;
}


export const AssertNotMember = createError(
'AGMERR003',
FAILURE_MESSAGES.NOT_A_MEMBER,
StatusCodes.INTERNAL_SERVER_ERROR,
);


export function assertIsMember<Err extends Error, Args extends unknown[]>(
account: AuthenticatedUser | AccountRaw,
error?: new (...args: Args) => Err,
Expand All @@ -29,9 +38,7 @@ export function assertIsMember<Err extends Error, Args extends unknown[]>(
if (error) {
throw new error(...args);
} else {
const defaultError = new NotMember();
defaultError.statusCode = StatusCodes.INTERNAL_SERVER_ERROR;
throw defaultError;
throw new AssertNotMember();
}
}
}
Expand All @@ -45,9 +52,7 @@ export function assertIsMemberForTest<Err extends Error, Args extends unknown[]>
if (error) {
throw new error(...args);
} else {
const defaultError = new NotMember();
defaultError.statusCode = StatusCodes.INTERNAL_SERVER_ERROR;
throw defaultError;
throw new AssertNotMember();
}
}
}
Expand Down
28 changes: 16 additions & 12 deletions src/services/chat/chatMessage.controller.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ describe('Chat Message tests', () => {
url: `${ITEMS_ROUTE_PREFIX}/${item.id}/chat`,
});

expect(response.json()).toMatchObject(new MemberCannotAccess(expect.anything()));
expect(response.json().message).toEqual(new MemberCannotAccess(item.id).message);
});
});

Expand Down Expand Up @@ -326,7 +326,7 @@ describe('Chat Message tests', () => {
payload,
});

expect(response.json()).toMatchObject(new MemberCannotAccess(expect.anything()));
expect(response.json().message).toEqual(new MemberCannotAccess(item.id).message);
});
});
});
Expand Down Expand Up @@ -460,14 +460,15 @@ describe('Chat Message tests', () => {
assertIsDefined(actor);
mockAuthenticate(actor);

const id = v4();
const payload = { body: 'hello' };
const response = await app.inject({
method: HttpMethod.Patch,
url: `${ITEMS_ROUTE_PREFIX}/${item.id}/chat/${v4()}`,
url: `${ITEMS_ROUTE_PREFIX}/${item.id}/chat/${id}`,
payload,
});

expect(response.json()).toMatchObject(new ChatMessageNotFound(expect.anything()));
expect(response.json().message).toEqual(new ChatMessageNotFound(id).message);
});

it('Throws if member does not have access to item', async () => {
Expand All @@ -488,7 +489,7 @@ describe('Chat Message tests', () => {
payload,
});

expect(response.json()).toMatchObject(new MemberCannotAccess(expect.anything()));
expect(response.json().message).toEqual(new MemberCannotAccess(chatMessage.id).message);
});

it('Throws if member does not have access to chat message', async () => {
Expand All @@ -511,7 +512,7 @@ describe('Chat Message tests', () => {
payload,
});
const res = await response.json();
expect(res).toMatchObject(new MemberCannotEditMessage(expect.anything()));
expect(res.message).toEqual(new MemberCannotEditMessage(chatMessage.id).message);
});
});
});
Expand Down Expand Up @@ -611,12 +612,13 @@ describe('Chat Message tests', () => {
assertIsDefined(actor);
mockAuthenticate(actor);

const id = v4();
const response = await app.inject({
method: HttpMethod.Delete,
url: `${ITEMS_ROUTE_PREFIX}/${item.id}/chat/${v4()}`,
url: `${ITEMS_ROUTE_PREFIX}/${item.id}/chat/${id}`,
});

expect(response.json()).toMatchObject(new ChatMessageNotFound(expect.anything()));
expect(response.json().message).toEqual(new ChatMessageNotFound(id).message);
});

it('Throws if member does not have access to item', async () => {
Expand All @@ -635,7 +637,7 @@ describe('Chat Message tests', () => {
url: `${ITEMS_ROUTE_PREFIX}/${item.id}/chat/${chatMessage.id}`,
});

expect(response.json()).toMatchObject(new MemberCannotAccess(item.id));
expect(response.json().message).toEqual(new MemberCannotAccess(item.id).message);
});

it('Throws if member does not have access to chat message', async () => {
Expand All @@ -655,8 +657,10 @@ describe('Chat Message tests', () => {
method: HttpMethod.Delete,
url: `${ITEMS_ROUTE_PREFIX}/${item.id}/chat/${chatMessage.id}`,
});
const res = await response.json();
expect(res).toMatchObject(new MemberCannotDeleteMessage({ id: expect.anything() }));

const expectedError = new MemberCannotDeleteMessage({ id: chatMessage.id });
expect(response.statusCode).toEqual(expectedError.statusCode);
expect(response.json().message).toEqual(expectedError.message);
});
});
});
Expand Down Expand Up @@ -745,7 +749,7 @@ describe('Chat Message tests', () => {
url: `${ITEMS_ROUTE_PREFIX}/${item.id}/chat`,
});

expect(response.json()).toMatchObject(new MemberCannotAccess(expect.anything()));
expect(response.json().message).toEqual(new MemberCannotAccess(item.id).message);
});
});
});
Expand Down
74 changes: 20 additions & 54 deletions src/services/chat/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,67 +2,33 @@ import { StatusCodes } from 'http-status-codes';

import { createError } from '@fastify/error';

import { ErrorFactory } from '@graasp/sdk';

const PLUGIN_NAME = 'graasp-plugin-chatbox';

/**
* Errors thrown by the chat tasks
*/

export const GraaspChatboxError = ErrorFactory(PLUGIN_NAME);

export class ChatMessageNotFound extends GraaspChatboxError {
constructor(data?: unknown) {
super(
{
code: 'GICERR003',
statusCode: StatusCodes.NOT_FOUND,
message: 'Chat Message not found',
},
data,
);
}
}
export const ChatMessageNotFound = createError(
'GICERR003',
'Chat Message not found',
StatusCodes.NOT_FOUND,
);

export class MemberCannotEditMessage extends GraaspChatboxError {
constructor(data?: unknown) {
super(
{
code: 'GICERR002',
statusCode: StatusCodes.UNAUTHORIZED,
message: 'Member can only edit own messages',
},
data,
);
}
}
export const MemberCannotEditMessage = createError(
'GICERR002',
'Member can only edit own messages',
StatusCodes.UNAUTHORIZED,
);

export class MemberCannotDeleteMessage extends GraaspChatboxError {
constructor(data: { id: string }) {
super(
{
code: 'GICERR005',
statusCode: StatusCodes.UNAUTHORIZED,
message: 'Member can only delete own messages',
},
data.id,
);
}
}
export const MemberCannotDeleteMessage = createError(
'GICERR005',
'Member can only delete own messages',
StatusCodes.UNAUTHORIZED,
);

export class MemberCannotAccessMention extends GraaspChatboxError {
constructor(data: { id: string }) {
super(
{
code: 'GICERR004',
statusCode: StatusCodes.UNAUTHORIZED,
message: 'Member can only view own mentions',
},
data.id,
);
}
}
export const MemberCannotAccessMention = createError(
'GICERR004',
'Member can only view own mentions',
StatusCodes.UNAUTHORIZED,
);

export const ChatMentionNotFound = createError(
'GICERR006',
Expand Down
Loading
Loading