Fix attempt: Check cloud project before sending it to avoid corrupt cloud project (#5183)

This commit is contained in:
AlexandreS
2023-03-31 13:45:45 +02:00
committed by GitHub
parent e52faae332
commit 418dd834c0
5 changed files with 43 additions and 9 deletions

View File

@@ -2117,7 +2117,6 @@ const MainFrame = (props: Props) => {
}));
}
} catch (rawError) {
// If any error happens, ensure we hide the snackbars.
_closeSnackMessage();
const errorMessage = getWriteErrorMessage
? getWriteErrorMessage(rawError)
@@ -2272,11 +2271,12 @@ const MainFrame = (props: Props) => {
} catch (rawError) {
showErrorBox({
message: i18n._(
t`Unable to save as the project! Please try again by choosing another location.`
t`Unable to save the project! Please try again later or save the project in another location.`
),
rawError,
errorId: 'project-save-error',
});
_closeSnackMessage();
} finally {
setIsSavingProject(false);
}
@@ -2288,6 +2288,7 @@ const MainFrame = (props: Props) => {
currentFileMetadata,
getStorageProviderOperations,
_showSnackMessage,
_closeSnackMessage,
_replaceSnackMessage,
i18n,
unsavedChanges,

View File

@@ -13,11 +13,33 @@ import type { MessageDescriptor } from '../../Utils/i18n/MessageDescriptor.flow'
import { serializeToJSON } from '../../Utils/Serializer';
import CloudSaveAsDialog from './CloudSaveAsDialog';
import { t } from '@lingui/macro';
import { createZipWithSingleTextFile } from '../../Utils/Zip.js/Utils';
import {
createZipWithSingleTextFile,
unzipFirstEntryOfBlob,
} from '../../Utils/Zip.js/Utils';
const zipProject = async (project: gdProject) => {
const zipProject = async (project: gdProject): Promise<[Blob, string]> => {
const projectJson = serializeToJSON(project);
return createZipWithSingleTextFile(projectJson, 'game.json');
const zippedProject = await createZipWithSingleTextFile(
projectJson,
'game.json'
);
return [zippedProject, projectJson];
};
const checkZipContent = async (
zip: Blob,
projectJson: string
): Promise<boolean> => {
try {
const unzippedProjectJson = await unzipFirstEntryOfBlob(zip);
return (
unzippedProjectJson === projectJson && !!JSON.parse(unzippedProjectJson)
);
} catch (error) {
console.error('An error occurred when checking zipped project.', error);
return false;
}
};
const zipProjectAndCommitVersion = async ({
@@ -31,11 +53,15 @@ const zipProjectAndCommitVersion = async ({
cloudProjectId: string,
options?: {| previousVersion: string |},
|}): Promise<?string> => {
const archive = await zipProject(project);
const [zippedProject, projectJson] = await zipProject(project);
const archiveIsSane = await checkZipContent(zippedProject, projectJson);
if (!archiveIsSane) {
throw new Error('Project compression failed before saving the project.');
}
const newVersion = await commitVersion({
authenticatedUser,
cloudProjectId,
zippedProject: archive,
zippedProject,
previousVersion: options ? options.previousVersion : null,
});
return newVersion;

View File

@@ -72,7 +72,9 @@ function ConfirmDeleteDialog(props: Props) {
]}
noMobileFullScreen
>
<Text size="body">{i18n._(props.message)}</Text>
<Text size="body" style={{ userSelect: 'text' }}>
{i18n._(props.message)}
</Text>
<LargeSpacer />
<TextField
autoFocus="desktop"

View File

@@ -47,6 +47,9 @@ type Props = {|
whiteSpace?: 'nowrap' | 'pre-wrap',
textOverflow?: 'ellipsis',
// Allow user to select text
userSelect?: 'text',
// Allow to expand the text
flex?: 1,

View File

@@ -2,7 +2,9 @@
import { initializeZipJs } from '.';
export const unzipFirstEntryOfBlob = async (zippedBlob: Blob) => {
export const unzipFirstEntryOfBlob = async (
zippedBlob: Blob
): Promise<string> => {
const zipJs: ZipJs = await initializeZipJs();
return new Promise((resolve, reject) => {