diff --git a/CHANGELOG.md b/CHANGELOG.md index c25b98d27a..0872e875f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -76,6 +76,7 @@ You should also include the user name that made the change. - 非モデレーターでも、権限を持つロールをアサインされたユーザーはインスタンスの招待コードを発行できるように @syuilo - 非モデレーターでも、権限を持つロールをアサインされたユーザーはカスタム絵文字の追加、編集、削除を行えるように @syuilo - ハードワードミュートの最大文字数を設定可能に @syuilo +- Webhookの作成可能数を設定可能に @syuilo - Server: signToActivityPubGet is set to true by default @syuilo - Server: improve syslog performance @syuilo - Server: Use undici instead of node-fetch and got @tamaina diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 1982681aed..f0291db54c 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -963,6 +963,7 @@ _role: driveCapacity: "ドライブ容量" antennaMax: "アンテナの作成可能数" wordMuteMax: "ワードミュートの最大文字数" + webhookMax: "Webhookの作成可能数" _condition: isLocal: "ローカルユーザー" isRemote: "リモートユーザー" diff --git a/packages/backend/src/core/RoleService.ts b/packages/backend/src/core/RoleService.ts index e7821ebd78..c639786ec6 100644 --- a/packages/backend/src/core/RoleService.ts +++ b/packages/backend/src/core/RoleService.ts @@ -22,6 +22,7 @@ export type RoleOptions = { driveCapacityMb: number; antennaLimit: number; wordMuteLimit: number; + webhookLimit: number; }; export const DEFAULT_ROLE: RoleOptions = { @@ -33,6 +34,7 @@ export const DEFAULT_ROLE: RoleOptions = { driveCapacityMb: 100, antennaLimit: 5, wordMuteLimit: 200, + webhookLimit: 3, }; @Injectable() @@ -203,6 +205,7 @@ export class RoleService implements OnApplicationShutdown { driveCapacityMb: Math.max(...getOptionValues('driveCapacityMb')), antennaLimit: Math.max(...getOptionValues('antennaLimit')), wordMuteLimit: Math.max(...getOptionValues('wordMuteLimit')), + webhookLimit: Math.max(...getOptionValues('webhookLimit')), }; } diff --git a/packages/backend/src/server/api/endpoints/i/webhooks/create.ts b/packages/backend/src/server/api/endpoints/i/webhooks/create.ts index 584c2ba6a4..45cfd8161c 100644 --- a/packages/backend/src/server/api/endpoints/i/webhooks/create.ts +++ b/packages/backend/src/server/api/endpoints/i/webhooks/create.ts @@ -5,6 +5,7 @@ import type { WebhooksRepository } from '@/models/index.js'; import { webhookEventTypes } from '@/models/entities/Webhook.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { DI } from '@/di-symbols.js'; +import { RoleService } from '@/core/RoleService.js'; export const meta = { tags: ['webhooks'], @@ -12,6 +13,14 @@ export const meta = { requireCredential: true, kind: 'write:account', + + errors: { + tooManyWebhooks: { + message: 'You cannot create webhook any more.', + code: 'TOO_MANY_WEBHOOKS', + id: '87a9bb19-111e-4e37-81d3-a3e7426453b0', + }, + }, } as const; export const paramDef = { @@ -38,8 +47,16 @@ export default class extends Endpoint { private idService: IdService, private globalEventService: GlobalEventService, + private roleService: RoleService, ) { super(meta, paramDef, async (ps, me) => { + const currentWebhooksCount = await this.webhooksRepository.countBy({ + userId: me.id, + }); + if (currentWebhooksCount > (await this.roleService.getUserRoleOptions(me.id)).webhookLimit) { + throw new ApiError(meta.errors.tooManyWebhooks); + } + const webhook = await this.webhooksRepository.insert({ id: this.idService.genId(), createdAt: new Date(), diff --git a/packages/frontend/src/pages/admin/roles.editor.vue b/packages/frontend/src/pages/admin/roles.editor.vue index 30bc6c238e..9d26707423 100644 --- a/packages/frontend/src/pages/admin/roles.editor.vue +++ b/packages/frontend/src/pages/admin/roles.editor.vue @@ -140,6 +140,18 @@ + + + + +
+ + + + + +
+
@@ -209,6 +221,8 @@ let options_antennaLimit_useDefault = $ref(role?.options?.antennaLimit?.useDefau let options_antennaLimit_value = $ref(role?.options?.antennaLimit?.value ?? 0); let options_wordMuteLimit_useDefault = $ref(role?.options?.wordMuteLimit?.useDefault ?? true); let options_wordMuteLimit_value = $ref(role?.options?.wordMuteLimit?.value ?? 0); +let options_webhookLimit_useDefault = $ref(role?.options?.webhookLimit?.useDefault ?? true); +let options_webhookLimit_value = $ref(role?.options?.webhookLimit?.value ?? 0); if (_DEV_) { watch($$(condFormula), () => { @@ -226,6 +240,7 @@ function getOptions() { driveCapacityMb: { useDefault: options_driveCapacityMb_useDefault, value: options_driveCapacityMb_value }, antennaLimit: { useDefault: options_antennaLimit_useDefault, value: options_antennaLimit_value }, wordMuteLimit: { useDefault: options_wordMuteLimit_useDefault, value: options_wordMuteLimit_value }, + webhookLimit: { useDefault: options_webhookLimit_useDefault, value: options_webhookLimit_value }, }; } diff --git a/packages/frontend/src/pages/admin/roles.vue b/packages/frontend/src/pages/admin/roles.vue index 001800ea26..cde5142a63 100644 --- a/packages/frontend/src/pages/admin/roles.vue +++ b/packages/frontend/src/pages/admin/roles.vue @@ -71,6 +71,13 @@ + + + + + + + {{ i18n.ts.save }} @@ -111,6 +118,7 @@ let options_canManageCustomEmojis = $ref(instance.baseRole.canManageCustomEmojis let options_driveCapacityMb = $ref(instance.baseRole.driveCapacityMb); let options_antennaLimit = $ref(instance.baseRole.antennaLimit); let options_wordMuteLimit = $ref(instance.baseRole.wordMuteLimit); +let options_webhookLimit = $ref(instance.baseRole.webhookLimit); async function updateBaseRole() { await os.apiWithDialog('admin/roles/update-default-role-override', { @@ -123,6 +131,7 @@ async function updateBaseRole() { driveCapacityMb: options_driveCapacityMb, antennaLimit: options_antennaLimit, wordMuteLimit: options_wordMuteLimit, + webhookLimit: options_webhookLimit, }, }); }