chore: Separate maximum import size config for document/workspace (#6566)

* chore: Separate maximum import size config for document/workspace

* Update .env.sample
This commit is contained in:
Tom Moor
2024-02-20 20:35:31 -08:00
committed by GitHub
parent 15046d00a5
commit 7c03963be1
11 changed files with 50 additions and 19 deletions

View File

@@ -66,6 +66,14 @@ FILE_STORAGE_LOCAL_ROOT_DIR=/var/lib/outline/data
# Maximum allowed size for the uploaded attachment.
FILE_STORAGE_UPLOAD_MAX_SIZE=262144000
# Override the maximum size of document imports, generally this should be lower
# than the document attachment maximum size.
FILE_STORAGE_IMPORT_MAX_SIZE=
# Override the maximum size of workspace imports, these can be especially large
# and the files are temporary being automatically deleted after a period of time.
FILE_STORAGE_WORKSPACE_IMPORT_MAX_SIZE=
# AUTHENTICATION
# Third party signin credentials, at least ONE OF EITHER Google, Slack,
@@ -142,10 +150,6 @@ ENABLE_UPDATES=true
# available memory by 512 for a rough estimate
WEB_CONCURRENCY=1
# Override the maximum size of document imports, could be required if you have
# especially large Word documents with embedded imagery
MAXIMUM_IMPORT_SIZE=5120000
# You can remove this line if your reverse proxy already logs incoming http
# requests and this ends up being duplicative
DEBUG=http

View File

@@ -38,7 +38,7 @@ function DropToImport({ disabled, onSubmit, children, format }: Props) {
try {
const attachment = await uploadFile(file, {
name: file.name,
preset: AttachmentPreset.Import,
preset: AttachmentPreset.WorkspaceImport,
});
await collections.import(attachment.id, format);
onSubmit();

View File

@@ -596,10 +596,10 @@ export default class DocumentsStore extends Store<Document> {
throw new Error(`The selected file type is not supported (${file.type})`);
}
if (file.size > env.MAXIMUM_IMPORT_SIZE) {
if (file.size > env.FILE_STORAGE_IMPORT_MAX_SIZE) {
throw new Error(
`The selected file was larger than the ${bytesToHumanReadable(
env.MAXIMUM_IMPORT_SIZE
env.FILE_STORAGE_IMPORT_MAX_SIZE
)} maximum size`
);
}

View File

@@ -33,7 +33,7 @@ router.post(
multipart({
maximumFileSize: Math.max(
env.FILE_STORAGE_UPLOAD_MAX_SIZE,
env.MAXIMUM_IMPORT_SIZE
env.FILE_STORAGE_IMPORT_MAX_SIZE
),
}),
async (ctx: APIContext<T.FilesCreateReq>) => {

View File

@@ -582,7 +582,8 @@ export class Environment {
this.toOptionalNumber(process.env.RATE_LIMITER_DURATION_WINDOW) ?? 60;
/**
* @deprecated Set max allowed upload size for file attachments.
* Set max allowed upload size for file attachments.
* @deprecated Use FILE_STORAGE_UPLOAD_MAX_SIZE instead
*/
@IsOptional()
@IsNumber()
@@ -671,17 +672,39 @@ export class Environment {
public FILE_STORAGE_UPLOAD_MAX_SIZE =
this.toOptionalNumber(process.env.FILE_STORAGE_UPLOAD_MAX_SIZE) ??
this.toOptionalNumber(process.env.AWS_S3_UPLOAD_MAX_SIZE) ??
100000000;
1000000;
/**
* Set max allowed upload size for document imports.
*/
@IsNumber()
public FILE_STORAGE_IMPORT_MAX_SIZE =
this.toOptionalNumber(process.env.FILE_STORAGE_IMPORT_MAX_SIZE) ??
this.toOptionalNumber(process.env.MAXIMUM_IMPORT_SIZE) ??
this.toOptionalNumber(process.env.FILE_STORAGE_UPLOAD_MAX_SIZE) ??
1000000;
/**
* Set max allowed upload size for imports at workspace level.
*/
@IsNumber()
public FILE_STORAGE_WORKSPACE_IMPORT_MAX_SIZE =
this.toOptionalNumber(process.env.FILE_STORAGE_WORKSPACE_IMPORT_MAX_SIZE) ??
this.toOptionalNumber(process.env.MAXIMUM_IMPORT_SIZE) ??
this.toOptionalNumber(process.env.FILE_STORAGE_UPLOAD_MAX_SIZE) ??
1000000;
/**
* Because imports can be much larger than regular file attachments and are
* deleted automatically we allow an optional separate limit on the size of
* imports.
*
* @deprecated Use `FILE_STORAGE_IMPORT_MAX_SIZE` or `FILE_STORAGE_WORKSPACE_IMPORT_MAX_SIZE` instead
*/
@IsNumber()
public MAXIMUM_IMPORT_SIZE = Math.max(
this.toOptionalNumber(process.env.MAXIMUM_IMPORT_SIZE) ?? 100000000,
this.FILE_STORAGE_UPLOAD_MAX_SIZE
@Deprecated("Use FILE_STORAGE_IMPORT_MAX_SIZE instead")
public MAXIMUM_IMPORT_SIZE = this.toOptionalNumber(
process.env.MAXIMUM_IMPORT_SIZE
);
/**

View File

@@ -86,6 +86,7 @@ export default class AttachmentHelper {
static presetToExpiry(preset: AttachmentPreset) {
switch (preset) {
case AttachmentPreset.Import:
case AttachmentPreset.WorkspaceImport:
return addHours(new Date(), 24);
default:
return undefined;
@@ -101,7 +102,9 @@ export default class AttachmentHelper {
static presetToMaxUploadSize(preset: AttachmentPreset) {
switch (preset) {
case AttachmentPreset.Import:
return env.MAXIMUM_IMPORT_SIZE;
return env.FILE_STORAGE_IMPORT_MAX_SIZE;
case AttachmentPreset.WorkspaceImport:
return env.FILE_STORAGE_WORKSPACE_IMPORT_MAX_SIZE;
case AttachmentPreset.Avatar:
case AttachmentPreset.DocumentAttachment:
default:

View File

@@ -24,7 +24,7 @@ export default function present(
SENTRY_TUNNEL: env.SENTRY_TUNNEL,
SLACK_CLIENT_ID: env.SLACK_CLIENT_ID,
SLACK_APP_ID: env.SLACK_APP_ID,
MAXIMUM_IMPORT_SIZE: env.MAXIMUM_IMPORT_SIZE,
FILE_STORAGE_IMPORT_MAX_SIZE: env.FILE_STORAGE_IMPORT_MAX_SIZE,
PDF_EXPORT_ENABLED: false,
DEFAULT_LANGUAGE: env.DEFAULT_LANGUAGE,
EMAIL_ENABLED: !!env.SMTP_HOST || env.isDevelopment,

View File

@@ -66,7 +66,7 @@ describe("#attachments.create", () => {
name: "test.zip",
contentType: "application/zip",
size: 10000,
preset: AttachmentPreset.Import,
preset: AttachmentPreset.WorkspaceImport,
token: user.getJwtToken(),
},
});

View File

@@ -1312,7 +1312,7 @@ router.post(
auth(),
rateLimiter(RateLimiterStrategy.TwentyFivePerMinute),
validate(T.DocumentsImportSchema),
multipart({ maximumFileSize: env.MAXIMUM_IMPORT_SIZE }),
multipart({ maximumFileSize: env.FILE_STORAGE_IMPORT_MAX_SIZE }),
transaction(),
async (ctx: APIContext<T.DocumentsImportReq>) => {
const { collectionId, parentDocumentId, publish } = ctx.input.body;

View File

@@ -48,7 +48,7 @@ api.use(
formidable: {
maxFileSize: Math.max(
env.FILE_STORAGE_UPLOAD_MAX_SIZE,
env.MAXIMUM_IMPORT_SIZE
env.FILE_STORAGE_IMPORT_MAX_SIZE
),
maxFieldsSize: 10 * 1024 * 1024,
},

View File

@@ -53,7 +53,7 @@ export type PublicEnv = {
SENTRY_TUNNEL: string | undefined;
SLACK_CLIENT_ID: string | undefined;
SLACK_APP_ID: string | undefined;
MAXIMUM_IMPORT_SIZE: number;
FILE_STORAGE_IMPORT_MAX_SIZE: number;
EMAIL_ENABLED: boolean;
PDF_EXPORT_ENABLED: boolean;
DEFAULT_LANGUAGE: string;
@@ -71,6 +71,7 @@ export type PublicEnv = {
export enum AttachmentPreset {
DocumentAttachment = "documentAttachment",
WorkspaceImport = "workspaceImport",
Import = "import",
Avatar = "avatar",
}