fix: always respect instance mutes (#8854)
* fix: muted user query also checks instances This way it can be ensured that the instance mute is used everywhere it is required without checking the whole codebase again. Muted users and muted instances should be used together anyways. * fix lint
This commit is contained in:
parent
e3461f1b58
commit
5728350267
8 changed files with 71 additions and 73 deletions
|
@ -1,40 +0,0 @@
|
|||
import { User } from '@/models/entities/user.js';
|
||||
import { id } from '@/models/id.js';
|
||||
import { UserProfiles } from '@/models/index.js';
|
||||
import { SelectQueryBuilder, Brackets } from 'typeorm';
|
||||
|
||||
function createMutesQuery(id: string) {
|
||||
return UserProfiles.createQueryBuilder('user_profile')
|
||||
.select('user_profile.mutedInstances')
|
||||
.where('user_profile.userId = :muterId', { muterId: id });
|
||||
}
|
||||
|
||||
export function generateMutedInstanceQuery(q: SelectQueryBuilder<any>, me: { id: User['id'] }) {
|
||||
const mutingQuery = createMutesQuery(me.id);
|
||||
|
||||
q
|
||||
.andWhere(new Brackets(qb => { qb
|
||||
.andWhere('note.userHost IS NULL')
|
||||
.orWhere(`NOT((${ mutingQuery.getQuery() })::jsonb ? note.userHost)`);
|
||||
}))
|
||||
.andWhere(new Brackets(qb => { qb
|
||||
.where(`note.replyUserHost IS NULL`)
|
||||
.orWhere(`NOT ((${ mutingQuery.getQuery() })::jsonb ? note.replyUserHost)`);
|
||||
}))
|
||||
.andWhere(new Brackets(qb => { qb
|
||||
.where(`note.renoteUserHost IS NULL`)
|
||||
.orWhere(`NOT ((${ mutingQuery.getQuery() })::jsonb ? note.renoteUserHost)`);
|
||||
}));
|
||||
q.setParameters(mutingQuery.getParameters());
|
||||
}
|
||||
|
||||
export function generateMutedInstanceNotificationQuery(q: SelectQueryBuilder<any>, me: { id: User['id'] }) {
|
||||
const mutingQuery = createMutesQuery(me.id);
|
||||
|
||||
q.andWhere(new Brackets(qb => { qb
|
||||
.andWhere('notifier.host IS NULL')
|
||||
.orWhere(`NOT (( ${mutingQuery.getQuery()} )::jsonb ? notifier.host)`);
|
||||
}));
|
||||
|
||||
q.setParameters(mutingQuery.getParameters());
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
import { User } from '@/models/entities/user.js';
|
||||
import { Mutings } from '@/models/index.js';
|
||||
import { SelectQueryBuilder, Brackets } from 'typeorm';
|
||||
import { User } from '@/models/entities/user.js';
|
||||
import { Mutings, UserProfiles } from '@/models/index.js';
|
||||
|
||||
export function generateMutedUserQuery(q: SelectQueryBuilder<any>, me: { id: User['id'] }, exclude?: User) {
|
||||
const mutingQuery = Mutings.createQueryBuilder('muting')
|
||||
|
@ -11,21 +11,39 @@ export function generateMutedUserQuery(q: SelectQueryBuilder<any>, me: { id: Use
|
|||
mutingQuery.andWhere('muting.muteeId != :excludeId', { excludeId: exclude.id });
|
||||
}
|
||||
|
||||
const mutingInstanceQuery = UserProfiles.createQueryBuilder('user_profile')
|
||||
.select('user_profile.mutedInstances')
|
||||
.where('user_profile.userId = :muterId', { muterId: me.id });
|
||||
|
||||
// 投稿の作者をミュートしていない かつ
|
||||
// 投稿の返信先の作者をミュートしていない かつ
|
||||
// 投稿の引用元の作者をミュートしていない
|
||||
q
|
||||
.andWhere(`note.userId NOT IN (${ mutingQuery.getQuery() })`)
|
||||
.andWhere(new Brackets(qb => { qb
|
||||
.where(`note.replyUserId IS NULL`)
|
||||
.where('note.replyUserId IS NULL')
|
||||
.orWhere(`note.replyUserId NOT IN (${ mutingQuery.getQuery() })`);
|
||||
}))
|
||||
.andWhere(new Brackets(qb => { qb
|
||||
.where(`note.renoteUserId IS NULL`)
|
||||
.where('note.renoteUserId IS NULL')
|
||||
.orWhere(`note.renoteUserId NOT IN (${ mutingQuery.getQuery() })`);
|
||||
}))
|
||||
// mute instances
|
||||
.andWhere(new Brackets(qb => { qb
|
||||
.andWhere('note.userHost IS NULL')
|
||||
.orWhere(`NOT ((${ mutingInstanceQuery.getQuery() })::jsonb ? note.userHost)`);
|
||||
}))
|
||||
.andWhere(new Brackets(qb => { qb
|
||||
.where('note.replyUserHost IS NULL')
|
||||
.orWhere(`NOT ((${ mutingInstanceQuery.getQuery() })::jsonb ? note.replyUserHost)`);
|
||||
}))
|
||||
.andWhere(new Brackets(qb => { qb
|
||||
.where('note.renoteUserHost IS NULL')
|
||||
.orWhere(`NOT ((${ mutingInstanceQuery.getQuery() })::jsonb ? note.renoteUserHost)`);
|
||||
}));
|
||||
|
||||
q.setParameters(mutingQuery.getParameters());
|
||||
q.setParameters(mutingInstanceQuery.getParameters());
|
||||
}
|
||||
|
||||
export function generateMutedUserQueryForUsers(q: SelectQueryBuilder<any>, me: { id: User['id'] }) {
|
||||
|
@ -33,8 +51,26 @@ export function generateMutedUserQueryForUsers(q: SelectQueryBuilder<any>, me: {
|
|||
.select('muting.muteeId')
|
||||
.where('muting.muterId = :muterId', { muterId: me.id });
|
||||
|
||||
const mutingInstanceQuery = UserProfiles.createQueryBuilder('user_profile')
|
||||
.select('user_profile.mutedInstances')
|
||||
.where('user_profile.userId = :muterId', { muterId: me.id });
|
||||
|
||||
q
|
||||
.andWhere(`user.id NOT IN (${ mutingQuery.getQuery() })`);
|
||||
.andWhere(`user.id NOT IN (${ mutingQuery.getQuery() })`)
|
||||
// mute instances
|
||||
.andWhere(new Brackets(qb => { qb
|
||||
.andWhere('note.userHost IS NULL')
|
||||
.orWhere(`NOT ((${ mutingInstanceQuery.getQuery() })::jsonb ? note.userHost)`);
|
||||
}))
|
||||
.andWhere(new Brackets(qb => { qb
|
||||
.where('note.replyUserHost IS NULL')
|
||||
.orWhere(`NOT ((${ mutingInstanceQuery.getQuery() })::jsonb ? note.replyUserHost)`);
|
||||
}))
|
||||
.andWhere(new Brackets(qb => { qb
|
||||
.where('note.renoteUserHost IS NULL')
|
||||
.orWhere(`NOT ((${ mutingInstanceQuery.getQuery() })::jsonb ? note.renoteUserHost)`);
|
||||
}));
|
||||
|
||||
q.setParameters(mutingQuery.getParameters());
|
||||
q.setParameters(mutingInstanceQuery.getParameters());
|
||||
}
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
import { Brackets } from 'typeorm';
|
||||
import { Notifications, Followings, Mutings, Users } from '@/models/index.js';
|
||||
import { Notifications, Followings, Mutings, Users, UserProfiles } from '@/models/index.js';
|
||||
import { notificationTypes } from '@/types.js';
|
||||
import read from '@/services/note/read.js';
|
||||
import { readNotification } from '../../common/read-notification.js';
|
||||
import define from '../../define.js';
|
||||
import { makePaginationQuery } from '../../common/make-pagination-query.js';
|
||||
import { generateMutedInstanceNotificationQuery } from '../../common/generate-muted-instance-query.js';
|
||||
|
||||
export const meta = {
|
||||
tags: ['account', 'notifications'],
|
||||
|
@ -67,6 +66,10 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
.select('muting.muteeId')
|
||||
.where('muting.muterId = :muterId', { muterId: user.id });
|
||||
|
||||
const mutingInstanceQuery = UserProfiles.createQueryBuilder('user_profile')
|
||||
.select('user_profile.mutedInstances')
|
||||
.where('user_profile.userId = :muterId', { muterId: user.id });
|
||||
|
||||
const suspendedQuery = Users.createQueryBuilder('users')
|
||||
.select('users.id')
|
||||
.where('users.isSuspended = TRUE');
|
||||
|
@ -89,14 +92,21 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
.leftJoinAndSelect('renoteUser.avatar', 'renoteUserAvatar')
|
||||
.leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner');
|
||||
|
||||
// muted users
|
||||
query.andWhere(new Brackets(qb => { qb
|
||||
.where(`notification.notifierId NOT IN (${ mutingQuery.getQuery() })`)
|
||||
.orWhere('notification.notifierId IS NULL');
|
||||
}));
|
||||
query.setParameters(mutingQuery.getParameters());
|
||||
|
||||
generateMutedInstanceNotificationQuery(query, user);
|
||||
// muted instances
|
||||
query.andWhere(new Brackets(qb => { qb
|
||||
.andWhere('notifier.host IS NULL')
|
||||
.orWhere(`NOT (( ${mutingInstanceQuery.getQuery()} )::jsonb ? notifier.host)`);
|
||||
}));
|
||||
query.setParameters(mutingInstanceQuery.getParameters());
|
||||
|
||||
// suspended users
|
||||
query.andWhere(new Brackets(qb => { qb
|
||||
.where(`notification.notifierId NOT IN (${ suspendedQuery.getQuery() })`)
|
||||
.orWhere('notification.notifierId IS NULL');
|
||||
|
|
|
@ -5,7 +5,6 @@ import { makePaginationQuery } from '../../common/make-pagination-query.js';
|
|||
import { generateVisibilityQuery } from '../../common/generate-visibility-query.js';
|
||||
import { generateMutedUserQuery } from '../../common/generate-muted-user-query.js';
|
||||
import { generateBlockedUserQuery } from '../../common/generate-block-query.js';
|
||||
import { generateMutedInstanceQuery } from '../../common/generate-muted-instance-query.js';
|
||||
|
||||
export const meta = {
|
||||
tags: ['notes'],
|
||||
|
@ -61,9 +60,10 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
.leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner');
|
||||
|
||||
generateVisibilityQuery(query, user);
|
||||
if (user) generateMutedUserQuery(query, user);
|
||||
if (user) generateBlockedUserQuery(query, user);
|
||||
if (user) generateMutedInstanceQuery(query, user);
|
||||
if (user) {
|
||||
generateMutedUserQuery(query, user);
|
||||
generateBlockedUserQuery(query, user);
|
||||
}
|
||||
|
||||
const notes = await query.take(ps.limit).getMany();
|
||||
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
import { fetchMeta } from '@/misc/fetch-meta.js';
|
||||
import { Notes, Users } from '@/models/index.js';
|
||||
import { Notes } from '@/models/index.js';
|
||||
import { activeUsersChart } from '@/services/chart/index.js';
|
||||
import define from '../../define.js';
|
||||
import { ApiError } from '../../error.js';
|
||||
import { makePaginationQuery } from '../../common/make-pagination-query.js';
|
||||
import { generateMutedUserQuery } from '../../common/generate-muted-user-query.js';
|
||||
import { generateMutedInstanceQuery } from '../../common/generate-muted-instance-query.js';
|
||||
import { generateRepliesQuery } from '../../common/generate-replies-query.js';
|
||||
import { generateMutedNoteQuery } from '../../common/generate-muted-note-query.js';
|
||||
import { generateBlockedUserQuery } from '../../common/generate-block-query.js';
|
||||
|
@ -76,10 +75,11 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
.leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner');
|
||||
|
||||
generateRepliesQuery(query, user);
|
||||
if (user) generateMutedUserQuery(query, user);
|
||||
if (user) generateMutedNoteQuery(query, user);
|
||||
if (user) generateBlockedUserQuery(query, user);
|
||||
if (user) generateMutedInstanceQuery(query, user);
|
||||
if (user) {
|
||||
generateMutedUserQuery(query, user);
|
||||
generateMutedNoteQuery(query, user);
|
||||
generateBlockedUserQuery(query, user);
|
||||
}
|
||||
|
||||
if (ps.withFiles) {
|
||||
query.andWhere('note.fileIds != \'{}\'');
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
import { Brackets } from 'typeorm';
|
||||
import { fetchMeta } from '@/misc/fetch-meta.js';
|
||||
import { Followings, Notes, Users } from '@/models/index.js';
|
||||
import { Followings, Notes } from '@/models/index.js';
|
||||
import { activeUsersChart } from '@/services/chart/index.js';
|
||||
import define from '../../define.js';
|
||||
import { ApiError } from '../../error.js';
|
||||
import { makePaginationQuery } from '../../common/make-pagination-query.js';
|
||||
import { generateVisibilityQuery } from '../../common/generate-visibility-query.js';
|
||||
import { generateMutedUserQuery } from '../../common/generate-muted-user-query.js';
|
||||
import { generateMutedInstanceQuery } from '../../common/generate-muted-instance-query.js';
|
||||
import { generateRepliesQuery } from '../../common/generate-replies-query.js';
|
||||
import { generateMutedNoteQuery } from '../../common/generate-muted-note-query.js';
|
||||
import { generateChannelQuery } from '../../common/generate-channel-query.js';
|
||||
|
@ -92,7 +91,6 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
generateRepliesQuery(query, user);
|
||||
generateVisibilityQuery(query, user);
|
||||
generateMutedUserQuery(query, user);
|
||||
generateMutedInstanceQuery(query, user);
|
||||
generateMutedNoteQuery(query, user);
|
||||
generateBlockedUserQuery(query, user);
|
||||
|
||||
|
@ -134,9 +132,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
const timeline = await query.take(ps.limit).getMany();
|
||||
|
||||
process.nextTick(() => {
|
||||
if (user) {
|
||||
activeUsersChart.read(user);
|
||||
}
|
||||
activeUsersChart.read(user);
|
||||
});
|
||||
|
||||
return await Notes.packMany(timeline, user);
|
||||
|
|
|
@ -5,7 +5,6 @@ import define from '../../define.js';
|
|||
import { makePaginationQuery } from '../../common/make-pagination-query.js';
|
||||
import { generateVisibilityQuery } from '../../common/generate-visibility-query.js';
|
||||
import { generateMutedUserQuery } from '../../common/generate-muted-user-query.js';
|
||||
import { generateMutedInstanceQuery } from '../../common/generate-muted-instance-query.js';
|
||||
import { generateRepliesQuery } from '../../common/generate-replies-query.js';
|
||||
import { generateMutedNoteQuery } from '../../common/generate-muted-note-query.js';
|
||||
import { generateChannelQuery } from '../../common/generate-channel-query.js';
|
||||
|
@ -84,7 +83,6 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
generateRepliesQuery(query, user);
|
||||
generateVisibilityQuery(query, user);
|
||||
generateMutedUserQuery(query, user);
|
||||
generateMutedInstanceQuery(query, user);
|
||||
generateMutedNoteQuery(query, user);
|
||||
generateBlockedUserQuery(query, user);
|
||||
|
||||
|
@ -126,9 +124,7 @@ export default define(meta, paramDef, async (ps, user) => {
|
|||
const timeline = await query.take(ps.limit).getMany();
|
||||
|
||||
process.nextTick(() => {
|
||||
if (user) {
|
||||
activeUsersChart.read(user);
|
||||
}
|
||||
activeUsersChart.read(user);
|
||||
});
|
||||
|
||||
return await Notes.packMany(timeline, user);
|
||||
|
|
|
@ -7,7 +7,6 @@ import { makePaginationQuery } from '../../common/make-pagination-query.js';
|
|||
import { generateVisibilityQuery } from '../../common/generate-visibility-query.js';
|
||||
import { generateMutedUserQuery } from '../../common/generate-muted-user-query.js';
|
||||
import { generateBlockedUserQuery } from '../../common/generate-block-query.js';
|
||||
import { generateMutedInstanceQuery } from '../../common/generate-muted-instance-query.js';
|
||||
|
||||
export const meta = {
|
||||
tags: ['users', 'notes'],
|
||||
|
@ -77,9 +76,10 @@ export default define(meta, paramDef, async (ps, me) => {
|
|||
.leftJoinAndSelect('renoteUser.banner', 'renoteUserBanner');
|
||||
|
||||
generateVisibilityQuery(query, me);
|
||||
if (me) generateMutedUserQuery(query, me, user);
|
||||
if (me) generateBlockedUserQuery(query, me);
|
||||
if (me) generateMutedInstanceQuery(query, me);
|
||||
if (me) {
|
||||
generateMutedUserQuery(query, me, user);
|
||||
generateBlockedUserQuery(query, me);
|
||||
}
|
||||
|
||||
if (ps.withFiles) {
|
||||
query.andWhere('note.fileIds != \'{}\'');
|
||||
|
|
Loading…
Reference in a new issue