MDL-39990 wiki: more detailed validation of view/edit access rights
authorMarina Glancy <marina@moodle.com>
Fri, 7 Feb 2014 05:54:43 +0000 (13:54 +0800)
committerDan Poltawski <dan@moodle.com>
Mon, 3 Mar 2014 06:45:03 +0000 (14:45 +0800)
19 files changed:
mod/wiki/admin.php
mod/wiki/comments.php
mod/wiki/create_form.php
mod/wiki/diff.php
mod/wiki/edit.php
mod/wiki/editcomments.php
mod/wiki/files.php
mod/wiki/filesedit.php
mod/wiki/history.php
mod/wiki/lib.php
mod/wiki/locallib.php
mod/wiki/lock.php
mod/wiki/map.php
mod/wiki/overridelocks.php
mod/wiki/prettyview.php
mod/wiki/restoreversion.php
mod/wiki/search.php
mod/wiki/view.php
mod/wiki/viewversion.php

index a9b511f..a99605c 100644 (file)
@@ -55,6 +55,9 @@ if (!$wiki = wiki_get_wiki($subwiki->wikiid)) {
 
 require_login($course, true, $cm);
 
+if (!wiki_user_can_view($subwiki, $wiki)) {
+    print_error('cannotviewpage', 'wiki');
+}
 
 $context = context_module::instance($cm->id);
 require_capability('mod/wiki:managewiki', $context);
index 1fa1e5a..1029ba2 100644 (file)
@@ -59,6 +59,10 @@ $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST)
 
 require_login($course, true, $cm);
 
+if (!wiki_user_can_view($subwiki, $wiki)) {
+    print_error('cannotviewpage', 'wiki');
+}
+
 // Trigger comment viewed event.
 $event = \mod_wiki\event\comments_viewed::create(
         array(
index 556023d..3553f45 100644 (file)
@@ -77,6 +77,7 @@ class mod_wiki_create_form extends moodleform {
                 $groupname = $groupinfo[$groupid];
                 $mform->addElement('static', 'groupdesciption', get_string('group'), $groupname);
                 $mform->addElement('hidden', 'groupinfo', $groupid);
+                $mform->setType('groupinfo', PARAM_INT);
             }
         }
 
index 4e3e29a..4b99ff5 100644 (file)
@@ -68,6 +68,10 @@ if ($compare >= $comparewith) {
 
 require_login($course, true, $cm);
 
+if (!wiki_user_can_view($subwiki, $wiki)) {
+    print_error('cannotviewpage', 'wiki');
+}
+
 $wikipage = new page_wiki_diff($wiki, $subwiki, $cm);
 
 $wikipage->set_page($page);
index 82969a1..12f62bc 100644 (file)
@@ -75,7 +75,10 @@ if (!empty($section) && !$sectioncontent = wiki_get_section_page($page, $section
 require_login($course, true, $cm);
 
 $context = context_module::instance($cm->id);
-require_capability('mod/wiki:editpage', $context);
+
+if (!wiki_user_can_edit($subwiki)) {
+    print_error('cannoteditpage', 'wiki');
+}
 
 if ($option == get_string('save', 'wiki')) {
     if (!confirm_sesskey()) {
index 5bdbad7..03229d3 100644 (file)
@@ -54,6 +54,10 @@ if (!$wiki = wiki_get_wiki($subwiki->wikiid)) {
 }
 require_login($course, true, $cm);
 
+if (!wiki_user_can_view($subwiki, $wiki)) {
+    print_error('cannotviewpage', 'wiki');
+}
+
 $editcomments = new page_wiki_editcomment($wiki, $subwiki, $cm);
 $comment = new stdClass();
 if ($action == 'edit') {
index b1642dc..91a6df4 100644 (file)
@@ -78,7 +78,11 @@ $context = context_module::instance($cm->id);
 
 $PAGE->set_url('/mod/wiki/files.php', array('pageid'=>$pageid));
 require_login($course, true, $cm);
-$PAGE->set_context($context);
+
+if (!wiki_user_can_view($subwiki, $wiki)) {
+    print_error('cannotviewfiles', 'wiki');
+}
+
 $PAGE->set_title(get_string('wikifiles', 'wiki'));
 $PAGE->set_heading($course->fullname);
 $PAGE->navbar->add(format_string(get_string('wikifiles', 'wiki')));
@@ -95,12 +99,8 @@ echo $renderer->tabs($page, $tabitems, $options);
 
 
 echo $OUTPUT->box_start('generalbox');
-if (has_capability('mod/wiki:viewpage', $context)) {
-    echo $renderer->wiki_print_subwiki_selector($PAGE->activityrecord, $subwiki, $page, 'files');
-    echo $renderer->wiki_files_tree($context, $subwiki);
-} else {
-    echo $OUTPUT->notification(get_string('cannotviewfiles', 'wiki'));
-}
+echo $renderer->wiki_print_subwiki_selector($PAGE->activityrecord, $subwiki, $page, 'files');
+echo $renderer->wiki_files_tree($context, $subwiki);
 echo $OUTPUT->box_end();
 
 if (has_capability('mod/wiki:managefiles', $context)) {
index f94f2c3..9713d2a 100644 (file)
@@ -53,6 +53,10 @@ $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST)
 $context = context_module::instance($cm->id);
 
 require_login($course, true, $cm);
+
+if (!wiki_user_can_view($subwiki, $wiki)) {
+    print_error('cannotviewpage', 'wiki');
+}
 require_capability('mod/wiki:managefiles', $context);
 
 if (empty($returnurl)) {
index a3662c8..d6f8697 100644 (file)
@@ -59,10 +59,13 @@ if (!$cm = get_coursemodule_from_instance('wiki', $wiki->id)) {
 $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST);
 
 require_login($course, true, $cm);
-$context = context_module::instance($cm->id);
-require_capability('mod/wiki:viewpage', $context);
+
+if (!wiki_user_can_view($subwiki, $wiki)) {
+    print_error('cannotviewpage', 'wiki');
+}
 
 // Trigger history viewed event.
+$context = context_module::instance($cm->id);
 $event = \mod_wiki\event\page_history_viewed::create(
         array(
             'context' => $context,
index 5ea72e3..a3b9da4 100644 (file)
@@ -280,7 +280,7 @@ function wiki_print_recent_activity($course, $viewfullnames, $timestart) {
     global $CFG, $DB, $OUTPUT;
 
     $usernamefields = get_all_user_name_fields(true, 'u');
-    $sql = "SELECT p.*, w.id as wikiid, sw.groupid, $usernamefields
+    $sql = "SELECT p.id, p.timemodified, p.subwikiid, sw.wikiid, w.wikimode, sw.userid, sw.groupid, $usernamefields
             FROM {wiki_pages} p
                 JOIN {wiki_subwikis} sw ON sw.id = p.subwikiid
                 JOIN {wiki} w ON w.id = sw.wikiid
@@ -290,48 +290,25 @@ function wiki_print_recent_activity($course, $viewfullnames, $timestart) {
     if (!$pages = $DB->get_records_sql($sql, array($timestart, $course->id))) {
         return false;
     }
-    $modinfo = get_fast_modinfo($course);
+    require_once($CFG->dirroot . "/mod/wiki/locallib.php");
 
     $wikis = array();
 
     $modinfo = get_fast_modinfo($course);
 
+    $subwikivisible = array();
     foreach ($pages as $page) {
-        if (!isset($modinfo->instances['wiki'][$page->wikiid])) {
-            // not visible
-            continue;
+        if (!isset($subwikivisible[$page->subwikiid])) {
+            $subwiki = (object)array('id' => $page->subwikiid, 'wikiid' => $page->wikiid,
+                'groupid' => $page->groupid, 'userid' => $page->userid);
+            $wiki = (object)array('id' => $page->wikiid, 'course' => $course->id, 'wikimode' => $page->wikimode);
+            $subwikivisible[$page->subwikiid] = wiki_user_can_view($subwiki, $wiki);
         }
-        $cm = $modinfo->instances['wiki'][$page->wikiid];
-        if (!$cm->uservisible) {
-            continue;
-        }
-        $context = context_module::instance($cm->id);
-
-        if (!has_capability('mod/wiki:viewpage', $context)) {
-            continue;
-        }
-
-        $groupmode = groups_get_activity_groupmode($cm, $course);
-
-        if ($groupmode) {
-            if ($groupmode == SEPARATEGROUPS and !has_capability('mod/wiki:managewiki', $context)) {
-                // separate mode
-                if (isguestuser()) {
-                    // shortcut
-                    continue;
-                }
-
-                if (is_null($modinfo->groups)) {
-                    $modinfo->groups = groups_get_user_groups($course->id); // load all my groups and cache it in modinfo
-                    }
-
-                if (!in_array($page->groupid, $modinfo->groups[0])) {
-                    continue;
-                }
-            }
+        if ($subwikivisible[$page->subwikiid]) {
+            $wikis[] = $page;
         }
-        $wikis[] = $page;
     }
+    unset($subwikivisible);
     unset($pages);
 
     if (!$wikis) {
index 8cb555d..533776e 100644 (file)
@@ -755,13 +755,27 @@ function wiki_parser_get_token($markup, $name) {
 /**
  * Checks if current user can view a subwiki
  *
- * @param $subwiki
+ * @param stdClass $subwiki usually record from {wiki_subwikis}. Must contain fields 'wikiid', 'groupid', 'userid'.
+ *     If it also contains fields 'course' and 'groupmode' from table {wiki} it will save extra DB query.
+ * @param stdClass $wiki optional wiki object if known
+ * @return bool
  */
-function wiki_user_can_view($subwiki) {
+function wiki_user_can_view($subwiki, $wiki = null) {
     global $USER;
 
-    $wiki = wiki_get_wiki($subwiki->wikiid);
-    $cm = get_coursemodule_from_instance('wiki', $wiki->id);
+    if (empty($wiki) || $wiki->id != $subwiki->wikiid) {
+        $wiki = wiki_get_wiki($subwiki->wikiid);
+    }
+    $modinfo = get_fast_modinfo($wiki->course);
+    if (!isset($modinfo->instances['wiki'][$subwiki->wikiid])) {
+        // Module does not exist.
+        return false;
+    }
+    $cm = $modinfo->instances['wiki'][$subwiki->wikiid];
+    if (!$cm->uservisible) {
+        // The whole module is not visible to the current user.
+        return false;
+    }
     $context = context_module::instance($cm->id);
 
     // Working depending on activity groupmode
@@ -803,7 +817,7 @@ function wiki_user_can_view($subwiki) {
         //      Each person owns a wiki.
         if ($wiki->wikimode == 'collaborative' || $wiki->wikimode == 'individual') {
             // Only members of subwiki group could view that wiki
-            if (groups_is_member($subwiki->groupid)) {
+            if (in_array($subwiki->groupid, $modinfo->get_groups($cm->groupingid))) {
                 // Only view capability needed
                 return has_capability('mod/wiki:viewpage', $context);
 
index a0764b6..4955a7b 100644 (file)
@@ -68,8 +68,9 @@ if (!empty($section) && !$sectioncontent = wiki_get_section_page($page, $section
 
 require_login($course, false, $cm);
 
-$context = context_module::instance($cm->id);
-require_capability('mod/wiki:editpage', $context);
+if (!wiki_user_can_edit($subwiki)) {
+    print_error('cannoteditpage', 'wiki');
+}
 
 $wikipage = new page_wiki_lock($wiki, $subwiki, $cm);
 $wikipage->set_page($page);
index 8ef6ec6..1a4951a 100644 (file)
@@ -54,11 +54,14 @@ if (!$wiki = wiki_get_wiki($subwiki->wikiid)) {
 }
 
 require_login($course, true, $cm);
-$context = context_module::instance($cm->id);
-require_capability('mod/wiki:viewpage', $context);
+
+if (!wiki_user_can_view($subwiki, $wiki)) {
+    print_error('cannotviewpage', 'wiki');
+}
 
 $wikipage = new page_wiki_map($wiki, $subwiki, $cm);
 
+$context = context_module::instance($cm->id);
 $event = \mod_wiki\event\page_map_viewed::create(
         array(
             'context' => $context,
index 98baecf..ea02d48 100644 (file)
@@ -64,12 +64,13 @@ if (!empty($section) && !$sectioncontent = wiki_get_section_page($page, $section
 
 require_login($course, true, $cm);
 
-$context = context_module::instance($cm->id);
-require_capability('mod/wiki:overridelock', $context);
+require_sesskey();
 
-if (!confirm_sesskey()) {
-    print_error(get_string('invalidsesskey', 'wiki'));
+if (!wiki_user_can_view($subwiki, $wiki)) {
+    print_error('cannotviewpage', 'wiki');
 }
+$context = context_module::instance($cm->id);
+require_capability('mod/wiki:overridelock', $context);
 
 $wikipage = new page_wiki_overridelocks($wiki, $subwiki, $cm);
 $wikipage->set_page($page);
index 148fab6..e496b6c 100644 (file)
@@ -53,13 +53,15 @@ if (!$wiki = wiki_get_wiki($subwiki->wikiid)) {
 
 require_login($course, true, $cm);
 
-$context = context_module::instance($cm->id);
-require_capability('mod/wiki:viewpage', $context);
+if (!wiki_user_can_view($subwiki, $wiki)) {
+    print_error('cannotviewpage', 'wiki');
+}
 
 $wikipage = new page_wiki_prettyview($wiki, $subwiki, $cm);
 
 $wikipage->set_page($page);
 
+$context = context_module::instance($cm->id);
 $event = \mod_wiki\event\page_viewed::create(
         array(
             'context' => $context,
index 92b6500..71245ef 100644 (file)
@@ -60,6 +60,10 @@ $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST)
 
 require_login($course, true, $cm);
 
+if (!wiki_user_can_view($subwiki)) {
+    print_error('cannotviewpage', 'wiki');
+}
+
 if ($confirm) {
     if (!confirm_sesskey()) {
         print_error(get_string('invalidsesskey', 'wiki'));
index 33e5453..76d2c7c 100644 (file)
@@ -45,12 +45,16 @@ if (!$gid = groups_get_activity_group($cm)) {
     $gid = 0;
 }
 if (!$subwiki = wiki_get_subwiki_by_group($cm->instance, $gid)) {
-    return false;
+    print_error('incorrectsubwikiid', 'wiki');
 }
 if (!$wiki = wiki_get_wiki($subwiki->wikiid)) {
     print_error('incorrectwikiid', 'wiki');
 }
 
+if (!wiki_user_can_view($subwiki, $wiki)) {
+    print_error('cannotviewfiles', 'wiki');
+}
+
 $wikipage = new page_wiki_search($wiki, $subwiki, $cm);
 
 $wikipage->set_search_string($search, $searchcontent);
index e2051e1..8d5f512 100644 (file)
@@ -271,8 +271,9 @@ if ($id) {
     print_error('incorrectparameters');
 }
 
-$context = context_module::instance($cm->id);
-require_capability('mod/wiki:viewpage', $context);
+if (!wiki_user_can_view($subwiki, $wiki)) {
+    print_error('cannotviewpage', 'wiki');
+}
 
 // Update 'viewed' state if required by completion system
 require_once($CFG->libdir . '/completionlib.php');
@@ -288,6 +289,7 @@ $wikipage = new page_wiki_view($wiki, $subwiki, $cm);
 $wikipage->set_gid($currentgroup);
 $wikipage->set_page($page);
 
+$context = context_module::instance($cm->id);
 if($pageid) {
     $event = \mod_wiki\event\page_viewed::create(
             array(
index 255c915..d034ef0 100644 (file)
@@ -60,6 +60,10 @@ $course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST)
 
 require_login($course, true, $cm);
 
+if (!wiki_user_can_view($subwiki, $wiki)) {
+    print_error('cannotviewpage', 'wiki');
+}
+
 $wikipage = new page_wiki_viewversion($wiki, $subwiki, $cm);
 
 $wikipage->set_page($page);