moodle/webservice/wsdoc.php

336 lines
12 KiB
PHP
Raw Normal View History

<?php
///////////////////////////////////////////////////////////////////////////
// //
// This file is part of Moodle - http://moodle.org/ //
// Moodle - Modular Object-Oriented Dynamic Learning Environment //
// //
// 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/>. //
// //
///////////////////////////////////////////////////////////////////////////
// disable moodle specific debug messages and any errors in output
define('NO_MOODLE_COOKIES', true);
require_once('../config.php');
require_once('lib.php');
/**
* This class generate the web service documentation specific to one
* web service user
* @package webservice
* @copyright 2009 Moodle Pty Ltd (http://moodle.com)
* @author Jerome Mouneyrac
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class webservice_documentation_generator {
/** @property array all external function description*/
protected $functions;
/** @property string $username name of local user */
protected $username = null;
/** @property string $password password of the local user */
protected $password = null;
/** @property string $token token of the local user */
protected $token = null;
/** @property object $webserviceuser authenticated web service user */
protected $webserviceuser = null;
/**
* Contructor
*/
public function __construct() {
$this->functionsdescriptions = array();
$this->functions = array();
}
/**
* Run the documentation generation
* @return void
*/
public function run() {
// init all properties from the request data
$this->get_authentication_parameters();
// this sets up $this->webserviceuser
try {
$this->authenticate_user();
} catch(moodle_exception $e) {
$errormessage = $e->debuginfo;
$displayloginpage = true;
}
if (!empty($displayloginpage)){
$this->display_login_page_html($errormessage);
} else {
// make a descriptions list of all function that user is allowed to excecute
$this->generate_documentation();
//finally display the documentation
$this->display_documentation_html();
}
die;
}
///////////////////////////
/////// CLASS METHODS /////
///////////////////////////
/**
* This method parses the $_REQUEST superglobal and looks for
* the following information:
* user authentication - username+password
* @return void
*/
protected function get_authentication_parameters() {
if (isset($_REQUEST['wsusername'])) {
$this->username = $_REQUEST['wsusername'];
}
if (isset($_REQUEST['wspassword'])) {
$this->password = $_REQUEST['wspassword'];
}
if (isset($_REQUEST['token'])) {
$this->token = $_REQUEST['token'];
}
}
/**
* Generate the documentation specific to the auhenticated webservice user
* @return void
*/
protected function generate_documentation() {
global $DB;
/// first of all get a complete list of services user is allowed to access
$params = array();
$wscond1 = '';
$wscond2 = '';
// make sure the function is listed in at least one service user is allowed to use
// allow access only if:
// 1/ entry in the external_services_users table if required
// 2/ validuntil not reached
// 3/ has capability if specified in service desc
// 4/ iprestriction
$sql = "SELECT s.*, NULL AS iprestriction
FROM {external_services} s
JOIN {external_services_functions} sf ON (sf.externalserviceid = s.id AND s.restrictedusers = 0)
WHERE s.enabled = 1 $wscond1
UNION
SELECT s.*, su.iprestriction
FROM {external_services} s
JOIN {external_services_functions} sf ON (sf.externalserviceid = s.id AND s.restrictedusers = 1)
JOIN {external_services_users} su ON (su.externalserviceid = s.id AND su.userid = :userid)
WHERE s.enabled = 1 AND su.validuntil IS NULL OR su.validuntil < :now $wscond2";
$params = array_merge($params, array('userid'=>$this->webserviceuser->id, 'now'=>time()));
$serviceids = array();
$rs = $DB->get_recordset_sql($sql, $params);
// make sure user may access at least one service
$allowed = false;
foreach ($rs as $service) {
if (isset($serviceids[$service->id])) {
continue;
}
if ($service->requiredcapability and !has_capability($service->requiredcapability, $this->restricted_context)) {
continue; // cap required, sorry
}
$serviceids[$service->id] = $service->id;
}
$rs->close();
// now get the list of all functions
if ($serviceids) {
list($serviceids, $params) = $DB->get_in_or_equal($serviceids);
$sql = "SELECT f.*
FROM {external_functions} f
WHERE f.name IN (SELECT sf.functionname
FROM {external_services_functions} sf
WHERE sf.externalserviceid $serviceids)";
$functions = $DB->get_records_sql($sql, $params);
} else {
$functions = array();
}
foreach ($functions as $function) {
$this->functions[$function->name] = external_function_info($function);
}
}
/**
* Authenticate user using username+password
* This function sets up $this->webserviceuser.
* called into the Moodle header
* @return void
*/
protected function authenticate_user() {
global $CFG, $DB;
if (!NO_MOODLE_COOKIES) {
throw new coding_exception('Cookies must be disabled!');
}
if (!$this->token) {
if (!is_enabled_auth('webservice')) {
throw new webservice_access_exception(get_string('wsauthnotenabled', 'webservice'));
}
if (!$auth = get_auth_plugin('webservice')) {
throw new webservice_access_exception(get_string('wsauthmissing', 'webservice'));
}
if (!$this->username) {
throw new webservice_access_exception(get_string('missingusername', 'webservice'));
}
if (!$this->password) {
throw new webservice_access_exception(get_string('missingpassword', 'webservice'));
}
if (!$auth->user_login_webservice($this->username, $this->password)) {
throw new webservice_access_exception(get_string('wrongusernamepassword', 'webservice'));
}
$this->webserviceuser = $DB->get_record('user', array('username'=>$this->username, 'mnethostid'=>$CFG->mnet_localhost_id, 'deleted'=>0), '*', MUST_EXIST);
} else {
if (!$token = $DB->get_record('external_tokens', array('token'=>$this->token, 'tokentype'=>EXTERNAL_TOKEN_PERMANENT))) {
// log failed login attempts
throw new webservice_access_exception(get_string('invalidtoken', 'webservice'));
}
if ($token->validuntil and $token->validuntil < time()) {
throw new webservice_access_exception(get_string('invalidtimedtoken', 'webservice'));
}
if ($token->iprestriction and !address_in_subnet(getremoteaddr(), $token->iprestriction)) {
throw new webservice_access_exception(get_string('invalidiptoken', 'webservice'));
}
$this->webserviceuser = $DB->get_record('user', array('id'=>$token->userid, 'deleted'=>0), '*', MUST_EXIST);
// log token access
$DB->set_field('external_tokens', 'lastaccess', time(), array('id'=>$token->id));
}
}
////////////////////////////////////////////////
///// DISPLAY METHODS /////
////////////////////////////////////////////////
/**
* Generate and display the documentation
*/
protected function display_documentation_html() {
global $PAGE, $OUTPUT, $SITE, $CFG;
$PAGE->set_url('/webservice/wsdoc');
$PAGE->set_docs_path('');
$PAGE->set_title($SITE->fullname." ".get_string('wsdocumentation', 'webservice'));
$PAGE->set_heading($SITE->fullname." ".get_string('wsdocumentation', 'webservice'));
$PAGE->set_pagelayout('popup');
$PAGE->set_pagetype('webservice-doc-generator');
echo $OUTPUT->header();
$activatedprotocol = array();
$activatedprotocol['rest'] = webservice_protocol_is_enabled('rest');
$activatedprotocol['xmlrpc'] = webservice_protocol_is_enabled('xmlrpc');
$renderer = $PAGE->get_renderer('core', 'webservice');
/// Check if we are in printable mode
$printableformat = false;
if (isset($_REQUEST['print'])) {
$printableformat = $_REQUEST['print'];
}
$authparams = array();
if (empty($this->token)) {
$authparams['wsusername'] = $this->username;
$authparams['wspassword'] = $this->password;
} else {
$authparams['wsusername'] = $this->webserviceuser->username;
$authparams['token'] = $this->token;
}
echo $renderer->documentation_html($this->functions, $printableformat, $activatedprotocol, $authparams);
/// trigger browser print operation
if (!empty($printableformat)) {
$PAGE->requires->js_function_call('window.print', array());
}
echo $OUTPUT->footer();
}
/**
* Display login page to the web service documentation
* @global object $PAGE
* @global object $OUTPUT
* @global object $SITE
* @global object $CFG
* @param string $errormessage error message displayed if wrong login
*/
protected function display_login_page_html($errormessage) {
global $PAGE, $OUTPUT, $SITE, $CFG;
$PAGE->set_url('/webservice/wsdoc');
$PAGE->set_docs_path('');
$PAGE->set_title($SITE->fullname." ".get_string('wsdocumentation', 'webservice'));
$PAGE->set_heading($SITE->fullname." ".get_string('wsdocumentation', 'webservice'));
$PAGE->set_pagelayout('popup');
$PAGE->set_pagetype('webservice-doc-generator-login');
echo $OUTPUT->header();
$renderer = $PAGE->get_renderer('core', 'webservice');
echo $renderer->login_page_html($errormessage);
echo $OUTPUT->footer();
}
}
///////////////////////////
/////// RUN THE SCRIPT ////
///////////////////////////
if (empty($CFG->enablewsdocumentation)) {
echo get_string('wsdocumentationdisable', 'webservice');
die;
}
//run the documentation generator
$generator = new webservice_documentation_generator();
$generator->run();
die;