Skip to content

Commit

Permalink
enhance: Check if notifierId is valid in NotificationEntityService
Browse files Browse the repository at this point in the history
  • Loading branch information
tai-cha committed Feb 20, 2024
1 parent 45a0677 commit b09abb8
Showing 1 changed file with 73 additions and 2 deletions.
75 changes: 73 additions & 2 deletions packages/backend/src/core/entities/NotificationEntityService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import type { Packed } from '@/misc/json-schema.js';
import { bindThis } from '@/decorators.js';
import { isNotNull } from '@/misc/is-not-null.js';
import { FilterUnionByProperty, notificationTypes } from '@/types.js';
import { CacheService } from '@/core/CacheService.js';
import { RoleEntityService } from './RoleEntityService.js';
import type { OnModuleInit } from '@nestjs/common';
import type { UserEntityService } from './UserEntityService.js';
Expand All @@ -41,6 +42,8 @@ export class NotificationEntityService implements OnModuleInit {
@Inject(DI.followRequestsRepository)
private followRequestsRepository: FollowRequestsRepository,

private cacheService: CacheService,

//private userEntityService: UserEntityService,
//private noteEntityService: NoteEntityService,
) {
Expand All @@ -64,8 +67,11 @@ export class NotificationEntityService implements OnModuleInit {
packedNotes: Map<MiNote['id'], Packed<'Note'>>;
packedUsers: Map<MiUser['id'], Packed<'UserLite'>>;
},
): Promise<Packed<'Notification'>> {
): Promise<Packed<'Notification'>|null> {
const notification = src;

if (!(await this.#isValidNotifier(notification, meId))) return null;

const noteIfNeed = NOTE_REQUIRED_NOTIFICATION_TYPES.has(notification.type) && 'noteId' in notification ? (
hint?.packedNotes != null
? hint.packedNotes.get(notification.noteId)
Expand Down Expand Up @@ -113,6 +119,8 @@ export class NotificationEntityService implements OnModuleInit {

let validNotifications = notifications;

validNotifications = await this.#filterValidNotifier(validNotifications, meId);

const noteIds = validNotifications.map(x => 'noteId' in x ? x.noteId : null).filter(isNotNull);
const notes = noteIds.length > 0 ? await this.notesRepository.find({
where: { id: In(noteIds) },
Expand Down Expand Up @@ -159,8 +167,11 @@ export class NotificationEntityService implements OnModuleInit {
packedNotes: Map<MiNote['id'], Packed<'Note'>>;
packedUsers: Map<MiUser['id'], Packed<'UserLite'>>;
},
): Promise<Packed<'Notification'>> {
): Promise<Packed<'Notification'>|null> {
const notification = src;

if (!(await this.#isValidNotifier(notification, meId))) return null;

const noteIfNeed = NOTE_REQUIRED_GROUPED_NOTIFICATION_TYPES.has(notification.type) && 'noteId' in notification ? (
hint?.packedNotes != null
? hint.packedNotes.get(notification.noteId)
Expand Down Expand Up @@ -244,6 +255,8 @@ export class NotificationEntityService implements OnModuleInit {

let validNotifications = notifications;

validNotifications = await this.#filterValidNotifier(validNotifications, meId);

const noteIds = validNotifications.map(x => 'noteId' in x ? x.noteId : null).filter(isNotNull);
const notes = noteIds.length > 0 ? await this.notesRepository.find({
where: { id: In(noteIds) },
Expand Down Expand Up @@ -282,4 +295,62 @@ export class NotificationEntityService implements OnModuleInit {
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;
}
}

0 comments on commit b09abb8

Please sign in to comment.