Merge branch 'develop' into fix-14452

This commit is contained in:
かっこかり 2024-08-24 19:11:41 +09:00 committed by GitHub
commit 9db8a64665
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 45 additions and 9 deletions

View File

@ -4,10 +4,11 @@
- -
### Client ### Client
- サイズ制限を超過するファイルをアップロードしようとした際にエラーを出すように
- Fix: アカウントがbotになっているときに二段階認証設定ダイアログの上にbotアカウントの注意書きが表示される問題を修正 - Fix: アカウントがbotになっているときに二段階認証設定ダイアログの上にbotアカウントの注意書きが表示される問題を修正
### Server ### Server
- - ファイルがサイズの制限を超えてアップロードされた際にエラーを返さなかった問題を修正
## 2024.8.0 ## 2024.8.0

4
locales/index.d.ts vendored
View File

@ -5068,6 +5068,10 @@ export interface Locale extends ILocale {
* *
*/ */
"createdAntennas": string; "createdAntennas": string;
/**
*
*/
"clipNoteLimitExceeded": string;
"_delivery": { "_delivery": {
/** /**
* *

View File

@ -1263,6 +1263,7 @@ confirmWhenRevealingSensitiveMedia: "センシティブなメディアを表示
sensitiveMediaRevealConfirm: "センシティブなメディアです。表示しますか?" sensitiveMediaRevealConfirm: "センシティブなメディアです。表示しますか?"
createdLists: "作成したリスト" createdLists: "作成したリスト"
createdAntennas: "作成したアンテナ" createdAntennas: "作成したアンテナ"
clipNoteLimitExceeded: "これ以上このクリップにノートを追加できません。"
_delivery: _delivery:
status: "配信状態" status: "配信状態"

View File

@ -133,7 +133,7 @@ export type Config = {
proxySmtp: string | undefined; proxySmtp: string | undefined;
proxyBypassHosts: string[] | undefined; proxyBypassHosts: string[] | undefined;
allowedPrivateNetworks: string[] | undefined; allowedPrivateNetworks: string[] | undefined;
maxFileSize: number | undefined; maxFileSize: number;
clusterLimit: number | undefined; clusterLimit: number | undefined;
id: string; id: string;
outgoingAddress: string | undefined; outgoingAddress: string | undefined;
@ -250,7 +250,7 @@ export function loadConfig(): Config {
proxySmtp: config.proxySmtp, proxySmtp: config.proxySmtp,
proxyBypassHosts: config.proxyBypassHosts, proxyBypassHosts: config.proxyBypassHosts,
allowedPrivateNetworks: config.allowedPrivateNetworks, allowedPrivateNetworks: config.allowedPrivateNetworks,
maxFileSize: config.maxFileSize, maxFileSize: config.maxFileSize ?? 262144000,
clusterLimit: config.clusterLimit, clusterLimit: config.clusterLimit,
outgoingAddress: config.outgoingAddress, outgoingAddress: config.outgoingAddress,
outgoingAddressFamily: config.outgoingAddressFamily, outgoingAddressFamily: config.outgoingAddressFamily,

View File

@ -42,7 +42,7 @@ export class DownloadService {
const timeout = 30 * 1000; const timeout = 30 * 1000;
const operationTimeout = 60 * 1000; const operationTimeout = 60 * 1000;
const maxSize = this.config.maxFileSize ?? 262144000; const maxSize = this.config.maxFileSize;
const urlObj = new URL(url); const urlObj = new URL(url);
let filename = urlObj.pathname.split('/').pop() ?? 'untitled'; let filename = urlObj.pathname.split('/').pop() ?? 'untitled';

View File

@ -129,6 +129,7 @@ export class MetaEntityService {
mediaProxy: this.config.mediaProxy, mediaProxy: this.config.mediaProxy,
enableUrlPreview: instance.urlPreviewEnabled, enableUrlPreview: instance.urlPreviewEnabled,
noteSearchableScope: (this.config.meilisearch == null || this.config.meilisearch.scope !== 'local') ? 'global' : 'local', noteSearchableScope: (this.config.meilisearch == null || this.config.meilisearch.scope !== 'local') ? 'global' : 'local',
maxFileSize: this.config.maxFileSize,
}; };
return packed; return packed;

View File

@ -253,6 +253,10 @@ export const packedMetaLiteSchema = {
optional: false, nullable: false, optional: false, nullable: false,
default: 'local', default: 'local',
}, },
maxFileSize: {
type: 'number',
optional: false, nullable: false,
},
}, },
} as const; } as const;

View File

@ -199,9 +199,18 @@ export class ApiCallService implements OnApplicationShutdown {
return; return;
} }
const [path] = await createTemp(); const [path, cleanup] = await createTemp();
await stream.pipeline(multipartData.file, fs.createWriteStream(path)); 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>; const fields = {} as Record<string, unknown>;
for (const [k, v] of Object.entries(multipartData.fields)) { for (const [k, v] of Object.entries(multipartData.fields)) {
fields[k] = typeof v === 'object' && 'value' in v ? v.value : undefined; fields[k] = typeof v === 'object' && 'value' in v ? v.value : undefined;

View File

@ -49,7 +49,7 @@ export class ApiServerService {
fastify.register(multipart, { fastify.register(multipart, {
limits: { limits: {
fileSize: this.config.maxFileSize ?? 262144000, fileSize: this.config.maxFileSize,
files: 1, files: 1,
}, },
}); });

View File

@ -176,10 +176,10 @@
<span class="button-label-big">Reload / リロード</span> <span class="button-label-big">Reload / リロード</span>
</button> </button>
<p><b>The following actions may solve the problem. / 以下を行うと解決する可能性があります</b></p> <p><b>The following actions may solve the problem. / 以下を行うと解決する可能性があります</b></p>
<p>Clear the browser cache / ブラウザのキャッシュをクリアする</p>
<p>Update your os and browser / ブラウザおよびOSを最新バージョンに更新する</p> <p>Update your os and browser / ブラウザおよびOSを最新バージョンに更新する</p>
<p>Disable an adblocker / アドブロッカーを無効にする</p> <p>Disable an adblocker / アドブロッカーを無効にする</p>
<p>&#40;Tor Browser&#41; Set dom.webaudio.enabled to true / dom.webaudio.enabledをtrueに設定する</p> <p>Clear the browser cache / ブラウザのキャッシュをクリアする</p>
<p>&#40;Tor Browser&#41; Set dom.webaudio.enabled to true / dom.webaudio.enabledをtrueに設定する</p>
<details style="color: #86b300;"> <details style="color: #86b300;">
<summary>Other options / その他のオプション</summary> <summary>Other options / その他のオプション</summary>
<a href="/flush"> <a href="/flush">
@ -212,7 +212,7 @@
<summary> <summary>
<code>ERROR CODE: ${code}</code> <code>ERROR CODE: ${code}</code>
</summary> </summary>
<code>${JSON.stringify(details)}</code>`; <code>${details.toString()} ${JSON.stringify(details)}</code>`;
errorsElement.appendChild(detailsElement); errorsElement.appendChild(detailsElement);
addStyle(` addStyle(`
* { * {

View File

@ -66,6 +66,11 @@ export async function getNoteClipMenu(props: {
}); });
if (props.currentClip?.id === clip.id) props.isDeleted.value = true; 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 { } else {
os.alert({ os.alert({
type: 'error', type: 'error',

View File

@ -13,6 +13,7 @@ import { apiUrl } from '@/config.js';
import { $i } from '@/account.js'; import { $i } from '@/account.js';
import { alert } from '@/os.js'; import { alert } from '@/os.js';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
import { instance } from '@/instance.js';
type Uploading = { type Uploading = {
id: string; id: string;
@ -39,6 +40,15 @@ export function uploadFile(
if (folder && typeof folder === 'object') folder = folder.id; 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) => { return new Promise((resolve, reject) => {
const id = uuid(); const id = uuid();

View File

@ -4947,6 +4947,7 @@ export type components = {
* @enum {string} * @enum {string}
*/ */
noteSearchableScope: 'local' | 'global'; noteSearchableScope: 'local' | 'global';
maxFileSize: number;
}; };
MetaDetailedOnly: { MetaDetailedOnly: {
features?: { features?: {