Hide suspended user profile (#5452)

This commit is contained in:
MeiMei 2020-01-02 02:47:20 +09:00 committed by syuilo
parent c49f2abe3b
commit 3be435049f
6 changed files with 40 additions and 11 deletions

View file

@ -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);

View file

@ -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
});
}

View file

@ -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());

View file

@ -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);
} }

View file

@ -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) {

View file

@ -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') {