From 9771f1c435d613ef5d8eecb9b32dd68527b3eefc Mon Sep 17 00:00:00 2001 From: syuilo <Syuilotan@yahoo.co.jp> Date: Fri, 29 Sep 2023 13:26:11 +0900 Subject: [PATCH] enhance: improve moderation log --- locales/index.d.ts | 3 +++ locales/ja-JP.yml | 3 +++ .../server/api/endpoints/admin/ad/create.ts | 8 ++++++ .../server/api/endpoints/admin/ad/delete.ts | 8 ++++++ .../server/api/endpoints/admin/ad/update.ts | 11 ++++++++ packages/backend/src/types.ts | 16 ++++++++++++ .../src/pages/admin/modlog.ModLog.vue | 26 ++++++++++++++++++- packages/misskey-js/etc/misskey-js.api.md | 2 +- packages/misskey-js/src/consts.ts | 16 ++++++++++++ 9 files changed, 91 insertions(+), 2 deletions(-) diff --git a/locales/index.d.ts b/locales/index.d.ts index b971e8905b..099ebbfc7a 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -2283,6 +2283,9 @@ export interface Locale { "unmarkSensitiveDriveFile": string; "resolveAbuseReport": string; "createInvitation": string; + "createAd": string; + "deleteAd": string; + "updateAd": string; }; } declare const locales: { diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 5822ba8fba..321c2c5f01 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -2196,3 +2196,6 @@ _moderationLogTypes: unmarkSensitiveDriveFile: "ファイルをセンシティブ解除" resolveAbuseReport: "通報を解決" createInvitation: "招待コードを作成" + createAd: "広告を作成" + deleteAd: "広告を削除" + updateAd: "広告を更新" diff --git a/packages/backend/src/server/api/endpoints/admin/ad/create.ts b/packages/backend/src/server/api/endpoints/admin/ad/create.ts index 2ed9410e78..e48dffecf4 100644 --- a/packages/backend/src/server/api/endpoints/admin/ad/create.ts +++ b/packages/backend/src/server/api/endpoints/admin/ad/create.ts @@ -8,6 +8,7 @@ import { Endpoint } from '@/server/api/endpoint-base.js'; import type { AdsRepository } from '@/models/_.js'; import { IdService } from '@/core/IdService.js'; import { DI } from '@/di-symbols.js'; +import { ModerationLogService } from '@/core/ModerationLogService.js'; export const meta = { tags: ['admin'], @@ -39,6 +40,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint- private adsRepository: AdsRepository, private idService: IdService, + private moderationLogService: ModerationLogService, ) { super(meta, paramDef, async (ps, me) => { const ad = await this.adsRepository.insert({ @@ -54,6 +56,12 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint- place: ps.place, memo: ps.memo, }).then(r => this.adsRepository.findOneByOrFail({ id: r.identifiers[0].id })); + + this.moderationLogService.log(me, 'createAd', { + adId: ad.id, + ad: ad, + }); + return ad; }); } diff --git a/packages/backend/src/server/api/endpoints/admin/ad/delete.ts b/packages/backend/src/server/api/endpoints/admin/ad/delete.ts index d3c53d4f67..8097133a4c 100644 --- a/packages/backend/src/server/api/endpoints/admin/ad/delete.ts +++ b/packages/backend/src/server/api/endpoints/admin/ad/delete.ts @@ -7,6 +7,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; import type { AdsRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; +import { ModerationLogService } from '@/core/ModerationLogService.js'; import { ApiError } from '../../../error.js'; export const meta = { @@ -37,6 +38,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint- constructor( @Inject(DI.adsRepository) private adsRepository: AdsRepository, + + private moderationLogService: ModerationLogService, ) { super(meta, paramDef, async (ps, me) => { const ad = await this.adsRepository.findOneBy({ id: ps.id }); @@ -44,6 +47,11 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint- if (ad == null) throw new ApiError(meta.errors.noSuchAd); await this.adsRepository.delete(ad.id); + + this.moderationLogService.log(me, 'deleteAd', { + adId: ad.id, + ad: ad, + }); }); } } diff --git a/packages/backend/src/server/api/endpoints/admin/ad/update.ts b/packages/backend/src/server/api/endpoints/admin/ad/update.ts index 5b77f67e10..d065f9ec50 100644 --- a/packages/backend/src/server/api/endpoints/admin/ad/update.ts +++ b/packages/backend/src/server/api/endpoints/admin/ad/update.ts @@ -7,6 +7,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; import type { AdsRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; +import { ModerationLogService } from '@/core/ModerationLogService.js'; import { ApiError } from '../../../error.js'; export const meta = { @@ -46,6 +47,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint- constructor( @Inject(DI.adsRepository) private adsRepository: AdsRepository, + + private moderationLogService: ModerationLogService, ) { super(meta, paramDef, async (ps, me) => { const ad = await this.adsRepository.findOneBy({ id: ps.id }); @@ -63,6 +66,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint- startsAt: new Date(ps.startsAt), dayOfWeek: ps.dayOfWeek, }); + + const updatedAd = await this.adsRepository.findOneByOrFail({ id: ad.id }); + + this.moderationLogService.log(me, 'updateAd', { + adId: ad.id, + before: ad, + after: updatedAd, + }); }); } } diff --git a/packages/backend/src/types.ts b/packages/backend/src/types.ts index 9e06d30aac..a9b9a55bc0 100644 --- a/packages/backend/src/types.ts +++ b/packages/backend/src/types.ts @@ -57,6 +57,9 @@ export const moderationLogTypes = [ 'unmarkSensitiveDriveFile', 'resolveAbuseReport', 'createInvitation', + 'createAd', + 'updateAd', + 'deleteAd', ] as const; export type ModerationLogPayloads = { @@ -202,6 +205,19 @@ export type ModerationLogPayloads = { createInvitation: { invitations: any[]; }; + createAd: { + adId: string; + ad: any; + }; + updateAd: { + adId: string; + before: any; + after: any; + }; + deleteAd: { + adId: string; + ad: any; + }; }; export type Serialized<T> = { diff --git a/packages/frontend/src/pages/admin/modlog.ModLog.vue b/packages/frontend/src/pages/admin/modlog.ModLog.vue index 8d83b32fa1..99b8544f33 100644 --- a/packages/frontend/src/pages/admin/modlog.ModLog.vue +++ b/packages/frontend/src/pages/admin/modlog.ModLog.vue @@ -6,7 +6,13 @@ SPDX-License-Identifier: AGPL-3.0-only <template> <MkFolder> <template #label> - <b>{{ i18n.ts._moderationLogTypes[log.type] }}</b> + <b + :class="{ + [$style.logGreen]: ['createRole', 'addCustomEmoji', 'createGlobalAnnouncement', 'createUserAnnouncement', 'createAd', 'createInvitation'].includes(log.type), + [$style.logYellow]: ['markSensitiveDriveFile', 'resetPassword'].includes(log.type), + [$style.logRed]: ['suspend', 'deleteRole', 'suspendRemoteInstance', 'deleteGlobalAnnouncement', 'deleteUserAnnouncement', 'deleteCustomEmoji', 'deleteNote', 'deleteDriveFile', 'deleteAd'].includes(log.type) + }" + >{{ i18n.ts._moderationLogTypes[log.type] }}</b> <span v-if="log.type === 'updateUserNote'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span> <span v-else-if="log.type === 'suspend'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span> <span v-else-if="log.type === 'unsuspend'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span> @@ -18,6 +24,7 @@ SPDX-License-Identifier: AGPL-3.0-only <span v-else-if="log.type === 'deleteRole'">: {{ log.info.role.name }}</span> <span v-else-if="log.type === 'addCustomEmoji'">: {{ log.info.emoji.name }}</span> <span v-else-if="log.type === 'updateCustomEmoji'">: {{ log.info.before.name }}</span> + <span v-else-if="log.type === 'deleteCustomEmoji'">: {{ log.info.emoji.name }}</span> <span v-else-if="log.type === 'markSensitiveDriveFile'">: @{{ log.info.fileUserUsername }}{{ log.info.fileUserHost ? '@' + log.info.fileUserHost : '' }}</span> <span v-else-if="log.type === 'unmarkSensitiveDriveFile'">: @{{ log.info.fileUserUsername }}{{ log.info.fileUserHost ? '@' + log.info.fileUserHost : '' }}</span> <span v-else-if="log.type === 'suspendRemoteInstance'">: {{ log.info.host }}</span> @@ -76,6 +83,11 @@ SPDX-License-Identifier: AGPL-3.0-only <CodeDiff :context="5" :hideHeader="true" :oldString="JSON5.stringify(log.info.before, null, '\t')" :newString="JSON5.stringify(log.info.after, null, '\t')" language="javascript" maxHeight="300px"/> </div> </template> + <template v-else-if="log.type === 'updateAd'"> + <div :class="$style.diff"> + <CodeDiff :context="5" :hideHeader="true" :oldString="JSON5.stringify(log.info.before, null, '\t')" :newString="JSON5.stringify(log.info.after, null, '\t')" language="javascript" maxHeight="300px"/> + </div> + </template> <details> <summary>raw</summary> @@ -114,4 +126,16 @@ const props = defineProps<{ border-radius: 6px; overflow: clip; } + +.logYellow { + color: var(--warning); +} + +.logRed { + color: var(--error); +} + +.logGreen { + color: var(--success); +} </style> diff --git a/packages/misskey-js/etc/misskey-js.api.md b/packages/misskey-js/etc/misskey-js.api.md index 97b43ee635..d24a0624d0 100644 --- a/packages/misskey-js/etc/misskey-js.api.md +++ b/packages/misskey-js/etc/misskey-js.api.md @@ -2625,7 +2625,7 @@ type ModerationLog = { }); // @public (undocumented) -export const moderationLogTypes: readonly ["updateServerSettings", "suspend", "unsuspend", "updateUserNote", "addCustomEmoji", "updateCustomEmoji", "deleteCustomEmoji", "assignRole", "unassignRole", "createRole", "updateRole", "deleteRole", "clearQueue", "promoteQueue", "deleteDriveFile", "deleteNote", "createGlobalAnnouncement", "createUserAnnouncement", "updateGlobalAnnouncement", "updateUserAnnouncement", "deleteGlobalAnnouncement", "deleteUserAnnouncement", "resetPassword", "suspendRemoteInstance", "unsuspendRemoteInstance", "markSensitiveDriveFile", "unmarkSensitiveDriveFile", "resolveAbuseReport", "createInvitation"]; +export const moderationLogTypes: readonly ["updateServerSettings", "suspend", "unsuspend", "updateUserNote", "addCustomEmoji", "updateCustomEmoji", "deleteCustomEmoji", "assignRole", "unassignRole", "createRole", "updateRole", "deleteRole", "clearQueue", "promoteQueue", "deleteDriveFile", "deleteNote", "createGlobalAnnouncement", "createUserAnnouncement", "updateGlobalAnnouncement", "updateUserAnnouncement", "deleteGlobalAnnouncement", "deleteUserAnnouncement", "resetPassword", "suspendRemoteInstance", "unsuspendRemoteInstance", "markSensitiveDriveFile", "unmarkSensitiveDriveFile", "resolveAbuseReport", "createInvitation", "createAd", "updateAd", "deleteAd"]; // @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 14a5b5643c..271a64274f 100644 --- a/packages/misskey-js/src/consts.ts +++ b/packages/misskey-js/src/consts.ts @@ -75,6 +75,9 @@ export const moderationLogTypes = [ 'unmarkSensitiveDriveFile', 'resolveAbuseReport', 'createInvitation', + 'createAd', + 'updateAd', + 'deleteAd', ] as const; export type ModerationLogPayloads = { @@ -220,4 +223,17 @@ export type ModerationLogPayloads = { createInvitation: { invitations: any[]; }; + createAd: { + adId: string; + ad: any; + }; + updateAd: { + adId: string; + before: any; + after: any; + }; + deleteAd: { + adId: string; + ad: any; + }; };