From 66d7b69377ac4ec82fbc1f84cee3a1a00e4dae66 Mon Sep 17 00:00:00 2001 From: Johann150 Date: Sun, 23 Oct 2022 13:34:37 +0200 Subject: [PATCH 1/5] server: refactor API handler and returning errors This refactors the API handler to not use default exports, be async instead of constructing a promise and modify how errors are returned. --- .../backend/src/server/api/api-handler.ts | 61 +++++++++---------- packages/backend/src/server/api/index.ts | 2 +- 2 files changed, 30 insertions(+), 33 deletions(-) diff --git a/packages/backend/src/server/api/api-handler.ts b/packages/backend/src/server/api/api-handler.ts index 956096367..f389ab8da 100644 --- a/packages/backend/src/server/api/api-handler.ts +++ b/packages/backend/src/server/api/api-handler.ts @@ -5,59 +5,56 @@ import authenticate, { AuthenticationError } from './authenticate.js'; import call from './call.js'; import { ApiError } from './error.js'; -export default (endpoint: IEndpoint, ctx: Koa.Context) => new Promise((res) => { +export async function handler(endpoint: IEndpoint, ctx: Koa.Context): Promise { const body = ctx.is('multipart/form-data') ? (ctx.request as any).body : ctx.method === 'GET' ? ctx.query : ctx.request.body; - const reply = (x?: any, y?: ApiError) => { - if (x == null) { - ctx.status = 204; - } else if (typeof x === 'number' && y) { - ctx.status = x; - ctx.body = { - error: { - message: y!.message, - code: y!.code, - id: y!.id, - kind: y!.kind, - ...(y!.info ? { info: y!.info } : {}), - }, - }; - } else { - // 文字列を返す場合は、JSON.stringify通さないとJSONと認識されない - ctx.body = typeof x === 'string' ? JSON.stringify(x) : x; + const error = (e: ApiError): void => { + ctx.status = e.httpStatusCode ?? 500; + if (e.httpStatusCode === 401) { + ctx.response.set('WWW-Authenticate', 'Bearer'); } - res(); - }; + ctx.body = { + error: { + message: e!.message, + code: e!.code, + ...(e!.info ? { info: e!.info } : {}), + endpoint: endpoint.name, + }, + }; + } // Authentication // for GET requests, do not even pass on the body parameter as it is considered unsafe - authenticate(ctx.headers.authorization, ctx.method === 'GET' ? null : body['i']).then(([user, app]) => { + await authenticate(ctx.headers.authorization, ctx.method === 'GET' ? null : body['i']).then(async ([user, app]) => { // API invoking - call(endpoint.name, user, app, body, ctx).then((res: any) => { + await call(endpoint.name, user, app, body, ctx).then((res: any) => { if (ctx.method === 'GET' && endpoint.meta.cacheSec && !body['i'] && !user) { ctx.set('Cache-Control', `public, max-age=${endpoint.meta.cacheSec}`); } - reply(res); + if (res == null) { + ctx.status = 204; + } else { + ctx.status = 200; + // If a string is returned, it must be passed through JSON.stringify to be recognized as JSON. + ctx.body = typeof res === 'string' ? JSON.stringify(res) : res; + } }).catch((e: ApiError) => { - reply(e.httpStatusCode ? e.httpStatusCode : e.kind === 'client' ? 400 : 500, e); + error(e); }); }).catch(e => { if (e instanceof AuthenticationError) { - ctx.response.status = 403; - ctx.response.set('WWW-Authenticate', 'Bearer'); - ctx.response.body = { + error({ message: 'Authentication failed: ' + e.message, code: 'AUTHENTICATION_FAILED', id: 'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', - kind: 'client', - }; - res(); + httpStatusCode: 401, + }); } else { - reply(500, new ApiError()); + error(new ApiError()); } }); -}); +}; diff --git a/packages/backend/src/server/api/index.ts b/packages/backend/src/server/api/index.ts index 83ece51f5..3f5708022 100644 --- a/packages/backend/src/server/api/index.ts +++ b/packages/backend/src/server/api/index.ts @@ -11,7 +11,7 @@ import cors from '@koa/cors'; import { Instances, AccessTokens, Users } from '@/models/index.js'; import config from '@/config/index.js'; import endpoints from './endpoints.js'; -import handler from './api-handler.js'; +import { handler } from './api-handler.js'; import signup from './private/signup.js'; import signin from './private/signin.js'; import signupPending from './private/signup-pending.js'; From 934ee82b8f48d71b2d4f675f1bd2106dee6c5f38 Mon Sep 17 00:00:00 2001 From: Johann150 Date: Thu, 20 Oct 2022 23:04:24 +0200 Subject: [PATCH 2/5] server: refactor ApiError to store error descriptions centrally The UUIDs are no longer used for errors and all errors should now have a descriptive message attached to them. Also, all errors should now have the proper HTTP status code for a reply instead of the generic 400 and 500 response codes. Because the errors all have more specific error codes, the "kind" of client or server is also abolished. --- .../backend/src/server/api/api-handler.ts | 9 +- packages/backend/src/server/api/call.ts | 56 +-- .../backend/src/server/api/common/signup.ts | 30 +- packages/backend/src/server/api/define.ts | 14 +- .../endpoints/admin/announcements/delete.ts | 10 +- .../endpoints/admin/announcements/update.ts | 10 +- .../api/endpoints/admin/drive/show-file.ts | 12 +- .../server/api/endpoints/admin/emoji/add.ts | 10 +- .../server/api/endpoints/admin/emoji/copy.ts | 14 +- .../api/endpoints/admin/emoji/delete.ts | 10 +- .../api/endpoints/admin/emoji/update.ts | 10 +- .../server/api/endpoints/admin/relays/add.ts | 12 +- .../server/api/endpoints/antennas/create.ts | 22 +- .../server/api/endpoints/antennas/delete.ts | 12 +- .../server/api/endpoints/antennas/notes.ts | 12 +- .../src/server/api/endpoints/antennas/show.ts | 12 +- .../server/api/endpoints/antennas/update.ts | 32 +- .../src/server/api/endpoints/ap/get.ts | 3 - .../src/server/api/endpoints/ap/show.ts | 10 +- .../src/server/api/endpoints/app/show.ts | 18 +- .../src/server/api/endpoints/auth/accept.ts | 12 +- .../api/endpoints/auth/session/generate.ts | 10 +- .../server/api/endpoints/auth/session/show.ts | 12 +- .../api/endpoints/auth/session/userkey.ts | 32 +- .../server/api/endpoints/blocking/create.ts | 30 +- .../server/api/endpoints/blocking/delete.ts | 34 +- .../server/api/endpoints/channels/create.ts | 12 +- .../server/api/endpoints/channels/follow.ts | 12 +- .../src/server/api/endpoints/channels/show.ts | 12 +- .../server/api/endpoints/channels/timeline.ts | 12 +- .../server/api/endpoints/channels/unfollow.ts | 12 +- .../server/api/endpoints/channels/update.ts | 32 +- .../server/api/endpoints/clips/add-note.ts | 30 +- .../src/server/api/endpoints/clips/delete.ts | 12 +- .../src/server/api/endpoints/clips/notes.ts | 14 +- .../server/api/endpoints/clips/remove-note.ts | 31 +- .../src/server/api/endpoints/clips/show.ts | 14 +- .../src/server/api/endpoints/clips/update.ts | 12 +- .../endpoints/drive/files/attached-notes.ts | 12 +- .../api/endpoints/drive/files/create.ts | 12 +- .../api/endpoints/drive/files/delete.ts | 20 +- .../server/api/endpoints/drive/files/show.ts | 20 +- .../api/endpoints/drive/files/update.ts | 38 +- .../api/endpoints/drive/folders/create.ts | 12 +- .../api/endpoints/drive/folders/delete.ts | 20 +- .../api/endpoints/drive/folders/show.ts | 12 +- .../api/endpoints/drive/folders/update.ts | 32 +- .../server/api/endpoints/following/create.ts | 46 +-- .../server/api/endpoints/following/delete.ts | 30 +- .../api/endpoints/following/invalidate.ts | 30 +- .../endpoints/following/requests/accept.ts | 17 +- .../endpoints/following/requests/cancel.ts | 18 +- .../endpoints/following/requests/reject.ts | 10 +- .../api/endpoints/gallery/posts/create.ts | 4 - .../api/endpoints/gallery/posts/delete.ts | 12 +- .../api/endpoints/gallery/posts/like.ts | 22 +- .../api/endpoints/gallery/posts/show.ts | 12 +- .../api/endpoints/gallery/posts/unlike.ts | 22 +- .../api/endpoints/gallery/posts/update.ts | 4 - .../src/server/api/endpoints/hashtags/show.ts | 12 +- .../server/api/endpoints/i/import-blocking.ts | 33 +- .../api/endpoints/i/import-following.ts | 33 +- .../server/api/endpoints/i/import-muting.ts | 33 +- .../api/endpoints/i/import-user-lists.ts | 33 +- .../backend/src/server/api/endpoints/i/pin.ts | 26 +- .../api/endpoints/i/read-announcement.ts | 16 +- .../api/endpoints/i/registry/get-detail.ts | 12 +- .../server/api/endpoints/i/registry/get.ts | 12 +- .../server/api/endpoints/i/registry/remove.ts | 12 +- .../src/server/api/endpoints/i/unpin.ts | 10 +- .../server/api/endpoints/i/update-email.ts | 24 +- .../src/server/api/endpoints/i/update.ts | 52 +-- .../server/api/endpoints/i/webhooks/delete.ts | 12 +- .../server/api/endpoints/i/webhooks/show.ts | 12 +- .../server/api/endpoints/i/webhooks/update.ts | 13 +- .../api/endpoints/messaging/messages.ts | 30 +- .../endpoints/messaging/messages/create.ts | 64 +-- .../endpoints/messaging/messages/delete.ts | 12 +- .../api/endpoints/messaging/messages/read.ts | 16 +- .../src/server/api/endpoints/mute/create.ts | 30 +- .../src/server/api/endpoints/mute/delete.ts | 30 +- .../src/server/api/endpoints/notes/clips.ts | 10 +- .../api/endpoints/notes/conversation.ts | 10 +- .../src/server/api/endpoints/notes/create.ts | 80 +--- .../src/server/api/endpoints/notes/delete.ts | 18 +- .../api/endpoints/notes/favorites/create.ts | 20 +- .../api/endpoints/notes/favorites/delete.ts | 20 +- .../api/endpoints/notes/global-timeline.ts | 10 +- .../api/endpoints/notes/hybrid-timeline.ts | 10 +- .../api/endpoints/notes/local-timeline.ts | 10 +- .../server/api/endpoints/notes/polls/vote.ts | 56 +-- .../server/api/endpoints/notes/reactions.ts | 10 +- .../api/endpoints/notes/reactions/create.ts | 26 +- .../api/endpoints/notes/reactions/delete.ts | 18 +- .../src/server/api/endpoints/notes/renotes.ts | 10 +- .../src/server/api/endpoints/notes/search.ts | 3 - .../src/server/api/endpoints/notes/show.ts | 12 +- .../endpoints/notes/thread-muting/create.ts | 10 +- .../endpoints/notes/thread-muting/delete.ts | 10 +- .../server/api/endpoints/notes/translate.ts | 10 +- .../server/api/endpoints/notes/unrenote.ts | 10 +- .../api/endpoints/notes/user-list-timeline.ts | 12 +- .../api/endpoints/notes/watching/create.ts | 10 +- .../api/endpoints/notes/watching/delete.ts | 10 +- .../api/endpoints/notifications/create.ts | 3 - .../api/endpoints/notifications/read.ts | 9 +- .../src/server/api/endpoints/page-push.ts | 12 +- .../src/server/api/endpoints/pages/create.ts | 19 +- .../src/server/api/endpoints/pages/delete.ts | 26 +- .../src/server/api/endpoints/pages/like.ts | 22 +- .../src/server/api/endpoints/pages/show.ts | 12 +- .../src/server/api/endpoints/pages/unlike.ts | 22 +- .../src/server/api/endpoints/pages/update.ts | 45 +-- .../api/endpoints/renote-mute/create.ts | 30 +- .../api/endpoints/renote-mute/delete.ts | 30 +- .../src/server/api/endpoints/reset-db.ts | 4 - .../server/api/endpoints/reset-password.ts | 12 +- .../server/api/endpoints/users/followers.ts | 24 +- .../server/api/endpoints/users/following.ts | 24 +- .../api/endpoints/users/groups/delete.ts | 12 +- .../users/groups/invitations/accept.ts | 17 +- .../users/groups/invitations/reject.ts | 17 +- .../api/endpoints/users/groups/invite.ts | 40 +- .../api/endpoints/users/groups/leave.ts | 22 +- .../server/api/endpoints/users/groups/pull.ts | 30 +- .../server/api/endpoints/users/groups/show.ts | 14 +- .../api/endpoints/users/groups/transfer.ts | 30 +- .../api/endpoints/users/groups/update.ts | 12 +- .../api/endpoints/users/lists/delete.ts | 12 +- .../server/api/endpoints/users/lists/pull.ts | 20 +- .../server/api/endpoints/users/lists/push.ts | 40 +- .../server/api/endpoints/users/lists/show.ts | 12 +- .../api/endpoints/users/lists/update.ts | 12 +- .../src/server/api/endpoints/users/notes.ts | 10 +- .../server/api/endpoints/users/reactions.ts | 10 +- .../api/endpoints/users/report-abuse.ts | 30 +- .../src/server/api/endpoints/users/show.ts | 19 +- .../src/server/api/endpoints/users/stats.ts | 10 +- packages/backend/src/server/api/error.ts | 366 +++++++++++++++++- 139 files changed, 768 insertions(+), 2241 deletions(-) diff --git a/packages/backend/src/server/api/api-handler.ts b/packages/backend/src/server/api/api-handler.ts index f389ab8da..e21585158 100644 --- a/packages/backend/src/server/api/api-handler.ts +++ b/packages/backend/src/server/api/api-handler.ts @@ -13,7 +13,7 @@ export async function handler(endpoint: IEndpoint, ctx: Koa.Context): Promise { - ctx.status = e.httpStatusCode ?? 500; + ctx.status = e.httpStatusCode; if (e.httpStatusCode === 401) { ctx.response.set('WWW-Authenticate', 'Bearer'); } @@ -47,12 +47,7 @@ export async function handler(endpoint: IEndpoint, ctx: Koa.Context): Promise { if (e instanceof AuthenticationError) { - error({ - message: 'Authentication failed: ' + e.message, - code: 'AUTHENTICATION_FAILED', - id: 'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', - httpStatusCode: 401, - }); + error(new ApiError('AUTHENTICATION_FAILED', e.message)); } else { error(new ApiError()); } diff --git a/packages/backend/src/server/api/call.ts b/packages/backend/src/server/api/call.ts index fe1698dbc..0bdbfe633 100644 --- a/packages/backend/src/server/api/call.ts +++ b/packages/backend/src/server/api/call.ts @@ -8,29 +8,16 @@ import endpoints, { IEndpointMeta } from './endpoints.js'; import { ApiError } from './error.js'; import { apiLogger } from './logger.js'; -const accessDenied = { - message: 'Access denied.', - code: 'ACCESS_DENIED', - id: '56f35758-7dd5-468b-8439-5d6fb8ec9b8e', -}; - export default async (endpoint: string, user: CacheableLocalUser | null | undefined, token: AccessToken | null | undefined, data: any, ctx?: Koa.Context) => { const isSecure = user != null && token == null; const isModerator = user != null && (user.isModerator || user.isAdmin); const ep = endpoints.find(e => e.name === endpoint); - if (ep == null) { - throw new ApiError({ - message: 'No such endpoint.', - code: 'NO_SUCH_ENDPOINT', - id: 'f8080b67-5f9c-4eb7-8c18-7f1eeae8f709', - httpStatusCode: 404, - }); - } + if (ep == null) throw new ApiError('NO_SUCH_ENDPOINT'); if (ep.meta.secure && !isSecure) { - throw new ApiError(accessDenied); + throw new ApiError('ACCESS_DENIED', 'This operation can only be performed with a native token.'); } if (ep.meta.limit && !isModerator) { @@ -50,47 +37,28 @@ export default async (endpoint: string, user: CacheableLocalUser | null | undefi // Rate limit await limiter(limit as IEndpointMeta['limit'] & { key: NonNullable }, limitActor).catch(e => { - throw new ApiError({ - message: 'Rate limit exceeded. Please try again later.', - code: 'RATE_LIMIT_EXCEEDED', - id: 'd5826d14-3982-4d2e-8011-b9e9f02499ef', - httpStatusCode: 429, - }); + throw new ApiError('RATE_LIMIT_EXCEEDED'); }); } if (ep.meta.requireCredential && user == null) { - throw new ApiError({ - message: 'Credential required.', - code: 'CREDENTIAL_REQUIRED', - id: '1384574d-a912-4b81-8601-c7b1c4085df1', - httpStatusCode: 401, - }); + throw new ApiError('AUTHENTICATION_REQUIRED'); } if (ep.meta.requireCredential && user!.isSuspended) { - throw new ApiError({ - message: 'Your account has been suspended.', - code: 'YOUR_ACCOUNT_SUSPENDED', - id: 'a8c724b3-6e9c-4b46-b1a8-bc3ed6258370', - httpStatusCode: 403, - }); + throw new ApiError('SUSPENDED'); } if (ep.meta.requireAdmin && !user!.isAdmin) { - throw new ApiError(accessDenied, { reason: 'You are not the admin.' }); + throw new ApiError('ACCESS_DENIED', 'This operation requires administrator privileges.'); } if (ep.meta.requireModerator && !isModerator) { - throw new ApiError(accessDenied, { reason: 'You are not a moderator.' }); + throw new ApiError('ACCESS_DENIED', 'This operation requires moderator privileges.'); } if (token && ep.meta.kind && !token.permission.some(p => p === ep.meta.kind)) { - throw new ApiError({ - message: 'Your app does not have the necessary permissions to use this endpoint.', - code: 'PERMISSION_DENIED', - id: '1370e5b7-d4eb-4566-bb1d-7748ee6a1838', - }); + throw new ApiError('ACCESS_DENIED', 'This operation requires privileges which this token does not grant.'); } // Cast non JSON input @@ -101,11 +69,7 @@ export default async (endpoint: string, user: CacheableLocalUser | null | undefi try { data[k] = JSON.parse(data[k]); } catch (e) { - throw new ApiError({ - message: 'Invalid param.', - code: 'INVALID_PARAM', - id: '0b5f1631-7c1a-41a6-b399-cce335f34d85', - }, { + throw new ApiError('INVALID_PARAM', { param: k, reason: `cannot cast to ${param.type}`, }); @@ -129,7 +93,7 @@ export default async (endpoint: string, user: CacheableLocalUser | null | undefi stack: e.stack, }, }); - throw new ApiError(null, { + throw new ApiError('INTERNAL_ERROR', { e: { message: e.message, code: e.name, diff --git a/packages/backend/src/server/api/common/signup.ts b/packages/backend/src/server/api/common/signup.ts index 3ac4ac0ba..150d27218 100644 --- a/packages/backend/src/server/api/common/signup.ts +++ b/packages/backend/src/server/api/common/signup.ts @@ -24,25 +24,13 @@ export async function signup(opts: { // Validate username if (!Users.validateLocalUsername(username)) { - throw new ApiError({ - message: 'This username is invalid.', - code: 'INVALID_USERNAME', - id: 'ece89f3c-d845-4d9a-850b-1735285e8cd4', - kind: 'client', - httpStatusCode: 400, - }); + throw new ApiError('INVALID_USERNAME'); } if (password != null && passwordHash == null) { // Validate password if (!Users.validatePassword(password)) { - throw new ApiError({ - message: 'This password is invalid.', - code: 'INVALID_PASSWORD', - id: 'a941905b-fe7b-43e2-8ecd-50ad3a2287ab', - kind: 'client', - httpStatusCode: 400, - }); + throw new ApiError('INVALID_PASSWORD'); } // Generate hash of password @@ -53,22 +41,14 @@ export async function signup(opts: { // Generate secret const secret = generateUserToken(); - const duplicateUsernameError = { - message: 'This username is not available.', - code: 'USED_USERNAME', - id: '7ddd595e-6860-4593-93c5-9fdbcb80cd81', - kind: 'client', - httpStatusCode: 409, - }; - // Check username duplication if (await Users.findOneBy({ usernameLower: username.toLowerCase(), host: IsNull() })) { - throw new ApiError(duplicateUsernameError); + throw new ApiError('USED_USERNAME'); } // Check deleted username duplication if (await UsedUsernames.findOneBy({ username: username.toLowerCase() })) { - throw new ApiError(duplicateUsernameError); + throw new ApiError('USED_USERNAME'); } const keyPair = await new Promise((res, rej) => @@ -97,7 +77,7 @@ export async function signup(opts: { host: IsNull(), }); - if (exist) throw new ApiError(duplicateUsernameError); + if (exist) throw new ApiError('USED_USERNAME'); account = await transactionalEntityManager.save(new User({ id: genId(), diff --git a/packages/backend/src/server/api/define.ts b/packages/backend/src/server/api/define.ts index 6000357bd..840283957 100644 --- a/packages/backend/src/server/api/define.ts +++ b/packages/backend/src/server/api/define.ts @@ -28,22 +28,16 @@ export default function (meta: T, pa fs.unlink(file.path, () => {}); } - if (meta.requireFile && file == null) return Promise.reject(new ApiError({ - message: 'File required.', - code: 'FILE_REQUIRED', - id: '4267801e-70d1-416a-b011-4ee502885d8b', - })); + if (meta.requireFile && file == null) { + return Promise.reject(new ApiError('FILE_REQUIRED')); + } const valid = validate(params); if (!valid) { if (file) cleanup(); const errors = validate.errors!; - const err = new ApiError({ - message: 'Invalid param.', - code: 'INVALID_PARAM', - id: '3d81ceae-475f-4600-b2a8-2bc116157532', - }, { + const err = new ApiError('INVALID_PARAM', { param: errors[0].schemaPath, reason: errors[0].message, }); diff --git a/packages/backend/src/server/api/endpoints/admin/announcements/delete.ts b/packages/backend/src/server/api/endpoints/admin/announcements/delete.ts index 0debf2579..656d4c553 100644 --- a/packages/backend/src/server/api/endpoints/admin/announcements/delete.ts +++ b/packages/backend/src/server/api/endpoints/admin/announcements/delete.ts @@ -8,13 +8,7 @@ export const meta = { requireCredential: true, requireModerator: true, - errors: { - noSuchAnnouncement: { - message: 'No such announcement.', - code: 'NO_SUCH_ANNOUNCEMENT', - id: 'ecad8040-a276-4e85-bda9-015a708d291e', - }, - }, + errors: ['NO_SUCH_ANNOUNCEMENT'], } as const; export const paramDef = { @@ -29,7 +23,7 @@ export const paramDef = { export default define(meta, paramDef, async (ps, me) => { const announcement = await Announcements.findOneBy({ id: ps.id }); - if (announcement == null) throw new ApiError(meta.errors.noSuchAnnouncement); + if (announcement == null) throw new ApiError('NO_SUCH_ANNOUNCEMENT'); await Announcements.delete(announcement.id); }); diff --git a/packages/backend/src/server/api/endpoints/admin/announcements/update.ts b/packages/backend/src/server/api/endpoints/admin/announcements/update.ts index af1fa4568..6cc94ce3b 100644 --- a/packages/backend/src/server/api/endpoints/admin/announcements/update.ts +++ b/packages/backend/src/server/api/endpoints/admin/announcements/update.ts @@ -8,13 +8,7 @@ export const meta = { requireCredential: true, requireModerator: true, - errors: { - noSuchAnnouncement: { - message: 'No such announcement.', - code: 'NO_SUCH_ANNOUNCEMENT', - id: 'd3aae5a7-6372-4cb4-b61c-f511ffc2d7cc', - }, - }, + errors: ['NO_SUCH_ANNOUNCEMENT'], } as const; export const paramDef = { @@ -32,7 +26,7 @@ export const paramDef = { export default define(meta, paramDef, async (ps, me) => { const announcement = await Announcements.findOneBy({ id: ps.id }); - if (announcement == null) throw new ApiError(meta.errors.noSuchAnnouncement); + if (announcement == null) throw new ApiError('NO_SUCH_ANNOUNCEMENT'); await Announcements.update(announcement.id, { updatedAt: new Date(), diff --git a/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts b/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts index ebe378c4f..9f36e6f30 100644 --- a/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts +++ b/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts @@ -8,13 +8,7 @@ export const meta = { requireCredential: true, requireModerator: true, - errors: { - noSuchFile: { - message: 'No such file.', - code: 'NO_SUCH_FILE', - id: 'caf3ca38-c6e5-472e-a30c-b05377dcc240', - }, - }, + errors: ['NO_SUCH_FILE'], res: { type: 'object', @@ -180,9 +174,7 @@ export default define(meta, paramDef, async (ps, me) => { }], }); - if (file == null) { - throw new ApiError(meta.errors.noSuchFile); - } + if (file == null) throw new ApiError('NO_SUCH_FILE'); return file; }); diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/add.ts b/packages/backend/src/server/api/endpoints/admin/emoji/add.ts index 2f612fa7c..ad5b9896c 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/add.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/add.ts @@ -13,13 +13,7 @@ export const meta = { requireCredential: true, requireModerator: true, - errors: { - noSuchFile: { - message: 'No such file.', - code: 'NO_SUCH_FILE', - id: 'fc46b5a4-6b92-4c33-ac66-b806659bb5cf', - }, - }, + errors: ['NO_SUCH_FILE'], } as const; export const paramDef = { @@ -34,7 +28,7 @@ export const paramDef = { export default define(meta, paramDef, async (ps, me) => { const file = await DriveFiles.findOneBy({ id: ps.fileId }); - if (file == null) throw new ApiError(meta.errors.noSuchFile); + if (file == null) throw new ApiError('NO_SUCH_FILE'); const name = file.name.split('.')[0].match(/^[a-z0-9_]+$/) ? file.name.split('.')[0] : `_${rndstr('a-z0-9', 8)}_`; diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts b/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts index e5bbaefe9..a13a47376 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts @@ -13,13 +13,7 @@ export const meta = { requireCredential: true, requireModerator: true, - errors: { - noSuchEmoji: { - message: 'No such emoji.', - code: 'NO_SUCH_EMOJI', - id: 'e2785b66-dca3-4087-9cac-b93c541cc425', - }, - }, + errors: ['NO_SUCH_EMOJI', 'INTERNAL_ERROR'], res: { type: 'object', @@ -46,9 +40,7 @@ export const paramDef = { export default define(meta, paramDef, async (ps, me) => { const emoji = await Emojis.findOneBy({ id: ps.emojiId }); - if (emoji == null) { - throw new ApiError(meta.errors.noSuchEmoji); - } + if (emoji == null) throw new ApiError('NO_SUCH_EMOJI'); let driveFile: DriveFile; @@ -56,7 +48,7 @@ export default define(meta, paramDef, async (ps, me) => { // Create file driveFile = await uploadFromUrl({ url: emoji.originalUrl, user: null, force: true }); } catch (e) { - throw new ApiError(); + throw new ApiError('INTERNAL_ERROR', e); } const copied = await Emojis.insert({ diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/delete.ts b/packages/backend/src/server/api/endpoints/admin/emoji/delete.ts index 3cb1402e4..ab80e81bb 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/delete.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/delete.ts @@ -10,13 +10,7 @@ export const meta = { requireCredential: true, requireModerator: true, - errors: { - noSuchEmoji: { - message: 'No such emoji.', - code: 'NO_SUCH_EMOJI', - id: 'be83669b-773a-44b7-b1f8-e5e5170ac3c2', - }, - }, + errors: ['NO_SUCH_EMOJI'], } as const; export const paramDef = { @@ -31,7 +25,7 @@ export const paramDef = { export default define(meta, paramDef, async (ps, me) => { const emoji = await Emojis.findOneBy({ id: ps.id }); - if (emoji == null) throw new ApiError(meta.errors.noSuchEmoji); + if (emoji == null) throw new ApiError('NO_SUCH_EMOJI'); await Emojis.delete(emoji.id); diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/update.ts b/packages/backend/src/server/api/endpoints/admin/emoji/update.ts index 70820e8df..e451374d5 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/update.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/update.ts @@ -9,13 +9,7 @@ export const meta = { requireCredential: true, requireModerator: true, - errors: { - noSuchEmoji: { - message: 'No such emoji.', - code: 'NO_SUCH_EMOJI', - id: '684dec9d-a8c2-4364-9aa8-456c49cb1dc8', - }, - }, + errors: ['NO_SUCH_EMOJI'], } as const; export const paramDef = { @@ -39,7 +33,7 @@ export const paramDef = { export default define(meta, paramDef, async (ps) => { const emoji = await Emojis.findOneBy({ id: ps.id }); - if (emoji == null) throw new ApiError(meta.errors.noSuchEmoji); + if (emoji == null) throw new ApiError('NO_SUCH_EMOJI'); await Emojis.update(emoji.id, { updatedAt: new Date(), diff --git a/packages/backend/src/server/api/endpoints/admin/relays/add.ts b/packages/backend/src/server/api/endpoints/admin/relays/add.ts index 94f757bdc..147b7298c 100644 --- a/packages/backend/src/server/api/endpoints/admin/relays/add.ts +++ b/packages/backend/src/server/api/endpoints/admin/relays/add.ts @@ -9,13 +9,7 @@ export const meta = { requireCredential: true, requireModerator: true, - errors: { - invalidUrl: { - message: 'Invalid URL', - code: 'INVALID_URL', - id: 'fb8c92d3-d4e5-44e7-b3d4-800d5cef8b2c', - }, - }, + errors: ['INVALID_URL'], res: { type: 'object', @@ -58,8 +52,8 @@ export const paramDef = { export default define(meta, paramDef, async (ps, user) => { try { if (new URL(ps.inbox).protocol !== 'https:') throw new Error('https only'); - } catch { - throw new ApiError(meta.errors.invalidUrl); + } catch (e) { + throw new ApiError('INVALID_URL', e); } return await addRelay(ps.inbox); diff --git a/packages/backend/src/server/api/endpoints/antennas/create.ts b/packages/backend/src/server/api/endpoints/antennas/create.ts index dca31edb1..5fae03808 100644 --- a/packages/backend/src/server/api/endpoints/antennas/create.ts +++ b/packages/backend/src/server/api/endpoints/antennas/create.ts @@ -11,19 +11,7 @@ export const meta = { kind: 'write:account', - errors: { - noSuchUserList: { - message: 'No such user list.', - code: 'NO_SUCH_USER_LIST', - id: '95063e93-a283-4b8b-9aa5-bcdb8df69a7f', - }, - - noSuchUserGroup: { - message: 'No such user group.', - code: 'NO_SUCH_USER_GROUP', - id: 'aa3c0b9a-8cae-47c0-92ac-202ce5906682', - }, - }, + errors: ['NO_SUCH_USER_LIST', 'NO_SUCH_GROUP'], res: { type: 'object', @@ -71,18 +59,14 @@ export default define(meta, paramDef, async (ps, user) => { userId: user.id, }); - if (userList == null) { - throw new ApiError(meta.errors.noSuchUserList); - } + if (userList == null) throw new ApiError('NO_SUCH_USER_LIST'); } else if (ps.src === 'group' && ps.userGroupId) { userGroupJoining = await UserGroupJoinings.findOneBy({ userGroupId: ps.userGroupId, userId: user.id, }); - if (userGroupJoining == null) { - throw new ApiError(meta.errors.noSuchUserGroup); - } + if (userGroupJoining == null) throw new ApiError('NO_SUCH_GROUP'); } const antenna = await Antennas.insert({ diff --git a/packages/backend/src/server/api/endpoints/antennas/delete.ts b/packages/backend/src/server/api/endpoints/antennas/delete.ts index d87f9ba00..c3ad26dda 100644 --- a/packages/backend/src/server/api/endpoints/antennas/delete.ts +++ b/packages/backend/src/server/api/endpoints/antennas/delete.ts @@ -10,13 +10,7 @@ export const meta = { kind: 'write:account', - errors: { - noSuchAntenna: { - message: 'No such antenna.', - code: 'NO_SUCH_ANTENNA', - id: 'b34dcf9d-348f-44bb-99d0-6c9314cfe2df', - }, - }, + errors: ['NO_SUCH_ANTENNA'], } as const; export const paramDef = { @@ -34,9 +28,7 @@ export default define(meta, paramDef, async (ps, user) => { userId: user.id, }); - if (antenna == null) { - throw new ApiError(meta.errors.noSuchAntenna); - } + if (antenna == null) throw new ApiError('NO_SUCH_ANTENNA'); await Antennas.delete(antenna.id); diff --git a/packages/backend/src/server/api/endpoints/antennas/notes.ts b/packages/backend/src/server/api/endpoints/antennas/notes.ts index 0231fcfd6..4dbc824a8 100644 --- a/packages/backend/src/server/api/endpoints/antennas/notes.ts +++ b/packages/backend/src/server/api/endpoints/antennas/notes.ts @@ -14,13 +14,7 @@ export const meta = { kind: 'read:account', - errors: { - noSuchAntenna: { - message: 'No such antenna.', - code: 'NO_SUCH_ANTENNA', - id: '850926e0-fd3b-49b6-b69a-b28a5dbd82fe', - }, - }, + errors: ['NO_SUCH_ANTENNA'], res: { type: 'array', @@ -53,9 +47,7 @@ export default define(meta, paramDef, async (ps, user) => { userId: user.id, }); - if (antenna == null) { - throw new ApiError(meta.errors.noSuchAntenna); - } + if (antenna == null) throw new ApiError('NO_SUCH_ANTENNA'); const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate) diff --git a/packages/backend/src/server/api/endpoints/antennas/show.ts b/packages/backend/src/server/api/endpoints/antennas/show.ts index 11e6e95c9..76278cd2c 100644 --- a/packages/backend/src/server/api/endpoints/antennas/show.ts +++ b/packages/backend/src/server/api/endpoints/antennas/show.ts @@ -9,13 +9,7 @@ export const meta = { kind: 'read:account', - errors: { - noSuchAntenna: { - message: 'No such antenna.', - code: 'NO_SUCH_ANTENNA', - id: 'c06569fb-b025-4f23-b22d-1fcd20d2816b', - }, - }, + errors: ['NO_SUCH_ANTENNA'], res: { type: 'object', @@ -40,9 +34,7 @@ export default define(meta, paramDef, async (ps, me) => { userId: me.id, }); - if (antenna == null) { - throw new ApiError(meta.errors.noSuchAntenna); - } + if (antenna == null) throw new ApiError('NO_SUCH_ANTENNA'); return await Antennas.pack(antenna); }); diff --git a/packages/backend/src/server/api/endpoints/antennas/update.ts b/packages/backend/src/server/api/endpoints/antennas/update.ts index e36696486..1bdafec4c 100644 --- a/packages/backend/src/server/api/endpoints/antennas/update.ts +++ b/packages/backend/src/server/api/endpoints/antennas/update.ts @@ -10,25 +10,7 @@ export const meta = { kind: 'write:account', - errors: { - noSuchAntenna: { - message: 'No such antenna.', - code: 'NO_SUCH_ANTENNA', - id: '10c673ac-8852-48eb-aa1f-f5b67f069290', - }, - - noSuchUserList: { - message: 'No such user list.', - code: 'NO_SUCH_USER_LIST', - id: '1c6b35c9-943e-48c2-81e4-2844989407f7', - }, - - noSuchUserGroup: { - message: 'No such user group.', - code: 'NO_SUCH_USER_GROUP', - id: '109ed789-b6eb-456e-b8a9-6059d567d385', - }, - }, + errors: ['NO_SUCH_ANTENNA', 'NO_SUCH_USER_LIST', 'NO_SUCH_GROUP'], res: { type: 'object', @@ -74,9 +56,7 @@ export default define(meta, paramDef, async (ps, user) => { userId: user.id, }); - if (antenna == null) { - throw new ApiError(meta.errors.noSuchAntenna); - } + if (antenna == null) throw new ApiError('NO_SUCH_ANTENNA'); let userList; let userGroupJoining; @@ -87,18 +67,14 @@ export default define(meta, paramDef, async (ps, user) => { userId: user.id, }); - if (userList == null) { - throw new ApiError(meta.errors.noSuchUserList); - } + if (userList == null) throw new ApiError('NO_SUCH_USER_LIST'); } else if (ps.src === 'group' && ps.userGroupId) { userGroupJoining = await UserGroupJoinings.findOneBy({ userGroupId: ps.userGroupId, userId: user.id, }); - if (userGroupJoining == null) { - throw new ApiError(meta.errors.noSuchUserGroup); - } + if (userGroupJoining == null) throw new ApiError('NO_SUCH_GROUP'); } await Antennas.update(antenna.id, { diff --git a/packages/backend/src/server/api/endpoints/ap/get.ts b/packages/backend/src/server/api/endpoints/ap/get.ts index 6e7804953..d20c36e7c 100644 --- a/packages/backend/src/server/api/endpoints/ap/get.ts +++ b/packages/backend/src/server/api/endpoints/ap/get.ts @@ -12,9 +12,6 @@ export const meta = { max: 30, }, - errors: { - }, - res: { type: 'object', optional: false, nullable: false, diff --git a/packages/backend/src/server/api/endpoints/ap/show.ts b/packages/backend/src/server/api/endpoints/ap/show.ts index cbebf0044..a1b18cab1 100644 --- a/packages/backend/src/server/api/endpoints/ap/show.ts +++ b/packages/backend/src/server/api/endpoints/ap/show.ts @@ -24,13 +24,7 @@ export const meta = { max: 30, }, - errors: { - noSuchObject: { - message: 'No such object.', - code: 'NO_SUCH_OBJECT', - id: 'dc94d745-1262-4e63-a17d-fecaa57efc82', - }, - }, + errors: ['NO_SUCH_OBJECT'], res: { optional: false, nullable: false, @@ -83,7 +77,7 @@ export default define(meta, paramDef, async (ps, me) => { if (object) { return object; } else { - throw new ApiError(meta.errors.noSuchObject); + throw new ApiError('NO_SUCH_OBJECT'); } }); diff --git a/packages/backend/src/server/api/endpoints/app/show.ts b/packages/backend/src/server/api/endpoints/app/show.ts index 3b84fa07b..048848437 100644 --- a/packages/backend/src/server/api/endpoints/app/show.ts +++ b/packages/backend/src/server/api/endpoints/app/show.ts @@ -5,13 +5,7 @@ import { ApiError } from '../../error.js'; export const meta = { tags: ['app'], - errors: { - noSuchApp: { - message: 'No such app.', - code: 'NO_SUCH_APP', - id: 'dce83913-2dc6-4093-8a7b-71dbb11718a3', - }, - }, + errors: ['NO_SUCH_APP'], res: { type: 'object', @@ -33,14 +27,12 @@ export default define(meta, paramDef, async (ps, user, token) => { const isSecure = user != null && token == null; // Lookup app - const ap = await Apps.findOneBy({ id: ps.appId }); + const app = await Apps.findOneBy({ id: ps.appId }); - if (ap == null) { - throw new ApiError(meta.errors.noSuchApp); - } + if (app == null) throw new ApiError('NO_SUCH_APP'); - return await Apps.pack(ap, user, { + return await Apps.pack(app, user, { detail: true, - includeSecret: isSecure && (ap.userId === user!.id), + includeSecret: isSecure && (app.userId === user!.id), }); }); diff --git a/packages/backend/src/server/api/endpoints/auth/accept.ts b/packages/backend/src/server/api/endpoints/auth/accept.ts index dac74afcc..691b4a867 100644 --- a/packages/backend/src/server/api/endpoints/auth/accept.ts +++ b/packages/backend/src/server/api/endpoints/auth/accept.ts @@ -12,13 +12,7 @@ export const meta = { secure: true, - errors: { - noSuchSession: { - message: 'No such session.', - code: 'NO_SUCH_SESSION', - id: '9c72d8de-391a-43c1-9d06-08d29efde8df', - }, - }, + errors: ['NO_SUCH_SESSION'], } as const; export const paramDef = { @@ -35,9 +29,7 @@ export default define(meta, paramDef, async (ps, user) => { const session = await AuthSessions .findOneBy({ token: ps.token }); - if (session == null) { - throw new ApiError(meta.errors.noSuchSession); - } + if (session == null) throw new ApiError('NO_SUCH_SESSION'); // Generate access token const accessToken = secureRndstr(32, true); diff --git a/packages/backend/src/server/api/endpoints/auth/session/generate.ts b/packages/backend/src/server/api/endpoints/auth/session/generate.ts index f40d70c2b..eeb51abc6 100644 --- a/packages/backend/src/server/api/endpoints/auth/session/generate.ts +++ b/packages/backend/src/server/api/endpoints/auth/session/generate.ts @@ -26,13 +26,7 @@ export const meta = { }, }, - errors: { - noSuchApp: { - message: 'No such app.', - code: 'NO_SUCH_APP', - id: '92f93e63-428e-4f2f-a5a4-39e1407fe998', - }, - }, + errors: ['NO_SUCH_APP'], } as const; export const paramDef = { @@ -51,7 +45,7 @@ export default define(meta, paramDef, async (ps) => { }); if (app == null) { - throw new ApiError(meta.errors.noSuchApp); + throw new ApiError('NO_SUCH_APP'); } // Generate token diff --git a/packages/backend/src/server/api/endpoints/auth/session/show.ts b/packages/backend/src/server/api/endpoints/auth/session/show.ts index 91ff9c12e..cd30bfcca 100644 --- a/packages/backend/src/server/api/endpoints/auth/session/show.ts +++ b/packages/backend/src/server/api/endpoints/auth/session/show.ts @@ -7,13 +7,7 @@ export const meta = { requireCredential: false, - errors: { - noSuchSession: { - message: 'No such session.', - code: 'NO_SUCH_SESSION', - id: 'bd72c97d-eba7-4adb-a467-f171b8847250', - }, - }, + errors: ['NO_SUCH_SESSION'], res: { type: 'object', @@ -52,9 +46,7 @@ export default define(meta, paramDef, async (ps, user) => { token: ps.token, }); - if (session == null) { - throw new ApiError(meta.errors.noSuchSession); - } + if (session == null) throw new ApiError('NO_SUCH_SESSION'); return await AuthSessions.pack(session, user); }); diff --git a/packages/backend/src/server/api/endpoints/auth/session/userkey.ts b/packages/backend/src/server/api/endpoints/auth/session/userkey.ts index 36c915ea4..3a741db44 100644 --- a/packages/backend/src/server/api/endpoints/auth/session/userkey.ts +++ b/packages/backend/src/server/api/endpoints/auth/session/userkey.ts @@ -24,25 +24,7 @@ export const meta = { }, }, - errors: { - noSuchApp: { - message: 'No such app.', - code: 'NO_SUCH_APP', - id: 'fcab192a-2c5a-43b7-8ad8-9b7054d8d40d', - }, - - noSuchSession: { - message: 'No such session.', - code: 'NO_SUCH_SESSION', - id: '5b5a1503-8bc8-4bd0-8054-dc189e8cdcb3', - }, - - pendingSession: { - message: 'This session is not completed yet.', - code: 'PENDING_SESSION', - id: '8c8a4145-02cc-4cca-8e66-29ba60445a8e', - }, - }, + errors: ['NO_SUCH_APP', 'NO_SUCH_SESSION', 'PENDING_SESSION'], } as const; export const paramDef = { @@ -61,9 +43,7 @@ export default define(meta, paramDef, async (ps) => { secret: ps.appSecret, }); - if (app == null) { - throw new ApiError(meta.errors.noSuchApp); - } + if (app == null) throw new ApiError('NO_SUCH_APP'); // Fetch token const session = await AuthSessions.findOneBy({ @@ -71,13 +51,9 @@ export default define(meta, paramDef, async (ps) => { appId: app.id, }); - if (session == null) { - throw new ApiError(meta.errors.noSuchSession); - } + if (session == null) throw new ApiError('NO_SUCH_SESSION'); - if (session.userId == null) { - throw new ApiError(meta.errors.pendingSession); - } + if (session.userId == null) throw new ApiError('PENDING_SESSION'); // Lookup access token const accessToken = await AccessTokens.findOneByOrFail({ diff --git a/packages/backend/src/server/api/endpoints/blocking/create.ts b/packages/backend/src/server/api/endpoints/blocking/create.ts index 14d6e121d..7f45ad522 100644 --- a/packages/backend/src/server/api/endpoints/blocking/create.ts +++ b/packages/backend/src/server/api/endpoints/blocking/create.ts @@ -17,25 +17,7 @@ export const meta = { kind: 'write:blocks', - errors: { - noSuchUser: { - message: 'No such user.', - code: 'NO_SUCH_USER', - id: '7cc4f851-e2f1-4621-9633-ec9e1d00c01e', - }, - - blockeeIsYourself: { - message: 'Blockee is yourself.', - code: 'BLOCKEE_IS_YOURSELF', - id: '88b19138-f28d-42c0-8499-6a31bbd0fdc6', - }, - - alreadyBlocking: { - message: 'You are already blocking that user.', - code: 'ALREADY_BLOCKING', - id: '787fed64-acb9-464a-82eb-afbd745b9614', - }, - }, + errors: ['NO_SUCH_USER', 'BLOCKEE_IS_YOURSELF', 'ALREADY_BLOCKING'], res: { type: 'object', @@ -57,13 +39,11 @@ export default define(meta, paramDef, async (ps, user) => { const blocker = await Users.findOneByOrFail({ id: user.id }); // 自分自身 - if (user.id === ps.userId) { - throw new ApiError(meta.errors.blockeeIsYourself); - } + if (user.id === ps.userId) throw new ApiError('BLOCKEE_IS_YOURSELF'); // Get blockee const blockee = await getUser(ps.userId).catch(e => { - if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser); + if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError('NO_SUCH_USER'); throw e; }); @@ -73,9 +53,7 @@ export default define(meta, paramDef, async (ps, user) => { blockeeId: blockee.id, }); - if (exist != null) { - throw new ApiError(meta.errors.alreadyBlocking); - } + if (exist != null) throw new ApiError('ALREADY_BLOCKING'); await create(blocker, blockee); diff --git a/packages/backend/src/server/api/endpoints/blocking/delete.ts b/packages/backend/src/server/api/endpoints/blocking/delete.ts index 53efc5cca..5e9ca9368 100644 --- a/packages/backend/src/server/api/endpoints/blocking/delete.ts +++ b/packages/backend/src/server/api/endpoints/blocking/delete.ts @@ -17,25 +17,7 @@ export const meta = { kind: 'write:blocks', - errors: { - noSuchUser: { - message: 'No such user.', - code: 'NO_SUCH_USER', - id: '8621d8bf-c358-4303-a066-5ea78610eb3f', - }, - - blockeeIsYourself: { - message: 'Blockee is yourself.', - code: 'BLOCKEE_IS_YOURSELF', - id: '06f6fac6-524b-473c-a354-e97a40ae6eac', - }, - - notBlocking: { - message: 'You are not blocking that user.', - code: 'NOT_BLOCKING', - id: '291b2efa-60c6-45c0-9f6a-045c8f9b02cd', - }, - }, + errors: ['NO_SUCH_USER', 'BLOCKEE_IS_YOURSELF', 'NOT_BLOCKING'], res: { type: 'object', @@ -54,16 +36,14 @@ export const paramDef = { // eslint-disable-next-line import/no-default-export export default define(meta, paramDef, async (ps, user) => { - const blocker = await Users.findOneByOrFail({ id: user.id }); - // Check if the blockee is yourself - if (user.id === ps.userId) { - throw new ApiError(meta.errors.blockeeIsYourself); - } + if (user.id === ps.userId) throw new ApiError('BLOCKEE_IS_YOURSELF'); + + const blocker = await Users.findOneByOrFail({ id: user.id }); // Get blockee const blockee = await getUser(ps.userId).catch(e => { - if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser); + if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError('NO_SUCH_USER'); throw e; }); @@ -73,9 +53,7 @@ export default define(meta, paramDef, async (ps, user) => { blockeeId: blockee.id, }); - if (exist == null) { - throw new ApiError(meta.errors.notBlocking); - } + if (exist == null) throw new ApiError('NOT_BLOCKING'); // Delete blocking await deleteBlocking(blocker, blockee); diff --git a/packages/backend/src/server/api/endpoints/channels/create.ts b/packages/backend/src/server/api/endpoints/channels/create.ts index ac8d63dd8..4962bd3da 100644 --- a/packages/backend/src/server/api/endpoints/channels/create.ts +++ b/packages/backend/src/server/api/endpoints/channels/create.ts @@ -17,13 +17,7 @@ export const meta = { ref: 'Channel', }, - errors: { - noSuchFile: { - message: 'No such file.', - code: 'NO_SUCH_FILE', - id: 'cd1e9f3e-5a12-4ab4-96f6-5d0a2cc32050', - }, - }, + errors: ['NO_SUCH_FILE'], } as const; export const paramDef = { @@ -45,9 +39,7 @@ export default define(meta, paramDef, async (ps, user) => { userId: user.id, }); - if (banner == null) { - throw new ApiError(meta.errors.noSuchFile); - } + if (banner == null) throw new ApiError('NO_SUCH_FILE'); } const channel = await Channels.insert({ diff --git a/packages/backend/src/server/api/endpoints/channels/follow.ts b/packages/backend/src/server/api/endpoints/channels/follow.ts index 9107ec4e8..99bf508c8 100644 --- a/packages/backend/src/server/api/endpoints/channels/follow.ts +++ b/packages/backend/src/server/api/endpoints/channels/follow.ts @@ -11,13 +11,7 @@ export const meta = { kind: 'write:channels', - errors: { - noSuchChannel: { - message: 'No such channel.', - code: 'NO_SUCH_CHANNEL', - id: 'c0031718-d573-4e85-928e-10039f1fbb68', - }, - }, + errors: ['NO_SUCH_CHANNEL'], } as const; export const paramDef = { @@ -34,9 +28,7 @@ export default define(meta, paramDef, async (ps, user) => { id: ps.channelId, }); - if (channel == null) { - throw new ApiError(meta.errors.noSuchChannel); - } + if (channel == null) throw new ApiError('NO_SUCH_CHANNEL'); await ChannelFollowings.insert({ id: genId(), diff --git a/packages/backend/src/server/api/endpoints/channels/show.ts b/packages/backend/src/server/api/endpoints/channels/show.ts index 0e55e73a0..c6a063746 100644 --- a/packages/backend/src/server/api/endpoints/channels/show.ts +++ b/packages/backend/src/server/api/endpoints/channels/show.ts @@ -13,13 +13,7 @@ export const meta = { ref: 'Channel', }, - errors: { - noSuchChannel: { - message: 'No such channel.', - code: 'NO_SUCH_CHANNEL', - id: '6f6c314b-7486-4897-8966-c04a66a02923', - }, - }, + errors: ['NO_SUCH_CHANNEL'], } as const; export const paramDef = { @@ -36,9 +30,7 @@ export default define(meta, paramDef, async (ps, me) => { id: ps.channelId, }); - if (channel == null) { - throw new ApiError(meta.errors.noSuchChannel); - } + if (channel == null) throw new ApiError('NO_SUCH_CHANNEL'); return await Channels.pack(channel, me); }); diff --git a/packages/backend/src/server/api/endpoints/channels/timeline.ts b/packages/backend/src/server/api/endpoints/channels/timeline.ts index 90db2db37..99e13d5ab 100644 --- a/packages/backend/src/server/api/endpoints/channels/timeline.ts +++ b/packages/backend/src/server/api/endpoints/channels/timeline.ts @@ -19,13 +19,7 @@ export const meta = { }, }, - errors: { - noSuchChannel: { - message: 'No such channel.', - code: 'NO_SUCH_CHANNEL', - id: '4d0eeeba-a02c-4c3c-9966-ef60d38d2e7f', - }, - }, + errors: ['NO_SUCH_CHANNEL'], } as const; export const paramDef = { @@ -47,9 +41,7 @@ export default define(meta, paramDef, async (ps, user) => { id: ps.channelId, }); - if (channel == null) { - throw new ApiError(meta.errors.noSuchChannel); - } + if (channel == null) throw new ApiError('NO_SUCH_CHANNEL'); //#region Construct query const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId, ps.sinceDate, ps.untilDate) diff --git a/packages/backend/src/server/api/endpoints/channels/unfollow.ts b/packages/backend/src/server/api/endpoints/channels/unfollow.ts index 262af1720..47e5d6d9b 100644 --- a/packages/backend/src/server/api/endpoints/channels/unfollow.ts +++ b/packages/backend/src/server/api/endpoints/channels/unfollow.ts @@ -10,13 +10,7 @@ export const meta = { kind: 'write:channels', - errors: { - noSuchChannel: { - message: 'No such channel.', - code: 'NO_SUCH_CHANNEL', - id: '19959ee9-0153-4c51-bbd9-a98c49dc59d6', - }, - }, + errors: ['NO_SUCH_CHANNEL'], } as const; export const paramDef = { @@ -33,9 +27,7 @@ export default define(meta, paramDef, async (ps, user) => { id: ps.channelId, }); - if (channel == null) { - throw new ApiError(meta.errors.noSuchChannel); - } + if (channel == null) throw new ApiError('NO_SUCH_CHANNEL'); await ChannelFollowings.delete({ followerId: user.id, diff --git a/packages/backend/src/server/api/endpoints/channels/update.ts b/packages/backend/src/server/api/endpoints/channels/update.ts index 4ca9369d1..33557df12 100644 --- a/packages/backend/src/server/api/endpoints/channels/update.ts +++ b/packages/backend/src/server/api/endpoints/channels/update.ts @@ -15,25 +15,7 @@ export const meta = { ref: 'Channel', }, - errors: { - noSuchChannel: { - message: 'No such channel.', - code: 'NO_SUCH_CHANNEL', - id: 'f9c5467f-d492-4c3c-9a8d-a70dacc86512', - }, - - accessDenied: { - message: 'You do not have edit privilege of the channel.', - code: 'ACCESS_DENIED', - id: '1fb7cb09-d46a-4fdf-b8df-057788cce513', - }, - - noSuchFile: { - message: 'No such file.', - code: 'NO_SUCH_FILE', - id: 'e86c14a4-0da2-4032-8df3-e737a04c7f3b', - }, - }, + errors: ['ACCESS_DENIED', 'NO_SUCH_CHANNEL', 'NO_SUCH_FILE'], } as const; export const paramDef = { @@ -53,13 +35,9 @@ export default define(meta, paramDef, async (ps, me) => { id: ps.channelId, }); - if (channel == null) { - throw new ApiError(meta.errors.noSuchChannel); - } + if (channel == null) throw new ApiError('NO_SUCH_CHANNEL'); - if (channel.userId !== me.id) { - throw new ApiError(meta.errors.accessDenied); - } + if (channel.userId !== me.id) throw new ApiError('ACCESS_DENIED', 'You are not the owner of this channel.'); // eslint:disable-next-line:no-unnecessary-initializer let banner = undefined; @@ -69,9 +47,7 @@ export default define(meta, paramDef, async (ps, me) => { userId: me.id, }); - if (banner == null) { - throw new ApiError(meta.errors.noSuchFile); - } + if (banner == null) throw new ApiError('NO_SUCH_FILE'); } else if (ps.bannerId === null) { banner = null; } diff --git a/packages/backend/src/server/api/endpoints/clips/add-note.ts b/packages/backend/src/server/api/endpoints/clips/add-note.ts index 15828303b..13b432d13 100644 --- a/packages/backend/src/server/api/endpoints/clips/add-note.ts +++ b/packages/backend/src/server/api/endpoints/clips/add-note.ts @@ -11,25 +11,7 @@ export const meta = { kind: 'write:account', - errors: { - noSuchClip: { - message: 'No such clip.', - code: 'NO_SUCH_CLIP', - id: 'd6e76cc0-a1b5-4c7c-a287-73fa9c716dcf', - }, - - noSuchNote: { - message: 'No such note.', - code: 'NO_SUCH_NOTE', - id: 'fc8c0b49-c7a3-4664-a0a6-b418d386bb8b', - }, - - alreadyClipped: { - message: 'The note has already been clipped.', - code: 'ALREADY_CLIPPED', - id: '734806c4-542c-463a-9311-15c512803965', - }, - }, + errors: ['ALREADY_CLIPPED', 'NO_SUCH_CLIP', 'NO_SUCH_NOTE'], } as const; export const paramDef = { @@ -48,12 +30,10 @@ export default define(meta, paramDef, async (ps, user) => { userId: user.id, }); - if (clip == null) { - throw new ApiError(meta.errors.noSuchClip); - } + if (clip == null) throw new ApiError('NO_SUCH_CLIP'); const note = await getNote(ps.noteId, user).catch(err => { - if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); + if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE'); throw err; }); @@ -62,9 +42,7 @@ export default define(meta, paramDef, async (ps, user) => { clipId: clip.id, }); - if (exist != null) { - throw new ApiError(meta.errors.alreadyClipped); - } + if (exist != null) throw new ApiError('ALREADY_CLIPPED'); await ClipNotes.insert({ id: genId(), diff --git a/packages/backend/src/server/api/endpoints/clips/delete.ts b/packages/backend/src/server/api/endpoints/clips/delete.ts index a6c10f546..3fd9ee0b1 100644 --- a/packages/backend/src/server/api/endpoints/clips/delete.ts +++ b/packages/backend/src/server/api/endpoints/clips/delete.ts @@ -9,13 +9,7 @@ export const meta = { kind: 'write:account', - errors: { - noSuchClip: { - message: 'No such clip.', - code: 'NO_SUCH_CLIP', - id: '70ca08ba-6865-4630-b6fb-8494759aa754', - }, - }, + errors: ['NO_SUCH_CLIP'], } as const; export const paramDef = { @@ -33,9 +27,7 @@ export default define(meta, paramDef, async (ps, user) => { userId: user.id, }); - if (clip == null) { - throw new ApiError(meta.errors.noSuchClip); - } + if (clip == null) throw new ApiError('NO_SUCH_CLIP'); await Clips.delete(clip.id); }); diff --git a/packages/backend/src/server/api/endpoints/clips/notes.ts b/packages/backend/src/server/api/endpoints/clips/notes.ts index b8614d6e1..8af046d03 100644 --- a/packages/backend/src/server/api/endpoints/clips/notes.ts +++ b/packages/backend/src/server/api/endpoints/clips/notes.ts @@ -13,13 +13,7 @@ export const meta = { kind: 'read:account', - errors: { - noSuchClip: { - message: 'No such clip.', - code: 'NO_SUCH_CLIP', - id: '1d7645e6-2b6d-4635-b0fe-fe22b0e72e00', - }, - }, + errors: ['NO_SUCH_CLIP'], res: { type: 'array', @@ -49,12 +43,10 @@ export default define(meta, paramDef, async (ps, user) => { id: ps.clipId, }); - if (clip == null) { - throw new ApiError(meta.errors.noSuchClip); - } + if (clip == null) throw new ApiError('NO_SUCH_CLIP'); if (!clip.isPublic && (user == null || (clip.userId !== user.id))) { - throw new ApiError(meta.errors.noSuchClip); + throw new ApiError('NO_SUCH_CLIP'); } const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId) diff --git a/packages/backend/src/server/api/endpoints/clips/remove-note.ts b/packages/backend/src/server/api/endpoints/clips/remove-note.ts index 7987553f6..e6b60178e 100644 --- a/packages/backend/src/server/api/endpoints/clips/remove-note.ts +++ b/packages/backend/src/server/api/endpoints/clips/remove-note.ts @@ -10,26 +10,7 @@ export const meta = { kind: 'write:account', - errors: { - noSuchClip: { - message: 'No such clip.', - code: 'NO_SUCH_CLIP', - id: 'b80525c6-97f7-49d7-a42d-ebccd49cfd52', - }, - - noSuchNote: { - message: 'No such note.', - code: 'NO_SUCH_NOTE', - id: 'aff017de-190e-434b-893e-33a9ff5049d8', - }, - - notClipped: { - message: 'That note is not added to this clip.', - code: 'NOT_CLIPPED', - id: '6b20c697-6e51-4120-b340-0e47899c7a20', - httpStatusCode: 409, - }, - }, + errors: ['NO_SUCH_CLIP', 'NO_SUCH_NOTE', 'NOT_CLIPPED'], } as const; export const paramDef = { @@ -48,12 +29,10 @@ export default define(meta, paramDef, async (ps, user) => { userId: user.id, }); - if (clip == null) { - throw new ApiError(meta.errors.noSuchClip); - } + if (clip == null) throw new ApiError('NO_SUCH_CLIP'); const note = await getNote(ps.noteId).catch(e => { - if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); + if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE'); throw e; }); @@ -62,7 +41,5 @@ export default define(meta, paramDef, async (ps, user) => { clipId: clip.id, }); - if (affected === 0) { - throw new ApiError(meta.errors.notClipped); - } + if (affected === 0) throw new ApiError('NOT_CLIPPED'); }); diff --git a/packages/backend/src/server/api/endpoints/clips/show.ts b/packages/backend/src/server/api/endpoints/clips/show.ts index 88a5c2eeb..942890dfe 100644 --- a/packages/backend/src/server/api/endpoints/clips/show.ts +++ b/packages/backend/src/server/api/endpoints/clips/show.ts @@ -9,13 +9,7 @@ export const meta = { kind: 'read:account', - errors: { - noSuchClip: { - message: 'No such clip.', - code: 'NO_SUCH_CLIP', - id: 'c3c5fe33-d62c-44d2-9ea5-d997703f5c20', - }, - }, + errors: ['NO_SUCH_CLIP'], res: { type: 'object', @@ -39,12 +33,10 @@ export default define(meta, paramDef, async (ps, me) => { id: ps.clipId, }); - if (clip == null) { - throw new ApiError(meta.errors.noSuchClip); - } + if (clip == null) throw new ApiError('NO_SUCH_CLIP'); if (!clip.isPublic && (me == null || (clip.userId !== me.id))) { - throw new ApiError(meta.errors.noSuchClip); + throw new ApiError('NO_SUCH_CLIP'); } return await Clips.pack(clip); diff --git a/packages/backend/src/server/api/endpoints/clips/update.ts b/packages/backend/src/server/api/endpoints/clips/update.ts index 2878042ba..6b26e2b20 100644 --- a/packages/backend/src/server/api/endpoints/clips/update.ts +++ b/packages/backend/src/server/api/endpoints/clips/update.ts @@ -9,13 +9,7 @@ export const meta = { kind: 'write:account', - errors: { - noSuchClip: { - message: 'No such clip.', - code: 'NO_SUCH_CLIP', - id: 'b4d92d70-b216-46fa-9a3f-a8c811699257', - }, - }, + errors: ['NO_SUCH_CLIP'], res: { type: 'object', @@ -43,9 +37,7 @@ export default define(meta, paramDef, async (ps, user) => { userId: user.id, }); - if (clip == null) { - throw new ApiError(meta.errors.noSuchClip); - } + if (clip == null) throw new ApiError('NO_SUCH_CLIP'); await Clips.update(clip.id, { name: ps.name, diff --git a/packages/backend/src/server/api/endpoints/drive/files/attached-notes.ts b/packages/backend/src/server/api/endpoints/drive/files/attached-notes.ts index 69718b926..bad04f188 100644 --- a/packages/backend/src/server/api/endpoints/drive/files/attached-notes.ts +++ b/packages/backend/src/server/api/endpoints/drive/files/attached-notes.ts @@ -21,13 +21,7 @@ export const meta = { }, }, - errors: { - noSuchFile: { - message: 'No such file.', - code: 'NO_SUCH_FILE', - id: 'c118ece3-2e4b-4296-99d1-51756e32d232', - }, - }, + errors: ['NO_SUCH_FILE'], } as const; export const paramDef = { @@ -46,9 +40,7 @@ export default define(meta, paramDef, async (ps, user) => { userId: user.id, }); - if (file == null) { - throw new ApiError(meta.errors.noSuchFile); - } + if (file == null) throw new ApiError('NO_SUCH_FILE'); const notes = await Notes.createQueryBuilder('note') .where(':file = ANY(note.fileIds)', { file: file.id }) diff --git a/packages/backend/src/server/api/endpoints/drive/files/create.ts b/packages/backend/src/server/api/endpoints/drive/files/create.ts index 123eadfce..8cbac7907 100644 --- a/packages/backend/src/server/api/endpoints/drive/files/create.ts +++ b/packages/backend/src/server/api/endpoints/drive/files/create.ts @@ -28,13 +28,7 @@ export const meta = { ref: 'DriveFile', }, - errors: { - invalidFileName: { - message: 'Invalid file name.', - code: 'INVALID_FILE_NAME', - id: 'f449b209-0c60-4e51-84d5-29486263bfd4', - }, - }, + errors: ['INTERNAL_ERROR', 'INVALID_FILE_NAME'], } as const; export const paramDef = { @@ -60,7 +54,7 @@ export default define(meta, paramDef, async (ps, user, _, file, cleanup) => { } else if (name === 'blob') { name = null; } else if (!DriveFiles.validateFileName(name)) { - throw new ApiError(meta.errors.invalidFileName); + throw new ApiError('INVALID_FILE_NAME'); } } else { name = null; @@ -74,7 +68,7 @@ export default define(meta, paramDef, async (ps, user, _, file, cleanup) => { if (e instanceof Error || typeof e === 'string') { apiLogger.error(e); } - throw new ApiError(); + throw new ApiError('INTERNAL_ERROR'); } finally { cleanup!(); } diff --git a/packages/backend/src/server/api/endpoints/drive/files/delete.ts b/packages/backend/src/server/api/endpoints/drive/files/delete.ts index a3f608c9d..c5a8f94b6 100644 --- a/packages/backend/src/server/api/endpoints/drive/files/delete.ts +++ b/packages/backend/src/server/api/endpoints/drive/files/delete.ts @@ -13,19 +13,7 @@ export const meta = { description: 'Delete an existing drive file.', - errors: { - noSuchFile: { - message: 'No such file.', - code: 'NO_SUCH_FILE', - id: '908939ec-e52b-4458-b395-1025195cea58', - }, - - accessDenied: { - message: 'Access denied.', - code: 'ACCESS_DENIED', - id: '5eb8d909-2540-4970-90b8-dd6f86088121', - }, - }, + errors: ['ACCESS_DENIED', 'NO_SUCH_FILE'], } as const; export const paramDef = { @@ -40,12 +28,10 @@ export const paramDef = { export default define(meta, paramDef, async (ps, user) => { const file = await DriveFiles.findOneBy({ id: ps.fileId }); - if (file == null) { - throw new ApiError(meta.errors.noSuchFile); - } + if (file == null) throw new ApiError('NO_SUCH_FILE'); if ((!user.isAdmin && !user.isModerator) && (file.userId !== user.id)) { - throw new ApiError(meta.errors.accessDenied); + throw new ApiError('ACCESS_DENIED'); } // Delete diff --git a/packages/backend/src/server/api/endpoints/drive/files/show.ts b/packages/backend/src/server/api/endpoints/drive/files/show.ts index 92796d552..08ac5ae2d 100644 --- a/packages/backend/src/server/api/endpoints/drive/files/show.ts +++ b/packages/backend/src/server/api/endpoints/drive/files/show.ts @@ -18,19 +18,7 @@ export const meta = { ref: 'DriveFile', }, - errors: { - noSuchFile: { - message: 'No such file.', - code: 'NO_SUCH_FILE', - id: '067bc436-2718-4795-b0fb-ecbe43949e31', - }, - - accessDenied: { - message: 'Access denied.', - code: 'ACCESS_DENIED', - id: '25b73c73-68b1-41d0-bad1-381cfdf6579f', - }, - }, + errors: ['ACCESS_DENIED', 'NO_SUCH_FILE'], } as const; export const paramDef = { @@ -69,12 +57,10 @@ export default define(meta, paramDef, async (ps, user) => { }); } - if (file == null) { - throw new ApiError(meta.errors.noSuchFile); - } + if (file == null) throw new ApiError('NO_SUCH_FILE'); if ((!user.isAdmin && !user.isModerator) && (file.userId !== user.id)) { - throw new ApiError(meta.errors.accessDenied); + throw new ApiError('ACCESS_DENIED'); } return await DriveFiles.pack(file, { diff --git a/packages/backend/src/server/api/endpoints/drive/files/update.ts b/packages/backend/src/server/api/endpoints/drive/files/update.ts index dedec03e2..3b5e57461 100644 --- a/packages/backend/src/server/api/endpoints/drive/files/update.ts +++ b/packages/backend/src/server/api/endpoints/drive/files/update.ts @@ -12,31 +12,7 @@ export const meta = { description: 'Update the properties of a drive file.', - errors: { - invalidFileName: { - message: 'Invalid file name.', - code: 'INVALID_FILE_NAME', - id: '395e7156-f9f0-475e-af89-53c3c23080c2', - }, - - noSuchFile: { - message: 'No such file.', - code: 'NO_SUCH_FILE', - id: 'e7778c7e-3af9-49cd-9690-6dbc3e6c972d', - }, - - accessDenied: { - message: 'Access denied.', - code: 'ACCESS_DENIED', - id: '01a53b27-82fc-445b-a0c1-b558465a8ed2', - }, - - noSuchFolder: { - message: 'No such folder.', - code: 'NO_SUCH_FOLDER', - id: 'ea8fb7a5-af77-4a08-b608-c0218176cd73', - }, - }, + errors: ['ACCESS_DENIED', 'INVALID_FILE_NAME', 'NO_SUCH_FILE', 'NO_SUCH_FOLDER'], res: { type: 'object', @@ -61,17 +37,15 @@ export const paramDef = { export default define(meta, paramDef, async (ps, user) => { const file = await DriveFiles.findOneBy({ id: ps.fileId }); - if (file == null) { - throw new ApiError(meta.errors.noSuchFile); - } + if (file == null) throw new ApiError('NO_SUCH_FILE'); if ((!user.isAdmin && !user.isModerator) && (file.userId !== user.id)) { - throw new ApiError(meta.errors.accessDenied); + throw new ApiError('ACCESS_DENIED'); } if (ps.name) file.name = ps.name; if (!DriveFiles.validateFileName(file.name)) { - throw new ApiError(meta.errors.invalidFileName); + throw new ApiError('INVALID_FILE_NAME'); } if (ps.comment !== undefined) file.comment = ps.comment; @@ -87,9 +61,7 @@ export default define(meta, paramDef, async (ps, user) => { userId: user.id, }); - if (folder == null) { - throw new ApiError(meta.errors.noSuchFolder); - } + if (folder == null) throw new ApiError('NO_SUCH_FOLDER'); file.folderId = folder.id; } diff --git a/packages/backend/src/server/api/endpoints/drive/folders/create.ts b/packages/backend/src/server/api/endpoints/drive/folders/create.ts index 6cb161a7f..ea4e201ff 100644 --- a/packages/backend/src/server/api/endpoints/drive/folders/create.ts +++ b/packages/backend/src/server/api/endpoints/drive/folders/create.ts @@ -11,13 +11,7 @@ export const meta = { kind: 'write:drive', - errors: { - noSuchFolder: { - message: 'No such folder.', - code: 'NO_SUCH_FOLDER', - id: '53326628-a00d-40a6-a3cd-8975105c0f95', - }, - }, + errors: ['NO_SUCH_FOLDER'], res: { type: 'object' as const, @@ -46,9 +40,7 @@ export default define(meta, paramDef, async (ps, user) => { userId: user.id, }); - if (parent == null) { - throw new ApiError(meta.errors.noSuchFolder); - } + if (parent == null) throw new ApiError('NO_SUCH_FOLDER'); } // Create folder diff --git a/packages/backend/src/server/api/endpoints/drive/folders/delete.ts b/packages/backend/src/server/api/endpoints/drive/folders/delete.ts index a4176312e..76aeba323 100644 --- a/packages/backend/src/server/api/endpoints/drive/folders/delete.ts +++ b/packages/backend/src/server/api/endpoints/drive/folders/delete.ts @@ -10,19 +10,7 @@ export const meta = { kind: 'write:drive', - errors: { - noSuchFolder: { - message: 'No such folder.', - code: 'NO_SUCH_FOLDER', - id: '1069098f-c281-440f-b085-f9932edbe091', - }, - - hasChildFilesOrFolders: { - message: 'This folder has child files or folders.', - code: 'HAS_CHILD_FILES_OR_FOLDERS', - id: 'b0fc8a17-963c-405d-bfbc-859a487295e1', - }, - }, + errors: ['HAS_CHILD_FILES_OR_FOLDERS', 'NO_SUCH_FOLDER'], } as const; export const paramDef = { @@ -41,9 +29,7 @@ export default define(meta, paramDef, async (ps, user) => { userId: user.id, }); - if (folder == null) { - throw new ApiError(meta.errors.noSuchFolder); - } + if (folder == null) throw new ApiError('NO_SUCH_FOLDER'); const [childFoldersCount, childFilesCount] = await Promise.all([ DriveFolders.countBy({ parentId: folder.id }), @@ -51,7 +37,7 @@ export default define(meta, paramDef, async (ps, user) => { ]); if (childFoldersCount !== 0 || childFilesCount !== 0) { - throw new ApiError(meta.errors.hasChildFilesOrFolders); + throw new ApiError('HAS_CHILD_FILES_OR_FOLDERS'); } await DriveFolders.delete(folder.id); diff --git a/packages/backend/src/server/api/endpoints/drive/folders/show.ts b/packages/backend/src/server/api/endpoints/drive/folders/show.ts index afb448214..9c8734227 100644 --- a/packages/backend/src/server/api/endpoints/drive/folders/show.ts +++ b/packages/backend/src/server/api/endpoints/drive/folders/show.ts @@ -15,13 +15,7 @@ export const meta = { ref: 'DriveFolder', }, - errors: { - noSuchFolder: { - message: 'No such folder.', - code: 'NO_SUCH_FOLDER', - id: 'd74ab9eb-bb09-4bba-bf24-fb58f761e1e9', - }, - }, + errors: ['NO_SUCH_FOLDER'], } as const; export const paramDef = { @@ -40,9 +34,7 @@ export default define(meta, paramDef, async (ps, user) => { userId: user.id, }); - if (folder == null) { - throw new ApiError(meta.errors.noSuchFolder); - } + if (folder == null) throw new ApiError('NO_SUCH_FOLDER'); return await DriveFolders.pack(folder, { detail: true, diff --git a/packages/backend/src/server/api/endpoints/drive/folders/update.ts b/packages/backend/src/server/api/endpoints/drive/folders/update.ts index a87420042..8813456bb 100644 --- a/packages/backend/src/server/api/endpoints/drive/folders/update.ts +++ b/packages/backend/src/server/api/endpoints/drive/folders/update.ts @@ -10,25 +10,7 @@ export const meta = { kind: 'write:drive', - errors: { - noSuchFolder: { - message: 'No such folder.', - code: 'NO_SUCH_FOLDER', - id: 'f7974dac-2c0d-4a27-926e-23583b28e98e', - }, - - noSuchParentFolder: { - message: 'No such parent folder.', - code: 'NO_SUCH_PARENT_FOLDER', - id: 'ce104e3a-faaf-49d5-b459-10ff0cbbcaa1', - }, - - recursiveNesting: { - message: 'It can not be structured like nesting folders recursively.', - code: 'NO_SUCH_PARENT_FOLDER', - id: 'ce104e3a-faaf-49d5-b459-10ff0cbbcaa1', - }, - }, + errors: ['NO_SUCH_FOLDER', 'NO_SUCH_PARENT_FOLDER', 'RECURSIVE_FOLDER'], res: { type: 'object', @@ -55,15 +37,13 @@ export default define(meta, paramDef, async (ps, user) => { userId: user.id, }); - if (folder == null) { - throw new ApiError(meta.errors.noSuchFolder); - } + if (folder == null) throw new ApiError('NO_SUCH_FOLDER'); if (ps.name) folder.name = ps.name; if (ps.parentId !== undefined) { if (ps.parentId === folder.id) { - throw new ApiError(meta.errors.recursiveNesting); + throw new ApiError('RECURSIVE_FOLDER'); } else if (ps.parentId === null) { folder.parentId = null; } else { @@ -73,9 +53,7 @@ export default define(meta, paramDef, async (ps, user) => { userId: user.id, }); - if (parent == null) { - throw new ApiError(meta.errors.noSuchParentFolder); - } + if (parent == null) throw new ApiError('NO_SUCH_PARENT_FOLDER'); // Check if the circular reference will occur async function checkCircle(folderId: string): Promise { @@ -95,7 +73,7 @@ export default define(meta, paramDef, async (ps, user) => { if (parent.parentId !== null) { if (await checkCircle(parent.parentId)) { - throw new ApiError(meta.errors.recursiveNesting); + throw new ApiError('RECURSIVE_FOLDER'); } } diff --git a/packages/backend/src/server/api/endpoints/following/create.ts b/packages/backend/src/server/api/endpoints/following/create.ts index 1bca40f16..90ec95172 100644 --- a/packages/backend/src/server/api/endpoints/following/create.ts +++ b/packages/backend/src/server/api/endpoints/following/create.ts @@ -18,37 +18,7 @@ export const meta = { kind: 'write:following', - errors: { - noSuchUser: { - message: 'No such user.', - code: 'NO_SUCH_USER', - id: 'fcd2eef9-a9b2-4c4f-8624-038099e90aa5', - }, - - followeeIsYourself: { - message: 'Followee is yourself.', - code: 'FOLLOWEE_IS_YOURSELF', - id: '26fbe7bb-a331-4857-af17-205b426669a9', - }, - - alreadyFollowing: { - message: 'You are already following that user.', - code: 'ALREADY_FOLLOWING', - id: '35387507-38c7-4cb9-9197-300b93783fa0', - }, - - blocking: { - message: 'You are blocking that user.', - code: 'BLOCKING', - id: '4e2206ec-aa4f-4960-b865-6c23ac38e2d9', - }, - - blocked: { - message: 'You are blocked by that user.', - code: 'BLOCKED', - id: 'c4ab57cc-4e41-45e9-bfd9-584f61e35ce0', - }, - }, + errors: ['ALREADY_FOLLOWING', 'BLOCKING', 'BLOCKED', 'FOLLOWEE_IS_YOURSELF', 'NO_SUCH_USER'], res: { type: 'object', @@ -70,13 +40,11 @@ export default define(meta, paramDef, async (ps, user) => { const follower = user; // 自分自身 - if (user.id === ps.userId) { - throw new ApiError(meta.errors.followeeIsYourself); - } + if (user.id === ps.userId) throw new ApiError('FOLLOWEE_IS_YOURSELF'); // Get followee const followee = await getUser(ps.userId).catch(e => { - if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser); + if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError('NO_SUCH_USER'); throw e; }); @@ -86,16 +54,14 @@ export default define(meta, paramDef, async (ps, user) => { followeeId: followee.id, }); - if (exist != null) { - throw new ApiError(meta.errors.alreadyFollowing); - } + if (exist != null) throw new ApiError('ALREADY_FOLLOWING'); try { await create(follower, followee); } catch (e) { if (e instanceof IdentifiableError) { - if (e.id === '710e8fb0-b8c3-4922-be49-d5d93d8e6a6e') throw new ApiError(meta.errors.blocking); - if (e.id === '3338392a-f764-498d-8855-db939dcf8c48') throw new ApiError(meta.errors.blocked); + if (e.id === '710e8fb0-b8c3-4922-be49-d5d93d8e6a6e') throw new ApiError('BLOCKING'); + if (e.id === '3338392a-f764-498d-8855-db939dcf8c48') throw new ApiError('BLOCKED'); } throw e; } diff --git a/packages/backend/src/server/api/endpoints/following/delete.ts b/packages/backend/src/server/api/endpoints/following/delete.ts index 3f9c217de..72c1ce6c6 100644 --- a/packages/backend/src/server/api/endpoints/following/delete.ts +++ b/packages/backend/src/server/api/endpoints/following/delete.ts @@ -17,25 +17,7 @@ export const meta = { kind: 'write:following', - errors: { - noSuchUser: { - message: 'No such user.', - code: 'NO_SUCH_USER', - id: '5b12c78d-2b28-4dca-99d2-f56139b42ff8', - }, - - followeeIsYourself: { - message: 'Followee is yourself.', - code: 'FOLLOWEE_IS_YOURSELF', - id: 'd9e400b9-36b0-4808-b1d8-79e707f1296c', - }, - - notFollowing: { - message: 'You are not following that user.', - code: 'NOT_FOLLOWING', - id: '5dbf82f5-c92b-40b1-87d1-6c8c0741fd09', - }, - }, + errors: ['FOLLOWEE_IS_YOURSELF', 'NO_SUCH_USER', 'NOT_FOLLOWING'], res: { type: 'object', @@ -57,13 +39,11 @@ export default define(meta, paramDef, async (ps, user) => { const follower = user; // Check if the followee is yourself - if (user.id === ps.userId) { - throw new ApiError(meta.errors.followeeIsYourself); - } + if (user.id === ps.userId) throw new ApiError('FOLLOWEE_IS_YOURSELF'); // Get followee const followee = await getUser(ps.userId).catch(e => { - if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser); + if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError('NO_SUCH_USER'); throw e; }); @@ -73,9 +53,7 @@ export default define(meta, paramDef, async (ps, user) => { followeeId: followee.id, }); - if (exist == null) { - throw new ApiError(meta.errors.notFollowing); - } + if (exist == null) throw new ApiError('NOT_FOLLOWING'); await deleteFollowing(follower, followee); diff --git a/packages/backend/src/server/api/endpoints/following/invalidate.ts b/packages/backend/src/server/api/endpoints/following/invalidate.ts index b9e84d81a..437d20ae7 100644 --- a/packages/backend/src/server/api/endpoints/following/invalidate.ts +++ b/packages/backend/src/server/api/endpoints/following/invalidate.ts @@ -17,25 +17,7 @@ export const meta = { kind: 'write:following', - errors: { - noSuchUser: { - message: 'No such user.', - code: 'NO_SUCH_USER', - id: '5b12c78d-2b28-4dca-99d2-f56139b42ff8', - }, - - followerIsYourself: { - message: 'Follower is yourself.', - code: 'FOLLOWER_IS_YOURSELF', - id: '07dc03b9-03da-422d-885b-438313707662', - }, - - notFollowing: { - message: 'The other use is not following you.', - code: 'NOT_FOLLOWING', - id: '5dbf82f5-c92b-40b1-87d1-6c8c0741fd09', - }, - }, + errors: ['FOLLOWER_IS_YOURSELF', 'NO_SUCH_USER', 'NOT_FOLLOWING'], res: { type: 'object', @@ -57,13 +39,11 @@ export default define(meta, paramDef, async (ps, user) => { const followee = user; // Check if the follower is yourself - if (user.id === ps.userId) { - throw new ApiError(meta.errors.followerIsYourself); - } + if (user.id === ps.userId) throw new ApiError('FOLLOWER_IS_YOURSELF'); // Get follower const follower = await getUser(ps.userId).catch(e => { - if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser); + if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError('NO_SUCH_USER'); throw e; }); @@ -73,9 +53,7 @@ export default define(meta, paramDef, async (ps, user) => { followeeId: followee.id, }); - if (exist == null) { - throw new ApiError(meta.errors.notFollowing); - } + if (exist == null) throw new ApiError('NOT_FOLLOWING'); await deleteFollowing(follower, followee); diff --git a/packages/backend/src/server/api/endpoints/following/requests/accept.ts b/packages/backend/src/server/api/endpoints/following/requests/accept.ts index e5df55375..cd30eab98 100644 --- a/packages/backend/src/server/api/endpoints/following/requests/accept.ts +++ b/packages/backend/src/server/api/endpoints/following/requests/accept.ts @@ -10,18 +10,7 @@ export const meta = { kind: 'write:following', - errors: { - noSuchUser: { - message: 'No such user.', - code: 'NO_SUCH_USER', - id: '66ce1645-d66c-46bb-8b79-96739af885bd', - }, - noFollowRequest: { - message: 'No follow request.', - code: 'NO_FOLLOW_REQUEST', - id: 'bcde4f8b-0913-4614-8881-614e522fb041', - }, - }, + errors: ['NO_SUCH_USER', 'NO_SUCH_FOLLOW_REQUEST'], } as const; export const paramDef = { @@ -36,12 +25,12 @@ export const paramDef = { export default define(meta, paramDef, async (ps, user) => { // Fetch follower const follower = await getUser(ps.userId).catch(e => { - if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser); + if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError('NO_SUCH_USER'); throw e; }); await acceptFollowRequest(user, follower).catch(e => { - if (e.id === '8884c2dd-5795-4ac9-b27e-6a01d38190f9') throw new ApiError(meta.errors.noFollowRequest); + if (e.id === '8884c2dd-5795-4ac9-b27e-6a01d38190f9') throw new ApiError('NO_SUCH_FOLLOW_REQUEST'); throw e; }); diff --git a/packages/backend/src/server/api/endpoints/following/requests/cancel.ts b/packages/backend/src/server/api/endpoints/following/requests/cancel.ts index 5f3a9c691..3827007f1 100644 --- a/packages/backend/src/server/api/endpoints/following/requests/cancel.ts +++ b/packages/backend/src/server/api/endpoints/following/requests/cancel.ts @@ -12,19 +12,7 @@ export const meta = { kind: 'write:following', - errors: { - noSuchUser: { - message: 'No such user.', - code: 'NO_SUCH_USER', - id: '4e68c551-fc4c-4e46-bb41-7d4a37bf9dab', - }, - - followRequestNotFound: { - message: 'Follow request not found.', - code: 'FOLLOW_REQUEST_NOT_FOUND', - id: '089b125b-d338-482a-9a09-e2622ac9f8d4', - }, - }, + errors: ['NO_SUCH_USER', 'NO_SUCH_FOLLOW_REQUEST'], res: { type: 'object', @@ -45,7 +33,7 @@ export const paramDef = { export default define(meta, paramDef, async (ps, user) => { // Fetch followee const followee = await getUser(ps.userId).catch(e => { - if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser); + if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError('NO_SUCH_USER'); throw e; }); @@ -53,7 +41,7 @@ export default define(meta, paramDef, async (ps, user) => { await cancelFollowRequest(followee, user); } catch (e) { if (e instanceof IdentifiableError) { - if (e.id === '17447091-ce07-46dd-b331-c1fd4f15b1e7') throw new ApiError(meta.errors.followRequestNotFound); + if (e.id === '17447091-ce07-46dd-b331-c1fd4f15b1e7') throw new ApiError('NO_SUCH_FOLLOW_REQUEST'); } throw e; } diff --git a/packages/backend/src/server/api/endpoints/following/requests/reject.ts b/packages/backend/src/server/api/endpoints/following/requests/reject.ts index cebe60428..8de83d508 100644 --- a/packages/backend/src/server/api/endpoints/following/requests/reject.ts +++ b/packages/backend/src/server/api/endpoints/following/requests/reject.ts @@ -10,13 +10,7 @@ export const meta = { kind: 'write:following', - errors: { - noSuchUser: { - message: 'No such user.', - code: 'NO_SUCH_USER', - id: 'abc2ffa6-25b2-4380-ba99-321ff3a94555', - }, - }, + errors: ['NO_SUCH_USER'], } as const; export const paramDef = { @@ -31,7 +25,7 @@ export const paramDef = { export default define(meta, paramDef, async (ps, user) => { // Fetch follower const follower = await getUser(ps.userId).catch(e => { - if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser); + if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError('NO_SUCH_USER'); throw e; }); diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/create.ts b/packages/backend/src/server/api/endpoints/gallery/posts/create.ts index 6757dba1f..a22b603a5 100644 --- a/packages/backend/src/server/api/endpoints/gallery/posts/create.ts +++ b/packages/backend/src/server/api/endpoints/gallery/posts/create.ts @@ -22,10 +22,6 @@ export const meta = { optional: false, nullable: false, ref: 'GalleryPost', }, - - errors: { - - }, } as const; export const paramDef = { diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/delete.ts b/packages/backend/src/server/api/endpoints/gallery/posts/delete.ts index 83bae3af8..65c0e62d0 100644 --- a/packages/backend/src/server/api/endpoints/gallery/posts/delete.ts +++ b/packages/backend/src/server/api/endpoints/gallery/posts/delete.ts @@ -9,13 +9,7 @@ export const meta = { kind: 'write:gallery', - errors: { - noSuchPost: { - message: 'No such post.', - code: 'NO_SUCH_POST', - id: 'ae52f367-4bd7-4ecd-afc6-5672fff427f5', - }, - }, + errors: ['NO_SUCH_POST'], } as const; export const paramDef = { @@ -33,9 +27,7 @@ export default define(meta, paramDef, async (ps, user) => { userId: user.id, }); - if (post == null) { - throw new ApiError(meta.errors.noSuchPost); - } + if (post == null) throw new ApiError('NO_SUCH_POST'); await GalleryPosts.delete(post.id); }); diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/like.ts b/packages/backend/src/server/api/endpoints/gallery/posts/like.ts index 60ae30710..3e0eda503 100644 --- a/packages/backend/src/server/api/endpoints/gallery/posts/like.ts +++ b/packages/backend/src/server/api/endpoints/gallery/posts/like.ts @@ -10,19 +10,7 @@ export const meta = { kind: 'write:gallery-likes', - errors: { - noSuchPost: { - message: 'No such post.', - code: 'NO_SUCH_POST', - id: '56c06af3-1287-442f-9701-c93f7c4a62ff', - }, - - alreadyLiked: { - message: 'The post has already been liked.', - code: 'ALREADY_LIKED', - id: '40e9ed56-a59c-473a-bf3f-f289c54fb5a7', - }, - }, + errors: ['NO_SUCH_POST', 'ALREADY_LIKED'], } as const; export const paramDef = { @@ -36,9 +24,7 @@ export const paramDef = { // eslint-disable-next-line import/no-default-export export default define(meta, paramDef, async (ps, user) => { const post = await GalleryPosts.findOneBy({ id: ps.postId }); - if (post == null) { - throw new ApiError(meta.errors.noSuchPost); - } + if (post == null) throw new ApiError('NO_SUCH_POST'); // if already liked const exist = await GalleryLikes.findOneBy({ @@ -46,9 +32,7 @@ export default define(meta, paramDef, async (ps, user) => { userId: user.id, }); - if (exist != null) { - throw new ApiError(meta.errors.alreadyLiked); - } + if (exist != null) throw new ApiError('ALREADY_LIKED'); // Create like await GalleryLikes.insert({ diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/show.ts b/packages/backend/src/server/api/endpoints/gallery/posts/show.ts index 5fa28b48b..640048028 100644 --- a/packages/backend/src/server/api/endpoints/gallery/posts/show.ts +++ b/packages/backend/src/server/api/endpoints/gallery/posts/show.ts @@ -7,13 +7,7 @@ export const meta = { requireCredential: false, - errors: { - noSuchPost: { - message: 'No such post.', - code: 'NO_SUCH_POST', - id: '1137bf14-c5b0-4604-85bb-5b5371b1cd45', - }, - }, + errors: ['NO_SUCH_POST'], res: { type: 'object', @@ -36,9 +30,7 @@ export default define(meta, paramDef, async (ps, me) => { id: ps.postId, }); - if (post == null) { - throw new ApiError(meta.errors.noSuchPost); - } + if (post == null) throw new ApiError('NO_SUCH_POST'); return await GalleryPosts.pack(post, me); }); diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/unlike.ts b/packages/backend/src/server/api/endpoints/gallery/posts/unlike.ts index fd1a10f2b..61d71905e 100644 --- a/packages/backend/src/server/api/endpoints/gallery/posts/unlike.ts +++ b/packages/backend/src/server/api/endpoints/gallery/posts/unlike.ts @@ -9,19 +9,7 @@ export const meta = { kind: 'write:gallery-likes', - errors: { - noSuchPost: { - message: 'No such post.', - code: 'NO_SUCH_POST', - id: 'c32e6dd0-b555-4413-925e-b3757d19ed84', - }, - - notLiked: { - message: 'You have not liked that post.', - code: 'NOT_LIKED', - id: 'e3e8e06e-be37-41f7-a5b4-87a8250288f0', - }, - }, + errors: ['NO_SUCH_POST', 'NOT_LIKED'], } as const; export const paramDef = { @@ -35,18 +23,14 @@ export const paramDef = { // eslint-disable-next-line import/no-default-export export default define(meta, paramDef, async (ps, user) => { const post = await GalleryPosts.findOneBy({ id: ps.postId }); - if (post == null) { - throw new ApiError(meta.errors.noSuchPost); - } + if (post == null) throw new ApiError('NO_SUCH_POST'); const exist = await GalleryLikes.findOneBy({ postId: post.id, userId: user.id, }); - if (exist == null) { - throw new ApiError(meta.errors.notLiked); - } + if (exist == null) throw new ApiError('NOT_LIKED'); // Delete like await GalleryLikes.delete(exist.id); diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/update.ts b/packages/backend/src/server/api/endpoints/gallery/posts/update.ts index 94be32b02..20cab9243 100644 --- a/packages/backend/src/server/api/endpoints/gallery/posts/update.ts +++ b/packages/backend/src/server/api/endpoints/gallery/posts/update.ts @@ -20,10 +20,6 @@ export const meta = { optional: false, nullable: false, ref: 'GalleryPost', }, - - errors: { - - }, } as const; export const paramDef = { diff --git a/packages/backend/src/server/api/endpoints/hashtags/show.ts b/packages/backend/src/server/api/endpoints/hashtags/show.ts index ae3d1449f..e66661a68 100644 --- a/packages/backend/src/server/api/endpoints/hashtags/show.ts +++ b/packages/backend/src/server/api/endpoints/hashtags/show.ts @@ -14,13 +14,7 @@ export const meta = { ref: 'Hashtag', }, - errors: { - noSuchHashtag: { - message: 'No such hashtag.', - code: 'NO_SUCH_HASHTAG', - id: '110ee688-193e-4a3a-9ecf-c167b2e6981e', - }, - }, + errors: ['NO_SUCH_HASHTAG'], } as const; export const paramDef = { @@ -34,9 +28,7 @@ export const paramDef = { // eslint-disable-next-line import/no-default-export export default define(meta, paramDef, async (ps, user) => { const hashtag = await Hashtags.findOneBy({ name: normalizeForSearch(ps.tag) }); - if (hashtag == null) { - throw new ApiError(meta.errors.noSuchHashtag); - } + if (hashtag == null) throw new ApiError('NO_SUCH_HASHTAG'); return await Hashtags.pack(hashtag); }); diff --git a/packages/backend/src/server/api/endpoints/i/import-blocking.ts b/packages/backend/src/server/api/endpoints/i/import-blocking.ts index f3ea6a42f..ed5ae4259 100644 --- a/packages/backend/src/server/api/endpoints/i/import-blocking.ts +++ b/packages/backend/src/server/api/endpoints/i/import-blocking.ts @@ -13,31 +13,7 @@ export const meta = { max: 1, }, - errors: { - noSuchFile: { - message: 'No such file.', - code: 'NO_SUCH_FILE', - id: 'ebb53e5f-6574-9c0c-0b92-7ca6def56d7e', - }, - - unexpectedFileType: { - message: 'We need csv file.', - code: 'UNEXPECTED_FILE_TYPE', - id: 'b6fab7d6-d945-d67c-dfdb-32da1cd12cfe', - }, - - tooBigFile: { - message: 'That file is too big.', - code: 'TOO_BIG_FILE', - id: 'b7fbf0b1-aeef-3b21-29ef-fadd4cb72ccf', - }, - - emptyFile: { - message: 'That file is empty.', - code: 'EMPTY_FILE', - id: '6f3a4dcc-f060-a707-4950-806fbdbe60d6', - }, - }, + errors: ['EMPTY_FILE', 'FILE_TOO_BIG', 'NO_SUCH_FILE'], } as const; export const paramDef = { @@ -52,10 +28,9 @@ export const paramDef = { export default define(meta, paramDef, async (ps, user) => { const file = await DriveFiles.findOneBy({ id: ps.fileId }); - if (file == null) throw new ApiError(meta.errors.noSuchFile); - //if (!file.type.endsWith('/csv')) throw new ApiError(meta.errors.unexpectedFileType); - if (file.size > 50000) throw new ApiError(meta.errors.tooBigFile); - if (file.size === 0) throw new ApiError(meta.errors.emptyFile); + if (file == null) throw new ApiError('EMPTY_FILE'); + if (file.size > 50000) throw new ApiError('FILE_TOO_BIG'); + if (file.size === 0) throw new ApiError('EMPTY_FILE'); createImportBlockingJob(user, file.id); }); diff --git a/packages/backend/src/server/api/endpoints/i/import-following.ts b/packages/backend/src/server/api/endpoints/i/import-following.ts index e5a4f1adf..b0d1a2dba 100644 --- a/packages/backend/src/server/api/endpoints/i/import-following.ts +++ b/packages/backend/src/server/api/endpoints/i/import-following.ts @@ -12,31 +12,7 @@ export const meta = { max: 1, }, - errors: { - noSuchFile: { - message: 'No such file.', - code: 'NO_SUCH_FILE', - id: 'b98644cf-a5ac-4277-a502-0b8054a709a3', - }, - - unexpectedFileType: { - message: 'We need csv file.', - code: 'UNEXPECTED_FILE_TYPE', - id: '660f3599-bce0-4f95-9dde-311fd841c183', - }, - - tooBigFile: { - message: 'That file is too big.', - code: 'TOO_BIG_FILE', - id: 'dee9d4ed-ad07-43ed-8b34-b2856398bc60', - }, - - emptyFile: { - message: 'That file is empty.', - code: 'EMPTY_FILE', - id: '31a1b42c-06f7-42ae-8a38-a661c5c9f691', - }, - }, + errors: ['EMPTY_FILE', 'FILE_TOO_BIG', 'NO_SUCH_FILE'], } as const; export const paramDef = { @@ -51,10 +27,9 @@ export const paramDef = { export default define(meta, paramDef, async (ps, user) => { const file = await DriveFiles.findOneBy({ id: ps.fileId }); - if (file == null) throw new ApiError(meta.errors.noSuchFile); - //if (!file.type.endsWith('/csv')) throw new ApiError(meta.errors.unexpectedFileType); - if (file.size > 50000) throw new ApiError(meta.errors.tooBigFile); - if (file.size === 0) throw new ApiError(meta.errors.emptyFile); + if (file == null) throw new ApiError('NO_SUCH_FILE'); + if (file.size > 50000) throw new ApiError('FILE_TOO_BIG'); + if (file.size === 0) throw new ApiError('EMPTY_FILE'); createImportFollowingJob(user, file.id); }); diff --git a/packages/backend/src/server/api/endpoints/i/import-muting.ts b/packages/backend/src/server/api/endpoints/i/import-muting.ts index 29acb5638..37149408b 100644 --- a/packages/backend/src/server/api/endpoints/i/import-muting.ts +++ b/packages/backend/src/server/api/endpoints/i/import-muting.ts @@ -13,31 +13,7 @@ export const meta = { max: 1, }, - errors: { - noSuchFile: { - message: 'No such file.', - code: 'NO_SUCH_FILE', - id: 'e674141e-bd2a-ba85-e616-aefb187c9c2a', - }, - - unexpectedFileType: { - message: 'We need csv file.', - code: 'UNEXPECTED_FILE_TYPE', - id: '568c6e42-c86c-ba09-c004-517f83f9f1a8', - }, - - tooBigFile: { - message: 'That file is too big.', - code: 'TOO_BIG_FILE', - id: '9b4ada6d-d7f7-0472-0713-4f558bd1ec9c', - }, - - emptyFile: { - message: 'That file is empty.', - code: 'EMPTY_FILE', - id: 'd2f12af1-e7b4-feac-86a3-519548f2728e', - }, - }, + errors: ['EMPTY_FILE', 'FILE_TOO_BIG', 'NO_SUCH_FILE'], } as const; export const paramDef = { @@ -52,10 +28,9 @@ export const paramDef = { export default define(meta, paramDef, async (ps, user) => { const file = await DriveFiles.findOneBy({ id: ps.fileId }); - if (file == null) throw new ApiError(meta.errors.noSuchFile); - //if (!file.type.endsWith('/csv')) throw new ApiError(meta.errors.unexpectedFileType); - if (file.size > 50000) throw new ApiError(meta.errors.tooBigFile); - if (file.size === 0) throw new ApiError(meta.errors.emptyFile); + if (file == null) throw new ApiError('NO_SUCH_FILE'); + if (file.size > 50000) throw new ApiError('FILE_TOO_BIG'); + if (file.size === 0) throw new ApiError('EMPTY_FILE'); createImportMutingJob(user, file.id); }); diff --git a/packages/backend/src/server/api/endpoints/i/import-user-lists.ts b/packages/backend/src/server/api/endpoints/i/import-user-lists.ts index 1158af3a1..67d6afd0c 100644 --- a/packages/backend/src/server/api/endpoints/i/import-user-lists.ts +++ b/packages/backend/src/server/api/endpoints/i/import-user-lists.ts @@ -12,31 +12,7 @@ export const meta = { max: 1, }, - errors: { - noSuchFile: { - message: 'No such file.', - code: 'NO_SUCH_FILE', - id: 'ea9cc34f-c415-4bc6-a6fe-28ac40357049', - }, - - unexpectedFileType: { - message: 'We need csv file.', - code: 'UNEXPECTED_FILE_TYPE', - id: 'a3c9edda-dd9b-4596-be6a-150ef813745c', - }, - - tooBigFile: { - message: 'That file is too big.', - code: 'TOO_BIG_FILE', - id: 'ae6e7a22-971b-4b52-b2be-fc0b9b121fe9', - }, - - emptyFile: { - message: 'That file is empty.', - code: 'EMPTY_FILE', - id: '99efe367-ce6e-4d44-93f8-5fae7b040356', - }, - }, + errors: ['EMPTY_FILE', 'FILE_TOO_BIG', 'NO_SUCH_FILE'], } as const; export const paramDef = { @@ -51,10 +27,9 @@ export const paramDef = { export default define(meta, paramDef, async (ps, user) => { const file = await DriveFiles.findOneBy({ id: ps.fileId }); - if (file == null) throw new ApiError(meta.errors.noSuchFile); - //if (!file.type.endsWith('/csv')) throw new ApiError(meta.errors.unexpectedFileType); - if (file.size > 30000) throw new ApiError(meta.errors.tooBigFile); - if (file.size === 0) throw new ApiError(meta.errors.emptyFile); + if (file == null) throw new ApiError('NO_SUCH_FILE'); + if (file.size > 30000) throw new ApiError('FILE_TOO_BIG'); + if (file.size === 0) throw new ApiError('EMPTY_FILE'); createImportUserListsJob(user, file.id); }); diff --git a/packages/backend/src/server/api/endpoints/i/pin.ts b/packages/backend/src/server/api/endpoints/i/pin.ts index 64f6a719d..e3a58bc70 100644 --- a/packages/backend/src/server/api/endpoints/i/pin.ts +++ b/packages/backend/src/server/api/endpoints/i/pin.ts @@ -10,25 +10,7 @@ export const meta = { kind: 'write:account', - errors: { - noSuchNote: { - message: 'No such note.', - code: 'NO_SUCH_NOTE', - id: '56734f8b-3928-431e-bf80-6ff87df40cb3', - }, - - pinLimitExceeded: { - message: 'You can not pin notes any more.', - code: 'PIN_LIMIT_EXCEEDED', - id: '72dab508-c64d-498f-8740-a8eec1ba385a', - }, - - alreadyPinned: { - message: 'That note has already been pinned.', - code: 'ALREADY_PINNED', - id: '8b18c2b7-68fe-4edb-9892-c0cbaeb6c913', - }, - }, + errors: ['ALREADY_PINNED', 'NO_SUCH_NOTE', 'PIN_LIMIT_EXCEEDED'], res: { type: 'object', @@ -48,9 +30,9 @@ export const paramDef = { // eslint-disable-next-line import/no-default-export export default define(meta, paramDef, async (ps, user) => { await addPinned(user, ps.noteId).catch(e => { - if (e.id === '70c4e51f-5bea-449c-a030-53bee3cce202') throw new ApiError(meta.errors.noSuchNote); - if (e.id === '15a018eb-58e5-4da1-93be-330fcc5e4e1a') throw new ApiError(meta.errors.pinLimitExceeded); - if (e.id === '23f0cf4e-59a3-4276-a91d-61a5891c1514') throw new ApiError(meta.errors.alreadyPinned); + if (e.id === '70c4e51f-5bea-449c-a030-53bee3cce202') throw new ApiError('NO_SUCH_NOTE'); + if (e.id === '15a018eb-58e5-4da1-93be-330fcc5e4e1a') throw new ApiError('PIN_LIMIT_EXCEEDED'); + if (e.id === '23f0cf4e-59a3-4276-a91d-61a5891c1514') throw new ApiError('ALREADY_PINNED'); throw e; }); diff --git a/packages/backend/src/server/api/endpoints/i/read-announcement.ts b/packages/backend/src/server/api/endpoints/i/read-announcement.ts index 44d533667..6d7e8954c 100644 --- a/packages/backend/src/server/api/endpoints/i/read-announcement.ts +++ b/packages/backend/src/server/api/endpoints/i/read-announcement.ts @@ -11,13 +11,7 @@ export const meta = { kind: 'write:account', - errors: { - noSuchAnnouncement: { - message: 'No such announcement.', - code: 'NO_SUCH_ANNOUNCEMENT', - id: '184663db-df88-4bc2-8b52-fb85f0681939', - }, - }, + errors: ['NO_SUCH_ANNOUNCEMENT'], } as const; export const paramDef = { @@ -33,9 +27,7 @@ export default define(meta, paramDef, async (ps, user) => { // Check if announcement exists const announcement = await Announcements.findOneBy({ id: ps.announcementId }); - if (announcement == null) { - throw new ApiError(meta.errors.noSuchAnnouncement); - } + if (announcement == null) throw new ApiError('NO_SUCH_ANNOUNCEMENT'); // Check if already read const read = await AnnouncementReads.findOneBy({ @@ -43,9 +35,7 @@ export default define(meta, paramDef, async (ps, user) => { userId: user.id, }); - if (read != null) { - return; - } + if (read != null) return; // Create read await AnnouncementReads.insert({ diff --git a/packages/backend/src/server/api/endpoints/i/registry/get-detail.ts b/packages/backend/src/server/api/endpoints/i/registry/get-detail.ts index 744b1d05b..7addd0fab 100644 --- a/packages/backend/src/server/api/endpoints/i/registry/get-detail.ts +++ b/packages/backend/src/server/api/endpoints/i/registry/get-detail.ts @@ -7,13 +7,7 @@ export const meta = { secure: true, - errors: { - noSuchKey: { - message: 'No such key.', - code: 'NO_SUCH_KEY', - id: '97a1e8e7-c0f7-47d2-957a-92e61256e01a', - }, - }, + errors: ['NO_SUCH_KEY'], } as const; export const paramDef = { @@ -37,9 +31,7 @@ export default define(meta, paramDef, async (ps, user) => { const item = await query.getOne(); - if (item == null) { - throw new ApiError(meta.errors.noSuchKey); - } + if (item == null) throw new ApiError('NO_SUCH_KEY'); return { updatedAt: item.updatedAt, diff --git a/packages/backend/src/server/api/endpoints/i/registry/get.ts b/packages/backend/src/server/api/endpoints/i/registry/get.ts index 1bae3c886..a9ca60485 100644 --- a/packages/backend/src/server/api/endpoints/i/registry/get.ts +++ b/packages/backend/src/server/api/endpoints/i/registry/get.ts @@ -7,13 +7,7 @@ export const meta = { secure: true, - errors: { - noSuchKey: { - message: 'No such key.', - code: 'NO_SUCH_KEY', - id: 'ac3ed68a-62f0-422b-a7bc-d5e09e8f6a6a', - }, - }, + errors: ['NO_SUCH_KEY'], } as const; export const paramDef = { @@ -37,9 +31,7 @@ export default define(meta, paramDef, async (ps, user) => { const item = await query.getOne(); - if (item == null) { - throw new ApiError(meta.errors.noSuchKey); - } + if (item == null) throw new ApiError('NO_SUCH_KEY'); return item.value; }); diff --git a/packages/backend/src/server/api/endpoints/i/registry/remove.ts b/packages/backend/src/server/api/endpoints/i/registry/remove.ts index 8467b2513..f656f3d83 100644 --- a/packages/backend/src/server/api/endpoints/i/registry/remove.ts +++ b/packages/backend/src/server/api/endpoints/i/registry/remove.ts @@ -7,13 +7,7 @@ export const meta = { secure: true, - errors: { - noSuchKey: { - message: 'No such key.', - code: 'NO_SUCH_KEY', - id: '1fac4e8a-a6cd-4e39-a4a5-3a7e11f1b019', - }, - }, + errors: ['NO_SUCH_KEY'], } as const; export const paramDef = { @@ -37,9 +31,7 @@ export default define(meta, paramDef, async (ps, user) => { const item = await query.getOne(); - if (item == null) { - throw new ApiError(meta.errors.noSuchKey); - } + if (item == null) throw new ApiError('NO_SUCH_KEY'); await RegistryItems.remove(item); }); diff --git a/packages/backend/src/server/api/endpoints/i/unpin.ts b/packages/backend/src/server/api/endpoints/i/unpin.ts index 2c63f8a88..88cb751b4 100644 --- a/packages/backend/src/server/api/endpoints/i/unpin.ts +++ b/packages/backend/src/server/api/endpoints/i/unpin.ts @@ -10,13 +10,7 @@ export const meta = { kind: 'write:account', - errors: { - noSuchNote: { - message: 'No such note.', - code: 'NO_SUCH_NOTE', - id: '454170ce-9d63-4a43-9da1-ea10afe81e21', - }, - }, + errors: ['NO_SUCH_NOTE'], res: { type: 'object', @@ -36,7 +30,7 @@ export const paramDef = { // eslint-disable-next-line import/no-default-export export default define(meta, paramDef, async (ps, user) => { await removePinned(user, ps.noteId).catch(e => { - if (e.id === 'b302d4cf-c050-400a-bbb3-be208681f40c') throw new ApiError(meta.errors.noSuchNote); + if (e.id === 'b302d4cf-c050-400a-bbb3-be208681f40c') throw new ApiError('NO_SUCH_NOTE'); throw e; }); diff --git a/packages/backend/src/server/api/endpoints/i/update-email.ts b/packages/backend/src/server/api/endpoints/i/update-email.ts index 3f9411de4..cb3d6356a 100644 --- a/packages/backend/src/server/api/endpoints/i/update-email.ts +++ b/packages/backend/src/server/api/endpoints/i/update-email.ts @@ -19,19 +19,9 @@ export const meta = { max: 3, }, - errors: { - incorrectPassword: { - message: 'Incorrect password.', - code: 'INCORRECT_PASSWORD', - id: 'e54c1d7e-e7d6-4103-86b6-0a95069b4ad3', - }, - - unavailable: { - message: 'Unavailable email address.', - code: 'UNAVAILABLE', - id: 'a2defefb-f220-8849-0af6-17f816099323', - }, - }, + // FIXME: refactor to remove both of these errors? + // the password should not be passed as it is not compatible with using OAuth + errors: ['ACCESS_DENIED', 'INTERNAL_ERROR'], } as const; export const paramDef = { @@ -50,15 +40,11 @@ export default define(meta, paramDef, async (ps, user) => { // Compare password const same = await bcrypt.compare(ps.password, profile.password!); - if (!same) { - throw new ApiError(meta.errors.incorrectPassword); - } + if (!same) throw new ApiError('ACCESS_DENIED'); if (ps.email != null) { const available = await validateEmailForAccount(ps.email); - if (!available) { - throw new ApiError(meta.errors.unavailable); - } + if (!available) throw new ApiError('INTERNAL_ERROR'); } await UserProfiles.update(user.id, { diff --git a/packages/backend/src/server/api/endpoints/i/update.ts b/packages/backend/src/server/api/endpoints/i/update.ts index c9557eadd..ce613b190 100644 --- a/packages/backend/src/server/api/endpoints/i/update.ts +++ b/packages/backend/src/server/api/endpoints/i/update.ts @@ -22,43 +22,7 @@ export const meta = { kind: 'write:account', - errors: { - noSuchAvatar: { - message: 'No such avatar file.', - code: 'NO_SUCH_AVATAR', - id: '539f3a45-f215-4f81-a9a8-31293640207f', - }, - - noSuchBanner: { - message: 'No such banner file.', - code: 'NO_SUCH_BANNER', - id: '0d8f5629-f210-41c2-9433-735831a58595', - }, - - avatarNotAnImage: { - message: 'The file specified as an avatar is not an image.', - code: 'AVATAR_NOT_AN_IMAGE', - id: 'f419f9f8-2f4d-46b1-9fb4-49d3a2fd7191', - }, - - bannerNotAnImage: { - message: 'The file specified as a banner is not an image.', - code: 'BANNER_NOT_AN_IMAGE', - id: '75aedb19-2afd-4e6d-87fc-67941256fa60', - }, - - noSuchPage: { - message: 'No such page.', - code: 'NO_SUCH_PAGE', - id: '8e01b590-7eb9-431b-a239-860e086c408e', - }, - - invalidRegexp: { - message: 'Invalid Regular Expression.', - code: 'INVALID_REGEXP', - id: '0d786918-10df-41cd-8f33-8dec7d9a89a5', - }, - }, + errors: ['INVALID_REGEXP', 'NO_SUCH_FILE', 'NO_SUCH_PAGE', 'NOT_AN_IMAGE'], res: { type: 'object', @@ -142,12 +106,12 @@ export default define(meta, paramDef, async (ps, _user, token) => { // validate regular expression syntax ps.mutedWords.filter(x => !Array.isArray(x)).forEach(x => { const regexp = x.match(/^\/(.+)\/(.*)$/); - if (!regexp) throw new ApiError(meta.errors.invalidRegexp); + if (!regexp) throw new ApiError('INVALID_REGEXP'); try { new RE2(regexp[1], regexp[2]); } catch (err) { - throw new ApiError(meta.errors.invalidRegexp); + throw new ApiError('INVALID_REGEXP'); } }); @@ -174,21 +138,21 @@ export default define(meta, paramDef, async (ps, _user, token) => { if (ps.avatarId) { const avatar = await DriveFiles.findOneBy({ id: ps.avatarId }); - if (avatar == null || avatar.userId !== user.id) throw new ApiError(meta.errors.noSuchAvatar); - if (!avatar.type.startsWith('image/')) throw new ApiError(meta.errors.avatarNotAnImage); + if (avatar == null || avatar.userId !== user.id) throw new ApiError('NO_SUCH_FILE', 'Avatar file not found.'); + if (!avatar.type.startsWith('image/')) throw new ApiError('NOT_AN_IMAGE', 'Avatar file is not an image.'); } if (ps.bannerId) { const banner = await DriveFiles.findOneBy({ id: ps.bannerId }); - if (banner == null || banner.userId !== user.id) throw new ApiError(meta.errors.noSuchBanner); - if (!banner.type.startsWith('image/')) throw new ApiError(meta.errors.bannerNotAnImage); + if (banner == null || banner.userId !== user.id) throw new ApiError('NO_SUCH_FILE', 'Banner file not found.'); + if (!banner.type.startsWith('image/')) throw new ApiError('BANNER_NOT_AN_IMAGE', 'Banner file is not an image.'); } if (ps.pinnedPageId) { const page = await Pages.findOneBy({ id: ps.pinnedPageId }); - if (page == null || page.userId !== user.id) throw new ApiError(meta.errors.noSuchPage); + if (page == null || page.userId !== user.id) throw new ApiError('NO_SUCH_PAGE'); profileUpdates.pinnedPageId = page.id; } else if (ps.pinnedPageId === null) { diff --git a/packages/backend/src/server/api/endpoints/i/webhooks/delete.ts b/packages/backend/src/server/api/endpoints/i/webhooks/delete.ts index 81ac30541..61778aa22 100644 --- a/packages/backend/src/server/api/endpoints/i/webhooks/delete.ts +++ b/packages/backend/src/server/api/endpoints/i/webhooks/delete.ts @@ -10,13 +10,7 @@ export const meta = { kind: 'write:account', - errors: { - noSuchWebhook: { - message: 'No such webhook.', - code: 'NO_SUCH_WEBHOOK', - id: 'bae73e5a-5522-4965-ae19-3a8688e71d82', - }, - }, + errors: ['NO_SUCH_WEBHOOK'], } as const; export const paramDef = { @@ -34,9 +28,7 @@ export default define(meta, paramDef, async (ps, user) => { userId: user.id, }); - if (webhook == null) { - throw new ApiError(meta.errors.noSuchWebhook); - } + if (webhook == null) throw new ApiError('NO_SUCH_WEBHOOK'); await Webhooks.delete(webhook.id); diff --git a/packages/backend/src/server/api/endpoints/i/webhooks/show.ts b/packages/backend/src/server/api/endpoints/i/webhooks/show.ts index d45a39813..21baed811 100644 --- a/packages/backend/src/server/api/endpoints/i/webhooks/show.ts +++ b/packages/backend/src/server/api/endpoints/i/webhooks/show.ts @@ -9,13 +9,7 @@ export const meta = { kind: 'read:account', - errors: { - noSuchWebhook: { - message: 'No such webhook.', - code: 'NO_SUCH_WEBHOOK', - id: '50f614d9-3047-4f7e-90d8-ad6b2d5fb098', - }, - }, + errors: ['NO_SUCH_WEBHOOK'], } as const; export const paramDef = { @@ -33,9 +27,7 @@ export default define(meta, paramDef, async (ps, user) => { userId: user.id, }); - if (webhook == null) { - throw new ApiError(meta.errors.noSuchWebhook); - } + if (webhook == null) throw new ApiError('NO_SUCH_WEBHOOK'); return webhook; }); diff --git a/packages/backend/src/server/api/endpoints/i/webhooks/update.ts b/packages/backend/src/server/api/endpoints/i/webhooks/update.ts index 0ffa8a318..d3076ba16 100644 --- a/packages/backend/src/server/api/endpoints/i/webhooks/update.ts +++ b/packages/backend/src/server/api/endpoints/i/webhooks/update.ts @@ -11,14 +11,7 @@ export const meta = { kind: 'write:account', - errors: { - noSuchWebhook: { - message: 'No such webhook.', - code: 'NO_SUCH_WEBHOOK', - id: 'fb0fea69-da18-45b1-828d-bd4fd1612518', - }, - }, - + errors: ['NO_SUCH_WEBHOOK'], } as const; export const paramDef = { @@ -43,9 +36,7 @@ export default define(meta, paramDef, async (ps, user) => { userId: user.id, }); - if (webhook == null) { - throw new ApiError(meta.errors.noSuchWebhook); - } + if (webhook == null) throw new ApiError('NO_SUCH_WEBHOOK'); await Webhooks.update(webhook.id, { name: ps.name, diff --git a/packages/backend/src/server/api/endpoints/messaging/messages.ts b/packages/backend/src/server/api/endpoints/messaging/messages.ts index c8006f490..88e17a054 100644 --- a/packages/backend/src/server/api/endpoints/messaging/messages.ts +++ b/packages/backend/src/server/api/endpoints/messaging/messages.ts @@ -23,25 +23,7 @@ export const meta = { }, }, - errors: { - noSuchUser: { - message: 'No such user.', - code: 'NO_SUCH_USER', - id: '11795c64-40ea-4198-b06e-3c873ed9039d', - }, - - noSuchGroup: { - message: 'No such group.', - code: 'NO_SUCH_GROUP', - id: 'c4d9f88c-9270-4632-b032-6ed8cee36f7f', - }, - - groupAccessDenied: { - message: 'You can not read messages of groups that you have not joined.', - code: 'GROUP_ACCESS_DENIED', - id: 'a053a8dd-a491-4718-8f87-50775aad9284', - }, - }, + errors: ['ACCESS_DENIED', 'NO_SUCH_USER', 'NO_SUCH_GROUP'], } as const; export const paramDef = { @@ -73,7 +55,7 @@ export default define(meta, paramDef, async (ps, user) => { if (ps.userId != null) { // Fetch recipient (user) const recipient = await getUser(ps.userId).catch(e => { - if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser); + if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError('NO_SUCH_USER'); throw e; }); @@ -110,9 +92,7 @@ export default define(meta, paramDef, async (ps, user) => { // Fetch recipient (group) const recipientGroup = await UserGroups.findOneBy({ id: ps.groupId }); - if (recipientGroup == null) { - throw new ApiError(meta.errors.noSuchGroup); - } + if (recipientGroup == null) throw new ApiError('NO_SUCH_GROUP'); // check joined const joining = await UserGroupJoinings.findOneBy({ @@ -120,9 +100,7 @@ export default define(meta, paramDef, async (ps, user) => { userGroupId: recipientGroup.id, }); - if (joining == null) { - throw new ApiError(meta.errors.groupAccessDenied); - } + if (joining == null) throw new ApiError('ACCESS_DENIED', 'You have to join a group to read messages in it.'); const query = makePaginationQuery(MessagingMessages.createQueryBuilder('message'), ps.sinceId, ps.untilId) .andWhere('message.groupId = :groupId', { groupId: recipientGroup.id }); diff --git a/packages/backend/src/server/api/endpoints/messaging/messages/create.ts b/packages/backend/src/server/api/endpoints/messaging/messages/create.ts index ad69ba1e0..020d596fc 100644 --- a/packages/backend/src/server/api/endpoints/messaging/messages/create.ts +++ b/packages/backend/src/server/api/endpoints/messaging/messages/create.ts @@ -19,51 +19,11 @@ export const meta = { ref: 'MessagingMessage', }, - errors: { - recipientIsYourself: { - message: 'You can not send a message to yourself.', - code: 'RECIPIENT_IS_YOURSELF', - id: '17e2ba79-e22a-4cbc-bf91-d327643f4a7e', - }, - - noSuchUser: { - message: 'No such user.', - code: 'NO_SUCH_USER', - id: '11795c64-40ea-4198-b06e-3c873ed9039d', - }, - - noSuchGroup: { - message: 'No such group.', - code: 'NO_SUCH_GROUP', - id: 'c94e2a5d-06aa-4914-8fa6-6a42e73d6537', - }, - - groupAccessDenied: { - message: 'You can not send messages to groups that you have not joined.', - code: 'GROUP_ACCESS_DENIED', - id: 'd96b3cca-5ad1-438b-ad8b-02f931308fbd', - }, - - noSuchFile: { - message: 'No such file.', - code: 'NO_SUCH_FILE', - id: '4372b8e2-185d-4146-8749-2f68864a3e5f', - }, - - youHaveBeenBlocked: { - message: 'You cannot send a message because you have been blocked by this user.', - code: 'YOU_HAVE_BEEN_BLOCKED', - id: 'c15a5199-7422-4968-941a-2a462c478f7d', - }, - }, + errors: ['ACCESS_DENIED', 'BLOCKED', 'NO_SUCH_FILE', 'NO_SUCH_USER', 'NO_SUCH_GROUP', 'RECIPIENT_IS_YOURSELF'], } as const; export const paramDef = { type: 'object', - properties: { - text: { type: 'string', nullable: true, maxLength: 3000 }, - fileId: { type: 'string', format: 'misskey:id' }, - }, anyOf: [ { properties: { @@ -137,13 +97,11 @@ export default define(meta, paramDef, async (ps, user) => { if (ps.userId != null) { // Myself - if (ps.userId === user.id) { - throw new ApiError(meta.errors.recipientIsYourself); - } + if (ps.userId === user.id) throw new ApiError('RECIPIENT_IS_YOURSELF'); // Fetch recipient (user) recipientUser = await getUser(ps.userId).catch(e => { - if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser); + if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError('NO_SUCH_USER'); throw e; }); @@ -152,16 +110,12 @@ export default define(meta, paramDef, async (ps, user) => { blockerId: recipientUser.id, blockeeId: user.id, }); - if (block) { - throw new ApiError(meta.errors.youHaveBeenBlocked); - } + if (block) throw new ApiError('BLOCKED'); } else if (ps.groupId != null) { // Fetch recipient (group) recipientGroup = await UserGroups.findOneBy({ id: ps.groupId! }); - if (recipientGroup == null) { - throw new ApiError(meta.errors.noSuchGroup); - } + if (recipientGroup == null) throw new ApiError('NO_SUCH_GROUP'); // check joined const joining = await UserGroupJoinings.findOneBy({ @@ -169,9 +123,7 @@ export default define(meta, paramDef, async (ps, user) => { userGroupId: recipientGroup.id, }); - if (joining == null) { - throw new ApiError(meta.errors.groupAccessDenied); - } + if (joining == null) throw new ApiError('ACCESS_DENIED', 'You have to join a group to send a message in it.'); } let file = null; @@ -181,9 +133,7 @@ export default define(meta, paramDef, async (ps, user) => { userId: user.id, }); - if (file == null) { - throw new ApiError(meta.errors.noSuchFile); - } + if (file == null) throw new ApiError('NO_SUCH_FILE'); } return await createMessage(user, recipientUser, recipientGroup, ps.text, file); diff --git a/packages/backend/src/server/api/endpoints/messaging/messages/delete.ts b/packages/backend/src/server/api/endpoints/messaging/messages/delete.ts index 1997a8eda..4e86fa530 100644 --- a/packages/backend/src/server/api/endpoints/messaging/messages/delete.ts +++ b/packages/backend/src/server/api/endpoints/messaging/messages/delete.ts @@ -17,13 +17,7 @@ export const meta = { minInterval: SECOND, }, - errors: { - noSuchMessage: { - message: 'No such message.', - code: 'NO_SUCH_MESSAGE', - id: '54b5b326-7925-42cf-8019-130fda8b56af', - }, - }, + errors: ['NO_SUCH_MESSAGE'], } as const; export const paramDef = { @@ -41,9 +35,7 @@ export default define(meta, paramDef, async (ps, user) => { userId: user.id, }); - if (message == null) { - throw new ApiError(meta.errors.noSuchMessage); - } + if (message == null) throw new ApiError('NO_SUCH_MESSAGE'); await deleteMessage(message); }); diff --git a/packages/backend/src/server/api/endpoints/messaging/messages/read.ts b/packages/backend/src/server/api/endpoints/messaging/messages/read.ts index c02b53469..3a3372c83 100644 --- a/packages/backend/src/server/api/endpoints/messaging/messages/read.ts +++ b/packages/backend/src/server/api/endpoints/messaging/messages/read.ts @@ -10,13 +10,7 @@ export const meta = { kind: 'write:messaging', - errors: { - noSuchMessage: { - message: 'No such message.', - code: 'NO_SUCH_MESSAGE', - id: '86d56a2f-a9c3-4afb-b13c-3e9bfef9aa14', - }, - }, + errors: ['NO_SUCH_MESSAGE'], } as const; export const paramDef = { @@ -31,18 +25,16 @@ export const paramDef = { export default define(meta, paramDef, async (ps, user) => { const message = await MessagingMessages.findOneBy({ id: ps.messageId }); - if (message == null) { - throw new ApiError(meta.errors.noSuchMessage); - } + if (message == null) throw new ApiError('NO_SUCH_MESSAGE'); if (message.recipientId) { await readUserMessagingMessage(user.id, message.userId, [message.id]).catch(e => { - if (e.id === 'e140a4bf-49ce-4fb6-b67c-b78dadf6b52f') throw new ApiError(meta.errors.noSuchMessage); + if (e.id === 'e140a4bf-49ce-4fb6-b67c-b78dadf6b52f') throw new ApiError('NO_SUCH_MESSAGE'); throw e; }); } else if (message.groupId) { await readGroupMessagingMessage(user.id, message.groupId, [message.id]).catch(e => { - if (e.id === '930a270c-714a-46b2-b776-ad27276dc569') throw new ApiError(meta.errors.noSuchMessage); + if (e.id === '930a270c-714a-46b2-b776-ad27276dc569') throw new ApiError('NO_SUCH_MESSAGE'); throw e; }); } diff --git a/packages/backend/src/server/api/endpoints/mute/create.ts b/packages/backend/src/server/api/endpoints/mute/create.ts index f10fe0e2f..705fe9deb 100644 --- a/packages/backend/src/server/api/endpoints/mute/create.ts +++ b/packages/backend/src/server/api/endpoints/mute/create.ts @@ -13,25 +13,7 @@ export const meta = { kind: 'write:mutes', - errors: { - noSuchUser: { - message: 'No such user.', - code: 'NO_SUCH_USER', - id: '6fef56f3-e765-4957-88e5-c6f65329b8a5', - }, - - muteeIsYourself: { - message: 'Mutee is yourself.', - code: 'MUTEE_IS_YOURSELF', - id: 'a4619cb2-5f23-484b-9301-94c903074e10', - }, - - alreadyMuting: { - message: 'You are already muting that user.', - code: 'ALREADY_MUTING', - id: '7e7359cb-160c-4956-b08f-4d1c653cd007', - }, - }, + errors: ['NO_SUCH_USER', 'MUTEE_IS_YOURSELF', 'ALREADY_MUTING'], } as const; export const paramDef = { @@ -52,13 +34,11 @@ export default define(meta, paramDef, async (ps, user) => { const muter = user; // 自分自身 - if (user.id === ps.userId) { - throw new ApiError(meta.errors.muteeIsYourself); - } + if (user.id === ps.userId) throw new ApiError('MUTEE_IS_YOURSELF'); // Get mutee const mutee = await getUser(ps.userId).catch(e => { - if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser); + if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError('NO_SUCH_USER'); throw e; }); @@ -68,9 +48,7 @@ export default define(meta, paramDef, async (ps, user) => { muteeId: mutee.id, }); - if (exist != null) { - throw new ApiError(meta.errors.alreadyMuting); - } + if (exist != null) throw new ApiError('ALREADY_MUTING'); if (ps.expiresAt && ps.expiresAt <= Date.now()) { return; diff --git a/packages/backend/src/server/api/endpoints/mute/delete.ts b/packages/backend/src/server/api/endpoints/mute/delete.ts index eed38528a..7585aeacb 100644 --- a/packages/backend/src/server/api/endpoints/mute/delete.ts +++ b/packages/backend/src/server/api/endpoints/mute/delete.ts @@ -11,25 +11,7 @@ export const meta = { kind: 'write:mutes', - errors: { - noSuchUser: { - message: 'No such user.', - code: 'NO_SUCH_USER', - id: 'b851d00b-8ab1-4a56-8b1b-e24187cb48ef', - }, - - muteeIsYourself: { - message: 'Mutee is yourself.', - code: 'MUTEE_IS_YOURSELF', - id: 'f428b029-6b39-4d48-a1d2-cc1ae6dd5cf9', - }, - - notMuting: { - message: 'You are not muting that user.', - code: 'NOT_MUTING', - id: '5467d020-daa9-4553-81e1-135c0c35a96d', - }, - }, + errors: ['NO_SUCH_USER', 'MUTEE_IS_YOURSELF', 'NOT_MUTING'], } as const; export const paramDef = { @@ -45,13 +27,11 @@ export default define(meta, paramDef, async (ps, user) => { const muter = user; // Check if the mutee is yourself - if (user.id === ps.userId) { - throw new ApiError(meta.errors.muteeIsYourself); - } + if (user.id === ps.userId) throw new ApiError('MUTEE_IS_YOURSELF'); // Get mutee const mutee = await getUser(ps.userId).catch(e => { - if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser); + if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError('NO_SUCH_USER'); throw e; }); @@ -61,9 +41,7 @@ export default define(meta, paramDef, async (ps, user) => { muteeId: mutee.id, }); - if (exist == null) { - throw new ApiError(meta.errors.notMuting); - } + if (exist == null) throw new ApiError('NOT_MUTING'); // Delete mute await Mutings.delete({ diff --git a/packages/backend/src/server/api/endpoints/notes/clips.ts b/packages/backend/src/server/api/endpoints/notes/clips.ts index 976c11260..e20b744a1 100644 --- a/packages/backend/src/server/api/endpoints/notes/clips.ts +++ b/packages/backend/src/server/api/endpoints/notes/clips.ts @@ -19,13 +19,7 @@ export const meta = { }, }, - errors: { - noSuchNote: { - message: 'No such note.', - code: 'NO_SUCH_NOTE', - id: '47db1a1c-b0af-458d-8fb4-986e4efafe1e', - }, - }, + errors: ['NO_SUCH_NOTE'], } as const; export const paramDef = { @@ -39,7 +33,7 @@ export const paramDef = { // eslint-disable-next-line import/no-default-export export default define(meta, paramDef, async (ps, me) => { const note = await getNote(ps.noteId, me).catch(err => { - if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); + if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE'); throw err; }); diff --git a/packages/backend/src/server/api/endpoints/notes/conversation.ts b/packages/backend/src/server/api/endpoints/notes/conversation.ts index 7ee052001..b4cbc55f0 100644 --- a/packages/backend/src/server/api/endpoints/notes/conversation.ts +++ b/packages/backend/src/server/api/endpoints/notes/conversation.ts @@ -19,13 +19,7 @@ export const meta = { }, }, - errors: { - noSuchNote: { - message: 'No such note.', - code: 'NO_SUCH_NOTE', - id: 'e1035875-9551-45ec-afa8-1ded1fcb53c8', - }, - }, + errors: ['NO_SUCH_NOTE'], } as const; export const paramDef = { @@ -41,7 +35,7 @@ export const paramDef = { // eslint-disable-next-line import/no-default-export export default define(meta, paramDef, async (ps, user) => { const note = await getNote(ps.noteId, user).catch(err => { - if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); + if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE'); throw err; }); diff --git a/packages/backend/src/server/api/endpoints/notes/create.ts b/packages/backend/src/server/api/endpoints/notes/create.ts index 97cbe6677..a52f38df0 100644 --- a/packages/backend/src/server/api/endpoints/notes/create.ts +++ b/packages/backend/src/server/api/endpoints/notes/create.ts @@ -37,55 +37,7 @@ export const meta = { }, }, - errors: { - noSuchRenoteTarget: { - message: 'No such renote target.', - code: 'NO_SUCH_RENOTE_TARGET', - id: 'b5c90186-4ab0-49c8-9bba-a1f76c282ba4', - }, - - cannotReRenote: { - message: 'You can not Renote a pure Renote.', - code: 'CANNOT_RENOTE_TO_A_PURE_RENOTE', - id: 'fd4cc33e-2a37-48dd-99cc-9b806eb2031a', - }, - - noSuchReplyTarget: { - message: 'No such reply target.', - code: 'NO_SUCH_REPLY_TARGET', - id: '749ee0f6-d3da-459a-bf02-282e2da4292c', - }, - - cannotReplyToPureRenote: { - message: 'You can not reply to a pure Renote.', - code: 'CANNOT_REPLY_TO_A_PURE_RENOTE', - id: '3ac74a84-8fd5-4bb0-870f-01804f82ce15', - }, - - cannotCreateAlreadyExpiredPoll: { - message: 'Poll is already expired.', - code: 'CANNOT_CREATE_ALREADY_EXPIRED_POLL', - id: '04da457d-b083-4055-9082-955525eda5a5', - }, - - noSuchChannel: { - message: 'No such channel.', - code: 'NO_SUCH_CHANNEL', - id: 'b1653923-5453-4edc-b786-7c4f39bb0bbb', - }, - - youHaveBeenBlocked: { - message: 'You have been blocked by this user.', - code: 'YOU_HAVE_BEEN_BLOCKED', - id: 'b390d7e1-8a5e-46ed-b625-06271cafd3d3', - }, - - lessRestrictiveVisibility: { - message: 'The visibility cannot be less restrictive than the parent note.', - code: 'LESS_RESTRICTIVE_VISIBILITY', - id: 'c8ab7a7a-8852-41e2-8b24-079bbaceb585', - }, - }, + errors: ['NO_SUCH_NOTE', 'PURE_RENOTE', 'EXPIRED_POLL', 'NO_SUCH_CHANNEL', 'BLOCKED', 'LESS_RESTRICTIVE_VISIBILITY'], } as const; export const paramDef = { @@ -199,17 +151,15 @@ export default define(meta, paramDef, async (ps, user) => { if (ps.renoteId != null) { // Fetch renote to note renote = await getNote(ps.renoteId, user).catch(e => { - if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchRenoteTarget); + if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE', 'Note to be renoted not found.'); throw e; }); - if (isPureRenote(renote)) { - throw new ApiError(meta.errors.cannotReRenote); - } + if (isPureRenote(renote)) throw new ApiError('PURE_RENOTE', 'Cannot renote a pure renote.'); // check that the visibility is not less restrictive if (noteVisibilities.indexOf(renote.visibility) > noteVisibilities.indexOf(ps.visibility)) { - throw new ApiError(meta.errors.lessRestrictiveVisibility); + throw new ApiError('LESS_RESTRICTIVE_VISIBILITY', `The renote has visibility ${renote.visibility}.`); } // Check blocking @@ -218,9 +168,7 @@ export default define(meta, paramDef, async (ps, user) => { blockerId: renote.userId, blockeeId: user.id, }); - if (block) { - throw new ApiError(meta.errors.youHaveBeenBlocked); - } + if (block) throw new ApiError('BLOCKED', 'Blocked by author of note to be renoted.'); } } @@ -228,17 +176,15 @@ export default define(meta, paramDef, async (ps, user) => { if (ps.replyId != null) { // Fetch reply reply = await getNote(ps.replyId, user).catch(e => { - if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchReplyTarget); + if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE', 'Replied to note not found.'); throw e; }); - if (isPureRenote(reply)) { - throw new ApiError(meta.errors.cannotReplyToPureRenote); - } + if (isPureRenote(reply)) throw new ApiError('PURE_RENOTE', 'Cannot reply to a pure renote.'); // check that the visibility is not less restrictive if (noteVisibilities.indexOf(reply.visibility) > noteVisibilities.indexOf(ps.visibility)) { - throw new ApiError(meta.errors.lessRestrictiveVisibility); + throw new ApiError('LESS_RESTRICTIVE_VISIBILITY', `The replied to note has visibility ${reply.visibility}.`); } // Check blocking @@ -247,16 +193,14 @@ export default define(meta, paramDef, async (ps, user) => { blockerId: reply.userId, blockeeId: user.id, }); - if (block) { - throw new ApiError(meta.errors.youHaveBeenBlocked); - } + if (block) throw new ApiError('BLOCKED', 'Blocked by author of replied to note.'); } } if (ps.poll) { if (typeof ps.poll.expiresAt === 'number') { if (ps.poll.expiresAt < Date.now()) { - throw new ApiError(meta.errors.cannotCreateAlreadyExpiredPoll); + throw new ApiError('EXPIRED_POLL'); } } else if (typeof ps.poll.expiredAfter === 'number') { ps.poll.expiresAt = Date.now() + ps.poll.expiredAfter; @@ -267,9 +211,7 @@ export default define(meta, paramDef, async (ps, user) => { if (ps.channelId != null) { channel = await Channels.findOneBy({ id: ps.channelId }); - if (channel == null) { - throw new ApiError(meta.errors.noSuchChannel); - } + if (channel == null) throw new ApiError('NO_SUCH_CHANNEL'); } // 投稿を作成 diff --git a/packages/backend/src/server/api/endpoints/notes/delete.ts b/packages/backend/src/server/api/endpoints/notes/delete.ts index 8aa1af85e..f33d04782 100644 --- a/packages/backend/src/server/api/endpoints/notes/delete.ts +++ b/packages/backend/src/server/api/endpoints/notes/delete.ts @@ -18,19 +18,7 @@ export const meta = { minInterval: SECOND, }, - errors: { - noSuchNote: { - message: 'No such note.', - code: 'NO_SUCH_NOTE', - id: '490be23f-8c1f-4796-819f-94cb4f9d1630', - }, - - accessDenied: { - message: 'Access denied.', - code: 'ACCESS_DENIED', - id: 'fe8d7103-0ea8-4ec3-814d-f8b401dc69e9', - }, - }, + errors: ['ACCESS_DENIED', 'NO_SUCH_NOTE'], } as const; export const paramDef = { @@ -44,12 +32,12 @@ export const paramDef = { // eslint-disable-next-line import/no-default-export export default define(meta, paramDef, async (ps, user) => { const note = await getNote(ps.noteId, user).catch(err => { - if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); + if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE'); throw err; }); if ((!user.isAdmin && !user.isModerator) && (note.userId !== user.id)) { - throw new ApiError(meta.errors.accessDenied); + throw new ApiError('ACCESS_DENIED'); } // この操作を行うのが投稿者とは限らない(例えばモデレーター)ため diff --git a/packages/backend/src/server/api/endpoints/notes/favorites/create.ts b/packages/backend/src/server/api/endpoints/notes/favorites/create.ts index b5dd88a4e..ffcb9b9e2 100644 --- a/packages/backend/src/server/api/endpoints/notes/favorites/create.ts +++ b/packages/backend/src/server/api/endpoints/notes/favorites/create.ts @@ -11,19 +11,7 @@ export const meta = { kind: 'write:favorites', - errors: { - noSuchNote: { - message: 'No such note.', - code: 'NO_SUCH_NOTE', - id: '6dd26674-e060-4816-909a-45ba3f4da458', - }, - - alreadyFavorited: { - message: 'The note has already been marked as a favorite.', - code: 'ALREADY_FAVORITED', - id: 'a402c12b-34dd-41d2-97d8-4d2ffd96a1a6', - }, - }, + errors: ['NO_SUCH_NOTE', 'ALREADY_FAVORITED'], } as const; export const paramDef = { @@ -38,7 +26,7 @@ export const paramDef = { export default define(meta, paramDef, async (ps, user) => { // Get favoritee const note = await getNote(ps.noteId, user).catch(err => { - if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); + if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE'); throw err; }); @@ -48,9 +36,7 @@ export default define(meta, paramDef, async (ps, user) => { userId: user.id, }); - if (exist != null) { - throw new ApiError(meta.errors.alreadyFavorited); - } + if (exist != null) throw new ApiError('ALREADY_FAVORITED'); // Create favorite await NoteFavorites.insert({ diff --git a/packages/backend/src/server/api/endpoints/notes/favorites/delete.ts b/packages/backend/src/server/api/endpoints/notes/favorites/delete.ts index 3f4d39254..7c590c403 100644 --- a/packages/backend/src/server/api/endpoints/notes/favorites/delete.ts +++ b/packages/backend/src/server/api/endpoints/notes/favorites/delete.ts @@ -10,19 +10,7 @@ export const meta = { kind: 'write:favorites', - errors: { - noSuchNote: { - message: 'No such note.', - code: 'NO_SUCH_NOTE', - id: '80848a2c-398f-4343-baa9-df1d57696c56', - }, - - notFavorited: { - message: 'You have not marked that note a favorite.', - code: 'NOT_FAVORITED', - id: 'b625fc69-635e-45e9-86f4-dbefbef35af5', - }, - }, + errors: ['NO_SUCH_NOTE', 'NOT_FAVORITED'], } as const; export const paramDef = { @@ -37,7 +25,7 @@ export const paramDef = { export default define(meta, paramDef, async (ps, user) => { // Get favoritee const note = await getNote(ps.noteId, user).catch(err => { - if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); + if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE'); throw err; }); @@ -47,9 +35,7 @@ export default define(meta, paramDef, async (ps, user) => { userId: user.id, }); - if (exist == null) { - throw new ApiError(meta.errors.notFavorited); - } + if (exist == null) throw new ApiError('NOT_FAVORITED'); // Delete favorite await NoteFavorites.delete(exist.id); diff --git a/packages/backend/src/server/api/endpoints/notes/global-timeline.ts b/packages/backend/src/server/api/endpoints/notes/global-timeline.ts index 3d32e7c7a..3cc8d292a 100644 --- a/packages/backend/src/server/api/endpoints/notes/global-timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/global-timeline.ts @@ -23,13 +23,7 @@ export const meta = { }, }, - errors: { - gtlDisabled: { - message: 'Global timeline has been disabled.', - code: 'GTL_DISABLED', - id: '0332fc13-6ab2-4427-ae80-a9fadffd1a6b', - }, - }, + errors: ['TIMELINE_DISABLED'], } as const; export const paramDef = { @@ -54,7 +48,7 @@ export default define(meta, paramDef, async (ps, user) => { const m = await fetchMeta(); if (m.disableGlobalTimeline) { if (user == null || (!user.isAdmin && !user.isModerator)) { - throw new ApiError(meta.errors.gtlDisabled); + throw new ApiError('TIMELINE_DISABLED'); } } diff --git a/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts b/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts index f2e86915f..18724c981 100644 --- a/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts @@ -28,13 +28,7 @@ export const meta = { }, }, - errors: { - stlDisabled: { - message: 'Hybrid timeline has been disabled.', - code: 'STL_DISABLED', - id: '620763f4-f621-4533-ab33-0577a1a3c342', - }, - }, + errors: ['TIMELINE_DISABLED'], } as const; export const paramDef = { @@ -61,7 +55,7 @@ export const paramDef = { export default define(meta, paramDef, async (ps, user) => { const m = await fetchMeta(); if (m.disableLocalTimeline && (!user.isAdmin && !user.isModerator)) { - throw new ApiError(meta.errors.stlDisabled); + throw new ApiError('TIMELINE_DISABLED'); } //#region Construct query diff --git a/packages/backend/src/server/api/endpoints/notes/local-timeline.ts b/packages/backend/src/server/api/endpoints/notes/local-timeline.ts index 6a65c028a..2e13fb432 100644 --- a/packages/backend/src/server/api/endpoints/notes/local-timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/local-timeline.ts @@ -26,13 +26,7 @@ export const meta = { }, }, - errors: { - ltlDisabled: { - message: 'Local timeline has been disabled.', - code: 'LTL_DISABLED', - id: '45a6eb02-7695-4393-b023-dd3be9aaaefd', - }, - }, + errors: ['TIMELINE_DISABLED'], } as const; export const paramDef = { @@ -61,7 +55,7 @@ export default define(meta, paramDef, async (ps, user) => { const m = await fetchMeta(); if (m.disableLocalTimeline) { if (user == null || (!user.isAdmin && !user.isModerator)) { - throw new ApiError(meta.errors.ltlDisabled); + throw new ApiError('TIMELINE_DISABLED'); } } diff --git a/packages/backend/src/server/api/endpoints/notes/polls/vote.ts b/packages/backend/src/server/api/endpoints/notes/polls/vote.ts index 331b03971..6648e996b 100644 --- a/packages/backend/src/server/api/endpoints/notes/polls/vote.ts +++ b/packages/backend/src/server/api/endpoints/notes/polls/vote.ts @@ -19,50 +19,14 @@ export const meta = { kind: 'write:votes', - errors: { - noSuchNote: { - message: 'No such note.', - code: 'NO_SUCH_NOTE', - id: 'ecafbd2e-c283-4d6d-aecb-1a0a33b75396', - }, - - noPoll: { - message: 'The note does not attach a poll.', - code: 'NO_POLL', - id: '5f979967-52d9-4314-a911-1c673727f92f', - }, - - invalidChoice: { - message: 'Choice ID is invalid.', - code: 'INVALID_CHOICE', - id: 'e0cc9a04-f2e8-41e4-a5f1-4127293260cc', - }, - - alreadyVoted: { - message: 'You have already voted.', - code: 'ALREADY_VOTED', - id: '0963fc77-efac-419b-9424-b391608dc6d8', - }, - - alreadyExpired: { - message: 'The poll is already expired.', - code: 'ALREADY_EXPIRED', - id: '1022a357-b085-4054-9083-8f8de358337e', - }, - - youHaveBeenBlocked: { - message: 'You cannot vote this poll because you have been blocked by this user.', - code: 'YOU_HAVE_BEEN_BLOCKED', - id: '85a5377e-b1e9-4617-b0b9-5bea73331e49', - }, - }, + errors: ['NO_SUCH_NOTE', 'INVALID_CHOICE', 'ALREADY_VOTED', 'EXPIRED_POLL', 'BLOCKED'], } as const; export const paramDef = { type: 'object', properties: { noteId: { type: 'string', format: 'misskey:id' }, - choice: { type: 'integer' }, + choice: { type: 'integer', minimum: 0 }, }, required: ['noteId', 'choice'], } as const; @@ -73,12 +37,12 @@ export default define(meta, paramDef, async (ps, user) => { // Get votee const note = await getNote(ps.noteId, user).catch(err => { - if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); + if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE'); throw err; }); if (!note.hasPoll) { - throw new ApiError(meta.errors.noPoll); + throw new ApiError('NO_SUCH_NOTE', 'The note exists but does not have a poll attached.'); } // Check blocking @@ -87,19 +51,17 @@ export default define(meta, paramDef, async (ps, user) => { blockerId: note.userId, blockeeId: user.id, }); - if (block) { - throw new ApiError(meta.errors.youHaveBeenBlocked); - } + if (block) throw new ApiError('BLOCKED'); } const poll = await Polls.findOneByOrFail({ noteId: note.id }); if (poll.expiresAt && poll.expiresAt < createdAt) { - throw new ApiError(meta.errors.alreadyExpired); + throw new ApiError('EXPIRED_POLL'); } if (poll.choices[ps.choice] == null) { - throw new ApiError(meta.errors.invalidChoice); + throw new ApiError('INVALID_CHOICE', `There are only ${poll.choices.length} choices.`); } // if already voted @@ -111,10 +73,10 @@ export default define(meta, paramDef, async (ps, user) => { if (exist.length) { if (poll.multiple) { if (exist.some(x => x.choice === ps.choice)) { - throw new ApiError(meta.errors.alreadyVoted); + throw new ApiError('ALREADY_VOTED', 'This is a multiple choice poll, but you already voted for that option.'); } } else { - throw new ApiError(meta.errors.alreadyVoted); + throw new ApiError('ALREADY_VOTED', 'This is a single choice poll.'); } } diff --git a/packages/backend/src/server/api/endpoints/notes/reactions.ts b/packages/backend/src/server/api/endpoints/notes/reactions.ts index b3b8e01c5..d7a63c056 100644 --- a/packages/backend/src/server/api/endpoints/notes/reactions.ts +++ b/packages/backend/src/server/api/endpoints/notes/reactions.ts @@ -23,13 +23,7 @@ export const meta = { }, }, - errors: { - noSuchNote: { - message: 'No such note.', - code: 'NO_SUCH_NOTE', - id: '263fff3d-d0e1-4af4-bea7-8408059b451a', - }, - }, + errors: ['NO_SUCH_NOTE'], } as const; export const paramDef = { @@ -53,7 +47,7 @@ export const paramDef = { export default define(meta, paramDef, async (ps, user) => { // check note visibility const note = await getNote(ps.noteId, user).catch(err => { - if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); + if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE'); throw err; }); diff --git a/packages/backend/src/server/api/endpoints/notes/reactions/create.ts b/packages/backend/src/server/api/endpoints/notes/reactions/create.ts index 5d27ab8fb..d99dc314e 100644 --- a/packages/backend/src/server/api/endpoints/notes/reactions/create.ts +++ b/packages/backend/src/server/api/endpoints/notes/reactions/create.ts @@ -10,25 +10,7 @@ export const meta = { kind: 'write:reactions', - errors: { - noSuchNote: { - message: 'No such note.', - code: 'NO_SUCH_NOTE', - id: '033d0620-5bfe-4027-965d-980b0c85a3ea', - }, - - alreadyReacted: { - message: 'You are already reacting to that note.', - code: 'ALREADY_REACTED', - id: '71efcf98-86d6-4e2b-b2ad-9d032369366b', - }, - - youHaveBeenBlocked: { - message: 'You cannot react this note because you have been blocked by this user.', - code: 'YOU_HAVE_BEEN_BLOCKED', - id: '20ef5475-9f38-4e4c-bd33-de6d979498ec', - }, - }, + errors: ['NO_SUCH_NOTE', 'ALREADY_REACTED', 'BLOCKED'], } as const; export const paramDef = { @@ -43,12 +25,12 @@ export const paramDef = { // eslint-disable-next-line import/no-default-export export default define(meta, paramDef, async (ps, user) => { const note = await getNote(ps.noteId, user).catch(err => { - if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); + if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE'); throw err; }); await createReaction(user, note, ps.reaction).catch(e => { - if (e.id === '51c42bb4-931a-456b-bff7-e5a8a70dd298') throw new ApiError(meta.errors.alreadyReacted); - if (e.id === 'e70412a4-7197-4726-8e74-f3e0deb92aa7') throw new ApiError(meta.errors.youHaveBeenBlocked); + if (e.id === '51c42bb4-931a-456b-bff7-e5a8a70dd298') throw new ApiError('ALREADY_REACTED'); + if (e.id === 'e70412a4-7197-4726-8e74-f3e0deb92aa7') throw new ApiError('BLOCKED'); throw e; }); return; diff --git a/packages/backend/src/server/api/endpoints/notes/reactions/delete.ts b/packages/backend/src/server/api/endpoints/notes/reactions/delete.ts index a5c50e4c2..b974fc3ef 100644 --- a/packages/backend/src/server/api/endpoints/notes/reactions/delete.ts +++ b/packages/backend/src/server/api/endpoints/notes/reactions/delete.ts @@ -17,19 +17,7 @@ export const meta = { minInterval: 3 * SECOND, }, - errors: { - noSuchNote: { - message: 'No such note.', - code: 'NO_SUCH_NOTE', - id: '764d9fce-f9f2-4a0e-92b1-6ceac9a7ad37', - }, - - notReacted: { - message: 'You are not reacting to that note.', - code: 'NOT_REACTED', - id: '92f4426d-4196-4125-aa5b-02943e2ec8fc', - }, - }, + errors: ['NO_SUCH_NOTE', 'NOT_REACTED'], } as const; export const paramDef = { @@ -43,11 +31,11 @@ export const paramDef = { // eslint-disable-next-line import/no-default-export export default define(meta, paramDef, async (ps, user) => { const note = await getNote(ps.noteId, user).catch(err => { - if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); + if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE'); throw err; }); await deleteReaction(user, note).catch(e => { - if (e.id === '60527ec9-b4cb-4a88-a6bd-32d3ad26817d') throw new ApiError(meta.errors.notReacted); + if (e.id === '60527ec9-b4cb-4a88-a6bd-32d3ad26817d') throw new ApiError('NOT_REACTED'); throw e; }); }); diff --git a/packages/backend/src/server/api/endpoints/notes/renotes.ts b/packages/backend/src/server/api/endpoints/notes/renotes.ts index 1fa9c5230..a0402cf2f 100644 --- a/packages/backend/src/server/api/endpoints/notes/renotes.ts +++ b/packages/backend/src/server/api/endpoints/notes/renotes.ts @@ -22,13 +22,7 @@ export const meta = { }, }, - errors: { - noSuchNote: { - message: 'No such note.', - code: 'NO_SUCH_NOTE', - id: '12908022-2e21-46cd-ba6a-3edaf6093f46', - }, - }, + errors: ['NO_SUCH_NOTE'], } as const; export const paramDef = { @@ -45,7 +39,7 @@ export const paramDef = { // eslint-disable-next-line import/no-default-export export default define(meta, paramDef, async (ps, user) => { const note = await getNote(ps.noteId, user).catch(err => { - if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); + if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE'); throw err; }); diff --git a/packages/backend/src/server/api/endpoints/notes/search.ts b/packages/backend/src/server/api/endpoints/notes/search.ts index 1d393f796..8d8b21238 100644 --- a/packages/backend/src/server/api/endpoints/notes/search.ts +++ b/packages/backend/src/server/api/endpoints/notes/search.ts @@ -22,9 +22,6 @@ export const meta = { ref: 'Note', }, }, - - errors: { - }, } as const; export const paramDef = { diff --git a/packages/backend/src/server/api/endpoints/notes/show.ts b/packages/backend/src/server/api/endpoints/notes/show.ts index c9c148747..b2dde8647 100644 --- a/packages/backend/src/server/api/endpoints/notes/show.ts +++ b/packages/backend/src/server/api/endpoints/notes/show.ts @@ -14,13 +14,7 @@ export const meta = { ref: 'Note', }, - errors: { - noSuchNote: { - message: 'No such note.', - code: 'NO_SUCH_NOTE', - id: '24fcbfc6-2e37-42b6-8388-c29b3861a08d', - }, - }, + errors: ['NO_SUCH_NOTE'], } as const; export const paramDef = { @@ -34,7 +28,7 @@ export const paramDef = { // eslint-disable-next-line import/no-default-export export default define(meta, paramDef, async (ps, user) => { const note = await getNote(ps.noteId, user).catch(err => { - if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); + if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE'); throw err; }); @@ -42,7 +36,7 @@ export default define(meta, paramDef, async (ps, user) => { // FIXME: packing with detail may throw an error if the reply or renote is not visible (#8774) detail: true, }).catch(err => { - if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); + if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE'); throw err; }); }); diff --git a/packages/backend/src/server/api/endpoints/notes/thread-muting/create.ts b/packages/backend/src/server/api/endpoints/notes/thread-muting/create.ts index efcafe306..dddb55fcb 100644 --- a/packages/backend/src/server/api/endpoints/notes/thread-muting/create.ts +++ b/packages/backend/src/server/api/endpoints/notes/thread-muting/create.ts @@ -13,13 +13,7 @@ export const meta = { kind: 'write:account', - errors: { - noSuchNote: { - message: 'No such note.', - code: 'NO_SUCH_NOTE', - id: '5ff67ada-ed3b-2e71-8e87-a1a421e177d2', - }, - }, + errors: ['NO_SUCH_NOTE'], } as const; export const paramDef = { @@ -41,7 +35,7 @@ export const paramDef = { // eslint-disable-next-line import/no-default-export export default define(meta, paramDef, async (ps, user) => { const note = await getNote(ps.noteId, user).catch(err => { - if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); + if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE'); throw err; }); diff --git a/packages/backend/src/server/api/endpoints/notes/thread-muting/delete.ts b/packages/backend/src/server/api/endpoints/notes/thread-muting/delete.ts index cbc0e5ce5..c1ea564eb 100644 --- a/packages/backend/src/server/api/endpoints/notes/thread-muting/delete.ts +++ b/packages/backend/src/server/api/endpoints/notes/thread-muting/delete.ts @@ -10,13 +10,7 @@ export const meta = { kind: 'write:account', - errors: { - noSuchNote: { - message: 'No such note.', - code: 'NO_SUCH_NOTE', - id: 'bddd57ac-ceb3-b29d-4334-86ea5fae481a', - }, - }, + errors: ['NO_SUCH_NOTE'], } as const; export const paramDef = { @@ -30,7 +24,7 @@ export const paramDef = { // eslint-disable-next-line import/no-default-export export default define(meta, paramDef, async (ps, user) => { const note = await getNote(ps.noteId, user).catch(err => { - if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); + if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE'); throw err; }); diff --git a/packages/backend/src/server/api/endpoints/notes/translate.ts b/packages/backend/src/server/api/endpoints/notes/translate.ts index c29623aa8..f62e07b4e 100644 --- a/packages/backend/src/server/api/endpoints/notes/translate.ts +++ b/packages/backend/src/server/api/endpoints/notes/translate.ts @@ -55,13 +55,7 @@ export const meta = { }, }, - errors: { - noSuchNote: { - message: 'No such note.', - code: 'NO_SUCH_NOTE', - id: 'bea9b03f-36e0-49c5-a4db-627a029f8971', - }, - }, + errors: ['NO_SUCH_NOTE'], } as const; // List of permitted languages from https://www.deepl.com/docs-api/translate-text/translate-text/ @@ -116,7 +110,7 @@ export const paramDef = { // eslint-disable-next-line import/no-default-export export default define(meta, paramDef, async (ps, user) => { const note = await getNote(ps.noteId, user).catch(err => { - if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); + if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE'); throw err; }); diff --git a/packages/backend/src/server/api/endpoints/notes/unrenote.ts b/packages/backend/src/server/api/endpoints/notes/unrenote.ts index 68fab7889..b7bb3009a 100644 --- a/packages/backend/src/server/api/endpoints/notes/unrenote.ts +++ b/packages/backend/src/server/api/endpoints/notes/unrenote.ts @@ -18,13 +18,7 @@ export const meta = { minInterval: SECOND, }, - errors: { - noSuchNote: { - message: 'No such note.', - code: 'NO_SUCH_NOTE', - id: 'efd4a259-2442-496b-8dd7-b255aa1a160f', - }, - }, + errors: ['NO_SUCH_NOTE'], } as const; export const paramDef = { @@ -38,7 +32,7 @@ export const paramDef = { // eslint-disable-next-line import/no-default-export export default define(meta, paramDef, async (ps, user) => { const note = await getNote(ps.noteId, user).catch(err => { - if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); + if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE'); throw err; }); diff --git a/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts b/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts index e603a8f62..c95efd6b6 100644 --- a/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts @@ -21,13 +21,7 @@ export const meta = { }, }, - errors: { - noSuchList: { - message: 'No such list.', - code: 'NO_SUCH_LIST', - id: '8fb1fbd5-e476-4c37-9fb0-43d55b63a2ff', - }, - }, + errors: ['NO_SUCH_USER_LIST'], } as const; export const paramDef = { @@ -58,9 +52,7 @@ export default define(meta, paramDef, async (ps, user) => { userId: user.id, }); - if (list == null) { - throw new ApiError(meta.errors.noSuchList); - } + if (list == null) throw new ApiError('NO_SUCH_USER_LIST'); //#region Construct query const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId) diff --git a/packages/backend/src/server/api/endpoints/notes/watching/create.ts b/packages/backend/src/server/api/endpoints/notes/watching/create.ts index 07c0517a1..002e9b007 100644 --- a/packages/backend/src/server/api/endpoints/notes/watching/create.ts +++ b/packages/backend/src/server/api/endpoints/notes/watching/create.ts @@ -10,13 +10,7 @@ export const meta = { kind: 'write:account', - errors: { - noSuchNote: { - message: 'No such note.', - code: 'NO_SUCH_NOTE', - id: 'ea0e37a6-90a3-4f58-ba6b-c328ca206fc7', - }, - }, + errors: ['NO_SUCH_NOTE'], } as const; export const paramDef = { @@ -30,7 +24,7 @@ export const paramDef = { // eslint-disable-next-line import/no-default-export export default define(meta, paramDef, async (ps, user) => { const note = await getNote(ps.noteId, user).catch(err => { - if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); + if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE'); throw err; }); diff --git a/packages/backend/src/server/api/endpoints/notes/watching/delete.ts b/packages/backend/src/server/api/endpoints/notes/watching/delete.ts index 5949c9cd1..54f7163b9 100644 --- a/packages/backend/src/server/api/endpoints/notes/watching/delete.ts +++ b/packages/backend/src/server/api/endpoints/notes/watching/delete.ts @@ -10,13 +10,7 @@ export const meta = { kind: 'write:account', - errors: { - noSuchNote: { - message: 'No such note.', - code: 'NO_SUCH_NOTE', - id: '09b3695c-f72c-4731-a428-7cff825fc82e', - }, - }, + errors: ['NO_SUCH_NOTE'], } as const; export const paramDef = { @@ -30,7 +24,7 @@ export const paramDef = { // eslint-disable-next-line import/no-default-export export default define(meta, paramDef, async (ps, user) => { const note = await getNote(ps.noteId, user).catch(err => { - if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote); + if (err.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError('NO_SUCH_NOTE'); throw err; }); diff --git a/packages/backend/src/server/api/endpoints/notifications/create.ts b/packages/backend/src/server/api/endpoints/notifications/create.ts index 80d513d8d..e45ebdd1d 100644 --- a/packages/backend/src/server/api/endpoints/notifications/create.ts +++ b/packages/backend/src/server/api/endpoints/notifications/create.ts @@ -7,9 +7,6 @@ export const meta = { requireCredential: true, kind: 'write:notifications', - - errors: { - }, } as const; export const paramDef = { diff --git a/packages/backend/src/server/api/endpoints/notifications/read.ts b/packages/backend/src/server/api/endpoints/notifications/read.ts index 7bce525a5..f7b64fddb 100644 --- a/packages/backend/src/server/api/endpoints/notifications/read.ts +++ b/packages/backend/src/server/api/endpoints/notifications/read.ts @@ -10,13 +10,8 @@ export const meta = { description: 'Mark a notification as read.', - errors: { - noSuchNotification: { - message: 'No such notification.', - code: 'NO_SUCH_NOTIFICATION', - id: 'efa929d5-05b5-47d1-beec-e6a4dbed011e', - }, - }, + // FIXME: This error makes sense here but will never be thrown here. + // errors: ['NO_SUCH_NOTIFICATION'], } as const; export const paramDef = { diff --git a/packages/backend/src/server/api/endpoints/page-push.ts b/packages/backend/src/server/api/endpoints/page-push.ts index 6dd3ede85..e69b279ea 100644 --- a/packages/backend/src/server/api/endpoints/page-push.ts +++ b/packages/backend/src/server/api/endpoints/page-push.ts @@ -7,13 +7,7 @@ export const meta = { requireCredential: true, secure: true, - errors: { - noSuchPage: { - message: 'No such page.', - code: 'NO_SUCH_PAGE', - id: '4a13ad31-6729-46b4-b9af-e86b265c2e74', - }, - }, + errors: ['NO_SUCH_PAGE'], } as const; export const paramDef = { @@ -29,9 +23,7 @@ export const paramDef = { // eslint-disable-next-line import/no-default-export export default define(meta, paramDef, async (ps, user) => { const page = await Pages.findOneBy({ id: ps.pageId }); - if (page == null) { - throw new ApiError(meta.errors.noSuchPage); - } + if (page == null) throw new ApiError('NO_SUCH_PAGE'); publishMainStream(page.userId, 'pageEvent', { pageId: ps.pageId, diff --git a/packages/backend/src/server/api/endpoints/pages/create.ts b/packages/backend/src/server/api/endpoints/pages/create.ts index 8eafe556c..7649792cd 100644 --- a/packages/backend/src/server/api/endpoints/pages/create.ts +++ b/packages/backend/src/server/api/endpoints/pages/create.ts @@ -23,18 +23,7 @@ export const meta = { ref: 'Page', }, - errors: { - noSuchFile: { - message: 'No such file.', - code: 'NO_SUCH_FILE', - id: 'b7b97489-0f66-4b12-a5ff-b21bd63f6e1c', - }, - nameAlreadyExists: { - message: 'Specified name already exists.', - code: 'NAME_ALREADY_EXISTS', - id: '4650348e-301c-499a-83c9-6aa988c66bc1', - }, - }, + errors: ['NO_SUCH_FILE', 'NAME_ALREADY_EXISTS'], } as const; export const paramDef = { @@ -61,9 +50,7 @@ export default define(meta, paramDef, async (ps, user) => { userId: user.id, }); - if (eyeCatchingImage == null) { - throw new ApiError(meta.errors.noSuchFile); - } + if (eyeCatchingImage == null) throw new ApiError('NO_SUCH_FILE'); } await Pages.findBy({ @@ -71,7 +58,7 @@ export default define(meta, paramDef, async (ps, user) => { name: ps.name, }).then(result => { if (result.length > 0) { - throw new ApiError(meta.errors.nameAlreadyExists); + throw new ApiError('NAME_ALREADY_EXISTS'); } }); diff --git a/packages/backend/src/server/api/endpoints/pages/delete.ts b/packages/backend/src/server/api/endpoints/pages/delete.ts index a7708e658..b8f8d43c7 100644 --- a/packages/backend/src/server/api/endpoints/pages/delete.ts +++ b/packages/backend/src/server/api/endpoints/pages/delete.ts @@ -9,19 +9,7 @@ export const meta = { kind: 'write:pages', - errors: { - noSuchPage: { - message: 'No such page.', - code: 'NO_SUCH_PAGE', - id: 'eb0c6e1d-d519-4764-9486-52a7e1c6392a', - }, - - accessDenied: { - message: 'Access denied.', - code: 'ACCESS_DENIED', - id: '8b741b3e-2c22-44b3-a15f-29949aa1601e', - }, - }, + errors: ['NO_SUCH_PAGE'], } as const; export const paramDef = { @@ -34,13 +22,11 @@ export const paramDef = { // eslint-disable-next-line import/no-default-export export default define(meta, paramDef, async (ps, user) => { - const page = await Pages.findOneBy({ id: ps.pageId }); - if (page == null) { - throw new ApiError(meta.errors.noSuchPage); - } - if (page.userId !== user.id) { - throw new ApiError(meta.errors.accessDenied); - } + const page = await Pages.findOneBy({ + id: ps.pageId, + userId: user.id, + }); + if (page == null) throw new ApiError('NO_SUCH_PAGE'); await Pages.delete(page.id); }); diff --git a/packages/backend/src/server/api/endpoints/pages/like.ts b/packages/backend/src/server/api/endpoints/pages/like.ts index b4aab40d3..19b0d99ed 100644 --- a/packages/backend/src/server/api/endpoints/pages/like.ts +++ b/packages/backend/src/server/api/endpoints/pages/like.ts @@ -10,19 +10,7 @@ export const meta = { kind: 'write:page-likes', - errors: { - noSuchPage: { - message: 'No such page.', - code: 'NO_SUCH_PAGE', - id: 'cc98a8a2-0dc3-4123-b198-62c71df18ed3', - }, - - alreadyLiked: { - message: 'The page has already been liked.', - code: 'ALREADY_LIKED', - id: 'cc98a8a2-0dc3-4123-b198-62c71df18ed3', - }, - }, + errors: ['ALREADY_LIKED', 'NO_SUCH_PAGE'], } as const; export const paramDef = { @@ -36,9 +24,7 @@ export const paramDef = { // eslint-disable-next-line import/no-default-export export default define(meta, paramDef, async (ps, user) => { const page = await Pages.findOneBy({ id: ps.pageId }); - if (page == null) { - throw new ApiError(meta.errors.noSuchPage); - } + if (page == null) throw new ApiError('NO_SUCH_PAGE'); // if already liked const exist = await PageLikes.findOneBy({ @@ -46,9 +32,7 @@ export default define(meta, paramDef, async (ps, user) => { userId: user.id, }); - if (exist != null) { - throw new ApiError(meta.errors.alreadyLiked); - } + if (exist != null) throw new ApiError('ALREADY_LIKED'); // Create like await PageLikes.insert({ diff --git a/packages/backend/src/server/api/endpoints/pages/show.ts b/packages/backend/src/server/api/endpoints/pages/show.ts index 5d37e86b9..9861efdaa 100644 --- a/packages/backend/src/server/api/endpoints/pages/show.ts +++ b/packages/backend/src/server/api/endpoints/pages/show.ts @@ -15,13 +15,7 @@ export const meta = { ref: 'Page', }, - errors: { - noSuchPage: { - message: 'No such page.', - code: 'NO_SUCH_PAGE', - id: '222120c0-3ead-4528-811b-b96f233388d7', - }, - }, + errors: ['NO_SUCH_PAGE'], } as const; export const paramDef = { @@ -62,9 +56,7 @@ export default define(meta, paramDef, async (ps, user) => { } } - if (page == null) { - throw new ApiError(meta.errors.noSuchPage); - } + if (page == null) throw new ApiError('NO_SUCH_PAGE'); return await Pages.pack(page, user); }); diff --git a/packages/backend/src/server/api/endpoints/pages/unlike.ts b/packages/backend/src/server/api/endpoints/pages/unlike.ts index 6b3a2bec1..5c18312d3 100644 --- a/packages/backend/src/server/api/endpoints/pages/unlike.ts +++ b/packages/backend/src/server/api/endpoints/pages/unlike.ts @@ -9,19 +9,7 @@ export const meta = { kind: 'write:page-likes', - errors: { - noSuchPage: { - message: 'No such page.', - code: 'NO_SUCH_PAGE', - id: 'a0d41e20-1993-40bd-890e-f6e560ae648e', - }, - - notLiked: { - message: 'You have not liked that page.', - code: 'NOT_LIKED', - id: 'f5e586b0-ce93-4050-b0e3-7f31af5259ee', - }, - }, + errors: ['NO_SUCH_PAGE', 'NOT_LIKED'], } as const; export const paramDef = { @@ -35,18 +23,14 @@ export const paramDef = { // eslint-disable-next-line import/no-default-export export default define(meta, paramDef, async (ps, user) => { const page = await Pages.findOneBy({ id: ps.pageId }); - if (page == null) { - throw new ApiError(meta.errors.noSuchPage); - } + if (page == null) throw new ApiError('NO_SUCH_PAGE'); const exist = await PageLikes.findOneBy({ pageId: page.id, userId: user.id, }); - if (exist == null) { - throw new ApiError(meta.errors.notLiked); - } + if (exist == null) throw new ApiError('NOT_LIKED'); // Delete like await PageLikes.delete(exist.id); diff --git a/packages/backend/src/server/api/endpoints/pages/update.ts b/packages/backend/src/server/api/endpoints/pages/update.ts index 319af3b88..f82f754d1 100644 --- a/packages/backend/src/server/api/endpoints/pages/update.ts +++ b/packages/backend/src/server/api/endpoints/pages/update.ts @@ -16,30 +16,7 @@ export const meta = { max: 300, }, - errors: { - noSuchPage: { - message: 'No such page.', - code: 'NO_SUCH_PAGE', - id: '21149b9e-3616-4778-9592-c4ce89f5a864', - }, - - accessDenied: { - message: 'Access denied.', - code: 'ACCESS_DENIED', - id: '3c15cd52-3b4b-4274-967d-6456fc4f792b', - }, - - noSuchFile: { - message: 'No such file.', - code: 'NO_SUCH_FILE', - id: 'cfc23c7c-3887-490e-af30-0ed576703c82', - }, - nameAlreadyExists: { - message: 'Specified name already exists.', - code: 'NAME_ALREADY_EXISTS', - id: '2298a392-d4a1-44c5-9ebb-ac1aeaa5a9ab', - }, - }, + errors: ['NAME_ALREADY_EXISTS', 'NO_SUCH_FILE', 'NO_SUCH_PAGE'], } as const; export const paramDef = { @@ -60,13 +37,11 @@ export const paramDef = { // eslint-disable-next-line import/no-default-export export default define(meta, paramDef, async (ps, user) => { - const page = await Pages.findOneBy({ id: ps.pageId }); - if (page == null) { - throw new ApiError(meta.errors.noSuchPage); - } - if (page.userId !== user.id) { - throw new ApiError(meta.errors.accessDenied); - } + const page = await Pages.findOneBy({ + id: ps.pageId, + userId: user.id, + }); + if (page == null) throw new ApiError('NO_SUCH_PAGE'); let eyeCatchingImage = null; if (ps.eyeCatchingImageId != null) { @@ -75,9 +50,7 @@ export default define(meta, paramDef, async (ps, user) => { userId: user.id, }); - if (eyeCatchingImage == null) { - throw new ApiError(meta.errors.noSuchFile); - } + if (eyeCatchingImage == null) throw new ApiError('NO_SUCH_FILE'); } await Pages.findBy({ @@ -85,9 +58,7 @@ export default define(meta, paramDef, async (ps, user) => { userId: user.id, name: ps.name, }).then(result => { - if (result.length > 0) { - throw new ApiError(meta.errors.nameAlreadyExists); - } + if (result.length > 0) throw new ApiError('NAME_ALREADY_EXISTS'); }); await Pages.update(page.id, { diff --git a/packages/backend/src/server/api/endpoints/renote-mute/create.ts b/packages/backend/src/server/api/endpoints/renote-mute/create.ts index e1db204b7..9320c4e2c 100644 --- a/packages/backend/src/server/api/endpoints/renote-mute/create.ts +++ b/packages/backend/src/server/api/endpoints/renote-mute/create.ts @@ -13,25 +13,7 @@ export const meta = { kind: 'write:mutes', - errors: { - noSuchUser: { - message: 'No such user.', - code: 'NO_SUCH_USER', - id: '6fef56f3-e765-4957-88e5-c6f65329b8a5', - }, - - muteeIsYourself: { - message: 'Mutee is yourself.', - code: 'MUTEE_IS_YOURSELF', - id: 'a4619cb2-5f23-484b-9301-94c903074e10', - }, - - alreadyMuting: { - message: 'You are already muting that user.', - code: 'ALREADY_MUTING', - id: '7e7359cb-160c-4956-b08f-4d1c653cd007', - }, - }, + errors: ['NO_SUCH_USER', 'MUTEE_IS_YOURSELF', 'ALREADY_MUTING'], } as const; export const paramDef = { @@ -47,13 +29,11 @@ export default define(meta, paramDef, async (ps, user) => { const muter = user; // Check if the mutee is yourself - if (user.id === ps.userId) { - throw new ApiError(meta.errors.muteeIsYourself); - } + if (user.id === ps.userId) throw new ApiError('MUTEE_IS_YOURSELF'); // Get mutee const mutee = await getUser(ps.userId).catch(e => { - if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser); + if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError('NO_SUCH_USER'); throw e; }); @@ -63,9 +43,7 @@ export default define(meta, paramDef, async (ps, user) => { muteeId: mutee.id, }); - if (exist != null) { - throw new ApiError(meta.errors.alreadyMuting); - } + if (exist != null) throw new ApiError('ALREADY_MUTING'); // Create mute await RenoteMutings.insert({ diff --git a/packages/backend/src/server/api/endpoints/renote-mute/delete.ts b/packages/backend/src/server/api/endpoints/renote-mute/delete.ts index bdfaae263..0f7c4cde7 100644 --- a/packages/backend/src/server/api/endpoints/renote-mute/delete.ts +++ b/packages/backend/src/server/api/endpoints/renote-mute/delete.ts @@ -11,25 +11,7 @@ export const meta = { kind: 'write:mutes', - errors: { - noSuchUser: { - message: 'No such user.', - code: 'NO_SUCH_USER', - id: 'b851d00b-8ab1-4a56-8b1b-e24187cb48ef', - }, - - muteeIsYourself: { - message: 'Mutee is yourself.', - code: 'MUTEE_IS_YOURSELF', - id: 'f428b029-6b39-4d48-a1d2-cc1ae6dd5cf9', - }, - - notMuting: { - message: 'You are not muting that user.', - code: 'NOT_MUTING', - id: '5467d020-daa9-4553-81e1-135c0c35a96d', - }, - }, + errors: ['NO_SUCH_USER', 'MUTEE_IS_YOURSELF', 'NOT_MUTING'], } as const; export const paramDef = { @@ -45,13 +27,11 @@ export default define(meta, paramDef, async (ps, user) => { const muter = user; // Check if the mutee is yourself - if (user.id === ps.userId) { - throw new ApiError(meta.errors.muteeIsYourself); - } + if (user.id === ps.userId) throw new ApiError('MUTEE_IS_YOURSELF'); // Get mutee const mutee = await getUser(ps.userId).catch(e => { - if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser); + if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError('NO_SUCH_USER'); throw e; }); @@ -61,9 +41,7 @@ export default define(meta, paramDef, async (ps, user) => { muteeId: mutee.id, }); - if (exist == null) { - throw new ApiError(meta.errors.notMuting); - } + if (exist == null) throw new ApiError('NOT_MUTING'); // Delete mute await RenoteMutings.delete({ diff --git a/packages/backend/src/server/api/endpoints/reset-db.ts b/packages/backend/src/server/api/endpoints/reset-db.ts index 7f17339e9..1d145c31d 100644 --- a/packages/backend/src/server/api/endpoints/reset-db.ts +++ b/packages/backend/src/server/api/endpoints/reset-db.ts @@ -7,10 +7,6 @@ export const meta = { requireCredential: false, description: 'Only available when running with NODE_ENV=testing. Reset the database and flush Redis.', - - errors: { - - }, } as const; export const paramDef = { diff --git a/packages/backend/src/server/api/endpoints/reset-password.ts b/packages/backend/src/server/api/endpoints/reset-password.ts index 5ed4600ec..51b26a2b0 100644 --- a/packages/backend/src/server/api/endpoints/reset-password.ts +++ b/packages/backend/src/server/api/endpoints/reset-password.ts @@ -15,13 +15,7 @@ export const meta = { max: 1, }, - errors: { - noSuchResetRequest: { - message: 'No such reset request.', - code: 'NO_SUCH_RESET_REQUEST', - id: '6382759d-294c-43de-89b3-4e825006ca43', - }, - }, + errors: ['NO_SUCH_RESET_REQUEST'], } as const; export const paramDef = { @@ -38,7 +32,7 @@ export default define(meta, paramDef, async (ps, user) => { const req = await PasswordResetRequests.findOneBy({ token: ps.token, }); - if (req == null) throw new ApiError(meta.errors.noSuchResetRequest); + if (req == null) throw new ApiError('NO_SUCH_RESET_REQUEST'); // expires after 30 minutes // This is a secondary check just in case the expiry task is broken, @@ -46,7 +40,7 @@ export default define(meta, paramDef, async (ps, user) => { // else strange is going on. if (Date.now() - req.createdAt.getTime() > 30 * MINUTE) { await PasswordResetRequests.delete(req.id); - throw new ApiError(meta.errors.noSuchResetRequest); + throw new ApiError('NO_SUCH_RESET_REQUEST'); } // Generate hash of password diff --git a/packages/backend/src/server/api/endpoints/users/followers.ts b/packages/backend/src/server/api/endpoints/users/followers.ts index 7f9f98076..e395c3f79 100644 --- a/packages/backend/src/server/api/endpoints/users/followers.ts +++ b/packages/backend/src/server/api/endpoints/users/followers.ts @@ -22,19 +22,7 @@ export const meta = { }, }, - errors: { - noSuchUser: { - message: 'No such user.', - code: 'NO_SUCH_USER', - id: '27fa5435-88ab-43de-9360-387de88727cd', - }, - - forbidden: { - message: 'Forbidden.', - code: 'FORBIDDEN', - id: '3c6a84db-d619-26af-ca14-06232a21df8a', - }, - }, + errors: ['NO_SUCH_USER', 'ACCESS_DENIED'], } as const; export const paramDef = { @@ -71,26 +59,24 @@ export default define(meta, paramDef, async (ps, me) => { ? { id: ps.userId } : { usernameLower: ps.username!.toLowerCase(), host: toPunyNullable(ps.host) ?? IsNull() }); - if (user == null) { - throw new ApiError(meta.errors.noSuchUser); - } + if (user == null) throw new ApiError('NO_SUCH_USER'); const profile = await UserProfiles.findOneByOrFail({ userId: user.id }); if (profile.ffVisibility === 'private') { if (me == null || (me.id !== user.id)) { - throw new ApiError(meta.errors.forbidden); + throw new ApiError('ACCESS_DENIED'); } } else if (profile.ffVisibility === 'followers') { if (me == null) { - throw new ApiError(meta.errors.forbidden); + throw new ApiError('ACCESS_DENIED'); } else if (me.id !== user.id) { const following = await Followings.findOneBy({ followeeId: user.id, followerId: me.id, }); if (following == null) { - throw new ApiError(meta.errors.forbidden); + throw new ApiError('ACCESS_DENIED'); } } } diff --git a/packages/backend/src/server/api/endpoints/users/following.ts b/packages/backend/src/server/api/endpoints/users/following.ts index 0aaa810f7..51ad75a77 100644 --- a/packages/backend/src/server/api/endpoints/users/following.ts +++ b/packages/backend/src/server/api/endpoints/users/following.ts @@ -22,19 +22,7 @@ export const meta = { }, }, - errors: { - noSuchUser: { - message: 'No such user.', - code: 'NO_SUCH_USER', - id: '63e4aba4-4156-4e53-be25-c9559e42d71b', - }, - - forbidden: { - message: 'Forbidden.', - code: 'FORBIDDEN', - id: 'f6cdb0df-c19f-ec5c-7dbb-0ba84a1f92ba', - }, - }, + errors: ['ACCESS_DENIED', 'NO_SUCH_USER'], } as const; export const paramDef = { @@ -71,26 +59,24 @@ export default define(meta, paramDef, async (ps, me) => { ? { id: ps.userId } : { usernameLower: ps.username!.toLowerCase(), host: toPunyNullable(ps.host) ?? IsNull() }); - if (user == null) { - throw new ApiError(meta.errors.noSuchUser); - } + if (user == null) throw new ApiError('NO_SUCH_USER'); const profile = await UserProfiles.findOneByOrFail({ userId: user.id }); if (profile.ffVisibility === 'private') { if (me == null || (me.id !== user.id)) { - throw new ApiError(meta.errors.forbidden); + throw new ApiError('ACCESS_DENIED'); } } else if (profile.ffVisibility === 'followers') { if (me == null) { - throw new ApiError(meta.errors.forbidden); + throw new ApiError('ACCESS_DENIED'); } else if (me.id !== user.id) { const following = await Followings.findOneBy({ followeeId: user.id, followerId: me.id, }); if (following == null) { - throw new ApiError(meta.errors.forbidden); + throw new ApiError('ACCESS_DENIED'); } } } diff --git a/packages/backend/src/server/api/endpoints/users/groups/delete.ts b/packages/backend/src/server/api/endpoints/users/groups/delete.ts index 2ff1f9aec..8c9ff7134 100644 --- a/packages/backend/src/server/api/endpoints/users/groups/delete.ts +++ b/packages/backend/src/server/api/endpoints/users/groups/delete.ts @@ -11,13 +11,7 @@ export const meta = { description: 'Delete an existing group.', - errors: { - noSuchGroup: { - message: 'No such group.', - code: 'NO_SUCH_GROUP', - id: '63dbd64c-cd77-413f-8e08-61781e210b38', - }, - }, + errors: ['NO_SUCH_GROUP'], } as const; export const paramDef = { @@ -35,9 +29,7 @@ export default define(meta, paramDef, async (ps, user) => { userId: user.id, }); - if (userGroup == null) { - throw new ApiError(meta.errors.noSuchGroup); - } + if (userGroup == null) throw new ApiError('NO_SUCH_GROUP'); await UserGroups.delete(userGroup.id); }); diff --git a/packages/backend/src/server/api/endpoints/users/groups/invitations/accept.ts b/packages/backend/src/server/api/endpoints/users/groups/invitations/accept.ts index 220fff5f3..88086a084 100644 --- a/packages/backend/src/server/api/endpoints/users/groups/invitations/accept.ts +++ b/packages/backend/src/server/api/endpoints/users/groups/invitations/accept.ts @@ -13,13 +13,7 @@ export const meta = { description: 'Join a group the authenticated user has been invited to.', - errors: { - noSuchInvitation: { - message: 'No such invitation.', - code: 'NO_SUCH_INVITATION', - id: '98c11eca-c890-4f42-9806-c8c8303ebb5e', - }, - }, + errors: ['NO_SUCH_INVITATION'], } as const; export const paramDef = { @@ -35,15 +29,10 @@ export default define(meta, paramDef, async (ps, user) => { // Fetch the invitation const invitation = await UserGroupInvitations.findOneBy({ id: ps.invitationId, + userId: user.id, }); - if (invitation == null) { - throw new ApiError(meta.errors.noSuchInvitation); - } - - if (invitation.userId !== user.id) { - throw new ApiError(meta.errors.noSuchInvitation); - } + if (invitation == null) throw new ApiError('NO_SUCH_INVITATION'); // Push the user await UserGroupJoinings.insert({ diff --git a/packages/backend/src/server/api/endpoints/users/groups/invitations/reject.ts b/packages/backend/src/server/api/endpoints/users/groups/invitations/reject.ts index 8d1d3db73..0f3712b02 100644 --- a/packages/backend/src/server/api/endpoints/users/groups/invitations/reject.ts +++ b/packages/backend/src/server/api/endpoints/users/groups/invitations/reject.ts @@ -11,13 +11,7 @@ export const meta = { description: 'Delete an existing group invitation for the authenticated user without joining the group.', - errors: { - noSuchInvitation: { - message: 'No such invitation.', - code: 'NO_SUCH_INVITATION', - id: 'ad7471d4-2cd9-44b4-ac68-e7136b4ce656', - }, - }, + errors: ['NO_SUCH_INVITATION'], } as const; export const paramDef = { @@ -33,15 +27,10 @@ export default define(meta, paramDef, async (ps, user) => { // Fetch the invitation const invitation = await UserGroupInvitations.findOneBy({ id: ps.invitationId, + userId: user.id, }); - if (invitation == null) { - throw new ApiError(meta.errors.noSuchInvitation); - } - - if (invitation.userId !== user.id) { - throw new ApiError(meta.errors.noSuchInvitation); - } + if (invitation == null) throw new ApiError('NO_SUCH_INVITATION'); await UserGroupInvitations.delete(invitation.id); }); diff --git a/packages/backend/src/server/api/endpoints/users/groups/invite.ts b/packages/backend/src/server/api/endpoints/users/groups/invite.ts index 1a8d320f3..7a792a49b 100644 --- a/packages/backend/src/server/api/endpoints/users/groups/invite.ts +++ b/packages/backend/src/server/api/endpoints/users/groups/invite.ts @@ -15,31 +15,7 @@ export const meta = { description: 'Invite a user to an existing group.', - errors: { - noSuchGroup: { - message: 'No such group.', - code: 'NO_SUCH_GROUP', - id: '583f8bc0-8eee-4b78-9299-1e14fc91e409', - }, - - noSuchUser: { - message: 'No such user.', - code: 'NO_SUCH_USER', - id: 'da52de61-002c-475b-90e1-ba64f9cf13a8', - }, - - alreadyAdded: { - message: 'That user has already been added to that group.', - code: 'ALREADY_ADDED', - id: '7e35c6a0-39b2-4488-aea6-6ee20bd5da2c', - }, - - alreadyInvited: { - message: 'That user has already been invited to that group.', - code: 'ALREADY_INVITED', - id: 'ee0f58b4-b529-4d13-b761-b9a3e69f97e6', - }, - }, + errors: ['NO_SUCH_USER', 'NO_SUCH_GROUP', 'ALREADY_ADDED', 'ALREADY_INVITED'], } as const; export const paramDef = { @@ -59,13 +35,11 @@ export default define(meta, paramDef, async (ps, me) => { userId: me.id, }); - if (userGroup == null) { - throw new ApiError(meta.errors.noSuchGroup); - } + if (userGroup == null) throw new ApiError('NO_SUCH_GROUP'); // Fetch the user const user = await getUser(ps.userId).catch(e => { - if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser); + if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError('NO_SUCH_USER'); throw e; }); @@ -74,18 +48,14 @@ export default define(meta, paramDef, async (ps, me) => { userId: user.id, }); - if (joining) { - throw new ApiError(meta.errors.alreadyAdded); - } + if (joining) throw new ApiError('ALREADY_ADDED'); const existInvitation = await UserGroupInvitations.findOneBy({ userGroupId: userGroup.id, userId: user.id, }); - if (existInvitation) { - throw new ApiError(meta.errors.alreadyInvited); - } + if (existInvitation) throw new ApiError('ALREADY_INVITED'); const invitation = await UserGroupInvitations.insert({ id: genId(), diff --git a/packages/backend/src/server/api/endpoints/users/groups/leave.ts b/packages/backend/src/server/api/endpoints/users/groups/leave.ts index 83dc757db..19a4982bb 100644 --- a/packages/backend/src/server/api/endpoints/users/groups/leave.ts +++ b/packages/backend/src/server/api/endpoints/users/groups/leave.ts @@ -11,19 +11,7 @@ export const meta = { description: 'Leave a group. The owner of a group can not leave. They must transfer ownership or delete the group instead.', - errors: { - noSuchGroup: { - message: 'No such group.', - code: 'NO_SUCH_GROUP', - id: '62780270-1f67-5dc0-daca-3eb510612e31', - }, - - youAreOwner: { - message: 'Your are the owner.', - code: 'YOU_ARE_OWNER', - id: 'b6d6e0c2-ef8a-9bb8-653d-79f4a3107c69', - }, - }, + errors: ['NO_SUCH_GROUP', 'GROUP_OWNER'], } as const; export const paramDef = { @@ -41,13 +29,9 @@ export default define(meta, paramDef, async (ps, me) => { id: ps.groupId, }); - if (userGroup == null) { - throw new ApiError(meta.errors.noSuchGroup); - } + if (userGroup == null) throw new ApiError('NO_SUCH_GROUP'); - if (me.id === userGroup.userId) { - throw new ApiError(meta.errors.youAreOwner); - } + if (me.id === userGroup.userId) throw new ApiError('GROUP_OWNER'); await UserGroupJoinings.delete({ userGroupId: userGroup.id, userId: me.id }); }); diff --git a/packages/backend/src/server/api/endpoints/users/groups/pull.ts b/packages/backend/src/server/api/endpoints/users/groups/pull.ts index ba67a1e5c..30caceb27 100644 --- a/packages/backend/src/server/api/endpoints/users/groups/pull.ts +++ b/packages/backend/src/server/api/endpoints/users/groups/pull.ts @@ -12,25 +12,7 @@ export const meta = { description: 'Removes a specified user from a group. The owner can not be removed.', - errors: { - noSuchGroup: { - message: 'No such group.', - code: 'NO_SUCH_GROUP', - id: '4662487c-05b1-4b78-86e5-fd46998aba74', - }, - - noSuchUser: { - message: 'No such user.', - code: 'NO_SUCH_USER', - id: '0b5cc374-3681-41da-861e-8bc1146f7a55', - }, - - isOwner: { - message: 'The user is the owner.', - code: 'IS_OWNER', - id: '1546eed5-4414-4dea-81c1-b0aec4f6d2af', - }, - }, + errors: ['NO_SUCH_USER', 'NO_SUCH_GROUP', 'GROUP_OWNER'], } as const; export const paramDef = { @@ -50,19 +32,15 @@ export default define(meta, paramDef, async (ps, me) => { userId: me.id, }); - if (userGroup == null) { - throw new ApiError(meta.errors.noSuchGroup); - } + if (userGroup == null) throw new ApiError('NO_SUCH_GROUP'); // Fetch the user const user = await getUser(ps.userId).catch(e => { - if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser); + if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError('NO_SUCH_USER'); throw e; }); - if (user.id === userGroup.userId) { - throw new ApiError(meta.errors.isOwner); - } + if (user.id === userGroup.userId) throw new ApiError('GROUP_OWNER'); // Pull the user await UserGroupJoinings.delete({ userGroupId: userGroup.id, userId: user.id }); diff --git a/packages/backend/src/server/api/endpoints/users/groups/show.ts b/packages/backend/src/server/api/endpoints/users/groups/show.ts index 21e3d9da2..eddd933c2 100644 --- a/packages/backend/src/server/api/endpoints/users/groups/show.ts +++ b/packages/backend/src/server/api/endpoints/users/groups/show.ts @@ -17,13 +17,7 @@ export const meta = { ref: 'UserGroup', }, - errors: { - noSuchGroup: { - message: 'No such group.', - code: 'NO_SUCH_GROUP', - id: 'ea04751e-9b7e-487b-a509-330fb6bd6b9b', - }, - }, + errors: ['NO_SUCH_GROUP'], } as const; export const paramDef = { @@ -41,9 +35,7 @@ export default define(meta, paramDef, async (ps, me) => { id: ps.groupId, }); - if (userGroup == null) { - throw new ApiError(meta.errors.noSuchGroup); - } + if (userGroup == null) throw new ApiError('NO_SUCH_GROUP'); const joining = await UserGroupJoinings.findOneBy({ userId: me.id, @@ -51,7 +43,7 @@ export default define(meta, paramDef, async (ps, me) => { }); if (joining == null && userGroup.userId !== me.id) { - throw new ApiError(meta.errors.noSuchGroup); + throw new ApiError('NO_SUCH_GROUP'); } return await UserGroups.pack(userGroup); diff --git a/packages/backend/src/server/api/endpoints/users/groups/transfer.ts b/packages/backend/src/server/api/endpoints/users/groups/transfer.ts index 6456e70dd..b6607e4f8 100644 --- a/packages/backend/src/server/api/endpoints/users/groups/transfer.ts +++ b/packages/backend/src/server/api/endpoints/users/groups/transfer.ts @@ -18,25 +18,7 @@ export const meta = { ref: 'UserGroup', }, - errors: { - noSuchGroup: { - message: 'No such group.', - code: 'NO_SUCH_GROUP', - id: '8e31d36b-2f88-4ccd-a438-e2d78a9162db', - }, - - noSuchUser: { - message: 'No such user.', - code: 'NO_SUCH_USER', - id: '711f7ebb-bbb9-4dfa-b540-b27809fed5e9', - }, - - noSuchGroupMember: { - message: 'No such group member.', - code: 'NO_SUCH_GROUP_MEMBER', - id: 'd31bebee-196d-42c2-9a3e-9474d4be6cc4', - }, - }, + errors: ['NO_SUCH_GROUP', 'NO_SUCH_USER'], } as const; export const paramDef = { @@ -56,13 +38,11 @@ export default define(meta, paramDef, async (ps, me) => { userId: me.id, }); - if (userGroup == null) { - throw new ApiError(meta.errors.noSuchGroup); - } + if (userGroup == null) throw new ApiError('NO_SUCH_GROUP'); // Fetch the user const user = await getUser(ps.userId).catch(e => { - if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser); + if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError('NO_SUCH_USER'); throw e; }); @@ -71,9 +51,7 @@ export default define(meta, paramDef, async (ps, me) => { userId: user.id, }); - if (joining == null) { - throw new ApiError(meta.errors.noSuchGroupMember); - } + if (joining == null) throw new ApiError('NO_SUCH_USER', 'The user exists but is not a member of the group.'); await UserGroups.update(userGroup.id, { userId: ps.userId, diff --git a/packages/backend/src/server/api/endpoints/users/groups/update.ts b/packages/backend/src/server/api/endpoints/users/groups/update.ts index 0a96165fc..81d5f26ec 100644 --- a/packages/backend/src/server/api/endpoints/users/groups/update.ts +++ b/packages/backend/src/server/api/endpoints/users/groups/update.ts @@ -17,13 +17,7 @@ export const meta = { ref: 'UserGroup', }, - errors: { - noSuchGroup: { - message: 'No such group.', - code: 'NO_SUCH_GROUP', - id: '9081cda3-7a9e-4fac-a6ce-908d70f282f6', - }, - }, + errors: ['NO_SUCH_GROUP'], } as const; export const paramDef = { @@ -43,9 +37,7 @@ export default define(meta, paramDef, async (ps, me) => { userId: me.id, }); - if (userGroup == null) { - throw new ApiError(meta.errors.noSuchGroup); - } + if (userGroup == null) throw new ApiError('NO_SUCH_GROUP'); await UserGroups.update(userGroup.id, { name: ps.name, diff --git a/packages/backend/src/server/api/endpoints/users/lists/delete.ts b/packages/backend/src/server/api/endpoints/users/lists/delete.ts index 5a7613c98..e8f476794 100644 --- a/packages/backend/src/server/api/endpoints/users/lists/delete.ts +++ b/packages/backend/src/server/api/endpoints/users/lists/delete.ts @@ -11,13 +11,7 @@ export const meta = { description: 'Delete an existing list of users.', - errors: { - noSuchList: { - message: 'No such list.', - code: 'NO_SUCH_LIST', - id: '78436795-db79-42f5-b1e2-55ea2cf19166', - }, - }, + errors: ['NO_SUCH_USER_LIST'], } as const; export const paramDef = { @@ -35,9 +29,7 @@ export default define(meta, paramDef, async (ps, user) => { userId: user.id, }); - if (userList == null) { - throw new ApiError(meta.errors.noSuchList); - } + if (userList == null) throw new ApiError('NO_SUCH_USER_LIST'); await UserLists.delete(userList.id); }); diff --git a/packages/backend/src/server/api/endpoints/users/lists/pull.ts b/packages/backend/src/server/api/endpoints/users/lists/pull.ts index d3d1d6555..0860b97ef 100644 --- a/packages/backend/src/server/api/endpoints/users/lists/pull.ts +++ b/packages/backend/src/server/api/endpoints/users/lists/pull.ts @@ -13,19 +13,7 @@ export const meta = { description: 'Remove a user from a list.', - errors: { - noSuchList: { - message: 'No such list.', - code: 'NO_SUCH_LIST', - id: '7f44670e-ab16-43b8-b4c1-ccd2ee89cc02', - }, - - noSuchUser: { - message: 'No such user.', - code: 'NO_SUCH_USER', - id: '588e7f72-c744-4a61-b180-d354e912bda2', - }, - }, + errors: ['NO_SUCH_USER', 'NO_SUCH_USER_LIST'], } as const; export const paramDef = { @@ -45,13 +33,11 @@ export default define(meta, paramDef, async (ps, me) => { userId: me.id, }); - if (userList == null) { - throw new ApiError(meta.errors.noSuchList); - } + if (userList == null) throw new ApiError('NO_SUCH_USER_LIST'); // Fetch the user const user = await getUser(ps.userId).catch(e => { - if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser); + if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError('NO_SUCH_USER'); throw e; }); diff --git a/packages/backend/src/server/api/endpoints/users/lists/push.ts b/packages/backend/src/server/api/endpoints/users/lists/push.ts index 12b7b8634..7552f3331 100644 --- a/packages/backend/src/server/api/endpoints/users/lists/push.ts +++ b/packages/backend/src/server/api/endpoints/users/lists/push.ts @@ -13,31 +13,7 @@ export const meta = { description: 'Add a user to an existing list.', - errors: { - noSuchList: { - message: 'No such list.', - code: 'NO_SUCH_LIST', - id: '2214501d-ac96-4049-b717-91e42272a711', - }, - - noSuchUser: { - message: 'No such user.', - code: 'NO_SUCH_USER', - id: 'a89abd3d-f0bc-4cce-beb1-2f446f4f1e6a', - }, - - alreadyAdded: { - message: 'That user has already been added to that list.', - code: 'ALREADY_ADDED', - id: '1de7c884-1595-49e9-857e-61f12f4d4fc5', - }, - - youHaveBeenBlocked: { - message: 'You cannot push this user because you have been blocked by this user.', - code: 'YOU_HAVE_BEEN_BLOCKED', - id: '990232c5-3f9d-4d83-9f3f-ef27b6332a4b', - }, - }, + errors: ['ALREADY_ADDED', 'BLOCKED', 'NO_SUCH_USER', 'NO_SUCH_USER_LIST'], } as const; export const paramDef = { @@ -57,13 +33,11 @@ export default define(meta, paramDef, async (ps, me) => { userId: me.id, }); - if (userList == null) { - throw new ApiError(meta.errors.noSuchList); - } + if (userList == null) throw new ApiError('NO_SUCH_USER_LIST'); // Fetch the user const user = await getUser(ps.userId).catch(e => { - if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser); + if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError('NO_SUCH_USER'); throw e; }); @@ -73,9 +47,7 @@ export default define(meta, paramDef, async (ps, me) => { blockerId: user.id, blockeeId: me.id, }); - if (block) { - throw new ApiError(meta.errors.youHaveBeenBlocked); - } + if (block) throw new ApiError('BLOCKED'); } const exist = await UserListJoinings.findOneBy({ @@ -83,9 +55,7 @@ export default define(meta, paramDef, async (ps, me) => { userId: user.id, }); - if (exist) { - throw new ApiError(meta.errors.alreadyAdded); - } + if (exist) throw new ApiError('ALREADY_ADDED'); // Push the user await pushUserToUserList(user, userList); diff --git a/packages/backend/src/server/api/endpoints/users/lists/show.ts b/packages/backend/src/server/api/endpoints/users/lists/show.ts index fd0612f73..64f280a61 100644 --- a/packages/backend/src/server/api/endpoints/users/lists/show.ts +++ b/packages/backend/src/server/api/endpoints/users/lists/show.ts @@ -17,13 +17,7 @@ export const meta = { ref: 'UserList', }, - errors: { - noSuchList: { - message: 'No such list.', - code: 'NO_SUCH_LIST', - id: '7bc05c21-1d7a-41ae-88f1-66820f4dc686', - }, - }, + errors: ['NO_SUCH_USER_LIST'], } as const; export const paramDef = { @@ -42,9 +36,7 @@ export default define(meta, paramDef, async (ps, me) => { userId: me.id, }); - if (userList == null) { - throw new ApiError(meta.errors.noSuchList); - } + if (userList == null) throw new ApiError('NO_SUCH_USER_LIST'); return await UserLists.pack(userList); }); diff --git a/packages/backend/src/server/api/endpoints/users/lists/update.ts b/packages/backend/src/server/api/endpoints/users/lists/update.ts index 65e708b95..f0df2d282 100644 --- a/packages/backend/src/server/api/endpoints/users/lists/update.ts +++ b/packages/backend/src/server/api/endpoints/users/lists/update.ts @@ -17,13 +17,7 @@ export const meta = { ref: 'UserList', }, - errors: { - noSuchList: { - message: 'No such list.', - code: 'NO_SUCH_LIST', - id: '796666fe-3dff-4d39-becb-8a5932c1d5b7', - }, - }, + errors: ['NO_SUCH_USER_LIST'], } as const; export const paramDef = { @@ -43,9 +37,7 @@ export default define(meta, paramDef, async (ps, user) => { userId: user.id, }); - if (userList == null) { - throw new ApiError(meta.errors.noSuchList); - } + if (userList == null) throw new ApiError('NO_SUCH_USER_LIST'); await UserLists.update(userList.id, { name: ps.name, diff --git a/packages/backend/src/server/api/endpoints/users/notes.ts b/packages/backend/src/server/api/endpoints/users/notes.ts index 9fa56fe83..02520036f 100644 --- a/packages/backend/src/server/api/endpoints/users/notes.ts +++ b/packages/backend/src/server/api/endpoints/users/notes.ts @@ -23,13 +23,7 @@ export const meta = { }, }, - errors: { - noSuchUser: { - message: 'No such user.', - code: 'NO_SUCH_USER', - id: '27e494ba-2ac2-48e8-893b-10d4d8c2387b', - }, - }, + errors: ['NO_SUCH_USER'], } as const; export const paramDef = { @@ -56,7 +50,7 @@ export const paramDef = { export default define(meta, paramDef, async (ps, me) => { // Lookup user const user = await getUser(ps.userId).catch(e => { - if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser); + if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError('NO_SUCH_USER'); throw e; }); diff --git a/packages/backend/src/server/api/endpoints/users/reactions.ts b/packages/backend/src/server/api/endpoints/users/reactions.ts index 4750dc4f9..67ef1271f 100644 --- a/packages/backend/src/server/api/endpoints/users/reactions.ts +++ b/packages/backend/src/server/api/endpoints/users/reactions.ts @@ -21,13 +21,7 @@ export const meta = { }, }, - errors: { - reactionsNotPublic: { - message: 'Reactions of the user is not public.', - code: 'REACTIONS_NOT_PUBLIC', - id: '673a7dd2-6924-1093-e0c0-e68456ceae5c', - }, - }, + errors: ['ACCESS_DENIED'], } as const; export const paramDef = { @@ -48,7 +42,7 @@ export default define(meta, paramDef, async (ps, me) => { const profile = await UserProfiles.findOneByOrFail({ userId: ps.userId }); if (me == null || (me.id !== ps.userId && !profile.publicReactions)) { - throw new ApiError(meta.errors.reactionsNotPublic); + throw new ApiError('ACCESS_DENIED'); } const query = makePaginationQuery(NoteReactions.createQueryBuilder('reaction'), diff --git a/packages/backend/src/server/api/endpoints/users/report-abuse.ts b/packages/backend/src/server/api/endpoints/users/report-abuse.ts index eacfe72f4..7ad92293f 100644 --- a/packages/backend/src/server/api/endpoints/users/report-abuse.ts +++ b/packages/backend/src/server/api/endpoints/users/report-abuse.ts @@ -16,25 +16,7 @@ export const meta = { description: 'File a report.', - errors: { - noSuchUser: { - message: 'No such user.', - code: 'NO_SUCH_USER', - id: '1acefcb5-0959-43fd-9685-b48305736cb5', - }, - - cannotReportYourself: { - message: 'Cannot report yourself.', - code: 'CANNOT_REPORT_YOURSELF', - id: '1e13149e-b1e8-43cf-902e-c01dbfcb202f', - }, - - cannotReportAdmin: { - message: 'Cannot report the admin.', - code: 'CANNOT_REPORT_THE_ADMIN', - id: '35e166f5-05fb-4f87-a2d5-adb42676d48f', - }, - }, + errors: ['NO_SUCH_USER', 'CANNOT_REPORT_ADMIN', 'CANNOT_REPORT_YOURSELF'], } as const; export const paramDef = { @@ -51,17 +33,13 @@ export const paramDef = { export default define(meta, paramDef, async (ps, me) => { // Lookup user const user = await getUser(ps.userId).catch(e => { - if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser); + if (e.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError('NO_SUCH_USER'); throw e; }); - if (user.id === me.id) { - throw new ApiError(meta.errors.cannotReportYourself); - } + if (user.id === me.id) throw new ApiError('CANNOT_REPORT_YOURSELF'); - if (user.isAdmin) { - throw new ApiError(meta.errors.cannotReportAdmin); - } + if (user.isAdmin) throw new ApiError('CANNOT_REPORT_ADMIN'); const uri = user.host == null ? `${config.url}/users/${user.id}` : user.uri; if (!ps.urls.includes(uri)) { diff --git a/packages/backend/src/server/api/endpoints/users/show.ts b/packages/backend/src/server/api/endpoints/users/show.ts index 846d83b49..33c0cfca3 100644 --- a/packages/backend/src/server/api/endpoints/users/show.ts +++ b/packages/backend/src/server/api/endpoints/users/show.ts @@ -30,20 +30,7 @@ export const meta = { ], }, - errors: { - failedToResolveRemoteUser: { - message: 'Failed to resolve remote user.', - code: 'FAILED_TO_RESOLVE_REMOTE_USER', - id: 'ef7b9be4-9cba-4e6f-ab41-90ed171c7d3c', - kind: 'server', - }, - - noSuchUser: { - message: 'No such user.', - code: 'NO_SUCH_USER', - id: '4362f8dc-731f-4ad8-a694-be5a88922a24', - }, - }, + errors: ['FAILED_TO_RESOLVE_REMOTE_USER', 'NO_SUCH_USER'], } as const; export const paramDef = { @@ -109,7 +96,7 @@ export default define(meta, paramDef, async (ps, me) => { if (typeof ps.host === 'string' && typeof ps.username === 'string') { user = await resolveUser(ps.username, ps.host).catch(e => { apiLogger.warn(`failed to resolve remote user: ${e}`); - throw new ApiError(meta.errors.failedToResolveRemoteUser); + throw new ApiError('FAILED_TO_RESOLVE_REMOTE_USER'); }); } else { const q: FindOptionsWhere = ps.userId != null @@ -120,7 +107,7 @@ export default define(meta, paramDef, async (ps, me) => { } if (user == null || (!isAdminOrModerator && user.isSuspended)) { - throw new ApiError(meta.errors.noSuchUser); + throw new ApiError('NO_SUCH_USER'); } return await Users.pack(user, me, { diff --git a/packages/backend/src/server/api/endpoints/users/stats.ts b/packages/backend/src/server/api/endpoints/users/stats.ts index 47f322ee9..55d4f4314 100644 --- a/packages/backend/src/server/api/endpoints/users/stats.ts +++ b/packages/backend/src/server/api/endpoints/users/stats.ts @@ -10,13 +10,7 @@ export const meta = { description: 'Show statistics about a user.', - errors: { - noSuchUser: { - message: 'No such user.', - code: 'NO_SUCH_USER', - id: '9e638e45-3b25-4ef7-8f95-07e8498f1819', - }, - }, + errors: ['NO_SUCH_USER'], res: { type: 'object', @@ -119,7 +113,7 @@ export const paramDef = { export default define(meta, paramDef, async (ps, me) => { const user = await Users.findOneBy({ id: ps.userId }); if (user == null) { - throw new ApiError(meta.errors.noSuchUser); + throw new ApiError('NO_SUCH_USER'); } const result = await awaitAll({ diff --git a/packages/backend/src/server/api/error.ts b/packages/backend/src/server/api/error.ts index 6fc5ea38b..2cdabce48 100644 --- a/packages/backend/src/server/api/error.ts +++ b/packages/backend/src/server/api/error.ts @@ -1,29 +1,357 @@ -type E = { message: string, code: string, id: string, kind?: 'client' | 'server', httpStatusCode?: number }; - export class ApiError extends Error { public message: string; public code: string; - public id: string; - public kind: string; - public httpStatusCode?: number; + public httpStatusCode: number; public info?: any; constructor( - e: E = { - message: 'Internal error occurred. Please contact us if the error persists.', - code: 'INTERNAL_ERROR', - id: '5d37dbcb-891e-41ca-a3d6-e690c97775ac', - kind: 'server', - httpStatusCode: 500, - }, + code: keyof errors = 'INTERNAL_ERROR', info?: any | null, ) { - super(e.message); - this.message = e.message; - this.code = e.code; - this.id = e.id; - this.kind = e.kind ?? 'client'; - this.httpStatusCode = e.httpStatusCode ?? 500; - this.info = info; + if(!code in errors) { + info = `Unknown error "${code}" occurred.`; + code = 'INTERNAL_ERROR'; + } + + const { message, httpStatusCode } = errors[code]; + super(message); + this.code = code; + this.message = message; + this.httpStatusCode = httpStatusCode; } } + +export const errors: Record = { + ACCESS_DENIED: { + message: 'Access denied.', + httpStatusCode: 403, + }, + ALREADY_ADDED: { + message: 'That user has already been added to that list or group.', + httpStatusCode: 409, + }, + ALREADY_BLOCKING: { + message: 'You are already blocking that user.', + httpStatusCode: 409, + }, + ALREADY_CLIPPED: { + message: 'That note is already added to that clip.', + httpStatusCode: 409, + }, + ALREADY_FAVORITED: { + message: 'That note is already favorited.', + httpStatusCode: 409, + }, + ALREADY_FOLLOWING: { + message: 'You are already following that user.', + httpStatusCode: 409, + }, + ALREADY_INVITED: { + message: 'That user has already been invited to that group.', + httpStatusCode: 409, + }, + ALREADY_LIKED: { + message: 'You already liked that page or gallery post.', + httpStatusCode: 409, + }, + ALREADY_MUTING: { + message: 'You are already muting that user.', + httpStatusCode: 409, + }, + ALREADY_PINNED: { + message: 'You already pinned that note.', + httpStatusCode: 409, + }, + ALREADY_REACTED: { + message: 'You already reacted to that note.', + httpStatusCode: 409, + }, + ALREADY_VOTED: { + message: 'You have already voted in that poll.', + httpStatusCode: 409, + }, + AUTHENTICATION_FAILED: { + message: 'Authentication failed.', + httpStatusCode: 401, + }, + AUTHENTICATION_REQUIRED: { + message: 'Authentication is required, but authenticating information was not or not appropriately provided.', + httpStatusCode: 401, + }, + BLOCKED: { + message: 'You are blocked by that user.', + httpStatusCode: 400, + }, + BLOCKEE_IS_YOURSELF: { + message: 'You cannot block yourself.', + httpStatusCode: 400, + }, + BLOCKING: { + message: 'You are blocking that user.', + httpStatusCode: 400, + }, + CANNOT_REPORT_ADMIN: { + message: 'You cannot report an administrator.', + httpStatusCode: 400, + }, + CANNOT_REPORT_YOURSELF: { + message: 'You cannot report yourself.', + httpStatusCode: 400, + }, + EMPTY_FILE: { + message: 'The provided file is empty.', + httpStatusCode: 400, + }, + EXPIRED_POLL: { + message: 'Poll is already expired.', + httpStatusCode: 400, + }, + FAILED_TO_RESOLVE_REMOTE_USER: { + message: 'Failed to resolve remote user.', + httpStatusCode: 502, + }, + FILE_TOO_BIG: { + message: 'The provided file is too big.', + httpStatusCode: 400, + }, + FILE_REQUIRED: { + message: 'This operation requires a file to be provided.', + httpStatusCode: 400, + }, + FOLLOWEE_IS_YOURSELF: { + message: 'You cannot follow yourself.', + httpStatusCode: 400, + }, + FOLLOWER_IS_YOURSELF: { + message: 'You cannot unfollow yourself.', + httpStatusCode: 400, + }, + GROUP_OWNER: { + message: 'The owner of a group may not leave. Instead, ownership can be transferred or the group deleted.', + httpStatusCode: 400, + }, + HAS_CHILD_FILES_OR_FOLDERS: { + message: 'That folder is not empty.', + httpStatusCode: 400, + }, + INTERNAL_ERROR: { + message: 'Internal error occurred. Please contact us if the error persists.', + httpStatusCode: 500, + }, + INVALID_CHOICE: { + message: 'Choice index is invalid.', + httpStatusCode: 400, + }, + INVALID_FILE_NAME: { + message: 'Invalid file name.', + httpStatusCode: 400, + }, + INVALID_PARAM: { + message: 'One or more parameters do not match the API definition.', + httpStatusCode: 400, + }, + INVALID_PASSWORD: { + message: 'The provided password is not suitable.', + httpStatusCode: 400, + }, + INVALID_REGEXP: { + message: 'Invalid Regular Expression', + httpStatusCode: 400, + }, + INVALID_URL: { + message: 'Invalid URL.', + httpStatusCode: 400, + }, + INVALID_USERNAME: { + message: 'Invalid username.', + httpStatusCode: 400, + }, + LESS_RESTRICTIVE_VISIBILITY: { + message: 'The visibility cannot be less restrictive than the parent note.', + httpStatusCode: 400, + }, + MUTEE_IS_YOURSELF: { + message: 'You cannot mute yourself.', + httpStatusCode: 400, + }, + NAME_ALREADY_EXISTS: { + message: 'The specified name already exists.', + httpStatusCode: 409, + }, + NO_POLL: { + message: 'The note does not have an attached poll.', + httpStatusCode: 404, + }, + NO_SUCH_ANNOUNCEMENT: { + message: 'No such announcement.', + httpStatusCode: 404, + }, + NO_SUCH_ANTENNA: { + message: 'No such antenna.', + httpStatusCode: 404, + }, + NO_SUCH_APP: { + message: 'No such app.', + httpStatusCode: 404, + }, + NO_SUCH_CLIP: { + message: 'No such clip.', + httpStatusCode: 404, + }, + NO_SUCH_CHANNEL: { + message: 'No such channel.', + httpStatusCode: 404, + }, + NO_SUCH_EMOJI: { + message: 'No such emoji.', + httpStatusCode: 404, + }, + NO_SUCH_ENDPOINT: { + message: 'No such endpoint.', + httpStatusCode: 404, + }, + NO_SUCH_FILE: { + message: 'No such file.', + httpStatusCode: 404, + }, + NO_SUCH_FOLDER: { + message: 'No such folder.', + httpStatusCode: 404, + }, + NO_SUCH_FOLLOW_REQUEST: { + message: 'No such follow request.', + httpStatusCode: 404, + }, + NO_SUCH_GROUP: { + message: 'No such user group.', + httpStatusCode: 404, + }, + NO_SUCH_HASHTAG: { + message: 'No such hashtag.', + httpStatusCode: 404, + }, + NO_SUCH_INVITATION: { + message: 'No such group invitation.', + httpStatusCode: 404, + }, + NO_SUCH_KEY: { + message: 'No such key.', + httpStatusCode: 404, + }, + NO_SUCH_NOTE: { + message: 'No such note.', + httpStatusCode: 404, + }, + NO_SUCH_NOTIFICATION: { + message: 'No such notification.', + httpStatusCode: 404, + }, + NO_SUCH_MESSAGE: { + message: 'No such message.', + httpStatusCode: 404, + }, + NO_SUCH_OBJECT: { + message: 'No such object.', + httpStatusCode: 404, + }, + NO_SUCH_PAGE: { + message: 'No such page.', + httpStatusCode: 404, + }, + NO_SUCH_PARENT_FOLDER: { + message: 'No such parent folder.', + httpStatusCode: 404, + }, + NO_SUCH_POST: { + message: 'No such gallery post.', + httpStatusCode: 404, + }, + NO_SUCH_RESET_REQUEST: { + message: 'No such password reset request.', + httpStatusCode: 404, + }, + NO_SUCH_SESSION: { + message: 'No such session', + httpStatusCode: 404, + }, + NO_SUCH_USER: { + message: 'No such user.', + httpStatusCode: 404, + }, + NO_SUCH_USER_LIST: { + message: 'No such user list.', + httpStatusCode: 404, + }, + NO_SUCH_WEBHOOK: { + message: 'No such webhook.', + httpStatusCode: 404, + }, + NOT_AN_IMAGE: { + message: 'The file specified was expected to be an image, but it is not.', + httpStatusCode: 400, + }, + NOT_BLOCKING: { + message: 'You are not blocking that user.', + httpStatusCode: 409, + }, + NOT_CLIPPED: { + message: 'That note is not added to that clip.', + httpStatusCode: 409, + }, + NOT_FAVORITED: { + message: 'You have not favorited that note.', + httpStatusCode: 409, + }, + NOT_FOLLOWING: { + message: 'You are not following that user.', + httpStatusCode: 409, + }, + NOT_LIKED: { + message: 'You have not liked that page or gallery post.', + httpStatusCode: 409, + }, + NOT_MUTING: { + message: 'You are not muting that user.', + httpStatusCode: 409, + }, + NOT_REACTED: { + message: 'You have not reacted to that note.', + httpStatusCode: 409, + }, + PENDING_SESSION: { + message: 'That authorization process has not been completed yet.', + httpStatusCode: 400, + }, + PIN_LIMIT_EXCEEDED: { + message: 'You can not pin any more notes.', + httpStatusCode: 400, + }, + PURE_RENOTE: { + message: 'You cannot renote or reply to a pure renote.', + httpStatusCode: 400, + }, + RATE_LIMIT_EXCEEDED: { + message: 'Rate limit exceeded. Please try again later.', + httpStatusCode: 429, + }, + RECIPIENT_IS_YOURSELF: { + message: 'You cannot send a message to yourself.', + httpStatusCode: 400, + }, + RECURSIVE_FOLDER: { + message: 'Folder cannot be its own parent.', + httpStatusCode: 400, + }, + SUSPENDED: { + message: 'Your account has been suspended.', + httpStatusCode: 403, + }, + TIMELINE_DISABLED: { + message: 'This timeline is disabled by an administrator.', + httpStatusCode: 503, + }, + USED_USERNAME: { + message: 'That username is not available because it is being used or has been used before. Usernames cannot be reassigned.', + httpStatusCode: 409, + }, +}; From 1dd935dc0ca8d140deae5a34effadfae8af83758 Mon Sep 17 00:00:00 2001 From: Johann150 Date: Thu, 27 Oct 2022 19:50:00 +0200 Subject: [PATCH 3/5] fix endpoint type definition for errors --- packages/backend/src/server/api/endpoints.ts | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/packages/backend/src/server/api/endpoints.ts b/packages/backend/src/server/api/endpoints.ts index ff35d848d..1268f2670 100644 --- a/packages/backend/src/server/api/endpoints.ts +++ b/packages/backend/src/server/api/endpoints.ts @@ -1,4 +1,5 @@ import { Schema } from '@/misc/schema.js'; +import { errors } from './error.js'; import * as ep___admin_meta from './endpoints/admin/meta.js'; import * as ep___admin_abuseUserReports from './endpoints/admin/abuse-user-reports.js'; @@ -621,13 +622,7 @@ export interface IEndpointMeta { readonly tags?: ReadonlyArray; - readonly errors?: { - readonly [key: string]: { - readonly message: string; - readonly code: string; - readonly id: string; - }; - }; + readonly errors?: Array; readonly res?: Schema; From fb76843c190ebc6c6185cfa35629ceda1cfbdf5f Mon Sep 17 00:00:00 2001 From: Johann150 Date: Thu, 27 Oct 2022 19:59:11 +0200 Subject: [PATCH 4/5] adapt OpenAPI documentation generation to new error definitions --- .../backend/src/server/api/openapi/errors.ts | 69 -------- .../src/server/api/openapi/gen-spec.ts | 161 ++++++++---------- .../src/server/api/openapi/http-codes.ts | 67 ++++++++ .../backend/src/server/api/openapi/schemas.ts | 18 +- 4 files changed, 145 insertions(+), 170 deletions(-) delete mode 100644 packages/backend/src/server/api/openapi/errors.ts create mode 100644 packages/backend/src/server/api/openapi/http-codes.ts diff --git a/packages/backend/src/server/api/openapi/errors.ts b/packages/backend/src/server/api/openapi/errors.ts deleted file mode 100644 index 3f733b4ea..000000000 --- a/packages/backend/src/server/api/openapi/errors.ts +++ /dev/null @@ -1,69 +0,0 @@ - -export const errors = { - '400': { - 'INVALID_PARAM': { - value: { - error: { - message: 'Invalid param.', - code: 'INVALID_PARAM', - id: '3d81ceae-475f-4600-b2a8-2bc116157532', - }, - }, - }, - }, - '401': { - 'CREDENTIAL_REQUIRED': { - value: { - error: { - message: 'Credential required.', - code: 'CREDENTIAL_REQUIRED', - id: '1384574d-a912-4b81-8601-c7b1c4085df1', - }, - }, - }, - }, - '403': { - 'AUTHENTICATION_FAILED': { - value: { - error: { - message: 'Authentication failed. Please ensure your token is correct.', - code: 'AUTHENTICATION_FAILED', - id: 'b0a7f5f8-dc2f-4171-b91f-de88ad238e14', - }, - }, - }, - }, - '418': { - 'I_AM_A_TEAPOT': { - value: { - error: { - message: 'I am a teapot.', - code: 'I_AM_A_TEAPOT', - id: '60c46cd1-f23a-46b1-bebe-5d2b73951a84', - }, - }, - }, - }, - '429': { - 'RATE_LIMIT_EXCEEDED': { - value: { - error: { - message: 'Rate limit exceeded. Please try again later.', - code: 'RATE_LIMIT_EXCEEDED', - id: 'd5826d14-3982-4d2e-8011-b9e9f02499ef', - }, - }, - }, - }, - '500': { - 'INTERNAL_ERROR': { - value: { - error: { - message: 'Internal error occurred. Please contact us if the error persists.', - code: 'INTERNAL_ERROR', - id: '5d37dbcb-891e-41ca-a3d6-e690c97775ac', - }, - }, - }, - }, -}; diff --git a/packages/backend/src/server/api/openapi/gen-spec.ts b/packages/backend/src/server/api/openapi/gen-spec.ts index 48b57a03c..497230596 100644 --- a/packages/backend/src/server/api/openapi/gen-spec.ts +++ b/packages/backend/src/server/api/openapi/gen-spec.ts @@ -1,7 +1,8 @@ import config from '@/config/index.js'; +import { errors as errorDefinitions } from '../error.js'; import endpoints from '../endpoints.js'; -import { errors as basicErrors } from './errors.js'; import { schemas, convertSchemaToOpenApiSchema } from './schemas.js'; +import { httpCodes } from './http-codes.js'; export function genOpenapiSpec() { const spec = { @@ -43,19 +44,75 @@ export function genOpenapiSpec() { }; for (const endpoint of endpoints.filter(ep => !ep.meta.secure)) { - const errors = {} as any; + // generate possible responses, first starting with errors + const responses = [ + // general error codes that can always happen + 'INVALID_PARAM', + 'INTERNAL_ERROR', + // error codes that happen only if authentication is required + ...(!endpoint.meta.requireCredential ? [] : [ + 'ACCESS_DENIED', + 'AUTHENTICATION_REQUIRED', + 'AUTHENTICATION_FAILED', + 'SUSPENDED', + ]), + // error codes that happen only if a rate limit is defined + ...(!endpoint.meta.limit ? [] : [ + 'RATE_LIMIT_EXCEEDED', + ]), + // error codes that happen only if a file is required + ...(!endpoint.meta.requireFile ? [] : [ + 'FILE_REQUIRED', + ]), + // endpoint specific error codes + ...(endpoint.meta.errors ?? []), + ] + .reduce((acc, code) => { + const { message, httpStatusCode } = errorDefinitions[code]; + const httpCode = httpStatusCode.toString(); - if (endpoint.meta.errors) { - for (const e of Object.values(endpoint.meta.errors)) { - errors[e.code] = { - value: { - error: e, + if(!(httpCode in acc)) { + acc[httpCode] = { + description: httpCodes[httpCode], + content: { + 'application/json': { + schema: { + '$ref': '#/components/schemas/Error', + }, + examples: {}, + }, }, }; } - } - const resSchema = endpoint.meta.res ? convertSchemaToOpenApiSchema(endpoint.meta.res) : {}; + acc[httpCode].content['application/json'].examples[code] = { + value: { + error: { + code, + message, + endpoint: endpoint.name, + }, + }, + }; + + return acc; + }, {}); + + // add successful response + if (endpoint.meta.res) { + responses['200'] = { + description: 'OK', + content: { + 'application/json': { + schema: convertSchemaToOpenApiSchema(endpoint.meta.res), + }, + }, + }; + } else { + responses['204'] = { + description: 'No Content', + }; + } let desc = (endpoint.meta.description ? endpoint.meta.description : 'No description provided.') + '\n\n'; desc += `**Credential required**: *${endpoint.meta.requireCredential ? 'Yes' : 'No'}*`; @@ -107,90 +164,7 @@ export function genOpenapiSpec() { }, }, }, - responses: { - ...(endpoint.meta.res ? { - '200': { - description: 'OK (with results)', - content: { - 'application/json': { - schema: resSchema, - }, - }, - }, - } : { - '204': { - description: 'OK (without any results)', - }, - }), - '400': { - description: 'Client error', - content: { - 'application/json': { - schema: { - $ref: '#/components/schemas/Error', - }, - examples: { ...errors, ...basicErrors['400'] }, - }, - }, - }, - '401': { - description: 'Authentication error', - content: { - 'application/json': { - schema: { - $ref: '#/components/schemas/Error', - }, - examples: basicErrors['401'], - }, - }, - }, - '403': { - description: 'Forbidden error', - content: { - 'application/json': { - schema: { - $ref: '#/components/schemas/Error', - }, - examples: basicErrors['403'], - }, - }, - }, - '418': { - description: 'I\'m Ai', - content: { - 'application/json': { - schema: { - $ref: '#/components/schemas/Error', - }, - examples: basicErrors['418'], - }, - }, - }, - ...(endpoint.meta.limit ? { - '429': { - description: 'Too many requests', - content: { - 'application/json': { - schema: { - $ref: '#/components/schemas/Error', - }, - examples: basicErrors['429'], - }, - }, - }, - } : {}), - '500': { - description: 'Internal server error', - content: { - 'application/json': { - schema: { - $ref: '#/components/schemas/Error', - }, - examples: basicErrors['500'], - }, - }, - }, - }, + responses, }; const path = { @@ -200,6 +174,7 @@ export function genOpenapiSpec() { path.get = { ...info }; // API Key authentication is not permitted for GET requests path.get.security = path.get.security.filter(elem => !Object.prototype.hasOwnProperty.call(elem, 'ApiKeyAuth')); + // fix the way parameters are passed delete path.get.requestBody; path.get.parameters = []; diff --git a/packages/backend/src/server/api/openapi/http-codes.ts b/packages/backend/src/server/api/openapi/http-codes.ts new file mode 100644 index 000000000..4727ef485 --- /dev/null +++ b/packages/backend/src/server/api/openapi/http-codes.ts @@ -0,0 +1,67 @@ +export const httpCodes: Record = { + "100": "Continue", + "101": "Switching Protocols", + "102": "Processing", + "103": "Early Hints", + "200": "OK", + "201": "Created", + "202": "Accepted", + "203": "Non-Authoritative Information", + "204": "No Content", + "205": "Reset Content", + "206": "Partial Content", + "207": "Multi-Status", + "208": "Already Reported", + "226": "IM Used", + "300": "Multiple Choices", + "301": "Moved Permanently", + "302": "Found", + "303": "See Other", + "304": "Not Modified", + "305": "Use Proxy", + "307": "Temporary Redirect", + "308": "Permanent Redirect", + "400": "Bad Request", + "401": "Unauthorized", + "402": "Payment Required", + "403": "Forbidden", + "404": "Not Found", + "405": "Method Not Allowed", + "406": "Not Acceptable", + "407": "Proxy Authentication Required", + "408": "Request Timeout", + "409": "Conflict", + "410": "Gone", + "411": "Length Required", + "412": "Precondition Failed", + "413": "Content Too Large", + "414": "URI Too Long", + "415": "Unsupported Media Type", + "416": "Range Not Satisfiable", + "417": "Expectation Failed", + "418": "I'm a Teapot", + "421": "Misdirected Request", + "422": "Unprocessable Content", + "423": "Locked", + "424": "Failed Dependency", + "425": "Too Early", + "426": "Upgrade Required", + "427": "Unassigned", + "428": "Precondition Required", + "429": "Too Many Requests", + "430": "Unassigned", + "431": "Request Header Fields Too Large", + "451": "Unavailable For Legal Reasons", + "500": "Internal Server Error", + "501": "Not Implemented", + "502": "Bad Gateway", + "503": "Service Unavailable", + "504": "Gateway Timeout", + "505": "HTTP Version Not Supported", + "506": "Variant Also Negotiates", + "507": "Insufficient Storage", + "508": "Loop Detected", + "509": "Unassigned", + "510": "Not Extended", + "511": "Network Authentication Required" +} diff --git a/packages/backend/src/server/api/openapi/schemas.ts b/packages/backend/src/server/api/openapi/schemas.ts index 4a0844b42..4bb72cd8a 100644 --- a/packages/backend/src/server/api/openapi/schemas.ts +++ b/packages/backend/src/server/api/openapi/schemas.ts @@ -36,19 +36,21 @@ export const schemas = { properties: { code: { type: 'string', - description: 'An error code. Unique within the endpoint.', + description: 'A machine and human readable error code.', + }, + endpoint: { + type: 'string', + description: 'Name of the API endpoint the error happened in.', }, message: { type: 'string', - description: 'An error message.', - }, - id: { - type: 'string', - format: 'uuid', - description: 'An error ID. This ID is static.', + description: 'A human readable error description in English.', }, + info: { + description: 'Potentially more information, primarily intended for developers.', + } }, - required: ['code', 'id', 'message'], + required: ['code', 'endpoint', 'message'], }, }, required: ['error'], From 735b9ab5029f301328c9f9747358038c7d47dadd Mon Sep 17 00:00:00 2001 From: Johann150 Date: Fri, 28 Oct 2022 16:57:56 +0200 Subject: [PATCH 5/5] fix some lints --- .../backend/src/server/api/api-handler.ts | 4 +- packages/backend/src/server/api/call.ts | 2 +- packages/backend/src/server/api/error.ts | 12 +- .../src/server/api/openapi/gen-spec.ts | 2 +- .../src/server/api/openapi/http-codes.ts | 132 +++++++++--------- .../backend/src/server/api/openapi/schemas.ts | 2 +- 6 files changed, 78 insertions(+), 76 deletions(-) diff --git a/packages/backend/src/server/api/api-handler.ts b/packages/backend/src/server/api/api-handler.ts index e21585158..30a8dbcf5 100644 --- a/packages/backend/src/server/api/api-handler.ts +++ b/packages/backend/src/server/api/api-handler.ts @@ -25,7 +25,7 @@ export async function handler(endpoint: IEndpoint, ctx: Koa.Context): Promise }, limitActor).catch(e => { + await limiter(limit as IEndpointMeta['limit'] & { key: NonNullable }, limitActor).catch(() => { throw new ApiError('RATE_LIMIT_EXCEEDED'); }); } diff --git a/packages/backend/src/server/api/error.ts b/packages/backend/src/server/api/error.ts index 2cdabce48..b93f5a2d2 100644 --- a/packages/backend/src/server/api/error.ts +++ b/packages/backend/src/server/api/error.ts @@ -8,14 +8,16 @@ export class ApiError extends Error { code: keyof errors = 'INTERNAL_ERROR', info?: any | null, ) { - if(!code in errors) { - info = `Unknown error "${code}" occurred.`; - code = 'INTERNAL_ERROR'; + if (!(code in errors)) { + this.info = `Unknown error "${code}" occurred.`; + this.code = 'INTERNAL_ERROR'; + } else { + this.info = info; + this.code = code; } - const { message, httpStatusCode } = errors[code]; + const { message, httpStatusCode } = errors[this.code]; super(message); - this.code = code; this.message = message; this.httpStatusCode = httpStatusCode; } diff --git a/packages/backend/src/server/api/openapi/gen-spec.ts b/packages/backend/src/server/api/openapi/gen-spec.ts index 497230596..f9795884d 100644 --- a/packages/backend/src/server/api/openapi/gen-spec.ts +++ b/packages/backend/src/server/api/openapi/gen-spec.ts @@ -71,7 +71,7 @@ export function genOpenapiSpec() { const { message, httpStatusCode } = errorDefinitions[code]; const httpCode = httpStatusCode.toString(); - if(!(httpCode in acc)) { + if (!(httpCode in acc)) { acc[httpCode] = { description: httpCodes[httpCode], content: { diff --git a/packages/backend/src/server/api/openapi/http-codes.ts b/packages/backend/src/server/api/openapi/http-codes.ts index 4727ef485..b3b74f867 100644 --- a/packages/backend/src/server/api/openapi/http-codes.ts +++ b/packages/backend/src/server/api/openapi/http-codes.ts @@ -1,67 +1,67 @@ export const httpCodes: Record = { - "100": "Continue", - "101": "Switching Protocols", - "102": "Processing", - "103": "Early Hints", - "200": "OK", - "201": "Created", - "202": "Accepted", - "203": "Non-Authoritative Information", - "204": "No Content", - "205": "Reset Content", - "206": "Partial Content", - "207": "Multi-Status", - "208": "Already Reported", - "226": "IM Used", - "300": "Multiple Choices", - "301": "Moved Permanently", - "302": "Found", - "303": "See Other", - "304": "Not Modified", - "305": "Use Proxy", - "307": "Temporary Redirect", - "308": "Permanent Redirect", - "400": "Bad Request", - "401": "Unauthorized", - "402": "Payment Required", - "403": "Forbidden", - "404": "Not Found", - "405": "Method Not Allowed", - "406": "Not Acceptable", - "407": "Proxy Authentication Required", - "408": "Request Timeout", - "409": "Conflict", - "410": "Gone", - "411": "Length Required", - "412": "Precondition Failed", - "413": "Content Too Large", - "414": "URI Too Long", - "415": "Unsupported Media Type", - "416": "Range Not Satisfiable", - "417": "Expectation Failed", - "418": "I'm a Teapot", - "421": "Misdirected Request", - "422": "Unprocessable Content", - "423": "Locked", - "424": "Failed Dependency", - "425": "Too Early", - "426": "Upgrade Required", - "427": "Unassigned", - "428": "Precondition Required", - "429": "Too Many Requests", - "430": "Unassigned", - "431": "Request Header Fields Too Large", - "451": "Unavailable For Legal Reasons", - "500": "Internal Server Error", - "501": "Not Implemented", - "502": "Bad Gateway", - "503": "Service Unavailable", - "504": "Gateway Timeout", - "505": "HTTP Version Not Supported", - "506": "Variant Also Negotiates", - "507": "Insufficient Storage", - "508": "Loop Detected", - "509": "Unassigned", - "510": "Not Extended", - "511": "Network Authentication Required" -} + '100': 'Continue', + '101': 'Switching Protocols', + '102': 'Processing', + '103': 'Early Hints', + '200': 'OK', + '201': 'Created', + '202': 'Accepted', + '203': 'Non-Authoritative Information', + '204': 'No Content', + '205': 'Reset Content', + '206': 'Partial Content', + '207': 'Multi-Status', + '208': 'Already Reported', + '226': 'IM Used', + '300': 'Multiple Choices', + '301': 'Moved Permanently', + '302': 'Found', + '303': 'See Other', + '304': 'Not Modified', + '305': 'Use Proxy', + '307': 'Temporary Redirect', + '308': 'Permanent Redirect', + '400': 'Bad Request', + '401': 'Unauthorized', + '402': 'Payment Required', + '403': 'Forbidden', + '404': 'Not Found', + '405': 'Method Not Allowed', + '406': 'Not Acceptable', + '407': 'Proxy Authentication Required', + '408': 'Request Timeout', + '409': 'Conflict', + '410': 'Gone', + '411': 'Length Required', + '412': 'Precondition Failed', + '413': 'Content Too Large', + '414': 'URI Too Long', + '415': 'Unsupported Media Type', + '416': 'Range Not Satisfiable', + '417': 'Expectation Failed', + '418': 'I'm a Teapot', + '421': 'Misdirected Request', + '422': 'Unprocessable Content', + '423': 'Locked', + '424': 'Failed Dependency', + '425': 'Too Early', + '426': 'Upgrade Required', + '427': 'Unassigned', + '428': 'Precondition Required', + '429': 'Too Many Requests', + '430': 'Unassigned', + '431': 'Request Header Fields Too Large', + '451': 'Unavailable For Legal Reasons', + '500': 'Internal Server Error', + '501': 'Not Implemented', + '502': 'Bad Gateway', + '503': 'Service Unavailable', + '504': 'Gateway Timeout', + '505': 'HTTP Version Not Supported', + '506': 'Variant Also Negotiates', + '507': 'Insufficient Storage', + '508': 'Loop Detected', + '509': 'Unassigned', + '510': 'Not Extended', + '511': 'Network Authentication Required', +}; diff --git a/packages/backend/src/server/api/openapi/schemas.ts b/packages/backend/src/server/api/openapi/schemas.ts index 4bb72cd8a..04346c53b 100644 --- a/packages/backend/src/server/api/openapi/schemas.ts +++ b/packages/backend/src/server/api/openapi/schemas.ts @@ -48,7 +48,7 @@ export const schemas = { }, info: { description: 'Potentially more information, primarily intended for developers.', - } + }, }, required: ['code', 'endpoint', 'message'], },