From: jerome mouneyrac Date: Tue, 12 Jan 2010 10:34:52 +0000 (+0000) Subject: webservice MDL-20805 added token creation page in user profil (with service required... X-Git-Url: http://git.mjollnir.org/gw?a=commitdiff_plain;h=5eacbd4be49fb27876492ffab8dad5d6674cf663;p=moodle.git webservice MDL-20805 added token creation page in user profil (with service required capability check and moodle/webservice:createtoken capibility check) --- diff --git a/admin/webservice/forms.php b/admin/webservice/forms.php index ac591ce088..9f347eb5ed 100644 --- a/admin/webservice/forms.php +++ b/admin/webservice/forms.php @@ -140,27 +140,35 @@ class web_service_token_form extends moodleform { $mform->addElement('header', 'token', get_string('token', 'webservice')); - //user searchable selector - $sql = "SELECT user.id, user.firstname, user.lastname, rassign.roleid - FROM {user} user - LEFT JOIN {role_assignments} rassign - ON user.id = rassign.userid - ORDER BY user.lastname"; - $users = $DB->get_records_sql($sql,array()); - $options = array(); - foreach ($users as $userid => $user) { - if ($user->roleid != 1) { - $options[$userid] = $user->firstname. " " . $user->lastname; + if (empty($data->nouserselection)) { + //user searchable selector + $sql = "SELECT user.id, user.firstname, user.lastname, rassign.roleid + FROM {user} user + LEFT JOIN {role_assignments} rassign + ON user.id = rassign.userid + ORDER BY user.lastname"; + $users = $DB->get_records_sql($sql,array()); + $options = array(); + foreach ($users as $userid => $user) { + if ($user->roleid != 1) { + $options[$userid] = $user->firstname. " " . $user->lastname; + } } + $mform->addElement('searchableselector', 'user', get_string('user'),$options); + $mform->addRule('user', get_string('required'), 'required', null, 'client'); } - $mform->addElement('searchableselector', 'user', get_string('user'),$options); - $mform->addRule('user', get_string('required'), 'required', null, 'client'); //service selector $services = $DB->get_records('external_services'); $options = array(); + $systemcontext = get_context_instance(CONTEXT_SYSTEM); foreach ($services as $serviceid => $service) { - $options[$serviceid] = $service->name; + //check that the user has the required capability (only for generation by the profil page) + if (empty($data->nouserselection) + || empty($service->requiredcapability) + || has_capability($service->requiredcapability, $systemcontext, $USER->id)) { + $options[$serviceid] = $service->name; + } } $mform->addElement('select', 'service', get_string('service', 'webservice'),$options); $mform->addRule('service', get_string('required'), 'required', null, 'client'); diff --git a/admin/webservice/tokens.php b/admin/webservice/tokens.php index 4e2fcd8959..a520e01559 100644 --- a/admin/webservice/tokens.php +++ b/admin/webservice/tokens.php @@ -67,7 +67,11 @@ switch ($action) { } else { $newtoken = new object(); $newtoken->token = $generatedtoken; - $newtoken->externalserviceid = $data->service; + if (empty($service->requiredcapability) || has_capability($service->requiredcapability, $systemcontext, $data->user)) { + $newtoken->externalserviceid = $data->service; + } else { + throw new moodle_exception('userhasnocapabilitytousethisservice'); + } $newtoken->tokentype = 2; $newtoken->userid = $data->user; //TODO: find a way to get the context - UPDATE FOLLOWING LINE diff --git a/lang/en_utf8/role.php b/lang/en_utf8/role.php index 7a6b3ebe3f..1933c8e75a 100644 --- a/lang/en_utf8/role.php +++ b/lang/en_utf8/role.php @@ -272,6 +272,7 @@ $string['userswithrole'] = 'All users with a role'; $string['useshowadvancedtochange'] = 'Use \'Show advanced\' to change'; $string['viewrole'] = 'View role details'; $string['viewingdefinitionofrolex'] = 'Viewing the definition of role \'$a\''; +$string['webservice:createtoken'] = 'Create a web service token'; $string['whydoesuserhavecap'] = 'Why does $a->fullname have capability $a->capability in context $a->context?'; $string['whydoesusernothavecap'] = 'Why does $a->fullname not have capability $a->capability in context $a->context?'; $string['xroleassignments'] = '$a\'s role assignments'; diff --git a/lib/db/access.php b/lib/db/access.php index db1548f32a..ed646db5ed 100644 --- a/lib/db/access.php +++ b/lib/db/access.php @@ -1509,5 +1509,14 @@ $capabilities = array( 'coursecreator' => CAP_ALLOW, 'admin' => CAP_ALLOW ) + ), + 'moodle/webservice:createtoken' => array( + + 'riskbitmask' => RISK_DATALOSS | RISK_SPAM | RISK_PERSONAL | RISK_XSS, + 'captype' => 'write', + 'contextlevel' => CONTEXT_SYSTEM, + 'legacy' => array( + 'admin' => CAP_ALLOW + ) ) ); diff --git a/lib/navigationlib.php b/lib/navigationlib.php index c1e50e6195..106fa0c0f4 100644 --- a/lib/navigationlib.php +++ b/lib/navigationlib.php @@ -3354,6 +3354,12 @@ class settings_navigation extends navigation_node { } } + // Webservice + if ($currentuser && !empty($CFG->enablewebservices) && has_capability('moodle/webservice:createtoken', $systemcontext)) { + $url = new moodle_url($CFG->wwwroot .'/user/managetoken.php', array('sesskey'=>sesskey())); + $usersetting->add(get_string('webservices', 'webservice'), $url, self::TYPE_SETTING); + } + // Repository if (!$currentuser) { require_once($CFG->dirroot . '/repository/lib.php'); diff --git a/user/managetoken.php b/user/managetoken.php new file mode 100644 index 0000000000..791f158f8d --- /dev/null +++ b/user/managetoken.php @@ -0,0 +1,183 @@ +. + +/** + * Web service test client. + * + * @package webservice + * @copyright 2009 Moodle Pty Ltd (http://moodle.com) + * @author Petr Skoda (skodak) + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require('../config.php'); + +$PAGE->set_url('user/managetoken.php'); + +$action = optional_param('action', '', PARAM_ACTION); +$tokenid = optional_param('tokenid', '', PARAM_SAFEDIR); +$confirm = optional_param('confirm', 0, PARAM_BOOL); + +require_login(); +require_sesskey(); +$returnurl = "$CFG->wwwroot/user/managetoken.php?sesskey=" . sesskey(); + +//TODO: include tabs.php => tabs.php is a bit ugly require variable $course, $user to be defined here +//look to a better solution, do we really need it? (see /user/portfolio.php and other profil pages) + +switch ($action) { + + case 'create': + require_once($CFG->dirroot."/admin/webservice/forms.php"); + $mform = new web_service_token_form(null, array('action' => 'create', 'nouserselection' => true)); + if ($mform->is_cancelled()) { + redirect($returnurl); + } else if ($data = $mform->get_data()) { + ignore_user_abort(true); // no interruption here! + + //generate token + $generatedtoken = md5(uniqid(rand(),1)); + + // make sure the token doesn't exist (even if it should be almost impossible with the random generation) + if ($DB->record_exists('external_tokens', array('token'=>$generatedtoken))) { + throw new moodle_exception('tokenalreadyexist'); + } else { + $newtoken = new object(); + $newtoken->token = $generatedtoken; + //check that the user has capability on this service + $service = $DB->get_record('external_services', array('id' => $data->service)); + if (empty($service)) { + throw new moodle_exception('servicedonotexist'); + } + if (empty($service->requiredcapability) || has_capability($service->requiredcapability, $systemcontext, $USER->id)) { + $newtoken->externalserviceid = $data->service; + } else { + throw new moodle_exception('nocapabilitytousethisservice'); + } + + $newtoken->tokentype = 2; + $newtoken->userid = $USER->id; + //TODO: find a way to get the context - UPDATE FOLLOWING LINE + $newtoken->contextid = get_context_instance(CONTEXT_SYSTEM)->id; + $newtoken->creatorid = $USER->id; + $newtoken->timecreated = time(); + $newtoken->validuntil = $data->validuntil; + if (!empty($data->iprestriction)) { + $newtoken->iprestriction = $data->iprestriction; + } + $DB->insert_record('external_tokens', $newtoken); + } + redirect($returnurl); + } + + //ask for function id + echo $OUTPUT->header(); + echo $OUTPUT->heading(get_string('createtoken', 'webservice')); + $mform->display(); + echo $OUTPUT->footer(); + die; + break; + + case 'delete': + $sql = "SELECT + token.id, token.token, user.firstname, user.lastname, service.name + FROM + {external_tokens} token, {user} user, {external_services} service + WHERE + token.creatorid=? AND token.id=? AND token.tokentype = 2 AND service.id = token.externalserviceid AND token.userid = user.id"; + $token = $DB->get_record_sql($sql, array($USER->id, $tokenid), MUST_EXIST); //must be the token creator + if (!$confirm) { + echo $OUTPUT->header(); + echo $OUTPUT->heading(get_string('managetokens', 'webservice')); + $optionsyes = array('tokenid'=>$tokenid, 'action'=>'delete', 'confirm'=>1, 'sesskey'=>sesskey()); + $optionsno = array('section'=>'webservicetokens', 'sesskey'=>sesskey()); + $formcontinue = new single_button(new moodle_url($returnurl, $optionsyes), get_string('delete')); + $formcancel = new single_button(new moodle_url($returnurl, $optionsno), get_string('cancel'), 'get'); + echo $OUTPUT->confirm(get_string('deletetokenconfirm', 'webservice', (object)array('user'=>$token->firstname." ".$token->lastname, 'service'=>$token->name)), $formcontinue, $formcancel); + echo $OUTPUT->footer(); + die; + } + $DB->delete_records('external_tokens', array('id'=>$token->id)); + redirect($returnurl); + break; + + default: //display the list of token + + // display strings + $stroperation = get_string('operation', 'webservice'); + $strtoken = get_string('token', 'webservice'); + $strservice = get_string('service', 'webservice'); + $struser = get_string('user'); + $strcontext = get_string('context', 'webservice'); + $strvaliduntil = get_string('validuntil', 'webservice'); + + $return = $OUTPUT->heading(get_string('webservicetokens', 'webservice'), 3, 'main', true); + $return .= $OUTPUT->box_start('generalbox webservicestokenui'); + + $table = new html_table(); + $table->head = array($strtoken, $struser, $strservice, $strcontext, $strvaliduntil, $stroperation); + $table->align = array('left', 'left', 'left', 'left', 'center'); + $table->width = '100%'; + $table->data = array(); + + //TODO: automatically delete obsolete token (service don't exist anymore), use LEFT JOIN for detection + + //here retrieve token list (including linked users firstname/lastname and linked services name) + $sql = "SELECT + token.id, token.token, user.firstname, user.lastname, service.name, token.validuntil + FROM + {external_tokens} token, {user} user, {external_services} service + WHERE + token.creatorid=? AND token.tokentype = 2 AND service.id = token.externalserviceid AND token.userid = user.id"; + $tokens = $DB->get_records_sql($sql, array( $USER->id)); + if (!empty($tokens)) { + foreach ($tokens as $token) { + //TODO: retrieve context + + $delete = "id."\">"; + $delete .= get_string('delete').""; + + if (empty($_SERVER['HTTPS'])) { + $token->token = get_string('activatehttps', 'webservice'); + } + + $validuntil = ''; + if (!empty($token->validuntil)) { + $validuntil = date("F j, Y"); //TODO: language support (look for moodle function) + } + + $table->data[] = array($token->token, $token->firstname." ".$token->lastname, $token->name, '', $validuntil, $delete); + } + + $return .= $OUTPUT->table($table); + $return .= get_string('httpswarning', 'webservice'); + } else { + $return .= get_string('notoken', 'webservice'); + } + + $return .= $OUTPUT->box_end(); + // "add a token" link + $return .= ""; + $return .= get_string('add').""; + echo $OUTPUT->header(); + echo $return; + echo $OUTPUT->footer(); + die(); + break; +} + +redirect($returnurl); \ No newline at end of file diff --git a/version.php b/version.php index 5b751a8d60..cf5ee394fc 100644 --- a/version.php +++ b/version.php @@ -6,7 +6,7 @@ // This is compared against the values stored in the database to determine // whether upgrades should be performed (see lib/db/*.php) - $version = 2010011200; // YYYYMMDD = date of the last version bump + $version = 2010011201; // YYYYMMDD = date of the last version bump // XX = daily increments $release = '2.0 dev (Build: 20100112)'; // Human-friendly version name