enhance: Check if notifierId is valid in NotificationEntityService

This commit is contained in:
taichan 2024-02-20 14:34:50 +09:00
parent 45a067788b
commit b09abb8c59
No known key found for this signature in database
GPG Key ID: CCE28623AFA24E9C
1 changed files with 73 additions and 2 deletions

View File

@ -15,6 +15,7 @@ import type { Packed } from '@/misc/json-schema.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { isNotNull } from '@/misc/is-not-null.js'; import { isNotNull } from '@/misc/is-not-null.js';
import { FilterUnionByProperty, notificationTypes } from '@/types.js'; import { FilterUnionByProperty, notificationTypes } from '@/types.js';
import { CacheService } from '@/core/CacheService.js';
import { RoleEntityService } from './RoleEntityService.js'; import { RoleEntityService } from './RoleEntityService.js';
import type { OnModuleInit } from '@nestjs/common'; import type { OnModuleInit } from '@nestjs/common';
import type { UserEntityService } from './UserEntityService.js'; import type { UserEntityService } from './UserEntityService.js';
@ -41,6 +42,8 @@ export class NotificationEntityService implements OnModuleInit {
@Inject(DI.followRequestsRepository) @Inject(DI.followRequestsRepository)
private followRequestsRepository: FollowRequestsRepository, private followRequestsRepository: FollowRequestsRepository,
private cacheService: CacheService,
//private userEntityService: UserEntityService, //private userEntityService: UserEntityService,
//private noteEntityService: NoteEntityService, //private noteEntityService: NoteEntityService,
) { ) {
@ -64,8 +67,11 @@ export class NotificationEntityService implements OnModuleInit {
packedNotes: Map<MiNote['id'], Packed<'Note'>>; packedNotes: Map<MiNote['id'], Packed<'Note'>>;
packedUsers: Map<MiUser['id'], Packed<'UserLite'>>; packedUsers: Map<MiUser['id'], Packed<'UserLite'>>;
}, },
): Promise<Packed<'Notification'>> { ): Promise<Packed<'Notification'>|null> {
const notification = src; const notification = src;
if (!(await this.#isValidNotifier(notification, meId))) return null;
const noteIfNeed = NOTE_REQUIRED_NOTIFICATION_TYPES.has(notification.type) && 'noteId' in notification ? ( const noteIfNeed = NOTE_REQUIRED_NOTIFICATION_TYPES.has(notification.type) && 'noteId' in notification ? (
hint?.packedNotes != null hint?.packedNotes != null
? hint.packedNotes.get(notification.noteId) ? hint.packedNotes.get(notification.noteId)
@ -113,6 +119,8 @@ export class NotificationEntityService implements OnModuleInit {
let validNotifications = notifications; let validNotifications = notifications;
validNotifications = await this.#filterValidNotifier(validNotifications, meId);
const noteIds = validNotifications.map(x => 'noteId' in x ? x.noteId : null).filter(isNotNull); const noteIds = validNotifications.map(x => 'noteId' in x ? x.noteId : null).filter(isNotNull);
const notes = noteIds.length > 0 ? await this.notesRepository.find({ const notes = noteIds.length > 0 ? await this.notesRepository.find({
where: { id: In(noteIds) }, where: { id: In(noteIds) },
@ -159,8 +167,11 @@ export class NotificationEntityService implements OnModuleInit {
packedNotes: Map<MiNote['id'], Packed<'Note'>>; packedNotes: Map<MiNote['id'], Packed<'Note'>>;
packedUsers: Map<MiUser['id'], Packed<'UserLite'>>; packedUsers: Map<MiUser['id'], Packed<'UserLite'>>;
}, },
): Promise<Packed<'Notification'>> { ): Promise<Packed<'Notification'>|null> {
const notification = src; const notification = src;
if (!(await this.#isValidNotifier(notification, meId))) return null;
const noteIfNeed = NOTE_REQUIRED_GROUPED_NOTIFICATION_TYPES.has(notification.type) && 'noteId' in notification ? ( const noteIfNeed = NOTE_REQUIRED_GROUPED_NOTIFICATION_TYPES.has(notification.type) && 'noteId' in notification ? (
hint?.packedNotes != null hint?.packedNotes != null
? hint.packedNotes.get(notification.noteId) ? hint.packedNotes.get(notification.noteId)
@ -244,6 +255,8 @@ export class NotificationEntityService implements OnModuleInit {
let validNotifications = notifications; let validNotifications = notifications;
validNotifications = await this.#filterValidNotifier(validNotifications, meId);
const noteIds = validNotifications.map(x => 'noteId' in x ? x.noteId : null).filter(isNotNull); const noteIds = validNotifications.map(x => 'noteId' in x ? x.noteId : null).filter(isNotNull);
const notes = noteIds.length > 0 ? await this.notesRepository.find({ const notes = noteIds.length > 0 ? await this.notesRepository.find({
where: { id: In(noteIds) }, where: { id: In(noteIds) },
@ -282,4 +295,62 @@ export class NotificationEntityService implements OnModuleInit {
packedUsers, packedUsers,
}))); })));
} }
/**
* notifierが存在するか
*/
async #isValidNotifier <T extends MiNotification | MiGroupedNotification> (
notification: T,
meId: MiUser['id'],
) : Promise<boolean> {
const [
userIdsWhoMeMuting,
userMutedInstances,
] = await Promise.all([
this.cacheService.userMutingsCache.fetch(meId),
this.cacheService.userProfileCache.fetch(meId).then(p => new Set(p.mutedInstances)),
]);
if (!('notifierId' in notification)) return true;
if (userIdsWhoMeMuting.has(notification.notifierId)) return false;
const notifier = await this.usersRepository.findOneBy({ id: notification.notifierId });
if (notifier === null) return false;
if (notifier.host && userMutedInstances.has(notifier.host)) return false;
if (notifier.isSuspended) return false;
return true;
}
/**
* notifierが存在するか
*/
async #filterValidNotifier <T extends MiNotification | MiGroupedNotification> (
notifications: T[],
meId: MiUser['id'],
) : Promise<T[]> {
const [
userIdsWhoMeMuting,
userMutedInstances,
] = await Promise.all([
this.cacheService.userMutingsCache.fetch(meId),
this.cacheService.userProfileCache.fetch(meId).then(p => new Set(p.mutedInstances)),
]);
const filteredNotifications = ((await Promise.all(notifications.map(async (notification) => {
if (!('notifierId' in notification)) return notification;
if (userIdsWhoMeMuting.has(notification.notifierId)) return null;
const notifier = await this.usersRepository.findOneBy({ id: notification.notifierId });
if (notifier === null) return null;
if (notifier.host && userMutedInstances.has(notifier.host)) return null;
if (notifier.isSuspended) return null;
return notification;
}))) as [T|null] ).filter((notification): notification is T => notification !== null);
return filteredNotifications;
}
} }