mirror of
https://github.com/fluxerapp/fluxer.git
synced 2026-09-03 05:10:25 +03:00
fix: allow POST /users/@me/channels with recipient_id 0 (#1160)
This commit is contained in:
@@ -23,6 +23,7 @@ import {requireEmailVerified} from '../../auth/EmailVerificationUtils';
|
||||
import type {ChannelID, UserID} from '../../BrandedTypes';
|
||||
import {createChannelID, createMessageID, createUserID} from '../../BrandedTypes';
|
||||
import {mapChannelToResponse} from '../../channel/ChannelMappers';
|
||||
import {SYSTEM_USER_ID} from '../../constants/Core';
|
||||
import type {IChannelRepository} from '../../channel/IChannelRepository';
|
||||
import type {ChannelService} from '../../channel/services/ChannelService';
|
||||
import {dispatchMessageCreateBroadcast} from '../../channel/services/message/MessageGatewayDispatch';
|
||||
@@ -161,7 +162,7 @@ export class UserChannelService {
|
||||
requestCache,
|
||||
});
|
||||
}
|
||||
if (!data.recipient_id) {
|
||||
if (data.recipient_id == null) {
|
||||
throw InputValidationError.fromCode('recipient_id', ValidationErrorCodes.RECIPIENT_IDS_CANNOT_BE_EMPTY);
|
||||
}
|
||||
const recipientId = createUserID(data.recipient_id);
|
||||
@@ -179,6 +180,9 @@ export class UserChannelService {
|
||||
}
|
||||
const targetUser = await this.userRepository.findUnique(recipientId);
|
||||
if (!targetUser) throw new UnknownUserError();
|
||||
if (recipientId === SYSTEM_USER_ID) {
|
||||
return await this.createNewDMChannel({userId, recipientId, userCacheService, requestCache});
|
||||
}
|
||||
await this.validateNewDmAllowed({sender: callingUser, recipient: targetUser});
|
||||
const channel = await this.createNewDMChannel({userId, recipientId, userCacheService, requestCache});
|
||||
return channel;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
import {FLUXERBOT_ID} from '@fluxer/constants/src/AppConstants';
|
||||
import {ChannelTypes} from '@fluxer/constants/src/ChannelConstants';
|
||||
import {UserFlags} from '@fluxer/constants/src/UserConstants';
|
||||
import {afterAll, beforeAll, beforeEach, describe, expect, test} from 'vitest';
|
||||
@@ -13,10 +14,14 @@ import {
|
||||
createFriendship,
|
||||
createGroupDmChannel,
|
||||
createGuild,
|
||||
deleteChannel,
|
||||
getChannel,
|
||||
type MinimalChannelResponse,
|
||||
sendChannelMessage,
|
||||
} from '../../channel/tests/ChannelTestUtils';
|
||||
import {createChannelID, createUserID} from '../../BrandedTypes';
|
||||
import {SYSTEM_USER_ID} from '../../constants/Core';
|
||||
import {UserRepository} from '../../user/repositories/UserRepository';
|
||||
import {ensureSessionStarted} from '../../message/tests/MessageTestUtils';
|
||||
import {type ApiTestHarness, createApiTestHarness} from '../../test/ApiTestHarness';
|
||||
import {HTTP_STATUS} from '../../test/TestConstants';
|
||||
@@ -149,6 +154,32 @@ describe('UserChannelService', () => {
|
||||
const channel2 = await createDmChannel(harness, user1.token, user2.userId);
|
||||
expect(channel2.id).toBe(channel1.id);
|
||||
});
|
||||
test('reopening closed system user DM accepts recipient_id 0', async () => {
|
||||
const user = await createTestAccount(harness);
|
||||
const userId = createUserID(BigInt(user.userId));
|
||||
const channelId = createChannelID(1000000000000000001n);
|
||||
const userRepository = new UserRepository();
|
||||
const channel = await userRepository.createDmChannelAndState(userId, SYSTEM_USER_ID, channelId);
|
||||
await userRepository.openPrivateChannelForUser(userId, channel);
|
||||
await deleteChannel(harness, user.token, channelId.toString());
|
||||
const reopened = await createBuilder<MinimalChannelResponse>(harness, user.token)
|
||||
.post('/users/@me/channels')
|
||||
.body({recipient_id: FLUXERBOT_ID})
|
||||
.expect(HTTP_STATUS.OK)
|
||||
.execute();
|
||||
expect(reopened.id).toBe(channelId.toString());
|
||||
expect(reopened.type).toBe(ChannelTypes.DM);
|
||||
});
|
||||
test('can create new system user DM without friendship or mutual guilds', async () => {
|
||||
const user = await createTestAccount(harness);
|
||||
const channel = await createBuilder<MinimalChannelResponse>(harness, user.token)
|
||||
.post('/users/@me/channels')
|
||||
.body({recipient_id: FLUXERBOT_ID})
|
||||
.expect(HTTP_STATUS.OK)
|
||||
.execute();
|
||||
expect(channel.id).toBeDefined();
|
||||
expect(channel.type).toBe(ChannelTypes.DM);
|
||||
});
|
||||
});
|
||||
describe('Group DM creation', () => {
|
||||
test('can create group DM with friends', async () => {
|
||||
|
||||
@@ -79,4 +79,11 @@ describe('CreatePrivateChannelRequest', () => {
|
||||
);
|
||||
expect(CreatePrivateChannelRequest.safeParse({recipients}).success).toBe(false);
|
||||
});
|
||||
it('allows DM requests to the system user id 0', () => {
|
||||
const parsed = CreatePrivateChannelRequest.safeParse({recipient_id: '0'});
|
||||
expect(parsed.success).toBe(true);
|
||||
if (parsed.success) {
|
||||
expect(parsed.data.recipient_id).toBe(0n);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -272,9 +272,13 @@ export const CreatePrivateChannelRequest = z
|
||||
.optional()
|
||||
.describe(`Array of user IDs for creating a group DM (max ${MAX_GROUP_DM_OTHER_RECIPIENTS})`),
|
||||
})
|
||||
.refine((data) => (data.recipient_id && !data.recipients) || (!data.recipient_id && data.recipients), {
|
||||
message: 'Either recipient_id or recipients must be provided, but not both',
|
||||
});
|
||||
.refine(
|
||||
(data) =>
|
||||
(data.recipient_id != null && data.recipients == null) || (data.recipient_id == null && data.recipients != null),
|
||||
{
|
||||
message: 'Either recipient_id or recipients must be provided, but not both',
|
||||
},
|
||||
);
|
||||
|
||||
export type CreatePrivateChannelRequest = z.infer<typeof CreatePrivateChannelRequest>;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user