Skip to content

Commit 017663a

Browse files
authored
Merge pull request #149 from anatawa12/block-mentions-from-non-followed
spec(backend/NoteCreateService): ローカルユーザーがまだ誰もフォローしていないリモートユーザーによる通知を引き起こす可能性のある投稿を拒否できるように (MisskeyIO#462) (patched)
2 parents 8815630 + b13d3d2 commit 017663a

File tree

3 files changed

+30
-1
lines changed

3 files changed

+30
-1
lines changed

CHANGELOG.md

+9
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,15 @@
1212
1313
-->
1414

15+
## 202x.x.x-kinel.x (unreleased)
16+
17+
### General
18+
19+
### Client
20+
21+
### Server
22+
- ローカルユーザーがまだ誰もフォローしていないリモートユーザーによる、通知を引き起こす可能性のある投稿を拒否できるように
23+
1524
## 2024.2.0-kinel.1
1625

1726
### Client

packages/backend/src/config.ts

+3
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ type Source = {
100100
maxWebImageSize?: number;
101101
withRepliesInHomeTL?: boolean;
102102
withRepliesInUserList?: boolean;
103+
blockMentionsFromUnfamiliarRemoteUsers?: boolean;
103104
}
104105
};
105106

@@ -185,6 +186,7 @@ export type Config = {
185186
maxWebImageSize?: number;
186187
withRepliesInHomeTL?: boolean,
187188
withRepliesInUserList: boolean,
189+
blockMentionsFromUnfamiliarRemoteUsers: boolean;
188190
}
189191
};
190192

@@ -230,6 +232,7 @@ export function loadConfig(): Config {
230232
// to avoid merge conflict in the future, this is at top
231233
nirila: Object.assign({
232234
withRepliesInUserList: true,
235+
blockMentionsFromUnfamiliarRemoteUsers: false,
233236
}, config.nirila ?? {}),
234237
version,
235238
publishTarballInsteadOfProvideRepositoryUrl: !!config.publishTarballInsteadOfProvideRepositoryUrl,

packages/backend/src/core/NoteCreateService.ts

+18-1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ import { UtilityService } from '@/core/UtilityService.js';
5959
import { UserBlockingService } from '@/core/UserBlockingService.js';
6060
import { isReply } from '@/misc/is-reply.js';
6161
import { trackPromise } from '@/misc/promise-tracker.js';
62+
import { IdentifiableError } from '@/misc/identifiable-error.js';
63+
import { LoggerService } from '@/core/LoggerService.js';
64+
import type Logger from '@/logger.js';
6265

6366
type NotificationType = 'reply' | 'renote' | 'quote' | 'mention';
6467

@@ -149,6 +152,7 @@ type Option = {
149152

150153
@Injectable()
151154
export class NoteCreateService implements OnApplicationShutdown {
155+
private logger: Logger;
152156
#shutdownController = new AbortController();
153157

154158
public static ContainsProhibitedWordsError = class extends Error {};
@@ -219,7 +223,10 @@ export class NoteCreateService implements OnApplicationShutdown {
219223
private instanceChart: InstanceChart,
220224
private utilityService: UtilityService,
221225
private userBlockingService: UserBlockingService,
222-
) { }
226+
private loggerService: LoggerService,
227+
) {
228+
this.logger = this.loggerService.getLogger('note:create');
229+
}
223230

224231
@bindThis
225232
public async create(user: {
@@ -359,6 +366,16 @@ export class NoteCreateService implements OnApplicationShutdown {
359366
mentionedUsers = data.apMentions ?? await this.extractMentionedUsers(user, combinedTokens);
360367
}
361368

369+
const willCauseNotification = mentionedUsers.filter(u => u.host === null).length > 0 || data.reply?.userHost === null || data.renote?.userHost === null;
370+
371+
if (this.config.nirila.blockMentionsFromUnfamiliarRemoteUsers && user.host !== null && willCauseNotification) {
372+
const userEntity = await this.usersRepository.findOneBy({ id: user.id });
373+
if ((userEntity?.followersCount ?? 0) === 0) {
374+
this.logger.error('Request rejected because user has no local followers', { user: user.id, note: data });
375+
throw new IdentifiableError('e11b3a16-f543-4885-8eb1-66cad131dbfd', 'Notes including mentions, replies, or renotes from remote users are not allowed until user has at least one local follower.');
376+
}
377+
}
378+
362379
tags = tags.filter(tag => Array.from(tag).length <= 128).splice(0, 32);
363380

364381
if (data.reply && (user.id !== data.reply.userId) && !mentionedUsers.some(u => u.id === data.reply!.userId)) {

0 commit comments

Comments
 (0)