Merge branch 'develop' into pr/13929
This commit is contained in:
		
						commit
						dec4a40bfd
					
				|  | @ -6,9 +6,10 @@ | |||
| ### Client | ||||
| - Feat: ノート単体・ユーザーのノート・クリップのノートの埋め込み機能 | ||||
|   - 埋め込みコードやウェブサイトへの実装方法の詳細はMisskey Hubに掲載予定です | ||||
| - サイズ制限を超過するファイルをアップロードしようとした際にエラーを出すように | ||||
| 
 | ||||
| ### Server | ||||
| - | ||||
| - ファイルがサイズの制限を超えてアップロードされた際にエラーを返さなかった問題を修正 | ||||
| 
 | ||||
| 
 | ||||
| ## 2024.8.0 | ||||
|  |  | |||
|  | @ -5080,6 +5080,10 @@ export interface Locale extends ILocale { | |||
|      * このユーザーのノート一覧 | ||||
|      */ | ||||
|     "noteOfThisUser": string; | ||||
|     /** | ||||
|      * これ以上このクリップにノートを追加できません。 | ||||
|      */ | ||||
|     "clipNoteLimitExceeded": string; | ||||
|     "_delivery": { | ||||
|         /** | ||||
|          * 配信状態 | ||||
|  |  | |||
|  | @ -1266,6 +1266,7 @@ createdAntennas: "作成したアンテナ" | |||
| fromX: "{x}から" | ||||
| copyEmbedCode: "埋め込みコードをコピー" | ||||
| noteOfThisUser: "このユーザーのノート一覧" | ||||
| clipNoteLimitExceeded: "これ以上このクリップにノートを追加できません。" | ||||
| 
 | ||||
| _delivery: | ||||
|   status: "配信状態" | ||||
|  |  | |||
|  | @ -133,7 +133,7 @@ export type Config = { | |||
| 	proxySmtp: string | undefined; | ||||
| 	proxyBypassHosts: string[] | undefined; | ||||
| 	allowedPrivateNetworks: string[] | undefined; | ||||
| 	maxFileSize: number | undefined; | ||||
| 	maxFileSize: number; | ||||
| 	clusterLimit: number | undefined; | ||||
| 	id: string; | ||||
| 	outgoingAddress: string | undefined; | ||||
|  | @ -258,7 +258,7 @@ export function loadConfig(): Config { | |||
| 		proxySmtp: config.proxySmtp, | ||||
| 		proxyBypassHosts: config.proxyBypassHosts, | ||||
| 		allowedPrivateNetworks: config.allowedPrivateNetworks, | ||||
| 		maxFileSize: config.maxFileSize, | ||||
| 		maxFileSize: config.maxFileSize ?? 262144000, | ||||
| 		clusterLimit: config.clusterLimit, | ||||
| 		outgoingAddress: config.outgoingAddress, | ||||
| 		outgoingAddressFamily: config.outgoingAddressFamily, | ||||
|  |  | |||
|  | @ -42,7 +42,7 @@ export class DownloadService { | |||
| 
 | ||||
| 		const timeout = 30 * 1000; | ||||
| 		const operationTimeout = 60 * 1000; | ||||
| 		const maxSize = this.config.maxFileSize ?? 262144000; | ||||
| 		const maxSize = this.config.maxFileSize; | ||||
| 
 | ||||
| 		const urlObj = new URL(url); | ||||
| 		let filename = urlObj.pathname.split('/').pop() ?? 'untitled'; | ||||
|  |  | |||
|  | @ -129,6 +129,7 @@ export class MetaEntityService { | |||
| 			mediaProxy: this.config.mediaProxy, | ||||
| 			enableUrlPreview: instance.urlPreviewEnabled, | ||||
| 			noteSearchableScope: (this.config.meilisearch == null || this.config.meilisearch.scope !== 'local') ? 'global' : 'local', | ||||
| 			maxFileSize: this.config.maxFileSize, | ||||
| 		}; | ||||
| 
 | ||||
| 		return packed; | ||||
|  |  | |||
|  | @ -253,6 +253,10 @@ export const packedMetaLiteSchema = { | |||
| 			optional: false, nullable: false, | ||||
| 			default: 'local', | ||||
| 		}, | ||||
| 		maxFileSize: { | ||||
| 			type: 'number', | ||||
| 			optional: false, nullable: false, | ||||
| 		}, | ||||
| 	}, | ||||
| } as const; | ||||
| 
 | ||||
|  |  | |||
|  | @ -199,9 +199,18 @@ export class ApiCallService implements OnApplicationShutdown { | |||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		const [path] = await createTemp(); | ||||
| 		const [path, cleanup] = await createTemp(); | ||||
| 		await stream.pipeline(multipartData.file, fs.createWriteStream(path)); | ||||
| 
 | ||||
| 		// ファイルサイズが制限を超えていた場合
 | ||||
| 		// なお truncated はストリームを読み切ってからでないと機能しないため、stream.pipeline より後にある必要がある
 | ||||
| 		if (multipartData.file.truncated) { | ||||
| 			cleanup(); | ||||
| 			reply.code(413); | ||||
| 			reply.send(); | ||||
| 			return; | ||||
| 		} | ||||
| 
 | ||||
| 		const fields = {} as Record<string, unknown>; | ||||
| 		for (const [k, v] of Object.entries(multipartData.fields)) { | ||||
| 			fields[k] = typeof v === 'object' && 'value' in v ? v.value : undefined; | ||||
|  |  | |||
|  | @ -49,7 +49,7 @@ export class ApiServerService { | |||
| 
 | ||||
| 		fastify.register(multipart, { | ||||
| 			limits: { | ||||
| 				fileSize: this.config.maxFileSize ?? 262144000, | ||||
| 				fileSize: this.config.maxFileSize, | ||||
| 				files: 1, | ||||
| 			}, | ||||
| 		}); | ||||
|  |  | |||
|  | @ -155,7 +155,7 @@ | |||
| 
 | ||||
| 		if (!errorsElement) { | ||||
| 			document.body.innerHTML = ` | ||||
| 			<svg class="icon-warning" xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-alert-triangle" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"> | ||||
| 			<svg class="icon-warning" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round"> | ||||
| 				<path stroke="none" d="M0 0h24v24H0z" fill="none"></path> | ||||
| 				<path d="M12 9v2m0 4v.01"></path> | ||||
| 				<path d="M5 19h14a2 2 0 0 0 1.84 -2.75l-7.1 -12.25a2 2 0 0 0 -3.5 0l-7.1 12.25a2 2 0 0 0 1.75 2.75"></path> | ||||
|  | @ -167,7 +167,7 @@ | |||
| 			<p><b>The following actions may solve the problem. / 以下を行うと解決する可能性があります。</b></p> | ||||
| 			<p>Update your os and browser / ブラウザおよびOSを最新バージョンに更新する</p> | ||||
| 			<p>Disable an adblocker / アドブロッカーを無効にする</p> | ||||
| 	 		<p>Clear the browser cache / ブラウザのキャッシュをクリアする</p> | ||||
| 			<p>Clear the browser cache / ブラウザのキャッシュをクリアする</p> | ||||
| 			<p>(Tor Browser) Set dom.webaudio.enabled to true / dom.webaudio.enabledをtrueに設定する</p> | ||||
| 			<details style="color: #86b300;"> | ||||
| 				<summary>Other options / その他のオプション</summary> | ||||
|  |  | |||
|  | @ -36,8 +36,6 @@ html | |||
| 		link(rel='prefetch' href=serverErrorImageUrl) | ||||
| 		link(rel='prefetch' href=infoImageUrl) | ||||
| 		link(rel='prefetch' href=notFoundImageUrl) | ||||
| 		//- https://github.com/misskey-dev/misskey/issues/9842 | ||||
| 		link(rel='stylesheet' href='/assets/tabler-icons/tabler-icons.min.css?v3.3.0') | ||||
| 		link(rel='modulepreload' href=`/vite/${entry.file}`) | ||||
| 
 | ||||
| 		if !config.frontendManifestExists | ||||
|  |  | |||
|  | @ -6,6 +6,8 @@ | |||
| // https://vitejs.dev/config/build-options.html#build-modulepreload
 | ||||
| import 'vite/modulepreload-polyfill'; | ||||
| 
 | ||||
| import '@tabler/icons-webfont/dist/tabler-icons.scss'; | ||||
| 
 | ||||
| import '@/style.scss'; | ||||
| import { mainBoot } from '@/boot/main-boot.js'; | ||||
| import { subBoot } from '@/boot/sub-boot.js'; | ||||
|  |  | |||
|  | @ -3,11 +3,6 @@ | |||
|  * SPDX-License-Identifier: AGPL-3.0-only | ||||
|  */ | ||||
| 
 | ||||
| // devモードで起動される際(index.htmlを使うとき)はrouterが暴発してしまってうまく読み込めない。
 | ||||
| // よって、devモードとして起動されるときはビルド時に組み込む形としておく。
 | ||||
| // (pnpm start時はpugファイルの中で静的リソースとして読み込むようになっており、この問題は起こっていない)
 | ||||
| import '@tabler/icons-webfont/dist/tabler-icons.scss'; | ||||
| 
 | ||||
| await main(); | ||||
| 
 | ||||
| import('@/_boot_.js'); | ||||
|  |  | |||
|  | @ -245,7 +245,7 @@ const submitText = computed((): string => { | |||
| }); | ||||
| 
 | ||||
| const textLength = computed((): number => { | ||||
| 	return (text.value + imeText.value).trim().length; | ||||
| 	return (text.value + imeText.value).length; | ||||
| }); | ||||
| 
 | ||||
| const maxTextLength = computed((): number => { | ||||
|  |  | |||
|  | @ -67,6 +67,11 @@ export async function getNoteClipMenu(props: { | |||
| 							}); | ||||
| 							if (props.currentClip?.id === clip.id) props.isDeleted.value = true; | ||||
| 						} | ||||
| 					} else if (err.id === 'f0dba960-ff73-4615-8df4-d6ac5d9dc118') { | ||||
| 						os.alert({ | ||||
| 							type: 'error', | ||||
| 							text: i18n.ts.clipNoteLimitExceeded, | ||||
| 						}); | ||||
| 					} else { | ||||
| 						os.alert({ | ||||
| 							type: 'error', | ||||
|  |  | |||
|  | @ -13,6 +13,7 @@ import { apiUrl } from '@/config.js'; | |||
| import { $i } from '@/account.js'; | ||||
| import { alert } from '@/os.js'; | ||||
| import { i18n } from '@/i18n.js'; | ||||
| import { instance } from '@/instance.js'; | ||||
| 
 | ||||
| type Uploading = { | ||||
| 	id: string; | ||||
|  | @ -39,6 +40,15 @@ export function uploadFile( | |||
| 
 | ||||
| 	if (folder && typeof folder === 'object') folder = folder.id; | ||||
| 
 | ||||
| 	if (file.size > instance.maxFileSize) { | ||||
| 		alert({ | ||||
| 			type: 'error', | ||||
| 			title: i18n.ts.failedToUpload, | ||||
| 			text: i18n.ts.cannotUploadBecauseExceedsFileSizeLimit, | ||||
| 		}); | ||||
| 		return Promise.reject(); | ||||
| 	} | ||||
| 
 | ||||
| 	return new Promise((resolve, reject) => { | ||||
| 		const id = uuid(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -4947,6 +4947,7 @@ export type components = { | |||
|        * @enum {string} | ||||
|        */ | ||||
|       noteSearchableScope: 'local' | 'global'; | ||||
|       maxFileSize: number; | ||||
|     }; | ||||
|     MetaDetailedOnly: { | ||||
|       features?: { | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue