MDL-67095 core_h5p: Prevent synchronous access to save the same h5p
authorcescobedo <carlos.escobedo@gmail.com>
Thu, 2 Apr 2020 14:18:12 +0000 (16:18 +0200)
committercescobedo <carlos.escobedo@gmail.com>
Fri, 17 Apr 2020 07:14:18 +0000 (09:14 +0200)
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).

h5p/classes/player.php
lang/en/h5p.php

index 9633388..e8c68a6 100644 (file)
@@ -28,6 +28,7 @@ defined('MOODLE_INTERNAL') || die();
 
 use core_h5p\local\library\autoloader;
 use core_xapi\local\statement\item_activity;
+use core\lock\lock_config;
 
 /**
  * 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.
             $onlyupdatelibs = !helper::can_update_library($file);
 
-            // Validate and store the H5P content before displaying it.
-            $h5pid = helper::save_h5p($this->factory, $file, $config, $onlyupdatelibs, false);
+            // Start lock to prevent synchronous access to save the same h5p.
+            $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)) {
                 // 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.
index c7235eb..b9858b5 100644 (file)
@@ -137,6 +137,7 @@ $string['licenseV3'] = 'Version 3';
 $string['licensee'] = 'Licensee';
 $string['licenseextras'] = 'License extras';
 $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['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}.';