Compare commits

...

2 Commits

Author SHA1 Message Date
Clément Pasteau
ba4a37813e Refactor into usage 2023-02-14 15:37:14 +01:00
Clément Pasteau
3f36054d54 Reduce allowed size for online web build to avoid abuse 2023-02-14 15:04:25 +01:00
7 changed files with 54 additions and 18 deletions

View File

@@ -26,6 +26,10 @@ import {
ExplanationHeader,
OnlineGameLink,
} from '../GenericExporters/OnlineWebExport';
import {
hasValidSubscriptionPlan,
onlineWebExportSizeOptions,
} from '../../Utils/GDevelopServices/Usage';
const gd: libGDevelop = global.gd;
type ExportState = null;
@@ -152,12 +156,16 @@ export const browserOnlineWebExportPipeline: ExportPipeline<
context: ExportPipelineContext<ExportState>,
{ textFiles, blobFiles }: ResourcesDownloadOutput
): Promise<Blob> => {
const hasValidSubscription = hasValidSubscriptionPlan(context.subscription);
return archiveFiles({
blobFiles,
textFiles,
basePath: '/export/',
onProgress: context.updateStepProgress,
sizeLimit: 250 * 1000 * 1000,
// Higher limit for users with a subscription.
sizeOptions: hasValidSubscription
? onlineWebExportSizeOptions.subscribed
: onlineWebExportSizeOptions.guest,
});
},

View File

@@ -257,6 +257,7 @@ export default class ExportLauncher extends Component<Props, State> {
project,
updateStepProgress: this._updateStepProgress,
exportState: this.state.exportState,
subscription: authenticatedUser.subscription,
};
setStep('export');
this.setState({

View File

@@ -3,11 +3,13 @@ import * as React from 'react';
import { type Build } from '../Utils/GDevelopServices/Build';
import { type AuthenticatedUser } from '../Profile/AuthenticatedUserContext';
import { type BuildStep } from './Builds/BuildStepsProgress';
import { type Subscription } from '../Utils/GDevelopServices/Usage';
export type ExportPipelineContext<ExportState> = {|
project: gdProject,
exportState: ExportState,
updateStepProgress: (count: number, total: number) => void,
subscription: ?Subscription,
|};
/**

View File

@@ -22,6 +22,10 @@ import {
OnlineGameLink,
} from '../GenericExporters/OnlineWebExport';
import { downloadUrlsToLocalFiles } from '../../Utils/LocalFileDownloader';
import {
hasValidSubscriptionPlan,
onlineWebExportSizeOptions,
} from '../../Utils/GDevelopServices/Usage';
const path = optionalRequire('path');
const os = optionalRequire('os');
const gd: libGDevelop = global.gd;
@@ -156,11 +160,15 @@ export const localOnlineWebExportPipeline: ExportPipeline<
context: ExportPipelineContext<ExportState>,
{ temporaryOutputDir }: ResourcesDownloadOutput
): Promise<CompressionOutput> => {
const hasValidSubscription = hasValidSubscriptionPlan(context.subscription);
const archiveOutputDir = os.tmpdir();
return archiveLocalFolder({
path: temporaryOutputDir,
outputFilename: path.join(archiveOutputDir, 'game-archive.zip'),
sizeLimit: 250 * 1000 * 1000,
// Higher limit for users with a subscription.
sizeOptions: hasValidSubscription
? onlineWebExportSizeOptions.subscribed
: onlineWebExportSizeOptions.guest,
});
},

View File

@@ -3,6 +3,7 @@ import { initializeZipJs } from './Zip.js';
import { downloadUrlsToBlobs, type ItemResult } from './BlobDownloader';
import path from 'path';
import { shortenString } from './StringHelpers.js';
import { type ExportSizeOptions } from './GDevelopServices/Usage';
export type BlobFileDescriptor = {|
filePath: string,
@@ -95,13 +96,13 @@ export const archiveFiles = async ({
blobFiles,
basePath,
onProgress,
sizeLimit,
sizeOptions,
}: {|
textFiles: Array<TextFileDescriptor>,
blobFiles: Array<BlobFileDescriptor>,
basePath: string,
onProgress: (count: number, total: number) => void,
sizeLimit?: number,
sizeOptions?: ExportSizeOptions,
|}): Promise<Blob> => {
const zipJs: ZipJs = await initializeZipJs();
@@ -154,15 +155,12 @@ export const archiveFiles = async ({
() => {
zipWriter.close((blob: Blob) => {
const fileSize = blob.size;
if (sizeLimit && fileSize > sizeLimit) {
if (sizeOptions && fileSize > sizeOptions.limit) {
const roundFileSizeInMb = Math.round(
fileSize / (1000 * 1000)
);
reject(
new Error(
`Archive is of size ${roundFileSizeInMb} MB, which is above the limit allowed of ${sizeLimit /
(1000 * 1000)} MB.`
)
new Error(sizeOptions.getErrorMessage(roundFileSizeInMb))
);
}
resolve(blob);

View File

@@ -190,6 +190,29 @@ export const businessPlan: PlanDetails = {
descriptionBullets: [],
};
const SUBSCRIBED_SIZE_LIMIT_IN_MB = 250;
const GUEST_SIZE_LIMIT_IN_MB = 50;
export type ExportSizeOptions = {|
limit: number,
getErrorMessage: (fileSizeInMb: number) => string,
|};
export const onlineWebExportSizeOptions: {
[key: 'guest' | 'subscribed']: ExportSizeOptions,
} = {
guest: {
limit: SUBSCRIBED_SIZE_LIMIT_IN_MB * 1000 * 1000,
getErrorMessage: (fileSizeInMb: number) =>
`Archive is of size ${fileSizeInMb} MB, which is above the limit allowed of ${SUBSCRIBED_SIZE_LIMIT_IN_MB} MB`,
},
subscribed: {
limit: GUEST_SIZE_LIMIT_IN_MB * 1000 * 1000,
getErrorMessage: (fileSizeInMb: number) =>
`Archive is of size ${fileSizeInMb} MB, which is above the limit allowed of ${GUEST_SIZE_LIMIT_IN_MB} MB. You can subscribe to GDevelop to increase the limit to ${SUBSCRIBED_SIZE_LIMIT_IN_MB} MB.`,
},
};
export const getUserUsages = (
getAuthorizationHeader: () => Promise<string>,
userId: string

View File

@@ -2,6 +2,7 @@
import optionalRequire from './OptionalRequire';
import optionalLazyRequire from '../Utils/OptionalLazyRequire';
import { type ExportSizeOptions } from './GDevelopServices/Usage';
const fs = optionalRequire('fs');
const lazyRequireArchiver = optionalLazyRequire('archiver');
@@ -12,11 +13,11 @@ const lazyRequireArchiver = optionalLazyRequire('archiver');
export const archiveLocalFolder = ({
path,
outputFilename,
sizeLimit,
sizeOptions,
}: {|
path: string,
outputFilename: string,
sizeLimit?: number,
sizeOptions?: ExportSizeOptions,
|}): Promise<string> => {
const archiver = lazyRequireArchiver();
return new Promise((resolve, reject) => {
@@ -32,14 +33,9 @@ export const archiveLocalFolder = ({
console.log(
`Archive written at ${outputFilename}, ${fileSize} total bytes.`
);
if (sizeLimit && fileSize > sizeLimit) {
if (sizeOptions && fileSize > sizeOptions.limit) {
const roundFileSizeInMb = Math.round(fileSize / (1000 * 1000));
reject(
new Error(
`Archive is of size ${roundFileSizeInMb} MB, which is above the limit allowed of ${sizeLimit /
(1000 * 1000)} MB.`
)
);
reject(new Error(sizeOptions.getErrorMessage(roundFileSizeInMb)));
}
resolve(outputFilename);
});