$PAGE->navbar->add(get_string('usercurrentsettings')); $PAGE->navbar->add(get_string('securitykeys', 'webservice'), new moodle_url('/user/managetoken.php', array('id' => $tokenid, 'sesskey' => sesskey()))); $PAGE->navbar->add(get_string('documentation', 'webservice')); //check web service are enabled if (empty($CFG->enablewsdocumentation)) { echo get_string('wsdocumentationdisable', 'webservice'); die; } //check that the current user is the token user $webservice = new webservice(); $token = $webservice->get_token_by_id($tokenid); if (empty($token) or empty($token->userid) or empty($USER->id) or $token->userid != $USER->id) { throw new moodle_exception('docaccessrefused', 'webservice'); } // get the list of all functions related to the token $functions = $webservice->get_external_functions(array($token->externalserviceid)); // get all the function descriptions $functiondescs = array(); foreach ($functions as $function) { $functiondescs[$function->name] = external_function_info($function); } //get activated protocol $activatedprotocol = array(); $activatedprotocol['rest'] = webservice_protocol_is_enabled('rest'); $activatedprotocol['xmlrpc'] = webservice_protocol_is_enabled('xmlrpc'); /// Check if we are in printable mode $printableformat = false; if (isset($_REQUEST['print'])) { $printableformat = $_REQUEST['print']; } /// OUTPUT
/** * Load the virtual class needed for the web service. * * Initialises the virtual class that contains the web service functions that the user is allowed to use. * The web service function will be available if the user: * - is validly registered in the external_services_users table. * - has the required capability. * - meets the IP restriction requirement. * This virtual class can be used by web service protocols such as SOAP, especially when generating WSDL. * NOTE: The implementation of this method has been mostly copied from webservice_zend_server::init_server_class(). */ protected function init_service_class() { global $USER, $DB; // Initialise service methods and struct classes. $this->servicemethods = array(); $this->servicestructs = array(); $params = array(); $wscond1 = ''; $wscond2 = ''; if ($this->restricted_serviceid) { $params = array('sid1' => $this->restricted_serviceid, 'sid2' => $this->restricted_serviceid); $wscond1 = 'AND s.id = :sid1'; $wscond2 = 'AND s.id = :sid2'; } $sql = "SELECT s.*, NULL AS iprestriction\n FROM {external_services} s\n JOIN {external_services_functions} sf ON (sf.externalserviceid = s.id AND s.restrictedusers = 0)\n WHERE s.enabled = 1 {$wscond1}\n\n UNION\n\n SELECT s.*, su.iprestriction\n FROM {external_services} s\n JOIN {external_services_functions} sf ON (sf.externalserviceid = s.id AND s.restrictedusers = 1)\n JOIN {external_services_users} su ON (su.externalserviceid = s.id AND su.userid = :userid)\n WHERE s.enabled = 1 AND (su.validuntil IS NULL OR su.validuntil < :now) {$wscond2}"; $params = array_merge($params, array('userid' => $USER->id, 'now' => time())); $serviceids = array(); $remoteaddr = getremoteaddr(); // Query list of external services for the user. $rs = $DB->get_recordset_sql($sql, $params); // Check which service ID to include. foreach ($rs as $service) { if (isset($serviceids[$service->id])) { continue; // Service already added. } if ($service->requiredcapability and !has_capability($service->requiredcapability, $this->restricted_context)) { continue; // Cap required, sorry. } if ($service->iprestriction and !address_in_subnet($remoteaddr, $service->iprestriction)) { continue; // Wrong request source ip, sorry. } $serviceids[$service->id] = $service->id; } $rs->close(); // Generate the virtual class name. $classname = 'webservices_virtual_class_000000'; while (class_exists($classname)) { $classname++; } $this->serviceclass = $classname; // Get the list of all available external functions. $wsmanager = new webservice(); $functions = $wsmanager->get_external_functions($serviceids); // Generate code for the virtual methods for this web service. $methods = ''; foreach ($functions as $function) { $methods .= $this->get_virtual_method_code($function); } $code = <<<EOD /** * Virtual class web services for user id {$USER->id} in context {$this->restricted_context->id}. */ class {$classname} { {$methods} } EOD; // Load the virtual class definition into memory. eval($code); }
echo $OUTPUT->heading($service->name); $mform->display(); echo $OUTPUT->footer(); die; } break; case 'delete': $PAGE->navbar->add(get_string('removefunction', 'webservice')); /// Delete function operation if (confirm_sesskey() and $service and empty($service->component)) { //check that the function to remove exists $function = $webservicemanager->get_external_function_by_id($functionid, MUST_EXIST); //display confirmation page if (!$confirm) { echo $OUTPUT->header(); echo $renderer->admin_remove_service_function_confirmation($function, $service); echo $OUTPUT->footer(); die; } //or remove the function from the service, then redirect to the function list $webservicemanager->remove_external_function_from_service($function->name, $service->id); redirect($functionlisturl); } break; } /// OUTPUT function list page echo $OUTPUT->header(); echo $OUTPUT->heading(get_string('addservicefunction', 'webservice', $service->name)); $functions = $webservicemanager->get_external_functions(array($service->id)); echo $renderer->admin_service_function_list($functions, $service); echo $OUTPUT->footer();
/** * Load virtual class needed for Zend api * @return void */ protected function init_service_class() { global $USER, $DB; // first ofall get a complete list of services user is allowed to access if ($this->restricted_serviceid) { $params = array('sid1' => $this->restricted_serviceid, 'sid2' => $this->restricted_serviceid); $wscond1 = 'AND s.id = :sid1'; $wscond2 = 'AND s.id = :sid2'; } else { $params = array(); $wscond1 = ''; $wscond2 = ''; } // now 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\n FROM {external_services} s\n JOIN {external_services_functions} sf ON (sf.externalserviceid = s.id AND s.restrictedusers = 0)\n WHERE s.enabled = 1 {$wscond1}\n\n UNION\n\n SELECT s.*, su.iprestriction\n FROM {external_services} s\n JOIN {external_services_functions} sf ON (sf.externalserviceid = s.id AND s.restrictedusers = 1)\n JOIN {external_services_users} su ON (su.externalserviceid = s.id AND su.userid = :userid)\n WHERE s.enabled = 1 AND su.validuntil IS NULL OR su.validuntil < :now {$wscond2}"; $params = array_merge($params, array('userid' => $USER->id, 'now' => time())); $serviceids = array(); $rs = $DB->get_recordset_sql($sql, $params); // now make sure user may access at least one service $remoteaddr = getremoteaddr(); $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 } if ($service->iprestriction and !address_in_subnet($remoteaddr, $service->iprestriction)) { continue; // wrong request source ip, sorry } $serviceids[$service->id] = $service->id; } $rs->close(); // now get the list of all functions $wsmanager = new webservice(); $functions = $wsmanager->get_external_functions($serviceids); // now make the virtual WS class with all the fuctions for this particular user $methods = ''; foreach ($functions as $function) { $methods .= $this->get_virtual_method_code($function); } // let's use unique class name, there might be problem in unit tests $classname = 'webservices_virtual_class_000000'; while (class_exists($classname)) { $classname++; } $code = ' /** * Virtual class web services for user id ' . $USER->id . ' in context ' . $this->restricted_context->id . '. */ class ' . $classname . ' { ' . $methods . ' } '; // load the virtual class definition into memory eval($code); $this->service_class = $classname; }
/** * Fetches the function description from database, * verifies user is allowed to use this function and * loads all paremeters and return descriptions. * @return void */ protected function load_function_info() { global $USER; if (empty($this->functionname)) { throw new WebserviceInvalidParameterException(get_string('missingfuncname', 'webserivce')); } // function must exist $function = webservice_function_info($this->functionname); if (!$function) { throw new WebserviceAccessException(get_string('accessextfunctionnotconf', 'auth.webservice')); } // first ofall get a complete list of services user is allowed to access if ($this->restricted_serviceid) { $wscond1 = 'AND s.id = ? '; $wscond2 = 'AND s.id = ? '; } else { $wscond1 = ''; $wscond2 = ''; } // now let's verify access control // now 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\n FROM {external_services} s\n JOIN {external_services_functions} sf ON (sf.externalserviceid = s.id AND (s.restrictedusers = ? OR s.tokenusers = ?) AND sf.functionname = ?)\n WHERE s.enabled = ? {$wscond1}\n\n UNION\n\n SELECT s.*, su.iprestriction\n FROM {external_services} s\n JOIN {external_services_functions} sf ON (sf.externalserviceid = s.id AND s.restrictedusers = ? AND sf.functionname = ?)\n JOIN {external_services_users} su ON (su.externalserviceid = s.id AND su.userid = ?)\n WHERE s.enabled = ? AND su.validuntil IS NULL OR su.validuntil < ? {$wscond2}"; $params = array(0, 1, $function->name, 1); $wscond1 && ($params[] = $this->restricted_serviceid); $params[] = 1; $params[] = $function->name; $params[] = $USER->get('id'); $params[] = 1; $params[] = time(); $wscond2 && ($params[] = $this->restricted_serviceid); $rs = get_recordset_sql($sql, $params); // now make sure user may access at least one service $remoteaddr = getremoteaddr(); $allowed = false; $serviceids = array(); foreach ($rs as $service) { $serviceids[] = $service['id']; if ($service['iprestriction'] and !address_in_subnet($remoteaddr, $service['iprestriction'])) { // wrong request source ip, sorry continue; } $allowed = true; // one service is enough, no need to continue break; } $rs->close(); if (!$allowed) { throw new WebserviceAccessException(get_string('accesstofunctionnotallowed', 'auth.webservice', $this->functionname)); } // now get the list of all functions - this triggers the stashing of // functions in the context $wsmanager = new webservice(); $functions = $wsmanager->get_external_functions($serviceids); // we have all we need now $this->function = $function; }