MDL-23437 backup - restore security checks
[moodle.git] / backup / util / checks / restore_check.class.php
1 <?php
3 // This file is part of Moodle - http://moodle.org/
4 //
5 // Moodle is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // Moodle is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
18 /**
19  * @package    moodlecore
20  * @subpackage backup-factories
21  * @copyright  2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com}
22  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
23  */
25 /**
26  * Non instantiable helper class providing different restore checks
27  *
28  * This class contains various static methods available in order to easily
29  * perform a bunch of restore architecture tests
30  *
31  * TODO: Finish phpdocs
32  */
33 abstract class restore_check {
35     public static function check_courseid($courseid) {
36         global $DB;
37         // id must exist in course table
38         if (! $DB->record_exists('course', array('id' => $courseid))) {
39             throw new restore_controller_exception('restore_check_course_not_exists', $courseid);
40         }
41         return true;
42     }
44     public static function check_user($userid) {
45         global $DB;
46         // userid must exist in user table
47         if (! $DB->record_exists('user', array('id' => $userid))) {
48             throw new restore_controller_exception('restore_check_user_not_exists', $userid);
49         }
50         return true;
51     }
53     public static function check_security($restore_controller, $apply) {
54         global $DB;
56         if (! $restore_controller instanceof restore_controller) {
57             throw new restore_controller_exception('restore_check_security_requires_restore_controller');
58         }
59         $restore_controller->log('checking plan security', backup::LOG_INFO);
61         // Some handy vars
62         $type     = $restore_controller->get_type();
63         $mode     = $restore_controller->get_mode();
64         $courseid = $restore_controller->get_courseid();
65         $coursectx= get_context_instance(CONTEXT_COURSE, $courseid);
66         $userid   = $restore_controller->get_userid();
68         // Note: all the checks along the function MUST be performed for $userid, that
69         // is the user who "requested" the course restore, not current $USER at all!!
71         // First of all, check the main restore[course|section|activity] principal caps
72         // Lacking the corresponding one makes this to break with exception always
73         switch ($type) {
74             case backup::TYPE_1COURSE :
75                 if (!has_capability('moodle/restore:restorecourse', $coursectx, $userid)) {
76                     $a = new stdclass();
77                     $a->userid = $userid;
78                     $a->courseid = $courseid;
79                     $a->capability = 'moodle/restore:restorecourse';
80                     throw new restore_controller_exception('restore_user_missing_capability', $a);
81                 }
82                 break;
83             case backup::TYPE_1SECTION :
84                 if (!has_capability('moodle/restore:restoresection', $coursectx, $userid)) {
85                     $a = new stdclass();
86                     $a->userid = $userid;
87                     $a->courseid = $courseid;
88                     $a->capability = 'moodle/restore:restoresection';
89                     throw new restore_controller_exception('restore_user_missing_capability', $a);
90                 }
91                 break;
92             case backup::TYPE_1ACTIVITY :
93                 if (!has_capability('moodle/restore:restoreactivity', $coursectx, $userid)) {
94                     $a = new stdclass();
95                     $a->userid = $userid;
96                     $a->courseid = $courseid;
97                     $a->capability = 'moodle/restore:restoreactivity';
98                     throw new restore_controller_exception('restore_user_missing_capability', $a);
99                 }
100                 break;
101             default :
102                 print_error('unknownrestoretype');
103         }
105         // Now, if restore mode is hub or import, check userid has permissions for those modes
106         switch ($mode) {
107             case backup::MODE_HUB:
108                 if (!has_capability('moodle/restore:restoretargethub', $coursectx, $userid)) {
109                     $a = new stdclass();
110                     $a->userid = $userid;
111                     $a->courseid = $courseid;
112                     $a->capability = 'moodle/restore:restoretargethub';
113                     throw new restore_controller_exception('restore_user_missing_capability', $a);
114                 }
115                 break;
116             case backup::MODE_IMPORT:
117                 if (!has_capability('moodle/restore:restoretargetimport', $coursectx, $userid)) {
118                     $a = new stdclass();
119                     $a->userid = $userid;
120                     $a->courseid = $courseid;
121                     $a->capability = 'moodle/restore:restoretargetimport';
122                     throw new restore_controller_exception('restore_user_missing_capability', $a);
123                 }
124                 break;
125         }
127         // Now, enforce 'moodle/restore:userinfo' to 'users' setting, applying changes if allowed,
128         // else throwing exception
129         $userssetting = $restore_controller->get_plan()->get_setting('users');
130         $prevvalue    = $userssetting->get_value();
131         $prevstatus   = $userssetting->get_status();
132         $hasusercap   = has_capability('moodle/restore:userinfo', $coursectx, $userid);
134         // If setting is enabled but user lacks permission
135         if (!$hasusercap && $prevvalue) { // If user has not the capability and setting is enabled
136             // Now analyse if we are allowed to apply changes or must stop with exception
137             if (!$apply) { // Cannot apply changes, throw exception
138                 $a = new stdclass();
139                 $a->setting = 'users';
140                 $a->value = $prevvalue;
141                 $a->capability = 'moodle/restore:userinfo';
142                 throw new restore_controller_exception('restore_setting_value_wrong_for_capability', $a);
144             } else { // Can apply changes
145                 $userssetting->set_value(false);                              // Set the value to false
146                 $userssetting->set_status(base_setting::LOCKED_BY_PERMISSION);// Set the status to locked by perm
147             }
148         }
150         // Now, if mode is HUB or IMPORT, and still we are including users in restore, turn them off
151         // Defaults processing should have handled this, but we need to be 100% sure
152         if ($mode == backup::MODE_IMPORT || $mode == backup::MODE_HUB) {
153             $userssetting = $restore_controller->get_plan()->get_setting('users');
154             if ($userssetting->get_value()) {
155                 $userssetting->set_value(false);                              // Set the value to false
156                 $userssetting->set_status(base_setting::LOCKED_BY_PERMISSION);// Set the status to locked by perm
157             }
158         }
160         return true;
161     }