summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHazelnoot <acomputerdog@gmail.com>2025-01-28 11:39:41 -0500
committerHazelnoot <acomputerdog@gmail.com>2025-02-16 19:20:41 -0500
commit568d82a9746d3d67a756b13fc007beb057dcc011 (patch)
treec1403f38bebcd931952b3fc712a2ffd66b54b62c
parentfix TypeScript errors in modlog.MogLog.vue (diff)
downloadsharkey-568d82a9746d3d67a756b13fc007beb057dcc011.tar.gz
sharkey-568d82a9746d3d67a756b13fc007beb057dcc011.tar.bz2
sharkey-568d82a9746d3d67a756b13fc007beb057dcc011.zip
record ModLog entry when setting a user's content warning
-rw-r--r--locales/index.d.ts4
-rw-r--r--packages/backend/src/server/api/endpoints/admin/cw-user.ts26
-rw-r--r--packages/backend/src/types.ts8
-rw-r--r--packages/frontend/src/pages/admin/modlog.ModLog.vue8
-rw-r--r--packages/misskey-js/etc/misskey-js.api.md5
-rw-r--r--packages/misskey-js/src/consts.ts8
-rw-r--r--packages/misskey-js/src/entities.ts4
-rw-r--r--sharkey-locales/en-US.yml1
8 files changed, 55 insertions, 9 deletions
diff --git a/locales/index.d.ts b/locales/index.d.ts
index 39feda5075..5b7df00f93 100644
--- a/locales/index.d.ts
+++ b/locales/index.d.ts
@@ -10219,6 +10219,10 @@ export interface Locale extends ILocale {
*/
"decline": string;
/**
+ * Set content warning for user
+ */
+ "setMandatoryCW": string;
+ /**
* Set remote instance as NSFW
*/
"setRemoteInstanceNSFW": string;
diff --git a/packages/backend/src/server/api/endpoints/admin/cw-user.ts b/packages/backend/src/server/api/endpoints/admin/cw-user.ts
index d48ca565a4..bdcfa6a0d9 100644
--- a/packages/backend/src/server/api/endpoints/admin/cw-user.ts
+++ b/packages/backend/src/server/api/endpoints/admin/cw-user.ts
@@ -9,6 +9,7 @@ import type { UsersRepository } from '@/models/_.js';
import { DI } from '@/di-symbols.js';
import { CacheService } from '@/core/CacheService.js';
import { GlobalEventService } from '@/core/GlobalEventService.js';
+import { ModerationLogService } from '@/core/ModerationLogService.js';
export const meta = {
tags: ['admin'],
@@ -34,18 +35,31 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
private readonly usersRepository: UsersRepository,
private readonly globalEventService: GlobalEventService,
+ private readonly cacheService: CacheService,
+ private readonly moderationLogService: ModerationLogService,
) {
- super(meta, paramDef, async ps => {
- const result = await this.usersRepository.update(ps.userId, {
+ super(meta, paramDef, async (ps, me) => {
+ const user = await this.cacheService.findUserById(ps.userId);
+
+ // Skip if there's nothing to do
+ if (user.mandatoryCW === ps.cw) return;
+
+ // Log event first.
+ // This ensures that we don't "lose" the log if an error occurs
+ await this.moderationLogService.log(me, 'setMandatoryCW', {
+ newCW: ps.cw,
+ oldCW: user.mandatoryCW,
+ userId: user.id,
+ userUsername: user.username,
+ userHost: user.host,
+ });
+
+ await this.usersRepository.update(ps.userId, {
// Collapse empty strings to null
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
mandatoryCW: ps.cw || null,
});
- if (result.affected && result.affected < 1) {
- throw new Error('No such user');
- }
-
// Synchronize caches and other processes
this.globalEventService.publishInternalEvent('localUserUpdated', { id: ps.userId });
});
diff --git a/packages/backend/src/types.ts b/packages/backend/src/types.ts
index 067481d9da..b359fa5a39 100644
--- a/packages/backend/src/types.ts
+++ b/packages/backend/src/types.ts
@@ -100,6 +100,7 @@ export const moderationLogTypes = [
'deleteGlobalAnnouncement',
'deleteUserAnnouncement',
'resetPassword',
+ 'setMandatoryCW',
'setRemoteInstanceNSFW',
'unsetRemoteInstanceNSFW',
'suspendRemoteInstance',
@@ -261,6 +262,13 @@ export type ModerationLogPayloads = {
userUsername: string;
userHost: string | null;
};
+ setMandatoryCW: {
+ newCW: string | null;
+ oldCW: string | null;
+ userId: string;
+ userUsername: string;
+ userHost: string | null;
+ };
setRemoteInstanceNSFW: {
id: string;
host: string;
diff --git a/packages/frontend/src/pages/admin/modlog.ModLog.vue b/packages/frontend/src/pages/admin/modlog.ModLog.vue
index 2e5c820054..741de875bc 100644
--- a/packages/frontend/src/pages/admin/modlog.ModLog.vue
+++ b/packages/frontend/src/pages/admin/modlog.ModLog.vue
@@ -22,6 +22,7 @@ SPDX-License-Identifier: AGPL-3.0-only
[$style.logYellow]: [
'markSensitiveDriveFile',
'resetPassword',
+ 'setMandatoryCW',
'suspendRemoteInstance',
'setRemoteInstanceNSFW',
'unsetRemoteInstanceNSFW',
@@ -55,6 +56,7 @@ SPDX-License-Identifier: AGPL-3.0-only
<span v-else-if="log.type === 'decline'">: @{{ 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>
<span v-else-if="log.type === 'resetPassword'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span>
+ <span v-else-if="log.type === 'setMandatoryCW'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span>
<span v-else-if="log.type === 'assignRole'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }} <i class="ti ti-arrow-right"></i> {{ log.info.roleName }}</span>
<span v-else-if="log.type === 'unassignRole'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }} <i class="ti ti-equal-not"></i> {{ log.info.roleName }}</span>
<span v-else-if="log.type === 'createRole'">: {{ log.info.role.name }}</span>
@@ -123,6 +125,12 @@ SPDX-License-Identifier: AGPL-3.0-only
<template v-else-if="log.type === 'approve'">
<div>{{ i18n.ts.user }}: <MkA :to="`/admin/user/${log.info.userId}`" class="_link">@{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</MkA></div>
</template>
+ <template v-else-if="log.type === 'setMandatoryCW'">
+ <div>{{ i18n.ts.user }}: <MkA :to="`/admin/user/${log.info.userId}`" class="_link">@{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</MkA></div>
+ <div :class="$style.diff">
+ <CodeDiff :context="0" :hideHeader="true" :oldString="log.info.oldCW ?? ''" :newString="log.info.newCW ?? ''" maxHeight="150px"/>
+ </div>
+ </template>
<template v-else-if="log.type === 'unsuspend'">
<div>{{ i18n.ts.user }}: <MkA :to="`/admin/user/${log.info.userId}`" class="_link">@{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</MkA></div>
</template>
diff --git a/packages/misskey-js/etc/misskey-js.api.md b/packages/misskey-js/etc/misskey-js.api.md
index ee8bfe322c..25921d14c8 100644
--- a/packages/misskey-js/etc/misskey-js.api.md
+++ b/packages/misskey-js/etc/misskey-js.api.md
@@ -2610,6 +2610,9 @@ type ModerationLog = {
type: 'deleteUserAnnouncement';
info: ModerationLogPayloads['deleteUserAnnouncement'];
} | {
+ type: 'setMandatoryCW';
+ info: ModerationLogPayloads['setMandatoryCW'];
+} | {
type: 'setRemoteInstanceNSFW';
info: ModerationLogPayloads['setRemoteInstanceNSFW'];
} | {
@@ -2708,7 +2711,7 @@ type ModerationLog = {
});
// @public (undocumented)
-export const moderationLogTypes: readonly ["updateServerSettings", "suspend", "approve", "decline", "unsuspend", "updateUserNote", "addCustomEmoji", "updateCustomEmoji", "deleteCustomEmoji", "assignRole", "unassignRole", "createRole", "updateRole", "deleteRole", "clearQueue", "promoteQueue", "deleteDriveFile", "deleteNote", "createGlobalAnnouncement", "createUserAnnouncement", "updateGlobalAnnouncement", "updateUserAnnouncement", "deleteGlobalAnnouncement", "deleteUserAnnouncement", "resetPassword", "setRemoteInstanceNSFW", "unsetRemoteInstanceNSFW", "suspendRemoteInstance", "unsuspendRemoteInstance", "rejectRemoteInstanceReports", "acceptRemoteInstanceReports", "updateRemoteInstanceNote", "markSensitiveDriveFile", "unmarkSensitiveDriveFile", "resolveAbuseReport", "forwardAbuseReport", "updateAbuseReportNote", "createInvitation", "createAd", "updateAd", "deleteAd", "createAvatarDecoration", "updateAvatarDecoration", "deleteAvatarDecoration", "unsetUserAvatar", "unsetUserBanner", "createSystemWebhook", "updateSystemWebhook", "deleteSystemWebhook", "createAbuseReportNotificationRecipient", "updateAbuseReportNotificationRecipient", "deleteAbuseReportNotificationRecipient", "deleteAccount", "deletePage", "deleteFlash", "deleteGalleryPost"];
+export const moderationLogTypes: readonly ["updateServerSettings", "suspend", "approve", "decline", "unsuspend", "updateUserNote", "addCustomEmoji", "updateCustomEmoji", "deleteCustomEmoji", "assignRole", "unassignRole", "createRole", "updateRole", "deleteRole", "clearQueue", "promoteQueue", "deleteDriveFile", "deleteNote", "createGlobalAnnouncement", "createUserAnnouncement", "updateGlobalAnnouncement", "updateUserAnnouncement", "deleteGlobalAnnouncement", "deleteUserAnnouncement", "resetPassword", "setMandatoryCW", "setRemoteInstanceNSFW", "unsetRemoteInstanceNSFW", "suspendRemoteInstance", "unsuspendRemoteInstance", "rejectRemoteInstanceReports", "acceptRemoteInstanceReports", "updateRemoteInstanceNote", "markSensitiveDriveFile", "unmarkSensitiveDriveFile", "resolveAbuseReport", "forwardAbuseReport", "updateAbuseReportNote", "createInvitation", "createAd", "updateAd", "deleteAd", "createAvatarDecoration", "updateAvatarDecoration", "deleteAvatarDecoration", "unsetUserAvatar", "unsetUserBanner", "createSystemWebhook", "updateSystemWebhook", "deleteSystemWebhook", "createAbuseReportNotificationRecipient", "updateAbuseReportNotificationRecipient", "deleteAbuseReportNotificationRecipient", "deleteAccount", "deletePage", "deleteFlash", "deleteGalleryPost"];
// @public (undocumented)
type MuteCreateRequest = operations['mute___create']['requestBody']['content']['application/json'];
diff --git a/packages/misskey-js/src/consts.ts b/packages/misskey-js/src/consts.ts
index fcb19be303..96da0a8fad 100644
--- a/packages/misskey-js/src/consts.ts
+++ b/packages/misskey-js/src/consts.ts
@@ -147,6 +147,7 @@ export const moderationLogTypes = [
'deleteGlobalAnnouncement',
'deleteUserAnnouncement',
'resetPassword',
+ 'setMandatoryCW',
'setRemoteInstanceNSFW',
'unsetRemoteInstanceNSFW',
'suspendRemoteInstance',
@@ -335,6 +336,13 @@ export type ModerationLogPayloads = {
userUsername: string;
userHost: string | null;
};
+ setMandatoryCW: {
+ newCW: string | null;
+ oldCW: string | null;
+ userId: string;
+ userUsername: string;
+ userHost: string | null;
+ };
setRemoteInstanceNSFW: {
id: string;
host: string;
diff --git a/packages/misskey-js/src/entities.ts b/packages/misskey-js/src/entities.ts
index b92c2537a1..3e88eae275 100644
--- a/packages/misskey-js/src/entities.ts
+++ b/packages/misskey-js/src/entities.ts
@@ -118,8 +118,8 @@ export type ModerationLog = {
type: 'deleteUserAnnouncement';
info: ModerationLogPayloads['deleteUserAnnouncement'];
} | {
- type: 'resetPassword';
- info: ModerationLogPayloads['resetPassword'];
+ type: 'setMandatoryCW';
+ info: ModerationLogPayloads['setMandatoryCW'];
} | {
type: 'setRemoteInstanceNSFW';
info: ModerationLogPayloads['setRemoteInstanceNSFW'];
diff --git a/sharkey-locales/en-US.yml b/sharkey-locales/en-US.yml
index a12d84e2f5..84dd527694 100644
--- a/sharkey-locales/en-US.yml
+++ b/sharkey-locales/en-US.yml
@@ -304,6 +304,7 @@ _abuseReport:
_moderationLogTypes:
approve: "Approved"
decline: "Declined"
+ setMandatoryCW: "Set content warning for user"
setRemoteInstanceNSFW: "Set remote instance as NSFW"
unsetRemoteInstanceNSFW: "Set remote instance as NSFW"
rejectRemoteInstanceReports: "Rejected reports from remote instance"