mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-17 21:15:32 +09:00
fix: allow POST /users/@me/channels with recipient_id 0 (#1160)
This commit is contained in:
1 parent
a45693f581
commit
41ec2544cf
4 files changed
+50
-4
No files matched your search
@@ -23,6 +23,7 @@ import {requireEmailVerified} from '../../auth/EmailVerificationUtils';
|
|||||||
import type {ChannelID, UserID} from '../../BrandedTypes';
|
import type {ChannelID, UserID} from '../../BrandedTypes';
|
||||||
import {createChannelID, createMessageID, createUserID} from '../../BrandedTypes';
|
import {createChannelID, createMessageID, createUserID} from '../../BrandedTypes';
|
||||||
import {mapChannelToResponse} from '../../channel/ChannelMappers';
|
import {mapChannelToResponse} from '../../channel/ChannelMappers';
|
||||||
|
import {SYSTEM_USER_ID} from '../../constants/Core';
|
||||||
import type {IChannelRepository} from '../../channel/IChannelRepository';
|
import type {IChannelRepository} from '../../channel/IChannelRepository';
|
||||||
import type {ChannelService} from '../../channel/services/ChannelService';
|
import type {ChannelService} from '../../channel/services/ChannelService';
|
||||||
import {dispatchMessageCreateBroadcast} from '../../channel/services/message/MessageGatewayDispatch';
|
import {dispatchMessageCreateBroadcast} from '../../channel/services/message/MessageGatewayDispatch';
|
||||||
@@ -161,7 +162,7 @@ export class UserChannelService {
|
|||||||
requestCache,
|
requestCache,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (!data.recipient_id) {
|
if (data.recipient_id == null) {
|
||||||
throw InputValidationError.fromCode('recipient_id', ValidationErrorCodes.RECIPIENT_IDS_CANNOT_BE_EMPTY);
|
throw InputValidationError.fromCode('recipient_id', ValidationErrorCodes.RECIPIENT_IDS_CANNOT_BE_EMPTY);
|
||||||
}
|
}
|
||||||
const recipientId = createUserID(data.recipient_id);
|
const recipientId = createUserID(data.recipient_id);
|
||||||
@@ -179,6 +180,9 @@ export class UserChannelService {
|
|||||||
}
|
}
|
||||||
const targetUser = await this.userRepository.findUnique(recipientId);
|
const targetUser = await this.userRepository.findUnique(recipientId);
|
||||||
if (!targetUser) throw new UnknownUserError();
|
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});
|
await this.validateNewDmAllowed({sender: callingUser, recipient: targetUser});
|
||||||
const channel = await this.createNewDMChannel({userId, recipientId, userCacheService, requestCache});
|
const channel = await this.createNewDMChannel({userId, recipientId, userCacheService, requestCache});
|
||||||
return channel;
|
return channel;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
|
import {FLUXERBOT_ID} from '@fluxer/constants/src/AppConstants';
|
||||||
import {ChannelTypes} from '@fluxer/constants/src/ChannelConstants';
|
import {ChannelTypes} from '@fluxer/constants/src/ChannelConstants';
|
||||||
import {UserFlags} from '@fluxer/constants/src/UserConstants';
|
import {UserFlags} from '@fluxer/constants/src/UserConstants';
|
||||||
import {afterAll, beforeAll, beforeEach, describe, expect, test} from 'vitest';
|
import {afterAll, beforeAll, beforeEach, describe, expect, test} from 'vitest';
|
||||||
@@ -13,10 +14,14 @@ import {
|
|||||||
createFriendship,
|
createFriendship,
|
||||||
createGroupDmChannel,
|
createGroupDmChannel,
|
||||||
createGuild,
|
createGuild,
|
||||||
|
deleteChannel,
|
||||||
getChannel,
|
getChannel,
|
||||||
type MinimalChannelResponse,
|
type MinimalChannelResponse,
|
||||||
sendChannelMessage,
|
sendChannelMessage,
|
||||||
} from '../../channel/tests/ChannelTestUtils';
|
} 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 {ensureSessionStarted} from '../../message/tests/MessageTestUtils';
|
||||||
import {type ApiTestHarness, createApiTestHarness} from '../../test/ApiTestHarness';
|
import {type ApiTestHarness, createApiTestHarness} from '../../test/ApiTestHarness';
|
||||||
import {HTTP_STATUS} from '../../test/TestConstants';
|
import {HTTP_STATUS} from '../../test/TestConstants';
|
||||||
@@ -149,6 +154,32 @@ describe('UserChannelService', () => {
|
|||||||
const channel2 = await createDmChannel(harness, user1.token, user2.userId);
|
const channel2 = await createDmChannel(harness, user1.token, user2.userId);
|
||||||
expect(channel2.id).toBe(channel1.id);
|
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', () => {
|
describe('Group DM creation', () => {
|
||||||
test('can create group DM with friends', async () => {
|
test('can create group DM with friends', async () => {
|
||||||
|
|||||||
@@ -79,4 +79,11 @@ describe('CreatePrivateChannelRequest', () => {
|
|||||||
);
|
);
|
||||||
expect(CreatePrivateChannelRequest.safeParse({recipients}).success).toBe(false);
|
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()
|
.optional()
|
||||||
.describe(`Array of user IDs for creating a group DM (max ${MAX_GROUP_DM_OTHER_RECIPIENTS})`),
|
.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), {
|
.refine(
|
||||||
message: 'Either recipient_id or recipients must be provided, but not both',
|
(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>;
|
export type CreatePrivateChannelRequest = z.infer<typeof CreatePrivateChannelRequest>;
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user