2 ///////////////////////////////////////////////////////////////////////////
4 // This file is part of Moodle - http://moodle.org/ //
5 // Moodle - Modular Object-Oriented Dynamic Learning Environment //
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. //
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. //
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/>. //
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');
31 * This class generate the web service documentation specific to one
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*/
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;
58 public function __construct() {
59 $this->functionsdescriptions
= array();
60 $this->functions
= array();
64 * Run the documentation generation
67 public function run() {
69 // init all properties from the request data
70 $this->get_authentication_parameters();
72 // this sets up $this->webserviceuser
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);
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();
94 ///////////////////////////
95 /////// CLASS METHODS /////
96 ///////////////////////////
99 * This method parses the $_REQUEST superglobal and looks for
100 * the following information:
101 * user authentication - username+password
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
120 protected function generate_documentation() {
123 /// first of all get a complete list of services user is allowed to access
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
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
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
155 foreach ($rs as $service) {
156 if (isset($serviceids[$service->id
])) {
159 if ($service->requiredcapability
and !has_capability($service->requiredcapability
, $this->restricted_context
)) {
160 continue; // cap required, sorry
162 $serviceids[$service->id
] = $service->id
;
166 // now get the list of all functions
168 list($serviceids, $params) = $DB->get_in_or_equal($serviceids);
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);
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
190 protected function authenticate_user() {
193 if (!NO_MOODLE_COOKIES
) {
194 throw new coding_exception('Cookies must be disabled!');
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
);
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
);
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
;
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');
332 //run the documentation generator
333 $generator = new webservice_documentation_generator();