MDL-21579 "Implement session token for embedded application" implemented a second...
[moodle.git] / webservice / wsdoc.php
blob6e5853fd737541e3d1aca207e99c2a8ccbc68b91
1 <?php
2 ///////////////////////////////////////////////////////////////////////////
3 // //
4 // This file is part of Moodle - http://moodle.org/ //
5 // Moodle - Modular Object-Oriented Dynamic Learning Environment //
6 // //
7 // Moodle is free software: you can redistribute it and/or modify //
8 // it under the terms of the GNU General Public License as published by //
9 // the Free Software Foundation, either version 3 of the License, or //
10 // (at your option) any later version. //
11 // //
12 // Moodle is distributed in the hope that it will be useful, //
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of //
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
15 // GNU General Public License for more details. //
16 // //
17 // You should have received a copy of the GNU General Public License //
18 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. //
19 // //
20 ///////////////////////////////////////////////////////////////////////////
23 // disable moodle specific debug messages and any errors in output
24 define('NO_MOODLE_COOKIES', true);
26 require_once('../config.php');
27 require_once('lib.php');
30 /**
31 * This class generate the web service documentation specific to one
32 * web service user
33 * @package webservice
34 * @copyright 2009 Moodle Pty Ltd (http://moodle.com)
35 * @author Jerome Mouneyrac
36 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
38 class webservice_documentation_generator {
40 /** @property array all external function description*/
41 protected $functions;
43 /** @property string $username name of local user */
44 protected $username = null;
46 /** @property string $password password of the local user */
47 protected $password = null;
49 /** @property string $token token of the local user */
50 protected $token = null;
52 /** @property object $webserviceuser authenticated web service user */
53 protected $webserviceuser = null;
55 /**
56 * Contructor
58 public function __construct() {
59 $this->functionsdescriptions = array();
60 $this->functions = array();
63 /**
64 * Run the documentation generation
65 * @return void
67 public function run() {
69 // init all properties from the request data
70 $this->get_authentication_parameters();
72 // this sets up $this->webserviceuser
73 try {
74 $this->authenticate_user();
75 } catch(moodle_exception $e) {
76 $errormessage = $e->debuginfo;
77 $displayloginpage = true;
80 if (!empty($displayloginpage)){
81 $this->display_login_page_html($errormessage);
82 } else {
83 // make a descriptions list of all function that user is allowed to excecute
84 $this->generate_documentation();
86 //finally display the documentation
87 $this->display_documentation_html();
90 die;
94 ///////////////////////////
95 /////// CLASS METHODS /////
96 ///////////////////////////
98 /**
99 * This method parses the $_REQUEST superglobal and looks for
100 * the following information:
101 * user authentication - username+password
102 * @return void
104 protected function get_authentication_parameters() {
105 if (isset($_REQUEST['wsusername'])) {
106 $this->username = $_REQUEST['wsusername'];
108 if (isset($_REQUEST['wspassword'])) {
109 $this->password = $_REQUEST['wspassword'];
111 if (isset($_REQUEST['token'])) {
112 $this->token = $_REQUEST['token'];
117 * Generate the documentation specific to the auhenticated webservice user
118 * @return void
120 protected function generate_documentation() {
121 global $DB;
123 /// first of all get a complete list of services user is allowed to access
124 $params = array();
125 $wscond1 = '';
126 $wscond2 = '';
128 // make sure the function is listed in at least one service user is allowed to use
129 // allow access only if:
130 // 1/ entry in the external_services_users table if required
131 // 2/ validuntil not reached
132 // 3/ has capability if specified in service desc
133 // 4/ iprestriction
135 $sql = "SELECT s.*, NULL AS iprestriction
136 FROM {external_services} s
137 JOIN {external_services_functions} sf ON (sf.externalserviceid = s.id AND s.restrictedusers = 0)
138 WHERE s.enabled = 1 $wscond1
140 UNION
142 SELECT s.*, su.iprestriction
143 FROM {external_services} s
144 JOIN {external_services_functions} sf ON (sf.externalserviceid = s.id AND s.restrictedusers = 1)
145 JOIN {external_services_users} su ON (su.externalserviceid = s.id AND su.userid = :userid)
146 WHERE s.enabled = 1 AND su.validuntil IS NULL OR su.validuntil < :now $wscond2";
148 $params = array_merge($params, array('userid'=>$this->webserviceuser->id, 'now'=>time()));
150 $serviceids = array();
151 $rs = $DB->get_recordset_sql($sql, $params);
153 // make sure user may access at least one service
154 $allowed = false;
155 foreach ($rs as $service) {
156 if (isset($serviceids[$service->id])) {
157 continue;
159 if ($service->requiredcapability and !has_capability($service->requiredcapability, $this->restricted_context)) {
160 continue; // cap required, sorry
162 $serviceids[$service->id] = $service->id;
164 $rs->close();
166 // now get the list of all functions
167 if ($serviceids) {
168 list($serviceids, $params) = $DB->get_in_or_equal($serviceids);
169 $sql = "SELECT f.*
170 FROM {external_functions} f
171 WHERE f.name IN (SELECT sf.functionname
172 FROM {external_services_functions} sf
173 WHERE sf.externalserviceid $serviceids)";
174 $functions = $DB->get_records_sql($sql, $params);
175 } else {
176 $functions = array();
179 foreach ($functions as $function) {
180 $this->functions[$function->name] = external_function_info($function);
185 * Authenticate user using username+password
186 * This function sets up $this->webserviceuser.
187 * called into the Moodle header
188 * @return void
190 protected function authenticate_user() {
191 global $CFG, $DB;
193 if (!NO_MOODLE_COOKIES) {
194 throw new coding_exception('Cookies must be disabled!');
197 if (!$this->token) {
198 if (!is_enabled_auth('webservice')) {
199 throw new webservice_access_exception(get_string('wsauthnotenabled', 'webservice'));
202 if (!$auth = get_auth_plugin('webservice')) {
203 throw new webservice_access_exception(get_string('wsauthmissing', 'webservice'));
206 if (!$this->username) {
207 throw new webservice_access_exception(get_string('missingusername', 'webservice'));
210 if (!$this->password) {
211 throw new webservice_access_exception(get_string('missingpassword', 'webservice'));
214 if (!$auth->user_login_webservice($this->username, $this->password)) {
215 throw new webservice_access_exception(get_string('wrongusernamepassword', 'webservice'));
218 $this->webserviceuser = $DB->get_record('user', array('username'=>$this->username, 'mnethostid'=>$CFG->mnet_localhost_id, 'deleted'=>0), '*', MUST_EXIST);
219 } else {
221 if (!$token = $DB->get_record('external_tokens', array('token'=>$this->token, 'tokentype'=>EXTERNAL_TOKEN_PERMANENT))) {
222 // log failed login attempts
223 throw new webservice_access_exception(get_string('invalidtoken', 'webservice'));
226 if ($token->validuntil and $token->validuntil < time()) {
227 throw new webservice_access_exception(get_string('invalidtimedtoken', 'webservice'));
230 if ($token->iprestriction and !address_in_subnet(getremoteaddr(), $token->iprestriction)) {
231 throw new webservice_access_exception(get_string('invalidiptoken', 'webservice'));
234 $this->webserviceuser = $DB->get_record('user', array('id'=>$token->userid, 'deleted'=>0), '*', MUST_EXIST);
236 // log token access
237 $DB->set_field('external_tokens', 'lastaccess', time(), array('id'=>$token->id));
244 ////////////////////////////////////////////////
245 ///// DISPLAY METHODS /////
246 ////////////////////////////////////////////////
249 * Generate and display the documentation
251 protected function display_documentation_html() {
252 global $PAGE, $OUTPUT, $SITE, $CFG;
254 $PAGE->set_url('/webservice/wsdoc');
255 $PAGE->set_docs_path('');
256 $PAGE->set_title($SITE->fullname." ".get_string('wsdocumentation', 'webservice'));
257 $PAGE->set_heading($SITE->fullname." ".get_string('wsdocumentation', 'webservice'));
258 $PAGE->set_pagelayout('popup');
259 $PAGE->set_pagetype('webservice-doc-generator');
261 echo $OUTPUT->header();
263 $activatedprotocol = array();
264 $activatedprotocol['rest'] = webservice_protocol_is_enabled('rest');
265 $activatedprotocol['xmlrpc'] = webservice_protocol_is_enabled('xmlrpc');
266 $renderer = $PAGE->get_renderer('core', 'webservice');
267 /// Check if we are in printable mode
268 $printableformat = false;
269 if (isset($_REQUEST['print'])) {
270 $printableformat = $_REQUEST['print'];
273 $authparams = array();
274 if (empty($this->token)) {
275 $authparams['wsusername'] = $this->username;
276 $authparams['wspassword'] = $this->password;
277 } else {
278 $authparams['wsusername'] = $this->webserviceuser->username;
279 $authparams['token'] = $this->token;
282 echo $renderer->documentation_html($this->functions, $printableformat, $activatedprotocol, $authparams);
284 /// trigger browser print operation
285 if (!empty($printableformat)) {
286 $PAGE->requires->js_function_call('window.print', array());
289 echo $OUTPUT->footer();
294 * Display login page to the web service documentation
295 * @global object $PAGE
296 * @global object $OUTPUT
297 * @global object $SITE
298 * @global object $CFG
299 * @param string $errormessage error message displayed if wrong login
301 protected function display_login_page_html($errormessage) {
302 global $PAGE, $OUTPUT, $SITE, $CFG;
304 $PAGE->set_url('/webservice/wsdoc');
305 $PAGE->set_docs_path('');
306 $PAGE->set_title($SITE->fullname." ".get_string('wsdocumentation', 'webservice'));
307 $PAGE->set_heading($SITE->fullname." ".get_string('wsdocumentation', 'webservice'));
308 $PAGE->set_pagelayout('popup');
309 $PAGE->set_pagetype('webservice-doc-generator-login');
311 echo $OUTPUT->header();
313 $renderer = $PAGE->get_renderer('core', 'webservice');
314 echo $renderer->login_page_html($errormessage);
316 echo $OUTPUT->footer();
323 ///////////////////////////
324 /////// RUN THE SCRIPT ////
325 ///////////////////////////
327 if (empty($CFG->enablewsdocumentation)) {
328 echo get_string('wsdocumentationdisable', 'webservice');
329 die;
332 //run the documentation generator
333 $generator = new webservice_documentation_generator();
334 $generator->run();
335 die;