diff --git a/CHANGELOG.md b/CHANGELOG.md index d679a4c01f..137fb51f66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -80,6 +80,7 @@ You should also include the user name that made the change. - ユーザーリストおよびユーザーリスト内のユーザーの作成可能数を設定可能に @syuilo - ハードワードミュートの最大文字数を設定可能に @syuilo - Webhookの作成可能数を設定可能に @syuilo +- ノートをピン留めできる数を設定可能に @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 15a33932a5..67464e943d 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -962,6 +962,7 @@ _role: canInvite: "インスタンス招待コードの発行" canManageCustomEmojis: "カスタム絵文字の管理" driveCapacity: "ドライブ容量" + pinMax: "ノートのピン留めの最大数" antennaMax: "アンテナの作成可能数" wordMuteMax: "ワードミュートの最大文字数" webhookMax: "Webhookの作成可能数" diff --git a/packages/backend/src/core/NotePiningService.ts b/packages/backend/src/core/NotePiningService.ts index f8997574a7..bc038e17a7 100644 --- a/packages/backend/src/core/NotePiningService.ts +++ b/packages/backend/src/core/NotePiningService.ts @@ -12,6 +12,7 @@ import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { ApDeliverManagerService } from '@/core/activitypub/ApDeliverManagerService.js'; import { ApRendererService } from '@/core/activitypub/ApRendererService.js'; import { bindThis } from '@/decorators.js'; +import { RoleService } from '@/core/RoleService.js'; @Injectable() export class NotePiningService { @@ -30,6 +31,7 @@ export class NotePiningService { private userEntityService: UserEntityService, private idService: IdService, + private roleService: RoleService, private relayService: RelayService, private apDeliverManagerService: ApDeliverManagerService, private apRendererService: ApRendererService, @@ -55,7 +57,7 @@ export class NotePiningService { const pinings = await this.userNotePiningsRepository.findBy({ userId: user.id }); - if (pinings.length >= 5) { + if (pinings.length >= (await this.roleService.getUserRoleOptions(user.id)).pinLimit) { throw new IdentifiableError('15a018eb-58e5-4da1-93be-330fcc5e4e1a', 'You can not pin notes any more.'); } diff --git a/packages/backend/src/core/RoleService.ts b/packages/backend/src/core/RoleService.ts index 0ddcb44ca1..984aef727f 100644 --- a/packages/backend/src/core/RoleService.ts +++ b/packages/backend/src/core/RoleService.ts @@ -20,6 +20,7 @@ export type RoleOptions = { canInvite: boolean; canManageCustomEmojis: boolean; driveCapacityMb: number; + pinLimit: number; antennaLimit: number; wordMuteLimit: number; webhookLimit: number; @@ -36,6 +37,7 @@ export const DEFAULT_ROLE: RoleOptions = { canInvite: false, canManageCustomEmojis: false, driveCapacityMb: 100, + pinLimit: 5, antennaLimit: 5, wordMuteLimit: 200, webhookLimit: 3, @@ -211,6 +213,7 @@ export class RoleService implements OnApplicationShutdown { canInvite: getOptionValues('canInvite').some(x => x === true), canManageCustomEmojis: getOptionValues('canManageCustomEmojis').some(x => x === true), driveCapacityMb: Math.max(...getOptionValues('driveCapacityMb')), + pinLimit: Math.max(...getOptionValues('pinLimit')), antennaLimit: Math.max(...getOptionValues('antennaLimit')), wordMuteLimit: Math.max(...getOptionValues('wordMuteLimit')), webhookLimit: Math.max(...getOptionValues('webhookLimit')), diff --git a/packages/frontend/src/pages/admin/roles.editor.vue b/packages/frontend/src/pages/admin/roles.editor.vue index 001409cac8..fc5e2b9d12 100644 --- a/packages/frontend/src/pages/admin/roles.editor.vue +++ b/packages/frontend/src/pages/admin/roles.editor.vue @@ -116,6 +116,18 @@ + + {{ i18n.ts._role._options.pinMax }} + {{ options_pinLimit_useDefault ? i18n.ts._role.useBaseValue : (options_pinLimit_value) }} + + + {{ i18n.ts._role.useBaseValue }} + + + + + + {{ i18n.ts._role._options.antennaMax }} {{ options_antennaLimit_useDefault ? i18n.ts._role.useBaseValue : (options_antennaLimit_value) }} @@ -265,6 +277,8 @@ let options_canManageCustomEmojis_useDefault = $ref(role?.options?.canManageCust let options_canManageCustomEmojis_value = $ref(role?.options?.canManageCustomEmojis?.value ?? false); let options_driveCapacityMb_useDefault = $ref(role?.options?.driveCapacityMb?.useDefault ?? true); let options_driveCapacityMb_value = $ref(role?.options?.driveCapacityMb?.value ?? 0); +let options_pinLimit_useDefault = $ref(role?.options?.pinLimit?.useDefault ?? true); +let options_pinLimit_value = $ref(role?.options?.pinLimit?.value ?? 0); let options_antennaLimit_useDefault = $ref(role?.options?.antennaLimit?.useDefault ?? true); let options_antennaLimit_value = $ref(role?.options?.antennaLimit?.value ?? 0); let options_wordMuteLimit_useDefault = $ref(role?.options?.wordMuteLimit?.useDefault ?? true); @@ -294,6 +308,7 @@ function getOptions() { canInvite: { useDefault: options_canInvite_useDefault, value: options_canInvite_value }, canManageCustomEmojis: { useDefault: options_canManageCustomEmojis_useDefault, value: options_canManageCustomEmojis_value }, driveCapacityMb: { useDefault: options_driveCapacityMb_useDefault, value: options_driveCapacityMb_value }, + pinLimit: { useDefault: options_pinLimit_useDefault, value: options_pinLimit_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 7a2f269310..68be6bbdd6 100644 --- a/packages/frontend/src/pages/admin/roles.vue +++ b/packages/frontend/src/pages/admin/roles.vue @@ -56,6 +56,13 @@ + + {{ i18n.ts._role._options.pinMax }} + {{ options_pinLimit }} + + + + {{ i18n.ts._role._options.antennaMax }} {{ options_antennaLimit }} @@ -144,6 +151,7 @@ let options_canPublicNote = $ref(instance.baseRole.canPublicNote); let options_canInvite = $ref(instance.baseRole.canInvite); let options_canManageCustomEmojis = $ref(instance.baseRole.canManageCustomEmojis); let options_driveCapacityMb = $ref(instance.baseRole.driveCapacityMb); +let options_pinLimit = $ref(instance.baseRole.pinLimit); let options_antennaLimit = $ref(instance.baseRole.antennaLimit); let options_wordMuteLimit = $ref(instance.baseRole.wordMuteLimit); let options_webhookLimit = $ref(instance.baseRole.webhookLimit); @@ -161,6 +169,7 @@ async function updateBaseRole() { canInvite: options_canInvite, canManageCustomEmojis: options_canManageCustomEmojis, driveCapacityMb: options_driveCapacityMb, + pinLimit: options_pinLimit, antennaLimit: options_antennaLimit, wordMuteLimit: options_wordMuteLimit, webhookLimit: options_webhookLimit,