Skip to content

Commit

Permalink
Merge pull request #4175 from albertgasset/MOBILE-4642
Browse files Browse the repository at this point in the history
MOBILE-4642 h5p: Prevent partially saved packages
  • Loading branch information
dpalou authored Sep 17, 2024
2 parents 437f309 + 6624d13 commit 7271ee3
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 23 deletions.
39 changes: 39 additions & 0 deletions src/core/features/h5p/classes/file-storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -449,4 +449,43 @@ export class CoreH5PFileStorage {
}
}

/**
* Check that library is fully saved to the file system.
*
* @param libraryData Library data.
* @param siteId Site ID. If not defined, current site.
* @returns Promise resolved with true if all library files are present.
*/
async checkLibrary(libraryData: CoreH5PLibraryBeingSaved, siteId?: string): Promise<boolean> {
const getFileNames = async (baseDir: string, dirName = ''): Promise<string[]> => {
const entries = await CoreFile.getDirectoryContents( baseDir + dirName);
const fileNames: string[] = [];

for (const entry of entries) {
const name = dirName + '/' + entry.name;
if (entry.isDirectory) {
fileNames.push(...(await getFileNames(baseDir, name)));
} else {
fileNames.push(name);
}
}

return fileNames;
};

if (!libraryData.uploadDirectory) {
return true;
}

siteId = siteId || CoreSites.getCurrentSiteId();
const folderPath = this.getLibraryFolderPath(libraryData, siteId);

const [sourceFiles, destFiles] = await Promise.all([
getFileNames(libraryData.uploadDirectory),
getFileNames(folderPath).catch(() => ([])).then(files => new Set(files)),
]);

return sourceFiles.every(name => destFiles.has(name));
}

}
33 changes: 10 additions & 23 deletions src/core/features/h5p/classes/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ export class CoreH5PStorage {

const newerPatchVersion = existingLibrary.patchversion < libraryData.patchVersion;

if (!newerPatchVersion) {
// Make sure the library is fully saved to the file system if it is present in the DB.
// Some files might be missing if a previous library update was interrupted.
if (!newerPatchVersion && await this.h5pCore.h5pFS.checkLibrary(libraryData, siteId)) {
// Same or older version, no need to save.
libraryData.saveDependencies = false;

Expand All @@ -79,21 +81,12 @@ export class CoreH5PStorage {
libraryData.metadataSettings = libraryData.metadataSettings ?
CoreH5PMetadata.boolifyAndEncodeSettings(libraryData.metadataSettings) : undefined;

// Save the library files before saving to DB, in case the app is closed while copying the files.
await this.h5pCore.h5pFS.saveLibrary(libraryData, siteId);

// Save the library data in DB.
await this.h5pFramework.saveLibraryData(libraryData, siteId);

// Now save it in FS.
try {
await this.h5pCore.h5pFS.saveLibrary(libraryData, siteId);
} catch (error) {
if (libraryData.libraryId) {
// An error occurred, delete the DB data because the lib FS data has been deleted.
await this.h5pFramework.deleteLibrary(libraryData.libraryId, siteId);
}

throw error;
}

if (libraryData.libraryId !== undefined) {
const promises: Promise<void>[] = [];

Expand Down Expand Up @@ -196,21 +189,15 @@ export class CoreH5PStorage {

content.params = JSON.stringify(data.contentJsonData);

// Save the content data in DB.
await this.h5pCore.saveContent(content, folderName, fileUrl, siteId);

// Save the content files in their right place in FS.
const destFolder = CorePath.concatenatePaths(CoreFileProvider.TMPFOLDER, 'h5p/' + folderName);
const contentPath = CorePath.concatenatePaths(destFolder, 'content');

try {
await this.h5pCore.h5pFS.saveContent(contentPath, folderName, siteId);
} catch (error) {
// An error occurred, delete the DB data because the content files have been deleted.
await this.h5pFramework.deleteContentData(content.id!, siteId);
// Save the content files before saving to DB, in case the app is closed while copying the files.
await this.h5pCore.h5pFS.saveContent(contentPath, folderName, siteId);

throw error;
}
// Save the content data in DB.
await this.h5pCore.saveContent(content, folderName, fileUrl, siteId);
}

return content;
Expand Down

0 comments on commit 7271ee3

Please sign in to comment.