diff --git a/admin/tool/lp/classes/api.php b/admin/tool/lp/classes/api.php index 961e223e3fe62..0127271e7eabc 100644 --- a/admin/tool/lp/classes/api.php +++ b/admin/tool/lp/classes/api.php @@ -1199,24 +1199,25 @@ public static function reorder_template_competency($templateid, $competencyidfro */ public static function list_user_plans($userid) { global $USER; - $select = 'userid = :userid'; $params = array('userid' => $userid); - $context = context_user::instance($userid); - // We can allow guest user to pass they will not have LP. - if ($USER->id != $userid) { - require_capability('tool/lp:planview', $context); - } else { - require_capability('tool/lp:planviewown', $context); + // Check that we can read something here. + if (!plan::can_read_user($userid) && !plan::can_read_user_draft($userid)) { + throw new required_capability_exception($context, 'tool/lp:planview', 'nopermissions', ''); } - // Users that can manage plans can only see active and completed plans. - if (!has_any_capability(array('tool/lp:planmanage', 'tool/lp:planmanageown', 'tool/lp:plancreateown'), $context)) { + // The user cannot view the drafts. + if (!plan::can_read_user_draft($userid)) { $select = ' AND status != :statusdraft'; $params['statusdraft'] = plan::STATUS_DRAFT; } + // The user cannot view the non-drafts. + if (!plan::can_read_user($userid)) { + $select = ' AND status = :statusdraft'; + $params['statusdraft'] = plan::STATUS_DRAFT; + } return plan::get_records_select($select, $params, 'timemodified DESC'); } @@ -1229,30 +1230,13 @@ public static function list_user_plans($userid) { */ public static function create_plan(stdClass $record) { global $USER; + $plan = new plan(0, $record); - $context = context_user::instance($record->userid); - - $manageplans = has_capability('tool/lp:planmanage', $context); - $createdraft = has_capability('tool/lp:plancreateown', $context); - $manageownplan = has_capability('tool/lp:planmanageown', $context); - - // Any of them is enough. - if ($USER->id == $record->userid && !$manageplans && !$createdraft && !$manageownplan) { - // Exception about plancreateown as it is the one that is closer to basic users. - throw new required_capability_exception($context, 'tool/lp:plancreateown', 'nopermissions', ''); - } else if ($USER->id != $record->userid && !$manageplans) { + if (!$plan->can_manage()) { + $context = context_user::instance($plan->get_userid()); throw new required_capability_exception($context, 'tool/lp:planmanage', 'nopermissions', ''); } - if (!isset($record->status)) { - // Default to status draft. - $record->status = plan::STATUS_DRAFT; - } else if ($record->status !== plan::STATUS_DRAFT && !$manageplans && !$manageownplan) { - // If the user can only create drafts we don't allow them to set other status. - throw new required_capability_exception($context, 'tool/lp:planmanageown', 'nopermissions', ''); - } - - $plan = new plan(0, $record); $plan->create(); return $plan; } @@ -1265,37 +1249,28 @@ public static function create_plan(stdClass $record) { */ public static function update_plan(stdClass $record) { global $USER; + $plan = new plan($record->id); - $context = context_user::instance($record->userid); - - $manageplans = has_capability('tool/lp:planmanage', $context); - $createdraft = has_capability('tool/lp:plancreateown', $context); - $manageownplan = has_capability('tool/lp:planmanageown', $context); - - // Any of them is enough. - if ($USER->id == $record->userid && !$manageplans && !$createdraft && !$manageownplan) { - throw new required_capability_exception($context, 'tool/lp:planmanageown', 'nopermissions', ''); - } else if (!$manageplans) { + // Validate that the plan as it is can be managed. + if (!$plan->can_manage()) { + $context = context_user::instance($plan->get_userid()); throw new required_capability_exception($context, 'tool/lp:planmanage', 'nopermissions', ''); } - $plan = new plan($record->id); - - // We don't allow users without planmanage and without - // planmanageown to edit plans that other users modified. - if (!$manageplans && !$manageownplan && $USER->id != $plan->get_usermodified()) { - throw new \moodle_exception('erroreditingmodifiedplan', 'tool_lp'); - } else if (!$manageplans && $USER->id != $plan->get_userid()) { - throw new required_capability_exception($context, 'tool/lp:planmanage', 'nopermissions', ''); + // Prevent change of ownership as the capabilities are checked against that. + if (isset($record->userid) && $plan->get_userid() != $record->userid) { + throw new coding_exception('A plan cannot be transfered to another user'); } + $plan->from_record($record); - // If the user can only create drafts we don't allow them to set other status. - if ($record->status !== plan::STATUS_DRAFT && !$manageplans && !$manageownplan) { - throw new required_capability_exception($context, 'tool/lp:planmanageown', 'nopermissions', ''); + // Revalidate after the data has be injected. This handles status change, etc... + if (!$plan->can_manage()) { + $context = context_user::instance($plan->get_userid()); + throw new required_capability_exception($context, 'tool/lp:planmanage', 'nopermissions', ''); } - $plan->from_record($record); - return $plan->update(); + $plan->update(); + return $plan; } /** @@ -1306,22 +1281,13 @@ public static function update_plan(stdClass $record) { */ public static function read_plan($id) { global $USER; - $plan = new plan($id); - $context = context_user::instance($plan->get_userid()); - if ($USER->id == $plan->get_userid()) { - require_capability('tool/lp:planviewown', $context); - } else { - require_capability('tool/lp:planview', $context); + if (!$plan->can_read()) { + $context = context_user::instance($plan->get_userid()); + throw new required_capability_exception($context, 'tool/lp:planview', 'nopermissions', ''); } - // We require any of these capabilities to retrieve draft plans. - if ($plan->get_status() == plan::STATUS_DRAFT && - !has_any_capability(array('tool/lp:planmanageown', 'tool/lp:planmanage', 'tool/lp:plancreateown'), $context)) { - // Exception about plancreateown as it is the one that is closer to basic users. - throw new required_capability_exception($context, 'tool/lp:plancreateown', 'nopermissions', ''); - } return $plan; } @@ -1333,20 +1299,10 @@ public static function read_plan($id) { */ public static function delete_plan($id) { global $USER; - $plan = new plan($id); - $context = context_user::instance($plan->get_userid()); - - $manageplans = has_capability('tool/lp:planmanage', $context); - $manageownplan = has_capability('tool/lp:planmanageown', $context); - - if ($USER->id == $plan->get_userid() && $USER->id != $plan->get_usermodified() && - !$manageplans && !$manageownplan) { - // A normal user can only edit its plan if they created it. - throw new required_capability_exception($context, 'tool/lp:planmanageown', 'nopermissions', ''); - } else if ($USER->id != $plan->get_userid() && !$manageplans) { - // Other users needs to have tool/lp:planmanage. + if (!$plan->can_manage()) { + $context = context_user::instance($plan->get_userid()); throw new required_capability_exception($context, 'tool/lp:planmanage', 'nopermissions', ''); } diff --git a/admin/tool/lp/classes/external.php b/admin/tool/lp/classes/external.php index 6b392c9e298d5..69651c48fd19a 100644 --- a/admin/tool/lp/classes/external.php +++ b/admin/tool/lp/classes/external.php @@ -3099,7 +3099,7 @@ public static function create_plan($name, $description, $descriptionformat, $use $result = api::create_plan($params); $record = $result->to_record(); $record->statusname = $result->get_statusname(); - $record->usercanupdate = $result->can_update(); + $record->usercanupdate = $result->can_manage(); return external_api::clean_returnvalue(self::create_plan_returns(), $record); } @@ -3207,7 +3207,7 @@ public static function update_plan($id, $name, $description, $descriptionformat, $result = api::update_plan($params); $record = $result->to_record(); $record->statusname = $result->get_statusname(); - $record->usercanupdate = $result->can_update(); + $record->usercanupdate = $result->can_manage(); return external_api::clean_returnvalue(self::update_plan_returns(), $record); } @@ -3249,7 +3249,7 @@ public static function read_plan($id) { $result = api::read_plan($params['id']); $record = $result->to_record(); $record->statusname = $result->get_statusname(); - $record->usercanupdate = $result->can_update(); + $record->usercanupdate = $result->can_manage(); return external_api::clean_returnvalue(self::read_plan_returns(), $record); } diff --git a/admin/tool/lp/classes/form/plan.php b/admin/tool/lp/classes/form/plan.php index 9341b5872d528..2d317f571e170 100644 --- a/admin/tool/lp/classes/form/plan.php +++ b/admin/tool/lp/classes/form/plan.php @@ -59,12 +59,6 @@ public function definition() { $mform->addElement('editor', 'description', get_string('plandescription', 'tool_lp'), array('rows' => 4)); $mform->setType('description', PARAM_TEXT); - $templates = $this->get_template_options(); - if ($templates) { - $mform->addElement('select', 'templateid', get_string('plantemplate', 'tool_lp'), $templates); - $mform->addHelpButton('templateid', 'plantemplate', 'tool_lp'); - } - $mform->addElement('date_selector', 'duedate', get_string('duedate', 'tool_lp')); $mform->addHelpButton('duedate', 'duedate', 'tool_lp'); diff --git a/admin/tool/lp/classes/output/plans_page.php b/admin/tool/lp/classes/output/plans_page.php index eca11f2f992b8..cbce7bd3d351f 100644 --- a/admin/tool/lp/classes/output/plans_page.php +++ b/admin/tool/lp/classes/output/plans_page.php @@ -88,7 +88,7 @@ public function export_for_template(renderer_base $output) { foreach ($this->plans as $plan) { $record = $plan->to_record(); $record->statusname = $plan->get_statusname(); - $record->usercanupdate = $plan->can_update(); + $record->usercanupdate = $plan->can_manage(); $data->plans[] = $record; } } diff --git a/admin/tool/lp/classes/plan.php b/admin/tool/lp/classes/plan.php index 78f37ab259927..36911fd45e9fe 100644 --- a/admin/tool/lp/classes/plan.php +++ b/admin/tool/lp/classes/plan.php @@ -86,33 +86,27 @@ protected static function define_properties() { } /** - * Whether the current user can update the learning plan. + * Whether the current user can manage the plan. * - * @return bool|null + * @return bool */ - public function can_update() { - global $USER; - - // Null if the record has not been filled. - if (!$userid = $this->get_userid()) { - return null; - } - - $context = context_user::instance($userid); - - // Not all users can edit all plans, the template should know about it. - if (has_capability('tool/lp:planmanage', $context) || - has_capability('tool/lp:planmanageown', $context)) { - return true; + public function can_manage() { + if ($this->get_status() == self::STATUS_DRAFT) { + return self::can_manage_user_draft($this->get_userid()); } + return self::can_manage_user($this->get_userid()); + } - // The user that created the template can also edit it if he was the last one that modified it. But - // can't do it if it is already completed. - if ($USER->id == $userid && $this->get_usermodified() == $USER->id && $this->get_status() != self::STATUS_COMPLETE) { - return true; + /** + * Whether the current user can read the plan. + * + * @return bool + */ + public function can_read() { + if ($this->get_status() == self::STATUS_DRAFT) { + return self::can_read_user_draft($this->get_userid()); } - - return false; + return self::can_read_user($this->get_userid()); } /** @@ -158,4 +152,78 @@ protected function validate_templateid($value) { return true; } + /** + * Can the current user manage a user's plan? + * + * @param int $planuserid The user to whom the plan would belong. + * @return bool + */ + public static function can_manage_user($planuserid) { + global $USER; + $context = context_user::instance($planuserid); + + $capabilities = array('tool/lp:planmanage'); + if ($context->instanceid == $USER->id) { + $capabilities[] = 'tool/lp:planmanageown'; + } + + return has_any_capability($capabilities, $context); + } + + /** + * Can the current user manage a user's draft plan? + * + * @param int $planuserid The user to whom the plan would belong. + * @return bool + */ + public static function can_manage_user_draft($planuserid) { + global $USER; + $context = context_user::instance($planuserid); + + $capabilities = array('tool/lp:planmanagedraft'); + if ($context->instanceid == $USER->id) { + $capabilities[] = 'tool/lp:planmanageowndraft'; + } + + return has_any_capability($capabilities, $context); + } + + /** + * Can the current user view a user's plan? + * + * @param int $planuserid The user to whom the plan would belong. + * @return bool + */ + public static function can_read_user($planuserid) { + global $USER; + $context = context_user::instance($planuserid); + + $capabilities = array('tool/lp:planview'); + if ($context->instanceid == $USER->id) { + $capabilities[] = 'tool/lp:planviewown'; + } + + return has_any_capability($capabilities, $context) + || self::can_manage_user($planuserid); + } + + /** + * Can the current user view a user's draft plan? + * + * @param int $planuserid The user to whom the plan would belong. + * @return bool + */ + public static function can_read_user_draft($planuserid) { + global $USER; + $context = context_user::instance($planuserid); + + $capabilities = array('tool/lp:planviewdraft'); + if ($context->instanceid == $USER->id) { + $capabilities[] = 'tool/lp:planviewowndraft'; + } + + return has_any_capability($capabilities, $context) + || self::can_manage_user_draft($planuserid); + } + } diff --git a/admin/tool/lp/db/access.php b/admin/tool/lp/db/access.php index f154bee29de01..049410d110e3a 100644 --- a/admin/tool/lp/db/access.php +++ b/admin/tool/lp/db/access.php @@ -60,16 +60,16 @@ ), 'clonepermissionsfrom' => 'moodle/block:view' ), - 'tool/lp:plancreateown' => array( + 'tool/lp:planmanage' => array( 'captype' => 'write', 'contextlevel' => CONTEXT_USER, 'archetypes' => array( ), 'clonepermissionsfrom' => 'moodle/site:config' ), - 'tool/lp:planmanage' => array( + 'tool/lp:planmanagedraft' => array( 'captype' => 'write', - 'contextlevel' => CONTEXT_SYSTEM, + 'contextlevel' => CONTEXT_USER, 'archetypes' => array( ), 'clonepermissionsfrom' => 'moodle/site:config' @@ -81,6 +81,13 @@ ), 'clonepermissionsfrom' => 'moodle/site:config' ), + 'tool/lp:planmanageowndraft' => array( + 'captype' => 'write', + 'contextlevel' => CONTEXT_USER, + 'archetypes' => array( + ), + 'clonepermissionsfrom' => 'moodle/site:config' + ), 'tool/lp:planview' => array( 'captype' => 'read', 'contextlevel' => CONTEXT_USER, @@ -88,6 +95,13 @@ ), 'clonepermissionsfrom' => 'moodle/site:config' ), + 'tool/lp:planviewdraft' => array( + 'captype' => 'read', + 'contextlevel' => CONTEXT_USER, + 'archetypes' => array( + ), + 'clonepermissionsfrom' => 'moodle/site:config' + ), 'tool/lp:planviewown' => array( 'captype' => 'read', 'contextlevel' => CONTEXT_USER, @@ -96,6 +110,13 @@ ), 'clonepermissionsfrom' => 'moodle/block:view' ), + 'tool/lp:planviewowndraft' => array( + 'captype' => 'read', + 'contextlevel' => CONTEXT_USER, + 'archetypes' => array( + ), + 'clonepermissionsfrom' => 'moodle/site:config' + ), 'tool/lp:templatemanage' => array( 'captype' => 'write', 'contextlevel' => CONTEXT_COURSECAT, diff --git a/admin/tool/lp/editplan.php b/admin/tool/lp/editplan.php index 3adee2c85354b..507f85d375fc7 100644 --- a/admin/tool/lp/editplan.php +++ b/admin/tool/lp/editplan.php @@ -55,21 +55,12 @@ $PAGE->set_heading($pagetitle); $output = $PAGE->get_renderer('tool_lp'); -$manageplans = has_capability('tool/lp:planmanage', $context); -$owncapabilities = array('tool/lp:plancreateown', 'tool/lp:planmanageown'); -if ($USER->id === $userid && !has_any_capability($owncapabilities, $context) && !$manageplans) { - throw new required_capability_exception($context, 'tool/lp:planmanageown', 'nopermissions', ''); -} else if (!$manageplans) { +// TODO MDL-51646 Handle user creating plan, editing plan, drafts, etc... +if (!\tool_lp\plan::can_manage_user_draft($userid)) { throw new required_capability_exception($context, 'tool/lp:planmanage', 'nopermissions', ''); } -// Passing the templates list to the form. -$templates = array(); -if ($manageplans) { - $templates = \tool_lp\api::list_templates('', '', 0, 0, context_system::instance(), 'children'); -} - -$customdata = array('id' => $id, 'userid' => $userid, 'templates' => $templates); +$customdata = array('id' => $id, 'userid' => $userid); $form = new \tool_lp\form\plan(null, $customdata); if ($form->is_cancelled()) { redirect(new moodle_url('/admin/tool/lp/plans.php?userid=' . $userid)); diff --git a/admin/tool/lp/lang/en/tool_lp.php b/admin/tool/lp/lang/en/tool_lp.php index 79e0f643dbb4a..c9d772f090cb5 100644 --- a/admin/tool/lp/lang/en/tool_lp.php +++ b/admin/tool/lp/lang/en/tool_lp.php @@ -63,8 +63,6 @@ $string['editthisplan'] = 'Edit this learning plan'; $string['errorcannotsetduedateinthepast'] = 'The due date cannot be set in the past.'; $string['errorcannotchangeapastduedate'] = 'The due date has passed, it cannot be changed.'; -$string['erroreditingmodifiedplan'] = 'You can not edit a learning plan modified by another user if you don\'t have -tool/lp:planmanage or tool/lp:planmanageown capabilities.'; $string['errornocompetency'] = '{$a} competency can not be found'; $string['errorplanstatus'] = 'Learning plans \'{$a}\' status unknown'; $string['errorscaleconfiguration'] = 'You must configure the scale by selecting default and proficient values.'; @@ -88,11 +86,14 @@ $string['lp:competencyread'] = 'View competency frameworks'; $string['lp:coursecompetencymanage'] = 'Manage course competencies'; $string['lp:coursecompetencyread'] = 'View course competencies'; -$string['lp:plancreateown'] = 'Create own learning plans'; $string['lp:planmanage'] = 'Manage learning plans'; +$string['lp:planmanagedraft'] = 'Manage draft learning plans'; $string['lp:planmanageown'] = 'Manage own learning plans'; +$string['lp:planmanageowndraft'] = 'Manage own draft learning plans'; $string['lp:planview'] = 'View all learning plans'; +$string['lp:planviewdraft'] = 'View draft learning plans'; $string['lp:planviewown'] = 'View own learning plans'; +$string['lp:planviewowndraft'] = 'View own draft learning plans'; $string['lp:templatemanage'] = 'Manage templates'; $string['lp:templateread'] = 'View template'; $string['managecompetenciesandframeworks'] = 'Manage competencies and frameworks'; diff --git a/admin/tool/lp/lib.php b/admin/tool/lp/lib.php index afe42729ee436..6c5fb921c3bc3 100644 --- a/admin/tool/lp/lib.php +++ b/admin/tool/lp/lib.php @@ -59,12 +59,7 @@ function tool_lp_extend_navigation_course($navigation, $course, $coursecontext) function tool_lp_myprofile_navigation(core_user\output\myprofile\tree $tree, $user, $iscurrentuser, $course) { global $USER; - $context = context_user::instance($USER->id); - if (!$iscurrentuser && !has_capability('tool/lp:planview', $context)) { - return false; - } - - if (!has_capability('tool/lp:planviewown', $context)) { + if (!\tool_lp\plan::can_read_user($user->id)) { return false; } diff --git a/admin/tool/lp/plans.php b/admin/tool/lp/plans.php index ed255dc6a141d..59431aba32874 100644 --- a/admin/tool/lp/plans.php +++ b/admin/tool/lp/plans.php @@ -24,18 +24,12 @@ require_once(__DIR__ . '/../../../config.php'); -$userid = optional_param('userid', false, PARAM_INT); - require_login(null, false); if (isguestuser()) { throw new require_login_exception('Guests are not allowed here.'); } -$iscurrentuser = $userid == $USER->id; -if ($userid === false) { - $userid = $USER->id; -} -$context = context_user::instance($userid); +$userid = optional_param('userid', $USER->id, PARAM_INT); // Check that the user is a valid user. $user = core_user::get_user($userid); @@ -43,12 +37,9 @@ throw new moodle_exception('invaliduser', 'error'); } -if (!has_capability('tool/lp:planview', $context)) { - if ($iscurrentuser) { - require_capability('tool/lp:planviewown', $context); - } else { - throw new required_capability_exception($context, 'tool/lp:planview', 'nopermissions', ''); - } +$context = context_user::instance($userid); +if (!\tool_lp\plan::can_read_user($userid) && !\tool_lp\plan::can_read_user_draft($userid)) { + throw new required_capability_exception($context, 'tool/lp:planview', 'nopermissions', ''); } $url = new moodle_url('/admin/tool/lp/plans.php', array('userid' => $userid)); diff --git a/admin/tool/lp/tests/externallib_test.php b/admin/tool/lp/tests/externallib_test.php index f5c4affef2dfe..d1ca622467d0d 100644 --- a/admin/tool/lp/tests/externallib_test.php +++ b/admin/tool/lp/tests/externallib_test.php @@ -100,6 +100,7 @@ protected function setUp() { unassign_capability('tool/lp:competencymanage', $authrole->id); unassign_capability('tool/lp:competencyread', $authrole->id); unassign_capability('tool/lp:planmanage', $authrole->id); + unassign_capability('tool/lp:planmanagedraft', $authrole->id); unassign_capability('tool/lp:planmanageown', $authrole->id); unassign_capability('tool/lp:planview', $authrole->id); unassign_capability('tool/lp:templatemanage', $authrole->id); @@ -112,6 +113,7 @@ protected function setUp() { assign_capability('tool/lp:competencymanage', CAP_ALLOW, $this->creatorrole, $syscontext->id); assign_capability('tool/lp:competencyread', CAP_ALLOW, $this->userrole, $syscontext->id); assign_capability('tool/lp:planmanage', CAP_ALLOW, $this->creatorrole, $syscontext->id); + assign_capability('tool/lp:planmanagedraft', CAP_ALLOW, $this->creatorrole, $syscontext->id); assign_capability('tool/lp:planmanageown', CAP_ALLOW, $this->creatorrole, $syscontext->id); assign_capability('tool/lp:planview', CAP_ALLOW, $this->creatorrole, $syscontext->id); assign_capability('tool/lp:templatemanage', CAP_ALLOW, $this->creatorrole, $syscontext->id); @@ -1052,7 +1054,7 @@ public function test_create_and_update_plans() { $this->assertEquals('nopermissions', $e->errorcode); } - assign_capability('tool/lp:plancreateown', CAP_ALLOW, $this->userrole, $syscontext->id); + assign_capability('tool/lp:planmanageowndraft', CAP_ALLOW, $this->userrole, $syscontext->id); accesslib_clear_all_caches_for_unit_testing(); $this->setUser($this->user); @@ -1095,7 +1097,7 @@ public function test_create_and_update_plans() { } unassign_capability('tool/lp:planmanageown', $this->userrole, $syscontext->id); - unassign_capability('tool/lp:plancreateown', $this->userrole, $syscontext->id); + unassign_capability('tool/lp:planmanageowndraft', $this->userrole, $syscontext->id); accesslib_clear_all_caches_for_unit_testing(); try { @@ -1133,31 +1135,69 @@ public function test_read_plans() { $plan2['usercanupdate'] = false; $plan3['usercanupdate'] = false; - // You need planmanage, planmanageown or plancreateown to see draft plans. + // Prevent the user from seeing their own non-draft plans. + assign_capability('tool/lp:planviewown', CAP_PROHIBIT, $this->userrole, $syscontext->id, true); + assign_capability('tool/lp:planviewowndraft', CAP_ALLOW, $this->userrole, $syscontext->id, true); + accesslib_clear_all_caches_for_unit_testing(); + + $this->assertEquals((array)$plan1, external::read_plan($plan1['id'])); + try { - external::read_plan($plan1['id']); - $this->fail('Exception expected due to not permissions to read draft plan'); + external::read_plan($plan2['id']); + $this->fail('Exception expected due to not permissions to read plan'); + } catch (moodle_exception $e) { + $this->assertEquals('nopermissions', $e->errorcode); + } + try { + external::read_plan($plan3['id']); + $this->fail('Exception expected due to not permissions to read plan'); } catch (moodle_exception $e) { $this->assertEquals('nopermissions', $e->errorcode); } - $this->assertEquals((Array)$plan2, external::read_plan($plan2['id'])); - $this->assertEquals((Array)$plan3, external::read_plan($plan3['id'])); - assign_capability('tool/lp:plancreateown', CAP_ALLOW, $this->userrole, $syscontext->id); + // Allow user to see their plan. + assign_capability('tool/lp:planviewown', CAP_ALLOW, $this->userrole, $syscontext->id, true); + assign_capability('tool/lp:planmanageowndraft', CAP_PROHIBIT, $this->userrole, $syscontext->id, true); accesslib_clear_all_caches_for_unit_testing(); - $this->assertEquals((Array)$plan1, external::read_plan($plan1['id'])); + $this->assertEquals((array)$plan1, external::read_plan($plan1['id'])); + $this->assertEquals((array)$plan2, external::read_plan($plan2['id'])); + $this->assertEquals((array)$plan3, external::read_plan($plan3['id'])); - assign_capability('tool/lp:planviewown', CAP_PROHIBIT, $this->userrole, $syscontext->id); - unassign_capability('tool/lp:plancreateown', $this->userrole, $syscontext->id); + // Allow use to manage their own draft plan. + assign_capability('tool/lp:planviewown', CAP_PROHIBIT, $this->userrole, $syscontext->id, true); + assign_capability('tool/lp:planmanageown', CAP_PROHIBIT, $this->userrole, $syscontext->id, true); + assign_capability('tool/lp:planmanageowndraft', CAP_ALLOW, $this->userrole, $syscontext->id, true); accesslib_clear_all_caches_for_unit_testing(); + $plan1['usercanupdate'] = true; + $this->assertEquals((array)$plan1, external::read_plan($plan1['id'])); + try { + external::read_plan($plan2['id']); + $this->fail('Exception expected due to not permissions to read plan'); + } catch (moodle_exception $e) { + $this->assertEquals('nopermissions', $e->errorcode); + } try { - $plan = external::read_plan($plan2['id']); - $this->fail('Exception expected due to not permissions to view own plans'); + external::read_plan($plan3['id']); + $this->fail('Exception expected due to not permissions to read plan'); } catch (moodle_exception $e) { $this->assertEquals('nopermissions', $e->errorcode); } + + // Allow use to manage their plan. + assign_capability('tool/lp:planviewown', CAP_PROHIBIT, $this->userrole, $syscontext->id, true); + assign_capability('tool/lp:planmanageown', CAP_PROHIBIT, $this->userrole, $syscontext->id, true); + assign_capability('tool/lp:planmanageowndraft', CAP_PROHIBIT, $this->userrole, $syscontext->id, true); + assign_capability('tool/lp:planmanageown', CAP_ALLOW, $this->userrole, $syscontext->id, true); + accesslib_clear_all_caches_for_unit_testing(); + + $plan1['usercanupdate'] = false; + $plan2['usercanupdate'] = true; + $plan3['usercanupdate'] = true; + $this->assertEquals((array)$plan1, external::read_plan($plan1['id'])); + $this->assertEquals((array)$plan2, external::read_plan($plan2['id'])); + $this->assertEquals((array)$plan3, external::read_plan($plan3['id'])); } public function test_delete_plans() { diff --git a/admin/tool/lp/tests/plan_test.php b/admin/tool/lp/tests/plan_test.php new file mode 100644 index 0000000000000..045de07078bc3 --- /dev/null +++ b/admin/tool/lp/tests/plan_test.php @@ -0,0 +1,253 @@ +. + +/** + * Plan persistent class tests. + * + * @package tool_lp + * @copyright 2015 Frédéric Massart - FMCorz.net + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); +global $CFG; + +/** + * Plan persistent testcase. + * + * @package tool_lp + * @copyright 2015 Frédéric Massart - FMCorz.net + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class tool_lp_plan_testcase extends advanced_testcase { + + public function test_can_manage_user() { + $this->resetAfterTest(true); + + $manage = create_role('Manage', 'manage', 'Plan manager'); + $manageown = create_role('Manageown', 'manageown', 'Own plan manager'); + + $u1 = $this->getDataGenerator()->create_user(); + $u2 = $this->getDataGenerator()->create_user(); + $u3 = $this->getDataGenerator()->create_user(); + + $syscontext = context_system::instance(); + $u1context = context_user::instance($u1->id); + $u2context = context_user::instance($u2->id); + $u3context = context_user::instance($u3->id); + + assign_capability('tool/lp:planmanage', CAP_ALLOW, $manage, $syscontext->id); + assign_capability('tool/lp:planmanageown', CAP_ALLOW, $manageown, $u2context->id); + + role_assign($manage, $u1->id, $syscontext->id); + role_assign($manageown, $u2->id, $syscontext->id); + role_assign($manage, $u3->id, $u2context->id); + accesslib_clear_all_caches_for_unit_testing(); + + $this->setUser($u1); + $this->assertTrue(\tool_lp\plan::can_manage_user($u1->id)); + $this->assertTrue(\tool_lp\plan::can_manage_user($u2->id)); + $this->assertTrue(\tool_lp\plan::can_manage_user($u3->id)); + + $this->setUser($u2); + $this->assertFalse(\tool_lp\plan::can_manage_user($u1->id)); + $this->assertTrue(\tool_lp\plan::can_manage_user($u2->id)); + $this->assertFalse(\tool_lp\plan::can_manage_user($u3->id)); + + $this->setUser($u3); + $this->assertFalse(\tool_lp\plan::can_manage_user($u1->id)); + $this->assertTrue(\tool_lp\plan::can_manage_user($u2->id)); + $this->assertFalse(\tool_lp\plan::can_manage_user($u3->id)); + } + + public function test_can_manage_user_draft() { + $this->resetAfterTest(true); + + $manage = create_role('Manage', 'manage', 'Plan manager'); + $manageown = create_role('Manageown', 'manageown', 'Own plan manager'); + $managedraft = create_role('Managedraft', 'managedraft', 'Draft plan manager'); + $manageowndraft = create_role('Manageowndraft', 'manageowndraft', 'Own draft plan manager'); + + $u1 = $this->getDataGenerator()->create_user(); + $u2 = $this->getDataGenerator()->create_user(); + $u3 = $this->getDataGenerator()->create_user(); + $u4 = $this->getDataGenerator()->create_user(); + $u5 = $this->getDataGenerator()->create_user(); + + $syscontext = context_system::instance(); + $u1context = context_user::instance($u1->id); + $u2context = context_user::instance($u2->id); + $u3context = context_user::instance($u3->id); + $u4context = context_user::instance($u4->id); + $u5context = context_user::instance($u5->id); + + assign_capability('tool/lp:planmanage', CAP_ALLOW, $manage, $syscontext->id); + assign_capability('tool/lp:planmanageown', CAP_ALLOW, $manageown, $syscontext->id); + assign_capability('tool/lp:planmanagedraft', CAP_ALLOW, $managedraft, $syscontext->id); + assign_capability('tool/lp:planmanageowndraft', CAP_ALLOW, $manageowndraft, $syscontext->id); + + role_assign($manage, $u1->id, $syscontext->id); + role_assign($manageown, $u2->id, $syscontext->id); + role_assign($managedraft, $u3->id, $syscontext->id); + role_assign($managedraft, $u4->id, $u2context->id); + role_assign($manageowndraft, $u5->id, $syscontext->id); + accesslib_clear_all_caches_for_unit_testing(); + + $this->setUser($u1); + $this->assertFalse(\tool_lp\plan::can_manage_user_draft($u1->id)); + $this->assertFalse(\tool_lp\plan::can_manage_user_draft($u2->id)); + $this->assertFalse(\tool_lp\plan::can_manage_user_draft($u3->id)); + $this->assertFalse(\tool_lp\plan::can_manage_user_draft($u4->id)); + $this->assertFalse(\tool_lp\plan::can_manage_user_draft($u5->id)); + + $this->setUser($u2); + $this->assertFalse(\tool_lp\plan::can_manage_user_draft($u1->id)); + $this->assertFalse(\tool_lp\plan::can_manage_user_draft($u2->id)); + $this->assertFalse(\tool_lp\plan::can_manage_user_draft($u3->id)); + $this->assertFalse(\tool_lp\plan::can_manage_user_draft($u4->id)); + $this->assertFalse(\tool_lp\plan::can_manage_user_draft($u5->id)); + + $this->setUser($u3); + $this->assertTrue(\tool_lp\plan::can_manage_user_draft($u1->id)); + $this->assertTrue(\tool_lp\plan::can_manage_user_draft($u2->id)); + $this->assertTrue(\tool_lp\plan::can_manage_user_draft($u3->id)); + $this->assertTrue(\tool_lp\plan::can_manage_user_draft($u4->id)); + $this->assertTrue(\tool_lp\plan::can_manage_user_draft($u5->id)); + + $this->setUser($u4); + $this->assertFalse(\tool_lp\plan::can_manage_user_draft($u1->id)); + $this->assertTrue(\tool_lp\plan::can_manage_user_draft($u2->id)); + $this->assertFalse(\tool_lp\plan::can_manage_user_draft($u3->id)); + $this->assertFalse(\tool_lp\plan::can_manage_user_draft($u4->id)); + $this->assertFalse(\tool_lp\plan::can_manage_user_draft($u5->id)); + + $this->setUser($u5); + $this->assertFalse(\tool_lp\plan::can_manage_user_draft($u1->id)); + $this->assertFalse(\tool_lp\plan::can_manage_user_draft($u2->id)); + $this->assertFalse(\tool_lp\plan::can_manage_user_draft($u3->id)); + $this->assertFalse(\tool_lp\plan::can_manage_user_draft($u4->id)); + $this->assertTrue(\tool_lp\plan::can_manage_user_draft($u5->id)); + } + + public function test_can_read_user() { + $this->resetAfterTest(true); + + $read = create_role('Read', 'read', 'Plan reader'); + $readown = create_role('Readown', 'readown', 'Own plan reader'); + + $u1 = $this->getDataGenerator()->create_user(); + $u2 = $this->getDataGenerator()->create_user(); + $u3 = $this->getDataGenerator()->create_user(); + + $syscontext = context_system::instance(); + $u1context = context_user::instance($u1->id); + $u2context = context_user::instance($u2->id); + $u3context = context_user::instance($u3->id); + + assign_capability('tool/lp:planview', CAP_ALLOW, $read, $syscontext->id); + assign_capability('tool/lp:planviewown', CAP_ALLOW, $readown, $u2context->id); + + role_assign($read, $u1->id, $syscontext->id); + role_assign($readown, $u2->id, $syscontext->id); + role_assign($read, $u3->id, $u2context->id); + accesslib_clear_all_caches_for_unit_testing(); + + $this->setUser($u1); + $this->assertTrue(\tool_lp\plan::can_read_user($u1->id)); + $this->assertTrue(\tool_lp\plan::can_read_user($u2->id)); + $this->assertTrue(\tool_lp\plan::can_read_user($u3->id)); + + $this->setUser($u2); + $this->assertFalse(\tool_lp\plan::can_read_user($u1->id)); + $this->assertTrue(\tool_lp\plan::can_read_user($u2->id)); + $this->assertFalse(\tool_lp\plan::can_read_user($u3->id)); + + $this->setUser($u3); + $this->assertFalse(\tool_lp\plan::can_read_user($u1->id)); + $this->assertTrue(\tool_lp\plan::can_read_user($u2->id)); + $this->assertTrue(\tool_lp\plan::can_read_user($u3->id)); // Due to the default capability. + } + + public function test_can_read_user_draft() { + $this->resetAfterTest(true); + + $read = create_role('Read', 'read', 'Plan readr'); + $readown = create_role('Readown', 'readown', 'Own plan readr'); + $readdraft = create_role('Readdraft', 'readdraft', 'Draft plan readr'); + $readowndraft = create_role('Readowndraft', 'readowndraft', 'Own draft plan readr'); + + $u1 = $this->getDataGenerator()->create_user(); + $u2 = $this->getDataGenerator()->create_user(); + $u3 = $this->getDataGenerator()->create_user(); + $u4 = $this->getDataGenerator()->create_user(); + $u5 = $this->getDataGenerator()->create_user(); + + $syscontext = context_system::instance(); + $u1context = context_user::instance($u1->id); + $u2context = context_user::instance($u2->id); + $u3context = context_user::instance($u3->id); + $u4context = context_user::instance($u4->id); + $u5context = context_user::instance($u5->id); + + assign_capability('tool/lp:planview', CAP_ALLOW, $read, $syscontext->id); + assign_capability('tool/lp:planviewown', CAP_ALLOW, $readown, $syscontext->id); + assign_capability('tool/lp:planviewdraft', CAP_ALLOW, $readdraft, $syscontext->id); + assign_capability('tool/lp:planviewowndraft', CAP_ALLOW, $readowndraft, $syscontext->id); + assign_capability('tool/lp:planviewown', CAP_PROHIBIT, $readowndraft, $syscontext->id); + + role_assign($read, $u1->id, $syscontext->id); + role_assign($readown, $u2->id, $syscontext->id); + role_assign($readdraft, $u3->id, $syscontext->id); + role_assign($readdraft, $u4->id, $u2context->id); + role_assign($readowndraft, $u5->id, $syscontext->id); + accesslib_clear_all_caches_for_unit_testing(); + + $this->setUser($u1); + $this->assertFalse(\tool_lp\plan::can_read_user_draft($u1->id)); + $this->assertFalse(\tool_lp\plan::can_read_user_draft($u2->id)); + $this->assertFalse(\tool_lp\plan::can_read_user_draft($u3->id)); + $this->assertFalse(\tool_lp\plan::can_read_user_draft($u4->id)); + $this->assertFalse(\tool_lp\plan::can_read_user_draft($u5->id)); + + $this->setUser($u2); + $this->assertFalse(\tool_lp\plan::can_read_user_draft($u1->id)); + $this->assertFalse(\tool_lp\plan::can_read_user_draft($u2->id)); + $this->assertFalse(\tool_lp\plan::can_read_user_draft($u3->id)); + $this->assertFalse(\tool_lp\plan::can_read_user_draft($u4->id)); + $this->assertFalse(\tool_lp\plan::can_read_user_draft($u5->id)); + + $this->setUser($u3); + $this->assertTrue(\tool_lp\plan::can_read_user_draft($u1->id)); + $this->assertTrue(\tool_lp\plan::can_read_user_draft($u2->id)); + $this->assertTrue(\tool_lp\plan::can_read_user_draft($u3->id)); + $this->assertTrue(\tool_lp\plan::can_read_user_draft($u4->id)); + $this->assertTrue(\tool_lp\plan::can_read_user_draft($u5->id)); + + $this->setUser($u4); + $this->assertFalse(\tool_lp\plan::can_read_user_draft($u1->id)); + $this->assertTrue(\tool_lp\plan::can_read_user_draft($u2->id)); + $this->assertFalse(\tool_lp\plan::can_read_user_draft($u3->id)); + $this->assertFalse(\tool_lp\plan::can_read_user_draft($u4->id)); + $this->assertFalse(\tool_lp\plan::can_read_user_draft($u5->id)); + + $this->setUser($u5); + $this->assertFalse(\tool_lp\plan::can_read_user_draft($u1->id)); + $this->assertFalse(\tool_lp\plan::can_read_user_draft($u2->id)); + $this->assertFalse(\tool_lp\plan::can_read_user_draft($u3->id)); + $this->assertFalse(\tool_lp\plan::can_read_user_draft($u4->id)); + $this->assertTrue(\tool_lp\plan::can_read_user_draft($u5->id)); + } +} diff --git a/admin/tool/lp/version.php b/admin/tool/lp/version.php index 7e18f485a417c..6f6d8b0205b7f 100644 --- a/admin/tool/lp/version.php +++ b/admin/tool/lp/version.php @@ -25,7 +25,7 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2015052420; // The current plugin version (Date: YYYYMMDDXX). +$plugin->version = 2015052422; // The current plugin version (Date: YYYYMMDDXX). $plugin->requires = 2014110400; // Requires this Moodle version. $plugin->component = 'tool_lp'; // Full name of the plugin (used for diagnostics).