MDL-19233 restore of roles - prevent role creation, role assignment and
authorEloy Lafuente <stronk7@moodle.org>
Mon, 22 Mar 2010 22:33:30 +0000 (22:33 +0000)
committerEloy Lafuente <stronk7@moodle.org>
Mon, 22 Mar 2010 22:33:30 +0000 (22:33 +0000)
permission overrides by observing corresponding caps. Improve role mapping a bit.
Credit goes to Daniel Neis. Merged from 19_STABLE

backup/restore_check.html
backup/restore_form.html
backup/restorelib.php
lang/en_utf8/moodle.php

index 3c7cf14..4263908 100644 (file)
             }
         }
 
+        // Re-check all the roles creation/mapping stuff
+        if (!empty($restore->course_id)) {
+            $contexttosearch = get_context_instance(CONTEXT_COURSE, $restore->course_id);
+        // if we know the target category, check capability on it
+        } else if (!empty($restore->restore_restorecatto)) {
+            $contexttosearch = get_context_instance(CONTEXT_COURSECAT, $restore->restore_restorecatto);
+        } else {
+            $contexttosearch = get_context_instance(CONTEXT_SYSTEM);
+        }
+        $cancreateroles = has_capability('moodle/role:manage', get_context_instance(CONTEXT_SYSTEM));
+        $canassignroles = has_capability('moodle/role:assign', $contexttosearch);
+        $canoverridecaps= has_capability('moodle/role:override', $contexttosearch) || has_capability('moodle/role:safeoverride', $contexttosearch);
+        if (!empty($restore->rolesmapping)) {
+            foreach ($restore->rolesmapping as $originalrole => $targetrole) {
+                // First, if new role is selected, check used really can do that
+                if (empty($targetrole) && !$cancreateroles) {
+                    $messages[] = get_string('restorecannotcreateorassignroles');
+                    $show_continue_button = false;
+                    break;
+                }
+                // Now, check that the target role is available for role assignments
+                if (!empty($targetrole) && !$canassignroles) {
+                    $messages[] = get_string('restorecannotassignroles');
+                    $show_continue_button = false;
+                    break;
+                }
+                // Now, check that the target role is available for capability overrides
+                if (!empty($targetrole) && !$canoverridecaps) {
+                    $messages[] = get_string('restorecannotoverrideperms');
+                    $show_continue_button = false;
+                    break;
+                }
+            }
+        }
 
     /// If restoring users and backup has mnet remote users and we are restoring to different site, forbid restore to non-admins. MDL-17009
         if ($restore->users != 2 &&                                                   /// If restoring users
index 674b5e5..3ec04cb 100644 (file)
@@ -624,9 +624,10 @@ if ($restoreuserinfo) {
     $allroles = get_records('role');
 
     echo ('<table width="100%" class="restore-form-instances">');
-    echo ('<tr><td align="right" style="width:50%"><b>'.get_string('sourcerole').'</b></td><td align="left" style="width:50%"><b>'.get_string('targetrole').'</b></td></tr>');
 
     if ($info->backup_moodle_version < 2006092801) {
+        echo ('<tr><td align="right" style="width:50%"><b>'.get_string('sourcerole').'</b></td><td align="left" style="width:50%"><b>'.get_string('targetrole').'</b></td></tr>');
+
         // 1.6 and below backup
 
         /// Editting teacher
@@ -671,6 +672,20 @@ if ($restoreuserinfo) {
         // 1.7 and above backup
         $roles = restore_read_xml_roles($xml_file);
 
+        // Calculate if any role can be mapped
+        $str_new = '';
+        $canmaproles = false;
+        if (has_capability('moodle/role:manage', get_context_instance(CONTEXT_SYSTEM))) {
+            $str_new = 'new role';
+            $canmaproles = true;
+        } else if (!empty($siterolesarray)) {
+            $canmaproles = true;
+        }
+
+        if ($canmaproles) {
+            echo ('<tr><td align="right" style="width:50%"><b>'.get_string('sourcerole').'</b></td><td align="left" style="width:50%"><b>'.get_string('targetrole').'</b></td></tr>');
+        }
+
         if (!empty($roles->roles)) { // possible to have course with no roles
             foreach ($siterolesarray as $siteroleid=>$siteroleshortname) {
                 $siteroleschoicearray[$siteroleid] = $siterolesnamearray[$siteroleid]." (". $siterolesarray[$siteroleid].")";
@@ -678,7 +693,12 @@ if ($restoreuserinfo) {
 
             foreach ($roles->roles as $roleid=>$role) {
 
-                $mappableroles = $siteroleschoicearray;
+                if (!$canmaproles) { // User cannot map roles at all, add hidden element and continue
+                    echo "<tr><td colspan=\"2\"><input type=\"hidden\" name=\"roles_{$roleid}\" value=\"0\" /></td></tr>";
+                    continue;
+                }
+
+                $mappableroles = !empty($siteroleschoicearray) ? $siteroleschoicearray : array();
 
                 echo ('<tr><td align="right">');
                 echo '<label for="menuroles_'.$roleid.'">'.format_string($role->name)." (".($role->shortname).")".'</label>';
@@ -702,8 +722,21 @@ if ($restoreuserinfo) {
                             break;
                         }
                     }
+                    // Hack a bit, so, if role continues unmatched, and was "editingteacher", and "teacher" is available
+                    // preselect it as fallback matching (can happen a lot)
+                    if ($matchrole == 0 && $role->shortname == 'editingteacher' && in_array('teacher', $siterolesarray)) {
+                        $matchrole = array_search('teacher', $siterolesarray);
+                    }
+
+                    // If arrived here, role continues unmatched and the user lacks the 'moodle/role:manage' capability
+                    // perform automatic matching to site defaultcourseroleid (only if available in the list)
+                    if ($matchrole == 0 && !has_capability('moodle/role:manage', get_context_instance(CONTEXT_SYSTEM))) {
+                        if (array_key_exists($CFG->defaultcourseroleid, $siterolesarray)) {
+                            $matchrole = $CFG->defaultcourseroleid;
+                        }
+                    }
                 }
-                echo html_writer::select($mappableroles, "roles_".$roleid, $matchrole, array(''=>'new role'));
+                echo html_writer::select($mappableroles, "roles_".$roleid, $matchrole, array('' => $str_new));
                 echo ('</td></tr>');
             }
         }
index a96109e..e018a9e 100644 (file)
@@ -9339,7 +9339,7 @@ WHERE
      * It isn't now, just overwriting
      */
     function restore_create_roles($restore, $xmlfile) {
-        global $DB;
+        global $DB, $CFG;
         if (!defined('RESTORE_SILENTLY')) {
             echo "<li>".get_string("creatingrolesdefinitions").'</li>';
         }
@@ -9374,7 +9374,8 @@ WHERE
                     $status = backup_putid($restore->backup_unique_code,"role",$oldroleid,
                                      $rolemappings[$oldroleid]); // adding a new id
 
-                } else {
+                // check for permissions before create new roles
+                } else if (has_capability('moodle/role:manage', get_context_instance(CONTEXT_SYSTEM))) {
 
                     // code to make new role name/short name if same role name or shortname exists
                     $fullname = $roledata->name;
@@ -9432,7 +9433,14 @@ WHERE
 
                         $DB->insert_record('role_capabilities', $roleinfo);
                     }
+                } else {
+                    // map the new role to course default role
+                    if (!$default_role = get_field("course", "defaultrole", "id", $restore->course_id)) {
+                        $default_role = $CFG->defaultcourseroleid;
+                    }
+                    $status = backup_putid($restore->backup_unique_code, "role", $oldroleid, $default_role);
                 }
+
             /// Now, restore role nameincourse (only if the role had nameincourse in backup)
                 if (!empty($roledata->nameincourse)) {
                     $newrole = backup_getid($restore->backup_unique_code, 'role', $oldroleid); /// Look for target role
index e80f1a2..910f0b4 100644 (file)
@@ -1388,7 +1388,10 @@ $string['resource'] = 'Resource';
 $string['resources'] = 'Resources';
 $string['restore'] = 'Restore';
 $string['restorecancelled'] = 'Restore cancelled';
+$string['restorecannotassignroles'] = 'Restore needs to assign roles and you do not have permission to do so';
+$string['restorecannotcreateorassignroles'] = 'Restore needs to create or assign roles and you do not have permission to do so';
 $string['restorecannotcreateuser'] = 'Restore needs to create user \'$a\' from backup file and you do not have permission to do so';
+$string['restorecannotoverrideperms'] = 'Restore needs to override permissions and you do not have permission to do so';
 $string['restorecoursenow'] = 'Restore this course now!';
 $string['restoredaccount'] = 'Restored account';
 $string['restoredaccountinfo'] = 'This account was imported from another server and the password has been lost. To set a new password by email, please click \"Continue\"';