fix(api): correct guild permission and mfa checks (#2499)

This commit is contained in:
Hampus authored and GitHub committed 2026-09-06 15:28:01 +02:00
1 parent f392636857
commit 908e1b8bd4
12 files changed
+303 -86

No files matched your search

@@ -174,7 +174,7 @@ export abstract class BaseChannelAuthService {
const guildId = channel.guildId!;
const [authContextResult, guildMemberResult] = await Promise.all([
this.fetchGuildAuthContextOrThrow({guildId, userId, channelId: this.parentLookupChannelId(channel)}),
this.gatewayService.getGuildMember({guildId, userId}),
this.fetchGuildMemberOrThrow({guildId, userId}),
]);
if (!authContextResult) {
this.throwGuildAccessError();
@@ -285,6 +285,18 @@ export abstract class BaseChannelAuthService {
}
}
private async fetchGuildMemberOrThrow(params: {guildId: GuildID; userId: UserID}): Promise<{
success: boolean;
memberData?: GuildMemberResponse;
}> {
try {
return await this.gatewayService.getGuildMember(params);
} catch (error) {
await this.handleGuildAccessError(error, params.guildId);
throw error;
}
}
private async handleGuildAccessError(error: unknown, guildId: GuildID): Promise<void> {
if (error instanceof UnknownGuildError) {
if (await this.guildExists(guildId)) {
@@ -2,6 +2,7 @@
import {Permissions} from '@fluxer/constants/src/ChannelConstants';
import {MAX_MESSAGE_LENGTH_PREMIUM} from '@fluxer/constants/src/LimitConstants';
import {UnknownGuildError} from '@fluxer/errors/src/domains/guild/UnknownGuildError';
import type {MessageResponse} from '@fluxer/schema/src/domains/message/MessageResponseSchemas';
import {afterAll, beforeAll, beforeEach, describe, expect, it, vi} from 'vitest';
import {createTestAccount} from '../../auth/tests/AuthTestUtils';
@@ -9,7 +10,7 @@ import {authorizeBot, createTestBotAccount} from '../../bot/tests/BotTestUtils';
import {ensureSessionStarted} from '../../message/tests/MessageTestUtils';
import {getGatewayService} from '../../middleware/ServiceRegistry';
import {type ApiTestHarness, createApiTestHarness} from '../../test/ApiTestHarness';
import {HTTP_STATUS} from '../../test/TestConstants';
import {HTTP_STATUS, TEST_TIMEOUTS, wait} from '../../test/TestConstants';
import {createBuilder} from '../../test/TestRequestBuilder';
import {ChannelDataRepository} from '../repositories/ChannelDataRepository';
import {
@@ -169,6 +170,34 @@ describe('Message send permissions', () => {
}
});
it('returns ACCESS_DENIED not UNKNOWN_GUILD when the Gateway has dropped a guild whose record survives', async () => {
const {owner, systemChannel} = await setupTestGuildWithMembers(harness, 0);
await ensureSessionStarted(harness, owner.token);
const gatewayService = getGatewayService();
for (const memberSettlesFirst of [true, false]) {
const getGuildAuthContext = vi.spyOn(gatewayService, 'getGuildAuthContext').mockImplementation(async () => {
if (memberSettlesFirst) await wait(TEST_TIMEOUTS.IMMEDIATE);
throw new UnknownGuildError();
});
const getGuildMember = vi.spyOn(gatewayService, 'getGuildMember').mockImplementation(async () => {
if (!memberSettlesFirst) await wait(TEST_TIMEOUTS.IMMEDIATE);
throw new UnknownGuildError();
});
try {
await createBuilder(harness, owner.token)
.post(`/channels/${systemChannel.id}/messages`)
.body({content: 'the gateway forgot this guild'})
.expect(HTTP_STATUS.FORBIDDEN, 'ACCESS_DENIED')
.execute();
} finally {
getGuildAuthContext.mockRestore();
getGuildMember.mockRestore();
}
}
});
it('allows bot message content up to 4000 characters', async () => {
const {owner, guild, systemChannel} = await setupTestGuildWithMembers(harness, 0);
const botAccount = await createTestBotAccount(harness);