From 8e5a90589d9203a9f5abb2c4d67151c126915b11 Mon Sep 17 00:00:00 2001 From: syuilo Date: Sun, 24 Sep 2023 10:57:24 +0900 Subject: [PATCH] improve moderation log --- locales/index.d.ts | 2 + locales/ja-JP.yml | 2 + .../backend/src/core/CustomEmojiService.ts | 41 ++++++++++++++++--- .../server/api/endpoints/admin/emoji/add.ts | 8 +--- .../api/endpoints/admin/emoji/delete-bulk.ts | 2 +- .../api/endpoints/admin/emoji/delete.ts | 2 +- .../api/endpoints/admin/emoji/update.ts | 2 +- packages/backend/src/types.ts | 12 ++++++ packages/misskey-js/etc/misskey-js.api.md | 8 +++- packages/misskey-js/src/consts.ts | 12 ++++++ packages/misskey-js/src/entities.ts | 6 +++ 11 files changed, 81 insertions(+), 16 deletions(-) diff --git a/locales/index.d.ts b/locales/index.d.ts index c2f50dd54a..0ca5919dd4 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -2256,6 +2256,8 @@ export interface Locale { "suspend": string; "unsuspend": string; "addCustomEmoji": string; + "updateCustomEmoji": string; + "deleteCustomEmoji": string; "updateServerSettings": string; "updateUserNote": string; "deleteDriveFile": string; diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 43a3394264..13ab6755e6 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -2169,6 +2169,8 @@ _moderationLogTypes: suspend: "凍結" unsuspend: "凍結解除" addCustomEmoji: "カスタム絵文字追加" + updateCustomEmoji: "カスタム絵文字更新" + deleteCustomEmoji: "カスタム絵文字削除" updateServerSettings: "サーバー設定更新" updateUserNote: "モデレーションノート更新" deleteDriveFile: "ファイルを削除" diff --git a/packages/backend/src/core/CustomEmojiService.ts b/packages/backend/src/core/CustomEmojiService.ts index aa5490eba7..b14a8666e6 100644 --- a/packages/backend/src/core/CustomEmojiService.ts +++ b/packages/backend/src/core/CustomEmojiService.ts @@ -12,12 +12,13 @@ import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import type { MiDriveFile } from '@/models/DriveFile.js'; import type { MiEmoji } from '@/models/Emoji.js'; -import type { EmojisRepository, MiRole } from '@/models/_.js'; +import type { EmojisRepository, MiRole, MiUser } from '@/models/_.js'; import { bindThis } from '@/decorators.js'; import { MemoryKVCache, RedisSingleCache } from '@/misc/cache.js'; import { UtilityService } from '@/core/UtilityService.js'; import { query } from '@/misc/prelude/url.js'; import type { Serialized } from '@/server/api/stream/types.js'; +import { ModerationLogService } from '@/core/ModerationLogService.js'; const parseEmojiStrRegexp = /^(\w+)(?:@([\w.-]+))?$/; @@ -36,6 +37,7 @@ export class CustomEmojiService implements OnApplicationShutdown { private utilityService: UtilityService, private idService: IdService, private emojiEntityService: EmojiEntityService, + private moderationLogService: ModerationLogService, private globalEventService: GlobalEventService, ) { this.cache = new MemoryKVCache(1000 * 60 * 60 * 12); @@ -66,7 +68,7 @@ export class CustomEmojiService implements OnApplicationShutdown { isSensitive: boolean; localOnly: boolean; roleIdsThatCanBeUsedThisEmojiAsReaction: MiRole['id'][]; - }): Promise { + }, moderator?: MiUser): Promise { const emoji = await this.emojisRepository.insert({ id: this.idService.genId(), updatedAt: new Date(), @@ -89,6 +91,13 @@ export class CustomEmojiService implements OnApplicationShutdown { this.globalEventService.publishBroadcastStream('emojiAdded', { emoji: await this.emojiEntityService.packDetailed(emoji.id), }); + + if (moderator) { + this.moderationLogService.log(moderator, 'addCustomEmoji', { + emojiId: emoji.id, + emoji: emoji, + }); + } } return emoji; @@ -104,7 +113,7 @@ export class CustomEmojiService implements OnApplicationShutdown { isSensitive?: boolean; localOnly?: boolean; roleIdsThatCanBeUsedThisEmojiAsReaction?: MiRole['id'][]; - }): Promise { + }, moderator?: MiUser): Promise { const emoji = await this.emojisRepository.findOneByOrFail({ id: id }); const sameNameEmoji = await this.emojisRepository.findOneBy({ name: data.name, host: IsNull() }); if (sameNameEmoji != null && sameNameEmoji.id !== id) throw new Error('name already exists'); @@ -140,6 +149,14 @@ export class CustomEmojiService implements OnApplicationShutdown { emoji: updated, }); } + + if (moderator) { + this.moderationLogService.log(moderator, 'updateCustomEmoji', { + emojiId: emoji.id, + before: emoji, + after: updated, + }); + } } @bindThis @@ -231,7 +248,7 @@ export class CustomEmojiService implements OnApplicationShutdown { } @bindThis - public async delete(id: MiEmoji['id']) { + public async delete(id: MiEmoji['id'], moderator?: MiUser) { const emoji = await this.emojisRepository.findOneByOrFail({ id: id }); await this.emojisRepository.delete(emoji.id); @@ -241,16 +258,30 @@ export class CustomEmojiService implements OnApplicationShutdown { this.globalEventService.publishBroadcastStream('emojiDeleted', { emojis: [await this.emojiEntityService.packDetailed(emoji)], }); + + if (moderator) { + this.moderationLogService.log(moderator, 'deleteCustomEmoji', { + emojiId: emoji.id, + emoji: emoji, + }); + } } @bindThis - public async deleteBulk(ids: MiEmoji['id'][]) { + public async deleteBulk(ids: MiEmoji['id'][], moderator?: MiUser) { const emojis = await this.emojisRepository.findBy({ id: In(ids), }); for (const emoji of emojis) { await this.emojisRepository.delete(emoji.id); + + if (moderator) { + this.moderationLogService.log(moderator, 'deleteCustomEmoji', { + emojiId: emoji.id, + emoji: emoji, + }); + } } this.localEmojisCache.refresh(); diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/add.ts b/packages/backend/src/server/api/endpoints/admin/emoji/add.ts index fc297c4702..24d3a8a943 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/add.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/add.ts @@ -8,7 +8,6 @@ import { Endpoint } from '@/server/api/endpoint-base.js'; import type { DriveFilesRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { CustomEmojiService } from '@/core/CustomEmojiService.js'; -import { ModerationLogService } from '@/core/ModerationLogService.js'; import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js'; import { ApiError } from '../../../error.js'; @@ -61,7 +60,6 @@ export default class extends Endpoint { // eslint- private customEmojiService: CustomEmojiService, private emojiEntityService: EmojiEntityService, - private moderationLogService: ModerationLogService, ) { super(meta, paramDef, async (ps, me) => { const driveFile = await this.driveFilesRepository.findOneBy({ id: ps.fileId }); @@ -77,11 +75,7 @@ export default class extends Endpoint { // eslint- isSensitive: ps.isSensitive ?? false, localOnly: ps.localOnly ?? false, roleIdsThatCanBeUsedThisEmojiAsReaction: ps.roleIdsThatCanBeUsedThisEmojiAsReaction ?? [], - }); - - this.moderationLogService.log(me, 'addCustomEmoji', { - emojiId: emoji.id, - }); + }, me); return this.emojiEntityService.packDetailed(emoji); }); diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/delete-bulk.ts b/packages/backend/src/server/api/endpoints/admin/emoji/delete-bulk.ts index 4221913049..e6c1bf317f 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/delete-bulk.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/delete-bulk.ts @@ -30,7 +30,7 @@ export default class extends Endpoint { // eslint- private customEmojiService: CustomEmojiService, ) { super(meta, paramDef, async (ps, me) => { - await this.customEmojiService.deleteBulk(ps.ids); + await this.customEmojiService.deleteBulk(ps.ids, me); }); } } diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/delete.ts b/packages/backend/src/server/api/endpoints/admin/emoji/delete.ts index f020e22182..58aa0b9950 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/delete.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/delete.ts @@ -36,7 +36,7 @@ export default class extends Endpoint { // eslint- private customEmojiService: CustomEmojiService, ) { super(meta, paramDef, async (ps, me) => { - await this.customEmojiService.delete(ps.id); + await this.customEmojiService.delete(ps.id, me); }); } } diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/update.ts b/packages/backend/src/server/api/endpoints/admin/emoji/update.ts index f01be9e27a..2d69857408 100644 --- a/packages/backend/src/server/api/endpoints/admin/emoji/update.ts +++ b/packages/backend/src/server/api/endpoints/admin/emoji/update.ts @@ -84,7 +84,7 @@ export default class extends Endpoint { // eslint- isSensitive: ps.isSensitive, localOnly: ps.localOnly, roleIdsThatCanBeUsedThisEmojiAsReaction: ps.roleIdsThatCanBeUsedThisEmojiAsReaction, - }); + }, me); }); } } diff --git a/packages/backend/src/types.ts b/packages/backend/src/types.ts index b85388d6e4..ea78bb919a 100644 --- a/packages/backend/src/types.ts +++ b/packages/backend/src/types.ts @@ -33,6 +33,8 @@ export const moderationLogTypes = [ 'unsuspend', 'updateUserNote', 'addCustomEmoji', + 'updateCustomEmoji', + 'deleteCustomEmoji', 'assignRole', 'unassignRole', 'updateRole', @@ -70,6 +72,16 @@ export type ModerationLogPayloads = { }; addCustomEmoji: { emojiId: string; + emoji: any; + }; + updateCustomEmoji: { + emojiId: string; + before: any; + after: any; + }; + deleteCustomEmoji: { + emojiId: string; + emoji: any; }; assignRole: { userId: string; diff --git a/packages/misskey-js/etc/misskey-js.api.md b/packages/misskey-js/etc/misskey-js.api.md index b5d07a394c..d8b6aa44d8 100644 --- a/packages/misskey-js/etc/misskey-js.api.md +++ b/packages/misskey-js/etc/misskey-js.api.md @@ -2538,6 +2538,12 @@ type ModerationLog = { } | { type: 'addCustomEmoji'; info: ModerationLogPayloads['addCustomEmoji']; +} | { + type: 'updateCustomEmoji'; + info: ModerationLogPayloads['updateCustomEmoji']; +} | { + type: 'deleteCustomEmoji'; + info: ModerationLogPayloads['deleteCustomEmoji']; } | { type: 'assignRole'; info: ModerationLogPayloads['assignRole']; @@ -2592,7 +2598,7 @@ type ModerationLog = { }); // @public (undocumented) -export const moderationLogTypes: readonly ["updateServerSettings", "suspend", "unsuspend", "updateUserNote", "addCustomEmoji", "assignRole", "unassignRole", "updateRole", "deleteRole", "clearQueue", "promoteQueue", "deleteDriveFile", "deleteNote", "createGlobalAnnouncement", "createUserAnnouncement", "updateGlobalAnnouncement", "updateUserAnnouncement", "deleteGlobalAnnouncement", "deleteUserAnnouncement", "resetPassword", "suspendRemoteInstance", "unsuspendRemoteInstance"]; +export const moderationLogTypes: readonly ["updateServerSettings", "suspend", "unsuspend", "updateUserNote", "addCustomEmoji", "updateCustomEmoji", "deleteCustomEmoji", "assignRole", "unassignRole", "updateRole", "deleteRole", "clearQueue", "promoteQueue", "deleteDriveFile", "deleteNote", "createGlobalAnnouncement", "createUserAnnouncement", "updateGlobalAnnouncement", "updateUserAnnouncement", "deleteGlobalAnnouncement", "deleteUserAnnouncement", "resetPassword", "suspendRemoteInstance", "unsuspendRemoteInstance"]; // @public (undocumented) export const mutedNoteReasons: readonly ["word", "manual", "spam", "other"]; diff --git a/packages/misskey-js/src/consts.ts b/packages/misskey-js/src/consts.ts index dd4fd2609f..462ad16cc8 100644 --- a/packages/misskey-js/src/consts.ts +++ b/packages/misskey-js/src/consts.ts @@ -51,6 +51,8 @@ export const moderationLogTypes = [ 'unsuspend', 'updateUserNote', 'addCustomEmoji', + 'updateCustomEmoji', + 'deleteCustomEmoji', 'assignRole', 'unassignRole', 'updateRole', @@ -88,6 +90,16 @@ export type ModerationLogPayloads = { }; addCustomEmoji: { emojiId: string; + emoji: any; + }; + updateCustomEmoji: { + emojiId: string; + before: any; + after: any; + }; + deleteCustomEmoji: { + emojiId: string; + emoji: any; }; assignRole: { userId: string; diff --git a/packages/misskey-js/src/entities.ts b/packages/misskey-js/src/entities.ts index b157eb59f6..e6a97f0209 100644 --- a/packages/misskey-js/src/entities.ts +++ b/packages/misskey-js/src/entities.ts @@ -589,6 +589,12 @@ export type ModerationLog = { } | { type: 'addCustomEmoji'; info: ModerationLogPayloads['addCustomEmoji']; +} | { + type: 'updateCustomEmoji'; + info: ModerationLogPayloads['updateCustomEmoji']; +} | { + type: 'deleteCustomEmoji'; + info: ModerationLogPayloads['deleteCustomEmoji']; } | { type: 'assignRole'; info: ModerationLogPayloads['assignRole'];