diff --git a/src/server/activitypub.ts b/src/server/activitypub.ts index 3094d69b15..be8a118b9d 100644 --- a/src/server/activitypub.ts +++ b/src/server/activitypub.ts @@ -165,7 +165,8 @@ router.get('/users/:user', async (ctx, next) => { const user = await Users.findOne({ id: userId, - host: null + host: null, + isSuspended: false }); await userInfo(ctx, user); @@ -176,7 +177,8 @@ router.get('/@:user', async (ctx, next) => { const user = await Users.findOne({ usernameLower: ctx.params.user.toLowerCase(), - host: null + host: null, + isSuspended: false }); await userInfo(ctx, user); diff --git a/src/server/api/endpoints/admin/suspend-user.ts b/src/server/api/endpoints/admin/suspend-user.ts index 6ba0d91505..1202315541 100644 --- a/src/server/api/endpoints/admin/suspend-user.ts +++ b/src/server/api/endpoints/admin/suspend-user.ts @@ -2,7 +2,7 @@ import $ from 'cafy'; import { ID } from '../../../../misc/cafy-id'; import define from '../../define'; import deleteFollowing from '../../../../services/following/delete'; -import { Users, Followings } from '../../../../models'; +import { Users, Followings, Notifications } from '../../../../models'; import { User } from '../../../../models/entities/user'; import { insertModerationLog } from '../../../../services/insert-moderation-log'; import { doPostSuspend } from '../../../../services/suspend-user'; @@ -55,6 +55,7 @@ export default define(meta, async (ps, me) => { (async () => { await doPostSuspend(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); } } + +async function readAllNotify(notifier: User) { + await Notifications.update({ + notifierId: notifier.id, + isRead: false, + }, { + isRead: true + }); +} diff --git a/src/server/api/endpoints/i/notifications.ts b/src/server/api/endpoints/i/notifications.ts index aa72e9a176..cd00501a2e 100644 --- a/src/server/api/endpoints/i/notifications.ts +++ b/src/server/api/endpoints/i/notifications.ts @@ -3,7 +3,7 @@ import { ID } from '../../../../misc/cafy-id'; import { readNotification } from '../../common/read-notification'; import define from '../../define'; import { makePaginationQuery } from '../../common/make-pagination-query'; -import { Notifications, Followings, Mutings } from '../../../../models'; +import { Notifications, Followings, Mutings, Users } from '../../../../models'; export const meta = { desc: { @@ -72,6 +72,10 @@ export default define(meta, async (ps, user) => { .select('muting.muteeId') .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) .andWhere(`notification.notifieeId = :meId`, { meId: user.id }) .leftJoinAndSelect('notification.notifier', 'notifier'); @@ -79,6 +83,8 @@ export default define(meta, async (ps, user) => { query.andWhere(`notification.notifierId NOT IN (${ mutingQuery.getQuery() })`); query.setParameters(mutingQuery.getParameters()); + query.andWhere(`notification.notifierId NOT IN (${ suspendedQuery.getQuery() })`); + if (ps.following) { query.andWhere(`((notification.notifierId IN (${ followingQuery.getQuery() })) OR (notification.notifierId = :meId))`, { meId: user.id }); query.setParameters(followingQuery.getParameters()); diff --git a/src/server/api/endpoints/users/show.ts b/src/server/api/endpoints/users/show.ts index d17dd51c0a..f49017a8c3 100644 --- a/src/server/api/endpoints/users/show.ts +++ b/src/server/api/endpoints/users/show.ts @@ -66,13 +66,18 @@ export const meta = { export default define(meta, async (ps, me) => { let user; + const isAdminOrModerator = me && (me.isAdmin || me.isModerator); + if (ps.userIds) { if (ps.userIds.length === 0) { return []; } - const users = await Users.find({ + const users = await Users.find(isAdminOrModerator ? { id: In(ps.userIds) + } : { + id: In(ps.userIds), + isSuspended: false }); 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); } - if (user == null) { + if (user == null || (!isAdminOrModerator && user.isSuspended)) { throw new ApiError(meta.errors.noSuchUser); } diff --git a/src/server/web/index.ts b/src/server/web/index.ts index dff6e139c8..06c7274f5a 100644 --- a/src/server/web/index.ts +++ b/src/server/web/index.ts @@ -101,7 +101,8 @@ const getFeed = async (acct: string) => { const { username, host } = parseAcct(acct); const user = await Users.findOne({ usernameLower: username.toLowerCase(), - host + host, + isSuspended: false }); 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 user = await Users.findOne({ usernameLower: username.toLowerCase(), - host + host, + isSuspended: false }); if (user != null) { @@ -170,6 +172,7 @@ router.get(['/@:user', '/@:user/:sub'], async (ctx, next) => { ctx.set('Cache-Control', 'public, max-age=30'); } else { // リモートユーザーなので + // モデレータがAPI経由で参照可能にするために404にはしない await next(); } }); @@ -177,7 +180,8 @@ router.get(['/@:user', '/@:user/:sub'], async (ctx, next) => { router.get('/users/:user', async ctx => { const user = await Users.findOne({ id: ctx.params.user, - host: null + host: null, + isSuspended: false }); if (user == null) { diff --git a/src/server/well-known.ts b/src/server/well-known.ts index 94c871eca2..63837a9b70 100644 --- a/src/server/well-known.ts +++ b/src/server/well-known.ts @@ -49,7 +49,8 @@ router.get('/.well-known/nodeinfo', async ctx => { router.get(webFingerPath, async ctx => { const fromId = (id: User['id']): Record => ({ id, - host: null + host: null, + isSuspended: false }); const generateQuery = (resource: string) => @@ -63,7 +64,8 @@ router.get(webFingerPath, async ctx => { const fromAcct = (acct: Acct): Record | number => !acct.host || acct.host === config.host.toLowerCase() ? { usernameLower: acct.username, - host: null + host: null, + isSuspended: false } : 422; if (typeof ctx.query.resource !== 'string') {