From 8706fa0747d2aa517b176ceac7b601d53e7e731f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=82=E3=82=8F=E3=82=8F=E3=82=8F=E3=81=A8=E3=83=BC?= =?UTF-8?q?=E3=81=AB=E3=82=85?= <17376330+u1-liquid@users.noreply.github.com> Date: Fri, 18 Oct 2024 08:53:33 +0900 Subject: [PATCH] =?UTF-8?q?feat(moderation):=20=E3=83=A2=E3=83=87=E3=83=AC?= =?UTF-8?q?=E3=83=BC=E3=82=BF=E3=83=BC=E3=81=8C=E3=83=A6=E3=83=BC=E3=82=B6?= =?UTF-8?q?=E3=83=BC=E3=81=AE=E5=90=8D=E5=89=8D=E3=82=92=E5=A4=89=E6=9B=B4?= =?UTF-8?q?=E3=81=A7=E3=81=8D=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=EF=BC=86?= =?UTF-8?q?=E3=83=88=E3=83=BC=E3=82=AF=E3=83=B3=E3=82=92=E5=86=8D=E7=94=9F?= =?UTF-8?q?=E6=88=90=E3=81=A7=E3=81=8D=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?= =?UTF-8?q?=20(MisskeyIO#747)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- locales/ca-ES.yml | 4 +- locales/en-US.yml | 12 +- locales/es-ES.yml | 4 +- locales/id-ID.yml | 4 +- locales/index.d.ts | 24 +++- locales/it-IT.yml | 4 +- locales/ja-JP.yml | 12 +- locales/ja-KS.yml | 4 +- locales/ko-KR.yml | 8 +- locales/th-TH.yml | 4 +- locales/zh-CN.yml | 4 +- locales/zh-TW.yml | 4 +- .../backend/src/server/api/EndpointsModule.ts | 8 ++ packages/backend/src/server/api/endpoints.ts | 4 + .../endpoints/admin/regenerate-user-token.ts | 61 ++++++++ .../api/endpoints/admin/unset-user-avatar.ts | 2 +- .../api/endpoints/admin/unset-user-banner.ts | 2 +- .../endpoints/admin/unset-user-mutual-link.ts | 2 +- .../api/endpoints/admin/update-user-name.ts | 53 +++++++ packages/backend/src/types.ts | 14 ++ packages/frontend/src/pages/admin-user.vue | 32 ++++- .../src/pages/admin/modlog.ModLog.vue | 13 +- packages/misskey-js/etc/misskey-js.api.md | 18 ++- .../misskey-js/src/autogen/apiClientJSDoc.ts | 28 +++- packages/misskey-js/src/autogen/endpoint.ts | 4 + packages/misskey-js/src/autogen/entities.ts | 2 + packages/misskey-js/src/autogen/types.ts | 135 +++++++++++++++++- packages/misskey-js/src/consts.ts | 22 ++- packages/misskey-js/src/entities.ts | 6 + 29 files changed, 444 insertions(+), 50 deletions(-) create mode 100644 packages/backend/src/server/api/endpoints/admin/regenerate-user-token.ts create mode 100644 packages/backend/src/server/api/endpoints/admin/update-user-name.ts diff --git a/locales/ca-ES.yml b/locales/ca-ES.yml index d035555c73af..3989868cee2d 100644 --- a/locales/ca-ES.yml +++ b/locales/ca-ES.yml @@ -2003,8 +2003,8 @@ _permissions: "read:admin:show-user": "Veure informació privada de l'usuari " "read:admin:show-users": "Veure informació privada de l'usuari " "write:admin:suspend-user": "Suspendre usuari" - "write:admin:unset-user-avatar": "Esborrar avatar d'usuari " - "write:admin:unset-user-banner": "Esborrar bàner de l'usuari " + "write:admin:user-avatar": "Esborrar avatar d'usuari " + "write:admin:user-banner": "Esborrar bàner de l'usuari " "write:admin:unsuspend-user": "Treure la suspensió d'un usuari" "write:admin:meta": "Gestionar les metadades de la instància" "write:admin:user-note": "Gestionar les notes de moderació " diff --git a/locales/en-US.yml b/locales/en-US.yml index 7265b9ee879c..5f62bc8ebc37 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -693,6 +693,7 @@ useGlobalSetting: "Use global settings" useGlobalSettingDesc: "If turned on, your account's notification settings will be used. If turned off, individual configurations can be made." other: "Other" regenerateLoginToken: "Regenerate login token" +regenerateLoginTokenConfirm: "Are you sure you want to regenerate the login token? All devices will be logged out." regenerateLoginTokenDescription: "Regenerates the token used internally during login. Normally this action is not necessary. If regenerated, all devices will be logged out." theKeywordWhenSearchingForCustomEmoji: "This is the keyword when searching for custom emojis." setMultipleBySeparatingWithSpace: "Separate multiple entries with spaces." @@ -1060,7 +1061,7 @@ likeOnlyForRemote: "All (Only likes for remote instances)" nonSensitiveOnly: "Non-sensitive only" nonSensitiveOnlyForLocalLikeOnlyForRemote: "Non-sensitive only (Only likes from remote)" rolesAssignedToMe: "Roles assigned to me" -resetPasswordConfirm: "Really reset your password?" +resetPasswordConfirm: "Are you sure you want to reset password?" sensitiveWords: "Sensitive words" sensitiveWordsDescription: "The visibility of all notes containing any of the configured words will be set to \"Home\" automatically. You can list multiple by separating them via line breaks." sensitiveWordsDescription2: "Using spaces will create AND expressions and surrounding keywords with slashes will turn them into a regular expression." @@ -1268,6 +1269,7 @@ inquiry: "Contact" here: "here" mutualLink: "Mutual Link" saveThisFile: "Save this file to Drive" +changeUserName: "Change name" _bubbleGame: howToPlay: "How to play" hold: "Hold" @@ -2111,6 +2113,7 @@ _permissions: "read:admin:user-ips": "View user IP addresses" "read:admin:meta": "View instance metadata" "write:admin:reset-password": "Reset user password" + "write:admin:regenerate-user-token": "Regenerate user login token" "write:admin:resolve-abuse-user-report": "Resolve user report" "write:admin:send-email": "Send email" "read:admin:server-info": "View server info" @@ -2118,11 +2121,12 @@ _permissions: "read:admin:show-user": "View private user info" "read:admin:show-users": "View private user info" "write:admin:suspend-user": "Suspend user" - "write:admin:unset-user-avatar": "Remove user avatar" - "write:admin:unset-user-banner": "Remove user banner" - "write:admin:unset-user-mutual-link": "Remove user mutual link" + "write:admin:user-avatar": "Remove user avatar" + "write:admin:user-banner": "Remove user banner" + "write:admin:user-mutual-link": "Remove user mutual link" "write:admin:unsuspend-user": "Unsuspend user" "write:admin:meta": "Manage instance metadata" + "write:admin:user-name": "Change user name" "write:admin:user-note": "Manage moderation note" "write:admin:roles": "Manage roles" "read:admin:roles": "View roles" diff --git a/locales/es-ES.yml b/locales/es-ES.yml index 2e05364c312f..61cdb4f06f01 100644 --- a/locales/es-ES.yml +++ b/locales/es-ES.yml @@ -2031,8 +2031,8 @@ _permissions: "read:admin:show-user": "Ver información privada de usuario" "read:admin:show-users": "Ver información privada de usuario" "write:admin:suspend-user": "Suspender cuentas de usuario" - "write:admin:unset-user-avatar": "Quitar avatares de usuario" - "write:admin:unset-user-banner": "Quitar banner de usuarios" + "write:admin:user-avatar": "Quitar avatares de usuario" + "write:admin:user-banner": "Quitar banner de usuarios" "write:admin:unsuspend-user": "Quitar suspensión de cuentas de usuario" "write:admin:meta": "Edición de metadatos de la instancia" "write:admin:user-note": "Moderación de notas" diff --git a/locales/id-ID.yml b/locales/id-ID.yml index f8e645d63b57..c93824ccba11 100644 --- a/locales/id-ID.yml +++ b/locales/id-ID.yml @@ -2034,8 +2034,8 @@ _permissions: "read:admin:show-user": "Lihat informasi pengguna privat" "read:admin:show-users": "Lihat informasi pengguna privat" "write:admin:suspend-user": "Tangguhkan pengguna" - "write:admin:unset-user-avatar": "Hapus avatar pengguna" - "write:admin:unset-user-banner": "Hapus banner pengguna" + "write:admin:user-avatar": "Hapus avatar pengguna" + "write:admin:user-banner": "Hapus banner pengguna" "write:admin:unsuspend-user": "Batalkan penangguhan pengguna" "write:admin:meta": "Kelola metadata instansi" "write:admin:user-note": "Kelola moderasi catatan" diff --git a/locales/index.d.ts b/locales/index.d.ts index 69afc03744f4..5da7951fbb5a 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -2796,6 +2796,10 @@ export interface Locale extends ILocale { * ログイントークンを再生成 */ "regenerateLoginToken": string; + /** + * ログイントークンを再生成しますか? + */ + "regenerateLoginTokenConfirm": string; /** * ログインに使用される内部トークンを再生成します。通常この操作を行う必要はありません。再生成すると、全てのデバイスでログアウトされます。 */ @@ -4268,7 +4272,7 @@ export interface Locale extends ILocale { */ "rolesAssignedToMe": string; /** - * パスワードリセットしますか? + * パスワードをリセットしますか? */ "resetPasswordConfirm": string; /** @@ -5130,6 +5134,10 @@ export interface Locale extends ILocale { * このファイルをドライブに保存する */ "saveThisFile": string; + /** + * 名前を変更 + */ + "changeUserName": string; "_bubbleGame": { /** * 遊び方 @@ -8235,6 +8243,10 @@ export interface Locale extends ILocale { * ユーザーのパスワードをリセットする */ "write:admin:reset-password": string; + /** + * ユーザーのログイントークンを再生成する + */ + "write:admin:regenerate-user-token": string; /** * ユーザーからの通報を解決する */ @@ -8266,15 +8278,15 @@ export interface Locale extends ILocale { /** * ユーザーのアバターを削除する */ - "write:admin:unset-user-avatar": string; + "write:admin:user-avatar": string; /** * ユーザーのバーナーを削除する */ - "write:admin:unset-user-banner": string; + "write:admin:user-banner": string; /** * ユーザーの相互リンクを削除する */ - "write:admin:unset-user-mutual-link": string; + "write:admin:user-mutual-link": string; /** * ユーザーの凍結を解除する */ @@ -8283,6 +8295,10 @@ export interface Locale extends ILocale { * インスタンスのメタデータを操作する */ "write:admin:meta": string; + /** + * ユーザーの名前を変更する + */ + "write:admin:user-name": string; /** * モデレーションノートを操作する */ diff --git a/locales/it-IT.yml b/locales/it-IT.yml index 0a250a2e289e..e563a1779383 100644 --- a/locales/it-IT.yml +++ b/locales/it-IT.yml @@ -2027,8 +2027,8 @@ _permissions: "read:admin:show-user": "Vedere le informazioni private degli account utente" "read:admin:show-users": "Vedere le informazioni private degli account utente" "write:admin:suspend-user": "Sospendere i profili" - "write:admin:unset-user-avatar": "Rimuovere la foto profilo dai profili" - "write:admin:unset-user-banner": "Rimuovere l'immagine testata dai profili" + "write:admin:user-avatar": "Rimuovere la foto profilo dai profili" + "write:admin:user-banner": "Rimuovere l'immagine testata dai profili" "write:admin:unsuspend-user": "Togliere la sospensione ai profili" "write:admin:meta": "Modificare i metadati dell'istanza" "write:admin:user-note": "Scrivere annotazioni di moderazione" diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index b01bcd90aabc..76611df5895a 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -695,6 +695,7 @@ useGlobalSetting: "グローバル設定を使う" useGlobalSettingDesc: "オンにすると、アカウントの通知設定が使用されます。オフにすると、個別に設定できるようになります。" other: "その他" regenerateLoginToken: "ログイントークンを再生成" +regenerateLoginTokenConfirm: "ログイントークンを再生成しますか?" regenerateLoginTokenDescription: "ログインに使用される内部トークンを再生成します。通常この操作を行う必要はありません。再生成すると、全てのデバイスでログアウトされます。" theKeywordWhenSearchingForCustomEmoji: "カスタム絵文字を検索する時のキーワードになります。" setMultipleBySeparatingWithSpace: "スペースで区切って複数設定できます。" @@ -1062,7 +1063,7 @@ likeOnlyForRemote: "全て (リモートはいいねのみ)" nonSensitiveOnly: "非センシティブのみ" nonSensitiveOnlyForLocalLikeOnlyForRemote: "非センシティブのみ (リモートはいいねのみ)" rolesAssignedToMe: "自分に割り当てられたロール" -resetPasswordConfirm: "パスワードリセットしますか?" +resetPasswordConfirm: "パスワードをリセットしますか?" sensitiveWords: "センシティブワード" sensitiveWordsDescription: "設定したワードが含まれるノートの公開範囲をホームにします。改行で区切って複数設定できます。" sensitiveWordsDescription2: "スペースで区切るとAND指定になり、キーワードをスラッシュで囲むと正規表現になります。" @@ -1277,6 +1278,7 @@ muteThisUser: "このユーザーをミュートする" here: "こちら" mutualLink: "相互リンク" saveThisFile: "このファイルをドライブに保存する" +changeUserName: "名前を変更" _bubbleGame: howToPlay: "遊び方" @@ -2157,6 +2159,7 @@ _permissions: "read:admin:user-ips": "ユーザーのIPアドレスを見る" "read:admin:meta": "インスタンスのメタデータを見る" "write:admin:reset-password": "ユーザーのパスワードをリセットする" + "write:admin:regenerate-user-token": "ユーザーのログイントークンを再生成する" "write:admin:resolve-abuse-user-report": "ユーザーからの通報を解決する" "write:admin:send-email": "メールを送る" "read:admin:server-info": "サーバーの情報を見る" @@ -2164,11 +2167,12 @@ _permissions: "read:admin:show-user": "ユーザーのプライベートな情報を見る" "read:admin:show-users": "ユーザーのプライベートな情報を見る" "write:admin:suspend-user": "ユーザーを凍結する" - "write:admin:unset-user-avatar": "ユーザーのアバターを削除する" - "write:admin:unset-user-banner": "ユーザーのバーナーを削除する" - "write:admin:unset-user-mutual-link": "ユーザーの相互リンクを削除する" + "write:admin:user-avatar": "ユーザーのアバターを削除する" + "write:admin:user-banner": "ユーザーのバーナーを削除する" + "write:admin:user-mutual-link": "ユーザーの相互リンクを削除する" "write:admin:unsuspend-user": "ユーザーの凍結を解除する" "write:admin:meta": "インスタンスのメタデータを操作する" + "write:admin:user-name": "ユーザーの名前を変更する" "write:admin:user-note": "モデレーションノートを操作する" "write:admin:roles": "ロールを操作する" "read:admin:roles": "ロールを見る" diff --git a/locales/ja-KS.yml b/locales/ja-KS.yml index 301520ff5be9..1602d4f3a2dd 100644 --- a/locales/ja-KS.yml +++ b/locales/ja-KS.yml @@ -2034,8 +2034,8 @@ _permissions: "read:admin:show-user": "ユーザーのプライベートな情報見る" "read:admin:show-users": "ユーザーのプライベートな情報見る" "write:admin:suspend-user": "ユーザーを凍結" - "write:admin:unset-user-avatar": "ユーザーのアバターを削除" - "write:admin:unset-user-banner": "ユーザーのバナーを削除" + "write:admin:user-avatar": "ユーザーのアバターを削除" + "write:admin:user-banner": "ユーザーのバナーを削除" "write:admin:unsuspend-user": "ユーザーの凍結解除" "write:admin:meta": "インスタンスのメタデータいじる" "write:admin:user-note": "モデレーションノートいじる" diff --git a/locales/ko-KR.yml b/locales/ko-KR.yml index 4a6d505513cd..30daa72aa61b 100644 --- a/locales/ko-KR.yml +++ b/locales/ko-KR.yml @@ -692,6 +692,7 @@ useGlobalSetting: "글로벌 설정을 사용하기" useGlobalSettingDesc: "활성화하면 계정의 알림 설정이 적용됩니다. 비활성화하면 개별적으로 설정할 수 있게 됩니다." other: "기타" regenerateLoginToken: "로그인 토큰을 재생성" +regenerateLoginTokenConfirm: "정말 로그인 토큰을 재생성하시겠습니까? 이 작업을 실행하면 이 계정으로 로그인한 모든 기기에서 로그아웃됩니다." regenerateLoginTokenDescription: "로그인할 때 사용되는 내부 토큰을 재생성합니다. 일반적으로 이 작업을 실행할 필요는 없습니다. 이 기능을 사용하면 이 계정으로 로그인한 모든 기기에서 로그아웃됩니다." theKeywordWhenSearchingForCustomEmoji: "맞춤 이모티콘을 검색할 때 키워드가 됩니다." setMultipleBySeparatingWithSpace: "공백으로 구분하여 여러 개 설정할 수 있습니다." @@ -1261,6 +1262,7 @@ useNativeUIForVideoAudioPlayer: "브라우저 UI에서 미디어 재생" here: "여기" mutualLink: "서로링크" saveThisFile: "이 파일을 드라이브에 저장" +changeUserName: "이름 변경" _bubbleGame: howToPlay: "설명" hold: "홀드" @@ -2102,9 +2104,9 @@ _permissions: "read:admin:show-user": "사용자 개인정보 보기" "read:admin:show-users": "사용자 개인정보 보기" "write:admin:suspend-user": "사용자 정지하기" - "write:admin:unset-user-avatar": "사용자 아바타 삭제하기" - "write:admin:unset-user-banner": "사용자 배너 삭제하기" - "write:admin:unset-user-mutual-link": "사용자의 서로링크 삭제하기" + "write:admin:user-avatar": "사용자 아바타 삭제하기" + "write:admin:user-banner": "사용자 배너 삭제하기" + "write:admin:user-mutual-link": "사용자의 서로링크 삭제하기" "write:admin:unsuspend-user": "사용자 정지 해제하기" "write:admin:meta": "인스턴스 메타데이터 수정하기" "write:admin:user-note": "조정 기록 수정하기" diff --git a/locales/th-TH.yml b/locales/th-TH.yml index 020b95485475..847e5d354540 100644 --- a/locales/th-TH.yml +++ b/locales/th-TH.yml @@ -2034,8 +2034,8 @@ _permissions: "read:admin:show-user": "ดูข้อมูลส่วนตัวของผู้ใช้" "read:admin:show-users": "ดูข้อมูลส่วนตัวของผู้ใช้" "write:admin:suspend-user": "ระงับผู้ใช้" - "write:admin:unset-user-avatar": "ลบอวตารผู้ใช้" - "write:admin:unset-user-banner": "ลบแบนเนอร์ผู้ใช้" + "write:admin:user-avatar": "ลบอวตารผู้ใช้" + "write:admin:user-banner": "ลบแบนเนอร์ผู้ใช้" "write:admin:unsuspend-user": "ยกเลิกการระงับผู้ใช้" "write:admin:meta": "จัดการข้อมูลเมตาของอินสแตนซ์" "write:admin:user-note": "จัดการโน้ตการกลั่นกรอง" diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml index 4926bdf44848..25407db5e0f7 100644 --- a/locales/zh-CN.yml +++ b/locales/zh-CN.yml @@ -2052,8 +2052,8 @@ _permissions: "read:admin:show-user": "查看用户的非公开信息" "read:admin:show-users": "查看用户的非公开信息" "write:admin:suspend-user": "冻结用户" - "write:admin:unset-user-avatar": "删除用户头像" - "write:admin:unset-user-banner": "删除用户横幅" + "write:admin:user-avatar": "删除用户头像" + "write:admin:user-banner": "删除用户横幅" "write:admin:unsuspend-user": "解除用户冻结" "write:admin:meta": "编辑实例元数据" "write:admin:user-note": "编辑管理笔记" diff --git a/locales/zh-TW.yml b/locales/zh-TW.yml index 477e2131752c..2f083bb8ead6 100644 --- a/locales/zh-TW.yml +++ b/locales/zh-TW.yml @@ -2034,8 +2034,8 @@ _permissions: "read:admin:show-user": "查看使用者的私密資訊" "read:admin:show-users": "查看使用者的私密資訊" "write:admin:suspend-user": "凍結使用者" - "write:admin:unset-user-avatar": "刪除使用者的頭像" - "write:admin:unset-user-banner": "刪除使用者的橫幅" + "write:admin:user-avatar": "刪除使用者的頭像" + "write:admin:user-banner": "刪除使用者的橫幅" "write:admin:unsuspend-user": "解除凍結使用者" "write:admin:meta": "編輯實例的詮釋資料" "write:admin:user-note": "編輯審查筆記" diff --git a/packages/backend/src/server/api/EndpointsModule.ts b/packages/backend/src/server/api/EndpointsModule.ts index 1b669a31c905..7b564affeb5d 100644 --- a/packages/backend/src/server/api/EndpointsModule.ts +++ b/packages/backend/src/server/api/EndpointsModule.ts @@ -73,6 +73,7 @@ import * as ep___admin_relays_add from './endpoints/admin/relays/add.js'; import * as ep___admin_relays_list from './endpoints/admin/relays/list.js'; import * as ep___admin_relays_remove from './endpoints/admin/relays/remove.js'; import * as ep___admin_resetPassword from './endpoints/admin/reset-password.js'; +import * as ep___admin_regenerateUserToken from './endpoints/admin/regenerate-user-token.js'; import * as ep___admin_resolveAbuseUserReport from './endpoints/admin/resolve-abuse-user-report.js'; import * as ep___admin_sendEmail from './endpoints/admin/send-email.js'; import * as ep___admin_serverInfo from './endpoints/admin/server-info.js'; @@ -83,6 +84,7 @@ import * as ep___admin_showUsers from './endpoints/admin/show-users.js'; import * as ep___admin_suspendUser from './endpoints/admin/suspend-user.js'; import * as ep___admin_unsuspendUser from './endpoints/admin/unsuspend-user.js'; import * as ep___admin_updateMeta from './endpoints/admin/update-meta.js'; +import * as ep___admin_updateUserName from './endpoints/admin/update-user-name.js'; import * as ep___admin_updateUserNote from './endpoints/admin/update-user-note.js'; import * as ep___admin_roles_create from './endpoints/admin/roles/create.js'; import * as ep___admin_roles_delete from './endpoints/admin/roles/delete.js'; @@ -465,6 +467,7 @@ const $admin_relays_add: Provider = { provide: 'ep:admin/relays/add', useClass: const $admin_relays_list: Provider = { provide: 'ep:admin/relays/list', useClass: ep___admin_relays_list.default }; const $admin_relays_remove: Provider = { provide: 'ep:admin/relays/remove', useClass: ep___admin_relays_remove.default }; const $admin_resetPassword: Provider = { provide: 'ep:admin/reset-password', useClass: ep___admin_resetPassword.default }; +const $admin_regenerateUserToken: Provider = { provide: 'ep:admin/regenerate-user-token', useClass: ep___admin_regenerateUserToken.default }; const $admin_resolveAbuseUserReport: Provider = { provide: 'ep:admin/resolve-abuse-user-report', useClass: ep___admin_resolveAbuseUserReport.default }; const $admin_sendEmail: Provider = { provide: 'ep:admin/send-email', useClass: ep___admin_sendEmail.default }; const $admin_serverInfo: Provider = { provide: 'ep:admin/server-info', useClass: ep___admin_serverInfo.default }; @@ -475,6 +478,7 @@ const $admin_showUsers: Provider = { provide: 'ep:admin/show-users', useClass: e const $admin_suspendUser: Provider = { provide: 'ep:admin/suspend-user', useClass: ep___admin_suspendUser.default }; const $admin_unsuspendUser: Provider = { provide: 'ep:admin/unsuspend-user', useClass: ep___admin_unsuspendUser.default }; const $admin_updateMeta: Provider = { provide: 'ep:admin/update-meta', useClass: ep___admin_updateMeta.default }; +const $admin_updateUserName: Provider = { provide: 'ep:admin/update-user-name', useClass: ep___admin_updateUserName.default }; const $admin_updateUserNote: Provider = { provide: 'ep:admin/update-user-note', useClass: ep___admin_updateUserNote.default }; const $admin_roles_create: Provider = { provide: 'ep:admin/roles/create', useClass: ep___admin_roles_create.default }; const $admin_roles_delete: Provider = { provide: 'ep:admin/roles/delete', useClass: ep___admin_roles_delete.default }; @@ -861,6 +865,7 @@ const $reversi_verify: Provider = { provide: 'ep:reversi/verify', useClass: ep__ $admin_relays_list, $admin_relays_remove, $admin_resetPassword, + $admin_regenerateUserToken, $admin_resolveAbuseUserReport, $admin_sendEmail, $admin_serverInfo, @@ -871,6 +876,7 @@ const $reversi_verify: Provider = { provide: 'ep:reversi/verify', useClass: ep__ $admin_suspendUser, $admin_unsuspendUser, $admin_updateMeta, + $admin_updateUserName, $admin_updateUserNote, $admin_roles_create, $admin_roles_delete, @@ -1251,6 +1257,7 @@ const $reversi_verify: Provider = { provide: 'ep:reversi/verify', useClass: ep__ $admin_relays_list, $admin_relays_remove, $admin_resetPassword, + $admin_regenerateUserToken, $admin_resolveAbuseUserReport, $admin_sendEmail, $admin_serverInfo, @@ -1261,6 +1268,7 @@ const $reversi_verify: Provider = { provide: 'ep:reversi/verify', useClass: ep__ $admin_suspendUser, $admin_unsuspendUser, $admin_updateMeta, + $admin_updateUserName, $admin_updateUserNote, $admin_roles_create, $admin_roles_delete, diff --git a/packages/backend/src/server/api/endpoints.ts b/packages/backend/src/server/api/endpoints.ts index 0dc4d9ffb94a..a603a7077c74 100644 --- a/packages/backend/src/server/api/endpoints.ts +++ b/packages/backend/src/server/api/endpoints.ts @@ -73,6 +73,7 @@ import * as ep___admin_relays_add from './endpoints/admin/relays/add.js'; import * as ep___admin_relays_list from './endpoints/admin/relays/list.js'; import * as ep___admin_relays_remove from './endpoints/admin/relays/remove.js'; import * as ep___admin_resetPassword from './endpoints/admin/reset-password.js'; +import * as ep___admin_regenerateUserToken from './endpoints/admin/regenerate-user-token.js'; import * as ep___admin_resolveAbuseUserReport from './endpoints/admin/resolve-abuse-user-report.js'; import * as ep___admin_sendEmail from './endpoints/admin/send-email.js'; import * as ep___admin_serverInfo from './endpoints/admin/server-info.js'; @@ -83,6 +84,7 @@ import * as ep___admin_showUsers from './endpoints/admin/show-users.js'; import * as ep___admin_suspendUser from './endpoints/admin/suspend-user.js'; import * as ep___admin_unsuspendUser from './endpoints/admin/unsuspend-user.js'; import * as ep___admin_updateMeta from './endpoints/admin/update-meta.js'; +import * as ep___admin_updateUserName from './endpoints/admin/update-user-name.js'; import * as ep___admin_updateUserNote from './endpoints/admin/update-user-note.js'; import * as ep___admin_roles_create from './endpoints/admin/roles/create.js'; import * as ep___admin_roles_delete from './endpoints/admin/roles/delete.js'; @@ -463,6 +465,7 @@ const eps = [ ['admin/relays/list', ep___admin_relays_list], ['admin/relays/remove', ep___admin_relays_remove], ['admin/reset-password', ep___admin_resetPassword], + ['admin/regenerate-user-token', ep___admin_regenerateUserToken], ['admin/resolve-abuse-user-report', ep___admin_resolveAbuseUserReport], ['admin/send-email', ep___admin_sendEmail], ['admin/server-info', ep___admin_serverInfo], @@ -473,6 +476,7 @@ const eps = [ ['admin/suspend-user', ep___admin_suspendUser], ['admin/unsuspend-user', ep___admin_unsuspendUser], ['admin/update-meta', ep___admin_updateMeta], + ['admin/update-user-name', ep___admin_updateUserName], ['admin/update-user-note', ep___admin_updateUserNote], ['admin/roles/create', ep___admin_roles_create], ['admin/roles/delete', ep___admin_roles_delete], diff --git a/packages/backend/src/server/api/endpoints/admin/regenerate-user-token.ts b/packages/backend/src/server/api/endpoints/admin/regenerate-user-token.ts new file mode 100644 index 000000000000..97567882c73c --- /dev/null +++ b/packages/backend/src/server/api/endpoints/admin/regenerate-user-token.ts @@ -0,0 +1,61 @@ +import { Inject, Injectable } from '@nestjs/common'; +import { Endpoint } from '@/server/api/endpoint-base.js'; +import type { UsersRepository } from '@/models/_.js'; +import generateUserToken from '@/misc/generate-native-user-token.js'; +import { GlobalEventService } from '@/core/GlobalEventService.js'; +import { DI } from '@/di-symbols.js'; +import { ModerationLogService } from '@/core/ModerationLogService.js'; + +export const meta = { + tags: ['admin'], + + requireCredential: true, + requireModerator: true, + kind: 'write:admin:regenerate-user-token', +} 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 { + constructor( + @Inject(DI.usersRepository) + private usersRepository: UsersRepository, + + private globalEventService: GlobalEventService, + private moderationLogService: ModerationLogService, + ) { + super(meta, paramDef, async (ps, me) => { + const user = await this.usersRepository.findOneBy({ id: ps.userId }); + + if (user == null) { + throw new Error('user not found'); + } + + const oldToken = user.token; + if (oldToken == null) return; + + const newToken = generateUserToken(); + await this.usersRepository.update(user.id, { + token: newToken, + }); + + // Publish event + this.globalEventService.publishInternalEvent('userTokenRegenerated', { id: user.id, oldToken, newToken }); + this.globalEventService.publishMainStream(user.id, 'myTokenRegenerated'); + + this.moderationLogService.log(me, 'regenerateUserToken', { + userId: user.id, + userUsername: user.username, + userHost: user.host, + }); + }); + } +} diff --git a/packages/backend/src/server/api/endpoints/admin/unset-user-avatar.ts b/packages/backend/src/server/api/endpoints/admin/unset-user-avatar.ts index ddab6f3a9d56..89bb35c51cfe 100644 --- a/packages/backend/src/server/api/endpoints/admin/unset-user-avatar.ts +++ b/packages/backend/src/server/api/endpoints/admin/unset-user-avatar.ts @@ -14,7 +14,7 @@ export const meta = { requireCredential: true, requireModerator: true, - kind: 'write:admin:unset-user-avatar', + kind: 'write:admin:user-avatar', } as const; export const paramDef = { diff --git a/packages/backend/src/server/api/endpoints/admin/unset-user-banner.ts b/packages/backend/src/server/api/endpoints/admin/unset-user-banner.ts index e16dad719ce1..218b60a4e232 100644 --- a/packages/backend/src/server/api/endpoints/admin/unset-user-banner.ts +++ b/packages/backend/src/server/api/endpoints/admin/unset-user-banner.ts @@ -14,7 +14,7 @@ export const meta = { requireCredential: true, requireModerator: true, - kind: 'write:admin:unset-user-banner', + kind: 'write:admin:user-banner', } as const; export const paramDef = { diff --git a/packages/backend/src/server/api/endpoints/admin/unset-user-mutual-link.ts b/packages/backend/src/server/api/endpoints/admin/unset-user-mutual-link.ts index ba2674656faf..84a1ccd401aa 100644 --- a/packages/backend/src/server/api/endpoints/admin/unset-user-mutual-link.ts +++ b/packages/backend/src/server/api/endpoints/admin/unset-user-mutual-link.ts @@ -12,7 +12,7 @@ export const meta = { requireCredential: true, requireModerator: true, - kind: 'write:admin:unset-user-mutual-link', + kind: 'write:admin:user-mutual-link', } as const; export const paramDef = { diff --git a/packages/backend/src/server/api/endpoints/admin/update-user-name.ts b/packages/backend/src/server/api/endpoints/admin/update-user-name.ts new file mode 100644 index 000000000000..e95937877aa5 --- /dev/null +++ b/packages/backend/src/server/api/endpoints/admin/update-user-name.ts @@ -0,0 +1,53 @@ +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'; +import { ModerationLogService } from '@/core/ModerationLogService.js'; + +export const meta = { + tags: ['admin'], + + requireCredential: true, + requireModerator: true, + kind: 'write:admin:user-name', +} as const; + +export const paramDef = { + type: 'object', + properties: { + userId: { type: 'string', format: 'misskey:id' }, + name: { type: 'string' }, + }, + required: ['userId'], +} as const; + +// eslint-disable-next-line import/no-default-export +@Injectable() +export default class extends Endpoint { + constructor( + @Inject(DI.usersRepository) + private usersRepository: UsersRepository, + + private moderationLogService: ModerationLogService, + ) { + 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, { + name: ps.name ?? null, + }); + + this.moderationLogService.log(me, 'updateUserName', { + userId: user.id, + userUsername: user.username, + userHost: user.host, + before: user.name, + after: ps.name ?? null, + }); + }); + } +} diff --git a/packages/backend/src/types.ts b/packages/backend/src/types.ts index 2b5e901fb90e..9e595e83efcd 100644 --- a/packages/backend/src/types.ts +++ b/packages/backend/src/types.ts @@ -55,6 +55,7 @@ export const moderationLogTypes = [ 'updateServerSettings', 'suspend', 'unsuspend', + 'updateUserName', 'updateUserNote', 'addCustomEmoji', 'updateCustomEmoji', @@ -75,6 +76,7 @@ export const moderationLogTypes = [ 'deleteGlobalAnnouncement', 'deleteUserAnnouncement', 'resetPassword', + 'regenerateUserToken', 'suspendRemoteInstance', 'unsuspendRemoteInstance', 'updateRemoteInstanceNote', @@ -114,6 +116,13 @@ export type ModerationLogPayloads = { userUsername: string; userHost: string | null; }; + updateUserName: { + userId: string; + userUsername: string; + userHost: string | null; + before: string | null; + after: string | null; + }; updateUserNote: { userId: string; userUsername: string; @@ -217,6 +226,11 @@ export type ModerationLogPayloads = { userUsername: string; userHost: string | null; }; + regenerateUserToken: { + userId: string; + userUsername: string; + userHost: string | null; + }; suspendRemoteInstance: { id: string; host: string; diff --git a/packages/frontend/src/pages/admin-user.vue b/packages/frontend/src/pages/admin-user.vue index 4f339e550175..aae2b77cec3d 100644 --- a/packages/frontend/src/pages/admin-user.vue +++ b/packages/frontend/src/pages/admin-user.vue @@ -63,7 +63,11 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ i18n.ts.suspend }} - {{ i18n.ts.resetPassword }} +
+ {{ i18n.ts.resetPassword }} + {{ i18n.ts.regenerateLoginToken }} +
+ {{ i18n.ts.changeUserName }} {{ i18n.ts.unsetUserAvatar }} {{ i18n.ts.unsetUserBanner }} @@ -339,6 +343,18 @@ async function resetPassword() { } } +async function regenerateLoginToken() { + const confirm = await os.confirm({ + type: 'warning', + text: i18n.ts.regenerateLoginTokenConfirm, + }); + if (confirm.canceled) return; + + await os.apiWithDialog('admin/regenerate-user-token', { + userId: user.value.id, + }).then(refreshUser); +} + async function toggleSuspend(v) { const confirm = await os.confirm({ type: 'warning', @@ -353,6 +369,20 @@ async function toggleSuspend(v) { } } +async function updateUserName() { + const { canceled, result: name } = await os.inputText({ + type: 'text', + title: i18n.ts.enterUsername, + default: '', + }); + if (canceled) return; + + await os.apiWithDialog('admin/update-user-name', { + userId: user.value.id, + name: name || undefined, + }).then(refreshUser); +} + async function unsetUserAvatar() { const confirm = await os.confirm({ type: 'warning', diff --git a/packages/frontend/src/pages/admin/modlog.ModLog.vue b/packages/frontend/src/pages/admin/modlog.ModLog.vue index e33c88272187..7cfb3150669c 100644 --- a/packages/frontend/src/pages/admin/modlog.ModLog.vue +++ b/packages/frontend/src/pages/admin/modlog.ModLog.vue @@ -9,14 +9,19 @@ SPDX-License-Identifier: AGPL-3.0-only {{ i18n.ts._moderationLogTypes[log.type] }} : @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }} + : @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }} + : @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }} + : @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }} + : @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }} : @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }} : @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }} : @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }} + : @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }} : @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }} {{ log.info.roleName }} : @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }} {{ log.info.roleName }} : {{ log.info.role.name }} @@ -59,6 +64,12 @@ SPDX-License-Identifier: AGPL-3.0-only
+