MDL-16094 File storage conversion Quiz and Questions
[moodle.git] / webservice / wsdoc.php
CommitLineData
fbe52a39 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///////////////////////////////////////////////////////////////////////////
21
cc93c7da 22
d4c6ef70 23// disable moodle specific debug messages and any errors in output
d4c6ef70 24define('NO_MOODLE_COOKIES', true);
25
fbe52a39 26require_once('../config.php');
27require_once('lib.php');
472f56d9 28
fbe52a39 29
d4c6ef70 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
37 */
38class webservice_documentation_generator {
39
abf7dc44 40 /** @property array all external function description*/
d4c6ef70 41 protected $functions;
42
43 /** @property string $username name of local user */
44 protected $username = null;
472f56d9 45
d4c6ef70 46 /** @property string $password password of the local user */
47 protected $password = null;
fbe52a39 48
85b4c447 49 /** @property string $token token of the local user */
50 protected $token = null;
51
abf7dc44 52 /** @property object $webserviceuser authenticated web service user */
53 protected $webserviceuser = null;
54
d4c6ef70 55 /**
56 * Contructor
57 */
58 public function __construct() {
59 $this->functionsdescriptions = array();
60 $this->functions = array();
61 }
fbe52a39 62
d4c6ef70 63 /**
64 * Run the documentation generation
d4c6ef70 65 * @return void
66 */
67 public function run() {
472f56d9 68
d4c6ef70 69 // init all properties from the request data
70 $this->get_authentication_parameters();
472f56d9 71
abf7dc44 72 // this sets up $this->webserviceuser
d4c6ef70 73 try {
74 $this->authenticate_user();
75 } catch(moodle_exception $e) {
76 $errormessage = $e->debuginfo;
77 $displayloginpage = true;
78 }
472f56d9 79
d4c6ef70 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();
472f56d9 85
d4c6ef70 86 //finally display the documentation
87 $this->display_documentation_html();
88 }
472f56d9 89
d4c6ef70 90 die;
91 }
472f56d9 92
472f56d9 93
d4c6ef70 94///////////////////////////
95/////// CLASS METHODS /////
96///////////////////////////
fbe52a39 97
d4c6ef70 98 /**
99 * This method parses the $_REQUEST superglobal and looks for
100 * the following information:
101 * user authentication - username+password
102 * @return void
103 */
104 protected function get_authentication_parameters() {
105 if (isset($_REQUEST['wsusername'])) {
106 $this->username = $_REQUEST['wsusername'];
107 }
108 if (isset($_REQUEST['wspassword'])) {
109 $this->password = $_REQUEST['wspassword'];
110 }
85b4c447 111 if (isset($_REQUEST['token'])) {
112 $this->token = $_REQUEST['token'];
113 }
fbe52a39 114 }
fbe52a39 115
d4c6ef70 116 /**
117 * Generate the documentation specific to the auhenticated webservice user
118 * @return void
119 */
120 protected function generate_documentation() {
abf7dc44 121 global $DB;
fbe52a39 122
d4c6ef70 123 /// first of all get a complete list of services user is allowed to access
124 $params = array();
125 $wscond1 = '';
126 $wscond2 = '';
127
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
134
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
139
140 UNION
141
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";
147
abf7dc44 148 $params = array_merge($params, array('userid'=>$this->webserviceuser->id, 'now'=>time()));
d4c6ef70 149
150 $serviceids = array();
151 $rs = $DB->get_recordset_sql($sql, $params);
152
153 // make sure user may access at least one service
d4c6ef70 154 $allowed = false;
155 foreach ($rs as $service) {
156 if (isset($serviceids[$service->id])) {
157 continue;
158 }
159 if ($service->requiredcapability and !has_capability($service->requiredcapability, $this->restricted_context)) {
160 continue; // cap required, sorry
161 }
d4c6ef70 162 $serviceids[$service->id] = $service->id;
163 }
164 $rs->close();
165
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();
177 }
178
179 foreach ($functions as $function) {
180 $this->functions[$function->name] = external_function_info($function);
181 }
182 }
183
184 /**
185 * Authenticate user using username+password
abf7dc44 186 * This function sets up $this->webserviceuser.
d4c6ef70 187 * called into the Moodle header
188 * @return void
189 */
190 protected function authenticate_user() {
abf7dc44 191 global $CFG, $DB;
d4c6ef70 192
193 if (!NO_MOODLE_COOKIES) {
194 throw new coding_exception('Cookies must be disabled!');
195 }
196
0991947b 197 if (!$this->token) {
198 if (!is_enabled_auth('webservice')) {
199 throw new webservice_access_exception(get_string('wsauthnotenabled', 'webservice'));
200 }
d4c6ef70 201
0991947b 202 if (!$auth = get_auth_plugin('webservice')) {
203 throw new webservice_access_exception(get_string('wsauthmissing', 'webservice'));
204 }
2f67a9b3 205
85b4c447 206 if (!$this->username) {
207 throw new webservice_access_exception(get_string('missingusername', 'webservice'));
208 }
d4c6ef70 209
85b4c447 210 if (!$this->password) {
211 throw new webservice_access_exception(get_string('missingpassword', 'webservice'));
212 }
d4c6ef70 213
85b4c447 214 if (!$auth->user_login_webservice($this->username, $this->password)) {
215 throw new webservice_access_exception(get_string('wrongusernamepassword', 'webservice'));
216 }
d4c6ef70 217
85b4c447 218 $this->webserviceuser = $DB->get_record('user', array('username'=>$this->username, 'mnethostid'=>$CFG->mnet_localhost_id, 'deleted'=>0), '*', MUST_EXIST);
219 } else {
0991947b 220
85b4c447 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'));
224 }
d4c6ef70 225
85b4c447 226 if ($token->validuntil and $token->validuntil < time()) {
227 throw new webservice_access_exception(get_string('invalidtimedtoken', 'webservice'));
228 }
229
230 if ($token->iprestriction and !address_in_subnet(getremoteaddr(), $token->iprestriction)) {
231 throw new webservice_access_exception(get_string('invalidiptoken', 'webservice'));
232 }
233
234 $this->webserviceuser = $DB->get_record('user', array('id'=>$token->userid, 'deleted'=>0), '*', MUST_EXIST);
235
236 // log token access
237 $DB->set_field('external_tokens', 'lastaccess', time(), array('id'=>$token->id));
238 }
239
8725605d 240
d4c6ef70 241
242 }
243
244////////////////////////////////////////////////
245///// DISPLAY METHODS /////
246////////////////////////////////////////////////
247
248 /**
249 * Generate and display the documentation
250 */
251 protected function display_documentation_html() {
7886efc4 252 global $PAGE, $OUTPUT, $SITE, $CFG;
d4c6ef70 253
8725605d 254 $PAGE->set_context(get_context_instance(CONTEXT_SYSTEM));
d4c6ef70 255 $PAGE->set_url('/webservice/wsdoc');
256 $PAGE->set_docs_path('');
257 $PAGE->set_title($SITE->fullname." ".get_string('wsdocumentation', 'webservice'));
258 $PAGE->set_heading($SITE->fullname." ".get_string('wsdocumentation', 'webservice'));
78946b9b 259 $PAGE->set_pagelayout('popup');
7886efc4 260 $PAGE->set_pagetype('webservice-doc-generator');
abf7dc44 261
d4c6ef70 262 echo $OUTPUT->header();
abf7dc44 263
264 $activatedprotocol = array();
265 $activatedprotocol['rest'] = webservice_protocol_is_enabled('rest');
266 $activatedprotocol['xmlrpc'] = webservice_protocol_is_enabled('xmlrpc');
267 $renderer = $PAGE->get_renderer('core', 'webservice');
cdb0bd6a 268 /// Check if we are in printable mode
269 $printableformat = false;
270 if (isset($_REQUEST['print'])) {
271 $printableformat = $_REQUEST['print'];
272 }
cdb0bd6a 273
85b4c447 274 $authparams = array();
275 if (empty($this->token)) {
276 $authparams['wsusername'] = $this->username;
277 $authparams['wspassword'] = $this->password;
278 } else {
279 $authparams['wsusername'] = $this->webserviceuser->username;
280 $authparams['token'] = $this->token;
281 }
8725605d 282
85b4c447 283 echo $renderer->documentation_html($this->functions, $printableformat, $activatedprotocol, $authparams);
8725605d 284
cdb0bd6a 285 /// trigger browser print operation
286 if (!empty($printableformat)) {
287 $PAGE->requires->js_function_call('window.print', array());
288 }
abf7dc44 289
d4c6ef70 290 echo $OUTPUT->footer();
291
292 }
293
294 /**
295 * Display login page to the web service documentation
abf7dc44 296 * @global object $PAGE
297 * @global object $OUTPUT
298 * @global object $SITE
299 * @global object $CFG
d4c6ef70 300 * @param string $errormessage error message displayed if wrong login
301 */
302 protected function display_login_page_html($errormessage) {
303 global $PAGE, $OUTPUT, $SITE, $CFG;
304
8725605d 305 $PAGE->set_context(get_context_instance(CONTEXT_SYSTEM));
d4c6ef70 306 $PAGE->set_url('/webservice/wsdoc');
307 $PAGE->set_docs_path('');
308 $PAGE->set_title($SITE->fullname." ".get_string('wsdocumentation', 'webservice'));
309 $PAGE->set_heading($SITE->fullname." ".get_string('wsdocumentation', 'webservice'));
78946b9b 310 $PAGE->set_pagelayout('popup');
7886efc4 311 $PAGE->set_pagetype('webservice-doc-generator-login');
d4c6ef70 312
313 echo $OUTPUT->header();
7886efc4 314
315 $renderer = $PAGE->get_renderer('core', 'webservice');
d4c6ef70 316 echo $renderer->login_page_html($errormessage);
8725605d 317
d4c6ef70 318 echo $OUTPUT->footer();
fbe52a39 319
fbe52a39 320 }
d4c6ef70 321
fbe52a39 322}
d4c6ef70 323
324
325///////////////////////////
326/////// RUN THE SCRIPT ////
327///////////////////////////
328
7886efc4 329if (empty($CFG->enablewsdocumentation)) {
330 echo get_string('wsdocumentationdisable', 'webservice');
331 die;
332}
333
d4c6ef70 334//run the documentation generator
335$generator = new webservice_documentation_generator();
336$generator->run();
337die;