fix(backend): ブロックした相手から自分のノートが見えないように(/users/featured-notes, /users/notes) (#12511)

* fix: ブロックした相手から自分のノートが見えないように(ユーザー,チャンネル)

* Update CHANGELOG.md

* /users/featured-notesでもブロックを考慮するように

* cacheServiceを使うように

* /channels/timeline.tsで必要のないnoteFilterを持たないように

* Update CHANGELOG.md

* FanoutTimelineEndpointServiceへの対応

- ブロックされている場合は、/users/notesでノートが表示されない
- ミュートしている場合は、ノートが表示される
This commit is contained in:
KanariKanaru 2023-12-07 18:15:38 +09:00 committed by GitHub
parent bcf6b7f5ee
commit e6d01e33e6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 21 additions and 4 deletions

View file

@ -62,6 +62,7 @@
- Fix: ユーザのノート一覧にてインスタンスミュートが効かない問題 - Fix: ユーザのノート一覧にてインスタンスミュートが効かない問題
- Fix: チャンネルのノート一覧にてインスタンスミュートが効かない問題 - Fix: チャンネルのノート一覧にてインスタンスミュートが効かない問題
- Fix: 「みつける」が年越し時に壊れる問題を修正 - Fix: 「みつける」が年越し時に壊れる問題を修正
- Fix: アカウントをブロックした際に、自身のユーザーのページでノートが相手に表示される問題を修正
## 2023.11.1 ## 2023.11.1

View file

@ -28,6 +28,7 @@ type TimelineOptions = {
redisTimelines: FanoutTimelineName[], redisTimelines: FanoutTimelineName[],
noteFilter?: (note: MiNote) => boolean, noteFilter?: (note: MiNote) => boolean,
alwaysIncludeMyNotes?: boolean; alwaysIncludeMyNotes?: boolean;
ignoreAuthorFromBlock?: boolean;
ignoreAuthorFromMute?: boolean; ignoreAuthorFromMute?: boolean;
excludeNoFiles?: boolean; excludeNoFiles?: boolean;
excludeReplies?: boolean; excludeReplies?: boolean;
@ -113,7 +114,7 @@ export class FanoutTimelineEndpointService {
const parentFilter = filter; const parentFilter = filter;
filter = (note) => { filter = (note) => {
if (isUserRelated(note, userIdsWhoBlockingMe, ps.ignoreAuthorFromMute)) return false; if (isUserRelated(note, userIdsWhoBlockingMe, ps.ignoreAuthorFromBlock)) return false;
if (isUserRelated(note, userIdsWhoMeMuting, ps.ignoreAuthorFromMute)) return false; if (isUserRelated(note, userIdsWhoMeMuting, ps.ignoreAuthorFromMute)) return false;
if (isPureRenote(note) && isUserRelated(note, userIdsWhoMeMutingRenotes, ps.ignoreAuthorFromMute)) return false; if (isPureRenote(note) && isUserRelated(note, userIdsWhoMeMutingRenotes, ps.ignoreAuthorFromMute)) return false;
if (isInstanceMuted(note, userMutedInstances)) return false; if (isInstanceMuted(note, userMutedInstances)) return false;

View file

@ -9,6 +9,8 @@ import { Endpoint } from '@/server/api/endpoint-base.js';
import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import { FeaturedService } from '@/core/FeaturedService.js'; import { FeaturedService } from '@/core/FeaturedService.js';
import { CacheService } from '@/core/CacheService.js';
import { isUserRelated } from '@/misc/is-user-related.js';
export const meta = { export const meta = {
tags: ['notes'], tags: ['notes'],
@ -46,6 +48,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
private noteEntityService: NoteEntityService, private noteEntityService: NoteEntityService,
private featuredService: FeaturedService, private featuredService: FeaturedService,
private cacheService: CacheService,
) { ) {
super(meta, paramDef, async (ps, me) => { super(meta, paramDef, async (ps, me) => {
let noteIds = await this.featuredService.getPerUserNotesRanking(ps.userId, 50); let noteIds = await this.featuredService.getPerUserNotesRanking(ps.userId, 50);
@ -60,6 +63,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
return []; return [];
} }
const [
userIdsWhoMeMuting,
userIdsWhoBlockingMe,
] = me ? await Promise.all([
this.cacheService.userMutingsCache.fetch(me.id),
this.cacheService.userBlockedCache.fetch(me.id),
]) : [new Set<string>(), new Set<string>()];
const query = this.notesRepository.createQueryBuilder('note') const query = this.notesRepository.createQueryBuilder('note')
.where('note.id IN (:...noteIds)', { noteIds: noteIds }) .where('note.id IN (:...noteIds)', { noteIds: noteIds })
.innerJoinAndSelect('note.user', 'user') .innerJoinAndSelect('note.user', 'user')
@ -69,10 +80,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
.leftJoinAndSelect('renote.user', 'renoteUser') .leftJoinAndSelect('renote.user', 'renoteUser')
.leftJoinAndSelect('note.channel', 'channel'); .leftJoinAndSelect('note.channel', 'channel');
const notes = await query.getMany(); const notes = (await query.getMany()).filter(note => {
notes.sort((a, b) => a.id > b.id ? -1 : 1); if (me && isUserRelated(note, userIdsWhoBlockingMe, false)) return false;
if (me && isUserRelated(note, userIdsWhoMeMuting, true)) return false;
// TODO: ミュート等考慮 return true;
});
notes.sort((a, b) => a.id > b.id ? -1 : 1);
return await this.noteEntityService.packMany(notes, me); return await this.noteEntityService.packMany(notes, me);
}); });