summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNafu Satsuki <satsuki@nafusoft.dev>2023-11-18 05:20:11 +0900
committersyuilo <Syuilotan@yahoo.co.jp>2023-11-18 21:07:47 +0900
commit2b6f789a5bc741d9092d29ea17d03be794ef5d51 (patch)
tree1521e71e2da7018c6d51ff90b6132ebb18b01048
parentlint fix (diff)
downloadsharkey-2b6f789a5bc741d9092d29ea17d03be794ef5d51.tar.gz
sharkey-2b6f789a5bc741d9092d29ea17d03be794ef5d51.tar.bz2
sharkey-2b6f789a5bc741d9092d29ea17d03be794ef5d51.zip
feat(moderation): モデレーターがユーザーのアイコンもしくはバナー画像を未設定状態にできる機能を追加 (MisskeyIO#222)
Co-authored-by: まっちゃとーにゅ <17376330+u1-liquid@users.noreply.github.com>
-rw-r--r--locales/en-US.yml4
-rw-r--r--locales/index.d.ts4
-rw-r--r--locales/ja-JP.yml4
-rw-r--r--packages/backend/src/server/api/EndpointsModule.ts8
-rw-r--r--packages/backend/src/server/api/endpoints.ts4
-rw-r--r--packages/backend/src/server/api/endpoints/admin/delete-user-avatar.ts48
-rw-r--r--packages/backend/src/server/api/endpoints/admin/delete-user-banner.ts48
-rw-r--r--packages/frontend/src/pages/admin-user.vue42
-rw-r--r--packages/misskey-js/etc/misskey-js.api.md12
-rw-r--r--packages/misskey-js/src/api.types.ts2
10 files changed, 176 insertions, 0 deletions
diff --git a/locales/en-US.yml b/locales/en-US.yml
index 09fd726c9f..2aba028e45 100644
--- a/locales/en-US.yml
+++ b/locales/en-US.yml
@@ -564,6 +564,10 @@ output: "Output"
script: "Script"
disablePagesScript: "Disable AiScript on Pages"
updateRemoteUser: "Update remote user information"
+deleteUserAvatar: "Delete user icon"
+deleteUserAvatarConfirm: "Are you sure that you want to delete this user's icon?"
+deleteUserBanner: "Delete user banner"
+deleteUserBannerConfirm: "Are you sure that you want to delete this user's banner?"
deleteAllFiles: "Delete all files"
deleteAllFilesConfirm: "Are you sure that you want to delete all files?"
removeAllFollowing: "Unfollow all followed users"
diff --git a/locales/index.d.ts b/locales/index.d.ts
index 6baed91c42..6fd6d3641a 100644
--- a/locales/index.d.ts
+++ b/locales/index.d.ts
@@ -567,6 +567,10 @@ export interface Locale {
"script": string;
"disablePagesScript": string;
"updateRemoteUser": string;
+ "deleteUserAvatar": string;
+ "deleteUserAvatarConfirm": string;
+ "deleteUserBanner": string;
+ "deleteUserBannerConfirm": string;
"deleteAllFiles": string;
"deleteAllFilesConfirm": string;
"removeAllFollowing": string;
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index e59a550df5..9685e9c5a5 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -564,6 +564,10 @@ output: "出力"
script: "スクリプト"
disablePagesScript: "Pagesのスクリプトを無効にする"
updateRemoteUser: "リモートユーザー情報の更新"
+deleteUserAvatar: "アイコンを削除"
+deleteUserAvatarConfirm: "アイコンを削除しますか?"
+deleteUserBanner: "バナーを削除"
+deleteUserBannerConfirm: "バナーを削除しますか?"
deleteAllFiles: "すべてのファイルを削除"
deleteAllFilesConfirm: "すべてのファイルを削除しますか?"
removeAllFollowing: "フォローを全解除"
diff --git a/packages/backend/src/server/api/EndpointsModule.ts b/packages/backend/src/server/api/EndpointsModule.ts
index 6d813ae04e..3797b46d04 100644
--- a/packages/backend/src/server/api/EndpointsModule.ts
+++ b/packages/backend/src/server/api/EndpointsModule.ts
@@ -24,6 +24,8 @@ import * as ep___admin_avatarDecorations_delete from './endpoints/admin/avatar-d
import * as ep___admin_avatarDecorations_list from './endpoints/admin/avatar-decorations/list.js';
import * as ep___admin_avatarDecorations_update from './endpoints/admin/avatar-decorations/update.js';
import * as ep___admin_deleteAllFilesOfAUser from './endpoints/admin/delete-all-files-of-a-user.js';
+import * as ep___admin_deleteUserAvatar from './endpoints/admin/delete-user-avatar.js';
+import * as ep___admin_deleteUserBanner from './endpoints/admin/delete-user-banner.js';
import * as ep___admin_drive_cleanRemoteFiles from './endpoints/admin/drive/clean-remote-files.js';
import * as ep___admin_drive_cleanup from './endpoints/admin/drive/cleanup.js';
import * as ep___admin_drive_files from './endpoints/admin/drive/files.js';
@@ -383,6 +385,8 @@ const $admin_avatarDecorations_delete: Provider = { provide: 'ep:admin/avatar-de
const $admin_avatarDecorations_list: Provider = { provide: 'ep:admin/avatar-decorations/list', useClass: ep___admin_avatarDecorations_list.default };
const $admin_avatarDecorations_update: Provider = { provide: 'ep:admin/avatar-decorations/update', useClass: ep___admin_avatarDecorations_update.default };
const $admin_deleteAllFilesOfAUser: Provider = { provide: 'ep:admin/delete-all-files-of-a-user', useClass: ep___admin_deleteAllFilesOfAUser.default };
+const $admin_deleteUserAvatar: Provider = { provide: 'ep:admin/delete-user-avatar', useClass: ep___admin_deleteUserAvatar.default };
+const $admin_deleteUserBanner: Provider = { provide: 'ep:admin/delete-user-banner', useClass: ep___admin_deleteUserBanner.default };
const $admin_drive_cleanRemoteFiles: Provider = { provide: 'ep:admin/drive/clean-remote-files', useClass: ep___admin_drive_cleanRemoteFiles.default };
const $admin_drive_cleanup: Provider = { provide: 'ep:admin/drive/cleanup', useClass: ep___admin_drive_cleanup.default };
const $admin_drive_files: Provider = { provide: 'ep:admin/drive/files', useClass: ep___admin_drive_files.default };
@@ -746,6 +750,8 @@ const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention
$admin_avatarDecorations_list,
$admin_avatarDecorations_update,
$admin_deleteAllFilesOfAUser,
+ $admin_deleteUserAvatar,
+ $admin_deleteUserBanner,
$admin_drive_cleanRemoteFiles,
$admin_drive_cleanup,
$admin_drive_files,
@@ -1103,6 +1109,8 @@ const $retention: Provider = { provide: 'ep:retention', useClass: ep___retention
$admin_avatarDecorations_list,
$admin_avatarDecorations_update,
$admin_deleteAllFilesOfAUser,
+ $admin_deleteUserAvatar,
+ $admin_deleteUserBanner,
$admin_drive_cleanRemoteFiles,
$admin_drive_cleanup,
$admin_drive_files,
diff --git a/packages/backend/src/server/api/endpoints.ts b/packages/backend/src/server/api/endpoints.ts
index ef4bd3e2b5..4162ace337 100644
--- a/packages/backend/src/server/api/endpoints.ts
+++ b/packages/backend/src/server/api/endpoints.ts
@@ -24,6 +24,8 @@ import * as ep___admin_avatarDecorations_delete from './endpoints/admin/avatar-d
import * as ep___admin_avatarDecorations_list from './endpoints/admin/avatar-decorations/list.js';
import * as ep___admin_avatarDecorations_update from './endpoints/admin/avatar-decorations/update.js';
import * as ep___admin_deleteAllFilesOfAUser from './endpoints/admin/delete-all-files-of-a-user.js';
+import * as ep___admin_deleteUserAvatar from './endpoints/admin/delete-user-avatar.js';
+import * as ep___admin_deleteUserBanner from './endpoints/admin/delete-user-banner.js';
import * as ep___admin_drive_cleanRemoteFiles from './endpoints/admin/drive/clean-remote-files.js';
import * as ep___admin_drive_cleanup from './endpoints/admin/drive/cleanup.js';
import * as ep___admin_drive_files from './endpoints/admin/drive/files.js';
@@ -381,6 +383,8 @@ const eps = [
['admin/avatar-decorations/list', ep___admin_avatarDecorations_list],
['admin/avatar-decorations/update', ep___admin_avatarDecorations_update],
['admin/delete-all-files-of-a-user', ep___admin_deleteAllFilesOfAUser],
+ ['admin/delete-user-avatar', ep___admin_deleteUserAvatar],
+ ['admin/delete-user-banner', ep___admin_deleteUserBanner],
['admin/drive/clean-remote-files', ep___admin_drive_cleanRemoteFiles],
['admin/drive/cleanup', ep___admin_drive_cleanup],
['admin/drive/files', ep___admin_drive_files],
diff --git a/packages/backend/src/server/api/endpoints/admin/delete-user-avatar.ts b/packages/backend/src/server/api/endpoints/admin/delete-user-avatar.ts
new file mode 100644
index 0000000000..d3c78d7fb6
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/admin/delete-user-avatar.ts
@@ -0,0 +1,48 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { Inject, Injectable } from '@nestjs/common';
+import type { UsersRepository } from '@/models/_.js';
+import { Endpoint } from '@/server/api/endpoint-base.js';
+import { DI } from '@/di-symbols.js';
+
+export const meta = {
+ tags: ['admin'],
+
+ requireCredential: true,
+ requireModerator: true,
+} as const;
+
+export const paramDef = {
+ type: 'object',
+ properties: {
+ userId: { type: 'string', format: 'misskey:id' },
+ },
+ required: ['userId'],
+} as const;
+
+// eslint-disable-next-line import/no-default-export
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> {
+ constructor(
+ @Inject(DI.usersRepository)
+ private usersRepository: UsersRepository,
+ ) {
+ super(meta, paramDef, async (ps, me) => {
+ const user = await this.usersRepository.findOneBy({ id: ps.userId });
+
+ if (user == null) {
+ throw new Error('user not found');
+ }
+
+ await this.usersRepository.update(user.id, {
+ avatar: null,
+ avatarId: null,
+ avatarUrl: null,
+ avatarBlurhash: null,
+ });
+ });
+ }
+}
diff --git a/packages/backend/src/server/api/endpoints/admin/delete-user-banner.ts b/packages/backend/src/server/api/endpoints/admin/delete-user-banner.ts
new file mode 100644
index 0000000000..e076cdcfc1
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/admin/delete-user-banner.ts
@@ -0,0 +1,48 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and other misskey contributors
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { Inject, Injectable } from '@nestjs/common';
+import type { UsersRepository } from '@/models/_.js';
+import { Endpoint } from '@/server/api/endpoint-base.js';
+import { DI } from '@/di-symbols.js';
+
+export const meta = {
+ tags: ['admin'],
+
+ requireCredential: true,
+ requireModerator: true,
+} as const;
+
+export const paramDef = {
+ type: 'object',
+ properties: {
+ userId: { type: 'string', format: 'misskey:id' },
+ },
+ required: ['userId'],
+} as const;
+
+// eslint-disable-next-line import/no-default-export
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> {
+ constructor(
+ @Inject(DI.usersRepository)
+ private usersRepository: UsersRepository,
+ ) {
+ super(meta, paramDef, async (ps, me) => {
+ const user = await this.usersRepository.findOneBy({ id: ps.userId });
+
+ if (user == null) {
+ throw new Error('user not found');
+ }
+
+ await this.usersRepository.update(user.id, {
+ banner: null,
+ bannerId: null,
+ bannerUrl: null,
+ bannerBlurhash: null,
+ });
+ });
+ }
+}
diff --git a/packages/frontend/src/pages/admin-user.vue b/packages/frontend/src/pages/admin-user.vue
index 5d671acf31..9f4975e888 100644
--- a/packages/frontend/src/pages/admin-user.vue
+++ b/packages/frontend/src/pages/admin-user.vue
@@ -122,6 +122,10 @@ SPDX-License-Identifier: AGPL-3.0-only
</template>
</MkFolder>
+ <div>
+ <MkButton v-if="iAmModerator" inline danger style="margin-right: 8px;" @click="deleteUserAvatar"><i class="ti ti-user-circle"></i> {{ i18n.ts.deleteUserAvatar }}</MkButton>
+ <MkButton v-if="iAmModerator" inline danger @click="deleteUserBanner"><i class="ti ti-photo"></i> {{ i18n.ts.deleteUserBanner }}</MkButton>
+ </div>
<MkButton v-if="$i.isAdmin" inline danger @click="deleteAccount">{{ i18n.ts.deleteAccount }}</MkButton>
</div>
</FormSection>
@@ -320,6 +324,44 @@ async function toggleSuspend(v) {
}
}
+async function deleteUserAvatar() {
+ const confirm = await os.confirm({
+ type: 'warning',
+ text: i18n.ts.deleteUserAvatarConfirm,
+ });
+ if (confirm.canceled) return;
+ const process = async () => {
+ await os.api('admin/delete-user-avatar', { userId: user.id });
+ os.success();
+ };
+ await process().catch(err => {
+ os.alert({
+ type: 'error',
+ text: err.toString(),
+ });
+ });
+ refreshUser();
+}
+
+async function deleteUserBanner() {
+ const confirm = await os.confirm({
+ type: 'warning',
+ text: i18n.ts.deleteUserBannerConfirm,
+ });
+ if (confirm.canceled) return;
+ const process = async () => {
+ await os.api('admin/delete-user-banner', { userId: user.id });
+ os.success();
+ };
+ await process().catch(err => {
+ os.alert({
+ type: 'error',
+ text: err.toString(),
+ });
+ });
+ refreshUser();
+}
+
async function deleteAllFiles() {
const confirm = await os.confirm({
type: 'warning',
diff --git a/packages/misskey-js/etc/misskey-js.api.md b/packages/misskey-js/etc/misskey-js.api.md
index 87922ba791..f4bcaa8066 100644
--- a/packages/misskey-js/etc/misskey-js.api.md
+++ b/packages/misskey-js/etc/misskey-js.api.md
@@ -345,6 +345,18 @@ export type Endpoints = {
};
res: null;
};
+ 'admin/delete-user-avatar': {
+ req: {
+ userId: User['id'];
+ };
+ res: null;
+ };
+ 'admin/delete-user-banner': {
+ req: {
+ userId: User['id'];
+ };
+ res: null;
+ };
'admin/delete-logs': {
req: NoParams;
res: null;
diff --git a/packages/misskey-js/src/api.types.ts b/packages/misskey-js/src/api.types.ts
index 54b175fcf1..e3f28c644e 100644
--- a/packages/misskey-js/src/api.types.ts
+++ b/packages/misskey-js/src/api.types.ts
@@ -15,6 +15,8 @@ export type Endpoints = {
// admin
'admin/abuse-user-reports': { req: TODO; res: TODO; };
'admin/delete-all-files-of-a-user': { req: { userId: User['id']; }; res: null; };
+ 'admin/delete-user-avatar': { req: { userId: User['id']; }; res: null; };
+ 'admin/delete-user-banner': { req: { userId: User['id']; }; res: null; };
'admin/delete-logs': { req: NoParams; res: null; };
'admin/get-index-stats': { req: TODO; res: TODO; };
'admin/get-table-stats': { req: TODO; res: TODO; };