MDL-50782 Ajax: No require_login for all ajax webservice calls
authorDamyon Wiese <damyon@moodle.com>
Mon, 13 Jul 2015 04:21:33 +0000 (12:21 +0800)
committerDamyon Wiese <damyon@moodle.com>
Tue, 8 Sep 2015 01:16:58 +0000 (09:16 +0800)
Some webservice functions need to be available without a login, e.g.
fetching strings and templates.

External functions must call validate_context if they require a valid login etc.

Added a new parameter to services.php: "loginrequired". Default is true.

lang/en/webservice.php
lib/ajax/service.php
lib/db/services.php
lib/externallib.php
webservice/renderer.php

index 36079b6..82d7588 100644 (file)
@@ -117,6 +117,7 @@ $string['iprestriction'] = 'IP restriction';
 $string['iprestriction_help'] = 'The user will need to call the web service from the listed IPs (separated by commas).';
 $string['key'] = 'Key';
 $string['keyshelp'] = 'The keys are used to access your Moodle account from external applications.';
+$string['loginrequired'] = 'Restricted to logged in users';
 $string['manageprotocols'] = 'Manage protocols';
 $string['managetokens'] = 'Manage tokens';
 $string['missingcaps'] = 'Missing capabilities';
index 938ffa8..166b8a8 100644 (file)
@@ -32,7 +32,6 @@ define('AJAX_SCRIPT', true);
 require_once(dirname(__FILE__) . '/../../config.php');
 require_once($CFG->libdir . '/externallib.php');
 
-require_login(null, true, null, true, true);
 require_sesskey();
 
 $rawjson = file_get_contents('php://input');
@@ -58,6 +57,14 @@ foreach ($requests as $request) {
             throw new moodle_exception('servicenotavailable', 'webservice');
         }
 
+        // Do not allow access to write or delete webservices as a public user.
+        if ($externalfunctioninfo->loginrequired) {
+            if (!isloggedin()) {
+                error_log('This external function is not available to public users. Failed to call "' . $methodname . '"');
+                throw new moodle_exception('servicenotavailable', 'webservice');
+            }
+        }
+
         // Validate params, this also sorts the params properly, we need the correct order in the next part.
         $callable = array($externalfunctioninfo->classname, 'validate_parameters');
         $params = call_user_func($callable,
index 70187da..415f0fd 100644 (file)
@@ -975,6 +975,7 @@ $functions = array(
         'classpath'   => 'lib/external/externallib.php',
         'description' => 'Return a translated string - similar to core get_string() call',
         'type'        => 'read',
+        'loginrequired' => false
     ),
 
     'core_get_strings' => array(
@@ -983,6 +984,7 @@ $functions = array(
         'classpath'   => 'lib/external/externallib.php',
         'description' => 'Return some translated strings - like several core get_string() calls',
         'type'        => 'read',
+        'loginrequired' => false
     ),
 
     'core_get_component_strings' => array(
@@ -992,6 +994,7 @@ $functions = array(
         'description' => 'Return all raw strings (with {$a->xxx}) for a specific component
             - similar to core get_component_strings() call',
         'type'        => 'read',
+        'loginrequired' => false
     ),
 
 
@@ -1029,7 +1032,8 @@ $functions = array(
         'classname'   => 'core\output\external',
         'methodname'  => 'load_template',
         'description' => 'Load a template for a renderable',
-        'type'        => 'read'
+        'type'        => 'read',
+        'loginrequired' => false
     ),
 
     // Completion related functions.
index 035ba63..d392cf1 100644 (file)
@@ -112,6 +112,14 @@ function external_function_info($function, $strictness=MUST_EXIST) {
         if (isset($functions[$function->name]['testclientpath'])) {
             $function->testclientpath = $functions[$function->name]['testclientpath'];
         }
+        if (isset($functions[$function->name]['type'])) {
+            $function->type = $functions[$function->name]['type'];
+        }
+        if (isset($functions[$function->name]['loginrequired'])) {
+            $function->loginrequired = $functions[$function->name]['loginrequired'];
+        } else {
+            $function->loginrequired = true;
+        }
     }
 
     return $function;
index c04825a..cc4b685 100644 (file)
@@ -812,6 +812,13 @@ EOF;
             }
             $documentationhtml .= $br . $br;
 
+            // Login required info.
+            $documentationhtml .= html_writer::start_tag('span', array('style' => 'color:#EA33A6'));
+            $documentationhtml .= get_string('loginrequired', 'webservice') . $br;
+            $documentationhtml .= html_writer::end_tag('span');
+            $documentationhtml .= $description->loginrequired ? get_string('yes') : get_string('no');
+            $documentationhtml .= $br . $br;
+
             // Ajax info.
             $documentationhtml .= html_writer::start_tag('span', array('style' => 'color:#EA33A6'));
             $documentationhtml .= get_string('callablefromajax', 'webservice') . $br;