mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-18 05:25:40 +09:00
fix(gateway): return precise rpc errors and bound snowflakes (#2491)
This commit is contained in:
1 parent
214d19d45a
commit
31d7cb81d6
8 files changed
+183
-16
No files matched your search
@@ -15,6 +15,8 @@ export const GatewayRpcMethodErrorCodes = {
|
||||
CONNECTION_NOT_FOUND: 'connection_not_found',
|
||||
MODERATOR_MISSING_CONNECT: 'moderator_missing_connect',
|
||||
TARGET_MISSING_CONNECT: 'target_missing_connect',
|
||||
INVALID_PARAMS: 'invalid_params',
|
||||
BATCH_TOO_LARGE: 'batch_too_large',
|
||||
} as const;
|
||||
|
||||
export class GatewayRpcMethodError extends Error {
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import {APIErrorCodes} from '@fluxer/constants/src/ApiErrorCodes';
|
||||
import {CallAlreadyExistsError} from '@fluxer/errors/src/domains/channel/CallAlreadyExistsError';
|
||||
import {InvalidChannelTypeForCallError} from '@fluxer/errors/src/domains/channel/InvalidChannelTypeForCallError';
|
||||
import {NoActiveCallError} from '@fluxer/errors/src/domains/channel/NoActiveCallError';
|
||||
import {UnknownChannelError} from '@fluxer/errors/src/domains/channel/UnknownChannelError';
|
||||
import {BadGatewayError} from '@fluxer/errors/src/domains/core/BadGatewayError';
|
||||
import {BadRequestError} from '@fluxer/errors/src/domains/core/BadRequestError';
|
||||
import {GatewayTimeoutError} from '@fluxer/errors/src/domains/core/GatewayTimeoutError';
|
||||
import {MissingPermissionsError} from '@fluxer/errors/src/domains/core/MissingPermissionsError';
|
||||
import {ServiceUnavailableError} from '@fluxer/errors/src/domains/core/ServiceUnavailableError';
|
||||
@@ -47,6 +49,8 @@ const GATEWAY_ERROR_TO_DOMAIN_ERROR: Record<string, () => Error> = {
|
||||
[GatewayRpcMethodErrorCodes.CONNECTION_NOT_FOUND]: () => new UserNotInVoiceError(),
|
||||
[GatewayRpcMethodErrorCodes.MODERATOR_MISSING_CONNECT]: () => new MissingPermissionsError(),
|
||||
[GatewayRpcMethodErrorCodes.TARGET_MISSING_CONNECT]: () => new MissingPermissionsError(),
|
||||
[GatewayRpcMethodErrorCodes.INVALID_PARAMS]: () => new BadRequestError({code: APIErrorCodes.INVALID_FORM_BODY}),
|
||||
[GatewayRpcMethodErrorCodes.BATCH_TOO_LARGE]: () => new BadRequestError({code: APIErrorCodes.INVALID_FORM_BODY}),
|
||||
};
|
||||
|
||||
interface DispatchGuildParams {
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import {APIErrorCodes} from '@fluxer/constants/src/ApiErrorCodes';
|
||||
import {BadGatewayError} from '@fluxer/errors/src/domains/core/BadGatewayError';
|
||||
import {BadRequestError} from '@fluxer/errors/src/domains/core/BadRequestError';
|
||||
import {UnknownGuildError} from '@fluxer/errors/src/domains/guild/UnknownGuildError';
|
||||
import {afterEach, describe, expect, it} from 'vitest';
|
||||
import {createGuildID, createUserID} from '../../BrandedTypes';
|
||||
import {GatewayRpcClient} from '../GatewayRpcClient';
|
||||
import {GatewayRpcMethodError, GatewayRpcMethodErrorCodes} from '../GatewayRpcError';
|
||||
import {GatewayService} from '../GatewayService';
|
||||
import type {IGatewayRpcTransport} from '../IGatewayRpcTransport';
|
||||
|
||||
function failingTransport(code: string): IGatewayRpcTransport {
|
||||
return {
|
||||
async call(): Promise<unknown> {
|
||||
throw new GatewayRpcMethodError(code);
|
||||
},
|
||||
async destroy(): Promise<void> {},
|
||||
};
|
||||
}
|
||||
|
||||
function serviceRaising(code: string): GatewayService {
|
||||
GatewayRpcClient.createForTests(failingTransport(code));
|
||||
return new GatewayService();
|
||||
}
|
||||
|
||||
describe('GatewayService gateway error mapping', () => {
|
||||
afterEach(async () => {
|
||||
await GatewayRpcClient.resetForTests();
|
||||
});
|
||||
|
||||
it('maps guild_not_found from guild.get_user_permissions to UnknownGuildError', async () => {
|
||||
const service = serviceRaising(GatewayRpcMethodErrorCodes.GUILD_NOT_FOUND);
|
||||
await expect(
|
||||
service.getUserPermissions({guildId: createGuildID(1n), userId: createUserID(2n)}),
|
||||
).rejects.toBeInstanceOf(UnknownGuildError);
|
||||
});
|
||||
|
||||
it('maps guild_not_found from guild.check_permission to UnknownGuildError', async () => {
|
||||
const service = serviceRaising(GatewayRpcMethodErrorCodes.GUILD_NOT_FOUND);
|
||||
await expect(
|
||||
service.checkPermission({guildId: createGuildID(1n), userId: createUserID(2n), permission: 1n}),
|
||||
).rejects.toBeInstanceOf(UnknownGuildError);
|
||||
});
|
||||
|
||||
it('maps an unrecognised gateway error from guild.check_permission to BadGatewayError', async () => {
|
||||
const service = serviceRaising('permission_check_error');
|
||||
await expect(
|
||||
service.checkPermission({guildId: createGuildID(1n), userId: createUserID(2n), permission: 1n}),
|
||||
).rejects.toBeInstanceOf(BadGatewayError);
|
||||
});
|
||||
|
||||
it('maps invalid_params to a 400 instead of an upstream failure', async () => {
|
||||
const service = serviceRaising(GatewayRpcMethodErrorCodes.INVALID_PARAMS);
|
||||
const error = await service
|
||||
.checkPermission({guildId: createGuildID(1n), userId: createUserID(2n), permission: 1n})
|
||||
.catch((raised: unknown) => raised);
|
||||
expect(error).toBeInstanceOf(BadRequestError);
|
||||
expect((error as BadRequestError).status).toBe(400);
|
||||
expect((error as BadRequestError).code).toBe(APIErrorCodes.INVALID_FORM_BODY);
|
||||
});
|
||||
|
||||
it('maps batch_too_large to a 400 instead of an upstream failure', async () => {
|
||||
const service = serviceRaising(GatewayRpcMethodErrorCodes.BATCH_TOO_LARGE);
|
||||
const error = await service
|
||||
.getUserPermissionsBatch({guildIds: [createGuildID(1n)], userId: createUserID(2n)})
|
||||
.catch((raised: unknown) => raised);
|
||||
expect(error).toBeInstanceOf(BadRequestError);
|
||||
expect((error as BadRequestError).status).toBe(400);
|
||||
expect((error as BadRequestError).code).toBe(APIErrorCodes.INVALID_FORM_BODY);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user