From ac3f3ec4b8c8b467d98ed3f9ef5747276120d318 Mon Sep 17 00:00:00 2001 From: KanariKanaru <93921745+kanarikanaru@users.noreply.github.com> Date: Fri, 14 Jun 2024 04:08:49 +0900 Subject: [PATCH] =?UTF-8?q?Revert=20"feat:=20=E9=80=9A=E5=A0=B1=E3=82=92?= =?UTF-8?q?=E5=8F=97=E3=81=91=E3=81=9F=E9=9A=9B=E3=81=AB=E3=83=A1=E3=83=BC?= =?UTF-8?q?=E3=83=AB=E3=81=BE=E3=81=9F=E3=81=AFWebhook=E3=81=A7=E9=80=9A?= =?UTF-8?q?=E7=9F=A5=E3=82=92=E9=80=81=E5=87=BA=E5=87=BA=E6=9D=A5=E3=82=8B?= =?UTF-8?q?=E3=82=88=E3=81=86=E3=81=AB=E3=81=99=E3=82=8B=20(#13758)"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 61fae45390283aee7ac582aa5303aae863de0f7a. --- CHANGELOG.md | 1 - locales/index.d.ts | 94 -- locales/ja-JP.yml | 27 - ...1713656541000-abuse-report-notification.js | 62 -- .../core/AbuseReportNotificationService.ts | 406 -------- .../backend/src/core/AbuseReportService.ts | 128 --- packages/backend/src/core/CoreModule.ts | 44 +- packages/backend/src/core/EmailService.ts | 2 - .../backend/src/core/GlobalEventService.ts | 4 - .../backend/src/core/NoteCreateService.ts | 12 +- packages/backend/src/core/QueueModule.ts | 38 +- packages/backend/src/core/QueueService.ts | 63 +- packages/backend/src/core/RoleService.ts | 30 +- .../backend/src/core/SystemWebhookService.ts | 233 ----- .../backend/src/core/UserBlockingService.ts | 6 +- .../backend/src/core/UserFollowingService.ts | 12 +- .../backend/src/core/UserWebhookService.ts | 99 -- packages/backend/src/core/WebhookService.ts | 97 ++ .../src/core/activitypub/ApInboxService.ts | 10 +- ...eportNotificationRecipientEntityService.ts | 88 -- .../entities/SystemWebhookEntityService.ts | 74 -- packages/backend/src/di-symbols.ts | 2 - packages/backend/src/misc/json-schema.ts | 28 +- .../AbuseReportNotificationRecipient.ts | 100 -- .../backend/src/models/RepositoryModule.ts | 98 +- packages/backend/src/models/SystemWebhook.ts | 98 -- packages/backend/src/models/_.ts | 6 - .../abuse-report-notification-recipient.ts | 50 - .../src/models/json-schema/system-webhook.ts | 54 - packages/backend/src/postgres.ts | 8 +- .../backend/src/queue/QueueProcessorModule.ts | 6 +- .../src/queue/QueueProcessorService.ts | 153 +-- packages/backend/src/queue/const.ts | 3 +- .../SystemWebhookDeliverProcessorService.ts | 87 -- ...e.ts => WebhookDeliverProcessorService.ts} | 6 +- packages/backend/src/queue/types.ts | 12 +- .../backend/src/server/api/EndpointsModule.ts | 42 +- packages/backend/src/server/api/endpoints.ts | 38 +- .../notification-recipient/create.ts | 122 --- .../notification-recipient/delete.ts | 44 - .../notification-recipient/list.ts | 55 -- .../notification-recipient/show.ts | 64 -- .../notification-recipient/update.ts | 128 --- .../server/api/endpoints/admin/queue/stats.ts | 5 +- .../admin/resolve-abuse-user-report.ts | 53 +- .../endpoints/admin/system-webhook/create.ts | 85 -- .../endpoints/admin/system-webhook/delete.ts | 44 - .../endpoints/admin/system-webhook/list.ts | 60 -- .../endpoints/admin/system-webhook/show.ts | 62 -- .../endpoints/admin/system-webhook/update.ts | 91 -- .../api/endpoints/users/report-abuse.ts | 54 +- .../src/server/web/ClientServerService.ts | 17 +- packages/backend/src/types.ts | 32 - .../backend/test/e2e/synalio/abuse-report.ts | 401 -------- .../unit/AbuseReportNotificationService.ts | 343 ------- packages/backend/test/unit/RoleService.ts | 132 +-- .../backend/test/unit/SystemWebhookService.ts | 515 ---------- packages/frontend/src/components/MkButton.vue | 2 - .../frontend/src/components/MkDivider.vue | 32 - packages/frontend/src/components/MkSwitch.vue | 5 +- .../components/MkSystemWebhookEditor.impl.ts | 45 - .../src/components/MkSystemWebhookEditor.vue | 217 ---- .../notification-recipient.editor.vue | 307 ------ .../notification-recipient.item.vue | 114 --- .../abuse-report/notification-recipient.vue | 176 ---- packages/frontend/src/pages/admin/abuses.vue | 85 +- packages/frontend/src/pages/admin/index.vue | 5 - .../src/pages/admin/modlog.ModLog.vue | 48 +- .../src/pages/admin/system-webhook.item.vue | 117 --- .../src/pages/admin/system-webhook.vue | 96 -- packages/frontend/src/router/definition.ts | 8 - packages/misskey-js/etc/misskey-js.api.md | 105 +- .../misskey-js/src/autogen/apiClientJSDoc.ts | 120 --- packages/misskey-js/src/autogen/endpoint.ts | 28 - packages/misskey-js/src/autogen/entities.ts | 18 - packages/misskey-js/src/autogen/models.ts | 2 - packages/misskey-js/src/autogen/types.ts | 929 +++--------------- packages/misskey-js/src/consts.ts | 26 - packages/misskey-js/src/entities.ts | 19 +- 79 files changed, 487 insertions(+), 6645 deletions(-) delete mode 100644 packages/backend/migration/1713656541000-abuse-report-notification.js delete mode 100644 packages/backend/src/core/AbuseReportNotificationService.ts delete mode 100644 packages/backend/src/core/AbuseReportService.ts delete mode 100644 packages/backend/src/core/SystemWebhookService.ts delete mode 100644 packages/backend/src/core/UserWebhookService.ts create mode 100644 packages/backend/src/core/WebhookService.ts delete mode 100644 packages/backend/src/core/entities/AbuseReportNotificationRecipientEntityService.ts delete mode 100644 packages/backend/src/core/entities/SystemWebhookEntityService.ts delete mode 100644 packages/backend/src/models/AbuseReportNotificationRecipient.ts delete mode 100644 packages/backend/src/models/SystemWebhook.ts delete mode 100644 packages/backend/src/models/json-schema/abuse-report-notification-recipient.ts delete mode 100644 packages/backend/src/models/json-schema/system-webhook.ts delete mode 100644 packages/backend/src/queue/processors/SystemWebhookDeliverProcessorService.ts rename packages/backend/src/queue/processors/{UserWebhookDeliverProcessorService.ts => WebhookDeliverProcessorService.ts} (92%) delete mode 100644 packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/create.ts delete mode 100644 packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/delete.ts delete mode 100644 packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/list.ts delete mode 100644 packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/show.ts delete mode 100644 packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/update.ts delete mode 100644 packages/backend/src/server/api/endpoints/admin/system-webhook/create.ts delete mode 100644 packages/backend/src/server/api/endpoints/admin/system-webhook/delete.ts delete mode 100644 packages/backend/src/server/api/endpoints/admin/system-webhook/list.ts delete mode 100644 packages/backend/src/server/api/endpoints/admin/system-webhook/show.ts delete mode 100644 packages/backend/src/server/api/endpoints/admin/system-webhook/update.ts delete mode 100644 packages/backend/test/e2e/synalio/abuse-report.ts delete mode 100644 packages/backend/test/unit/AbuseReportNotificationService.ts delete mode 100644 packages/backend/test/unit/SystemWebhookService.ts delete mode 100644 packages/frontend/src/components/MkDivider.vue delete mode 100644 packages/frontend/src/components/MkSystemWebhookEditor.impl.ts delete mode 100644 packages/frontend/src/components/MkSystemWebhookEditor.vue delete mode 100644 packages/frontend/src/pages/admin/abuse-report/notification-recipient.editor.vue delete mode 100644 packages/frontend/src/pages/admin/abuse-report/notification-recipient.item.vue delete mode 100644 packages/frontend/src/pages/admin/abuse-report/notification-recipient.vue delete mode 100644 packages/frontend/src/pages/admin/system-webhook.item.vue delete mode 100644 packages/frontend/src/pages/admin/system-webhook.vue diff --git a/CHANGELOG.md b/CHANGELOG.md index a4d39e3eb68c..3378697bf9a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,6 @@ ## Unreleased ### General -- Feat: 通報を受けた際、または解決した際に、予め登録した宛先に通知を飛ばせるように(mail or webhook) #13705 - Fix: 配信停止したインスタンス一覧が見れなくなる問題を修正 ### Client diff --git a/locales/index.d.ts b/locales/index.d.ts index 1608b52a60b3..5d0eafafdc2e 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -9313,10 +9313,6 @@ export interface Locale extends ILocale { * Webhookを作成 */ "createWebhook": string; - /** - * Webhookを編集 - */ - "modifyWebhook": string; /** * 名前 */ @@ -9363,72 +9359,6 @@ export interface Locale extends ILocale { */ "mention": string; }; - "_systemEvents": { - /** - * ユーザーから通報があったとき - */ - "abuseReport": string; - /** - * ユーザーからの通報を処理したとき - */ - "abuseReportResolved": string; - }; - /** - * Webhookを削除しますか? - */ - "deleteConfirm": string; - }; - "_abuseReport": { - "_notificationRecipient": { - /** - * 通報の通知先を追加 - */ - "createRecipient": string; - /** - * 通報の通知先を編集 - */ - "modifyRecipient": string; - /** - * 通知先の種類 - */ - "recipientType": string; - "_recipientType": { - /** - * メール - */ - "mail": string; - /** - * Webhook - */ - "webhook": string; - "_captions": { - /** - * モデレーター権限を持つユーザーのメールアドレスに通知を送ります(通報を受けた時のみ) - */ - "mail": string; - /** - * 指定したSystemWebhookに通知を送ります(通報を受けた時と通報を解決した時にそれぞれ発信) - */ - "webhook": string; - }; - }; - /** - * キーワード - */ - "keywords": string; - /** - * 通知先ユーザー - */ - "notifiedUser": string; - /** - * 使用するWebhook - */ - "notifiedWebhook": string; - /** - * 通知先を削除しますか? - */ - "deleteConfirm": string; - }; }; "_moderationLogTypes": { /** @@ -9575,30 +9505,6 @@ export interface Locale extends ILocale { * ユーザーのバナーを解除 */ "unsetUserBanner": string; - /** - * SystemWebhookを作成 - */ - "createSystemWebhook": string; - /** - * SystemWebhookを更新 - */ - "updateSystemWebhook": string; - /** - * SystemWebhookを削除 - */ - "deleteSystemWebhook": string; - /** - * 通報の通知先を作成 - */ - "createAbuseReportNotificationRecipient": string; - /** - * 通報の通知先を更新 - */ - "updateAbuseReportNotificationRecipient": string; - /** - * 通報の通知先を削除 - */ - "deleteAbuseReportNotificationRecipient": string; }; "_fileViewer": { /** diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 96460fb467a3..5065d4329b75 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -2470,7 +2470,6 @@ _drivecleaner: _webhookSettings: createWebhook: "Webhookを作成" - modifyWebhook: "Webhookを編集" name: "名前" secret: "シークレット" events: "Webhookを実行するタイミング" @@ -2483,26 +2482,6 @@ _webhookSettings: renote: "Renoteされたとき" reaction: "リアクションがあったとき" mention: "メンションされたとき" - _systemEvents: - abuseReport: "ユーザーから通報があったとき" - abuseReportResolved: "ユーザーからの通報を処理したとき" - deleteConfirm: "Webhookを削除しますか?" - -_abuseReport: - _notificationRecipient: - createRecipient: "通報の通知先を追加" - modifyRecipient: "通報の通知先を編集" - recipientType: "通知先の種類" - _recipientType: - mail: "メール" - webhook: "Webhook" - _captions: - mail: "モデレーター権限を持つユーザーのメールアドレスに通知を送ります(通報を受けた時のみ)" - webhook: "指定したSystemWebhookに通知を送ります(通報を受けた時と通報を解決した時にそれぞれ発信)" - keywords: "キーワード" - notifiedUser: "通知先ユーザー" - notifiedWebhook: "使用するWebhook" - deleteConfirm: "通知先を削除しますか?" _moderationLogTypes: createRole: "ロールを作成" @@ -2541,12 +2520,6 @@ _moderationLogTypes: deleteAvatarDecoration: "アイコンデコレーションを削除" unsetUserAvatar: "ユーザーのアイコンを解除" unsetUserBanner: "ユーザーのバナーを解除" - createSystemWebhook: "SystemWebhookを作成" - updateSystemWebhook: "SystemWebhookを更新" - deleteSystemWebhook: "SystemWebhookを削除" - createAbuseReportNotificationRecipient: "通報の通知先を作成" - updateAbuseReportNotificationRecipient: "通報の通知先を更新" - deleteAbuseReportNotificationRecipient: "通報の通知先を削除" _fileViewer: title: "ファイルの詳細" diff --git a/packages/backend/migration/1713656541000-abuse-report-notification.js b/packages/backend/migration/1713656541000-abuse-report-notification.js deleted file mode 100644 index 4a754f81e2f5..000000000000 --- a/packages/backend/migration/1713656541000-abuse-report-notification.js +++ /dev/null @@ -1,62 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -export class AbuseReportNotification1713656541000 { - name = 'AbuseReportNotification1713656541000' - - async up(queryRunner) { - await queryRunner.query(` - CREATE TABLE "system_webhook" ( - "id" varchar(32) NOT NULL, - "isActive" boolean NOT NULL DEFAULT true, - "updatedAt" timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, - "latestSentAt" timestamp with time zone NULL DEFAULT NULL, - "latestStatus" integer NULL DEFAULT NULL, - "name" varchar(255) NOT NULL, - "on" varchar(128) [] NOT NULL DEFAULT '{}'::character varying[], - "url" varchar(1024) NOT NULL, - "secret" varchar(1024) NOT NULL, - CONSTRAINT "PK_system_webhook_id" PRIMARY KEY ("id") - ); - CREATE INDEX "IDX_system_webhook_isActive" ON "system_webhook" ("isActive"); - CREATE INDEX "IDX_system_webhook_on" ON "system_webhook" USING gin ("on"); - - CREATE TABLE "abuse_report_notification_recipient" ( - "id" varchar(32) NOT NULL, - "isActive" boolean NOT NULL DEFAULT true, - "updatedAt" timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, - "name" varchar(255) NOT NULL, - "method" varchar(64) NOT NULL, - "userId" varchar(32) NULL DEFAULT NULL, - "systemWebhookId" varchar(32) NULL DEFAULT NULL, - CONSTRAINT "PK_abuse_report_notification_recipient_id" PRIMARY KEY ("id"), - CONSTRAINT "FK_abuse_report_notification_recipient_userId1" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION, - CONSTRAINT "FK_abuse_report_notification_recipient_userId2" FOREIGN KEY ("userId") REFERENCES "user_profile"("userId") ON DELETE CASCADE ON UPDATE NO ACTION, - CONSTRAINT "FK_abuse_report_notification_recipient_systemWebhookId" FOREIGN KEY ("systemWebhookId") REFERENCES "system_webhook"("id") ON DELETE CASCADE ON UPDATE NO ACTION - ); - CREATE INDEX "IDX_abuse_report_notification_recipient_isActive" ON "abuse_report_notification_recipient" ("isActive"); - CREATE INDEX "IDX_abuse_report_notification_recipient_method" ON "abuse_report_notification_recipient" ("method"); - CREATE INDEX "IDX_abuse_report_notification_recipient_userId" ON "abuse_report_notification_recipient" ("userId"); - CREATE INDEX "IDX_abuse_report_notification_recipient_systemWebhookId" ON "abuse_report_notification_recipient" ("systemWebhookId"); - `); - } - - async down(queryRunner) { - await queryRunner.query(` - ALTER TABLE "abuse_report_notification_recipient" DROP CONSTRAINT "FK_abuse_report_notification_recipient_userId1"; - ALTER TABLE "abuse_report_notification_recipient" DROP CONSTRAINT "FK_abuse_report_notification_recipient_userId2"; - ALTER TABLE "abuse_report_notification_recipient" DROP CONSTRAINT "FK_abuse_report_notification_recipient_systemWebhookId"; - DROP INDEX "IDX_abuse_report_notification_recipient_isActive"; - DROP INDEX "IDX_abuse_report_notification_recipient_method"; - DROP INDEX "IDX_abuse_report_notification_recipient_userId"; - DROP INDEX "IDX_abuse_report_notification_recipient_systemWebhookId"; - DROP TABLE "abuse_report_notification_recipient"; - - DROP INDEX "IDX_system_webhook_isActive"; - DROP INDEX "IDX_system_webhook_on"; - DROP TABLE "system_webhook"; - `); - } -} diff --git a/packages/backend/src/core/AbuseReportNotificationService.ts b/packages/backend/src/core/AbuseReportNotificationService.ts deleted file mode 100644 index df752afcd876..000000000000 --- a/packages/backend/src/core/AbuseReportNotificationService.ts +++ /dev/null @@ -1,406 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { Inject, Injectable, type OnApplicationShutdown } from '@nestjs/common'; -import { Brackets, In, IsNull, Not } from 'typeorm'; -import * as Redis from 'ioredis'; -import sanitizeHtml from 'sanitize-html'; -import { DI } from '@/di-symbols.js'; -import { bindThis } from '@/decorators.js'; -import { GlobalEvents, GlobalEventService } from '@/core/GlobalEventService.js'; -import { isNotNull } from '@/misc/is-not-null.js'; -import type { - AbuseReportNotificationRecipientRepository, - MiAbuseReportNotificationRecipient, - MiAbuseUserReport, - MiUser, -} from '@/models/_.js'; -import { EmailService } from '@/core/EmailService.js'; -import { MetaService } from '@/core/MetaService.js'; -import { RoleService } from '@/core/RoleService.js'; -import { RecipientMethod } from '@/models/AbuseReportNotificationRecipient.js'; -import { ModerationLogService } from '@/core/ModerationLogService.js'; -import { SystemWebhookService } from '@/core/SystemWebhookService.js'; -import { IdService } from './IdService.js'; - -@Injectable() -export class AbuseReportNotificationService implements OnApplicationShutdown { - constructor( - @Inject(DI.abuseReportNotificationRecipientRepository) - private abuseReportNotificationRecipientRepository: AbuseReportNotificationRecipientRepository, - @Inject(DI.redisForSub) - private redisForSub: Redis.Redis, - private idService: IdService, - private roleService: RoleService, - private systemWebhookService: SystemWebhookService, - private emailService: EmailService, - private metaService: MetaService, - private moderationLogService: ModerationLogService, - private globalEventService: GlobalEventService, - ) { - this.redisForSub.on('message', this.onMessage); - } - - /** - * 管理者用Redisイベントを用いて{@link abuseReports}の内容を管理者各位に通知する. - * 通知先ユーザは{@link RoleService.getModeratorIds}の取得結果に依る. - * - * @see RoleService.getModeratorIds - * @see GlobalEventService.publishAdminStream - */ - @bindThis - public async notifyAdminStream(abuseReports: MiAbuseUserReport[]) { - if (abuseReports.length <= 0) { - return; - } - - const moderatorIds = await this.roleService.getModeratorIds(true, true); - - for (const moderatorId of moderatorIds) { - for (const abuseReport of abuseReports) { - this.globalEventService.publishAdminStream( - moderatorId, - 'newAbuseUserReport', - { - id: abuseReport.id, - targetUserId: abuseReport.targetUserId, - reporterId: abuseReport.reporterId, - comment: abuseReport.comment, - }, - ); - } - } - } - - /** - * Mailを用いて{@link abuseReports}の内容を管理者各位に通知する. - * メールアドレスの送信先は以下の通り. - * - モデレータ権限所有者ユーザ(設定画面からメールアドレスの設定を行っているユーザに限る) - * - metaテーブルに設定されているメールアドレス - * - * @see EmailService.sendEmail - */ - @bindThis - public async notifyMail(abuseReports: MiAbuseUserReport[]) { - if (abuseReports.length <= 0) { - return; - } - - const recipientEMailAddresses = await this.fetchEMailRecipients().then(it => it - .filter(it => it.isActive && it.userProfile?.emailVerified) - .map(it => it.userProfile?.email) - .filter(isNotNull), - ); - - // 送信先の鮮度を保つため、毎回取得する - const meta = await this.metaService.fetch(true); - recipientEMailAddresses.push( - ...(meta.email ? [meta.email] : []), - ); - - if (recipientEMailAddresses.length <= 0) { - return; - } - - for (const mailAddress of recipientEMailAddresses) { - await Promise.all( - abuseReports.map(it => { - // TODO: 送信処理はJobQueue化したい - return this.emailService.sendEmail( - mailAddress, - 'New Abuse Report', - sanitizeHtml(it.comment), - sanitizeHtml(it.comment), - ); - }), - ); - } - } - - /** - * SystemWebhookを用いて{@link abuseReports}の内容を管理者各位に通知する. - * ここではJobQueueへのエンキューのみを行うため、即時実行されない. - * - * @see SystemWebhookService.enqueueSystemWebhook - */ - @bindThis - public async notifySystemWebhook( - abuseReports: MiAbuseUserReport[], - type: 'abuseReport' | 'abuseReportResolved', - ) { - if (abuseReports.length <= 0) { - return; - } - - const recipientWebhookIds = await this.fetchWebhookRecipients() - .then(it => it - .filter(it => it.isActive && it.systemWebhookId && it.method === 'webhook') - .map(it => it.systemWebhookId) - .filter(isNotNull)); - for (const webhookId of recipientWebhookIds) { - await Promise.all( - abuseReports.map(it => { - return this.systemWebhookService.enqueueSystemWebhook( - webhookId, - type, - it, - ); - }), - ); - } - } - - /** - * 通報の通知先一覧を取得する. - * - * @param {Object} [params] クエリの取得条件 - * @param {Object} [params.method] 取得する通知先の通知方法 - * @param {Object} [opts] 動作時の詳細なオプション - * @param {boolean} [opts.removeUnauthorized] 副作用としてモデレータ権限を持たない送信先ユーザをDBから削除するかどうか(default: true) - * @param {boolean} [opts.joinUser] 通知先のユーザ情報をJOINするかどうか(default: false) - * @param {boolean} [opts.joinSystemWebhook] 通知先のSystemWebhook情報をJOINするかどうか(default: false) - * @see removeUnauthorizedRecipientUsers - */ - @bindThis - public async fetchRecipients( - params?: { - ids?: MiAbuseReportNotificationRecipient['id'][], - method?: RecipientMethod[], - }, - opts?: { - removeUnauthorized?: boolean, - joinUser?: boolean, - joinSystemWebhook?: boolean, - }, - ): Promise { - const query = this.abuseReportNotificationRecipientRepository.createQueryBuilder('recipient'); - - if (opts?.joinUser) { - query.innerJoinAndSelect('user', 'user', 'recipient.userId = user.id'); - query.innerJoinAndSelect('recipient.userProfile', 'userProfile'); - } - - if (opts?.joinSystemWebhook) { - query.innerJoinAndSelect('recipient.systemWebhook', 'systemWebhook'); - } - - if (params?.ids) { - query.andWhere({ id: In(params.ids) }); - } - - if (params?.method) { - query.andWhere(new Brackets(qb => { - if (params.method?.includes('email')) { - qb.orWhere({ method: 'email', userId: Not(IsNull()) }); - } - if (params.method?.includes('webhook')) { - qb.orWhere({ method: 'webhook', userId: IsNull() }); - } - })); - } - - const recipients = await query.getMany(); - if (recipients.length <= 0) { - return []; - } - - // アサイン有効期限切れはイベントで拾えないので、このタイミングでチェック及び削除(オプション) - return (opts?.removeUnauthorized ?? true) - ? await this.removeUnauthorizedRecipientUsers(recipients) - : recipients; - } - - /** - * EMailの通知先一覧を取得する. - * リレーション先の{@link MiUser}および{@link MiUserProfile}も同時に取得する. - * - * @param {Object} [opts] - * @param {boolean} [opts.removeUnauthorized] 副作用としてモデレータ権限を持たない送信先ユーザをDBから削除するかどうか(default: true) - * @see removeUnauthorizedRecipientUsers - */ - @bindThis - public async fetchEMailRecipients(opts?: { - removeUnauthorized?: boolean - }): Promise { - return this.fetchRecipients({ method: ['email'] }, { joinUser: true, ...opts }); - } - - /** - * Webhookの通知先一覧を取得する. - * リレーション先の{@link MiSystemWebhook}も同時に取得する. - */ - @bindThis - public fetchWebhookRecipients(): Promise { - return this.fetchRecipients({ method: ['webhook'] }, { joinSystemWebhook: true }); - } - - /** - * 通知先を作成する. - */ - @bindThis - public async createRecipient( - params: { - isActive: MiAbuseReportNotificationRecipient['isActive']; - name: MiAbuseReportNotificationRecipient['name']; - method: MiAbuseReportNotificationRecipient['method']; - userId: MiAbuseReportNotificationRecipient['userId']; - systemWebhookId: MiAbuseReportNotificationRecipient['systemWebhookId']; - }, - updater: MiUser, - ): Promise { - const id = this.idService.gen(); - await this.abuseReportNotificationRecipientRepository.insert({ - ...params, - id, - }); - - const created = await this.abuseReportNotificationRecipientRepository.findOneByOrFail({ id: id }); - - this.moderationLogService - .log(updater, 'createAbuseReportNotificationRecipient', { - recipientId: id, - recipient: created, - }) - .then(); - - return created; - } - - /** - * 通知先を更新する. - */ - @bindThis - public async updateRecipient( - params: { - id: MiAbuseReportNotificationRecipient['id']; - isActive: MiAbuseReportNotificationRecipient['isActive']; - name: MiAbuseReportNotificationRecipient['name']; - method: MiAbuseReportNotificationRecipient['method']; - userId: MiAbuseReportNotificationRecipient['userId']; - systemWebhookId: MiAbuseReportNotificationRecipient['systemWebhookId']; - }, - updater: MiUser, - ): Promise { - const beforeEntity = await this.abuseReportNotificationRecipientRepository.findOneByOrFail({ id: params.id }); - - await this.abuseReportNotificationRecipientRepository.update(params.id, { - isActive: params.isActive, - updatedAt: new Date(), - name: params.name, - method: params.method, - userId: params.userId, - systemWebhookId: params.systemWebhookId, - }); - - const afterEntity = await this.abuseReportNotificationRecipientRepository.findOneByOrFail({ id: params.id }); - - this.moderationLogService - .log(updater, 'updateAbuseReportNotificationRecipient', { - recipientId: params.id, - before: beforeEntity, - after: afterEntity, - }) - .then(); - - return afterEntity; - } - - /** - * 通知先を削除する. - */ - @bindThis - public async deleteRecipient( - id: MiAbuseReportNotificationRecipient['id'], - updater: MiUser, - ) { - const entity = await this.abuseReportNotificationRecipientRepository.findBy({ id }); - - await this.abuseReportNotificationRecipientRepository.delete(id); - - this.moderationLogService - .log(updater, 'deleteAbuseReportNotificationRecipient', { - recipientId: id, - recipient: entity, - }) - .then(); - } - - /** - * モデレータ権限を持たない(*1)通知先ユーザを削除する. - * - * *1: 以下の両方を満たすものの事を言う - * - 通知先にユーザIDが設定されている - * - 付与ロールにモデレータ権限がない or アサインの有効期限が切れている - * - * @param recipients 通知先一覧の配列 - * @returns {@lisk recipients}からモデレータ権限を持たない通知先を削除した配列 - */ - @bindThis - private async removeUnauthorizedRecipientUsers(recipients: MiAbuseReportNotificationRecipient[]): Promise { - const userRecipients = recipients.filter(it => it.userId !== null); - const recipientUserIds = new Set(userRecipients.map(it => it.userId).filter(isNotNull)); - if (recipientUserIds.size <= 0) { - // ユーザが通知先として設定されていない場合、この関数での処理を行うべきレコードが無い - return recipients; - } - - // モデレータ権限の有無で通知先設定を振り分ける - const authorizedUserIds = await this.roleService.getModeratorIds(true, true); - const authorizedUserRecipients = Array.of(); - const unauthorizedUserRecipients = Array.of(); - for (const recipient of userRecipients) { - // eslint-disable-next-line - if (authorizedUserIds.includes(recipient.userId!)) { - authorizedUserRecipients.push(recipient); - } else { - unauthorizedUserRecipients.push(recipient); - } - } - - // モデレータ権限を持たない通知先をDBから削除する - if (unauthorizedUserRecipients.length > 0) { - await this.abuseReportNotificationRecipientRepository.delete(unauthorizedUserRecipients.map(it => it.id)); - } - const nonUserRecipients = recipients.filter(it => it.userId === null); - return [...nonUserRecipients, ...authorizedUserRecipients].sort((a, b) => a.id.localeCompare(b.id)); - } - - @bindThis - private async onMessage(_: string, data: string): Promise { - const obj = JSON.parse(data); - if (obj.channel !== 'internal') { - return; - } - - const { type } = obj.message as GlobalEvents['internal']['payload']; - switch (type) { - case 'roleUpdated': - case 'roleDeleted': - case 'userRoleUnassigned': { - // 場合によってはキャッシュ更新よりも先にここが呼ばれてしまう可能性があるのでnextTickで遅延実行 - process.nextTick(async () => { - const recipients = await this.abuseReportNotificationRecipientRepository.findBy({ - userId: Not(IsNull()), - }); - await this.removeUnauthorizedRecipientUsers(recipients); - }); - break; - } - default: { - break; - } - } - } - - @bindThis - public dispose(): void { - this.redisForSub.off('message', this.onMessage); - } - - @bindThis - public onApplicationShutdown(signal?: string | undefined): void { - this.dispose(); - } -} diff --git a/packages/backend/src/core/AbuseReportService.ts b/packages/backend/src/core/AbuseReportService.ts deleted file mode 100644 index 69c51509ba40..000000000000 --- a/packages/backend/src/core/AbuseReportService.ts +++ /dev/null @@ -1,128 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { Inject, Injectable } from '@nestjs/common'; -import { In } from 'typeorm'; -import { DI } from '@/di-symbols.js'; -import { bindThis } from '@/decorators.js'; -import type { AbuseUserReportsRepository, MiAbuseUserReport, MiUser, UsersRepository } from '@/models/_.js'; -import { AbuseReportNotificationService } from '@/core/AbuseReportNotificationService.js'; -import { QueueService } from '@/core/QueueService.js'; -import { InstanceActorService } from '@/core/InstanceActorService.js'; -import { ApRendererService } from '@/core/activitypub/ApRendererService.js'; -import { ModerationLogService } from '@/core/ModerationLogService.js'; -import { IdService } from './IdService.js'; - -@Injectable() -export class AbuseReportService { - constructor( - @Inject(DI.abuseUserReportsRepository) - private abuseUserReportsRepository: AbuseUserReportsRepository, - @Inject(DI.usersRepository) - private usersRepository: UsersRepository, - private idService: IdService, - private abuseReportNotificationService: AbuseReportNotificationService, - private queueService: QueueService, - private instanceActorService: InstanceActorService, - private apRendererService: ApRendererService, - private moderationLogService: ModerationLogService, - ) { - } - - /** - * ユーザからの通報をDBに記録し、その内容を下記の手段で管理者各位に通知する. - * - 管理者用Redisイベント - * - EMail(モデレータ権限所有者ユーザ+metaテーブルに設定されているメールアドレス) - * - SystemWebhook - * - * @param params 通報内容. もし複数件の通報に対応した時のために、あらかじめ複数件を処理できる前提で考える - * @see AbuseReportNotificationService.notify - */ - @bindThis - public async report(params: { - targetUserId: MiAbuseUserReport['targetUserId'], - targetUserHost: MiAbuseUserReport['targetUserHost'], - reporterId: MiAbuseUserReport['reporterId'], - reporterHost: MiAbuseUserReport['reporterHost'], - comment: string, - }[]) { - const entities = params.map(param => { - return { - id: this.idService.gen(), - targetUserId: param.targetUserId, - targetUserHost: param.targetUserHost, - reporterId: param.reporterId, - reporterHost: param.reporterHost, - comment: param.comment, - }; - }); - - const reports = Array.of(); - for (const entity of entities) { - const report = await this.abuseUserReportsRepository.insertOne(entity); - reports.push(report); - } - - return Promise.all([ - this.abuseReportNotificationService.notifyAdminStream(reports), - this.abuseReportNotificationService.notifySystemWebhook(reports, 'abuseReport'), - this.abuseReportNotificationService.notifyMail(reports), - ]); - } - - /** - * 通報を解決し、その内容を下記の手段で管理者各位に通知する. - * - SystemWebhook - * - * @param params 通報内容. もし複数件の通報に対応した時のために、あらかじめ複数件を処理できる前提で考える - * @param operator 通報を処理したユーザ - * @see AbuseReportNotificationService.notify - */ - @bindThis - public async resolve( - params: { - reportId: string; - forward: boolean; - }[], - operator: MiUser, - ) { - const paramsMap = new Map(params.map(it => [it.reportId, it])); - const reports = await this.abuseUserReportsRepository.findBy({ - id: In(params.map(it => it.reportId)), - }); - - for (const report of reports) { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const ps = paramsMap.get(report.id)!; - - await this.abuseUserReportsRepository.update(report.id, { - resolved: true, - assigneeId: operator.id, - forwarded: ps.forward && report.targetUserHost !== null, - }); - - if (ps.forward && report.targetUserHost != null) { - const actor = await this.instanceActorService.getInstanceActor(); - const targetUser = await this.usersRepository.findOneByOrFail({ id: report.targetUserId }); - - // eslint-disable-next-line - const flag = this.apRendererService.renderFlag(actor, targetUser.uri!, report.comment); - const contextAssignedFlag = this.apRendererService.addContext(flag); - this.queueService.deliver(actor, contextAssignedFlag, targetUser.inbox, false); - } - - this.moderationLogService - .log(operator, 'resolveAbuseReport', { - reportId: report.id, - report: report, - forwarded: ps.forward && report.targetUserHost !== null, - }) - .then(); - } - - return this.abuseUserReportsRepository.findBy({ id: In(reports.map(it => it.id)) }) - .then(reports => this.abuseReportNotificationService.notifySystemWebhook(reports, 'abuseReportResolved')); - } -} diff --git a/packages/backend/src/core/CoreModule.ts b/packages/backend/src/core/CoreModule.ts index b5b34487ec81..be80df6f1cf1 100644 --- a/packages/backend/src/core/CoreModule.ts +++ b/packages/backend/src/core/CoreModule.ts @@ -5,13 +5,6 @@ import { Module } from '@nestjs/common'; import { FanoutTimelineEndpointService } from '@/core/FanoutTimelineEndpointService.js'; -import { AbuseReportService } from '@/core/AbuseReportService.js'; -import { SystemWebhookEntityService } from '@/core/entities/SystemWebhookEntityService.js'; -import { - AbuseReportNotificationRecipientEntityService, -} from '@/core/entities/AbuseReportNotificationRecipientEntityService.js'; -import { AbuseReportNotificationService } from '@/core/AbuseReportNotificationService.js'; -import { SystemWebhookService } from '@/core/SystemWebhookService.js'; import { AccountMoveService } from './AccountMoveService.js'; import { AccountUpdateService } from './AccountUpdateService.js'; import { AiService } from './AiService.js'; @@ -63,7 +56,7 @@ import { UserMutingService } from './UserMutingService.js'; import { UserSuspendService } from './UserSuspendService.js'; import { UserAuthService } from './UserAuthService.js'; import { VideoProcessingService } from './VideoProcessingService.js'; -import { UserWebhookService } from './UserWebhookService.js'; +import { WebhookService } from './WebhookService.js'; import { ProxyAccountService } from './ProxyAccountService.js'; import { UtilityService } from './UtilityService.js'; import { FileInfoService } from './FileInfoService.js'; @@ -151,8 +144,6 @@ import type { Provider } from '@nestjs/common'; //#region 文字列ベースでのinjection用(循環参照対応のため) const $LoggerService: Provider = { provide: 'LoggerService', useExisting: LoggerService }; -const $AbuseReportService: Provider = { provide: 'AbuseReportService', useExisting: AbuseReportService }; -const $AbuseReportNotificationService: Provider = { provide: 'AbuseReportNotificationService', useExisting: AbuseReportNotificationService }; const $AccountMoveService: Provider = { provide: 'AccountMoveService', useExisting: AccountMoveService }; const $AccountUpdateService: Provider = { provide: 'AccountUpdateService', useExisting: AccountUpdateService }; const $AiService: Provider = { provide: 'AiService', useExisting: AiService }; @@ -205,8 +196,7 @@ const $UserMutingService: Provider = { provide: 'UserMutingService', useExisting const $UserSuspendService: Provider = { provide: 'UserSuspendService', useExisting: UserSuspendService }; const $UserAuthService: Provider = { provide: 'UserAuthService', useExisting: UserAuthService }; const $VideoProcessingService: Provider = { provide: 'VideoProcessingService', useExisting: VideoProcessingService }; -const $UserWebhookService: Provider = { provide: 'UserWebhookService', useExisting: UserWebhookService }; -const $SystemWebhookService: Provider = { provide: 'SystemWebhookService', useExisting: SystemWebhookService }; +const $WebhookService: Provider = { provide: 'WebhookService', useExisting: WebhookService }; const $UtilityService: Provider = { provide: 'UtilityService', useExisting: UtilityService }; const $FileInfoService: Provider = { provide: 'FileInfoService', useExisting: FileInfoService }; const $SearchService: Provider = { provide: 'SearchService', useExisting: SearchService }; @@ -235,7 +225,6 @@ const $ChartManagementService: Provider = { provide: 'ChartManagementService', u const $AbuseUserReportEntityService: Provider = { provide: 'AbuseUserReportEntityService', useExisting: AbuseUserReportEntityService }; const $AnnouncementEntityService: Provider = { provide: 'AnnouncementEntityService', useExisting: AnnouncementEntityService }; -const $AbuseReportNotificationRecipientEntityService: Provider = { provide: 'AbuseReportNotificationRecipientEntityService', useExisting: AbuseReportNotificationRecipientEntityService }; const $AntennaEntityService: Provider = { provide: 'AntennaEntityService', useExisting: AntennaEntityService }; const $AppEntityService: Provider = { provide: 'AppEntityService', useExisting: AppEntityService }; const $AuthSessionEntityService: Provider = { provide: 'AuthSessionEntityService', useExisting: AuthSessionEntityService }; @@ -269,7 +258,6 @@ const $FlashLikeEntityService: Provider = { provide: 'FlashLikeEntityService', u const $RoleEntityService: Provider = { provide: 'RoleEntityService', useExisting: RoleEntityService }; const $ReversiGameEntityService: Provider = { provide: 'ReversiGameEntityService', useExisting: ReversiGameEntityService }; const $MetaEntityService: Provider = { provide: 'MetaEntityService', useExisting: MetaEntityService }; -const $SystemWebhookEntityService: Provider = { provide: 'SystemWebhookEntityService', useExisting: SystemWebhookEntityService }; const $ApAudienceService: Provider = { provide: 'ApAudienceService', useExisting: ApAudienceService }; const $ApDbResolverService: Provider = { provide: 'ApDbResolverService', useExisting: ApDbResolverService }; @@ -297,8 +285,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting ], providers: [ LoggerService, - AbuseReportService, - AbuseReportNotificationService, AccountMoveService, AccountUpdateService, AiService, @@ -351,8 +337,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting UserSuspendService, UserAuthService, VideoProcessingService, - UserWebhookService, - SystemWebhookService, + WebhookService, UtilityService, FileInfoService, SearchService, @@ -381,7 +366,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting AbuseUserReportEntityService, AnnouncementEntityService, - AbuseReportNotificationRecipientEntityService, AntennaEntityService, AppEntityService, AuthSessionEntityService, @@ -415,7 +399,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting RoleEntityService, ReversiGameEntityService, MetaEntityService, - SystemWebhookEntityService, ApAudienceService, ApDbResolverService, @@ -439,8 +422,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting //#region 文字列ベースでのinjection用(循環参照対応のため) $LoggerService, - $AbuseReportService, - $AbuseReportNotificationService, $AccountMoveService, $AccountUpdateService, $AiService, @@ -493,8 +474,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting $UserSuspendService, $UserAuthService, $VideoProcessingService, - $UserWebhookService, - $SystemWebhookService, + $WebhookService, $UtilityService, $FileInfoService, $SearchService, @@ -523,7 +503,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting $AbuseUserReportEntityService, $AnnouncementEntityService, - $AbuseReportNotificationRecipientEntityService, $AntennaEntityService, $AppEntityService, $AuthSessionEntityService, @@ -557,7 +536,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting $RoleEntityService, $ReversiGameEntityService, $MetaEntityService, - $SystemWebhookEntityService, $ApAudienceService, $ApDbResolverService, @@ -582,8 +560,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting exports: [ QueueModule, LoggerService, - AbuseReportService, - AbuseReportNotificationService, AccountMoveService, AccountUpdateService, AiService, @@ -636,8 +612,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting UserSuspendService, UserAuthService, VideoProcessingService, - UserWebhookService, - SystemWebhookService, + WebhookService, UtilityService, FileInfoService, SearchService, @@ -665,7 +640,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting AbuseUserReportEntityService, AnnouncementEntityService, - AbuseReportNotificationRecipientEntityService, AntennaEntityService, AppEntityService, AuthSessionEntityService, @@ -699,7 +673,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting RoleEntityService, ReversiGameEntityService, MetaEntityService, - SystemWebhookEntityService, ApAudienceService, ApDbResolverService, @@ -723,8 +696,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting //#region 文字列ベースでのinjection用(循環参照対応のため) $LoggerService, - $AbuseReportService, - $AbuseReportNotificationService, $AccountMoveService, $AccountUpdateService, $AiService, @@ -777,8 +748,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting $UserSuspendService, $UserAuthService, $VideoProcessingService, - $UserWebhookService, - $SystemWebhookService, + $WebhookService, $UtilityService, $FileInfoService, $SearchService, @@ -806,7 +776,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting $AbuseUserReportEntityService, $AnnouncementEntityService, - $AbuseReportNotificationRecipientEntityService, $AntennaEntityService, $AppEntityService, $AuthSessionEntityService, @@ -840,7 +809,6 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting $RoleEntityService, $ReversiGameEntityService, $MetaEntityService, - $SystemWebhookEntityService, $ApAudienceService, $ApDbResolverService, diff --git a/packages/backend/src/core/EmailService.ts b/packages/backend/src/core/EmailService.ts index 435dbbae28a9..08f8f80a6ed9 100644 --- a/packages/backend/src/core/EmailService.ts +++ b/packages/backend/src/core/EmailService.ts @@ -16,7 +16,6 @@ import type { UserProfilesRepository } from '@/models/_.js'; import { LoggerService } from '@/core/LoggerService.js'; import { bindThis } from '@/decorators.js'; import { HttpRequestService } from '@/core/HttpRequestService.js'; -import { QueueService } from '@/core/QueueService.js'; @Injectable() export class EmailService { @@ -33,7 +32,6 @@ export class EmailService { private loggerService: LoggerService, private utilityService: UtilityService, private httpRequestService: HttpRequestService, - private queueService: QueueService, ) { this.logger = this.loggerService.getLogger('email'); } diff --git a/packages/backend/src/core/GlobalEventService.ts b/packages/backend/src/core/GlobalEventService.ts index a70743bed203..90efd63f3a05 100644 --- a/packages/backend/src/core/GlobalEventService.ts +++ b/packages/backend/src/core/GlobalEventService.ts @@ -18,7 +18,6 @@ import type { MiAbuseUserReport } from '@/models/AbuseUserReport.js'; import type { MiSignin } from '@/models/Signin.js'; import type { MiPage } from '@/models/Page.js'; import type { MiWebhook } from '@/models/Webhook.js'; -import type { MiSystemWebhook } from '@/models/SystemWebhook.js'; import type { MiMeta } from '@/models/Meta.js'; import { MiAvatarDecoration, MiReversiGame, MiRole, MiRoleAssignment } from '@/models/_.js'; import type { Packed } from '@/misc/json-schema.js'; @@ -228,9 +227,6 @@ export interface InternalEventTypes { webhookCreated: MiWebhook; webhookDeleted: MiWebhook; webhookUpdated: MiWebhook; - systemWebhookCreated: MiSystemWebhook; - systemWebhookDeleted: MiSystemWebhook; - systemWebhookUpdated: MiSystemWebhook; antennaCreated: MiAntenna; antennaDeleted: MiAntenna; antennaUpdated: MiAntenna; diff --git a/packages/backend/src/core/NoteCreateService.ts b/packages/backend/src/core/NoteCreateService.ts index ef3b5229d015..06818a6db96e 100644 --- a/packages/backend/src/core/NoteCreateService.ts +++ b/packages/backend/src/core/NoteCreateService.ts @@ -38,7 +38,7 @@ import InstanceChart from '@/core/chart/charts/instance.js'; import ActiveUsersChart from '@/core/chart/charts/active-users.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { NotificationService } from '@/core/NotificationService.js'; -import { UserWebhookService } from '@/core/UserWebhookService.js'; +import { WebhookService } from '@/core/WebhookService.js'; import { HashtagService } from '@/core/HashtagService.js'; import { AntennaService } from '@/core/AntennaService.js'; import { QueueService } from '@/core/QueueService.js'; @@ -205,7 +205,7 @@ export class NoteCreateService implements OnApplicationShutdown { private federatedInstanceService: FederatedInstanceService, private hashtagService: HashtagService, private antennaService: AntennaService, - private webhookService: UserWebhookService, + private webhookService: WebhookService, private featuredService: FeaturedService, private remoteUserResolveService: RemoteUserResolveService, private apDeliverManagerService: ApDeliverManagerService, @@ -611,7 +611,7 @@ export class NoteCreateService implements OnApplicationShutdown { this.webhookService.getActiveWebhooks().then(webhooks => { webhooks = webhooks.filter(x => x.userId === user.id && x.on.includes('note')); for (const webhook of webhooks) { - this.queueService.userWebhookDeliver(webhook, 'note', { + this.queueService.webhookDeliver(webhook, 'note', { note: noteObj, }); } @@ -638,7 +638,7 @@ export class NoteCreateService implements OnApplicationShutdown { const webhooks = (await this.webhookService.getActiveWebhooks()).filter(x => x.userId === data.reply!.userId && x.on.includes('reply')); for (const webhook of webhooks) { - this.queueService.userWebhookDeliver(webhook, 'reply', { + this.queueService.webhookDeliver(webhook, 'reply', { note: noteObj, }); } @@ -661,7 +661,7 @@ export class NoteCreateService implements OnApplicationShutdown { const webhooks = (await this.webhookService.getActiveWebhooks()).filter(x => x.userId === data.renote!.userId && x.on.includes('renote')); for (const webhook of webhooks) { - this.queueService.userWebhookDeliver(webhook, 'renote', { + this.queueService.webhookDeliver(webhook, 'renote', { note: noteObj, }); } @@ -793,7 +793,7 @@ export class NoteCreateService implements OnApplicationShutdown { const webhooks = (await this.webhookService.getActiveWebhooks()).filter(x => x.userId === u.id && x.on.includes('mention')); for (const webhook of webhooks) { - this.queueService.userWebhookDeliver(webhook, 'mention', { + this.queueService.webhookDeliver(webhook, 'mention', { note: detailPackedNote, }); } diff --git a/packages/backend/src/core/QueueModule.ts b/packages/backend/src/core/QueueModule.ts index b10b8e589955..216734e9e5e4 100644 --- a/packages/backend/src/core/QueueModule.ts +++ b/packages/backend/src/core/QueueModule.ts @@ -7,17 +7,10 @@ import { Inject, Module, OnApplicationShutdown } from '@nestjs/common'; import * as Bull from 'bullmq'; import { DI } from '@/di-symbols.js'; import type { Config } from '@/config.js'; -import { baseQueueOptions, QUEUE } from '@/queue/const.js'; +import { QUEUE, baseQueueOptions } from '@/queue/const.js'; import { allSettled } from '@/misc/promise-tracker.js'; -import { - DeliverJobData, - EndedPollNotificationJobData, - InboxJobData, - RelationshipJobData, - UserWebhookDeliverJobData, - SystemWebhookDeliverJobData, -} from '../queue/types.js'; import type { Provider } from '@nestjs/common'; +import type { DeliverJobData, InboxJobData, EndedPollNotificationJobData, WebhookDeliverJobData, RelationshipJobData } from '../queue/types.js'; export type SystemQueue = Bull.Queue>; export type EndedPollNotificationQueue = Bull.Queue; @@ -26,8 +19,7 @@ export type InboxQueue = Bull.Queue; export type DbQueue = Bull.Queue; export type RelationshipQueue = Bull.Queue; export type ObjectStorageQueue = Bull.Queue; -export type UserWebhookDeliverQueue = Bull.Queue; -export type SystemWebhookDeliverQueue = Bull.Queue; +export type WebhookDeliverQueue = Bull.Queue; const $system: Provider = { provide: 'queue:system', @@ -71,15 +63,9 @@ const $objectStorage: Provider = { inject: [DI.config], }; -const $userWebhookDeliver: Provider = { - provide: 'queue:userWebhookDeliver', - useFactory: (config: Config) => new Bull.Queue(QUEUE.USER_WEBHOOK_DELIVER, baseQueueOptions(config, QUEUE.USER_WEBHOOK_DELIVER)), - inject: [DI.config], -}; - -const $systemWebhookDeliver: Provider = { - provide: 'queue:systemWebhookDeliver', - useFactory: (config: Config) => new Bull.Queue(QUEUE.SYSTEM_WEBHOOK_DELIVER, baseQueueOptions(config, QUEUE.SYSTEM_WEBHOOK_DELIVER)), +const $webhookDeliver: Provider = { + provide: 'queue:webhookDeliver', + useFactory: (config: Config) => new Bull.Queue(QUEUE.WEBHOOK_DELIVER, baseQueueOptions(config, QUEUE.WEBHOOK_DELIVER)), inject: [DI.config], }; @@ -94,8 +80,7 @@ const $systemWebhookDeliver: Provider = { $db, $relationship, $objectStorage, - $userWebhookDeliver, - $systemWebhookDeliver, + $webhookDeliver, ], exports: [ $system, @@ -105,8 +90,7 @@ const $systemWebhookDeliver: Provider = { $db, $relationship, $objectStorage, - $userWebhookDeliver, - $systemWebhookDeliver, + $webhookDeliver, ], }) export class QueueModule implements OnApplicationShutdown { @@ -118,8 +102,7 @@ export class QueueModule implements OnApplicationShutdown { @Inject('queue:db') public dbQueue: DbQueue, @Inject('queue:relationship') public relationshipQueue: RelationshipQueue, @Inject('queue:objectStorage') public objectStorageQueue: ObjectStorageQueue, - @Inject('queue:userWebhookDeliver') public userWebhookDeliverQueue: UserWebhookDeliverQueue, - @Inject('queue:systemWebhookDeliver') public systemWebhookDeliverQueue: SystemWebhookDeliverQueue, + @Inject('queue:webhookDeliver') public webhookDeliverQueue: WebhookDeliverQueue, ) {} public async dispose(): Promise { @@ -134,8 +117,7 @@ export class QueueModule implements OnApplicationShutdown { this.dbQueue.close(), this.relationshipQueue.close(), this.objectStorageQueue.close(), - this.userWebhookDeliverQueue.close(), - this.systemWebhookDeliverQueue.close(), + this.webhookDeliverQueue.close(), ]); } diff --git a/packages/backend/src/core/QueueService.ts b/packages/backend/src/core/QueueService.ts index 80827a500b56..c258a22927d4 100644 --- a/packages/backend/src/core/QueueService.ts +++ b/packages/backend/src/core/QueueService.ts @@ -8,33 +8,15 @@ import { Inject, Injectable } from '@nestjs/common'; import type { IActivity } from '@/core/activitypub/type.js'; import type { MiDriveFile } from '@/models/DriveFile.js'; import type { MiWebhook, webhookEventTypes } from '@/models/Webhook.js'; -import type { MiSystemWebhook, SystemWebhookEventType } from '@/models/SystemWebhook.js'; import type { Config } from '@/config.js'; import { DI } from '@/di-symbols.js'; import { bindThis } from '@/decorators.js'; import type { Antenna } from '@/server/api/endpoints/i/import-antennas.js'; -import { ApRequestCreator } from '@/core/activitypub/ApRequestService.js'; -import type { - DbJobData, - DeliverJobData, - RelationshipJobData, - SystemWebhookDeliverJobData, - ThinUser, - UserWebhookDeliverJobData, -} from '../queue/types.js'; -import type { - DbQueue, - DeliverQueue, - EndedPollNotificationQueue, - InboxQueue, - ObjectStorageQueue, - RelationshipQueue, - SystemQueue, - UserWebhookDeliverQueue, - SystemWebhookDeliverQueue, -} from './QueueModule.js'; +import type { DbQueue, DeliverQueue, EndedPollNotificationQueue, InboxQueue, ObjectStorageQueue, RelationshipQueue, SystemQueue, WebhookDeliverQueue } from './QueueModule.js'; +import type { DbJobData, DeliverJobData, RelationshipJobData, ThinUser } from '../queue/types.js'; import type httpSignature from '@peertube/http-signature'; import type * as Bull from 'bullmq'; +import { ApRequestCreator } from '@/core/activitypub/ApRequestService.js'; @Injectable() export class QueueService { @@ -49,8 +31,7 @@ export class QueueService { @Inject('queue:db') public dbQueue: DbQueue, @Inject('queue:relationship') public relationshipQueue: RelationshipQueue, @Inject('queue:objectStorage') public objectStorageQueue: ObjectStorageQueue, - @Inject('queue:userWebhookDeliver') public userWebhookDeliverQueue: UserWebhookDeliverQueue, - @Inject('queue:systemWebhookDeliver') public systemWebhookDeliverQueue: SystemWebhookDeliverQueue, + @Inject('queue:webhookDeliver') public webhookDeliverQueue: WebhookDeliverQueue, ) { this.systemQueue.add('tickCharts', { }, { @@ -450,13 +431,9 @@ export class QueueService { }); } - /** - * @see UserWebhookDeliverJobData - * @see WebhookDeliverProcessorService - */ @bindThis - public userWebhookDeliver(webhook: MiWebhook, type: typeof webhookEventTypes[number], content: unknown) { - const data: UserWebhookDeliverJobData = { + public webhookDeliver(webhook: MiWebhook, type: typeof webhookEventTypes[number], content: unknown) { + const data = { type, content, webhookId: webhook.id, @@ -467,33 +444,7 @@ export class QueueService { eventId: randomUUID(), }; - return this.userWebhookDeliverQueue.add(webhook.id, data, { - attempts: 4, - backoff: { - type: 'custom', - }, - removeOnComplete: true, - removeOnFail: true, - }); - } - - /** - * @see SystemWebhookDeliverJobData - * @see WebhookDeliverProcessorService - */ - @bindThis - public systemWebhookDeliver(webhook: MiSystemWebhook, type: SystemWebhookEventType, content: unknown) { - const data: SystemWebhookDeliverJobData = { - type, - content, - webhookId: webhook.id, - to: webhook.url, - secret: webhook.secret, - createdAt: Date.now(), - eventId: randomUUID(), - }; - - return this.systemWebhookDeliverQueue.add(webhook.id, data, { + return this.webhookDeliverQueue.add(webhook.id, data, { attempts: 4, backoff: { type: 'custom', diff --git a/packages/backend/src/core/RoleService.ts b/packages/backend/src/core/RoleService.ts index e2ebecb99f4f..d6eea702970b 100644 --- a/packages/backend/src/core/RoleService.ts +++ b/packages/backend/src/core/RoleService.ts @@ -410,32 +410,14 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit { } @bindThis - public async getModeratorIds(includeAdmins = true, excludeExpire = false): Promise { + public async getModeratorIds(includeAdmins = true): Promise { const roles = await this.rolesCache.fetch(() => this.rolesRepository.findBy({})); - const moderatorRoles = includeAdmins - ? roles.filter(r => r.isModerator || r.isAdministrator) - : roles.filter(r => r.isModerator); - + const moderatorRoles = includeAdmins ? roles.filter(r => r.isModerator || r.isAdministrator) : roles.filter(r => r.isModerator); + const assigns = moderatorRoles.length > 0 ? await this.roleAssignmentsRepository.findBy({ + roleId: In(moderatorRoles.map(r => r.id)), + }) : []; // TODO: isRootなアカウントも含める - const assigns = moderatorRoles.length > 0 - ? await this.roleAssignmentsRepository.findBy({ roleId: In(moderatorRoles.map(r => r.id)) }) - : []; - - const now = Date.now(); - const result = [ - // Setを経由して重複を除去(ユーザIDは重複する可能性があるので) - ...new Set( - assigns - .filter(it => - (excludeExpire) - ? (it.expiresAt == null || it.expiresAt.getTime() > now) - : true, - ) - .map(a => a.userId), - ), - ]; - - return result.sort((x, y) => x.localeCompare(y)); + return assigns.map(a => a.userId); } @bindThis diff --git a/packages/backend/src/core/SystemWebhookService.ts b/packages/backend/src/core/SystemWebhookService.ts deleted file mode 100644 index bc6851f788da..000000000000 --- a/packages/backend/src/core/SystemWebhookService.ts +++ /dev/null @@ -1,233 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { Inject, Injectable } from '@nestjs/common'; -import * as Redis from 'ioredis'; -import type { MiUser, SystemWebhooksRepository } from '@/models/_.js'; -import { DI } from '@/di-symbols.js'; -import { bindThis } from '@/decorators.js'; -import { GlobalEvents, GlobalEventService } from '@/core/GlobalEventService.js'; -import { MiSystemWebhook, type SystemWebhookEventType } from '@/models/SystemWebhook.js'; -import { IdService } from '@/core/IdService.js'; -import { QueueService } from '@/core/QueueService.js'; -import { ModerationLogService } from '@/core/ModerationLogService.js'; -import { LoggerService } from '@/core/LoggerService.js'; -import Logger from '@/logger.js'; -import type { OnApplicationShutdown } from '@nestjs/common'; - -@Injectable() -export class SystemWebhookService implements OnApplicationShutdown { - private logger: Logger; - private activeSystemWebhooksFetched = false; - private activeSystemWebhooks: MiSystemWebhook[] = []; - - constructor( - @Inject(DI.redisForSub) - private redisForSub: Redis.Redis, - @Inject(DI.systemWebhooksRepository) - private systemWebhooksRepository: SystemWebhooksRepository, - private idService: IdService, - private queueService: QueueService, - private moderationLogService: ModerationLogService, - private loggerService: LoggerService, - private globalEventService: GlobalEventService, - ) { - this.redisForSub.on('message', this.onMessage); - this.logger = this.loggerService.getLogger('webhook'); - } - - @bindThis - public async fetchActiveSystemWebhooks() { - if (!this.activeSystemWebhooksFetched) { - this.activeSystemWebhooks = await this.systemWebhooksRepository.findBy({ - isActive: true, - }); - this.activeSystemWebhooksFetched = true; - } - - return this.activeSystemWebhooks; - } - - /** - * SystemWebhook の一覧を取得する. - */ - @bindThis - public async fetchSystemWebhooks(params?: { - ids?: MiSystemWebhook['id'][]; - isActive?: MiSystemWebhook['isActive']; - on?: MiSystemWebhook['on']; - }): Promise { - const query = this.systemWebhooksRepository.createQueryBuilder('systemWebhook'); - if (params) { - if (params.ids && params.ids.length > 0) { - query.andWhere('systemWebhook.id IN (:...ids)', { ids: params.ids }); - } - if (params.isActive !== undefined) { - query.andWhere('systemWebhook.isActive = :isActive', { isActive: params.isActive }); - } - if (params.on && params.on.length > 0) { - query.andWhere(':on <@ systemWebhook.on', { on: params.on }); - } - } - - return query.getMany(); - } - - /** - * SystemWebhook を作成する. - */ - @bindThis - public async createSystemWebhook( - params: { - isActive: MiSystemWebhook['isActive']; - name: MiSystemWebhook['name']; - on: MiSystemWebhook['on']; - url: MiSystemWebhook['url']; - secret: MiSystemWebhook['secret']; - }, - updater: MiUser, - ): Promise { - const id = this.idService.gen(); - await this.systemWebhooksRepository.insert({ - ...params, - id, - }); - - const webhook = await this.systemWebhooksRepository.findOneByOrFail({ id }); - this.globalEventService.publishInternalEvent('systemWebhookCreated', webhook); - this.moderationLogService - .log(updater, 'createSystemWebhook', { - systemWebhookId: webhook.id, - webhook: webhook, - }) - .then(); - - return webhook; - } - - /** - * SystemWebhook を更新する. - */ - @bindThis - public async updateSystemWebhook( - params: { - id: MiSystemWebhook['id']; - isActive: MiSystemWebhook['isActive']; - name: MiSystemWebhook['name']; - on: MiSystemWebhook['on']; - url: MiSystemWebhook['url']; - secret: MiSystemWebhook['secret']; - }, - updater: MiUser, - ): Promise { - const beforeEntity = await this.systemWebhooksRepository.findOneByOrFail({ id: params.id }); - await this.systemWebhooksRepository.update(beforeEntity.id, { - updatedAt: new Date(), - isActive: params.isActive, - name: params.name, - on: params.on, - url: params.url, - secret: params.secret, - }); - - const afterEntity = await this.systemWebhooksRepository.findOneByOrFail({ id: beforeEntity.id }); - this.globalEventService.publishInternalEvent('systemWebhookUpdated', afterEntity); - this.moderationLogService - .log(updater, 'updateSystemWebhook', { - systemWebhookId: beforeEntity.id, - before: beforeEntity, - after: afterEntity, - }) - .then(); - - return afterEntity; - } - - /** - * SystemWebhook を削除する. - */ - @bindThis - public async deleteSystemWebhook(id: MiSystemWebhook['id'], updater: MiUser) { - const webhook = await this.systemWebhooksRepository.findOneByOrFail({ id }); - await this.systemWebhooksRepository.delete(id); - - this.globalEventService.publishInternalEvent('systemWebhookDeleted', webhook); - this.moderationLogService - .log(updater, 'deleteSystemWebhook', { - systemWebhookId: webhook.id, - webhook, - }) - .then(); - } - - /** - * SystemWebhook をWebhook配送キューに追加する - * @see QueueService.systemWebhookDeliver - */ - @bindThis - public async enqueueSystemWebhook(webhook: MiSystemWebhook | MiSystemWebhook['id'], type: SystemWebhookEventType, content: unknown) { - const webhookEntity = typeof webhook === 'string' - ? (await this.fetchActiveSystemWebhooks()).find(a => a.id === webhook) - : webhook; - if (!webhookEntity || !webhookEntity.isActive) { - this.logger.info(`Webhook is not active or not found : ${webhook}`); - return; - } - - if (!webhookEntity.on.includes(type)) { - this.logger.info(`Webhook ${webhookEntity.id} is not listening to ${type}`); - return; - } - - return this.queueService.systemWebhookDeliver(webhookEntity, type, content); - } - - @bindThis - private async onMessage(_: string, data: string): Promise { - const obj = JSON.parse(data); - if (obj.channel !== 'internal') { - return; - } - - const { type, body } = obj.message as GlobalEvents['internal']['payload']; - switch (type) { - case 'systemWebhookCreated': { - if (body.isActive) { - this.activeSystemWebhooks.push(MiSystemWebhook.deserialize(body)); - } - break; - } - case 'systemWebhookUpdated': { - if (body.isActive) { - const i = this.activeSystemWebhooks.findIndex(a => a.id === body.id); - if (i > -1) { - this.activeSystemWebhooks[i] = MiSystemWebhook.deserialize(body); - } else { - this.activeSystemWebhooks.push(MiSystemWebhook.deserialize(body)); - } - } else { - this.activeSystemWebhooks = this.activeSystemWebhooks.filter(a => a.id !== body.id); - } - break; - } - case 'systemWebhookDeleted': { - this.activeSystemWebhooks = this.activeSystemWebhooks.filter(a => a.id !== body.id); - break; - } - default: - break; - } - } - - @bindThis - public dispose(): void { - this.redisForSub.off('message', this.onMessage); - } - - @bindThis - public onApplicationShutdown(signal?: string | undefined): void { - this.dispose(); - } -} diff --git a/packages/backend/src/core/UserBlockingService.ts b/packages/backend/src/core/UserBlockingService.ts index 2f1310b8efe7..96f389b54c55 100644 --- a/packages/backend/src/core/UserBlockingService.ts +++ b/packages/backend/src/core/UserBlockingService.ts @@ -16,7 +16,7 @@ import Logger from '@/logger.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { ApRendererService } from '@/core/activitypub/ApRendererService.js'; import { LoggerService } from '@/core/LoggerService.js'; -import { UserWebhookService } from '@/core/UserWebhookService.js'; +import { WebhookService } from '@/core/WebhookService.js'; import { bindThis } from '@/decorators.js'; import { CacheService } from '@/core/CacheService.js'; import { UserFollowingService } from '@/core/UserFollowingService.js'; @@ -46,7 +46,7 @@ export class UserBlockingService implements OnModuleInit { private idService: IdService, private queueService: QueueService, private globalEventService: GlobalEventService, - private webhookService: UserWebhookService, + private webhookService: WebhookService, private apRendererService: ApRendererService, private loggerService: LoggerService, ) { @@ -121,7 +121,7 @@ export class UserBlockingService implements OnModuleInit { const webhooks = (await this.webhookService.getActiveWebhooks()).filter(x => x.userId === follower.id && x.on.includes('unfollow')); for (const webhook of webhooks) { - this.queueService.userWebhookDeliver(webhook, 'unfollow', { + this.queueService.webhookDeliver(webhook, 'unfollow', { user: packed, }); } diff --git a/packages/backend/src/core/UserFollowingService.ts b/packages/backend/src/core/UserFollowingService.ts index 267a6a3f1b78..406ea040316a 100644 --- a/packages/backend/src/core/UserFollowingService.ts +++ b/packages/backend/src/core/UserFollowingService.ts @@ -16,7 +16,7 @@ import { isDuplicateKeyValueError } from '@/misc/is-duplicate-key-value-error.js import type { Packed } from '@/misc/json-schema.js'; import InstanceChart from '@/core/chart/charts/instance.js'; import { FederatedInstanceService } from '@/core/FederatedInstanceService.js'; -import { UserWebhookService } from '@/core/UserWebhookService.js'; +import { WebhookService } from '@/core/WebhookService.js'; import { NotificationService } from '@/core/NotificationService.js'; import { DI } from '@/di-symbols.js'; import type { FollowingsRepository, FollowRequestsRepository, InstancesRepository, UserProfilesRepository, UsersRepository } from '@/models/_.js'; @@ -82,7 +82,7 @@ export class UserFollowingService implements OnModuleInit { private metaService: MetaService, private notificationService: NotificationService, private federatedInstanceService: FederatedInstanceService, - private webhookService: UserWebhookService, + private webhookService: WebhookService, private apRendererService: ApRendererService, private accountMoveService: AccountMoveService, private fanoutTimelineService: FanoutTimelineService, @@ -331,7 +331,7 @@ export class UserFollowingService implements OnModuleInit { const webhooks = (await this.webhookService.getActiveWebhooks()).filter(x => x.userId === follower.id && x.on.includes('follow')); for (const webhook of webhooks) { - this.queueService.userWebhookDeliver(webhook, 'follow', { + this.queueService.webhookDeliver(webhook, 'follow', { user: packed, }); } @@ -345,7 +345,7 @@ export class UserFollowingService implements OnModuleInit { const webhooks = (await this.webhookService.getActiveWebhooks()).filter(x => x.userId === followee.id && x.on.includes('followed')); for (const webhook of webhooks) { - this.queueService.userWebhookDeliver(webhook, 'followed', { + this.queueService.webhookDeliver(webhook, 'followed', { user: packed, }); } @@ -398,7 +398,7 @@ export class UserFollowingService implements OnModuleInit { const webhooks = (await this.webhookService.getActiveWebhooks()).filter(x => x.userId === follower.id && x.on.includes('unfollow')); for (const webhook of webhooks) { - this.queueService.userWebhookDeliver(webhook, 'unfollow', { + this.queueService.webhookDeliver(webhook, 'unfollow', { user: packed, }); } @@ -740,7 +740,7 @@ export class UserFollowingService implements OnModuleInit { const webhooks = (await this.webhookService.getActiveWebhooks()).filter(x => x.userId === follower.id && x.on.includes('unfollow')); for (const webhook of webhooks) { - this.queueService.userWebhookDeliver(webhook, 'unfollow', { + this.queueService.webhookDeliver(webhook, 'unfollow', { user: packedFollowee, }); } diff --git a/packages/backend/src/core/UserWebhookService.ts b/packages/backend/src/core/UserWebhookService.ts deleted file mode 100644 index e96bfeea9581..000000000000 --- a/packages/backend/src/core/UserWebhookService.ts +++ /dev/null @@ -1,99 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { Inject, Injectable } from '@nestjs/common'; -import * as Redis from 'ioredis'; -import type { WebhooksRepository } from '@/models/_.js'; -import type { MiWebhook } from '@/models/Webhook.js'; -import { DI } from '@/di-symbols.js'; -import { bindThis } from '@/decorators.js'; -import { GlobalEvents } from '@/core/GlobalEventService.js'; -import type { OnApplicationShutdown } from '@nestjs/common'; - -@Injectable() -export class UserWebhookService implements OnApplicationShutdown { - private activeWebhooksFetched = false; - private activeWebhooks: MiWebhook[] = []; - - constructor( - @Inject(DI.redisForSub) - private redisForSub: Redis.Redis, - @Inject(DI.webhooksRepository) - private webhooksRepository: WebhooksRepository, - ) { - this.redisForSub.on('message', this.onMessage); - } - - @bindThis - public async getActiveWebhooks() { - if (!this.activeWebhooksFetched) { - this.activeWebhooks = await this.webhooksRepository.findBy({ - active: true, - }); - this.activeWebhooksFetched = true; - } - - return this.activeWebhooks; - } - - @bindThis - private async onMessage(_: string, data: string): Promise { - const obj = JSON.parse(data); - if (obj.channel !== 'internal') { - return; - } - - const { type, body } = obj.message as GlobalEvents['internal']['payload']; - switch (type) { - case 'webhookCreated': { - if (body.active) { - this.activeWebhooks.push({ // TODO: このあたりのデシリアライズ処理は各modelファイル内に関数としてexportしたい - ...body, - latestSentAt: body.latestSentAt ? new Date(body.latestSentAt) : null, - user: null, // joinなカラムは通常取ってこないので - }); - } - break; - } - case 'webhookUpdated': { - if (body.active) { - const i = this.activeWebhooks.findIndex(a => a.id === body.id); - if (i > -1) { - this.activeWebhooks[i] = { // TODO: このあたりのデシリアライズ処理は各modelファイル内に関数としてexportしたい - ...body, - latestSentAt: body.latestSentAt ? new Date(body.latestSentAt) : null, - user: null, // joinなカラムは通常取ってこないので - }; - } else { - this.activeWebhooks.push({ // TODO: このあたりのデシリアライズ処理は各modelファイル内に関数としてexportしたい - ...body, - latestSentAt: body.latestSentAt ? new Date(body.latestSentAt) : null, - user: null, // joinなカラムは通常取ってこないので - }); - } - } else { - this.activeWebhooks = this.activeWebhooks.filter(a => a.id !== body.id); - } - break; - } - case 'webhookDeleted': { - this.activeWebhooks = this.activeWebhooks.filter(a => a.id !== body.id); - break; - } - default: - break; - } - } - - @bindThis - public dispose(): void { - this.redisForSub.off('message', this.onMessage); - } - - @bindThis - public onApplicationShutdown(signal?: string | undefined): void { - this.dispose(); - } -} diff --git a/packages/backend/src/core/WebhookService.ts b/packages/backend/src/core/WebhookService.ts new file mode 100644 index 000000000000..6be34977b064 --- /dev/null +++ b/packages/backend/src/core/WebhookService.ts @@ -0,0 +1,97 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Inject, Injectable } from '@nestjs/common'; +import * as Redis from 'ioredis'; +import type { WebhooksRepository } from '@/models/_.js'; +import type { MiWebhook } from '@/models/Webhook.js'; +import { DI } from '@/di-symbols.js'; +import { bindThis } from '@/decorators.js'; +import type { GlobalEvents } from '@/core/GlobalEventService.js'; +import type { OnApplicationShutdown } from '@nestjs/common'; + +@Injectable() +export class WebhookService implements OnApplicationShutdown { + private webhooksFetched = false; + private webhooks: MiWebhook[] = []; + + constructor( + @Inject(DI.redisForSub) + private redisForSub: Redis.Redis, + + @Inject(DI.webhooksRepository) + private webhooksRepository: WebhooksRepository, + ) { + //this.onMessage = this.onMessage.bind(this); + this.redisForSub.on('message', this.onMessage); + } + + @bindThis + public async getActiveWebhooks() { + if (!this.webhooksFetched) { + this.webhooks = await this.webhooksRepository.findBy({ + active: true, + }); + this.webhooksFetched = true; + } + + return this.webhooks; + } + + @bindThis + private async onMessage(_: string, data: string): Promise { + const obj = JSON.parse(data); + + if (obj.channel === 'internal') { + const { type, body } = obj.message as GlobalEvents['internal']['payload']; + switch (type) { + case 'webhookCreated': + if (body.active) { + this.webhooks.push({ // TODO: このあたりのデシリアライズ処理は各modelファイル内に関数としてexportしたい + ...body, + latestSentAt: body.latestSentAt ? new Date(body.latestSentAt) : null, + user: null, // joinなカラムは通常取ってこないので + }); + } + break; + case 'webhookUpdated': + if (body.active) { + const i = this.webhooks.findIndex(a => a.id === body.id); + if (i > -1) { + this.webhooks[i] = { // TODO: このあたりのデシリアライズ処理は各modelファイル内に関数としてexportしたい + ...body, + latestSentAt: body.latestSentAt ? new Date(body.latestSentAt) : null, + user: null, // joinなカラムは通常取ってこないので + }; + } else { + this.webhooks.push({ // TODO: このあたりのデシリアライズ処理は各modelファイル内に関数としてexportしたい + ...body, + latestSentAt: body.latestSentAt ? new Date(body.latestSentAt) : null, + user: null, // joinなカラムは通常取ってこないので + }); + } + } else { + this.webhooks = this.webhooks.filter(a => a.id !== body.id); + } + break; + case 'webhookDeleted': + this.webhooks = this.webhooks.filter(a => a.id !== body.id); + break; + default: + break; + } + } + } + + @bindThis + public dispose(): void { + this.redisForSub.off('message', this.onMessage); + } + + @bindThis + public onApplicationShutdown(signal?: string | undefined): void { + this.dispose(); + } +} diff --git a/packages/backend/src/core/activitypub/ApInboxService.ts b/packages/backend/src/core/activitypub/ApInboxService.ts index de3178b4827f..d0d206760cb9 100644 --- a/packages/backend/src/core/activitypub/ApInboxService.ts +++ b/packages/backend/src/core/activitypub/ApInboxService.ts @@ -29,7 +29,6 @@ import { bindThis } from '@/decorators.js'; import type { MiRemoteUser } from '@/models/User.js'; import { isNotNull } from '@/misc/is-not-null.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; -import { AbuseReportService } from '@/core/AbuseReportService.js'; import { getApHrefNullable, getApId, getApIds, getApType, isAccept, isActor, isAdd, isAnnounce, isBlock, isCollection, isCollectionOrOrderedCollection, isCreate, isDelete, isFlag, isFollow, isLike, isMove, isPost, isReject, isRemove, isTombstone, isUndo, isUpdate, validActor, validPost } from './type.js'; import { ApNoteService } from './models/ApNoteService.js'; import { ApLoggerService } from './ApLoggerService.js'; @@ -58,6 +57,9 @@ export class ApInboxService { @Inject(DI.followingsRepository) private followingsRepository: FollowingsRepository, + @Inject(DI.abuseUserReportsRepository) + private abuseUserReportsRepository: AbuseUserReportsRepository, + @Inject(DI.followRequestsRepository) private followRequestsRepository: FollowRequestsRepository, @@ -66,7 +68,6 @@ export class ApInboxService { private utilityService: UtilityService, private idService: IdService, private metaService: MetaService, - private abuseReportService: AbuseReportService, private userFollowingService: UserFollowingService, private apAudienceService: ApAudienceService, private reactionService: ReactionService, @@ -544,13 +545,14 @@ export class ApInboxService { }); if (users.length < 1) return 'skip'; - await this.abuseReportService.report([{ + await this.abuseUserReportsRepository.insert({ + id: this.idService.gen(), targetUserId: users[0].id, targetUserHost: users[0].host, reporterId: actor.id, reporterHost: actor.host, comment: `${activity.content}\n${JSON.stringify(uris, null, 2)}`, - }]); + }); return 'ok'; } diff --git a/packages/backend/src/core/entities/AbuseReportNotificationRecipientEntityService.ts b/packages/backend/src/core/entities/AbuseReportNotificationRecipientEntityService.ts deleted file mode 100644 index 6819afafd9f5..000000000000 --- a/packages/backend/src/core/entities/AbuseReportNotificationRecipientEntityService.ts +++ /dev/null @@ -1,88 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { Inject, Injectable } from '@nestjs/common'; -import { In } from 'typeorm'; -import { DI } from '@/di-symbols.js'; -import type { AbuseReportNotificationRecipientRepository, MiAbuseReportNotificationRecipient } from '@/models/_.js'; -import { bindThis } from '@/decorators.js'; -import { UserEntityService } from '@/core/entities/UserEntityService.js'; -import { Packed } from '@/misc/json-schema.js'; -import { SystemWebhookEntityService } from '@/core/entities/SystemWebhookEntityService.js'; -import { isNotNull } from '@/misc/is-not-null.js'; - -@Injectable() -export class AbuseReportNotificationRecipientEntityService { - constructor( - @Inject(DI.abuseReportNotificationRecipientRepository) - private abuseReportNotificationRecipientRepository: AbuseReportNotificationRecipientRepository, - private userEntityService: UserEntityService, - private systemWebhookEntityService: SystemWebhookEntityService, - ) { - } - - @bindThis - public async pack( - src: MiAbuseReportNotificationRecipient['id'] | MiAbuseReportNotificationRecipient, - opts?: { - users: Map>, - webhooks: Map>, - }, - ): Promise> { - const recipient = typeof src === 'object' - ? src - : await this.abuseReportNotificationRecipientRepository.findOneByOrFail({ id: src }); - const user = recipient.userId - ? (opts?.users.get(recipient.userId) ?? await this.userEntityService.pack<'UserLite'>(recipient.userId)) - : undefined; - const webhook = recipient.systemWebhookId - ? (opts?.webhooks.get(recipient.systemWebhookId) ?? await this.systemWebhookEntityService.pack(recipient.systemWebhookId)) - : undefined; - - return { - id: recipient.id, - isActive: recipient.isActive, - updatedAt: recipient.updatedAt.toISOString(), - name: recipient.name, - method: recipient.method, - userId: recipient.userId ?? undefined, - user: user, - systemWebhookId: recipient.systemWebhookId ?? undefined, - systemWebhook: webhook, - }; - } - - @bindThis - public async packMany( - src: MiAbuseReportNotificationRecipient['id'][] | MiAbuseReportNotificationRecipient[], - ): Promise[]> { - const objs = src.filter((it): it is MiAbuseReportNotificationRecipient => typeof it === 'object'); - const ids = src.filter((it): it is MiAbuseReportNotificationRecipient['id'] => typeof it === 'string'); - if (ids.length > 0) { - objs.push( - ...await this.abuseReportNotificationRecipientRepository.findBy({ id: In(ids) }), - ); - } - - const userIds = objs.map(it => it.userId).filter(isNotNull); - const users: Map> = (userIds.length > 0) - ? await this.userEntityService.packMany(userIds) - .then(it => new Map(it.map(it => [it.id, it]))) - : new Map(); - - const systemWebhookIds = objs.map(it => it.systemWebhookId).filter(isNotNull); - const systemWebhooks: Map> = (systemWebhookIds.length > 0) - ? await this.systemWebhookEntityService.packMany(systemWebhookIds) - .then(it => new Map(it.map(it => [it.id, it]))) - : new Map(); - - return Promise - .all( - objs.map(it => this.pack(it, { users: users, webhooks: systemWebhooks })), - ) - .then(it => it.sort((a, b) => a.id.localeCompare(b.id))); - } -} - diff --git a/packages/backend/src/core/entities/SystemWebhookEntityService.ts b/packages/backend/src/core/entities/SystemWebhookEntityService.ts deleted file mode 100644 index e18734091c62..000000000000 --- a/packages/backend/src/core/entities/SystemWebhookEntityService.ts +++ /dev/null @@ -1,74 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { Inject, Injectable } from '@nestjs/common'; -import { In } from 'typeorm'; -import { DI } from '@/di-symbols.js'; -import type { MiSystemWebhook, SystemWebhooksRepository } from '@/models/_.js'; -import { bindThis } from '@/decorators.js'; -import { Packed } from '@/misc/json-schema.js'; - -@Injectable() -export class SystemWebhookEntityService { - constructor( - @Inject(DI.systemWebhooksRepository) - private systemWebhooksRepository: SystemWebhooksRepository, - ) { - } - - @bindThis - public async pack( - src: MiSystemWebhook['id'] | MiSystemWebhook, - opts?: { - webhooks: Map - }, - ): Promise> { - const webhook = typeof src === 'object' - ? src - : opts?.webhooks.get(src) ?? await this.systemWebhooksRepository.findOneByOrFail({ id: src }); - - return { - id: webhook.id, - isActive: webhook.isActive, - updatedAt: webhook.updatedAt.toISOString(), - latestSentAt: webhook.latestSentAt?.toISOString() ?? null, - latestStatus: webhook.latestStatus, - name: webhook.name, - on: webhook.on, - url: webhook.url, - secret: webhook.secret, - }; - } - - @bindThis - public async packMany(src: MiSystemWebhook['id'][] | MiSystemWebhook[]): Promise[]> { - if (src.length === 0) { - return []; - } - - const webhooks = Array.of(); - webhooks.push( - ...src.filter((it): it is MiSystemWebhook => typeof it === 'object'), - ); - - const ids = src.filter((it): it is MiSystemWebhook['id'] => typeof it === 'string'); - if (ids.length > 0) { - webhooks.push( - ...await this.systemWebhooksRepository.findBy({ id: In(ids) }), - ); - } - - return Promise - .all( - webhooks.map(x => - this.pack(x, { - webhooks: new Map(webhooks.map(x => [x.id, x])), - }), - ), - ) - .then(it => it.sort((a, b) => a.id.localeCompare(b.id))); - } -} - diff --git a/packages/backend/src/di-symbols.ts b/packages/backend/src/di-symbols.ts index 271082b4ff35..919f4794a325 100644 --- a/packages/backend/src/di-symbols.ts +++ b/packages/backend/src/di-symbols.ts @@ -49,7 +49,6 @@ export const DI = { swSubscriptionsRepository: Symbol('swSubscriptionsRepository'), hashtagsRepository: Symbol('hashtagsRepository'), abuseUserReportsRepository: Symbol('abuseUserReportsRepository'), - abuseReportNotificationRecipientRepository: Symbol('abuseReportNotificationRecipientRepository'), registrationTicketsRepository: Symbol('registrationTicketsRepository'), authSessionsRepository: Symbol('authSessionsRepository'), accessTokensRepository: Symbol('accessTokensRepository'), @@ -71,7 +70,6 @@ export const DI = { channelFavoritesRepository: Symbol('channelFavoritesRepository'), registryItemsRepository: Symbol('registryItemsRepository'), webhooksRepository: Symbol('webhooksRepository'), - systemWebhooksRepository: Symbol('systemWebhooksRepository'), adsRepository: Symbol('adsRepository'), passwordResetRequestsRepository: Symbol('passwordResetRequestsRepository'), retentionAggregationsRepository: Symbol('retentionAggregationsRepository'), diff --git a/packages/backend/src/misc/json-schema.ts b/packages/backend/src/misc/json-schema.ts index a721b8663c3c..41e5bfe9e4ad 100644 --- a/packages/backend/src/misc/json-schema.ts +++ b/packages/backend/src/misc/json-schema.ts @@ -4,12 +4,12 @@ */ import { - packedMeDetailedOnlySchema, - packedMeDetailedSchema, + packedUserLiteSchema, packedUserDetailedNotMeOnlySchema, + packedMeDetailedOnlySchema, packedUserDetailedNotMeSchema, + packedMeDetailedSchema, packedUserDetailedSchema, - packedUserLiteSchema, packedUserSchema, } from '@/models/json-schema/user.js'; import { packedNoteSchema } from '@/models/json-schema/note.js'; @@ -25,7 +25,7 @@ import { packedBlockingSchema } from '@/models/json-schema/blocking.js'; import { packedNoteReactionSchema } from '@/models/json-schema/note-reaction.js'; import { packedHashtagSchema } from '@/models/json-schema/hashtag.js'; import { packedInviteCodeSchema } from '@/models/json-schema/invite-code.js'; -import { packedPageBlockSchema, packedPageSchema } from '@/models/json-schema/page.js'; +import { packedPageSchema, packedPageBlockSchema } from '@/models/json-schema/page.js'; import { packedNoteFavoriteSchema } from '@/models/json-schema/note-favorite.js'; import { packedChannelSchema } from '@/models/json-schema/channel.js'; import { packedAntennaSchema } from '@/models/json-schema/antenna.js'; @@ -38,27 +38,25 @@ import { packedFlashSchema } from '@/models/json-schema/flash.js'; import { packedAnnouncementSchema } from '@/models/json-schema/announcement.js'; import { packedSigninSchema } from '@/models/json-schema/signin.js'; import { - packedRoleCondFormulaFollowersOrFollowingOrNotesSchema, + packedRoleLiteSchema, + packedRoleSchema, + packedRolePoliciesSchema, packedRoleCondFormulaLogicsSchema, + packedRoleCondFormulaValueNot, + packedRoleCondFormulaValueIsLocalOrRemoteSchema, packedRoleCondFormulaValueAssignedRoleSchema, packedRoleCondFormulaValueCreatedSchema, - packedRoleCondFormulaValueIsLocalOrRemoteSchema, - packedRoleCondFormulaValueNot, + packedRoleCondFormulaFollowersOrFollowingOrNotesSchema, packedRoleCondFormulaValueSchema, packedRoleCondFormulaValueUserSettingBooleanSchema, - packedRoleLiteSchema, - packedRolePoliciesSchema, - packedRoleSchema, } from '@/models/json-schema/role.js'; import { packedAdSchema } from '@/models/json-schema/ad.js'; -import { packedReversiGameDetailedSchema, packedReversiGameLiteSchema } from '@/models/json-schema/reversi-game.js'; +import { packedReversiGameLiteSchema, packedReversiGameDetailedSchema } from '@/models/json-schema/reversi-game.js'; import { + packedMetaLiteSchema, packedMetaDetailedOnlySchema, packedMetaDetailedSchema, - packedMetaLiteSchema, } from '@/models/json-schema/meta.js'; -import { packedSystemWebhookSchema } from '@/models/json-schema/system-webhook.js'; -import { packedAbuseReportNotificationRecipientSchema } from '@/models/json-schema/abuse-report-notification-recipient.js'; export const refs = { UserLite: packedUserLiteSchema, @@ -113,8 +111,6 @@ export const refs = { MetaLite: packedMetaLiteSchema, MetaDetailedOnly: packedMetaDetailedOnlySchema, MetaDetailed: packedMetaDetailedSchema, - SystemWebhook: packedSystemWebhookSchema, - AbuseReportNotificationRecipient: packedAbuseReportNotificationRecipientSchema, }; export type Packed = SchemaType; diff --git a/packages/backend/src/models/AbuseReportNotificationRecipient.ts b/packages/backend/src/models/AbuseReportNotificationRecipient.ts deleted file mode 100644 index fbff880afca4..000000000000 --- a/packages/backend/src/models/AbuseReportNotificationRecipient.ts +++ /dev/null @@ -1,100 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { Column, Entity, Index, JoinColumn, ManyToOne, PrimaryColumn } from 'typeorm'; -import { MiSystemWebhook } from '@/models/SystemWebhook.js'; -import { MiUserProfile } from '@/models/UserProfile.js'; -import { id } from './util/id.js'; -import { MiUser } from './User.js'; - -/** - * 通報受信時に通知を送信する方法. - */ -export type RecipientMethod = 'email' | 'webhook'; - -@Entity('abuse_report_notification_recipient') -export class MiAbuseReportNotificationRecipient { - @PrimaryColumn(id()) - public id: string; - - /** - * 有効かどうか. - */ - @Index() - @Column('boolean', { - default: true, - }) - public isActive: boolean; - - /** - * 更新日時. - */ - @Column('timestamp with time zone', { - default: () => 'CURRENT_TIMESTAMP', - }) - public updatedAt: Date; - - /** - * 通知設定名. - */ - @Column('varchar', { - length: 255, - }) - public name: string; - - /** - * 通知方法. - */ - @Index() - @Column('varchar', { - length: 64, - }) - public method: RecipientMethod; - - /** - * 通知先のユーザID. - */ - @Index() - @Column({ - ...id(), - nullable: true, - }) - public userId: MiUser['id'] | null; - - /** - * 通知先のユーザ. - */ - @ManyToOne(type => MiUser, { - onDelete: 'CASCADE', - }) - @JoinColumn({ name: 'userId', referencedColumnName: 'id', foreignKeyConstraintName: 'FK_abuse_report_notification_recipient_userId1' }) - public user: MiUser | null; - - /** - * 通知先のユーザプロフィール. - */ - @ManyToOne(type => MiUserProfile, {}) - @JoinColumn({ name: 'userId', referencedColumnName: 'userId', foreignKeyConstraintName: 'FK_abuse_report_notification_recipient_userId2' }) - public userProfile: MiUserProfile | null; - - /** - * 通知先のシステムWebhookId. - */ - @Index() - @Column({ - ...id(), - nullable: true, - }) - public systemWebhookId: string | null; - - /** - * 通知先のシステムWebhook. - */ - @ManyToOne(type => MiSystemWebhook, { - onDelete: 'CASCADE', - }) - @JoinColumn() - public systemWebhook: MiSystemWebhook | null; -} diff --git a/packages/backend/src/models/RepositoryModule.ts b/packages/backend/src/models/RepositoryModule.ts index ea0f88babaa7..d3062d6b36f8 100644 --- a/packages/backend/src/models/RepositoryModule.ts +++ b/packages/backend/src/models/RepositoryModule.ts @@ -3,83 +3,11 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import type { Provider } from '@nestjs/common'; import { Module } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import { - MiAbuseReportNotificationRecipient, - MiAbuseUserReport, - MiAccessToken, - MiAd, - MiAnnouncement, - MiAnnouncementRead, - MiAntenna, - MiApp, - MiAuthSession, - MiAvatarDecoration, - MiBlocking, - MiBubbleGameRecord, - MiChannel, - MiChannelFavorite, - MiChannelFollowing, - MiClip, - MiClipFavorite, - MiClipNote, - MiDriveFile, - MiDriveFolder, - MiEmoji, - MiFlash, - MiFlashLike, - MiFollowing, - MiFollowRequest, - MiGalleryLike, - MiGalleryPost, - MiHashtag, - MiInstance, - MiMeta, - MiModerationLog, - MiMuting, - MiNote, - MiNoteFavorite, - MiNoteReaction, - MiNoteThreadMuting, - MiNoteUnread, - MiPage, - MiPageLike, - MiPasswordResetRequest, - MiPoll, - MiPollVote, - MiPromoNote, - MiPromoRead, - MiRegistrationTicket, - MiRegistryItem, - MiRelay, - MiRenoteMuting, - MiRepository, - miRepository, - MiRetentionAggregation, - MiReversiGame, - MiRole, - MiRoleAssignment, - MiSignin, - MiSwSubscription, - MiSystemWebhook, - MiUsedUsername, - MiUser, - MiUserIp, - MiUserKeypair, - MiUserList, - MiUserListFavorite, - MiUserListMembership, - MiUserMemo, - MiUserNotePining, - MiUserPending, - MiUserProfile, - MiUserPublickey, - MiUserSecurityKey, - MiWebhook -} from './_.js'; +import { MiRepository, MiAbuseUserReport, MiAccessToken, MiAd, MiAnnouncement, MiAnnouncementRead, MiAntenna, MiApp, MiAuthSession, MiAvatarDecoration, MiBlocking, MiChannel, MiChannelFavorite, MiChannelFollowing, MiClip, MiClipFavorite, MiClipNote, MiDriveFile, MiDriveFolder, MiEmoji, MiFlash, MiFlashLike, MiFollowRequest, MiFollowing, MiGalleryLike, MiGalleryPost, MiHashtag, MiInstance, MiMeta, MiModerationLog, MiMuting, MiNote, MiNoteFavorite, MiNoteReaction, MiNoteThreadMuting, MiNoteUnread, MiPage, MiPageLike, MiPasswordResetRequest, MiPoll, MiPollVote, MiPromoNote, MiPromoRead, MiRegistrationTicket, MiRegistryItem, MiRelay, MiRenoteMuting, MiRetentionAggregation, MiRole, MiRoleAssignment, MiSignin, MiSwSubscription, MiUsedUsername, MiUser, MiUserIp, MiUserKeypair, MiUserList, MiUserListFavorite, MiUserListMembership, MiUserMemo, MiUserNotePining, MiUserPending, MiUserProfile, MiUserPublickey, MiUserSecurityKey, MiWebhook, MiBubbleGameRecord, MiReversiGame, miRepository } from './_.js'; import type { DataSource } from 'typeorm'; +import type { Provider } from '@nestjs/common'; const $usersRepository: Provider = { provide: DI.usersRepository, @@ -297,12 +225,6 @@ const $abuseUserReportsRepository: Provider = { inject: [DI.db], }; -const $abuseReportNotificationRecipientRepository: Provider = { - provide: DI.abuseReportNotificationRecipientRepository, - useFactory: (db: DataSource) => db.getRepository(MiAbuseReportNotificationRecipient), - inject: [DI.db], -}; - const $registrationTicketsRepository: Provider = { provide: DI.registrationTicketsRepository, useFactory: (db: DataSource) => db.getRepository(MiRegistrationTicket).extend(miRepository as MiRepository), @@ -429,12 +351,6 @@ const $webhooksRepository: Provider = { inject: [DI.db], }; -const $systemWebhooksRepository: Provider = { - provide: DI.systemWebhooksRepository, - useFactory: (db: DataSource) => db.getRepository(MiSystemWebhook), - inject: [DI.db], -}; - const $adsRepository: Provider = { provide: DI.adsRepository, useFactory: (db: DataSource) => db.getRepository(MiAd).extend(miRepository as MiRepository), @@ -496,7 +412,8 @@ const $reversiGamesRepository: Provider = { }; @Module({ - imports: [], + imports: [ + ], providers: [ $usersRepository, $notesRepository, @@ -534,7 +451,6 @@ const $reversiGamesRepository: Provider = { $swSubscriptionsRepository, $hashtagsRepository, $abuseUserReportsRepository, - $abuseReportNotificationRecipientRepository, $registrationTicketsRepository, $authSessionsRepository, $accessTokensRepository, @@ -556,7 +472,6 @@ const $reversiGamesRepository: Provider = { $channelFavoritesRepository, $registryItemsRepository, $webhooksRepository, - $systemWebhooksRepository, $adsRepository, $passwordResetRequestsRepository, $retentionAggregationsRepository, @@ -605,7 +520,6 @@ const $reversiGamesRepository: Provider = { $swSubscriptionsRepository, $hashtagsRepository, $abuseUserReportsRepository, - $abuseReportNotificationRecipientRepository, $registrationTicketsRepository, $authSessionsRepository, $accessTokensRepository, @@ -627,7 +541,6 @@ const $reversiGamesRepository: Provider = { $channelFavoritesRepository, $registryItemsRepository, $webhooksRepository, - $systemWebhooksRepository, $adsRepository, $passwordResetRequestsRepository, $retentionAggregationsRepository, @@ -640,5 +553,4 @@ const $reversiGamesRepository: Provider = { $reversiGamesRepository, ], }) -export class RepositoryModule { -} +export class RepositoryModule {} diff --git a/packages/backend/src/models/SystemWebhook.ts b/packages/backend/src/models/SystemWebhook.ts deleted file mode 100644 index 86fb323d1daf..000000000000 --- a/packages/backend/src/models/SystemWebhook.ts +++ /dev/null @@ -1,98 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { Column, Entity, Index, PrimaryColumn } from 'typeorm'; -import { Serialized } from '@/types.js'; -import { id } from './util/id.js'; - -export const systemWebhookEventTypes = [ - // ユーザからの通報を受けたとき - 'abuseReport', - // 通報を処理したとき - 'abuseReportResolved', -] as const; -export type SystemWebhookEventType = typeof systemWebhookEventTypes[number]; - -@Entity('system_webhook') -export class MiSystemWebhook { - @PrimaryColumn(id()) - public id: string; - - /** - * 有効かどうか. - */ - @Index('IDX_system_webhook_isActive', { synchronize: false }) - @Column('boolean', { - default: true, - }) - public isActive: boolean; - - /** - * 更新日時. - */ - @Column('timestamp with time zone', { - default: () => 'CURRENT_TIMESTAMP', - }) - public updatedAt: Date; - - /** - * 最後に送信された日時. - */ - @Column('timestamp with time zone', { - nullable: true, - }) - public latestSentAt: Date | null; - - /** - * 最後に送信されたステータスコード - */ - @Column('integer', { - nullable: true, - }) - public latestStatus: number | null; - - /** - * 通知設定名. - */ - @Column('varchar', { - length: 255, - }) - public name: string; - - /** - * イベント種別. - */ - @Index('IDX_system_webhook_on', { synchronize: false }) - @Column('varchar', { - length: 128, - array: true, - default: '{}', - }) - public on: SystemWebhookEventType[]; - - /** - * Webhook送信先のURL. - */ - @Column('varchar', { - length: 1024, - }) - public url: string; - - /** - * Webhook検証用の値. - */ - @Column('varchar', { - length: 1024, - }) - public secret: string; - - static deserialize(obj: Serialized): MiSystemWebhook { - return { - ...obj, - updatedAt: new Date(obj.updatedAt), - latestSentAt: obj.latestSentAt ? new Date(obj.latestSentAt) : null, - }; - } -} diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index d366ce48d035..2e6a41586e45 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -11,7 +11,6 @@ import { RawSqlResultsToEntityTransformer } from 'typeorm/query-builder/transfor import { ObjectUtils } from 'typeorm/util/ObjectUtils.js'; import { OrmUtils } from 'typeorm/util/OrmUtils.js'; import { MiAbuseUserReport } from '@/models/AbuseUserReport.js'; -import { MiAbuseReportNotificationRecipient } from '@/models/AbuseReportNotificationRecipient.js'; import { MiAccessToken } from '@/models/AccessToken.js'; import { MiAd } from '@/models/Ad.js'; import { MiAnnouncement } from '@/models/Announcement.js'; @@ -69,7 +68,6 @@ import { MiUserPublickey } from '@/models/UserPublickey.js'; import { MiUserSecurityKey } from '@/models/UserSecurityKey.js'; import { MiUserMemo } from '@/models/UserMemo.js'; import { MiWebhook } from '@/models/Webhook.js'; -import { MiSystemWebhook } from '@/models/SystemWebhook.js'; import { MiChannel } from '@/models/Channel.js'; import { MiRetentionAggregation } from '@/models/RetentionAggregation.js'; import { MiRole } from '@/models/Role.js'; @@ -146,7 +144,6 @@ export const miRepository = { export { MiAbuseUserReport, - MiAbuseReportNotificationRecipient, MiAccessToken, MiAd, MiAnnouncement, @@ -204,7 +201,6 @@ export { MiUserPublickey, MiUserSecurityKey, MiWebhook, - MiSystemWebhook, MiChannel, MiRetentionAggregation, MiRole, @@ -217,7 +213,6 @@ export { }; export type AbuseUserReportsRepository = Repository & MiRepository; -export type AbuseReportNotificationRecipientRepository = Repository & MiRepository; export type AccessTokensRepository = Repository & MiRepository; export type AdsRepository = Repository & MiRepository; export type AnnouncementsRepository = Repository & MiRepository; @@ -275,7 +270,6 @@ export type UserProfilesRepository = Repository & MiRepository & MiRepository; export type UserSecurityKeysRepository = Repository & MiRepository; export type WebhooksRepository = Repository & MiRepository; -export type SystemWebhooksRepository = Repository & MiRepository; export type ChannelsRepository = Repository & MiRepository; export type RetentionAggregationsRepository = Repository & MiRepository; export type RolesRepository = Repository & MiRepository; diff --git a/packages/backend/src/models/json-schema/abuse-report-notification-recipient.ts b/packages/backend/src/models/json-schema/abuse-report-notification-recipient.ts deleted file mode 100644 index 6215f0f5a202..000000000000 --- a/packages/backend/src/models/json-schema/abuse-report-notification-recipient.ts +++ /dev/null @@ -1,50 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -export const packedAbuseReportNotificationRecipientSchema = { - type: 'object', - properties: { - id: { - type: 'string', - optional: false, nullable: false, - }, - isActive: { - type: 'boolean', - optional: false, nullable: false, - }, - updatedAt: { - type: 'string', - format: 'date-time', - optional: false, nullable: false, - }, - name: { - type: 'string', - optional: false, nullable: false, - }, - method: { - type: 'string', - optional: false, nullable: false, - enum: ['email', 'webhook'], - }, - userId: { - type: 'string', - optional: true, nullable: false, - }, - user: { - type: 'object', - optional: true, nullable: false, - ref: 'UserLite', - }, - systemWebhookId: { - type: 'string', - optional: true, nullable: false, - }, - systemWebhook: { - type: 'object', - optional: true, nullable: false, - ref: 'SystemWebhook', - }, - }, -} as const; diff --git a/packages/backend/src/models/json-schema/system-webhook.ts b/packages/backend/src/models/json-schema/system-webhook.ts deleted file mode 100644 index d83065a74329..000000000000 --- a/packages/backend/src/models/json-schema/system-webhook.ts +++ /dev/null @@ -1,54 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { systemWebhookEventTypes } from '@/models/SystemWebhook.js'; - -export const packedSystemWebhookSchema = { - type: 'object', - properties: { - id: { - type: 'string', - optional: false, nullable: false, - }, - isActive: { - type: 'boolean', - optional: false, nullable: false, - }, - updatedAt: { - type: 'string', - format: 'date-time', - optional: false, nullable: false, - }, - latestSentAt: { - type: 'string', - format: 'date-time', - optional: false, nullable: true, - }, - latestStatus: { - type: 'number', - optional: false, nullable: true, - }, - name: { - type: 'string', - optional: false, nullable: false, - }, - on: { - type: 'array', - items: { - type: 'string', - optional: false, nullable: false, - enum: systemWebhookEventTypes, - }, - }, - url: { - type: 'string', - optional: false, nullable: false, - }, - secret: { - type: 'string', - optional: false, nullable: false, - }, - }, -} as const; diff --git a/packages/backend/src/postgres.ts b/packages/backend/src/postgres.ts index 251a03c303a7..aa2aa5e373da 100644 --- a/packages/backend/src/postgres.ts +++ b/packages/backend/src/postgres.ts @@ -5,12 +5,13 @@ // https://github.com/typeorm/typeorm/issues/2400 import pg from 'pg'; +pg.types.setTypeParser(20, Number); + import { DataSource, Logger } from 'typeorm'; import * as highlight from 'cli-highlight'; import { entities as charts } from '@/core/chart/entities.js'; import { MiAbuseUserReport } from '@/models/AbuseUserReport.js'; -import { MiAbuseReportNotificationRecipient } from '@/models/AbuseReportNotificationRecipient.js'; import { MiAccessToken } from '@/models/AccessToken.js'; import { MiAd } from '@/models/Ad.js'; import { MiAnnouncement } from '@/models/Announcement.js'; @@ -68,7 +69,6 @@ import { MiUserProfile } from '@/models/UserProfile.js'; import { MiUserPublickey } from '@/models/UserPublickey.js'; import { MiUserSecurityKey } from '@/models/UserSecurityKey.js'; import { MiWebhook } from '@/models/Webhook.js'; -import { MiSystemWebhook } from '@/models/SystemWebhook.js'; import { MiChannel } from '@/models/Channel.js'; import { MiRetentionAggregation } from '@/models/RetentionAggregation.js'; import { MiRole } from '@/models/Role.js'; @@ -83,8 +83,6 @@ import { Config } from '@/config.js'; import MisskeyLogger from '@/logger.js'; import { bindThis } from '@/decorators.js'; -pg.types.setTypeParser(20, Number); - export const dbLogger = new MisskeyLogger('db'); const sqlLogger = dbLogger.createSubLogger('sql', 'gray'); @@ -169,7 +167,6 @@ export const entities = [ MiHashtag, MiSwSubscription, MiAbuseUserReport, - MiAbuseReportNotificationRecipient, MiRegistrationTicket, MiSignin, MiModerationLog, @@ -188,7 +185,6 @@ export const entities = [ MiPasswordResetRequest, MiUserPending, MiWebhook, - MiSystemWebhook, MiUserIp, MiRetentionAggregation, MiRole, diff --git a/packages/backend/src/queue/QueueProcessorModule.ts b/packages/backend/src/queue/QueueProcessorModule.ts index a1fd38fcc58c..808615899769 100644 --- a/packages/backend/src/queue/QueueProcessorModule.ts +++ b/packages/backend/src/queue/QueueProcessorModule.ts @@ -11,8 +11,7 @@ import { QueueProcessorService } from './QueueProcessorService.js'; import { DeliverProcessorService } from './processors/DeliverProcessorService.js'; import { EndedPollNotificationProcessorService } from './processors/EndedPollNotificationProcessorService.js'; import { InboxProcessorService } from './processors/InboxProcessorService.js'; -import { UserWebhookDeliverProcessorService } from './processors/UserWebhookDeliverProcessorService.js'; -import { SystemWebhookDeliverProcessorService } from './processors/SystemWebhookDeliverProcessorService.js'; +import { WebhookDeliverProcessorService } from './processors/WebhookDeliverProcessorService.js'; import { CheckExpiredMutingsProcessorService } from './processors/CheckExpiredMutingsProcessorService.js'; import { CleanChartsProcessorService } from './processors/CleanChartsProcessorService.js'; import { CleanProcessorService } from './processors/CleanProcessorService.js'; @@ -72,8 +71,7 @@ import { RelationshipProcessorService } from './processors/RelationshipProcessor DeleteFileProcessorService, CleanRemoteFilesProcessorService, RelationshipProcessorService, - UserWebhookDeliverProcessorService, - SystemWebhookDeliverProcessorService, + WebhookDeliverProcessorService, EndedPollNotificationProcessorService, DeliverProcessorService, InboxProcessorService, diff --git a/packages/backend/src/queue/QueueProcessorService.ts b/packages/backend/src/queue/QueueProcessorService.ts index 7bd74f3210f8..7bfe1f4caa47 100644 --- a/packages/backend/src/queue/QueueProcessorService.ts +++ b/packages/backend/src/queue/QueueProcessorService.ts @@ -10,8 +10,7 @@ import type { Config } from '@/config.js'; import { DI } from '@/di-symbols.js'; import type Logger from '@/logger.js'; import { bindThis } from '@/decorators.js'; -import { UserWebhookDeliverProcessorService } from './processors/UserWebhookDeliverProcessorService.js'; -import { SystemWebhookDeliverProcessorService } from './processors/SystemWebhookDeliverProcessorService.js'; +import { WebhookDeliverProcessorService } from './processors/WebhookDeliverProcessorService.js'; import { EndedPollNotificationProcessorService } from './processors/EndedPollNotificationProcessorService.js'; import { DeliverProcessorService } from './processors/DeliverProcessorService.js'; import { InboxProcessorService } from './processors/InboxProcessorService.js'; @@ -77,8 +76,7 @@ export class QueueProcessorService implements OnApplicationShutdown { private dbQueueWorker: Bull.Worker; private deliverQueueWorker: Bull.Worker; private inboxQueueWorker: Bull.Worker; - private userWebhookDeliverQueueWorker: Bull.Worker; - private systemWebhookDeliverQueueWorker: Bull.Worker; + private webhookDeliverQueueWorker: Bull.Worker; private relationshipQueueWorker: Bull.Worker; private objectStorageQueueWorker: Bull.Worker; private endedPollNotificationQueueWorker: Bull.Worker; @@ -88,8 +86,7 @@ export class QueueProcessorService implements OnApplicationShutdown { private config: Config, private queueLoggerService: QueueLoggerService, - private userWebhookDeliverProcessorService: UserWebhookDeliverProcessorService, - private systemWebhookDeliverProcessorService: SystemWebhookDeliverProcessorService, + private webhookDeliverProcessorService: WebhookDeliverProcessorService, private endedPollNotificationProcessorService: EndedPollNotificationProcessorService, private deliverProcessorService: DeliverProcessorService, private inboxProcessorService: InboxProcessorService, @@ -163,13 +160,13 @@ export class QueueProcessorService implements OnApplicationShutdown { autorun: false, }); - const logger = this.logger.createSubLogger('system'); + const systemLogger = this.logger.createSubLogger('system'); this.systemQueueWorker - .on('active', (job) => logger.debug(`active id=${job.id}`)) - .on('completed', (job, result) => logger.debug(`completed(${result}) id=${job.id}`)) + .on('active', (job) => systemLogger.debug(`active id=${job.id}`)) + .on('completed', (job, result) => systemLogger.debug(`completed(${result}) id=${job.id}`)) .on('failed', (job, err: Error) => { - logger.error(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) }); + systemLogger.error(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) }); if (config.sentryForBackend) { Sentry.captureMessage(`Queue: System: ${job?.name ?? '?'}: ${err.message}`, { level: 'error', @@ -177,8 +174,8 @@ export class QueueProcessorService implements OnApplicationShutdown { }); } }) - .on('error', (err: Error) => logger.error(`error ${err.stack}`, { e: renderError(err) })) - .on('stalled', (jobId) => logger.warn(`stalled id=${jobId}`)); + .on('error', (err: Error) => systemLogger.error(`error ${err.stack}`, { e: renderError(err) })) + .on('stalled', (jobId) => systemLogger.warn(`stalled id=${jobId}`)); } //#endregion @@ -220,13 +217,13 @@ export class QueueProcessorService implements OnApplicationShutdown { autorun: false, }); - const logger = this.logger.createSubLogger('db'); + const dbLogger = this.logger.createSubLogger('db'); this.dbQueueWorker - .on('active', (job) => logger.debug(`active id=${job.id}`)) - .on('completed', (job, result) => logger.debug(`completed(${result}) id=${job.id}`)) + .on('active', (job) => dbLogger.debug(`active id=${job.id}`)) + .on('completed', (job, result) => dbLogger.debug(`completed(${result}) id=${job.id}`)) .on('failed', (job, err) => { - logger.error(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) }); + dbLogger.error(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) }); if (config.sentryForBackend) { Sentry.captureMessage(`Queue: DB: ${job?.name ?? '?'}: ${err.message}`, { level: 'error', @@ -234,8 +231,8 @@ export class QueueProcessorService implements OnApplicationShutdown { }); } }) - .on('error', (err: Error) => logger.error(`error ${err.stack}`, { e: renderError(err) })) - .on('stalled', (jobId) => logger.warn(`stalled id=${jobId}`)); + .on('error', (err: Error) => dbLogger.error(`error ${err.stack}`, { e: renderError(err) })) + .on('stalled', (jobId) => dbLogger.warn(`stalled id=${jobId}`)); } //#endregion @@ -260,13 +257,13 @@ export class QueueProcessorService implements OnApplicationShutdown { }, }); - const logger = this.logger.createSubLogger('deliver'); + const deliverLogger = this.logger.createSubLogger('deliver'); this.deliverQueueWorker - .on('active', (job) => logger.debug(`active ${getJobInfo(job, true)} to=${job.data.to}`)) - .on('completed', (job, result) => logger.debug(`completed(${result}) ${getJobInfo(job, true)} to=${job.data.to}`)) + .on('active', (job) => deliverLogger.debug(`active ${getJobInfo(job, true)} to=${job.data.to}`)) + .on('completed', (job, result) => deliverLogger.debug(`completed(${result}) ${getJobInfo(job, true)} to=${job.data.to}`)) .on('failed', (job, err) => { - logger.error(`failed(${err.stack}) ${getJobInfo(job)} to=${job ? job.data.to : '-'}`); + deliverLogger.error(`failed(${err.stack}) ${getJobInfo(job)} to=${job ? job.data.to : '-'}`); if (config.sentryForBackend) { Sentry.captureMessage(`Queue: Deliver: ${err.message}`, { level: 'error', @@ -274,8 +271,8 @@ export class QueueProcessorService implements OnApplicationShutdown { }); } }) - .on('error', (err: Error) => logger.error(`error ${err.stack}`, { e: renderError(err) })) - .on('stalled', (jobId) => logger.warn(`stalled id=${jobId}`)); + .on('error', (err: Error) => deliverLogger.error(`error ${err.stack}`, { e: renderError(err) })) + .on('stalled', (jobId) => deliverLogger.warn(`stalled id=${jobId}`)); } //#endregion @@ -300,13 +297,13 @@ export class QueueProcessorService implements OnApplicationShutdown { }, }); - const logger = this.logger.createSubLogger('inbox'); + const inboxLogger = this.logger.createSubLogger('inbox'); this.inboxQueueWorker - .on('active', (job) => logger.debug(`active ${getJobInfo(job, true)}`)) - .on('completed', (job, result) => logger.debug(`completed(${result}) ${getJobInfo(job, true)}`)) + .on('active', (job) => inboxLogger.debug(`active ${getJobInfo(job, true)}`)) + .on('completed', (job, result) => inboxLogger.debug(`completed(${result}) ${getJobInfo(job, true)}`)) .on('failed', (job, err) => { - logger.error(`failed(${err.stack}) ${getJobInfo(job)} activity=${job ? (job.data.activity ? job.data.activity.id : 'none') : '-'}`, { job, e: renderError(err) }); + inboxLogger.error(`failed(${err.stack}) ${getJobInfo(job)} activity=${job ? (job.data.activity ? job.data.activity.id : 'none') : '-'}`, { job, e: renderError(err) }); if (config.sentryForBackend) { Sentry.captureMessage(`Queue: Inbox: ${err.message}`, { level: 'error', @@ -314,21 +311,21 @@ export class QueueProcessorService implements OnApplicationShutdown { }); } }) - .on('error', (err: Error) => logger.error(`error ${err.stack}`, { e: renderError(err) })) - .on('stalled', (jobId) => logger.warn(`stalled id=${jobId}`)); + .on('error', (err: Error) => inboxLogger.error(`error ${err.stack}`, { e: renderError(err) })) + .on('stalled', (jobId) => inboxLogger.warn(`stalled id=${jobId}`)); } //#endregion - //#region user-webhook deliver + //#region webhook deliver { - this.userWebhookDeliverQueueWorker = new Bull.Worker(QUEUE.USER_WEBHOOK_DELIVER, (job) => { + this.webhookDeliverQueueWorker = new Bull.Worker(QUEUE.WEBHOOK_DELIVER, (job) => { if (this.config.sentryForBackend) { - return Sentry.startSpan({ name: 'Queue: UserWebhookDeliver' }, () => this.userWebhookDeliverProcessorService.process(job)); + return Sentry.startSpan({ name: 'Queue: WebhookDeliver' }, () => this.webhookDeliverProcessorService.process(job)); } else { - return this.userWebhookDeliverProcessorService.process(job); + return this.webhookDeliverProcessorService.process(job); } }, { - ...baseQueueOptions(this.config, QUEUE.USER_WEBHOOK_DELIVER), + ...baseQueueOptions(this.config, QUEUE.WEBHOOK_DELIVER), autorun: false, concurrency: 64, limiter: { @@ -340,62 +337,22 @@ export class QueueProcessorService implements OnApplicationShutdown { }, }); - const logger = this.logger.createSubLogger('user-webhook'); + const webhookLogger = this.logger.createSubLogger('webhook'); - this.userWebhookDeliverQueueWorker - .on('active', (job) => logger.debug(`active ${getJobInfo(job, true)} to=${job.data.to}`)) - .on('completed', (job, result) => logger.debug(`completed(${result}) ${getJobInfo(job, true)} to=${job.data.to}`)) + this.webhookDeliverQueueWorker + .on('active', (job) => webhookLogger.debug(`active ${getJobInfo(job, true)} to=${job.data.to}`)) + .on('completed', (job, result) => webhookLogger.debug(`completed(${result}) ${getJobInfo(job, true)} to=${job.data.to}`)) .on('failed', (job, err) => { - logger.error(`failed(${err.stack}) ${getJobInfo(job)} to=${job ? job.data.to : '-'}`); + webhookLogger.error(`failed(${err.stack}) ${getJobInfo(job)} to=${job ? job.data.to : '-'}`); if (config.sentryForBackend) { - Sentry.captureMessage(`Queue: UserWebhookDeliver: ${err.message}`, { + Sentry.captureMessage(`Queue: WebhookDeliver: ${err.message}`, { level: 'error', extra: { job, err }, }); } }) - .on('error', (err: Error) => logger.error(`error ${err.stack}`, { e: renderError(err) })) - .on('stalled', (jobId) => logger.warn(`stalled id=${jobId}`)); - } - //#endregion - - //#region system-webhook deliver - { - this.systemWebhookDeliverQueueWorker = new Bull.Worker(QUEUE.SYSTEM_WEBHOOK_DELIVER, (job) => { - if (this.config.sentryForBackend) { - return Sentry.startSpan({ name: 'Queue: SystemWebhookDeliver' }, () => this.systemWebhookDeliverProcessorService.process(job)); - } else { - return this.systemWebhookDeliverProcessorService.process(job); - } - }, { - ...baseQueueOptions(this.config, QUEUE.SYSTEM_WEBHOOK_DELIVER), - autorun: false, - concurrency: 16, - limiter: { - max: 16, - duration: 1000, - }, - settings: { - backoffStrategy: httpRelatedBackoff, - }, - }); - - const logger = this.logger.createSubLogger('system-webhook'); - - this.systemWebhookDeliverQueueWorker - .on('active', (job) => logger.debug(`active ${getJobInfo(job, true)} to=${job.data.to}`)) - .on('completed', (job, result) => logger.debug(`completed(${result}) ${getJobInfo(job, true)} to=${job.data.to}`)) - .on('failed', (job, err) => { - logger.error(`failed(${err.stack}) ${getJobInfo(job)} to=${job ? job.data.to : '-'}`); - if (config.sentryForBackend) { - Sentry.captureMessage(`Queue: SystemWebhookDeliver: ${err.message}`, { - level: 'error', - extra: { job, err }, - }); - } - }) - .on('error', (err: Error) => logger.error(`error ${err.stack}`, { e: renderError(err) })) - .on('stalled', (jobId) => logger.warn(`stalled id=${jobId}`)); + .on('error', (err: Error) => webhookLogger.error(`error ${err.stack}`, { e: renderError(err) })) + .on('stalled', (jobId) => webhookLogger.warn(`stalled id=${jobId}`)); } //#endregion @@ -427,13 +384,13 @@ export class QueueProcessorService implements OnApplicationShutdown { }, }); - const logger = this.logger.createSubLogger('relationship'); + const relationshipLogger = this.logger.createSubLogger('relationship'); this.relationshipQueueWorker - .on('active', (job) => logger.debug(`active id=${job.id}`)) - .on('completed', (job, result) => logger.debug(`completed(${result}) id=${job.id}`)) + .on('active', (job) => relationshipLogger.debug(`active id=${job.id}`)) + .on('completed', (job, result) => relationshipLogger.debug(`completed(${result}) id=${job.id}`)) .on('failed', (job, err) => { - logger.error(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) }); + relationshipLogger.error(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) }); if (config.sentryForBackend) { Sentry.captureMessage(`Queue: Relationship: ${job?.name ?? '?'}: ${err.message}`, { level: 'error', @@ -441,8 +398,8 @@ export class QueueProcessorService implements OnApplicationShutdown { }); } }) - .on('error', (err: Error) => logger.error(`error ${err.stack}`, { e: renderError(err) })) - .on('stalled', (jobId) => logger.warn(`stalled id=${jobId}`)); + .on('error', (err: Error) => relationshipLogger.error(`error ${err.stack}`, { e: renderError(err) })) + .on('stalled', (jobId) => relationshipLogger.warn(`stalled id=${jobId}`)); } //#endregion @@ -468,13 +425,13 @@ export class QueueProcessorService implements OnApplicationShutdown { concurrency: 16, }); - const logger = this.logger.createSubLogger('objectStorage'); + const objectStorageLogger = this.logger.createSubLogger('objectStorage'); this.objectStorageQueueWorker - .on('active', (job) => logger.debug(`active id=${job.id}`)) - .on('completed', (job, result) => logger.debug(`completed(${result}) id=${job.id}`)) + .on('active', (job) => objectStorageLogger.debug(`active id=${job.id}`)) + .on('completed', (job, result) => objectStorageLogger.debug(`completed(${result}) id=${job.id}`)) .on('failed', (job, err) => { - logger.error(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) }); + objectStorageLogger.error(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) }); if (config.sentryForBackend) { Sentry.captureMessage(`Queue: ObjectStorage: ${job?.name ?? '?'}: ${err.message}`, { level: 'error', @@ -482,8 +439,8 @@ export class QueueProcessorService implements OnApplicationShutdown { }); } }) - .on('error', (err: Error) => logger.error(`error ${err.stack}`, { e: renderError(err) })) - .on('stalled', (jobId) => logger.warn(`stalled id=${jobId}`)); + .on('error', (err: Error) => objectStorageLogger.error(`error ${err.stack}`, { e: renderError(err) })) + .on('stalled', (jobId) => objectStorageLogger.warn(`stalled id=${jobId}`)); } //#endregion @@ -510,8 +467,7 @@ export class QueueProcessorService implements OnApplicationShutdown { this.dbQueueWorker.run(), this.deliverQueueWorker.run(), this.inboxQueueWorker.run(), - this.userWebhookDeliverQueueWorker.run(), - this.systemWebhookDeliverQueueWorker.run(), + this.webhookDeliverQueueWorker.run(), this.relationshipQueueWorker.run(), this.objectStorageQueueWorker.run(), this.endedPollNotificationQueueWorker.run(), @@ -525,8 +481,7 @@ export class QueueProcessorService implements OnApplicationShutdown { this.dbQueueWorker.close(), this.deliverQueueWorker.close(), this.inboxQueueWorker.close(), - this.userWebhookDeliverQueueWorker.close(), - this.systemWebhookDeliverQueueWorker.close(), + this.webhookDeliverQueueWorker.close(), this.relationshipQueueWorker.close(), this.objectStorageQueueWorker.close(), this.endedPollNotificationQueueWorker.close(), diff --git a/packages/backend/src/queue/const.ts b/packages/backend/src/queue/const.ts index 67f689b61849..132e9166121c 100644 --- a/packages/backend/src/queue/const.ts +++ b/packages/backend/src/queue/const.ts @@ -14,8 +14,7 @@ export const QUEUE = { DB: 'db', RELATIONSHIP: 'relationship', OBJECT_STORAGE: 'objectStorage', - USER_WEBHOOK_DELIVER: 'userWebhookDeliver', - SYSTEM_WEBHOOK_DELIVER: 'systemWebhookDeliver', + WEBHOOK_DELIVER: 'webhookDeliver', }; export function baseQueueOptions(config: Config, queueName: typeof QUEUE[keyof typeof QUEUE]): Bull.QueueOptions { diff --git a/packages/backend/src/queue/processors/SystemWebhookDeliverProcessorService.ts b/packages/backend/src/queue/processors/SystemWebhookDeliverProcessorService.ts deleted file mode 100644 index f6bef5268456..000000000000 --- a/packages/backend/src/queue/processors/SystemWebhookDeliverProcessorService.ts +++ /dev/null @@ -1,87 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { Inject, Injectable } from '@nestjs/common'; -import * as Bull from 'bullmq'; -import { DI } from '@/di-symbols.js'; -import type { SystemWebhooksRepository } from '@/models/_.js'; -import type { Config } from '@/config.js'; -import type Logger from '@/logger.js'; -import { HttpRequestService } from '@/core/HttpRequestService.js'; -import { StatusError } from '@/misc/status-error.js'; -import { bindThis } from '@/decorators.js'; -import { QueueLoggerService } from '../QueueLoggerService.js'; -import { SystemWebhookDeliverJobData } from '../types.js'; - -@Injectable() -export class SystemWebhookDeliverProcessorService { - private logger: Logger; - - constructor( - @Inject(DI.config) - private config: Config, - - @Inject(DI.systemWebhooksRepository) - private systemWebhooksRepository: SystemWebhooksRepository, - - private httpRequestService: HttpRequestService, - private queueLoggerService: QueueLoggerService, - ) { - this.logger = this.queueLoggerService.logger.createSubLogger('webhook'); - } - - @bindThis - public async process(job: Bull.Job): Promise { - try { - this.logger.debug(`delivering ${job.data.webhookId}`); - - const res = await this.httpRequestService.send(job.data.to, { - method: 'POST', - headers: { - 'User-Agent': 'Misskey-Hooks', - 'X-Misskey-Host': this.config.host, - 'X-Misskey-Hook-Id': job.data.webhookId, - 'X-Misskey-Hook-Secret': job.data.secret, - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - server: this.config.url, - hookId: job.data.webhookId, - eventId: job.data.eventId, - createdAt: job.data.createdAt, - type: job.data.type, - body: job.data.content, - }), - }); - - this.systemWebhooksRepository.update({ id: job.data.webhookId }, { - latestSentAt: new Date(), - latestStatus: res.status, - }); - - return 'Success'; - } catch (res) { - this.logger.error(res as Error); - - this.systemWebhooksRepository.update({ id: job.data.webhookId }, { - latestSentAt: new Date(), - latestStatus: res instanceof StatusError ? res.statusCode : 1, - }); - - if (res instanceof StatusError) { - // 4xx - if (!res.isRetryable) { - throw new Bull.UnrecoverableError(`${res.statusCode} ${res.statusMessage}`); - } - - // 5xx etc. - throw new Error(`${res.statusCode} ${res.statusMessage}`); - } else { - // DNS error, socket error, timeout ... - throw res; - } - } - } -} diff --git a/packages/backend/src/queue/processors/UserWebhookDeliverProcessorService.ts b/packages/backend/src/queue/processors/WebhookDeliverProcessorService.ts similarity index 92% rename from packages/backend/src/queue/processors/UserWebhookDeliverProcessorService.ts rename to packages/backend/src/queue/processors/WebhookDeliverProcessorService.ts index 9ec630ef7047..8c260c0137ce 100644 --- a/packages/backend/src/queue/processors/UserWebhookDeliverProcessorService.ts +++ b/packages/backend/src/queue/processors/WebhookDeliverProcessorService.ts @@ -13,10 +13,10 @@ import { HttpRequestService } from '@/core/HttpRequestService.js'; import { StatusError } from '@/misc/status-error.js'; import { bindThis } from '@/decorators.js'; import { QueueLoggerService } from '../QueueLoggerService.js'; -import { UserWebhookDeliverJobData } from '../types.js'; +import type { WebhookDeliverJobData } from '../types.js'; @Injectable() -export class UserWebhookDeliverProcessorService { +export class WebhookDeliverProcessorService { private logger: Logger; constructor( @@ -33,7 +33,7 @@ export class UserWebhookDeliverProcessorService { } @bindThis - public async process(job: Bull.Job): Promise { + public async process(job: Bull.Job): Promise { try { this.logger.debug(`delivering ${job.data.webhookId}`); diff --git a/packages/backend/src/queue/types.ts b/packages/backend/src/queue/types.ts index a4077a0547ea..ce57ba745eb4 100644 --- a/packages/backend/src/queue/types.ts +++ b/packages/backend/src/queue/types.ts @@ -106,17 +106,7 @@ export type EndedPollNotificationJobData = { noteId: MiNote['id']; }; -export type SystemWebhookDeliverJobData = { - type: string; - content: unknown; - webhookId: MiWebhook['id']; - to: string; - secret: string; - createdAt: number; - eventId: string; -}; - -export type UserWebhookDeliverJobData = { +export type WebhookDeliverJobData = { type: string; content: unknown; webhookId: MiWebhook['id']; diff --git a/packages/backend/src/server/api/EndpointsModule.ts b/packages/backend/src/server/api/EndpointsModule.ts index 41576bedaae7..c645f4bcc61c 100644 --- a/packages/backend/src/server/api/EndpointsModule.ts +++ b/packages/backend/src/server/api/EndpointsModule.ts @@ -6,13 +6,8 @@ import { Module } from '@nestjs/common'; import { CoreModule } from '@/core/CoreModule.js'; -import * as ep___admin_abuseReport_notificationRecipient_list from '@/server/api/endpoints/admin/abuse-report/notification-recipient/list.js'; -import * as ep___admin_abuseReport_notificationRecipient_show from '@/server/api/endpoints/admin/abuse-report/notification-recipient/show.js'; -import * as ep___admin_abuseReport_notificationRecipient_create from '@/server/api/endpoints/admin/abuse-report/notification-recipient/create.js'; -import * as ep___admin_abuseReport_notificationRecipient_update from '@/server/api/endpoints/admin/abuse-report/notification-recipient/update.js'; -import * as ep___admin_abuseReport_notificationRecipient_delete from '@/server/api/endpoints/admin/abuse-report/notification-recipient/delete.js'; -import * as ep___admin_abuseUserReports from './endpoints/admin/abuse-user-reports.js'; import * as ep___admin_meta from './endpoints/admin/meta.js'; +import * as ep___admin_abuseUserReports from './endpoints/admin/abuse-user-reports.js'; import * as ep___admin_accounts_create from './endpoints/admin/accounts/create.js'; import * as ep___admin_accounts_delete from './endpoints/admin/accounts/delete.js'; import * as ep___admin_accounts_findByEmail from './endpoints/admin/accounts/find-by-email.js'; @@ -87,11 +82,6 @@ import * as ep___admin_roles_assign from './endpoints/admin/roles/assign.js'; import * as ep___admin_roles_unassign from './endpoints/admin/roles/unassign.js'; import * as ep___admin_roles_updateDefaultPolicies from './endpoints/admin/roles/update-default-policies.js'; import * as ep___admin_roles_users from './endpoints/admin/roles/users.js'; -import * as ep___admin_systemWebhook_create from './endpoints/admin/system-webhook/create.js'; -import * as ep___admin_systemWebhook_delete from './endpoints/admin/system-webhook/delete.js'; -import * as ep___admin_systemWebhook_list from './endpoints/admin/system-webhook/list.js'; -import * as ep___admin_systemWebhook_show from './endpoints/admin/system-webhook/show.js'; -import * as ep___admin_systemWebhook_update from './endpoints/admin/system-webhook/update.js'; import * as ep___announcements from './endpoints/announcements.js'; import * as ep___announcements_show from './endpoints/announcements/show.js'; import * as ep___antennas_create from './endpoints/antennas/create.js'; @@ -391,11 +381,6 @@ import type { Provider } from '@nestjs/common'; const $admin_meta: Provider = { provide: 'ep:admin/meta', useClass: ep___admin_meta.default }; const $admin_abuseUserReports: Provider = { provide: 'ep:admin/abuse-user-reports', useClass: ep___admin_abuseUserReports.default }; -const $admin_abuseReport_notificationRecipient_list: Provider = { provide: 'ep:admin/abuse-report/notification-recipient/list', useClass: ep___admin_abuseReport_notificationRecipient_list.default }; -const $admin_abuseReport_notificationRecipient_show: Provider = { provide: 'ep:admin/abuse-report/notification-recipient/show', useClass: ep___admin_abuseReport_notificationRecipient_show.default }; -const $admin_abuseReport_notificationRecipient_create: Provider = { provide: 'ep:admin/abuse-report/notification-recipient/create', useClass: ep___admin_abuseReport_notificationRecipient_create.default }; -const $admin_abuseReport_notificationRecipient_update: Provider = { provide: 'ep:admin/abuse-report/notification-recipient/update', useClass: ep___admin_abuseReport_notificationRecipient_update.default }; -const $admin_abuseReport_notificationRecipient_delete: Provider = { provide: 'ep:admin/abuse-report/notification-recipient/delete', useClass: ep___admin_abuseReport_notificationRecipient_delete.default }; const $admin_accounts_create: Provider = { provide: 'ep:admin/accounts/create', useClass: ep___admin_accounts_create.default }; const $admin_accounts_delete: Provider = { provide: 'ep:admin/accounts/delete', useClass: ep___admin_accounts_delete.default }; const $admin_accounts_findByEmail: Provider = { provide: 'ep:admin/accounts/find-by-email', useClass: ep___admin_accounts_findByEmail.default }; @@ -470,11 +455,6 @@ const $admin_roles_assign: Provider = { provide: 'ep:admin/roles/assign', useCla const $admin_roles_unassign: Provider = { provide: 'ep:admin/roles/unassign', useClass: ep___admin_roles_unassign.default }; const $admin_roles_updateDefaultPolicies: Provider = { provide: 'ep:admin/roles/update-default-policies', useClass: ep___admin_roles_updateDefaultPolicies.default }; const $admin_roles_users: Provider = { provide: 'ep:admin/roles/users', useClass: ep___admin_roles_users.default }; -const $admin_systemWebhook_create: Provider = { provide: 'ep:admin/system-webhook/create', useClass: ep___admin_systemWebhook_create.default }; -const $admin_systemWebhook_delete: Provider = { provide: 'ep:admin/system-webhook/delete', useClass: ep___admin_systemWebhook_delete.default }; -const $admin_systemWebhook_list: Provider = { provide: 'ep:admin/system-webhook/list', useClass: ep___admin_systemWebhook_list.default }; -const $admin_systemWebhook_show: Provider = { provide: 'ep:admin/system-webhook/show', useClass: ep___admin_systemWebhook_show.default }; -const $admin_systemWebhook_update: Provider = { provide: 'ep:admin/system-webhook/update', useClass: ep___admin_systemWebhook_update.default }; const $announcements: Provider = { provide: 'ep:announcements', useClass: ep___announcements.default }; const $announcements_show: Provider = { provide: 'ep:announcements/show', useClass: ep___announcements_show.default }; const $antennas_create: Provider = { provide: 'ep:antennas/create', useClass: ep___antennas_create.default }; @@ -778,11 +758,6 @@ const $reversi_verify: Provider = { provide: 'ep:reversi/verify', useClass: ep__ ApiLoggerService, $admin_meta, $admin_abuseUserReports, - $admin_abuseReport_notificationRecipient_list, - $admin_abuseReport_notificationRecipient_show, - $admin_abuseReport_notificationRecipient_create, - $admin_abuseReport_notificationRecipient_update, - $admin_abuseReport_notificationRecipient_delete, $admin_accounts_create, $admin_accounts_delete, $admin_accounts_findByEmail, @@ -857,11 +832,6 @@ const $reversi_verify: Provider = { provide: 'ep:reversi/verify', useClass: ep__ $admin_roles_unassign, $admin_roles_updateDefaultPolicies, $admin_roles_users, - $admin_systemWebhook_create, - $admin_systemWebhook_delete, - $admin_systemWebhook_list, - $admin_systemWebhook_show, - $admin_systemWebhook_update, $announcements, $announcements_show, $antennas_create, @@ -1159,11 +1129,6 @@ const $reversi_verify: Provider = { provide: 'ep:reversi/verify', useClass: ep__ exports: [ $admin_meta, $admin_abuseUserReports, - $admin_abuseReport_notificationRecipient_list, - $admin_abuseReport_notificationRecipient_show, - $admin_abuseReport_notificationRecipient_create, - $admin_abuseReport_notificationRecipient_update, - $admin_abuseReport_notificationRecipient_delete, $admin_accounts_create, $admin_accounts_delete, $admin_accounts_findByEmail, @@ -1238,11 +1203,6 @@ const $reversi_verify: Provider = { provide: 'ep:reversi/verify', useClass: ep__ $admin_roles_unassign, $admin_roles_updateDefaultPolicies, $admin_roles_users, - $admin_systemWebhook_create, - $admin_systemWebhook_delete, - $admin_systemWebhook_list, - $admin_systemWebhook_show, - $admin_systemWebhook_update, $announcements, $announcements_show, $antennas_create, diff --git a/packages/backend/src/server/api/endpoints.ts b/packages/backend/src/server/api/endpoints.ts index 3dfb7fdad4c2..a38c62f35a9d 100644 --- a/packages/backend/src/server/api/endpoints.ts +++ b/packages/backend/src/server/api/endpoints.ts @@ -6,18 +6,8 @@ import { permissions } from 'misskey-js'; import type { KeyOf, Schema } from '@/misc/json-schema.js'; -import * as ep___admin_abuseReport_notificationRecipient_list - from '@/server/api/endpoints/admin/abuse-report/notification-recipient/list.js'; -import * as ep___admin_abuseReport_notificationRecipient_show - from '@/server/api/endpoints/admin/abuse-report/notification-recipient/show.js'; -import * as ep___admin_abuseReport_notificationRecipient_create - from '@/server/api/endpoints/admin/abuse-report/notification-recipient/create.js'; -import * as ep___admin_abuseReport_notificationRecipient_update - from '@/server/api/endpoints/admin/abuse-report/notification-recipient/update.js'; -import * as ep___admin_abuseReport_notificationRecipient_delete - from '@/server/api/endpoints/admin/abuse-report/notification-recipient/delete.js'; -import * as ep___admin_abuseUserReports from './endpoints/admin/abuse-user-reports.js'; import * as ep___admin_meta from './endpoints/admin/meta.js'; +import * as ep___admin_abuseUserReports from './endpoints/admin/abuse-user-reports.js'; import * as ep___admin_accounts_create from './endpoints/admin/accounts/create.js'; import * as ep___admin_accounts_delete from './endpoints/admin/accounts/delete.js'; import * as ep___admin_accounts_findByEmail from './endpoints/admin/accounts/find-by-email.js'; @@ -54,8 +44,7 @@ import * as ep___admin_emoji_setCategoryBulk from './endpoints/admin/emoji/set-c import * as ep___admin_emoji_setLicenseBulk from './endpoints/admin/emoji/set-license-bulk.js'; import * as ep___admin_emoji_update from './endpoints/admin/emoji/update.js'; import * as ep___admin_federation_deleteAllFiles from './endpoints/admin/federation/delete-all-files.js'; -import * as ep___admin_federation_refreshRemoteInstanceMetadata - from './endpoints/admin/federation/refresh-remote-instance-metadata.js'; +import * as ep___admin_federation_refreshRemoteInstanceMetadata from './endpoints/admin/federation/refresh-remote-instance-metadata.js'; import * as ep___admin_federation_removeAllFollowing from './endpoints/admin/federation/remove-all-following.js'; import * as ep___admin_federation_updateInstance from './endpoints/admin/federation/update-instance.js'; import * as ep___admin_getIndexStats from './endpoints/admin/get-index-stats.js'; @@ -93,11 +82,6 @@ import * as ep___admin_roles_assign from './endpoints/admin/roles/assign.js'; import * as ep___admin_roles_unassign from './endpoints/admin/roles/unassign.js'; import * as ep___admin_roles_updateDefaultPolicies from './endpoints/admin/roles/update-default-policies.js'; import * as ep___admin_roles_users from './endpoints/admin/roles/users.js'; -import * as ep___admin_systemWebhook_create from './endpoints/admin/system-webhook/create.js'; -import * as ep___admin_systemWebhook_delete from './endpoints/admin/system-webhook/delete.js'; -import * as ep___admin_systemWebhook_list from './endpoints/admin/system-webhook/list.js'; -import * as ep___admin_systemWebhook_show from './endpoints/admin/system-webhook/show.js'; -import * as ep___admin_systemWebhook_update from './endpoints/admin/system-webhook/update.js'; import * as ep___announcements from './endpoints/announcements.js'; import * as ep___announcements_show from './endpoints/announcements/show.js'; import * as ep___antennas_create from './endpoints/antennas/create.js'; @@ -395,11 +379,6 @@ import * as ep___reversi_verify from './endpoints/reversi/verify.js'; const eps = [ ['admin/meta', ep___admin_meta], ['admin/abuse-user-reports', ep___admin_abuseUserReports], - ['admin/abuse-report/notification-recipient/list', ep___admin_abuseReport_notificationRecipient_list], - ['admin/abuse-report/notification-recipient/show', ep___admin_abuseReport_notificationRecipient_show], - ['admin/abuse-report/notification-recipient/create', ep___admin_abuseReport_notificationRecipient_create], - ['admin/abuse-report/notification-recipient/update', ep___admin_abuseReport_notificationRecipient_update], - ['admin/abuse-report/notification-recipient/delete', ep___admin_abuseReport_notificationRecipient_delete], ['admin/accounts/create', ep___admin_accounts_create], ['admin/accounts/delete', ep___admin_accounts_delete], ['admin/accounts/find-by-email', ep___admin_accounts_findByEmail], @@ -474,11 +453,6 @@ const eps = [ ['admin/roles/unassign', ep___admin_roles_unassign], ['admin/roles/update-default-policies', ep___admin_roles_updateDefaultPolicies], ['admin/roles/users', ep___admin_roles_users], - ['admin/system-webhook/create', ep___admin_systemWebhook_create], - ['admin/system-webhook/delete', ep___admin_systemWebhook_delete], - ['admin/system-webhook/list', ep___admin_systemWebhook_list], - ['admin/system-webhook/show', ep___admin_systemWebhook_show], - ['admin/system-webhook/update', ep___admin_systemWebhook_update], ['announcements', ep___announcements], ['announcements/show', ep___announcements_show], ['antennas/create', ep___antennas_create], @@ -899,12 +873,8 @@ export interface IEndpoint { const endpoints: IEndpoint[] = (eps as [string, any]).map(([name, ep]) => { return { name: name, - get meta() { - return ep.meta ?? {}; - }, - get params() { - return ep.paramDef; - }, + get meta() { return ep.meta ?? {}; }, + get params() { return ep.paramDef; }, }; }); diff --git a/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/create.ts b/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/create.ts deleted file mode 100644 index bdfbcba51897..000000000000 --- a/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/create.ts +++ /dev/null @@ -1,122 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { Inject, Injectable } from '@nestjs/common'; -import { Endpoint } from '@/server/api/endpoint-base.js'; -import { ApiError } from '@/server/api/error.js'; -import { - AbuseReportNotificationRecipientEntityService, -} from '@/core/entities/AbuseReportNotificationRecipientEntityService.js'; -import { AbuseReportNotificationService } from '@/core/AbuseReportNotificationService.js'; -import { DI } from '@/di-symbols.js'; -import type { UserProfilesRepository } from '@/models/_.js'; - -export const meta = { - tags: ['admin', 'abuse-report', 'notification-recipient'], - - requireCredential: true, - requireModerator: true, - secure: true, - kind: 'write:admin:abuse-report:notification-recipient', - - res: { - type: 'object', - ref: 'AbuseReportNotificationRecipient', - }, - - errors: { - correlationCheckEmail: { - message: 'If "method" is email, "userId" must be set.', - code: 'CORRELATION_CHECK_EMAIL', - id: '348bb8ae-575a-6fe9-4327-5811999def8f', - httpStatusCode: 400, - }, - correlationCheckWebhook: { - message: 'If "method" is webhook, "systemWebhookId" must be set.', - code: 'CORRELATION_CHECK_WEBHOOK', - id: 'b0c15051-de2d-29ef-260c-9585cddd701a', - httpStatusCode: 400, - }, - emailAddressNotSet: { - message: 'Email address is not set.', - code: 'EMAIL_ADDRESS_NOT_SET', - id: '7cc1d85e-2f58-fc31-b644-3de8d0d3421f', - httpStatusCode: 400, - }, - }, -} as const; - -export const paramDef = { - type: 'object', - properties: { - isActive: { - type: 'boolean', - }, - name: { - type: 'string', - minLength: 1, - maxLength: 255, - }, - method: { - type: 'string', - enum: ['email', 'webhook'], - }, - userId: { - type: 'string', - format: 'misskey:id', - }, - systemWebhookId: { - type: 'string', - format: 'misskey:id', - }, - }, - required: [ - 'isActive', - 'name', - 'method', - ], -} as const; - -@Injectable() -export default class extends Endpoint { // eslint-disable-line import/no-default-export - constructor( - @Inject(DI.userProfilesRepository) - private userProfilesRepository: UserProfilesRepository, - private abuseReportNotificationService: AbuseReportNotificationService, - private abuseReportNotificationRecipientEntityService: AbuseReportNotificationRecipientEntityService, - ) { - super(meta, paramDef, async (ps, me) => { - if (ps.method === 'email') { - const userProfile = await this.userProfilesRepository.findOneBy({ userId: ps.userId }); - if (!ps.userId || !userProfile) { - throw new ApiError(meta.errors.correlationCheckEmail); - } - - if (!userProfile.email || !userProfile.emailVerified) { - throw new ApiError(meta.errors.emailAddressNotSet); - } - } - - if (ps.method === 'webhook' && !ps.systemWebhookId) { - throw new ApiError(meta.errors.correlationCheckWebhook); - } - - const userId = ps.method === 'email' ? ps.userId : null; - const systemWebhookId = ps.method === 'webhook' ? ps.systemWebhookId : null; - const result = await this.abuseReportNotificationService.createRecipient( - { - isActive: ps.isActive, - name: ps.name, - method: ps.method, - userId: userId ?? null, - systemWebhookId: systemWebhookId ?? null, - }, - me, - ); - - return this.abuseReportNotificationRecipientEntityService.pack(result); - }); - } -} diff --git a/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/delete.ts b/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/delete.ts deleted file mode 100644 index b6dc44e09c9a..000000000000 --- a/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/delete.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { Injectable } from '@nestjs/common'; -import { Endpoint } from '@/server/api/endpoint-base.js'; -import { AbuseReportNotificationService } from '@/core/AbuseReportNotificationService.js'; - -export const meta = { - tags: ['admin', 'abuse-report', 'notification-recipient'], - - requireCredential: true, - requireModerator: true, - secure: true, - kind: 'write:admin:abuse-report:notification-recipient', -} as const; - -export const paramDef = { - type: 'object', - properties: { - id: { - type: 'string', - format: 'misskey:id', - }, - }, - required: [ - 'id', - ], -} as const; - -@Injectable() -export default class extends Endpoint { // eslint-disable-line import/no-default-export - constructor( - private abuseReportNotificationService: AbuseReportNotificationService, - ) { - super(meta, paramDef, async (ps, me) => { - await this.abuseReportNotificationService.deleteRecipient( - ps.id, - me, - ); - }); - } -} diff --git a/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/list.ts b/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/list.ts deleted file mode 100644 index dad9161a8a74..000000000000 --- a/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/list.ts +++ /dev/null @@ -1,55 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { Injectable } from '@nestjs/common'; -import { Endpoint } from '@/server/api/endpoint-base.js'; -import { - AbuseReportNotificationRecipientEntityService, -} from '@/core/entities/AbuseReportNotificationRecipientEntityService.js'; -import { AbuseReportNotificationService } from '@/core/AbuseReportNotificationService.js'; - -export const meta = { - tags: ['admin', 'abuse-report', 'notification-recipient'], - - requireCredential: true, - requireModerator: true, - secure: true, - kind: 'read:admin:abuse-report:notification-recipient', - - res: { - type: 'array', - items: { - type: 'object', - ref: 'AbuseReportNotificationRecipient', - }, - }, -} as const; - -export const paramDef = { - type: 'object', - properties: { - method: { - type: 'array', - items: { - type: 'string', - enum: ['email', 'webhook'], - }, - }, - }, - required: [], -} as const; - -@Injectable() -export default class extends Endpoint { // eslint-disable-line import/no-default-export - constructor( - private abuseReportNotificationService: AbuseReportNotificationService, - private abuseReportNotificationRecipientEntityService: AbuseReportNotificationRecipientEntityService, - ) { - super(meta, paramDef, async (ps) => { - const recipients = await this.abuseReportNotificationService.fetchRecipients({ method: ps.method }); - return this.abuseReportNotificationRecipientEntityService.packMany(recipients); - }); - } -} diff --git a/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/show.ts b/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/show.ts deleted file mode 100644 index 557798f946e0..000000000000 --- a/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/show.ts +++ /dev/null @@ -1,64 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { Injectable } from '@nestjs/common'; -import { Endpoint } from '@/server/api/endpoint-base.js'; -import { - AbuseReportNotificationRecipientEntityService, -} from '@/core/entities/AbuseReportNotificationRecipientEntityService.js'; -import { AbuseReportNotificationService } from '@/core/AbuseReportNotificationService.js'; -import { ApiError } from '@/server/api/error.js'; - -export const meta = { - tags: ['admin', 'abuse-report', 'notification-recipient'], - - requireCredential: true, - requireModerator: true, - secure: true, - kind: 'read:admin:abuse-report:notification-recipient', - - res: { - type: 'object', - ref: 'AbuseReportNotificationRecipient', - }, - - errors: { - noSuchRecipient: { - message: 'No such recipient.', - code: 'NO_SUCH_RECIPIENT', - id: '013de6a8-f757-04cb-4d73-cc2a7e3368e4', - kind: 'server', - httpStatusCode: 404, - }, - }, -} as const; - -export const paramDef = { - type: 'object', - properties: { - id: { - type: 'string', - format: 'misskey:id', - }, - }, - required: ['id'], -} as const; - -@Injectable() -export default class extends Endpoint { // eslint-disable-line import/no-default-export - constructor( - private abuseReportNotificationService: AbuseReportNotificationService, - private abuseReportNotificationRecipientEntityService: AbuseReportNotificationRecipientEntityService, - ) { - super(meta, paramDef, async (ps) => { - const recipients = await this.abuseReportNotificationService.fetchRecipients({ ids: [ps.id] }); - if (recipients.length === 0) { - throw new ApiError(meta.errors.noSuchRecipient); - } - - return this.abuseReportNotificationRecipientEntityService.pack(recipients[0]); - }); - } -} diff --git a/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/update.ts b/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/update.ts deleted file mode 100644 index bd4b4852171c..000000000000 --- a/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/update.ts +++ /dev/null @@ -1,128 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { Inject, Injectable } from '@nestjs/common'; -import { Endpoint } from '@/server/api/endpoint-base.js'; -import { ApiError } from '@/server/api/error.js'; -import { - AbuseReportNotificationRecipientEntityService, -} from '@/core/entities/AbuseReportNotificationRecipientEntityService.js'; -import { AbuseReportNotificationService } from '@/core/AbuseReportNotificationService.js'; -import { DI } from '@/di-symbols.js'; -import type { UserProfilesRepository } from '@/models/_.js'; - -export const meta = { - tags: ['admin', 'abuse-report', 'notification-recipient'], - - requireCredential: true, - requireModerator: true, - secure: true, - kind: 'write:admin:abuse-report:notification-recipient', - - res: { - type: 'object', - ref: 'AbuseReportNotificationRecipient', - }, - - errors: { - correlationCheckEmail: { - message: 'If "method" is email, "userId" must be set.', - code: 'CORRELATION_CHECK_EMAIL', - id: '348bb8ae-575a-6fe9-4327-5811999def8f', - httpStatusCode: 400, - }, - correlationCheckWebhook: { - message: 'If "method" is webhook, "systemWebhookId" must be set.', - code: 'CORRELATION_CHECK_WEBHOOK', - id: 'b0c15051-de2d-29ef-260c-9585cddd701a', - httpStatusCode: 400, - }, - emailAddressNotSet: { - message: 'Email address is not set.', - code: 'EMAIL_ADDRESS_NOT_SET', - id: '7cc1d85e-2f58-fc31-b644-3de8d0d3421f', - httpStatusCode: 400, - }, - }, -} as const; - -export const paramDef = { - type: 'object', - properties: { - id: { - type: 'string', - format: 'misskey:id', - }, - isActive: { - type: 'boolean', - }, - name: { - type: 'string', - minLength: 1, - maxLength: 255, - }, - method: { - type: 'string', - enum: ['email', 'webhook'], - }, - userId: { - type: 'string', - format: 'misskey:id', - }, - systemWebhookId: { - type: 'string', - format: 'misskey:id', - }, - }, - required: [ - 'id', - 'isActive', - 'name', - 'method', - ], -} as const; - -@Injectable() -export default class extends Endpoint { // eslint-disable-line import/no-default-export - constructor( - @Inject(DI.userProfilesRepository) - private userProfilesRepository: UserProfilesRepository, - private abuseReportNotificationService: AbuseReportNotificationService, - private abuseReportNotificationRecipientEntityService: AbuseReportNotificationRecipientEntityService, - ) { - super(meta, paramDef, async (ps, me) => { - if (ps.method === 'email') { - const userProfile = await this.userProfilesRepository.findOneBy({ userId: ps.userId }); - if (!ps.userId || !userProfile) { - throw new ApiError(meta.errors.correlationCheckEmail); - } - - if (!userProfile.email || !userProfile.emailVerified) { - throw new ApiError(meta.errors.emailAddressNotSet); - } - } - - if (ps.method === 'webhook' && !ps.systemWebhookId) { - throw new ApiError(meta.errors.correlationCheckWebhook); - } - - const userId = ps.method === 'email' ? ps.userId : null; - const systemWebhookId = ps.method === 'webhook' ? ps.systemWebhookId : null; - const result = await this.abuseReportNotificationService.updateRecipient( - { - id: ps.id, - isActive: ps.isActive, - name: ps.name, - method: ps.method, - userId: userId ?? null, - systemWebhookId: systemWebhookId ?? null, - }, - me, - ); - - return this.abuseReportNotificationRecipientEntityService.pack(result); - }); - } -} diff --git a/packages/backend/src/server/api/endpoints/admin/queue/stats.ts b/packages/backend/src/server/api/endpoints/admin/queue/stats.ts index d7f9e4eaa301..9694b3fa40a3 100644 --- a/packages/backend/src/server/api/endpoints/admin/queue/stats.ts +++ b/packages/backend/src/server/api/endpoints/admin/queue/stats.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { DbQueue, DeliverQueue, EndedPollNotificationQueue, InboxQueue, ObjectStorageQueue, SystemQueue, UserWebhookDeliverQueue, SystemWebhookDeliverQueue } from '@/core/QueueModule.js'; +import type { DbQueue, DeliverQueue, EndedPollNotificationQueue, InboxQueue, ObjectStorageQueue, SystemQueue, WebhookDeliverQueue } from '@/core/QueueModule.js'; export const meta = { tags: ['admin'], @@ -53,8 +53,7 @@ export default class extends Endpoint { // eslint- @Inject('queue:inbox') public inboxQueue: InboxQueue, @Inject('queue:db') public dbQueue: DbQueue, @Inject('queue:objectStorage') public objectStorageQueue: ObjectStorageQueue, - @Inject('queue:userWebhookDeliver') public userWebhookDeliverQueue: UserWebhookDeliverQueue, - @Inject('queue:systemWebhookDeliver') public systemWebhookDeliverQueue: SystemWebhookDeliverQueue, + @Inject('queue:webhookDeliver') public webhookDeliverQueue: WebhookDeliverQueue, ) { super(meta, paramDef, async (ps, me) => { const deliverJobCounts = await this.deliverQueue.getJobCounts(); diff --git a/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts b/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts index 9b79100fcf50..8b0456068b89 100644 --- a/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts +++ b/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts @@ -5,10 +5,12 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { AbuseUserReportsRepository } from '@/models/_.js'; +import type { UsersRepository, AbuseUserReportsRepository } from '@/models/_.js'; +import { InstanceActorService } from '@/core/InstanceActorService.js'; +import { QueueService } from '@/core/QueueService.js'; +import { ApRendererService } from '@/core/activitypub/ApRendererService.js'; import { DI } from '@/di-symbols.js'; -import { ApiError } from '@/server/api/error.js'; -import { AbuseReportService } from '@/core/AbuseReportService.js'; +import { ModerationLogService } from '@/core/ModerationLogService.js'; export const meta = { tags: ['admin'], @@ -16,16 +18,6 @@ export const meta = { requireCredential: true, requireModerator: true, kind: 'write:admin:resolve-abuse-user-report', - - errors: { - noSuchAbuseReport: { - message: 'No such abuse report.', - code: 'NO_SUCH_ABUSE_REPORT', - id: 'ac3794dd-2ce4-d878-e546-73c60c06b398', - kind: 'server', - httpStatusCode: 404, - }, - }, } as const; export const paramDef = { @@ -37,20 +29,47 @@ export const paramDef = { required: ['reportId'], } as const; +// TODO: ロジックをサービスに切り出す + @Injectable() export default class extends Endpoint { // eslint-disable-line import/no-default-export constructor( + @Inject(DI.usersRepository) + private usersRepository: UsersRepository, + @Inject(DI.abuseUserReportsRepository) private abuseUserReportsRepository: AbuseUserReportsRepository, - private abuseReportService: AbuseReportService, + + private queueService: QueueService, + private instanceActorService: InstanceActorService, + private apRendererService: ApRendererService, + private moderationLogService: ModerationLogService, ) { super(meta, paramDef, async (ps, me) => { const report = await this.abuseUserReportsRepository.findOneBy({ id: ps.reportId }); - if (!report) { - throw new ApiError(meta.errors.noSuchAbuseReport); + + if (report == null) { + throw new Error('report not found'); } - await this.abuseReportService.resolve([{ reportId: report.id, forward: ps.forward }], me); + if (ps.forward && report.targetUserHost != null) { + const actor = await this.instanceActorService.getInstanceActor(); + const targetUser = await this.usersRepository.findOneByOrFail({ id: report.targetUserId }); + + this.queueService.deliver(actor, this.apRendererService.addContext(this.apRendererService.renderFlag(actor, targetUser.uri!, report.comment)), targetUser.inbox, false); + } + + await this.abuseUserReportsRepository.update(report.id, { + resolved: true, + assigneeId: me.id, + forwarded: ps.forward && report.targetUserHost != null, + }); + + this.moderationLogService.log(me, 'resolveAbuseReport', { + reportId: report.id, + report: report, + forwarded: ps.forward && report.targetUserHost != null, + }); }); } } diff --git a/packages/backend/src/server/api/endpoints/admin/system-webhook/create.ts b/packages/backend/src/server/api/endpoints/admin/system-webhook/create.ts deleted file mode 100644 index 28071e7a3382..000000000000 --- a/packages/backend/src/server/api/endpoints/admin/system-webhook/create.ts +++ /dev/null @@ -1,85 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { Injectable } from '@nestjs/common'; -import { Endpoint } from '@/server/api/endpoint-base.js'; -import { SystemWebhookEntityService } from '@/core/entities/SystemWebhookEntityService.js'; -import { systemWebhookEventTypes } from '@/models/SystemWebhook.js'; -import { SystemWebhookService } from '@/core/SystemWebhookService.js'; - -export const meta = { - tags: ['admin', 'system-webhook'], - - requireCredential: true, - requireModerator: true, - secure: true, - kind: 'write:admin:system-webhook', - - res: { - type: 'object', - ref: 'SystemWebhook', - }, -} as const; - -export const paramDef = { - type: 'object', - properties: { - isActive: { - type: 'boolean', - }, - name: { - type: 'string', - minLength: 1, - maxLength: 255, - }, - on: { - type: 'array', - items: { - type: 'string', - enum: systemWebhookEventTypes, - }, - }, - url: { - type: 'string', - minLength: 1, - maxLength: 1024, - }, - secret: { - type: 'string', - minLength: 1, - maxLength: 1024, - }, - }, - required: [ - 'isActive', - 'name', - 'on', - 'url', - 'secret', - ], -} as const; - -@Injectable() -export default class extends Endpoint { // eslint-disable-line import/no-default-export - constructor( - private systemWebhookService: SystemWebhookService, - private systemWebhookEntityService: SystemWebhookEntityService, - ) { - super(meta, paramDef, async (ps, me) => { - const result = await this.systemWebhookService.createSystemWebhook( - { - isActive: ps.isActive, - name: ps.name, - on: ps.on, - url: ps.url, - secret: ps.secret, - }, - me, - ); - - return this.systemWebhookEntityService.pack(result); - }); - } -} diff --git a/packages/backend/src/server/api/endpoints/admin/system-webhook/delete.ts b/packages/backend/src/server/api/endpoints/admin/system-webhook/delete.ts deleted file mode 100644 index 9cdfc7e70fec..000000000000 --- a/packages/backend/src/server/api/endpoints/admin/system-webhook/delete.ts +++ /dev/null @@ -1,44 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { Injectable } from '@nestjs/common'; -import { Endpoint } from '@/server/api/endpoint-base.js'; -import { SystemWebhookService } from '@/core/SystemWebhookService.js'; - -export const meta = { - tags: ['admin', 'system-webhook'], - - requireCredential: true, - requireModerator: true, - secure: true, - kind: 'write:admin:system-webhook', -} as const; - -export const paramDef = { - type: 'object', - properties: { - id: { - type: 'string', - format: 'misskey:id', - }, - }, - required: [ - 'id', - ], -} as const; - -@Injectable() -export default class extends Endpoint { // eslint-disable-line import/no-default-export - constructor( - private systemWebhookService: SystemWebhookService, - ) { - super(meta, paramDef, async (ps, me) => { - await this.systemWebhookService.deleteSystemWebhook( - ps.id, - me, - ); - }); - } -} diff --git a/packages/backend/src/server/api/endpoints/admin/system-webhook/list.ts b/packages/backend/src/server/api/endpoints/admin/system-webhook/list.ts deleted file mode 100644 index 7a440a774ed3..000000000000 --- a/packages/backend/src/server/api/endpoints/admin/system-webhook/list.ts +++ /dev/null @@ -1,60 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { Injectable } from '@nestjs/common'; -import { Endpoint } from '@/server/api/endpoint-base.js'; -import { SystemWebhookEntityService } from '@/core/entities/SystemWebhookEntityService.js'; -import { systemWebhookEventTypes } from '@/models/SystemWebhook.js'; -import { SystemWebhookService } from '@/core/SystemWebhookService.js'; - -export const meta = { - tags: ['admin', 'system-webhook'], - - requireCredential: true, - requireModerator: true, - secure: true, - kind: 'write:admin:system-webhook', - - res: { - type: 'array', - items: { - type: 'object', - ref: 'SystemWebhook', - }, - }, -} as const; - -export const paramDef = { - type: 'object', - properties: { - isActive: { - type: 'boolean', - }, - on: { - type: 'array', - items: { - type: 'string', - enum: systemWebhookEventTypes, - }, - }, - }, - required: [], -} as const; - -@Injectable() -export default class extends Endpoint { // eslint-disable-line import/no-default-export - constructor( - private systemWebhookService: SystemWebhookService, - private systemWebhookEntityService: SystemWebhookEntityService, - ) { - super(meta, paramDef, async (ps) => { - const webhooks = await this.systemWebhookService.fetchSystemWebhooks({ - isActive: ps.isActive, - on: ps.on, - }); - return this.systemWebhookEntityService.packMany(webhooks); - }); - } -} diff --git a/packages/backend/src/server/api/endpoints/admin/system-webhook/show.ts b/packages/backend/src/server/api/endpoints/admin/system-webhook/show.ts deleted file mode 100644 index 75862c96a7d1..000000000000 --- a/packages/backend/src/server/api/endpoints/admin/system-webhook/show.ts +++ /dev/null @@ -1,62 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { Injectable } from '@nestjs/common'; -import { Endpoint } from '@/server/api/endpoint-base.js'; -import { SystemWebhookEntityService } from '@/core/entities/SystemWebhookEntityService.js'; -import { ApiError } from '@/server/api/error.js'; -import { SystemWebhookService } from '@/core/SystemWebhookService.js'; - -export const meta = { - tags: ['admin', 'system-webhook'], - - requireCredential: true, - requireModerator: true, - secure: true, - kind: 'write:admin:system-webhook', - - res: { - type: 'object', - ref: 'SystemWebhook', - }, - - errors: { - noSuchSystemWebhook: { - message: 'No such SystemWebhook.', - code: 'NO_SUCH_SYSTEM_WEBHOOK', - id: '38dd1ffe-04b4-6ff5-d8ba-4e6a6ae22c9d', - kind: 'server', - httpStatusCode: 404, - }, - }, -} as const; - -export const paramDef = { - type: 'object', - properties: { - id: { - type: 'string', - format: 'misskey:id', - }, - }, - required: ['id'], -} as const; - -@Injectable() -export default class extends Endpoint { // eslint-disable-line import/no-default-export - constructor( - private systemWebhookService: SystemWebhookService, - private systemWebhookEntityService: SystemWebhookEntityService, - ) { - super(meta, paramDef, async (ps) => { - const webhooks = await this.systemWebhookService.fetchSystemWebhooks({ ids: [ps.id] }); - if (webhooks.length === 0) { - throw new ApiError(meta.errors.noSuchSystemWebhook); - } - - return this.systemWebhookEntityService.pack(webhooks[0]); - }); - } -} diff --git a/packages/backend/src/server/api/endpoints/admin/system-webhook/update.ts b/packages/backend/src/server/api/endpoints/admin/system-webhook/update.ts deleted file mode 100644 index 8d68bb8f87d8..000000000000 --- a/packages/backend/src/server/api/endpoints/admin/system-webhook/update.ts +++ /dev/null @@ -1,91 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { Injectable } from '@nestjs/common'; -import { Endpoint } from '@/server/api/endpoint-base.js'; -import { SystemWebhookEntityService } from '@/core/entities/SystemWebhookEntityService.js'; -import { systemWebhookEventTypes } from '@/models/SystemWebhook.js'; -import { SystemWebhookService } from '@/core/SystemWebhookService.js'; - -export const meta = { - tags: ['admin', 'system-webhook'], - - requireCredential: true, - requireModerator: true, - secure: true, - kind: 'write:admin:system-webhook', - - res: { - type: 'object', - ref: 'SystemWebhook', - }, -} as const; - -export const paramDef = { - type: 'object', - properties: { - id: { - type: 'string', - format: 'misskey:id', - }, - isActive: { - type: 'boolean', - }, - name: { - type: 'string', - minLength: 1, - maxLength: 255, - }, - on: { - type: 'array', - items: { - type: 'string', - enum: systemWebhookEventTypes, - }, - }, - url: { - type: 'string', - minLength: 1, - maxLength: 1024, - }, - secret: { - type: 'string', - minLength: 1, - maxLength: 1024, - }, - }, - required: [ - 'id', - 'isActive', - 'name', - 'on', - 'url', - 'secret', - ], -} as const; - -@Injectable() -export default class extends Endpoint { // eslint-disable-line import/no-default-export - constructor( - private systemWebhookService: SystemWebhookService, - private systemWebhookEntityService: SystemWebhookEntityService, - ) { - super(meta, paramDef, async (ps, me) => { - const result = await this.systemWebhookService.updateSystemWebhook( - { - id: ps.id, - isActive: ps.isActive, - name: ps.name, - on: ps.on, - url: ps.url, - secret: ps.secret, - }, - me, - ); - - return this.systemWebhookEntityService.pack(result); - }); - } -} diff --git a/packages/backend/src/server/api/endpoints/users/report-abuse.ts b/packages/backend/src/server/api/endpoints/users/report-abuse.ts index 5ff6de37d2ca..48e14b68cca5 100644 --- a/packages/backend/src/server/api/endpoints/users/report-abuse.ts +++ b/packages/backend/src/server/api/endpoints/users/report-abuse.ts @@ -3,11 +3,17 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { Injectable } from '@nestjs/common'; +import sanitizeHtml from 'sanitize-html'; +import { Inject, Injectable } from '@nestjs/common'; +import type { AbuseUserReportsRepository } from '@/models/_.js'; +import { IdService } from '@/core/IdService.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; +import { GlobalEventService } from '@/core/GlobalEventService.js'; +import { MetaService } from '@/core/MetaService.js'; +import { EmailService } from '@/core/EmailService.js'; +import { DI } from '@/di-symbols.js'; import { GetterService } from '@/server/api/GetterService.js'; import { RoleService } from '@/core/RoleService.js'; -import { AbuseReportService } from '@/core/AbuseReportService.js'; import { ApiError } from '../../error.js'; export const meta = { @@ -51,32 +57,60 @@ export const paramDef = { @Injectable() export default class extends Endpoint { // eslint-disable-line import/no-default-export constructor( + @Inject(DI.abuseUserReportsRepository) + private abuseUserReportsRepository: AbuseUserReportsRepository, + + private idService: IdService, + private metaService: MetaService, + private emailService: EmailService, private getterService: GetterService, private roleService: RoleService, - private abuseReportService: AbuseReportService, + private globalEventService: GlobalEventService, ) { super(meta, paramDef, async (ps, me) => { // Lookup user - const targetUser = await this.getterService.getUser(ps.userId).catch(err => { + const user = await this.getterService.getUser(ps.userId).catch(err => { if (err.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser); throw err; }); - if (targetUser.id === me.id) { + if (user.id === me.id) { throw new ApiError(meta.errors.cannotReportYourself); } - if (await this.roleService.isAdministrator(targetUser)) { + if (await this.roleService.isAdministrator(user)) { throw new ApiError(meta.errors.cannotReportAdmin); } - await this.abuseReportService.report([{ - targetUserId: targetUser.id, - targetUserHost: targetUser.host, + const report = await this.abuseUserReportsRepository.insertOne({ + id: this.idService.gen(), + targetUserId: user.id, + targetUserHost: user.host, reporterId: me.id, reporterHost: null, comment: ps.comment, - }]); + }); + + // Publish event to moderators + setImmediate(async () => { + const moderators = await this.roleService.getModerators(); + + for (const moderator of moderators) { + this.globalEventService.publishAdminStream(moderator.id, 'newAbuseUserReport', { + id: report.id, + targetUserId: report.targetUserId, + reporterId: report.reporterId, + comment: report.comment, + }); + } + + const meta = await this.metaService.fetch(); + if (meta.email) { + this.emailService.sendEmail(meta.email, 'New abuse report', + sanitizeHtml(ps.comment), + sanitizeHtml(ps.comment)); + } + }); }); } } diff --git a/packages/backend/src/server/web/ClientServerService.ts b/packages/backend/src/server/web/ClientServerService.ts index f55790b6363b..ab03489c0d76 100644 --- a/packages/backend/src/server/web/ClientServerService.ts +++ b/packages/backend/src/server/web/ClientServerService.ts @@ -25,16 +25,7 @@ import { getNoteSummary } from '@/misc/get-note-summary.js'; import { DI } from '@/di-symbols.js'; import * as Acct from '@/misc/acct.js'; import { MetaService } from '@/core/MetaService.js'; -import type { - DbQueue, - DeliverQueue, - EndedPollNotificationQueue, - InboxQueue, - ObjectStorageQueue, - SystemQueue, - UserWebhookDeliverQueue, - SystemWebhookDeliverQueue, -} from '@/core/QueueModule.js'; +import type { DbQueue, DeliverQueue, EndedPollNotificationQueue, InboxQueue, ObjectStorageQueue, SystemQueue, WebhookDeliverQueue } from '@/core/QueueModule.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; import { PageEntityService } from '@/core/entities/PageEntityService.js'; @@ -120,8 +111,7 @@ export class ClientServerService { @Inject('queue:inbox') public inboxQueue: InboxQueue, @Inject('queue:db') public dbQueue: DbQueue, @Inject('queue:objectStorage') public objectStorageQueue: ObjectStorageQueue, - @Inject('queue:userWebhookDeliver') public userWebhookDeliverQueue: UserWebhookDeliverQueue, - @Inject('queue:systemWebhookDeliver') public systemWebhookDeliverQueue: SystemWebhookDeliverQueue, + @Inject('queue:webhookDeliver') public webhookDeliverQueue: WebhookDeliverQueue, ) { //this.createServer = this.createServer.bind(this); } @@ -249,8 +239,7 @@ export class ClientServerService { this.inboxQueue, this.dbQueue, this.objectStorageQueue, - this.userWebhookDeliverQueue, - this.systemWebhookDeliverQueue, + this.webhookDeliverQueue, ].map(q => new BullMQAdapter(q)), serverAdapter, }); diff --git a/packages/backend/src/types.ts b/packages/backend/src/types.ts index ecbbee4eff1b..929070d0d290 100644 --- a/packages/backend/src/types.ts +++ b/packages/backend/src/types.ts @@ -90,12 +90,6 @@ export const moderationLogTypes = [ 'deleteAvatarDecoration', 'unsetUserAvatar', 'unsetUserBanner', - 'createSystemWebhook', - 'updateSystemWebhook', - 'deleteSystemWebhook', - 'createAbuseReportNotificationRecipient', - 'updateAbuseReportNotificationRecipient', - 'deleteAbuseReportNotificationRecipient', ] as const; export type ModerationLogPayloads = { @@ -288,32 +282,6 @@ export type ModerationLogPayloads = { userHost: string | null; fileId: string; }; - createSystemWebhook: { - systemWebhookId: string; - webhook: any; - }; - updateSystemWebhook: { - systemWebhookId: string; - before: any; - after: any; - }; - deleteSystemWebhook: { - systemWebhookId: string; - webhook: any; - }; - createAbuseReportNotificationRecipient: { - recipientId: string; - recipient: any; - }; - updateAbuseReportNotificationRecipient: { - recipientId: string; - before: any; - after: any; - }; - deleteAbuseReportNotificationRecipient: { - recipientId: string; - recipient: any; - }; }; export type Serialized = { diff --git a/packages/backend/test/e2e/synalio/abuse-report.ts b/packages/backend/test/e2e/synalio/abuse-report.ts deleted file mode 100644 index b0cc3d13ecb4..000000000000 --- a/packages/backend/test/e2e/synalio/abuse-report.ts +++ /dev/null @@ -1,401 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { entities } from 'misskey-js'; -import { beforeEach, describe, test } from '@jest/globals'; -import Fastify from 'fastify'; -import { api, randomString, role, signup, startJobQueue, UserToken } from '../../utils.js'; -import type { INestApplicationContext } from '@nestjs/common'; - -const WEBHOOK_HOST = 'http://localhost:15080'; -const WEBHOOK_PORT = 15080; -process.env.NODE_ENV = 'test'; - -describe('[シナリオ] ユーザ通報', () => { - let queue: INestApplicationContext; - let admin: entities.SignupResponse; - let alice: entities.SignupResponse; - let bob: entities.SignupResponse; - - type SystemWebhookPayload = { - server: string; - hookId: string; - eventId: string; - createdAt: string; - type: string; - body: any; - } - - // ------------------------------------------------------------------------------------------- - - async function captureWebhook(postAction: () => Promise): Promise { - const fastify = Fastify(); - - let timeoutHandle: NodeJS.Timeout | null = null; - const result = await new Promise(async (resolve, reject) => { - fastify.all('/', async (req, res) => { - timeoutHandle && clearTimeout(timeoutHandle); - - const body = JSON.stringify(req.body); - res.status(200).send('ok'); - await fastify.close(); - resolve(body); - }); - - await fastify.listen({ port: WEBHOOK_PORT }); - - timeoutHandle = setTimeout(async () => { - await fastify.close(); - reject(new Error('timeout')); - }, 3000); - - try { - await postAction(); - } catch (e) { - await fastify.close(); - reject(e); - } - }); - - await fastify.close(); - - return JSON.parse(result) as T; - } - - async function createSystemWebhook(args?: Partial, credential?: UserToken): Promise { - const res = await api( - 'admin/system-webhook/create', - { - isActive: true, - name: randomString(), - on: ['abuseReport'], - url: WEBHOOK_HOST, - secret: randomString(), - ...args, - }, - credential ?? admin, - ); - return res.body; - } - - async function createAbuseReportNotificationRecipient(args?: Partial, credential?: UserToken): Promise { - const res = await api( - 'admin/abuse-report/notification-recipient/create', - { - isActive: true, - name: randomString(), - method: 'webhook', - ...args, - }, - credential ?? admin, - ); - return res.body; - } - - async function createAbuseReport(args?: Partial, credential?: UserToken): Promise { - const res = await api( - 'users/report-abuse', - { - userId: alice.id, - comment: randomString(), - ...args, - }, - credential ?? admin, - ); - return res.body; - } - - async function resolveAbuseReport(args?: Partial, credential?: UserToken): Promise { - const res = await api( - 'admin/resolve-abuse-user-report', - { - reportId: admin.id, - ...args, - }, - credential ?? admin, - ); - return res.body; - } - - // ------------------------------------------------------------------------------------------- - - beforeAll(async () => { - queue = await startJobQueue(); - admin = await signup({ username: 'admin' }); - alice = await signup({ username: 'alice' }); - bob = await signup({ username: 'bob' }); - - await role(admin, { isAdministrator: true }); - }, 1000 * 60 * 2); - - afterAll(async () => { - await queue.close(); - }); - - // ------------------------------------------------------------------------------------------- - - describe('SystemWebhook', () => { - beforeEach(async () => { - const webhooks = await api('admin/system-webhook/list', {}, admin); - for (const webhook of webhooks.body) { - await api('admin/system-webhook/delete', { id: webhook.id }, admin); - } - }); - - test('通報を受けた -> abuseReportが送出される', async () => { - const webhook = await createSystemWebhook({ - on: ['abuseReport'], - isActive: true, - }); - await createAbuseReportNotificationRecipient({ systemWebhookId: webhook.id }); - - // 通報(bob -> alice) - const abuse = { - userId: alice.id, - comment: randomString(), - }; - const webhookBody = await captureWebhook(async () => { - await createAbuseReport(abuse, bob); - }); - - console.log(JSON.stringify(webhookBody, null, 2)); - - expect(webhookBody.hookId).toBe(webhook.id); - expect(webhookBody.type).toBe('abuseReport'); - expect(webhookBody.body.targetUserId).toBe(alice.id); - expect(webhookBody.body.reporterId).toBe(bob.id); - expect(webhookBody.body.comment).toBe(abuse.comment); - }); - - test('通報を受けた -> abuseReportが送出される -> 解決 -> abuseReportResolvedが送出される', async () => { - const webhook = await createSystemWebhook({ - on: ['abuseReport', 'abuseReportResolved'], - isActive: true, - }); - await createAbuseReportNotificationRecipient({ systemWebhookId: webhook.id }); - - // 通報(bob -> alice) - const abuse = { - userId: alice.id, - comment: randomString(), - }; - const webhookBody1 = await captureWebhook(async () => { - await createAbuseReport(abuse, bob); - }); - - console.log(JSON.stringify(webhookBody1, null, 2)); - expect(webhookBody1.hookId).toBe(webhook.id); - expect(webhookBody1.type).toBe('abuseReport'); - expect(webhookBody1.body.targetUserId).toBe(alice.id); - expect(webhookBody1.body.reporterId).toBe(bob.id); - expect(webhookBody1.body.assigneeId).toBeNull(); - expect(webhookBody1.body.resolved).toBe(false); - expect(webhookBody1.body.comment).toBe(abuse.comment); - - // 解決 - const webhookBody2 = await captureWebhook(async () => { - await resolveAbuseReport({ - reportId: webhookBody1.body.id, - forward: false, - }, admin); - }); - - console.log(JSON.stringify(webhookBody2, null, 2)); - expect(webhookBody2.hookId).toBe(webhook.id); - expect(webhookBody2.type).toBe('abuseReportResolved'); - expect(webhookBody2.body.targetUserId).toBe(alice.id); - expect(webhookBody2.body.reporterId).toBe(bob.id); - expect(webhookBody2.body.assigneeId).toBe(admin.id); - expect(webhookBody2.body.resolved).toBe(true); - expect(webhookBody2.body.comment).toBe(abuse.comment); - }); - - test('通報を受けた -> abuseReportが未許可の場合は送出されない', async () => { - const webhook = await createSystemWebhook({ - on: [], - isActive: true, - }); - await createAbuseReportNotificationRecipient({ systemWebhookId: webhook.id }); - - // 通報(bob -> alice) - const abuse = { - userId: alice.id, - comment: randomString(), - }; - const webhookBody = await captureWebhook(async () => { - await createAbuseReport(abuse, bob); - }).catch(e => e.message); - - expect(webhookBody).toBe('timeout'); - }); - - test('通報を受けた -> abuseReportが未許可の場合は送出されない -> 解決 -> abuseReportResolvedが送出される', async () => { - const webhook = await createSystemWebhook({ - on: ['abuseReportResolved'], - isActive: true, - }); - await createAbuseReportNotificationRecipient({ systemWebhookId: webhook.id }); - - // 通報(bob -> alice) - const abuse = { - userId: alice.id, - comment: randomString(), - }; - const webhookBody1 = await captureWebhook(async () => { - await createAbuseReport(abuse, bob); - }).catch(e => e.message); - - expect(webhookBody1).toBe('timeout'); - - const abuseReportId = (await api('admin/abuse-user-reports', {}, admin)).body[0].id; - - // 解決 - const webhookBody2 = await captureWebhook(async () => { - await resolveAbuseReport({ - reportId: abuseReportId, - forward: false, - }, admin); - }); - - console.log(JSON.stringify(webhookBody2, null, 2)); - expect(webhookBody2.hookId).toBe(webhook.id); - expect(webhookBody2.type).toBe('abuseReportResolved'); - expect(webhookBody2.body.targetUserId).toBe(alice.id); - expect(webhookBody2.body.reporterId).toBe(bob.id); - expect(webhookBody2.body.assigneeId).toBe(admin.id); - expect(webhookBody2.body.resolved).toBe(true); - expect(webhookBody2.body.comment).toBe(abuse.comment); - }); - - test('通報を受けた -> abuseReportが送出される -> 解決 -> abuseReportResolvedが未許可の場合は送出されない', async () => { - const webhook = await createSystemWebhook({ - on: ['abuseReport'], - isActive: true, - }); - await createAbuseReportNotificationRecipient({ systemWebhookId: webhook.id }); - - // 通報(bob -> alice) - const abuse = { - userId: alice.id, - comment: randomString(), - }; - const webhookBody1 = await captureWebhook(async () => { - await createAbuseReport(abuse, bob); - }); - - console.log(JSON.stringify(webhookBody1, null, 2)); - expect(webhookBody1.hookId).toBe(webhook.id); - expect(webhookBody1.type).toBe('abuseReport'); - expect(webhookBody1.body.targetUserId).toBe(alice.id); - expect(webhookBody1.body.reporterId).toBe(bob.id); - expect(webhookBody1.body.assigneeId).toBeNull(); - expect(webhookBody1.body.resolved).toBe(false); - expect(webhookBody1.body.comment).toBe(abuse.comment); - - // 解決 - const webhookBody2 = await captureWebhook(async () => { - await resolveAbuseReport({ - reportId: webhookBody1.body.id, - forward: false, - }, admin); - }).catch(e => e.message); - - expect(webhookBody2).toBe('timeout'); - }); - - test('通報を受けた -> abuseReportが未許可の場合は送出されない -> 解決 -> abuseReportResolvedが未許可の場合は送出されない', async () => { - const webhook = await createSystemWebhook({ - on: [], - isActive: true, - }); - await createAbuseReportNotificationRecipient({ systemWebhookId: webhook.id }); - - // 通報(bob -> alice) - const abuse = { - userId: alice.id, - comment: randomString(), - }; - const webhookBody1 = await captureWebhook(async () => { - await createAbuseReport(abuse, bob); - }).catch(e => e.message); - - expect(webhookBody1).toBe('timeout'); - - const abuseReportId = (await api('admin/abuse-user-reports', {}, admin)).body[0].id; - - // 解決 - const webhookBody2 = await captureWebhook(async () => { - await resolveAbuseReport({ - reportId: abuseReportId, - forward: false, - }, admin); - }).catch(e => e.message); - - expect(webhookBody2).toBe('timeout'); - }); - - test('通報を受けた -> Webhookが無効の場合は送出されない', async () => { - const webhook = await createSystemWebhook({ - on: ['abuseReport', 'abuseReportResolved'], - isActive: false, - }); - await createAbuseReportNotificationRecipient({ systemWebhookId: webhook.id }); - - // 通報(bob -> alice) - const abuse = { - userId: alice.id, - comment: randomString(), - }; - const webhookBody1 = await captureWebhook(async () => { - await createAbuseReport(abuse, bob); - }).catch(e => e.message); - - expect(webhookBody1).toBe('timeout'); - - const abuseReportId = (await api('admin/abuse-user-reports', {}, admin)).body[0].id; - - // 解決 - const webhookBody2 = await captureWebhook(async () => { - await resolveAbuseReport({ - reportId: abuseReportId, - forward: false, - }, admin); - }).catch(e => e.message); - - expect(webhookBody2).toBe('timeout'); - }); - - test('通報を受けた -> 通知設定が無効の場合は送出されない', async () => { - const webhook = await createSystemWebhook({ - on: ['abuseReport', 'abuseReportResolved'], - isActive: true, - }); - await createAbuseReportNotificationRecipient({ systemWebhookId: webhook.id, isActive: false }); - - // 通報(bob -> alice) - const abuse = { - userId: alice.id, - comment: randomString(), - }; - const webhookBody1 = await captureWebhook(async () => { - await createAbuseReport(abuse, bob); - }).catch(e => e.message); - - expect(webhookBody1).toBe('timeout'); - - const abuseReportId = (await api('admin/abuse-user-reports', {}, admin)).body[0].id; - - // 解決 - const webhookBody2 = await captureWebhook(async () => { - await resolveAbuseReport({ - reportId: abuseReportId, - forward: false, - }, admin); - }).catch(e => e.message); - - expect(webhookBody2).toBe('timeout'); - }); - }); -}); diff --git a/packages/backend/test/unit/AbuseReportNotificationService.ts b/packages/backend/test/unit/AbuseReportNotificationService.ts deleted file mode 100644 index e971659070ea..000000000000 --- a/packages/backend/test/unit/AbuseReportNotificationService.ts +++ /dev/null @@ -1,343 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { jest } from '@jest/globals'; -import { Test, TestingModule } from '@nestjs/testing'; -import { AbuseReportNotificationService } from '@/core/AbuseReportNotificationService.js'; -import { - AbuseReportNotificationRecipientRepository, - MiAbuseReportNotificationRecipient, - MiSystemWebhook, - MiUser, - SystemWebhooksRepository, - UserProfilesRepository, - UsersRepository, -} from '@/models/_.js'; -import { DI } from '@/di-symbols.js'; -import { GlobalModule } from '@/GlobalModule.js'; -import { IdService } from '@/core/IdService.js'; -import { EmailService } from '@/core/EmailService.js'; -import { RoleService } from '@/core/RoleService.js'; -import { MetaService } from '@/core/MetaService.js'; -import { ModerationLogService } from '@/core/ModerationLogService.js'; -import { GlobalEventService } from '@/core/GlobalEventService.js'; -import { RecipientMethod } from '@/models/AbuseReportNotificationRecipient.js'; -import { SystemWebhookService } from '@/core/SystemWebhookService.js'; -import { randomString } from '../utils.js'; - -process.env.NODE_ENV = 'test'; - -describe('AbuseReportNotificationService', () => { - let app: TestingModule; - let service: AbuseReportNotificationService; - - // -------------------------------------------------------------------------------------- - - let usersRepository: UsersRepository; - let userProfilesRepository: UserProfilesRepository; - let systemWebhooksRepository: SystemWebhooksRepository; - let abuseReportNotificationRecipientRepository: AbuseReportNotificationRecipientRepository; - let idService: IdService; - let roleService: jest.Mocked; - let emailService: jest.Mocked; - let webhookService: jest.Mocked; - - // -------------------------------------------------------------------------------------- - - let root: MiUser; - let alice: MiUser; - let bob: MiUser; - let systemWebhook1: MiSystemWebhook; - let systemWebhook2: MiSystemWebhook; - - // -------------------------------------------------------------------------------------- - - async function createUser(data: Partial = {}) { - const user = await usersRepository - .insert({ - id: idService.gen(), - ...data, - }) - .then(x => usersRepository.findOneByOrFail(x.identifiers[0])); - - await userProfilesRepository.insert({ - userId: user.id, - }); - - return user; - } - - async function createWebhook(data: Partial = {}) { - return systemWebhooksRepository - .insert({ - id: idService.gen(), - name: randomString(), - on: ['abuseReport'], - url: 'https://example.com', - secret: randomString(), - ...data, - }) - .then(x => systemWebhooksRepository.findOneByOrFail(x.identifiers[0])); - } - - async function createRecipient(data: Partial = {}) { - return abuseReportNotificationRecipientRepository - .insert({ - id: idService.gen(), - isActive: true, - name: randomString(), - ...data, - }) - .then(x => abuseReportNotificationRecipientRepository.findOneByOrFail(x.identifiers[0])); - } - - // -------------------------------------------------------------------------------------- - - beforeAll(async () => { - app = await Test - .createTestingModule({ - imports: [ - GlobalModule, - ], - providers: [ - AbuseReportNotificationService, - IdService, - { - provide: RoleService, useFactory: () => ({ getModeratorIds: jest.fn() }), - }, - { - provide: SystemWebhookService, useFactory: () => ({ enqueueSystemWebhook: jest.fn() }), - }, - { - provide: EmailService, useFactory: () => ({ sendEmail: jest.fn() }), - }, - { - provide: MetaService, useFactory: () => ({ fetch: jest.fn() }), - }, - { - provide: ModerationLogService, useFactory: () => ({ log: () => Promise.resolve() }), - }, - { - provide: GlobalEventService, useFactory: () => ({ publishAdminStream: jest.fn() }), - }, - ], - }) - .compile(); - - usersRepository = app.get(DI.usersRepository); - userProfilesRepository = app.get(DI.userProfilesRepository); - systemWebhooksRepository = app.get(DI.systemWebhooksRepository); - abuseReportNotificationRecipientRepository = app.get(DI.abuseReportNotificationRecipientRepository); - - service = app.get(AbuseReportNotificationService); - idService = app.get(IdService); - roleService = app.get(RoleService) as jest.Mocked; - emailService = app.get(EmailService) as jest.Mocked; - webhookService = app.get(SystemWebhookService) as jest.Mocked; - - app.enableShutdownHooks(); - }); - - beforeEach(async () => { - root = await createUser({ username: 'root', usernameLower: 'root', isRoot: true }); - alice = await createUser({ username: 'alice', usernameLower: 'alice', isRoot: false }); - bob = await createUser({ username: 'bob', usernameLower: 'bob', isRoot: false }); - systemWebhook1 = await createWebhook(); - systemWebhook2 = await createWebhook(); - - roleService.getModeratorIds.mockResolvedValue([root.id, alice.id, bob.id]); - }); - - afterEach(async () => { - emailService.sendEmail.mockClear(); - webhookService.enqueueSystemWebhook.mockClear(); - - await usersRepository.delete({}); - await userProfilesRepository.delete({}); - await systemWebhooksRepository.delete({}); - await abuseReportNotificationRecipientRepository.delete({}); - }); - - afterAll(async () => { - await app.close(); - }); - - // -------------------------------------------------------------------------------------- - - describe('createRecipient', () => { - test('作成成功1', async () => { - const params = { - isActive: true, - name: randomString(), - method: 'email' as RecipientMethod, - userId: alice.id, - systemWebhookId: null, - }; - - const recipient1 = await service.createRecipient(params, root); - expect(recipient1).toMatchObject(params); - }); - - test('作成成功2', async () => { - const params = { - isActive: true, - name: randomString(), - method: 'webhook' as RecipientMethod, - userId: null, - systemWebhookId: systemWebhook1.id, - }; - - const recipient1 = await service.createRecipient(params, root); - expect(recipient1).toMatchObject(params); - }); - }); - - describe('updateRecipient', () => { - test('更新成功1', async () => { - const recipient1 = await createRecipient({ - method: 'email', - userId: alice.id, - }); - - const params = { - id: recipient1.id, - isActive: false, - name: randomString(), - method: 'email' as RecipientMethod, - userId: bob.id, - systemWebhookId: null, - }; - - const recipient2 = await service.updateRecipient(params, root); - expect(recipient2).toMatchObject(params); - }); - - test('更新成功2', async () => { - const recipient1 = await createRecipient({ - method: 'webhook', - systemWebhookId: systemWebhook1.id, - }); - - const params = { - id: recipient1.id, - isActive: false, - name: randomString(), - method: 'webhook' as RecipientMethod, - userId: null, - systemWebhookId: systemWebhook2.id, - }; - - const recipient2 = await service.updateRecipient(params, root); - expect(recipient2).toMatchObject(params); - }); - }); - - describe('deleteRecipient', () => { - test('削除成功1', async () => { - const recipient1 = await createRecipient({ - method: 'email', - userId: alice.id, - }); - - await service.deleteRecipient(recipient1.id, root); - - await expect(abuseReportNotificationRecipientRepository.findOneBy({ id: recipient1.id })).resolves.toBeNull(); - }); - }); - - describe('fetchRecipients', () => { - async function create() { - const recipient1 = await createRecipient({ - method: 'email', - userId: alice.id, - }); - const recipient2 = await createRecipient({ - method: 'email', - userId: bob.id, - }); - - const recipient3 = await createRecipient({ - method: 'webhook', - systemWebhookId: systemWebhook1.id, - }); - const recipient4 = await createRecipient({ - method: 'webhook', - systemWebhookId: systemWebhook2.id, - }); - - return [recipient1, recipient2, recipient3, recipient4]; - } - - test('フィルタなし', async () => { - const [recipient1, recipient2, recipient3, recipient4] = await create(); - - const recipients = await service.fetchRecipients({}); - expect(recipients).toEqual([recipient1, recipient2, recipient3, recipient4]); - }); - - test('フィルタなし(非モデレータは除外される)', async () => { - roleService.getModeratorIds.mockClear(); - roleService.getModeratorIds.mockResolvedValue([root.id, bob.id]); - - const [recipient1, recipient2, recipient3, recipient4] = await create(); - - const recipients = await service.fetchRecipients({}); - // aliceはモデレータではないので除外される - expect(recipients).toEqual([recipient2, recipient3, recipient4]); - }); - - test('フィルタなし(非モデレータでも除外されないオプション設定)', async () => { - roleService.getModeratorIds.mockClear(); - roleService.getModeratorIds.mockResolvedValue([root.id, bob.id]); - - const [recipient1, recipient2, recipient3, recipient4] = await create(); - - const recipients = await service.fetchRecipients({}, { removeUnauthorized: false }); - expect(recipients).toEqual([recipient1, recipient2, recipient3, recipient4]); - }); - - test('emailのみ', async () => { - const [recipient1, recipient2, recipient3, recipient4] = await create(); - - const recipients = await service.fetchRecipients({ method: ['email'] }); - expect(recipients).toEqual([recipient1, recipient2]); - }); - - test('webhookのみ', async () => { - const [recipient1, recipient2, recipient3, recipient4] = await create(); - - const recipients = await service.fetchRecipients({ method: ['webhook'] }); - expect(recipients).toEqual([recipient3, recipient4]); - }); - - test('すべて', async () => { - const [recipient1, recipient2, recipient3, recipient4] = await create(); - - const recipients = await service.fetchRecipients({ method: ['email', 'webhook'] }); - expect(recipients).toEqual([recipient1, recipient2, recipient3, recipient4]); - }); - - test('ID指定', async () => { - const [recipient1, recipient2, recipient3, recipient4] = await create(); - - const recipients = await service.fetchRecipients({ ids: [recipient1.id, recipient3.id] }); - expect(recipients).toEqual([recipient1, recipient3]); - }); - - test('ID指定(method=emailではないIDが混ざりこまない)', async () => { - const [recipient1, recipient2, recipient3, recipient4] = await create(); - - const recipients = await service.fetchRecipients({ ids: [recipient1.id, recipient3.id], method: ['email'] }); - expect(recipients).toEqual([recipient1]); - }); - - test('ID指定(method=webhookではないIDが混ざりこまない)', async () => { - const [recipient1, recipient2, recipient3, recipient4] = await create(); - - const recipients = await service.fetchRecipients({ ids: [recipient1.id, recipient3.id], method: ['webhook'] }); - expect(recipients).toEqual([recipient3]); - }); - }); -}); diff --git a/packages/backend/test/unit/RoleService.ts b/packages/backend/test/unit/RoleService.ts index 69fa4162fbac..ec441735d7e6 100644 --- a/packages/backend/test/unit/RoleService.ts +++ b/packages/backend/test/unit/RoleService.ts @@ -3,6 +3,8 @@ * SPDX-License-Identifier: AGPL-3.0-only */ +import { UserEntityService } from '@/core/entities/UserEntityService.js'; + process.env.NODE_ENV = 'test'; import { jest } from '@jest/globals'; @@ -11,14 +13,7 @@ import { Test } from '@nestjs/testing'; import * as lolex from '@sinonjs/fake-timers'; import { GlobalModule } from '@/GlobalModule.js'; import { RoleService } from '@/core/RoleService.js'; -import { - MiRole, - MiRoleAssignment, - MiUser, - RoleAssignmentsRepository, - RolesRepository, - UsersRepository, -} from '@/models/_.js'; +import type { MiRole, MiUser, RoleAssignmentsRepository, RolesRepository, UsersRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { MetaService } from '@/core/MetaService.js'; import { genAidx } from '@/misc/id/aidx.js'; @@ -28,7 +23,6 @@ import { GlobalEventService } from '@/core/GlobalEventService.js'; import { secureRndstr } from '@/misc/secure-rndstr.js'; import { NotificationService } from '@/core/NotificationService.js'; import { RoleCondFormulaValue } from '@/models/Role.js'; -import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { sleep } from '../utils.js'; import type { TestingModule } from '@nestjs/testing'; import type { MockFunctionMetadata } from 'jest-mock'; @@ -45,27 +39,27 @@ describe('RoleService', () => { let notificationService: jest.Mocked; let clock: lolex.InstalledClock; - async function createUser(data: Partial = {}) { + function createUser(data: Partial = {}) { const un = secureRndstr(16); - const x = await usersRepository.insert({ + return usersRepository.insert({ id: genAidx(Date.now()), username: un, usernameLower: un, ...data, - }); - return await usersRepository.findOneByOrFail(x.identifiers[0]); + }) + .then(x => usersRepository.findOneByOrFail(x.identifiers[0])); } - async function createRole(data: Partial = {}) { - const x = await rolesRepository.insert({ + function createRole(data: Partial = {}) { + return rolesRepository.insert({ id: genAidx(Date.now()), updatedAt: new Date(), lastUsedAt: new Date(), name: '', description: '', ...data, - }); - return await rolesRepository.findOneByOrFail(x.identifiers[0]); + }) + .then(x => rolesRepository.findOneByOrFail(x.identifiers[0])); } function createConditionalRole(condFormula: RoleCondFormulaValue, data: Partial = {}) { @@ -77,20 +71,6 @@ describe('RoleService', () => { }); } - async function assignRole(args: Partial) { - const id = genAidx(Date.now()); - const expiresAt = new Date(); - expiresAt.setDate(expiresAt.getDate() + 1); - - await roleAssignmentsRepository.insert({ - id, - expiresAt, - ...args, - }); - - return await roleAssignmentsRepository.findOneByOrFail({ id }); - } - function aidx() { return genAidx(Date.now()); } @@ -285,96 +265,6 @@ describe('RoleService', () => { }); }); - describe('getModeratorIds', () => { - test('includeAdmins = false, excludeExpire = false', async () => { - const [adminUser1, adminUser2, modeUser1, modeUser2, normalUser1, normalUser2] = await Promise.all([ - createUser(), createUser(), createUser(), createUser(), createUser(), createUser(), - ]); - - const role1 = await createRole({ name: 'admin', isAdministrator: true }); - const role2 = await createRole({ name: 'moderator', isModerator: true }); - const role3 = await createRole({ name: 'normal' }); - - await Promise.all([ - assignRole({ userId: adminUser1.id, roleId: role1.id }), - assignRole({ userId: adminUser2.id, roleId: role1.id, expiresAt: new Date(Date.now() - 1000) }), - assignRole({ userId: modeUser1.id, roleId: role2.id }), - assignRole({ userId: modeUser2.id, roleId: role2.id, expiresAt: new Date(Date.now() - 1000) }), - assignRole({ userId: normalUser1.id, roleId: role3.id }), - assignRole({ userId: normalUser2.id, roleId: role3.id, expiresAt: new Date(Date.now() - 1000) }), - ]); - - const result = await roleService.getModeratorIds(false, false); - expect(result).toEqual([modeUser1.id, modeUser2.id]); - }); - - test('includeAdmins = false, excludeExpire = true', async () => { - const [adminUser1, adminUser2, modeUser1, modeUser2, normalUser1, normalUser2] = await Promise.all([ - createUser(), createUser(), createUser(), createUser(), createUser(), createUser(), - ]); - - const role1 = await createRole({ name: 'admin', isAdministrator: true }); - const role2 = await createRole({ name: 'moderator', isModerator: true }); - const role3 = await createRole({ name: 'normal' }); - - await Promise.all([ - assignRole({ userId: adminUser1.id, roleId: role1.id }), - assignRole({ userId: adminUser2.id, roleId: role1.id, expiresAt: new Date(Date.now() - 1000) }), - assignRole({ userId: modeUser1.id, roleId: role2.id }), - assignRole({ userId: modeUser2.id, roleId: role2.id, expiresAt: new Date(Date.now() - 1000) }), - assignRole({ userId: normalUser1.id, roleId: role3.id }), - assignRole({ userId: normalUser2.id, roleId: role3.id, expiresAt: new Date(Date.now() - 1000) }), - ]); - - const result = await roleService.getModeratorIds(false, true); - expect(result).toEqual([modeUser1.id]); - }); - - test('includeAdmins = true, excludeExpire = false', async () => { - const [adminUser1, adminUser2, modeUser1, modeUser2, normalUser1, normalUser2] = await Promise.all([ - createUser(), createUser(), createUser(), createUser(), createUser(), createUser(), - ]); - - const role1 = await createRole({ name: 'admin', isAdministrator: true }); - const role2 = await createRole({ name: 'moderator', isModerator: true }); - const role3 = await createRole({ name: 'normal' }); - - await Promise.all([ - assignRole({ userId: adminUser1.id, roleId: role1.id }), - assignRole({ userId: adminUser2.id, roleId: role1.id, expiresAt: new Date(Date.now() - 1000) }), - assignRole({ userId: modeUser1.id, roleId: role2.id }), - assignRole({ userId: modeUser2.id, roleId: role2.id, expiresAt: new Date(Date.now() - 1000) }), - assignRole({ userId: normalUser1.id, roleId: role3.id }), - assignRole({ userId: normalUser2.id, roleId: role3.id, expiresAt: new Date(Date.now() - 1000) }), - ]); - - const result = await roleService.getModeratorIds(true, false); - expect(result).toEqual([adminUser1.id, adminUser2.id, modeUser1.id, modeUser2.id]); - }); - - test('includeAdmins = true, excludeExpire = true', async () => { - const [adminUser1, adminUser2, modeUser1, modeUser2, normalUser1, normalUser2] = await Promise.all([ - createUser(), createUser(), createUser(), createUser(), createUser(), createUser(), - ]); - - const role1 = await createRole({ name: 'admin', isAdministrator: true }); - const role2 = await createRole({ name: 'moderator', isModerator: true }); - const role3 = await createRole({ name: 'normal' }); - - await Promise.all([ - assignRole({ userId: adminUser1.id, roleId: role1.id }), - assignRole({ userId: adminUser2.id, roleId: role1.id, expiresAt: new Date(Date.now() - 1000) }), - assignRole({ userId: modeUser1.id, roleId: role2.id }), - assignRole({ userId: modeUser2.id, roleId: role2.id, expiresAt: new Date(Date.now() - 1000) }), - assignRole({ userId: normalUser1.id, roleId: role3.id }), - assignRole({ userId: normalUser2.id, roleId: role3.id, expiresAt: new Date(Date.now() - 1000) }), - ]); - - const result = await roleService.getModeratorIds(true, true); - expect(result).toEqual([adminUser1.id, modeUser1.id]); - }); - }); - describe('conditional role', () => { test('~かつ~', async () => { const [user1, user2, user3, user4] = await Promise.all([ diff --git a/packages/backend/test/unit/SystemWebhookService.ts b/packages/backend/test/unit/SystemWebhookService.ts deleted file mode 100644 index 41b7f977ca8a..000000000000 --- a/packages/backend/test/unit/SystemWebhookService.ts +++ /dev/null @@ -1,515 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { afterEach, beforeEach, describe, expect, jest } from '@jest/globals'; -import { Test, TestingModule } from '@nestjs/testing'; -import { MiUser } from '@/models/User.js'; -import { MiSystemWebhook, SystemWebhookEventType } from '@/models/SystemWebhook.js'; -import { SystemWebhooksRepository, UsersRepository } from '@/models/_.js'; -import { IdService } from '@/core/IdService.js'; -import { GlobalModule } from '@/GlobalModule.js'; -import { ModerationLogService } from '@/core/ModerationLogService.js'; -import { GlobalEventService } from '@/core/GlobalEventService.js'; -import { DI } from '@/di-symbols.js'; -import { QueueService } from '@/core/QueueService.js'; -import { LoggerService } from '@/core/LoggerService.js'; -import { SystemWebhookService } from '@/core/SystemWebhookService.js'; -import { randomString, sleep } from '../utils.js'; - -describe('SystemWebhookService', () => { - let app: TestingModule; - let service: SystemWebhookService; - - // -------------------------------------------------------------------------------------- - - let usersRepository: UsersRepository; - let systemWebhooksRepository: SystemWebhooksRepository; - let idService: IdService; - let queueService: jest.Mocked; - - // -------------------------------------------------------------------------------------- - - let root: MiUser; - - // -------------------------------------------------------------------------------------- - - async function createUser(data: Partial = {}) { - return await usersRepository - .insert({ - id: idService.gen(), - ...data, - }) - .then(x => usersRepository.findOneByOrFail(x.identifiers[0])); - } - - async function createWebhook(data: Partial = {}) { - return systemWebhooksRepository - .insert({ - id: idService.gen(), - name: randomString(), - on: ['abuseReport'], - url: 'https://example.com', - secret: randomString(), - ...data, - }) - .then(x => systemWebhooksRepository.findOneByOrFail(x.identifiers[0])); - } - - // -------------------------------------------------------------------------------------- - - async function beforeAllImpl() { - app = await Test - .createTestingModule({ - imports: [ - GlobalModule, - ], - providers: [ - SystemWebhookService, - IdService, - LoggerService, - GlobalEventService, - { - provide: QueueService, useFactory: () => ({ systemWebhookDeliver: jest.fn() }), - }, - { - provide: ModerationLogService, useFactory: () => ({ log: () => Promise.resolve() }), - }, - ], - }) - .compile(); - - usersRepository = app.get(DI.usersRepository); - systemWebhooksRepository = app.get(DI.systemWebhooksRepository); - - service = app.get(SystemWebhookService); - idService = app.get(IdService); - queueService = app.get(QueueService) as jest.Mocked; - - app.enableShutdownHooks(); - } - - async function afterAllImpl() { - await app.close(); - } - - async function beforeEachImpl() { - root = await createUser({ isRoot: true, username: 'root', usernameLower: 'root' }); - } - - async function afterEachImpl() { - await usersRepository.delete({}); - await systemWebhooksRepository.delete({}); - } - - // -------------------------------------------------------------------------------------- - - describe('アプリを毎回作り直す必要のないグループ', () => { - beforeAll(beforeAllImpl); - afterAll(afterAllImpl); - beforeEach(beforeEachImpl); - afterEach(afterEachImpl); - - describe('fetchSystemWebhooks', () => { - test('フィルタなし', async () => { - const webhook1 = await createWebhook({ - isActive: true, - on: ['abuseReport'], - }); - const webhook2 = await createWebhook({ - isActive: false, - on: ['abuseReport'], - }); - const webhook3 = await createWebhook({ - isActive: true, - on: ['abuseReportResolved'], - }); - const webhook4 = await createWebhook({ - isActive: false, - on: [], - }); - - const fetchedWebhooks = await service.fetchSystemWebhooks(); - expect(fetchedWebhooks).toEqual([webhook1, webhook2, webhook3, webhook4]); - }); - - test('activeのみ', async () => { - const webhook1 = await createWebhook({ - isActive: true, - on: ['abuseReport'], - }); - const webhook2 = await createWebhook({ - isActive: false, - on: ['abuseReport'], - }); - const webhook3 = await createWebhook({ - isActive: true, - on: ['abuseReportResolved'], - }); - const webhook4 = await createWebhook({ - isActive: false, - on: [], - }); - - const fetchedWebhooks = await service.fetchSystemWebhooks({ isActive: true }); - expect(fetchedWebhooks).toEqual([webhook1, webhook3]); - }); - - test('特定のイベントのみ', async () => { - const webhook1 = await createWebhook({ - isActive: true, - on: ['abuseReport'], - }); - const webhook2 = await createWebhook({ - isActive: false, - on: ['abuseReport'], - }); - const webhook3 = await createWebhook({ - isActive: true, - on: ['abuseReportResolved'], - }); - const webhook4 = await createWebhook({ - isActive: false, - on: [], - }); - - const fetchedWebhooks = await service.fetchSystemWebhooks({ on: ['abuseReport'] }); - expect(fetchedWebhooks).toEqual([webhook1, webhook2]); - }); - - test('activeな特定のイベントのみ', async () => { - const webhook1 = await createWebhook({ - isActive: true, - on: ['abuseReport'], - }); - const webhook2 = await createWebhook({ - isActive: false, - on: ['abuseReport'], - }); - const webhook3 = await createWebhook({ - isActive: true, - on: ['abuseReportResolved'], - }); - const webhook4 = await createWebhook({ - isActive: false, - on: [], - }); - - const fetchedWebhooks = await service.fetchSystemWebhooks({ on: ['abuseReport'], isActive: true }); - expect(fetchedWebhooks).toEqual([webhook1]); - }); - - test('ID指定', async () => { - const webhook1 = await createWebhook({ - isActive: true, - on: ['abuseReport'], - }); - const webhook2 = await createWebhook({ - isActive: false, - on: ['abuseReport'], - }); - const webhook3 = await createWebhook({ - isActive: true, - on: ['abuseReportResolved'], - }); - const webhook4 = await createWebhook({ - isActive: false, - on: [], - }); - - const fetchedWebhooks = await service.fetchSystemWebhooks({ ids: [webhook1.id, webhook4.id] }); - expect(fetchedWebhooks).toEqual([webhook1, webhook4]); - }); - - test('ID指定(他条件とANDになるか見たい)', async () => { - const webhook1 = await createWebhook({ - isActive: true, - on: ['abuseReport'], - }); - const webhook2 = await createWebhook({ - isActive: false, - on: ['abuseReport'], - }); - const webhook3 = await createWebhook({ - isActive: true, - on: ['abuseReportResolved'], - }); - const webhook4 = await createWebhook({ - isActive: false, - on: [], - }); - - const fetchedWebhooks = await service.fetchSystemWebhooks({ ids: [webhook1.id, webhook4.id], isActive: false }); - expect(fetchedWebhooks).toEqual([webhook4]); - }); - }); - - describe('createSystemWebhook', () => { - test('作成成功 ', async () => { - const params = { - isActive: true, - name: randomString(), - on: ['abuseReport'] as SystemWebhookEventType[], - url: 'https://example.com', - secret: randomString(), - }; - - const webhook = await service.createSystemWebhook(params, root); - expect(webhook).toMatchObject(params); - }); - }); - - describe('updateSystemWebhook', () => { - test('更新成功', async () => { - const webhook = await createWebhook({ - isActive: true, - on: ['abuseReport'], - }); - - const params = { - id: webhook.id, - isActive: false, - name: randomString(), - on: ['abuseReport'] as SystemWebhookEventType[], - url: randomString(), - secret: randomString(), - }; - - const updatedWebhook = await service.updateSystemWebhook(params, root); - expect(updatedWebhook).toMatchObject(params); - }); - }); - - describe('deleteSystemWebhook', () => { - test('削除成功', async () => { - const webhook = await createWebhook({ - isActive: true, - on: ['abuseReport'], - }); - - await service.deleteSystemWebhook(webhook.id, root); - - await expect(systemWebhooksRepository.findOneBy({ id: webhook.id })).resolves.toBeNull(); - }); - }); - }); - - describe('アプリを毎回作り直す必要があるグループ', () => { - beforeEach(async () => { - await beforeAllImpl(); - await beforeEachImpl(); - }); - - afterEach(async () => { - await afterEachImpl(); - await afterAllImpl(); - }); - - describe('enqueueSystemWebhook', () => { - test('キューに追加成功', async () => { - const webhook = await createWebhook({ - isActive: true, - on: ['abuseReport'], - }); - await service.enqueueSystemWebhook(webhook.id, 'abuseReport', { foo: 'bar' }); - - expect(queueService.systemWebhookDeliver).toHaveBeenCalled(); - }); - - test('非アクティブなWebhookはキューに追加されない', async () => { - const webhook = await createWebhook({ - isActive: false, - on: ['abuseReport'], - }); - await service.enqueueSystemWebhook(webhook.id, 'abuseReport', { foo: 'bar' }); - - expect(queueService.systemWebhookDeliver).not.toHaveBeenCalled(); - }); - - test('未許可のイベント種別が渡された場合はWebhookはキューに追加されない', async () => { - const webhook1 = await createWebhook({ - isActive: true, - on: [], - }); - const webhook2 = await createWebhook({ - isActive: true, - on: ['abuseReportResolved'], - }); - await service.enqueueSystemWebhook(webhook1.id, 'abuseReport', { foo: 'bar' }); - await service.enqueueSystemWebhook(webhook2.id, 'abuseReport', { foo: 'bar' }); - - expect(queueService.systemWebhookDeliver).not.toHaveBeenCalled(); - }); - }); - - describe('fetchActiveSystemWebhooks', () => { - describe('systemWebhookCreated', () => { - test('ActiveなWebhookが追加された時、キャッシュに追加されている', async () => { - const webhook = await service.createSystemWebhook( - { - isActive: true, - name: randomString(), - on: ['abuseReport'], - url: 'https://example.com', - secret: randomString(), - }, - root, - ); - - // redisでの配信経由で更新されるのでちょっと待つ - await sleep(500); - - const fetchedWebhooks = await service.fetchActiveSystemWebhooks(); - expect(fetchedWebhooks).toEqual([webhook]); - }); - - test('NotActiveなWebhookが追加された時、キャッシュに追加されていない', async () => { - const webhook = await service.createSystemWebhook( - { - isActive: false, - name: randomString(), - on: ['abuseReport'], - url: 'https://example.com', - secret: randomString(), - }, - root, - ); - - // redisでの配信経由で更新されるのでちょっと待つ - await sleep(500); - - const fetchedWebhooks = await service.fetchActiveSystemWebhooks(); - expect(fetchedWebhooks).toEqual([]); - }); - }); - - describe('systemWebhookUpdated', () => { - test('ActiveなWebhookが編集された時、キャッシュに反映されている', async () => { - const id = idService.gen(); - await createWebhook({ id }); - // キャッシュ作成 - const webhook1 = await service.fetchActiveSystemWebhooks(); - // 読み込まれていることをチェック - expect(webhook1.length).toEqual(1); - expect(webhook1[0].id).toEqual(id); - - const webhook2 = await service.updateSystemWebhook( - { - id, - isActive: true, - name: randomString(), - on: ['abuseReport'], - url: 'https://example.com', - secret: randomString(), - }, - root, - ); - - // redisでの配信経由で更新されるのでちょっと待つ - await sleep(500); - - const fetchedWebhooks = await service.fetchActiveSystemWebhooks(); - expect(fetchedWebhooks).toEqual([webhook2]); - }); - - test('NotActiveなWebhookが編集された時、キャッシュに追加されない', async () => { - const id = idService.gen(); - await createWebhook({ id, isActive: false }); - // キャッシュ作成 - const webhook1 = await service.fetchActiveSystemWebhooks(); - // 読み込まれていないことをチェック - expect(webhook1.length).toEqual(0); - - const webhook2 = await service.updateSystemWebhook( - { - id, - isActive: false, - name: randomString(), - on: ['abuseReport'], - url: 'https://example.com', - secret: randomString(), - }, - root, - ); - - // redisでの配信経由で更新されるのでちょっと待つ - await sleep(500); - - const fetchedWebhooks = await service.fetchActiveSystemWebhooks(); - expect(fetchedWebhooks.length).toEqual(0); - }); - - test('NotActiveなWebhookがActiveにされた時、キャッシュに追加されている', async () => { - const id = idService.gen(); - const baseWebhook = await createWebhook({ id, isActive: false }); - // キャッシュ作成 - const webhook1 = await service.fetchActiveSystemWebhooks(); - // 読み込まれていないことをチェック - expect(webhook1.length).toEqual(0); - - const webhook2 = await service.updateSystemWebhook( - { - ...baseWebhook, - isActive: true, - }, - root, - ); - - // redisでの配信経由で更新されるのでちょっと待つ - await sleep(500); - - const fetchedWebhooks = await service.fetchActiveSystemWebhooks(); - expect(fetchedWebhooks).toEqual([webhook2]); - }); - - test('ActiveなWebhookがNotActiveにされた時、キャッシュから削除されている', async () => { - const id = idService.gen(); - const baseWebhook = await createWebhook({ id, isActive: true }); - // キャッシュ作成 - const webhook1 = await service.fetchActiveSystemWebhooks(); - // 読み込まれていることをチェック - expect(webhook1.length).toEqual(1); - expect(webhook1[0].id).toEqual(id); - - const webhook2 = await service.updateSystemWebhook( - { - ...baseWebhook, - isActive: false, - }, - root, - ); - - // redisでの配信経由で更新されるのでちょっと待つ - await sleep(500); - - const fetchedWebhooks = await service.fetchActiveSystemWebhooks(); - expect(fetchedWebhooks.length).toEqual(0); - }); - }); - - describe('systemWebhookDeleted', () => { - test('キャッシュから削除されている', async () => { - const id = idService.gen(); - const baseWebhook = await createWebhook({ id, isActive: true }); - // キャッシュ作成 - const webhook1 = await service.fetchActiveSystemWebhooks(); - // 読み込まれていることをチェック - expect(webhook1.length).toEqual(1); - expect(webhook1[0].id).toEqual(id); - - const webhook2 = await service.deleteSystemWebhook( - id, - root, - ); - - // redisでの配信経由で更新されるのでちょっと待つ - await sleep(500); - - const fetchedWebhooks = await service.fetchActiveSystemWebhooks(); - expect(fetchedWebhooks.length).toEqual(0); - }); - }); - }); - }); -}); diff --git a/packages/frontend/src/components/MkButton.vue b/packages/frontend/src/components/MkButton.vue index 25b003ba5a59..3489255b9152 100644 --- a/packages/frontend/src/components/MkButton.vue +++ b/packages/frontend/src/components/MkButton.vue @@ -11,7 +11,6 @@ SPDX-License-Identifier: AGPL-3.0-only :type="type" :name="name" :value="value" - :disabled="disabled" @click="emit('click', $event)" @mousedown="onMousedown" > @@ -56,7 +55,6 @@ const props = defineProps<{ asLike?: boolean; name?: string; value?: string; - disabled?: boolean; }>(); const emit = defineEmits<{ diff --git a/packages/frontend/src/components/MkDivider.vue b/packages/frontend/src/components/MkDivider.vue deleted file mode 100644 index e4e3af99e429..000000000000 --- a/packages/frontend/src/components/MkDivider.vue +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - diff --git a/packages/frontend/src/components/MkSwitch.vue b/packages/frontend/src/components/MkSwitch.vue index 721ac357f414..a19b45448bb9 100644 --- a/packages/frontend/src/components/MkSwitch.vue +++ b/packages/frontend/src/components/MkSwitch.vue @@ -13,7 +13,7 @@ SPDX-License-Identifier: AGPL-3.0-only @keydown.enter="toggle" > - + @@ -34,19 +34,16 @@ const props = defineProps<{ modelValue: boolean | Ref; disabled?: boolean; helpText?: string; - noBody?: boolean; }>(); const emit = defineEmits<{ (ev: 'update:modelValue', v: boolean): void; - (ev: 'change', v: boolean): void; }>(); const checked = toRefs(props).modelValue; const toggle = () => { if (props.disabled) return; emit('update:modelValue', !checked.value); - emit('change', !checked.value); }; diff --git a/packages/frontend/src/components/MkSystemWebhookEditor.impl.ts b/packages/frontend/src/components/MkSystemWebhookEditor.impl.ts deleted file mode 100644 index 1222d3261db8..000000000000 --- a/packages/frontend/src/components/MkSystemWebhookEditor.impl.ts +++ /dev/null @@ -1,45 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { defineAsyncComponent } from 'vue'; -import * as os from '@/os.js'; - -export type SystemWebhookEventType = 'abuseReport' | 'abuseReportResolved'; - -export type MkSystemWebhookEditorProps = { - mode: 'create' | 'edit'; - id?: string; - requiredEvents?: SystemWebhookEventType[]; -}; - -export type MkSystemWebhookResult = { - id?: string; - isActive: boolean; - name: string; - on: SystemWebhookEventType[]; - url: string; - secret: string; -}; - -export async function showSystemWebhookEditorDialog(props: MkSystemWebhookEditorProps): Promise { - const { dispose, result } = await new Promise<{ dispose: () => void, result: MkSystemWebhookResult | null }>(async resolve => { - const res = await os.popup( - defineAsyncComponent(() => import('@/components/MkSystemWebhookEditor.vue')), - props, - { - submitted: (ev: MkSystemWebhookResult) => { - resolve({ dispose: res.dispose, result: ev }); - }, - closed: () => { - resolve({ dispose: res.dispose, result: null }); - }, - }, - ); - }); - - dispose(); - - return result; -} diff --git a/packages/frontend/src/components/MkSystemWebhookEditor.vue b/packages/frontend/src/components/MkSystemWebhookEditor.vue deleted file mode 100644 index 007d841f001a..000000000000 --- a/packages/frontend/src/components/MkSystemWebhookEditor.vue +++ /dev/null @@ -1,217 +0,0 @@ - - - - - - - diff --git a/packages/frontend/src/pages/admin/abuse-report/notification-recipient.editor.vue b/packages/frontend/src/pages/admin/abuse-report/notification-recipient.editor.vue deleted file mode 100644 index ffe9c620d637..000000000000 --- a/packages/frontend/src/pages/admin/abuse-report/notification-recipient.editor.vue +++ /dev/null @@ -1,307 +0,0 @@ - - - - - - - diff --git a/packages/frontend/src/pages/admin/abuse-report/notification-recipient.item.vue b/packages/frontend/src/pages/admin/abuse-report/notification-recipient.item.vue deleted file mode 100644 index 0b86808fafb1..000000000000 --- a/packages/frontend/src/pages/admin/abuse-report/notification-recipient.item.vue +++ /dev/null @@ -1,114 +0,0 @@ - - - - - - - diff --git a/packages/frontend/src/pages/admin/abuse-report/notification-recipient.vue b/packages/frontend/src/pages/admin/abuse-report/notification-recipient.vue deleted file mode 100644 index a52f8eb7af94..000000000000 --- a/packages/frontend/src/pages/admin/abuse-report/notification-recipient.vue +++ /dev/null @@ -1,176 +0,0 @@ - - - - - - - diff --git a/packages/frontend/src/pages/admin/abuses.vue b/packages/frontend/src/pages/admin/abuses.vue index 9a9fa472a598..d2f4a4b531e6 100644 --- a/packages/frontend/src/pages/admin/abuses.vue +++ b/packages/frontend/src/pages/admin/abuses.vue @@ -7,33 +7,30 @@ SPDX-License-Identifier: AGPL-3.0-only -
-
- {{ "通知設定" }} -
- -
- - - - - - - - - - - - - - - - - - -
- - - - - + + + +
+
@@ -61,7 +60,6 @@ import MkPagination from '@/components/MkPagination.vue'; import XAbuseReport from '@/components/MkAbuseReport.vue'; import { i18n } from '@/i18n.js'; import { definePageMetadata } from '@/scripts/page-metadata.js'; -import MkButton from '@/components/MkButton.vue'; const reports = shallowRef>(); @@ -82,7 +80,7 @@ const pagination = { }; function resolved(reportId) { - reports.value?.removeItem(reportId); + reports.value.removeItem(reportId); } const headerActions = computed(() => []); @@ -94,26 +92,3 @@ definePageMetadata(() => ({ icon: 'ti ti-exclamation-circle', })); - - diff --git a/packages/frontend/src/pages/admin/index.vue b/packages/frontend/src/pages/admin/index.vue index 292f10da1a18..794feae202ad 100644 --- a/packages/frontend/src/pages/admin/index.vue +++ b/packages/frontend/src/pages/admin/index.vue @@ -214,11 +214,6 @@ const menuDef = computed(() => [{ text: i18n.ts.externalServices, to: '/admin/external-services', active: currentPage.value?.route.name === 'external-services', - }, { - icon: 'ti ti-webhook', - text: 'Webhook', - to: '/admin/system-webhook', - active: currentPage.value?.route.name === 'system-webhook', }, { icon: 'ti ti-adjustments', text: i18n.ts.other, diff --git a/packages/frontend/src/pages/admin/modlog.ModLog.vue b/packages/frontend/src/pages/admin/modlog.ModLog.vue index 91f1c7c5e625..e33c88272187 100644 --- a/packages/frontend/src/pages/admin/modlog.ModLog.vue +++ b/packages/frontend/src/pages/admin/modlog.ModLog.vue @@ -8,35 +8,9 @@ SPDX-License-Identifier: AGPL-3.0-only - -
raw diff --git a/packages/frontend/src/pages/admin/system-webhook.item.vue b/packages/frontend/src/pages/admin/system-webhook.item.vue deleted file mode 100644 index 0c07122af33a..000000000000 --- a/packages/frontend/src/pages/admin/system-webhook.item.vue +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - diff --git a/packages/frontend/src/pages/admin/system-webhook.vue b/packages/frontend/src/pages/admin/system-webhook.vue deleted file mode 100644 index 7a40eec94494..000000000000 --- a/packages/frontend/src/pages/admin/system-webhook.vue +++ /dev/null @@ -1,96 +0,0 @@ - - - - - - - diff --git a/packages/frontend/src/router/definition.ts b/packages/frontend/src/router/definition.ts index 8a443f627b23..c12ae0fa572b 100644 --- a/packages/frontend/src/router/definition.ts +++ b/packages/frontend/src/router/definition.ts @@ -471,14 +471,6 @@ const routes: RouteDef[] = [{ path: '/invites', name: 'invites', component: page(() => import('@/pages/admin/invites.vue')), - }, { - path: '/abuse-report-notification-recipient', - name: 'abuse-report-notification-recipient', - component: page(() => import('@/pages/admin/abuse-report/notification-recipient.vue')), - }, { - path: '/system-webhook', - name: 'system-webhook', - component: page(() => import('@/pages/admin/system-webhook.vue')), }, { path: '/', component: page(() => import('@/pages/_empty_.vue')), diff --git a/packages/misskey-js/etc/misskey-js.api.md b/packages/misskey-js/etc/misskey-js.api.md index bea89f2a7c0a..6ff711cabbb5 100644 --- a/packages/misskey-js/etc/misskey-js.api.md +++ b/packages/misskey-js/etc/misskey-js.api.md @@ -6,11 +6,6 @@ import { EventEmitter } from 'eventemitter3'; -// Warning: (ae-forgotten-export) The symbol "components" needs to be exported by the entry point index.d.ts -// -// @public (undocumented) -type AbuseReportNotificationRecipient = components['schemas']['AbuseReportNotificationRecipient']; - // @public (undocumented) export type Acct = { username: string; @@ -26,38 +21,13 @@ declare namespace acct { } export { acct } +// Warning: (ae-forgotten-export) The symbol "components" needs to be exported by the entry point index.d.ts +// // @public (undocumented) type Ad = components['schemas']['Ad']; // Warning: (ae-forgotten-export) The symbol "operations" needs to be exported by the entry point index.d.ts // -// @public (undocumented) -type AdminAbuseReportNotificationRecipientCreateRequest = operations['admin___abuse-report___notification-recipient___create']['requestBody']['content']['application/json']; - -// @public (undocumented) -type AdminAbuseReportNotificationRecipientCreateResponse = operations['admin___abuse-report___notification-recipient___create']['responses']['200']['content']['application/json']; - -// @public (undocumented) -type AdminAbuseReportNotificationRecipientDeleteRequest = operations['admin___abuse-report___notification-recipient___delete']['requestBody']['content']['application/json']; - -// @public (undocumented) -type AdminAbuseReportNotificationRecipientListRequest = operations['admin___abuse-report___notification-recipient___list']['requestBody']['content']['application/json']; - -// @public (undocumented) -type AdminAbuseReportNotificationRecipientListResponse = operations['admin___abuse-report___notification-recipient___list']['responses']['200']['content']['application/json']; - -// @public (undocumented) -type AdminAbuseReportNotificationRecipientShowRequest = operations['admin___abuse-report___notification-recipient___show']['requestBody']['content']['application/json']; - -// @public (undocumented) -type AdminAbuseReportNotificationRecipientShowResponse = operations['admin___abuse-report___notification-recipient___show']['responses']['200']['content']['application/json']; - -// @public (undocumented) -type AdminAbuseReportNotificationRecipientUpdateRequest = operations['admin___abuse-report___notification-recipient___update']['requestBody']['content']['application/json']; - -// @public (undocumented) -type AdminAbuseReportNotificationRecipientUpdateResponse = operations['admin___abuse-report___notification-recipient___update']['responses']['200']['content']['application/json']; - // @public (undocumented) type AdminAbuseUserReportsRequest = operations['admin___abuse-user-reports']['requestBody']['content']['application/json']; @@ -337,33 +307,6 @@ type AdminShowUsersResponse = operations['admin___show-users']['responses']['200 // @public (undocumented) type AdminSuspendUserRequest = operations['admin___suspend-user']['requestBody']['content']['application/json']; -// @public (undocumented) -type AdminSystemWebhookCreateRequest = operations['admin___system-webhook___create']['requestBody']['content']['application/json']; - -// @public (undocumented) -type AdminSystemWebhookCreateResponse = operations['admin___system-webhook___create']['responses']['200']['content']['application/json']; - -// @public (undocumented) -type AdminSystemWebhookDeleteRequest = operations['admin___system-webhook___delete']['requestBody']['content']['application/json']; - -// @public (undocumented) -type AdminSystemWebhookListRequest = operations['admin___system-webhook___list']['requestBody']['content']['application/json']; - -// @public (undocumented) -type AdminSystemWebhookListResponse = operations['admin___system-webhook___list']['responses']['200']['content']['application/json']; - -// @public (undocumented) -type AdminSystemWebhookShowRequest = operations['admin___system-webhook___show']['requestBody']['content']['application/json']; - -// @public (undocumented) -type AdminSystemWebhookShowResponse = operations['admin___system-webhook___show']['responses']['200']['content']['application/json']; - -// @public (undocumented) -type AdminSystemWebhookUpdateRequest = operations['admin___system-webhook___update']['requestBody']['content']['application/json']; - -// @public (undocumented) -type AdminSystemWebhookUpdateResponse = operations['admin___system-webhook___update']['responses']['200']['content']['application/json']; - // @public (undocumented) type AdminUnsetUserAvatarRequest = operations['admin___unset-user-avatar']['requestBody']['content']['application/json']; @@ -1190,15 +1133,6 @@ declare namespace entities { AdminMetaResponse, AdminAbuseUserReportsRequest, AdminAbuseUserReportsResponse, - AdminAbuseReportNotificationRecipientListRequest, - AdminAbuseReportNotificationRecipientListResponse, - AdminAbuseReportNotificationRecipientShowRequest, - AdminAbuseReportNotificationRecipientShowResponse, - AdminAbuseReportNotificationRecipientCreateRequest, - AdminAbuseReportNotificationRecipientCreateResponse, - AdminAbuseReportNotificationRecipientUpdateRequest, - AdminAbuseReportNotificationRecipientUpdateResponse, - AdminAbuseReportNotificationRecipientDeleteRequest, AdminAccountsCreateRequest, AdminAccountsCreateResponse, AdminAccountsDeleteRequest, @@ -1294,15 +1228,6 @@ declare namespace entities { AdminRolesUpdateDefaultPoliciesRequest, AdminRolesUsersRequest, AdminRolesUsersResponse, - AdminSystemWebhookCreateRequest, - AdminSystemWebhookCreateResponse, - AdminSystemWebhookDeleteRequest, - AdminSystemWebhookListRequest, - AdminSystemWebhookListResponse, - AdminSystemWebhookShowRequest, - AdminSystemWebhookShowResponse, - AdminSystemWebhookUpdateRequest, - AdminSystemWebhookUpdateResponse, AnnouncementsRequest, AnnouncementsResponse, AnnouncementsShowRequest, @@ -1808,9 +1733,7 @@ declare namespace entities { ReversiGameDetailed, MetaLite, MetaDetailedOnly, - MetaDetailed, - SystemWebhook, - AbuseReportNotificationRecipient + MetaDetailed } } export { entities } @@ -2457,23 +2380,8 @@ type ModerationLog = { type: 'unsetUserAvatar'; info: ModerationLogPayloads['unsetUserAvatar']; } | { - type: 'createSystemWebhook'; - info: ModerationLogPayloads['createSystemWebhook']; -} | { - type: 'updateSystemWebhook'; - info: ModerationLogPayloads['updateSystemWebhook']; -} | { - type: 'deleteSystemWebhook'; - info: ModerationLogPayloads['deleteSystemWebhook']; -} | { - type: 'createAbuseReportNotificationRecipient'; - info: ModerationLogPayloads['createAbuseReportNotificationRecipient']; -} | { - type: 'updateAbuseReportNotificationRecipient'; - info: ModerationLogPayloads['updateAbuseReportNotificationRecipient']; -} | { - type: 'deleteAbuseReportNotificationRecipient'; - info: ModerationLogPayloads['deleteAbuseReportNotificationRecipient']; + type: 'unsetUserBanner'; + info: ModerationLogPayloads['unsetUserBanner']; }); // @public (undocumented) @@ -3013,9 +2921,6 @@ type SwUpdateRegistrationRequest = operations['sw___update-registration']['reque // @public (undocumented) type SwUpdateRegistrationResponse = operations['sw___update-registration']['responses']['200']['content']['application/json']; -// @public (undocumented) -type SystemWebhook = components['schemas']['SystemWebhook']; - // @public (undocumented) type TestRequest = operations['test']['requestBody']['content']['application/json']; diff --git a/packages/misskey-js/src/autogen/apiClientJSDoc.ts b/packages/misskey-js/src/autogen/apiClientJSDoc.ts index e799d4a0c5e0..181f7274b7b6 100644 --- a/packages/misskey-js/src/autogen/apiClientJSDoc.ts +++ b/packages/misskey-js/src/autogen/apiClientJSDoc.ts @@ -25,66 +25,6 @@ declare module '../api.js' { credential?: string | null, ): Promise>; - /** - * No description provided. - * - * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. - * **Credential required**: *Yes* / **Permission**: *read:admin:abuse-report:notification-recipient* - */ - request( - endpoint: E, - params: P, - credential?: string | null, - ): Promise>; - - /** - * No description provided. - * - * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. - * **Credential required**: *Yes* / **Permission**: *read:admin:abuse-report:notification-recipient* - */ - request( - endpoint: E, - params: P, - credential?: string | null, - ): Promise>; - - /** - * No description provided. - * - * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. - * **Credential required**: *Yes* / **Permission**: *write:admin:abuse-report:notification-recipient* - */ - request( - endpoint: E, - params: P, - credential?: string | null, - ): Promise>; - - /** - * No description provided. - * - * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. - * **Credential required**: *Yes* / **Permission**: *write:admin:abuse-report:notification-recipient* - */ - request( - endpoint: E, - params: P, - credential?: string | null, - ): Promise>; - - /** - * No description provided. - * - * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. - * **Credential required**: *Yes* / **Permission**: *write:admin:abuse-report:notification-recipient* - */ - request( - endpoint: E, - params: P, - credential?: string | null, - ): Promise>; - /** * No description provided. * @@ -900,66 +840,6 @@ declare module '../api.js' { credential?: string | null, ): Promise>; - /** - * No description provided. - * - * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. - * **Credential required**: *Yes* / **Permission**: *write:admin:system-webhook* - */ - request( - endpoint: E, - params: P, - credential?: string | null, - ): Promise>; - - /** - * No description provided. - * - * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. - * **Credential required**: *Yes* / **Permission**: *write:admin:system-webhook* - */ - request( - endpoint: E, - params: P, - credential?: string | null, - ): Promise>; - - /** - * No description provided. - * - * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. - * **Credential required**: *Yes* / **Permission**: *write:admin:system-webhook* - */ - request( - endpoint: E, - params: P, - credential?: string | null, - ): Promise>; - - /** - * No description provided. - * - * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. - * **Credential required**: *Yes* / **Permission**: *write:admin:system-webhook* - */ - request( - endpoint: E, - params: P, - credential?: string | null, - ): Promise>; - - /** - * No description provided. - * - * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. - * **Credential required**: *Yes* / **Permission**: *write:admin:system-webhook* - */ - request( - endpoint: E, - params: P, - credential?: string | null, - ): Promise>; - /** * No description provided. * diff --git a/packages/misskey-js/src/autogen/endpoint.ts b/packages/misskey-js/src/autogen/endpoint.ts index 20c8509d4c6f..ab3baf16700d 100644 --- a/packages/misskey-js/src/autogen/endpoint.ts +++ b/packages/misskey-js/src/autogen/endpoint.ts @@ -4,15 +4,6 @@ import type { AdminMetaResponse, AdminAbuseUserReportsRequest, AdminAbuseUserReportsResponse, - AdminAbuseReportNotificationRecipientListRequest, - AdminAbuseReportNotificationRecipientListResponse, - AdminAbuseReportNotificationRecipientShowRequest, - AdminAbuseReportNotificationRecipientShowResponse, - AdminAbuseReportNotificationRecipientCreateRequest, - AdminAbuseReportNotificationRecipientCreateResponse, - AdminAbuseReportNotificationRecipientUpdateRequest, - AdminAbuseReportNotificationRecipientUpdateResponse, - AdminAbuseReportNotificationRecipientDeleteRequest, AdminAccountsCreateRequest, AdminAccountsCreateResponse, AdminAccountsDeleteRequest, @@ -108,15 +99,6 @@ import type { AdminRolesUpdateDefaultPoliciesRequest, AdminRolesUsersRequest, AdminRolesUsersResponse, - AdminSystemWebhookCreateRequest, - AdminSystemWebhookCreateResponse, - AdminSystemWebhookDeleteRequest, - AdminSystemWebhookListRequest, - AdminSystemWebhookListResponse, - AdminSystemWebhookShowRequest, - AdminSystemWebhookShowResponse, - AdminSystemWebhookUpdateRequest, - AdminSystemWebhookUpdateResponse, AnnouncementsRequest, AnnouncementsResponse, AnnouncementsShowRequest, @@ -576,11 +558,6 @@ import type { export type Endpoints = { 'admin/meta': { req: EmptyRequest; res: AdminMetaResponse }; 'admin/abuse-user-reports': { req: AdminAbuseUserReportsRequest; res: AdminAbuseUserReportsResponse }; - 'admin/abuse-report/notification-recipient/list': { req: AdminAbuseReportNotificationRecipientListRequest; res: AdminAbuseReportNotificationRecipientListResponse }; - 'admin/abuse-report/notification-recipient/show': { req: AdminAbuseReportNotificationRecipientShowRequest; res: AdminAbuseReportNotificationRecipientShowResponse }; - 'admin/abuse-report/notification-recipient/create': { req: AdminAbuseReportNotificationRecipientCreateRequest; res: AdminAbuseReportNotificationRecipientCreateResponse }; - 'admin/abuse-report/notification-recipient/update': { req: AdminAbuseReportNotificationRecipientUpdateRequest; res: AdminAbuseReportNotificationRecipientUpdateResponse }; - 'admin/abuse-report/notification-recipient/delete': { req: AdminAbuseReportNotificationRecipientDeleteRequest; res: EmptyResponse }; 'admin/accounts/create': { req: AdminAccountsCreateRequest; res: AdminAccountsCreateResponse }; 'admin/accounts/delete': { req: AdminAccountsDeleteRequest; res: EmptyResponse }; 'admin/accounts/find-by-email': { req: AdminAccountsFindByEmailRequest; res: AdminAccountsFindByEmailResponse }; @@ -655,11 +632,6 @@ export type Endpoints = { 'admin/roles/unassign': { req: AdminRolesUnassignRequest; res: EmptyResponse }; 'admin/roles/update-default-policies': { req: AdminRolesUpdateDefaultPoliciesRequest; res: EmptyResponse }; 'admin/roles/users': { req: AdminRolesUsersRequest; res: AdminRolesUsersResponse }; - 'admin/system-webhook/create': { req: AdminSystemWebhookCreateRequest; res: AdminSystemWebhookCreateResponse }; - 'admin/system-webhook/delete': { req: AdminSystemWebhookDeleteRequest; res: EmptyResponse }; - 'admin/system-webhook/list': { req: AdminSystemWebhookListRequest; res: AdminSystemWebhookListResponse }; - 'admin/system-webhook/show': { req: AdminSystemWebhookShowRequest; res: AdminSystemWebhookShowResponse }; - 'admin/system-webhook/update': { req: AdminSystemWebhookUpdateRequest; res: AdminSystemWebhookUpdateResponse }; 'announcements': { req: AnnouncementsRequest; res: AnnouncementsResponse }; 'announcements/show': { req: AnnouncementsShowRequest; res: AnnouncementsShowResponse }; 'antennas/create': { req: AntennasCreateRequest; res: AntennasCreateResponse }; diff --git a/packages/misskey-js/src/autogen/entities.ts b/packages/misskey-js/src/autogen/entities.ts index 357b5e9eaf68..02ca932d8a38 100644 --- a/packages/misskey-js/src/autogen/entities.ts +++ b/packages/misskey-js/src/autogen/entities.ts @@ -7,15 +7,6 @@ export type EmptyResponse = Record | undefined; export type AdminMetaResponse = operations['admin___meta']['responses']['200']['content']['application/json']; export type AdminAbuseUserReportsRequest = operations['admin___abuse-user-reports']['requestBody']['content']['application/json']; export type AdminAbuseUserReportsResponse = operations['admin___abuse-user-reports']['responses']['200']['content']['application/json']; -export type AdminAbuseReportNotificationRecipientListRequest = operations['admin___abuse-report___notification-recipient___list']['requestBody']['content']['application/json']; -export type AdminAbuseReportNotificationRecipientListResponse = operations['admin___abuse-report___notification-recipient___list']['responses']['200']['content']['application/json']; -export type AdminAbuseReportNotificationRecipientShowRequest = operations['admin___abuse-report___notification-recipient___show']['requestBody']['content']['application/json']; -export type AdminAbuseReportNotificationRecipientShowResponse = operations['admin___abuse-report___notification-recipient___show']['responses']['200']['content']['application/json']; -export type AdminAbuseReportNotificationRecipientCreateRequest = operations['admin___abuse-report___notification-recipient___create']['requestBody']['content']['application/json']; -export type AdminAbuseReportNotificationRecipientCreateResponse = operations['admin___abuse-report___notification-recipient___create']['responses']['200']['content']['application/json']; -export type AdminAbuseReportNotificationRecipientUpdateRequest = operations['admin___abuse-report___notification-recipient___update']['requestBody']['content']['application/json']; -export type AdminAbuseReportNotificationRecipientUpdateResponse = operations['admin___abuse-report___notification-recipient___update']['responses']['200']['content']['application/json']; -export type AdminAbuseReportNotificationRecipientDeleteRequest = operations['admin___abuse-report___notification-recipient___delete']['requestBody']['content']['application/json']; export type AdminAccountsCreateRequest = operations['admin___accounts___create']['requestBody']['content']['application/json']; export type AdminAccountsCreateResponse = operations['admin___accounts___create']['responses']['200']['content']['application/json']; export type AdminAccountsDeleteRequest = operations['admin___accounts___delete']['requestBody']['content']['application/json']; @@ -111,15 +102,6 @@ export type AdminRolesUnassignRequest = operations['admin___roles___unassign'][' export type AdminRolesUpdateDefaultPoliciesRequest = operations['admin___roles___update-default-policies']['requestBody']['content']['application/json']; export type AdminRolesUsersRequest = operations['admin___roles___users']['requestBody']['content']['application/json']; export type AdminRolesUsersResponse = operations['admin___roles___users']['responses']['200']['content']['application/json']; -export type AdminSystemWebhookCreateRequest = operations['admin___system-webhook___create']['requestBody']['content']['application/json']; -export type AdminSystemWebhookCreateResponse = operations['admin___system-webhook___create']['responses']['200']['content']['application/json']; -export type AdminSystemWebhookDeleteRequest = operations['admin___system-webhook___delete']['requestBody']['content']['application/json']; -export type AdminSystemWebhookListRequest = operations['admin___system-webhook___list']['requestBody']['content']['application/json']; -export type AdminSystemWebhookListResponse = operations['admin___system-webhook___list']['responses']['200']['content']['application/json']; -export type AdminSystemWebhookShowRequest = operations['admin___system-webhook___show']['requestBody']['content']['application/json']; -export type AdminSystemWebhookShowResponse = operations['admin___system-webhook___show']['responses']['200']['content']['application/json']; -export type AdminSystemWebhookUpdateRequest = operations['admin___system-webhook___update']['requestBody']['content']['application/json']; -export type AdminSystemWebhookUpdateResponse = operations['admin___system-webhook___update']['responses']['200']['content']['application/json']; export type AnnouncementsRequest = operations['announcements']['requestBody']['content']['application/json']; export type AnnouncementsResponse = operations['announcements']['responses']['200']['content']['application/json']; export type AnnouncementsShowRequest = operations['announcements___show']['requestBody']['content']['application/json']; diff --git a/packages/misskey-js/src/autogen/models.ts b/packages/misskey-js/src/autogen/models.ts index 04574849d44d..a6e5fbe6890e 100644 --- a/packages/misskey-js/src/autogen/models.ts +++ b/packages/misskey-js/src/autogen/models.ts @@ -51,5 +51,3 @@ export type ReversiGameDetailed = components['schemas']['ReversiGameDetailed']; export type MetaLite = components['schemas']['MetaLite']; export type MetaDetailedOnly = components['schemas']['MetaDetailedOnly']; export type MetaDetailed = components['schemas']['MetaDetailed']; -export type SystemWebhook = components['schemas']['SystemWebhook']; -export type AbuseReportNotificationRecipient = components['schemas']['AbuseReportNotificationRecipient']; diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts index 729b4bf92ec7..e14f160c10a5 100644 --- a/packages/misskey-js/src/autogen/types.ts +++ b/packages/misskey-js/src/autogen/types.ts @@ -30,56 +30,6 @@ export type paths = { */ post: operations['admin___abuse-user-reports']; }; - '/admin/abuse-report/notification-recipient/list': { - /** - * admin/abuse-report/notification-recipient/list - * @description No description provided. - * - * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. - * **Credential required**: *Yes* / **Permission**: *read:admin:abuse-report:notification-recipient* - */ - post: operations['admin___abuse-report___notification-recipient___list']; - }; - '/admin/abuse-report/notification-recipient/show': { - /** - * admin/abuse-report/notification-recipient/show - * @description No description provided. - * - * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. - * **Credential required**: *Yes* / **Permission**: *read:admin:abuse-report:notification-recipient* - */ - post: operations['admin___abuse-report___notification-recipient___show']; - }; - '/admin/abuse-report/notification-recipient/create': { - /** - * admin/abuse-report/notification-recipient/create - * @description No description provided. - * - * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. - * **Credential required**: *Yes* / **Permission**: *write:admin:abuse-report:notification-recipient* - */ - post: operations['admin___abuse-report___notification-recipient___create']; - }; - '/admin/abuse-report/notification-recipient/update': { - /** - * admin/abuse-report/notification-recipient/update - * @description No description provided. - * - * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. - * **Credential required**: *Yes* / **Permission**: *write:admin:abuse-report:notification-recipient* - */ - post: operations['admin___abuse-report___notification-recipient___update']; - }; - '/admin/abuse-report/notification-recipient/delete': { - /** - * admin/abuse-report/notification-recipient/delete - * @description No description provided. - * - * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. - * **Credential required**: *Yes* / **Permission**: *write:admin:abuse-report:notification-recipient* - */ - post: operations['admin___abuse-report___notification-recipient___delete']; - }; '/admin/accounts/create': { /** * admin/accounts/create @@ -747,56 +697,6 @@ export type paths = { */ post: operations['admin___roles___users']; }; - '/admin/system-webhook/create': { - /** - * admin/system-webhook/create - * @description No description provided. - * - * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. - * **Credential required**: *Yes* / **Permission**: *write:admin:system-webhook* - */ - post: operations['admin___system-webhook___create']; - }; - '/admin/system-webhook/delete': { - /** - * admin/system-webhook/delete - * @description No description provided. - * - * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. - * **Credential required**: *Yes* / **Permission**: *write:admin:system-webhook* - */ - post: operations['admin___system-webhook___delete']; - }; - '/admin/system-webhook/list': { - /** - * admin/system-webhook/list - * @description No description provided. - * - * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. - * **Credential required**: *Yes* / **Permission**: *write:admin:system-webhook* - */ - post: operations['admin___system-webhook___list']; - }; - '/admin/system-webhook/show': { - /** - * admin/system-webhook/show - * @description No description provided. - * - * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. - * **Credential required**: *Yes* / **Permission**: *write:admin:system-webhook* - */ - post: operations['admin___system-webhook___show']; - }; - '/admin/system-webhook/update': { - /** - * admin/system-webhook/update - * @description No description provided. - * - * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. - * **Credential required**: *Yes* / **Permission**: *write:admin:system-webhook* - */ - post: operations['admin___system-webhook___update']; - }; '/announcements': { /** * announcements @@ -4958,32 +4858,6 @@ export type components = { cacheRemoteSensitiveFiles: boolean; }; MetaDetailed: components['schemas']['MetaLite'] & components['schemas']['MetaDetailedOnly']; - SystemWebhook: { - id: string; - isActive: boolean; - /** Format: date-time */ - updatedAt: string; - /** Format: date-time */ - latestSentAt: string | null; - latestStatus: number | null; - name: string; - on: ('abuseReport' | 'abuseReportResolved')[]; - url: string; - secret: string; - }; - AbuseReportNotificationRecipient: { - id: string; - isActive: boolean; - /** Format: date-time */ - updatedAt: string; - name: string; - /** @enum {string} */ - method: 'email' | 'webhook'; - userId?: string; - user?: components['schemas']['UserLite']; - systemWebhookId?: string; - systemWebhook?: components['schemas']['SystemWebhook']; - }; }; responses: never; parameters: never; @@ -5251,17 +5125,17 @@ export type operations = { }; }; /** - * admin/abuse-report/notification-recipient/list + * admin/accounts/create * @description No description provided. * - * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. - * **Credential required**: *Yes* / **Permission**: *read:admin:abuse-report:notification-recipient* + * **Credential required**: *No* */ - 'admin___abuse-report___notification-recipient___list': { + admin___accounts___create: { requestBody: { content: { 'application/json': { - method?: ('email' | 'webhook')[]; + username: string; + password: string; }; }; }; @@ -5269,7 +5143,7 @@ export type operations = { /** @description OK (with results) */ 200: { content: { - 'application/json': components['schemas']['AbuseReportNotificationRecipient'][]; + 'application/json': components['schemas']['MeDetailed']; }; }; /** @description Client error */ @@ -5305,27 +5179,24 @@ export type operations = { }; }; /** - * admin/abuse-report/notification-recipient/show + * admin/accounts/delete * @description No description provided. * - * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. - * **Credential required**: *Yes* / **Permission**: *read:admin:abuse-report:notification-recipient* + * **Credential required**: *Yes* / **Permission**: *write:admin:account* */ - 'admin___abuse-report___notification-recipient___show': { + admin___accounts___delete: { requestBody: { content: { 'application/json': { /** Format: misskey:id */ - id: string; + userId: string; }; }; }; responses: { - /** @description OK (with results) */ - 200: { - content: { - 'application/json': components['schemas']['AbuseReportNotificationRecipient']; - }; + /** @description OK (without any results) */ + 204: { + content: never; }; /** @description Client error */ 400: { @@ -5360,24 +5231,16 @@ export type operations = { }; }; /** - * admin/abuse-report/notification-recipient/create + * admin/accounts/find-by-email * @description No description provided. * - * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. - * **Credential required**: *Yes* / **Permission**: *write:admin:abuse-report:notification-recipient* + * **Credential required**: *Yes* / **Permission**: *read:admin:account* */ - 'admin___abuse-report___notification-recipient___create': { + 'admin___accounts___find-by-email': { requestBody: { content: { 'application/json': { - isActive: boolean; - name: string; - /** @enum {string} */ - method: 'email' | 'webhook'; - /** Format: misskey:id */ - userId?: string; - /** Format: misskey:id */ - systemWebhookId?: string; + email: string; }; }; }; @@ -5385,7 +5248,7 @@ export type operations = { /** @description OK (with results) */ 200: { content: { - 'application/json': components['schemas']['AbuseReportNotificationRecipient']; + 'application/json': components['schemas']['UserDetailedNotMe']; }; }; /** @description Client error */ @@ -5421,26 +5284,24 @@ export type operations = { }; }; /** - * admin/abuse-report/notification-recipient/update + * admin/ad/create * @description No description provided. * - * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. - * **Credential required**: *Yes* / **Permission**: *write:admin:abuse-report:notification-recipient* + * **Credential required**: *Yes* / **Permission**: *write:admin:ad* */ - 'admin___abuse-report___notification-recipient___update': { + admin___ad___create: { requestBody: { content: { 'application/json': { - /** Format: misskey:id */ - id: string; - isActive: boolean; - name: string; - /** @enum {string} */ - method: 'email' | 'webhook'; - /** Format: misskey:id */ - userId?: string; - /** Format: misskey:id */ - systemWebhookId?: string; + url: string; + memo: string; + place: string; + priority: string; + ratio: number; + expiresAt: number; + startsAt: number; + imageUrl: string; + dayOfWeek: number; }; }; }; @@ -5448,7 +5309,7 @@ export type operations = { /** @description OK (with results) */ 200: { content: { - 'application/json': components['schemas']['AbuseReportNotificationRecipient']; + 'application/json': components['schemas']['Ad']; }; }; /** @description Client error */ @@ -5484,13 +5345,12 @@ export type operations = { }; }; /** - * admin/abuse-report/notification-recipient/delete + * admin/ad/delete * @description No description provided. * - * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. - * **Credential required**: *Yes* / **Permission**: *write:admin:abuse-report:notification-recipient* + * **Credential required**: *Yes* / **Permission**: *write:admin:ad* */ - 'admin___abuse-report___notification-recipient___delete': { + admin___ad___delete: { requestBody: { content: { 'application/json': { @@ -5537,17 +5397,23 @@ export type operations = { }; }; /** - * admin/accounts/create + * admin/ad/list * @description No description provided. * - * **Credential required**: *No* + * **Credential required**: *Yes* / **Permission**: *read:admin:ad* */ - admin___accounts___create: { + admin___ad___list: { requestBody: { content: { 'application/json': { - username: string; - password: string; + /** @default 10 */ + limit?: number; + /** Format: misskey:id */ + sinceId?: string; + /** Format: misskey:id */ + untilId?: string; + /** @default null */ + publishing?: boolean | null; }; }; }; @@ -5555,7 +5421,7 @@ export type operations = { /** @description OK (with results) */ 200: { content: { - 'application/json': components['schemas']['MeDetailed']; + 'application/json': components['schemas']['Ad'][]; }; }; /** @description Client error */ @@ -5591,17 +5457,26 @@ export type operations = { }; }; /** - * admin/accounts/delete + * admin/ad/update * @description No description provided. * - * **Credential required**: *Yes* / **Permission**: *write:admin:account* + * **Credential required**: *Yes* / **Permission**: *write:admin:ad* */ - admin___accounts___delete: { + admin___ad___update: { requestBody: { content: { 'application/json': { /** Format: misskey:id */ - userId: string; + id: string; + memo: string; + url: string; + imageUrl: string; + place: string; + priority: string; + ratio: number; + expiresAt: number; + startsAt: number; + dayOfWeek: number; }; }; }; @@ -5643,16 +5518,39 @@ export type operations = { }; }; /** - * admin/accounts/find-by-email + * admin/announcements/create * @description No description provided. * - * **Credential required**: *Yes* / **Permission**: *read:admin:account* + * **Credential required**: *Yes* / **Permission**: *write:admin:announcements* */ - 'admin___accounts___find-by-email': { + admin___announcements___create: { requestBody: { content: { 'application/json': { - email: string; + title: string; + text: string; + imageUrl: string | null; + /** + * @default info + * @enum {string} + */ + icon?: 'info' | 'warning' | 'error' | 'success'; + /** + * @default normal + * @enum {string} + */ + display?: 'normal' | 'banner' | 'dialog'; + /** @default false */ + forExistingUsers?: boolean; + /** @default false */ + silence?: boolean; + /** @default false */ + needConfirmationToRead?: boolean; + /** + * Format: misskey:id + * @default null + */ + userId?: string | null; }; }; }; @@ -5660,7 +5558,20 @@ export type operations = { /** @description OK (with results) */ 200: { content: { - 'application/json': components['schemas']['UserDetailedNotMe']; + 'application/json': { + /** + * Format: id + * @example xxxxxxxxxx + */ + id: string; + /** Format: date-time */ + createdAt: string; + /** Format: date-time */ + updatedAt: string | null; + title: string; + text: string; + imageUrl: string | null; + }; }; }; /** @description Client error */ @@ -5696,33 +5607,24 @@ export type operations = { }; }; /** - * admin/ad/create + * admin/announcements/delete * @description No description provided. * - * **Credential required**: *Yes* / **Permission**: *write:admin:ad* + * **Credential required**: *Yes* / **Permission**: *write:admin:announcements* */ - admin___ad___create: { + admin___announcements___delete: { requestBody: { content: { 'application/json': { - url: string; - memo: string; - place: string; - priority: string; - ratio: number; - expiresAt: number; - startsAt: number; - imageUrl: string; - dayOfWeek: number; + /** Format: misskey:id */ + id: string; }; }; }; responses: { - /** @description OK (with results) */ - 200: { - content: { - 'application/json': components['schemas']['Ad']; - }; + /** @description OK (without any results) */ + 204: { + content: never; }; /** @description Client error */ 400: { @@ -5757,337 +5659,23 @@ export type operations = { }; }; /** - * admin/ad/delete + * admin/announcements/list * @description No description provided. * - * **Credential required**: *Yes* / **Permission**: *write:admin:ad* + * **Credential required**: *Yes* / **Permission**: *read:admin:announcements* */ - admin___ad___delete: { + admin___announcements___list: { requestBody: { content: { 'application/json': { + /** @default 10 */ + limit?: number; /** Format: misskey:id */ - id: string; - }; - }; - }; - responses: { - /** @description OK (without any results) */ - 204: { - content: never; - }; - /** @description Client error */ - 400: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - /** @description Authentication error */ - 401: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - /** @description Forbidden error */ - 403: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - /** @description I'm Ai */ - 418: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - }; - }; - /** - * admin/ad/list - * @description No description provided. - * - * **Credential required**: *Yes* / **Permission**: *read:admin:ad* - */ - admin___ad___list: { - requestBody: { - content: { - 'application/json': { - /** @default 10 */ - limit?: number; - /** Format: misskey:id */ - sinceId?: string; - /** Format: misskey:id */ - untilId?: string; - /** @default null */ - publishing?: boolean | null; - }; - }; - }; - responses: { - /** @description OK (with results) */ - 200: { - content: { - 'application/json': components['schemas']['Ad'][]; - }; - }; - /** @description Client error */ - 400: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - /** @description Authentication error */ - 401: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - /** @description Forbidden error */ - 403: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - /** @description I'm Ai */ - 418: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - }; - }; - /** - * admin/ad/update - * @description No description provided. - * - * **Credential required**: *Yes* / **Permission**: *write:admin:ad* - */ - admin___ad___update: { - requestBody: { - content: { - 'application/json': { - /** Format: misskey:id */ - id: string; - memo: string; - url: string; - imageUrl: string; - place: string; - priority: string; - ratio: number; - expiresAt: number; - startsAt: number; - dayOfWeek: number; - }; - }; - }; - responses: { - /** @description OK (without any results) */ - 204: { - content: never; - }; - /** @description Client error */ - 400: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - /** @description Authentication error */ - 401: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - /** @description Forbidden error */ - 403: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - /** @description I'm Ai */ - 418: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - }; - }; - /** - * admin/announcements/create - * @description No description provided. - * - * **Credential required**: *Yes* / **Permission**: *write:admin:announcements* - */ - admin___announcements___create: { - requestBody: { - content: { - 'application/json': { - title: string; - text: string; - imageUrl: string | null; - /** - * @default info - * @enum {string} - */ - icon?: 'info' | 'warning' | 'error' | 'success'; - /** - * @default normal - * @enum {string} - */ - display?: 'normal' | 'banner' | 'dialog'; - /** @default false */ - forExistingUsers?: boolean; - /** @default false */ - silence?: boolean; - /** @default false */ - needConfirmationToRead?: boolean; - /** - * Format: misskey:id - * @default null - */ - userId?: string | null; - }; - }; - }; - responses: { - /** @description OK (with results) */ - 200: { - content: { - 'application/json': { - /** - * Format: id - * @example xxxxxxxxxx - */ - id: string; - /** Format: date-time */ - createdAt: string; - /** Format: date-time */ - updatedAt: string | null; - title: string; - text: string; - imageUrl: string | null; - }; - }; - }; - /** @description Client error */ - 400: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - /** @description Authentication error */ - 401: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - /** @description Forbidden error */ - 403: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - /** @description I'm Ai */ - 418: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - }; - }; - /** - * admin/announcements/delete - * @description No description provided. - * - * **Credential required**: *Yes* / **Permission**: *write:admin:announcements* - */ - admin___announcements___delete: { - requestBody: { - content: { - 'application/json': { - /** Format: misskey:id */ - id: string; - }; - }; - }; - responses: { - /** @description OK (without any results) */ - 204: { - content: never; - }; - /** @description Client error */ - 400: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - /** @description Authentication error */ - 401: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - /** @description Forbidden error */ - 403: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - /** @description I'm Ai */ - 418: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - }; - }; - /** - * admin/announcements/list - * @description No description provided. - * - * **Credential required**: *Yes* / **Permission**: *read:admin:announcements* - */ - admin___announcements___list: { - requestBody: { - content: { - 'application/json': { - /** @default 10 */ - limit?: number; - /** Format: misskey:id */ - sinceId?: string; - /** Format: misskey:id */ - untilId?: string; - /** Format: misskey:id */ - userId?: string | null; + sinceId?: string; + /** Format: misskey:id */ + untilId?: string; + /** Format: misskey:id */ + userId?: string | null; }; }; }; @@ -10026,287 +9614,6 @@ export type operations = { }; }; }; - /** - * admin/system-webhook/create - * @description No description provided. - * - * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. - * **Credential required**: *Yes* / **Permission**: *write:admin:system-webhook* - */ - 'admin___system-webhook___create': { - requestBody: { - content: { - 'application/json': { - isActive: boolean; - name: string; - on: ('abuseReport' | 'abuseReportResolved')[]; - url: string; - secret: string; - }; - }; - }; - responses: { - /** @description OK (with results) */ - 200: { - content: { - 'application/json': components['schemas']['SystemWebhook']; - }; - }; - /** @description Client error */ - 400: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - /** @description Authentication error */ - 401: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - /** @description Forbidden error */ - 403: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - /** @description I'm Ai */ - 418: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - }; - }; - /** - * admin/system-webhook/delete - * @description No description provided. - * - * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. - * **Credential required**: *Yes* / **Permission**: *write:admin:system-webhook* - */ - 'admin___system-webhook___delete': { - requestBody: { - content: { - 'application/json': { - /** Format: misskey:id */ - id: string; - }; - }; - }; - responses: { - /** @description OK (without any results) */ - 204: { - content: never; - }; - /** @description Client error */ - 400: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - /** @description Authentication error */ - 401: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - /** @description Forbidden error */ - 403: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - /** @description I'm Ai */ - 418: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - }; - }; - /** - * admin/system-webhook/list - * @description No description provided. - * - * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. - * **Credential required**: *Yes* / **Permission**: *write:admin:system-webhook* - */ - 'admin___system-webhook___list': { - requestBody: { - content: { - 'application/json': { - isActive?: boolean; - on?: ('abuseReport' | 'abuseReportResolved')[]; - }; - }; - }; - responses: { - /** @description OK (with results) */ - 200: { - content: { - 'application/json': components['schemas']['SystemWebhook'][]; - }; - }; - /** @description Client error */ - 400: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - /** @description Authentication error */ - 401: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - /** @description Forbidden error */ - 403: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - /** @description I'm Ai */ - 418: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - }; - }; - /** - * admin/system-webhook/show - * @description No description provided. - * - * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. - * **Credential required**: *Yes* / **Permission**: *write:admin:system-webhook* - */ - 'admin___system-webhook___show': { - requestBody: { - content: { - 'application/json': { - /** Format: misskey:id */ - id: string; - }; - }; - }; - responses: { - /** @description OK (with results) */ - 200: { - content: { - 'application/json': components['schemas']['SystemWebhook']; - }; - }; - /** @description Client error */ - 400: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - /** @description Authentication error */ - 401: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - /** @description Forbidden error */ - 403: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - /** @description I'm Ai */ - 418: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - }; - }; - /** - * admin/system-webhook/update - * @description No description provided. - * - * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. - * **Credential required**: *Yes* / **Permission**: *write:admin:system-webhook* - */ - 'admin___system-webhook___update': { - requestBody: { - content: { - 'application/json': { - /** Format: misskey:id */ - id: string; - isActive: boolean; - name: string; - on: ('abuseReport' | 'abuseReportResolved')[]; - url: string; - secret: string; - }; - }; - }; - responses: { - /** @description OK (with results) */ - 200: { - content: { - 'application/json': components['schemas']['SystemWebhook']; - }; - }; - /** @description Client error */ - 400: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - /** @description Authentication error */ - 401: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - /** @description Forbidden error */ - 403: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - /** @description I'm Ai */ - 418: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - /** @description Internal server error */ - 500: { - content: { - 'application/json': components['schemas']['Error']; - }; - }; - }; - }; /** * announcements * @description No description provided. diff --git a/packages/misskey-js/src/consts.ts b/packages/misskey-js/src/consts.ts index 03b906929006..fd6ef4d68ded 100644 --- a/packages/misskey-js/src/consts.ts +++ b/packages/misskey-js/src/consts.ts @@ -325,30 +325,4 @@ export type ModerationLogPayloads = { userHost: string | null; fileId: string; }; - createSystemWebhook: { - systemWebhookId: string; - webhook: any; - }; - updateSystemWebhook: { - systemWebhookId: string; - before: any; - after: any; - }; - deleteSystemWebhook: { - systemWebhookId: string; - webhook: any; - }; - createAbuseReportNotificationRecipient: { - recipientId: string; - recipient: any; - }; - updateAbuseReportNotificationRecipient: { - recipientId: string; - before: any; - after: any; - }; - deleteAbuseReportNotificationRecipient: { - recipientId: string; - recipient: any; - }; }; diff --git a/packages/misskey-js/src/entities.ts b/packages/misskey-js/src/entities.ts index 7a84cb6a1a63..35503d6d6fff 100644 --- a/packages/misskey-js/src/entities.ts +++ b/packages/misskey-js/src/entities.ts @@ -132,23 +132,8 @@ export type ModerationLog = { type: 'unsetUserAvatar'; info: ModerationLogPayloads['unsetUserAvatar']; } | { - type: 'createSystemWebhook'; - info: ModerationLogPayloads['createSystemWebhook']; -} | { - type: 'updateSystemWebhook'; - info: ModerationLogPayloads['updateSystemWebhook']; -} | { - type: 'deleteSystemWebhook'; - info: ModerationLogPayloads['deleteSystemWebhook']; -} | { - type: 'createAbuseReportNotificationRecipient'; - info: ModerationLogPayloads['createAbuseReportNotificationRecipient']; -} | { - type: 'updateAbuseReportNotificationRecipient'; - info: ModerationLogPayloads['updateAbuseReportNotificationRecipient']; -} | { - type: 'deleteAbuseReportNotificationRecipient'; - info: ModerationLogPayloads['deleteAbuseReportNotificationRecipient']; + type: 'unsetUserBanner'; + info: ModerationLogPayloads['unsetUserBanner']; }); export type ServerStats = {