From 9481b5a6e8dc55c30b1521b97405973052c15117 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Sun, 27 Apr 2025 09:35:44 +0900 Subject: [PATCH] =?UTF-8?q?feat:=20=E3=82=A2=E3=83=83=E3=83=97=E3=83=AD?= =?UTF-8?q?=E3=83=BC=E3=83=89=E5=8F=AF=E8=83=BD=E3=81=AA=E6=9C=80=E5=A4=A7?= =?UTF-8?q?=E3=83=95=E3=82=A1=E3=82=A4=E3=83=AB=E3=82=B5=E3=82=A4=E3=82=BA?= =?UTF-8?q?=E3=82=92=E3=83=AD=E3=83=BC=E3=83=AB=E3=81=94=E3=81=A8=E3=81=AB?= =?UTF-8?q?=E8=A8=AD=E5=AE=9A=E5=8F=AF=E8=83=BD=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + locales/index.d.ts | 4 ++++ locales/ja-JP.yml | 1 + packages/backend/src/core/DriveService.ts | 7 +++++++ packages/backend/src/core/RoleService.ts | 3 +++ .../backend/src/models/json-schema/role.ts | 4 ++++ .../api/endpoints/drive/files/create.ts | 9 ++++++++- packages/frontend-shared/js/const.ts | 1 + .../frontend/src/pages/admin/roles.editor.vue | 20 +++++++++++++++++++ packages/frontend/src/pages/admin/roles.vue | 8 ++++++++ packages/frontend/src/utility/upload.ts | 2 +- packages/misskey-js/src/autogen/types.ts | 1 + 12 files changed, 59 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7c3100b486..69edfaca91 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ### General - Feat: bull-boardに代わるジョブキューの管理ツールが実装されました +- Feat: アップロード可能な最大ファイルサイズをロールごとに設定可能に - Enhance: チャットの新規メッセージをプッシュ通知するように ### Client diff --git a/locales/index.d.ts b/locales/index.d.ts index cb632dfb25..97505a1605 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -7464,6 +7464,10 @@ export interface Locale extends ILocale { * ドライブ容量 */ "driveCapacity": string; + /** + * アップロード可能な最大ファイルサイズ + */ + "maxFileSize": string; /** * ファイルにNSFWを常に付与 */ diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index fb2590d8fd..737e69a376 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1934,6 +1934,7 @@ _role: canManageCustomEmojis: "カスタム絵文字の管理" canManageAvatarDecorations: "アバターデコレーションの管理" driveCapacity: "ドライブ容量" + maxFileSize: "アップロード可能な最大ファイルサイズ" alwaysMarkNsfw: "ファイルにNSFWを常に付与" canUpdateBioMedia: "アイコンとバナーの更新を許可" pinMax: "ノートのピン留めの最大数" diff --git a/packages/backend/src/core/DriveService.ts b/packages/backend/src/core/DriveService.ts index 1550fe3d3c..5f1e373429 100644 --- a/packages/backend/src/core/DriveService.ts +++ b/packages/backend/src/core/DriveService.ts @@ -522,9 +522,16 @@ export class DriveService { const policies = await this.roleService.getUserPolicies(user.id); const driveCapacity = 1024 * 1024 * policies.driveCapacityMb; + const maxFileSize = 1024 * 1024 * policies.maxFileSizeMb; this.registerLogger.debug('drive capacity override applied'); this.registerLogger.debug(`overrideCap: ${driveCapacity}bytes, usage: ${usage}bytes, u+s: ${usage + info.size}bytes`); + if (maxFileSize < info.size) { + if (isLocalUser) { + throw new IdentifiableError('f9e4e5f3-4df4-40b5-b400-f236945f7073', 'Max file size exceeded.'); + } + } + // If usage limit exceeded if (driveCapacity < usage + info.size) { if (isLocalUser) { diff --git a/packages/backend/src/core/RoleService.ts b/packages/backend/src/core/RoleService.ts index 601959cc96..fc97780ba3 100644 --- a/packages/backend/src/core/RoleService.ts +++ b/packages/backend/src/core/RoleService.ts @@ -46,6 +46,7 @@ export type RolePolicies = { canUseTranslator: boolean; canHideAds: boolean; driveCapacityMb: number; + maxFileSizeMb: number; alwaysMarkNsfw: boolean; canUpdateBioMedia: boolean; pinLimit: number; @@ -81,6 +82,7 @@ export const DEFAULT_POLICIES: RolePolicies = { canUseTranslator: true, canHideAds: false, driveCapacityMb: 100, + maxFileSizeMb: 10, alwaysMarkNsfw: false, canUpdateBioMedia: true, pinLimit: 5, @@ -391,6 +393,7 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit { canUseTranslator: calc('canUseTranslator', vs => vs.some(v => v === true)), canHideAds: calc('canHideAds', vs => vs.some(v => v === true)), driveCapacityMb: calc('driveCapacityMb', vs => Math.max(...vs)), + maxFileSizeMb: calc('maxFileSizeMb', vs => Math.max(...vs)), alwaysMarkNsfw: calc('alwaysMarkNsfw', vs => vs.some(v => v === true)), canUpdateBioMedia: calc('canUpdateBioMedia', vs => vs.some(v => v === true)), pinLimit: calc('pinLimit', vs => Math.max(...vs)), diff --git a/packages/backend/src/models/json-schema/role.ts b/packages/backend/src/models/json-schema/role.ts index 1cfcb830e0..e67704e8d3 100644 --- a/packages/backend/src/models/json-schema/role.ts +++ b/packages/backend/src/models/json-schema/role.ts @@ -224,6 +224,10 @@ export const packedRolePoliciesSchema = { type: 'integer', optional: false, nullable: false, }, + maxFileSizeMb: { + type: 'integer', + optional: false, nullable: false, + }, alwaysMarkNsfw: { type: 'boolean', optional: false, nullable: false, diff --git a/packages/backend/src/server/api/endpoints/drive/files/create.ts b/packages/backend/src/server/api/endpoints/drive/files/create.ts index 74eb4dded7..17face8f82 100644 --- a/packages/backend/src/server/api/endpoints/drive/files/create.ts +++ b/packages/backend/src/server/api/endpoints/drive/files/create.ts @@ -10,9 +10,9 @@ import { IdentifiableError } from '@/misc/identifiable-error.js'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js'; import { DriveService } from '@/core/DriveService.js'; -import { ApiError } from '../../../error.js'; import { MiMeta } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; +import { ApiError } from '../../../error.js'; export const meta = { tags: ['drive'], @@ -56,6 +56,12 @@ export const meta = { code: 'NO_FREE_SPACE', id: 'd08dbc37-a6a9-463a-8c47-96c32ab5f064', }, + + maxFileSizeExceeded: { + message: 'Cannot upload the file because it exceeds the maximum file size.', + code: 'MAX_FILE_SIZE_EXCEEDED', + id: 'b9d8c348-33f0-4673-b9a9-5d4da058977a', + }, }, } as const; @@ -115,6 +121,7 @@ export default class extends Endpoint { // eslint- if (err instanceof IdentifiableError) { if (err.id === '282f77bf-5816-4f72-9264-aa14d8261a21') throw new ApiError(meta.errors.inappropriate); if (err.id === 'c6244ed2-a39a-4e1c-bf93-f0fbd7764fa6') throw new ApiError(meta.errors.noFreeSpace); + if (err.id === 'f9e4e5f3-4df4-40b5-b400-f236945f7073') throw new ApiError(meta.errors.maxFileSizeExceeded); } throw new ApiError(); } finally { diff --git a/packages/frontend-shared/js/const.ts b/packages/frontend-shared/js/const.ts index de65c3db97..84b5afe78f 100644 --- a/packages/frontend-shared/js/const.ts +++ b/packages/frontend-shared/js/const.ts @@ -91,6 +91,7 @@ export const ROLE_POLICIES = [ 'canUseTranslator', 'canHideAds', 'driveCapacityMb', + 'maxFileSizeMb', 'alwaysMarkNsfw', 'canUpdateBioMedia', 'pinLimit', diff --git a/packages/frontend/src/pages/admin/roles.editor.vue b/packages/frontend/src/pages/admin/roles.editor.vue index 930a63f5a9..2473d4e90d 100644 --- a/packages/frontend/src/pages/admin/roles.editor.vue +++ b/packages/frontend/src/pages/admin/roles.editor.vue @@ -386,6 +386,26 @@ SPDX-License-Identifier: AGPL-3.0-only + + + +
+ + + + + + + + + +
+
+