diff --git a/course/externallib.php b/course/externallib.php index fef36477c9d99..deed6962ce9b4 100644 --- a/course/externallib.php +++ b/course/externallib.php @@ -302,8 +302,7 @@ public static function get_courses($options) { $exceptionparam = new stdClass(); $exceptionparam->message = $e->getMessage(); $exceptionparam->courseid = $course->id; - throw new moodle_exception( - get_string('errorcoursecontextnotvalid', 'webservice', $exceptionparam)); + throw new moodle_exception('errorcoursecontextnotvalid', 'webservice', '', $exceptionparam); } require_capability('moodle/course:view', $context); @@ -520,23 +519,20 @@ public static function create_courses($courses) { $exceptionparam = new stdClass(); $exceptionparam->message = $e->getMessage(); $exceptionparam->catid = $course['categoryid']; - throw new moodle_exception( - get_string('errorcatcontextnotvalid', 'webservice', $exceptionparam)); + throw new moodle_exception('errorcatcontextnotvalid', 'webservice', '', $exceptionparam); } require_capability('moodle/course:create', $context); // Make sure lang is valid if (key_exists('lang', $course) and empty($availablelangs[$course['lang']])) { - throw new moodle_exception( - get_string('errorinvalidparam', 'webservice', 'lang')); + throw new moodle_exception('errorinvalidparam', 'webservice', '', 'lang'); } // Make sure theme is valid if (key_exists('forcetheme', $course)) { if (!empty($CFG->allowcoursethemes)) { if (empty($availablethemes[$course['forcetheme']])) { - throw new moodle_exception( - get_string('errorinvalidparam', 'webservice', 'forcetheme')); + throw new moodle_exception('errorinvalidparam', 'webservice', '', 'forcetheme'); } else { $course['theme'] = $course['forcetheme']; } diff --git a/enrol/externallib.php b/enrol/externallib.php index 57b6ac13efdce..08438e18b770c 100644 --- a/enrol/externallib.php +++ b/enrol/externallib.php @@ -207,7 +207,7 @@ public static function get_enrolled_users($courseid, $options) { $exceptionparam = new stdClass(); $exceptionparam->message = $e->getMessage(); $exceptionparam->courseid = $params['courseid']; - throw new moodle_exception(get_string('errorcoursecontextnotvalid' , 'webservice', $exceptionparam)); + throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam); } if ($courseid == SITEID) { @@ -543,7 +543,7 @@ public static function get_enrolled_users($courseid, $withcapability = null, $gr $exceptionparam = new stdClass(); $exceptionparam->message = $e->getMessage(); $exceptionparam->courseid = $params['courseid']; - throw new moodle_exception(get_string('errorcoursecontextnotvalid' , 'webservice', $exceptionparam)); + throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam); } if ($courseid == SITEID) { diff --git a/group/externallib.php b/group/externallib.php index 128ad9e4ba5ec..ab4b6eb90f960 100644 --- a/group/externallib.php +++ b/group/externallib.php @@ -95,8 +95,7 @@ public static function create_groups($groups) { $exceptionparam = new stdClass(); $exceptionparam->message = $e->getMessage(); $exceptionparam->courseid = $group->courseid; - throw new moodle_exception( - get_string('errorcoursecontextnotvalid' , 'webservice', $exceptionparam)); + throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam); } require_capability('moodle/course:managegroups', $context); @@ -168,8 +167,7 @@ public static function get_groups($groupids) { $exceptionparam = new stdClass(); $exceptionparam->message = $e->getMessage(); $exceptionparam->courseid = $group->courseid; - throw new moodle_exception( - get_string('errorcoursecontextnotvalid' , 'webservice', $exceptionparam)); + throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam); } require_capability('moodle/course:managegroups', $context); @@ -231,8 +229,7 @@ public static function get_course_groups($courseid) { $exceptionparam = new stdClass(); $exceptionparam->message = $e->getMessage(); $exceptionparam->courseid = $params['courseid']; - throw new moodle_exception( - get_string('errorcoursecontextnotvalid' , 'webservice', $exceptionparam)); + throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam); } require_capability('moodle/course:managegroups', $context); @@ -310,8 +307,7 @@ public static function delete_groups($groupids) { $exceptionparam = new stdClass(); $exceptionparam->message = $e->getMessage(); $exceptionparam->courseid = $group->courseid; - throw new moodle_exception( - get_string('errorcoursecontextnotvalid' , 'webservice', $exceptionparam)); + throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam); } require_capability('moodle/course:managegroups', $context); @@ -369,8 +365,7 @@ public static function get_group_members($groupids) { $exceptionparam = new stdClass(); $exceptionparam->message = $e->getMessage(); $exceptionparam->courseid = $group->courseid; - throw new moodle_exception( - get_string('errorcoursecontextnotvalid' , 'webservice', $exceptionparam)); + throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam); } require_capability('moodle/course:managegroups', $context); @@ -450,8 +445,7 @@ public static function add_group_members($members) { $exceptionparam = new stdClass(); $exceptionparam->message = $e->getMessage(); $exceptionparam->courseid = $group->courseid; - throw new moodle_exception( - get_string('errorcoursecontextnotvalid' , 'webservice', $exceptionparam)); + throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam); } require_capability('moodle/course:managegroups', $context); @@ -529,8 +523,7 @@ public static function delete_group_members($members) { $exceptionparam = new stdClass(); $exceptionparam->message = $e->getMessage(); $exceptionparam->courseid = $group->courseid; - throw new moodle_exception( - get_string('errorcoursecontextnotvalid' , 'webservice', $exceptionparam)); + throw new moodle_exception('errorcoursecontextnotvalid' , 'webservice', '', $exceptionparam); } require_capability('moodle/course:managegroups', $context); diff --git a/lang/en/webservice.php b/lang/en/webservice.php index 7eb7ce449aa2f..08c3d40bbb9b9 100644 --- a/lang/en/webservice.php +++ b/lang/en/webservice.php @@ -25,7 +25,6 @@ $string['accessexception'] = 'Access control exception'; $string['actwebserviceshhdr'] = 'Active web service protocols'; -$string['accesstofunctionnotallowed'] = 'Access to the function {$a}() is not allowed. Please check if a service containing the function is enabled. In the service settings: if the service is restricted check that the user is listed. Still in the service settings check for IP restriction or if the service requires a capability.'; $string['addaservice'] = 'Add service'; $string['addcapabilitytousers'] = 'Check users capability'; $string['addcapabilitytousersdescription'] = 'Users should have two capabilities - webservice:createtoken and a capability matching the protocols used, for example webservice/rest:use, webservice/soap:use. To achieve this, create a web services role with the appropriate capabilities allowed and assign it to the web services user as a system role.'; @@ -75,7 +74,6 @@ $string['enableprotocolsdescription'] = 'At least one protocol should be enabled. For security reasons, only protocols that are to be used should be enabled.'; $string['enablews'] = 'Enable web services'; $string['enablewsdescription'] = 'Web services must be enabled in Advanced features.'; -$string['enabledirectdownload'] = 'Web service file downloading must be enabled in external service settings'; $string['entertoken'] = 'Enter a security key/token:'; $string['error'] = 'Error: {$a}'; $string['errorcatcontextnotvalid'] = 'You cannot execute functions in the category context (category id:{$a->catid}). The context error message was: {$a->message}'; @@ -106,7 +104,6 @@ $string['invalidiptoken'] = 'Invalid token - your IP is not supported'; $string['invalidtimedtoken'] = 'Invalid token - token expired'; $string['invalidtoken'] = 'Invalid token - token not found'; -$string['invalidtokensession'] = 'Invalid session based token - session not found or expired'; $string['iprestriction'] = 'IP restriction'; $string['iprestriction_help'] = 'The user will need to call web service from the listed IPs.'; $string['key'] = 'Key'; @@ -136,7 +133,6 @@ $string['potusersmatching'] = 'Not authorised users matching'; $string['print'] = 'Print all'; $string['protocol'] = 'Protocol'; -$string['protocolnotallowed'] = 'You are not allowed to use the {$a} protocol (missing capability: webservice/{$a}:use)'; $string['removefunction'] = 'Remove'; $string['removefunctionconfirm'] = 'Do you really want to remove function "{$a->function}" from service "{$a->service}"?'; $string['requireauthentication'] = 'This method requires authentication with xxx permission.'; @@ -205,8 +201,6 @@ $string['wsaccessusernologin'] = 'Refused web service access for nologin authentication username: {$a}'; $string['wsaccessusersuspended'] = 'Refused web service access for suspended username: {$a}'; $string['wsaccessuserunconfirmed'] = 'Refused web service access for unconfirmed username: {$a}'; -$string['wsauthmissing'] = 'The web service authentication plugin is missing.'; -$string['wsauthnotenabled'] = 'The web service authentication plugin is disabled.'; $string['wsclientdoc'] = 'Moodle web service client documentation'; $string['wsdocapi'] = 'API Documentation'; $string['wsdocumentation'] = 'Web service documentation'; diff --git a/webservice/lib.php b/webservice/lib.php index 1b0ff8b274b05..7946bd88a9750 100644 --- a/webservice/lib.php +++ b/webservice/lib.php @@ -60,25 +60,27 @@ public function authenticate_user($token) { // web service must be enabled to use this script if (!$CFG->enablewebservices) { - throw new webservice_access_exception(get_string('enablewsdescription', 'webservice')); + throw new webservice_access_exception('Web services are not enabled in Advanced features.'); } // Obtain token record if (!$token = $DB->get_record('external_tokens', array('token' => $token))) { - throw new webservice_access_exception(get_string('invalidtoken', 'webservice')); + //client may want to display login form => moodle_exception + throw new moodle_exception('invalidtoken', 'webservice'); } // Validate token date if ($token->validuntil and $token->validuntil < time()) { add_to_log(SITEID, 'webservice', get_string('tokenauthlog', 'webservice'), '', get_string('invalidtimedtoken', 'webservice'), 0); $DB->delete_records('external_tokens', array('token' => $token->token)); - throw new webservice_access_exception(get_string('invalidtimedtoken', 'webservice')); + throw new webservice_access_exception('Invalid token - token expired - check validuntil time for the token'); } // Check ip if ($token->iprestriction and !address_in_subnet(getremoteaddr(), $token->iprestriction)) { add_to_log(SITEID, 'webservice', get_string('tokenauthlog', 'webservice'), '', get_string('failedtolog', 'webservice') . ": " . getremoteaddr(), 0); - throw new webservice_access_exception(get_string('invalidiptoken', 'webservice')); + throw new webservice_access_exception('Invalid token - IP:' . getremoteaddr() + . ' is not supported'); } //retrieve user link to the token @@ -95,26 +97,27 @@ public function authenticate_user($token) { $session = session_get_instance(); if (!$session->session_exists($token->sid)) { $DB->delete_records('external_tokens', array('sid' => $token->sid)); - throw new webservice_access_exception(get_string('invalidtokensession', 'webservice')); + throw new webservice_access_exception('Invalid session based token - session not found or expired'); } } //Non admin can not authenticate if maintenance mode $hassiteconfig = has_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM), $user); if (!empty($CFG->maintenance_enabled) and !$hassiteconfig) { - throw new webservice_access_exception(get_string('sitemaintenance', 'admin')); + //this is usually temporary, client want to implement code logic => moodle_exception + throw new moodle_exception('sitemaintenance', 'admin'); } //retrieve web service record $service = $DB->get_record('external_services', array('id' => $token->externalserviceid, 'enabled' => 1)); if (empty($service)) { // will throw exception if no token found - throw new webservice_access_exception(get_string('servicenotavailable', 'webservice')); + throw new webservice_access_exception('Web service is not available (it doesn\'t exist or might be disabled)'); } //check if there is any required system capability if ($service->requiredcapability and !has_capability($service->requiredcapability, get_context_instance(CONTEXT_SYSTEM), $user)) { - throw new webservice_access_exception(get_string('missingrequiredcapability', 'webservice', $service->requiredcapability)); + throw new webservice_access_exception('The capability ' . $service->requiredcapability . ' is required.'); } //specific checks related to user restricted service @@ -122,34 +125,37 @@ public function authenticate_user($token) { $authoriseduser = $DB->get_record('external_services_users', array('externalserviceid' => $service->id, 'userid' => $user->id)); if (empty($authoriseduser)) { - throw new webservice_access_exception(get_string('usernotallowed', 'webservice', $service->name)); + throw new webservice_access_exception( + 'The user is not allowed for this service. First you need to allow this user on the ' + . $service->name . '\'s allowed users administration page.'); } if (!empty($authoriseduser->validuntil) and $authoriseduser->validuntil < time()) { - throw new webservice_access_exception(get_string('invalidtimedtoken', 'webservice')); + throw new webservice_access_exception('Invalid service - service expired - check validuntil time for this allowed user'); } if (!empty($authoriseduser->iprestriction) and !address_in_subnet(getremoteaddr(), $authoriseduser->iprestriction)) { - throw new webservice_access_exception(get_string('invalidiptoken', 'webservice')); + throw new webservice_access_exception('Invalid service - IP:' . getremoteaddr() + . ' is not supported - check this allowed user'); } } //only confirmed user should be able to call web service if (empty($user->confirmed)) { add_to_log(SITEID, 'webservice', 'user unconfirmed', '', $user->username); - throw new webservice_access_exception(get_string('usernotconfirmed', 'moodle', $user->username)); + throw new moodle_exception('usernotconfirmed', 'moodle', '', $user->username); } //check the user is suspended if (!empty($user->suspended)) { add_to_log(SITEID, 'webservice', 'user suspended', '', $user->username); - throw new webservice_access_exception(get_string('usersuspended', 'webservice')); + throw new webservice_access_exception('Refused web service access for suspended username: ' . $user->username); } //check if the auth method is nologin (in this case refuse connection) if ($user->auth == 'nologin') { add_to_log(SITEID, 'webservice', 'nologin auth attempt with web service', '', $user->username); - throw new webservice_access_exception(get_string('nologinauth', 'webservice')); + throw new webservice_access_exception('Refused web service access for nologin authentication username: ' . $user->username); } //Check if the user password is expired @@ -158,7 +164,7 @@ public function authenticate_user($token) { $days2expire = $auth->password_expire($user->username); if (intval($days2expire) < 0) { add_to_log(SITEID, 'webservice', 'expired password', '', $user->username); - throw new webservice_access_exception(get_string('passwordisexpired', 'webservice')); + throw new moodle_exception('passwordisexpired', 'webservice'); } } @@ -686,6 +692,10 @@ public function remove_external_function_from_service($functionname, $serviceid) /** * Exception indicating access control problem in web service call + * This exception should return general errors about web service setup. + * Errors related to the user like wrong username/password should not use it, + * you should not use this exception if you want to let the client implement + * some code logic against an access error. * * @package core_webservice * @copyright 2009 Petr Skodak @@ -818,27 +828,27 @@ protected function authenticate_user() { //we check that authentication plugin is enabled //it is only required by simple authentication if (!is_enabled_auth('webservice')) { - throw new webservice_access_exception(get_string('wsauthnotenabled', 'webservice')); + throw new webservice_access_exception('The web service authentication plugin is disabled.'); } if (!$auth = get_auth_plugin('webservice')) { - throw new webservice_access_exception(get_string('wsauthmissing', 'webservice')); + throw new webservice_access_exception('The web service authentication plugin is missing.'); } $this->restricted_context = get_context_instance(CONTEXT_SYSTEM); if (!$this->username) { - throw new webservice_access_exception(get_string('missingusername', 'webservice')); + throw new moodle_exception('missingusername', 'webservice'); } if (!$this->password) { - throw new webservice_access_exception(get_string('missingpassword', 'webservice')); + throw new moodle_exception('missingpassword', 'webservice'); } if (!$auth->user_login_webservice($this->username, $this->password)) { // log failed login attempts add_to_log(SITEID, 'webservice', get_string('simpleauthlog', 'webservice'), '' , get_string('failedtolog', 'webservice').": ".$this->username."/".$this->password." - ".getremoteaddr() , 0); - throw new webservice_access_exception(get_string('wrongusernamepassword', 'webservice')); + throw new moodle_exception('wrongusernamepassword', 'webservice'); } $user = $DB->get_record('user', array('username'=>$this->username, 'mnethostid'=>$CFG->mnet_localhost_id), '*', MUST_EXIST); @@ -852,25 +862,25 @@ protected function authenticate_user() { //Non admin can not authenticate if maintenance mode $hassiteconfig = has_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM), $user); if (!empty($CFG->maintenance_enabled) and !$hassiteconfig) { - throw new webservice_access_exception(get_string('sitemaintenance', 'admin')); + throw new moodle_exception('sitemaintenance', 'admin'); } //only confirmed user should be able to call web service if (!empty($user->deleted)) { add_to_log(SITEID, '', '', '', get_string('wsaccessuserdeleted', 'webservice', $user->username) . " - ".getremoteaddr(), 0, $user->id); - throw new webservice_access_exception(get_string('wsaccessuserdeleted', 'webservice', $user->username)); + throw new webservice_access_exception('Refused web service access for deleted username: ' . $user->username); } //only confirmed user should be able to call web service if (empty($user->confirmed)) { add_to_log(SITEID, '', '', '', get_string('wsaccessuserunconfirmed', 'webservice', $user->username) . " - ".getremoteaddr(), 0, $user->id); - throw new webservice_access_exception(get_string('wsaccessuserunconfirmed', 'webservice', $user->username)); + throw new moodle_exception('wsaccessuserunconfirmed', 'webservice', '', $user->username); } //check the user is suspended if (!empty($user->suspended)) { add_to_log(SITEID, '', '', '', get_string('wsaccessusersuspended', 'webservice', $user->username) . " - ".getremoteaddr(), 0, $user->id); - throw new webservice_access_exception(get_string('wsaccessusersuspended', 'webservice', $user->username)); + throw new webservice_access_exception('Refused web service access for suspended username: ' . $user->username); } //retrieve the authentication plugin if no previously done @@ -883,14 +893,14 @@ protected function authenticate_user() { $days2expire = $auth->password_expire($user->username); if (intval($days2expire) < 0 ) { add_to_log(SITEID, '', '', '', get_string('wsaccessuserexpired', 'webservice', $user->username) . " - ".getremoteaddr(), 0, $user->id); - throw new webservice_access_exception(get_string('wsaccessuserexpired', 'webservice', $user->username)); + throw new webservice_access_exception('Refused web service access for password expired username: ' . $user->username); } } //check if the auth method is nologin (in this case refuse connection) if ($user->auth=='nologin') { add_to_log(SITEID, '', '', '', get_string('wsaccessusernologin', 'webservice', $user->username) . " - ".getremoteaddr(), 0, $user->id); - throw new webservice_access_exception(get_string('wsaccessusernologin', 'webservice', $user->username)); + throw new webservice_access_exception('Refused web service access for nologin authentication username: ' . $user->username); } // now fake user login, the session is completely empty too @@ -899,7 +909,7 @@ protected function authenticate_user() { $this->userid = $user->id; if ($this->authmethod != WEBSERVICE_AUTHMETHOD_SESSION_TOKEN && !has_capability("webservice/$this->wsname:use", $this->restricted_context)) { - throw new webservice_access_exception(get_string('protocolnotallowed', 'webservice', $this->wsname)); + throw new webservice_access_exception('You are not allowed to use the {$a} protocol (missing capability: webservice/' . $this->wsname . ':use)'); } external_api::set_context_restriction($this->restricted_context); @@ -917,25 +927,26 @@ protected function authenticate_by_token($tokentype){ if (!$token = $DB->get_record('external_tokens', array('token'=>$this->token, 'tokentype'=>$tokentype))) { // log failed login attempts add_to_log(SITEID, 'webservice', get_string('tokenauthlog', 'webservice'), '' , get_string('failedtolog', 'webservice').": ".$this->token. " - ".getremoteaddr() , 0); - throw new webservice_access_exception(get_string('invalidtoken', 'webservice')); + throw new moodle_exception('invalidtoken', 'webservice'); } if ($token->validuntil and $token->validuntil < time()) { $DB->delete_records('external_tokens', array('token'=>$this->token, 'tokentype'=>$tokentype)); - throw new webservice_access_exception(get_string('invalidtimedtoken', 'webservice')); + throw new webservice_access_exception('Invalid token - token expired - check validuntil time for the token'); } if ($token->sid){//assumes that if sid is set then there must be a valid associated session no matter the token type $session = session_get_instance(); if (!$session->session_exists($token->sid)){ $DB->delete_records('external_tokens', array('sid'=>$token->sid)); - throw new webservice_access_exception(get_string('invalidtokensession', 'webservice')); + throw new webservice_access_exception('Invalid session based token - session not found or expired'); } } if ($token->iprestriction and !address_in_subnet(getremoteaddr(), $token->iprestriction)) { add_to_log(SITEID, 'webservice', get_string('tokenauthlog', 'webservice'), '' , get_string('failedtolog', 'webservice').": ".getremoteaddr() , 0); - throw new webservice_access_exception(get_string('invalidiptoken', 'webservice')); + throw new webservice_access_exception('Invalid service - IP:' . getremoteaddr() + . ' is not supported - check this allowed user'); } $this->restricted_context = get_context_instance_by_id($token->contextid); @@ -1585,7 +1596,12 @@ protected function load_function_info() { } $rs->close(); if (!$allowed) { - throw new webservice_access_exception(get_string('accesstofunctionnotallowed', 'webservice', $this->functionname)); + throw new webservice_access_exception( + 'Access to the function '.$this->functionname.'() is not allowed. + Please check if a service containing the function is enabled. + In the service settings: if the service is restricted check that + the user is listed. Still in the service settings check for + IP restriction or if the service requires a capability.'); } // we have all we need now diff --git a/webservice/pluginfile.php b/webservice/pluginfile.php index acc3f1ca0b82f..f49480f985634 100644 --- a/webservice/pluginfile.php +++ b/webservice/pluginfile.php @@ -46,7 +46,7 @@ //check the service allows file download $enabledfiledownload = (int) ($authenticationinfo['service']->downloadfiles); if (empty($enabledfiledownload)) { - throw new webservice_access_exception(get_string('enabledirectdownload', 'webservice')); + throw new webservice_access_exception('Web service file downloading must be enabled in external service settings'); } //finally we can serve the file :)