MDL-50783 Ajax: Configure how to call a webservice through db/service.php
authorDamyon Wiese <damyon@moodle.com>
Thu, 16 Jul 2015 06:14:33 +0000 (14:14 +0800)
committerDamyon Wiese <damyon@moodle.com>
Mon, 14 Sep 2015 07:10:21 +0000 (15:10 +0800)
Now the db/service.php array can contain these extra keys to provide information
on how a webservice may be called:

    'ajax' => true (Default is false)

Replaces the xx_is_allowed_from_ajax callback.

    'loginrequired' => false (Default is true)

Means that this webservice can be called through lib/ajax/service-nosession.php
which sets NO_MOODLE_COOKIES to true (faster). This is only safe for webservices returning
static public data (e.g. get_string).

19 files changed:
admin/tool/templatelibrary/amd/build/display.min.js
admin/tool/templatelibrary/amd/build/search.min.js
admin/tool/templatelibrary/amd/src/display.js
admin/tool/templatelibrary/amd/src/search.js
admin/tool/templatelibrary/classes/external.php
admin/tool/templatelibrary/db/services.php
lib/ajax/service-nologin.php [new file with mode: 0644]
lib/ajax/service.php
lib/amd/build/ajax.min.js
lib/amd/build/str.min.js
lib/amd/build/templates.min.js
lib/amd/src/ajax.js
lib/amd/src/str.js
lib/amd/src/templates.js
lib/classes/output/external.php
lib/db/services.php
lib/external/externallib.php
lib/externallib.php
tag/classes/external.php

index a5bf8ab..49c0afe 100644 (file)
Binary files a/admin/tool/templatelibrary/amd/build/display.min.js and b/admin/tool/templatelibrary/amd/build/display.min.js differ
index 062e585..869d27b 100644 (file)
Binary files a/admin/tool/templatelibrary/amd/build/search.min.js and b/admin/tool/templatelibrary/amd/build/search.min.js differ
index 1585a18..bb2f77a 100644 (file)
@@ -133,7 +133,7 @@ define(['jquery', 'core/ajax', 'core/log', 'core/notification', 'core/templates'
                     component: component,
                     template: name
             }
-        }]);
+        }], true, false);
 
         // When returns a new promise that is resolved when all the passed in promises are resolved.
         // The arguments to the done become the values of each resolved promise.
index d4eefe6..efefb26 100644 (file)
@@ -53,7 +53,7 @@ define(['jquery', 'core/ajax', 'core/log', 'core/notification', 'core/templates'
               args: { component: componentStr, search: searchStr },
               done: reloadListTemplate,
               fail: notification.exception }
-        ]);
+        ], true, false);
     };
 
     var throttle = null;
index 100172b..be583a2 100644 (file)
@@ -63,14 +63,6 @@ class external extends external_api {
         return new external_function_parameters($params);
     }
 
-    /**
-     * Expose to AJAX
-     * @return boolean
-     */
-    public static function list_templates_is_allowed_from_ajax() {
-        return true;
-    }
-
     /**
      * Loads the list of templates.
      * @param string $component Limit the search to a component.
@@ -108,16 +100,6 @@ class external extends external_api {
             );
     }
 
-    /**
-     * Can this function be called directly from ajax?
-     *
-     * @return boolean
-     * @since Moodle 2.9
-     */
-    public static function load_canonical_template_is_allowed_from_ajax() {
-        return true;
-    }
-
     /**
      * Return a mustache template.
      * Note - this function differs from the function core_output_load_template
index c1a9479..9dda647 100644 (file)
@@ -32,12 +32,16 @@ $functions = array(
         'description' => 'List/search templates by component.',
         'type'        => 'read',
         'capabilities'=> '',
+        'ajax'        => true,
+        'loginrequired' => false,
     ),
     'tool_templatelibrary_load_canonical_template' => array(
         'classname'   => 'tool_templatelibrary\external',
         'methodname'  => 'load_canonical_template',
         'description' => 'Load a canonical template by name (not the theme overidden one).',
-        'type'        => 'read'
+        'type'        => 'read',
+        'ajax'        => true,
+        'loginrequired' => false,
     ),
 
 );
diff --git a/lib/ajax/service-nologin.php b/lib/ajax/service-nologin.php
new file mode 100644 (file)
index 0000000..7120ade
--- /dev/null
@@ -0,0 +1,31 @@
+<?php
+// This file is part of Moodle - http://moodle.org/
+//
+// Moodle is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// Moodle is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
+
+/**
+ * This file is used to call any registered externallib function in Moodle.
+ *
+ * It will process more than one request and return more than one response if required.
+ * It is recommended to add webservice functions and re-use this script instead of
+ * writing any new custom ajax scripts.
+ *
+ * @since Moodle 2.9
+ * @package core
+ * @copyright 2015 Damyon Wiese
+ * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+define('NO_MOODLE_COOKIES', true);
+require_once('service.php');
index 166b8a8..366f1ad 100644 (file)
@@ -32,8 +32,6 @@ define('AJAX_SCRIPT', true);
 require_once(dirname(__FILE__) . '/../../config.php');
 require_once($CFG->libdir . '/externallib.php');
 
-require_sesskey();
-
 $rawjson = file_get_contents('php://input');
 
 $requests = json_decode($rawjson, true);
@@ -54,6 +52,7 @@ foreach ($requests as $request) {
         $externalfunctioninfo = external_function_info($methodname);
 
         if (!$externalfunctioninfo->allowed_from_ajax) {
+            error_log('This external function is not available to ajax. Failed to call "' . $methodname . '"');
             throw new moodle_exception('servicenotavailable', 'webservice');
         }
 
@@ -62,6 +61,8 @@ foreach ($requests as $request) {
             if (!isloggedin()) {
                 error_log('This external function is not available to public users. Failed to call "' . $methodname . '"');
                 throw new moodle_exception('servicenotavailable', 'webservice');
+            } else {
+                require_sesskey();
             }
         }
 
index 2a80dfe..7ed899b 100644 (file)
Binary files a/lib/amd/build/ajax.min.js and b/lib/amd/build/ajax.min.js differ
index ace0e93..33d26c9 100644 (file)
Binary files a/lib/amd/build/str.min.js and b/lib/amd/build/str.min.js differ
index ed4aa32..c75432b 100644 (file)
Binary files a/lib/amd/build/templates.min.js and b/lib/amd/build/templates.min.js differ
index 2966cb4..6b497c3 100644 (file)
@@ -104,9 +104,13 @@ define(['jquery', 'core/config'], function($, config) {
          *                   can be attached to the promises returned by this function.
          * @param {Boolean} async Optional, defaults to true.
          *                  If false - this function will not return until the promises are resolved.
+         * @param {Boolean} loginrequired Optional, defaults to true.
+         *                  If false - this function will call the faster nologin ajax script - but
+         *                  will fail unless all functions have been marked as 'loginrequired' => false
+         *                  in services.php
          * @return {Promise[]} Array of promises that will be resolved when the ajax call returns.
          */
-        call: function(requests, async) {
+        call: function(requests, async, loginrequired) {
             var ajaxRequestData = [],
                 i,
                 promises = [];
@@ -144,15 +148,20 @@ define(['jquery', 'core/config'], function($, config) {
                 async: async
             };
 
+            var script = config.wwwroot + '/lib/ajax/service.php?sesskey=' + config.sesskey;
+            if (!loginrequired) {
+                script = config.wwwroot + '/lib/ajax/service-nologin.php?sesskey=' + config.sesskey;
+            }
+
             // Jquery deprecated done and fail with async=false so we need to do this 2 ways.
             if (async) {
-                $.ajax(config.wwwroot + '/lib/ajax/service.php?sesskey=' + config.sesskey, settings)
+                $.ajax(script, settings)
                     .done(requestSuccess)
                     .fail(requestFail);
             } else {
                 settings.success = requestSuccess;
                 settings.error = requestFail;
-                $.ajax(config.wwwroot + '/lib/ajax/service.php?sesskey=' + config.sesskey, settings);
+                $.ajax(script, settings);
             }
 
             return promises;
index d66c164..76830d3 100644 (file)
@@ -140,7 +140,7 @@ define(['jquery', 'core/ajax', 'core/localstorage'], function($, ajax, storage)
                     });
                 }
 
-                var deferreds = ajax.call(ajaxrequests);
+                var deferreds = ajax.call(ajaxrequests, true, false);
                 $.when.apply(null, deferreds).done(
                     function() {
                         // Turn the list of arguments (unknown length) into a real array.
index 93ed7d1..a152e03 100644 (file)
@@ -310,7 +310,7 @@ define([ 'core/mustache',
                 template: name,
                 themename: currentThemeName
             }
-        }], async);
+        }], async, false);
 
         promises[0].done(
             function (templateSource) {
index 17b1ca7..a76248e 100644 (file)
@@ -55,16 +55,6 @@ class external extends external_api {
             );
     }
 
-    /**
-     * Can this function be called directly from ajax?
-     *
-     * @return boolean
-     * @since Moodle 2.9
-     */
-    public static function load_template_is_allowed_from_ajax() {
-        return true;
-    }
-
     /**
      * Return a mustache template, and all the strings it requires.
      *
index 415f0fd..5c2ad25 100644 (file)
@@ -975,7 +975,8 @@ $functions = array(
         'classpath'   => 'lib/external/externallib.php',
         'description' => 'Return a translated string - similar to core get_string() call',
         'type'        => 'read',
-        'loginrequired' => false
+        'loginrequired' => false,
+        'ajax'        => true,
     ),
 
     'core_get_strings' => array(
@@ -984,7 +985,8 @@ $functions = array(
         'classpath'   => 'lib/external/externallib.php',
         'description' => 'Return some translated strings - like several core get_string() calls',
         'type'        => 'read',
-        'loginrequired' => false
+        'loginrequired' => false,
+        'ajax'        => true,
     ),
 
     'core_get_component_strings' => array(
@@ -994,7 +996,8 @@ $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
+        'loginrequired' => false,
+        'ajax'        => true,
     ),
 
 
@@ -1033,7 +1036,8 @@ $functions = array(
         'methodname'  => 'load_template',
         'description' => 'Load a template for a renderable',
         'type'        => 'read',
-        'loginrequired' => false
+        'loginrequired' => false,
+        'ajax'        => true,
     ),
 
     // Completion related functions.
@@ -1075,6 +1079,7 @@ $functions = array(
         'methodname'  => 'update_tags',
         'description' => 'Updates tags',
         'type'        => 'write',
+        'ajax'        => true
     ),
 
     'core_tag_get_tags' => array(
@@ -1082,6 +1087,7 @@ $functions = array(
         'methodname'  => 'get_tags',
         'description' => 'Gets tags by their ids',
         'type'        => 'read',
+        'ajax'        => true
     ),
 
 );
index 1909c2f..a0526c5 100644 (file)
@@ -77,16 +77,6 @@ class core_external extends external_api {
         return $strparams;
     }
 
-    /**
-     * Can this function be called directly from ajax?
-     *
-     * @return boolean
-     * @since Moodle 2.9
-     */
-    public static function get_string_is_allowed_from_ajax() {
-        return true;
-    }
-
     /**
      * Returns description of get_string parameters
      *
@@ -163,17 +153,6 @@ class core_external extends external_api {
         );
     }
 
-    /**
-     * Can this function be called directly from ajax?
-     *
-     * @return boolean
-     * @since Moodle 2.9
-     */
-    public static function get_strings_is_allowed_from_ajax() {
-        return true;
-    }
-
-
     /**
      * Return multiple call to core get_string()
      *
@@ -237,16 +216,6 @@ class core_external extends external_api {
         );
     }
 
-    /**
-     * Can this function be called directly from ajax?
-     *
-     * @return boolean
-     * @since Moodle 2.9
-     */
-    public static function get_component_strings_is_allowed_from_ajax() {
-        return true;
-    }
-
     /**
      * Return all lang strings of a component - call to core get_component_strings().
      *
index d392cf1..951f215 100644 (file)
@@ -115,6 +115,9 @@ function external_function_info($function, $strictness=MUST_EXIST) {
         if (isset($functions[$function->name]['type'])) {
             $function->type = $functions[$function->name]['type'];
         }
+        if (isset($functions[$function->name]['ajax'])) {
+            $function->allowed_from_ajax = $functions[$function->name]['ajax'];
+        }
         if (isset($functions[$function->name]['loginrequired'])) {
             $function->loginrequired = $functions[$function->name]['loginrequired'];
         } else {
index ee8f1a0..2bb564f 100644 (file)
@@ -59,15 +59,6 @@ class core_tag_external extends external_api {
         );
     }
 
-    /**
-     * Expose to AJAX
-     *
-     * @return boolean
-     */
-    public static function update_tags_is_allowed_from_ajax() {
-        return true;
-    }
-
     /**
      * Update tags
      *
@@ -194,15 +185,6 @@ class core_tag_external extends external_api {
         );
     }
 
-    /**
-     * Expose to AJAX
-     *
-     * @return boolean
-     */
-    public static function get_tags_is_allowed_from_ajax() {
-        return true;
-    }
-
     /**
      * Get tags by their ids
      *
@@ -281,4 +263,4 @@ class core_tag_external extends external_api {
             )
         );
     }
-}
\ No newline at end of file
+}