From 4af7c9d188da683780aa6494775b97b659e62dda Mon Sep 17 00:00:00 2001 From: "Andrew Davis (andyjdavis)" Date: Fri, 1 Apr 2011 17:20:33 +0800 Subject: [PATCH] MDL-26838 rating: remove logged in users ability to sidestep rating validity checks --- lang/en/rating.php | 1 + lib/outputrenderers.php | 4 ++ mod/data/lib.php | 77 +++++++++++++++++++++++++++++++-- mod/data/view.php | 3 +- mod/forum/lib.php | 95 ++++++++++++++++++++++++++++++++++++++--- mod/forum/user.php | 1 + mod/glossary/lib.php | 63 ++++++++++++++++++++++++--- mod/glossary/view.php | 3 +- rating/lib.php | 68 ++++++++++++++++------------- rating/rate.php | 45 ++++++++++--------- rating/rate_ajax.php | 41 ++++++++++-------- 11 files changed, 314 insertions(+), 87 deletions(-) diff --git a/lang/en/rating.php b/lang/en/rating.php index 4e7936ad959a4..3ab441e44e989 100644 --- a/lang/en/rating.php +++ b/lang/en/rating.php @@ -50,6 +50,7 @@ $string['rate'] = 'Rate'; $string['ratepermissiondenied'] = 'You do not have permission to rate this item'; $string['rating'] = 'Rating'; +$string['ratinginvalid'] = 'Rating is invalid'; $string['ratingtime'] = 'Restrict ratings to items with dates in this range:'; $string['ratings'] = 'Ratings'; $string['rolewarning'] = 'Roles with permission to rate'; diff --git a/lib/outputrenderers.php b/lib/outputrenderers.php index 6d89aba67e6e0..15711eff9bda4 100644 --- a/lib/outputrenderers.php +++ b/lib/outputrenderers.php @@ -1526,6 +1526,10 @@ function render_rating(rating $rating) { $attributes = array('type'=>'hidden', 'class'=>'ratinginput', 'name'=>'contextid', 'value'=>$rating->context->id); $formstart .= html_writer::empty_tag('input', $attributes); + $attributes['name'] = 'component'; + $attributes['value'] = $rating->settings->component; + $formstart .= html_writer::empty_tag('input', $attributes); + $attributes['name'] = 'itemid'; $attributes['value'] = $rating->itemid; $formstart .= html_writer::empty_tag('input', $attributes); diff --git a/mod/data/lib.php b/mod/data/lib.php index 8351cebe419b4..9b5f58d0b1915 100644 --- a/mod/data/lib.php +++ b/mod/data/lib.php @@ -1369,11 +1369,80 @@ function data_rating_permissions($options) { } /** - * Returns the names of the table and columns necessary to check items for ratings - * @return array an array containing the item table, item id and user id columns + * Validates a submitted rating + * @param array $params submitted data + * context => object the context in which the rated items exists [required] + * itemid => int the ID of the object being rated + * scaleid => int the scale from which the user can select a rating. Used for bounds checking. [required] + * rating => int the submitted rating + * rateduserid => int the id of the user whose items have been rated. NOT the user who submitted the ratings. 0 to update all. [required] + * aggregation => int the aggregation method to apply when calculating grades ie RATING_AGGREGATE_AVERAGE [required] + * @return boolean true if the rating is valid */ -function data_rating_item_check_info() { - return array('data_records','id','userid'); +function data_rating_add($params) { + global $DB, $USER; + + if (!array_key_exists('itemid', $params) || !array_key_exists('context', $params)) { + debugging('itemid or context not supplied'); + return false; + } + + $datasql = "SELECT d.id as did, d.course, r.userid as userid, d.approval, r.approved, r.timecreated, d.assesstimestart, d.assesstimefinish, r.groupid + FROM {data_records} r + JOIN {data} d ON r.dataid = d.id + WHERE r.id = :itemid"; + $dataparams = array('itemid'=>$params['itemid']); + if (!$info = $DB->get_record_sql($datasql, $dataparams)) { + //item id doesn't exist + return false; + } + + if ($info->userid == $USER->id) { + //user is attempting to rate their own glossary entry + return false; + } + + if ($info->approval && !$info->approved) { + //database requires approval but this item isnt approved + return false; + } + + //check the item we're rating was created in the assessable time window + if (!empty($info->assesstimestart) && !empty($info->assesstimefinish)) { + if ($info->timecreated < $info->assesstimestart || $info->timecreated > $info->assesstimefinish) { + return false; + } + } + + $dataid = $info->did; + $groupid = $info->groupid; + $courseid = $info->course; + + $cm = get_coursemodule_from_instance('data', $dataid); + if (empty($cm)) { + return false; + } + $context = get_context_instance(CONTEXT_MODULE, $cm->id); + + //if the supplied context doesnt match the item's context + if (empty($context) || $context->id != $params['context']->id) { + return false; + } + + // Make sure groups allow this user to see the item they're rating + $course = $DB->get_record('course', array('id'=>$courseid), '*', MUST_EXIST); + if ($groupid > 0 and $groupmode = groups_get_activity_groupmode($cm, $course)) { // Groups are being used + if (!groups_group_exists($groupid)) { // Can't find group + return false;//something is wrong + } + + if (!groups_is_member($groupid) and !has_capability('moodle/site:accessallgroups', $context)) { + // do not allow rating of posts from other groups when in SEPARATEGROUPS or VISIBLEGROUPS + return false; + } + } + + return true; } diff --git a/mod/data/view.php b/mod/data/view.php index d94443d37b2df..018bf52589418 100644 --- a/mod/data/view.php +++ b/mod/data/view.php @@ -667,6 +667,7 @@ if ($data->assessed!=RATING_AGGREGATE_NONE) { $ratingoptions = new stdclass(); $ratingoptions->context = $context; + $ratingoptions->component = 'mod_data'; $ratingoptions->items = $records; $ratingoptions->aggregate = $data->assessed;//the aggregation method $ratingoptions->scaleid = $data->scale; @@ -674,8 +675,6 @@ $ratingoptions->returnurl = $CFG->wwwroot.'/mod/data/'.$baseurl; $ratingoptions->assesstimestart = $data->assesstimestart; $ratingoptions->assesstimefinish = $data->assesstimefinish; - $ratingoptions->plugintype = 'mod'; - $ratingoptions->pluginname = 'data'; $rm = new rating_manager(); $records = $rm->get_ratings($ratingoptions); diff --git a/mod/forum/lib.php b/mod/forum/lib.php index a2ef362c1af29..9d4be891071e4 100644 --- a/mod/forum/lib.php +++ b/mod/forum/lib.php @@ -3457,11 +3457,93 @@ function forum_rating_permissions($contextid) { } /** - * Returns the names of the table and columns necessary to check items for ratings - * @return array an array containing the item table, item id and user id columns - */ -function forum_rating_item_check_info() { - return array('forum_posts','id','userid'); + * Validates a submitted rating + * @param array $params submitted data + * context => object the context in which the rated items exists [required] + * itemid => int the ID of the object being rated [required] + * scaleid => int the scale from which the user can select a rating. Used for bounds checking. [required] + * rating => int the submitted rating [required] + * rateduserid => int the id of the user whose items have been rated. NOT the user who submitted the ratings. 0 to update all. [required] + * aggregation => int the aggregation method to apply when calculating grades ie RATING_AGGREGATE_AVERAGE [required] + * @return boolean true if the rating is valid + */ +function forum_rating_add($params) { + global $DB, $USER; + + if (!array_key_exists('itemid', $params) || !array_key_exists('context', $params)) { + return false; + } + + $forumsql = "SELECT f.id as fid, f.course, d.id as did, p.userid as userid, p.created, f.assesstimestart, f.assesstimefinish, d.groupid + FROM {forum_posts} p + JOIN {forum_discussions} d ON p.discussion = d.id + JOIN {forum} f ON d.forum = f.id + WHERE p.id = :itemid"; + $forumparams = array('itemid'=>$params['itemid']); + if (!$info = $DB->get_record_sql($forumsql, $forumparams)) { + //item id doesn't exist + return false; + } + + if ($info->userid == $USER->id) { + //user is attempting to rate their own post + return false; + } + + //check the item we're rating was created in the assessable time window + if (!empty($info->assesstimestart) && !empty($info->assesstimefinish)) { + if ($info->timecreated < $info->assesstimestart || $info->timecreated > $info->assesstimefinish) { + return false; + } + } + + $forumid = $info->fid; + $discussionid = $info->did; + $groupid = $info->groupid; + $courseid = $info->course; + + $cm = get_coursemodule_from_instance('forum', $forumid); + if (empty($cm)) { + return false; + } + $context = get_context_instance(CONTEXT_MODULE, $cm->id); + + //if the supplied context doesnt match the item's context + if (empty($context) || $context->id != $params['context']->id) { + return false; + } + + // Make sure groups allow this user to see the item they're rating + $course = $DB->get_record('course', array('id'=>$courseid), '*', MUST_EXIST); + if ($groupid > 0 and $groupmode = groups_get_activity_groupmode($cm, $course)) { // Groups are being used + if (!groups_group_exists($groupid)) { // Can't find group + return false;//something is wrong + } + + if (!groups_is_member($groupid) and !has_capability('moodle/site:accessallgroups', $context)) { + // do not allow rating of posts from other groups when in SEPARATEGROUPS or VISIBLEGROUPS + return false; + } + } + + //need to load the full objects here as ajax scripts don't like + //the debugging messages produced by forum_user_can_see_post() if you just supply IDs + if (!$forum = $DB->get_record('forum',array('id'=>$forumid))) { + return false; + } + if (!$post = $DB->get_record('forum_posts',array('id'=>$params['itemid']))) { + return false; + } + if (!$discussion = $DB->get_record('forum_discussions',array('id'=>$discussionid))) { + return false; + } + + //perform some final capability checks + if( !forum_user_can_see_post($forum, $discussion, $post, $USER, $cm)) { + return false; + } + + return true; } @@ -5333,6 +5415,7 @@ function forum_print_discussion($course, $cm, $forum, $discussion, $post, $mode, if ($forum->assessed!=RATING_AGGREGATE_NONE) { $ratingoptions = new stdclass(); $ratingoptions->context = $modcontext; + $ratingoptions->component = 'mod_forum'; $ratingoptions->items = $posts; $ratingoptions->aggregate = $forum->assessed;//the aggregation method $ratingoptions->scaleid = $forum->scale; @@ -5344,8 +5427,6 @@ function forum_print_discussion($course, $cm, $forum, $discussion, $post, $mode, } $ratingoptions->assesstimestart = $forum->assesstimestart; $ratingoptions->assesstimefinish = $forum->assesstimefinish; - $ratingoptions->plugintype = 'mod'; - $ratingoptions->pluginname = 'forum'; $rm = new rating_manager(); $posts = $rm->get_ratings($ratingoptions); diff --git a/mod/forum/user.php b/mod/forum/user.php index 65760566bca6f..020ba7614e448 100644 --- a/mod/forum/user.php +++ b/mod/forum/user.php @@ -165,6 +165,7 @@ //load ratings if ($forum->assessed!=RATING_AGGREGATE_NONE) { $ratingoptions->context = $forum->context; + $ratingoptions->component = 'mod_forum'; $ratingoptions->items = array($post); $ratingoptions->aggregate = $forum->assessed;//the aggregation method $ratingoptions->scaleid = $forum->scale; diff --git a/mod/glossary/lib.php b/mod/glossary/lib.php index b79d4a63666bd..d3f51ce460d74 100644 --- a/mod/glossary/lib.php +++ b/mod/glossary/lib.php @@ -471,11 +471,64 @@ function glossary_rating_permissions($options) { } /** - * Returns the names of the table and columns necessary to check items for ratings - * @return array an array containing the item table, item id and user id columns - */ -function glossary_rating_item_check_info() { - return array('glossary_entries','id','userid'); + * Validates a submitted rating + * @param array $params submitted data + * context => object the context in which the rated items exists [required] + * itemid => int the ID of the object being rated + * scaleid => int the scale from which the user can select a rating. Used for bounds checking. [required] + * rating => int the submitted rating + * rateduserid => int the id of the user whose items have been rated. NOT the user who submitted the ratings. 0 to update all. [required] + * aggregation => int the aggregation method to apply when calculating grades ie RATING_AGGREGATE_AVERAGE [optional] + * @return boolean true if the rating is valid + */ +function glossary_rating_add($params) { + global $DB, $USER; + + if (!array_key_exists('itemid', $params) || !array_key_exists('context', $params)) { + return false; + } + + $glossarysql = "SELECT g.id as gid, e.userid as userid, e.approved, e.timecreated, g.assesstimestart, g.assesstimefinish + FROM {glossary_entries} e + JOIN {glossary} g ON e.glossaryid = g.id + WHERE e.id = :itemid"; + $glossaryparams = array('itemid'=>$params['itemid']); + if (!$info = $DB->get_record_sql($glossarysql, $glossaryparams)) { + //item id doesn't exist + return false; + } + + if ($info->userid == $USER->id) { + //user is attempting to rate their own glossary entry + return false; + } + + if (!$info->approved) { + //item isnt approved + return false; + } + + //check the item we're rating was created in the assessable time window + if (!empty($info->assesstimestart) && !empty($info->assesstimefinish)) { + if ($info->timecreated < $info->assesstimestart || $info->timecreated > $info->assesstimefinish) { + return false; + } + } + + $glossaryid = $info->gid; + + $cm = get_coursemodule_from_instance('glossary', $glossaryid); + if (empty($cm)) { + return false; + } + $context = get_context_instance(CONTEXT_MODULE, $cm->id); + + //if the supplied context doesnt match the item's context + if (empty($context) || $context->id != $params['context']->id) { + return false; + } + + return true; } /** diff --git a/mod/glossary/view.php b/mod/glossary/view.php index 236a52557dce1..3369fd9fe6a85 100644 --- a/mod/glossary/view.php +++ b/mod/glossary/view.php @@ -396,6 +396,7 @@ if ($glossary->assessed!=RATING_AGGREGATE_NONE) { $ratingoptions = new stdclass(); $ratingoptions->context = $context; + $ratingoptions->component = 'mod_glossary'; $ratingoptions->items = $allentries; $ratingoptions->aggregate = $glossary->assessed;//the aggregation method $ratingoptions->scaleid = $glossary->scale; @@ -403,8 +404,6 @@ $ratingoptions->returnurl = $CFG->wwwroot.'/mod/glossary/view.php?id='.$cm->id; $ratingoptions->assesstimestart = $glossary->assesstimestart; $ratingoptions->assesstimefinish = $glossary->assesstimefinish; - $ratingoptions->plugintype = 'mod'; - $ratingoptions->pluginname = 'glossary'; $rm = new rating_manager(); $allentries = $rm->get_ratings($ratingoptions); diff --git a/rating/lib.php b/rating/lib.php index 29313e2786a05..8c545ca6fb2e3 100644 --- a/rating/lib.php +++ b/rating/lib.php @@ -50,6 +50,12 @@ class rating implements renderable { */ public $context; + /** + * The component using ratings. For example "mod_forum" + * @var component + */ + public $component; + /** * The id of the item (forum post, glossary item etc) being rated * @var int @@ -78,6 +84,7 @@ class rating implements renderable { * Constructor. * @param object $options { * context => context context to use for the rating [required] + * component => component using ratings ie mod_forum [required] * itemid => int the id of the associated item (forum post, glossary item etc) [required] * scaleid => int The scale in use when the rating was submitted [required] * userid => int The id of the user who submitted the rating [required] @@ -85,6 +92,7 @@ class rating implements renderable { */ public function __construct($options) { $this->context = $options->context; + $this->component = $options->component; $this->itemid = $options->itemid; $this->scaleid = $options->scaleid; $this->userid = $options->userid; @@ -107,6 +115,7 @@ public function update_rating($rating) { $ratingoptions = new stdclass(); $ratingoptions->context = $this->context; + $ratingoptions->component = $this->component; $ratingoptions->items = $items; $ratingoptions->aggregate = RATING_AGGREGATE_AVERAGE;//we dont actually care what aggregation method is applied $ratingoptions->scaleid = $this->scaleid; @@ -236,6 +245,7 @@ public function get_all_ratings_for_item($options) { * Rating objects are available at $item->rating * @param object $options { * context => context the context in which the ratings exists [required] + * component => the component name ie mod_forum [required] * items => array an array of items such as forum posts or glossary items. They must have an 'id' member ie $items[0]->id[required] * aggregate => int what aggregation method should be applied. RATING_AGGREGATE_AVERAGE, RATING_AGGREGATE_MAXIMUM etc [required] * scaleid => int the scale from which the user can select a rating [required] @@ -243,8 +253,6 @@ public function get_all_ratings_for_item($options) { * returnurl => string the url to return the user to after submitting a rating. Can be left null for ajax requests [optional] * assesstimestart => int only allow rating of items created after this timestamp [optional] * assesstimefinish => int only allow rating of items created before this timestamp [optional] - * plugintype => string plugin type ie 'mod' Used to find the permissions callback [optional] - * pluginname => string plugin name ie 'forum' Used to find the permissions callback [optional] * @return array the array of items with their ratings attached at $items[0]->rating */ public function get_ratings($options) { @@ -335,6 +343,7 @@ public function get_ratings($options) { //should $settings and $settings->permissions be declared as proper classes? $settings = new stdclass(); //settings that are common to all ratings objects in this context + $settings->component =$options->component; $settings->scale = $scaleobj; //the scale to use now $settings->aggregationmethod = $options->aggregate; if( !empty($options->returnurl) ) { @@ -357,9 +366,7 @@ public function get_ratings($options) { $settings->permissions->rate = has_capability('moodle/rating:rate',$options->context);//can submit ratings //check module capabilities (mostly for backwards compatability with old modules that previously implemented their own ratings) - $plugintype = !empty($options->plugintype) ? $options->plugintype : null; - $pluginname = !empty($options->pluginname) ? $options->pluginname : null; - $pluginpermissionsarray = $this->get_plugin_permissions_array($options->context->id, $plugintype, $pluginname); + $pluginpermissionsarray = $this->get_plugin_permissions_array($options->context->id, $options->component); $settings->pluginpermissions = new stdclass(); $settings->pluginpermissions->view = $pluginpermissionsarray['view']; @@ -370,6 +377,7 @@ public function get_ratings($options) { $rating = null; $ratingoptions = new stdclass(); $ratingoptions->context = $options->context;//context is common to all ratings in the set + $ratingoptions->component = $options->component; foreach($options->items as $item) { $rating = null; //match the item with its corresponding rating @@ -601,15 +609,15 @@ public function get_aggregation_method($aggregate) { /** * Looks for a callback and retrieves permissions from the plugin whose items are being rated * @param int $contextid The current context id - * @param string plugintype the type of plugin ie 'mod' - * @param string pluginname the name of the plugin ie 'forum' + * @param string component the name of the component that is using ratings ie 'mod_forum' * @return array rating related permissions */ - public function get_plugin_permissions_array($contextid, $plugintype=null, $pluginname=null) { + public function get_plugin_permissions_array($contextid, $component=null) { $pluginpermissionsarray = null; $defaultpluginpermissions = array('rate'=>true,'view'=>true,'viewany'=>true,'viewall'=>true);//all true == rely on system level permissions if no plugin callback is defined - if ($plugintype && $pluginname) { - $pluginpermissionsarray = plugin_callback($plugintype, $pluginname, 'rating', 'permissions', array($contextid), $defaultpluginpermissions); + if (!empty($component)) { + list($type, $name) = normalize_component($component); + $pluginpermissionsarray = plugin_callback($type, $name, 'rating', 'permissions', array($contextid), $defaultpluginpermissions); } else { $pluginpermissionsarray = $defaultpluginpermissions; } @@ -617,27 +625,29 @@ public function get_plugin_permissions_array($contextid, $plugintype=null, $plug } /** - * Checks if the item exists and is NOT owned by the current owner. Uses a callback to find out what table to look in. - * @param string plugintype the type of plugin ie 'mod' - * @param string pluginname the name of the plugin ie 'forum' - * @return boolean True if the callback doesn't exist. True if the item exists and doesn't belong to the current user. False otherwise. - */ - public function check_item_and_owner($plugintype, $pluginname, $itemid) { - global $DB, $USER; - - list($tablename,$itemidcol,$useridcol) = plugin_callback($plugintype, $pluginname, 'rating', 'item_check_info'); + * Validates a submitted rating + * @param array $params submitted data + * context => object the context in which the rated items exists [required] + * itemid => int the ID of the object being rated + * scaleid => int the scale from which the user can select a rating. Used for bounds checking. [required] + * rating => int the submitted rating + * rateduserid => int the id of the user whose items have been rated. NOT the user who submitted the ratings. 0 to update all. [required] + * aggregation => int the aggregation method to apply when calculating grades ie RATING_AGGREGATE_AVERAGE [optional] + * @return boolean true if the rating is valid + */ + public function check_rating_is_valid($component, $params) { + list($plugintype, $pluginname) = normalize_component($component); - if (!empty($tablename)) { - $item = $DB->get_record($tablename, array($itemidcol=>$itemid), $useridcol); - if ($item) { - if ($item->userid!=$USER->id) { - return true; - } - } + //this looks for a function like forum_rating_is_valid() in mod_forum lib.php + //wrapping the params array in another array as call_user_func_array() expands arrays into multiple arguments + $isvalid = plugin_callback($plugintype, $pluginname, 'rating', 'add', array($params), null); - return false;//item doesn't exist or belongs to the current user - } else { - return true;//callback doesn't exist + //if null then the callback doesn't exist + if ($isvalid === null) { + $isvalid = false; + debugging('plugin rating_add() function not found'); } + + return $isvalid; } }//end rating_manager class definition diff --git a/rating/rate.php b/rating/rate.php index e0417a4292c99..ab7ccaa33eb31 100644 --- a/rating/rate.php +++ b/rating/rate.php @@ -30,6 +30,7 @@ require_once('lib.php'); $contextid = required_param('contextid', PARAM_INT); +$component = required_param('component', PARAM_ALPHAEXT); $itemid = required_param('itemid', PARAM_INT); $scaleid = required_param('scaleid', PARAM_INT); $userrating = required_param('rating', PARAM_INT); @@ -42,8 +43,10 @@ require_login($course, false, $cm); $contextid = null;//now we have a context object throw away the id from the user +$PAGE->set_context($context); +$PAGE->set_url('/rating/rate.php', array('contextid'=>$context->id)); -if (!confirm_sesskey() || $USER->id==$rateduserid) { +if (!confirm_sesskey() || $USER->id==$rateduserid || !has_capability('moodle/rating:rate',$context)) { echo $OUTPUT->header(); echo get_string('ratepermissiondenied', 'rating'); echo $OUTPUT->footer(); @@ -53,32 +56,33 @@ $rm = new rating_manager(); //check the module rating permissions -$pluginrateallowed = true; -$pluginpermissionsarray = null; -if ($context->contextlevel==CONTEXT_MODULE) { - $plugintype = 'mod'; - $pluginname = $cm->modname; - $pluginpermissionsarray = $rm->get_plugin_permissions_array($context->id, $plugintype, $pluginname); - $pluginrateallowed = $pluginpermissionsarray['rate']; - - if ($pluginrateallowed) { - //check the item exists and isn't owned by the current user - $pluginrateallowed = $rm->check_item_and_owner($plugintype, $pluginname, $itemid); - } -} +//doing this check here rather than within rating_manager::get_ratings() so we can return a json error response +$pluginpermissionsarray = $rm->get_plugin_permissions_array($context->id, $component); -if (!$pluginrateallowed || !has_capability('moodle/rating:rate',$context)) { - echo $OUTPUT->header(); - echo get_string('ratepermissiondenied', 'rating'); - echo $OUTPUT->footer(); +if (!$pluginpermissionsarray['rate']) { + $result->error = get_string('ratepermissiondenied', 'rating'); + echo json_encode($result); die(); +} else { + $params = array( + 'context' => $context, + 'itemid' => $itemid, + 'scaleid' => $scaleid, + 'rating' => $userrating, + 'rateduserid' => $rateduserid); + + if (!$rm->check_rating_is_valid($component, $params)) { + echo $OUTPUT->header(); + echo get_string('ratinginvalid', 'rating'); + echo $OUTPUT->footer(); + die(); + } } -$PAGE->set_url('/lib/rate.php', array('contextid'=>$context->id)); - if ($userrating != RATING_UNSET_RATING) { $ratingoptions = new stdClass(); $ratingoptions->context = $context; + $ratingoptions->component = $component; $ratingoptions->itemid = $itemid; $ratingoptions->scaleid = $scaleid; $ratingoptions->userid = $USER->id; @@ -88,6 +92,7 @@ } else { //delete the rating if the user set to Rate... $options = new stdClass(); $options->contextid = $context->id; + $options->component = $component; $options->userid = $USER->id; $options->itemid = $itemid; diff --git a/rating/rate_ajax.php b/rating/rate_ajax.php index a1a2cb704c7bc..9e13ed831885d 100644 --- a/rating/rate_ajax.php +++ b/rating/rate_ajax.php @@ -32,6 +32,7 @@ require_once('lib.php'); $contextid = required_param('contextid', PARAM_INT); +$component = required_param('component', PARAM_ALPHAEXT); $itemid = required_param('itemid', PARAM_INT); $scaleid = required_param('scaleid', PARAM_INT); $userrating = required_param('rating', PARAM_INT); @@ -51,8 +52,10 @@ require_login($course, false, $cm); $contextid = null;//now we have a context object throw away the id from the user +$PAGE->set_context($context); +$PAGE->set_url('/rating/rate_ajax.php', array('contextid'=>$context->id)); -if (!confirm_sesskey() || $USER->id==$rateduserid) { +if (!confirm_sesskey() || $USER->id==$rateduserid || !has_capability('moodle/rating:rate',$context)) { echo $OUTPUT->header(); echo get_string('ratepermissiondenied', 'rating'); echo $OUTPUT->footer(); @@ -62,32 +65,33 @@ $rm = new rating_manager(); //check the module rating permissions -//doing this check here rather than within rating_manager::get_ratings so we can return a json error response -$pluginrateallowed = true; -$pluginpermissionsarray = null; -if ($context->contextlevel==CONTEXT_MODULE) { - $plugintype = 'mod'; - $pluginname = $cm->modname; - $pluginpermissionsarray = $rm->get_plugin_permissions_array($context->id, $plugintype, $pluginname); - $pluginrateallowed = $pluginpermissionsarray['rate']; - - if ($pluginrateallowed) { - //check the item exists and isn't owned by the current user - $pluginrateallowed = $rm->check_item_and_owner($plugintype, $pluginname, $itemid); - } -} +//doing this check here rather than within rating_manager::get_ratings() so we can return a json error response +$pluginpermissionsarray = $rm->get_plugin_permissions_array($context->id, $component); -if (!$pluginrateallowed || !has_capability('moodle/rating:rate',$context)) { +if (!$pluginpermissionsarray['rate']) { $result->error = get_string('ratepermissiondenied', 'rating'); echo json_encode($result); die(); +} else { + $params = array( + 'context' => $context, + 'itemid' => $itemid, + 'scaleid' => $scaleid, + 'rating' => $userrating, + 'rateduserid' => $rateduserid, + 'aggregation' => $aggregationmethod); + + if (!$rm->check_rating_is_valid($component, $params)) { + $result->error = get_string('ratinginvalid', 'rating'); + echo json_encode($result); + die(); + } } -$PAGE->set_url('/lib/rate.php', array('contextid'=>$context->id)); - //rating options used to update the rating then retrieve the aggregate $ratingoptions = new stdClass(); $ratingoptions->context = $context; +$ratingoptions->component = $component; $ratingoptions->itemid = $itemid; $ratingoptions->scaleid = $scaleid; $ratingoptions->userid = $USER->id; @@ -98,6 +102,7 @@ } else { //delete the rating if the user set to Rate... $options = new stdClass(); $options->contextid = $context->id; + $options->component = $component; $options->userid = $USER->id; $options->itemid = $itemid;