mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-18 21:45:31 +09:00
fix(api): always allow opening a dm channel (#2423)
This commit is contained in:
1 parent
902dd60ff9
commit
9c1b38aeaf
4 files changed
+22
-51
No files matched your search
@@ -31,7 +31,7 @@ describe('DM Blocking Behaviors', () => {
|
|||||||
await harness?.shutdown();
|
await harness?.shutdown();
|
||||||
});
|
});
|
||||||
describe('DM Creation Blocking', () => {
|
describe('DM Creation Blocking', () => {
|
||||||
it('prevents DM creation when the other user has blocked you, even with mutual guild', async () => {
|
it('allows DM creation when the other user has blocked you', async () => {
|
||||||
const user1 = await createTestAccount(harness);
|
const user1 = await createTestAccount(harness);
|
||||||
const user2 = await createTestAccount(harness);
|
const user2 = await createTestAccount(harness);
|
||||||
const guild = await createGuild(harness, user1.token, 'Test Community');
|
const guild = await createGuild(harness, user1.token, 'Test Community');
|
||||||
@@ -42,10 +42,10 @@ describe('DM Blocking Behaviors', () => {
|
|||||||
await createBuilder(harness, user2.token)
|
await createBuilder(harness, user2.token)
|
||||||
.post('/users/@me/channels')
|
.post('/users/@me/channels')
|
||||||
.body({recipient_id: user1.userId})
|
.body({recipient_id: user1.userId})
|
||||||
.expect(HTTP_STATUS.BAD_REQUEST)
|
.expect(HTTP_STATUS.OK)
|
||||||
.execute();
|
.execute();
|
||||||
});
|
});
|
||||||
it('prevents DM creation with someone you have blocked, even with mutual guild', async () => {
|
it('allows DM creation with someone you have blocked', async () => {
|
||||||
const user1 = await createTestAccount(harness);
|
const user1 = await createTestAccount(harness);
|
||||||
const user2 = await createTestAccount(harness);
|
const user2 = await createTestAccount(harness);
|
||||||
const guild = await createGuild(harness, user1.token, 'Test Community');
|
const guild = await createGuild(harness, user1.token, 'Test Community');
|
||||||
@@ -56,7 +56,7 @@ describe('DM Blocking Behaviors', () => {
|
|||||||
await createBuilder(harness, user1.token)
|
await createBuilder(harness, user1.token)
|
||||||
.post('/users/@me/channels')
|
.post('/users/@me/channels')
|
||||||
.body({recipient_id: user2.userId})
|
.body({recipient_id: user2.userId})
|
||||||
.expect(HTTP_STATUS.BAD_REQUEST)
|
.expect(HTTP_STATUS.OK)
|
||||||
.execute();
|
.execute();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
+7
-9
@@ -1,11 +1,11 @@
|
|||||||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||||
|
|
||||||
import {afterAll, beforeAll, beforeEach, describe, it} from 'vitest';
|
import {afterAll, beforeAll, beforeEach, describe, expect, it} from 'vitest';
|
||||||
import {createTestAccount} from '../../auth/tests/AuthTestUtils';
|
import {createTestAccount} from '../../auth/tests/AuthTestUtils';
|
||||||
import {type ApiTestHarness, createApiTestHarness} from '../../test/ApiTestHarness';
|
import {type ApiTestHarness, createApiTestHarness} from '../../test/ApiTestHarness';
|
||||||
import {createBuilder} from '../../test/TestRequestBuilder';
|
import {createDmChannel} from './ChannelTestUtils';
|
||||||
|
|
||||||
describe('DM creation requires friendship or mutual guild', () => {
|
describe('DM creation allowed with strangers', () => {
|
||||||
let harness: ApiTestHarness;
|
let harness: ApiTestHarness;
|
||||||
beforeAll(async () => {
|
beforeAll(async () => {
|
||||||
harness = await createApiTestHarness();
|
harness = await createApiTestHarness();
|
||||||
@@ -16,13 +16,11 @@ describe('DM creation requires friendship or mutual guild', () => {
|
|||||||
afterAll(async () => {
|
afterAll(async () => {
|
||||||
await harness?.shutdown();
|
await harness?.shutdown();
|
||||||
});
|
});
|
||||||
it('prevents DM creation with strangers who you do not share a guild with and are not friends with', async () => {
|
it('allows opening a DM with a stranger who shares no guild and is not a friend', async () => {
|
||||||
const user1 = await createTestAccount(harness);
|
const user1 = await createTestAccount(harness);
|
||||||
const user2 = await createTestAccount(harness);
|
const user2 = await createTestAccount(harness);
|
||||||
await createBuilder(harness, user1.token)
|
const dm = await createDmChannel(harness, user1.token, user2.userId);
|
||||||
.post('/users/@me/channels')
|
expect(dm.id).toBeTruthy();
|
||||||
.body({recipient_id: user2.userId})
|
expect(dm.id.length).toBeGreaterThan(0);
|
||||||
.expect(400)
|
|
||||||
.execute();
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -5,7 +5,6 @@ import type {LimitKey} from '@fluxer/constants/src/LimitConfigMetadata';
|
|||||||
import {MAX_GROUP_DM_RECIPIENTS, MAX_GROUP_DMS_PER_USER} from '@fluxer/constants/src/LimitConstants';
|
import {MAX_GROUP_DM_RECIPIENTS, MAX_GROUP_DMS_PER_USER} from '@fluxer/constants/src/LimitConstants';
|
||||||
import {RelationshipTypes} from '@fluxer/constants/src/UserConstants';
|
import {RelationshipTypes} from '@fluxer/constants/src/UserConstants';
|
||||||
import {ValidationErrorCodes} from '@fluxer/constants/src/ValidationErrorCodes';
|
import {ValidationErrorCodes} from '@fluxer/constants/src/ValidationErrorCodes';
|
||||||
import {CannotSendMessagesToUserError} from '@fluxer/errors/src/domains/channel/CannotSendMessagesToUserError';
|
|
||||||
import type {GroupDmUnaddableRecipient} from '@fluxer/errors/src/domains/channel/GroupDmRecipientsNotAddableError';
|
import type {GroupDmUnaddableRecipient} from '@fluxer/errors/src/domains/channel/GroupDmRecipientsNotAddableError';
|
||||||
import {GroupDmRecipientsNotAddableError} from '@fluxer/errors/src/domains/channel/GroupDmRecipientsNotAddableError';
|
import {GroupDmRecipientsNotAddableError} from '@fluxer/errors/src/domains/channel/GroupDmRecipientsNotAddableError';
|
||||||
import {MaxGroupDmRecipientsError} from '@fluxer/errors/src/domains/channel/MaxGroupDmRecipientsError';
|
import {MaxGroupDmRecipientsError} from '@fluxer/errors/src/domains/channel/MaxGroupDmRecipientsError';
|
||||||
@@ -30,7 +29,6 @@ import {
|
|||||||
createMessageResponseDataService,
|
createMessageResponseDataService,
|
||||||
messageResponseAccessForGuild,
|
messageResponseAccessForGuild,
|
||||||
} from '../../channel/services/message/MessageResponseDataService';
|
} from '../../channel/services/message/MessageResponseDataService';
|
||||||
import {SYSTEM_USER_ID} from '../../constants/Core';
|
|
||||||
import type {IGatewayService} from '../../infrastructure/IGatewayService';
|
import type {IGatewayService} from '../../infrastructure/IGatewayService';
|
||||||
import type {ISnowflakeService} from '../../infrastructure/ISnowflakeService';
|
import type {ISnowflakeService} from '../../infrastructure/ISnowflakeService';
|
||||||
import type {UserCacheService} from '../../infrastructure/UserCacheService';
|
import type {UserCacheService} from '../../infrastructure/UserCacheService';
|
||||||
@@ -45,7 +43,6 @@ import type {UserPermissionUtils} from '../../utils/UserPermissionUtils';
|
|||||||
import type {IUserAccountRepository} from '../repositories/IUserAccountRepository';
|
import type {IUserAccountRepository} from '../repositories/IUserAccountRepository';
|
||||||
import type {IUserChannelRepository} from '../repositories/IUserChannelRepository';
|
import type {IUserChannelRepository} from '../repositories/IUserChannelRepository';
|
||||||
import type {IUserRelationshipRepository} from '../repositories/IUserRelationshipRepository';
|
import type {IUserRelationshipRepository} from '../repositories/IUserRelationshipRepository';
|
||||||
import {isBugHunterBotUser} from '../UserHelpers';
|
|
||||||
import type {DirectMessageSpamMitigationService} from './DirectMessageSpamMitigationService';
|
import type {DirectMessageSpamMitigationService} from './DirectMessageSpamMitigationService';
|
||||||
import {createDirectMessageSpamMitigationService} from './DirectMessageSpamMitigationService';
|
import {createDirectMessageSpamMitigationService} from './DirectMessageSpamMitigationService';
|
||||||
|
|
||||||
@@ -180,13 +177,8 @@ 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});
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
async pinDmChannel({userId, channelId}: {userId: UserID; channelId: ChannelID}): Promise<void> {
|
async pinDmChannel({userId, channelId}: {userId: UserID; channelId: ChannelID}): Promise<void> {
|
||||||
const channel = await this.channelService.channelData.operations.getChannel({userId, channelId});
|
const channel = await this.channelService.channelData.operations.getChannel({userId, channelId});
|
||||||
@@ -258,30 +250,6 @@ export class UserChannelService {
|
|||||||
return await this.userRepository.findExistingDmState(userId, recipientId);
|
return await this.userRepository.findExistingDmState(userId, recipientId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async validateNewDmAllowed({sender, recipient}: {sender: User; recipient: User}): Promise<void> {
|
|
||||||
if (isBugHunterBotUser(sender)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const [senderBlockedRecipient, recipientBlockedSender, friendship] = await Promise.all([
|
|
||||||
this.userRepository.getRelationship(sender.id, recipient.id, RelationshipTypes.BLOCKED),
|
|
||||||
this.userRepository.getRelationship(recipient.id, sender.id, RelationshipTypes.BLOCKED),
|
|
||||||
this.userRepository.getRelationship(sender.id, recipient.id, RelationshipTypes.FRIEND),
|
|
||||||
]);
|
|
||||||
if (senderBlockedRecipient || recipientBlockedSender) {
|
|
||||||
throw new CannotSendMessagesToUserError();
|
|
||||||
}
|
|
||||||
if (friendship) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const hasMutualGuilds = await this.userPermissionUtils.checkMutualGuildsForDmAccessAsync({
|
|
||||||
userId: sender.id,
|
|
||||||
targetId: recipient.id,
|
|
||||||
});
|
|
||||||
if (!hasMutualGuilds) {
|
|
||||||
throw new CannotSendMessagesToUserError();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async ensureDmOpenForBothUsers({
|
async ensureDmOpenForBothUsers({
|
||||||
userId,
|
userId,
|
||||||
recipientId,
|
recipientId,
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ describe('UserChannelService', () => {
|
|||||||
.expect(HTTP_STATUS.NOT_FOUND, 'UNKNOWN_USER')
|
.expect(HTTP_STATUS.NOT_FOUND, 'UNKNOWN_USER')
|
||||||
.execute();
|
.execute();
|
||||||
});
|
});
|
||||||
test('cannot create DM with blocked user', async () => {
|
test('can create DM with a user who blocked you', async () => {
|
||||||
const user1 = await createTestAccount(harness);
|
const user1 = await createTestAccount(harness);
|
||||||
const user2 = await createTestAccount(harness);
|
const user2 = await createTestAccount(harness);
|
||||||
const guild = await createGuild(harness, user1.token, 'Test Community');
|
const guild = await createGuild(harness, user1.token, 'Test Community');
|
||||||
@@ -117,11 +117,16 @@ describe('UserChannelService', () => {
|
|||||||
const invite = await createChannelInvite(harness, user1.token, systemChannel.id);
|
const invite = await createChannelInvite(harness, user1.token, systemChannel.id);
|
||||||
await acceptInvite(harness, user2.token, invite.code);
|
await acceptInvite(harness, user2.token, invite.code);
|
||||||
await blockUser(harness, user1, user2.userId);
|
await blockUser(harness, user1, user2.userId);
|
||||||
await createBuilder(harness, user1.token)
|
const channel = await createDmChannel(harness, user1.token, user2.userId);
|
||||||
.post('/users/@me/channels')
|
expect(channel.id).toBeDefined();
|
||||||
.body({recipient_id: user2.userId})
|
expect(channel.type).toBe(ChannelTypes.DM);
|
||||||
.expect(HTTP_STATUS.BAD_REQUEST, 'CANNOT_SEND_MESSAGES_TO_USER')
|
});
|
||||||
.execute();
|
test('can create DM with a user who shares no mutual community', async () => {
|
||||||
|
const user1 = await createTestAccount(harness);
|
||||||
|
const user2 = await createTestAccount(harness);
|
||||||
|
const channel = await createDmChannel(harness, user1.token, user2.userId);
|
||||||
|
expect(channel.id).toBeDefined();
|
||||||
|
expect(channel.type).toBe(ChannelTypes.DM);
|
||||||
});
|
});
|
||||||
test('unclaimed account cannot create DM', async () => {
|
test('unclaimed account cannot create DM', async () => {
|
||||||
const user1 = await createTestAccount(harness);
|
const user1 = await createTestAccount(harness);
|
||||||
|
|||||||
Reference in new issue
Block a user