Hide suspended user profile (#5452)
This commit is contained in:
		| @@ -165,7 +165,8 @@ router.get('/users/:user', async (ctx, next) => { | |||||||
|  |  | ||||||
| 	const user = await Users.findOne({ | 	const user = await Users.findOne({ | ||||||
| 		id: userId, | 		id: userId, | ||||||
| 		host: null | 		host: null, | ||||||
|  | 		isSuspended: false | ||||||
| 	}); | 	}); | ||||||
|  |  | ||||||
| 	await userInfo(ctx, user); | 	await userInfo(ctx, user); | ||||||
| @@ -176,7 +177,8 @@ router.get('/@:user', async (ctx, next) => { | |||||||
|  |  | ||||||
| 	const user = await Users.findOne({ | 	const user = await Users.findOne({ | ||||||
| 		usernameLower: ctx.params.user.toLowerCase(), | 		usernameLower: ctx.params.user.toLowerCase(), | ||||||
| 		host: null | 		host: null, | ||||||
|  | 		isSuspended: false | ||||||
| 	}); | 	}); | ||||||
|  |  | ||||||
| 	await userInfo(ctx, user); | 	await userInfo(ctx, user); | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ import $ from 'cafy'; | |||||||
| import { ID } from '../../../../misc/cafy-id'; | import { ID } from '../../../../misc/cafy-id'; | ||||||
| import define from '../../define'; | import define from '../../define'; | ||||||
| import deleteFollowing from '../../../../services/following/delete'; | import deleteFollowing from '../../../../services/following/delete'; | ||||||
| import { Users, Followings } from '../../../../models'; | import { Users, Followings, Notifications } from '../../../../models'; | ||||||
| import { User } from '../../../../models/entities/user'; | import { User } from '../../../../models/entities/user'; | ||||||
| import { insertModerationLog } from '../../../../services/insert-moderation-log'; | import { insertModerationLog } from '../../../../services/insert-moderation-log'; | ||||||
| import { doPostSuspend } from '../../../../services/suspend-user'; | import { doPostSuspend } from '../../../../services/suspend-user'; | ||||||
| @@ -55,6 +55,7 @@ export default define(meta, async (ps, me) => { | |||||||
| 	(async () => { | 	(async () => { | ||||||
| 		await doPostSuspend(user).catch(e => {}); | 		await doPostSuspend(user).catch(e => {}); | ||||||
| 		await unFollowAll(user).catch(e => {}); | 		await unFollowAll(user).catch(e => {}); | ||||||
|  | 		await readAllNotify(user).catch(e => {}); | ||||||
| 	})(); | 	})(); | ||||||
| }); | }); | ||||||
|  |  | ||||||
| @@ -75,3 +76,12 @@ async function unFollowAll(follower: User) { | |||||||
| 		await deleteFollowing(follower, followee, true); | 		await deleteFollowing(follower, followee, true); | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
|  | async function readAllNotify(notifier: User) { | ||||||
|  | 	await Notifications.update({ | ||||||
|  | 		notifierId: notifier.id, | ||||||
|  | 		isRead: false, | ||||||
|  | 	}, { | ||||||
|  | 		isRead: true | ||||||
|  | 	}); | ||||||
|  | } | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ import { ID } from '../../../../misc/cafy-id'; | |||||||
| import { readNotification } from '../../common/read-notification'; | import { readNotification } from '../../common/read-notification'; | ||||||
| import define from '../../define'; | import define from '../../define'; | ||||||
| import { makePaginationQuery } from '../../common/make-pagination-query'; | import { makePaginationQuery } from '../../common/make-pagination-query'; | ||||||
| import { Notifications, Followings, Mutings } from '../../../../models'; | import { Notifications, Followings, Mutings, Users } from '../../../../models'; | ||||||
|  |  | ||||||
| export const meta = { | export const meta = { | ||||||
| 	desc: { | 	desc: { | ||||||
| @@ -72,6 +72,10 @@ export default define(meta, async (ps, user) => { | |||||||
| 		.select('muting.muteeId') | 		.select('muting.muteeId') | ||||||
| 		.where('muting.muterId = :muterId', { muterId: user.id }); | 		.where('muting.muterId = :muterId', { muterId: user.id }); | ||||||
|  |  | ||||||
|  | 	const suspendedQuery = Users.createQueryBuilder('users') | ||||||
|  | 		.select('id') | ||||||
|  | 		.where('users.isSuspended = TRUE'); | ||||||
|  |  | ||||||
| 	const query = makePaginationQuery(Notifications.createQueryBuilder('notification'), ps.sinceId, ps.untilId) | 	const query = makePaginationQuery(Notifications.createQueryBuilder('notification'), ps.sinceId, ps.untilId) | ||||||
| 		.andWhere(`notification.notifieeId = :meId`, { meId: user.id }) | 		.andWhere(`notification.notifieeId = :meId`, { meId: user.id }) | ||||||
| 		.leftJoinAndSelect('notification.notifier', 'notifier'); | 		.leftJoinAndSelect('notification.notifier', 'notifier'); | ||||||
| @@ -79,6 +83,8 @@ export default define(meta, async (ps, user) => { | |||||||
| 	query.andWhere(`notification.notifierId NOT IN (${ mutingQuery.getQuery() })`); | 	query.andWhere(`notification.notifierId NOT IN (${ mutingQuery.getQuery() })`); | ||||||
| 	query.setParameters(mutingQuery.getParameters()); | 	query.setParameters(mutingQuery.getParameters()); | ||||||
|  |  | ||||||
|  | 	query.andWhere(`notification.notifierId NOT IN (${ suspendedQuery.getQuery() })`); | ||||||
|  |  | ||||||
| 	if (ps.following) { | 	if (ps.following) { | ||||||
| 		query.andWhere(`((notification.notifierId IN (${ followingQuery.getQuery() })) OR (notification.notifierId = :meId))`, { meId: user.id }); | 		query.andWhere(`((notification.notifierId IN (${ followingQuery.getQuery() })) OR (notification.notifierId = :meId))`, { meId: user.id }); | ||||||
| 		query.setParameters(followingQuery.getParameters()); | 		query.setParameters(followingQuery.getParameters()); | ||||||
|   | |||||||
| @@ -66,13 +66,18 @@ export const meta = { | |||||||
| export default define(meta, async (ps, me) => { | export default define(meta, async (ps, me) => { | ||||||
| 	let user; | 	let user; | ||||||
|  |  | ||||||
|  | 	const isAdminOrModerator = me && (me.isAdmin || me.isModerator); | ||||||
|  |  | ||||||
| 	if (ps.userIds) { | 	if (ps.userIds) { | ||||||
| 		if (ps.userIds.length === 0) { | 		if (ps.userIds.length === 0) { | ||||||
| 			return []; | 			return []; | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		const users = await Users.find({ | 		const users = await Users.find(isAdminOrModerator ? { | ||||||
| 			id: In(ps.userIds) | 			id: In(ps.userIds) | ||||||
|  | 		} : { | ||||||
|  | 			id: In(ps.userIds), | ||||||
|  | 			isSuspended: false | ||||||
| 		}); | 		}); | ||||||
|  |  | ||||||
| 		return await Promise.all(users.map(u => Users.pack(u, me, { | 		return await Promise.all(users.map(u => Users.pack(u, me, { | ||||||
| @@ -93,7 +98,7 @@ export default define(meta, async (ps, me) => { | |||||||
| 			user = await Users.findOne(q); | 			user = await Users.findOne(q); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		if (user == null) { | 		if (user == null || (!isAdminOrModerator && user.isSuspended)) { | ||||||
| 			throw new ApiError(meta.errors.noSuchUser); | 			throw new ApiError(meta.errors.noSuchUser); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -101,7 +101,8 @@ const getFeed = async (acct: string) => { | |||||||
| 	const { username, host } = parseAcct(acct); | 	const { username, host } = parseAcct(acct); | ||||||
| 	const user = await Users.findOne({ | 	const user = await Users.findOne({ | ||||||
| 		usernameLower: username.toLowerCase(), | 		usernameLower: username.toLowerCase(), | ||||||
| 		host | 		host, | ||||||
|  | 		isSuspended: false | ||||||
| 	}); | 	}); | ||||||
|  |  | ||||||
| 	return user && await packFeed(user); | 	return user && await packFeed(user); | ||||||
| @@ -149,7 +150,8 @@ router.get(['/@:user', '/@:user/:sub'], async (ctx, next) => { | |||||||
| 	const { username, host } = parseAcct(ctx.params.user); | 	const { username, host } = parseAcct(ctx.params.user); | ||||||
| 	const user = await Users.findOne({ | 	const user = await Users.findOne({ | ||||||
| 		usernameLower: username.toLowerCase(), | 		usernameLower: username.toLowerCase(), | ||||||
| 		host | 		host, | ||||||
|  | 		isSuspended: false | ||||||
| 	}); | 	}); | ||||||
|  |  | ||||||
| 	if (user != null) { | 	if (user != null) { | ||||||
| @@ -170,6 +172,7 @@ router.get(['/@:user', '/@:user/:sub'], async (ctx, next) => { | |||||||
| 		ctx.set('Cache-Control', 'public, max-age=30'); | 		ctx.set('Cache-Control', 'public, max-age=30'); | ||||||
| 	} else { | 	} else { | ||||||
| 		// リモートユーザーなので | 		// リモートユーザーなので | ||||||
|  | 		// モデレータがAPI経由で参照可能にするために404にはしない | ||||||
| 		await next(); | 		await next(); | ||||||
| 	} | 	} | ||||||
| }); | }); | ||||||
| @@ -177,7 +180,8 @@ router.get(['/@:user', '/@:user/:sub'], async (ctx, next) => { | |||||||
| router.get('/users/:user', async ctx => { | router.get('/users/:user', async ctx => { | ||||||
| 	const user = await Users.findOne({ | 	const user = await Users.findOne({ | ||||||
| 		id: ctx.params.user, | 		id: ctx.params.user, | ||||||
| 		host: null | 		host: null, | ||||||
|  | 		isSuspended: false | ||||||
| 	}); | 	}); | ||||||
|  |  | ||||||
| 	if (user == null) { | 	if (user == null) { | ||||||
|   | |||||||
| @@ -49,7 +49,8 @@ router.get('/.well-known/nodeinfo', async ctx => { | |||||||
| router.get(webFingerPath, async ctx => { | router.get(webFingerPath, async ctx => { | ||||||
| 	const fromId = (id: User['id']): Record<string, any> => ({ | 	const fromId = (id: User['id']): Record<string, any> => ({ | ||||||
| 		id, | 		id, | ||||||
| 		host: null | 		host: null, | ||||||
|  | 		isSuspended: false | ||||||
| 	}); | 	}); | ||||||
|  |  | ||||||
| 	const generateQuery = (resource: string) => | 	const generateQuery = (resource: string) => | ||||||
| @@ -63,7 +64,8 @@ router.get(webFingerPath, async ctx => { | |||||||
| 	const fromAcct = (acct: Acct): Record<string, any> | number => | 	const fromAcct = (acct: Acct): Record<string, any> | number => | ||||||
| 		!acct.host || acct.host === config.host.toLowerCase() ? { | 		!acct.host || acct.host === config.host.toLowerCase() ? { | ||||||
| 			usernameLower: acct.username, | 			usernameLower: acct.username, | ||||||
| 			host: null | 			host: null, | ||||||
|  | 			isSuspended: false | ||||||
| 		} : 422; | 		} : 422; | ||||||
|  |  | ||||||
| 	if (typeof ctx.query.resource !== 'string') { | 	if (typeof ctx.query.resource !== 'string') { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 MeiMei
					MeiMei