mirror of
https://github.com/paricafe/misskey.git
synced 2024-11-24 12:56:43 -06:00
chore(edit): only send to relative users
to prevent possible data leak
This commit is contained in:
parent
728c8c6eb8
commit
70a1c308f0
1 changed files with 68 additions and 28 deletions
|
@ -5,6 +5,7 @@
|
|||
|
||||
import { Brackets, In } from 'typeorm';
|
||||
import { Injectable, Inject } from '@nestjs/common';
|
||||
import * as mfm from 'mfm-js';
|
||||
import type { MiUser, MiLocalUser, MiRemoteUser } from '@/models/User.js';
|
||||
import type { MiNote, IMentionedRemoteUsers } from '@/models/Note.js';
|
||||
import type { InstancesRepository, NotesRepository, UsersRepository } from '@/models/_.js';
|
||||
|
@ -24,8 +25,10 @@ import { bindThis } from '@/decorators.js';
|
|||
import { MetaService } from '@/core/MetaService.js';
|
||||
import { SearchService } from '@/core/SearchService.js';
|
||||
import { ModerationLogService } from '@/core/ModerationLogService.js';
|
||||
import { isPureRenote } from '@/misc/is-pure-renote.js';
|
||||
import { IdService } from '@/core/IdService.js';
|
||||
import { trackPromise } from '@/misc/promise-tracker.js';
|
||||
import { extractMentions } from '@/misc/extract-mentions.js';
|
||||
import { RemoteUserResolveService } from '@/core/RemoteUserResolveService.js';
|
||||
|
||||
@Injectable()
|
||||
export class NoteUpdateService {
|
||||
|
@ -47,6 +50,7 @@ export class NoteUpdateService {
|
|||
private globalEventService: GlobalEventService,
|
||||
private relayService: RelayService,
|
||||
private federatedInstanceService: FederatedInstanceService,
|
||||
private remoteUserResolveService: RemoteUserResolveService,
|
||||
private apRendererService: ApRendererService,
|
||||
private apDeliverManagerService: ApDeliverManagerService,
|
||||
private metaService: MetaService,
|
||||
|
@ -82,7 +86,7 @@ export class NoteUpdateService {
|
|||
await this.apRendererService.renderNote(newNote, false), newNote,
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
this.deliverToConcerned(user, newNote, content);
|
||||
}
|
||||
}
|
||||
|
@ -114,38 +118,74 @@ export class NoteUpdateService {
|
|||
}
|
||||
|
||||
@bindThis
|
||||
private async getMentionedRemoteUsers(note: MiNote) {
|
||||
const where = [] as any[];
|
||||
private async extractMentionedUsers(user: { host: MiUser['host']; }, tokens: mfm.MfmNode[]): Promise<MiUser[]> {
|
||||
if (tokens == null) return [];
|
||||
|
||||
// mention / reply / dm
|
||||
const uris = (JSON.parse(note.mentionedRemoteUsers) as IMentionedRemoteUsers).map(x => x.uri);
|
||||
if (uris.length > 0) {
|
||||
where.push(
|
||||
{ uri: In(uris) },
|
||||
);
|
||||
}
|
||||
const mentions = extractMentions(tokens);
|
||||
let mentionedUsers = (await Promise.all(mentions.map(m =>
|
||||
this.remoteUserResolveService.resolveUser(m.username, m.host ?? user.host).catch(() => null),
|
||||
))).filter(x => x != null) as MiUser[];
|
||||
|
||||
// renote / quote
|
||||
if (note.renoteUserId) {
|
||||
where.push({
|
||||
id: note.renoteUserId,
|
||||
});
|
||||
}
|
||||
// Drop duplicate users
|
||||
mentionedUsers = mentionedUsers.filter((u, i, self) =>
|
||||
i === self.findIndex(u2 => u.id === u2.id),
|
||||
);
|
||||
|
||||
if (where.length === 0) return [];
|
||||
|
||||
return await this.usersRepository.find({
|
||||
where,
|
||||
}) as MiRemoteUser[];
|
||||
return mentionedUsers;
|
||||
}
|
||||
|
||||
@bindThis
|
||||
private async deliverToConcerned(user: { id: MiLocalUser['id']; host: null; }, note: MiNote, content: any) {
|
||||
this.apDeliverManagerService.deliverToFollowers(user, content);
|
||||
this.relayService.deliverToRelays(user, content);
|
||||
const remoteUsers = await this.getMentionedRemoteUsers(note);
|
||||
for (const remoteUser of remoteUsers) {
|
||||
this.apDeliverManagerService.deliverToUser(user, content, remoteUser);
|
||||
private async deliverToConcerned(user: { id: MiLocalUser['id']; host: null; }, note: MiNote, noteActivity: any) {
|
||||
const dm = this.apDeliverManagerService.createDeliverManager(user, noteActivity);
|
||||
|
||||
// Parse MFM if needed
|
||||
const tokens = (note.text ? mfm.parse(note.text)! : []);
|
||||
const cwTokens = note.cw ? mfm.parse(note.cw)! : [];
|
||||
|
||||
const combinedTokens = tokens.concat(cwTokens);
|
||||
|
||||
const mentionedUsers = await this.extractMentionedUsers(user, combinedTokens);
|
||||
|
||||
if (note.reply && (user.id !== note.reply.userId) && !mentionedUsers.some(u => u.id === note.reply!.userId)) {
|
||||
mentionedUsers.push(await this.usersRepository.findOneByOrFail({ id: note.reply.userId }));
|
||||
}
|
||||
|
||||
if (note.visibility === 'specified') {
|
||||
if (note.visibleUserIds == null) throw new Error('invalid param');
|
||||
|
||||
for (const u of note.visibleUserIds) {
|
||||
if (!mentionedUsers.some(x => x.id === u)) {
|
||||
mentionedUsers.push(await this.usersRepository.findOneByOrFail({ id: u }));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// メンションされたリモートユーザーに配送
|
||||
for (const u of mentionedUsers.filter(u => this.userEntityService.isRemoteUser(u))) {
|
||||
dm.addDirectRecipe(u as MiRemoteUser);
|
||||
}
|
||||
|
||||
// 投稿がリプライかつ投稿者がローカルユーザーかつリプライ先の投稿の投稿者がリモートユーザーなら配送
|
||||
if (note.reply && note.reply.userHost !== null) {
|
||||
const u = await this.usersRepository.findOneBy({ id: note.reply.userId });
|
||||
if (u && this.userEntityService.isRemoteUser(u)) dm.addDirectRecipe(u);
|
||||
}
|
||||
|
||||
// 投稿がRenoteかつ投稿者がローカルユーザーかつRenote元の投稿の投稿者がリモートユーザーなら配送
|
||||
if (note.renote && note.renote.userHost !== null) {
|
||||
const u = await this.usersRepository.findOneBy({ id: note.renote.userId });
|
||||
if (u && this.userEntityService.isRemoteUser(u)) dm.addDirectRecipe(u);
|
||||
}
|
||||
|
||||
// フォロワーに配送
|
||||
if (['public', 'home', 'followers'].includes(note.visibility)) {
|
||||
dm.addFollowersRecipe();
|
||||
}
|
||||
|
||||
if (['public'].includes(note.visibility)) {
|
||||
this.relayService.deliverToRelays(user, noteActivity);
|
||||
}
|
||||
|
||||
trackPromise(dm.execute());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue