isSuspendedの周囲にisRemoteSuspendedの考慮を追加

This commit is contained in:
tamaina 2025-07-07 12:35:41 +09:00
parent 4417f0525c
commit 585ff3d262
13 changed files with 30 additions and 7 deletions

View File

@ -151,6 +151,7 @@ export class FanoutTimelineEndpointService {
}; };
if (!ps.ignoreAuthorFromUserSuspension) { if (!ps.ignoreAuthorFromUserSuspension) {
if (note.user!.isSuspended) return false; if (note.user!.isSuspended) return false;
if (note.user!.isRemoteSuspended) return false;
} }
if (note.userId !== note.renoteUserId && noteJoined.renoteUser?.isSuspended) return false; if (note.userId !== note.renoteUserId && noteJoined.renoteUser?.isSuspended) return false;
if (note.userId !== note.replyUserId && noteJoined.replyUser?.isSuspended) return false; if (note.userId !== note.replyUserId && noteJoined.replyUser?.isSuspended) return false;

View File

@ -254,7 +254,7 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit {
} }
// サスペンド済みユーザである // サスペンド済みユーザである
case 'isSuspended': { case 'isSuspended': {
return user.isSuspended; return this.userEntityService.isSuspendedEither(user);
} }
// 鍵アカウントユーザである // 鍵アカウントユーザである
case 'isLocked': { case 'isLocked': {

View File

@ -207,7 +207,7 @@ export class UserSearchService {
} }
} }
userQuery.andWhere('user.isSuspended = FALSE'); userQuery.andWhere('user.isSuspended = FALSE').andWhere('user.isRemoteSuspended = FALSE');
return userQuery; return userQuery;
} }
@ -243,7 +243,8 @@ export class UserSearchService {
.where('user.updatedAt IS NULL') .where('user.updatedAt IS NULL')
.orWhere('user.updatedAt > :activeThreshold', { activeThreshold: activeThreshold }); .orWhere('user.updatedAt > :activeThreshold', { activeThreshold: activeThreshold });
})) }))
.andWhere('user.isSuspended = FALSE'); .andWhere('user.isSuspended = FALSE')
.andWhere('user.isRemoteSuspended = FALSE');
if (mutingQuery) { if (mutingQuery) {
nameQuery.andWhere(`user.id NOT IN (${mutingQuery.getQuery()})`); nameQuery.andWhere(`user.id NOT IN (${mutingQuery.getQuery()})`);
@ -286,6 +287,7 @@ export class UserSearchService {
.orWhere('user.updatedAt > :activeThreshold', { activeThreshold: activeThreshold }); .orWhere('user.updatedAt > :activeThreshold', { activeThreshold: activeThreshold });
})) }))
.andWhere('user.isSuspended = FALSE') .andWhere('user.isSuspended = FALSE')
.andWhere('user.isRemoteSuspended = FALSE')
.setParameters(profQuery.getParameters()); .setParameters(profQuery.getParameters());
users = users.concat(await userQuery users = users.concat(await userQuery

View File

@ -290,7 +290,7 @@ export class NotificationEntityService implements OnModuleInit {
if (notifier == null) return false; if (notifier == null) return false;
if (notifier.host && userMutedInstances.has(notifier.host)) return false; if (notifier.host && userMutedInstances.has(notifier.host)) return false;
if (notifier.isSuspended) return false; if (this.userEntityService.isSuspendedEither(notifier)) return false;
return true; return true;
} }

View File

@ -69,6 +69,10 @@ function isRemoteUser(user: MiUser | { host: MiUser['host'] }): boolean {
return !isLocalUser(user); return !isLocalUser(user);
} }
function isSuspendedEither(user: MiUser): boolean {
return user.isSuspended || user.isRemoteSuspended;
}
export type UserRelation = { export type UserRelation = {
id: MiUser['id'] id: MiUser['id']
following: MiFollowing | null, following: MiFollowing | null,
@ -163,6 +167,7 @@ export class UserEntityService implements OnModuleInit {
public isLocalUser = isLocalUser; public isLocalUser = isLocalUser;
public isRemoteUser = isRemoteUser; public isRemoteUser = isRemoteUser;
public isSuspendedEither = isSuspendedEither;
@bindThis @bindThis
public async getRelation(me: MiUser['id'], target: MiUser['id']): Promise<UserRelation> { public async getRelation(me: MiUser['id'], target: MiUser['id']): Promise<UserRelation> {
@ -537,7 +542,7 @@ export class UserEntityService implements OnModuleInit {
bannerBlurhash: user.bannerId == null ? null : user.bannerBlurhash, bannerBlurhash: user.bannerId == null ? null : user.bannerBlurhash,
isLocked: user.isLocked, isLocked: user.isLocked,
isSilenced: this.roleService.getUserPolicies(user.id).then(r => !r.canPublicNote), isSilenced: this.roleService.getUserPolicies(user.id).then(r => !r.canPublicNote),
isSuspended: user.isSuspended, isSuspended: this.isSuspendedEither(user),
description: profile!.description, description: profile!.description,
location: profile!.location, location: profile!.location,
birthday: profile!.birthday, birthday: profile!.birthday,

View File

@ -215,6 +215,7 @@ export class ServerService implements OnApplicationShutdown {
usernameLower: username.toLowerCase(), usernameLower: username.toLowerCase(),
host: (host == null) || (host === this.config.host) ? IsNull() : host, host: (host == null) || (host === this.config.host) ? IsNull() : host,
isSuspended: false, isSuspended: false,
isRemoteSuspended: false,
}, },
}); });

View File

@ -124,6 +124,10 @@ export const meta = {
type: 'boolean', type: 'boolean',
optional: false, nullable: false, optional: false, nullable: false,
}, },
isRemoteSuspended: {
type: 'boolean',
optional: false, nullable: false,
},
isHibernated: { isHibernated: {
type: 'boolean', type: 'boolean',
optional: false, nullable: false, optional: false, nullable: false,
@ -246,6 +250,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
isModerator: isModerator, isModerator: isModerator,
isSilenced: isSilenced, isSilenced: isSilenced,
isSuspended: user.isSuspended, isSuspended: user.isSuspended,
isRemoteSuspended: user.isRemoteSuspended,
isHibernated: user.isHibernated, isHibernated: user.isHibernated,
lastActiveDate: user.lastActiveDate ? user.lastActiveDate.toISOString() : null, lastActiveDate: user.lastActiveDate ? user.lastActiveDate.toISOString() : null,
moderationNote: profile.moderationNote ?? '', moderationNote: profile.moderationNote ?? '',

View File

@ -61,7 +61,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
const query = this.usersRepository.createQueryBuilder('user'); const query = this.usersRepository.createQueryBuilder('user');
switch (ps.state) { switch (ps.state) {
case 'available': query.where('user.isSuspended = FALSE'); break; case 'available': query.where('user.isSuspended = FALSE').andWhere('user.isRemoteSuspended = FALSE'); break;
case 'alive': query.where('user.updatedAt > :date', { date: new Date(Date.now() - 1000 * 60 * 60 * 24 * 5) }); break; case 'alive': query.where('user.updatedAt > :date', { date: new Date(Date.now() - 1000 * 60 * 60 * 24 * 5) }); break;
case 'suspended': query.where('user.isSuspended = TRUE'); break; case 'suspended': query.where('user.isSuspended = TRUE'); break;
case 'admin': { case 'admin': {

View File

@ -51,7 +51,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
if (!safeForSql(normalizeForSearch(ps.tag))) throw new Error('Injection'); if (!safeForSql(normalizeForSearch(ps.tag))) throw new Error('Injection');
const query = this.usersRepository.createQueryBuilder('user') const query = this.usersRepository.createQueryBuilder('user')
.where(':tag <@ user.tags', { tag: [normalizeForSearch(ps.tag)] }) .where(':tag <@ user.tags', { tag: [normalizeForSearch(ps.tag)] })
.andWhere('user.isSuspended = FALSE'); .andWhere('user.isSuspended = FALSE')
.andWhere('user.isRemoteSuspended = FALSE');
const recent = new Date(Date.now() - (1000 * 60 * 60 * 24 * 5)); const recent = new Date(Date.now() - (1000 * 60 * 60 * 24 * 5));

View File

@ -138,6 +138,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
} : { } : {
id: In(ps.userIds), id: In(ps.userIds),
isSuspended: false, isSuspended: false,
isRemoteSuspended: false,
}); });
// リクエストされた通りに並べ替え // リクエストされた通りに並べ替え

View File

@ -451,6 +451,7 @@ export class ClientServerService {
usernameLower: username.toLowerCase(), usernameLower: username.toLowerCase(),
host: host ?? IsNull(), host: host ?? IsNull(),
isSuspended: false, isSuspended: false,
isRemoteSuspended: false,
requireSigninToViewContents: false, requireSigninToViewContents: false,
}); });
@ -510,6 +511,7 @@ export class ClientServerService {
usernameLower: username.toLowerCase(), usernameLower: username.toLowerCase(),
host: host ?? IsNull(), host: host ?? IsNull(),
isSuspended: false, isSuspended: false,
isRemoteSuspended: false,
}); });
vary(reply.raw, 'Accept'); vary(reply.raw, 'Accept');
@ -559,6 +561,7 @@ export class ClientServerService {
id: request.params.user, id: request.params.user,
host: IsNull(), host: IsNull(),
isSuspended: false, isSuspended: false,
isRemoteSuspended: false,
}); });
if (user == null) { if (user == null) {

View File

@ -15,6 +15,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<span class="sub"><span class="acct _monospace">@{{ acct(user) }}</span></span> <span class="sub"><span class="acct _monospace">@{{ acct(user) }}</span></span>
<span class="state"> <span class="state">
<span v-if="suspended" class="suspended">Suspended</span> <span v-if="suspended" class="suspended">Suspended</span>
<span v-if="remoteSuspended" class="suspended">Suspended in Remote</span>
<span v-if="silenced" class="silenced">Silenced</span> <span v-if="silenced" class="silenced">Silenced</span>
<span v-if="moderator" class="moderator">Moderator</span> <span v-if="moderator" class="moderator">Moderator</span>
</span> </span>
@ -254,6 +255,7 @@ const ap = ref<any>(null);
const moderator = ref(false); const moderator = ref(false);
const silenced = ref(false); const silenced = ref(false);
const suspended = ref(false); const suspended = ref(false);
const remoteSuspended = ref(false);
const isSystem = ref(false); const isSystem = ref(false);
const moderationNote = ref(''); const moderationNote = ref('');
const filesPaginator = markRaw(new Paginator('admin/drive/files', { const filesPaginator = markRaw(new Paginator('admin/drive/files', {
@ -288,6 +290,7 @@ function createFetcher() {
moderator.value = info.value.isModerator; moderator.value = info.value.isModerator;
silenced.value = info.value.isSilenced; silenced.value = info.value.isSilenced;
suspended.value = info.value.isSuspended; suspended.value = info.value.isSuspended;
remoteSuspended.value = info.value.isRemoteSuspended;
moderationNote.value = info.value.moderationNote; moderationNote.value = info.value.moderationNote;
isSystem.value = user.value.host == null && user.value.username.includes('.'); isSystem.value = user.value.host == null && user.value.username.includes('.');

View File

@ -11586,6 +11586,7 @@ export interface operations {
isModerator: boolean; isModerator: boolean;
isSilenced: boolean; isSilenced: boolean;
isSuspended: boolean; isSuspended: boolean;
isRemoteSuspended: boolean;
isHibernated: boolean; isHibernated: boolean;
lastActiveDate: string | null; lastActiveDate: string | null;
moderationNote: string; moderationNote: string;