MDL-67095 core_h5p: Prevent synchronous access to save the same h5p

When deploying a new H5P resource we need to ensure that
we don't start deploying the same H5P in another thread
(e.g. for another session/user).
This commit is contained in:
cescobedo 2020-04-02 16:18:12 +02:00
parent 788dfb9c7d
commit e84ce938d9
2 changed files with 16 additions and 2 deletions

View file

@ -28,6 +28,7 @@ defined('MOODLE_INTERNAL') || die();
use core_h5p\local\library\autoloader; use core_h5p\local\library\autoloader;
use core_xapi\local\statement\item_activity; use core_xapi\local\statement\item_activity;
use core\lock\lock_config;
/** /**
* H5P player class, for displaying any local H5P content. * H5P player class, for displaying any local H5P content.
@ -337,8 +338,20 @@ class player {
// content-type libraries exist, to avoid users without the h5p:updatelibraries capability upload malicious content. // content-type libraries exist, to avoid users without the h5p:updatelibraries capability upload malicious content.
$onlyupdatelibs = !helper::can_update_library($file); $onlyupdatelibs = !helper::can_update_library($file);
// Validate and store the H5P content before displaying it. // Start lock to prevent synchronous access to save the same h5p.
$h5pid = helper::save_h5p($this->factory, $file, $config, $onlyupdatelibs, false); $lockfactory = lock_config::get_lock_factory('core_h5p');
$lockkey = 'core_h5p_' . $pathnamehash;
if ($lock = $lockfactory->get_lock($lockkey, 10)) {
try {
// Validate and store the H5P content before displaying it.
$h5pid = helper::save_h5p($this->factory, $file, $config, $onlyupdatelibs, false);
} finally {
$lock->release();
}
} else {
$this->core->h5pF->setErrorMessage(get_string('lockh5pdeploy', 'core_h5p'));
return false;
};
if (!$h5pid && $file->get_userid() != $USER->id && has_capability('moodle/h5p:updatelibraries', $this->context)) { if (!$h5pid && $file->get_userid() != $USER->id && has_capability('moodle/h5p:updatelibraries', $this->context)) {
// The user has permission to update libraries but the package has been uploaded by a different // The user has permission to update libraries but the package has been uploaded by a different
// user without this permission. Check if there is some missing required library error. // user without this permission. Check if there is some missing required library error.

View file

@ -137,6 +137,7 @@ $string['licenseV3'] = 'Version 3';
$string['licensee'] = 'Licensee'; $string['licensee'] = 'Licensee';
$string['licenseextras'] = 'License extras'; $string['licenseextras'] = 'License extras';
$string['licenseversion'] = 'License version'; $string['licenseversion'] = 'License version';
$string['lockh5pdeploy'] = 'This H5P content cannot be accessed because it is being deployed. Please try again later.';
$string['missingcontentfolder'] = 'A valid content folder is missing'; $string['missingcontentfolder'] = 'A valid content folder is missing';
$string['missingcoreversion'] = 'The system was unable to install the {$a->%component} component from the package, as it requires a newer version of the H5P plugin. This site is currently running version {$a->%current}, whereas the required version is {$a->%required} or higher. Please upgrade and then try again.'; $string['missingcoreversion'] = 'The system was unable to install the {$a->%component} component from the package, as it requires a newer version of the H5P plugin. This site is currently running version {$a->%current}, whereas the required version is {$a->%required} or higher. Please upgrade and then try again.';
$string['missingdependency'] = 'Missing dependency {$a->@dep} required by {$a->@lib}.'; $string['missingdependency'] = 'Missing dependency {$a->@dep} required by {$a->@lib}.';